- common.css: fieldset > *:not(:last-child) gets margin-bottom: var(--space-xs) - admin.css: .param-form fieldset > * zeroes margin to avoid double-spacing with flex gap
15 KiB
XAMXAM TODO
Merge apropos editables into À propos page + remove charte + source code URL
actions/apropos.php— onlycontacts; removed credits, erg_urlactions/page.php— removechartefrom allowed slugscontenus.php(front controller) — filter pages to only showabout+licensestemplates/admin/contenus.php— restored "Pages statiques" tablecontenus-edit.php(front controller) —aboutslug loads contacts for unified edittemplates/admin/contenus-edit.php—about_pagetype: Markdown editor + contacts on one pagetemplates/admin/apropos-groups-form.php— reusable partial for contactsDatabase.php— simplified getAproposContent/saveAproposContent (contacts-only JSON)storage/schema.sql— removed credits, erg_url; only contacts remainsAboutController.php— removed credits, sourceCode DB loadingtemplates/public/about.php— hardcoded source code URL, hardcoded credits HTMLapropos.css—.apropos-toc-sourcestyles
Duplicate TFE submission prevention (fixes)
DuplicateThesisException— typed exception carrying existing thesis metadataDatabase::findDuplicateThesis()— year + author + normalised-title matching (exact, prefix, Levenshtein ≤10%)ThesisCreateController::submit()— calls duplicate check before any DB write, throwsDuplicateThesisExceptionAppLogger::logDuplicate()— dedicated log action (status: duplicate) for audit trailApp::flash/consumeFlash— extended to supportwarningtype alongsideerror/successadmin/actions/formulaire.php— catchesDuplicateThesisExceptionseparately; logs it; flashes HTML warning with link to existing thesis; repopulates formpartage/index.php— same catch block; plain-text warning (no admin link) surfaced on the student form viaflash-warningbanner; form repopulatedtoast.php— renderstoast--warningblockadmin.css—.toast--warningstyle + link colourform.css—.flash-warningstyle (partage form)
Admin audit logging
AdminLoggerclass — JSON-lines to/var/log/xamxam.log(prod) orstorage/logs/admin.log(dev), mirrors toadmin_audit_logDB tableadmin_audit_logDB table — created in schema + migratedshare_links.is_archivedcolumn — archive replaces delete; stats preservedShareLink::archive()— new method;toggleActivereturns new state;listActive()/listArchived()split;validateLinkblocks archived slugsactions/acces-etudiante.php— delete→archive, all actions logged (create, toggle, set_password, archive)actions/publish.php— publish/unpublish loggedactions/delete.php— delete / bulk-delete / delete-all loggedactions/visibility.php— visibility changes loggedactions/export-csv.php— CSV export loggedactions/export-db.php— DB export loggedactions/edit.php— TFE edit loggedactions/formulaire.php— TFE add from admin loggedactions/tag.php— rename/merge/delete loggedactions/page.php— static page edits loggedactions/apropos.php— à-propos edits loggedactions/form-help.php— form structure edits loggedactions/access-request.php— approve/reject loggedactions/maintenance.php— maintenance on/off loggedactions/settings.php— formulaire toggles, objet types, SMTP update loggedactions/smtp-test.php— SMTP test loggedtemplates/admin/acces.php— archive button, archived links collapsible sectionscripts/setup-server.sh— provision/var/log/xamxam.logwith correct ownership
Multi-author support
ThesisCreateController::validateAndSanitise()— comma-splitauteurice, sort alphabetically, build author entries arrayDatabase::createThesis()— removed hardcodedauthor_idinsert; authors linked viasetThesisAuthors()insteadThesisEditController::save()— authors sorted alphabetically beforesetThesisAuthors()Database::findDuplicateThesis()— acceptsarrayof author names, matches any shared author viaIN+DISTINCT- File folder naming — slug generated from all authors alphabetically sorted (both create and edit)
v_theses_fullGROUP_CONCAT —ORDER BY a.name ASCfor deterministic alphabetical display- Migration
012_author_view_order.sql— rebuilds view with alphabetical author ordering
Fix remote 500s and broken TFE pages (post-deploy)
migrations/pending/008_share_links_is_archived.sql—ALTER TABLE share_links ADD COLUMN is_archived(missing on remote; breaksacces.php)migrations/pending/009_admin_audit_log.sql—CREATE TABLE admin_audit_log(missing on remote)migrations/pending/010_smtp_notify_email.sql—ALTER TABLE smtp_settings ADD COLUMN notify_email(missing on remote; breaksparametres.phpviaSmtpRelay::getSettings())migrations/pending/011_thesis_files_sort_and_label.sql—ALTER TABLE thesis_files ADD COLUMN sort_order / display_label(missing on remote; breaks every public TFE detail page)justfile— addeddeploy-migraterecipe: SSHes to remote and runsphp migrations/run.php
Replace browser dialogs with <dialog> modals
admin/index.php—alert()(no selection) →<dialog id="no-selection-dialog">;confirm()bulk publish/unpublish →<dialog id="bulk-confirm-dialog">;confirm()bulk delete →<dialog id="bulk-delete-dialog">;confirm()single delete →<dialog id="delete-thesis-dialog">; inlineconfirm()on Dépublier button removed (no confirmation needed for reversible action)admin/tags.php—confirm()merge →<dialog id="merge-tag-dialog">;confirm()delete →<dialog id="delete-tag-dialog">admin/acces-etudiante.php—confirm()delete link →<dialog id="delete-link-dialog">admin/acces.php—confirm()archive link →<dialog id="archive-link-dialog">admin/parametres.php—confirm()enable maintenance →<dialog id="enable-maintenance-dialog">;confirm()delete all TFE →<dialog id="delete-all-tfe-dialog">; admin passwordconfirm()kept withTODOcommentadmin/account.php— admin passwordconfirm()kept withTODOcommentadmin.css— added.admin-dialog--sm,.admin-dialog__alert,.admin-dialog__footerstyles
Fix 403 on HTMX tab requests in parametres.php
AdminAuth::requireLogin()— now sets$_SESSION[SESSION_KEY]when accepting nginx Basic Auth credentials (was returning early without marking the session)AdminAuth::isAuthenticated()— now falls back toPHP_AUTH_PWverification (same logic asrequireLogin) so HTMX requests tosystem-fragment.phpauthenticate even before a session exists
Duplicate warning display fixes
toast-fragment.php— 204 guard now also checkswarning; warning was silently discarded beforepartage/index.php— warning stored as plain text (no pre-escaping);htmlspecialchars()applied once at render; was double-encoded beforepartage/index.php—flash-warningdiv getsid+tabindex=-1; inline JS scrolls and focuses it on loadadmin/footer.php—htmx:afterSettlelistener focuses.toast--warningafter HTMX injects the toast fragment
Sticky save/cancel buttons on edit page
templates/admin/edit.php— moved.admin-form-footerfrom bottom to top-right, right after<h1>admin.css— added.admin-form-footer--stickyvariant withposition:sticky; top:0; justify-content:flex-end
Fix CSV importer column shift and data repair
- Pad rows to expected column count to avoid offset warnings from short rows
- Distinguish
$yearRaw !== ''beforeintval()to handle empty-year rows correctly - Improve missing-field error message: lists which fields are missing, includes identifier/title snippet
- Derive year from identifier when year column is empty
- Auto-detect column-shifted CSV: when orientation/finality columns are empty but synopsis/context match known orientation/finality names, remap on import
- Migration
013_fix_csv_column_shift.sql: move orientation from synopsis→orientation_id, finality from context_note→finality_id for already-imported theses - Migration
013_fix_remarks_keywords.php: move keywords from remarks→tags+thesis_tags for already-imported theses
Standardise répertoire filter column rendering
- Centralise filter column rendering into a shared
repFilterEntry()function - Define
$filterColumnsconfig array as single source of truth for the 5 filter columns - All columns (years, ap, or, fi, kw) now share identical fade/select/HTMX logic via the same code path
- Fix single-valued FK columns (years, ap, or, fi): matched entries now use full intersection so clicking one entry correctly fades others with zero results
- Fix column ordering: students between finalité and mots-clés
Add spacing between form elements inside fieldsets
common.css—fieldset > *:not(:last-child) { margin-bottom: var(--space-xs); }admin.css—.param-form fieldset > * { margin-bottom: 0; }to avoid double-spacing with flex gap
Standardise buttons with .btn base class
- Create
.btnbase class in common.css:border-radius: 10px; padding: var(--space-xs)+ background + cursor - Add
.btn--primary(accent bg),.btn--secondary(--bg bg + border),.btn--sm,.btn--lg,.btn--danger,.btn--warning,.btn--success,.btn--ghost,.btn--muted,.btn--blue,.btn--yellow,.btn--green,.btn--redmodifiers - Replace old button definitions in admin.css, form.css, tfe.css, file-access.css, system.css with empty alias comments
- Update all PHP templates to use new
.btnclasses (btn btn--primary,btn btn--secondary,btn btn--danger, etc.) - Update border-radius on pagination buttons to 10px for consistency
- Exclude
storage/maintenance.flagfrom rsync deploy and git
Admin file export system
ExportController: addgetAllThesisFiles(),buildExportManifest(),createExportZip()— gathers all thesis files, creates zip with files/ + manifest.jsonadmin/actions/export-files.php— thin dispatcher, streams zip, logs auditAdminLogger::logFilesExport()— audit log entry for file exportstemplates/admin/index.php— add "Exporter fichiers" button next to CSV export buttonDatabase::getAllThesisFilesForExport()— query all thesis_files + identifierdocs/export.md— documentation en français pour administrateurs : fonctionnement, contenu du ZIP, procédure de restauration complète et partielle
Validate & refactor TFE form fields (new spec)
-
Schema: add
exemplaire_baiuandexemplaire_ergboolean columns totheses -
Schema: add
jury_promoteur_ulbboolean column tothesis_supervisors -
Schema: persist
cc4rcheckbox inthesestable -
Schema: update
v_theses_fullview to include new columns + jury split (interne/externe/ULB) -
Admin edit form: add
jury_points,remarks,exemplaire_baiu,exemplaire_ergfields (Backoffice fieldset) -
Admin edit form: add
promoteur_ulbcheckbox in jury fieldset -
Admin edit form: reorder fields to match spec layout
-
Public TFE fiche: split lecteur·ice(s) into interne/externe
-
Public TFE fiche: add promoteur·ice ULB display
-
ThesisEditController: handle new fields in save()
-
ThesisCreateController: handle CC4r + is_ulb in jury methods
-
Database::updateThesis: include new columns (remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc4r)
-
Database::setThesisJury: include is_ulb column
-
Database::getThesisJury: include is_ulb in SELECT
-
StudentEmail: use new jury_lecteurs_internes/externes and jury_promoteurs_ulb columns
-
Recapitulatif: show promoteur·ice ULB and lecteur·ices interne/externe
-
Migration:
014_tfe_form_fields.sql— ALTER + view rebuild -
Fix
Call to undefined function old()in admin edit page — defineold()inapp/public/admin/edit.php(was only inadd.php) -
Add Note contextuelle and Backoffice fieldsets to admin add form (matching edit form)
-
Database::createThesis()— addcontext_note,remarks,jury_points,exemplaire_baiu,exemplaire_erg,cc4rcolumns -
ThesisCreateController::validateAndSanitise()— handle new admin-only fields -
ThesisCreateController::submit()— pass new fields tocreateThesis() -
Replace admin E-mail de confirmation fieldset with Contact interne in Backoffice section (add + edit)
-
Remove confirmation email sending from add/edit (admin never sent; student partage unchanged)
Refactor form structure per spec (student vs admin)
- Remove
jury_presidentfield from student-facing forms (edit keeps it as optional) - Jury: split into promoteur·ice interne, promoteur·ice ULB, lecteur·ice interne, lecteur·ice externe — each with +add button
- AP filtering: student form hides PACS; admin form shows all APs
- Language: add "autre" text field alongside predefined checkboxes
- Duration: split into pages field + minutes field + annexes checkbox
- Licence: removed from métadonnées fieldset, now only in degrés d'ouverture section
- Degrés d'ouverture: généralités FIRST, then radio choice (Libre/Interne/Interdit), then licence dropdown + custom text + CC2r
- CC4r → CC2r rename in form UI +
cc2rPOST name - Licence: custom licence text field added (
license_customDB column) - Généralités text editable via form help block (
fieldset_generalites) - Libre option: hidden in student form when disabled in settings; always shown in admin
- Contact:
contact_visiblefield always present in TFE info; admin getscontact_publiccheckbox separately - Email confirmation: mandatory in student form, optional in admin
- Fichiers: cover image hint updated to 4:3 ratio
- All three form pages (admin add, admin edit, partage) updated
- Controllers updated:
collectJuryMembers,validateAndSanitise,buildFileSizeInfo,license_custom,cc2r→cc4rmapping
Fix form field required states & missing fields per spec
- Admin add: add
contact_publiccheckbox (matching edit form) - Admin add + partage + admin edit: formats checkbox-list
$required = true - All forms: jury promoteur·ice interne
requiredattribute - All forms: jury lecteur·ice interne
requiredattribute (at least one) - All forms: jury lecteur·ice externe
requiredattribute (at least one) - All forms: licence select
$required = true - Admin edit: add "E-mail de confirmation" fieldset
- Partage: contact always visible (POST handler defaults
showContactto true when nocontact_publickey present) - Partage: filter PACS from AP programs dropdown
- Verify no duplicate asterisks on any field
- Admin add:
contact_publicPOST handling in ThesisCreateController for admin submissions - Server-side validation: formats required, jury members required, licence required (ThesisCreateController + ThesisEditController)
- Autofocus mappings for new validation errors (format, jury, licence)