You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
3.1 KiB
Vue

<template>
<section class="scene">
<div class="header">
<h2>{{title}}</h2>
<button class="remove" @click="removeScene">remove</button>
</div>
<draggable
tag="transition-group"
:component-data="{
tag: 'div',
type: 'transition-group',
name: !drag ? 'flip-list' : null
}"
v-bind="dragOptions"
group="shots"
class="shots list-group"
:list="shots"
@start="drag=true"
@end="drag=false"
item-key="id">
<template #footer>
<AddShot @add="add"/>
</template>
<template #item="{element, index}">
<ShotEntry
:key="element.title, index"
:title="element.title"
:description="element.description"
:img="element.img"
:color="element.color"
:order="index + 1"
@remove="remove(index)"
@update="update"
/>
</template>
</draggable>
<button @click="serialize">Export scene</button>
</section>
</template>
<script setup>
import draggable from 'vuedraggable'
import AddShot from '../components/AddShot.vue'
import ShotEntry from '../components/ShotEntry.vue'
import {utils} from '../composables/utils.js'
import {ref, computed} from 'vue'
const {blobToBase64, download} = utils()
const props = defineProps({
title: String,
series: Array
})
const emit = defineEmits(['remove'])
const shots = ref(props.series || [])
const drag = ref(false)
const dragOptions = computed(()=> {
return {
animation: 200,
group: "description",
disabled: false,
ghostClass: "ghost"
}})
const add = (e) => {
shots.value.push(e)
}
const remove = (index) => {
shots.value.splice(index, 1)
}
const update = (e) => {
let index = e.order - 1
shots.value[index].title = e.title
shots.value[index].description = e.description
shots.value[index].color = e.color
}
const removeScene = () => {
emit('remove')
}
const serialize = async () => {
let series = await Promise.all(shots.value.map(async (shot) => {
let img = await blobToBase64(shot.file)
return {
title: shot.title,
description: shot.description,
color: shot.color,
img: img
}
}))
download(
JSON.stringify({title: props.title, series}),
`${props.title}.json`,
'text/plain'
)
}
</script>
<style>
.shots {
margin-block: 32px;
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.ghost {
opacity: 0.5;
}
.scene {
margin-block: 32px;
}
.header {
margin-block: 32px;
display: flex;
gap: 8px;
}
.header h2 {
margin: 0;
}
.header .remove {
position: relative;
color: currentColor;
opacity: 0.5;
font-size: 0.8rem;
}
.header .remove:hover {
opacity: 1;
background: none;
color: currentColor;
}
@media print {
.shots {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
}
</style>