diff --git a/TODO.md b/TODO.md index ccd1562..d54bd5c 100644 --- a/TODO.md +++ b/TODO.md @@ -106,3 +106,22 @@ - [x] `templates/admin/index.php` — add "Exporter fichiers" button next to CSV export button - [x] `Database::getAllThesisFilesForExport()` — query all thesis_files + identifier - [x] `docs/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) +- [x] Schema: add `exemplaire_baiu` and `exemplaire_erg` boolean columns to `theses` +- [x] Schema: add `jury_promoteur_ulb` boolean column to `thesis_supervisors` +- [x] Schema: persist `cc4r` checkbox in `theses` table +- [x] Schema: update `v_theses_full` view to include new columns + jury split (interne/externe/ULB) +- [x] Admin edit form: add `jury_points`, `remarks`, `exemplaire_baiu`, `exemplaire_erg` fields (Backoffice fieldset) +- [x] Admin edit form: add `promoteur_ulb` checkbox in jury fieldset +- [x] Admin edit form: reorder fields to match spec layout +- [x] Public TFE fiche: split lecteur·ice(s) into interne/externe +- [x] Public TFE fiche: add promoteur·ice ULB display +- [x] ThesisEditController: handle new fields in save() +- [x] ThesisCreateController: handle CC4r + is_ulb in jury methods +- [x] Database::updateThesis: include new columns (remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc4r) +- [x] Database::setThesisJury: include is_ulb column +- [x] Database::getThesisJury: include is_ulb in SELECT +- [x] StudentEmail: use new jury_lecteurs_internes/externes and jury_promoteurs_ulb columns +- [x] Recapitulatif: show promoteur·ice ULB and lecteur·ices interne/externe +- [x] Migration: `014_tfe_form_fields.sql` — ALTER + view rebuild diff --git a/app/migrations/pending/008_share_links_is_archived.sql b/app/migrations/applied/008_share_links_is_archived.sql similarity index 100% rename from app/migrations/pending/008_share_links_is_archived.sql rename to app/migrations/applied/008_share_links_is_archived.sql diff --git a/app/migrations/pending/009_admin_audit_log.sql b/app/migrations/applied/009_admin_audit_log.sql similarity index 100% rename from app/migrations/pending/009_admin_audit_log.sql rename to app/migrations/applied/009_admin_audit_log.sql diff --git a/app/migrations/pending/010_smtp_notify_email.sql b/app/migrations/applied/010_smtp_notify_email.sql similarity index 100% rename from app/migrations/pending/010_smtp_notify_email.sql rename to app/migrations/applied/010_smtp_notify_email.sql diff --git a/app/migrations/pending/011_thesis_files_sort_and_label.sql b/app/migrations/applied/011_thesis_files_sort_and_label.sql similarity index 100% rename from app/migrations/pending/011_thesis_files_sort_and_label.sql rename to app/migrations/applied/011_thesis_files_sort_and_label.sql diff --git a/app/migrations/pending/012_author_view_order.sql b/app/migrations/applied/012_author_view_order.sql similarity index 100% rename from app/migrations/pending/012_author_view_order.sql rename to app/migrations/applied/012_author_view_order.sql diff --git a/app/migrations/applied/014_tfe_form_fields.sql b/app/migrations/applied/014_tfe_form_fields.sql new file mode 100644 index 0000000..f1977d1 --- /dev/null +++ b/app/migrations/applied/014_tfe_form_fields.sql @@ -0,0 +1,81 @@ +-- Add new columns for the updated TFE form spec +-- Runs during schema validation / migration + +ALTER TABLE theses ADD COLUMN exemplaire_baiu INTEGER NOT NULL DEFAULT 0; +ALTER TABLE theses ADD COLUMN exemplaire_erg INTEGER NOT NULL DEFAULT 0; +ALTER TABLE theses ADD COLUMN cc4r INTEGER NOT NULL DEFAULT 0; +ALTER TABLE theses ADD COLUMN remarks TEXT; + +ALTER TABLE thesis_supervisors ADD COLUMN is_ulb INTEGER NOT NULL DEFAULT 0; + +-- Rebuild the full view to include new columns +DROP VIEW IF EXISTS v_theses_public; +DROP VIEW IF EXISTS v_theses_full; + +CREATE VIEW IF NOT EXISTS v_theses_full AS +SELECT + t.id, + t.identifier, + t.title, + t.subtitle, + t.year, + t.is_doctoral, + t.objet, + o.name as orientation, + ap.name as ap_program, + ft.name as finality_type, + t.synopsis, + t.context_note, + t.duration_minutes, + t.duration_pages, + t.file_size_info, + at.name as access_type, + lt.name as license_type, + t.license_id, + t.access_type_id, + t.jury_points, + t.submitted_at, + t.defense_date, + t.published_at, + t.is_published, + t.baiu_link, + t.banner_path, + t.exemplaire_baiu, + t.exemplaire_erg, + t.cc4r, + t.remarks, + t.jury_note_added, + GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors, + GROUP_CONCAT(DISTINCT s.name) as supervisors, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 0 THEN s.name END) as jury_promoteurs, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 1 THEN s.name END) as jury_promoteurs_ulb, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 0 THEN s.name END) as jury_lecteurs_internes, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 1 THEN s.name END) as jury_lecteurs_externes, + GROUP_CONCAT(DISTINCT l.name) as languages, + GROUP_CONCAT(DISTINCT fmt.name) as formats, + GROUP_CONCAT(DISTINCT tg.name) as keywords, + -- First author's email and contact-visibility flag + (SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_email, + (SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_show_contact +FROM theses t +LEFT JOIN orientations o ON t.orientation_id = o.id +LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id +LEFT JOIN finality_types ft ON t.finality_id = ft.id +LEFT JOIN access_types at ON t.access_type_id = at.id +LEFT JOIN license_types lt ON t.license_id = lt.id +LEFT JOIN thesis_authors ta ON t.id = ta.thesis_id +LEFT JOIN authors a ON ta.author_id = a.id +LEFT JOIN thesis_supervisors ts ON t.id = ts.thesis_id +LEFT JOIN supervisors s ON ts.supervisor_id = s.id +LEFT JOIN thesis_languages tl ON t.id = tl.thesis_id +LEFT JOIN languages l ON tl.language_id = l.id +LEFT JOIN thesis_formats tf ON t.id = tf.thesis_id +LEFT JOIN format_types fmt ON tf.format_id = fmt.id +LEFT JOIN thesis_tags tt ON t.id = tt.thesis_id +LEFT JOIN tags tg ON tt.tag_id = tg.id +GROUP BY t.id; + +CREATE VIEW IF NOT EXISTS v_theses_public AS +SELECT * FROM v_theses_full +WHERE is_published = 1; diff --git a/app/src/Controllers/TfeController.php b/app/src/Controllers/TfeController.php index 293b1ad..a5e6a39 100644 --- a/app/src/Controllers/TfeController.php +++ b/app/src/Controllers/TfeController.php @@ -112,10 +112,12 @@ class TfeController 'accessTypeId' => $accessTypeId, 'isInterdit' => $isInterdit, 'captionFiles' => $captionFiles, - 'juryPresidents' => $juryByRole['presidents'], - 'promoteursInternes' => $juryByRole['internes'], - 'promoteursExternes' => $juryByRole['externes'], - 'juryLecteurs' => $juryByRole['lecteurs'], + 'juryPresidents' => $juryByRole['presidents'], + 'promoteursInternes' => $juryByRole['internes'], + 'promoteursExternes' => $juryByRole['externes'], + 'promoteursUlb' => $juryByRole['ulb'], + 'juryLecteursInternes' => $juryByRole['lecteurs_internes'], + 'juryLecteursExternes' => $juryByRole['lecteurs_externes'], // Restricted files access 'restrictedEnabled' => $restrictedEnabled, @@ -199,14 +201,14 @@ class TfeController } /** - * Split jury members by role and internal/external flag. + * Split jury members by role and internal/external/ULB flags. * * @param array> $jury - * @return array{presidents: list, internes: list, externes: list, lecteurs: list} + * @return array{presidents: list, internes: list, externes: list, ulb: list, lecteurs_internes: list, lecteurs_externes: list} */ private function splitJuryByRole(array $jury): array { - $result = ['presidents' => [], 'internes' => [], 'externes' => [], 'lecteurs' => []]; + $result = ['presidents' => [], 'internes' => [], 'externes' => [], 'ulb' => [], 'lecteurs_internes' => [], 'lecteurs_externes' => []]; foreach ($jury as $member) { $name = $member['name'] ?? ''; @@ -219,14 +221,20 @@ class TfeController $result['presidents'][] = $name; break; case 'promoteur': - if ((int)$member['is_external'] === 1) { + if ((int)($member['is_ulb'] ?? 0) === 1) { + $result['ulb'][] = $name; + } elseif ((int)$member['is_external'] === 1) { $result['externes'][] = $name; } else { $result['internes'][] = $name; } break; case 'lecteur': - $result['lecteurs'][] = $name; + if ((int)$member['is_external'] === 1) { + $result['lecteurs_externes'][] = $name; + } else { + $result['lecteurs_internes'][] = $name; + } break; } } diff --git a/app/src/Controllers/ThesisCreateController.php b/app/src/Controllers/ThesisCreateController.php index bdfddbe..3be3509 100644 --- a/app/src/Controllers/ThesisCreateController.php +++ b/app/src/Controllers/ThesisCreateController.php @@ -322,6 +322,7 @@ class ThesisCreateController 'name' => trim($post['jury_promoteur']), 'role' => 'promoteur', 'is_external' => isset($post['jury_promoteur_ext']) ? 1 : 0, + 'is_ulb' => isset($post['jury_promoteur_ulb']) ? 1 : 0, ]; } foreach ($post['jury_lecteurs'] ?? [] as $i => $name) { diff --git a/app/src/Controllers/ThesisEditController.php b/app/src/Controllers/ThesisEditController.php index f5b8d55..3c2f36f 100644 --- a/app/src/Controllers/ThesisEditController.php +++ b/app/src/Controllers/ThesisEditController.php @@ -127,6 +127,7 @@ class ThesisEditController 'currentContextNote' => $currentContextNote, 'currentAuthorEmail' => $currentAuthorEmail, 'currentAuthorShowContact' => $currentAuthorShowContact, + 'currentRaw' => $rawRow, 'pageTitle' => 'Éditer TFE - ' . htmlspecialchars($thesis['title']), ]; } @@ -166,19 +167,24 @@ class ThesisEditController try { // ── 1. Thesis metadata ──────────────────────────────────────────── $this->db->updateThesis($thesisId, [ - 'title' => trim($post['titre'] ?? ''), - 'subtitle' => trim($post['subtitle'] ?? ''), - 'year' => intval($post['année'] ?? 0), - 'orientation_id' => intval($post['orientation'] ?? 0), - 'ap_program_id' => intval($post['ap'] ?? 0), - 'finality_id' => intval($post['finality'] ?? 0), - 'synopsis' => trim($post['synopsis'] ?? ''), - 'context_note' => trim($post['context_note'] ?? ''), - 'file_size_info' => trim($post['duration_info'] ?? ''), - 'baiu_link' => trim($post['lien'] ?? ''), - 'license_id' => filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null, - 'access_type_id' => filter_var($post['access_type_id'] ?? '', FILTER_VALIDATE_INT) ?: null, - 'is_published' => isset($post['is_published']), + 'title' => trim($post['titre'] ?? ''), + 'subtitle' => trim($post['subtitle'] ?? ''), + 'year' => intval($post['année'] ?? 0), + 'orientation_id' => intval($post['orientation'] ?? 0), + 'ap_program_id' => intval($post['ap'] ?? 0), + 'finality_id' => intval($post['finality'] ?? 0), + 'synopsis' => trim($post['synopsis'] ?? ''), + 'context_note' => trim($post['context_note'] ?? ''), + 'file_size_info' => trim($post['duration_info'] ?? ''), + 'baiu_link' => trim($post['lien'] ?? ''), + 'license_id' => filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null, + 'access_type_id' => filter_var($post['access_type_id'] ?? '', FILTER_VALIDATE_INT) ?: null, + 'is_published' => isset($post['is_published']), + 'remarks' => trim($post['remarks'] ?? ''), + 'jury_points' => $post['jury_points'] ?? null, + 'exemplaire_baiu' => !empty($post['exemplaire_baiu']), + 'exemplaire_erg' => !empty($post['exemplaire_erg']), + 'cc4r' => !empty($post['cc4r']), ]); // ── 2. Authors (alphabetically sorted) ───────────────────────────── @@ -552,6 +558,7 @@ class ThesisEditController 'name' => trim($post['jury_promoteur']), 'role' => 'promoteur', 'is_external' => isset($post['jury_promoteur_ext']) ? 1 : 0, + 'is_ulb' => isset($post['jury_promoteur_ulb']) ? 1 : 0, ]; } diff --git a/app/src/Database.php b/app/src/Database.php index d571963..7c5f1bc 100644 --- a/app/src/Database.php +++ b/app/src/Database.php @@ -1405,7 +1405,7 @@ class Database public function getThesisJury(int $thesisId): array { $stmt = $this->pdo->prepare(' - SELECT s.id, s.name, ts.role, ts.is_external, ts.supervisor_order + SELECT s.id, s.name, ts.role, ts.is_external, ts.is_ulb, ts.supervisor_order FROM thesis_supervisors ts JOIN supervisors s ON s.id = ts.supervisor_id WHERE ts.thesis_id = ? @@ -1428,8 +1428,8 @@ class Database try { $this->pdo->prepare('DELETE FROM thesis_supervisors WHERE thesis_id = ?')->execute([$thesisId]); $stmt = $this->pdo->prepare(' - INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, supervisor_order) - VALUES (?, ?, ?, ?, ?) + INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, is_ulb, supervisor_order) + VALUES (?, ?, ?, ?, ?, ?) '); foreach ($juryMembers as $order => $member) { $name = trim($member['name'] ?? ''); @@ -1440,7 +1440,8 @@ class Database $role = in_array($member['role'], ['president', 'promoteur', 'lecteur']) ? $member['role'] : 'promoteur'; $isExternal = isset($member['is_external']) ? (int)$member['is_external'] : 0; - $stmt->execute([$thesisId, $supervisorId, $role, $isExternal, (int)$order + 1]); + $isUlb = isset($member['is_ulb']) ? (int)$member['is_ulb'] : 0; + $stmt->execute([$thesisId, $supervisorId, $role, $isExternal, $isUlb, (int)$order + 1]); } if (!$alreadyInTransaction) { $this->pdo->commit(); @@ -1650,7 +1651,7 @@ class Database public function getThesisRawFields(int $thesisId): ?array { $stmt = $this->pdo->prepare( - 'SELECT license_id, access_type_id, context_note FROM theses WHERE id = ? LIMIT 1' + 'SELECT license_id, access_type_id, context_note, remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc4r FROM theses WHERE id = ? LIMIT 1' ); $stmt->execute([$thesisId]); $row = $stmt->fetch(); @@ -1784,6 +1785,11 @@ class Database license_id = ?, access_type_id = ?, is_published = ?, + remarks = ?, + jury_points = ?, + exemplaire_baiu = ?, + exemplaire_erg = ?, + cc4r = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? '); @@ -1801,6 +1807,11 @@ class Database $data['license_id'] ?? null, $data['access_type_id'] ?? null, $data['is_published'] ? 1 : 0, + !empty($data['remarks']) ? $data['remarks'] : null, + isset($data['jury_points']) && $data['jury_points'] !== '' ? (float)$data['jury_points'] : null, + !empty($data['exemplaire_baiu']) ? 1 : 0, + !empty($data['exemplaire_erg']) ? 1 : 0, + !empty($data['cc4r']) ? 1 : 0, $thesisId, ]); } diff --git a/app/src/StudentEmail.php b/app/src/StudentEmail.php index a9f1a5c..a56b3f7 100644 --- a/app/src/StudentEmail.php +++ b/app/src/StudentEmail.php @@ -32,8 +32,10 @@ class StudentEmail 'Format(s)' => $thesis['formats'] ?? '', 'Mots-clés' => $thesis['keywords'] ?? '', 'Promoteur·ice(s)' => $thesis['jury_promoteurs'] ?? '', + 'Promoteur·ice(s) ULB' => $thesis['jury_promoteurs_ulb'] ?? '', 'Président·e du jury' => $thesis['jury_president'] ?? '', - 'Lecteurs·rices' => $thesis['jury_lecteurs'] ?? '', + 'Lecteurs·rices (interne)' => $thesis['jury_lecteurs_internes'] ?? '', + 'Lecteurs·rices (externe)' => $thesis['jury_lecteurs_externes'] ?? '', 'Durée / Taille' => $thesis['file_size_info'] ?? '', 'Lien' => $thesis['baiu_link'] ?? '', 'Type d\'accès' => $thesis['access_type'] ?? '', diff --git a/app/storage/schema.sql b/app/storage/schema.sql index f7e8900..d583f72 100644 --- a/app/storage/schema.sql +++ b/app/storage/schema.sql @@ -185,7 +185,7 @@ CREATE TABLE IF NOT EXISTS theses ( license_id INTEGER, -- Jury information - jury_points DECIMAL(4,2), -- Points out of 20 + jury_points DECIMAL(4,2), -- Points out of 20 (backoffice only) jury_note_added BOOLEAN DEFAULT 0, -- Whether jury president added a note -- Publication status @@ -200,6 +200,13 @@ CREATE TABLE IF NOT EXISTS theses ( -- Home page card banner (optional, landscape image) banner_path TEXT, -- path relative to STORAGE_ROOT (e.g. "banners/abc.jpg") + -- Logistics checkboxes (backoffice only) + exemplaire_baiu BOOLEAN DEFAULT 0, -- Physical copy at BAIU + exemplaire_erg BOOLEAN DEFAULT 0, -- Physical copy at ERG + + -- CC4r acceptance (collected in student form) + cc4r BOOLEAN DEFAULT 0 + -- Timestamps created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, @@ -233,6 +240,7 @@ CREATE TABLE IF NOT EXISTS thesis_supervisors ( supervisor_order INTEGER DEFAULT 1, role TEXT NOT NULL DEFAULT 'promoteur', -- 'president'|'promoteur'|'lecteur' is_external INTEGER NOT NULL DEFAULT 0, -- 0 = internal, 1 = external + is_ulb INTEGER NOT NULL DEFAULT 0, -- 1 = ULB promoteur PRIMARY KEY (thesis_id, supervisor_id), FOREIGN KEY (thesis_id) REFERENCES theses(id) ON DELETE CASCADE, FOREIGN KEY (supervisor_id) REFERENCES supervisors(id) ON DELETE CASCADE @@ -527,11 +535,18 @@ SELECT t.is_published, t.baiu_link, t.banner_path, + t.exemplaire_baiu, + t.exemplaire_erg, + t.cc4r, + t.remarks, + t.jury_note_added, GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors, GROUP_CONCAT(DISTINCT s.name) as supervisors, GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president, - GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' THEN s.name END) as jury_promoteurs, - GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' THEN s.name END) as jury_lecteurs, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 0 THEN s.name END) as jury_promoteurs, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 1 THEN s.name END) as jury_promoteurs_ulb, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 0 THEN s.name END) as jury_lecteurs_internes, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 1 THEN s.name END) as jury_lecteurs_externes, GROUP_CONCAT(DISTINCT l.name) as languages, GROUP_CONCAT(DISTINCT fmt.name) as formats, GROUP_CONCAT(DISTINCT tg.name) as keywords, diff --git a/app/templates/admin/edit.php b/app/templates/admin/edit.php index 131b921..6d61503 100644 --- a/app/templates/admin/edit.php +++ b/app/templates/admin/edit.php @@ -44,6 +44,7 @@ $juryPresident = null; $juryPromoteur = null; $juryPromoteurExt = 0; + $juryPromoteurUlb = 0; $juryLecteurs = []; foreach ($jury as $jm) { if ($jm['role'] === 'president') { @@ -51,6 +52,7 @@ } elseif ($jm['role'] === 'promoteur') { $juryPromoteur = $jm['name']; $juryPromoteurExt = (int)$jm['is_external']; + $juryPromoteurUlb = (int)($jm['is_ulb'] ?? 0); } elseif ($jm['role'] === 'lecteur') { $juryLecteurs[] = $jm; } @@ -216,8 +218,54 @@ include APP_ROOT . '/templates/partials/form/fieldset-metadata.php'; ?> - +
+ Backoffice + +
+ + + Note du jury (interne, non visible publiquement). +
+ +
+ + + Notes internes (non visibles publiquement). +
+ +
+ + Case logistique : cocher si un exemplaire physique est disponible à la BAIU. +
+ +
+ + Case logistique : cocher si un exemplaire physique est disponible à l'ERG. +
+ +
+ + Conditions collectives de réutilisation. +
+
+ + +
Note contextuelle
diff --git a/app/templates/admin/recapitulatif.php b/app/templates/admin/recapitulatif.php index 37b58f4..5a71090 100644 --- a/app/templates/admin/recapitulatif.php +++ b/app/templates/admin/recapitulatif.php @@ -57,6 +57,15 @@
Promoteur·ice(s)
+ +
Promoteur·ice(s) ULB
+ + +
Lecteur·ices (interne)
+ + +
Lecteur·ices (externe)
+ diff --git a/app/templates/partials/form/fieldset-tfe-info.php b/app/templates/partials/form/fieldset-tfe-info.php index adffea1..5291e5a 100644 --- a/app/templates/partials/form/fieldset-tfe-info.php +++ b/app/templates/partials/form/fieldset-tfe-info.php @@ -60,7 +60,7 @@ $synopsisExtra = $synopsisExtra ?? ''; include APP_ROOT . '/templates/partials/form/text-field.php'; ?> 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?> @@ -69,9 +69,9 @@ $synopsisExtra = $synopsisExtra ?? ''; - Si cette case est cochée, votre contact apparaîtra sur la page publique de votre TFE. + Si coché, votre contact apparaîtra sur la page publique. L'adresse est toujours conservée en interne.
diff --git a/app/templates/partials/form/jury-fieldset.php b/app/templates/partials/form/jury-fieldset.php index 63372b4..09144d4 100644 --- a/app/templates/partials/form/jury-fieldset.php +++ b/app/templates/partials/form/jury-fieldset.php @@ -5,6 +5,7 @@ * Variables consumed (all optional — defaults to empty/add-mode): * $juryPresident string|null President name * $juryPromoteur string|null Promoteur name + * $juryPromoteurUlb int 1 if promoteur is ULB, 0 otherwise * $juryPromoteurExt int 1 if promoteur is external, 0 otherwise * $juryLecteurs array Each element: ['name' => string, 'is_external' => int] * @@ -16,6 +17,7 @@ $juryPresident = $juryPresident ?? null; $juryPromoteur = $juryPromoteur ?? null; $juryPromoteurExt = $juryPromoteurExt ?? 0; +$juryPromoteurUlb = $juryPromoteurUlb ?? 0; $juryLecteurs = $juryLecteurs ?? []; // In add-mode, repopulate from flash form data when helpers are available. @@ -51,6 +53,11 @@ $juryIdx = max(count($juryLecteurs), 1); aria-label="Promoteur·ice — externe"> Externe +
diff --git a/app/templates/public/tfe.php b/app/templates/public/tfe.php index 0ef64de..4a922e0 100644 --- a/app/templates/public/tfe.php +++ b/app/templates/public/tfe.php @@ -141,6 +141,23 @@ + +
+
Promoteur·ice ULB :
+
'' . + htmlspecialchars($n) . + "", + $promoteursUlb, + ); + echo implode(", ", $links); + ?>
+
+ +
Président·e du jury :
@@ -158,9 +175,9 @@
- +
-
Lecteur·ices :
+
Lecteur·ice(s) interne :
'' . htmlspecialchars($n) . "", - $juryLecteurs, + $juryLecteursInternes, + ); + echo implode(", ", $links); + ?>
+
+ + + +
+
Lecteur·ice(s) externe :
+
'' . + htmlspecialchars($n) . + "", + $juryLecteursExternes, ); echo implode(", ", $links); ?>