ia: Umbenennung — Library→Archiv, Wiki→Library (URLs, Content, Code)
Neue Informationsarchitektur: - ARCHIV (/archiv) = die fertigen Texte (vormals Library): Essays mit Byline, Quellen/Zitieren, Dialog, Versionsverlauf. Section "archiv". - LIBRARY (/library) = das verlinkte Werkstattwissen (vormals Wiki): zwei- spaltig mit Gruppen-Navigation + Filter. Section "library". Umgesetzt: - content/ + layouts/ verschoben (git mv), Menü (ARCHIV+LIBRARY, kein WIKI), Startseiten-Journal zieht jetzt Section "archiv", Querverweise umgeschrieben (/library→/archiv, /wiki→/library). - CMS: files.js klassifiziert archiv/<sec>→beitrag, library/→biblio; stats.js + Admin (Typ "Library-Seite", KIND_LABEL, Pfade) nachgezogen. - single.html: Byline/Provenance/Dialog an Section "archiv" gebunden. - Beide Header zentriert (section-header) — einheitlicher Look. - Interne Dialog-Werte (thread.kind='library', Forum "Beiträge") unverändert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+10
-10
@@ -22,7 +22,7 @@ const hexOf = (name) => (COLORS.find((c) => c[0] === name) || [])[2] || 'transpa
|
||||
|
||||
const LAYOUTS = ['', 'text', 'image', 'icon'];
|
||||
const SECTIONS = ['buerofuehrung', 'software', 'theorie'];
|
||||
const KIND_LABEL = { beitrag: 'Beiträge', wiki: 'Wiki', seite: 'Seiten', rubrik: 'Rubriken' };
|
||||
const KIND_LABEL = { beitrag: 'Beiträge', biblio: 'Library', seite: 'Seiten', rubrik: 'Rubriken' };
|
||||
|
||||
const EMPTY = {
|
||||
isNew: true, path: '', type: 'beitrag', section: 'software', slug: '',
|
||||
@@ -89,7 +89,7 @@ function Dashboard({ email }) {
|
||||
|
||||
const q = query.trim().toLowerCase();
|
||||
const filtered = q ? entries.filter((e) => e.title.toLowerCase().includes(q) || (e.section || '').includes(q)) : entries;
|
||||
const groups = { beitrag: [], wiki: [], seite: [], rubrik: [] };
|
||||
const groups = { beitrag: [], biblio: [], seite: [], rubrik: [] };
|
||||
for (const e of filtered) (groups[e.kind] || groups.seite).push(e);
|
||||
|
||||
return (
|
||||
@@ -126,7 +126,7 @@ function Dashboard({ email }) {
|
||||
<aside>
|
||||
<button className="new" onClick={() => setCurrent({ ...EMPTY })}>+ Neuer Beitrag</button>
|
||||
<div className="search"><span>⌕</span><input placeholder="Suchen…" value={query} onChange={(e) => setQuery(e.target.value)} /></div>
|
||||
{['beitrag', 'wiki', 'seite', 'rubrik'].map((kind) => groups[kind].length > 0 && (
|
||||
{['beitrag', 'biblio', 'seite', 'rubrik'].map((kind) => groups[kind].length > 0 && (
|
||||
<div className="group" key={kind}>
|
||||
<div className="group-title">{KIND_LABEL[kind]} <span>{groups[kind].length}</span></div>
|
||||
<ul className="list">
|
||||
@@ -169,7 +169,7 @@ function Editor({ initial, onSaved, onMsg }) {
|
||||
const dragging = useRef(false);
|
||||
const coverIn = useRef(null);
|
||||
const set = (k) => (e) => setF({ ...f, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value });
|
||||
const isWiki = f.type === 'wiki' || (f.path || '').startsWith('wiki/');
|
||||
const isWiki = f.type === 'biblio' || (f.path || '').startsWith('library/');
|
||||
|
||||
async function pickCover(ev) {
|
||||
const file = ev.target.files?.[0]; ev.target.value = '';
|
||||
@@ -198,8 +198,8 @@ function Editor({ initial, onSaved, onMsg }) {
|
||||
if (!data.isNew) return data.path;
|
||||
const slug = (data.slug || '').trim();
|
||||
if (!slug) return '';
|
||||
if (data.type === 'beitrag') return `library/${data.section}/${slug}.md`;
|
||||
if (data.type === 'wiki') return `wiki/${slug}.md`;
|
||||
if (data.type === 'beitrag') return `archiv/${data.section}/${slug}.md`;
|
||||
if (data.type === 'biblio') return `library/${slug}.md`;
|
||||
return `${slug}.md`;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ function Editor({ initial, onSaved, onMsg }) {
|
||||
<label className="sm">Typ
|
||||
<select value={f.type} onChange={set('type')}>
|
||||
<option value="beitrag">Beitrag</option>
|
||||
<option value="wiki">Wiki-Seite</option>
|
||||
<option value="biblio">Library-Seite</option>
|
||||
<option value="seite">Seite</option>
|
||||
</select>
|
||||
</label>
|
||||
@@ -423,7 +423,7 @@ function Overview({ onMsg, go }) {
|
||||
<h2>Übersicht</h2>
|
||||
<div className="stat-grid">
|
||||
<Card label="Beiträge" value={s.content.beitraege} hint={`${s.content.entwuerfe} Entwürfe`} to="content" />
|
||||
<Card label="Wiki-Seiten" value={s.content.wiki} to="content" />
|
||||
<Card label="Library-Seiten" value={s.content.library} to="content" />
|
||||
<Card label="Seiten" value={s.content.seiten} />
|
||||
<Card label="Autor:innen" value={s.users.total} hint={`${s.users.admin} Admin · ${s.users.editor} Red.`} to="users" />
|
||||
<Card label="Foren" value={s.dialog.forums} to="forums" />
|
||||
@@ -438,7 +438,7 @@ function Overview({ onMsg, go }) {
|
||||
<button onClick={() => go('users')}>Autor:innen & Rollen</button>
|
||||
<a className="quick-link" href="/" target="_blank" rel="noreferrer">Website ↗</a>
|
||||
<a className="quick-link" href="/dialog/" target="_blank" rel="noreferrer">Dialog ↗</a>
|
||||
<a className="quick-link" href="/wiki/" target="_blank" rel="noreferrer">Wiki ↗</a>
|
||||
<a className="quick-link" href="/library/" target="_blank" rel="noreferrer">Library ↗</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -681,7 +681,7 @@ function slugify(s) {
|
||||
function fromRead(r) {
|
||||
const fm = r.frontmatter || {};
|
||||
const p = r.path || '';
|
||||
const type = p.startsWith('library/') ? 'beitrag' : p.startsWith('wiki/') ? 'wiki' : 'seite';
|
||||
const type = p.startsWith('archiv/') ? 'beitrag' : p.startsWith('library/') ? 'biblio' : 'seite';
|
||||
return {
|
||||
isNew: false, path: r.path, type, section: '', slug: '',
|
||||
title: fm.title || '', date: fm.date ? String(fm.date).slice(0, 10) : '',
|
||||
|
||||
@@ -26,7 +26,8 @@ async function walk(dir) {
|
||||
return out;
|
||||
}
|
||||
|
||||
// Beitrag (library/<section>/<slug>.md) | Rubrik (_index.md) | Seite (sonst).
|
||||
// Beitrag (archiv/<section>/<slug>.md) | Library-Seite (library/<slug>.md)
|
||||
// | Rubrik (_index.md) | Seite (sonst).
|
||||
function classify(rel) {
|
||||
const base = path.basename(rel);
|
||||
const parts = rel.split('/');
|
||||
@@ -34,11 +35,11 @@ function classify(rel) {
|
||||
const section = parts.length >= 2 ? parts[parts.length - 2] : 'home';
|
||||
return { kind: 'rubrik', section };
|
||||
}
|
||||
if (parts[0] === 'library' && parts.length === 3) {
|
||||
if (parts[0] === 'archiv' && parts.length === 3) {
|
||||
return { kind: 'beitrag', section: parts[1] };
|
||||
}
|
||||
if (parts[0] === 'wiki') {
|
||||
return { kind: 'wiki', section: 'wiki' };
|
||||
if (parts[0] === 'library') {
|
||||
return { kind: 'biblio', section: 'library' };
|
||||
}
|
||||
return { kind: 'seite', section: null };
|
||||
}
|
||||
@@ -85,8 +86,8 @@ export async function listEntries() {
|
||||
url: urlFor(rel),
|
||||
});
|
||||
}
|
||||
// Beiträge zuerst, dann Wiki, Seiten, Rubriken; je nach Datum/Titel.
|
||||
const order = { beitrag: 0, wiki: 1, seite: 2, rubrik: 3 };
|
||||
// Beiträge zuerst, dann Library, Seiten, Rubriken; je nach Datum/Titel.
|
||||
const order = { beitrag: 0, biblio: 1, seite: 2, rubrik: 3 };
|
||||
items.sort((a, b) =>
|
||||
(order[a.kind] - order[b.kind]) ||
|
||||
(b.date || '').localeCompare(a.date || '') ||
|
||||
|
||||
@@ -9,11 +9,11 @@ stats.use('*', requireAdmin);
|
||||
|
||||
stats.get('/', async (c) => {
|
||||
// Inhalte aus dem Dateisystem zählen.
|
||||
const content = { beitraege: 0, entwuerfe: 0, wiki: 0, seiten: 0, rubriken: 0 };
|
||||
const content = { beitraege: 0, entwuerfe: 0, library: 0, seiten: 0, rubriken: 0 };
|
||||
try {
|
||||
for (const e of await listEntries()) {
|
||||
if (e.kind === 'beitrag') { content.beitraege++; if (e.draft) content.entwuerfe++; }
|
||||
else if (e.kind === 'wiki') content.wiki++;
|
||||
else if (e.kind === 'biblio') content.library++;
|
||||
else if (e.kind === 'rubrik') content.rubriken++;
|
||||
else content.seiten++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user