mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Fix relink: close modal + HTMX refresh for immediate pool update
- After relink, always close the modal (even if FilePond input not found, e.g. page refreshed by live-reload during the fetch). - After closing, re-fetch #format-fichiers-block via HTMX from /admin/fragments/fichiers.php?_thesis_id=N which loads thesis files from DB and re-renders the fragment with pre-populated FilePond pools. The afterSwap handler auto-reinitializes FilePond instances. - Updated admin/fragments/fichiers.php to accept _thesis_id, load existing files from DB, build per-queue-type JSON, and render in edit mode.
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -31,6 +31,8 @@
|
|||||||
- [x] CSS: .relink-modal + .file-browser styles in form.css
|
- [x] CSS: .relink-modal + .file-browser styles in form.css
|
||||||
- [x] Fix: relinked file not appearing in FilePond pool — add file metadata to addFile() options and extensive diag logging
|
- [x] Fix: relinked file not appearing in FilePond pool — add file metadata to addFile() options and extensive diag logging
|
||||||
- [x] Fix: addFile called with single object instead of (source, options) — FilePond API mismatch prevented files from loading
|
- [x] Fix: addFile called with single object instead of (source, options) — FilePond API mismatch prevented files from loading
|
||||||
|
- [x] Fix: use type 'limbo' for relinked files so they go through DID_COMPLETE_ITEM_PROCESSING → onprocessfile → syncOrderInput + green checkmark visual
|
||||||
|
- [x] Fix: change .filepond--file default border from yellow to green (existing files never reach processing-complete state)
|
||||||
- [ ] Migration: rename existing theses/ directories to documents/ on disk and update DB paths
|
- [ ] Migration: rename existing theses/ directories to documents/ on disk and update DB paths
|
||||||
|
|
||||||
## Trash policy
|
## Trash policy
|
||||||
|
|||||||
@@ -1,13 +1,59 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Admin fragment: Format(s) + Fichiers block (HTMX partial).
|
* Admin fragment: Format(s) + Fichiers block (HTMX partial).
|
||||||
|
*
|
||||||
|
* GET /admin/fragments/fichiers.php?_thesis_id=123
|
||||||
|
*
|
||||||
|
* When _thesis_id is provided, loads existing files from DB and renders
|
||||||
|
* the fragment in edit mode with pre-populated FilePond pools. Used by
|
||||||
|
* the relink flow to refresh pools after a file is linked server-side.
|
||||||
*/
|
*/
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
require_once APP_ROOT . '/src/Database.php';
|
||||||
App::boot();
|
App::boot();
|
||||||
|
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
$_POST['admin_mode'] = '1';
|
$_POST['admin_mode'] = '1';
|
||||||
|
|
||||||
|
$thesisId = filter_var($_GET['_thesis_id'] ?? '', FILTER_VALIDATE_INT);
|
||||||
|
if ($thesisId) {
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$currentFiles = $db->getThesisFiles($thesisId);
|
||||||
|
|
||||||
|
// Build per-queue-type existing-files JSON for FilePond edit mode
|
||||||
|
$buildQueueFilesJson = function (array $files, string $queueType): array {
|
||||||
|
$result = [];
|
||||||
|
foreach ($files as $f) {
|
||||||
|
$ft = $f['file_type'] ?? '';
|
||||||
|
$fp = $f['file_path'] ?? '';
|
||||||
|
if (str_starts_with($fp, 'http://') || str_starts_with($fp, 'https://')) continue;
|
||||||
|
if ($queueType === 'cover' && $ft !== 'cover') continue;
|
||||||
|
if ($queueType === 'note_intention' && $ft !== 'note_intention') continue;
|
||||||
|
if ($queueType === 'tfe' && ($ft === 'cover' || $ft === 'note_intention' || $ft === 'annex')) continue;
|
||||||
|
if ($queueType === 'annexe' && $ft !== 'annex') continue;
|
||||||
|
$result[] = [
|
||||||
|
'source' => (string)((int)$f['id']),
|
||||||
|
'options' => [
|
||||||
|
'type' => 'local',
|
||||||
|
'file' => [
|
||||||
|
'name' => $f['file_name'] ?? basename($f['file_path'] ?? ''),
|
||||||
|
'size' => (int)($f['file_size'] ?? 0),
|
||||||
|
'type' => $f['mime_type'] ?? 'application/octet-stream',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
};
|
||||||
|
|
||||||
|
$existingFilesJsonForCover = $buildQueueFilesJson($currentFiles, 'cover');
|
||||||
|
$existingFilesJsonForNoteIntention = $buildQueueFilesJson($currentFiles, 'note_intention');
|
||||||
|
$existingFilesJsonForTfe = $buildQueueFilesJson($currentFiles, 'tfe');
|
||||||
|
$existingFilesJsonForAnnexe = $buildQueueFilesJson($currentFiles, 'annexe');
|
||||||
|
|
||||||
|
$_POST['edit_mode'] = '1';
|
||||||
|
}
|
||||||
|
|
||||||
require_once APP_ROOT . '/templates/partials/form/fichiers-fragment.php';
|
require_once APP_ROOT . '/templates/partials/form/fichiers-fragment.php';
|
||||||
|
|||||||
@@ -629,15 +629,33 @@
|
|||||||
}
|
}
|
||||||
console.log('[relink] success | new_id=' + data.id);
|
console.log('[relink] success | new_id=' + data.id);
|
||||||
|
|
||||||
// Add the new file to the FilePond pool
|
// Add the new file to the FilePond pool, then close the modal.
|
||||||
|
// If the DOM was replaced (e.g. live-reload), refresh the
|
||||||
|
// form fragment via HTMX so the server re-renders the pools
|
||||||
|
// with the newly-linked file included.
|
||||||
var input = document.querySelector(`.tfe-file-picker[data-queue-type="${queueType}"]`);
|
var input = document.querySelector(`.tfe-file-picker[data-queue-type="${queueType}"]`);
|
||||||
console.log('[relink] looking for input | selector=' + `.tfe-file-picker[data-queue-type="${queueType}"]` + ' | found=' + !!input);
|
console.log('[relink] looking for input | selector=' + `.tfe-file-picker[data-queue-type="${queueType}"]` + ' | found=' + !!input);
|
||||||
|
var closeAndRefresh = function() {
|
||||||
|
var modal = document.getElementById('relink-modal');
|
||||||
|
if (modal) modal.close();
|
||||||
|
// Re-fetch the fichiers fragment from the server so the
|
||||||
|
// newly-linked file appears in the FilePond pools.
|
||||||
|
var block = document.getElementById('format-fichiers-block');
|
||||||
|
if (block && window.htmx) {
|
||||||
|
var url = '/admin/fragments/fichiers.php';
|
||||||
|
if (window.__xamxamRelinkCtx && window.__xamxamRelinkCtx.thesisId) {
|
||||||
|
url += '?_thesis_id=' + encodeURIComponent(window.__xamxamRelinkCtx.thesisId);
|
||||||
|
}
|
||||||
|
htmx.ajax('GET', url, {
|
||||||
|
target: '#format-fichiers-block',
|
||||||
|
swap: 'outerHTML'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
if (input) {
|
if (input) {
|
||||||
var pond = FilePond.find(input);
|
var pond = FilePond.find(input);
|
||||||
console.log('[relink] looking for pond | found=' + !!pond);
|
console.log('[relink] looking for pond | found=' + !!pond);
|
||||||
if (pond) {
|
if (pond) {
|
||||||
// Add as LIMBO to trigger server.load, which returns the actual file blob + headers.
|
|
||||||
// type: 'local' with file metadata skips load and may not render correctly.
|
|
||||||
pond.addFile(String(data.id), {
|
pond.addFile(String(data.id), {
|
||||||
type: 'limbo',
|
type: 'limbo',
|
||||||
file: {
|
file: {
|
||||||
@@ -647,18 +665,18 @@
|
|||||||
}
|
}
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log('[relink] addFile resolved | source=' + String(data.id) + ' | queueType=' + queueType);
|
console.log('[relink] addFile resolved | source=' + String(data.id) + ' | queueType=' + queueType);
|
||||||
// Close modal after file is added to the pond.
|
closeAndRefresh();
|
||||||
// syncOrderInput fires via onprocessfile / onupdatefiles.
|
|
||||||
var modal = document.getElementById('relink-modal');
|
|
||||||
if (modal) modal.close();
|
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
console.error('[relink] addFile rejected', err);
|
console.error('[relink] addFile rejected', err);
|
||||||
|
closeAndRefresh();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('[relink] FilePond.find returned null for input', input);
|
console.error('[relink] FilePond.find returned null for input', input);
|
||||||
|
closeAndRefresh();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('[relink] input not found | queueType=' + queueType);
|
console.warn('[relink] input not found, page may have reloaded | queueType=' + queueType);
|
||||||
|
closeAndRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark form dirty
|
// Mark form dirty
|
||||||
|
|||||||
Reference in New Issue
Block a user