feat(frontend): redesign settings/common with Aurora cassettes
Splits the monolithic settings page into 6 focused glass components matching
the polish of the recently redesigned settings/backup page.
- SettingsHero: PageHeader with 4 live status pills (URL host, timezone +
ticking clock, locale codes, log severity tinted by level)
- IdentityCassette: groups External URL + Timezone + Locales as numbered
rows; URL field gains copy + open chips and a mint border when valid
- TelegramCassette: webhook secret with show/hide toggle and verified
status chip; cache TTL/max as oversized mono numerals with humanized
previews ("720 hrs -> 30d")
- CacheLedger: mirrors BackupLedger -- big total, gradient capacity meter,
tone-edged URL/Asset bucket rows colored by oldest entry age
- LoggingCassette: per-module overrides become tone-edged chips with
severity-colored level borders; raw-text fallback behind toggle; live
ACTIVE preview line
- SaveBar: sticky dirty-aware footer with citrus pulse, italic message,
and Discard/Save (only renders when settings differ from baseline)
No backend changes -- same /settings and /settings/telegram-cache/* endpoints.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { t } from '$lib/i18n';
|
||||
import PageHeader, { type HeaderPill } from '$lib/components/PageHeader.svelte';
|
||||
|
||||
type Tone = 'mint' | 'sky' | 'orchid' | 'coral' | 'citrus' | 'primary';
|
||||
|
||||
interface Settings {
|
||||
external_url: string;
|
||||
timezone: string;
|
||||
supported_locales: string;
|
||||
log_level: string;
|
||||
log_format: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
settings: Settings;
|
||||
}
|
||||
|
||||
let { settings }: Props = $props();
|
||||
|
||||
// Live tick so the timezone pill shows the current local HH:MM.
|
||||
let now = $state(new Date());
|
||||
let tick: ReturnType<typeof setInterval> | null = null;
|
||||
onMount(() => { tick = setInterval(() => { now = new Date(); }, 30_000); });
|
||||
onDestroy(() => { if (tick) clearInterval(tick); });
|
||||
|
||||
function fmtClock(tz: string): string {
|
||||
try {
|
||||
return new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: tz || 'UTC',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
}).format(now);
|
||||
} catch { return '--:--'; }
|
||||
}
|
||||
|
||||
function hostFromUrl(url: string): string {
|
||||
if (!url) return '';
|
||||
try { return new URL(url).host; }
|
||||
catch { return url.replace(/^https?:\/\//, '').replace(/\/$/, ''); }
|
||||
}
|
||||
|
||||
function localeCount(csv: string): number {
|
||||
if (!csv) return 0;
|
||||
return csv.split(',').map(s => s.trim()).filter(Boolean).length;
|
||||
}
|
||||
|
||||
const SEVERITY_TONE: Record<string, Tone> = {
|
||||
DEBUG: 'sky',
|
||||
INFO: 'mint',
|
||||
WARNING: 'citrus',
|
||||
ERROR: 'coral',
|
||||
};
|
||||
|
||||
const pills = $derived.by<HeaderPill[]>(() => {
|
||||
const out: HeaderPill[] = [];
|
||||
|
||||
const host = hostFromUrl(settings.external_url);
|
||||
out.push(host
|
||||
? { label: host, tone: 'sky' }
|
||||
: { label: t('settings.heroNoUrl') }
|
||||
);
|
||||
|
||||
const tz = settings.timezone || 'UTC';
|
||||
out.push({ label: `${tz} · ${fmtClock(tz)}`, tone: 'primary' });
|
||||
|
||||
const locales = settings.supported_locales || '';
|
||||
const count = localeCount(locales);
|
||||
out.push({
|
||||
label: count > 0
|
||||
? locales.split(',').map(s => s.trim()).filter(Boolean).map(s => s.toUpperCase()).join(' · ')
|
||||
: t('settings.heroNoLocales'),
|
||||
tone: 'orchid',
|
||||
});
|
||||
|
||||
const lvl = (settings.log_level || 'INFO').toUpperCase();
|
||||
out.push({
|
||||
label: `${lvl} · ${settings.log_format || 'text'}`,
|
||||
tone: SEVERITY_TONE[lvl] ?? 'mint',
|
||||
});
|
||||
|
||||
return out;
|
||||
});
|
||||
</script>
|
||||
|
||||
<PageHeader
|
||||
title={t('settings.title')}
|
||||
emphasis={t('settings.titleEmphasis')}
|
||||
description={t('settings.description')}
|
||||
crumb={t('crumbs.systemConfiguration')}
|
||||
{pills}
|
||||
/>
|
||||
Reference in New Issue
Block a user