diff --git a/TODO.md b/TODO.md index 8adf3a7..e3f0ccb 100644 --- a/TODO.md +++ b/TODO.md @@ -39,6 +39,21 @@ - [x] Update `root` directive in `nginx/posterg.conf` - [x] Update `STORAGE_ROOT` production path in `app/bootstrap.php` +## Form Help Blocks (student-facing explanatory text) + +- [x] Migration `004_add_form_help_blocks.sql` — `form_help_blocks` table with 8 seeded keys +- [x] `Database` methods: `getFormHelpBlock`, `setFormHelpBlock`, `getAllFormHelpBlocks`, `FORM_HELP_KEYS`, `FORM_HELP_LABELS` +- [x] `actions/form-help.php` — CSRF-validated save handler +- [x] `actions/page.php` — CSRF-validated save handler for static pages (was missing) +- [x] `contenus.php` controller — load `$formHelpBlocks`, add CSRF token +- [x] `contenus-edit.php` controller — handle `?form_block=` route +- [x] `templates/admin/contenus.php` — flash messages + form help blocks table with edit links +- [x] `templates/admin/contenus-edit.php` — `form_help` edit branch with OverType Markdown editor +- [x] `templates/partials/form/form-help-block.php` — renders Markdown block via Parsedown (safe mode), silent on empty +- [x] `partage/index.php` — load all blocks once, inject at all 8 positions (replaced TODO comments) +- [x] `form.css` — `.form-help-block` styled with accent left-border +- [x] `admin.css` — `.muted` utility class + ## Centralise Form Templates - [x] Extract shared fieldset partials: `fieldset-tfe-info.php`, `fieldset-academic.php`, `fieldset-files.php`, `fieldset-metadata.php`, `fieldset-licence-explanation.php` diff --git a/app/public/admin/actions/page.php b/app/public/admin/actions/page.php new file mode 100644 index 0000000..804d27d --- /dev/null +++ b/app/public/admin/actions/page.php @@ -0,0 +1,39 @@ +savePage($slug, $content); + App::flash('success', 'Page « ' . htmlspecialchars($slug) . ' » mise à jour.'); +} catch (Exception $e) { + error_log('page save error: ' . $e->getMessage()); + App::flash('error', 'Erreur lors de la sauvegarde : ' . htmlspecialchars($e->getMessage())); +} + +$_SESSION['csrf_token'] = bin2hex(random_bytes(32)); +header('Location: /admin/contenus.php'); +exit; diff --git a/app/public/assets/css/admin.css b/app/public/assets/css/admin.css index ca9d000..51a8411 100644 --- a/app/public/assets/css/admin.css +++ b/app/public/assets/css/admin.css @@ -1643,3 +1643,10 @@ /* ── Form group, student mode, thanks page → see form.css ───────────────── */ + +/* ── Utility ─────────────────────────────────────────────────────────────── */ + +.muted { + color: var(--text-secondary); + font-style: italic; +} diff --git a/app/public/assets/css/form.css b/app/public/assets/css/form.css index 1fe6a5a..190d254 100644 --- a/app/public/assets/css/form.css +++ b/app/public/assets/css/form.css @@ -786,3 +786,26 @@ a.recap-file-name:hover { background: var(--accent-secondary); transform: translateY(-1px); } + + +/* ── Form help blocks ────────────────────────────────────────────────────── */ + +.form-help-block { + background: color-mix(in srgb, var(--accent-primary) 8%, transparent); + border-left: 3px solid var(--accent-primary); + border-radius: 0 6px 6px 0; + padding: var(--space-s) var(--space-m); + margin-bottom: var(--space-s); + font-size: var(--step--1); + color: var(--text-primary); + line-height: 1.6; +} + +.form-help-block > *:first-child { margin-top: 0; } +.form-help-block > *:last-child { margin-bottom: 0; } + +.form-help-block p { margin: 0 0 var(--space-xs); } +.form-help-block ul, +.form-help-block ol { margin: 0 0 var(--space-xs); padding-left: var(--space-m); } +.form-help-block li { margin-bottom: var(--space-3xs); } +.form-help-block a { color: var(--accent-primary); } diff --git a/app/public/partage/index.php b/app/public/partage/index.php index 7b0f6ce..25cd92c 100644 --- a/app/public/partage/index.php +++ b/app/public/partage/index.php @@ -210,6 +210,10 @@ function renderShareLinkForm(string $slug, array $link): void $shareOldFn = fn(string $key, string $default = '') => old($formData, $key, $default); // No autofocus in the share form — identity function. $shareWithAutofocusFn = fn(string $field, array $attrs = []) => $attrs; + + // Load all form help blocks in one query. + $helpBlocks = Database::getInstance()->getAllFormHelpBlocks(); + $helpFn = fn(string $key) => $helpBlocks[$key]['content'] ?? ''; ?> @@ -243,9 +247,7 @@ function renderShareLinkForm(string $slug, array $link): void - +

* Champs obligatoires

@@ -253,13 +255,15 @@ function renderShareLinkForm(string $slug, array $link): void @@ -279,9 +283,8 @@ function renderShareLinkForm(string $slug, array $link): void ]; } } - // TODO: Add a note explaining the jury composition to students: - // who counts as external, what role each member plays, and - // whether this information will be publicly visible. + $helpContent = $helpFn('fieldset_jury'); + include APP_ROOT . '/templates/partials/form/form-help-block.php'; require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?> @@ -289,17 +292,15 @@ function renderShareLinkForm(string $slug, array $link): void @@ -309,10 +310,8 @@ function renderShareLinkForm(string $slug, array $link): void $withAutofocusFn = $shareWithAutofocusFn; $showDescription = false; $defaultAccessTypeId = 2; - // TODO: Add an explanation of each access level (Libre / Interne / Interdit) - // close to the "Visibilité / Accès" select so students understand - // the implications before choosing. Cross-reference the licence - // fieldset below. + $helpContent = $helpFn('fieldset_access'); + include APP_ROOT . '/templates/partials/form/form-help-block.php'; include APP_ROOT . '/templates/partials/form/fieldset-metadata.php'; ?> @@ -322,8 +321,7 @@ function renderShareLinkForm(string $slug, array $link): void
E-mail de confirmation - + Contenus - - + + - - + +

Pages statiques

diff --git a/app/templates/partials/form/form-help-block.php b/app/templates/partials/form/form-help-block.php new file mode 100644 index 0000000..a3be101 --- /dev/null +++ b/app/templates/partials/form/form-help-block.php @@ -0,0 +1,26 @@ +setSafeMode(true); +$html = $pd->text($helpContent); +?> +
+ +
+