- image-gen, text-gen: books list streamed (listBooks is expensive on cold cache) - ai-jobs: jobs list streamed; add 30s cache to listAIJobs (was uncached listAll) - changelog: Gitea releases streamed on cold cache; cached path stays synchronous - admin/+layout.svelte: remove duplicate audio/translation/image-gen nav links
65 lines
2.4 KiB
Svelte
65 lines
2.4 KiB
Svelte
<script lang="ts">
|
|
import type { PageData } from './$types';
|
|
import * as m from '$lib/paraglide/messages.js';
|
|
|
|
let { data }: { data: PageData } = $props();
|
|
|
|
function fmtDate(s: string) {
|
|
return new Date(s).toLocaleDateString(undefined, {
|
|
year: 'numeric', month: 'short', day: 'numeric'
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>{m.admin_changelog_page_title()}</title>
|
|
</svelte:head>
|
|
|
|
<div class="space-y-6 max-w-2xl">
|
|
<div class="flex items-center gap-3">
|
|
<h1 class="text-xl font-semibold text-(--color-text) flex-1">{m.admin_changelog_heading()}</h1>
|
|
<a
|
|
href="https://gitea.kalekber.cc/kamil/libnovel/releases"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="text-xs text-(--color-muted) hover:text-(--color-text) transition-colors flex items-center gap-1"
|
|
>
|
|
{m.admin_changelog_gitea()}
|
|
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
|
|
{#await data.releases}
|
|
<p class="text-sm text-(--color-muted) py-8 text-center">Loading releases…</p>
|
|
{:then releases}
|
|
{#if releases.length === 0}
|
|
<p class="text-sm text-(--color-muted) py-8 text-center">{m.admin_changelog_no_releases()}</p>
|
|
{:else}
|
|
<div class="space-y-0 divide-y divide-(--color-border) border border-(--color-border) rounded-xl overflow-hidden">
|
|
{#each releases as release}
|
|
<div class="px-5 py-4 bg-(--color-surface) space-y-2">
|
|
<div class="flex items-baseline gap-3 flex-wrap">
|
|
<span class="font-mono text-sm font-semibold text-(--color-brand)">{release.tag_name}</span>
|
|
{#if release.name && release.name !== release.tag_name}
|
|
<span class="text-sm text-(--color-text)">{release.name}</span>
|
|
{/if}
|
|
{#if release.prerelease}
|
|
<span class="text-xs px-1.5 py-0.5 rounded bg-(--color-surface-3) text-(--color-muted)">pre-release</span>
|
|
{/if}
|
|
<span class="text-xs text-(--color-muted) ml-auto">{fmtDate(release.published_at)}</span>
|
|
</div>
|
|
{#if release.body.trim()}
|
|
<p class="text-sm text-(--color-muted) leading-relaxed whitespace-pre-wrap">{release.body.trim()}</p>
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
{:catch}
|
|
<p class="text-sm text-(--color-danger)">{m.admin_changelog_load_error({ error: 'Failed to load releases' })}</p>
|
|
{/await}
|
|
</div>
|