minor design update for index page.
This commit is contained in:
parent
a188c20099
commit
a2f5c770c6
3 changed files with 173 additions and 87 deletions
|
|
@ -234,7 +234,7 @@
|
||||||
|
|
||||||
<div class="columns is-multiline" v-else>
|
<div class="columns is-multiline" v-else>
|
||||||
<LateLoader :unrender="true" :min-height="showThumbnails ? 410 : 210" class="column is-6"
|
<LateLoader :unrender="true" :min-height="showThumbnails ? 410 : 210" class="column is-6"
|
||||||
v-for="item in sortCompleted" :key="item._id">
|
v-for="item in filteredItems(sortCompleted)" :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"
|
||||||
:class="{ 'is-bordered-danger': item.status === 'error', 'is-bordered-info': item.live_in || item.is_live }">
|
:class="{ 'is-bordered-danger': item.status === 'error', 'is-bordered-info': item.live_in || item.is_live }">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
|
|
@ -286,18 +286,8 @@
|
||||||
</template>
|
</template>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content is-flex-grow-1">
|
<div class="card-content">
|
||||||
<div class="columns is-mobile is-multiline">
|
<div class="columns is-mobile is-multiline">
|
||||||
<div class="column is-12" v-if="item.error">
|
|
||||||
<div class="is-text-overflow is-pointer" @click="toggle_class($event)">
|
|
||||||
<span class="has-text-danger">{{ item.error }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column is-12" v-if="showMessage(item)">
|
|
||||||
<div class="is-text-overflow is-pointer" @click="toggle_class($event)">
|
|
||||||
<span class="has-text-danger">{{ item.msg }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column is-half-mobile has-text-centered is-text-overflow is-unselectable">
|
<div class="column is-half-mobile has-text-centered is-text-overflow is-unselectable">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon" :class="setIconColor(item)"><i :class="[setIcon(item), is_queued(item)]" /></span>
|
<span class="icon" :class="setIconColor(item)"><i :class="[setIcon(item), is_queued(item)]" /></span>
|
||||||
|
|
@ -329,14 +319,6 @@
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-half-mobile">
|
|
||||||
<a class="button is-danger is-fullwidth" @click="removeItem(item)">
|
|
||||||
<span class="icon-text is-block">
|
|
||||||
<span class="icon"><i class="fa-solid fa-trash-can" /></span>
|
|
||||||
<span>Remove</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column is-half-mobile" v-if="item.filename && item.status === 'finished'">
|
<div class="column is-half-mobile" v-if="item.filename && item.status === 'finished'">
|
||||||
<a class="button is-link is-fullwidth" :href="makeDownload(config, item)"
|
<a class="button is-link is-fullwidth" :href="makeDownload(config, item)"
|
||||||
|
|
@ -347,7 +329,17 @@
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="column" v-if="item.url && !config.app.basic_mode">
|
|
||||||
|
<div class="column is-half-mobile">
|
||||||
|
<a class="button is-danger is-fullwidth" @click="removeItem(item)">
|
||||||
|
<span class="icon-text is-block">
|
||||||
|
<span class="icon"><i class="fa-solid fa-trash-can" /></span>
|
||||||
|
<span>Remove</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
<Dropdown icons="fa-solid fa-cogs" label="Actions">
|
<Dropdown icons="fa-solid fa-cogs" label="Actions">
|
||||||
<template v-if="'finished' === item.status && item.filename">
|
<template v-if="'finished' === item.status && item.filename">
|
||||||
<NuxtLink @click="playVideo(item)" class="dropdown-item">
|
<NuxtLink @click="playVideo(item)" class="dropdown-item">
|
||||||
|
|
@ -365,12 +357,13 @@
|
||||||
<hr class="dropdown-divider" />
|
<hr class="dropdown-divider" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<NuxtLink class="dropdown-item" @click="emitter('getInfo', item.url)">
|
<NuxtLink class="dropdown-item" @click="emitter('getInfo', item.url)" v-if="!config.app.basic_mode">
|
||||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||||
<span>yt-dlp Information</span>
|
<span>yt-dlp Information</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="dropdown-item" @click="emitter('getItemInfo', item._id)">
|
<NuxtLink class="dropdown-item" @click="emitter('getItemInfo', item._id)"
|
||||||
|
v-if="!config.app.basic_mode">
|
||||||
<span class="icon"><i class="fa-solid fa-info-circle" /></span>
|
<span class="icon"><i class="fa-solid fa-info-circle" /></span>
|
||||||
<span>Local Information</span>
|
<span>Local Information</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
@ -383,7 +376,7 @@
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="'finished' !== item.status && config.app?.keep_archive">
|
<template v-if="'finished' !== item.status && config.app?.keep_archive && !config.app.basic_mode">
|
||||||
<hr class="dropdown-divider" />
|
<hr class="dropdown-divider" />
|
||||||
<NuxtLink class="dropdown-item has-text-danger" @click="addArchiveDialog(item)">
|
<NuxtLink class="dropdown-item has-text-danger" @click="addArchiveDialog(item)">
|
||||||
<span class="icon"><i class="fa-solid fa-box-archive" /></span>
|
<span class="icon"><i class="fa-solid fa-box-archive" /></span>
|
||||||
|
|
@ -391,7 +384,8 @@
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="'finished' === item.status && item.filename && config.app?.keep_archive">
|
<template
|
||||||
|
v-if="'finished' === item.status && item.filename && config.app?.keep_archive && !config.app.basic_mode">
|
||||||
<hr class="dropdown-divider" />
|
<hr class="dropdown-divider" />
|
||||||
<NuxtLink class="dropdown-item" @click="removeFromArchiveDialog(item)">
|
<NuxtLink class="dropdown-item" @click="removeFromArchiveDialog(item)">
|
||||||
<span class="icon"><i class="fa-solid fa-box-archive" /></span>
|
<span class="icon"><i class="fa-solid fa-box-archive" /></span>
|
||||||
|
|
@ -400,6 +394,19 @@
|
||||||
</template>
|
</template>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="columns is-mobile is-multiline" v-if="item.error || showMessage(item)">
|
||||||
|
<div class="column is-12" v-if="item.error">
|
||||||
|
<div class="is-text-overflow is-pointer" @click="toggle_class($event)">
|
||||||
|
<span class="has-text-danger">{{ item.error }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-12" v-if="showMessage(item)">
|
||||||
|
<div class="is-text-overflow is-pointer" @click="toggle_class($event)">
|
||||||
|
<span class="has-text-danger">{{ item.msg }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -408,8 +415,12 @@
|
||||||
|
|
||||||
<div class="columns is-multiline" v-if="!hasItems">
|
<div class="columns is-multiline" v-if="!hasItems">
|
||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
|
<Message message_class="has-background-warning-90 has-text-dark" title="No results for downloaded items."
|
||||||
|
icon="fas fa-search" :useClose="true" @close="() => emitter('clear_search')" v-if="query">
|
||||||
|
<span class="is-block">No results found for '<span class="is-underlined is-bold">{{ query }}</span>'.</span>
|
||||||
|
</Message>
|
||||||
<Message message_class="has-background-success-90 has-text-dark" title="No records in history."
|
<Message message_class="has-background-success-90 has-text-dark" title="No records in history."
|
||||||
icon="fas fa-circle-check" v-if="socket.isConnected" />
|
icon="fas fa-circle-check" v-else-if="socket.isConnected" />
|
||||||
<Message message_class="has-background-info-90 has-text-dark" title="Connecting.." icon="fas fa-spinner fa-spin"
|
<Message message_class="has-background-info-90 has-text-dark" title="Connecting.." icon="fas fa-spinner fa-spin"
|
||||||
v-else />
|
v-else />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -446,12 +457,17 @@ import { getEmbedable, isEmbedable } from '~/utils/embedable'
|
||||||
import { formatBytes, makeDownload, uri } from '~/utils/index'
|
import { formatBytes, makeDownload, uri } from '~/utils/index'
|
||||||
import Dropdown from './Dropdown.vue'
|
import Dropdown from './Dropdown.vue'
|
||||||
|
|
||||||
const emitter = defineEmits(['getInfo', 'add_new', 'getItemInfo'])
|
const emitter = defineEmits(['getInfo', 'add_new', 'getItemInfo', 'clear_search'])
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
thumbnails: {
|
thumbnails: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -461,34 +477,42 @@ const socket = useSocketStore()
|
||||||
const toast = useNotification()
|
const toast = useNotification()
|
||||||
const box = useConfirm()
|
const box = useConfirm()
|
||||||
|
|
||||||
const selectedElms = ref([])
|
|
||||||
const masterSelectAll = ref(false)
|
|
||||||
const showCompleted = useStorage('showCompleted', true)
|
const showCompleted = useStorage('showCompleted', true)
|
||||||
const hideThumbnail = useStorage('hideThumbnailHistory', false)
|
const hideThumbnail = useStorage('hideThumbnailHistory', false)
|
||||||
const direction = useStorage('sortCompleted', 'desc')
|
const direction = useStorage('sortCompleted', 'desc')
|
||||||
const display_style = useStorage('display_style', 'cards')
|
const display_style = useStorage('display_style', 'cards')
|
||||||
const table_container = ref(false)
|
const bg_enable = useStorage('random_bg', true)
|
||||||
|
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
||||||
|
|
||||||
|
const selectedElms = ref([])
|
||||||
|
const masterSelectAll = ref(false)
|
||||||
|
const table_container = ref(false)
|
||||||
const embed_url = ref('')
|
const embed_url = ref('')
|
||||||
const video_item = ref(null)
|
const video_item = ref(null)
|
||||||
|
|
||||||
const dialog_confirm = ref({
|
const dialog_confirm = ref({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: 'Confirm Action',
|
title: 'Confirm Action',
|
||||||
confirm: (opts) => { },
|
confirm: () => { },
|
||||||
message: '',
|
message: '',
|
||||||
options: [
|
options: [
|
||||||
{ key: 'remove_history', label: 'Also, Remove from history.' },
|
{ key: 'remove_history', label: 'Also, Remove from history.' },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const showThumbnails = computed(() => props.thumbnails && !hideThumbnail.value)
|
||||||
|
|
||||||
const playVideo = item => video_item.value = item
|
const playVideo = item => video_item.value = item
|
||||||
const closeVideo = () => video_item.value = null
|
const closeVideo = () => video_item.value = null
|
||||||
|
|
||||||
const showThumbnails = computed(() => props.thumbnails && !hideThumbnail.value)
|
const filteredItems = items => !props.query ? items : items.filter(filterItem)
|
||||||
|
|
||||||
const bg_enable = useStorage('random_bg', true)
|
const filterItem = item => {
|
||||||
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
const q = props.query?.toLowerCase()
|
||||||
|
if (!q) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return Object.values(item).some(v => typeof v === 'string' && v.toLowerCase().includes(q))
|
||||||
|
}
|
||||||
|
|
||||||
watch(masterSelectAll, (value) => {
|
watch(masterSelectAll, (value) => {
|
||||||
for (const key in stateStore.history) {
|
for (const key in stateStore.history) {
|
||||||
|
|
@ -512,7 +536,7 @@ const sortCompleted = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const hasSelected = computed(() => selectedElms.value.length > 0)
|
const hasSelected = computed(() => selectedElms.value.length > 0)
|
||||||
const hasItems = computed(() => stateStore.count('history') > 0)
|
const hasItems = computed(() => filteredItems(sortCompleted.value).length > 0)
|
||||||
|
|
||||||
const showMessage = (item) => {
|
const showMessage = (item) => {
|
||||||
if (!item?.msg || item.msg === item?.error) {
|
if (!item?.msg || item.msg === item?.error) {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas" :class="showQueue ? 'fa-solid fa-arrow-up' : 'fa-solid fa-arrow-down'" />
|
<i class="fas" :class="showQueue ? 'fa-solid fa-arrow-up' : 'fa-solid fa-arrow-down'" />
|
||||||
</span>
|
</span>
|
||||||
<span>Queue <span v-if="hasQueuedItems">({{ stateStore.count('queue') }})</span></span>
|
<span>Queue <span v-if="hasQueuedItems">({{ filteredItems.length }})</span></span>
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div v-if="showQueue">
|
<div v-if="showQueue">
|
||||||
<div class="columns is-multiline is-mobile has-text-centered" v-if="hasQueuedItems">
|
<div class="columns is-multiline is-mobile has-text-centered" v-if="filteredItems.length > 0">
|
||||||
<div class="column is-half-mobile" v-if="'cards' === display_style">
|
<div class="column is-half-mobile" v-if="'cards' === display_style">
|
||||||
<button type="button" class="button is-fullwidth is-ghost" @click="masterSelectAll = !masterSelectAll">
|
<button type="button" class="button is-fullwidth is-ghost" @click="masterSelectAll = !masterSelectAll">
|
||||||
<span class="icon-text is-block">
|
<span class="icon-text is-block">
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns is-multiline" v-if="'list' === display_style">
|
<div class="columns is-multiline" v-if="'list' === display_style">
|
||||||
<div class="column is-12" v-if="hasQueuedItems">
|
<div class="column is-12" v-if="filteredItems.length > 0">
|
||||||
<div class="table-container is-responsive">
|
<div :class="{ 'table-container': table_container }">
|
||||||
<table class="table is-striped is-hoverable is-fullwidth is-bordered"
|
<table class="table is-striped is-hoverable is-fullwidth is-bordered"
|
||||||
style="min-width: 1300px; table-layout: fixed;">
|
style="min-width: 1300px; table-layout: fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="item in stateStore.queue" :key="item._id">
|
<tr v-for="item in filteredItems" :key="item._id">
|
||||||
<td class="has-text-centered is-vcentered">
|
<td class="has-text-centered is-vcentered">
|
||||||
<label class="checkbox is-block">
|
<label class="checkbox is-block">
|
||||||
<input class="completed-checkbox" type="checkbox" v-model="selectedElms"
|
<input class="completed-checkbox" type="checkbox" v-model="selectedElms"
|
||||||
|
|
@ -105,26 +105,34 @@
|
||||||
:data-datetime="item.datetime" v-rtime="item.datetime" />
|
:data-datetime="item.datetime" v-rtime="item.datetime" />
|
||||||
</td>
|
</td>
|
||||||
<td class="is-vcentered is-items-center">
|
<td class="is-vcentered is-items-center">
|
||||||
<div class="field is-grouped is-grouped-centered">
|
<Dropdown icons="fa-solid fa-cogs" @open_state="s => table_container = !s"
|
||||||
<div class="control" v-if="isEmbedable(item.url)">
|
:button_classes="'is-small'" label="Actions">
|
||||||
<button @click="() => embed_url = getEmbedable(item.url)" v-tooltip="'Play video'"
|
<template v-if="isEmbedable(item.url)">
|
||||||
class="button is-danger is-small">
|
<NuxtLink class="dropdown-item has-text-danger" @click="embed_url = getEmbedable(item.url)">
|
||||||
<span class="icon"><i class="fa-solid fa-play" /></span>
|
<span class="icon"><i class="fa-solid fa-play" /></span>
|
||||||
</button>
|
<span>Play video</span>
|
||||||
</div>
|
</NuxtLink>
|
||||||
<div class="control">
|
<hr class="dropdown-divider" />
|
||||||
<button class="button is-warning is-small" @click="confirmCancel(item);"
|
</template>
|
||||||
v-tooltip="'Cancel download'">
|
|
||||||
<span class="icon"><i class="fa-solid fa-eject" /></span>
|
<NuxtLink class="dropdown-item has-text-warning" @click="confirmCancel(item);">
|
||||||
</button>
|
<span class="icon"><i class="fa-solid fa-eject" /></span>
|
||||||
</div>
|
<span>Cancel Item</span>
|
||||||
<div class="control" v-if="item.url && !config.app.basic_mode">
|
</NuxtLink>
|
||||||
<button class="button is-info is-small" @click="emitter('getInfo', item.url)"
|
|
||||||
v-tooltip="'Show video information'">
|
<hr class="dropdown-divider" v-if="!config.app.basic_mode" />
|
||||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
|
||||||
</button>
|
<NuxtLink class="dropdown-item" @click="emitter('getInfo', item.url)" v-if="!config.app.basic_mode">
|
||||||
</div>
|
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||||
</div>
|
<span>yt-dlp Information</span>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<NuxtLink class="dropdown-item" @click="emitter('getItemInfo', item._id)"
|
||||||
|
v-if="!config.app.basic_mode">
|
||||||
|
<span class="icon"><i class="fa-solid fa-info-circle" /></span>
|
||||||
|
<span>Local Information</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</Dropdown>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -135,8 +143,8 @@
|
||||||
|
|
||||||
<div class="columns is-multiline" v-else>
|
<div class="columns is-multiline" v-else>
|
||||||
<LateLoader :unrender="true" :min-height="showThumbnails ? 475 : 265" class="column is-6"
|
<LateLoader :unrender="true" :min-height="showThumbnails ? 475 : 265" class="column is-6"
|
||||||
v-for="item in stateStore.queue" :key="item._id">
|
v-for="item in filteredItems" :key="item._id">
|
||||||
<div class="card is-flex is-full-height is-flex-direction-column">
|
<div class="card">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
<div class="card-header-title is-text-overflow is-block" v-tooltip="item.title">
|
<div class="card-header-title is-text-overflow is-block" v-tooltip="item.title">
|
||||||
<NuxtLink target="_blank" :href="item.url">{{ item.title }}</NuxtLink>
|
<NuxtLink target="_blank" :href="item.url">{{ item.title }}</NuxtLink>
|
||||||
|
|
@ -149,11 +157,6 @@
|
||||||
{{ formatTime(item.extras.duration) }}
|
{{ formatTime(item.extras.duration) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="control" v-if="!showThumbnails && isEmbedable(item.url)">
|
|
||||||
<NuxtLink @click="embed_url = getEmbedable(item.url)" v-tooltip="'Play video'">
|
|
||||||
<span class="icon has-text-danger"><i class="fa-solid fa-play" /></span>
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button @click="hideThumbnail = !hideThumbnail" v-if="thumbnails">
|
<button @click="hideThumbnail = !hideThumbnail" v-if="thumbnails">
|
||||||
<span class="icon"><i class="fa-solid"
|
<span class="icon"><i class="fa-solid"
|
||||||
|
|
@ -184,7 +187,7 @@
|
||||||
</template>
|
</template>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content is-flex-grow-1">
|
<div class="card-content">
|
||||||
<div class="columns is-multiline is-mobile">
|
<div class="columns is-multiline is-mobile">
|
||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
<div class="progress-bar is-unselectable">
|
<div class="progress-bar is-unselectable">
|
||||||
|
|
@ -217,11 +220,27 @@
|
||||||
<span>Cancel</span>
|
<span>Cancel</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-half-mobile" v-if="item.url && !config.app.basic_mode">
|
<div class="column is-half-mobile">
|
||||||
<button class="button is-info is-fullwidth" @click="emitter('getInfo', item.url)">
|
<Dropdown icons="fa-solid fa-cogs" @open_state="s => table_container = !s" label="Actions">
|
||||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
<template v-if="isEmbedable(item.url)">
|
||||||
<span>Information</span>
|
<NuxtLink class="dropdown-item has-text-danger" @click="embed_url = getEmbedable(item.url)">
|
||||||
</button>
|
<span class="icon"><i class="fa-solid fa-play" /></span>
|
||||||
|
<span>Play video</span>
|
||||||
|
</NuxtLink>
|
||||||
|
<hr class="dropdown-divider" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<NuxtLink class="dropdown-item" @click="emitter('getInfo', item.url)" v-if="!config.app.basic_mode">
|
||||||
|
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||||
|
<span>yt-dlp Information</span>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<NuxtLink class="dropdown-item" @click="emitter('getItemInfo', item._id)"
|
||||||
|
v-if="!config.app.basic_mode">
|
||||||
|
<span class="icon"><i class="fa-solid fa-info-circle" /></span>
|
||||||
|
<span>Local Information</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -229,6 +248,14 @@
|
||||||
</LateLoader>
|
</LateLoader>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="columns is-multiline" v-if="hasQueuedItems && filteredItems.length < 1 && query">
|
||||||
|
<div class="column is-12">
|
||||||
|
<Message message_class="has-background-warning-90 has-text-dark" title="No results for queued items"
|
||||||
|
icon="fas fa-search" :useClose="true" @close="() => emitter('clear_search')" v-if="query">
|
||||||
|
<span class="is-block">No results found for '<span class="is-underlined is-bold">{{ query }}</span>'.</span>
|
||||||
|
</Message>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal is-active" v-if="embed_url">
|
<div class="modal is-active" v-if="embed_url">
|
||||||
<div class="modal-background" @click="embed_url = ''"></div>
|
<div class="modal-background" @click="embed_url = ''"></div>
|
||||||
|
|
@ -246,11 +273,16 @@ import { useStorage } from '@vueuse/core'
|
||||||
import { ucFirst } from '~/utils/index'
|
import { ucFirst } from '~/utils/index'
|
||||||
import { isEmbedable, getEmbedable } from '~/utils/embedable'
|
import { isEmbedable, getEmbedable } from '~/utils/embedable'
|
||||||
|
|
||||||
const emitter = defineEmits(['getInfo'])
|
const emitter = defineEmits(['getInfo', 'clear_search', 'getItemInfo'])
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
thumbnails: {
|
thumbnails: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const config = useConfigStore()
|
const config = useConfigStore()
|
||||||
|
|
@ -258,18 +290,19 @@ const stateStore = useStateStore()
|
||||||
const socket = useSocketStore()
|
const socket = useSocketStore()
|
||||||
const box = useConfirm()
|
const box = useConfirm()
|
||||||
|
|
||||||
const selectedElms = ref([])
|
|
||||||
const masterSelectAll = ref(false)
|
|
||||||
const showQueue = useStorage('showQueue', true)
|
const showQueue = useStorage('showQueue', true)
|
||||||
const hideThumbnail = useStorage('hideThumbnailQueue', false)
|
const hideThumbnail = useStorage('hideThumbnailQueue', false)
|
||||||
const display_style = useStorage('display_style', 'cards')
|
const display_style = useStorage('display_style', 'cards')
|
||||||
const showThumbnails = computed(() => props.thumbnails && !hideThumbnail.value)
|
|
||||||
|
|
||||||
const embed_url = ref('')
|
|
||||||
|
|
||||||
const bg_enable = useStorage('random_bg', true)
|
const bg_enable = useStorage('random_bg', true)
|
||||||
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
||||||
|
|
||||||
|
const selectedElms = ref([])
|
||||||
|
const masterSelectAll = ref(false)
|
||||||
|
const embed_url = ref('')
|
||||||
|
const table_container = ref(false)
|
||||||
|
|
||||||
|
const showThumbnails = computed(() => props.thumbnails && !hideThumbnail.value)
|
||||||
|
|
||||||
watch(masterSelectAll, (value) => {
|
watch(masterSelectAll, (value) => {
|
||||||
for (const key in stateStore.queue) {
|
for (const key in stateStore.queue) {
|
||||||
const element = stateStore.queue[key]
|
const element = stateStore.queue[key]
|
||||||
|
|
@ -281,6 +314,14 @@ watch(masterSelectAll, (value) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const filteredItems = computed(() => {
|
||||||
|
const q = props.query?.toLowerCase();
|
||||||
|
if (!q) {
|
||||||
|
return Object.values(stateStore.queue)
|
||||||
|
}
|
||||||
|
return Object.values(stateStore.queue).filter(i => Object.values(i).some(v => typeof v === 'string' && v.toLowerCase().includes(q)));
|
||||||
|
});
|
||||||
|
|
||||||
const hasSelected = computed(() => selectedElms.value.length > 0)
|
const hasSelected = computed(() => selectedElms.value.length > 0)
|
||||||
const hasQueuedItems = computed(() => stateStore.count('queue') > 0)
|
const hasQueuedItems = computed(() => stateStore.count('queue') > 0)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,19 @@
|
||||||
|
|
||||||
<div class="is-pulled-right" v-if="socket.isConnected">
|
<div class="is-pulled-right" v-if="socket.isConnected">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
|
<p class="control has-icons-left" v-if="toggleFilter">
|
||||||
|
<input type="search" v-model.lazy="query" class="input" id="filter"
|
||||||
|
placeholder="Filter displayed content">
|
||||||
|
<span class="icon is-left"><i class="fas fa-filter" /></span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="control">
|
||||||
|
<button class="button is-danger is-light" v-tooltip.bottom="'Filter'"
|
||||||
|
@click="toggleFilter = !toggleFilter">
|
||||||
|
<span class="icon"><i class="fas fa-filter" /></span>
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="control" v-if="!config.app.basic_mode && false === config.app.basic_mode">
|
<p class="control" v-if="!config.app.basic_mode && false === config.app.basic_mode">
|
||||||
<button class="button is-warning" @click="pauseDownload" v-if="false === config.paused"
|
<button class="button is-warning" @click="pauseDownload" v-if="false === config.paused"
|
||||||
v-tooltip.bottom="'Pause non-active downloads.'">
|
v-tooltip.bottom="'Pause non-active downloads.'">
|
||||||
|
|
@ -49,10 +62,11 @@
|
||||||
|
|
||||||
<NewDownload v-if="config.showForm || config.app.basic_mode" @getInfo="url => get_info = url" :item="item_form"
|
<NewDownload v-if="config.showForm || config.app.basic_mode" @getInfo="url => get_info = url" :item="item_form"
|
||||||
@clear_form="item_form = {}" @remove_archive="" />
|
@clear_form="item_form = {}" @remove_archive="" />
|
||||||
<Queue @getInfo="(url: string) => view_info(url, false)" :thumbnails="show_thumbnail"
|
<Queue @getInfo="(url: string) => view_info(url, false)" :thumbnails="show_thumbnail" :query="query"
|
||||||
@getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)" />
|
@getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)" @clear_search="query = ''" />
|
||||||
<History @getInfo="(url: string) => view_info(url, false)" @add_new="item => toNewDownload(item)"
|
<History @getInfo="(url: string) => view_info(url, false)" @add_new="item => toNewDownload(item)" :query="query"
|
||||||
:thumbnails="show_thumbnail" @getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)" />
|
:thumbnails="show_thumbnail" @getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)"
|
||||||
|
@clear_search="query = ''" />
|
||||||
<GetInfo v-if="get_info" :link="get_info" :useUrl="get_info_use_url" @closeModel="close_info()" />
|
<GetInfo v-if="get_info" :link="get_info" :useUrl="get_info_use_url" @closeModel="close_info()" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -64,15 +78,22 @@ const config = useConfigStore()
|
||||||
const stateStore = useStateStore()
|
const stateStore = useStateStore()
|
||||||
const socket = useSocketStore()
|
const socket = useSocketStore()
|
||||||
const box = useConfirm()
|
const box = useConfirm()
|
||||||
|
|
||||||
const get_info = ref<string>('')
|
|
||||||
const get_info_use_url = ref<boolean>(false)
|
|
||||||
const bg_enable = useStorage<boolean>('random_bg', true)
|
const bg_enable = useStorage<boolean>('random_bg', true)
|
||||||
const bg_opacity = useStorage<number>('random_bg_opacity', 0.85)
|
const bg_opacity = useStorage<number>('random_bg_opacity', 0.85)
|
||||||
const display_style = useStorage<string>('display_style', 'cards')
|
const display_style = useStorage<string>('display_style', 'cards')
|
||||||
const show_thumbnail = useStorage<boolean>('show_thumbnail', true)
|
const show_thumbnail = useStorage<boolean>('show_thumbnail', true)
|
||||||
|
|
||||||
|
const get_info = ref<string>('')
|
||||||
|
const get_info_use_url = ref<boolean>(false)
|
||||||
const item_form = ref({})
|
const item_form = ref({})
|
||||||
|
const query = ref()
|
||||||
|
const toggleFilter = ref(false)
|
||||||
|
|
||||||
|
watch(toggleFilter, () => {
|
||||||
|
if (!toggleFilter.value) {
|
||||||
|
query.value = ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!config.app.ui_update_title) {
|
if (!config.app.ui_update_title) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue