sintonia_webapp/resources/js/components/content/partials/TrackList.vue

171 lines
No EOL
4.7 KiB
Vue

<script setup lang="ts">
import {onMounted, ref, watch} from "vue";
import draggable from "vuedraggable";
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([])
onMounted(() => {
console.log(props.tracks)
trackList.value = props.tracks.map((track, key) => {
const track_info = {
type: null,
id: 0,
title: '',
order: key,
db_element: null,
}
if (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.id = track.file_id
} else if (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.id = track.block_id
}
return track_info
})
console.log(trackList.value)
})
const checkMove = (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(trackList, (newVal, oldVal) => {
console.log(newVal)
})
const change = (event) => {
console.log(event)
//When adding an element
if (Object.hasOwn(event, 'added')) {
//Adding position
trackList.value[event.added.newIndex].position = event.added.newIndex
//Check element type
//File
if (Object.hasOwn(event.added.element, 'track_title')) {
trackList.value[event.added.newIndex].type = 'audioclip'
trackList.value[event.added.newIndex].title = event.added.element.track_title
trackList.value[event.added.newIndex].subtitle = event.added.element.artist_name
}
//Block
if (Object.hasOwn(event.added.element, 'criteria')) {
trackList.value[event.added.newIndex].type = 'block'
trackList.value[event.added.newIndex].title = event.added.element.name
trackList.value[event.added.newIndex].subtitle = event.added.element.creator.login
}
trackList.value[event.added.newIndex].db_element = event.added.element
}
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 }}
</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>
<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>