Add release notes and build version metadata
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { BookOpenText, CheckCircle2, History, Info, Rocket, ShieldCheck, Sparkles, Tag } from '@lucide/vue'
|
||||
|
||||
import { buildDateLabel, buildVersion, releaseNotes, semanticVersion, versionRules, type ReleaseChangeType } from '../../lib/releaseNotes'
|
||||
import Button from '../ui/Button.vue'
|
||||
import Card from '../ui/Card.vue'
|
||||
import Modal from '../ui/Modal.vue'
|
||||
|
||||
const changelogOpen = ref(false)
|
||||
|
||||
const featureCount = computed(() => releaseNotes.filter((note) => note.type === 'feature').length)
|
||||
const fixCount = computed(() => releaseNotes.filter((note) => note.type === 'fix').length)
|
||||
|
||||
function changeTypeLabel(type: ReleaseChangeType) {
|
||||
if (type === 'major') return 'Major'
|
||||
if (type === 'feature') return 'Feature'
|
||||
return 'Fix'
|
||||
}
|
||||
|
||||
function changeTypeClasses(type: ReleaseChangeType) {
|
||||
if (type === 'major') {
|
||||
return {
|
||||
badge: 'bg-rose-50 text-rose-700',
|
||||
icon: 'bg-rose-100 text-rose-700',
|
||||
panel: 'border-rose-100 bg-rose-50/45',
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'feature') {
|
||||
return {
|
||||
badge: 'bg-violet-50 text-violet-700',
|
||||
icon: 'bg-violet-100 text-violet-700',
|
||||
panel: 'border-violet-100 bg-violet-50/50',
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
badge: 'bg-emerald-50 text-emerald-700',
|
||||
icon: 'bg-emerald-100 text-emerald-700',
|
||||
panel: 'border-emerald-100 bg-emerald-50/45',
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="overflow-hidden">
|
||||
<div class="border-b border-violet-100 bg-gradient-to-br from-white via-violet-50/70 to-emerald-50/55 p-6">
|
||||
<div class="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="grid h-12 w-12 shrink-0 place-items-center rounded-2xl bg-violet-100 text-violet-700">
|
||||
<Rocket class="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.24em] text-violet-500">Build Version</p>
|
||||
<h2 class="mt-1 text-xl font-bold text-slate-900">Version {{ buildVersion }}</h2>
|
||||
<p class="mt-2 max-w-3xl text-sm leading-6 text-slate-500">
|
||||
Feature-Release vom {{ buildDateLabel }} mit Twitch Login, Team-Verknuepfung, Admin-UX-Polish und Backend-Haertung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button type="button" variant="ghost" class="gap-2 rounded-2xl px-5" @click="changelogOpen = true">
|
||||
<BookOpenText class="h-4 w-4" />
|
||||
Changelog ansehen
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-3 p-5 md:grid-cols-3">
|
||||
<div class="rounded-2xl border border-violet-100 bg-violet-50/55 px-4 py-3">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">Release-Typ</p>
|
||||
<strong class="mt-1 block text-lg text-violet-700">Feature</strong>
|
||||
<p class="mt-1 text-xs leading-5 text-slate-600">Nach deiner Regel: 0.x.0.</p>
|
||||
</div>
|
||||
<div class="rounded-2xl border border-emerald-100 bg-emerald-50/55 px-4 py-3">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">Neue Features</p>
|
||||
<strong class="mt-1 block text-lg text-emerald-700">{{ featureCount }}</strong>
|
||||
<p class="mt-1 text-xs leading-5 text-slate-600">Sichtbare neue Funktionen und bessere Workflows.</p>
|
||||
</div>
|
||||
<div class="rounded-2xl border border-amber-100 bg-amber-50/65 px-4 py-3">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">Fixes & Polish</p>
|
||||
<strong class="mt-1 block text-lg text-amber-700">{{ fixCount }}</strong>
|
||||
<p class="mt-1 text-xs leading-5 text-slate-600">Stabilitaet, UI-Feedback und Backend-Hygiene.</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Modal
|
||||
:open="changelogOpen"
|
||||
title="Changelog"
|
||||
:subtitle="`Build ${buildVersion} · ${buildDateLabel}`"
|
||||
size="lg"
|
||||
@close="changelogOpen = false"
|
||||
>
|
||||
<div class="space-y-6">
|
||||
<section>
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag class="h-4 w-4 text-violet-600" />
|
||||
<h3 class="text-sm font-bold text-slate-900">Versionsschema</h3>
|
||||
</div>
|
||||
<div class="mt-3 grid gap-3 md:grid-cols-3">
|
||||
<div
|
||||
v-for="rule in versionRules"
|
||||
:key="rule.pattern"
|
||||
class="rounded-2xl border border-violet-100 bg-white px-4 py-3"
|
||||
>
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.18em] text-violet-500">{{ rule.pattern }}</p>
|
||||
<strong class="mt-1 block text-sm text-slate-900">{{ rule.label }}</strong>
|
||||
<p class="mt-1 text-xs leading-5 text-slate-500">{{ rule.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="flex items-center gap-2">
|
||||
<History class="h-4 w-4 text-violet-600" />
|
||||
<h3 class="text-sm font-bold text-slate-900">Was neu ist</h3>
|
||||
</div>
|
||||
<div class="mt-3 space-y-3">
|
||||
<article
|
||||
v-for="note in releaseNotes"
|
||||
:key="note.title"
|
||||
class="rounded-2xl border p-4"
|
||||
:class="changeTypeClasses(note.type).panel"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="grid h-9 w-9 shrink-0 place-items-center rounded-xl" :class="changeTypeClasses(note.type).icon">
|
||||
<Sparkles v-if="note.type === 'feature'" class="h-4 w-4" />
|
||||
<ShieldCheck v-else-if="note.type === 'major'" class="h-4 w-4" />
|
||||
<CheckCircle2 v-else class="h-4 w-4" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<h4 class="text-sm font-bold text-slate-900">{{ note.title }}</h4>
|
||||
<span class="rounded-full px-2.5 py-1 text-[11px] font-semibold" :class="changeTypeClasses(note.type).badge">
|
||||
{{ changeTypeLabel(note.type) }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="mt-1 text-sm leading-6 text-slate-600">{{ note.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="flex items-start gap-3 rounded-2xl border border-violet-100 bg-violet-50/60 px-4 py-3 text-sm leading-6 text-violet-900">
|
||||
<Info class="mt-0.5 h-4 w-4 shrink-0" />
|
||||
<p>Diese Version ist als <strong>{{ semanticVersion }}</strong> gesetzt, weil der Schwerpunkt auf neuen Features und groesseren UX-Verbesserungen liegt. Die Pipeline darf Build-Metadaten ergaenzen, aber nicht selbst Major, Feature oder Fix entscheiden.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<Button type="button" variant="ghost" @click="changelogOpen = false">Schließen</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
@@ -0,0 +1,88 @@
|
||||
export type ReleaseChangeType = 'major' | 'feature' | 'fix'
|
||||
|
||||
export interface ReleaseNoteItem {
|
||||
type: ReleaseChangeType
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface VersionRule {
|
||||
pattern: string
|
||||
label: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export const semanticVersion = '0.1.0'
|
||||
export const buildVersion = import.meta.env.VITE_BUILD_VERSION?.trim() || semanticVersion
|
||||
export const buildDateLabel = import.meta.env.VITE_BUILD_DATE?.trim() || '26.06.2026'
|
||||
|
||||
export const versionRules: VersionRule[] = [
|
||||
{
|
||||
pattern: 'x.0.0',
|
||||
label: 'Major Changes',
|
||||
description: 'Grosse Umbauten, Breaking Changes oder Releases, die sich wie ein neues Kapitel anfuehlen.',
|
||||
},
|
||||
{
|
||||
pattern: '0.x.0',
|
||||
label: 'Neue Features',
|
||||
description: 'Neue Funktionen, groessere UI-Flows oder sichtbare Produktverbesserungen.',
|
||||
},
|
||||
{
|
||||
pattern: '0.0.x',
|
||||
label: 'Minor & Bugfixes',
|
||||
description: 'Kleine Verbesserungen, Bugfixes, Copy-Polish und unkritische Feinschliffe.',
|
||||
},
|
||||
]
|
||||
|
||||
export const releaseNotes: ReleaseNoteItem[] = [
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Twitch Login ist live',
|
||||
description: 'Login und Account-Verknuepfung laufen jetzt ueber den offiziellen Twitch OAuth Flow.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Team-Accounts koennen Twitch verbinden',
|
||||
description: 'Teammitglieder koennen ihren Account mit Twitch verknuepfen, wieder loesen und danach sauber ueber Twitch einsteigen.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Team-Status aktualisiert sich automatisch',
|
||||
description: 'In der Teamverwaltung siehst du regelmaessig, wer online ist. Die Ansicht aktualisiert sich alle 30 Sekunden.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Moderation ist schneller bedienbar',
|
||||
description: 'Reviewed Nominierungen und Risiko-Queues lassen sich angenehmer mit Pfeiltasten und Tastatur bedienen.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Admin-Bereiche wurden aufgeraeumt',
|
||||
description: 'Jahre, Landingpage, Risiko, Team und Analytics sind kompakter, klarer gruppiert und weniger erschlagend.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'User-Profil wurde repariert und ueberarbeitet',
|
||||
description: 'Das Profil ist wieder ein echter Teil des Flows, inklusive Twitch-Verknuepfung und sauberem Account-Status.',
|
||||
},
|
||||
{
|
||||
type: 'feature',
|
||||
title: 'Besseres Feedback beim Bearbeiten',
|
||||
description: 'Buttons haben Animationen, Speichern/Bearbeiten gibt sichtbarere Rueckmeldung und Modals fuehlen sich stabiler an.',
|
||||
},
|
||||
{
|
||||
type: 'fix',
|
||||
title: 'Dropdowns sehen wieder korrekt aus',
|
||||
description: 'Das Dropdown-Design wurde stabilisiert und passt nun besser zum restlichen Admin-UI.',
|
||||
},
|
||||
{
|
||||
type: 'fix',
|
||||
title: 'Backend, Auth und Sicherheit wurden gehaertet',
|
||||
description: 'Sessions, Team-Rechte, Audit-Logs, Public Writes, Vote-Eindeutigkeit und Runtime-Settings wurden robuster gemacht.',
|
||||
},
|
||||
{
|
||||
type: 'fix',
|
||||
title: 'Datenbank- und Deploy-Sicherheit verbessert',
|
||||
description: 'Healthchecks, Migrationen, Seed-Verhalten und produktionsnahe Konfiguration sind klarer sichtbar und weniger fehleranfaellig.',
|
||||
},
|
||||
]
|
||||
@@ -5,6 +5,7 @@ import { onBeforeRouteLeave } from 'vue-router'
|
||||
|
||||
import AdminOperationalSettingsCard from '../../components/admin/AdminOperationalSettingsCard.vue'
|
||||
import AdminPageHeader from '../../components/admin/AdminPageHeader.vue'
|
||||
import AdminReleaseNotesCard from '../../components/admin/AdminReleaseNotesCard.vue'
|
||||
import AdminSeasonToolbar from '../../components/admin/AdminSeasonToolbar.vue'
|
||||
import AdminSettingsDatabaseCard from '../../components/admin/AdminSettingsDatabaseCard.vue'
|
||||
import AdminSettingsOverviewBoard from '../../components/admin/AdminSettingsOverviewBoard.vue'
|
||||
@@ -90,6 +91,8 @@ onBeforeUnmount(() => window.removeEventListener('beforeunload', handleBeforeUnl
|
||||
:content-completion="contentCompletion"
|
||||
/>
|
||||
|
||||
<AdminReleaseNotesCard />
|
||||
|
||||
<AdminOperationalSettingsCard
|
||||
v-model:demo-password="demoPasswordInput"
|
||||
v-model:twitch-client-secret="twitchClientSecretInput"
|
||||
|
||||
Reference in New Issue
Block a user