From 401c8f006c88464e09e8ca5440063cf96274f634 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Fri, 28 Aug 2026 13:20:49 +0200 Subject: [PATCH] Workspace: Formulare richtig ausgerichtet, PDF-Ablage und Schalter URSACHE ZUERST: .feld--breit stand in DREI HTML-Dateien (wissen, scouting, dateien) -- und war NIE im CSS definiert. Das Raster (auto-fit, minmax(170px)) gab deshalb jedem Feld dieselbe Breite, egal was drin steht: Der Titel war so schmal wie eine Auswahl, lange Kategorienamen wurden abgeschnitten ("1. TikTok - Grundla"), und die Tag-Vorschlaege stapelten sich zu einer halben Seite. Jetzt zwoelf Spalten statt auto-fit. Damit laesst sich sagen, WIE breit ein Feld sein soll: Titel, Beschreibung und Kategorie ueber die ganze Zeile, Stufe/Geraet/Datum zu dritt nebeneinander. Unter 860 px zwei Spalten, unter 560 px eine. Die Klasse ist zentral definiert, also wirken die drei betroffenen Seiten sofort mit. Gemessen danach: Titel/Beschreibung/Kategorie je 1058 px, die drei kleinen je 342 px, Kategorie nicht mehr abgeschnitten. PDF-ABLAGE statt nacktem Dateifeld. Der Browser-Knopf war abgeschnitten ("K...") und sah aus wie ein Fremdkoerper. Jetzt eine eigene Flaeche: Klicken, Ziehen oder Tastatur. Sie markiert sich gruen, sobald eine Datei drin ist, prueft schon im Browser auf PDF und schlaegt den Dateinamen als Titel vor, wenn der noch leer ist. Sie steht bewusst GANZ OBEN: Man laedt etwas hoch und beschreibt DANN, was es ist -- nicht umgekehrt. SCHALTER statt Kaestchen fuer "besonders wichtig". Ein Kaestchen von 17 Pixeln ist auf dem Handy kaum zu treffen und sagt nicht, was passiert. Der Schalter ist gross, zeigt seinen Zustand in Gold (dieselbe Farbe wie die Marke "Wichtig" spaeter) und erklaert sich in einer Zeile: "Erscheint zusaetzlich ganz oben unter Neu & wichtig". Tag-Vorschlaege kompakter: von zehn Zeilen auf zwei. Geprueft: Handy ohne Ueberlauf, 0 Konsolenfehler, Dateiwahl markiert die Flaeche und fuellt den Titel, Schalter schaltet. --- workspace/assets/css/aufgaben.css | 22 ++++++- workspace/assets/css/wissen.css | 102 ++++++++++++++++++++++++------ workspace/assets/js/wissen.js | 56 ++++++++++++++-- workspace/aufgaben.html | 10 +-- workspace/bereich.html | 12 ++-- workspace/calls.html | 12 ++-- workspace/dateien.html | 12 ++-- workspace/index.html | 4 +- workspace/kalender.html | 12 ++-- workspace/personen.html | 12 ++-- workspace/profil.html | 12 ++-- workspace/report.html | 12 ++-- workspace/scouting.html | 12 ++-- workspace/start.html | 8 +-- workspace/startcheck.html | 12 ++-- workspace/wissen.html | 50 ++++++++++----- 16 files changed, 254 insertions(+), 106 deletions(-) diff --git a/workspace/assets/css/aufgaben.css b/workspace/assets/css/aufgaben.css index b767050a..1acee8a7 100644 --- a/workspace/assets/css/aufgaben.css +++ b/workspace/assets/css/aufgaben.css @@ -26,9 +26,27 @@ border-radius: var(--radius); } .neu__zeile { margin-bottom: 14px; } +/* Zwoelf Spalten statt auto-fit: Damit laesst sich sagen, WIE breit ein + Feld sein soll -- ein Titel braucht die ganze Zeile, eine Stufe ein + Drittel. auto-fit gab jedem Feld dieselbe Breite, egal was drin steht. */ .neu__raster { - display: grid; gap: 14px; margin-bottom: 8px; - grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); + display: grid; gap: 14px 16px; margin-bottom: 8px; + grid-template-columns: repeat(12, 1fr); +} +/* Vorgabe: ein Drittel. Reicht fuer Auswahlfelder und Datumsangaben. */ +.neu__raster > .feld { grid-column: span 4; min-width: 0; } + +/* Diese Klasse stand in drei HTML-Dateien, war aber NIE definiert -- + deshalb quetschte das Raster jedes Feld in dieselbe Breite und lange + Kategorienamen wurden abgeschnitten. */ +.neu__raster > .feld--breit { grid-column: 1 / -1; } +.neu__raster > .feld--halb { grid-column: span 6; } + +@media (max-width: 860px) { + .neu__raster > .feld { grid-column: span 6; } +} +@media (max-width: 560px) { + .neu__raster > .feld, .neu__raster > .feld--halb { grid-column: 1 / -1; } } .neu__knoepfe { display: flex; gap: 10px; align-items: center; margin-top: 12px; } diff --git a/workspace/assets/css/wissen.css b/workspace/assets/css/wissen.css index 6940ebf5..094c2604 100644 --- a/workspace/assets/css/wissen.css +++ b/workspace/assets/css/wissen.css @@ -206,31 +206,94 @@ /* ---------- Formular ---------------------------------------------------------- */ -.haken { display: flex; align-items: center; gap: 9px; font-size: .87rem; cursor: pointer; } -.haken input { width: 17px; height: 17px; accent-color: var(--akzent); cursor: pointer; } +/* ---------- Ablagefläche für die PDF ------------------------------------ + Ein nacktes sah aus wie ein Fremdkörper und der + Knopf wurde vom Browser abgeschnitten ("K..."). Eine eigene Fläche + nimmt auch gezogene Dateien an -- der Weg, den man ohnehin erwartet. */ -.tag-vorschlag { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; } +.pdf-ablage { + display: grid; place-items: center; gap: 5px; + padding: 26px 20px; cursor: pointer; + border: 1px dashed rgba(255, 255, 255, .2); + border-radius: var(--radius); + background: rgba(255, 255, 255, .022); + transition: border-color .18s ease, background .18s ease; +} +.pdf-ablage:hover, .pdf-ablage:focus-visible { + outline: none; + border-color: rgba(63, 189, 245, .55); + background: rgba(63, 189, 245, .06); +} +.pdf-ablage[data-drueber="ja"] { + border-color: var(--akzent); border-style: solid; + background: rgba(63, 189, 245, .1); +} +.pdf-ablage[data-fertig="ja"] { + border-style: solid; border-color: rgba(95, 201, 154, .45); + background: rgba(95, 201, 154, .07); +} +.pdf-ablage__zeichen { + width: 26px; height: 26px; + fill: none; stroke: var(--text-still); stroke-width: 1.6; + stroke-linecap: round; stroke-linejoin: round; +} +.pdf-ablage[data-fertig="ja"] .pdf-ablage__zeichen { stroke: #5fc99a; } +.pdf-ablage__text { margin: 0; font-size: .92rem; color: var(--text-leise); text-align: center; } +.pdf-ablage__text strong { color: var(--akzent); } +.pdf-ablage__klein { margin: 0; font-size: .77rem; color: var(--text-still); } + +/* ---------- Schalter „besonders wichtig“ --------------------------------- + Ein Kästchen von 17 Pixeln ist auf dem Handy kaum zu treffen und sagt + nicht, was passiert. Der Schalter ist groß, zeigt seinen Zustand und + erklärt sich in einer Zeile. */ + +.schalter { + display: flex; align-items: flex-start; gap: 14px; + margin-top: 18px; padding: 14px 16px; cursor: pointer; + border: 1px solid var(--rand); border-radius: var(--radius); + background: rgba(255, 255, 255, .022); + transition: border-color .18s ease, background .18s ease; +} +.schalter:hover { border-color: rgba(255, 255, 255, .2); } +.schalter input { position: absolute; opacity: 0; width: 0; height: 0; } +.schalter__gleis { + flex: none; position: relative; width: 42px; height: 24px; margin-top: 1px; + border-radius: 999px; + background: rgba(255, 255, 255, .1); + border: 1px solid var(--rand); + transition: background .2s ease, border-color .2s ease; +} +.schalter__punkt { + position: absolute; left: 3px; top: 3px; width: 16px; height: 16px; + border-radius: 50%; background: var(--text-still); + transition: transform .2s ease, background .2s ease; +} +.schalter input:checked + .schalter__gleis { + background: rgba(232, 192, 125, .3); + border-color: rgba(232, 192, 125, .6); +} +.schalter input:checked + .schalter__gleis .schalter__punkt { + transform: translateX(18px); background: #e8c07d; +} +.schalter input:focus-visible + .schalter__gleis { + box-shadow: 0 0 0 3px rgba(232, 192, 125, .28); +} +.schalter:has(input:checked) { + border-color: rgba(232, 192, 125, .35); + background: rgba(232, 192, 125, .05); +} +.schalter__text { display: grid; gap: 2px; font-size: .88rem; } +.schalter__text .leise { font-size: .79rem; } + +.tag-vorschlag { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 8px; } .tag-knopf { - padding: 4px 10px; cursor: pointer; + padding: 3px 9px; cursor: pointer; font-size: .73rem; background: transparent; border: 1px dashed var(--rand); border-radius: 999px; - color: var(--text-still); font: inherit; font-size: .74rem; + color: var(--text-still); font-family: inherit; transition: color .16s ease, border-color .16s ease; } .tag-knopf:hover { color: var(--akzent); border-color: rgba(63, 189, 245, .45); border-style: solid; } -#n-datei { - width: 100%; padding: 10px 12px; - background: rgba(255, 255, 255, .04); - border: 1px dashed var(--rand); border-radius: var(--radius-klein); - color: var(--text-leise); font: inherit; font-size: .85rem; cursor: pointer; -} -#n-datei::file-selector-button { - margin-right: 12px; padding: 6px 13px; cursor: pointer; - background: rgba(63, 189, 245, .12); - border: 1px solid rgba(63, 189, 245, .3); border-radius: 8px; - color: var(--akzent); font: inherit; font-size: .8rem; font-weight: 600; -} - .leer-hinweis { display: grid; gap: 12px; justify-items: center; padding: 34px 22px; margin-bottom: 26px; text-align: center; @@ -247,6 +310,7 @@ } @media (prefers-reduced-motion: reduce) { - .kachel, .pdf, .marke-tag, .tag-knopf { transition: none; } + .kachel, .pdf, .marke-tag, .tag-knopf, .pdf-ablage, + .schalter, .schalter__gleis, .schalter__punkt { transition: none; } .kachel:hover { transform: none; } } diff --git a/workspace/assets/js/wissen.js b/workspace/assets/js/wissen.js index 4465430c..503caed0 100644 --- a/workspace/assets/js/wissen.js +++ b/workspace/assets/js/wissen.js @@ -339,7 +339,7 @@ $('neu-block').hidden = true; $('neu-auf').hidden = !aufbau.darf_pflegen; $('neu-form').reset(); - $('n-dateiname').textContent = 'Höchstens 40 MB. Nur echte PDF-Dateien.'; + zeigeDatei(); bearbeite = null; } @@ -374,11 +374,57 @@ $('neu-auf').addEventListener('click', () => formularOeffnen(null)); $('neu-zu').addEventListener('click', formularSchliessen); - $('n-datei').addEventListener('change', () => { + /* ---------- Ablagefläche ---------------------------------------------- */ + + const ablage = $('n-ablage'); + + function zeigeDatei() { const d = $('n-datei').files[0]; - $('n-dateiname').textContent = d - ? `${d.name} · ${groesse(d.size)}` - : 'Höchstens 40 MB. Nur echte PDF-Dateien.'; + const text = $('n-dateiname'); + text.textContent = ''; + if (!d) { + text.append(document.createTextNode('PDF hierher ziehen oder ')); + text.append(el('strong', null, 'auswählen')); + delete ablage.dataset.fertig; + return; + } + text.append(el('strong', null, d.name)); + text.append(document.createTextNode(' · ' + groesse(d.size))); + ablage.dataset.fertig = 'ja'; + /* Ist der Titel noch leer, den Dateinamen als Vorschlag nehmen -- + er ist fast immer schon die halbe Miete. */ + if (!$('n-titel').value.trim()) { + $('n-titel').value = d.name.replace(/\.pdf$/i, '').replace(/[_-]+/g, ' ').trim().slice(0, 140); + } + } + + function nimmDatei(d) { + if (!d) return; + if (!/\.pdf$/i.test(d.name) && d.type !== 'application/pdf') { + $('n-fehler').textContent = 'Das ist keine PDF-Datei.'; + return; + } + const dt = new DataTransfer(); + dt.items.add(d); + $('n-datei').files = dt.files; + $('n-fehler').textContent = ''; + zeigeDatei(); + } + + ablage.addEventListener('click', () => $('n-datei').click()); + ablage.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); $('n-datei').click(); } + }); + $('n-datei').addEventListener('change', zeigeDatei); + for (const art of ['dragenter', 'dragover']) { + ablage.addEventListener(art, (e) => { e.preventDefault(); ablage.dataset.drueber = 'ja'; }); + } + for (const art of ['dragleave', 'drop']) { + ablage.addEventListener(art, () => { delete ablage.dataset.drueber; }); + } + ablage.addEventListener('drop', (e) => { + e.preventDefault(); + nimmDatei(e.dataTransfer?.files?.[0]); }); $('neu-form').addEventListener('submit', async (e) => { diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 0921d593..ea1f4cce 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -7,9 +7,9 @@ - - - + + + @@ -134,7 +134,7 @@ - - + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 4d13b036..e84ac3d4 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -98,7 +98,7 @@ - - + + diff --git a/workspace/calls.html b/workspace/calls.html index 4e55e111..7622bb7f 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -49,7 +49,7 @@ - - + + diff --git a/workspace/dateien.html b/workspace/dateien.html index 766abea7..241611c1 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -88,7 +88,7 @@ - - + + diff --git a/workspace/index.html b/workspace/index.html index ee953414..402eb106 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -25,7 +25,7 @@ type="image/webp" media="(max-width: 899px)" /> - + @@ -130,6 +130,6 @@

- + diff --git a/workspace/kalender.html b/workspace/kalender.html index 51b915b8..cb87db37 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -94,7 +94,7 @@ - - + + diff --git a/workspace/personen.html b/workspace/personen.html index 9981a746..231f5e0a 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -87,7 +87,7 @@ - - + + diff --git a/workspace/profil.html b/workspace/profil.html index 54bea75f..21a4f993 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -127,7 +127,7 @@ - - + + diff --git a/workspace/report.html b/workspace/report.html index 655afc2d..7ca5da71 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -86,7 +86,7 @@ - - + + diff --git a/workspace/scouting.html b/workspace/scouting.html index a745ade7..d9611ada 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -124,7 +124,7 @@ - - + + diff --git a/workspace/start.html b/workspace/start.html index 07e0d387..77fcd6a7 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -7,8 +7,8 @@ - - + + @@ -56,7 +56,7 @@

- - + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index 325aaa70..606ee080 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -65,7 +65,7 @@ - - + + diff --git a/workspace/wissen.html b/workspace/wissen.html index 0d78c7d1..968af94f 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -93,6 +93,22 @@