fix $t type errors, fix message presets, create new preset set on channel creation

This commit is contained in:
jb-alvarado 2024-08-27 11:16:58 +02:00
parent 0b1e083ce5
commit 8d8ab58ef4
19 changed files with 538 additions and 826 deletions

View File

@ -1,7 +1,7 @@
<template>
<div class="min-w-[200px] pe-8 w-[768px]">
<h2 class="pt-3 text-3xl">{{ $t('advanced.title') }}</h2>
<p class="mt-5 font-bold text-orange-500">{{ $t('advanced.warning') }}</p>
<h2 class="pt-3 text-3xl">{{ t('advanced.title') }}</h2>
<p class="mt-5 font-bold text-orange-500">{{ t('advanced.warning') }}</p>
<form
v-if="configStore.advanced"
class="mt-10 grid md:grid-cols-[180px_auto] gap-5"
@ -28,14 +28,14 @@
</div>
</template>
<div class="mt-5 mb-10">
<button class="btn btn-primary" type="submit">{{ $t('config.save') }}</button>
<button class="btn btn-primary" type="submit">{{ t('config.save') }}</button>
</div>
</form>
</div>
<GenericModal
:title="$t('config.restartTile')"
:text="$t('config.restartText')"
:title="t('config.restartTile')"
:text="t('config.restartText')"
:show="showModal"
:modal-action="restart"
/>

View File

@ -1,15 +1,15 @@
<template>
<div v-if="configStore.channels && configStore.channels[configStore.id]" class="w-full max-w-[800px]">
<h2 class="pt-3 text-3xl">{{ $t('config.channelConf') }} ({{ configStore.channels[configStore.id].id }})</h2>
<h2 class="pt-3 text-3xl">{{ t('config.channelConf') }} ({{ configStore.channels[configStore.id].id }})</h2>
<div class="w-full flex justify-end my-4">
<button v-if="authStore.role === 'GlobalAdmin'" class="btn btn-sm btn-primary" @click="addChannel()">
{{ $t('config.addChannel') }}
{{ t('config.addChannel') }}
</button>
</div>
<form class="w-full" @submit.prevent="onSubmitChannel">
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('config.name') }}</span>
<span class="label-text">{{ t('config.name') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].name"
@ -21,7 +21,7 @@
<label class="form-control w-full mt-5">
<div class="label">
<span class="label-text">{{ $t('config.previewUrl') }}</span>
<span class="label-text">{{ t('config.previewUrl') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].preview_url"
@ -32,7 +32,7 @@
<label class="form-control w-full mt-5">
<div class="label">
<span class="label-text">{{ $t('config.extensions') }}</span>
<span class="label-text">{{ t('config.extensions') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].extra_extensions"
@ -45,12 +45,12 @@
<div class="mt-7 font-bold h-3">
<p v-if="configStore.playout.storage.shared_storage">
<SvgIcon name="warning" classes="inline mr-2" />
<span>{{ $t('config.sharedStorage') }}</span>
<span>{{ t('config.sharedStorage') }}</span>
</p>
</div>
<label class="form-control w-full mt-3">
<div class="label">
<span class="label-text">{{ $t('config.hlsPath') }}</span>
<span class="label-text">{{ t('config.hlsPath') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].hls_path"
@ -61,7 +61,7 @@
<label class="form-control w-full mt-5">
<div class="label">
<span class="label-text">{{ $t('config.playlistPath') }}</span>
<span class="label-text">{{ t('config.playlistPath') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].playlist_path"
@ -72,7 +72,7 @@
<label class="form-control w-full mt-5">
<div class="label">
<span class="label-text">{{ $t('config.storagePath') }}</span>
<span class="label-text">{{ t('config.storagePath') }}</span>
</div>
<input
v-model="configStore.channels[configStore.id].storage_path"
@ -83,7 +83,7 @@
</template>
<div class="join my-4">
<button class="join-item btn btn-primary" type="submit">{{ $t('config.save') }}</button>
<button class="join-item btn btn-primary" type="submit">{{ t('config.save') }}</button>
<button
v-if="
authStore.role === 'GlobalAdmin' &&
@ -93,7 +93,7 @@
class="join-item btn btn-primary"
@click="deleteChannel()"
>
{{ $t('config.delete') }}
{{ t('config.delete') }}
</button>
</div>
</form>
@ -134,7 +134,9 @@ async function onSubmitChannel() {
*/
const update = await configStore.setChannelConfig(configStore.channels[configStore.id])
if (update.status) {
console.log(update)
if (update.status && update.status < 400) {
indexStore.msgAlert('success', t('config.updateChannelSuccess'), 2)
} else {
indexStore.msgAlert('error', t('config.updateChannelFailed'), 2)

View File

@ -1,6 +1,6 @@
<template>
<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
v-if="configStore.playout"
class="mt-10 grid md:grid-cols-[180px_auto] gap-5"
@ -26,7 +26,7 @@
v-else-if="name.toString() === 'sender_pass'"
v-model="item[name]"
type="password"
:placeholder="$t('config.placeholderPass')"
:placeholder="t('config.placeholderPass')"
class="input input-sm input-bordered w-full"
/>
<textarea
@ -73,14 +73,14 @@
</div>
</template>
<div class="mt-5 mb-10">
<button class="btn btn-primary" type="submit">{{ $t('config.save') }}</button>
<button class="btn btn-primary" type="submit">{{ t('config.save') }}</button>
</div>
</form>
</div>
<GenericModal
:title="$t('config.restartTile')"
:text="$t('config.restartText')"
:title="t('config.restartTile')"
:text="t('config.restartText')"
:show="showModal"
:modal-action="restart"
/>

View File

@ -1,6 +1,6 @@
<template>
<div class="w-full max-w-[800px] pe-8">
<h2 class="pt-3 text-3xl">{{ $t('user.title') }}</h2>
<h2 class="pt-3 text-3xl">{{ t('user.title') }}</h2>
<div v-if="authStore.role === 'GlobalAdmin'" class="flex flex-col xs:flex-row gap-2 w-full mb-5 mt-10">
<div class="grow">
<select v-model="selected" class="select select-bordered w-full max-w-xs" @change="onChange($event)">
@ -9,17 +9,17 @@
</div>
<div class="flex-none join">
<button class="join-item btn btn-primary" title="Add new User" @click="showUserModal = true">
{{ $t('user.add') }}
{{ t('user.add') }}
</button>
<button class="join-item btn btn-primary" title="Delete selected user" @click="deleteUser()">
{{ $t('user.delete') }}
{{ t('user.delete') }}
</button>
</div>
</div>
<form v-if="configStore.configUser" class="mt-5" @submit.prevent="onSubmitUser">
<label class="form-control w-full max-w-md">
<div class="label">
<span class="label-text">{{ $t('user.name') }}</span>
<span class="label-text">{{ t('user.name') }}</span>
</div>
<input
v-model="configStore.configUser.username"
@ -31,21 +31,21 @@
<label class="form-control w-full max-w-md mt-3">
<div class="label">
<span class="label-text">{{ $t('user.mail') }}</span>
<span class="label-text">{{ t('user.mail') }}</span>
</div>
<input v-model="configStore.configUser.mail" type="email" class="input input-bordered w-full" />
</label>
<label class="form-control w-full max-w-md mt-3">
<div class="label">
<span class="label-text">{{ $t('user.newPass') }}</span>
<span class="label-text">{{ t('user.newPass') }}</span>
</div>
<input v-model="newPass" type="password" class="input input-bordered w-full" />
</label>
<label class="form-control w-full max-w-md mt-3">
<div class="label">
<span class="label-text">{{ $t('user.confirmPass') }}</span>
<span class="label-text">{{ t('user.confirmPass') }}</span>
</div>
<input v-model="confirmPass" type="password" class="input input-bordered w-full" />
</label>
@ -65,7 +65,7 @@
</div>
<div>
<button class="btn btn-primary mt-5" type="submit">{{ $t('user.save') }}</button>
<button class="btn btn-primary mt-5" type="submit">{{ t('user.save') }}</button>
</div>
</form>
</div>
@ -74,28 +74,28 @@
<div class="w-full max-w-[500px] h-[490px]">
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('user.name') }}</span>
<span class="label-text">{{ t('user.name') }}</span>
</div>
<input v-model="user.username" name="username" type="text" class="input input-bordered w-full" />
</label>
<label class="form-control w-full mt-3">
<div class="label">
<span class="label-text">{{ $t('user.mail') }}</span>
<span class="label-text">{{ t('user.mail') }}</span>
</div>
<input v-model="user.mail" name="mail" type="email" class="input input-bordered w-full" />
</label>
<label class="form-control w-full mt-3">
<div class="label">
<span class="label-text">{{ $t('user.password') }}</span>
<span class="label-text">{{ t('user.password') }}</span>
</div>
<input v-model="user.password" type="password" class="input input-bordered w-full" />
</label>
<label class="form-control w-full mt-3">
<div class="label">
<span class="label-text">{{ $t('user.confirmPass') }}</span>
<span class="label-text">{{ t('user.confirmPass') }}</span>
</div>
<input v-model="user.confirm" type="password" class="input input-bordered w-full" />
</label>
@ -115,7 +115,7 @@
<div class="form-control mt-3">
<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 v-model.number="user.admin" type="checkbox" class="checkbox" />
</label>
</div>

View File

@ -3,10 +3,12 @@
<div
class="w-2 h-2 rounded-full"
:class="indexStore.sseConnected ? 'bg-success shadow shadow-success' : 'bg-error shadow shadow-error'"
:title="indexStore.sseConnected ? $t('socketConnected') : $t('socketDisconnected')"
:title="indexStore.sseConnected ? t('socketConnected') : t('socketDisconnected')"
/>
</div>
</template>
<script setup lang="ts">
const { t } = useI18n()
const indexStore = useIndex()
</script>

View File

@ -19,10 +19,10 @@
<div v-if="!hideButtons" class="flex justify-end mt-3">
<div class="join">
<button class="btn btn-sm bg-base-300 hover:bg-base-300/50 join-item" @click="modalAction(false)">
{{ $t('cancel') }}
{{ t('cancel') }}
</button>
<button class="btn btn-sm bg-base-300 hover:bg-base-300/50 join-item" @click="modalAction(true)">
{{ $t('ok') }}
{{ t('ok') }}
</button>
</div>
</div>
@ -30,6 +30,8 @@
</div>
</template>
<script setup lang="ts">
const { t } = useI18n()
defineProps({
title: {
type: String,

View File

@ -40,7 +40,7 @@
</li>
<li class="bg-base-100 rounded-md">
<button class="h-[27px] text-base" exactActiveClass="is-active" @click="logout()">
{{ $t('button.logout') }}
{{ t('button.logout') }}
</button>
</li>
</ul>
@ -77,7 +77,7 @@
</li>
<li class="bg-base-100 rounded-md p-0">
<button class="h-[27px] pt-[4px] text-base" @click="logout()">
{{ $t('button.logout') }}
{{ t('button.logout') }}
</button>
</li>
<li class="p-0">

View File

@ -51,7 +51,7 @@
<div class="w-full h-full bg-base-100 rounded flex items-center p-3 shadow">
<div class="w-full h-full flex flex-col">
<div v-if="playlistStore.ingestRuns" class="h-1/3 font-bold truncate">
{{ $t('control.ingest') }}
{{ t('control.ingest') }}
</div>
<div
v-else
@ -61,18 +61,18 @@
{{
playlistStore.currentClipTitle ||
filename(playlistStore.currentClip) ||
$t('control.noClip')
t('control.noClip')
}}
</div>
<div class="grow">
<strong>{{ $t('player.duration') }}:</strong>
<strong>{{ t('player.duration') }}:</strong>
{{ secToHMS(playlistStore.currentClipDuration) }} |
<strong>{{ $t('player.in') }}:</strong> {{ secToHMS(playlistStore.currentClipIn) }} |
<strong>{{ $t('player.out') }}:</strong>
<strong>{{ t('player.in') }}:</strong> {{ secToHMS(playlistStore.currentClipIn) }} |
<strong>{{ t('player.out') }}:</strong>
{{ secToHMS(playlistStore.currentClipOut) }}
<template v-if="playlistStore.shift !== 0">
| <strong>{{ $t('player.shift') }}:</strong>
| <strong>{{ t('player.shift') }}:</strong>
{{ secToHMS(playlistStore.shift) }}
</template>
</div>
@ -94,7 +94,7 @@
<div class="text-center">
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.start')"
:title="t('control.start')"
class="btn btn-primary h-full w-full text-7xl text-lime-600"
:class="playlistStore.playoutIsRunning && 'shadow-glow shadow-lime-600'"
@click="controlProcess('start')"
@ -104,7 +104,7 @@
</div>
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.last')"
:title="t('control.last')"
class="btn btn-primary h-full w-full text-7xl text-cyan-600"
@click="controlPlayout('back')"
>
@ -116,7 +116,7 @@
<div class="text-center">
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.stop')"
:title="t('control.stop')"
class="btn btn-primary h-full w-full text-7xl text-red-600"
@click="controlProcess('stop')"
>
@ -126,7 +126,7 @@
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.reset')"
:title="t('control.reset')"
class="btn btn-primary h-full w-full text-6xl text-cyan-600"
@click="controlPlayout('reset')"
>
@ -138,7 +138,7 @@
<div class="text-center">
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.restart')"
:title="t('control.restart')"
class="btn btn-primary h-full w-full text-6xl text-yellow-500"
@click="controlProcess('restart')"
>
@ -148,7 +148,7 @@
<div class="w-full h-1/2 aspect-square p-2">
<button
:title="$t('control.next')"
:title="t('control.next')"
class="btn btn-primary h-full w-full text-7xl text-cyan-600"
@click="controlPlayout('next')"
>
@ -258,7 +258,7 @@ watch([data], () => {
try {
const playout_status = JSON.parse(data.value)
playlistStore.setStatus(playout_status)
} catch (_) {
} catch {
indexStore.sseConnected = true
resetStatus()
}

View File

@ -5,7 +5,7 @@
<div
class="relative flex flex-col bg-base-100 w-[800px] min-w-[300px] max-w-[90vw] h-[680px] rounded-md p-5 shadow-xl"
>
<div class="font-bold text-lg">{{ $t('player.generateProgram') }}</div>
<div class="font-bold text-lg">{{ t('player.generateProgram') }}</div>
<div class="h-[calc(100%-95px)] mt-3">
<div role="tablist" class="tabs tabs-bordered">
@ -14,7 +14,7 @@
name="my_tabs_2"
role="tab"
class="tab"
:aria-label="$t('player.simple')"
:aria-label="t('player.simple')"
checked
@change="advancedGenerator = false"
/>
@ -91,7 +91,7 @@
name="my_tabs_2"
role="tab"
class="tab"
:aria-label="$t('player.advanced')"
:aria-label="t('player.advanced')"
@change=";(advancedGenerator = true), resetCheckboxes()"
/>
<div role="tabpanel" class="tab-content pt-3">
@ -118,7 +118,7 @@
<button
type="button"
class="btn btn-sm btn-primary"
:title="$t('player.addBlock')"
:title="t('player.addBlock')"
@click="addTemplate()"
>
<i class="bi bi-folder-plus" />
@ -174,7 +174,7 @@
<div
class="input input-sm input-bordered join-item px-2 text-center bg-base-200 leading-7"
>
{{ $t('player.start') }}:
{{ t('player.start') }}:
</div>
<input
v-model="item.start"
@ -184,7 +184,7 @@
<div
class="input input-sm input-bordered join-item px-2 text-center bg-base-200 leading-7"
>
{{ $t('player.duration') }}:
{{ t('player.duration') }}:
</div>
<input
v-model="item.duration"
@ -196,7 +196,7 @@
:class="item.shuffle ? 'bg-base-100' : 'bg-base-300'"
@click="item.shuffle = !item.shuffle"
>
{{ item.shuffle ? $t('player.shuffle') : $t('player.sorted') }}
{{ item.shuffle ? t('player.shuffle') : t('player.sorted') }}
</button>
</div>
@ -241,7 +241,7 @@
<div class="flex h-14 pt-6 justify-end items-center">
<div v-if="!advancedGenerator" class="form-control">
<label class="label cursor-pointer w-12">
<span class="label-text">{{ $t('player.all') }}</span>
<span class="label-text">{{ t('player.all') }}</span>
<input
v-model="generateFromAll"
type="checkbox"
@ -256,10 +256,10 @@
class="btn btn-sm btn-primary join-item"
@click="resetCheckboxes(), resetTemplate(), close()"
>
{{ $t('cancel') }}
{{ t('cancel') }}
</button>
<button type="button" class="btn btn-sm btn-primary join-item" @click="generatePlaylist(), close()">
{{ $t('ok') }}
{{ t('ok') }}
</button>
</div>
</div>

View File

@ -12,47 +12,47 @@
<tr class="bg-base-100 rounded-tr-lg">
<th v-if="!configStore.playout.playlist.infinit" class="w-[85px] p-0 text-left">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.start') }}
{{ t('player.start') }}
</div>
</th>
<th class="w-full p-0 text-left">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.file') }}
{{ t('player.file') }}
</div>
</th>
<th class="w-[85px] p-0 text-center">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.play') }}
{{ t('player.play') }}
</div>
</th>
<th class="w-[85px] p-0 text-center">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.duration') }}
{{ t('player.duration') }}
</div>
</th>
<th class="w-[85px] p-0 text-center hidden xl:table-cell">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.in') }}
{{ t('player.in') }}
</div>
</th>
<th class="w-[85px] p-0 text-center hidden xl:table-cell">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.out') }}
{{ t('player.out') }}
</div>
</th>
<th class="w-[85px] p-0 text-center hidden xl:table-cell justify-center">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.ad') }}
{{ t('player.ad') }}
</div>
</th>
<th class="w-[85px] p-0 text-center">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.edit') }}
{{ t('player.edit') }}
</div>
</th>
<th class="w-[85px] p-0 text-center hidden xl:table-cell justify-center">
<div class="border-b border-my-gray px-4 py-3 -mb-[2px]">
{{ $t('player.delete') }}
{{ t('player.delete') }}
</div>
</th>
</tr>
@ -125,6 +125,7 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia'
const { t } = useI18n()
const { $dayjs } = useNuxtApp()
const { width } = useWindowSize({ initialWidth: 800 })

View File

@ -15,18 +15,18 @@
</span>
</div>
<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 gap-2">
<div>
<strong>{{ $t('system.cores') }}:</strong> {{ sysStat.cpu.cores }}
<strong>{{ t('system.cores') }}:</strong> {{ sysStat.cpu.cores }}
</div>
<div>
<strong>{{ $t('system.usage') }}:</strong> {{ sysStat.cpu.usage.toFixed(2) }}%
<strong>{{ t('system.usage') }}:</strong> {{ sysStat.cpu.usage.toFixed(2) }}%
</div>
</div>
</div>
<div class="p-4 border border-primary">
<div class="text-xl">{{ $t('system.load') }}</div>
<div class="text-xl">{{ t('system.load') }}</div>
<div class="grid grid-cols-3 gap-2">
<div>{{ sysStat.load.one }}</div>
<div>{{ sysStat.load.five }}</div>
@ -34,54 +34,54 @@
</div>
</div>
<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 gap-2">
<div>
<strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.memory.total) }}
<strong>{{ t('system.total') }}:</strong> {{ fileSize(sysStat.memory.total) }}
</div>
<div>
<strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.memory.used) }}
<strong>{{ t('system.usage') }}:</strong> {{ fileSize(sysStat.memory.used) }}
</div>
</div>
</div>
<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 gap-2">
<div>
<strong>{{ $t('system.total') }}:</strong> {{ fileSize(sysStat.swap.total) }}
<strong>{{ t('system.total') }}:</strong> {{ fileSize(sysStat.swap.total) }}
</div>
<div>
<strong>{{ $t('system.usage') }}:</strong> {{ fileSize(sysStat.swap.used) }}
<strong>{{ t('system.usage') }}:</strong> {{ fileSize(sysStat.swap.used) }}
</div>
</div>
</div>
<div class="p-4 border border-primary">
<div class="text-xl">
{{ $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 class="grid grid-cols-2 gap-2">
<div>
<strong>{{ $t('system.in') }}:</strong> {{ fileSize(sysStat.network?.current_in) }}
<strong>{{ t('system.in') }}:</strong> {{ fileSize(sysStat.network?.current_in) }}
</div>
<div>
<strong>{{ $t('system.out') }}:</strong> {{ fileSize(sysStat.network?.current_out) }}
<strong>{{ t('system.out') }}:</strong> {{ fileSize(sysStat.network?.current_out) }}
</div>
<div>{{ fileSize(sysStat.network?.total_in) }}</div>
<div>{{ fileSize(sysStat.network?.total_out) }}</div>
</div>
</div>
<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" class="grid grid-cols-2 gap-2">
<div v-if="sysStat.storage" class="col-span-2">
<strong>{{ $t('system.device') }}:</strong> {{ sysStat.storage?.path }}
<strong>{{ t('system.device') }}:</strong> {{ sysStat.storage?.path }}
</div>
<div>
<strong>{{ $t('system.size') }}:</strong> {{ fileSize(sysStat.storage?.total) }}
<strong>{{ t('system.size') }}:</strong> {{ fileSize(sysStat.storage?.total) }}
</div>
<div>
<strong>{{ $t('system.used') }}:</strong> {{ fileSize(sysStat.storage?.used) }}
<strong>{{ t('system.used') }}:</strong> {{ fileSize(sysStat.storage?.used) }}
</div>
</div>
</div>
@ -90,6 +90,7 @@
</template>
<script setup lang="ts">
const { fileSize } = stringFormatter()
const { t } = useI18n()
const authStore = useAuth()
const configStore = useConfig()
@ -151,7 +152,7 @@ watch([data], () => {
if (data.value) {
try {
sysStat.value = JSON.parse(data.value)
} catch (_) {
} catch {
indexStore.sseConnected = true
}
}

1021
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "ffplayout-frontend",
"version": "0.11.3",
"version": "0.12.0",
"description": "Web GUI for ffplayout",
"author": "Jonathan Baecker",
"private": true,
@ -17,7 +17,7 @@
"@pinia/nuxt": "^0.5.4",
"@vueform/multiselect": "^2.6.9",
"@vuepic/vue-datepicker": "^9.0.2",
"@vueuse/nuxt": "^11.0.1",
"@vueuse/nuxt": "^11.0.3",
"bootstrap-icons": "^1.11.3",
"dayjs": "^1.11.13",
"jwt-decode": "^4.0.0",
@ -30,8 +30,8 @@
"video.js": "^8.17.3"
},
"devDependencies": {
"@nuxt/eslint": "^0.5.2",
"@nuxtjs/i18n": "^8.5.0",
"@nuxt/eslint": "^0.5.3",
"@nuxtjs/i18n": "^8.5.1",
"@nuxtjs/tailwindcss": "^6.12.1",
"@types/lodash": "^4.17.7",
"@types/video.js": "^7.3.58",

View File

@ -6,7 +6,7 @@
:class="activeConf === 1 && 'btn-secondary'"
@click="activeConf = 1"
>
{{ $t('config.channel') }}
{{ t('config.channel') }}
</button>
<button
v-if="authStore.role === 'GlobalAdmin'"
@ -28,7 +28,7 @@
:class="activeConf === 4 && 'btn-secondary'"
@click="activeConf = 4"
>
{{ $t('config.user') }}
{{ t('config.user') }}
</button>
</div>
<div class="w-[calc(100%-70px)] mt-10 px-6">

View File

@ -7,26 +7,26 @@
<SystemStats v-if="configStore.channels.length > 0" />
<div class="flex flex-wrap justify-center gap-1 md:gap-0 md:join mt-5">
<NuxtLink :to="localePath({ name: 'player' })" class="btn join-item btn-primary px-2">
{{ $t('button.player') }}
{{ t('button.player') }}
</NuxtLink>
<NuxtLink :to="localePath({ name: 'media' })" class="btn join-item btn-primary px-2">
{{ $t('button.media') }}
{{ t('button.media') }}
</NuxtLink>
<NuxtLink :to="localePath({ name: 'message' })" class="btn join-item btn-primary px-2">
{{ $t('button.message') }}
{{ t('button.message') }}
</NuxtLink>
<NuxtLink :to="localePath({ name: 'logging' })" class="btn join-item btn-primary px-2">
{{ $t('button.logging') }}
{{ t('button.logging') }}
</NuxtLink>
<NuxtLink
v-if="authStore.role.toLowerCase().includes('admin')"
:to="localePath({ name: 'configure' })"
class="btn join-item btn-primary px-2"
>
{{ $t('button.configure') }}
{{ t('button.configure') }}
</NuxtLink>
<button class="btn join-item btn-primary px-2" @click="logout()">
{{ $t('button.logout') }}
{{ t('button.logout') }}
</button>
<select
v-model="selectedLang"
@ -55,7 +55,7 @@
v-model="formUsername"
type="text"
name="username"
:placeholder="$t('input.username')"
:placeholder="t('input.username')"
class="input input-bordered w-full"
required
/>
@ -64,7 +64,7 @@
v-model="formPassword"
type="password"
name="passwort"
:placeholder="$t('input.password')"
:placeholder="t('input.password')"
class="input input-bordered w-full mt-5"
required
/>
@ -72,7 +72,7 @@
<div class="w-full mt-4 grid grid-flow-row-dense grid-cols-12 grid-rows-1 gap-2">
<div class="col-span-3">
<button type="submit" class="btn btn-primary">
{{ $t('button.login') }}
{{ t('button.login') }}
</button>
</div>
<div class="col-span-12 sm:col-span-9">

View File

@ -25,7 +25,7 @@
:ui="{ input: 'join-item input !input-sm !input-bordered !w-[300px] text-right !pe-3' }"
required
/>
<button class="btn btn-sm btn-primary join-item" :title="$t('log.download')" @click="downloadLog">
<button class="btn btn-sm btn-primary join-item" :title="t('log.download')" @click="downloadLog">
<i class="bi-download" />
</button>
</div>

View File

@ -212,14 +212,14 @@
<div class="join">
<button
class="btn btn-sm btn-primary join-item"
:title="$t('media.create')"
:title="t('media.create')"
@click="showCreateModal = true"
>
<i class="bi-folder-plus" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('media.upload')"
:title="t('media.upload')"
@click="showUploadModal = true"
>
<i class="bi-upload" />
@ -230,14 +230,14 @@
<GenericModal
:show="showDeleteModal"
:title="$t('media.deleteTitle')"
:text="`${$t('media.deleteQuestion')}:<br /><strong>${deleteName}</strong>`"
:title="t('media.deleteTitle')"
:text="`${t('media.deleteQuestion')}:<br /><strong>${deleteName}</strong>`"
:modal-action="deleteFileOrFolder"
/>
<GenericModal
:show="showPreviewModal"
:title="`${$t('media.preview')}: ${previewName}`"
:title="`${t('media.preview')}: ${previewName}`"
:modal-action="closePlayer"
:hide-buttons="true"
>
@ -247,25 +247,25 @@
</div>
</GenericModal>
<GenericModal :show="showRenameModal" :title="$t('media.rename')" :modal-action="renameFile">
<GenericModal :show="showRenameModal" :title="t('media.rename')" :modal-action="renameFile">
<label class="form-control w-full max-w-md">
<div class="label">
<span class="label-text">{{ $t('media.newFile') }}</span>
<span class="label-text">{{ t('media.newFile') }}</span>
</div>
<input v-model="renameNewName" type="text" class="input input-bordered w-full" />
</label>
</GenericModal>
<GenericModal :show="showCreateModal" :title="$t('media.createFolder')" :modal-action="createFolder">
<GenericModal :show="showCreateModal" :title="t('media.createFolder')" :modal-action="createFolder">
<label class="form-control w-full max-w-md">
<div class="label">
<span class="label-text">{{ $t('media.foldername') }}</span>
<span class="label-text">{{ t('media.foldername') }}</span>
</div>
<input v-model="folderName.name" type="text" class="input input-bordered w-full" />
</label>
</GenericModal>
<GenericModal :show="showUploadModal" :title="$t('media.upload')" :modal-action="uploadFiles">
<GenericModal :show="showUploadModal" :title="t('media.upload')" :modal-action="uploadFiles">
<div class="w-[700px] max-w-full">
<input
ref="fileInputName"
@ -278,7 +278,7 @@
<label class="form-control w-full mt-3">
<div class="label">
<span class="label-text">{{ $t('media.current') }}:</span>
<span class="label-text">{{ t('media.current') }}:</span>
</div>
<progress class="progress progress-accent" :value="currentProgress" max="100" />
</label>
@ -286,14 +286,14 @@
<label class="form-control w-full mt-1">
<div class="label">
<span class="label-text"
>{{ $t('media.overall') }} ({{ currentNumber }}/{{ inputFiles.length }}):</span
>{{ t('media.overall') }} ({{ currentNumber }}/{{ inputFiles.length }}):</span
>
</div>
<progress class="progress progress-accent" :value="overallProgress" max="100" />
</label>
<label class="form-control w-full mt-1">
<div class="label">
<span class="label-text">{{ $t('media.uploading') }}:</span>
<span class="label-text">{{ t('media.uploading') }}:</span>
</div>
<input v-model="uploadTask" type="text" class="input input-sm input-bordered w-full" disabled />
</label>

View File

@ -15,21 +15,21 @@
<div class="join">
<button
class="btn btn-sm join-item btn-primary"
:title="$t('message.savePreset')"
:title="t('message.savePreset')"
@click="savePreset()"
>
<i class="bi-cloud-upload" />
</button>
<button
class="btn btn-sm join-item btn-primary"
:title="$t('message.newPreset')"
:title="t('message.newPreset')"
@click="showCreateModal = true"
>
<i class="bi-file-plus" />
</button>
<button
class="btn btn-sm join-item btn-primary"
:title="$t('message.delPreset')"
:title="t('message.delPreset')"
@click="showDeleteModal = true"
>
<i class="bi-file-minus" />
@ -42,7 +42,7 @@
v-model="form.text"
class="textarea textarea-bordered w-full"
rows="4"
:placeholder="$t('message.placeholder')"
:placeholder="t('message.placeholder')"
/>
<div class="mt-2 grid xs:grid-cols-[auto_150px_150px] gap-4">
@ -50,7 +50,7 @@
<div class="form-control">
<label class="cursor-pointer p-0">
<div class="label">
<span class="label-text">{{ $t('message.xAxis') }}</span>
<span class="label-text">{{ t('message.xAxis') }}</span>
</div>
<input
v-model="form.x"
@ -65,7 +65,7 @@
<div class="form-control">
<label class="cursor-pointer p-0">
<div class="label">
<span class="label-text">{{ $t('message.yAxis') }}</span>
<span class="label-text">{{ t('message.yAxis') }}</span>
</div>
<input
v-model="form.y"
@ -81,7 +81,7 @@
<div class="xs:mt-10">
<div class="form-control">
<label class="label cursor-pointer p-0">
<span class="label-text">{{ $t('message.showBox') }}</span>
<span class="label-text">{{ t('message.showBox') }}</span>
<input
v-model="form.showBox"
type="checkbox"
@ -92,7 +92,7 @@
<label class="mt-2 form-control w-full">
<div class="label">
<span class="label-text">{{ $t('message.boxColor') }}</span>
<span class="label-text">{{ t('message.boxColor') }}</span>
</div>
<input
v-model="form.boxColor"
@ -104,7 +104,7 @@
</div>
<label class="form-control w-full xs:mt-[68px]">
<div class="label">
<span class="label-text">{{ $t('message.boxAlpha') }}</span>
<span class="label-text">{{ t('message.boxAlpha') }}</span>
</div>
<input
v-model="form.boxAlpha"
@ -121,7 +121,7 @@
<div>
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('message.size') }}</span>
<span class="label-text">{{ t('message.size') }}</span>
</div>
<input
v-model="form.fontSize"
@ -133,7 +133,7 @@
<label class="form-control w-full mt-2">
<div class="label">
<span class="label-text">{{ $t('message.fontColor') }}</span>
<span class="label-text">{{ t('message.fontColor') }}</span>
</div>
<input
v-model="form.fontColor"
@ -146,7 +146,7 @@
<div>
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('message.spacing') }}</span>
<span class="label-text">{{ t('message.spacing') }}</span>
</div>
<input
v-model="form.fontSpacing"
@ -157,7 +157,7 @@
</label>
<label class="form-control w-full mt-2">
<div class="label">
<span class="label-text">{{ $t('message.fontAlpha') }}</span>
<span class="label-text">{{ t('message.fontAlpha') }}</span>
</div>
<input
v-model="form.fontAlpha"
@ -174,7 +174,7 @@
<div class="grow">
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('message.overallAlpha') }}</span>
<span class="label-text">{{ t('message.overallAlpha') }}</span>
</div>
<input
v-model="form.overallAlpha"
@ -185,7 +185,7 @@
</label>
<label class="form-control w-full xs:max-w-[150px] mt-2">
<div class="label">
<span class="label-text">{{ $t('message.borderWidth') }}</span>
<span class="label-text">{{ t('message.borderWidth') }}</span>
</div>
<input
v-model="form.border"
@ -198,16 +198,16 @@
</div>
<div class="mt-5">
<button class="btn btn-primary send-btn" type="submit">{{ $t('message.send') }}</button>
<button class="btn btn-primary send-btn" type="submit">{{ t('message.send') }}</button>
</div>
</form>
</div>
</div>
<GenericModal :show="showCreateModal" :title="$t('message.newPreset')" :modal-action="createNewPreset">
<GenericModal :show="showCreateModal" :title="t('message.newPreset')" :modal-action="createNewPreset">
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ $t('message.name') }}</span>
<span class="label-text">{{ t('message.name') }}</span>
</div>
<input v-model="newPresetName" type="text" class="input input-bordered w-full" />
</label>
@ -215,8 +215,8 @@
<GenericModal
:show="showDeleteModal"
:title="$t('message.delPreset')"
:text="`${$t('message.delText')}: <strong> ${selected}</strong>?`"
:title="t('message.delPreset')"
:text="`${t('message.delText')}: <strong> ${selected}</strong>?`"
:modal-action="deletePreset"
/>
</div>
@ -227,6 +227,7 @@ const { t } = useI18n()
const authStore = useAuth()
const configStore = useConfig()
const indexStore = useIndex()
const { id } = storeToRefs(useConfig())
const { numberToHex, hexToNumber } = stringFormatter()
useHead({
@ -265,6 +266,12 @@ onMounted(() => {
getPreset(-1)
})
watch([id], () => {
nextTick(() => {
getPreset(-1)
})
})
async function getPreset(index: number) {
fetch(`/api/presets/${configStore.channels[configStore.id].id}`, {
method: 'GET',
@ -350,7 +357,7 @@ async function savePreset() {
channel_id: configStore.channels[configStore.id].id,
}
const response = await fetch(`/api/presets/${form.value.id}`, {
const response = await fetch(`/api/presets/${configStore.channels[configStore.id].id}/${form.value.id}`, {
method: 'PUT',
headers: { ...configStore.contentType, ...authStore.authHeader },
body: JSON.stringify(preset),
@ -389,7 +396,7 @@ async function createNewPreset(create: boolean) {
channel_id: configStore.channels[configStore.id].id,
}
const response = await fetch('/api/presets/', {
const response = await fetch(`/api/presets/${configStore.channels[configStore.id].id}/`, {
method: 'POST',
headers: { ...configStore.contentType, ...authStore.authHeader },
body: JSON.stringify(preset),
@ -410,7 +417,7 @@ async function deletePreset(del: boolean) {
showDeleteModal.value = false
if (del && selected.value && selected.value !== '') {
await fetch(`/api/presets/${form.value.id}`, {
await fetch(`/api/presets/${configStore.channels[configStore.id].id}/${form.value.id}`, {
method: 'DELETE',
headers: authStore.authHeader,
})

View File

@ -7,7 +7,7 @@
<div
v-if="firstLoad && beforeDayStart"
class="tooltip tooltip-right tooltip-warning"
:data-tip="$t('player.dateYesterday')"
:data-tip="t('player.dateYesterday')"
>
<SvgIcon name="warning" />
</div>
@ -53,55 +53,55 @@
</div>
<div v-if="configStore.playout.processing.mode === 'playlist'" class="h-16 join flex justify-end p-3">
<button class="btn btn-sm btn-primary join-item" :title="$t('player.copy')" @click="showCopyModal = true">
<button class="btn btn-sm btn-primary join-item" :title="t('player.copy')" @click="showCopyModal = true">
<i class="bi-files" />
</button>
<button
v-if="!configStore.playout.playlist.loop"
class="btn btn-sm btn-primary join-item"
:title="$t('player.loop')"
:title="t('player.loop')"
@click="loopClips()"
>
<i class="bi-view-stacked" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.remote')"
:title="t('player.remote')"
@click="showSourceModal = true"
>
<i class="bi-file-earmark-plus" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.import')"
:title="t('player.import')"
@click="showImportModal = true"
>
<i class="bi-file-text" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.generate')"
:title="t('player.generate')"
@click="mediaStore.getTree('', true), (showPlaylistGenerator = true)"
>
<i class="bi-sort-down-alt" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.reset')"
:title="t('player.reset')"
@click=";(playlistStore.playlist.length = 0), playlistTable.getPlaylist()"
>
<i class="bi-arrow-counterclockwise" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.save')"
:title="t('player.save')"
@click=";(targetDate = listDate), savePlaylist(true)"
>
<i class="bi-download" />
</button>
<button
class="btn btn-sm btn-primary join-item"
:title="$t('player.deletePlaylist')"
:title="t('player.deletePlaylist')"
@click="showDeleteModal = true"
>
<i class="bi-trash" />
@ -110,7 +110,7 @@
<GenericModal
:show="showPreviewModal"
:title="`${$t('media.preview')}: ${previewName}`"
:title="`${t('media.preview')}: ${previewName}`"
:hide-buttons="true"
:modal-action="closePlayer"
>
@ -120,7 +120,7 @@
</div>
</GenericModal>
<GenericModal :show="showCopyModal" :title="$t('player.copyTo')" :modal-action="savePlaylist">
<GenericModal :show="showCopyModal" :title="t('player.copyTo')" :modal-action="savePlaylist">
<VueDatePicker
v-model="targetDate"
:clearable="false"
@ -136,60 +136,60 @@
/>
</GenericModal>
<GenericModal :show="showSourceModal" :title="$t('player.addEdit')" :modal-action="processSource">
<GenericModal :show="showSourceModal" :title="t('player.addEdit')" :modal-action="processSource">
<div>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.title') }}</span>
<span class="label-text">{{ t('player.title') }}</span>
</div>
<input v-model.number="newSource.title" type="text" class="input input-sm input-bordered w-auto" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.duration') }}</span>
<span class="label-text">{{ t('player.duration') }}</span>
</div>
<TimePicker v-model="newSource.duration" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.in') }}</span>
<span class="label-text">{{ t('player.in') }}</span>
</div>
<TimePicker v-model="newSource.in" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.out') }}</span>
<span class="label-text">{{ t('player.out') }}</span>
</div>
<TimePicker v-model="newSource.out" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.file') }}</span>
<span class="label-text">{{ t('player.file') }}</span>
</div>
<input v-model="newSource.source" type="text" class="input input-sm input-bordered w-auto" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.audio') }}</span>
<span class="label-text">{{ t('player.audio') }}</span>
</div>
<input v-model="newSource.audio" type="text" class="input input-sm input-bordered w-auto" />
</label>
<label class="form-control w-auto mt-auto">
<div class="label">
<span class="label-text">{{ $t('player.customFilter') }}</span>
<span class="label-text">{{ t('player.customFilter') }}</span>
</div>
<input v-model="newSource.custom_filter" type="text" class="input input-sm input-bordered w-auto" />
</label>
<div class="form-control">
<label class="cursor-pointer label">
<span class="label-text">{{ $t('player.ad') }}</span>
<span class="label-text">{{ t('player.ad') }}</span>
<input
type="checkbox"
class="checkbox checkbox-sm"
@ -201,7 +201,7 @@
</div>
</GenericModal>
<GenericModal :show="showImportModal" :title="$t('player.import')" :modal-action="importPlaylist">
<GenericModal :show="showImportModal" :title="t('player.import')" :modal-action="importPlaylist">
<input
type="file"
class="file-input file-input-sm file-input-bordered w-full"
@ -212,7 +212,7 @@
<GenericModal :show="showDeleteModal" title="Delete Program" :modal-action="deletePlaylist">
<span>
{{ $t('player.deleteFrom') }} <strong>{{ listDate }}</strong>
{{ t('player.deleteFrom') }} <strong>{{ listDate }}</strong>
</span>
</GenericModal>