ignore escape characters in regex, get playlist from other days, fix ffplayout #599, colorize over length, save playlists longer then 24 hours, format with prettier, eslint ignore slash on void
This commit is contained in:
parent
6c574feda1
commit
cbb69d0e16
2
.gitignore
vendored
2
.gitignore
vendored
@ -29,8 +29,6 @@ tv-media/
|
|||||||
Videos
|
Videos
|
||||||
Videos/
|
Videos/
|
||||||
*.tar*
|
*.tar*
|
||||||
.vscode
|
|
||||||
.vscode/
|
|
||||||
home
|
home
|
||||||
home/
|
home/
|
||||||
live1
|
live1
|
||||||
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"eslint.experimental.useFlatConfig": true,
|
||||||
|
}
|
@ -18,7 +18,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
placeholder="Type here"
|
placeholder="Type here"
|
||||||
class="input input-bordered w-full"
|
class="input input-bordered w-full"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-5">
|
<label class="form-control w-full mt-5">
|
||||||
@ -29,7 +29,7 @@
|
|||||||
v-model="configStore.configGui[configStore.configID].preview_url"
|
v-model="configStore.configGui[configStore.configID].preview_url"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered w-full"
|
class="input input-bordered w-full"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-5">
|
<label class="form-control w-full mt-5">
|
||||||
@ -40,7 +40,7 @@
|
|||||||
v-model="configStore.configGui[configStore.configID].config_path"
|
v-model="configStore.configGui[configStore.configID].config_path"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered w-full"
|
class="input input-bordered w-full"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-5">
|
<label class="form-control w-full mt-5">
|
||||||
@ -51,7 +51,7 @@
|
|||||||
v-model="configStore.configGui[configStore.configID].extra_extensions"
|
v-model="configStore.configGui[configStore.configID].extra_extensions"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered w-full"
|
class="input input-bordered w-full"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-5">
|
<label class="form-control w-full mt-5">
|
||||||
@ -63,7 +63,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered w-full !bg-base-100"
|
class="input input-bordered w-full !bg-base-100"
|
||||||
disabled
|
disabled
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="join my-4">
|
<div class="join my-4">
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
<div class="max-w-[1200px] pe-8">
|
<div class="max-w-[1200px] pe-8">
|
||||||
<h2 class="pt-3 text-3xl">{{ $t('config.playoutConf') }}</h2>
|
<h2 class="pt-3 text-3xl">{{ $t('config.playoutConf') }}</h2>
|
||||||
<form
|
<form
|
||||||
v-if="configStore.configPlayout"
|
v-if="configStore.playout"
|
||||||
class="mt-10 grid md:grid-cols-[180px_auto] gap-5"
|
class="mt-10 grid md:grid-cols-[180px_auto] gap-5"
|
||||||
@submit.prevent="onSubmitPlayout"
|
@submit.prevent="onSubmitPlayout"
|
||||||
>
|
>
|
||||||
<template v-for="(item, key) in configStore.configPlayout" :key="key">
|
<template v-for="(item, key) in configStore.playout" :key="key">
|
||||||
<div class="text-xl pt-3 text-right">{{ setTitle(key.toString()) }}:</div>
|
<div class="text-xl pt-3 text-right">{{ setTitle(key.toString()) }}:</div>
|
||||||
<div class="md:pt-4">
|
<div class="md:pt-4">
|
||||||
<label
|
<label
|
||||||
@ -15,6 +15,7 @@
|
|||||||
class="form-control w-full"
|
class="form-control w-full"
|
||||||
:class="[typeof prop === 'boolean' && 'flex-row', name.toString() !== 'help_text' && 'mt-2']"
|
:class="[typeof prop === 'boolean' && 'flex-row', name.toString() !== 'help_text' && 'mt-2']"
|
||||||
>
|
>
|
||||||
|
<template v-if="name.toString() !== 'startInSec' && name.toString() !== 'lengthInSec'">
|
||||||
<div v-if="name.toString() !== 'help_text'" class="label">
|
<div v-if="name.toString() !== 'help_text'" class="label">
|
||||||
<span class="label-text !text-md font-bold">{{ name }}</span>
|
<span class="label-text !text-md font-bold">{{ name }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -27,7 +28,7 @@
|
|||||||
type="password"
|
type="password"
|
||||||
:placeholder="$t('config.placeholderPass')"
|
:placeholder="$t('config.placeholderPass')"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
>
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
v-else-if="name.toString() === 'output_param' || name.toString() === 'custom_filter'"
|
v-else-if="name.toString() === 'output_param' || name.toString() === 'custom_filter'"
|
||||||
v-model="item[name]"
|
v-model="item[name]"
|
||||||
@ -39,7 +40,7 @@
|
|||||||
v-model="item[name]"
|
v-model="item[name]"
|
||||||
type="number"
|
type="number"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-else-if="typeof prop === 'number'"
|
v-else-if="typeof prop === 'number'"
|
||||||
v-model="item[name]"
|
v-model="item[name]"
|
||||||
@ -47,31 +48,32 @@
|
|||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
step="0.0001"
|
step="0.0001"
|
||||||
style="max-width: 250px"
|
style="max-width: 250px"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-else-if="typeof prop === 'boolean'"
|
v-else-if="typeof prop === 'boolean'"
|
||||||
v-model="item[name]"
|
v-model="item[name]"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox checkbox-sm ms-2 mt-2"
|
class="checkbox checkbox-sm ms-2 mt-2"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-else-if="name === 'ignore_lines'"
|
v-else-if="name === 'ignore_lines'"
|
||||||
v-model="formatIgnoreLines"
|
v-model="formatIgnoreLines"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-else
|
v-else
|
||||||
:id="name"
|
:id="name"
|
||||||
v-model="item[name]"
|
v-model="item[name]"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
>
|
/>
|
||||||
|
</template>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="mt-5 mb-10">
|
<div class="mt-5 mb-10">
|
||||||
<button class="btn btn-primary" type="submit">Save</button>
|
<button class="btn btn-primary" type="submit">{{ $t('config.save') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -95,11 +97,11 @@ const showModal = ref(false)
|
|||||||
|
|
||||||
const formatIgnoreLines = computed({
|
const formatIgnoreLines = computed({
|
||||||
get() {
|
get() {
|
||||||
return configStore.configPlayout.logging.ignore_lines.join(';')
|
return configStore.playout.logging.ignore_lines.join(';')
|
||||||
},
|
},
|
||||||
|
|
||||||
set(value) {
|
set(value) {
|
||||||
configStore.configPlayout.logging.ignore_lines = value.split(';')
|
configStore.playout.logging.ignore_lines = value.split(';')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -162,7 +164,7 @@ function setHelp(key: string, text: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmitPlayout() {
|
async function onSubmitPlayout() {
|
||||||
const update = await configStore.setPlayoutConfig(configStore.configPlayout)
|
const update = await configStore.setPlayoutConfig(configStore.playout)
|
||||||
|
|
||||||
if (update.status === 200) {
|
if (update.status === 200) {
|
||||||
indexStore.msgAlert('success', 'Update playout config success!', 2)
|
indexStore.msgAlert('success', 'Update playout config success!', 2)
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
<h2 class="pt-3 text-3xl">{{ $t('user.title') }}</h2>
|
<h2 class="pt-3 text-3xl">{{ $t('user.title') }}</h2>
|
||||||
<div class="flex flex-col xs:flex-row gap-2 w-full mb-5 mt-10">
|
<div class="flex flex-col xs:flex-row gap-2 w-full mb-5 mt-10">
|
||||||
<div class="grow">
|
<div class="grow">
|
||||||
<select class="select select-bordered w-full max-w-xs" v-model="selected" @change="onChange($event)">
|
<select v-model="selected" class="select select-bordered w-full max-w-xs" @change="onChange($event)">
|
||||||
<option v-for="item in users">{{ item.username }}</option>
|
<option v-for="item in users" :key="item.username">{{ item.username }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-none join">
|
<div class="flex-none join">
|
||||||
@ -22,9 +22,9 @@
|
|||||||
<span class="label-text">{{ $t('user.name') }}</span>
|
<span class="label-text">{{ $t('user.name') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
|
v-model="configStore.configUser.username"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered w-full !bg-base-100"
|
class="input input-bordered w-full !bg-base-100"
|
||||||
v-model="configStore.configUser.username"
|
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -33,33 +33,21 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.mail') }}</span>
|
<span class="label-text">{{ $t('user.mail') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-model="configStore.configUser.mail" type="email" class="input input-bordered w-full" />
|
||||||
type="email"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
v-model="configStore.configUser.mail"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full max-w-md mt-3">
|
<label class="form-control w-full max-w-md mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.newPass') }}</span>
|
<span class="label-text">{{ $t('user.newPass') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-model="newPass" type="password" class="input input-bordered w-full" />
|
||||||
type="password"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
v-model="newPass"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full max-w-md mt-3">
|
<label class="form-control w-full max-w-md mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.confirmPass') }}</span>
|
<span class="label-text">{{ $t('user.confirmPass') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-model="confirmPass" type="password" class="input input-bordered w-full" />
|
||||||
type="password"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
v-model="confirmPass"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -74,42 +62,34 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.name') }}</span>
|
<span class="label-text">{{ $t('user.name') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="input input-bordered w-full" v-model="user.username" />
|
<input v-model="user.username" type="text" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.mail') }}</span>
|
<span class="label-text">{{ $t('user.mail') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="email" class="input input-bordered w-full" v-model="user.mail" />
|
<input v-model="user.mail" type="email" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.password') }}</span>
|
<span class="label-text">{{ $t('user.password') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-model="user.password" type="password" class="input input-bordered w-full" />
|
||||||
type="password"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
v-model="user.password"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('user.confirmPass') }}</span>
|
<span class="label-text">{{ $t('user.confirmPass') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-model="user.confirm" type="password" class="input input-bordered w-full" />
|
||||||
type="password"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
v-model="user.confirm"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="form-control mt-3">
|
<div class="form-control mt-3">
|
||||||
<label class="label cursor-pointer w-1/2">
|
<label class="label cursor-pointer w-1/2">
|
||||||
<span class="label-text">{{ $t('user.admin') }}</span>
|
<span class="label-text">{{ $t('user.admin') }}</span>
|
||||||
<input type="checkbox" class="checkbox" v-model.number="user.admin" />
|
<input v-model.number="user.admin" type="checkbox" class="checkbox" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -243,7 +223,7 @@ async function addUser(add: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmitUser() {
|
async function onSubmitUser() {
|
||||||
if (newPass && newPass.value === confirmPass.value) {
|
if (newPass.value && newPass.value === confirmPass.value) {
|
||||||
configStore.configUser.password = newPass.value
|
configStore.configUser.password = newPass.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<div class="font-bold text-lg truncate flex-1 w-0">{{ title }}</div>
|
<div class="font-bold text-lg truncate flex-1 w-0">{{ title }}</div>
|
||||||
<button v-if="hideButtons" class="btn btn-sm w-8 h-8 rounded-full" @click="modalAction(false)">
|
<button v-if="hideButtons" class="btn btn-sm w-8 h-8 rounded-full" @click="modalAction(false)">
|
||||||
<i class="bi bi-x-lg"/>
|
<i class="bi bi-x-lg" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="navbar bg-base-100 min-h-[52px] p-0 shadow">
|
<div class="navbar bg-base-100 min-h-[52px] p-0 shadow">
|
||||||
<NuxtLink class="navbar-brand min-w-[46px] p-2" href="/">
|
<NuxtLink class="navbar-brand min-w-[46px] p-2" href="/">
|
||||||
<img src="~/assets/images/ffplayout-small.png" class="img-fluid" alt="Logo" width="30" height="30" >
|
<img src="~/assets/images/ffplayout-small.png" class="img-fluid" alt="Logo" width="30" height="30" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<div class="navbar-end w-1/5 grow">
|
<div class="navbar-end w-1/5 grow">
|
||||||
<label class="swap swap-rotate me-2 md:hidden">
|
<label class="swap swap-rotate me-2 md:hidden">
|
||||||
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" >
|
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" />
|
||||||
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
||||||
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
||||||
</label>
|
</label>
|
||||||
@ -81,7 +81,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="p-0">
|
<li class="p-0">
|
||||||
<label class="swap swap-rotate">
|
<label class="swap swap-rotate">
|
||||||
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" >
|
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" />
|
||||||
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
||||||
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
||||||
</label>
|
</label>
|
||||||
|
@ -61,8 +61,10 @@
|
|||||||
{{ filename(playlistStore.currentClip) }}
|
{{ filename(playlistStore.currentClip) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="grow">
|
<div class="grow">
|
||||||
<strong>{{ $t('player.duration') }}:</strong> {{ secToHMS(playlistStore.currentClipDuration) }} |
|
<strong>{{ $t('player.duration') }}:</strong>
|
||||||
<strong>{{ $t('player.in') }}:</strong> {{ secToHMS(playlistStore.currentClipIn) }} | <strong>{{ $t('player.out') }}:</strong>
|
{{ secToHMS(playlistStore.currentClipDuration) }} |
|
||||||
|
<strong>{{ $t('player.in') }}:</strong> {{ secToHMS(playlistStore.currentClipIn) }} |
|
||||||
|
<strong>{{ $t('player.out') }}:</strong>
|
||||||
{{ secToHMS(playlistStore.currentClipOut) }}
|
{{ secToHMS(playlistStore.currentClipOut) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="h-1/3">
|
<div class="h-1/3">
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
aria-label="Simple"
|
aria-label="Simple"
|
||||||
checked
|
checked
|
||||||
@change="advancedGenerator = false"
|
@change="advancedGenerator = false"
|
||||||
>
|
/>
|
||||||
<div role="tabpanel" class="tab-content w-full pt-3">
|
<div role="tabpanel" class="tab-content w-full pt-3">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
@ -78,7 +78,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -93,7 +93,7 @@
|
|||||||
class="tab"
|
class="tab"
|
||||||
aria-label="Advanced"
|
aria-label="Advanced"
|
||||||
@change=";(advancedGenerator = true), resetCheckboxes()"
|
@change=";(advancedGenerator = true), resetCheckboxes()"
|
||||||
>
|
/>
|
||||||
<div role="tabpanel" class="tab-content pt-3">
|
<div role="tabpanel" class="tab-content pt-3">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="grid grid-cols-[auto_48px] px-3 pt-0">
|
<div class="grid grid-cols-[auto_48px] px-3 pt-0">
|
||||||
@ -121,7 +121,7 @@
|
|||||||
title="Add time block"
|
title="Add time block"
|
||||||
@click="addTemplate()"
|
@click="addTemplate()"
|
||||||
>
|
>
|
||||||
<i class="bi bi-folder-plus"/>
|
<i class="bi bi-folder-plus" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -180,7 +180,7 @@
|
|||||||
v-model="item.start"
|
v-model="item.start"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered join-item px-2 text-center"
|
class="input input-sm input-bordered join-item px-2 text-center"
|
||||||
>
|
/>
|
||||||
<div
|
<div
|
||||||
class="input input-sm input-bordered join-item px-2 text-center bg-base-200"
|
class="input input-sm input-bordered join-item px-2 text-center bg-base-200"
|
||||||
>
|
>
|
||||||
@ -190,7 +190,7 @@
|
|||||||
v-model="item.duration"
|
v-model="item.duration"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered join-item px-2 text-center"
|
class="input input-sm input-bordered join-item px-2 text-center"
|
||||||
>
|
/>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm input-bordered join-item"
|
class="btn btn-sm input-bordered join-item"
|
||||||
:class="item.shuffle ? 'bg-base-100' : 'bg-base-300'"
|
:class="item.shuffle ? 'bg-base-100' : 'bg-base-300'"
|
||||||
@ -247,7 +247,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox checkbox-xs rounded"
|
class="checkbox checkbox-xs rounded"
|
||||||
@change="resetCheckboxes()"
|
@change="resetCheckboxes()"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="join ms-2">
|
<div class="join ms-2">
|
||||||
@ -291,12 +291,14 @@ const advancedGenerator = ref(false)
|
|||||||
const selectedFolders = ref([] as string[])
|
const selectedFolders = ref([] as string[])
|
||||||
const generateFromAll = ref(false)
|
const generateFromAll = ref(false)
|
||||||
const template = ref({
|
const template = ref({
|
||||||
sources: [{
|
sources: [
|
||||||
start: configStore.configPlayout.playlist.day_start,
|
{
|
||||||
|
start: configStore.playout.playlist.day_start,
|
||||||
duration: '02:00:00',
|
duration: '02:00:00',
|
||||||
shuffle: false,
|
shuffle: false,
|
||||||
paths: [],
|
paths: [],
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
} as Template)
|
} as Template)
|
||||||
|
|
||||||
const templateBrowserSortOptions = {
|
const templateBrowserSortOptions = {
|
||||||
@ -331,12 +333,7 @@ async function generatePlaylist() {
|
|||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(playlistStore.listDate, response.program, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
response.program,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
indexStore.msgAlert('success', 'Generate Playlist done...', 2)
|
indexStore.msgAlert('success', 'Generate Playlist done...', 2)
|
||||||
})
|
})
|
||||||
.catch((e: any) => {
|
.catch((e: any) => {
|
||||||
@ -379,7 +376,7 @@ function addFolderToTemplate(event: any, item: TemplateItem) {
|
|||||||
|
|
||||||
event.item.remove()
|
event.item.remove()
|
||||||
|
|
||||||
const storagePath = configStore.configPlayout.storage.path
|
const storagePath = configStore.playout.storage.path
|
||||||
const navPath = mediaStore.folderCrumbs[mediaStore.folderCrumbs.length - 1].path
|
const navPath = mediaStore.folderCrumbs[mediaStore.folderCrumbs.length - 1].path
|
||||||
const sourcePath = `${storagePath}/${navPath}/${mediaStore.folderList.folders[o].name}`.replace(/\/[/]+/g, '/')
|
const sourcePath = `${storagePath}/${navPath}/${mediaStore.folderList.folders[o].name}`.replace(/\/[/]+/g, '/')
|
||||||
|
|
||||||
@ -404,7 +401,10 @@ function addTemplate() {
|
|||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
const t = $dayjs(`2000-01-01T${last.duration}`)
|
const t = $dayjs(`2000-01-01T${last.duration}`)
|
||||||
start = $dayjs(`2000-01-01T${last.start}`).add(t.hour(), 'hour').add(t.minute(), 'minute').add(t.second(), 'second')
|
start = $dayjs(`2000-01-01T${last.start}`)
|
||||||
|
.add(t.hour(), 'hour')
|
||||||
|
.add(t.minute(), 'minute')
|
||||||
|
.add(t.second(), 'second')
|
||||||
}
|
}
|
||||||
|
|
||||||
template.value.sources.push({
|
template.value.sources.push({
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
playlistStore.playoutIsRunning &&
|
playlistStore.playoutIsRunning &&
|
||||||
listDate === todayDate &&
|
listDate === todayDate &&
|
||||||
index === playlistStore.currentClipIndex,
|
index === playlistStore.currentClipIndex,
|
||||||
|
'!bg-amber-600/40': element.overtime,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<td class="ps-4 py-2 text-left">{{ secondsToTime(element.begin) }}</td>
|
<td class="ps-4 py-2 text-left">{{ secondsToTime(element.begin) }}</td>
|
||||||
@ -96,7 +97,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
:checked="element.category && element.category === 'advertisement' ? true : false"
|
:checked="element.category && element.category === 'advertisement' ? true : false"
|
||||||
@change="setCategory($event, element)"
|
@change="setCategory($event, element)"
|
||||||
>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-2 text-center hover:text-base-content/70">
|
<td class="py-2 text-center hover:text-base-content/70">
|
||||||
<button @click="editItem(index)">
|
<button @click="editItem(index)">
|
||||||
@ -193,7 +194,7 @@ function addClip(event: any) {
|
|||||||
|
|
||||||
event.item.remove()
|
event.item.remove()
|
||||||
|
|
||||||
const storagePath = configStore.configPlayout.storage.path
|
const storagePath = configStore.playout.storage.path
|
||||||
const sourcePath = `${storagePath}/${mediaStore.folderTree.source}/${mediaStore.folderTree.files[o].name}`.replace(
|
const sourcePath = `${storagePath}/${mediaStore.folderTree.source}/${mediaStore.folderTree.files[o].name}`.replace(
|
||||||
/\/[/]+/g,
|
/\/[/]+/g,
|
||||||
'/'
|
'/'
|
||||||
@ -208,12 +209,7 @@ function addClip(event: any) {
|
|||||||
duration: mediaStore.folderTree.files[o].duration,
|
duration: mediaStore.folderTree.files[o].duration,
|
||||||
})
|
})
|
||||||
|
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(listDate.value, playlistStore.playlist, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
playlistStore.playlist,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const newNode = document.getElementById(`clip-${n}`)
|
const newNode = document.getElementById(`clip-${n}`)
|
||||||
@ -225,12 +221,7 @@ function addClip(event: any) {
|
|||||||
function moveItemInArray(event: any) {
|
function moveItemInArray(event: any) {
|
||||||
playlistStore.playlist.splice(event.newIndex, 0, playlistStore.playlist.splice(event.oldIndex, 1)[0])
|
playlistStore.playlist.splice(event.newIndex, 0, playlistStore.playlist.splice(event.oldIndex, 1)[0])
|
||||||
|
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(listDate.value, playlistStore.playlist, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
playlistStore.playlist,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
removeBG(event.item)
|
removeBG(event.item)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="p-4 bg-base-100">
|
<div class="p-4 bg-base-100">
|
||||||
<span class="text-3xl">{{ sysStat.system.name }} {{ sysStat.system.version }}</span>
|
<span class="text-3xl">{{ sysStat.system.name }} {{ sysStat.system.version }}</span>
|
||||||
<span v-if="sysStat.system.kernel">
|
<span v-if="sysStat.system.kernel">
|
||||||
<br >
|
<br />
|
||||||
{{ sysStat.system.kernel }}
|
{{ sysStat.system.kernel }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -16,8 +16,12 @@
|
|||||||
<div class="p-4 border border-primary">
|
<div class="p-4 border border-primary">
|
||||||
<div class="text-xl">{{ $t('system.cpu') }}</div>
|
<div class="text-xl">{{ $t('system.cpu') }}</div>
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<div><strong>{{ $t('system.cores') }}:</strong> {{ sysStat.cpu.cores }}</div>
|
<div>
|
||||||
<div><strong>{{ $t('system.usage') }}:</strong> {{ sysStat.cpu.usage.toFixed(2) }}%</div>
|
<strong>{{ $t('system.cores') }}:</strong> {{ sysStat.cpu.cores }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('system.usage') }}:</strong> {{ sysStat.cpu.usage.toFixed(2) }}%
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 border border-primary">
|
<div class="p-4 border border-primary">
|
||||||
@ -31,15 +35,23 @@
|
|||||||
<div class="p-4 border border-primary">
|
<div class="p-4 border border-primary">
|
||||||
<div class="text-xl">{{ $t('system.memory') }}</div>
|
<div class="text-xl">{{ $t('system.memory') }}</div>
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<div><strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.memory.total) }}</div>
|
<div>
|
||||||
<div><strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.memory.used) }}</div>
|
<strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.memory.total) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.memory.used) }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 border border-primary">
|
<div class="p-4 border border-primary">
|
||||||
<div class="text-xl">{{ $t('system.swap') }}</div>
|
<div class="text-xl">{{ $t('system.swap') }}</div>
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<div><strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.swap.total) }}</div>
|
<div>
|
||||||
<div><strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.swap.used) }}</div>
|
<strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.swap.total) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.swap.used) }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 border border-primary">
|
<div class="p-4 border border-primary">
|
||||||
@ -47,19 +59,29 @@
|
|||||||
{{ $t('system.network') }} <span v-if="sysStat.network" class="fs-6">{{ sysStat.network?.name }}</span>
|
{{ $t('system.network') }} <span v-if="sysStat.network" class="fs-6">{{ sysStat.network?.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<div><strong>{{ $t('system.in') }}:</strong> {{ fileSize(sysStat.network?.current_in) }}</div>
|
<div>
|
||||||
<div><strong>{{ $t('system.out') }}:</strong> {{ fileSize(sysStat.network?.current_out) }}</div>
|
<strong>{{ $t('system.in') }}:</strong> {{ fileSize(sysStat.network?.current_in) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('system.out') }}:</strong> {{ fileSize(sysStat.network?.current_out) }}
|
||||||
|
</div>
|
||||||
<div>{{ fileSize(sysStat.network?.total_in) }}</div>
|
<div>{{ fileSize(sysStat.network?.total_in) }}</div>
|
||||||
<div>{{ fileSize(sysStat.network?.total_out) }}</div>
|
<div>{{ fileSize(sysStat.network?.total_out) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="sysStat.storage?.path" class="p-4 border border-primary">
|
<div v-if="sysStat.storage?.path" class="p-4 border border-primary">
|
||||||
<div class="text-xl">{{ $t('system.storage') }}</div>
|
<div class="text-xl">{{ $t('system.storage') }}</div>
|
||||||
<div v-if="sysStat.storage"><strong>{{ $t('system.device') }}:</strong> {{ sysStat.storage?.path }}</div>
|
<div v-if="sysStat.storage">
|
||||||
|
<strong>{{ $t('system.device') }}:</strong> {{ sysStat.storage?.path }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="sysStat.storage" class="grid grid-cols-2">
|
<div v-if="sysStat.storage" class="grid grid-cols-2">
|
||||||
<div><strong>{{ $t('system.size') }}:</strong> {{ fileSize(sysStat.storage?.total) }}</div>
|
<div>
|
||||||
<div><strong>{{ $t('system.used') }}:</strong> {{ fileSize(sysStat.storage?.used) }}</div>
|
<strong>{{ $t('system.size') }}:</strong> {{ fileSize(sysStat.storage?.total) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>{{ $t('system.used') }}:</strong> {{ fileSize(sysStat.storage?.used) }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="col-6 bg-primary p-2 border" />
|
<div v-else class="col-6 bg-primary p-2 border" />
|
||||||
|
@ -181,15 +181,22 @@ export const playlistOperations = () => {
|
|||||||
return String(Date.now().toString(32) + Math.random().toString(16)).replace(/\./g, '')
|
return String(Date.now().toString(32) + Math.random().toString(16)).replace(/\./g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
function processPlaylist(dayStart: number, length: number, list: PlaylistItem[], forSave: boolean) {
|
function processPlaylist(date: string, list: PlaylistItem[], forSave: boolean) {
|
||||||
if (!dayStart) {
|
const configStore = useConfig()
|
||||||
dayStart = 0
|
|
||||||
}
|
let begin = configStore.playout.playlist.startInSec
|
||||||
|
|
||||||
let begin = dayStart
|
|
||||||
const newList = []
|
const newList = []
|
||||||
|
|
||||||
for (const item of list) {
|
for (const item of list) {
|
||||||
|
if (configStore.playout.playlist.startInSec === begin) {
|
||||||
|
if (!forSave) {
|
||||||
|
item.date = date
|
||||||
|
} else {
|
||||||
|
delete item.date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!item.uid) {
|
if (!item.uid) {
|
||||||
item.uid = genUID()
|
item.uid = genUID()
|
||||||
}
|
}
|
||||||
@ -208,16 +215,15 @@ export const playlistOperations = () => {
|
|||||||
delete item.custom_filter
|
delete item.custom_filter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (begin + (item.out - item.in) > length + dayStart) {
|
if (
|
||||||
item.class = 'overLength'
|
begin >= configStore.playout.playlist.startInSec + configStore.playout.playlist.lengthInSec &&
|
||||||
|
!configStore.playout.playlist.infinit
|
||||||
|
) {
|
||||||
if (forSave) {
|
if (forSave) {
|
||||||
item.out = length + dayStart - begin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forSave && begin >= length + dayStart) {
|
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
item.overtime = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newList.push(item)
|
newList.push(item)
|
||||||
|
@ -13,8 +13,10 @@ export default withNuxt(
|
|||||||
// }
|
// }
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
"vue/no-v-html": "off",
|
'no-control-regex': 'off',
|
||||||
|
'vue/html-self-closing': 'off',
|
||||||
|
'vue/no-v-html': 'off',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -144,7 +144,8 @@ export default {
|
|||||||
help: 'Hilfe',
|
help: 'Hilfe',
|
||||||
generalText: `Manchmal kann es vorkommen, dass eine Datei beschädigt, aber noch abspielbar ist, was einen Streaming-Fehler bei allen folgenden Dateien verursachen kann. Die einzige Möglichkeit, dies zu beheben, besteht darin, ffplayout anzuhalten und neu zu starten. Wir sagen hier nur, wann es gestoppt werden muss, der Startvorgang ist Ihnen überlassen. Der beste Weg ist ein systemd-Dienst unter Linux.
|
generalText: `Manchmal kann es vorkommen, dass eine Datei beschädigt, aber noch abspielbar ist, was einen Streaming-Fehler bei allen folgenden Dateien verursachen kann. Die einzige Möglichkeit, dies zu beheben, besteht darin, ffplayout anzuhalten und neu zu starten. Wir sagen hier nur, wann es gestoppt werden muss, der Startvorgang ist Ihnen überlassen. Der beste Weg ist ein systemd-Dienst unter Linux.
|
||||||
'stop_threshold' wird ffplayout stoppen, wenn es zeitlich über diesem Wert liegt. Eine Zahl kleiner als 3 kann zu unerwarteten Fehlern führen.`,
|
'stop_threshold' wird ffplayout stoppen, wenn es zeitlich über diesem Wert liegt. Eine Zahl kleiner als 3 kann zu unerwarteten Fehlern führen.`,
|
||||||
rpcText: 'Führe einen JSON-RPC-Server aus, um Informationen über die Wiedergabe und einige Kontrollfunktionen zu erhalten.',
|
rpcText:
|
||||||
|
'Führe einen JSON-RPC-Server aus, um Informationen über die Wiedergabe und einige Kontrollfunktionen zu erhalten.',
|
||||||
mailText: `Senden Sie Fehlermeldungen an die E-Mail-Adresse, z. B. fehlende Playlist, ungültiges json-Format, fehlender Clip-Pfad. Lassen Sie den Empfänger leer, wenn Sie keine Benachrichtigung benötigen. 'mail_level' kann INFO, WARNING oder ERROR sein. 'interval' bedeutet Sekunden, bis eine neue E-Mail gesendet wird.`,
|
mailText: `Senden Sie Fehlermeldungen an die E-Mail-Adresse, z. B. fehlende Playlist, ungültiges json-Format, fehlender Clip-Pfad. Lassen Sie den Empfänger leer, wenn Sie keine Benachrichtigung benötigen. 'mail_level' kann INFO, WARNING oder ERROR sein. 'interval' bedeutet Sekunden, bis eine neue E-Mail gesendet wird.`,
|
||||||
logText: `Wenn 'log_to_file' true ist, wird in eine Datei protokolliert, wenn false, in die Konsole. 'backup_count' gibt an, wie lange die Log-Dateien in Tagen gespeichert werden. 'local_time' auf false setzt die Log-Zeitstempel auf UTC. Pfad zu /var/log/ nur, wenn Sie dies als Daemon ausführen.
|
logText: `Wenn 'log_to_file' true ist, wird in eine Datei protokolliert, wenn false, in die Konsole. 'backup_count' gibt an, wie lange die Log-Dateien in Tagen gespeichert werden. 'local_time' auf false setzt die Log-Zeitstempel auf UTC. Pfad zu /var/log/ nur, wenn Sie dies als Daemon ausführen.
|
||||||
'level' kann DEBUG, INFO, WARNING, ERROR sein. 'ffmpeg_level' kann INFO, WARNING, ERROR sein. 'detect_silence' protokolliert eine Fehlermeldung, wenn die Audiospur während des Validierungsprozesses 15 Sekunden lang still ist.`,
|
'level' kann DEBUG, INFO, WARNING, ERROR sein. 'ffmpeg_level' kann INFO, WARNING, ERROR sein. 'detect_silence' protokolliert eine Fehlermeldung, wenn die Audiospur während des Validierungsprozesses 15 Sekunden lang still ist.`,
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ffplayout-frontend",
|
"name": "ffplayout-frontend",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ffplayout-frontend",
|
"name": "ffplayout-frontend",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxtjs/color-mode": "^3.4.0",
|
"@nuxtjs/color-mode": "^3.4.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ffplayout-frontend",
|
"name": "ffplayout-frontend",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"description": "Web GUI for ffplayout",
|
"description": "Web GUI for ffplayout",
|
||||||
"author": "Jonathan Baecker",
|
"author": "Jonathan Baecker",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label class="join-item btn btn-primary swap swap-rotate me-2">
|
<label class="join-item btn btn-primary swap swap-rotate me-2">
|
||||||
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" >
|
<input type="checkbox" :checked="indexStore.darkMode" @change="toggleDarkTheme" />
|
||||||
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
<SvgIcon name="swap-on" classes="w-5 h-5" />
|
||||||
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
<SvgIcon name="swap-off" classes="w-5 h-5" />
|
||||||
</label>
|
</label>
|
||||||
@ -54,7 +54,7 @@
|
|||||||
:placeholder="$t('input.username')"
|
:placeholder="$t('input.username')"
|
||||||
class="input input-bordered w-full"
|
class="input input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
v-model="formPassword"
|
v-model="formPassword"
|
||||||
@ -62,7 +62,7 @@
|
|||||||
:placeholder="$t('input.password')"
|
:placeholder="$t('input.password')"
|
||||||
class="input input-bordered w-full mt-5"
|
class="input input-bordered w-full mt-5"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
|
|
||||||
<div class="w-full mt-4 grid grid-flow-row-dense grid-cols-12 grid-rows-1 gap-2">
|
<div class="w-full mt-4 grid grid-flow-row-dense grid-cols-12 grid-rows-1 gap-2">
|
||||||
<div class="col-span-3">
|
<div class="col-span-3">
|
||||||
|
@ -205,7 +205,7 @@
|
|||||||
>
|
>
|
||||||
<div class="w-[1024px] max-w-full aspect-video">
|
<div class="w-[1024px] max-w-full aspect-video">
|
||||||
<VideoPlayer v-if="isVideo && previewOpt" reference="previewPlayer" :options="previewOpt" />
|
<VideoPlayer v-if="isVideo && previewOpt" reference="previewPlayer" :options="previewOpt" />
|
||||||
<img v-else :src="previewUrl" class="img-fluid" :alt="previewName" >
|
<img v-else :src="previewUrl" class="img-fluid" :alt="previewName" />
|
||||||
</div>
|
</div>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
@ -214,7 +214,7 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('media.newFile') }}</span>
|
<span class="label-text">{{ $t('media.newFile') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="renameNewName" type="text" class="input input-bordered w-full" >
|
<input v-model="renameNewName" type="text" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
@ -223,7 +223,7 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('media.foldername') }}</span>
|
<span class="label-text">{{ $t('media.foldername') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="folderName.name" type="text" class="input input-bordered w-full" >
|
<input v-model="folderName.name" type="text" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
@ -236,7 +236,7 @@
|
|||||||
:accept="extensions"
|
:accept="extensions"
|
||||||
multiple
|
multiple
|
||||||
@change="onFileChange"
|
@change="onFileChange"
|
||||||
>
|
/>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
@ -257,7 +257,7 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('media.uploading') }}:</span>
|
<span class="label-text">{{ $t('media.uploading') }}:</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="uploadTask" type="text" class="input input-sm input-bordered w-full" disabled >
|
<input v-model="uploadTask" type="text" class="input input-sm input-bordered w-full" disabled />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
@ -313,7 +313,7 @@ const lastPath = ref('')
|
|||||||
const xhr = ref(new XMLHttpRequest())
|
const xhr = ref(new XMLHttpRequest())
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
let config_extensions = configStore.configPlayout.storage.extensions
|
let config_extensions = configStore.playout.storage.extensions
|
||||||
let extra_extensions = configStore.configGui[configStore.configID].extra_extensions
|
let extra_extensions = configStore.configGui[configStore.configID].extra_extensions
|
||||||
|
|
||||||
if (typeof config_extensions === 'string') {
|
if (typeof config_extensions === 'string') {
|
||||||
@ -428,7 +428,7 @@ function setPreviewData(path: string) {
|
|||||||
? 'application/x-mpegURL'
|
? 'application/x-mpegURL'
|
||||||
: `video/${ext}`
|
: `video/${ext}`
|
||||||
|
|
||||||
if (configStore.configPlayout.storage.extensions.includes(`${ext}`)) {
|
if (configStore.playout.storage.extensions.includes(`${ext}`)) {
|
||||||
isVideo.value = true
|
isVideo.value = true
|
||||||
previewOpt.value = {
|
previewOpt.value = {
|
||||||
liveui: false,
|
liveui: false,
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
placeholder="X"
|
placeholder="X"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -73,7 +73,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
placeholder="Y"
|
placeholder="Y"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +86,7 @@
|
|||||||
v-model="form.showBox"
|
v-model="form.showBox"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox checkbox-xs rounded-sm"
|
class="checkbox checkbox-xs rounded-sm"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -99,7 +99,7 @@
|
|||||||
type="color"
|
type="color"
|
||||||
class="input input-sm input-bordered w-full p-1"
|
class="input input-sm input-bordered w-full p-1"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label class="form-control w-full xs:mt-[68px]">
|
<label class="form-control w-full xs:mt-[68px]">
|
||||||
@ -114,7 +114,7 @@
|
|||||||
step="0.01"
|
step="0.01"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid xs:grid-cols-[150px_150px_auto] gap-4 mt-2">
|
<div class="grid xs:grid-cols-[150px_150px_auto] gap-4 mt-2">
|
||||||
@ -128,7 +128,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-2">
|
<label class="form-control w-full mt-2">
|
||||||
@ -140,7 +140,7 @@
|
|||||||
type="color"
|
type="color"
|
||||||
class="input input-sm input-bordered w-full p-1"
|
class="input input-sm input-bordered w-full p-1"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -153,7 +153,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="form-control w-full mt-2">
|
<label class="form-control w-full mt-2">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
max="1"
|
max="1"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -181,7 +181,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="form-control w-full xs:max-w-[150px] mt-2">
|
<label class="form-control w-full xs:max-w-[150px] mt-2">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
@ -192,7 +192,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
required
|
required
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -209,7 +209,7 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">{{ $t('message.name') }}</span>
|
<span class="label-text">{{ $t('message.name') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="newPresetName" type="text" class="input input-bordered w-full" >
|
<input v-model="newPresetName" type="text" class="input input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<i class="bi-files" />
|
<i class="bi-files" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="!configStore.configPlayout.playlist.loop"
|
v-if="!configStore.playout.playlist.loop"
|
||||||
class="btn btn-sm btn-primary join-item"
|
class="btn btn-sm btn-primary join-item"
|
||||||
:title="$t('player.loop')"
|
:title="$t('player.loop')"
|
||||||
@click="loopClips()"
|
@click="loopClips()"
|
||||||
@ -72,7 +72,11 @@
|
|||||||
>
|
>
|
||||||
<i class="bi-sort-down-alt" />
|
<i class="bi-sort-down-alt" />
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-sm btn-primary join-item" :title="$t('player.reset')" @click=";(playlistStore.playlist.length = 0), getPlaylist()">
|
<button
|
||||||
|
class="btn btn-sm btn-primary join-item"
|
||||||
|
:title="$t('player.reset')"
|
||||||
|
@click=";(playlistStore.playlist.length = 0), getPlaylist()"
|
||||||
|
>
|
||||||
<i class="bi-arrow-counterclockwise" />
|
<i class="bi-arrow-counterclockwise" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@ -99,7 +103,7 @@
|
|||||||
>
|
>
|
||||||
<div class="w-[1024px] max-w-full aspect-video">
|
<div class="w-[1024px] max-w-full aspect-video">
|
||||||
<VideoPlayer v-if="isVideo && previewOpt" reference="previewPlayer" :options="previewOpt" />
|
<VideoPlayer v-if="isVideo && previewOpt" reference="previewPlayer" :options="previewOpt" />
|
||||||
<img v-else :src="previewUrl" class="img-fluid" :alt="previewName" >
|
<img v-else :src="previewUrl" class="img-fluid" :alt="previewName" />
|
||||||
</div>
|
</div>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
@ -109,14 +113,14 @@
|
|||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">In</span>
|
<span class="label-text">In</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model.number="newSource.in" type="number" class="input input-sm input-bordered w-full" >
|
<input v-model.number="newSource.in" type="number" class="input input-sm input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">Out</span>
|
<span class="label-text">Out</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model.number="newSource.out" type="number" class="input input-sm input-bordered w-full" >
|
<input v-model.number="newSource.out" type="number" class="input input-sm input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
@ -127,34 +131,34 @@
|
|||||||
v-model.number="newSource.duration"
|
v-model.number="newSource.duration"
|
||||||
type="number"
|
type="number"
|
||||||
class="input input-sm input-bordered w-full"
|
class="input input-sm input-bordered w-full"
|
||||||
>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">Source</span>
|
<span class="label-text">Source</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="newSource.source" type="text" class="input input-sm input-bordered w-full" >
|
<input v-model="newSource.source" type="text" class="input input-sm input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">Audio</span>
|
<span class="label-text">Audio</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="newSource.audio" type="text" class="input input-sm input-bordered w-full" >
|
<input v-model="newSource.audio" type="text" class="input input-sm input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full mt-3">
|
<label class="form-control w-full mt-3">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">Custom Filter</span>
|
<span class="label-text">Custom Filter</span>
|
||||||
</div>
|
</div>
|
||||||
<input v-model="newSource.custom_filter" type="text" class="input input-sm input-bordered w-full" >
|
<input v-model="newSource.custom_filter" type="text" class="input input-sm input-bordered w-full" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="cursor-pointer label">
|
<label class="cursor-pointer label">
|
||||||
<span class="label-text">Advertisement</span>
|
<span class="label-text">Advertisement</span>
|
||||||
<input type="checkbox" class="checkbox checkbox-sm" @click="isAd" >
|
<input type="checkbox" class="checkbox checkbox-sm" @click="isAd" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -166,11 +170,11 @@
|
|||||||
class="file-input file-input-sm file-input-bordered w-full"
|
class="file-input file-input-sm file-input-bordered w-full"
|
||||||
multiple
|
multiple
|
||||||
@change="onFileChange"
|
@change="onFileChange"
|
||||||
>
|
/>
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
<GenericModal :show="showCopyModal" :title="`Copy Program ${listDate}`" :modal-action="savePlaylist">
|
<GenericModal :show="showCopyModal" :title="`Copy Program ${listDate}`" :modal-action="savePlaylist">
|
||||||
<input v-model="targetDate" type="date" class="input input-sm input-bordered w-full" >
|
<input v-model="targetDate" type="date" class="input input-sm input-bordered w-full" />
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
|
|
||||||
<GenericModal :show="showDeleteModal" title="Delete Program" :modal-action="deletePlaylist">
|
<GenericModal :show="showDeleteModal" title="Delete Program" :modal-action="deletePlaylist">
|
||||||
@ -271,7 +275,7 @@ function closePlayer() {
|
|||||||
|
|
||||||
function setPreviewData(path: string) {
|
function setPreviewData(path: string) {
|
||||||
let fullPath = path
|
let fullPath = path
|
||||||
const storagePath = configStore.configPlayout.storage.path
|
const storagePath = configStore.playout.storage.path
|
||||||
const lastIndex = storagePath.lastIndexOf('/')
|
const lastIndex = storagePath.lastIndexOf('/')
|
||||||
|
|
||||||
if (!path.includes('/')) {
|
if (!path.includes('/')) {
|
||||||
@ -301,7 +305,7 @@ function setPreviewData(path: string) {
|
|||||||
? 'application/x-mpegURL'
|
? 'application/x-mpegURL'
|
||||||
: `video/${ext}`
|
: `video/${ext}`
|
||||||
|
|
||||||
if (configStore.configPlayout.storage.extensions.includes(`${ext}`)) {
|
if (configStore.playout.storage.extensions.includes(`${ext}`)) {
|
||||||
isVideo.value = true
|
isVideo.value = true
|
||||||
previewOpt.value = {
|
previewOpt.value = {
|
||||||
liveui: false,
|
liveui: false,
|
||||||
@ -327,20 +331,10 @@ function processSource(process: boolean) {
|
|||||||
if (process) {
|
if (process) {
|
||||||
if (editId.value === -1) {
|
if (editId.value === -1) {
|
||||||
playlistStore.playlist.push(newSource.value)
|
playlistStore.playlist.push(newSource.value)
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(listDate.value, playlistStore.playlist, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
playlistStore.playlist,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
playlistStore.playlist[editId.value] = newSource.value
|
playlistStore.playlist[editId.value] = newSource.value
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(listDate.value, playlistStore.playlist, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
playlistStore.playlist,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +393,7 @@ function loopClips() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playlistStore.playlist = processPlaylist(configStore.startInSec, configStore.playlistLength, tempList, false)
|
playlistStore.playlist = processPlaylist(listDate.value, tempList, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFileChange(evt: any) {
|
function onFileChange(evt: any) {
|
||||||
@ -455,12 +449,7 @@ async function savePlaylist(save: boolean) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
playlistStore.playlist = processPlaylist(
|
playlistStore.playlist = processPlaylist(listDate.value, playlistStore.playlist, true)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
playlistStore.playlist,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
const saveList = playlistStore.playlist.map(({ begin, ...item }) => item)
|
const saveList = playlistStore.playlist.map(({ begin, ...item }) => item)
|
||||||
|
|
||||||
await $fetch(`/api/playlist/${configStore.configGui[configStore.configID].id}/`, {
|
await $fetch(`/api/playlist/${configStore.configGui[configStore.configID].id}/`, {
|
||||||
|
@ -3,12 +3,12 @@ import type { LoDashStatic } from 'lodash'
|
|||||||
|
|
||||||
declare module '#app' {
|
declare module '#app' {
|
||||||
interface NuxtApp {
|
interface NuxtApp {
|
||||||
$_: LoDashStatic;
|
$_: LoDashStatic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
$_: LoDashStatic;
|
$_: LoDashStatic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
import VueDatePicker from '@vuepic/vue-datepicker'
|
||||||
import '@vuepic/vue-datepicker/dist/main.css'
|
import '@vuepic/vue-datepicker/dist/main.css'
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
@ -10,9 +10,8 @@ export const useConfig = defineStore('config', {
|
|||||||
contentType: { 'content-type': 'application/json;charset=UTF-8' },
|
contentType: { 'content-type': 'application/json;charset=UTF-8' },
|
||||||
configGui: [] as GuiConfig[],
|
configGui: [] as GuiConfig[],
|
||||||
configGuiRaw: [] as GuiConfig[],
|
configGuiRaw: [] as GuiConfig[],
|
||||||
startInSec: 0,
|
|
||||||
playlistLength: 86400.0,
|
playlistLength: 86400.0,
|
||||||
configPlayout: {} as any,
|
playout: {} as any,
|
||||||
currentUser: '',
|
currentUser: '',
|
||||||
configUser: {} as User,
|
configUser: {} as User,
|
||||||
utcOffset: 0,
|
utcOffset: 0,
|
||||||
@ -41,7 +40,7 @@ export const useConfig = defineStore('config', {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: authStore.authHeader,
|
headers: authStore.authHeader,
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
statusCode = response.status
|
statusCode = response.status
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@ -128,19 +127,14 @@ export const useConfig = defineStore('config', {
|
|||||||
})
|
})
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.playlist.day_start) {
|
data.playlist.startInSec = timeToSeconds(data.playlist.day_start ?? 0)
|
||||||
this.startInSec = timeToSeconds(data.playlist.day_start)
|
data.playlist.lengthInSec = timeToSeconds(data.playlist.length ?? this.playlistLength)
|
||||||
}
|
|
||||||
|
|
||||||
if (data.playlist.length) {
|
|
||||||
this.playlistLength = timeToSeconds(data.playlist.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.storage.extensions) {
|
if (data.storage.extensions) {
|
||||||
data.storage.extensions = data.storage.extensions.join(',')
|
data.storage.extensions = data.storage.extensions.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.configPlayout = data
|
this.playout = data
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
indexStore.msgAlert('error', 'No playout config found!', 3)
|
indexStore.msgAlert('error', 'No playout config found!', 3)
|
||||||
@ -151,8 +145,9 @@ export const useConfig = defineStore('config', {
|
|||||||
const authStore = useAuth()
|
const authStore = useAuth()
|
||||||
const channel = this.configGui[this.configID].id
|
const channel = this.configGui[this.configID].id
|
||||||
|
|
||||||
this.startInSec = timeToSeconds(obj.playlist.day_start)
|
|
||||||
this.playlistLength = timeToSeconds(obj.playlist.length)
|
this.playlistLength = timeToSeconds(obj.playlist.length)
|
||||||
|
this.playout.playlist.startInSec = timeToSeconds(obj.playlist.day_start)
|
||||||
|
this.playout.playlist.lengthInSec = timeToSeconds(obj.playlist.length)
|
||||||
|
|
||||||
if (typeof obj.storage.extensions === 'string') {
|
if (typeof obj.storage.extensions === 'string') {
|
||||||
obj.storage.extensions = obj.storage.extensions.replace(' ', '').split(/,|;/)
|
obj.storage.extensions = obj.storage.extensions.replace(' ', '').split(/,|;/)
|
||||||
|
@ -7,7 +7,6 @@ import { defineStore } from 'pinia'
|
|||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
dayjs.extend(timezone)
|
dayjs.extend(timezone)
|
||||||
|
|
||||||
// const { timeToSeconds } = stringFormatter()
|
|
||||||
const { processPlaylist } = playlistOperations()
|
const { processPlaylist } = playlistOperations()
|
||||||
|
|
||||||
export const usePlaylist = defineStore('playlist', {
|
export const usePlaylist = defineStore('playlist', {
|
||||||
@ -34,15 +33,8 @@ export const usePlaylist = defineStore('playlist', {
|
|||||||
const authStore = useAuth()
|
const authStore = useAuth()
|
||||||
const configStore = useConfig()
|
const configStore = useConfig()
|
||||||
const indexStore = useIndex()
|
const indexStore = useIndex()
|
||||||
let statusCode = 0
|
|
||||||
|
|
||||||
// const timeInSec = timeToSeconds(dayjs().utcOffset(configStore.utcOffset).format('HH:mm:ss'))
|
|
||||||
const channel = configStore.configGui[configStore.configID].id
|
const channel = configStore.configGui[configStore.configID].id
|
||||||
// let dateToday = dayjs().utcOffset(configStore.utcOffset).format('YYYY-MM-DD')
|
let statusCode = 0
|
||||||
|
|
||||||
// if (configStore.startInSec > timeInSec) {
|
|
||||||
// dateToday = dayjs(dateToday).utcOffset(configStore.utcOffset).subtract(1, 'day').format('YYYY-MM-DD')
|
|
||||||
// }
|
|
||||||
|
|
||||||
await fetch(`/api/playlist/${channel}?date=${date}`, {
|
await fetch(`/api/playlist/${channel}?date=${date}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -55,32 +47,29 @@ export const usePlaylist = defineStore('playlist', {
|
|||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.program) {
|
if (data.program) {
|
||||||
const programData = processPlaylist(
|
const programData = processPlaylist(date, data.program, false)
|
||||||
configStore.startInSec,
|
|
||||||
configStore.playlistLength,
|
|
||||||
data.program,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.playlist.length > 0 &&
|
this.playlist.length > 0 &&
|
||||||
|
programData.length > 0 &&
|
||||||
|
this.playlist[0].date === date &&
|
||||||
$_.differenceWith(this.playlist, programData, (a, b) => {
|
$_.differenceWith(this.playlist, programData, (a, b) => {
|
||||||
return $_.isEqual($_.omit(a, ['uid']), $_.omit(b, ['uid']))
|
return $_.isEqual($_.omit(a, ['uid']), $_.omit(b, ['uid']))
|
||||||
}).length > 0
|
}).length > 0
|
||||||
) {
|
) {
|
||||||
indexStore.msgAlert('warning', $i18n.t('player.unsavedProgram'), 3)
|
indexStore.msgAlert('warning', $i18n.t('player.unsavedProgram'), 3)
|
||||||
} else if (this.playlist.length === 0) {
|
} else {
|
||||||
this.playlist = programData
|
this.playlist = programData ?? []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
if (statusCode > 0 && statusCode !== 204) {
|
if (statusCode >= 400) {
|
||||||
indexStore.msgAlert('error', e, 3)
|
indexStore.msgAlert('error', e, 3)
|
||||||
}
|
} else if (this.playlist.length > 0 && this.playlist[0].date === date) {
|
||||||
|
|
||||||
if (this.playlist.length > 0) {
|
|
||||||
indexStore.msgAlert('warning', $i18n.t('player.unsavedProgram'), 3)
|
indexStore.msgAlert('warning', $i18n.t('player.unsavedProgram'), 3)
|
||||||
|
} else {
|
||||||
|
this.playlist = []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
boxShadow: {
|
boxShadow: {
|
||||||
'3xl': '0 1em 5em rgba(0, 0, 0, 0.3)',
|
'3xl': '0 1em 5em rgba(0, 0, 0, 0.3)',
|
||||||
'glow': '0 0 10px rgba(0, 0, 0, 0.3)',
|
glow: '0 0 10px rgba(0, 0, 0, 0.3)',
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
'my-gray': 'var(--my-gray)',
|
'my-gray': 'var(--my-gray)',
|
||||||
|
5
types/index.d.ts
vendored
5
types/index.d.ts
vendored
@ -48,6 +48,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface PlaylistItem {
|
interface PlaylistItem {
|
||||||
|
date?: string
|
||||||
uid: string
|
uid: string
|
||||||
begin: number
|
begin: number
|
||||||
source: string
|
source: string
|
||||||
@ -57,7 +58,7 @@ declare global {
|
|||||||
audio?: string
|
audio?: string
|
||||||
category?: string
|
category?: string
|
||||||
custom_filter?: string
|
custom_filter?: string
|
||||||
class?: string
|
overtime?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FileObject {
|
interface FileObject {
|
||||||
@ -112,6 +113,6 @@ declare global {
|
|||||||
network?: { name: string; current_in: number; current_out: number; total_in: number; total_out: number }
|
network?: { name: string; current_in: number; current_out: number; total_in: number; total_out: number }
|
||||||
storage?: { path: string; total: number; used: number }
|
storage?: { path: string; total: number; used: number }
|
||||||
swap: { total: number; used: number; free: number }
|
swap: { total: number; used: number; free: number }
|
||||||
system: { name?: string; kernel?: string; version?: string, ffp_version?: string }
|
system: { name?: string; kernel?: string; version?: string; ffp_version?: string }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user