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 @@ - - - + + +