From fc0fd0c7483ae358fa4efb20230de4c97a73dbd0 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Mon, 31 Aug 2026 12:26:50 +0200 Subject: [PATCH] Wissen: "Neu" laeuft nach 48 Stunden von selbst ab Filipe: neue Anleitungen sollen nach 48 Stunden aus dem oberen Block verschwinden und nur noch in ihrer Kategorie zu finden sein. Vorher standen sie dort 30 Tage. ZUERST EIN PROBLEM IM BESTAND: Es gab gar keinen Zeitpunkt, nur ein Datum (veroeffentlicht). Eine abends um 23 Uhr eingestellte Anleitung waere damit nur 25 statt 48 Stunden neu gewesen. Neue Spalte "hochgeladen" mit dem genauen Zeitpunkt -- eine Spalte anzuhaengen laesst SQLite anstandslos zu, anders als eine geaenderte CHECK-Regel. Alte Eintraege ohne Zeitstempel fallen auf Mitternacht des Datums zurueck, geprueft. ZWEI DINGE BEWUSST GETRENNT: NEU laeuft nach 48 Stunden ab, gemessen ab dem Hochladen. Nicht ab "veroeffentlicht" -- das ist nur ein Datum und darf frei gesetzt werden. WICHTIG bleibt stehen, bis es jemand abschaltet. Es ist eine Entscheidung von Hand ("Erscheint zusaetzlich ganz oben unter Neu & wichtig"), keine Eigenschaft, die von selbst verfaellt -- sonst waere der Schalter sinnlos. Wer eine angepinnte Anleitung loswerden will, nimmt sie ueber "Bearbeiten" wieder heraus. Damit man sieht, WARUM etwas oben steht, gibt es jetzt zwei Marken statt einer: "Neu" (gruen, laeuft ab) und "Wichtig" (gold, bleibt). Sonst wundert man sich, wenn eine verschwindet und die andere nicht. Unter der Ueberschrift steht dieselbe Regel in einem Satz. Geprueft mit kuenstlich gealterten Eintraegen: 0 h -> im Block, Marke "Neu" 47 h -> im Block, Marke "Neu" 49 h -> raus, aber weiterhin in der Kategorie 200 h + wichtig -> im Block, nur Marke "Wichtig" 300 h -> raus, in der Kategorie auffindbar ohne Zeitstempel -> faellt auf das Datum zurueck --- server/workspace-wissen.js | 40 ++++++++++++++++++++++++++------- server/workspace.js | 14 ++++++++++++ workspace/assets/css/wissen.css | 13 +++++++++++ workspace/assets/js/wissen.js | 6 +++++ workspace/aufgaben.html | 12 +++++----- workspace/bereich.html | 14 ++++++------ workspace/calls.html | 16 ++++++------- workspace/dateien.html | 14 ++++++------ workspace/index.html | 4 ++-- workspace/kalender.html | 14 ++++++------ workspace/personen.html | 14 ++++++------ workspace/profil.html | 14 ++++++------ workspace/report.html | 16 ++++++------- workspace/scouting.html | 14 ++++++------ workspace/start.html | 10 ++++----- workspace/startcheck.html | 16 ++++++------- workspace/wissen.html | 14 ++++++------ 17 files changed, 151 insertions(+), 94 deletions(-) diff --git a/server/workspace-wissen.js b/server/workspace-wissen.js index c04fc5c2..1d8c7cd0 100644 --- a/server/workspace-wissen.js +++ b/server/workspace-wissen.js @@ -34,6 +34,11 @@ const TITEL_MAX = 140; const TEXT_MAX = 400; const TAGS_MAX = 8; +/* Wie lange eine Anleitung unter "Neu & wichtig" steht. Danach ist sie + nur noch in ihrer Kategorie zu finden -- so wie es sein soll: Der + Block oben ist eine Neuigkeitenanzeige, kein zweites Regal. */ +const NEU_STUNDEN = 48; + const jetzt = () => new Date().toISOString(); const heute = () => new Date().toISOString().slice(0, 10); @@ -233,7 +238,7 @@ wissenRouter.get("/workspace/api/wissen", (req, res) => { const liste = db().prepare(` SELECT w.id, w.titel, w.beschreibung, w.kategorie, w.stufe, w.geraet, w.tags, w.name_original, w.groesse, w.wichtig, w.veroeffentlicht, w.aktualisiert, - p.name AS von + w.hochgeladen, p.name AS von FROM wissen w LEFT JOIN personen p ON p.id = w.erstellt_von ${wo} ORDER BY w.wichtig DESC, @@ -243,12 +248,31 @@ wissenRouter.get("/workspace/api/wissen", (req, res) => { for (const e of liste) e.tags = e.tags ? String(e.tags).split(",").filter(Boolean) : []; /* Neu und wichtig -- der Einstieg fuer alle, die nicht suchen, - sondern schauen wollen, was sich getan hat. */ + sondern schauen wollen, was sich getan hat. + + ZWEI VERSCHIEDENE DINGE, bewusst getrennt: + + NEU laeuft nach 48 Stunden von selbst ab. Gemessen ab dem + Hochladen, nicht ab dem Veroeffentlichungsdatum -- das ist nur ein + Datum und darf frei gesetzt werden. Bei alten Eintraegen ohne + Zeitstempel wird auf Mitternacht des Datums zurueckgefallen. + + WICHTIG bleibt stehen, bis es jemand wieder abschaltet. Es ist + eine Entscheidung von Hand ("Erscheint zusaetzlich ganz oben"), + keine Eigenschaft, die von selbst verfaellt -- sonst waere der + Schalter sinnlos. */ + const grenze = Date.now() - NEU_STUNDEN * 3600_000; + const istNeu = (e) => { + const wann = e.hochgeladen + ? Date.parse(e.hochgeladen) + : Date.parse((e.veroeffentlicht || "") + "T00:00:00"); + return Number.isFinite(wann) && wann >= grenze; + }; const neu = !k && !q && !stufe && !geraet && !tag - ? liste.filter((e) => e.wichtig - || (Date.now() - Date.parse(e.aktualisiert || e.veroeffentlicht) < 30 * 86400_000)) - .slice(0, 6) + ? liste.filter((e) => e.wichtig || istNeu(e)).slice(0, 6) : []; + /* Damit die Oberflaeche sagen kann, WARUM etwas oben steht. */ + for (const e of neu) e.ist_neu = istNeu(e); res.json({ eintraege: liste, neu, gesamt: liste.length }); } catch (fehler) { @@ -364,12 +388,12 @@ wissenRouter.post( const { lastInsertRowid } = db().prepare(` INSERT INTO wissen (titel, beschreibung, kategorie, stufe, geraet, tags, - name_original, name_datei, groesse, wichtig, veroeffentlicht, erstellt_von) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`).run( + name_original, name_datei, groesse, wichtig, veroeffentlicht, hochgeladen, erstellt_von) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)`).run( aus.titel, aus.beschreibung ?? null, aus.kategorie, aus.stufe ?? "einsteiger", aus.geraet ?? "egal", aus.tags ?? null, name, dateiname, req.body.length, aus.wichtig ?? 0, - aus.veroeffentlicht ?? heute(), req.person.id); + aus.veroeffentlicht ?? heute(), jetzt(), req.person.id); protokolliere("wissen_hochgeladen", { personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req), diff --git a/server/workspace.js b/server/workspace.js index 4cd0abc3..91cd6870 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -117,6 +117,20 @@ let _dbFehler = null; function umstellungen(d) { const jetztStempel = new Date().toISOString().slice(0, 16).replace(/[-:T]/g, ""); + /* ---- Zeitpunkt des Hochladens in der Bibliothek ---- + Eine neue Spalte laesst SQLite anstandslos anhaengen -- anders als + eine CHECK-Regel. Alte Eintraege bleiben leer und fallen auf das + Veroeffentlichungsdatum zurueck. */ + try { + const spalten = d.prepare("PRAGMA table_info(wissen)").all().map((s) => s.name); + if (spalten.length && !spalten.includes("hochgeladen")) { + d.exec("ALTER TABLE wissen ADD COLUMN hochgeladen TEXT"); + console.log("[workspace] Spalte 'hochgeladen' in der Bibliothek ergaenzt."); + } + } catch (fehler) { + console.error("[workspace] Spalte 'hochgeladen':", fehler?.message); + } + /* ---- Rolle "manager" erlauben ---- */ const bauplan = d.prepare( "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'personen'").get()?.sql || ""; diff --git a/workspace/assets/css/wissen.css b/workspace/assets/css/wissen.css index 3ac015a1..8a281c167 100644 --- a/workspace/assets/css/wissen.css +++ b/workspace/assets/css/wissen.css @@ -409,3 +409,16 @@ @media (prefers-reduced-motion: reduce) { .katwahl__knopf, .filterreihe__knopf { transition: none; } } + +/* "Neu" laeuft nach 48 Stunden ab, "Wichtig" bleibt bis zum Abschalten. + Zwei Marken statt einer -- sonst sieht man nicht, warum eine Anleitung + oben steht, und wundert sich, wenn eine verschwindet und die andere + nicht. */ +.marke-neu { + padding: 3px 9px; border-radius: 999px; + font-size: .71rem; font-weight: 600; + color: #5fc99a; + background: rgba(95, 201, 154, .12); + border: 1px solid rgba(95, 201, 154, .38); +} +.block__frage { margin: -6px 0 13px; font-size: .82rem; color: var(--text-still); max-width: 76ch; } diff --git a/workspace/assets/js/wissen.js b/workspace/assets/js/wissen.js index 2b730f88..4739f647 100644 --- a/workspace/assets/js/wissen.js +++ b/workspace/assets/js/wissen.js @@ -87,6 +87,9 @@ const kopf = el('div', 'block__kopf'); kopf.append(el('h2', 'block__titel', 'Neu & wichtig')); s.append(kopf); + s.append(el('p', 'block__frage', + 'Neu eingestellte Anleitungen stehen 48 Stunden hier. Danach sind sie ' + + 'in ihrer Kategorie zu finden – angepinnte bleiben, bis du sie abschaltest.')); const box = el('div', 'karten'); for (const e of neuLetzte) box.append(karte(e)); s.append(box); @@ -152,6 +155,9 @@ stufe.dataset.stufe = e.stufe; marken.append(stufe); if (e.geraet && e.geraet !== 'egal') marken.append(el('span', 'marke-geraet', aufbau.geraete[e.geraet])); + /* "Neu" laeuft ab, "Wichtig" nicht -- deshalb zwei Marken und nicht + eine. Sonst waere nicht erkennbar, warum etwas oben steht. */ + if (e.ist_neu) marken.append(el('span', 'marke-neu', 'Neu')); if (e.wichtig) marken.append(el('span', 'marke-wichtig', 'Wichtig')); for (const t of e.tags) { const b = el('button', 'marke-tag', '#' + t); diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index d602e9cf..d8248cf6 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -7,9 +7,9 @@ - - - + + + @@ -134,8 +134,8 @@ - - - + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 283a752d..10e3a869 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -98,8 +98,8 @@ - - - + + + diff --git a/workspace/calls.html b/workspace/calls.html index d9e4bcd6..0517fe41 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -49,9 +49,9 @@ - - - - + + + + diff --git a/workspace/dateien.html b/workspace/dateien.html index 0c69b349..2adc1b79 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -88,8 +88,8 @@ - - - + + + diff --git a/workspace/index.html b/workspace/index.html index 52e01e3c..6d2d4d8d 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -25,7 +25,7 @@ type="image/webp" media="(max-width: 899px)" /> - + @@ -143,6 +143,6 @@

- + diff --git a/workspace/kalender.html b/workspace/kalender.html index 73c1dec7..9972bf9c 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -94,8 +94,8 @@ - - - + + + diff --git a/workspace/personen.html b/workspace/personen.html index cf2c50ef..aa9917c4 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -93,8 +93,8 @@ - - - + + + diff --git a/workspace/profil.html b/workspace/profil.html index 1ad95d61..bb339c2b 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -127,8 +127,8 @@ - - - + + + diff --git a/workspace/report.html b/workspace/report.html index 79c04244..eed66bcc 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -86,9 +86,9 @@ - - - - + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index 9b33831f..21b89b4d 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -124,8 +124,8 @@ - - - + + + diff --git a/workspace/start.html b/workspace/start.html index 0be93392..f5016bb2 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -7,8 +7,8 @@ - - + + @@ -56,8 +56,8 @@

- - - + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index e10e6c0b..82292c80 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -65,9 +65,9 @@ - - - - + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index b83b9c41..5669d135 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -170,8 +170,8 @@ - - - + + +