Add section/subsection picker to editor with wikiref injection
This commit is contained in:
@@ -1,7 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
const SECTIONS = [
|
||||||
|
{ label: 'BincioTech', slug: 'bincio-tech', sub: [
|
||||||
|
{ label: 'Gear e accessori', slug: 'gear-accessori' },
|
||||||
|
{ label: 'Componenti e upgrade', slug: 'componenti-upgrade' },
|
||||||
|
{ label: 'Tecnologia e elettronica', slug: 'tecnologia' },
|
||||||
|
]},
|
||||||
|
{ label: 'BincioOfficina', slug: 'bincio-officina', sub: [
|
||||||
|
{ label: 'Manutenzione', slug: 'manutenzione' },
|
||||||
|
{ label: 'Riparazioni', slug: 'riparazioni' },
|
||||||
|
{ label: 'Fai da te', slug: 'fai-da-te' },
|
||||||
|
]},
|
||||||
|
{ label: 'BincioTour', slug: 'bincio-tour', sub: [
|
||||||
|
{ label: 'Tour report', slug: 'tour-report' },
|
||||||
|
{ label: 'Bike packing', slug: 'bike-packing' },
|
||||||
|
{ label: 'Rotte e itinerari', slug: 'rotte-itinerari' },
|
||||||
|
{ label: 'Logistica', slug: 'logistica' },
|
||||||
|
]},
|
||||||
|
{ label: 'BincioCorsa', slug: 'bincio-corsa', sub: [
|
||||||
|
{ label: 'Allenamento', slug: 'allenamento' },
|
||||||
|
{ label: 'Gare e competizioni', slug: 'gare' },
|
||||||
|
{ label: 'Performance', slug: 'performance' },
|
||||||
|
]},
|
||||||
|
{ label: 'BincioAbbigliamento', slug: 'bincio-abbigliamento', sub: [
|
||||||
|
{ label: 'Abbigliamento tecnico', slug: 'tecnico' },
|
||||||
|
{ label: 'Comfort e protezione', slug: 'comfort' },
|
||||||
|
{ label: 'Stagionalità', slug: 'stagionalita' },
|
||||||
|
]},
|
||||||
|
];
|
||||||
|
|
||||||
let open = false;
|
let open = false;
|
||||||
let isNew = false;
|
let isNew = false;
|
||||||
let slug = '';
|
let slug = ''; // used for existing pages
|
||||||
|
let baseName = ''; // page name part for new pages
|
||||||
|
let selectedSection = '';
|
||||||
|
let selectedSub = '';
|
||||||
let content = '';
|
let content = '';
|
||||||
let apiBase = '/pages';
|
let apiBase = '/pages';
|
||||||
let saving = false;
|
let saving = false;
|
||||||
@@ -13,9 +45,16 @@
|
|||||||
let dragOver = false;
|
let dragOver = false;
|
||||||
let fileInput: HTMLInputElement;
|
let fileInput: HTMLInputElement;
|
||||||
|
|
||||||
|
$: section = SECTIONS.find(s => s.slug === selectedSection) ?? null;
|
||||||
|
$: subs = section?.sub ?? [];
|
||||||
|
$: fullSlug = [selectedSection, selectedSub, baseName].filter(Boolean).join('/');
|
||||||
|
|
||||||
function reset(detail: { slug?: string; apiBase?: string }) {
|
function reset(detail: { slug?: string; apiBase?: string }) {
|
||||||
apiBase = detail.apiBase ?? '/pages';
|
apiBase = detail.apiBase ?? '/pages';
|
||||||
slug = detail.slug ?? '';
|
slug = detail.slug ?? '';
|
||||||
|
baseName = '';
|
||||||
|
selectedSection = '';
|
||||||
|
selectedSub = '';
|
||||||
content = '';
|
content = '';
|
||||||
isNew = !slug;
|
isNew = !slug;
|
||||||
saving = false;
|
saving = false;
|
||||||
@@ -25,6 +64,23 @@
|
|||||||
errorMsg = '';
|
errorMsg = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onSectionChange() {
|
||||||
|
selectedSub = '';
|
||||||
|
applyWikiref();
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyWikiref() {
|
||||||
|
const newRef = section ? `[[${section.label}]]` : '';
|
||||||
|
const existing = /\[\[Bincio[A-Za-z]+\]\]/;
|
||||||
|
if (existing.test(content)) {
|
||||||
|
content = newRef
|
||||||
|
? content.replace(existing, newRef)
|
||||||
|
: content.replace(new RegExp(`\\s*\\[\\[Bincio[A-Za-z]+\\]\\]\\n?`), '');
|
||||||
|
} else if (newRef) {
|
||||||
|
content = content.trimEnd() + '\n\n' + newRef + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadContent() {
|
async function loadContent() {
|
||||||
if (!slug) return;
|
if (!slug) return;
|
||||||
try {
|
try {
|
||||||
@@ -39,9 +95,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
const s = slug.trim().toLowerCase().replace(/\s+/g, '-');
|
const s = (isNew ? fullSlug : slug).trim().toLowerCase().replace(/\s+/g, '-');
|
||||||
if (!s) { errorMsg = 'Nome richiesto'; return; }
|
if (!s) { errorMsg = 'Nome richiesto'; return; }
|
||||||
slug = s;
|
if (isNew) baseName = baseName.trim().toLowerCase().replace(/\s+/g, '-');
|
||||||
|
else slug = s;
|
||||||
saving = true;
|
saving = true;
|
||||||
errorMsg = '';
|
errorMsg = '';
|
||||||
try {
|
try {
|
||||||
@@ -131,12 +188,43 @@
|
|||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
>
|
>
|
||||||
<!-- Header bar -->
|
<!-- Header bar -->
|
||||||
<div class="flex items-center gap-3 px-4 h-12 border-b shrink-0" style="border-color: var(--border)">
|
<div class="flex items-center gap-2 px-4 h-12 border-b shrink-0" style="border-color: var(--border)">
|
||||||
{#if isNew}
|
{#if isNew}
|
||||||
|
<!-- Section picker -->
|
||||||
|
<select
|
||||||
|
bind:value={selectedSection}
|
||||||
|
on:change={onSectionChange}
|
||||||
|
class="bg-transparent text-xs outline-none cursor-pointer shrink-0"
|
||||||
|
style="color: var(--text-4)"
|
||||||
|
>
|
||||||
|
<option value="">— sezione —</option>
|
||||||
|
{#each SECTIONS as s}
|
||||||
|
<option value={s.slug}>{s.label}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
{#if subs.length}
|
||||||
|
<span class="text-zinc-600 shrink-0">/</span>
|
||||||
|
<select
|
||||||
|
bind:value={selectedSub}
|
||||||
|
class="bg-transparent text-xs outline-none cursor-pointer shrink-0"
|
||||||
|
style="color: var(--text-4)"
|
||||||
|
>
|
||||||
|
<option value="">— sottosezione —</option>
|
||||||
|
{#each subs as sub}
|
||||||
|
<option value={sub.slug}>{sub.label}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if selectedSection}
|
||||||
|
<span class="text-zinc-600 shrink-0">/</span>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={slug}
|
bind:value={baseName}
|
||||||
placeholder="nome-pagina o cartella/nome"
|
placeholder="nome-pagina"
|
||||||
class="bg-transparent text-sm font-mono outline-none flex-1 min-w-0"
|
class="bg-transparent text-sm font-mono outline-none flex-1 min-w-0"
|
||||||
style="color: var(--text-2)"
|
style="color: var(--text-2)"
|
||||||
autofocus
|
autofocus
|
||||||
|
|||||||
Reference in New Issue
Block a user