Files
FabledCurator/frontend/src/components/settings/DownloadsActivityPanel.vue
T
bvandeusen a2d1ed935d
CI / lint (push) Successful in 3s
CI / frontend-build (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 35s
CI / integration (push) Successful in 3m57s
refactor(ui): DRY the settings-card CSS tokens + fix unstyled headers (#161)
- Promote .fc-section-h to a global token (app.css). It was copied identically
  into 4 cards, and TranslationCard used the class with NO local def — so its
  section headers rendered unstyled. Now fixed everywhere.
- Promote .fc-good / .fc-weak status colours to globals; delete the local copies
  in the GPU/heads cards. (.fc-ok stays local — divergent: on-surface in
  HeadsCard vs success in QueuesTable. .fc-bad stays — different name.)
- Delete 10 identical local .fc-muted redefinitions that crept back after the
  2026-06-09 sweep; the global utility already covers them.
- DbMaintenanceCard: opacity:0.6 muted text → the .fc-muted token (the exact
  anti-pattern that token's comment forbids).
- HeadsCard: collapse byte-identical ratePct() into pct().

CSS-only + one template class swap; no logic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NsmJSQxnNxGgtM5Yz4GAqi
2026-07-13 21:51:23 -04:00

77 lines
2.3 KiB
Vue

<template>
<v-card class="mb-4">
<CardHeading icon="mdi-download" title="Downloads (last 24h)">
<v-spacer />
<v-btn
variant="text" size="small" rounded="pill"
to="/subscriptions?tab=downloads"
>
Open subscriptions
<v-icon end size="small">mdi-arrow-right</v-icon>
</v-btn>
</CardHeading>
<v-card-text>
<div class="d-flex align-center flex-wrap mb-2" style="gap: 8px">
<v-chip size="small" variant="tonal" color="success">
{{ stats.ok }} ok
</v-chip>
<v-chip
size="small" variant="tonal"
:color="stats.error ? 'error' : undefined"
>
{{ stats.error }} failed
</v-chip>
<v-chip v-if="stats.running" size="small" variant="tonal" color="accent">
{{ stats.running }} running
</v-chip>
<v-chip v-if="stats.pending" size="small" variant="tonal">
{{ stats.pending }} pending
</v-chip>
<v-chip v-if="stats.skipped" size="small" variant="tonal">
{{ stats.skipped }} skipped
</v-chip>
</div>
<p v-if="!failing.length" class="fc-muted text-body-2 mb-0">
All subscription sources healthy.
</p>
<p v-else class="text-body-2 mb-0">
<b class="fc-bad">{{ failing.length }}</b> failing source(s):
<span class="fc-muted">{{ failingNames }}</span>
</p>
</v-card-text>
</v-card>
</template>
<script setup>
import { computed, onMounted, onUnmounted } from 'vue'
import { storeToRefs } from 'pinia'
import CardHeading from '../common/CardHeading.vue'
import { useDownloadsStore } from '../../stores/downloads.js'
const store = useDownloadsStore()
const { stats, failing } = storeToRefs(store)
let pollId = null
const failingNames = computed(() => {
const names = failing.value.map((s) => s.artist_name || s.url).slice(0, 3)
const extra = failing.value.length - names.length
return names.join(', ') + (extra > 0 ? ` +${extra} more` : '')
})
function poll() {
store.loadStats(24)
store.loadFailing()
}
onMounted(() => {
poll()
pollId = setInterval(() => { if (!document.hidden) poll() }, 30000)
})
onUnmounted(() => { if (pollId) clearInterval(pollId) })
</script>
<style scoped>
.fc-bad { color: rgb(var(--v-theme-error)); }
</style>