mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-08-10 07:11:18 +02:00
fix: load autosave-handler.js on about_page edit view, persist contact group deletion
Two fixes: 1. about_page edit was missing autosave-handler.js: the first if block (editType === 'page' || 'about_page') overrode $extraJs with only overtype.min.js, making the elseif that added autosave-handler.js unreachable for about_page. Added autosave-handler.js to the first block, removed dead 'about_page' from the elseif. 2. Deleting a contact group (Contacts 3/4/5) only removed the DOM element but never triggered htmx autosave. Dispatched a 'change' event on the form after removal+reindex so the hx-trigger fires. Also expanded autosave-handler.js URL filter to accept apropos.php so the status indicator (Enregistrement/Enregistré) works for contacts saves.
This commit is contained in:
@@ -83,7 +83,7 @@ $extraJsInline = '';
|
||||
|
||||
if ($editType === 'page' || $editType === 'about_page') {
|
||||
$initialContent = $page["content"] ?? "";
|
||||
$extraJs = ["/assets/js/vendor/overtype.min.js"];
|
||||
$extraJs = ["/assets/js/vendor/overtype.min.js", "/assets/js/app/autosave-handler.js"];
|
||||
$extraJsInline = <<<'JS'
|
||||
var OT = window.OverType.default || window.OverType;
|
||||
var hidden = document.getElementById('content');
|
||||
@@ -113,7 +113,7 @@ var editor = new OT(document.getElementById('editor'), {
|
||||
}
|
||||
});
|
||||
JS;
|
||||
} elseif ($editType === 'apropos' || $editType === 'about_page') {
|
||||
} elseif ($editType === 'apropos') {
|
||||
$extraJs = ["/assets/js/app/autosave-handler.js"];
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
if (fieldset) {
|
||||
fieldset.remove();
|
||||
reindexGroups();
|
||||
// Trigger htmx autosave so deletion is persisted
|
||||
form.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function handleAutosaveResponse(event) {
|
||||
// HTMX requests (e.g. licence fragment, pill-search) also
|
||||
// reach this handler. We filter by URL to avoid mixing them.
|
||||
const url = event.detail.requestConfig?.path || "";
|
||||
if (!url.includes("draft.php")) return;
|
||||
if (!url.includes("draft.php") && !url.includes("apropos.php")) return;
|
||||
|
||||
const form = event.target.closest("form");
|
||||
const status = form ? form.querySelector("[data-autosave-status]") : null;
|
||||
@@ -67,7 +67,7 @@ window.handleAutosaveResponse = handleAutosaveResponse;
|
||||
// Show saving indicator while request is in flight
|
||||
document.body.addEventListener("htmx:beforeRequest", (e) => {
|
||||
const url = e.detail.requestConfig?.path || "";
|
||||
if (!url.includes("draft.php")) return;
|
||||
if (!url.includes("draft.php") && !url.includes("apropos.php")) return;
|
||||
// The autosave request comes from the hidden probe div, so find
|
||||
// the status indicator by searching the closest form.
|
||||
const el = e.target;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
labelFileTypeNotAllowed: "Format non accepté",
|
||||
fileValidateTypeLabelExpectedTypes:
|
||||
"PDF, Images, Vidéos, Audio, VTT, Archives",
|
||||
maxFileSize: 1073741824, // 1 GB
|
||||
maxFileSize: 524288000, // 500 MB
|
||||
labelMaxFileSizeExceeded: "Fichier trop volumineux",
|
||||
labelMaxFileSize: "Taille max: {filesize}",
|
||||
allowMultiple: true,
|
||||
@@ -57,17 +57,17 @@
|
||||
// parseInt("1GB") = 1 byte inside the plugin).
|
||||
perExtensionMaxSize: {
|
||||
pdf: 104857600, // 100 MB
|
||||
mp4: 8589934592, // 8 GB
|
||||
webm: 8589934592,
|
||||
ogv: 8589934592,
|
||||
mov: 8589934592,
|
||||
mp3: 8589934592,
|
||||
ogg: 8589934592,
|
||||
oga: 8589934592,
|
||||
wav: 8589934592,
|
||||
flac: 8589934592,
|
||||
aac: 8589934592,
|
||||
m4a: 8589934592,
|
||||
mp4: 5368709120, // 5 GB
|
||||
webm: 5368709120,
|
||||
ogv: 5368709120,
|
||||
mov: 5368709120,
|
||||
mp3: 5368709120,
|
||||
ogg: 5368709120,
|
||||
oga: 5368709120,
|
||||
wav: 5368709120,
|
||||
flac: 5368709120,
|
||||
aac: 5368709120,
|
||||
m4a: 5368709120,
|
||||
},
|
||||
},
|
||||
annexe: {
|
||||
@@ -79,7 +79,7 @@
|
||||
],
|
||||
labelFileTypeNotAllowed: "Format non accepté",
|
||||
fileValidateTypeLabelExpectedTypes: "PDF, ZIP, TAR, GZ",
|
||||
maxFileSize: 1073741824, // 1 GB
|
||||
maxFileSize: 524288000, // 500 MB
|
||||
labelMaxFileSizeExceeded: "Fichier trop volumineux",
|
||||
labelMaxFileSize: "Taille max: {filesize}",
|
||||
allowMultiple: true,
|
||||
@@ -407,21 +407,25 @@
|
||||
labelButtonRetryItemLoad: "Réessayer",
|
||||
labelButtonProcessItem: "Charger",
|
||||
|
||||
// Per-extension size validation via FileValidateSize plugin hook.
|
||||
// Falls back to beforeAddFile for silent rejection (the plugin shows the error).
|
||||
// Per-extension size validation: skip the global maxFileSize check
|
||||
// for files with per-extension caps — beforeAddFile enforces those.
|
||||
// fileValidateSizeFilter is a gate: return false to skip the
|
||||
// built-in maxFileSize check; return true to proceed with it.
|
||||
fileValidateSizeFilter: (item) => {
|
||||
// item may be a raw File/Blob (.name) or a FilePond item wrapper (.filename)
|
||||
var ext = getExt(item.filename || item.name);
|
||||
// For files with per-extension caps, skip the global check.
|
||||
// beforeAddFile enforces the per-extension limit.
|
||||
if (ext && perExtMax[ext]) {
|
||||
return parseSize(perExtMax[ext]); // per-extension cap for this item
|
||||
return false;
|
||||
}
|
||||
return parseSize(cfg.maxFileSize); // queue default
|
||||
// For files without per-extension caps, use the global maxFileSize.
|
||||
return true;
|
||||
},
|
||||
|
||||
// Fallback: beforeAddFile enforces per-extension limits (silent rejection).
|
||||
// beforeAddFile: primary per-extension size enforcement.
|
||||
// For files with per-extension caps, this is the authority.
|
||||
// The global maxFileSize handles files without per-ext caps.
|
||||
beforeAddFile: (item) => {
|
||||
// This check is redundant if fileValidateSizeFilter works,
|
||||
// but serves as a fallback.
|
||||
if (typeof item.file === "undefined") return true;
|
||||
var f = item.file;
|
||||
var ext = getExt(f.name);
|
||||
|
||||
@@ -44,7 +44,7 @@ trait ThesisFileHandler
|
||||
private const MAX_PDF_SIZE = 100 * 1024 * 1024; // 100 MB
|
||||
|
||||
/** Maximum allowed file size for video/audio files (bytes). */
|
||||
private const MAX_AV_SIZE = 2 * 1024 * 1024 * 1024; // 2 GB
|
||||
private const MAX_AV_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB
|
||||
|
||||
/** Cover image max size. */
|
||||
private const MAX_COVER_SIZE = 20 * 1024 * 1024; // 20 MB
|
||||
|
||||
@@ -105,10 +105,10 @@ $constraints = match ($fieldName) {
|
||||
'mp3', 'ogg', 'oga', 'wav', 'flac', 'aac', 'm4a',
|
||||
'vtt', 'zip', 'tar', 'gz', 'tgz',
|
||||
],
|
||||
'maxSize' => 500 * 1024 * 1024, // 500 MB
|
||||
'maxSize' => 500 * 1024 * 1024, // 500 MB (default, overridden per-type below)
|
||||
'label' => 'Fichier TFE',
|
||||
'allowedDesc' => 'PDF, images, vidéos, audio, archives',
|
||||
'maxSizeDesc' => '500 MB',
|
||||
'maxSizeDesc' => '500 MB (5 GB pour vidéos/audio, 100 MB pour PDF)',
|
||||
],
|
||||
'annexes' => [
|
||||
'mimes' => [
|
||||
@@ -182,6 +182,14 @@ foreach ($allFiles as $idx => $f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Per-type size override: video/audio up to 8 GB
|
||||
$isAv = preg_match('/^(video|audio)\//', $mimeType)
|
||||
|| in_array($ext, ['mp4','webm','ogv','mov','mp3','ogg','oga','wav','flac','aac','m4a']);
|
||||
if ($isAv && $effMaxSize < 5 * 1024 * 1024 * 1024) {
|
||||
$effMaxSize = 5 * 1024 * 1024 * 1024;
|
||||
$effMaxDesc = '5 GB';
|
||||
}
|
||||
|
||||
if ($size > $effMaxSize) {
|
||||
$mb = round($size / 1024 / 1024, 1);
|
||||
$errors[] = '✕ <em>' . htmlspecialchars($f['name']) . '</em> : fichier trop volumineux ('
|
||||
|
||||
@@ -54,17 +54,17 @@ class FilepondHandler
|
||||
public const QUEUE_SIZE_LIMITS = [
|
||||
'cover' => 20 * 1024 * 1024, // 20 MB
|
||||
'note_intention' => 100 * 1024 * 1024, // 100 MB
|
||||
'tfe' => 1024 * 1024 * 1024, // 1 GB (default for non-AV, non-PDF)
|
||||
'video' => 8 * 1024 * 1024 * 1024, // 8 GB
|
||||
'audio' => 8 * 1024 * 1024 * 1024, // 8 GB
|
||||
'annexe' => 1024 * 1024 * 1024, // 1 GB
|
||||
'peertube_video' => 8 * 1024 * 1024 * 1024, // 8 GB
|
||||
'peertube_audio' => 8 * 1024 * 1024 * 1024, // 8 GB
|
||||
'tfe' => 500 * 1024 * 1024, // 500 MB (default for non-AV, non-PDF)
|
||||
'video' => 5 * 1024 * 1024 * 1024, // 5 GB
|
||||
'audio' => 5 * 1024 * 1024 * 1024, // 5 GB
|
||||
'annexe' => 500 * 1024 * 1024, // 500 MB
|
||||
'peertube_video' => 5 * 1024 * 1024 * 1024, // 5 GB
|
||||
'peertube_audio' => 5 * 1024 * 1024 * 1024, // 5 GB
|
||||
];
|
||||
|
||||
public const AV_EXTENSIONS = ['mp4', 'webm', 'ogv', 'mov', 'mp3', 'ogg', 'oga', 'wav', 'flac', 'aac', 'm4a'];
|
||||
public const MAX_PDF_SIZE = 100 * 1024 * 1024; // 100 MB
|
||||
public const MAX_AV_SIZE = 8 * 1024 * 1024 * 1024; // 8 GB
|
||||
public const MAX_AV_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB
|
||||
|
||||
// ── Log prefix for distinguishing admin vs partage ───────────────────────
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
|
||||
Glissez pour réordonner.
|
||||
<br>
|
||||
<br>
|
||||
PDF (max 100 MB) · Images (max 1 GB) · Vidéo & Audio (max 8 GB) · VTT · Archives (max 1 GB).
|
||||
PDF (max 100 MB) · Images (max 500 MB) · Vidéo & Audio (max 5 GB) · VTT · Archives (max 500 MB).
|
||||
<br>→ PDFs trop lourds ? <a href="https://www.bentopdf.com" target="_blank" rel="noopener">https://bentopdf.com/</a>
|
||||
<?php if ($peerTubeEnabled): ?>
|
||||
<br><br>Vidéos et audio hébergés sur <a href="<?= htmlspecialchars($peerTubeSettings['instance_url']) ?>" target="_blank" rel="noopener">PeerTube</a>.
|
||||
@@ -202,7 +202,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
|
||||
data-queue-type="annexe"
|
||||
data-existing-files='<?= htmlspecialchars(json_encode($existingFilesJsonForAnnexe ?? []), ENT_QUOTES) ?>'
|
||||
aria-describedby="annexe-files-hint">
|
||||
<small id="annexe-files-hint" class="admin-file-hint">PDF ou archives ZIP/TAR. Max 1 GB. Glissez pour réordonner.</small>
|
||||
<small id="annexe-files-hint" class="admin-file-hint">PDF ou archives ZIP/TAR. Max 500 MB. Glissez pour réordonner.</small>
|
||||
</div>
|
||||
<?php if ($editMode): ?>
|
||||
<button type="button" class="btn btn--sm btn--ghost file-browser-trigger"
|
||||
|
||||
@@ -43,7 +43,7 @@ $adminMode = $adminMode ?? false;
|
||||
class="tfe-file-picker"
|
||||
data-queue-type="tfe">
|
||||
<small class="admin-file-hint">
|
||||
Types acceptés : PDF · JPG/PNG/GIF/WEBP · MP4/WebM/MOV (vidéo) · MP3/OGG/WAV/FLAC (audio) · ZIP/TAR (archives). Max 1 GB par fichier.
|
||||
Types acceptés : PDF (max 100 MB) · JPG/PNG/GIF/WEBP (max 500 MB) · MP4/WebM/MOV (vidéo, max 5 GB) · MP3/OGG/WAV/FLAC (audio, max 5 GB) · ZIP/TAR (archives, max 500 MB).
|
||||
Les fichiers <code>.vtt</code> sont des sous-titres et seront associés automatiquement à la vidéo précédente.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user