316 lines
12 KiB
Vue
316 lines
12 KiB
Vue
<template>
|
|
<div>
|
|
<div class="columns is-multiline">
|
|
<div class="column is-12 is-clearfix is-unselectable">
|
|
<span class="title is-4">
|
|
<span class="icon"><i class="fas fa-list-check"></i></span>
|
|
Legacy Events
|
|
</span>
|
|
<div class="is-pulled-right">
|
|
<div class="field is-grouped">
|
|
<p class="control">
|
|
<button class="button is-info" @click.prevent="loadContent">
|
|
<span class="icon"><i class="fas fa-sync"></i></span>
|
|
</button>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="is-hidden-mobile">
|
|
<span class="subtitle">
|
|
This page will show events that are queued to be handled or sent to the backends.
|
|
This endpoint is being deprecated and will be removed in the future, We are migrating to the new
|
|
<code>events</code> endpoint.
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-12" v-if="queue.length < 1 && progress.length < 1">
|
|
<Message v-if="isLoading" message_class="has-background-info-90 has-text-dark" title="Loading"
|
|
icon="fas fa-spinner fa-spin" message="Loading data. Please wait..."/>
|
|
<Message v-else message_class="is-background-success-90 has-text-dark" title="Information"
|
|
icon="fas fa-info-circle"
|
|
message="There are currently no queued events."/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="columns is-multiline" v-if="queue.length > 0">
|
|
<div class="column is-12">
|
|
<span class="title is-5">
|
|
<span class="icon"><i class="fas fa-eye"></i></span>
|
|
State events
|
|
</span>
|
|
<div class="subtitle is-hidden-mobile">
|
|
Events that are changing the play state. Consumed by <code>state:push</code> task.
|
|
</div>
|
|
</div>
|
|
<div class="column is-4 is-6-tablet" v-for="i in queue" :key="`queue-${i.key}`">
|
|
<div class="card" :class="{ 'is-success': i.item.watched }">
|
|
<header class="card-header">
|
|
<p class="card-header-title is-text-overflow pr-1">
|
|
<span class="icon">
|
|
<i class="fas" :class="{'fa-eye-slash': !i.item.watched,'fa-eye': i.item.watched}"></i>
|
|
</span>
|
|
<NuxtLink :to="'/history/'+i.item.id" v-text="makeName(i.item)"/>
|
|
</p>
|
|
<span class="card-header-icon">
|
|
<button class="button is-danger is-small" @click="deleteItem(i.item, 'queue', i.key)">
|
|
<span class="icon"><i class="fas fa-trash"></i></span>
|
|
</button>
|
|
</span>
|
|
</header>
|
|
<div class="card-content">
|
|
<div class="columns is-multiline is-mobile has-text-centered">
|
|
<div class="column is-12 has-text-left" v-if="i.item?.content_title">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-heading"></i> </span>
|
|
<NuxtLink :to="makeSearchLink('subtitle',i.item.content_title)" v-text="i.item.content_title"/>
|
|
</div>
|
|
</div>
|
|
<div class="column is-12 has-text-left" v-if="i.item?.content_path">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-file"></i> </span>
|
|
<NuxtLink :to="makeSearchLink('path',i.item.content_path)" v-text="i.item.content_path"/>
|
|
</div>
|
|
</div>
|
|
<div class="column is-12 has-text-left" v-if="i.item?.progress">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-bars-progress"></i></span>
|
|
{{ formatDuration(i.item.progress) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer has-text-centered">
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-calendar"></i> </span>
|
|
<span class="has-tooltip"
|
|
v-tooltip="`${getMoment(ag(i.item.extra, `${i.item.via}.received_at`, i.item.updated_at)).format(TOOLTIP_DATE_FORMAT)}`">
|
|
{{ getMoment(ag(i.item.extra, `${i.item.via}.received_at`, i.item.updated_at)).fromNow() }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-server"></i> </span>
|
|
<NuxtLink :to="'/backend/'+i.item.via" v-text="i.item.via"/>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-envelope"></i> </span>
|
|
<span>{{ i.item.event ?? '-' }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="columns is-multiline" v-if="progress.length > 0">
|
|
<div class="column is-12">
|
|
<span class="title is-5">
|
|
<span class="icon"><i class="fas fa-bars-progress"></i></span>
|
|
Watch progress events
|
|
</span>
|
|
<div class="subtitle is-hidden-mobile">
|
|
Events that are changing the play progress. Consumed by <code>state:progress</code> task.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-4 is-6-tablet" v-for="i in progress" :key="`progress-${i.key}`">
|
|
<div class="card" :class="{ 'is-success': i.item.watched }">
|
|
<header class="card-header">
|
|
<p class="card-header-title is-text-overflow pr-1">
|
|
<span class="icon">
|
|
<i class="fas" :class="{'fa-eye-slash': !i.item.watched,'fa-eye': i.item.watched}"></i>
|
|
</span>
|
|
<NuxtLink :to="'/history/'+i.item.id" v-text="makeName(i.item)"/>
|
|
</p>
|
|
<span class="card-header-icon">
|
|
<button class="button is-danger is-small" @click="deleteItem(i.item, 'progress', i.key)">
|
|
<span class="icon"><i class="fas fa-trash"></i></span>
|
|
</button>
|
|
</span>
|
|
</header>
|
|
<div class="card-content">
|
|
<div class="columns is-multiline is-mobile has-text-centered">
|
|
<div class="column is-12 has-text-left" v-if="i.item?.content_title">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-heading"></i> </span>
|
|
<NuxtLink :to="makeSearchLink('subtitle',i.item.content_title)" v-text="i.item.content_title"/>
|
|
</div>
|
|
</div>
|
|
<div class="column is-12 has-text-left" v-if="i.item?.content_path">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-file"></i> </span>
|
|
<NuxtLink :to="makeSearchLink('path',i.item.content_path)" v-text="i.item.content_path"/>
|
|
</div>
|
|
</div>
|
|
<div class="column is-6 has-text-left">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-info-circle"></i></span>
|
|
is Tainted: {{ i.item?.isTainted ? 'Yes' : 'No' }}
|
|
</div>
|
|
</div>
|
|
<div class="column is-6 has-text-right" v-if="i.item?.progress">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-bars-progress"></i></span>
|
|
{{ formatDuration(i.item.progress) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer has-text-centered">
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-calendar"></i> </span>
|
|
<span class="has-tooltip"
|
|
v-tooltip="`${getMoment(ag(i.item.extra, `${i.item.via}.received_at`, i.item.updated_at)).format(TOOLTIP_DATE_FORMAT)}`">
|
|
{{ getMoment(ag(i.item.extra, `${i.item.via}.received_at`, i.item.updated_at)).fromNow() }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-server"></i> </span>
|
|
<NuxtLink :to="'/backend/'+i.item.via" v-text="i.item.via"/>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer-item">
|
|
<div class="is-text-overflow">
|
|
<span class="icon"><i class="fas fa-envelope"></i> </span>
|
|
<span>{{ i.item.event ?? '-' }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="columns is-multiline">
|
|
<div class="column is-12">
|
|
<Message message_class="has-background-info-90 has-text-dark" :toggle="show_page_tips"
|
|
@toggle="show_page_tips = !show_page_tips" :use-toggle="true" title="Tips" icon="fas fa-info-circle">
|
|
<ul>
|
|
<li>
|
|
Events marked with <code>is Tainted: Yes</code>, are interesting but are too chaotic to be useful be used
|
|
to
|
|
determine play state. However, we do use them to update local metadata & play progress.
|
|
</li>
|
|
<li>
|
|
Events marked with <code>is Tainted: No</code>, are events that are used to determine play state.
|
|
</li>
|
|
<li>
|
|
If you are fast enough, you might be able to see the event before it is consumed by the backend. which
|
|
allow
|
|
you to delete it from the queue if you desire.
|
|
</li>
|
|
</ul>
|
|
</Message>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import request from '~/utils/request'
|
|
import moment from 'moment'
|
|
import Message from '~/components/Message'
|
|
import {ag, formatDuration, makeName, makeSearchLink, notification, TOOLTIP_DATE_FORMAT} from '~/utils/index'
|
|
import {useStorage} from '@vueuse/core'
|
|
|
|
useHead({title: 'Queue'})
|
|
|
|
const queue = ref([])
|
|
const progress = ref([])
|
|
const isLoading = ref(false)
|
|
const show_page_tips = useStorage('show_page_tips', true)
|
|
|
|
const loadContent = async () => {
|
|
try {
|
|
isLoading.value = true
|
|
queue.value = []
|
|
progress.value = []
|
|
|
|
const response = await request(`/system/old_events`)
|
|
let json
|
|
|
|
try {
|
|
json = await response.json()
|
|
if (useRoute().name !== 'events') {
|
|
return
|
|
}
|
|
} catch (e) {
|
|
json = {
|
|
error: {
|
|
code: response.status,
|
|
message: response.statusText
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!response.ok) {
|
|
notification('error', 'Error', `${json.error.code}: ${json.error.message}`)
|
|
return
|
|
}
|
|
|
|
queue.value = json?.queue
|
|
progress.value = json?.progress
|
|
} catch (e) {
|
|
return notification('error', 'Error', e.message)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
const deleteItem = async (item, type, key) => {
|
|
if (!confirm(`Remove '${makeName(item)}' from the '${type}' list?`)) {
|
|
return
|
|
}
|
|
|
|
try {
|
|
const response = await request(`/system/old_events/0`, {
|
|
method: 'DELETE',
|
|
body: JSON.stringify({type: type, id: key})
|
|
})
|
|
|
|
if (200 !== response.status) {
|
|
let json
|
|
|
|
try {
|
|
json = await response.json()
|
|
} catch (e) {
|
|
json = {
|
|
error: {
|
|
code: response.status,
|
|
message: response.statusText
|
|
}
|
|
}
|
|
}
|
|
|
|
notification('error', 'Error', `${json.error.code}: ${json.error.message}`)
|
|
return
|
|
}
|
|
|
|
notification('success', 'Success', 'Item successfully deleted from queue.')
|
|
|
|
switch (type) {
|
|
case 'queue':
|
|
queue.value = queue.value.filter(i => i.key !== key)
|
|
break
|
|
case 'progress':
|
|
progress.value = progress.value.filter(i => i.key !== key)
|
|
break
|
|
}
|
|
|
|
} catch (e) {
|
|
return notification('error', 'Error', e.message)
|
|
}
|
|
}
|
|
const getMoment = (time) => time.toString().length < 13 ? moment.unix(time) : moment(time)
|
|
|
|
onMounted(async () => loadContent())
|
|
</script>
|