feat: multi-type file upload with sort order, labels, and expanded MIME support

- DB migration 007: add sort_order + display_label to thesis_files
- Database: getThesisFiles ordered by sort_order; insertThesisFile accepts label/order;
  new reorderThesisFiles() and updateThesisFileLabel() methods
- ThesisCreateController + ThesisEditController: expand allowed MIME/exts to include
  audio (mp3/ogg/wav/flac/aac/m4a), video (webm/mov/ogv), image (gif/webp),
  archives (tar/gz), any-ext via octet-stream; max size raised to 500 MB;
  accept file_labels[] and file_orders[] POST fields; detectFileType() helper
- MediaController: expanded MIME allowlist; HTTP Range support for audio/video;
  force-download for unknown types; inline for known displayable types
- fieldset-files.php: sortable queue UI with SortableJS, per-file labels, 500 MB hint
- templates/admin/edit.php: existing files as sortable list with drag handles,
  type icons, label inputs, delete checkboxes, hidden sort-order fields
- file-upload-queue.js: new JS replacing file-preview.js — sortable new-file queue,
  per-file labels, hidden order fields on submit, backward-compat legacy preview
- tfe.php: renders audio (<audio>), all video formats, images, PDF, and
  download-only 'other' files; reads display_label; sorted by sort_order
- tfe.css + form.css: styles for audio player, download files, sortable queue,
  drag handles, file type badges, label inputs
- .htaccess + .user.ini: upload_max_filesize=512M / post_max_size=520M
This commit is contained in:
Pontoporeia
2026-04-30 13:07:09 +02:00
parent 2188ff5479
commit a83dc1c74e
17 changed files with 1026 additions and 274 deletions

View File

@@ -244,7 +244,8 @@ function renderShareLinkForm(string $slug, array $link): void
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="<?= App::assetV('/assets/css/common.css') ?>">
<link rel="stylesheet" href="<?= App::assetV('/assets/css/form.css') ?>">
<script src="<?= App::assetV('/assets/js/file-preview.js') ?>" defer></script>
<script src="<?= App::assetV('/assets/js/sortable.min.js') ?>" defer></script>
<script src="<?= App::assetV('/assets/js/file-upload-queue.js') ?>" defer></script>
</head>
<body class="student-body">
<main id="main-content">