feat(fe smartblock): started working on smart blocks editor
This commit is contained in:
parent
8ba2731c31
commit
08c50d6a97
7 changed files with 516 additions and 3 deletions
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import Table from "@/components/content/partials/Table.vue";
|
||||
import PlaylistEditor from "@/components/content/partials/PlaylistEditor.vue";
|
||||
import ConfirmDelete from "@/components/content/partials/dialogs/ConfirmDelete.vue";
|
||||
import {onBeforeMount, reactive, ref, watch} from "vue";
|
||||
import {blocks_page} from "@/composables/content/blocks_page.ts";
|
||||
import SmartBlockEditor from "@partials/SmartBlockEditor.vue";
|
||||
|
||||
const props = defineProps({
|
||||
hideColumns: {
|
||||
|
@ -101,7 +101,7 @@ watch(search, (newValue, oldValue) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<PlaylistEditor
|
||||
<SmartBlockEditor
|
||||
v-if="itemEdited.id !== null && !dialog.open"
|
||||
:item="itemEdited"
|
||||
@go-back="resetItemEdited"
|
||||
|
@ -125,7 +125,7 @@ watch(search, (newValue, oldValue) => {
|
|||
>
|
||||
<template v-slot:header-buttons>
|
||||
<v-btn color="primary" @click="edit(0)">
|
||||
Crea una nuova Playlist
|
||||
Crea un nuovo blocco dinamico
|
||||
</v-btn>
|
||||
</template>
|
||||
<template v-slot:dialog>
|
||||
|
|
132
resources/js/components/content/partials/SmartBlockEditor.vue
Normal file
132
resources/js/components/content/partials/SmartBlockEditor.vue
Normal file
|
@ -0,0 +1,132 @@
|
|||
<script setup lang="ts">
|
||||
import Sources from "@/components/content/partials/Sources.vue";
|
||||
import TrackList from "@/components/content/partials/TrackList.vue";
|
||||
import {useAuthStore} from "@/stores/auth.store.ts";
|
||||
import {reactive, ref} from "vue";
|
||||
import {smartblock} from "@models/smartblock/smartblock.ts";
|
||||
|
||||
const auth = useAuthStore();
|
||||
|
||||
const emit = defineEmits([
|
||||
'saveItem'
|
||||
])
|
||||
|
||||
const props = defineProps({
|
||||
item: Object,
|
||||
})
|
||||
|
||||
const item = props.item.id > 0 ? props.item : reactive({
|
||||
id: 0,
|
||||
name: '',
|
||||
creator_id: auth.userData.user.id,
|
||||
description: '',
|
||||
tracks: [],
|
||||
criteria: [],
|
||||
limit: {
|
||||
type: null,
|
||||
quantity: null
|
||||
},
|
||||
repeated_tracks: false,
|
||||
overflow_tracks: false
|
||||
})
|
||||
|
||||
const smartblockFields = smartblock(item)
|
||||
|
||||
//Is true if there is a required field empty or while saving
|
||||
const disabledSaveButton = ref(true)
|
||||
|
||||
|
||||
const update = (list) => {
|
||||
item.tracks = list
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
// const errors
|
||||
emit('saveItem', item)
|
||||
}
|
||||
|
||||
const checkError = (field, model) => {
|
||||
if (field.required) {
|
||||
const error = field.required && (model === '' || model === null)
|
||||
disabledSaveButton.value = error
|
||||
return error
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const updateProperty = (criteria, prop) => {
|
||||
console.log(criteria, prop)
|
||||
item[prop] = criteria
|
||||
console.log(item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-row no-gutters>
|
||||
<v-col>
|
||||
<Component
|
||||
v-for="(field, key) in smartblockFields()"
|
||||
:is="field.component"
|
||||
:label="field.label"
|
||||
:radioButtons="field.radioButtons"
|
||||
:value="field.value"
|
||||
:disabled="field.disabled"
|
||||
:density="'compact'"
|
||||
@update:modelValue="checkError(field, item[key])"
|
||||
@update-property="updateProperty"
|
||||
:error="checkError(field, item[key])"
|
||||
:limit="item.limit"
|
||||
rows="2"
|
||||
:items="field.items"
|
||||
v-model="item[key]"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
density="compact"
|
||||
hide-details="auto"
|
||||
class="mb-2"
|
||||
clearable
|
||||
:active="true"
|
||||
/>
|
||||
<v-btn
|
||||
color="accent"
|
||||
@click="$emit('goBack')"
|
||||
>Torna indietro</v-btn>
|
||||
<v-btn
|
||||
color="secondary"
|
||||
@click="preview"
|
||||
>Anteprima</v-btn>
|
||||
<v-btn
|
||||
color="primary"
|
||||
@click="save"
|
||||
:disabled="disabledSaveButton"
|
||||
>Salva</v-btn>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<TrackList
|
||||
:tracks="item.tracks"
|
||||
@update-tracks="update"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
{{item}}
|
||||
<!-- <v-row class="tables" no-gutters>-->
|
||||
<!-- <v-col>-->
|
||||
<!-- <TrackList-->
|
||||
<!-- :tracks="item.tracks"-->
|
||||
<!-- @update-tracks="update"-->
|
||||
<!-- />-->
|
||||
<!-- </v-col>-->
|
||||
<!-- <v-col>-->
|
||||
<!-- <Sources />-->
|
||||
<!-- </v-col>-->
|
||||
<!-- </v-row>-->
|
||||
<!-- <v-row no-gutters>-->
|
||||
<!-- </v-row>-->
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.tables > .v-col {
|
||||
width: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
},
|
||||
radioButtons: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-radio-group :label="label">
|
||||
<v-radio
|
||||
v-for="radioButton in radioButtons"
|
||||
:label="radioButton.label"
|
||||
:value="radioButton.value"
|
||||
></v-radio>
|
||||
</v-radio-group>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,94 @@
|
|||
<script setup lang="ts">
|
||||
import {smartblockCriteria} from "@models/smartblock/smartblockCriteria.ts";
|
||||
import {ref, watch} from "vue";
|
||||
import {trackType} from "@/composables/content/track_type.ts";
|
||||
|
||||
const emit = defineEmits(['updateProperty'])
|
||||
|
||||
const { criteria, modifiers } = smartblockCriteria()
|
||||
const trackTypes = trackType(false)
|
||||
console.log(trackTypes)
|
||||
|
||||
const activeCriteria = ref([])
|
||||
const firstCriteria = activeCriteria.value.push({
|
||||
criteria: '',
|
||||
modifier: '',
|
||||
value: ''
|
||||
})
|
||||
|
||||
watch(activeCriteria.value, (newVal, oldVal) => {
|
||||
console.log(newVal)
|
||||
emit('updateProperty', newVal, 'criteria')
|
||||
})
|
||||
|
||||
const addCriteria = () => {
|
||||
activeCriteria.value.push({
|
||||
criteria: '',
|
||||
modifier: '',
|
||||
value: ''
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label for="criteria" class="v-label">Criteri di popolamento</label>
|
||||
<fieldset id="criteria" class="smartblock-criteria">
|
||||
<v-row v-for="(current, index) in activeCriteria">
|
||||
<v-col
|
||||
v-if="index > 0"
|
||||
cols="12"
|
||||
class="text-center"
|
||||
>E</v-col>
|
||||
<v-col>
|
||||
<v-select
|
||||
v-model="activeCriteria[index].criteria"
|
||||
label="Seleziona il criterio"
|
||||
:items="criteria"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select
|
||||
v-model="activeCriteria[index].modifier"
|
||||
label="Seleziona il modificatore"
|
||||
:items="modifiers
|
||||
.filter(mod => mod.type === criteria.find(cri => cri.value === activeCriteria[index].criteria)?.type || mod.type === 'all')"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
v-if="activeCriteria[index].criteria != 'track_type_id'"
|
||||
label="Valore scelto"
|
||||
v-model="activeCriteria[index].value"
|
||||
:type="criteria.find(cri => cri.value === activeCriteria[index].criteria)?.type === 'number' ? 'number' : 'text'"
|
||||
></v-text-field>
|
||||
<v-select
|
||||
v-else
|
||||
:items="trackTypes.trackTypes.value"
|
||||
v-model="activeCriteria[index].value"
|
||||
item-title="type_name"
|
||||
item-value="id"
|
||||
></v-select>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="index > 0"
|
||||
cols="1"
|
||||
>
|
||||
<v-icon
|
||||
@click="activeCriteria.splice(index,1)"
|
||||
>mdi-close</v-icon>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</fieldset>
|
||||
<v-btn
|
||||
color="secundary"
|
||||
@click="addCriteria"
|
||||
>Aggiungi un nuovo criterio</v-btn>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,65 @@
|
|||
<script setup lang="ts">
|
||||
import {reactive} from "vue";
|
||||
|
||||
const emit = defineEmits([
|
||||
'updateProperty'
|
||||
])
|
||||
|
||||
const limit = reactive({
|
||||
type: null,
|
||||
quantity: null
|
||||
})
|
||||
|
||||
const limitItems = [
|
||||
{
|
||||
title: 'Ore',
|
||||
value: 'hours',
|
||||
},
|
||||
{
|
||||
title: 'Minuti',
|
||||
value: 'minutes',
|
||||
},
|
||||
{
|
||||
title: 'Tracce',
|
||||
value: 'items',
|
||||
},
|
||||
{
|
||||
title: 'Tempo rimanente della trasmissione',
|
||||
value: 'remaining',
|
||||
}
|
||||
]
|
||||
|
||||
const update = (e) => {
|
||||
emit('updateProperty', limit, 'limit')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<span>Limite a</span>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
v-if="limit.type !== 'remaining'"
|
||||
label="Quanto"
|
||||
v-model="limit.quantity"
|
||||
@update:modelValue="update"
|
||||
type="number"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select
|
||||
label="Cosa"
|
||||
v-model="limit.type"
|
||||
:items="limitItems"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
@update:modelValue="update"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
113
resources/js/composables/content/models/smartblock/smartblock.ts
Normal file
113
resources/js/composables/content/models/smartblock/smartblock.ts
Normal file
|
@ -0,0 +1,113 @@
|
|||
import {VCheckbox, VSelect, VTextarea, VTextField} from "vuetify/components";
|
||||
import RadioGroup from "@partials/fields/smartblock/RadioGroup.vue";
|
||||
import SmartBlockCriteria from "@partials/fields/smartblock/SmartBlockCriteria.vue";
|
||||
import SmartBlockLimit from "@partials/fields/smartblock/SmartBlockLimit.vue";
|
||||
|
||||
export function smartblock(item) {
|
||||
const visibleFields = {
|
||||
name: {
|
||||
title: 'Nome',
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
title: 'Descrizione',
|
||||
required: false
|
||||
},
|
||||
type: {
|
||||
title: 'Tipologia blocco',
|
||||
required: true,
|
||||
radioButtons: [
|
||||
{
|
||||
label: 'Dinamico',
|
||||
value: 'dynamic'
|
||||
},
|
||||
{
|
||||
label: 'Statico',
|
||||
value: 'static'
|
||||
}
|
||||
]
|
||||
},
|
||||
criteria: {
|
||||
title: 'Seleziona i criteri',
|
||||
required: true
|
||||
},
|
||||
limit: {
|
||||
title: 'Limite a',
|
||||
required: true
|
||||
},
|
||||
repeated_tracks: {
|
||||
title: 'Permetti al ripetizione delle tracce',
|
||||
required: false
|
||||
},
|
||||
overflow_tracks: {
|
||||
title: 'Permetti all\'ultima traccia di andare oltre il limite',
|
||||
required: false
|
||||
},
|
||||
sort: {
|
||||
title: 'Ordina per',
|
||||
required: true
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
const fields = {}
|
||||
Object.keys(visibleFields).forEach((key) => {
|
||||
fields[key] = {
|
||||
label: visibleFields[key].title,
|
||||
value: item !== null ? item[key] : '',
|
||||
required: visibleFields[key].required,
|
||||
component: VTextField
|
||||
}
|
||||
// console.log(fields)
|
||||
switch (key) {
|
||||
case 'name':
|
||||
fields[key].component = VTextField
|
||||
break
|
||||
case 'description':
|
||||
fields[key].component = VTextarea
|
||||
break
|
||||
case 'type':
|
||||
fields[key].component = RadioGroup
|
||||
fields[key].radioButtons = visibleFields[key].radioButtons
|
||||
break
|
||||
case 'criteria':
|
||||
fields[key].component = SmartBlockCriteria
|
||||
break
|
||||
case 'limit':
|
||||
fields[key].component = SmartBlockLimit
|
||||
break
|
||||
case 'repeated_tracks':
|
||||
case 'overflow_tracks':
|
||||
fields[key].component = VCheckbox
|
||||
break
|
||||
case 'sort':
|
||||
fields[key].component = VSelect
|
||||
fields[key].items = [
|
||||
{
|
||||
title: 'Random',
|
||||
value: 'random'
|
||||
},
|
||||
{
|
||||
title: 'Dal più recente',
|
||||
value: 'newest'
|
||||
},
|
||||
{
|
||||
title: 'Dal meno recente',
|
||||
value: 'oldest'
|
||||
},
|
||||
{
|
||||
title: 'Più recentemente andate in onda',
|
||||
value: 'mostrecentplay'
|
||||
},
|
||||
{
|
||||
title: 'Meno recentemente andate in onda',
|
||||
value: 'leastrecentplay'
|
||||
}
|
||||
]
|
||||
break
|
||||
}
|
||||
})
|
||||
// console.log(fields)
|
||||
return fields
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
export function smartblockCriteria() {
|
||||
const criteria = [ {
|
||||
type: 'string',
|
||||
title: 'Nome dell\'Album',
|
||||
value: 'album_title'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
title: 'Nome dell\'Artista',
|
||||
value: 'artist_name'
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
title: 'Bit Rate (kbps)',
|
||||
value: 'bit_rate'
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
title: 'BPM',
|
||||
value: 'bpm'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
title: 'Genere',
|
||||
value: 'genre'
|
||||
},
|
||||
{
|
||||
type: 'TrackType',
|
||||
title: 'Tipo di traccia',
|
||||
value: 'track_type_id'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
const modifiers = [
|
||||
{
|
||||
value: 'contains',
|
||||
title: 'contiene',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
value: 'does not contains',
|
||||
title: 'non contiene',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
value: 'starts with',
|
||||
title: 'comincia con',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
value: 'ends with',
|
||||
title: 'finisce con',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
value: 'is greater than',
|
||||
title: 'è maggiore di',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
value: 'is less than',
|
||||
title: 'è minore di',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
value: 'is in the range',
|
||||
title: 'è tra',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
value: 'is',
|
||||
title: 'è uguale a',
|
||||
type: 'all'
|
||||
},
|
||||
{
|
||||
value: 'is not',
|
||||
title: 'è diverso da',
|
||||
type: 'all'
|
||||
},
|
||||
]
|
||||
|
||||
return { criteria, modifiers }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue