minor design update. Ref #441

This commit is contained in:
arabcoders 2025-10-14 18:16:52 +03:00 committed by felix
parent 145dd056c5
commit 048139ae2a
2 changed files with 81 additions and 64 deletions

View file

@ -4,11 +4,17 @@
<div class="column is-12 is-clearfix is-unselectable"> <div class="column is-12 is-clearfix is-unselectable">
<span class="title is-4"> <span class="title is-4">
<span class="icon-text"> <span class="icon-text">
<span class="icon"><i class="fa-solid fa-sliders" /></span> <template v-if="toggleForm">
<span>Presets</span> <span class="icon"><i class="fa-solid" :class="{ 'fa-edit': presetRef, 'fa-plus': !presetRef }" /></span>
<span>{{ presetRef ? `Edit - ${preset.name}` : 'Add' }}</span>
</template>
<template v-else>
<span class="icon"><i class="fa-solid fa-sliders" /></span>
<span>Presets</span>
</template>
</span> </span>
</span> </span>
<div class="is-pulled-right"> <div class="is-pulled-right" v-if="!toggleForm">
<div class="field is-grouped"> <div class="field is-grouped">
<p class="control"> <p class="control">
<button class="button is-primary" @click="resetForm(false); toggleForm = !toggleForm;" <button class="button is-primary" @click="resetForm(false); toggleForm = !toggleForm;"
@ -38,7 +44,7 @@
</p> </p>
</div> </div>
</div> </div>
<div class="is-hidden-mobile"> <div class="is-hidden-mobile" v-if="!toggleForm">
<span class="subtitle">Presets are pre-defined command options for yt-dlp that you want to apply to given <span class="subtitle">Presets are pre-defined command options for yt-dlp that you want to apply to given
download.</span> download.</span>
</div> </div>
@ -68,13 +74,10 @@
<tbody> <tbody>
<tr v-for="item in presetsNoDefault" :key="item.id"> <tr v-for="item in presetsNoDefault" :key="item.id">
<td class="is-text-overflow is-vcentered"> <td class="is-text-overflow is-vcentered">
<div> {{ item.name }}</div> {{ item.name }}
<div class="is-unselectable"> <span class="icon" v-if="item.cookies" v-tooltip="'Has cookies'">
<span class="icon-text" v-if="item.cookies"> <i class="fa-solid fa-cookie has-text-primary" />
<span class="icon"><i class="fa-solid fa-cookie" /></span> </span>
<span>Cookies</span>
</span>
</div>
</td> </td>
<td class="is-vcentered is-items-center"> <td class="is-vcentered is-items-center">
<div class="field is-grouped is-grouped-centered"> <div class="field is-grouped is-grouped-centered">
@ -109,61 +112,54 @@
<div class="column is-6" v-for="item in presetsNoDefault" :key="item.id"> <div class="column is-6" v-for="item in presetsNoDefault" :key="item.id">
<div class="card is-flex is-full-height is-flex-direction-column"> <div class="card is-flex is-full-height is-flex-direction-column">
<header class="card-header"> <header class="card-header">
<div class="card-header-title is-text-overflow is-block" v-text="item.name" /> <div class="card-header-title is-block is-clickable"
:class="{ 'is-text-overflow': !isExpanded(item.id, 'title') }" @click="toggleExpand(item.id, 'title')"
:title="!isExpanded(item.id, 'title') ? 'Click to expand' : 'Click to collapse'" v-text="item.name" />
<div class="card-header-icon"> <div class="card-header-icon">
<button class="has-text-info" v-tooltip="'Export'" @click="exportItem(item)"> <span v-if="item.cookies" class="icon" v-tooltip="'Has cookies'">
<i class="fa-solid fa-cookie has-text-primary" />
</span>
<button class="has-text-info" v-tooltip="'Export preset'" @click="exportItem(item)">
<span class="icon"><i class="fa-solid fa-file-export" /></span> <span class="icon"><i class="fa-solid fa-file-export" /></span>
</button> </button>
<button @click="item.raw = !item.raw">
<span class="icon"><i class="fa-solid" :class="{
'fa-arrow-down': !item?.raw,
'fa-arrow-up': item?.raw,
}" /></span>
</button>
</div> </div>
</header> </header>
<div class="card-content is-flex-grow-1"> <div class="card-content is-flex-grow-1">
<div class="content"> <div class="content">
<p class="is-text-overflow" v-if="item.folder"> <p :class="{ 'is-text-overflow': !isExpanded(item.id, 'folder'), 'is-clickable': true }"
v-if="item.folder" @click="toggleExpand(item.id, 'folder')"
:title="!isExpanded(item.id, 'folder') ? 'Click to expand' : 'Click to collapse'">
<span class="icon"><i class="fa-solid fa-folder" /></span> <span class="icon"><i class="fa-solid fa-folder" /></span>
<span>{{ calcPath(item.folder) }}</span> <span>{{ calcPath(item.folder) }}</span>
</p> </p>
<p class="is-text-overflow" v-if="item.template"> <p :class="{ 'is-text-overflow': !isExpanded(item.id, 'template'), 'is-clickable': true }"
v-if="item.template" @click="toggleExpand(item.id, 'template')"
:title="!isExpanded(item.id, 'template') ? 'Click to expand' : 'Click to collapse'">
<span class="icon"><i class="fa-solid fa-file" /></span> <span class="icon"><i class="fa-solid fa-file" /></span>
<span>{{ item.template }}</span> <span>{{ item.template }}</span>
</p> </p>
<p class="is-text-overflow" v-if="item.cli"> <p :class="{ 'is-text-overflow': !isExpanded(item.id, 'cli'), 'is-clickable': true }" v-if="item.cli"
@click="toggleExpand(item.id, 'cli')"
:title="!isExpanded(item.id, 'cli') ? 'Click to expand' : 'Click to collapse'">
<span class="icon"><i class="fa-solid fa-terminal" /></span> <span class="icon"><i class="fa-solid fa-terminal" /></span>
<span>{{ item.cli }}</span> <span>{{ item.cli }}</span>
</p> </p>
<p class="is-text-overflow" v-if="item.cookies"> <p :class="{ 'is-text-overflow': !isExpanded(item.id, 'description'), 'is-clickable': true }"
<span class="icon"><i class="fa-solid fa-cookie" /></span> v-if="item.description" @click="toggleExpand(item.id, 'description')"
<span>Has cookies</span> :title="!isExpanded(item.id, 'cli') ? 'Click to expand' : 'Click to collapse'">
<span class="icon"><i class="fa-solid fa-d" /></span>
<span>{{ item.description }}</span>
</p> </p>
<button @click="item.toggle_description = !item.toggle_description" v-if="item.description">
<span class="icon"><i class="fa-solid"
:class="{ 'fa-arrow-down': !item?.raw, 'fa-arrow-up': item?.raw, }" /></span>
<span>{{ !item.toggle_description ? 'Show' : 'Hide' }} Description</span>
</button>
</div> </div>
</div> </div>
<div class="card-content content m-1 p-1 is-overflow-auto" style="max-height: 300px;" <div class="card-content content m-1 p-1 is-overflow-auto" style="max-height: 300px;"
v-if="item?.toggle_description"> v-if="item?.toggle_description">
<div class="is-pre-wrap">{{ item.description }}</div> <div class="is-pre-wrap">{{ item.description }}</div>
</div> </div>
<div class="card-content content is-overflow-auto m-0 p-0" v-if="item?.raw" style="max-height: 300px;">
<div class="is-position-relative">
<pre><code>{{ filterItem(item) }}</code></pre>
<button class="button is-small is-primary is-position-absolute" style="top:0; right:0"
@click="copyText(filterItem(item))">
<span class="icon"><i class="fa-solid fa-copy" /></span>
</button>
</div>
</div>
<div class="card-footer mt-auto"> <div class="card-footer mt-auto">
<div class="card-footer-item"> <div class="card-footer-item">
<button class="button is-warning is-fullwidth" @click="editItem(item)"> <button class="button is-warning is-fullwidth" @click="editItem(item)">
<span class="icon"><i class="fa-solid fa-cog" /></span> <span class="icon"><i class="fa-solid fa-edit" /></span>
<span>Edit</span> <span>Edit</span>
</button> </button>
</div> </div>
@ -190,10 +186,10 @@
<div class="columns is-multiline" v-if="presets && presets.length > 0"> <div class="columns is-multiline" v-if="presets && presets.length > 0">
<div class="column is-12"> <div class="column is-12">
<Message message_class="has-background-info-90 has-text-dark" title="Tips" icon="fas fa-info-circle"> <Message message_class="has-background-warning-90 has-text-dark">
<ul> <p>When you export preset, it doesn't include the <strong>cookies</strong> field contents for security
<li>When you export preset, it doesn't include <code>Cookies</code> field for security reasons.</li> reasons.
</ul> </p>
</Message> </Message>
</div> </div>
</div> </div>
@ -204,7 +200,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useStorage } from '@vueuse/core' import { useStorage } from '@vueuse/core'
import type { Preset } from '~/types/presets' import type { Preset } from '~/types/presets'
import {useConfirm} from '~/composables/useConfirm' import { useConfirm } from '~/composables/useConfirm'
const toast = useNotification() const toast = useNotification()
const config = useConfigStore() const config = useConfigStore()
@ -222,9 +218,29 @@ const isLoading = ref(true)
const initialLoad = ref(true) const initialLoad = ref(true)
const addInProgress = ref(false) const addInProgress = ref(false)
const remove_keys = ['raw', 'toggle_description'] const remove_keys = ['raw', 'toggle_description']
const expandedItems = ref<Record<string, Set<string>>>({})
const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default)) const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default))
const toggleExpand = (itemId: string | undefined, field: string) => {
if (!itemId) return
if (!expandedItems.value[itemId]) {
expandedItems.value[itemId] = new Set()
}
if (expandedItems.value[itemId].has(field)) {
expandedItems.value[itemId].delete(field)
} else {
expandedItems.value[itemId].add(field)
}
}
const isExpanded = (itemId: string | undefined, field: string): boolean => {
if (!itemId) return false
return expandedItems.value[itemId]?.has(field) ?? false
}
watch(() => socket.isConnected, async () => { watch(() => socket.isConnected, async () => {
if (socket.isConnected && initialLoad.value) { if (socket.isConnected && initialLoad.value) {
await reloadContent(true) await reloadContent(true)

View file

@ -4,11 +4,17 @@
<div class="column is-12 is-clearfix is-unselectable"> <div class="column is-12 is-clearfix is-unselectable">
<span class="title is-4"> <span class="title is-4">
<span class="icon-text"> <span class="icon-text">
<span class="icon"><i class="fa-solid fa-tasks" /></span> <template v-if="toggleForm">
<span>Tasks</span> <span class="icon"><i class="fa-solid" :class="{ 'fa-edit': taskRef, 'fa-plus': !taskRef }" /></span>
<span>{{ taskRef ? `Edit - ${task.name}` : 'Add' }}</span>
</template>
<template v-else>
<span class="icon"><i class="fa-solid fa-tasks" /></span>
<span>Tasks</span>
</template>
</span> </span>
</span> </span>
<div class="is-pulled-right"> <div class="is-pulled-right" v-if="!toggleForm">
<div class="field is-grouped"> <div class="field is-grouped">
<p class="control has-icons-left" v-if="toggleFilter && tasks && tasks.length > 0"> <p class="control has-icons-left" v-if="toggleFilter && tasks && tasks.length > 0">
<input type="search" v-model.lazy="query" class="input" id="filter" <input type="search" v-model.lazy="query" class="input" id="filter"
@ -17,24 +23,21 @@
</p> </p>
<p class="control" v-if="tasks && tasks.length > 0"> <p class="control" v-if="tasks && tasks.length > 0">
<button class="button is-danger is-light" v-tooltip.bottom="'Filter'" <button class="button is-danger is-light" @click="toggleFilter = !toggleFilter">
@click="toggleFilter = !toggleFilter">
<span class="icon"><i class="fas fa-filter" /></span> <span class="icon"><i class="fas fa-filter" /></span>
<span v-if="!isMobile">Filter</span> <span v-if="!isMobile">Filter</span>
</button> </button>
</p> </p>
<p class="control"> <p class="control">
<button class="button is-primary" @click="resetForm(false); toggleForm = !toggleForm" <button class="button is-primary" @click="resetForm(false); toggleForm = !toggleForm">
v-tooltip.bottom="'Toggle Add form'">
<span class="icon"><i class="fas fa-add" /></span> <span class="icon"><i class="fas fa-add" /></span>
<span v-if="!isMobile">New Task</span> <span v-if="!isMobile"> New Task</span>
</button> </button>
</p> </p>
<p class="control"> <p class="control">
<button v-tooltip.bottom="'Change display style'" class="button has-tooltip-bottom" <button class="button" @click="() => display_style = display_style === 'list' ? 'grid' : 'list'">
@click="() => display_style = display_style === 'list' ? 'grid' : 'list'">
<span class="icon"> <span class="icon">
<i class="fa-solid" <i class="fa-solid"
:class="{ 'fa-table': display_style !== 'list', 'fa-table-list': display_style === 'list' }" /></span> :class="{ 'fa-table': display_style !== 'list', 'fa-table-list': display_style === 'list' }" /></span>
@ -53,7 +56,7 @@
</p> </p>
</div> </div>
</div> </div>
<div class="is-hidden-mobile"> <div class="is-hidden-mobile" v-if="!toggleForm">
<span class="subtitle"> <span class="subtitle">
The task runner is simple queue system that allows you to poll channels or playlists for new content at The task runner is simple queue system that allows you to poll channels or playlists for new content at
specified intervals. specified intervals.
@ -180,14 +183,12 @@
<td class="is-vcentered is-items-center"> <td class="is-vcentered is-items-center">
<div class="field is-grouped is-grouped-centered"> <div class="field is-grouped is-grouped-centered">
<div class="control"> <div class="control">
<button class="button is-warning is-small is-fullwidth" v-tooltip="'Edit'" <button class="button is-warning is-small is-fullwidth" @click="editItem(item)">
@click="editItem(item)"> <span class="icon"><i class="fa-solid fa-edit" /></span>
<span class="icon"><i class="fa-solid fa-cog" /></span>
</button> </button>
</div> </div>
<div class="control"> <div class="control">
<button class="button is-danger is-small is-fullwidth" v-tooltip="'Delete'" <button class="button is-danger is-small is-fullwidth" @click="deleteItem(item)">
@click="deleteItem(item)">
<span class="icon"><i class="fa-solid fa-trash" /></span> <span class="icon"><i class="fa-solid fa-trash" /></span>
</button> </button>
</div> </div>
@ -257,13 +258,13 @@
</span> </span>
</div> </div>
<div class="control"> <div class="control">
<span class="icon" v-tooltip="`RSS monitoring is ${item.handler_enabled ? 'enabled' : 'disabled'}`"> <span class="icon" v-tooltip="`Task handler is ${item.handler_enabled ? 'enabled' : 'disabled'}`">
<i class="fa-solid fa-rss" <i class="fa-solid fa-rss"
:class="{ 'has-text-success': item.handler_enabled, 'has-text-danger': !item.handler_enabled }" /> :class="{ 'has-text-success': item.handler_enabled, 'has-text-danger': !item.handler_enabled }" />
</span> </span>
</div> </div>
<div class="control"> <div class="control">
<a class="has-text-info" v-tooltip="'Export task.'" @click.prevent="exportItem(item)"> <a class="has-text-info" @click.prevent="exportItem(item)">
<span class="icon"><i class="fa-solid fa-file-export" /></span> <span class="icon"><i class="fa-solid fa-file-export" /></span>
</a> </a>
</div> </div>
@ -310,7 +311,7 @@
<div class="card-footer mt-auto"> <div class="card-footer mt-auto">
<div class="card-footer-item"> <div class="card-footer-item">
<button class="button is-warning is-fullwidth" @click="editItem(item);"> <button class="button is-warning is-fullwidth" @click="editItem(item);">
<span class="icon"><i class="fa-solid fa-cog" /></span> <span class="icon"><i class="fa-solid fa-edit" /></span>
<span>Edit</span> <span>Edit</span>
</button> </button>
</div> </div>