WebUI QoL improvements.
This commit is contained in:
@@ -176,3 +176,7 @@ body {
|
|||||||
.is-pointer-help {
|
.is-pointer-help {
|
||||||
cursor: help;
|
cursor: help;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-text-contents {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<NuxtLink :to="'/history/'+item.id" v-text="item?.full_title ?? makeName(item)"/>
|
<NuxtLink :to="'/history/'+item.id" v-text="item?.full_title ?? makeName(item)"/>
|
||||||
</p>
|
</p>
|
||||||
<span class="card-header-icon">
|
<span class="card-header-icon" @click="item.showRawData = !item?.showRawData">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas" :class="{'fa-tv': 'episode' === item.type, 'fa-film': 'movie' === item.type}"></i>
|
<i class="fas" :class="{'fa-tv': 'episode' === item.type, 'fa-film': 'movie' === item.type}"></i>
|
||||||
</span>
|
</span>
|
||||||
@@ -217,20 +217,31 @@
|
|||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="columns is-multiline is-mobile has-text-centered">
|
<div class="columns is-multiline is-mobile has-text-centered">
|
||||||
<div class="column is-12 has-text-left" v-if="item?.content_title">
|
<div class="column is-12 has-text-left" v-if="item?.content_title">
|
||||||
<div class="is-text-overflow is-clickable"
|
<div class="field is-grouped">
|
||||||
@click="(e) => e.target.classList.toggle('is-text-overflow')">
|
<div class="control is-clickable"
|
||||||
<span class="icon"><i class="fas fa-heading"></i></span>
|
:class="{'is-text-overflow': !item?.expand_title, 'is-text-contents': item?.expand_title}"
|
||||||
<NuxtLink :to="makeSearchLink('subtitle', item.content_title)"
|
@click="item.expand_title = !item?.expand_title">
|
||||||
@click="triggerSearch('subtitle', item.content_title)" v-text="item.content_title"/>
|
<span class="icon"><i class="fas fa-heading"></i> </span>
|
||||||
|
<NuxtLink :to="makeSearchLink('subtitle',item.content_title)" v-text="item.content_title"/>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<span class="icon is-clickable" @click="copyText(item.content_title, false)">
|
||||||
|
<i class="fas fa-copy"></i></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12 is-clickable has-text-left" v-if="item?.content_path"
|
<div class="column is-12 has-text-left" v-if="item?.content_path">
|
||||||
@click="(e) => e.target.firstChild?.classList?.toggle('is-text-overflow')">
|
<div class="field is-grouped">
|
||||||
<div class="is-text-overflow">
|
<div class="control is-clickable"
|
||||||
<span class="icon"><i class="fas fa-file"></i></span>
|
:class="{'is-text-overflow': !item?.expand_path, 'is-text-contents': item?.expand_path}"
|
||||||
<NuxtLink :to="makeSearchLink('path', item.content_path)"
|
@click="item.expand_path = !item?.expand_path">
|
||||||
@click="triggerSearch('path', item.content_path)"
|
<span class="icon"><i class="fas fa-file"></i> </span>
|
||||||
v-text="item?.content_path"/>
|
<NuxtLink :to="makeSearchLink('path',item.content_path)" v-text="item.content_path"/>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<span class="icon is-clickable" @click="copyText(item.content_path, false)">
|
||||||
|
<i class="fas fa-copy"></i></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12 has-text-left" v-if="item?.progress">
|
<div class="column is-12 has-text-left" v-if="item?.progress">
|
||||||
@@ -239,6 +250,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-content p-0 m-0" v-if="item?.showRawData">
|
||||||
|
<pre style="position: relative; max-height: 343px;"><code>{{ JSON.stringify(item, null, 2) }}</code>
|
||||||
|
<button class="button m-4" @click="() => copyText(JSON.stringify(item, null, 2))"
|
||||||
|
style="position: absolute; top:0; right:0;">
|
||||||
|
<span class="icon"><i class="fas fa-copy"></i></span>
|
||||||
|
</button>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
<div class="card-footer has-text-centered">
|
<div class="card-footer has-text-centered">
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
<div class="is-text-overflow">
|
<div class="is-text-overflow">
|
||||||
@@ -253,6 +272,10 @@
|
|||||||
<div class="is-text-overflow">
|
<div class="is-text-overflow">
|
||||||
<span class="icon"><i class="fas fa-server"></i> </span>
|
<span class="icon"><i class="fas fa-server"></i> </span>
|
||||||
<NuxtLink :to="'/backend/'+item.via" v-text="item.via"/>
|
<NuxtLink :to="'/backend/'+item.via" v-text="item.via"/>
|
||||||
|
<span v-if="item?.metadata && Object.keys(item?.metadata).length > 1"
|
||||||
|
v-tooltip="`Also reported by: ${Object.keys(item.metadata).filter(i => i !== item.via).join(', ')}.`">
|
||||||
|
(<span class="has-tooltip">+{{ Object.keys(item.metadata).length - 1 }}</span>)
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
@@ -277,6 +300,7 @@ import moment from 'moment'
|
|||||||
import Message from '~/components/Message'
|
import Message from '~/components/Message'
|
||||||
import {
|
import {
|
||||||
awaitElement,
|
awaitElement,
|
||||||
|
copyText,
|
||||||
formatDuration,
|
formatDuration,
|
||||||
makeName,
|
makeName,
|
||||||
makePagination,
|
makePagination,
|
||||||
@@ -311,7 +335,7 @@ const selectAll = ref(false)
|
|||||||
const selected_ids = ref([])
|
const selected_ids = ref([])
|
||||||
const massActionInProgress = ref(false)
|
const massActionInProgress = ref(false)
|
||||||
|
|
||||||
watch(selectAll, v => selected_ids.value = v ? items.value.map(i => i.id) : []);
|
watch(selectAll, v => selected_ids.value = v ? filteredRows(items.value).map(i => i.id) : []);
|
||||||
|
|
||||||
const loadContent = async (pageNumber, fromPopState = false) => {
|
const loadContent = async (pageNumber, fromPopState = false) => {
|
||||||
pageNumber = parseInt(pageNumber)
|
pageNumber = parseInt(pageNumber)
|
||||||
@@ -585,7 +609,7 @@ watch(filter, val => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
'path': '/parity',
|
'path': '/history',
|
||||||
'query': {
|
'query': {
|
||||||
...route.query,
|
...route.query,
|
||||||
'filter': undefined
|
'filter': undefined
|
||||||
@@ -599,7 +623,7 @@ watch(filter, val => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
'path': '/parity',
|
'path': '/history',
|
||||||
'query': {
|
'query': {
|
||||||
...route.query,
|
...route.query,
|
||||||
'filter': val
|
'filter': val
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<NuxtLink :to="'/history/'+item.id" v-text="makeName(item)"/>
|
<NuxtLink :to="'/history/'+item.id" v-text="makeName(item)"/>
|
||||||
</p>
|
</p>
|
||||||
<span class="card-header-icon">
|
<span class="card-header-icon" @click="item.showRawData = !item?.showRawData">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas"
|
<i class="fas"
|
||||||
:class="{ 'fa-tv': 'episode' === item.type.toLowerCase(), 'fa-film': 'movie' === item.type.toLowerCase()}"></i>
|
:class="{ 'fa-tv': 'episode' === item.type.toLowerCase(), 'fa-film': 'movie' === item.type.toLowerCase()}"></i>
|
||||||
@@ -134,34 +134,73 @@
|
|||||||
</header>
|
</header>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="columns is-multiline is-mobile">
|
<div class="columns is-multiline is-mobile">
|
||||||
<div class="column is-12 " v-if="item?.content_title">
|
<div class="column is-12" v-if="item?.content_title">
|
||||||
<div class="is-text-overflow is-clickable"
|
<div class="field is-grouped">
|
||||||
@click="(e) => e.target.classList.toggle('is-text-overflow')">
|
<div class="control is-clickable"
|
||||||
<span class="icon"><i class="fas fa-heading"></i> </span>
|
:class="{'is-text-overflow': !item?.expand_title, 'is-text-contents': item?.expand_title}"
|
||||||
<NuxtLink :to="makeSearchLink('subtitle',item.content_title)" v-text="item.content_title"/>
|
@click="item.expand_title = !item?.expand_title">
|
||||||
|
<span class="icon"><i class="fas fa-heading"></i> </span>
|
||||||
|
<NuxtLink :to="makeSearchLink('subtitle',item.content_title)" v-text="item.content_title"/>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<span class="icon is-clickable" @click="copyText(item.content_title, false)">
|
||||||
|
<i class="fas fa-copy"></i></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12 is-clickable " v-if="item?.content_path"
|
<div class="column is-12" v-if="item?.content_path">
|
||||||
@click="(e) => e.target.firstChild?.classList?.toggle('is-text-overflow')">
|
<div class="field is-grouped">
|
||||||
<div class="is-text-overflow">
|
<div class="control is-clickable"
|
||||||
<span class="icon"><i class="fas fa-file"></i> </span>
|
:class="{'is-text-overflow': !item?.expand_path, 'is-text-contents': item?.expand_path}"
|
||||||
<NuxtLink :to="makeSearchLink('path',item.content_path)" v-text="item.content_path"/>
|
@click="item.expand_path = !item?.expand_path">
|
||||||
|
<span class="icon"><i class="fas fa-file"></i> </span>
|
||||||
|
<NuxtLink :to="makeSearchLink('path',item.content_path)" v-text="item.content_path"/>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<span class="icon is-clickable" @click="copyText(item.content_path, false)">
|
||||||
|
<i class="fas fa-copy"></i></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
<span class="icon"><i class="fas fa-check"></i> </span>
|
<div class="field is-grouped">
|
||||||
<span v-for="backend in item.reported_by">
|
<div class="control is-expanded is-unselectable">
|
||||||
<NuxtLink :to="'/backend/'+backend" v-text="backend" class="tag"/>
|
<span class="icon"><i class="fas fa-check"></i> </span>
|
||||||
</span>
|
<span>Reported By</span>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<template v-for="backend in item.reported_by" :key="`${item.id}-rb-${backend}`">
|
||||||
|
<NuxtLink :to="'/backend/'+backend" v-text="backend" class="tag"/>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column is-12">
|
<div class="column is-12">
|
||||||
<span class="icon"><i class="fas fa-times"></i> </span>
|
<div class="field is-grouped">
|
||||||
<span v-for="backend in item.not_reported_by">
|
<div class="control is-expanded is-unselectable">
|
||||||
<NuxtLink :to="'/backend/'+backend" v-text="backend" class="tag"/>
|
<span class="icon"><i class="fas fa-times"></i> </span>
|
||||||
</span>
|
<span>Not Reported By</span>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<template v-for="backend in item.not_reported_by" :key="`${item.id}-nrb-${backend}`">
|
||||||
|
<NuxtLink :to="'/backend/'+backend" v-text="backend" class="tag"/>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-content p-0 m-0" v-if="item?.showRawData">
|
||||||
|
<pre style="position: relative; max-height: 343px;"><code>{{ JSON.stringify(item, null, 2) }}</code>
|
||||||
|
<button class="button m-4" @click="() => copyText(JSON.stringify(item, null, 2))"
|
||||||
|
style="position: absolute; top:0; right:0;">
|
||||||
|
<span class="icon"><i class="fas fa-copy"></i></span>
|
||||||
|
</button>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@@ -237,7 +276,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import request from '~/utils/request'
|
import request from '~/utils/request'
|
||||||
import Message from '~/components/Message'
|
import Message from '~/components/Message'
|
||||||
import {awaitElement, makeName, makePagination, makeSearchLink, notification, TOOLTIP_DATE_FORMAT} from '~/utils/index'
|
import {
|
||||||
|
awaitElement,
|
||||||
|
copyText,
|
||||||
|
makeName,
|
||||||
|
makePagination,
|
||||||
|
makeSearchLink,
|
||||||
|
notification,
|
||||||
|
TOOLTIP_DATE_FORMAT
|
||||||
|
} from '~/utils/index'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import {useStorage} from '@vueuse/core'
|
import {useStorage} from '@vueuse/core'
|
||||||
import Lazy from '~/components/Lazy'
|
import Lazy from '~/components/Lazy'
|
||||||
|
|||||||
@@ -273,13 +273,19 @@ const formatDuration = (milliseconds) => {
|
|||||||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyText = (str) => {
|
const copyText = (str, showNotification = true) => {
|
||||||
if (navigator.clipboard) {
|
if (navigator.clipboard) {
|
||||||
navigator.clipboard.writeText(str).then(() => {
|
navigator.clipboard.writeText(str).then(() => {
|
||||||
notification('success', 'Success', 'Report has been copied to clipboard.')
|
if (!showNotification) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notification('success', 'Success', 'Text copied to clipboard.')
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('Failed to copy: ', error)
|
console.error('Failed to copy: ', error)
|
||||||
notification('error', 'Error', 'Failed to copy to clipboard.')
|
if (!showNotification) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notification('error', 'Error', 'Failed to copy text to clipboard.')
|
||||||
});
|
});
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -290,7 +296,9 @@ const copyText = (str) => {
|
|||||||
el.select()
|
el.select()
|
||||||
document.execCommand('copy')
|
document.execCommand('copy')
|
||||||
document.body.removeChild(el)
|
document.body.removeChild(el)
|
||||||
|
if (!showNotification) {
|
||||||
|
return
|
||||||
|
}
|
||||||
notification('success', 'Success', 'Text copied to clipboard.')
|
notification('success', 'Success', 'Text copied to clipboard.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user