mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
schema: validate against new TFE field spec
- add exemplaire_baiu, exemplaire_erg, cc4r, remarks; - add is_ulb to jury; - split jury_lecteurs into interne/externe in view; - refactor admin edit form with backoffice fields; - update public fiche to show promoteur ULB and split lecteurs
This commit is contained in:
19
TODO.md
19
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
|
||||
|
||||
81
app/migrations/applied/014_tfe_form_fields.sql
Normal file
81
app/migrations/applied/014_tfe_form_fields.sql
Normal file
@@ -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;
|
||||
@@ -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<int, array<string, mixed>> $jury
|
||||
* @return array{presidents: list<string>, internes: list<string>, externes: list<string>, lecteurs: list<string>}
|
||||
* @return array{presidents: list<string>, internes: list<string>, externes: list<string>, ulb: list<string>, lecteurs_internes: list<string>, lecteurs_externes: list<string>}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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'] ?? '',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
?>
|
||||
|
||||
<!-- ═══════════════════ Note contextuelle ═══════════════════ -->
|
||||
<!-- ═══════════════════ Backoffice ═══════════════════ -->
|
||||
<fieldset>
|
||||
<legend>Backoffice</legend>
|
||||
|
||||
<div class="admin-form-group">
|
||||
<label for="jury_points">Points :</label>
|
||||
<input type="number" id="jury_points" name="jury_points"
|
||||
value="<?= htmlspecialchars($currentRaw['jury_points'] ?? '') ?>"
|
||||
step="0.01" min="0" max="20" placeholder="sur 20">
|
||||
<small>Note du jury (interne, non visible publiquement).</small>
|
||||
</div>
|
||||
|
||||
<div class="admin-form-group">
|
||||
<label for="remarks">Remarques :</label>
|
||||
<textarea id="remarks" name="remarks" rows="4"><?= htmlspecialchars($currentRaw['remarks'] ?? '') ?></textarea>
|
||||
<small>Notes internes (non visibles publiquement).</small>
|
||||
</div>
|
||||
|
||||
<div class="admin-form-group">
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="exemplaire_baiu" value="1"
|
||||
<?= !empty($currentRaw['exemplaire_baiu']) ? 'checked' : '' ?>>
|
||||
Exemplaire physique BAIU
|
||||
</label>
|
||||
<small>Case logistique : cocher si un exemplaire physique est disponible à la BAIU.</small>
|
||||
</div>
|
||||
|
||||
<div class="admin-form-group">
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="exemplaire_erg" value="1"
|
||||
<?= !empty($currentRaw['exemplaire_erg']) ? 'checked' : '' ?>>
|
||||
Exemplaire physique ERG
|
||||
</label>
|
||||
<small>Case logistique : cocher si un exemplaire physique est disponible à l'ERG.</small>
|
||||
</div>
|
||||
|
||||
<div class="admin-form-group">
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="cc4r" value="1"
|
||||
<?= !empty($currentRaw['cc4r']) ? 'checked' : '' ?>>
|
||||
CC4r accepté
|
||||
</label>
|
||||
<small>Conditions collectives de réutilisation.</small>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- ═══════════════════ Note contextuelle ═══════════════════ -->
|
||||
<fieldset id="section-context-note">
|
||||
<legend>Note contextuelle</legend>
|
||||
<div>
|
||||
<label for="context_note">Note contextuelle :</label>
|
||||
|
||||
@@ -57,6 +57,15 @@
|
||||
<?php if ($thesis['supervisors']): ?>
|
||||
<dt>Promoteur·ice(s)</dt><dd><?= htmlspecialchars($thesis['supervisors']) ?></dd>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($thesis['jury_promoteurs_ulb'])): ?>
|
||||
<dt>Promoteur·ice(s) ULB</dt><dd><?= htmlspecialchars($thesis['jury_promoteurs_ulb']) ?></dd>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($thesis['jury_lecteurs_internes'])): ?>
|
||||
<dt>Lecteur·ices (interne)</dt><dd><?= htmlspecialchars($thesis['jury_lecteurs_internes']) ?></dd>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($thesis['jury_lecteurs_externes'])): ?>
|
||||
<dt>Lecteur·ices (externe)</dt><dd><?= htmlspecialchars($thesis['jury_lecteurs_externes']) ?></dd>
|
||||
<?php endif; ?>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ $synopsisExtra = $synopsisExtra ?? '';
|
||||
include APP_ROOT . '/templates/partials/form/text-field.php';
|
||||
?>
|
||||
<?php
|
||||
$name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = $oldFn('mail');
|
||||
$name = 'mail'; $label = 'Contact visible (optionnel) [mail/site/insta/etc.] :'; $value = $oldFn('mail');
|
||||
$attrs = ['autocomplete' => 'email'];
|
||||
include APP_ROOT . '/templates/partials/form/text-field.php';
|
||||
?>
|
||||
@@ -69,9 +69,9 @@ $synopsisExtra = $synopsisExtra ?? '';
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="contact_public" value="1"
|
||||
<?= !empty($formData['contact_public']) ? 'checked' : '' ?>>
|
||||
Je veux que mon contact soit accessible à toustes depuis la plateforme xamxam
|
||||
Rendre mon contact visible publiquement sur la fiche du TFE
|
||||
</label>
|
||||
<small>Si cette case est cochée, votre contact apparaîtra sur la page publique de votre TFE.</small>
|
||||
<small>Si coché, votre contact apparaîtra sur la page publique. L'adresse est toujours conservée en interne.</small>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -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);
|
||||
<?= $juryPromoteurExt ? 'checked' : '' ?>
|
||||
aria-label="Promoteur·ice — externe"> Externe
|
||||
</label>
|
||||
<label class="admin-checkbox-label admin-jury-ext">
|
||||
<input type="checkbox" name="jury_promoteur_ulb" value="1"
|
||||
<?= $juryPromoteurUlb ? 'checked' : '' ?>
|
||||
aria-label="Promoteur·ice — ULB"> ULB
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -141,6 +141,23 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($promoteursUlb)): ?>
|
||||
<div>
|
||||
<dt>Promoteur·ice ULB :</dt>
|
||||
<dd><?php
|
||||
$links = array_map(
|
||||
fn($n) => '<a href="/search?query=' .
|
||||
urlencode($n) .
|
||||
'">' .
|
||||
htmlspecialchars($n) .
|
||||
"</a>",
|
||||
$promoteursUlb,
|
||||
);
|
||||
echo implode(", ", $links);
|
||||
?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($juryPresidents)): ?>
|
||||
<div>
|
||||
<dt>Président·e du jury :</dt>
|
||||
@@ -158,9 +175,9 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($juryLecteurs)): ?>
|
||||
<?php if (!empty($juryLecteursInternes)): ?>
|
||||
<div>
|
||||
<dt>Lecteur·ices :</dt>
|
||||
<dt>Lecteur·ice(s) interne :</dt>
|
||||
<dd><?php
|
||||
$links = array_map(
|
||||
fn($n) => '<a href="/search?query=' .
|
||||
@@ -168,7 +185,24 @@
|
||||
'">' .
|
||||
htmlspecialchars($n) .
|
||||
"</a>",
|
||||
$juryLecteurs,
|
||||
$juryLecteursInternes,
|
||||
);
|
||||
echo implode(", ", $links);
|
||||
?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($juryLecteursExternes)): ?>
|
||||
<div>
|
||||
<dt>Lecteur·ice(s) externe :</dt>
|
||||
<dd><?php
|
||||
$links = array_map(
|
||||
fn($n) => '<a href="/search?query=' .
|
||||
urlencode($n) .
|
||||
'">' .
|
||||
htmlspecialchars($n) .
|
||||
"</a>",
|
||||
$juryLecteursExternes,
|
||||
);
|
||||
echo implode(", ", $links);
|
||||
?></dd>
|
||||
|
||||
Reference in New Issue
Block a user