modals.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import { defineAsyncComponent } from "vue";
  2. import { defineStore } from "pinia";
  3. import { generateUuid } from "@common/utils/generateUuid";
  4. import { useWebsocketsStore } from "@/stores/websockets";
  5. import { useConfigStore } from "@/stores/config";
  6. export const useModalsStore = defineStore("modals", {
  7. state: (): {
  8. modals: Record<string, { modal: string; props?: Record<string, any> }>;
  9. activeModals: string[];
  10. preventCloseUnsaved: Record<string, () => boolean>;
  11. preventCloseCbs: Record<string, () => Promise<void>>;
  12. } => ({
  13. modals: {},
  14. activeModals: [],
  15. preventCloseUnsaved: {},
  16. preventCloseCbs: {}
  17. }),
  18. actions: {
  19. openModal(
  20. dataOrModal: string | { modal: string; props?: Record<string, any> }
  21. ) {
  22. const uuid = generateUuid();
  23. let modal;
  24. let props;
  25. if (typeof dataOrModal === "string") modal = dataOrModal;
  26. else {
  27. modal = dataOrModal.modal;
  28. props = dataOrModal.props;
  29. }
  30. this.modals[uuid] = { modal, props };
  31. this.activeModals.push(uuid);
  32. return { uuid };
  33. },
  34. closeModal(uuid: string, force = false) {
  35. Object.entries(this.modals).forEach(([_uuid, modal]) => {
  36. if (uuid === _uuid) {
  37. if (modal.modal === "register") {
  38. const configStore = useConfigStore();
  39. if (configStore.recaptcha.enabled)
  40. window.location.reload();
  41. }
  42. const close = () => {
  43. const { socket } = useWebsocketsStore();
  44. socket.destroyModalListeners(uuid);
  45. this.activeModals.splice(
  46. this.activeModals.indexOf(uuid),
  47. 1
  48. );
  49. delete this.modals[uuid];
  50. delete this.preventCloseCbs[uuid];
  51. delete this.preventCloseUnsaved[uuid];
  52. };
  53. if (
  54. !force &&
  55. typeof this.preventCloseCbs[uuid] !== "undefined"
  56. )
  57. this.preventCloseCbs[uuid]().then(() => {
  58. close();
  59. });
  60. else if (
  61. !force &&
  62. typeof this.preventCloseUnsaved[uuid] !== "undefined" &&
  63. this.preventCloseUnsaved[uuid]()
  64. ) {
  65. this.openModal({
  66. modal: "confirm",
  67. props: {
  68. message:
  69. "You have unsaved changes. Are you sure you want to discard these changes and close the modal?",
  70. onCompleted: close
  71. }
  72. });
  73. } else close();
  74. }
  75. });
  76. },
  77. closeCurrentModal(force = false) {
  78. const currentlyActiveModalUuid =
  79. this.activeModals[this.activeModals.length - 1];
  80. this.closeModal(currentlyActiveModalUuid, force);
  81. },
  82. closeAllModals() {
  83. const { socket } = useWebsocketsStore();
  84. this.activeModals.forEach(modalUuid => {
  85. socket.destroyModalListeners(modalUuid);
  86. });
  87. this.activeModals = [];
  88. this.modals = {};
  89. }
  90. }
  91. });
  92. export const useModalComponents = (
  93. baseDirectory: string,
  94. map: Record<string, string>
  95. ) => {
  96. const modalComponents: Record<string, any> = {};
  97. Object.entries(map).forEach(([mapKey, mapValue]) => {
  98. modalComponents[mapKey] = defineAsyncComponent(
  99. () => import(`@/${baseDirectory}/${mapValue}`)
  100. );
  101. });
  102. return modalComponents;
  103. };