refactor: unify edit mode Format+Fichiers with add/partage HTMX fragment

- Edit mode now uses the same fichiers-fragment.php as add and partage,
  instead of duplicating the format checkboxes + new-file upload + website
  URL fieldsets.
- Edit-only elements (existing files list, cover replace) stay in
  a separate #edit-existing-files-block below the shared fragment.
- Removed .zip/.tar/.gz from the main TFE upload accept in both
  fichiers-fragment.php and fieldset-files.php. Archives go only
  in the Annexes file input.
- Removed admin/format-website-fragment.php dependency from edit
  (no longer needed — the shared fragment handles website too).

fix: jury repop crash + hx-preserve on file inputs, remove zip/tar from tfe accept

- Jury fieldset add-mode repopulation now handles both scalar (legacy)
  and array (new dynamic multi-row) values for jury_promoteur and
  jury_promoteur_ulb_name. htmlspecialchars() was choking on array value.
- All file inputs in fichiers-fragment.php wrapped in hx-preserve
  containers so HTMX swaps don't wipe user-selected files when toggling
  formats or the annexes checkbox.
- Removed .zip/.tar/.gz from main TFE file accept — archives only via
  annexes input (which already had multiple + correct accept).
- Edit mode now reuses the same fichiers-fragment.php fragment.

fix: file inputs re-initialize after HTMX swap via inline script

- Exposed window.XamxamInitFileUploads from file-upload-queue.js IIFE
  so HTMX fragments can trigger re-binding without a global listener.
- fichiers-fragment.php emits <script>XamxamInitFileUploads()</script>
  at the end of the #format-fichiers-block fragment.
- Removed hx-preserve wrappers — they prevented re-render after
  format/annexes toggles changed visible inputs.
- This also fixes .zip removal from TFE accept and jury repopulation
  array crash from the previous commit.

refactor: simplify file-upload-queue.js, remove file-preview.js

- file-upload-queue.js rewritten from ~250 lines to ~120 lines:
  no more DataTransfer machinery, no IIFE wrapper, uses .onchange
  instead of addEventListener for simpler HTMX re-init.
- window.XamxamInitFileUploads is the function itself (not an IIFE export).
- Merged file-preview.js functionality into file-upload-queue.js
  (single-file .data-preview handling). Deleted file-preview.js.
- fichiers-fragment.php inline script calls XamxamInitFileUploads()
  after every HTMX swap (same as before).

debug: add console.log to file-upload-queue.js for file input behavior

Adds logging at key points to diagnose why only one file is displayed:
- XamxamInitFileUploads called
- TFE queue picker init (id, multiple attribute state)
- onchange event (files count, names)
- fileArray post-concat length
- Single-file preview bindings (id, multiple attribute)

Remove after debug session.
This commit is contained in:
Pontoporeia
2026-05-08 17:31:17 +02:00
parent 8f4f9d00b4
commit 77fd282e29
10 changed files with 173 additions and 337 deletions

View File

@@ -22,6 +22,7 @@
<tr>
<th scope="col">Lien</th>
<th scope="col">Objet</th>
<th scope="col">Année</th>
<th scope="col">Statut</th>
<th scope="col">Mot de passe</th>
<th scope="col">Utilisations</th>
@@ -40,6 +41,9 @@
$created = date('d/m/Y H:i', strtotime($link['created_at']));
$expires = $link['expires_at'] ? date('d/m/Y', strtotime($link['expires_at'])) : '-';
$hasLinkPassword = !empty($link['password_hash']);
$linkName = $link['name'] ?? '';
$linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
$linkLockedYear = $link['locked_year'] ?? null;
?>
<tr>
<td>
@@ -53,6 +57,13 @@
<span style="color:var(--text-secondary);font-size:var(--step--2);">Tous</span>
<?php endif; ?>
</td>
<td>
<?php if ($link['locked_year']): ?>
<span class="status-badge" style="background:var(--accent-green-muted-bg, #e6f7ec);color:var(--accent-green, #1a7f4b);border:1px solid var(--accent-green, #1a7f4b);">🔒 <?= htmlspecialchars((string)$link['locked_year']) ?></span>
<?php else: ?>
<span style="color:var(--text-secondary);font-size:var(--step--2);">Libre</span>
<?php endif; ?>
</td>
<td>
<?php if ($isExpired): ?>
<span class="status-badge status-pending"><?= $statusLabel ?></span>
@@ -86,6 +97,11 @@
<?= $link['is_active'] ? '⏸' : '▶' ?>
</button>
</form>
<button type="button" class="btn btn--sm btn--yellow admin-btn-edit"
onclick="openEditLinkDialog(<?= $link['id'] ?>, <?= htmlspecialchars(json_encode($linkName), ENT_QUOTES) ?>, <?= htmlspecialchars(json_encode($linkExpiresVal), ENT_QUOTES) ?>, <?= htmlspecialchars(json_encode($linkLockedYear), ENT_QUOTES) ?>)"
title="Modifier le lien">
✏️
</button>
<button type="button" class="btn btn--sm btn--yellow admin-btn-edit"
onclick="openPasswordDialog(<?= $link['id'] ?>, <?= $hasLinkPassword ? 'true' : 'false' ?>)"
title="Modifier le mot de passe">
@@ -324,6 +340,19 @@
<input type="datetime-local" id="create-expires" name="expires_at">
<small>Laissez vide pour qu'il n'expire jamais.</small>
</div>
<fieldset>
<legend>Année académique verrouillée</legend>
<div>
<label for="create-locked-year">Année (optionnel)</label>
<input type="number" id="create-locked-year" name="locked_year"
min="2000" max="<?= date('Y') + 3 ?>" placeholder="<?= date('Y') ?>">
<small style="max-width:42ch;">
Si renseignée, le formulaire masquera le champ Année et forcera cette valeur.
Ainsi les identifiants TFE (ex: <strong><?= date('Y') ?>-001</strong>) correspondront
à la bonne année. Laissez vide pour laisser l'étudiant·e choisir.
</small>
</div>
</fieldset>
<div class="admin-form-footer">
<button type="submit" class="btn btn--primary">Créer le lien</button>
<button type="button" class="btn btn--secondary"