import { defineAsyncComponent } from "vue"; import { defineStore } from "pinia"; import utils from "@/utils"; import { useWebsocketsStore } from "@/stores/websockets"; export const useModalsStore = defineStore("modals", { state: (): { modals: Record }>; activeModals: string[]; preventCloseUnsaved: Record boolean>; preventCloseCbs: Record Promise>; } => ({ modals: {}, activeModals: [], preventCloseUnsaved: {}, preventCloseCbs: {} }), actions: { openModal( dataOrModal: string | { modal: string; props?: Record } ) { const uuid = utils.guid(); let modal; let props; if (typeof dataOrModal === "string") modal = dataOrModal; else { modal = dataOrModal.modal; props = dataOrModal.props; } this.modals[uuid] = { modal, props }; this.activeModals.push(uuid); return { uuid }; }, closeModal(uuid: string, force = false) { Object.entries(this.modals).forEach(([_uuid, modal]) => { if (uuid === _uuid) { if (modal.modal === "register") lofig .get("recaptcha.enabled") .then((enabled: boolean) => { if (enabled) window.location.reload(); }); const close = () => { const { socket } = useWebsocketsStore(); socket.destroyModalListeners(uuid); this.activeModals.splice( this.activeModals.indexOf(uuid), 1 ); delete this.modals[uuid]; delete this.preventCloseCbs[uuid]; delete this.preventCloseUnsaved[uuid]; }; if ( !force && typeof this.preventCloseCbs[uuid] !== "undefined" ) this.preventCloseCbs[uuid]().then(() => { close(); }); else if ( !force && typeof this.preventCloseUnsaved[uuid] !== "undefined" && this.preventCloseUnsaved[uuid]() ) { this.openModal({ modal: "confirm", props: { message: "You have unsaved changes. Are you sure you want to discard these changes and close the modal?", onCompleted: close } }); } else close(); } }); }, closeCurrentModal(force = false) { const currentlyActiveModalUuid = this.activeModals[this.activeModals.length - 1]; this.closeModal(currentlyActiveModalUuid, force); }, closeAllModals() { const { socket } = useWebsocketsStore(); this.activeModals.forEach(modalUuid => { socket.destroyModalListeners(modalUuid); }); this.activeModals = []; this.modals = {}; } } }); export const useModalComponents = ( baseDirectory: string, map: Record ) => { const modalComponents: Record = {}; Object.entries(map).forEach(([mapKey, mapValue]) => { modalComponents[mapKey] = defineAsyncComponent( () => import(`@/${baseDirectory}/${mapValue}`) ); }); return modalComponents; };