feat(FE): spot
This commit is contained in:
parent
7eadbe16f5
commit
5af0b32634
18 changed files with 162 additions and 52 deletions
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, onActivated, onDeactivated, ref} from "vue";
|
||||
import {computed, onActivated, onDeactivated, onMounted, ref} from "vue";
|
||||
import {useAuthStore} from "@/stores/auth.store.ts";
|
||||
import {deleteShow} from "@models/show/show.ts";
|
||||
import {baseShowInstance, deleteShowInstance, getShowInstances} from "@models/show/showInstance.ts";
|
||||
|
@ -76,7 +76,7 @@ const goBack = async () => {
|
|||
// so reducing the network calls sent
|
||||
// That requires the handling of the context menu
|
||||
// and the show/instance id in a different way though
|
||||
onActivated(async () => {
|
||||
onMounted(async () => {
|
||||
await triggerFetchShowInstances(new Date());
|
||||
intervalId = setInterval(async () => {
|
||||
if (!isRunning.value) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import {playlist_page} from "@/composables/content/playlist_page.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 {reactive, ref, watch} from "vue";
|
||||
import {onBeforeMount, onMounted, type PropType, reactive, ref, watch} from "vue";
|
||||
import {usePlaylistStore} from "@/stores/playlist.store.ts";
|
||||
import {baseSmartBlock} from "@models/smartblock/smartblock.ts";
|
||||
import {basePlaylist} from "@models/playlist/playlist.ts";
|
||||
|
@ -12,6 +12,16 @@ const playlistStore = usePlaylistStore();
|
|||
|
||||
const { items, listData, headers, selected, loading, search, getItems, editItem, deleteItem } = playlist_page();
|
||||
|
||||
// Props and data
|
||||
const props = defineProps({
|
||||
showType: {
|
||||
type: String as PropType<'spot' | null>,
|
||||
required: false,
|
||||
validator: (value: string) => ['spot'].includes(value),
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const itemEdited = ref({
|
||||
id: null
|
||||
});
|
||||
|
@ -37,10 +47,11 @@ const edit = (item) => {
|
|||
item = basePlaylist();
|
||||
}
|
||||
playlistStore.loadPlaylist(item);
|
||||
playlistStore.currentPlaylist.playlist_type = props.showType;
|
||||
itemEdited.value = item;
|
||||
}
|
||||
|
||||
const save = (item) => {
|
||||
const save = (item) => {5
|
||||
if (item.name === '') {
|
||||
//Check required fields
|
||||
console.log('error!')
|
||||
|
@ -91,7 +102,6 @@ const resetItemEdited = () => {
|
|||
watch(search, (newValue, oldValue) => {
|
||||
getItems(listData)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import {reactive, ref, watch} from "vue";
|
||||
import {onActivated, onBeforeMount, onMounted, type PropType, reactive, ref, watch} from "vue";
|
||||
import Table from "@partials/Table.vue";
|
||||
import ConfirmDelete from "@partials/dialogs/ConfirmDelete.vue";
|
||||
import {show_page} from "@/composables/content/show/show_page.ts";
|
||||
|
@ -8,6 +8,16 @@ import {baseShow, type Show} from "@models/show/show";
|
|||
|
||||
const {items, listData, headers, selected, loading, search, getItems, editItem, deleteItem} = show_page()
|
||||
|
||||
// Props and data
|
||||
|
||||
const props = defineProps({
|
||||
showType: {
|
||||
type: String as PropType<'show' | 'spot'>,
|
||||
required: true,
|
||||
validator: (value: string) => ['show', 'spot'].includes(value),
|
||||
},
|
||||
});
|
||||
|
||||
const showCreateEditMode = ref(false);
|
||||
let showSelected = ref<Number | null>(null);
|
||||
|
||||
|
@ -23,6 +33,7 @@ const dialog = reactive({
|
|||
text: ''
|
||||
})
|
||||
|
||||
// Funcs
|
||||
const openDialog = (type, title: string = '', text: string = '') => {
|
||||
dialog.open = true
|
||||
dialog.type = type
|
||||
|
@ -46,8 +57,8 @@ const saveItem = (item) => {
|
|||
}
|
||||
|
||||
const cancel = (item) => {
|
||||
let deleteMessage = 'Vuoi cancellare lo show selezionato?'
|
||||
if(bulk.value.state) deleteMessage = 'Vuoi cancellare gli show selezionati?'
|
||||
let deleteMessage = `Vuoi cancellare lo ${props.showType} selezionato?`
|
||||
if (bulk.value.state) deleteMessage = `Vuoi cancellare gli ${props.showType} selezionati?`
|
||||
bulk.value.items = item
|
||||
showSelected.value = item?.id
|
||||
openDialog(
|
||||
|
@ -78,19 +89,23 @@ const resetItemEdited = () => {
|
|||
showSelected.value = null
|
||||
}
|
||||
|
||||
watch(search, (newValue, oldValue) => {
|
||||
const options = {...listData};
|
||||
getItems(options)
|
||||
})
|
||||
|
||||
const goBack = () => {
|
||||
showCreateEditMode.value = false
|
||||
showSelected.value = null
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
listData.show_type = props.showType
|
||||
})
|
||||
|
||||
watch(search, (newValue, oldValue) => {
|
||||
const options = {...listData};
|
||||
getItems(options)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ShowForm v-if="showCreateEditMode" :showId="showSelected" @go-back="goBack"/>
|
||||
<ShowForm v-if="showCreateEditMode" :showId="showSelected" :showType="props.showType" @go-back="goBack"/>
|
||||
<Table
|
||||
v-else
|
||||
:headers="headers"
|
||||
|
@ -109,7 +124,7 @@ const goBack = () => {
|
|||
>
|
||||
<template v-slot:header-buttons>
|
||||
<v-btn color="primary" @click="create">
|
||||
Crea una nuova trasmissione
|
||||
<span>Crea un nuovo {{ props.showType }} </span>
|
||||
</v-btn>
|
||||
</template>
|
||||
<template v-slot:dialog>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import Table from "@/components/content/partials/Table.vue";
|
||||
import ConfirmDelete from "@/components/content/partials/dialogs/ConfirmDelete.vue";
|
||||
import {onBeforeMount, reactive, ref, watch} from "vue";
|
||||
import {onBeforeMount, type PropType, reactive, ref, watch} from "vue";
|
||||
import {smartblock_page} from "@/composables/content/smartblock_page.ts";
|
||||
import SmartBlockEditor from "@partials/SmartBlockEditor.vue";
|
||||
import {useSmartBlockStore} from "@/stores/smartblock.store.ts";
|
||||
|
@ -15,7 +15,12 @@ const props = defineProps({
|
|||
isDraggable: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
showType: {
|
||||
type: String as PropType<'spot' | null>,
|
||||
required: false,
|
||||
validator: (value: string) => ['spot'].includes(value),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
@ -49,6 +54,7 @@ const edit = (item) => {
|
|||
item = baseSmartBlock();
|
||||
}
|
||||
smartBlockStore.loadSmartBlock(item);
|
||||
smartBlockStore.currentSmartBlock.smart_block_type = props.showType;
|
||||
itemEdited.value = item;
|
||||
console.log(smartBlockStore)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import {ref, onMounted, type PropType} from "vue";;
|
||||
import {ref, onMounted, type PropType} from "vue";
|
||||
|
||||
;
|
||||
import ShowScheduleForm from "@partials/show/ShowScheduleForm.vue";
|
||||
import {useShowStore} from "@/stores/show.store.ts";
|
||||
import {useShowStore} from "@stores/show/show.store.ts";
|
||||
import {getUser} from "@models/User.ts";
|
||||
import {getPlaylist} from "@models/playlist.ts";
|
||||
import ColorPickerButton from "@partials/fields/misc/ColorPickerButton.vue";
|
||||
import {useShowDaysStore} from "@/stores/showDays.store.ts";
|
||||
import {useShowDaysStore} from "@stores/show/showDays.store.ts";
|
||||
|
||||
// Props and emits
|
||||
const props = defineProps({
|
||||
|
@ -13,6 +15,11 @@ const props = defineProps({
|
|||
type: Number as PropType<number | null>,
|
||||
required: true,
|
||||
},
|
||||
showType: {
|
||||
type: String as PropType<'show' | 'spot'>,
|
||||
required: true,
|
||||
validator: (value: string) => ['show', 'spot'].includes(value),
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['go-back']);
|
||||
|
||||
|
@ -31,15 +38,27 @@ const showDaysStore = useShowDaysStore()
|
|||
// Funcs
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
// Prepare show store
|
||||
if (props.showId === null) {
|
||||
showStore.resetShow()
|
||||
showStore.currentShow.showType = props.showType
|
||||
} else {
|
||||
const selectedShow = await showStore.getShow(props.showId, {withDjs: true})
|
||||
const withDjs = props.showType === 'show';
|
||||
const selectedShow = await showStore.getShow(props.showId, {showType: props.showType, withDjs: withDjs})
|
||||
showStore.loadShow(selectedShow)
|
||||
showStore.currentShow.showType = props.showType
|
||||
}
|
||||
|
||||
// fill store
|
||||
let playlistOptions = {playlistType: 'spot'};
|
||||
|
||||
if (props.showType === 'show') {
|
||||
usersDJs.value = await getUser({role: 'dj'});
|
||||
playlists.value = await getPlaylist({});
|
||||
loading.value = false
|
||||
playlistOptions.playlistType = null;
|
||||
}
|
||||
|
||||
playlists.value = await getPlaylist(playlistOptions);
|
||||
loading.value = false;
|
||||
})
|
||||
|
||||
const toggleShowScheduleForm = () => {
|
||||
|
@ -105,7 +124,7 @@ const createShow = () => {
|
|||
</v-col>
|
||||
|
||||
<!-- URL Field -->
|
||||
<v-col cols="12" md="6" lg="4">
|
||||
<v-col v-if="props.showType == 'show'" cols="12" md="6" lg="4">
|
||||
<v-card>
|
||||
<v-text-field
|
||||
v-model="showStore.currentShow.url"
|
||||
|
@ -197,7 +216,7 @@ const createShow = () => {
|
|||
|
||||
<!-- TODO Instead of the dj name, obj obj is shown -->
|
||||
<!-- DJs Select -->
|
||||
<v-col cols="12" md="6" lg="4">
|
||||
<v-col v-if="props.showType == 'show'" cols="12" md="6" lg="4">
|
||||
<v-card>
|
||||
<v-select
|
||||
v-model="showStore.currentShow.showDjs"
|
||||
|
@ -216,8 +235,11 @@ const createShow = () => {
|
|||
|
||||
<v-card-actions>
|
||||
<v-btn color="accent" @click="goBack">Torna indietro</v-btn>
|
||||
<v-btn v-if="showStore.currentShow.id" color="accent" @click="showStore.updateShow()" :disabled="!isFormValid" >Salva</v-btn>
|
||||
<v-btn color="accent" @click="toggleShowScheduleForm" :disabled="!isFormValid" >Regole di programmazione</v-btn>
|
||||
<v-btn v-if="showStore.currentShow.id" color="accent" @click="showStore.updateShow()"
|
||||
:disabled="!isFormValid">Salva
|
||||
</v-btn>
|
||||
<v-btn color="accent" @click="toggleShowScheduleForm" :disabled="!isFormValid">Regole di programmazione
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import ShowStartEndTime from "@partials/fields/show/ShowStartEndTime.vue";
|
||||
import {useShowInstanceStore} from "@/stores/showInstance.store.ts";
|
||||
import {useShowInstanceStore} from "@stores/show/showInstance.store.ts";
|
||||
import {onMounted, ref, watch, type PropType} from "vue";
|
||||
import {baseShowInstance, type ShowInstance} from "@models/show/showInstance.ts";
|
||||
import {extractTime} from "@/helpers/DateFormatter.ts";
|
||||
|
@ -8,7 +8,7 @@ import {getPlaylistContent} from "@models/playlist.ts";
|
|||
import Sources from "@partials/Sources.vue";
|
||||
import TrackList from "@partials/TrackList.vue";
|
||||
import {DateTime} from "luxon";
|
||||
import {useShowStore} from "@/stores/show.store.ts";
|
||||
import {useShowStore} from "@stores/show/show.store.ts";
|
||||
|
||||
const emits = defineEmits(['toggle-menu-edit-instance']);
|
||||
// Props
|
||||
|
|
|
@ -3,7 +3,7 @@ import {onMounted, type PropType, ref, watch} from 'vue';
|
|||
import {showRepetitionData} from "@models/show/ShowRepetition.ts";
|
||||
import DaysCheckbox from "@partials/fields/show/DaysCheckbox.vue";
|
||||
import ShowStartEndTime from "@partials/fields/show/ShowStartEndTime.vue";
|
||||
import {useShowDaysStore} from "@/stores/showDays.store.ts";
|
||||
import {useShowDaysStore} from "@stores/show/showDays.store.ts";
|
||||
|
||||
// Emits and props
|
||||
const emits = defineEmits(['toggle-show-schedule-form', 'trigger-show-creation'])
|
||||
|
|
|
@ -40,6 +40,7 @@ export function playlist(item) {
|
|||
}
|
||||
|
||||
// TODO playlist interface
|
||||
// TODO Add filter if playlist is spot
|
||||
export const getPlaylist = async (options: {
|
||||
id?: number | null;
|
||||
scheduled?: number | null;
|
||||
|
|
|
@ -11,6 +11,7 @@ export interface Playlist {
|
|||
description?: string; // Opzionale
|
||||
length: number; // Durata della playlist
|
||||
contents: PlaylistContent[];
|
||||
playlist_type: 'spot' | null
|
||||
}
|
||||
|
||||
export const basePlaylist = (): Playlist => {
|
||||
|
@ -21,6 +22,7 @@ export const basePlaylist = (): Playlist => {
|
|||
description: '',
|
||||
length: 0,
|
||||
contents: [],
|
||||
playlist_type: null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ export interface Show {
|
|||
showDjs?: ShowDJs[];
|
||||
showInstances?: ShowInstance[];
|
||||
playlist?: any;
|
||||
|
||||
// Extra
|
||||
showType: 'show' | "spot" // Either show or spot
|
||||
}
|
||||
|
||||
export const baseShow = (): Show => {
|
||||
|
@ -46,6 +49,7 @@ export const baseShow = (): Show => {
|
|||
autoplaylistRepeat: false,
|
||||
showDjs: null,
|
||||
showDays: null,
|
||||
showType: "show"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface SmartBlock {
|
|||
contents?: SmartBlockContent[]; // Contenuti associati (opzionale)
|
||||
criteria?: SmartBlockCriteria[]; // Criteri associati (opzionale)
|
||||
tracks?: SmartBlockContent[];
|
||||
smart_block_type: 'spot' | null;
|
||||
}
|
||||
|
||||
export const baseSmartBlock = (): SmartBlock => {
|
||||
|
@ -30,6 +31,7 @@ export const baseSmartBlock = (): SmartBlock => {
|
|||
contents: null,
|
||||
criteria: [],
|
||||
tracks: [],
|
||||
smart_block_type: null,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export function playlist_page() {
|
|||
params: {
|
||||
page: page_info.page,
|
||||
per_page: page_info.itemsPerPage,
|
||||
all: search.value
|
||||
all: search.value,
|
||||
}
|
||||
}).then((response) => {
|
||||
console.log(response)
|
||||
|
|
|
@ -18,7 +18,12 @@ export function show_page() {
|
|||
const headers = showTableHeader
|
||||
|
||||
const getItems = async (options) => {
|
||||
return getShows(options).then(showList => {
|
||||
const showSearchOptions = {
|
||||
page: options.page,
|
||||
per_page: options.itemsPerPage,
|
||||
all: search.value,
|
||||
}
|
||||
return getShows(showSearchOptions).then(showList => {
|
||||
listData.itemsPerPage = showList.per_page;
|
||||
listData.first_page = showList.from;
|
||||
listData.last_page = showList.last_page;
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, defineAsyncComponent} from 'vue';
|
||||
import {computed, defineAsyncComponent, ref, watch} from 'vue';
|
||||
|
||||
// Props and data
|
||||
const props = defineProps({
|
||||
page: Object,
|
||||
});
|
||||
|
||||
const currentPage = computed(() => props.page.id)
|
||||
|
||||
const showType = ref<'show' | 'spot' | null>(null)
|
||||
|
||||
/**
|
||||
* ToDo:
|
||||
*/
|
||||
|
@ -18,13 +21,30 @@ const tabs = {
|
|||
blocks: defineAsyncComponent(() => import('@components/content/SmartBlock.vue')),
|
||||
webstream: defineAsyncComponent(() => import('@components/content/Webstream.vue')),
|
||||
podcast: defineAsyncComponent(() => import('@components/content/Podcast.vue')),
|
||||
spot: defineAsyncComponent(() => import('@components/content/Show.vue')),
|
||||
'spot-playlist': defineAsyncComponent(() => import('@components/content/Playlist.vue')),
|
||||
'spot-blocks': defineAsyncComponent(() => import('@components/content/SmartBlock.vue')),
|
||||
}
|
||||
|
||||
watch(currentPage, (newVal) => {
|
||||
showType.value = null
|
||||
switch (true) {
|
||||
case newVal === 'show':
|
||||
showType.value = 'show'
|
||||
break
|
||||
case ['spot', 'spot-playlist', 'spot-block'].some(item => newVal.includes(item)):
|
||||
showType.value = 'spot'
|
||||
break
|
||||
}
|
||||
}, {immediate: true})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-col>
|
||||
<!-- <keep-alive>-->
|
||||
<Component :is="tabs[currentPage]" />
|
||||
<Component :is="tabs[currentPage]"
|
||||
v-bind="showType ? { showType: showType } : {}"
|
||||
/>
|
||||
<!-- </keep-alive>-->
|
||||
</v-col>
|
||||
</template>
|
||||
|
|
|
@ -30,13 +30,27 @@ const pages = [
|
|||
id: 'podcast',
|
||||
name: 'Podcast',
|
||||
component: '@components/content/Podcast.vue',
|
||||
component: '@components/content/Blocks.vue',
|
||||
},
|
||||
{
|
||||
id: 'webstream',
|
||||
name: 'Webstream',
|
||||
component: '@components/content/Webstream.vue',
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'spot',
|
||||
name: 'Spot',
|
||||
component: '@components/content/Show.vue',
|
||||
},
|
||||
{
|
||||
id: 'spot-playlist',
|
||||
name: 'Spot playlist',
|
||||
component: '@components/content/Playlist.vue',
|
||||
},
|
||||
{
|
||||
id: 'spot-blocks',
|
||||
name: 'Spot Blocchi dinamici',
|
||||
component: '@components/content/SmartBlock.vue',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {defineStore} from 'pinia'
|
||||
import {type Show, baseShow} from '@models/show/show'
|
||||
import type {ShowDays} from "@models/show/showDays";
|
||||
import {type Show, baseShow} from '@models/show/show.ts'
|
||||
import type {ShowDays} from "@models/show/showDays.ts";
|
||||
import axios, {type AxiosResponse} from "axios";
|
||||
import {camelToSnake, cleanOptions, snakeToCamel} from "@/helpers/AxiosHelper.ts";
|
||||
import {extractTimeUTC} from "@/helpers/DateFormatter.ts";
|
||||
|
@ -21,17 +21,26 @@ export const useShowStore = defineStore('show', {
|
|||
resetShow() {
|
||||
this.currentShow = {...baseShow()};
|
||||
},
|
||||
async getShow(id: Number, options: {
|
||||
async getShow(
|
||||
id: number,
|
||||
{
|
||||
showType = 'show',
|
||||
withDjs,
|
||||
isScheduled,
|
||||
}: {
|
||||
showType?: 'show' | 'spot';
|
||||
withDjs?: boolean | null;
|
||||
isScheduled?: boolean | null;
|
||||
}) {
|
||||
const filteredParams = cleanOptions(options);
|
||||
} = {}
|
||||
) {
|
||||
const filteredParams = cleanOptions({showType, withDjs, isScheduled});
|
||||
|
||||
return await axios.get(`/show/${id}`, {params: filteredParams})
|
||||
.then((response: AxiosResponse) => {
|
||||
return snakeToCamel(response.data);
|
||||
}).catch((error: Error) => {
|
||||
console.log("Error: " + error);
|
||||
})
|
||||
});
|
||||
},
|
||||
async createShow() {
|
||||
let showData = {...this.currentShow};
|
|
@ -1,5 +1,5 @@
|
|||
import {defineStore} from 'pinia'
|
||||
import type {ShowDays} from "@models/show/showDays";
|
||||
import type {ShowDays} from "@models/show/showDays.ts";
|
||||
import axios, {type AxiosResponse} from "axios";
|
||||
import {camelToSnake, cleanOptions, snakeToCamel} from "@/helpers/AxiosHelper.ts";
|
||||
import {extractTime, extractTimeUTC} from "@/helpers/DateFormatter.ts";
|
Loading…
Add table
Add a link
Reference in a new issue