App Nuxt 3 + Nuxt UI qui lit les projets du CMS Grav et compose des portfolios A3 paysage exportés en PDF (gabarit book_v3) : composeur WYSIWYG, templates cover/toc/projet/grille/page libre, pipeline Playwright + Ghostscript, gel du contenu à la génération, partage public opt-in. Dépôt autonome : Dockerfile (base Playwright + Ghostscript + ffmpeg + rsync) inclus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
67 lines
2.0 KiB
Vue
67 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
const route = useRoute()
|
|
const toast = useToast()
|
|
const syncing = ref(false)
|
|
|
|
async function refreshContent() {
|
|
syncing.value = true
|
|
try {
|
|
const result = await $fetch<{ ok: boolean, summary: string }>('/api/sync', {
|
|
method: 'POST',
|
|
timeout: 900_000,
|
|
})
|
|
toast.add({
|
|
title: result.ok ? 'Contenu rafraîchi' : 'Synchronisation en échec',
|
|
description: result.summary,
|
|
color: result.ok ? 'success' : 'error',
|
|
})
|
|
if (result.ok) await refreshNuxtData()
|
|
} catch {
|
|
toast.add({ title: 'Échec de la synchronisation', color: 'error' })
|
|
} finally {
|
|
syncing.value = false
|
|
}
|
|
}
|
|
|
|
async function logout() {
|
|
await $fetch('/api/auth/logout', { method: 'POST' })
|
|
navigateTo('/login')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-screen bg-[var(--fl-base)] dark:bg-neutral-950">
|
|
<header
|
|
v-if="route.path !== '/login'"
|
|
class="sticky top-0 z-40 border-b border-neutral-200 bg-white/90 backdrop-blur dark:border-neutral-800 dark:bg-neutral-900/90"
|
|
>
|
|
<UContainer class="flex h-14 items-center gap-6">
|
|
<NuxtLink to="/" class="flex items-center gap-2 font-bold text-[var(--fl-ink)] dark:text-white">
|
|
<span class="flex size-7 items-center justify-center rounded-full bg-[var(--fl-ink)] text-xs text-white">FL</span>
|
|
Portfolios
|
|
</NuxtLink>
|
|
<div class="ml-auto flex items-center gap-1">
|
|
<UTooltip text="Actualise les données depuis Grav">
|
|
<UButton
|
|
icon="i-lucide-refresh-cw"
|
|
label="Rafraîchir"
|
|
variant="ghost"
|
|
color="neutral"
|
|
:loading="syncing"
|
|
@click="refreshContent"
|
|
/>
|
|
</UTooltip>
|
|
<UButton
|
|
icon="i-lucide-log-out"
|
|
variant="ghost"
|
|
color="neutral"
|
|
aria-label="Se déconnecter"
|
|
@click="logout"
|
|
/>
|
|
</div>
|
|
</UContainer>
|
|
</header>
|
|
<slot />
|
|
</div>
|
|
</template>
|