瀏覽代碼

refactor: Moved openModal data intake from pinia stores to component props

Owen Diffey 2 年之前
父節點
當前提交
ba83bb5838
共有 53 個文件被更改,包括 266 次插入719 次删除
  1. 3 3
      frontend/src/App.vue
  2. 2 2
      frontend/src/components/ActivityItem.vue
  3. 2 1
      frontend/src/components/ModalManager.vue
  4. 7 7
      frontend/src/components/PlaylistTabBase.vue
  5. 3 3
      frontend/src/components/SongItem.vue
  6. 1 1
      frontend/src/components/StationInfoBox.vue
  7. 9 15
      frontend/src/components/modals/BulkActions.vue
  8. 5 14
      frontend/src/components/modals/Confirm.vue
  9. 1 1
      frontend/src/components/modals/CreatePlaylist.vue
  10. 4 13
      frontend/src/components/modals/CreateStation.vue
  11. 9 16
      frontend/src/components/modals/EditNews.vue
  12. 3 3
      frontend/src/components/modals/EditPlaylist/Tabs/AddSongs.vue
  13. 4 3
      frontend/src/components/modals/EditPlaylist/index.vue
  14. 18 29
      frontend/src/components/modals/EditSong/index.vue
  15. 20 40
      frontend/src/components/modals/EditUser.vue
  16. 6 3
      frontend/src/components/modals/ImportAlbum.vue
  17. 8 1
      frontend/src/components/modals/ManageStation/index.vue
  18. 3 7
      frontend/src/components/modals/RemoveAccount.vue
  19. 6 21
      frontend/src/components/modals/Report.vue
  20. 23 23
      frontend/src/components/modals/ViewApiRequest.vue
  21. 11 17
      frontend/src/components/modals/ViewPunishment.vue
  22. 10 16
      frontend/src/components/modals/ViewReport.vue
  23. 16 32
      frontend/src/components/modals/ViewYoutubeVideo.vue
  24. 4 13
      frontend/src/components/modals/WhatIsNew.vue
  25. 1 1
      frontend/src/composables/useForm.ts
  26. 2 2
      frontend/src/pages/Admin/News.vue
  27. 1 1
      frontend/src/pages/Admin/Playlists.vue
  28. 1 1
      frontend/src/pages/Admin/Reports.vue
  29. 11 25
      frontend/src/pages/Admin/Songs/Import.vue
  30. 23 36
      frontend/src/pages/Admin/Songs/index.vue
  31. 2 2
      frontend/src/pages/Admin/Stations.vue
  32. 1 1
      frontend/src/pages/Admin/Users/Punishments.vue
  33. 1 1
      frontend/src/pages/Admin/Users/index.vue
  34. 24 33
      frontend/src/pages/Admin/YouTube/Videos.vue
  35. 1 1
      frontend/src/pages/Admin/YouTube/index.vue
  36. 4 4
      frontend/src/pages/Home.vue
  37. 2 2
      frontend/src/pages/Profile/Tabs/Playlists.vue
  38. 1 1
      frontend/src/pages/Settings/Tabs/Account.vue
  39. 0 13
      frontend/src/stores/bulkActions.ts
  40. 0 25
      frontend/src/stores/confirm.ts
  41. 0 13
      frontend/src/stores/createStation.ts
  42. 0 17
      frontend/src/stores/editNews.ts
  43. 0 5
      frontend/src/stores/editPlaylist.ts
  44. 0 21
      frontend/src/stores/editUser.ts
  45. 0 4
      frontend/src/stores/importAlbum.ts
  46. 13 84
      frontend/src/stores/modals.ts
  47. 0 15
      frontend/src/stores/removeAccount.ts
  48. 0 16
      frontend/src/stores/report.ts
  49. 0 37
      frontend/src/stores/viewApiRequest.ts
  50. 0 27
      frontend/src/stores/viewPunishment.ts
  51. 0 15
      frontend/src/stores/viewReport.ts
  52. 0 16
      frontend/src/stores/viewYoutubeVideo.ts
  53. 0 16
      frontend/src/stores/whatIsNew.ts

+ 3 - 3
frontend/src/App.vue

@@ -209,7 +209,7 @@ onMounted(async () => {
 
 			if (news) {
 				if (newUser) {
-					openModal({ modal: "whatIsNew", data: { news } });
+					openModal({ modal: "whatIsNew", props: { news } });
 				} else if (localStorage.getItem("whatIsNew")) {
 					if (
 						parseInt(localStorage.getItem("whatIsNew") as string) <
@@ -217,7 +217,7 @@ onMounted(async () => {
 					) {
 						openModal({
 							modal: "whatIsNew",
-							data: { news }
+							props: { news }
 						});
 						localStorage.setItem(
 							"whatIsNew",
@@ -233,7 +233,7 @@ onMounted(async () => {
 					)
 						openModal({
 							modal: "whatIsNew",
-							data: { news }
+							props: { news }
 						});
 					localStorage.setItem(
 						"whatIsNew",

+ 2 - 2
frontend/src/components/ActivityItem.vue

@@ -126,7 +126,7 @@ onMounted(() => {
 						@click="
 							openModal({
 								modal: 'viewReport',
-								data: { reportId: activity.payload.reportId }
+								props: { reportId: activity.payload.reportId }
 							})
 						"
 						>report</a
@@ -139,7 +139,7 @@ onMounted(() => {
 						@click="
 							openModal({
 								modal: 'editPlaylist',
-								data: {
+								props: {
 									playlistId: activity.payload.playlistId
 								}
 							})

+ 2 - 1
frontend/src/components/ModalManager.vue

@@ -35,8 +35,9 @@ const modalComponents = shallowRef(
 	<div>
 		<div v-for="activeModalUuid in activeModals" :key="activeModalUuid">
 			<component
-				:is="modalComponents[modals[activeModalUuid]]"
+				:is="modalComponents[modals[activeModalUuid].modal]"
 				:modal-uuid="activeModalUuid"
+				v-bind="modals[activeModalUuid].props"
 			/>
 		</div>
 	</div>

+ 7 - 7
frontend/src/components/PlaylistTabBase.vue

@@ -492,7 +492,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: {
+										props: {
 											playlistId: featuredPlaylist._id
 										}
 									})
@@ -511,7 +511,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: {
+										props: {
 											playlistId: featuredPlaylist._id
 										}
 									})
@@ -676,7 +676,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: playlist._id }
+										props: { playlistId: playlist._id }
 									})
 								"
 								class="material-icons edit-icon"
@@ -693,7 +693,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: playlist._id }
+										props: { playlistId: playlist._id }
 									})
 								"
 								class="material-icons edit-icon"
@@ -758,7 +758,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: playlist._id }
+										props: { playlistId: playlist._id }
 									})
 								"
 								class="material-icons edit-icon"
@@ -775,7 +775,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: playlist._id }
+										props: { playlistId: playlist._id }
 									})
 								"
 								class="material-icons edit-icon"
@@ -949,7 +949,7 @@ onMounted(() => {
 										@click="
 											openModal({
 												modal: 'editPlaylist',
-												data: {
+												props: {
 													playlistId: element._id
 												}
 											})

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

@@ -93,14 +93,14 @@ const hoverTippy = () => {
 
 const report = song => {
 	hideTippyElements();
-	openModal({ modal: "report", data: { song } });
+	openModal({ modal: "report", props: { song } });
 };
 
 const edit = song => {
 	hideTippyElements();
 	openModal({
 		modal: "editSong",
-		data: { song }
+		props: { song }
 	});
 };
 
@@ -204,7 +204,7 @@ onUnmounted(() => {
 								@click="
 									openModal({
 										modal: 'viewYoutubeVideo',
-										data: {
+										props: {
 											youtubeId: song.youtubeId
 										}
 									})

+ 1 - 1
frontend/src/components/StationInfoBox.vue

@@ -143,7 +143,7 @@ const unfavoriteStation = () => {
 				@click="
 					openModal({
 						modal: 'manageStation',
-						data: {
+						props: {
 							stationId: station._id,
 							sector: 'station'
 						}

+ 9 - 15
frontend/src/components/modals/BulkActions.vue

@@ -1,10 +1,8 @@
 <script setup lang="ts">
 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";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
@@ -13,7 +11,8 @@ const AutoSuggest = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	type: { type: Object, required: true }
 });
 
 const { closeCurrentModal } = useModalsStore();
@@ -22,9 +21,6 @@ const { setJob } = useLongJobsStore();
 
 const { socket } = useWebsocketsStore();
 
-const bulkActionsStore = useBulkActionsStore(props);
-const { type } = storeToRefs(bulkActionsStore);
-
 const method = ref("add");
 const items = ref([]);
 const itemInput = ref();
@@ -32,10 +28,10 @@ const allItems = ref([]);
 
 const addItem = () => {
 	if (!itemInput.value) return;
-	if (type.value.regex && !type.value.regex.test(itemInput.value)) {
-		new Toast(`Invalid ${type.value.name} format.`);
+	if (props.type.regex && !props.type.regex.test(itemInput.value)) {
+		new Toast(`Invalid ${props.type.name} format.`);
 	} else if (items.value.includes(itemInput.value)) {
-		new Toast(`Duplicate ${type.value.name} specified.`);
+		new Toast(`Duplicate ${props.type.name} specified.`);
 	} else {
 		items.value.push(itemInput.value);
 		itemInput.value = null;
@@ -51,10 +47,10 @@ const applyChanges = () => {
 	let title;
 
 	socket.dispatch(
-		type.value.action,
+		props.type.action,
 		method.value,
 		items.value,
-		type.value.items,
+		props.type.items,
 		{
 			cb: () => {},
 			onProgress: res => {
@@ -78,14 +74,12 @@ const applyChanges = () => {
 onBeforeUnmount(() => {
 	itemInput.value = null;
 	items.value = [];
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	bulkActionsStore.$dispose();
 });
 
 onMounted(() => {
 	socket.onConnect(() => {
-		if (type.value.autosuggest && type.value.autosuggestDataAction)
-			socket.dispatch(type.value.autosuggestDataAction, res => {
+		if (props.type.autosuggest && props.type.autosuggestDataAction)
+			socket.dispatch(props.type.autosuggestDataAction, res => {
 				if (res.status === "success") {
 					const { items } = res.data;
 					allItems.value = items;

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

@@ -1,30 +1,21 @@
 <script setup lang="ts">
-import { defineAsyncComponent, onBeforeUnmount } from "vue";
-import { storeToRefs } from "pinia";
-import { useConfirmStore } from "@/stores/confirm";
+import { defineAsyncComponent } from "vue";
 import { useModalsStore } from "@/stores/modals";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	message: { type: String || Array, required: true },
+	onCompleted: { type: Function, required: true }
 });
 
-const confirmStore = useConfirmStore(props);
-const { message } = storeToRefs(confirmStore);
-const { confirm } = confirmStore;
-
 const { closeCurrentModal } = useModalsStore();
 
 const confirmAction = () => {
-	confirm();
+	props.onCompleted();
 	closeCurrentModal();
 };
-
-onBeforeUnmount(() => {
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	confirmStore.$dispose();
-});
 </script>
 
 <template>

+ 1 - 1
frontend/src/components/modals/CreatePlaylist.vue

@@ -40,7 +40,7 @@ const createPlaylist = () => {
 			if (!window.addToPlaylistDropdown) {
 				openModal({
 					modal: "editPlaylist",
-					data: { playlistId: res.data.playlistId }
+					props: { playlistId: res.data.playlistId }
 				});
 			}
 		}

+ 4 - 13
frontend/src/components/modals/CreateStation.vue

@@ -1,23 +1,19 @@
 <script setup lang="ts">
-import { defineAsyncComponent, ref, onBeforeUnmount } from "vue";
+import { defineAsyncComponent, ref } 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 Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	official: { type: Boolean, default: false }
 });
 
 const { socket } = useWebsocketsStore();
 
-const createStationStore = useCreateStationStore(props);
-const { official } = storeToRefs(createStationStore);
-
 const { closeCurrentModal } = useModalsStore();
 
 const newStation = ref({
@@ -64,7 +60,7 @@ const submitModal = () => {
 		"stations.create",
 		{
 			name,
-			type: official.value ? "official" : "community",
+			type: props.official ? "official" : "community",
 			displayName,
 			description
 		},
@@ -76,11 +72,6 @@ const submitModal = () => {
 		}
 	);
 };
-
-onBeforeUnmount(() => {
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	createStationStore.$dispose();
-});
 </script>
 
 <template>

+ 9 - 16
frontend/src/components/modals/EditNews.vue

@@ -1,14 +1,12 @@
 <script setup lang="ts">
-import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from "vue";
+import { defineAsyncComponent, ref, onMounted } from "vue";
 import { marked } from "marked";
 import DOMPurify from "dompurify";
 import Toast from "toasters";
 import { formatDistance } from "date-fns";
-import { storeToRefs } from "pinia";
 import { GetNewsResponse } from "@musare_types/actions/NewsActions";
 import { GenericResponse } from "@musare_types/actions/GenericActions";
 import { useWebsocketsStore } from "@/stores/websockets";
-import { useEditNewsStore } from "@/stores/editNews";
 import { useModalsStore } from "@/stores/modals";
 import { useForm } from "@/composables/useForm";
 
@@ -21,14 +19,14 @@ const UserLink = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	createNews: { type: Boolean, default: false },
+	newsId: { type: String, default: null },
+	sector: { type: String, default: "admin" }
 });
 
 const { socket } = useWebsocketsStore();
 
-const editNewsStore = useEditNewsStore(props);
-const { createNews, newsId } = storeToRefs(editNewsStore);
-
 const { closeCurrentModal } = useModalsStore();
 
 const createdBy = ref();
@@ -83,8 +81,8 @@ const { inputs, save, setOriginalValue } = useForm(
 				if (res.status === "success") resolve();
 				else reject(new Error(res.message));
 			};
-			if (createNews.value) socket.dispatch("news.create", data, cb);
-			else socket.dispatch("news.update", newsId.value, data, cb);
+			if (props.createNews) socket.dispatch("news.create", data, cb);
+			else socket.dispatch("news.update", props.newsId, data, cb);
 		} else {
 			if (status === "unchanged") new Toast(messages.unchanged);
 			else if (status === "error")
@@ -99,11 +97,6 @@ const { inputs, save, setOriginalValue } = useForm(
 	}
 );
 
-onBeforeUnmount(() => {
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	editNewsStore.$dispose();
-});
-
 onMounted(() => {
 	marked.use({
 		renderer: {
@@ -117,10 +110,10 @@ onMounted(() => {
 	});
 
 	socket.onConnect(() => {
-		if (newsId.value && !createNews.value) {
+		if (props.newsId && !props.createNews) {
 			socket.dispatch(
 				`news.getNewsFromId`,
-				newsId.value,
+				props.newsId,
 				(res: GetNewsResponse) => {
 					if (res.status === "success") {
 						setOriginalValue({

+ 3 - 3
frontend/src/components/modals/EditPlaylist/Tabs/AddSongs.vue

@@ -17,7 +17,7 @@ const props = defineProps({
 });
 
 const editPlaylistStore = useEditPlaylistStore(props);
-const { playlistId, playlist } = storeToRefs(editPlaylistStore);
+const { playlist } = storeToRefs(editPlaylistStore);
 
 const sitename = ref("Musare");
 
@@ -141,7 +141,7 @@ onMounted(async () => {
 								v-tippy
 								@click="
 									addMusareSongToPlaylist(
-										playlistId,
+										playlist._id,
 										song.youtubeId,
 										index
 									)
@@ -216,7 +216,7 @@ onMounted(async () => {
 								v-tippy
 								@click="
 									addYouTubeSongToPlaylist(
-										playlistId,
+										playlist._id,
 										result.id,
 										index
 									)

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

@@ -30,7 +30,8 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	playlistId: { type: String, required: true }
 });
 
 const { socket } = useWebsocketsStore();
@@ -54,7 +55,7 @@ const playlistSongs = computed({
 	}
 });
 
-const { playlistId, tab, playlist } = storeToRefs(editPlaylistStore);
+const { tab, playlist } = storeToRefs(editPlaylistStore);
 const { setPlaylist, clearPlaylist, addSong, removeSong, repositionedSong } =
 	editPlaylistStore;
 
@@ -248,7 +249,7 @@ const clearAndRefillGenrePlaylist = () => {
 onMounted(() => {
 	socket.onConnect(() => {
 		gettingSongs.value = true;
-		socket.dispatch("playlists.getPlaylist", playlistId.value, res => {
+		socket.dispatch("playlists.getPlaylist", props.playlistId, res => {
 			if (res.status === "success") {
 				setPlaylist(res.data.playlist);
 			} else new Toast(res.message);

+ 18 - 29
frontend/src/components/modals/EditSong/index.vue

@@ -50,7 +50,9 @@ const props = defineProps({
 		type: String,
 		default: "modals/editSong/MODAL_UUID"
 	},
-	discogsAlbum: { type: Object, default: null }
+	discogsAlbum: { type: Object, default: null },
+	song: { type: Object, default: null },
+	songs: { type: Array, default: null }
 });
 
 const editSongStore = useEditSongStore(props);
@@ -454,25 +456,6 @@ const toggleMobileSidebar = () => {
 	sidebarMobileActive.value = !sidebarMobileActive.value;
 };
 
-const handleConfirmed = ({ action, params }) => {
-	if (typeof action === "function") {
-		if (params) action(params);
-		else action();
-	}
-};
-
-const confirmAction = ({ message, action, params }) => {
-	openModal({
-		modal: "confirm",
-		data: {
-			message,
-			action,
-			params,
-			onCompleted: handleConfirmed
-		}
-	});
-};
-
 const onCloseOrNext = (next?: boolean): Promise<void> =>
 	new Promise(resolve => {
 		const confirmReasons = [];
@@ -503,10 +486,12 @@ const onCloseOrNext = (next?: boolean): Promise<void> =>
 		}
 
 		if (confirmReasons.length > 0)
-			confirmAction({
-				message: confirmReasons,
-				action: resolve,
-				params: null
+			openModal({
+				modal: "confirm",
+				props: {
+					message: confirmReasons,
+					onCompleted: resolve
+				}
 			});
 		else resolve();
 	});
@@ -927,6 +912,8 @@ watch(
 );
 
 onMounted(async () => {
+	editSongStore.init({ song: props.song, songs: props.songs });
+
 	editSongStore.form = {
 		inputs,
 		unsavedChanges,
@@ -2317,11 +2304,13 @@ onBeforeUnmount(() => {
 							v-if="hasPermission('songs.remove')"
 							class="button is-danger icon-with-button material-icons"
 							@click.prevent="
-								confirmAction({
-									message:
-										'Removing this song will remove it from all playlists and cause a ratings recalculation.',
-									action: remove,
-									params: song._id
+								openModal({
+									modal: 'confirm',
+									props: {
+										message:
+											'Removing this song will remove it from all playlists and cause a ratings recalculation.',
+										onCompleted: () => remove(song._id)
+									}
 								})
 							"
 							content="Delete Song"

+ 20 - 40
frontend/src/components/modals/EditUser.vue

@@ -1,9 +1,7 @@
 <script setup lang="ts">
 import { defineAsyncComponent, watch, onMounted, onBeforeUnmount } from "vue";
 import Toast from "toasters";
-import { storeToRefs } from "pinia";
 import validation from "@/validation";
-import { useEditUserStore } from "@/stores/editUser";
 import { useWebsocketsStore } from "@/stores/websockets";
 import { useModalsStore } from "@/stores/modals";
 import { useUserAuthStore } from "@/stores/userAuth";
@@ -15,16 +13,12 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	userId: { type: String, required: true }
 });
 
-const editUserStore = useEditUserStore(props);
-
 const { socket } = useWebsocketsStore();
 
-const { userId, user } = storeToRefs(editUserStore);
-const { setUser } = editUserStore;
-
 const { closeCurrentModal, preventCloseUnsaved } = useModalsStore();
 
 const { hasPermission } = useUserAuthStore();
@@ -37,7 +31,7 @@ const {
 } = useForm(
 	{
 		username: {
-			value: user.value.username,
+			value: "",
 			validate: value => {
 				if (!validation.isLength(value, 2, 32))
 					return "Username must have between 2 and 32 characters.";
@@ -51,10 +45,9 @@ const {
 		if (status === "success")
 			socket.dispatch(
 				"users.updateUsername",
-				user.value._id,
+				props.userId,
 				values.username,
 				res => {
-					user.value.username = values.username;
 					if (res.status === "success") {
 						resolve();
 						new Toast(res.message);
@@ -100,10 +93,9 @@ const {
 		if (status === "success")
 			socket.dispatch(
 				"users.updateEmail",
-				user.value._id,
+				props.userId,
 				values.email,
 				res => {
-					user.value.email.address = values.email;
 					if (res.status === "success") {
 						resolve();
 						new Toast(res.message);
@@ -129,15 +121,14 @@ const {
 	save: saveRole,
 	setOriginalValue: setRole
 } = useForm(
-	{ role: user.value.role },
+	{ role: "" },
 	({ status, messages, values }, resolve, reject) => {
 		if (status === "success")
 			socket.dispatch(
 				"users.updateRole",
-				user.value._id,
+				props.userId,
 				values.role,
 				res => {
-					user.value.role = values.role;
 					if (res.status === "success") {
 						resolve();
 						new Toast(res.message);
@@ -179,7 +170,7 @@ const {
 		if (status === "success")
 			socket.dispatch(
 				"users.banUserById",
-				user.value._id,
+				props.userId,
 				values.reason,
 				values.expiresAt,
 				res => {
@@ -202,25 +193,25 @@ const {
 );
 
 const resendVerificationEmail = () => {
-	socket.dispatch(`users.resendVerifyEmail`, user.value._id, res => {
+	socket.dispatch(`users.resendVerifyEmail`, props.userId, res => {
 		new Toast(res.message);
 	});
 };
 
 const requestPasswordReset = () => {
-	socket.dispatch(`users.adminRequestPasswordReset`, user.value._id, res => {
+	socket.dispatch(`users.adminRequestPasswordReset`, props.userId, res => {
 		new Toast(res.message);
 	});
 };
 
 const removeAccount = () => {
-	socket.dispatch(`users.adminRemove`, user.value._id, res => {
+	socket.dispatch(`users.adminRemove`, props.userId, res => {
 		new Toast(res.message);
 	});
 };
 
 const removeSessions = () => {
-	socket.dispatch(`users.removeSessions`, user.value._id, res => {
+	socket.dispatch(`users.removeSessions`, props.userId, res => {
 		new Toast(res.message);
 	});
 };
@@ -231,17 +222,6 @@ watch(
 		if (!value) closeCurrentModal();
 	}
 );
-watch(user, (value, oldValue) => {
-	if (value.username !== oldValue.username)
-		setUsername({ username: value.username });
-	if (
-		value.email &&
-		(value.email.address !== (oldValue.email && oldValue.email.address) ||
-			!emailInputs.value.email.value)
-	)
-		setEmail({ email: value.email.address });
-	if (value.role !== oldValue.role) setRole({ role: value.role });
-});
 
 onMounted(() => {
 	preventCloseUnsaved[props.modalUuid] = () =>
@@ -252,16 +232,18 @@ onMounted(() => {
 		0;
 
 	socket.onConnect(() => {
-		socket.dispatch(`users.getUserFromId`, userId.value, res => {
+		socket.dispatch(`users.getUserFromId`, props.userId, res => {
 			if (res.status === "success") {
-				setUser(res.data);
+				setUsername({ username: res.data.username });
+				setEmail({ email: res.data.email.address });
+				setRole({ role: res.data.role });
 
-				socket.dispatch("apis.joinRoom", `edit-user.${userId.value}`);
+				socket.dispatch("apis.joinRoom", `edit-user.${props.userId}`);
 
 				socket.on(
 					"event:user.removed",
 					res => {
-						if (res.data.userId === userId.value)
+						if (res.data.userId === props.userId)
 							closeCurrentModal();
 					},
 					{ modalUuid: props.modalUuid }
@@ -276,16 +258,14 @@ onMounted(() => {
 
 onBeforeUnmount(() => {
 	delete preventCloseUnsaved[props.modalUuid];
-	socket.dispatch("apis.leaveRoom", `edit-user.${userId.value}`, () => {});
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	editUserStore.$dispose();
+	socket.dispatch("apis.leaveRoom", `edit-user.${props.userId}`, () => {});
 });
 </script>
 
 <template>
 	<div>
 		<modal title="Edit User">
-			<template #body v-if="user && user._id">
+			<template #body>
 				<div class="section">
 					<label class="label"> Change username </label>
 					<p class="control is-grouped">

+ 6 - 3
frontend/src/components/modals/ImportAlbum.vue

@@ -19,7 +19,8 @@ const SongItem = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	songs: { type: Array, required: true }
 });
 
 const { socket } = useWebsocketsStore();
@@ -117,7 +118,7 @@ const startEditingSongs = () => {
 	else {
 		openModal({
 			modal: "editSong",
-			data: { songs: songsToEdit.value }
+			props: { songs: songsToEdit.value }
 		});
 	}
 };
@@ -325,6 +326,8 @@ const updateTrackSong = updatedSong => {
 };
 
 onMounted(() => {
+	setPlaylistSongs(props.songs);
+
 	preventCloseCbs[props.modalUuid] = (): Promise<void> =>
 		new Promise(resolve => {
 			const confirmReasons = [];
@@ -343,7 +346,7 @@ onMounted(() => {
 			if (confirmReasons.length > 0)
 				openModal({
 					modal: "confirm",
-					data: {
+					props: {
 						message: confirmReasons,
 						onCompleted: resolve
 					}

+ 8 - 1
frontend/src/components/modals/ManageStation/index.vue

@@ -31,7 +31,9 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	stationId: { type: String, required: true },
+	sector: { type: String, default: "admin" }
 });
 
 const tabs = ref([]);
@@ -147,6 +149,11 @@ watch(
 );
 
 onMounted(() => {
+	manageStationStore.init({
+		stationId: props.stationId,
+		sector: props.sector
+	});
+
 	socket.onConnect(() => {
 		socket.dispatch(
 			`stations.getStationById`,

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

@@ -2,10 +2,8 @@
 import { defineAsyncComponent, ref, onMounted } from "vue";
 import { useRoute } from "vue-router";
 import Toast from "toasters";
-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 Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
@@ -14,7 +12,8 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	githubLinkConfirmed: { type: Boolean, default: false }
 });
 
 const settingsStore = useSettingsStore();
@@ -22,9 +21,6 @@ const route = useRoute();
 
 const { socket } = useWebsocketsStore();
 
-const removeAccountStore = useRemoveAccountStore(props);
-const { githubLinkConfirmed } = storeToRefs(removeAccountStore);
-
 const { isPasswordLinked, isGithubLinked } = settingsStore;
 
 const { closeCurrentModal } = useModalsStore();
@@ -114,7 +110,7 @@ onMounted(async () => {
 		"siteSettings.githubAuthentication"
 	);
 
-	if (githubLinkConfirmed.value === true) confirmGithubLink();
+	if (props.githubLinkConfirmed === true) confirmGithubLink();
 });
 </script>
 

+ 6 - 21
frontend/src/components/modals/Report.vue

@@ -1,16 +1,8 @@
 <script setup lang="ts">
-import {
-	defineAsyncComponent,
-	ref,
-	onMounted,
-	onBeforeUnmount,
-	computed
-} from "vue";
+import { defineAsyncComponent, ref, onMounted, computed } 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 { useForm } from "@/composables/useForm";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
@@ -22,14 +14,12 @@ const ReportInfoItem = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	song: { type: Object, required: true }
 });
 
 const { socket } = useWebsocketsStore();
 
-const reportStore = useReportStore(props);
-const { song } = storeToRefs(reportStore);
-
 const { openModal, closeCurrentModal } = useModalsStore();
 
 const existingReports = ref([]);
@@ -190,7 +180,7 @@ const { inputs, save } = useForm(
 					"reports.create",
 					{
 						issues,
-						youtubeId: song.value.youtubeId
+						youtubeId: props.song.youtubeId
 					},
 					res => {
 						if (res.status === "success") {
@@ -225,7 +215,7 @@ const categories = computed(() =>
 
 onMounted(() => {
 	socket.onConnect(() => {
-		socket.dispatch("reports.myReportsForSong", song.value._id, res => {
+		socket.dispatch("reports.myReportsForSong", props.song._id, res => {
 			if (res.status === "success") {
 				existingReports.value = res.data.reports;
 				existingReports.value.forEach(report =>
@@ -258,11 +248,6 @@ onMounted(() => {
 		);
 	});
 });
-
-onBeforeUnmount(() => {
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	reportStore.$dispose();
-});
 </script>
 
 <template>
@@ -446,7 +431,7 @@ onBeforeUnmount(() => {
 											@click="
 												openModal({
 													modal: 'viewReport',
-													data: {
+													props: {
 														reportId: report._id
 													}
 												})

+ 23 - 23
frontend/src/components/modals/ViewApiRequest.vue

@@ -2,10 +2,8 @@
 import { defineAsyncComponent, 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 "vue-json-pretty/lib/styles.css";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
@@ -14,43 +12,47 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	requestId: { type: String, required: true },
+	removeAction: { type: String, required: true }
 });
 
 const { socket } = useWebsocketsStore();
 
-const viewApiRequestStore = useViewApiRequestStore(props);
-const { requestId, request, removeAction } = storeToRefs(viewApiRequestStore);
-const { viewApiRequest } = viewApiRequestStore;
-
 const { closeCurrentModal } = useModalsStore();
 
 const loaded = ref(false);
+const request = ref({
+	_id: null,
+	url: null,
+	params: {},
+	results: [],
+	date: null,
+	quotaCost: null
+});
 
 const remove = () => {
-	if (removeAction.value)
-		socket.dispatch(removeAction.value, requestId.value, res => {
-			if (res.status === "success") {
-				new Toast("API request successfully removed.");
-				closeCurrentModal();
-			} else {
-				new Toast("API request with that ID not found.");
-			}
-		});
+	socket.dispatch(props.removeAction, props.requestId, res => {
+		if (res.status === "success") {
+			new Toast("API request successfully removed.");
+			closeCurrentModal();
+		} else {
+			new Toast("API request with that ID not found.");
+		}
+	});
 };
 
 onMounted(() => {
 	socket.onConnect(() => {
 		loaded.value = false;
-		socket.dispatch("youtube.getApiRequest", requestId.value, res => {
+		socket.dispatch("youtube.getApiRequest", props.requestId, res => {
 			if (res.status === "success") {
-				const { apiRequest } = res.data;
-				viewApiRequest(apiRequest);
+				request.value = res.data.apiRequest;
 				loaded.value = true;
 
 				socket.dispatch(
 					"apis.joinRoom",
-					`view-api-request.${requestId.value}`
+					`view-api-request.${props.requestId}`
 				);
 
 				socket.on(
@@ -72,11 +74,9 @@ onMounted(() => {
 onBeforeUnmount(() => {
 	socket.dispatch(
 		"apis.leaveRoom",
-		`view-api-request.${requestId.value}`,
+		`view-api-request.${props.requestId}`,
 		() => {}
 	);
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	viewApiRequestStore.$dispose();
 });
 </script>
 

+ 11 - 17
frontend/src/components/modals/ViewPunishment.vue

@@ -1,10 +1,8 @@
 <script setup lang="ts">
-import { defineAsyncComponent, onMounted, onBeforeUnmount } from "vue";
+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 { useViewPunishmentStore } from "@/stores/viewPunishment";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
 const PunishmentItem = defineAsyncComponent(
@@ -12,25 +10,24 @@ const PunishmentItem = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	punishmentId: { type: String, required: true }
 });
 
 const { socket } = useWebsocketsStore();
 
-const viewPunishmentStore = useViewPunishmentStore(props);
-const { punishmentId, punishment } = storeToRefs(viewPunishmentStore);
-const { viewPunishment } = viewPunishmentStore;
-
 const { closeCurrentModal } = useModalsStore();
 
+const punishment = ref({});
+
 const deactivatePunishment = event => {
 	event.preventDefault();
 	socket.dispatch(
 		"punishments.deactivatePunishment",
-		punishmentId.value,
+		props.punishmentId,
 		res => {
 			if (res.status === "success") {
-				viewPunishmentStore.deactivatePunishment();
+				punishment.value.active = false;
 			} else {
 				new Toast(res.message);
 			}
@@ -40,13 +37,13 @@ const deactivatePunishment = event => {
 
 onMounted(() => {
 	socket.onConnect(() => {
-		socket.dispatch(`punishments.findOne`, punishmentId.value, res => {
+		socket.dispatch(`punishments.findOne`, props.punishmentId, res => {
 			if (res.status === "success") {
-				viewPunishment(res.data.punishment);
+				punishment.value = res.data.punishment;
 
 				socket.dispatch(
 					"apis.joinRoom",
-					`view-punishment.${punishmentId.value}`
+					`view-punishment.${props.punishmentId}`
 				);
 
 				socket.on(
@@ -67,12 +64,9 @@ onMounted(() => {
 onBeforeUnmount(() => {
 	socket.dispatch(
 		"apis.leaveRoom",
-		`view-punishment.${punishmentId.value}`,
+		`view-punishment.${props.punishmentId}`,
 		() => {}
 	);
-
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	viewPunishmentStore.$dispose();
 });
 </script>
 

+ 10 - 16
frontend/src/components/modals/ViewReport.vue

@@ -7,10 +7,8 @@ import {
 	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 { useUserAuthStore } from "@/stores/userAuth";
 import { useReports } from "@/composables/useReports";
 import { Report } from "@/types/report";
@@ -27,14 +25,12 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	reportId: { type: String, required: true }
 });
 
 const { socket } = useWebsocketsStore();
 
-const viewReportStore = useViewReportStore(props);
-const { reportId } = storeToRefs(viewReportStore);
-
 const { openModal, closeCurrentModal } = useModalsStore();
 
 const { resolveReport, removeReport } = useReports();
@@ -54,21 +50,21 @@ const report = ref<Report>({});
 const song = ref();
 
 const resolve = value =>
-	resolveReport({ reportId: reportId.value, value })
+	resolveReport({ reportId: props.reportId, value })
 		.then((res: any) => {
 			if (res.status !== "success") new Toast(res.message);
 		})
 		.catch(err => new Toast(err.message));
 
 const remove = () =>
-	removeReport(reportId.value)
+	removeReport(props.reportId)
 		.then((res: any) => {
 			if (res.status === "success") closeCurrentModal();
 		})
 		.catch(err => new Toast(err.message));
 
 const toggleIssue = issueId => {
-	socket.dispatch("reports.toggleIssue", reportId.value, issueId, res => {
+	socket.dispatch("reports.toggleIssue", props.reportId, issueId, res => {
 		if (res.status !== "success") new Toast(res.message);
 	});
 };
@@ -76,7 +72,7 @@ const toggleIssue = issueId => {
 const openSong = () => {
 	openModal({
 		modal: "editSong",
-		data: { song: report.value.song }
+		props: { song: report.value.song }
 	});
 };
 
@@ -89,13 +85,13 @@ watch(
 
 onMounted(() => {
 	socket.onConnect(() => {
-		socket.dispatch("reports.findOne", reportId.value, res => {
+		socket.dispatch("reports.findOne", props.reportId, res => {
 			if (res.status === "success") {
 				report.value = res.data.report;
 
 				socket.dispatch(
 					"apis.joinRoom",
-					`view-report.${reportId.value}`
+					`view-report.${props.reportId}`
 				);
 
 				socket.dispatch(
@@ -132,7 +128,7 @@ onMounted(() => {
 				socket.on(
 					"event:admin.report.issue.toggled",
 					res => {
-						if (reportId.value === res.data.reportId) {
+						if (props.reportId === res.data.reportId) {
 							const issue = report.value.issues.find(
 								issue =>
 									issue._id.toString() === res.data.issueId
@@ -152,9 +148,7 @@ onMounted(() => {
 });
 
 onBeforeUnmount(() => {
-	socket.dispatch("apis.leaveRoom", `view-report.${reportId.value}`);
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	viewReportStore.$dispose();
+	socket.dispatch("apis.leaveRoom", `view-report.${props.reportId}`);
 });
 </script>
 

+ 16 - 32
frontend/src/components/modals/ViewYoutubeVideo.vue

@@ -16,7 +16,9 @@ const SongThumbnail = defineAsyncComponent(
 );
 
 const props = defineProps({
-	modalUuid: { type: String, required: true }
+	modalUuid: { type: String, required: true },
+	videoId: { type: String, default: null },
+	youtubeId: { type: String, default: null }
 });
 
 const interval = ref(null);
@@ -30,9 +32,7 @@ const activityWatchVideoLastStartDuration = ref(0);
 
 const viewYoutubeVideoStore = useViewYoutubeVideoStore(props);
 const stationStore = useStationStore();
-const { videoId, youtubeId, video, player } = storeToRefs(
-	viewYoutubeVideoStore
-);
+const { video, player } = storeToRefs(viewYoutubeVideoStore);
 const {
 	updatePlayer,
 	stopVideo,
@@ -51,7 +51,7 @@ const userAuthStore = useUserAuthStore();
 const { hasPermission } = userAuthStore;
 
 const remove = () => {
-	socket.dispatch("youtube.removeVideos", videoId.value, res => {
+	socket.dispatch("youtube.removeVideos", video.value._id, res => {
 		if (res.status === "success") {
 			new Toast("YouTube video successfully removed.");
 			closeCurrentModal();
@@ -61,25 +61,6 @@ const remove = () => {
 	});
 };
 
-const handleConfirmed = ({ action, params }) => {
-	if (typeof action === "function") {
-		if (params) action(params);
-		else action();
-	}
-};
-
-const confirmAction = ({ message, action }) => {
-	openModal({
-		modal: "confirm",
-		data: {
-			message,
-			action,
-			params: null,
-			onCompleted: handleConfirmed
-		}
-	});
-};
-
 const seekTo = position => {
 	pauseVideo(false);
 	player.value.player.seekTo(position);
@@ -222,7 +203,7 @@ onMounted(() => {
 		loaded.value = false;
 		socket.dispatch(
 			"youtube.getVideo",
-			videoId.value || youtubeId.value,
+			props.videoId || props.youtubeId,
 			true,
 			res => {
 				if (res.status === "success") {
@@ -457,7 +438,7 @@ onMounted(() => {
 
 					socket.dispatch(
 						"apis.joinRoom",
-						`view-youtube-video.${videoId.value}`
+						`view-youtube-video.${video.value._id}`
 					);
 
 					socket.on(
@@ -491,7 +472,7 @@ onBeforeUnmount(() => {
 
 	socket.dispatch(
 		"apis.leaveRoom",
-		`view-youtube-video.${videoId.value}`,
+		`view-youtube-video.${video.value._id}`,
 		() => {}
 	);
 
@@ -720,7 +701,7 @@ onBeforeUnmount(() => {
 				"
 				class="button is-primary icon-with-button material-icons"
 				@click.prevent="
-					openModal({ modal: 'editSong', data: { song: video } })
+					openModal({ modal: 'editSong', props: { song: video } })
 				"
 				content="Create/edit song from video"
 				v-tippy
@@ -732,10 +713,13 @@ onBeforeUnmount(() => {
 					v-if="hasPermission('youtube.removeVideos')"
 					class="button is-danger icon-with-button material-icons"
 					@click.prevent="
-						confirmAction({
-							message:
-								'Removing this video will remove it from all playlists and cause a ratings recalculation.',
-							action: remove
+						openModal({
+							modal: 'confirm',
+							props: {
+								message:
+									'Removing this video will remove it from all playlists and cause a ratings recalculation.',
+								onCompleted: remove
+							}
 						})
 					"
 					content="Delete Video"

+ 4 - 13
frontend/src/components/modals/WhatIsNew.vue

@@ -1,23 +1,19 @@
 <script setup lang="ts">
-import { defineAsyncComponent, onMounted, onBeforeUnmount } from "vue";
-import { storeToRefs } from "pinia";
+import { defineAsyncComponent, onMounted } from "vue";
 import { formatDistance } from "date-fns";
 import { marked } from "marked";
 import dompurify from "dompurify";
-import { useWhatIsNewStore } from "@/stores/whatIsNew";
 
 const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
 const UserLink = defineAsyncComponent(
 	() => import("@/components/UserLink.vue")
 );
 
-const props = defineProps({
-	modalUuid: { type: String, required: true }
+defineProps({
+	modalUuid: { type: String, required: true },
+	news: { type: Object, required: true }
 });
 
-const whatIsNewStore = useWhatIsNewStore(props);
-const { news } = storeToRefs(whatIsNewStore);
-
 onMounted(() => {
 	marked.use({
 		renderer: {
@@ -31,11 +27,6 @@ onMounted(() => {
 	});
 });
 
-onBeforeUnmount(() => {
-	// Delete the Pinia store that was created for this modal, after all other cleanup tasks are performed
-	whatIsNewStore.$dispose();
-});
-
 const { sanitize } = dompurify;
 </script>
 

+ 1 - 1
frontend/src/composables/useForm.ts

@@ -145,7 +145,7 @@ export const useForm = (
 			if (sourceChanged.value.length > 0)
 				openModal({
 					modal: "confirm",
-					data: {
+					props: {
 						message:
 							"Updates have been made whilst you were making changes. Are you sure you want to continue?",
 						onCompleted: onSave

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

@@ -151,7 +151,7 @@ const remove = (id: string) => {
 					@click="
 						openModal({
 							modal: 'editNews',
-							data: { createNews: true }
+							props: { createNews: true }
 						})
 					"
 				>
@@ -176,7 +176,7 @@ const remove = (id: string) => {
 						@click="
 							openModal({
 								modal: 'editNews',
-								data: { newsId: slotProps.item._id }
+								props: { newsId: slotProps.item._id }
 							})
 						"
 						content="Edit News"

+ 1 - 1
frontend/src/pages/Admin/Playlists.vue

@@ -276,7 +276,7 @@ const formatTimeLong = length => utils.formatTimeLong(length);
 						@click="
 							openModal({
 								modal: 'editPlaylist',
-								data: { playlistId: slotProps.item._id }
+								props: { playlistId: slotProps.item._id }
 							})
 						"
 						:disabled="slotProps.item.removed"

+ 1 - 1
frontend/src/pages/Admin/Reports.vue

@@ -198,7 +198,7 @@ const getDateFormatted = createdAt => {
 						@click="
 							openModal({
 								modal: 'viewReport',
-								data: { reportId: slotProps.item._id }
+								props: { reportId: slotProps.item._id }
 							})
 						"
 						:disabled="slotProps.item.removed"

+ 11 - 25
frontend/src/pages/Admin/Songs/Import.vue

@@ -361,7 +361,7 @@ const importAlbum = youtubeIds => {
 		if (res.status === "success") {
 			openModal({
 				modal: "importAlbum",
-				data: { songs: res.data.songs }
+				props: { songs: res.data.songs }
 			});
 		} else new Toast("Could not get songs.");
 	});
@@ -372,25 +372,6 @@ const removeImportJob = jobId => {
 		new Toast(res.message);
 	});
 };
-
-const handleConfirmed = ({ action, params }) => {
-	if (typeof action === "function") {
-		if (params) action(params);
-		else action();
-	}
-};
-
-const confirmAction = ({ message, action, params }) => {
-	openModal({
-		modal: "confirm",
-		data: {
-			message,
-			action,
-			params,
-			onCompleted: handleConfirmed
-		}
-	});
-};
 </script>
 
 <template>
@@ -574,11 +555,16 @@ const confirmAction = ({ message, action, params }) => {
 									"
 									class="button is-danger icon-with-button material-icons"
 									@click.prevent="
-										confirmAction({
-											message:
-												'Note: Removing an import will not remove any videos or songs.',
-											action: removeImportJob,
-											params: slotProps.item._id
+										openModal({
+											modal: 'confirm',
+											props: {
+												message:
+													'Note: Removing an import will not remove any videos or songs.',
+												onCompleted: () =>
+													removeImportJob(
+														slotProps.item._id
+													)
+											}
 										})
 									"
 									:disabled="

+ 23 - 36
frontend/src/pages/Admin/Songs/index.vue

@@ -323,14 +323,14 @@ const { openModal } = useModalsStore();
 const create = () => {
 	openModal({
 		modal: "editSong",
-		data: { song: { newSong: true } }
+		props: { song: { newSong: true } }
 	});
 };
 
 const editOne = song => {
 	openModal({
 		modal: "editSong",
-		data: { song }
+		props: { song }
 	});
 };
 
@@ -340,7 +340,7 @@ const editMany = selectedRows => {
 		const songs = selectedRows.map(row => ({
 			youtubeId: row.youtubeId
 		}));
-		openModal({ modal: "editSong", data: { songs } });
+		openModal({ modal: "editSong", props: { songs } });
 	}
 };
 
@@ -414,7 +414,7 @@ const importAlbum = selectedRows => {
 		if (res.status === "success") {
 			openModal({
 				modal: "importAlbum",
-				data: { songs: res.data.songs }
+				props: { songs: res.data.songs }
 			});
 		}
 	});
@@ -423,7 +423,7 @@ const importAlbum = selectedRows => {
 const setTags = selectedRows => {
 	openModal({
 		modal: "bulkActions",
-		data: {
+		props: {
 			type: {
 				name: "tags",
 				action: "songs.editTags",
@@ -439,7 +439,7 @@ const setTags = selectedRows => {
 const setArtists = selectedRows => {
 	openModal({
 		modal: "bulkActions",
-		data: {
+		props: {
 			type: {
 				name: "artists",
 				action: "songs.editArtists",
@@ -455,7 +455,7 @@ const setArtists = selectedRows => {
 const setGenres = selectedRows => {
 	openModal({
 		modal: "bulkActions",
-		data: {
+		props: {
 			type: {
 				name: "genres",
 				action: "songs.editGenres",
@@ -510,25 +510,6 @@ const getDateFormatted = createdAt => {
 	return `${year}-${month}-${day} ${hour}:${minute}`;
 };
 
-const handleConfirmed = ({ action, params }) => {
-	if (typeof action === "function") {
-		if (params) action(params);
-		else action();
-	}
-};
-
-const confirmAction = ({ message, action, params }) => {
-	openModal({
-		modal: "confirm",
-		data: {
-			message,
-			action,
-			params,
-			onCompleted: handleConfirmed
-		}
-	});
-};
-
 onMounted(() => {
 	if (route.query.songId) {
 		socket.dispatch("songs.getSongFromSongId", route.query.songId, res => {
@@ -618,11 +599,14 @@ onMounted(() => {
 						v-if="hasPermission('songs.remove')"
 						class="button is-danger icon-with-button material-icons"
 						@click.prevent="
-							confirmAction({
-								message:
-									'Removing this song will remove it from all playlists and cause a ratings recalculation.',
-								action: deleteOne,
-								params: slotProps.item._id
+							openModal({
+								modal: 'confirm',
+								props: {
+									message:
+										'Removing this song will remove it from all playlists and cause a ratings recalculation.',
+									onCompleted: () =>
+										deleteOne(slotProps.item._id)
+								}
 							})
 						"
 						:disabled="slotProps.item.removed"
@@ -792,11 +776,14 @@ onMounted(() => {
 						v-if="hasPermission('songs.remove')"
 						class="material-icons delete-icon"
 						@click.prevent="
-							confirmAction({
-								message:
-									'Removing these songs will remove them from all playlists and cause a ratings recalculation.',
-								action: deleteMany,
-								params: slotProps.item
+							openModal({
+								modal: 'confirm',
+								props: {
+									message:
+										'Removing these songs will remove them from all playlists and cause a ratings recalculation.',
+									onCompleted: () =>
+										deleteMany(slotProps.item)
+								}
 							})
 						"
 						content="Delete Songs"

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

@@ -332,7 +332,7 @@ const remove = stationId => {
 					@click="
 						openModal({
 							modal: 'createStation',
-							data: { official: true }
+							props: { official: true }
 						})
 					"
 				>
@@ -356,7 +356,7 @@ const remove = stationId => {
 						@click="
 							openModal({
 								modal: 'manageStation',
-								data: {
+								props: {
 									stationId: slotProps.item._id,
 									sector: 'admin'
 								}

+ 1 - 1
frontend/src/pages/Admin/Users/Punishments.vue

@@ -224,7 +224,7 @@ const deactivatePunishment = punishmentId => {
 						@click="
 							openModal({
 								modal: 'viewPunishment',
-								data: { punishmentId: slotProps.item._id }
+								props: { punishmentId: slotProps.item._id }
 							})
 						"
 						:disabled="slotProps.item.removed"

+ 1 - 1
frontend/src/pages/Admin/Users/index.vue

@@ -204,7 +204,7 @@ const { openModal } = useModalsStore();
 const { hasPermission } = useUserAuthStore();
 
 const edit = userId => {
-	openModal({ modal: "editUser", data: { userId } });
+	openModal({ modal: "editUser", props: { userId } });
 };
 
 onMounted(() => {

+ 24 - 33
frontend/src/pages/Admin/YouTube/Videos.vue

@@ -208,7 +208,7 @@ const { openModal } = useModalsStore();
 const editOne = song => {
 	openModal({
 		modal: "editSong",
-		data: { song }
+		props: { song }
 	});
 };
 
@@ -218,7 +218,7 @@ const editMany = selectedRows => {
 		const songs = selectedRows.map(row => ({
 			youtubeId: row.youtubeId
 		}));
-		openModal({ modal: "editSong", data: { songs } });
+		openModal({ modal: "editSong", props: { songs } });
 	}
 };
 
@@ -228,7 +228,7 @@ const importAlbum = selectedRows => {
 		if (res.status === "success") {
 			openModal({
 				modal: "importAlbum",
-				data: { songs: res.data.songs }
+				props: { songs: res.data.songs }
 			});
 		} else new Toast("Could not get songs.");
 	});
@@ -265,25 +265,6 @@ const getDateFormatted = createdAt => {
 	const minute = `${date.getMinutes()}`.padStart(2, "0");
 	return `${year}-${month}-${day} ${hour}:${minute}`;
 };
-
-const handleConfirmed = ({ action, params }) => {
-	if (typeof action === "function") {
-		if (params) action(params);
-		else action();
-	}
-};
-
-const confirmAction = ({ message, action, params }) => {
-	openModal({
-		modal: "confirm",
-		data: {
-			message,
-			action,
-			params,
-			onCompleted: handleConfirmed
-		}
-	});
-};
 </script>
 
 <template>
@@ -315,7 +296,7 @@ const confirmAction = ({ message, action, params }) => {
 						@click="
 							openModal({
 								modal: 'viewYoutubeVideo',
-								data: {
+								props: {
 									videoId: slotProps.item._id
 								}
 							})
@@ -347,11 +328,14 @@ const confirmAction = ({ message, action, params }) => {
 						v-if="hasPermission('youtube.removeVideos')"
 						class="button is-danger icon-with-button material-icons"
 						@click.prevent="
-							confirmAction({
-								message:
-									'Removing this video will remove it from all playlists and cause a ratings recalculation.',
-								action: removeVideos,
-								params: slotProps.item._id
+							openModal({
+								modal: 'confirm',
+								props: {
+									message:
+										'Removing this video will remove it from all playlists and cause a ratings recalculation.',
+									onCompleted: () =>
+										removeVideos(slotProps.item._id)
+								}
 							})
 						"
 						:disabled="slotProps.item.removed"
@@ -438,11 +422,18 @@ const confirmAction = ({ message, action, params }) => {
 						v-if="hasPermission('youtube.removeVideos')"
 						class="material-icons delete-icon"
 						@click.prevent="
-							confirmAction({
-								message:
-									'Removing these videos will remove them from all playlists and cause a ratings recalculation.',
-								action: removeVideos,
-								params: slotProps.item.map(video => video._id)
+							openModal({
+								modal: 'confirm',
+								props: {
+									message:
+										'Removing these videos will remove them from all playlists and cause a ratings recalculation.',
+									onCompleted: () =>
+										removeVideos(
+											slotProps.item.map(
+												video => video._id
+											)
+										)
+								}
 							})
 						"
 						content="Delete Videos"

+ 1 - 1
frontend/src/pages/Admin/YouTube/index.vue

@@ -270,7 +270,7 @@ onMounted(() => {
 							@click="
 								openModal({
 									modal: 'viewApiRequest',
-									data: {
+									props: {
 										requestId: slotProps.item._id,
 										removeAction:
 											'youtube.removeStoredApiRequest'

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

@@ -451,7 +451,7 @@ onBeforeUnmount(() => {
 												@click.prevent="
 													openModal({
 														modal: 'manageStation',
-														data: {
+														props: {
 															stationId:
 																element._id,
 															sector: 'home'
@@ -469,7 +469,7 @@ onBeforeUnmount(() => {
 												@click.prevent="
 													openModal({
 														modal: 'manageStation',
-														data: {
+														props: {
 															stationId:
 																element._id,
 															sector: 'home'
@@ -732,7 +732,7 @@ onBeforeUnmount(() => {
 										@click.prevent="
 											openModal({
 												modal: 'manageStation',
-												data: {
+												props: {
 													stationId: station._id,
 													sector: 'home'
 												}
@@ -749,7 +749,7 @@ onBeforeUnmount(() => {
 										@click.prevent="
 											openModal({
 												modal: 'manageStation',
-												data: {
+												props: {
 													stationId: station._id,
 													sector: 'home'
 												}

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

@@ -69,7 +69,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: element._id }
+										props: { playlistId: element._id }
 									})
 								"
 								class="material-icons edit-icon"
@@ -82,7 +82,7 @@ onMounted(() => {
 								@click="
 									openModal({
 										modal: 'editPlaylist',
-										data: { playlistId: element._id }
+										props: { playlistId: element._id }
 									})
 								"
 								class="material-icons view-icon"

+ 1 - 1
frontend/src/pages/Settings/Tabs/Account.vue

@@ -149,7 +149,7 @@ onMounted(() => {
 	) {
 		openModal({
 			modal: "removeAccount",
-			data: { githubLinkConfirmed: true }
+			props: { githubLinkConfirmed: true }
 		});
 	}
 });

+ 0 - 13
frontend/src/stores/bulkActions.ts

@@ -1,13 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useBulkActionsStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`bulkActions-${modalUuid}`, {
-		state: () => ({
-			type: null
-		}),
-		actions: {
-			init({ type }) {
-				this.type = type;
-			}
-		}
-	})();

+ 0 - 25
frontend/src/stores/confirm.ts

@@ -1,25 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useConfirmStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`confirm-${modalUuid}`, {
-		state: () => ({
-			message: "",
-			onCompleted: null,
-			action: null,
-			params: null
-		}),
-		actions: {
-			init({ message, onCompleted, action, params }) {
-				this.message = message;
-				this.onCompleted = onCompleted;
-				this.action = action;
-				this.params = params;
-			},
-			confirm() {
-				this.onCompleted({
-					action: this.action,
-					params: this.params
-				});
-			}
-		}
-	})();

+ 0 - 13
frontend/src/stores/createStation.ts

@@ -1,13 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useCreateStationStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`createStation-${modalUuid}`, {
-		state: () => ({
-			official: false
-		}),
-		actions: {
-			init({ official }) {
-				this.official = !!official;
-			}
-		}
-	})();

+ 0 - 17
frontend/src/stores/editNews.ts

@@ -1,17 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useEditNewsStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`editNews-${modalUuid}`, {
-		state: () => ({
-			createNews: false,
-			newsId: null,
-			sector: "admin"
-		}),
-		actions: {
-			init({ createNews, newsId, sector }) {
-				if (createNews) this.createNews = createNews;
-				if (newsId) this.newsId = newsId;
-				if (sector) this.sector = sector;
-			}
-		}
-	})();

+ 0 - 5
frontend/src/stores/editPlaylist.ts

@@ -4,18 +4,13 @@ import { Playlist } from "@/types/playlist";
 export const useEditPlaylistStore = ({ modalUuid }: { modalUuid: string }) =>
 	defineStore(`editPlaylist-${modalUuid}`, {
 		state: (): {
-			playlistId: string;
 			tab: string;
 			playlist: Playlist;
 		} => ({
-			playlistId: null,
 			tab: "settings",
 			playlist: { songs: [] }
 		}),
 		actions: {
-			init({ playlistId }) {
-				this.playlistId = playlistId;
-			},
 			showTab(tab) {
 				this.tab = tab;
 			},

+ 0 - 21
frontend/src/stores/editUser.ts

@@ -1,21 +0,0 @@
-import { defineStore } from "pinia";
-import { User } from "@/types/user";
-
-export const useEditUserStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`editUser-${modalUuid}`, {
-		state: (): {
-			userId: string;
-			user: User;
-		} => ({
-			userId: null,
-			user: {}
-		}),
-		actions: {
-			init({ userId }) {
-				this.userId = userId;
-			},
-			setUser(user) {
-				this.user = user;
-			}
-		}
-	})();

+ 0 - 4
frontend/src/stores/importAlbum.ts

@@ -34,10 +34,6 @@ export const useImportAlbumStore = ({ modalUuid }: { modalUuid: string }) =>
 			prefillDiscogs: false
 		}),
 		actions: {
-			init({ songs }) {
-				this.originalPlaylistSongs = JSON.parse(JSON.stringify(songs));
-				this.playlistSongs = JSON.parse(JSON.stringify(songs));
-			},
 			showDiscogsTab(tab) {
 				this.discogsTab = tab;
 			},

+ 13 - 84
frontend/src/stores/modals.ts

@@ -3,26 +3,10 @@ import { defineStore } from "pinia";
 import utils from "@/utils";
 
 import { useWebsocketsStore } from "@/stores/websockets";
-import { useEditUserStore } from "@/stores/editUser";
-import { useEditSongStore } from "@/stores/editSong";
-import { useBulkActionsStore } from "@/stores/bulkActions";
-import { useConfirmStore } from "@/stores/confirm";
-import { useCreateStationStore } from "@/stores/createStation";
-import { useEditNewsStore } from "@/stores/editNews";
-import { useEditPlaylistStore } from "@/stores/editPlaylist";
-import { useImportAlbumStore } from "@/stores/importAlbum";
-import { useManageStationStore } from "@/stores/manageStation";
-import { useRemoveAccountStore } from "@/stores/removeAccount";
-import { useReportStore } from "@/stores/report";
-import { useViewApiRequestStore } from "@/stores/viewApiRequest";
-import { useViewPunishmentStore } from "@/stores/viewPunishment";
-import { useViewReportStore } from "@/stores/viewReport";
-import { useViewYoutubeVideoStore } from "@/stores/viewYoutubeVideo";
-import { useWhatIsNewStore } from "@/stores/whatIsNew";
 
 export const useModalsStore = defineStore("modals", {
 	state: (): {
-		modals: Record<string, string>;
+		modals: Record<string, { modal: string; props?: Record<string, any> }>;
 		activeModals: string[];
 		preventCloseUnsaved: Record<string, () => boolean>;
 		preventCloseCbs: Record<string, () => Promise<void>>;
@@ -36,7 +20,7 @@ export const useModalsStore = defineStore("modals", {
 		closeModal(uuid: string) {
 			Object.entries(this.modals).forEach(([_uuid, modal]) => {
 				if (uuid === _uuid) {
-					if (modal === "register")
+					if (modal.modal === "register")
 						lofig
 							.get("recaptcha.enabled")
 							.then((enabled: boolean) => {
@@ -61,7 +45,7 @@ export const useModalsStore = defineStore("modals", {
 					) {
 						this.openModal({
 							modal: "confirm",
-							data: {
+							props: {
 								message:
 									"You have unsaved changes. Are you sure you want to discard these changes and close the modal?",
 								onCompleted: close
@@ -71,76 +55,21 @@ export const useModalsStore = defineStore("modals", {
 				}
 			});
 		},
-		openModal(dataOrModal: string | { modal: string; data?: any }) {
+		openModal(
+			propsOrModal:
+				| string
+				| { modal: string; props?: Record<string, any> }
+		) {
 			const uuid = utils.guid();
-
 			let modal;
-			let data;
-			if (typeof dataOrModal === "string") modal = dataOrModal;
+			let props;
+			if (typeof propsOrModal === "string") modal = propsOrModal;
 			else {
-				modal = dataOrModal.modal;
-				data = dataOrModal.data;
-			}
-			this.modals[uuid] = modal;
-
-			let store;
-			switch (modal) {
-				case "editUser":
-					store = useEditUserStore({ modalUuid: uuid });
-					break;
-				case "editSong":
-					store = useEditSongStore({ modalUuid: uuid });
-					break;
-				case "bulkActions":
-					store = useBulkActionsStore({ modalUuid: uuid });
-					break;
-				case "confirm":
-					store = useConfirmStore({ modalUuid: uuid });
-					break;
-				case "createStation":
-					store = useCreateStationStore({ modalUuid: uuid });
-					break;
-				case "editNews":
-					store = useEditNewsStore({ modalUuid: uuid });
-					break;
-				case "editPlaylist":
-					store = useEditPlaylistStore({ modalUuid: uuid });
-					break;
-				case "importAlbum":
-					store = useImportAlbumStore({ modalUuid: uuid });
-					break;
-				case "manageStation":
-					store = useManageStationStore({ modalUuid: uuid });
-					break;
-				case "removeAccount":
-					store = useRemoveAccountStore({ modalUuid: uuid });
-					break;
-				case "report":
-					store = useReportStore({ modalUuid: uuid });
-					break;
-				case "viewApiRequest":
-					store = useViewApiRequestStore({ modalUuid: uuid });
-					break;
-				case "viewPunishment":
-					store = useViewPunishmentStore({ modalUuid: uuid });
-					break;
-				case "viewReport":
-					store = useViewReportStore({ modalUuid: uuid });
-					break;
-				case "viewYoutubeVideo":
-					store = useViewYoutubeVideoStore({ modalUuid: uuid });
-					break;
-				case "whatIsNew":
-					store = useWhatIsNewStore({ modalUuid: uuid });
-					break;
-				default:
-					break;
+				modal = propsOrModal.modal;
+				props = propsOrModal.props;
 			}
-			if (store && typeof store.init === "function" && data)
-				store.init(data);
-
+			this.modals[uuid] = { modal, props };
 			this.activeModals.push(uuid);
-
 			return { uuid };
 		},
 		closeCurrentModal() {

+ 0 - 15
frontend/src/stores/removeAccount.ts

@@ -1,15 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useRemoveAccountStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`removeAccount-${modalUuid}`, {
-		state: (): {
-			githubLinkConfirmed: boolean;
-		} => ({
-			githubLinkConfirmed: false
-		}),
-		actions: {
-			init({ githubLinkConfirmed }) {
-				this.githubLinkConfirmed = !!githubLinkConfirmed;
-			}
-		}
-	})();

+ 0 - 16
frontend/src/stores/report.ts

@@ -1,16 +0,0 @@
-import { defineStore } from "pinia";
-import { Song } from "@/types/song";
-
-export const useReportStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`report-${modalUuid}`, {
-		state: (): {
-			song: Song;
-		} => ({
-			song: {}
-		}),
-		actions: {
-			init({ song }) {
-				this.song = song;
-			}
-		}
-	})();

+ 0 - 37
frontend/src/stores/viewApiRequest.ts

@@ -1,37 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useViewApiRequestStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`viewApiRequest-${modalUuid}`, {
-		state: (): {
-			requestId: string;
-			request: {
-				_id: string;
-				url: string;
-				params: object;
-				results: any;
-				date: number;
-				quotaCost: number;
-			};
-			removeAction: string | null;
-		} => ({
-			requestId: null,
-			request: {
-				_id: null,
-				url: null,
-				params: {},
-				results: [],
-				date: null,
-				quotaCost: null
-			},
-			removeAction: null
-		}),
-		actions: {
-			init({ requestId, removeAction }) {
-				this.requestId = requestId;
-				this.removeAction = removeAction;
-			},
-			viewApiRequest(request) {
-				this.request = request;
-			}
-		}
-	})();

+ 0 - 27
frontend/src/stores/viewPunishment.ts

@@ -1,27 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useViewPunishmentStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`viewPunishment-${modalUuid}`, {
-		state: (): {
-			punishmentId: string;
-			punishment: {
-				_id: string;
-			};
-		} => ({
-			punishmentId: null,
-			punishment: {
-				_id: null
-			}
-		}),
-		actions: {
-			init({ punishmentId }: { punishmentId: string }) {
-				this.punishmentId = punishmentId;
-			},
-			viewPunishment(punishment) {
-				this.punishment = punishment;
-			},
-			deactivatePunishment() {
-				this.punishment.active = false;
-			}
-		}
-	})();

+ 0 - 15
frontend/src/stores/viewReport.ts

@@ -1,15 +0,0 @@
-import { defineStore } from "pinia";
-
-export const useViewReportStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`viewReport-${modalUuid}`, {
-		state: (): {
-			reportId: string;
-		} => ({
-			reportId: null
-		}),
-		actions: {
-			init({ reportId }: { reportId: string }) {
-				this.reportId = reportId;
-			}
-		}
-	})();

+ 0 - 16
frontend/src/stores/viewYoutubeVideo.ts

@@ -7,8 +7,6 @@ export const useViewYoutubeVideoStore = ({
 }) =>
 	defineStore(`viewYoutubeVideo-${modalUuid}`, {
 		state: (): {
-			videoId: string;
-			youtubeId: string;
 			video: {
 				_id: string;
 				youtubeId: string;
@@ -32,8 +30,6 @@ export const useViewYoutubeVideoStore = ({
 				showRateDropdown: boolean;
 			};
 		} => ({
-			videoId: null,
-			youtubeId: null,
 			video: {
 				_id: null,
 				youtubeId: null,
@@ -58,19 +54,7 @@ export const useViewYoutubeVideoStore = ({
 			}
 		}),
 		actions: {
-			init({
-				videoId,
-				youtubeId
-			}: {
-				videoId: string;
-				youtubeId: string;
-			}) {
-				this.videoId = videoId;
-				this.youtubeId = youtubeId;
-			},
 			viewYoutubeVideo(video) {
-				this.videoId = this.videoId || video._id;
-				this.youtubeId = video.youtubeId || video.youtubeId;
 				this.video = video;
 			},
 			updatePlayer(player) {

+ 0 - 16
frontend/src/stores/whatIsNew.ts

@@ -1,16 +0,0 @@
-import { NewsModel } from "@musare_types/models/News";
-import { defineStore } from "pinia";
-
-export const useWhatIsNewStore = ({ modalUuid }: { modalUuid: string }) =>
-	defineStore(`whatIsNew-${modalUuid}`, {
-		state: (): {
-			news: NewsModel;
-		} => ({
-			news: null
-		}),
-		actions: {
-			init({ news }: { news: NewsModel }) {
-				this.news = news;
-			}
-		}
-	})();