fix(post-form): render photo thumbnails on edit + clearer load errors

QA feedback fixes for the front-end journal edit form:

- Photos on edit showed a filename with no thumbnail. addFile(url,{type:'local'})
  routed through the form plugin's FilePond server.load, which returned HTML (not
  the image bytes), so image-preview had nothing to render. Fetch each image as a
  Blob and add it as a File (ordered) — the thumbnail renders, and type:'local'
  still means it is never re-uploaded and its filename rides the photo_order
  manifest. Verified: fileType image/jpeg, previews render, reorder/remove unchanged.

- Distinguish a deleted/missing entry (API 404 → "this entry no longer exists")
  from a transient load failure ("check your connection") in the prefill catch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 14:55:05 +02:00
co-authored by Claude Opus 4.8
parent 03323bcadf
commit ff31683075
2 changed files with 33 additions and 9 deletions
+32 -8
View File
@@ -801,11 +801,30 @@ function editLoadPhotos(route) {
});
editWaitForPond(function (pond) {
try { pond.setOptions({ allowBrowse: true, allowDrop: true, allowReorder: true }); } catch (e) { /* older API */ }
images.forEach(function (m) {
try {
var p = pond.addFile(route + '/' + m.filename, { type: 'local' });
if (p && typeof p.catch === 'function') p.catch(function () { /* skip a broken URL */ });
} catch (e) { /* older FilePond API — skip */ }
// Fetch each image as a real Blob and add it as a File. Passing a
// plain URL to addFile({type:'local'}) routes through the form
// plugin's FilePond server.load, which returns HTML here (not the
// image bytes) — so the image-preview plugin had nothing to render
// and items showed as a bare filename. A real File gives FilePond
// the image data → thumbnail renders. type:'local' still means it
// is never re-uploaded; its filename rides the photo_order manifest.
Promise.all(images.map(function (m) {
return fetch(route + '/' + m.filename, { credentials: 'include' })
.then(function (r) { return r.ok ? r.blob() : null; })
.then(function (blob) {
return blob ? new File([blob], m.filename, { type: blob.type || 'image/jpeg' }) : null;
})
.catch(function () { return null; });
})).then(function (files) {
// Add in the sorted (cover) order; index keeps FilePond's list
// ordered even though the fetches resolve concurrently.
files.forEach(function (file, i) {
if (!file) return;
try {
var p = pond.addFile(file, { type: 'local', index: i });
if (p && typeof p.catch === 'function') p.catch(function () { /* skip */ });
} catch (e) { /* older FilePond API — skip */ }
});
});
});
})
@@ -841,7 +860,7 @@ function initEditMode() {
form.setAttribute('action', '/post?edit=' + encodeURIComponent(route) + (ret ? '&return=' + encodeURIComponent(ret) : ''));
fetch('/api/v1/pages' + route, { credentials: 'include', headers: { Accept: 'application/json' } })
.then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
.then(function (r) { if (!r.ok) { var e = new Error('HTTP ' + r.status); e.status = r.status; throw e; } return r.json(); })
.then(function (json) {
var d = (json && json.data) || {};
var h = d.header || {};
@@ -870,10 +889,15 @@ function initEditMode() {
editLoadPhotos(route); // U7: pull the entry's existing photos into FilePond
})
.catch(function () {
.catch(function (err) {
// D7: inline error between heading and first field; keep the form
// disabled and empty rather than leaving a half-filled state.
editShowError(wrap, 'Sorry — this entry could not be loaded for editing. Go back to the journal and try again.');
// Distinguish a deleted/missing entry (404) from a transient load
// failure so the owner knows whether retrying is worthwhile.
var msg = (err && err.status === 404)
? 'This entry no longer exists — it may have been deleted. Head back to the journal.'
: 'Sorry — this entry couldnt be loaded for editing. Check your connection and try again.';
editShowError(wrap, msg);
editSubmitLabel(submitBtn, origLabel);
});
}