refactor form structure per new spec + fix

- split jury into interne/externe/ULB,
- remove president from student form,
- add language_autre,
- split duration into pages+minutes+annexes,
- move licence to degrés d'ouverture with CC2r,
- add license_custom,
- filter PACS from student AP list,
- editable généralités help block,
- Libre toggle per settings

Fix:
- missing comma after cc4r column in schema.sql
- remove duplicate form footer from partage template
- remove couverture from student files fieldset; add promoteur ULB conditional disable via JS on Approfondi
- promoteur ULB: remove 'si applicable', make required when visible
This commit is contained in:
Pontoporeia
2026-05-07 17:52:46 +02:00
parent dce0e0b301
commit 24d68dda59
21 changed files with 694 additions and 381 deletions

View File

@@ -12,9 +12,7 @@
<!-- ═══════════════════ Informations du TFE ═══════════════════ -->
<?php
// Build a merged $formData that includes contact_public for the fieldset partial.
$formData = array_merge($formData ?? [], ['contact_public' => $currentAuthorShowContact ?? false]);
// Build old()-compatible callable from the already-loaded $thesis data.
$editOldFn = function (string $key, string $default = '') use ($thesis, $formData, $currentAuthorEmail) {
if (!empty($formData[$key])) return htmlspecialchars($formData[$key]);
$map = [
@@ -35,30 +33,56 @@
$oldFn = $editOldFn;
$withAutofocusFn = $editWithAutofocusFn;
include APP_ROOT . '/templates/partials/form/fieldset-tfe-info.php';
// Restore $formData to original for downstream partials.
$formData = $_SESSION['form_data'] ?? [];
?>
<!-- ═══════════════════ Composition du jury ═══════════════════ -->
<?php
$juryPresident = null;
$juryPromoteur = null;
$juryPromoteurExt = 0;
$juryPromoteurUlb = 0;
$juryLecteurs = [];
foreach ($jury as $jm) {
if ($jm['role'] === 'president') {
$juryPresident = $jm['name'];
} elseif ($jm['role'] === 'promoteur') {
$juryPromoteur = $jm['name'];
$juryPromoteurExt = (int)$jm['is_external'];
$juryPromoteurUlb = (int)($jm['is_ulb'] ?? 0);
} elseif ($jm['role'] === 'lecteur') {
$juryLecteurs[] = $jm;
}
}
require APP_ROOT . '/templates/partials/form/jury-fieldset.php';
?>
<!-- Contact public checkbox (admin) -->
<fieldset>
<legend>Contact</legend>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="contact_public" value="1"
<?= !empty($formData['contact_public']) || $currentAuthorShowContact ? 'checked' : '' ?>>
Rendre le contact visible publiquement sur la fiche du TFE
</label>
<small>L'adresse est toujours conservée en interne comme contact de référence.</small>
</div>
</fieldset>
<!-- ═══════════════════ Langue(s) ═══════════════════ -->
<fieldset>
<legend>Langue(s)</legend>
<?php
$checkedLanguages = $formData['languages'] ?? $currentLanguages;
$name = 'languages'; $label = 'Langue(s) du TFE :'; $options = $languages; $checked = $checkedLanguages; $required = true;
include APP_ROOT . '/templates/partials/form/checkbox-list.php';
?>
<?php $name = 'language_autre'; $label = 'Autre(s) langue(s) :'; $value = old('language_autre'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
</fieldset>
<!-- ═══════════════════ Format(s) ═══════════════════ -->
<fieldset>
<legend>Format(s)</legend>
<?php
$checkedFormats = $formData['formats'] ?? $currentFormats;
$name = 'formats'; $label = 'Format(s) du TFE :'; $options = $formatTypes; $checked = $checkedFormats;
include APP_ROOT . '/templates/partials/form/checkbox-list.php';
?>
</fieldset>
<!-- ═══════════════════ Mots-clés ═══════════════════ -->
<fieldset>
<legend>Mots-clés</legend>
<?php
$editKwFormData = ['tag' => $thesis['keywords'] ?? ''];
$editKwOldFn = fn(string $key, string $default = '') => isset($editKwFormData[$key]) ? htmlspecialchars((string)$editKwFormData[$key]) : $default;
$oldFn = $editKwOldFn; $withAutofocusFn = $editWithAutofocusFn; $formData = $editKwFormData;
$name = 'tag'; $label = 'Mots-clés (max 10) :'; $value = $editKwOldFn('tag');
$placeholder = 'sociologie, anthropologie, ...';
$hint = 'Séparez par des virgules. Max 10 mots-clés.';
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
</fieldset>
<!-- ═══════════════════ Cadre académique ═══════════════════ -->
<?php
@@ -67,14 +91,10 @@
'orientation' => $thesis['orientation'],
'ap' => $thesis['ap_program'],
'finality' => $thesis['finality_type'],
'languages' => $currentLanguages,
'formats' => $currentFormats,
'tag' => $thesis['keywords'] ?? '',
];
$editAcademicOldFn = function (string $key, string $default = '') use ($editFormData) {
return isset($editFormData[$key]) && !is_array($editFormData[$key])
? htmlspecialchars((string)$editFormData[$key])
: $default;
? htmlspecialchars((string)$editFormData[$key]) : $default;
};
$oldFn = $editAcademicOldFn;
$withAutofocusFn = $editWithAutofocusFn;
@@ -82,6 +102,36 @@
include APP_ROOT . '/templates/partials/form/fieldset-academic.php';
?>
<!-- ═══════════════════ Composition du jury ═══════════════════ -->
<?php
$juryPromoteur = null;
$juryPromoteurUlb = null;
$lecteursInternes = [];
$lecteursExternes = [];
$juryPresident = null;
foreach ($jury as $jm) {
if ($jm['role'] === 'president') {
$juryPresident = $jm['name'];
} elseif ($jm['role'] === 'promoteur') {
if (($jm['is_ulb'] ?? 0) == 1) {
$juryPromoteurUlb = $jm['name'];
} else {
$juryPromoteur = $jm['name'];
}
} elseif ($jm['role'] === 'lecteur') {
if (($jm['is_external'] ?? 0) == 1) {
$lecteursExternes[] = $jm;
} else {
$lecteursInternes[] = $jm;
}
}
}
$showPresident = true;
$showPromoteurUlb = true;
$promoteurUlbConditional = false;
require APP_ROOT . '/templates/partials/form/jury-fieldset.php';
?>
<!-- ═══════════════════ Fichiers ═══════════════════ -->
<fieldset>
<legend>Fichiers</legend>
@@ -101,7 +151,7 @@
<?php endif; ?>
<input type="file" id="couverture" name="couverture" accept="image/jpeg,image/png" data-preview="fp-couverture">
<div id="fp-couverture" class="file-preview-list" aria-live="polite"></div>
<small><?= empty($currentCover) ? 'JPG, PNG. Max 20 MB.' : 'Laisser vide pour conserver la couverture actuelle. JPG, PNG. Max 20 MB.' ?></small>
<small><?= empty($currentCover) ? 'JPG, PNG. Format 4:3 recommandé. Max 20 MB.' : 'Laisser vide pour conserver la couverture actuelle. JPG, PNG. Max 20 MB.' ?></small>
</div>
</div>
@@ -127,13 +177,9 @@
};
?>
<li class="admin-file-list-item" data-file-id="<?= (int)$f['id'] ?>">
<!-- Hidden field carries sort order (updated by JS) -->
<input type="hidden" name="file_sort_order[]" value="<?= (int)$f['id'] ?>">
<span class="admin-file-drag-handle" title="Réordonner">⠿</span>
<span class="admin-file-icon-col"><?= $fIcon ?></span>
<span class="admin-file-info">
<a href="/media.php?path=<?= urlencode($f['file_path']) ?>" target="_blank" rel="noopener" class="admin-file-name">
<?= htmlspecialchars($f['file_name'] ?? basename($f['file_path'])) ?>
@@ -144,16 +190,13 @@
<span class="admin-file-size"><?= number_format($f['file_size'] / 1024 / 1024, 2) ?> MB</span>
<?php endif; ?>
</span>
<input type="text"
name="file_label[<?= (int)$f['id'] ?>]"
<input type="text" name="file_label[<?= (int)$f['id'] ?>]"
value="<?= htmlspecialchars($f['display_label'] ?? '') ?>"
placeholder="Légende / description (optionnel)"
class="admin-file-label-input">
</span>
<label class="admin-checkbox-label admin-file-delete">
<input type="checkbox" name="delete_files[]" value="<?= (int)$f['id'] ?>">
Supprimer
<input type="checkbox" name="delete_files[]" value="<?= (int)$f['id'] ?>"> Supprimer
</label>
</li>
<?php endforeach; ?>
@@ -183,8 +226,7 @@
<div class="admin-file-input">
<?php if (!empty($thesis['banner_path'])): ?>
<div class="admin-banner-preview">
<img src="/media.php?path=<?= urlencode($thesis['banner_path']) ?>"
alt="Bannière actuelle">
<img src="/media.php?path=<?= urlencode($thesis['banner_path']) ?>" alt="Bannière actuelle">
<label class="admin-checkbox-label">
<input type="checkbox" name="remove_banner" value="1"> Supprimer la bannière
</label>
@@ -200,24 +242,47 @@
<!-- ═══════════════════ Métadonnées complémentaires ═══════════════════ -->
<?php
$editMetaFormData = [
'license_id' => $currentLicenseId,
'duration_info' => $thesis['file_size_info'] ?? '',
'lien' => $thesis['baiu_link'] ?? '',
'access_type_id' => $currentAccessTypeId,
'duration_pages' => $currentRaw['duration_pages'] ?? '',
'duration_minutes' => $currentRaw['duration_minutes'] ?? '',
'lien' => $thesis['baiu_link'] ?? '',
];
$editMetaOldFn = function (string $key, string $default = '') use ($editMetaFormData) {
return isset($editMetaFormData[$key])
? htmlspecialchars((string)$editMetaFormData[$key])
: $default;
return isset($editMetaFormData[$key]) ? htmlspecialchars((string)$editMetaFormData[$key]) : $default;
};
$oldFn = $editMetaOldFn;
$withAutofocusFn = $editWithAutofocusFn;
$formData = $editMetaFormData;
$defaultAccessTypeId = $currentAccessTypeId;
$showDescription = true;
$oldFn = $editMetaOldFn;
$withAutofocusFn = $editWithAutofocusFn;
$formData = $editMetaFormData;
include APP_ROOT . '/templates/partials/form/fieldset-metadata.php';
?>
<!-- ═══════════════════ Degrés d'ouverture et licences ═══════════════════ -->
<?php
$formData = $_SESSION['form_data'] ?? [];
$libreEnabled = true; // always shown in admin
$interneEnabled = true;
$interditEnabled = true;
$generalitiesHtml = $helpFn('fieldset_generalites');
$defaultAccessTypeId = $currentAccessTypeId ?? 2;
$formData['access_type_id'] = $currentAccessTypeId;
$formData['license_id'] = $currentLicenseId;
$formData['license_custom'] = $currentRaw['license_custom'] ?? '';
$formData['cc2r'] = $currentRaw['cc4r'] ?? false;
include APP_ROOT . '/templates/partials/form/fieldset-licence-explanation.php';
?>
<!-- ═══════════════════ Note contextuelle ═══════════════════ -->
<fieldset>
<legend>Note contextuelle</legend>
<div>
<label for="context_note">Note contextuelle :</label>
<div>
<textarea id="context_note" name="context_note"
rows="4" maxlength="1500"><?= htmlspecialchars($currentContextNote ?? '') ?></textarea>
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
</div>
</div>
</fieldset>
<!-- ═══════════════════ Backoffice ═══════════════════ -->
<fieldset>
<legend>Backoffice</legend>
@@ -253,28 +318,6 @@
</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>
<div>
<textarea id="context_note" name="context_note"
rows="4" maxlength="1500"><?= htmlspecialchars($currentContextNote ?? '') ?></textarea>
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
</div>
</div>
</fieldset>
<!-- ═══════════════════ Publication ════════════════════════ -->
@@ -289,6 +332,5 @@
</div>
</fieldset>
</form>
</main>