|
@@ -1,6 +1,5 @@
|
|
|
<script setup lang="ts">
|
|
|
import { defineAsyncComponent, ref, computed, onUpdated } from "vue";
|
|
|
-import { Sortable } from "sortablejs-vue3";
|
|
|
import Toast from "toasters";
|
|
|
import { storeToRefs } from "pinia";
|
|
|
import { useWebsocketsStore } from "@/stores/websockets";
|
|
@@ -14,6 +13,9 @@ const SongItem = defineAsyncComponent(
|
|
|
const QuickConfirm = defineAsyncComponent(
|
|
|
() => import("@/components/QuickConfirm.vue")
|
|
|
);
|
|
|
+const Draggable = defineAsyncComponent(
|
|
|
+ () => import("@/components/Draggable.vue")
|
|
|
+);
|
|
|
|
|
|
const props = defineProps({
|
|
|
modalUuid: { type: String, default: "" },
|
|
@@ -27,12 +29,6 @@ const manageStationStore = useManageStationStore(props);
|
|
|
|
|
|
const { loggedIn, userId, role: userRole } = storeToRefs(userAuthStore);
|
|
|
|
|
|
-const repositionSongInList = payload => {
|
|
|
- if (props.sector === "manageStation")
|
|
|
- return manageStationStore.repositionSongInList(payload);
|
|
|
- return stationStore.repositionSongInList(payload);
|
|
|
-};
|
|
|
-
|
|
|
const actionableButtonVisible = ref(false);
|
|
|
const drag = ref(false);
|
|
|
const songItems = ref([]);
|
|
@@ -87,9 +83,10 @@ const removeFromQueue = youtubeId => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-const repositionSongInQueue = ({ oldIndex, newIndex }) => {
|
|
|
+const repositionSongInQueue = ({ moved }) => {
|
|
|
+ const { oldIndex, newIndex } = moved;
|
|
|
if (oldIndex === newIndex) return; // we only need to update when song is moved
|
|
|
- const song = queue.value[oldIndex];
|
|
|
+ const song = queue.value[newIndex];
|
|
|
socket.dispatch(
|
|
|
"stations.repositionSongInQueue",
|
|
|
station.value._id,
|
|
@@ -101,30 +98,38 @@ const repositionSongInQueue = ({ oldIndex, newIndex }) => {
|
|
|
res => {
|
|
|
new Toast({ content: res.message, timeout: 4000 });
|
|
|
if (res.status !== "success")
|
|
|
- repositionSongInList({
|
|
|
- ...song,
|
|
|
+ queue.value.splice(
|
|
|
oldIndex,
|
|
|
- newIndex
|
|
|
- });
|
|
|
+ 0,
|
|
|
+ queue.value.splice(newIndex, 1)[0]
|
|
|
+ );
|
|
|
}
|
|
|
);
|
|
|
};
|
|
|
|
|
|
const moveSongToTop = index => {
|
|
|
songItems.value[`song-item-${index}`].$refs.songActions.tippy.hide();
|
|
|
-
|
|
|
+ queue.value.splice(0, 0, queue.value.splice(index, 1)[0]);
|
|
|
repositionSongInQueue({
|
|
|
- oldIndex: index,
|
|
|
- newIndex: 0
|
|
|
+ moved: {
|
|
|
+ oldIndex: index,
|
|
|
+ newIndex: 0
|
|
|
+ }
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const moveSongToBottom = index => {
|
|
|
songItems.value[`song-item-${index}`].$refs.songActions.tippy.hide();
|
|
|
-
|
|
|
+ queue.value.splice(
|
|
|
+ queue.value.length - 1,
|
|
|
+ 0,
|
|
|
+ queue.value.splice(index, 1)[0]
|
|
|
+ );
|
|
|
repositionSongInQueue({
|
|
|
- oldIndex: index,
|
|
|
- newIndex: queue.value.length
|
|
|
+ moved: {
|
|
|
+ oldIndex: index,
|
|
|
+ newIndex: queue.value.length - 1
|
|
|
+ }
|
|
|
});
|
|
|
};
|
|
|
|
|
@@ -146,24 +151,23 @@ onUpdated(() => {
|
|
|
'scrollable-list': true
|
|
|
}"
|
|
|
>
|
|
|
- <Sortable
|
|
|
+ <draggable
|
|
|
:component-data="{
|
|
|
name: !drag ? 'draggable-list-transition' : null
|
|
|
}"
|
|
|
- :list="queue"
|
|
|
+ :name="`queue-${modalUuid}-${sector}`"
|
|
|
+ v-model:list="queue"
|
|
|
item-key="_id"
|
|
|
:options="dragOptions"
|
|
|
@start="drag = true"
|
|
|
@end="drag = false"
|
|
|
@update="repositionSongInQueue"
|
|
|
+ :disabled="!(isAdminOnly() || isOwnerOnly())"
|
|
|
>
|
|
|
<template #item="{ element, index }">
|
|
|
<song-item
|
|
|
:song="element"
|
|
|
:requested-by="true"
|
|
|
- :class="{
|
|
|
- 'item-draggable': isAdminOnly() || isOwnerOnly()
|
|
|
- }"
|
|
|
:disabled-actions="[]"
|
|
|
:ref="el => (songItems[`song-item-${index}`] = el)"
|
|
|
>
|
|
@@ -202,7 +206,7 @@ onUpdated(() => {
|
|
|
</template>
|
|
|
</song-item>
|
|
|
</template>
|
|
|
- </Sortable>
|
|
|
+ </draggable>
|
|
|
</div>
|
|
|
<p class="nothing-here-text has-text-centered" v-else>
|
|
|
There are no songs currently queued
|
|
@@ -227,7 +231,7 @@ onUpdated(() => {
|
|
|
max-height: 100%;
|
|
|
}
|
|
|
|
|
|
- .song-item:not(:last-of-type) {
|
|
|
+ :deep(.draggable-item:not(:last-of-type)) {
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
|