فهرست منبع

refactor: converted youtube videos admin page to composition API

Kristian Vos 2 سال پیش
والد
کامیت
2d914873a7
1فایلهای تغییر یافته به همراه250 افزوده شده و 256 حذف شده
  1. 250 256
      frontend/src/pages/Admin/YouTube/Videos.vue

+ 250 - 256
frontend/src/pages/Admin/YouTube/Videos.vue

@@ -1,3 +1,251 @@
+<script setup lang="ts">
+import { ref } from "vue";
+import { useStore } from "vuex";
+
+import Toast from "toasters";
+
+import AdvancedTable from "@/components/AdvancedTable.vue";
+import RunJobDropdown from "@/components/RunJobDropdown.vue";
+
+const store = useStore();
+
+const { socket } = store.state.websockets;
+
+const columnDefault = ref({
+	sortable: true,
+	hidable: true,
+	defaultVisibility: "shown",
+	draggable: true,
+	resizable: true,
+	minWidth: 200,
+	maxWidth: 600
+});
+const columns = ref([
+	{
+		name: "options",
+		displayName: "Options",
+		properties: ["_id", "youtubeId"],
+		sortable: false,
+		hidable: false,
+		resizable: false,
+		minWidth: 129,
+		defaultWidth: 129
+	},
+	{
+		name: "thumbnailImage",
+		displayName: "Thumb",
+		properties: ["youtubeId"],
+		sortable: false,
+		minWidth: 75,
+		defaultWidth: 75,
+		maxWidth: 75,
+		resizable: false
+	},
+	{
+		name: "youtubeId",
+		displayName: "YouTube ID",
+		properties: ["youtubeId"],
+		sortProperty: "youtubeId",
+		minWidth: 120,
+		defaultWidth: 120
+	},
+	{
+		name: "_id",
+		displayName: "Video ID",
+		properties: ["_id"],
+		sortProperty: "_id",
+		minWidth: 215,
+		defaultWidth: 215
+	},
+	{
+		name: "title",
+		displayName: "Title",
+		properties: ["title"],
+		sortProperty: "title"
+	},
+	{
+		name: "author",
+		displayName: "Author",
+		properties: ["author"],
+		sortProperty: "author"
+	},
+	{
+		name: "duration",
+		displayName: "Duration",
+		properties: ["duration"],
+		sortProperty: "duration",
+		defaultWidth: 200
+	},
+	{
+		name: "createdAt",
+		displayName: "Created At",
+		properties: ["createdAt"],
+		sortProperty: "createdAt",
+		defaultWidth: 200,
+		defaultVisibility: "hidden"
+	}
+]);
+const filters = ref([
+	{
+		name: "_id",
+		displayName: "Video ID",
+		property: "_id",
+		filterTypes: ["exact"],
+		defaultFilterType: "exact"
+	},
+	{
+		name: "youtubeId",
+		displayName: "YouTube ID",
+		property: "youtubeId",
+		filterTypes: ["contains", "exact", "regex"],
+		defaultFilterType: "contains"
+	},
+	{
+		name: "title",
+		displayName: "Title",
+		property: "title",
+		filterTypes: ["contains", "exact", "regex"],
+		defaultFilterType: "contains"
+	},
+	{
+		name: "author",
+		displayName: "Author",
+		property: "author",
+		filterTypes: ["contains", "exact", "regex"],
+		defaultFilterType: "contains"
+	},
+	{
+		name: "duration",
+		displayName: "Duration",
+		property: "duration",
+		filterTypes: [
+			"numberLesserEqual",
+			"numberLesser",
+			"numberGreater",
+			"numberGreaterEqual",
+			"numberEquals"
+		],
+		defaultFilterType: "numberLesser"
+	},
+	{
+		name: "createdAt",
+		displayName: "Created At",
+		property: "createdAt",
+		filterTypes: ["datetimeBefore", "datetimeAfter"],
+		defaultFilterType: "datetimeBefore"
+	},
+	{
+		name: "importJob",
+		displayName: "Import Job",
+		property: "importJob",
+		filterTypes: ["special"],
+		defaultFilterType: "special"
+	}
+]);
+const events = ref({
+	adminRoom: "youtubeVideos",
+	updated: {
+		event: "admin.youtubeVideo.updated",
+		id: "youtubeVideo._id",
+		item: "youtubeVideo"
+	},
+	removed: {
+		event: "admin.youtubeVideo.removed",
+		id: "videoId"
+	}
+});
+const jobs = ref([
+	{
+		name: "Recalculate all ratings",
+		socket: "media.recalculateAllRatings"
+	}
+]);
+
+const openModal = payload =>
+	store.dispatch("modalVisibility/openModal", payload);
+
+const editOne = song => {
+	openModal({
+		modal: "editSong",
+		data: { song }
+	});
+};
+
+const editMany = selectedRows => {
+	if (selectedRows.length === 1) editOne(selectedRows[0]);
+	else {
+		const songs = selectedRows.map(row => ({
+			youtubeId: row.youtubeId
+		}));
+		openModal({ modal: "editSongs", data: { songs } });
+	}
+};
+
+const importAlbum = selectedRows => {
+	const youtubeIds = selectedRows.map(({ youtubeId }) => youtubeId);
+	socket.dispatch("songs.getSongsFromYoutubeIds", youtubeIds, res => {
+		if (res.status === "success") {
+			openModal({
+				modal: "importAlbum",
+				data: { songs: res.data.songs }
+			});
+		} else new Toast("Could not get songs.");
+	});
+};
+
+const removeVideos = videoIds => {
+	let id;
+	let title;
+
+	socket.dispatch("youtube.removeVideos", videoIds, {
+		cb: () => {},
+		onProgress: res => {
+			if (res.status === "started") {
+				id = res.id;
+				title = res.title;
+			}
+
+			if (id)
+				// TODO fix
+				setJob({
+					id,
+					name: title,
+					...res
+				});
+		}
+	});
+};
+
+const getDateFormatted = createdAt => {
+	const date = new Date(createdAt);
+	const year = date.getFullYear();
+	const month = `${date.getMonth() + 1}`.padStart(2, 0);
+	const day = `${date.getDate()}`.padStart(2, 0);
+	const hour = `${date.getHours()}`.padStart(2, 0);
+	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>
 	<div class="admin-tab container">
 		<page-metadata title="Admin | YouTube | Videos" />
@@ -53,7 +301,7 @@
 							confirmAction({
 								message:
 									'Removing this video will remove it from all playlists and cause a ratings recalculation.',
-								action: 'removeVideos',
+								action: removeVideos,
 								params: slotProps.item._id
 							})
 						"
@@ -130,7 +378,7 @@
 							confirmAction({
 								message:
 									'Removing these videos will remove them from all playlists and cause a ratings recalculation.',
-								action: 'removeVideos',
+								action: removeVideos,
 								params: slotProps.item.map(video => video._id)
 							})
 						"
@@ -146,260 +394,6 @@
 	</div>
 </template>
 
-<script>
-import { mapActions, mapGetters } from "vuex";
-
-import Toast from "toasters";
-
-import AdvancedTable from "@/components/AdvancedTable.vue";
-import RunJobDropdown from "@/components/RunJobDropdown.vue";
-
-export default {
-	components: {
-		AdvancedTable,
-		RunJobDropdown
-	},
-	data() {
-		return {
-			columnDefault: {
-				sortable: true,
-				hidable: true,
-				defaultVisibility: "shown",
-				draggable: true,
-				resizable: true,
-				minWidth: 200,
-				maxWidth: 600
-			},
-			columns: [
-				{
-					name: "options",
-					displayName: "Options",
-					properties: ["_id", "youtubeId"],
-					sortable: false,
-					hidable: false,
-					resizable: false,
-					minWidth: 129,
-					defaultWidth: 129
-				},
-				{
-					name: "thumbnailImage",
-					displayName: "Thumb",
-					properties: ["youtubeId"],
-					sortable: false,
-					minWidth: 75,
-					defaultWidth: 75,
-					maxWidth: 75,
-					resizable: false
-				},
-				{
-					name: "youtubeId",
-					displayName: "YouTube ID",
-					properties: ["youtubeId"],
-					sortProperty: "youtubeId",
-					minWidth: 120,
-					defaultWidth: 120
-				},
-				{
-					name: "_id",
-					displayName: "Video ID",
-					properties: ["_id"],
-					sortProperty: "_id",
-					minWidth: 215,
-					defaultWidth: 215
-				},
-				{
-					name: "title",
-					displayName: "Title",
-					properties: ["title"],
-					sortProperty: "title"
-				},
-				{
-					name: "author",
-					displayName: "Author",
-					properties: ["author"],
-					sortProperty: "author"
-				},
-				{
-					name: "duration",
-					displayName: "Duration",
-					properties: ["duration"],
-					sortProperty: "duration",
-					defaultWidth: 200
-				},
-				{
-					name: "createdAt",
-					displayName: "Created At",
-					properties: ["createdAt"],
-					sortProperty: "createdAt",
-					defaultWidth: 200,
-					defaultVisibility: "hidden"
-				}
-			],
-			filters: [
-				{
-					name: "_id",
-					displayName: "Video ID",
-					property: "_id",
-					filterTypes: ["exact"],
-					defaultFilterType: "exact"
-				},
-				{
-					name: "youtubeId",
-					displayName: "YouTube ID",
-					property: "youtubeId",
-					filterTypes: ["contains", "exact", "regex"],
-					defaultFilterType: "contains"
-				},
-				{
-					name: "title",
-					displayName: "Title",
-					property: "title",
-					filterTypes: ["contains", "exact", "regex"],
-					defaultFilterType: "contains"
-				},
-				{
-					name: "author",
-					displayName: "Author",
-					property: "author",
-					filterTypes: ["contains", "exact", "regex"],
-					defaultFilterType: "contains"
-				},
-				{
-					name: "duration",
-					displayName: "Duration",
-					property: "duration",
-					filterTypes: [
-						"numberLesserEqual",
-						"numberLesser",
-						"numberGreater",
-						"numberGreaterEqual",
-						"numberEquals"
-					],
-					defaultFilterType: "numberLesser"
-				},
-				{
-					name: "createdAt",
-					displayName: "Created At",
-					property: "createdAt",
-					filterTypes: ["datetimeBefore", "datetimeAfter"],
-					defaultFilterType: "datetimeBefore"
-				},
-				{
-					name: "importJob",
-					displayName: "Import Job",
-					property: "importJob",
-					filterTypes: ["special"],
-					defaultFilterType: "special"
-				}
-			],
-			events: {
-				adminRoom: "youtubeVideos",
-				updated: {
-					event: "admin.youtubeVideo.updated",
-					id: "youtubeVideo._id",
-					item: "youtubeVideo"
-				},
-				removed: {
-					event: "admin.youtubeVideo.removed",
-					id: "videoId"
-				}
-			},
-			jobs: [
-				{
-					name: "Recalculate all ratings",
-					socket: "media.recalculateAllRatings"
-				}
-			]
-		};
-	},
-	computed: {
-		...mapGetters({
-			socket: "websockets/getSocket"
-		})
-	},
-	methods: {
-		editOne(song) {
-			this.openModal({
-				modal: "editSong",
-				data: { song }
-			});
-		},
-		editMany(selectedRows) {
-			if (selectedRows.length === 1) this.editOne(selectedRows[0]);
-			else {
-				const songs = selectedRows.map(row => ({
-					youtubeId: row.youtubeId
-				}));
-				this.openModal({ modal: "editSongs", data: { songs } });
-			}
-		},
-		importAlbum(selectedRows) {
-			const youtubeIds = selectedRows.map(({ youtubeId }) => youtubeId);
-			this.socket.dispatch(
-				"songs.getSongsFromYoutubeIds",
-				youtubeIds,
-				res => {
-					if (res.status === "success") {
-						this.openModal({
-							modal: "importAlbum",
-							data: { songs: res.data.songs }
-						});
-					} else new Toast("Could not get songs.");
-				}
-			);
-		},
-		removeVideos(videoIds) {
-			let id;
-			let title;
-
-			this.socket.dispatch("youtube.removeVideos", videoIds, {
-				cb: () => {},
-				onProgress: res => {
-					if (res.status === "started") {
-						id = res.id;
-						title = res.title;
-					}
-
-					if (id)
-						this.setJob({
-							id,
-							name: title,
-							...res
-						});
-				}
-			});
-		},
-		getDateFormatted(createdAt) {
-			const date = new Date(createdAt);
-			const year = date.getFullYear();
-			const month = `${date.getMonth() + 1}`.padStart(2, 0);
-			const day = `${date.getDate()}`.padStart(2, 0);
-			const hour = `${date.getHours()}`.padStart(2, 0);
-			const minute = `${date.getMinutes()}`.padStart(2, 0);
-			return `${year}-${month}-${day} ${hour}:${minute}`;
-		},
-		confirmAction({ message, action, params }) {
-			this.openModal({
-				modal: "confirm",
-				data: {
-					message,
-					action,
-					params,
-					onCompleted: this.handleConfirmed
-				}
-			});
-		},
-		handleConfirmed({ action, params }) {
-			if (typeof this[action] === "function") {
-				if (params) this[action](params);
-				else this[action]();
-			}
-		},
-		...mapActions("modalVisibility", ["openModal"])
-	}
-};
-</script>
-
 <style lang="less" scoped>
 :deep(.song-thumbnail) {
 	width: 50px;