160c394c3ffe387fa68a6192b35aacb42bdfc6fc
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
160c394c3f |
Rework forms, statistics, design and the sidebar foot in 1.15.0
Forms are an editor now: one card per field with add and remove, the technical name derived from the label, options only for a choice, and a new "Aussehen" section with a button label and four colours (field border and background, button and button text) that travel to the page as one rule per form inside the hashed style block. A live preview draws the form with the site's default button and names the text contrast. Statistics open with six figures (views against the same span before, average per day, busiest day, pages, referred views, missing addresses), a chart with grid lines and a title per bar, a weekday chart and ranked lists with share bars. The design screen shows the palette as colour cards with seven ready-made palettes, picks the base colours from the palette, previews every font in itself and the typography as a sample. The sidebar ends in an account card with role and a logout icon. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a434e0cefc |
Serve every font from this server and surface open tasks in 1.14.0
Fonts were still reachable from Google in two places. The editor and area previews were handed `googleFonts` and no `localFonts`, so the screen used most of the day fetched Lato from fonts.googleapis.com on every open; the public page fell back to the same link whenever the files were missing. Neither path remains: the template has no Google branch, `googleFontsUrl()` is gone, and the policies name no foreign font host - `font-src 'self'` publicly, `style-src 'self'; font-src 'self'` in administration. Without local files a site now shows the theme's fallback and says so. Preloading took the first two weights per family. The Kant-IT theme names Lato 400, 700 and 900 and sets its headings on 800/900, so the one weight that carried them loaded after the stylesheet and `font-display:swap` swapped the heading in plain sight. Every weight of the theme is preloaded now, latin subset, and the links sit before the stylesheet: measured cold, all three files finish at 168 ms against a first paint at 292 ms. Open tasks no longer hide on the screen that owns them. A strip above every management screen names what needs a button and carries it: a new version leads to System, missing fonts to Design. Neither asks the network - the version comes from the daily update-check task, the fonts from a look in the folder. System and update was unusable on a phone: `.stack` is a grid whose automatic column grows to its widest content, and one long database path pushed the page sideways. It gets `minmax(0, 1fr)`, the backup table stacks below 620px, and the prose is 45% shorter with the fine print folded away. The device chips drew the current device with an outline, which lies outside the box, ran under its neighbour and was clipped by the sidebar - it read as a cut-off red frame. Used devices are filled in `#9d4e0d` now (5.6:1), the current one carries a border inside the chip. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
3391fea58b | Add visual button presets, jump targets and menu controls | ||
|
|
495b26896e | Fassung 1.7.0: verlässliche Installation, übersichtliche Verwaltung und bedienbare Bewegung | ||
|
|
05ea703655 |
Fassung 1.6.0: der Aufgabenplan wird veroeffentlicht
Wiederkehrende Aufgaben ohne Cronjob (ADR 073): Sicherung, Statistik kuerzen, geplante Veroeffentlichung, Updatepruefung und Aufraeumen laufen als Plan in der Tabelle scheduled_task - eine Zeile je Aufgabe mit Faelligkeit, Sperre und letztem Ergebnis. Auf geteiltem Hosting gibt es oft keinen Cronjob; der Plan haengt stattdessen an Anfragen und an einem Takt aus dem geoeffneten Backend. Diese Arbeit entstand in einer parallel laufenden Sitzung und lag bis hierher unveroeffentlicht im Arbeitsverzeichnis: die Releases 1.5.0 bis 1.5.5 wurden bewusst aus dem jeweiligen Tag gebaut und enthielten sie deshalb nicht. Vor der Veroeffentlichung geprueft, nicht bloss eingepackt: - phpunit 452/452, npm test 28/28, npm run test:editor vollstaendig. - Die Migration 20260914000100 legt nur die Tabelle scheduled_task an und nimmt sie beim Zurueckrollen wieder weg. Sie fasst keine bestehenden Daten an. - Seit einer Stunde keine Schreibzugriffe der anderen Sitzung mehr. Dabei zwei Fehler behoben: - config/services.yaml verwendet !tagged_iterator. Das ist gueltiges Symfony, aber "lint:yaml config" kennt eigene Tags nur mit --parse-tags und gab 1 zurueck - der CI-Lauf waere daran gescheitert. Flag ergaenzt. - AdminHeadersSubscriber.php (aus 1.5.3) entsprach nicht dem Stil von php-cs-fixer; composer lint gab 8 zurueck. Behoben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d6d476177a |
Fassung 1.4.3: Update ohne Git, Verwaltung auf dem Telefon, eigene Symbole
Vier Wuensche und ein Fund beim Nachmessen. - Farbwaehler im Designbereich. Das Textfeld bleibt massgeblich, damit "@akzent" ein Verweis auf die Palette bleibt und nicht beim ersten Klick zu einem festen Hexwert erstarrt (ADR 066). - Die Verwaltung auf dem Telefon: das Menue klappt unter 760 px zu und nennt den Bereich, in dem man steht; Ziele 44 px, kein Skript. - Eigene SVG-Symbole statt Unicode-Zeichen - ein Telefon ersetzt die sonst durch Emoji in fremdem Stil. Zwei Eintraege trugen dabei denselben Pfad; ein Test findet beides (ADR 067). - Update aus dem Releasearchiv: der Weg fuer Installationen ohne Git. Zwei Schritte, weil ein Prozess, der sich selbst ausgetauscht hat, mit dem alten Code weiterarbeitet. var/, .env, hochgeladene Schriften und das erzeugte Buendel bleiben unberuehrt; public/ wird dazu Datei fuer Datei zusammengefuehrt. Geprueft ohne Netz gegen eine Releaseseite im Speicher (ADR 068). Beim Nachmessen der echten Startseite statt einer Testseite: das groesste Element ueber der Falz ist dort kein <img>, sondern der Hintergrund des ersten Abschnitts - und der steht nur im Stylesheet. Drei Vorabverweise mit denselben Geraetegrenzen wie der Compiler holen genau die Variante, die die Regel auch nimmt. LCP 1,3 s -> 1,1 s. Dabei gefunden: dasselbe Bild wurde je Geraeteregel neu abgefragt - Startseite 19 -> 15 Abfragen (ADR 069). Geprueft: 428 Tests auf PHP 8.2 und 8.4, Editor-, Browser- und Linkpruefung, Lighthouse auf drei echten Seiten (alles ausser der Leistung der Startseite 100). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5a8d67a638 |
Fassung 1.0.1: die laufende Fassung steht in der Verwaltung
Eine kleine, von außen sichtbare Änderung - sie ist der Prüfstein für das Update: nach dem Einspielen muss in der Seitenleiste 1.0.1 stehen, und der Weg dorthin muss die Schritte gegangen sein, die der Updater verspricht. Die Fassung kommt über eine Twig-Funktion in die Vorlage, nicht über einen globalen Dienst: die Vorlagen bekommen genau diese eine lesende Antwort und nicht einen Updater mit update() darauf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
52f0ab3807 |
Updater: neue Fassung über Git, mit Vorprüfung und Rückweg
Aus dem Plan in docs/UPDATE.md ist Code geworden: cms:update, cms:health, der Bildschirm "System" und der Wartungszustand. Die Vorprüfung ist die halbe Arbeit. Sie fragt nach proc_open, Git, sauberer Arbeitskopie, Herkunft, Schreibrechten und Platz - und danach, ob Datenbank und Medienordner wirklich von Git ausgenommen sind. Das ist der Punkt, an dem ein Update Inhalte zerstören könnte, also wird er geprüft und nicht angenommen. Jede Prüfung sagt, was zu tun ist, nicht bloß "fehlgeschlagen". Der Rückweg ist Teil des Wegs: scheitert ein Schritt, wird auf den vorherigen Commit zurückgesetzt. Die Datenbank nur dann zurückgeschrieben, wenn die Migration schon begonnen hatte - sonst verlöre der Rückweg Inhalte, die während des Updates entstanden sind. Antwortet der alte Stand im Rauchtest, geht die Website wieder online; antwortet er nicht, bleibt der Wartungszustand, weil eine kaputte Seite schlechter ist als eine ehrliche Meldung. Der Rauchtest läuft als eigener Prozess, denn nur ein frischer Prozess führt den neuen Code aus. Ein Test im laufenden Prozess hätte den alten geprüft und "alles in Ordnung" gemeldet. Kein symfony/process: der Runner sind dreißig Zeilen über proc_open mit dem Befehl als Array - kein Shell, nichts zu maskieren, und "proc_open ist abgeschaltet" wird die erste Antwort statt der Überraschung im dritten Schritt. 285 PHP-Tests / 1244 Assertions. Sechs davon fahren den Updater gegen echte Git-Repositorys in einem Temp-Verzeichnis, mit Platzhalterskripten für die zwei Befehle - inklusive des Fehlschlags, nach dem Code und Datenbank zurückgesetzt sein müssen. Nicht gegen dieses Projekt: ein Test, der die Arbeitskopie auscheckt, in der er läuft, ist ein Weg, Arbeit zu verlieren. Offen bleibt die Sicherung einer MySQL-Datenbank per mysqldump - dafür fehlt die Installation; der Updater sagt das im Schritt "Sicherung". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
99bad61179 |
Statistik: Zähler statt Protokoll, deshalb ohne Einwilligung
"Wieviel wann wo wie die Seite benutzt" - naheliegend wäre ein Analysewerkzeug gewesen, das eine Einwilligung braucht und damit genau die Besucher verliert, die ablehnen. Also andersherum: eine Messung, die niemanden wiedererkennt. Gespeichert wird ein Zähler je (Tag, Stunde, Pfad, Status, Verweis-Domain), kein Datensatz je Aufruf. Keine IP-Adresse, keine Kennung, kein Cookie - auch nicht gehasht, denn der Hash einer IP-Adresse bleibt ein Personenbezug. Ein Test liest die Spaltenliste der Tabelle und vergleicht sie mit dieser Zusage, damit sie beim nächsten Ausbau nicht unbemerkt fällt. Vom Verweis bleibt nur der Host: die volle Adresse kann einen Suchbegriff oder einen Namen tragen. Gezählt wird auf kernel.terminate, nach der Antwort - die Messung darf keine Anfrage verlangsamen, und ein Fehler beim Zählen kostet einen Zähler, nicht eine Seite. Nur GET auf HTML mit 200 oder 404; Verwaltung, Assets, Feed, Sitemap und Einwilligungsseite sind ausgenommen, erkennbare Maschinen über ihre Kennung. Das ist eine Heuristik, deshalb heißt die Zahl auf dem Bildschirm nicht "Besucher". Erfundene Crawler-Adressen laufen gesammelt unter (sonstige), sonst wächst die Tabelle mit jedem geprobten Pfad. Die Diagramme zeichnet der Server als SVG mit Klassen statt Stilattributen: kein Diagrammwerkzeug, kein Skript, und die Richtlinie bleibt streng. Die Zahlen stehen zusätzlich in einer Tabelle, weil ein Balken für einen Screenreader nichts ist. Was die Zahlen nicht sagen, steht auf dem Bildschirm: Aufrufe statt Besucher, keine Verweildauer, keine Absprungrate, kein Klickweg, kein Land. Das ist die Folge der Entscheidung, nicht eine Lücke. Aufbewahrung: nach 60 Tagen werden die Stunden eines Tages verschmolzen, nach 425 Tagen gelöscht - gut ein Jahr, damit der Vorjahresmonat vergleichbar bleibt. cms:stats:prune macht beides und gehört in einen Cronjob. 279 PHP-Tests / 1119 Assertions unter PHP 8.2.12 und 8.4.22, axe auf zwölf Verwaltungsbildschirmen ohne Verstöße. Dabei kam eine PHP-8.4-Verwarnung zu fputcsv() heraus, jetzt mit ausdrücklichem Escape-Parameter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
84d471acd9 |
Das System heißt KantSites
Umut hat den Namen festgelegt: aus dem Arbeitstitel "Kant CMS" wird KantSites. Geändert in allen Seitentiteln der Verwaltung, im Wortmarken-Schriftzug von Anmeldung und Seitenleiste, in den Fußzeilen, in den Demoinhalten für eine frische Installation, in package.json, .claude/launch.json und der Dokumentation. Die Bezeichnung der Website in der Datenbank heißt jetzt ebenfalls KantSites. Nicht angefasst: die bereits gespeicherten Demoinhalte der lokalen Installation. Titel wie "Die Grundlage · Kant CMS" und der Text im Kopfbereich sind Inhalt, nicht Systemname - die gehören in den Editor, nicht in ein Skript, das Revisionen umschreibt. 219 PHP-Tests / 881 Assertions grün, Playwright-Editortest grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
14031a5880 |
Benutzerverwaltung in der Oberfläche, Mediathek als eigene Seite
Konten gab es bisher nur über die Konsole. Unter "Benutzer" legt ein Administrator jetzt Konten an, ändert Rollen, setzt Passwörter und löscht Konten; unter "Mein Konto" ändert jeder sein eigenes Passwort, aber nur mit dem aktuellen in der Hand. Eine Rolle je Konto: Administrator, Veröffentlicher, Redakteur. Ein Passwort oder eine Rolle zu ändern meldet jede offene Sitzung dieses Kontos ab - dafür war nichts zu bauen, CmsUser::isEqualTo vergleicht Hash und Rollen mit der Datenbank. Genau eine Sitzung überlebt: die, die ihr eigenes Passwort geändert hat. "Jemanden sofort aussperren" ist damit dasselbe wie "Passwort setzen". Es bleibt immer ein Administrator übrig, nicht über eine Zählung, sondern weil niemand sein eigenes Konto löschen oder herabstufen kann und jede Änderung die Administratorrolle voraussetzt. Die zusätzliche Prüfung auf einen zweiten Administrator war damit unerreichbar und ist wieder heraus. Mediathek (Umut: "das sollte direkt laden in pagination"): /admin/media zeigt die Bilder jetzt selbst, 24 je Seite, neueste zuerst, mit Blättern und einem Schalter für archivierte. Hochladen und Bildangaben laufen über gewöhnliche Formulare ohne JavaScript; der Dialog bleibt der Weg, beim Bearbeiten ein Bild auszuwählen. Die Bild-ID steht in jeder Karte, weil Beitragsbild und Teilen-Vorschau genau diese ID erwarten. Die Migrationsliste der Testfixtures stand dreimal da und steht jetzt einmal in tests/TestSchema.php. 217 PHP-Tests / 845 Assertions unter PHP 8.2.12 und 8.4.22. axe deckt jetzt elf Bildschirme ab statt drei - alle Verwaltungsseiten, nicht nur Anmeldung, Seitenliste und Editor -, null Verstöße. Nicht geprüft: kein Screenreader; Blättern und Upload sind mit zwei Bildern geprüft, nicht mit einer großen Bibliothek. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4841bf65bc |
Verwaltung neu gestaltet: ein Rahmen statt sieben Kopfzeilen
Jede Verwaltungsseite trug bisher ihre eigene Kopfzeile und ihre eigene, unvollständige Liste von Links auf die anderen Seiten - die Seitenübersicht verlinkte sieben Bereiche, das Menü fünf, die Fassungen drei. Wo man war, stand nirgends. Jetzt gibt es einen Rahmen für alle: eine feste Seitenleiste mit der Navigation, der aktive Eintrag über aria-current markiert, und eine Kopfzeile mit Titel, einem Satz Erklärung und Platz für die Hauptaktion. Jede Seite füllt nur noch heading, lead, actions und content. Auf schmalen Fenstern wird die Seitenleiste zu einer scrollbaren Leiste, ohne JavaScript. Die Seitenübersicht zeigt je Seite eine Zeile mit dem Alltäglichen und einem Aufklappfeld "Einstellungen", das darunter an seinem Platz öffnet - vorher waren es sechs Aufklappfelder, deren Inhalt als absolut positionierter Kasten über den Rand der Karte hinausragte. Tabellen scrollen seitlich, statt die Karte aus dem Fenster zu schieben. Das Stylesheet ist geteilt: die Editorregeln stehen in editor.css, das nur Editor und Mediathek laden; admin.css ist neu geschrieben und lesbar. Der Editor behält seinen Aufbau und übernimmt die neue Gestaltung - Systemschrift, gleiche Radien, gleiche Schaltflächen, und ein paar Panelgrößen, die zum Lesen zu klein waren. Beim Zerlegen des Stylesheets schnitt mein Skript am Ende jedes @media-Blocks alle schließenden Klammern ab statt nur einer. editor.css war damit ab dem ersten Medienblock ungültig: der Browser behielt 29 von 202 Regeln. Gefunden hat das der Browsertest, an einer Vorschaubreite von 1236 statt 1240 Pixeln - vier Pixel als einziges Anzeichen dafür, dass dreiviertel des Stylesheets fehlte. 201 PHP-Tests / 716 Assertions unter PHP 8.2.12 und 8.4.22, Playwright- Editortest mit axe ohne Verstöße auf Anmeldung, Seitenübersicht und Editor, öffentliche Browserprüfung grün. Zwei Testselektoren zeigten auf umbenannte Klassen und prüfen dieselbe Sache nun über den neuen Namen. Nicht geprüft: kein Screenreader, und die Bildschirme Menüs, Formulare, Bereiche, Design, Einstellungen und Fassungen sind nur von Hand bedient, nicht automatisiert geprüft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |