add logging, messaging, color switch

This commit is contained in:
jb-alvarado 2024-04-06 23:12:06 +02:00
parent 1ca27b75ec
commit 32b370b425
6 changed files with 260 additions and 238 deletions

View File

@ -1,4 +1,5 @@
@import '_variables.scss';
@import 'bootstrap-icons/font/bootstrap-icons.css';
#__nuxt,
#__nuxt > div,

View File

@ -1,9 +1,24 @@
<template>
<div class="navbar bg-base-100 min-h-[52px] p-0">
<div class="navbar bg-base-100 min-h-[52px] p-0 text-base">
<NuxtLink class="navbar-brand p-2" href="/">
<img src="~/assets/images/ffplayout-small.png" class="img-fluid" alt="Logo" width="30" height="30" />
</NuxtLink>
<div class="navbar-end w-1/5 grow">
<label class="swap swap-rotate me-2 md:hidden">
<input type="checkbox" @change="toggleDarkTheme" :checked="indexStore.darkMode" />
<svg class="swap-on fill-current w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<path
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"
/>
</svg>
<svg class="swap-off fill-current w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
<path
d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"
/>
</svg>
</label>
<div class="dropdown dropdown-end z-50">
<div tabindex="0" role="button" class="btn btn-ghost md:hidden">
<svg
@ -30,12 +45,10 @@
</NuxtLink>
</li>
<li v-if="configStore.configGui.length > 1">
<details>
<details tabindex="0" @focusout="closeDropdown">
<summary>
<div class="h-[19px] text-base">
<span>
Channels
</span>
<span> Channels </span>
</div>
</summary>
<ul class="p-2">
@ -48,7 +61,7 @@
</details>
</li>
<li class="bg-base-100 rounded-md">
<button class="h-[27px]" exactActiveClass="is-active" @click="logout()">Logout</button>
<button class="h-[27px] text-base" exactActiveClass="is-active" @click="logout()">Logout</button>
</li>
</ul>
</div>
@ -63,26 +76,48 @@
</NuxtLink>
</li>
<li v-if="configStore.configGui.length > 1">
<details
tabindex="0"
@focusout="closeDropdown"
>
<details tabindex="0" @focusout="closeDropdown">
<summary>
<div class="h-[19px] text-base">
<span>
Channels
</span>
<span> Channels </span>
</div>
</summary>
<ul class="p-2 bg-base-100 rounded-md !mt-1 w-36" tabindex="0">
<li v-for="(channel, index) in configStore.configGui" :key="index">
<a class="dropdown-item" @click="selectChannel(index)">{{ channel.name }}</a>
<a class="dropdown-item" @click="selectChannel(index)">
{{ channel.name }}
</a>
</li>
</ul>
</details>
</li>
<li class="bg-base-100 rounded-md p-0">
<button class="h-[27px] pt-[6px]" @click="logout()">Logout</button>
<button class="h-[27px] pt-[4px] text-base" @click="logout()">Logout</button>
</li>
<li class="p-0">
<label class="swap swap-rotate">
<input type="checkbox" @change="toggleDarkTheme" :checked="indexStore.darkMode" />
<svg
class="swap-on fill-current w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 22 22"
>
<path
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"
/>
</svg>
<svg
class="swap-off fill-current w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 22 22"
>
<path
d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"
/>
</svg>
</label>
</li>
</ul>
</div>
@ -90,8 +125,10 @@
</template>
<script setup lang="ts">
const colorMode = useColorMode()
const authStore = useAuth()
const configStore = useConfig()
const indexStore = useIndex()
const router = useRouter()
const menuItems = ref([
@ -103,6 +140,10 @@ const menuItems = ref([
{ name: 'Configure', link: '/configure' },
])
if (colorMode.value === 'dark') {
indexStore.darkMode = true
}
function closeDropdown($event: any) {
setTimeout(() => {
$event.target.parentNode.removeAttribute('open')
@ -118,6 +159,16 @@ function selectChannel(index: number) {
configStore.configID = index
configStore.getPlayoutConfig()
}
function toggleDarkTheme() {
indexStore.darkMode = !indexStore.darkMode
if (indexStore.darkMode) {
colorMode.preference = 'dark'
} else {
colorMode.preference = 'light'
}
}
</script>
<style lang="scss" scoped>
.is-active > span::after {

View File

@ -18,8 +18,6 @@ const authStore = useAuth()
const route = useRoute()
console.log(route.name)
onMounted(() => {
// @ts-ignore
// new $bootstrap.Tooltip(document.body, {

View File

@ -1,11 +1,11 @@
<template>
<div class="date-container">
<div class="date-div">
<input type="date" class="form-control" v-model="listDate" />
<div class="flex justify-end my-3 pe-3">
<div>
<input type="date" class="input input-sm input-bordered w-full max-w-xs" v-model="listDate" />
</div>
</div>
<div class="log-container mt-2">
<div class="log-content" v-html="formatLog(currentLog)" />
<div class="px-3 inline-block h-[calc(100vh-130px)] text-[13px]">
<div class="bg-base-300 whitespace-pre h-full font-mono overflow-auto p-3" v-html="formatLog(currentLog)" />
</div>
</template>
@ -13,7 +13,7 @@
import { storeToRefs } from 'pinia'
useHead({
title: 'Logging | ffplayout'
title: 'Logging | ffplayout',
})
const { configID } = storeToRefs(useConfig())
@ -55,18 +55,6 @@ async function getLog() {
</script>
<style lang="scss">
.date-container {
width: 100%;
height: 37px;
}
.log-container {
background: $bg-secondary;
height: calc(100% - 120px);
margin: 1em;
padding: .5em;
overflow: hidden;
}
.log-time {
color: $log-time;
}
@ -76,7 +64,7 @@ async function getLog() {
}
.log-addr {
color: $log-addr ;
color: $log-addr;
font-weight: 500;
}
@ -84,17 +72,6 @@ async function getLog() {
color: $log-cmd;
}
.log-content {
color: $log-content;
width: 100%;
height: 100%;
font-family: monospace;
font-size: 13px;
white-space: pre;
overflow: scroll;
scrollbar-width: medium;
}
.log-info {
color: $log-info;
}

View File

@ -1,220 +1,220 @@
<template>
<div>
<Menu />
<div class="container mt-5">
<div class="preset-div">
<div class="row">
<div class="col">
<select class="form-select" v-model="selected" @change="onChange($event)">
<option v-for="item in presets">{{ item.name }}</option>
</select>
</div>
<div class="col-2">
<div class="btn-group" role="group">
<button class="btn btn-primary" title="Save Preset" data-tooltip=tooltip @click="savePreset()">
<i class="bi-cloud-upload" />
</button>
<button
class="btn btn-primary"
title="New Preset"
data-tooltip=tooltip
data-bs-toggle="modal"
data-bs-target="#createModal"
>
<i class="bi-file-plus" />
</button>
<button
class="btn btn-primary"
title="Delete Preset"
data-tooltip=tooltip
data-bs-toggle="modal"
data-bs-target="#deleteModal"
>
<i class="bi-file-minus" />
</button>
</div>
</div>
<div class="flex flex-col items-center mt-10 px-8">
<div class="mt-2 w-full max-w-4xl">
<div class="flex max-w-md gap-4">
<div>
<select
class="select select-sm select-bordered w-full max-w-md"
v-model="selected"
@change="onChange($event)"
>
<option v-for="item in presets">{{ item.name }}</option>
</select>
</div>
<div class="join">
<button class="btn btn-sm join-item btn-primary" title="Save Preset" @click="savePreset()">
<i class="bi-cloud-upload" />
</button>
<button class="btn btn-sm join-item btn-primary" title="New Preset" @click="showCreateModal = true">
<i class="bi-file-plus" />
</button>
<button
class="btn btn-sm join-item btn-primary"
title="Delete Preset"
@click="showDeleteModal = true"
>
<i class="bi-file-minus" />
</button>
</div>
</div>
<form @submit.prevent="submitMessage">
<textarea class="form-control message" v-model="form.text" rows="7" placeholder="Message" />
<form @submit.prevent="submitMessage" class="mt-6 w-full">
<textarea
class="textarea textarea-bordered w-full"
v-model="form.text"
rows="4"
placeholder="Message"
/>
<div class="row mt-3">
<div class="col">
<div class="mt-5 grid grid-cols-[auto_150px_150px] gap-4">
<div class="grow">
<input
class="form-control mt-1"
class="input input-sm input-bordered w-full"
v-model="form.x"
type="text"
title="X Axis"
data-tooltip=tooltip
placeholder="X"
required
/>
<input
class="form-control mt-2"
class="input input-sm input-bordered w-full mt-6"
v-model="form.y"
type="text"
title="Y Axis"
data-tooltip=tooltip
data-tooltip="tooltip"
placeholder="Y"
required
/>
<div class="row mt-2">
<div class="col">
<label for="input-size">Size</label>
<input
id="input-size"
class="form-control mt-2"
v-model="form.fontSize"
type="number"
required
/>
</div>
<div class="col">
<label for="input-spacing">Spacing</label>
<input
id="input-spacing"
class="form-control mt-2"
v-model="form.fontSpacing"
type="number"
required
/>
</div>
</div>
<div class="row mt-2">
<div class="col">
<label for="input-color">Font Color</label>
<input
id="input-color"
class="form-control mt-2"
v-model="form.fontColor"
type="color"
required
/>
</div>
<div class="col">
<label for="input-alpha">Font Alpha</label>
<input
id="input-alpha"
class="form-control mt-2"
v-model="form.fontAlpha"
type="number"
min="0"
max="1"
step="0.01"
/>
</div>
</div>
</div>
<div class="col">
<div class="form-check">
<input id="input-box" type="checkbox" class="form-check-input" v-model="form.showBox" />
<label for="input-box" class="form-check-label">Show Box</label>
<div>
<div class="form-control">
<label class="label cursor-pointer p-0">
<span class="label-text">Show Box</span>
<input type="checkbox" v-model="form.showBox" class="checkbox checkbox-xs rounded-sm" />
</label>
</div>
<div class="row">
<div class="col">
<label for="input-box-color">Box Color</label>
<input
id="input-box-color"
class="form-control mt-2"
v-model="form.boxColor"
type="color"
required
/>
<label class="form-control w-full">
<div class="label">
<span class="label-text">Box Color</span>
</div>
<div class="col">
<label for="input-box-alpha" class="form-check-label">Box Alpha</label>
<input
id="input-box-alpha"
class="form-control mt-2"
v-model="form.boxAlpha"
type="number"
min="0"
max="1"
step="0.01"
/>
</div>
<label for="input-border-w" class="form-check-label">Border Width</label>
<input
id="input-border-w"
class="form-control mt-2"
v-model="form.border"
type="number"
required
/>
<label for="input-overall-alpha" class="form-check-label mt-2">Overall Alpha</label>
<input
id="input-overall-alpha"
class="form-control mt-2"
v-model="form.overallAlpha"
type="text"
type="color"
class="input input-sm input-bordered w-full p-1"
v-model="form.boxColor"
required
/>
</label>
</div>
<label class="form-control w-full mt-5">
<div class="label">
<span class="label-text">Box Alpha</span>
</div>
<input
type="number"
min="0"
max="1"
step="0.01"
class="input input-sm input-bordered w-full"
v-model="form.boxAlpha"
required
/>
</label>
</div>
<div class="grid grid-cols-[150px_150px_auto] gap-4">
<div>
<label class="form-control w-full">
<div class="label">
<span class="label-text">Size</span>
</div>
<input
type="number"
class="input input-sm input-bordered w-full"
v-model="form.fontSize"
required
/>
</label>
<label class="form-control w-full mt-2">
<div class="label">
<span class="label-text">Font Color</span>
</div>
<input
type="color"
class="input input-sm input-bordered w-full p-1"
v-model="form.fontColor"
required
/>
</label>
</div>
<div>
<label class="form-control w-full">
<div class="label">
<span class="label-text">Spacing</span>
</div>
<input
type="number"
class="input input-sm input-bordered w-full"
v-model="form.fontSpacing"
required
/>
</label>
<label class="form-control w-full mt-2">
<div class="label">
<span class="label-text">Font Alpha</span>
</div>
<input
type="number"
class="input input-sm input-bordered w-full"
v-model="form.fontAlpha"
min="0"
max="1"
step="0.01"
required
/>
</label>
</div>
<div class="grow">
<label class="form-control w-full">
<div class="label">
<span class="label-text">Overall Alpha</span>
</div>
<input
type="text"
class="input input-sm input-bordered w-full"
v-model="form.overallAlpha"
required
/>
</label>
<label class="form-control w-full max-w-[150px] mt-2">
<div class="label">
<span class="label-text">Border Width</span>
</div>
<input
type="number"
class="input input-sm input-bordered w-full"
v-model="form.border"
required
/>
</label>
</div>
</div>
<div class="row mt-4">
<div class="col sub-btn">
<button class="btn btn-primary send-btn" type="submit">Send</button>
</div>
<div class="mt-5">
<button class="btn btn-primary send-btn" type="submit">Send</button>
</div>
</form>
</div>
</div>
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="createModalLabel">New Preset</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cancel"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
<label for="preset-name" class="col-form-label">Name:</label>
<input type="text" class="form-control" id="preset-name" v-model="newPresetName" />
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Cancel</button>
<button
type="button"
class="btn btn-primary"
@click="createNewPreset()"
data-bs-dismiss="modal"
>
Save
</button>
</div>
<div
v-if="showCreateModal"
class="z-50 fixed top-0 bottom-0 left-0 right-0 flex justify-center items-center bg-black/30"
>
<div class="flex flex-col bg-base-100 w-[400px] h-[200px] mt-[10%] rounded-md p-5 shadow-xl">
<div class="font-bold text-lg">New Preset</div>
<label class="form-control w-full">
<div class="label">
<span class="label-text">Name</span>
</div>
</div>
</div>
<input type="text" class="input input-bordered w-full" v-model="newPresetName" />
</label>
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="deleteModalLabel">Delete Preset</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cancel"></button>
</div>
<div class="modal-body">Are you sure that you want to delete preset: "{{ selected }}"?</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" @click="deletePreset()" data-bs-dismiss="modal">
Ok
</button>
</div>
<div class="mt-4 flex justify-end">
<div class="join">
<button
class="btn btn-sm bg-base-300 hover:bg-base-300/50 join-item"
@click=";(newPresetName = ''), (showCreateModal = false)"
>
Cancel
</button>
<button class="btn btn-sm bg-base-300 hover:bg-base-300/50 join-item" @click="createNewPreset()">
Ok
</button>
</div>
</div>
</div>
</div>
<Modal
:show="showDeleteModal"
title="Delete Preset"
:text="`Are you sure that you want to delete preset: <strong> ${selected}</strong>?`"
:modalAction="deletePreset"
/>
</template>
<script setup lang="ts">
@ -225,7 +225,7 @@ const { numberToHex, hexToNumber } = stringFormatter()
const contentType = { 'content-type': 'application/json;charset=UTF-8' }
useHead({
title: 'Messages | ffplayout'
title: 'Messages | ffplayout',
})
interface PresetName {
@ -250,6 +250,8 @@ const form = ref({
overallAlpha: '1',
})
const showCreateModal = ref(false)
const showDeleteModal = ref(false)
const selected = ref(null)
const newPresetName = ref('')
const presets = ref([] as PresetName[])
@ -358,6 +360,8 @@ async function savePreset() {
}
async function createNewPreset() {
showCreateModal.value = false
const preset = {
name: newPresetName.value,
text: form.value.text,
@ -393,8 +397,10 @@ async function createNewPreset() {
}
}
async function deletePreset() {
if (selected.value && selected.value !== '') {
async function deletePreset(del: boolean) {
showDeleteModal.value = false
if (del && selected.value && selected.value !== '') {
await fetch(`/api/presets/${form.value.id}`, {
method: 'DELETE',
headers: authStore.authHeader,
@ -431,15 +437,3 @@ async function submitMessage() {
}
}
</script>
<style scoped>
.preset-div {
width: 50%;
margin-bottom: 2em;
}
.sub-btn {
min-width: 90px;
max-width: 100px;
}
</style>

View File

@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
export const useIndex = defineStore('index', {
state: () => ({
darkMode: false,
showAlert: false,
alertVariant: 'alert-success',
alertMsg: '',