194 lines
No EOL
5.5 KiB
Vue
194 lines
No EOL
5.5 KiB
Vue
<script setup lang="ts">
|
|
import {onMounted, ref, watch} from "vue";
|
|
import draggable from "vuedraggable";
|
|
import {timeFormatter} from "@/helpers/TimeFormatter.ts";
|
|
|
|
const emit = defineEmits([
|
|
'updateTracks'
|
|
])
|
|
|
|
const props = defineProps({
|
|
tracks: {
|
|
type: Array,
|
|
required: true
|
|
}
|
|
})
|
|
|
|
const hiddenCriteria = [
|
|
'sort',
|
|
'repeat_tracks',
|
|
'overflow_tracks'
|
|
]
|
|
|
|
const trackList = ref([])
|
|
const openElements = ref([])
|
|
|
|
const rehydratateTracks = () => {
|
|
trackList.value = props.tracks.map((track, key) => {
|
|
const track_info = {
|
|
type: null,
|
|
id: 0,
|
|
title: '',
|
|
order: key,
|
|
db_element: null,
|
|
}
|
|
console.log(track)
|
|
if (Object.hasOwn(track, 'file') && track.file !== null) {
|
|
track_info.type = 'audioclip'
|
|
track_info.title = track.file.track_title
|
|
track_info.subtitle = track.file.artist_name
|
|
track_info.db_element = track.file
|
|
track_info.file = track.file
|
|
track_info.id = track.file_id
|
|
}
|
|
if (!Object.hasOwn(track, 'file') && track.type === 'audioclip') {
|
|
track_info.type = 'audioclip'
|
|
track_info.title = track.track_title
|
|
track_info.subtitle = track.artist_name
|
|
track_info.db_element = track
|
|
track_info.file = track
|
|
track_info.id = track.id
|
|
}
|
|
if (Object.hasOwn(track, 'block') && track.block !== null) {
|
|
track_info.type = 'block'
|
|
track_info.title = track.block.name
|
|
track_info.subtitle = track.block.creator.login
|
|
track_info.db_element = track.block
|
|
track_info.block = track.block
|
|
track_info.id = track.block_id
|
|
}
|
|
if (!Object.hasOwn(track, 'block') && track.type === 'block') {
|
|
track_info.type = 'block'
|
|
track_info.title = track.name
|
|
track_info.subtitle = track.creator.login
|
|
track_info.db_element = track
|
|
track_info.block = track
|
|
track_info.id = track.id
|
|
}
|
|
return track_info
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
rehydratateTracks()
|
|
})
|
|
|
|
const checkMove = (e) => {
|
|
console.log(e)
|
|
//if block element close criteria to avoid errors
|
|
if (openElements.value.includes(e.draggedContext.index)) {
|
|
delete openElements.value[openElements.value.indexOf(e.draggedContext.index)]
|
|
}
|
|
}
|
|
|
|
watch(props, (newVal, oldVal) => {
|
|
console.log(newVal)
|
|
rehydratateTracks()
|
|
})
|
|
|
|
const change = (event) => {
|
|
console.log(event)
|
|
if (Object.hasOwn(event, 'added')) {
|
|
if (Object.hasOwn(trackList.value[event.added.newIndex], 'track_title')) {
|
|
console.log('ye')
|
|
trackList.value[event.added.newIndex].type = 'audioclip';
|
|
trackList.value[event.added.newIndex].title = trackList.value[event.added.newIndex].track_title;
|
|
trackList.value[event.added.newIndex].subtitle = trackList.value[event.added.newIndex].artist_name;
|
|
}
|
|
if (Object.hasOwn(trackList.value[event.added.newIndex], 'criteria')) {
|
|
trackList.value[event.added.newIndex].type = 'block';
|
|
trackList.value[event.added.newIndex].title = trackList.value[event.added.newIndex].name;
|
|
trackList.value[event.added.newIndex].subtitle = trackList.value[event.added.newIndex].creator.login;
|
|
}
|
|
}
|
|
emit('updateTracks', trackList.value)
|
|
}
|
|
|
|
const remove = (item, index) => {
|
|
trackList.value.splice(index, 1)
|
|
emit('updateTracks', trackList.value)
|
|
}
|
|
|
|
const toggleElement = (index) => {
|
|
if (openElements.value.includes(index)) {
|
|
delete openElements.value[openElements.value.indexOf(index)]
|
|
} else {
|
|
openElements.value.push(index)
|
|
}
|
|
console.log(openElements.value)
|
|
}
|
|
|
|
const printCriteria = (criteria) => {
|
|
if (criteria.criteria === 'limit') {
|
|
return `Limite a ${criteria.value} ${criteria.modifier}`
|
|
} else {
|
|
return `${criteria.criteria} ${criteria.modifier} ${criteria.value}`
|
|
}
|
|
}
|
|
|
|
defineExpose({ draggable });
|
|
</script>
|
|
|
|
<template>
|
|
<v-list>
|
|
<draggable
|
|
:list="trackList"
|
|
item-key="position"
|
|
group="tracklist"
|
|
:move="checkMove"
|
|
@change="change"
|
|
class="draggable-list"
|
|
>
|
|
<template #item="{ element, index }">
|
|
<v-list-item>
|
|
<template v-slot:prepend>
|
|
<div class="index">
|
|
{{ index + 1 }}
|
|
<!-- {{ element }}-->
|
|
</div>
|
|
</template>
|
|
<v-list-item-title v-html="element.title"></v-list-item-title>
|
|
<v-list-item-subtitle v-html="element.subtitle"></v-list-item-subtitle>
|
|
<v-list-item-subtitle
|
|
v-if="openElements.includes(index)"
|
|
v-for="criteria in element.db_element.criteria.filter(el => hiddenCriteria.indexOf(el.criteria) === -1)"
|
|
v-html="printCriteria(criteria)"
|
|
class="criteria"
|
|
>
|
|
|
|
</v-list-item-subtitle>
|
|
<template v-slot:append>
|
|
<v-icon
|
|
v-if="element.type === 'block' && !openElements.includes(index)"
|
|
@click="toggleElement(index)"
|
|
>mdi-unfold-more-horizontal</v-icon>
|
|
<v-icon
|
|
v-if="element.type === 'block' && openElements.includes(index)"
|
|
@click="toggleElement(index)"
|
|
>mdi-unfold-less-horizontal</v-icon>
|
|
<span
|
|
v-if="element.db_element?.length"
|
|
>{{ timeFormatter(element.db_element.length) }}</span>
|
|
<v-icon
|
|
@click="remove(element, index)"
|
|
>mdi-close</v-icon>
|
|
</template>
|
|
</v-list-item>
|
|
</template>
|
|
</draggable>
|
|
</v-list>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.draggable-list {
|
|
min-height: 200px;
|
|
background-color: gray;
|
|
}
|
|
.criteria {
|
|
margin: 2px 0;
|
|
opacity: 1
|
|
}
|
|
.v-list-item-subtitle:not(.criteria) + .criteria {
|
|
margin-top: 8px;
|
|
}
|
|
</style> |