Browse Source

refactor(Draggable): Minor tweaks and fixes

Owen Diffey 2 years ago
parent
commit
9b8211daae

+ 0 - 16
frontend/src/components/AdvancedTable.vue

@@ -86,14 +86,6 @@ const count = ref(0);
 const sort = ref({});
 const orderedColumns = ref([]);
 const shownColumns = ref([]);
-const columnDragOptions = ref({
-	animation: 200,
-	group: "columns",
-	disabled: false,
-	ghostClass: "draggable-list-ghost",
-	filter: ".ignore-elements",
-	fallbackTolerance: 50
-});
 const editingFilters = ref([]);
 const appliedFilters = ref([]);
 const filterOperator = ref("or");
@@ -1531,10 +1523,6 @@ watch(selectedRows, (newSelectedRows, oldSelectedRows) => {
 								<draggable
 									v-model:list="orderedColumns"
 									item-key="name"
-									:options="{
-										...columnDragOptions,
-										group: 'dropdown-columns'
-									}"
 									@update="columnOrderChanged"
 									:attributes="{
 										class: column => ({
@@ -1620,10 +1608,6 @@ watch(selectedRows, (newSelectedRows, oldSelectedRows) => {
 							<draggable
 								v-model:list="orderedColumns"
 								item-key="name"
-								:options="{
-									...columnDragOptions,
-									handle: '.handle'
-								}"
 								@update="columnOrderChanged"
 								tag="th"
 								:attributes="{

+ 25 - 16
frontend/src/components/Draggable.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { PropType, onMounted, ref } from "vue";
+import { PropType, watch, onMounted, ref } from "vue";
 
 const props = defineProps({
 	name: { type: String, default: "" },
@@ -7,7 +7,6 @@ const props = defineProps({
 	list: { type: Array as PropType<any[]>, default: () => [] },
 	componentData: { type: Object, default: () => ({}) },
 	attributes: { type: Object, default: () => ({}) },
-	options: { type: Object, default: () => ({}) },
 	tag: { type: String, default: "div" },
 	class: { type: String, default: "" },
 	group: { type: String, default: "" },
@@ -15,8 +14,17 @@ const props = defineProps({
 });
 
 const mounted = ref(false);
+const data = ref([]);
+
+watch(
+	() => props.list,
+	list => {
+		data.value = list;
+	}
+);
 
 onMounted(() => {
+	data.value = props.list;
 	mounted.value = true;
 });
 
@@ -26,9 +34,8 @@ const itemOnMove = index => {
 	// Deletes the remove function for the dragging element
 	delete window.draggingItem.itemOnMove;
 	// Remove the item from the current list and return it
-	const list = props.list.slice();
-	const listItem = list.splice(index, 1)[0];
-	emit("update:list", list);
+	const listItem = data.value.splice(index, 1)[0];
+	emit("update:list", data.value);
 	return listItem;
 };
 
@@ -48,7 +55,7 @@ const onDragStart = (itemIndex: number, event: DragEvent) => {
 	window.draggingItem = {
 		itemIndex,
 		itemListName: props.name,
-		itemGroup: props.options.group,
+		itemGroup: props.group,
 		itemOnMove,
 		initialItemIndex: itemIndex,
 		initialItemListName: props.name
@@ -83,7 +90,7 @@ const onDragOver = (itemIndex: number, event: DragEvent) => {
 	if (fromIndex === toIndex && fromList === toList) return;
 
 	// If the dragging item isn't from the same group, don't continue
-	if (window.draggingItem.itemGroup !== props.options.group) return;
+	if (window.draggingItem.itemGroup !== props.group) return;
 
 	// Update the index and list name of the dragged item
 	window.draggingItem.itemIndex = toIndex;
@@ -95,18 +102,16 @@ const onDragOver = (itemIndex: number, event: DragEvent) => {
 		const item = window.draggingItem.itemOnMove(fromIndex);
 		// Define a new remove function for the dragging element
 		window.draggingItem.itemOnMove = itemOnMove;
-		window.draggingItem.itemGroup = props.options.group;
+		window.draggingItem.itemGroup = props.group;
 		// Add the item to the list at the new index
-		const list = props.list.slice();
-		list.splice(toIndex, 0, item);
-		emit("update:list", list);
+		data.value.splice(toIndex, 0, item);
+		emit("update:list", data.value);
 	}
 	// If the item is being reordered in the same list
 	else {
 		// Remove the item from the old position, and add the item to the new position
-		const list = props.list.slice();
-		list.splice(toIndex, 0, list.splice(fromIndex, 1)[0]);
-		emit("update:list", list);
+		data.value.splice(toIndex, 0, data.value.splice(fromIndex, 1)[0]);
+		emit("update:list", data.value);
 	}
 };
 // Gets called when the element that is being dragged is released
@@ -121,7 +126,11 @@ const onDrop = () => {
 		window.draggingItem;
 	if (itemListName === initialItemListName)
 		emit("update", {
-			moved: { oldIndex: initialItemIndex, newIndex: itemIndex }
+			moved: {
+				oldIndex: initialItemIndex,
+				newIndex: itemIndex,
+				updatedList: data.value
+			}
 		});
 	else emit("update", {});
 	delete window.draggingItem;
@@ -159,7 +168,7 @@ const hasSlotContent = (slot, slotProps = {}) => {
 </script>
 
 <template>
-	<template v-for="(item, itemIndex) in list" :key="item[itemKey]">
+	<template v-for="(item, itemIndex) in data" :key="item[itemKey]">
 		<component
 			v-if="hasSlotContent($slots.item, { element: item })"
 			:is="tag"

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

@@ -55,7 +55,6 @@ const {
 	Draggable,
 	drag,
 	playlists,
-	dragOptions,
 	savePlaylistOrder,
 	orderOfPlaylists,
 	myUserId,
@@ -819,7 +818,6 @@ onMounted(() => {
 						:name="`my-playlists-${type}-${sector}-${modalUuid}`"
 						v-model:list="playlists"
 						item-key="_id"
-						:options="dragOptions"
 						@start="drag = true"
 						@end="drag = false"
 						@update="savePlaylistOrder"

+ 0 - 8
frontend/src/components/Queue.vue

@@ -63,13 +63,6 @@ const isOwnerOnly = () =>
 
 const isAdminOnly = () => loggedIn.value && userRole.value === "admin";
 
-const dragOptions = computed(() => ({
-	animation: 200,
-	group: "queue",
-	disabled: !(isAdminOnly() || isOwnerOnly()),
-	ghostClass: "draggable-list-ghost"
-}));
-
 const removeFromQueue = youtubeId => {
 	socket.dispatch(
 		"stations.removeFromQueue",
@@ -158,7 +151,6 @@ onUpdated(() => {
 				:name="`queue-${modalUuid}-${sector}`"
 				v-model:list="queue"
 				item-key="_id"
-				:options="dragOptions"
 				@start="drag = true"
 				@end="drag = false"
 				@update="repositionSongInQueue"

+ 71 - 90
frontend/src/components/modals/EditPlaylist/index.vue

@@ -92,7 +92,7 @@ const isOwner = () =>
 const repositionSong = ({ moved }) => {
 	const { oldIndex, newIndex } = moved;
 	if (oldIndex === newIndex) return; // we only need to update when song is moved
-	const song = playlistSongs.value[oldIndex];
+	const song = playlistSongs.value[newIndex];
 	socket.dispatch(
 		"playlists.repositionSong",
 		playlist.value._id,
@@ -421,85 +421,79 @@ onBeforeUnmount(() => {
 							:disabled="!isEditable()"
 						>
 							<template #item="{ element, index }">
-								<div class="menu-list scrollable-list">
-									<song-item
-										:song="element"
-										:ref="
-											el =>
-												(songItems[
-													`song-item-${index}`
-												] = el)
-										"
-									>
-										<template #tippyActions>
-											<i
-												class="material-icons add-to-queue-icon"
-												v-if="
-													station &&
-													station.requests &&
-													station.requests.enabled &&
+								<song-item
+									:song="element"
+									:ref="
+										el =>
+											(songItems[`song-item-${index}`] =
+												el)
+									"
+								>
+									<template #tippyActions>
+										<i
+											class="material-icons add-to-queue-icon"
+											v-if="
+												station &&
+												station.requests &&
+												station.requests.enabled &&
+												(station.requests.access ===
+													'user' ||
 													(station.requests.access ===
-														'user' ||
-														(station.requests
-															.access ===
-															'owner' &&
-															(userRole ===
-																'admin' ||
-																station.owner ===
-																	userId)))
-												"
-												@click="
-													addSongToQueue(
-														element.youtubeId
-													)
-												"
-												content="Add Song to Queue"
-												v-tippy
-												>queue</i
-											>
-											<quick-confirm
-												v-if="
-													userId ===
-														playlist.createdBy ||
-													isEditable()
-												"
-												placement="left"
-												@confirm="
-													removeSongFromPlaylist(
-														element.youtubeId
-													)
-												"
-											>
-												<i
-													class="material-icons delete-icon"
-													content="Remove Song from Playlist"
-													v-tippy
-													>delete_forever</i
-												>
-											</quick-confirm>
+														'owner' &&
+														(userRole === 'admin' ||
+															station.owner ===
+																userId)))
+											"
+											@click="
+												addSongToQueue(
+													element.youtubeId
+												)
+											"
+											content="Add Song to Queue"
+											v-tippy
+											>queue</i
+										>
+										<quick-confirm
+											v-if="
+												userId === playlist.createdBy ||
+												isEditable()
+											"
+											placement="left"
+											@confirm="
+												removeSongFromPlaylist(
+													element.youtubeId
+												)
+											"
+										>
 											<i
-												class="material-icons"
-												v-if="isEditable() && index > 0"
-												@click="moveSongToTop(index)"
-												content="Move to top of Playlist"
+												class="material-icons delete-icon"
+												content="Remove Song from Playlist"
 												v-tippy
-												>vertical_align_top</i
+												>delete_forever</i
 											>
-											<i
-												v-if="
-													isEditable() &&
-													playlistSongs.length - 1 !==
-														index
-												"
-												@click="moveSongToBottom(index)"
-												class="material-icons"
-												content="Move to bottom of Playlist"
-												v-tippy
-												>vertical_align_bottom</i
-											>
-										</template>
-									</song-item>
-								</div>
+										</quick-confirm>
+										<i
+											class="material-icons"
+											v-if="isEditable() && index > 0"
+											@click="moveSongToTop(index)"
+											content="Move to top of Playlist"
+											v-tippy
+											>vertical_align_top</i
+										>
+										<i
+											v-if="
+												isEditable() &&
+												playlistSongs.length - 1 !==
+													index
+											"
+											@click="moveSongToBottom(index)"
+											class="material-icons"
+											content="Move to bottom of Playlist"
+											v-tippy
+											>vertical_align_bottom</i
+										>
+									</template>
+								</song-item>
 							</template>
 						</draggable>
 						<p v-else-if="gettingSongs" class="nothing-here-text">
@@ -586,19 +580,6 @@ onBeforeUnmount(() => {
 	}
 }
 
-.menu-list li {
-	display: flex;
-	justify-content: space-between;
-
-	&:not(:last-of-type) {
-		margin-bottom: 10px;
-	}
-
-	a {
-		display: flex;
-	}
-}
-
 .controls {
 	display: flex;
 
@@ -697,7 +678,7 @@ onBeforeUnmount(() => {
 
 	.right-section {
 		#rearrange-songs-section {
-			.scrollable-list:not(:last-of-type) {
+			:deep(.draggable-item:not(:last-of-type)) {
 				margin-bottom: 10px;
 			}
 		}

+ 0 - 7
frontend/src/composables/useSortablePlaylists.ts

@@ -24,12 +24,6 @@ export const useSortablePlaylists = () => {
 		}
 	});
 	const isCurrentUser = computed(() => userId.value === myUserId.value);
-	const dragOptions = computed(() => ({
-		animation: 200,
-		group: "playlists",
-		disabled: !isCurrentUser.value,
-		ghostClass: "draggable-list-ghost"
-	}));
 
 	const { socket } = useWebsocketsStore();
 
@@ -193,7 +187,6 @@ export const useSortablePlaylists = () => {
 		userId,
 		isCurrentUser,
 		playlists,
-		dragOptions,
 		orderOfPlaylists,
 		myUserId,
 		savePlaylistOrder,

+ 5 - 13
frontend/src/pages/Home.vue

@@ -77,15 +77,6 @@ const filteredStations = computed(() => {
 		);
 });
 
-const dragOptions = computed(() => ({
-	animation: 200,
-	group: "favoriteStations",
-	disabled: false,
-	ghostClass: "draggable-list-ghost",
-	filter: ".ignore-elements",
-	fallbackTolerance: 50
-}));
-
 const favoriteStations = computed(() =>
 	filteredStations.value
 		.filter(station => station.isFavorited === true)
@@ -155,10 +146,11 @@ const unfavoriteStation = stationId => {
 	});
 };
 
-const changeFavoriteOrder = () => {
+const changeFavoriteOrder = ({ moved }) => {
+	const { updatedList } = moved;
 	socket.dispatch(
 		"users.updateOrderOfFavoriteStations",
-		favoriteStations.value.map(station => station._id),
+		updatedList.map(station => station._id),
 		res => new Toast(res.message)
 	);
 };
@@ -397,8 +389,8 @@ onBeforeUnmount(() => {
 				<draggable
 					item-key="_id"
 					name="home-favorite-stations"
-					v-model:list="favoriteStations"
-					:options="dragOptions"
+					tag="span"
+					:list="favoriteStations"
 					@update="changeFavoriteOrder"
 				>
 					<template #item="{ element }">

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

@@ -12,15 +12,8 @@ const props = defineProps({
 	username: { type: String, default: "" }
 });
 
-const {
-	Draggable,
-	drag,
-	userId,
-	isCurrentUser,
-	playlists,
-	dragOptions,
-	savePlaylistOrder
-} = useSortablePlaylists();
+const { Draggable, drag, userId, isCurrentUser, playlists, savePlaylistOrder } =
+	useSortablePlaylists();
 
 const { openModal } = useModalsStore();
 
@@ -55,7 +48,6 @@ onMounted(() => {
 				v-if="playlists.length > 0"
 				v-model:list="playlists"
 				item-key="_id"
-				:options="dragOptions"
 				@start="drag = true"
 				@end="drag = false"
 				@update="savePlaylistOrder"