Browse Source

feat: added support for adding items to empty lists in custom draggable

Kristian Vos 2 years ago
parent
commit
9b6182be5e
2 changed files with 41 additions and 26 deletions
  1. 23 10
      frontend/src/components/Draggable.vue
  2. 18 16
      frontend/src/components/modals/ImportAlbum.vue

+ 23 - 10
frontend/src/components/Draggable.vue

@@ -79,15 +79,21 @@ const onDragStart = (itemIndex: number, event: DragEvent) => {
 };
 
 // When a dragging element hovers over another draggable element, this gets triggered, usually many times in a second
-const onDragOver = (itemIndex: number, event: DragEvent) => {
-	const getDraggableElement = (element: any): any =>
-		element.classList.contains("draggable-item")
+const onDragOver = (itemIndex: number, event: DragEvent, push = false) => {
+	const getDraggableElement = (element: HTMLElement): any =>
+		element.classList.contains("draggable-item") ||
+		element.classList.contains("empty-list-placeholder")
 			? element
 			: getDraggableElement(element.parentElement);
-	const draggableElement = getDraggableElement(event.target);
+	const draggableElement = getDraggableElement(event.target as HTMLElement);
 	const { draggable } = draggableElement;
 
-	if (props.disabled === true || !draggable || !window.draggingItem) return;
+	if (
+		props.disabled === true ||
+		(!draggable && !push) ||
+		!window.draggingItem
+	)
+		return;
 
 	// The index and list uuid of the item that is being dragged, stored in window since it can come from another list as well
 	const fromIndex = window.draggingItem.itemIndex;
@@ -96,9 +102,6 @@ const onDragOver = (itemIndex: number, event: DragEvent) => {
 	const toIndex = itemIndex;
 	const toList = listUuid.value;
 
-	// Don't continue if fromIndex is invalid
-	if (fromIndex === -1 || toIndex === -1) return;
-
 	// If the item hasn't changed position in the same list, don't continue
 	if (fromIndex === toIndex && fromList === toList) return;
 
@@ -121,7 +124,8 @@ const onDragOver = (itemIndex: number, event: DragEvent) => {
 		window.draggingItem.itemOnMove = itemOnMove;
 		window.draggingItem.itemGroup = props.group;
 		// Add the item to the list at the new index
-		data.value.splice(toIndex, 0, item);
+		if (push) data.value.push(item);
+		else data.value.splice(toIndex, 0, item);
 		emit("update:list", data.value);
 	}
 	// If the item is being reordered in the same list
@@ -188,7 +192,7 @@ const hasSlotContent = (slot: SlotType | undefined, slotProps = {}) => {
 <template>
 	<template v-for="(item, itemIndex) in data" :key="item[itemKey]">
 		<component
-			v-if="$slots.item && hasSlotContent($slots.item, { element: item })"
+			v-if="hasSlotContent($slots.item, { element: item })"
 			:is="tag"
 			:draggable="
 				typeof disabled === 'function' ? !disabled(item) : !disabled
@@ -206,6 +210,12 @@ const hasSlotContent = (slot: SlotType | undefined, slotProps = {}) => {
 			<slot name="item" :element="item" :index="itemIndex"></slot>
 		</component>
 	</template>
+	<div
+		v-if="data.length === 0"
+		class="empty-list-placeholder"
+		@dragover.prevent="onDragOver(0, $event, true)"
+		@drop.prevent
+	></div>
 </template>
 
 <style scoped>
@@ -215,4 +225,7 @@ const hasSlotContent = (slot: SlotType | undefined, slotProps = {}) => {
 .draggable-item:not(:last-of-type) {
 	margin-bottom: 10px;
 }
+.empty-list-placeholder {
+	flex: 1;
+}
 </style>

+ 18 - 16
frontend/src/components/modals/ImportAlbum.vue

@@ -400,7 +400,7 @@ onBeforeUnmount(() => {
 
 <template>
 	<div>
-		<modal title="Import Album" class="import-album-modal">
+		<modal title="Import Album" class="import-album-modal" size="wide">
 			<template #body>
 				<div class="tabs-container discogs-container">
 					<div class="tab-selection">
@@ -677,21 +677,22 @@ onBeforeUnmount(() => {
 							<span>{{ track.position }}.</span>
 							<p>{{ track.title }}</p>
 						</div>
-						<draggable
-							class="track-box-songs-drag-area"
-							v-model:list="trackSongs[index]"
-							:data-track-index="index"
-							item-key="_id"
-							:group="`import-album-${modalUuid}-songs`"
-						>
-							<template #item="{ element }">
-								<song-item
-									:key="`track-song-${element._id}`"
-									:song="element"
-								>
-								</song-item>
-							</template>
-						</draggable>
+						<!-- :data-track-index="index" -->
+						<div class="track-box-songs-drag-area">
+							<draggable
+								v-model:list="trackSongs[index]"
+								item-key="_id"
+								:group="`import-album-${modalUuid}-songs`"
+							>
+								<template #item="{ element }">
+									<song-item
+										:key="`track-song-${element._id}`"
+										:song="element"
+									>
+									</song-item>
+								</template>
+							</draggable>
+						</div>
 					</div>
 				</div>
 			</template>
@@ -1152,6 +1153,7 @@ onBeforeUnmount(() => {
 		.track-box-songs-drag-area {
 			flex: 1;
 			min-height: 100px;
+			display: flex;
 		}
 	}
 }