Sfoglia il codice sorgente

refactor: Converted modalVisibility Vuex store into modals Pinia store, and removed vuex

Owen Diffey 2 anni fa
parent
commit
b0e1dbb433
53 ha cambiato i file con 204 aggiunte e 539 eliminazioni
  1. 1 21
      frontend/package-lock.json
  2. 1 2
      frontend/package.json
  3. 4 10
      frontend/src/App.vue
  4. 1 1
      frontend/src/api/admin/index.ts
  5. 1 1
      frontend/src/api/auth.ts
  6. 3 7
      frontend/src/components/ActivityItem.vue
  7. 2 5
      frontend/src/components/AddToPlaylistDropdown.vue
  8. 4 4
      frontend/src/components/AdvancedTable.vue
  9. 5 7
      frontend/src/components/ModalManager.vue
  10. 2 5
      frontend/src/components/PlaylistTabBase.vue
  11. 2 4
      frontend/src/components/ReportInfoItem.vue
  12. 3 6
      frontend/src/components/SongItem.vue
  13. 3 5
      frontend/src/components/StationInfoBox.vue
  14. 2 3
      frontend/src/components/global/MainHeader.vue
  15. 2 5
      frontend/src/components/global/Modal.vue
  16. 2 5
      frontend/src/components/modals/BulkActions.vue
  17. 2 5
      frontend/src/components/modals/Confirm.vue
  18. 2 7
      frontend/src/components/modals/CreatePlaylist.vue
  19. 2 5
      frontend/src/components/modals/CreateStation.vue
  20. 2 5
      frontend/src/components/modals/EditNews.vue
  21. 3 5
      frontend/src/components/modals/EditPlaylist/index.vue
  22. 0 3
      frontend/src/components/modals/EditSong/Tabs/Reports.vue
  23. 5 8
      frontend/src/components/modals/EditSong/index.vue
  24. 2 8
      frontend/src/components/modals/EditSongs.vue
  25. 2 4
      frontend/src/components/modals/EditUser.vue
  26. 2 5
      frontend/src/components/modals/ImportAlbum.vue
  27. 2 7
      frontend/src/components/modals/Login.vue
  28. 2 5
      frontend/src/components/modals/ManageStation/index.vue
  29. 2 7
      frontend/src/components/modals/Register.vue
  30. 3 5
      frontend/src/components/modals/RemoveAccount.vue
  31. 2 7
      frontend/src/components/modals/Report.vue
  32. 2 5
      frontend/src/components/modals/ViewApiRequest.vue
  33. 2 5
      frontend/src/components/modals/ViewPunishment.vue
  34. 2 7
      frontend/src/components/modals/ViewReport.vue
  35. 2 8
      frontend/src/components/modals/ViewYoutubeVideo.vue
  36. 4 5
      frontend/src/main.ts
  37. 2 5
      frontend/src/pages/Admin/News.vue
  38. 2 5
      frontend/src/pages/Admin/Playlists.vue
  39. 2 5
      frontend/src/pages/Admin/Reports.vue
  40. 2 4
      frontend/src/pages/Admin/Songs/Import.vue
  41. 2 4
      frontend/src/pages/Admin/Songs/index.vue
  42. 2 5
      frontend/src/pages/Admin/Stations.vue
  43. 2 5
      frontend/src/pages/Admin/Users/Punishments.vue
  44. 2 4
      frontend/src/pages/Admin/Users/index.vue
  45. 2 5
      frontend/src/pages/Admin/YouTube/Videos.vue
  46. 2 4
      frontend/src/pages/Admin/YouTube/index.vue
  47. 2 4
      frontend/src/pages/Home.vue
  48. 2 4
      frontend/src/pages/Profile/Tabs/Playlists.vue
  49. 3 4
      frontend/src/pages/Settings/Tabs/Account.vue
  50. 28 27
      frontend/src/pages/Station/index.vue
  51. 0 15
      frontend/src/store/index.ts
  52. 66 96
      frontend/src/stores/modals.ts
  53. 0 136
      frontend/src/vuex_helpers.ts

+ 1 - 21
frontend/package-lock.json

@@ -31,8 +31,7 @@
         "vue-json-pretty": "^2.1.1",
         "vue-loader": "^17.0.0",
         "vue-router": "^4.1.3",
-        "vue-tippy": "^6.0.0-alpha.63",
-        "vuex": "^4.0.2"
+        "vue-tippy": "^6.0.0-alpha.63"
       },
       "devDependencies": {
         "@typescript-eslint/eslint-plugin": "^5.31.0",
@@ -5129,17 +5128,6 @@
         "typescript": "*"
       }
     },
-    "node_modules/vuex": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
-      "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
-      "dependencies": {
-        "@vue/devtools-api": "^6.0.0-beta.11"
-      },
-      "peerDependencies": {
-        "vue": "^3.0.2"
-      }
-    },
     "node_modules/watchpack": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
@@ -8893,14 +8881,6 @@
         "@volar/vue-typescript": "0.39.2"
       }
     },
-    "vuex": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
-      "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
-      "requires": {
-        "@vue/devtools-api": "^6.0.0-beta.11"
-      }
-    },
     "watchpack": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

+ 1 - 2
frontend/package.json

@@ -56,7 +56,6 @@
     "vue-json-pretty": "^2.1.1",
     "vue-loader": "^17.0.0",
     "vue-router": "^4.1.3",
-    "vue-tippy": "^6.0.0-alpha.63",
-    "vuex": "^4.0.2"
+    "vue-tippy": "^6.0.0-alpha.63"
   }
 }

+ 4 - 10
frontend/src/App.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { useRoute, useRouter } from "vue-router";
 import { defineAsyncComponent, ref, computed, watch, onMounted } from "vue";
 import Toast from "toasters";
@@ -7,6 +6,7 @@ import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
 import { useUserPreferencesStore } from "@/stores/userPreferences";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 import aw from "@/aw";
 import keyboardShortcuts from "@/keyboardShortcuts";
@@ -22,16 +22,13 @@ const FallingSnow = defineAsyncComponent(
 	() => import("@/components/FallingSnow.vue")
 );
 
-const store = useStore();
 const route = useRoute();
 const router = useRouter();
 
-const modals = computed(() => store.state.modalVisibility.modals);
-const activeModals = computed(() => store.state.modalVisibility.activeModals);
-
 const { socket } = useWebsocketsStore();
 const userAuthStore = useUserAuthStore();
 const userPreferencesStore = useUserPreferencesStore();
+const modalsStore = useModalsStore();
 
 const apiDomain = ref("");
 const socketConnected = ref(true);
@@ -51,14 +48,11 @@ const {
 	changeAnonymousSongRequests,
 	changeActivityWatch
 } = userPreferencesStore;
+const { modals, activeModals } = storeToRefs(modalsStore);
+const { openModal, closeCurrentModal } = modalsStore;
 
 const aModalIsOpen = computed(() => Object.keys(activeModals.value).length > 0);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
-
 const toggleNightMode = () => {
 	localStorage.setItem("nightmode", !nightmode.value);
 

+ 1 - 1
frontend/src/api/admin/index.ts

@@ -2,7 +2,7 @@
 
 import reports from "./reports";
 
-// when Vuex needs to interact with websockets
+// when Pinia needs to interact with websockets
 
 export default {
 	reports

+ 1 - 1
frontend/src/api/auth.ts

@@ -3,7 +3,7 @@
 import Toast from "toasters";
 import ws from "@/ws";
 
-// when Vuex needs to interact with websockets
+// when Pinia needs to interact with websockets
 
 export default {
 	register(user) {

+ 3 - 7
frontend/src/components/ActivityItem.vue

@@ -1,9 +1,7 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, computed, onMounted } from "vue";
 import { formatDistance, parseISO } from "date-fns";
-
-const store = useStore();
+import { useModalsStore } from "@/stores/modals";
 
 const props = defineProps({
 	activity: {
@@ -14,6 +12,8 @@ const props = defineProps({
 
 const theme = ref("blue");
 
+const { openModal } = useModalsStore();
+
 const messageParts = computed(() => {
 	const { message } = props.activity.payload;
 	const messageParts = message.split(
@@ -91,10 +91,6 @@ function getIcon() {
 	return icons[props.activity.type];
 }
 
-function openModal(payload) {
-	store.dispatch("modalVisibility/openModal", payload);
-}
-
 onMounted(() => {
 	if (props.activity.type === "station__edit_theme")
 		theme.value = props.activity.payload.message.replace(

+ 2 - 5
frontend/src/components/AddToPlaylistDropdown.vue

@@ -1,14 +1,12 @@
 <script setup lang="ts">
 import { ref, onMounted } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserPlaylistsStore } from "@/stores/userPlaylists";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 
-const store = useStore();
-
 const props = defineProps({
 	song: {
 		type: Object,
@@ -28,8 +26,7 @@ const userPlaylistsStore = useUserPlaylistsStore();
 const { playlists, fetchedPlaylists } = storeToRefs(userPlaylistsStore);
 const { setPlaylists, addPlaylist, removePlaylist } = userPlaylistsStore;
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const init = () => {
 	if (!fetchedPlaylists.value)

+ 4 - 4
frontend/src/components/AdvancedTable.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import {
 	defineAsyncComponent,
 	useSlots,
@@ -13,7 +12,9 @@ import {
 import { useRoute, useRouter } from "vue-router";
 import { Sortable } from "sortablejs-vue3";
 import Toast from "toasters";
+import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import keyboardShortcuts from "@/keyboardShortcuts";
 import ws from "@/ws";
 import useDragBox from "@/composables/useDragBox";
@@ -57,9 +58,8 @@ const slots = useSlots();
 const route = useRoute();
 const router = useRouter();
 
-const store = useStore();
-
-const activeModals = computed(() => store.state.modalVisibility.activeModals);
+const modalsStore = useModalsStore();
+const { activeModals } = storeToRefs(modalsStore);
 
 const { socket } = useWebsocketsStore();
 

+ 5 - 7
frontend/src/components/ModalManager.vue

@@ -1,12 +1,10 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
-import { computed, shallowRef } from "vue";
-import { useModalComponents } from "@/vuex_helpers";
+import { shallowRef } from "vue";
+import { storeToRefs } from "pinia";
+import { useModalsStore, useModalComponents } from "@/stores/modals";
 
-const store = useStore();
-
-const activeModals = computed(() => store.state.modalVisibility.activeModals);
-const modals = computed(() => store.state.modalVisibility.modals);
+const modalsStore = useModalsStore();
+const { modals, activeModals } = storeToRefs(modalsStore);
 
 const modalComponents = shallowRef(
 	useModalComponents("components/modals", {

+ 2 - 5
frontend/src/components/PlaylistTabBase.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref, reactive, computed, onMounted } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import ws from "@/ws";
@@ -9,6 +8,7 @@ import { useWebsocketsStore } from "@/stores/websockets";
 import { useStationStore } from "@/stores/station";
 import { useUserAuthStore } from "@/stores/userAuth";
 import { useUserPlaylistsStore } from "@/stores/userPlaylists";
+import { useModalsStore } from "@/stores/modals";
 import { useManageStationStore } from "@/stores/manageStation";
 
 import useSortablePlaylists from "@/composables/useSortablePlaylists";
@@ -31,8 +31,6 @@ const props = defineProps({
 
 const emit = defineEmits(["selected"]);
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 const stationStore = useStationStore();
 const userAuthStore = useUserAuthStore();
@@ -98,8 +96,7 @@ const nextPageResultsCount = computed(() =>
 	Math.min(search.pageSize, resultsLeftCount.value)
 );
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const { setPlaylists } = useUserPlaylistsStore();
 

+ 2 - 4
frontend/src/components/ReportInfoItem.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent } from "vue";
 import { formatDistance } from "date-fns";
+import { useModalsStore } from "@/stores/modals";
 
 const ProfilePicture = defineAsyncComponent(
 	() => import("@/components/ProfilePicture.vue")
@@ -12,9 +12,7 @@ defineProps({
 	createdAt: { type: String, default: "" }
 });
 
-const store = useStore();
-
-const closeModal = modal => store.dispatch("modalVisibility/closeModal", modal);
+const { closeModal } = useModalsStore();
 </script>
 
 <template>

+ 3 - 6
frontend/src/components/SongItem.vue

@@ -1,14 +1,12 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onMounted, onUnmounted } from "vue";
 import { formatDistance, parseISO } from "date-fns";
 import { storeToRefs } from "pinia";
 import AddToPlaylistDropdown from "./AddToPlaylistDropdown.vue";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import utils from "@/utils";
 
-const store = useStore();
-
 const props = defineProps({
 	song: {
 		type: Object,
@@ -44,6 +42,8 @@ const songActions = ref(null);
 const userAuthStore = useUserAuthStore();
 const { loggedIn, role: userRole } = storeToRefs(userAuthStore);
 
+const { openModal } = useModalsStore();
+
 function formatRequestedAt() {
 	if (props.requestedBy && props.song.requestedAt)
 		formatedRequestedAt.value = formatDistance(
@@ -79,9 +79,6 @@ function hideTippyElements() {
 function hoverTippy() {
 	hoveredTippy.value = true;
 }
-function openModal(payload) {
-	store.dispatch("modalVisibility/openModal", payload);
-}
 function report(song) {
 	hideTippyElements();
 	openModal({ modal: "report", data: { song } });

+ 3 - 5
frontend/src/components/StationInfoBox.vue

@@ -1,11 +1,10 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 
-const store = useStore();
 const userAuthStore = useUserAuthStore();
 
 const props = defineProps({
@@ -18,6 +17,8 @@ const props = defineProps({
 const { socket } = useWebsocketsStore();
 const { loggedIn, userId, role } = storeToRefs(userAuthStore);
 
+const { openModal } = useModalsStore();
+
 function isOwnerOnly() {
 	return loggedIn.value && userId.value === props.station.owner;
 }
@@ -60,9 +61,6 @@ function unfavoriteStation() {
 		} else new Toast(res.message);
 	});
 }
-
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
 </script>
 
 <template>

+ 2 - 3
frontend/src/components/global/MainHeader.vue

@@ -1,11 +1,11 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, onMounted, watch, nextTick } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
 import { useUserPreferencesStore } from "@/stores/userPreferences";
+import { useModalsStore } from "@/stores/modals";
 
 const ChristmasLights = defineAsyncComponent(
 	() => import("@/components/ChristmasLights.vue")
@@ -17,7 +17,6 @@ defineProps({
 	hideLoggedOut: { type: Boolean, default: false }
 });
 
-const store = useStore();
 const userAuthStore = useUserAuthStore();
 
 const localNightmode = ref(false);
@@ -37,7 +36,7 @@ const { loggedIn, username, role } = storeToRefs(userAuthStore);
 const { logout } = userAuthStore;
 const { changeNightmode } = useUserPreferencesStore();
 
-const openModal = modal => store.dispatch("modalVisibility/openModal", modal);
+const { openModal } = useModalsStore();
 
 const toggleNightmode = toggle => {
 	localNightmode.value = toggle || !localNightmode.value;

+ 2 - 5
frontend/src/components/global/Modal.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, onMounted } from "vue";
+import { useModalsStore } from "@/stores/modals";
 
 const ChristmasLights = defineAsyncComponent(
 	() => import("@/components/ChristmasLights.vue")
@@ -15,12 +15,9 @@ const props = defineProps({
 
 const emit = defineEmits(["close"]);
 
-const store = useStore();
-
 const christmas = ref(false);
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const closeCurrentModalClick = () => {
 	if (props.interceptClose) emit("close");

+ 2 - 5
frontend/src/components/modals/BulkActions.vue

@@ -1,11 +1,11 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, defineAsyncComponent, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useLongJobsStore } from "@/stores/longJobs";
 import { useBulkActionsStore } from "@/stores/bulkActions";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 
 const AutoSuggest = defineAsyncComponent(
@@ -16,10 +16,7 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const { setJob } = useLongJobsStore();
 

+ 2 - 5
frontend/src/components/modals/Confirm.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { onBeforeUnmount } from "vue";
 import { storeToRefs } from "pinia";
 import { useConfirmStore } from "@/stores/confirm";
+import { useModalsStore } from "@/stores/modals";
 
 const props = defineProps({
 	modalUuid: { type: String, default: "" }
@@ -12,10 +12,7 @@ const confirmStore = useConfirmStore(props);
 const { message } = storeToRefs(confirmStore);
 const { confirm } = confirmStore;
 
-const store = useStore();
-
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const confirmAction = () => {
 	confirm();

+ 2 - 7
frontend/src/components/modals/CreatePlaylist.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import validation from "@/validation";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 
 defineProps({
 	modalUuid: { type: String, default: "" }
@@ -15,12 +15,7 @@ const playlist = ref({
 	songs: []
 });
 
-const store = useStore();
-
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const { socket } = useWebsocketsStore();
 

+ 2 - 5
frontend/src/components/modals/CreateStation.vue

@@ -1,25 +1,22 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useCreateStationStore } from "@/stores/createStation";
+import { useModalsStore } from "@/stores/modals";
 import validation from "@/validation";
 
 const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const createStationStore = useCreateStationStore(props);
 const { official } = storeToRefs(createStationStore);
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const newStation = ref({
 	name: "",

+ 2 - 5
frontend/src/components/modals/EditNews.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from "vue";
 import { marked } from "marked";
 import DOMPurify from "dompurify";
@@ -8,6 +7,7 @@ import { formatDistance } from "date-fns";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useEditNewsStore } from "@/stores/editNews";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 
 const SaveButton = defineAsyncComponent(
@@ -18,15 +18,12 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const editNewsStore = useEditNewsStore(props);
 const { createNews, newsId } = storeToRefs(editNewsStore);
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const markdown = ref(
 	"# Header\n## Sub-Header\n- **So**\n- _Many_\n- ~Points~\n\nOther things you want to say and [link](https://example.com).\n\n### Sub-Sub-Header\n> Oh look, a quote!\n\n`lil code`\n\n```\nbig code\n```\n"

+ 3 - 5
frontend/src/components/modals/EditPlaylist/index.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import {
 	defineAsyncComponent,
 	ref,
@@ -14,6 +13,7 @@ import { useWebsocketsStore } from "@/stores/websockets";
 import { useEditPlaylistStore } from "@/stores/editPlaylist";
 import { useStationStore } from "@/stores/station";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 import utils from "@/utils";
 
@@ -30,8 +30,6 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 const editPlaylistStore = useEditPlaylistStore(props);
 const stationStore = useStationStore();
@@ -57,8 +55,8 @@ const { playlistId, tab, playlist } = storeToRefs(editPlaylistStore);
 const { setPlaylist, clearPlaylist, addSong, removeSong, repositionedSong } =
 	editPlaylistStore;
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
+
 const showTab = payload => {
 	tabs.value[`${payload}-tab`].scrollIntoView({ block: "nearest" });
 	editPlaylistStore.showTab(payload);

+ 0 - 3
frontend/src/components/modals/EditSong/Tabs/Reports.vue

@@ -53,9 +53,6 @@ const sortedByCategory = computed(() => {
 	return categories;
 });
 
-// const closeModal = payload =>
-// 	store.dispatch("modalVisibility/closeModal", payload);
-
 const { resolveReport } = editSongStore;
 
 const showTab = _tab => {

+ 5 - 8
frontend/src/components/modals/EditSong/index.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { storeToRefs } from "pinia";
 import {
 	defineAsyncComponent,
@@ -16,6 +15,7 @@ import validation from "@/validation";
 import keyboardShortcuts from "@/keyboardShortcuts";
 
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useEditSongStore } from "@/stores/editSong";
 
 const FloatingBox = defineAsyncComponent(
@@ -52,12 +52,12 @@ const emit = defineEmits([
 	"close"
 ]);
 
-const store = useStore();
 const editSongStore = useEditSongStore(props);
 const { socket } = useWebsocketsStore();
 
-const modals = computed(() => store.state.modalVisibility.modals);
-const activeModals = computed(() => store.state.modalVisibility.activeModals);
+const modalsStore = useModalsStore();
+const { modals, activeModals } = storeToRefs(modalsStore);
+const { openModal } = modalsStore;
 
 const {
 	tab,
@@ -162,12 +162,9 @@ const {
 	setPlaybackRate
 } = editSongStore;
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-
 const closeCurrentModal = () => {
 	if (props.bulk) emit("close");
-	else store.dispatch("modalVisibility/closeCurrentModal");
+	else modalsStore.closeCurrentModal();
 };
 
 const showTab = payload => {

+ 2 - 8
frontend/src/components/modals/EditSongs.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { storeToRefs } from "pinia";
 import {
 	defineAsyncComponent,
@@ -11,9 +10,9 @@ import {
 } from "vue";
 import Toast from "toasters";
 
+import { useModalsStore } from "@/stores/modals";
 import { useEditSongStore } from "@/stores/editSong";
 import { useEditSongsStore } from "@/stores/editSongs";
-
 import { useWebsocketsStore } from "@/stores/websockets";
 
 const EditSongModal = defineAsyncComponent(
@@ -27,8 +26,6 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const editSongStore = useEditSongStore(props);
 const editSongsStore = useEditSongsStore(props);
 
@@ -38,10 +35,7 @@ const { youtubeIds, songPrefillData } = storeToRefs(editSongsStore);
 
 const { editSong } = editSongStore;
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const items = ref([]);
 const currentSong = ref({});

+ 2 - 4
frontend/src/components/modals/EditUser.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, watch, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
@@ -7,21 +6,20 @@ import ws from "@/ws";
 import validation from "@/validation";
 import { useEditUserStore } from "@/stores/editUser";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 
 const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
 const editUserStore = useEditUserStore(props);
-const store = useStore();
 
 const { socket } = useWebsocketsStore();
 
 const { userId, user } = storeToRefs(editUserStore);
 const { setUser } = editUserStore;
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const ban = ref({ reason: "", expiresAt: "1h" });
 

+ 2 - 5
frontend/src/components/modals/ImportAlbum.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
 // TODO - Fix sortable
-import { useStore } from "vuex";
 import {
 	defineAsyncComponent,
 	ref,
@@ -12,6 +11,7 @@ import Toast from "toasters";
 import { Sortable } from "sortablejs-vue3";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useImportAlbumStore } from "@/stores/importAlbum";
 import ws from "@/ws";
 
@@ -23,8 +23,6 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const importAlbumStore = useImportAlbumStore(props);
@@ -39,8 +37,7 @@ const {
 	updatePlaylistSong
 } = importAlbumStore;
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const isImportingPlaylist = ref(false);
 const trackSongs = ref([]);

+ 2 - 7
frontend/src/components/modals/Login.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onMounted } from "vue";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 
 const route = useRoute();
 
@@ -19,14 +19,9 @@ const siteSettings = ref({
 });
 const passwordElement = ref();
 
-const store = useStore();
-
 const { login } = useUserAuthStore();
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const submitModal = () => {
 	login({

+ 2 - 5
frontend/src/components/modals/ManageStation/index.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import {
 	defineAsyncComponent,
 	ref,
@@ -11,6 +10,7 @@ import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import { useManageStationStore } from "@/stores/manageStation";
 
 const Queue = defineAsyncComponent(() => import("@/components/Queue.vue"));
@@ -30,8 +30,6 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const tabs = ref([]);
 
 const userAuthStore = useUserAuthStore();
@@ -65,8 +63,7 @@ const {
 	updateIsFavorited
 } = manageStationStore;
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const showTab = payload => {
 	if (tabs.value[`${payload}-tab`])

+ 2 - 7
frontend/src/components/modals/Register.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, watch, onMounted } from "vue";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import validation from "@/validation";
 
 const InputHelpBox = defineAsyncComponent(
@@ -44,14 +44,9 @@ const siteSettings = ref({
 });
 const passwordElement = ref();
 
-const store = useStore();
-
 const { register } = useUserAuthStore();
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const submitModal = () => {
 	if (!username.value.valid || !email.value.valid || !password.value.valid)

+ 3 - 5
frontend/src/components/modals/RemoveAccount.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onMounted } from "vue";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
@@ -7,6 +6,7 @@ import { storeToRefs } from "pinia";
 import { useSettingsStore } from "@/stores/settings";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useRemoveAccountStore } from "@/stores/removeAccount";
+import { useModalsStore } from "@/stores/modals";
 
 const props = defineProps({
 	modalUuid: { type: String, default: "" }
@@ -15,16 +15,14 @@ const props = defineProps({
 const settingsStore = useSettingsStore();
 const route = useRoute();
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const removeAccountStore = useRemoveAccountStore(props);
 const { githubLinkConfirmed } = storeToRefs(removeAccountStore);
 
 const { isPasswordLinked, isGithubLinked } = settingsStore;
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+
+const { closeCurrentModal } = useModalsStore();
 
 const step = ref("confirm-identity");
 const apiDomain = ref("");

+ 2 - 7
frontend/src/components/modals/Report.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useReportStore } from "@/stores/report";
 import ws from "@/ws";
 
@@ -18,17 +18,12 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const reportStore = useReportStore(props);
 const { song } = storeToRefs(reportStore);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const existingReports = ref([]);
 const customIssues = ref([]);

+ 2 - 5
frontend/src/components/modals/ViewApiRequest.vue

@@ -1,10 +1,10 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { ref, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import VueJsonPretty from "vue-json-pretty";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useViewApiRequestStore } from "@/stores/viewApiRequest";
 import ws from "@/ws";
 import "vue-json-pretty/lib/styles.css";
@@ -13,16 +13,13 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const viewApiRequestStore = useViewApiRequestStore(props);
 const { requestId, request, removeAction } = storeToRefs(viewApiRequestStore);
 const { viewApiRequest } = viewApiRequestStore;
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const loaded = ref(false);
 

+ 2 - 5
frontend/src/components/modals/ViewPunishment.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useViewPunishmentStore } from "@/stores/viewPunishment";
 import ws from "@/ws";
 
@@ -15,16 +15,13 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const viewPunishmentStore = useViewPunishmentStore(props);
 const { punishmentId, punishment } = storeToRefs(viewPunishmentStore);
 const { viewPunishment } = viewPunishmentStore;
 
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { closeCurrentModal } = useModalsStore();
 
 const init = () => {
 	socket.dispatch(`punishments.findOne`, punishmentId.value, res => {

+ 2 - 7
frontend/src/components/modals/ViewReport.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useViewReportStore } from "@/stores/viewReport";
 import ws from "@/ws";
 import admin from "@/api/admin/index";
@@ -19,17 +19,12 @@ const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const viewReportStore = useViewReportStore(props);
 const { reportId } = storeToRefs(viewReportStore);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const icons = ref({
 	duration: "timer",

+ 2 - 8
frontend/src/components/modals/ViewYoutubeVideo.vue

@@ -1,15 +1,13 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { onMounted, onBeforeUnmount, ref } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import aw from "@/aw";
 import ws from "@/ws";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import { useViewYoutubeVideoStore } from "@/stores/viewYoutubeVideo";
 
-const store = useStore();
-
 const props = defineProps({
 	modalUuid: { type: String, default: "" }
 });
@@ -36,11 +34,7 @@ const {
 	viewYoutubeVideo
 } = viewYoutubeVideoStore;
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
-
-const closeCurrentModal = () =>
-	store.dispatch("modalVisibility/closeCurrentModal");
+const { openModal, closeCurrentModal } = useModalsStore();
 
 const { socket } = useWebsocketsStore();
 

+ 4 - 5
frontend/src/main.ts

@@ -8,9 +8,9 @@ import "lofig";
 
 import { useUserAuthStore } from "@/stores/userAuth";
 import { useUserPreferencesStore } from "@/stores/userPreferences";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 import ms from "@/ms";
-import store from "./store";
 
 import AppComponent from "./App.vue";
 
@@ -35,8 +35,6 @@ const handleMetadata = attrs => {
 
 const app = createApp(AppComponent);
 
-app.use(store);
-
 app.use(VueTippy, {
 	directive: "tippy", // => v-tippy
 	flipDuration: 0,
@@ -237,6 +235,7 @@ const router = createRouter({
 });
 
 const userAuthStore = useUserAuthStore();
+const modalsStore = useModalsStore();
 
 router.beforeEach((to, from, next) => {
 	if (window.stationInterval) {
@@ -245,10 +244,10 @@ router.beforeEach((to, from, next) => {
 	}
 
 	// if (to.name === "station") {
-	// 	store.dispatch("modalVisibility/closeModal", "manageStation");
+	// 	modalsStore.closeModal("manageStation");
 	// }
 
-	store.dispatch("modalVisibility/closeAllModals");
+	modalsStore.closeAllModals();
 
 	if (ws.socket && to.fullPath !== from.fullPath) {
 		ws.clearCallbacks();

+ 2 - 5
frontend/src/pages/Admin/News.vue

@@ -1,15 +1,13 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
 );
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const columnDefault = ref({
@@ -116,8 +114,7 @@ const events = ref({
 	}
 });
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const remove = id => {
 	socket.dispatch("news.remove", id, res => new Toast(res.message));

+ 2 - 5
frontend/src/pages/Admin/Playlists.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
+import { useModalsStore } from "@/stores/modals";
 
 import utils from "@/utils";
 
@@ -11,8 +11,6 @@ const RunJobDropdown = defineAsyncComponent(
 	() => import("@/components/RunJobDropdown.vue")
 );
 
-const store = useStore();
-
 const columnDefault = ref({
 	sortable: true,
 	hidable: true,
@@ -225,8 +223,7 @@ const jobs = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const getDateFormatted = createdAt => {
 	const date = new Date(createdAt);

+ 2 - 5
frontend/src/pages/Admin/Reports.vue

@@ -1,15 +1,13 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import admin from "@/api/admin/index";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
 );
 
-const store = useStore();
-
 const columnDefault = ref({
 	sortable: true,
 	hidable: true,
@@ -145,8 +143,7 @@ const events = ref({
 	}
 });
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const resolve = (reportId, value) =>
 	admin.reports

+ 2 - 4
frontend/src/pages/Admin/Songs/Import.vue

@@ -1,16 +1,15 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import { useRouter } from "vue-router";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useLongJobsStore } from "@/stores/longJobs";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
 );
 
-const store = useStore();
 const router = useRouter();
 
 const { socket } = useWebsocketsStore();
@@ -236,8 +235,7 @@ const events = ref({
 	}
 });
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const { setJob } = useLongJobsStore();
 

+ 2 - 4
frontend/src/pages/Admin/Songs/index.vue

@@ -1,10 +1,10 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref, onMounted } from "vue";
-import { useStore } from "vuex";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useLongJobsStore } from "@/stores/longJobs";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
@@ -13,7 +13,6 @@ const RunJobDropdown = defineAsyncComponent(
 	() => import("@/components/RunJobDropdown.vue")
 );
 
-const store = useStore();
 const route = useRoute();
 
 const { setJob } = useLongJobsStore();
@@ -295,8 +294,7 @@ const jobs = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const create = () => {
 	openModal({

+ 2 - 5
frontend/src/pages/Admin/Stations.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
@@ -11,8 +11,6 @@ const RunJobDropdown = defineAsyncComponent(
 	() => import("@/components/RunJobDropdown.vue")
 );
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const columnDefault = ref({
@@ -298,8 +296,7 @@ const jobs = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const remove = stationId => {
 	socket.dispatch(

+ 2 - 5
frontend/src/pages/Admin/Users/Punishments.vue

@@ -1,15 +1,13 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
 );
 
-const store = useStore();
-
 const { socket } = useWebsocketsStore();
 
 const ipBan = ref({
@@ -146,8 +144,7 @@ const filters = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const banIP = () => {
 	socket.dispatch(

+ 2 - 4
frontend/src/pages/Admin/Users/index.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref, onMounted } from "vue";
-import { useStore } from "vuex";
 import { useRoute } from "vue-router";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
@@ -10,7 +10,6 @@ const ProfilePicture = defineAsyncComponent(
 	() => import("@/components/ProfilePicture.vue")
 );
 
-const store = useStore();
 const route = useRoute();
 
 const columnDefault = ref({
@@ -197,8 +196,7 @@ const events = ref({
 	}
 });
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const edit = userId => {
 	openModal({ modal: "editUser", data: { userId } });

+ 2 - 5
frontend/src/pages/Admin/YouTube/Videos.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref } from "vue";
-import { useStore } from "vuex";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useLongJobsStore } from "@/stores/longJobs";
+import { useModalsStore } from "@/stores/modals";
 
 const AdvancedTable = defineAsyncComponent(
 	() => import("@/components/AdvancedTable.vue")
@@ -12,8 +12,6 @@ const RunJobDropdown = defineAsyncComponent(
 	() => import("@/components/RunJobDropdown.vue")
 );
 
-const store = useStore();
-
 const { setJob } = useLongJobsStore();
 
 const { socket } = useWebsocketsStore();
@@ -168,8 +166,7 @@ const jobs = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const editOne = song => {
 	openModal({

+ 2 - 4
frontend/src/pages/Admin/YouTube/index.vue

@@ -1,9 +1,9 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref, onMounted } from "vue";
-import { useStore } from "vuex";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
 import { useWebsocketsStore } from "@/stores/websockets";
+import { useModalsStore } from "@/stores/modals";
 import ws from "@/ws";
 
 const AdvancedTable = defineAsyncComponent(
@@ -16,7 +16,6 @@ const LineChart = defineAsyncComponent(
 	() => import("@/components/LineChart.vue")
 );
 
-const store = useStore();
 const route = useRoute();
 
 const { socket } = useWebsocketsStore();
@@ -128,8 +127,7 @@ const jobs = ref([
 	}
 ]);
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const init = () => {
 	if (route.query.fromDate) fromDate.value = route.query.fromDate;

+ 2 - 4
frontend/src/pages/Home.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useStore } from "vuex";
 import { useRoute, useRouter } from "vue-router";
 import { ref, computed, onMounted, onBeforeUnmount } from "vue";
 import { Sortable } from "sortablejs-vue3";
@@ -7,10 +6,10 @@ import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import keyboardShortcuts from "@/keyboardShortcuts";
 import ws from "@/ws";
 
-const store = useStore();
 const userAuthStore = useUserAuthStore();
 const route = useRoute();
 const router = useRouter();
@@ -77,8 +76,7 @@ const favoriteStations = computed(() =>
 		)
 );
 
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+const { openModal } = useModalsStore();
 
 const init = () => {
 	socket.dispatch(

+ 2 - 4
frontend/src/pages/Profile/Tabs/Playlists.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { defineAsyncComponent, onMounted } from "vue";
-import { useStore } from "vuex";
 import useSortablePlaylists from "@/composables/useSortablePlaylists";
+import { useModalsStore } from "@/stores/modals";
 
 const PlaylistItem = defineAsyncComponent(
 	() => import("@/components/PlaylistItem.vue")
@@ -22,9 +22,7 @@ const {
 	savePlaylistOrder
 } = useSortablePlaylists();
 
-const store = useStore();
-
-const openModal = modal => store.dispatch("modalVisibility/openModal", modal);
+const { openModal } = useModalsStore();
 
 onMounted(() => {
 	userId.value = props.userId;

+ 3 - 4
frontend/src/pages/Settings/Tabs/Account.vue

@@ -1,12 +1,12 @@
 <script setup lang="ts">
 import { defineAsyncComponent, ref, watch, reactive, onMounted } from "vue";
-import { useStore } from "vuex";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
 import { useSettingsStore } from "@/stores/settings";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useUserAuthStore } from "@/stores/userAuth";
+import { useModalsStore } from "@/stores/modals";
 import _validation from "@/validation";
 
 const InputHelpBox = defineAsyncComponent(
@@ -18,7 +18,6 @@ const SaveButton = defineAsyncComponent(
 
 const settingsStore = useSettingsStore();
 const userAuthStore = useUserAuthStore();
-const store = useStore();
 const route = useRoute();
 
 const { socket } = useWebsocketsStore();
@@ -42,8 +41,8 @@ const validation = reactive({
 });
 
 const { updateOriginalUser } = settingsStore;
-const openModal = payload =>
-	store.dispatch("modalVisibility/openModal", payload);
+
+const { openModal } = useModalsStore();
 
 const onInput = inputName => {
 	validation[inputName].entered = true;

+ 28 - 27
frontend/src/pages/Station/index.vue

@@ -7,7 +7,6 @@ import {
 	onMounted,
 	onBeforeUnmount
 } from "vue";
-import { useStore } from "vuex";
 import { useRoute, useRouter } from "vue-router";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
@@ -17,6 +16,7 @@ import { useWebsocketsStore } from "@/stores/websockets";
 import { useStationStore } from "@/stores/station";
 import { useUserAuthStore } from "@/stores/userAuth";
 import { useUserPreferencesStore } from "@/stores/userPreferences";
+import { useModalsStore } from "@/stores/modals";
 import aw from "@/aw";
 import ms from "@/ms";
 import ws from "@/ws";
@@ -40,7 +40,6 @@ const StationSidebar = defineAsyncComponent(
 	() => import("./Sidebar/index.vue")
 );
 
-const store = useStore();
 const route = useRoute();
 const router = useRouter();
 
@@ -78,7 +77,7 @@ const activityWatchVideoLastYouTubeId = ref("");
 // const activityWatchVideoLastStartDuration = ref("");
 const nextCurrentSong = ref(null);
 const editSongModalWatcher = ref(null);
-const beforeEditSongModalLocalPaused = ref(null);
+// const beforeEditSongModalLocalPaused = ref(null);
 const socketConnected = ref(null);
 const persistentToastCheckerInterval = ref(null);
 const persistentToasts = ref([]);
@@ -95,7 +94,8 @@ const stationIdentifier = ref();
 const playerDebugBox = ref();
 const keyboardShortcutsHelper = ref();
 
-const activeModals = computed(() => store.state.modalVisibility.activeModals);
+const modalsStore = useModalsStore();
+const { activeModals } = storeToRefs(modalsStore);
 
 // TODO fix this if it still has some use, as this is no longer accurate
 // const video = computed(() => store.state.modals.editSong);
@@ -1070,29 +1070,30 @@ watch(
 );
 
 onMounted(async () => {
-	editSongModalWatcher.value = store.watch(
-		state =>
-			state.modalVisibility.activeModals.length > 0 &&
-			state.modalVisibility.modals[
-				state.modalVisibility.activeModals[
-					state.modalVisibility.activeModals.length - 1
-				]
-			] === "editSong"
-				? state.modals.editSong[
-						state.modalVisibility.activeModals[
-							state.modalVisibility.activeModals.length - 1
-						]
-				  ].video.paused
-				: null,
-		paused => {
-			if (paused && !beforeEditSongModalLocalPaused.value) {
-				resumeLocalStation();
-			} else if (!paused) {
-				beforeEditSongModalLocalPaused.value = localPaused.value;
-				pauseLocalStation();
-			}
-		}
-	);
+	// TODO
+	// editSongModalWatcher.value = store.watch(
+	// 	state =>
+	// 		state.modalVisibility.activeModals.length > 0 &&
+	// 		state.modalVisibility.modals[
+	// 			state.modalVisibility.activeModals[
+	// 				state.modalVisibility.activeModals.length - 1
+	// 			]
+	// 		] === "editSong"
+	// 			? state.modals.editSong[
+	// 					state.modalVisibility.activeModals[
+	// 						state.modalVisibility.activeModals.length - 1
+	// 					]
+	// 			  ].video.paused
+	// 			: null,
+	// 	paused => {
+	// 		if (paused && !beforeEditSongModalLocalPaused.value) {
+	// 			resumeLocalStation();
+	// 		} else if (!paused) {
+	// 			beforeEditSongModalLocalPaused.value = localPaused.value;
+	// 			pauseLocalStation();
+	// 		}
+	// 	}
+	// );
 
 	window.scrollTo(0, 0);
 

+ 0 - 15
frontend/src/store/index.ts

@@ -1,15 +0,0 @@
-/* eslint-disable import/no-cycle */
-import { createStore } from "vuex";
-
-import modalVisibility from "./modules/modalVisibility";
-
-export default createStore({
-	modules: {
-		modalVisibility,
-		modals: {
-			namespaced: true,
-			modules: {}
-		}
-	},
-	strict: false
-});

+ 66 - 96
frontend/src/store/modules/modalVisibility.ts → frontend/src/stores/modals.ts

@@ -1,4 +1,5 @@
-/* eslint no-param-reassign: 0 */
+import { defineStore } from "pinia";
+import { defineAsyncComponent } from "vue";
 import ws from "@/ws";
 
 import { useEditUserStore } from "@/stores/editUser";
@@ -19,46 +20,32 @@ import { useViewReportStore } from "@/stores/viewReport";
 import { useViewYoutubeVideoStore } from "@/stores/viewYoutubeVideo";
 import { useWhatIsNewStore } from "@/stores/whatIsNew";
 
-const state = {
-	modals: {},
-	activeModals: []
-};
-
-const piniaStores = [
-	"editUser",
-	"editSong",
-	"editSongs",
-	"bulkActions",
-	"confirm",
-	"createStation",
-	"editNews",
-	"editPlaylist",
-	"importAlbum",
-	"manageStation",
-	"removeAccount",
-	"report",
-	"viewApiRequest",
-	"viewPunishment",
-	"viewReport",
-	"viewYoutubeVideo",
-	"whatIsNew"
-];
-
-const modalModules = {};
-
-const getters = {};
-
-const actions = {
-	closeModal: ({ commit }, modal) => {
-		if (modal === "register")
-			lofig.get("recaptcha.enabled").then(enabled => {
-				if (enabled) window.location.reload();
+// TODO fix/decide eslint rule properly
+// eslint-disable-next-line
+export const useModalsStore = defineStore("modals", {
+	state: () => ({
+		modals: {},
+		activeModals: []
+	}),
+	actions: {
+		closeModal(modal) {
+			if (modal === "register")
+				lofig.get("recaptcha.enabled").then(enabled => {
+					if (enabled) window.location.reload();
+				});
+
+			Object.entries(this.modals).forEach(([uuid, _modal]) => {
+				if (modal === _modal) {
+					ws.destroyModalListeners(uuid);
+					this.activeModals.splice(
+						this.activeModals.indexOf(uuid),
+						1
+					);
+					delete this.modals[uuid];
+				}
 			});
-
-		commit("closeModal", modal);
-	},
-	openModal: ({ commit }, dataOrModal) =>
-		new Promise(resolve => {
+		},
+		openModal(dataOrModal) {
 			const uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
 				/[xy]/g,
 				symbol => {
@@ -75,35 +62,16 @@ const actions = {
 				}
 			);
 
-			if (typeof dataOrModal === "string")
-				commit("openModal", { modal: dataOrModal, uuid });
-			else commit("openModal", { ...dataOrModal, uuid });
-			resolve({ uuid });
-		}),
-	closeCurrentModal: ({ commit }) => {
-		commit("closeCurrentModal");
-	},
-	closeAllModals: ({ commit }) => {
-		commit("closeAllModals");
-	}
-};
-
-const mutations = {
-	closeModal(state, modal) {
-		Object.entries(state.modals).forEach(([uuid, _modal]) => {
-			if (modal === _modal) {
-				ws.destroyModalListeners(uuid);
-				state.activeModals.splice(state.activeModals.indexOf(uuid), 1);
-				delete state.modals[uuid];
+			let modal;
+			let data;
+			if (typeof dataOrModal === "string") modal = dataOrModal;
+			else {
+				modal = dataOrModal.modal;
+				data = dataOrModal.data;
 			}
-		});
-	},
-	openModal(state, { modal, uuid, data }) {
-		state.modals[uuid] = modal;
+			this.modals[uuid] = modal;
 
-		if (piniaStores.indexOf(modal) !== -1) {
 			let store;
-
 			switch (modal) {
 				case "editUser":
 					store = useEditUserStore({ modalUuid: uuid });
@@ -159,40 +127,42 @@ const mutations = {
 				default:
 					break;
 			}
-
 			if (typeof store.init === "function" && data) store.init(data);
-		} else if (modalModules[modal]) {
-			this.registerModule(["modals", modal, uuid], modalModules[modal]);
-			if (data) this.dispatch(`modals/${modal}/${uuid}/init`, data);
-		}
 
-		state.activeModals.push(uuid);
-	},
-	closeCurrentModal(state) {
-		const currentlyActiveModalUuid =
-			state.activeModals[state.activeModals.length - 1];
-		// TODO: make sure to only destroy/register modal listeners for a unique modal
-		// remove any websocket listeners for the modal
-		ws.destroyModalListeners(currentlyActiveModalUuid);
+			this.activeModals.push(uuid);
 
-		state.activeModals.pop();
+			return { uuid };
+		},
+		closeCurrentModal() {
+			const currentlyActiveModalUuid =
+				this.activeModals[this.activeModals.length - 1];
+			// TODO: make sure to only destroy/register modal listeners for a unique modal
+			// remove any websocket listeners for the modal
+			ws.destroyModalListeners(currentlyActiveModalUuid);
 
-		delete state.modals[currentlyActiveModalUuid];
-	},
-	closeAllModals(state) {
-		state.activeModals.forEach(modalUuid => {
-			ws.destroyModalListeners(modalUuid);
-		});
+			this.activeModals.pop();
 
-		state.activeModals = [];
-		state.modals = {};
-	}
-};
+			delete this.modals[currentlyActiveModalUuid];
+		},
+		closeAllModals() {
+			this.activeModals.forEach(modalUuid => {
+				ws.destroyModalListeners(modalUuid);
+			});
 
-export default {
-	namespaced: true,
-	state,
-	getters,
-	actions,
-	mutations
+			this.activeModals = [];
+			this.modals = {};
+		}
+	}
+});
+
+// TODO fix/decide eslint rule properly
+// eslint-disable-next-line
+export const useModalComponents = (baseDirectory, map) => {
+	const modalComponents = {};
+	Object.entries(map).forEach(([mapKey, mapValue]) => {
+		modalComponents[mapKey] = defineAsyncComponent(
+			() => import(`@/${baseDirectory}/${mapValue}`)
+		);
+	});
+	return modalComponents;
 };

+ 0 - 136
frontend/src/vuex_helpers.ts

@@ -1,136 +0,0 @@
-import { reactive, defineAsyncComponent } from "vue";
-
-import { useStore } from "vuex";
-
-const mapModalState = (namespace, map) => {
-	const modalState = {};
-	// console.log("MAP MODAL STATE", namespace);
-
-	Object.entries(map).forEach(
-		([mapKey, mapValue]: [string, (value: object) => void]) => {
-			modalState[mapKey] = function func() {
-				// console.log(
-				// 	321,
-				// 	namespace
-				// 		.replace(
-				// 			"MODAL_MODULE_PATH",
-				// 			namespace.indexOf("MODAL_MODULE_PATH") !== -1
-				// 				? this.modalModulePath
-				// 				: null
-				// 		)
-				// 		.replace("MODAL_UUID", this.modalUuid)
-				// 		.split("/")
-				// );
-				// console.log(3211, mapKey);
-
-				const state = namespace
-					.replace(
-						"MODAL_MODULE_PATH",
-						namespace.indexOf("MODAL_MODULE_PATH") !== -1
-							? this.modalModulePath
-							: null
-					)
-					.replace("MODAL_UUID", this.modalUuid)
-					.split("/")
-					.reduce((a, b) => a[b], this.$store.state);
-
-				// console.log(32111, state);
-				// if (state) console.log(321111, mapValue(state));
-				// else console.log(321111, "NADA");
-
-				if (state) return mapValue(state);
-				return mapValue({});
-			};
-		}
-	);
-	return modalState;
-};
-
-const mapModalActions = (namespace, map) => {
-	const modalState = {};
-	map.forEach(mapValue => {
-		modalState[mapValue] = function func(value) {
-			return this.$store.dispatch(
-				`${namespace
-					.replace(
-						"MODAL_MODULE_PATH",
-						namespace.indexOf("MODAL_MODULE_PATH") !== -1
-							? this.modalModulePath
-							: null
-					)
-					.replace("MODAL_UUID", this.modalUuid)}/${mapValue}`,
-				value
-			);
-		};
-	});
-	return modalState;
-};
-
-const mapModalComponents = (baseDirectory, map) => {
-	const modalComponents = {};
-	Object.entries(map).forEach(([mapKey, mapValue]) => {
-		modalComponents[mapKey] = () =>
-			defineAsyncComponent(
-				() => import(`./${baseDirectory}/${mapValue}`)
-			);
-	});
-	return modalComponents;
-};
-
-const useModalState = (namespace, options) => {
-	const store = useStore();
-
-	const modalState = namespace
-		.replace(
-			"MODAL_MODULE_PATH",
-			namespace.indexOf("MODAL_MODULE_PATH") !== -1
-				? options.modalModulePath
-				: null
-		)
-		.replace("MODAL_UUID", options.modalUuid)
-		.split("/")
-		.reduce((a, b) => a[b], store.state);
-
-	return reactive(modalState || {});
-};
-
-const useModalActions = (namespace, actions, options) => {
-	const store = useStore();
-
-	const pathStart = `${namespace
-		.replace(
-			"MODAL_MODULE_PATH",
-			namespace.indexOf("MODAL_MODULE_PATH") !== -1
-				? options.modalModulePath
-				: null
-		)
-		.replace("MODAL_UUID", options.modalUuid)}`;
-
-	const actionDispatchers = actions.map(actionName => [
-		actionName,
-		function func(value) {
-			return store.dispatch(`${pathStart}/${actionName}`, value);
-		}
-	]);
-
-	return Object.fromEntries(actionDispatchers);
-};
-
-const useModalComponents = (baseDirectory, map) => {
-	const modalComponents = {};
-	Object.entries(map).forEach(([mapKey, mapValue]) => {
-		modalComponents[mapKey] = defineAsyncComponent(
-			() => import(`./${baseDirectory}/${mapValue}`)
-		);
-	});
-	return modalComponents;
-};
-
-export {
-	mapModalState,
-	mapModalActions,
-	mapModalComponents,
-	useModalState,
-	useModalActions,
-	useModalComponents
-};