mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 01:53:03 +02:00
apropos/licence/charte use .page-content as a nested scroll container
(overflow-y:auto) inside html/body {height:100%; overflow:hidden} flex.
Firefox drops/clips that container's own padding-bottom (and last-child
margin) from the scrollable area -- scrollHeight came out ~80px short and
the last ~80px of content was unreachable. Chromium honours the padding.
Move the trailing space off the container padding onto a real content
spacer (.page-content > article::after, display:block; height) which both
browsers count as scrollable content. Verified via Playwright (Chromium +
Firefox): delta between article and scrollHeight is now 0 in both on all
three pages, consistent at all breakpoints. not-found unaffected (loads
its own not-found.css). 294 PHPUnit tests pass.
16 KiB
16 KiB
TODO
Last updated: 2026-08-31 Context: CSS waste strategy — full stream DEFERRED (tasks 10/u/w/x/y/z): unusedSymbols report showed only ~6.2KB/2.9% of 216KB reclaimable; pruning + per-page split parked (docs/css-split-analysis.md). #t (Interdit admin route) confirmed already implemented via /admin/media.php + media-viewer.php + recapitulatif link. No pending live tasks.
Pending
- #justfile-deploy-code-nginx-split [!medium] de-dup deploy-code: it bundled nginx config + server-side setup (full duplicate of deploy-nginx). Now code-only; deploy depends on deploy-nginx; provision-server's duplicate deploy-nginx removed; var/{cache,logs,tmp} mkdir moved into scripts/deploy-server.sh.
In Progress
- #cover-home-lazy-intersect-fix [!high] Fix lazy covers not loading after initial images. Root cause: home grid scrolls inside (overflow-y:auto, body height:100vh flex), but htmx
revealedlistens to window scroll only — so below-fold covers never revealed. Fix: hx-trigger="intersect threshold:0.05 once" (IntersectionObserver works inside any scroll container). VERIFIED LIVE: progressive scroll loads covers 5→11→15→20→22/22 (before: stuck ~5). Committed fix(home): use intersect trigger. - #cover-image-webp-avif-serve-lite [!medium] Serve lightweight webp cover thumbnails instead of full-res PNG originals (~99% on worst cases). DONE VERIFIED LIVE 2026-08-31:
cwebp -resize 800 q80sidecars (+ GD fallback for CMYK JPEGs) generated by ThesisFileHandler at upload (FilePond + legacy); /cover-fragment emits(webp source + original fallback); backfill scripts/generate-cover-webp.php + just deploy-cover-webp. PROD: tools installed (docs), 46/46 covers backfilled (44 cwebp + 2 GD/CMYK), app code deployed, /cover-fragment + /media?path=*.webp verified 200 image/webp 61KB (vs 15.8MB orig). AVIF dropped (no viable prod resize; WEBP sufficient). NOTE: just deploy-code's final nginx/permissions step needs sudo password (operational, pre-existing — not a regression).
In Progress
- #fix-toc-scrollbar-overlap-content-pages Fix TOC scrollbar overlapping text on about/charte/licence pages (desktop sticky sidebar). Root cause:
.tocscroll container (overflow-y:auto, 180px col) had no right gutter, so native scrollbar sat on top of link text. Fix: padding-right (not margin) on the.tocscroll container + matching padding on summary.
Pending
- #home-htmx-lazy-cover-images [!medium] Add htmx lazyloading on home page cover images:
revealed-triggered cover-fragment endpoint, swap-in<img>, settle fade CSS, load htmx on home
In Progress
- #cleanup-toc-fix-duplicate-id [+admin] Clear TOC links after cleanup restructure. Root cause: admin-toc.js assigned
sec.id = headingIdto sections, and on rebuild-because-of-htmx-swap the section + h2 ended up sharing the same id, so getElementById returned thewhose textContent dragged the whole data table into the TOC label. Fix: anchor links to the heading id and never give the section that id (no duplicate ids); verified via Playwright — TOC now lists exactly Tiléversements abandonnés / Corbeille / Vidéos PeerTube with no table text.
In Progress
- #cleanup-stats-under-headings [+admin] On the cleanup page, move each section's stat/count out of the heading to a line directly under it, and merge PeerTube into a single heading. cleanup-stats-fragment: "Téléversements abandonnés" / "Corbeille" h2 now bare, stat emitted as
<p class=n-meta>under the h2. peertube-orphans-fragment: removed the separate "Vidéos orphelines" h3; the orphan count now appears as the stat line under the static "Vidéos PeerTube" h2. Verified via Playwright: TOC still lists exactly 3 clean entries; stats render under headings.
In Progress
- #cleanup-stat-card [+admin] Render the cleanup-page section stats as a proper card box (
cleanup-stat-card, bigger than the old inline n-meta): padded panel (bg-secondary + border, radius 10px), step-1/700/accent text. Applied to the filepond, trash and PeerTube stat lines. Verified computed style via Playwright.
In Progress
- #cleanup-desc-and-tooltips [+admin] Cleanup page: add short French descriptions under each section heading (Téléversements abandonnés / Corbeille / Vidéos PeerTube) explaining what the data is and how safe deletion is (
.cleanup-section-desc), and native title tooltips on the Supprimer and Restaurer buttons of each row. Verified via Playwright (descriptions + tooltips render on all rows).
In Progress
- #cleanup-auto-gc-uploads [+scripts/deploy] Abandoned FilePond uploads are now garbage-collected automatically (they are risk-free staging dirs never linked to a TFE). Added
scripts/cleanup-tmp-uploads.php(dry-run by default, mirrors the admin cleanup filepond logic: missing-session via manifest.json + 2h fallback), hourly crondeploy/xamxam-tmp-cleanup.cron,just deploy-tmp-cleanup-cron+just deploy-check-tmp-cleanup-log, wired intodeploy-all-first, and documented in docs/deployment.md. Tested dry-run + --no-dry-run + active-session protection locally.
In Progress
- #cleanup-remove-filepond-section [+admin] Since abandoned FilePond uploads are GC'd by cron, removed the "Téléversements abandonnés" section from the cleanup page and the index "Nettoyer" badge now counts trash only. cleanup-stats-fragment.php renders only the Corbeille section (and "Corbeille vide" when empty); index.php badge is trash-only; admin-cleanup-bulk.js simplified to trash_files[] only. Verified via Playwright: only Corbeille + Vidéos PeerTube sections/TOC, no filepond checkboxes, tooltips intact.
In Progress
- #cleanup-page-title [+admin] Simplify cleanup page title from "Nettoyer les fichiers temporaires" to "Nettoyage" (page now mostly manages the Corbeille). Updated
app/public/admin/cleanup.phppageTitle andapp/templates/admin/cleanup.phph1.
In Progress
- #docs-cleanup-changes [docs] Update docs for the cleanup-page + GC changes made: admin README cleanup.php entry -> "Cleanup page (Corbeille — restore/delete trashed files)"; deployment.md adds a paragraph explaining abandoned uploads are auto-GC'd hourly and the page (titled Nettoyage) now only shows the Corbeille; added
just cleanup-tmp-uploadsrecipe and documented it in development.md alongside cleanup-drafts.
Completed
- #fix-content-page-bottom-spacing-firefox [!medium] Fix missing bottom spacing at scroll-end on apropos/licence/charte in Firefox. Root cause:
.page-contentis a nested scroll container (overflow-y:auto) inside html/body {height:100%; overflow:hidden} flex; Firefox drops/clips that container's ownpadding-bottom(and last-child margin) from the scrollable area while Chromium honours it — FF scrollHeight came out ~80px SHORTER and the last ~80px of content was unreachable (clipped). Fix: moved trailing space off the container padding (padding-bottom: 0at all breakpoints) onto a real content spacer.page-content > article::after { display:block; height: var(--space-2xl) }(var(--space-xl)below 768px), which both browsers count as scrollable content. VERIFIED via Playwright (Chromium + Firefox): before FF delta=−80 (clipped) vs Chrome 0; after both FF & Chrome delta=0 on licence/apropos and identical on charte; not-found page unaffected (loads its own not-found.min.css). 294 PHPUnit tests pass. - #cleanup-toc [+admin] Add sidebar TOC to admin cleanup page; drop the "Fichiers temporaires" section level and promote "Téléversements abandonnés" / "Corbeille" from h3 to h2 top-level sections (now TOC entries). Made admin-toc.js rebuild on htmx swap/settle so async-loaded fragment sections enter the TOC.
- #audit-all-docs-and [!high] Audit all docs/ and classify accurate vs stale
- #rewrite-development-md-to-match [!high] Rewrite development.md to match current just dev / app/ layout / PHPUnit
- #rewrite-deployment-md-to-match [!high] Rewrite deployment.md to match just deploy / /var/www/xamxam/ / backup
- #update-database-md-to-current [!high] Update database.md to current schema (tags, share_links, migrations, xamxam.db)
- #update-security-md-to-current [!medium] Update security.md to current state (xamxam paths, resolved items)
- #update-search-md-to-current [!medium] Update search.md to current schema (tags not keywords)
- #verify-fix-import-md-csv-format [!medium] Verify/fix import.md CSV format against current import
- #update-bookmarklet-md-form-field [!medium] Update bookmarklet.md form field names (cc2r, duration_pages/minutes, drop contact_public)
- #consolidate-archive-historical-analysis-docs [!medium] Consolidate/archive historical analysis docs
- #fix-nginx-readme-md-title [!low] Fix nginx README.md title + export.md cross-refs
- #fix-app-storage-readme-md-missing-database-spec-quick-schema [!medium] Fix app/storage/README.md (missing DATABASE_SPEC/QUICK_SCHEMA refs, wrong path)
- #update-css-md-asset-structure Update CSS.md asset structure + build bundling
- #correct-file-uploads-md-limits-banner Correct file-uploads.md limits, banner removal, FilePond transition
- #rewrite-app-public-admin-readme-md-to-current Rewrite app/public/admin/README.md to current structure
- #fix-nginx-docs-security-headers-md-csp-x-frame-options Fix nginx/docs/SECURITY_HEADERS.md CSP/X-Frame-Options
- #create-docs-readme-md-index-classifying Create docs/README.md index classifying all docs
- #standardise-all-log-filenames Standardise all log filenames to xamxam-{service}[-{date}].log convention
- #add-server-side-log-rename Add server-side log rename script + just recipe (migrate-log-names) for pre-existing logs
- #move-production-app-logs Move production app logs from storage/logs to /var/log/xamxam + add logrotate config
- #add-date-dropdown-to Add date dropdown to admin log viewer to browse retained daily log files
- #fix-heure-de-d-p-t Fix heure de dépôt (submitted_at) fausse dans backoffice récapitulatif: timezone Europe/Brussels + interpréter datetimes SQLite (UTC) comme UTC
- #add-date-de-d-p-t Add 'Date de dépôt' (date_depot) column: DB migration + view + recap display
- #csv-export-emit-date-depot CSV export: emit date_depot as Brussels-local date
- #csv-import-parse-date-depot CSV import: parse date_depot as Brussels-local and convert to UTC storage
- #default-exemplaire-baiu Default Exemplaire BAIU + ERG to true on student (partage) submission in ThesisCreateController, replicating admin add-form default
- #m-style-links-on Style links on licences, charte, a propos pages (underline + accent hover)
- #recherche-backoffice-par-identifiant Recherche backoffice par identifiant : ajouter t.identifier a la WHERE de getThesesList/getThesesListCount
- #add-admin-only-route-to [!low] Add admin-only route to open Interdit thesis files from backoffice --context repo
- #identify-which-templates-load [!high] Identify which templates load base.min.css and the page types — DONE inventory: docs/css-split-analysis.md. Key finding: head.php loads base.min.css on EVERY full page (App::render => templates/head.php unconditional). is the per-page-type mechanism (public/tfe/repertoire/content-page/not-found/form/admin/system). Centralize inventory in docs/css-split-analysis.md. Gates both split (w) and unusedSymbols corpus (11).
- #collect-content-sources-for [!high] Collect content sources for the unusedSymbols pass — Built scripts/css-content-sources.mjs: buildCorpus() returns {corpus, sources, totalBytes, safelist, prefixes}. Gathers templates/public/src PHP + first-party js/app JS (vendor excluded). Mined 22 exact dynamic classes (status-, log-, input-error, active, disabled, btn--, fhb-, admin-icon-btn--, status-published/pending/badge) + 5 suffix prefixes (status-access--, toc-level-, admin-import-log__item--, admin-body, student-body) from status-badge.php, SystemController statusClass/logLineClass, class= ternaries. Documented docs/css-split-analysis.md. Feeds task 12 report.
- #write-report-script-to [!medium] Write report script to compute unused selectors + reclaimable bytes — Built scripts/css-unused-report.mjs + just css-report recipe. Extracts class/id symbols per dist bundle, matches against buildCorpus() corpus + safelists, measures reclaimable bytes via lightningcss transform unusedSymbols (no stripping to disk). FULL RESULT: 216,383B total, ~6.2KB (2.9%) reclaimable. See docs/css-split-analysis.md table. Feeds task 14 go/no-go.
- #flag-or-safelist-dynamic [!medium] Flag or safelist dynamic classes before trusting the report — Vendor + dynamic safelists shipped. Dynamic: 22 exact classes (status-, log-, input-error, active, disabled, btn--, fhb-, admin-icon-btn--, status-badge/published/pending) + 5 DB/state suffix prefixes (status-access--, toc-level-, admin-import-log__item--, admin-body, student-body). VENDOR: filepond--* and htmx-* prefixes excluded (runtime vendor JS assembly) — without these the report inflated to 26% (56KB); with them honest 2.9%. Report surfaces needs-review (kept, not flagged removable).
- #summarize-findings-and-decide [!low] Summarize findings and decide whether to proceed to pruning — Decision recorded in docs/css-split-analysis.md. Data: 216,383B total, ~6.2KB (2.9%) reclaimable; base.min.css only 484B. SPLIT: NO-GO (base.css already well-used; split adds complexity for ~2% of one bundle) -> defer u-w-x-y. PRUNING: CONDITIONAL-GO on hand-verifiable dead set only, from SOURCE css files, re-run just css-report after each edit, never touch needs-review/vendor-prefix classes.
Deferred / Blocked
- #just-setup-backs-a [!medium] just setup backs a stale setup-dev.sh (clones php-live-reload, legacy admin/data/ dirs) — needs rewrite or removal
- #csv-export-writes-cc2r-exemplaire [!low] CSV export writes CC2r/Exemplaire columns that import's $cell mapping ignores — document or wire up
- #split-base-min-css-into-per-page [!medium] Split base.min.css into per-page bundles to reduce cross-page CSS waste — NO-GO (task 14): per-page split parked. base.min.css already well-used (only 484B/2.3% reclaimable); split adds build/template complexity for ~2% of one bundle. See docs/css-split-analysis.md decision.
- #define-per-page-type-css-bundle [!medium] Define per-page-type CSS bundle boundaries and entry files — Using the template->page-type map, decide which source files (components/*, utilities.css, reset, typography, etc.) belong in each page-type bundle. Document the mapping so shared-vs-page-specific splits are explicit and reviewable.
- #implement-per-page-bundles-in [!medium] Implement per-page bundles in scripts/build-css.mjs — Extend build-css.mjs with new bundle targets following the existing bundleCss/concatBundle pattern. Emit per-page-type .min.css outputs into app/public/assets/dist/. Keep base.min.css for pages not yet split.
- #wire-templates-to-load [!medium] Wire templates to load their page-type bundle instead of base.min.css — Update each template's tags to point at the appropriate per-page bundle. Ensure no page loads CSS it doesn't need and that shared pages still get full styling.
- #measure-before-after-css-bytes [!low] Measure before/after CSS bytes shipped per page type — Moot: part of split stream which is NO-GO (task 14). Skip unless split is revived.
- #add-lightningcss-unusedsymbols-report-only [!high] Add lightningcss unusedSymbols report-only pass for base.min.css — SEQUENCING: do this (unusedSymbols report-only) BEFORE the per-page split (u). Reasoning: high priority, zero-risk diagnostic-only, produces reclaimable-byte go/no-go (14) against ~216KB baseline; if pruning is not worthwhile the split may not be either. Reuses inventory from v (docs/css-split-analysis.md). Start: 11 collect-content-sources.