refactor(theme): share apiSend/apiErrorMsg between post-form and trip-publish
Address the P1 maintainability finding that trip-publish.js reimplemented post-form.js's apiSend + login-expired error copy verbatim. Extract both into js/src/api-utils.js and import from both entry points; esbuild inlines the module into each bundle so there is no runtime coupling. Also drops the stale data-trip-route reference from trip-publish.js's markup-contract comment. Rebuilt js/trip-publish.js and js/post/post-form.js. Verified: trip-publish suite 8/8; post suite unchanged (34 pass, same 6 owner-gate environmental fails as baseline — photo-editor specs that exercise post-form's apiSend/apiErrorMsg all green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mpdu3Dt1iVoozHwAMyjrbn
This commit is contained in:
@@ -11,6 +11,7 @@ import EasyMDE from 'easymde';
|
||||
import Sortable from 'sortablejs';
|
||||
import 'easymde/dist/easymde.min.css';
|
||||
import './post-form.css';
|
||||
import { apiSend, apiErrorMsg } from './api-utils.js';
|
||||
|
||||
/* ── Markdown editor (EasyMDE) ───────────────────────────── */
|
||||
function initEditor() {
|
||||
@@ -882,29 +883,7 @@ function initPhotoEditor(route) {
|
||||
if (sortable) sortable.option('disabled', b);
|
||||
}
|
||||
|
||||
// Mutation fetch that RESOLVES on success and REJECTS with a status-bearing
|
||||
// Error otherwise, so callers can tell an expired login (401/403) apart from a
|
||||
// generic failure. `okStatuses` lists extra codes to accept as success (e.g.
|
||||
// 204 no-content, or 404 already-gone for an idempotent DELETE). Cookies
|
||||
// auto-included. (Superseded the old boolean apiOk, which swallowed the code.)
|
||||
function apiSend(url, opts, okStatuses) {
|
||||
return fetch(url, Object.assign({ credentials: 'include' }, opts)).then(function (r) {
|
||||
if (r.ok || (okStatuses && okStatuses.indexOf(r.status) !== -1)) return r;
|
||||
var e = new Error('HTTP ' + r.status);
|
||||
e.status = r.status;
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
// Turn a failed apiSend/fetch into owner-facing copy. A 401/403 almost always
|
||||
// means the login session lapsed mid-edit — say so, because a plain "try
|
||||
// again" wouldn't help until they sign back in.
|
||||
function editErrorMsg(err, fallback) {
|
||||
var s = err && err.status;
|
||||
return (s === 401 || s === 403)
|
||||
? 'Your login session expired — sign in again, then retry.'
|
||||
: fallback;
|
||||
}
|
||||
// apiSend / apiErrorMsg now live in ./api-utils.js (shared with trip-publish.js).
|
||||
|
||||
function mediaList() {
|
||||
return fetch('/api/v1/pages' + route + '/media', { credentials: 'include', headers: { Accept: 'application/json' } })
|
||||
@@ -990,7 +969,7 @@ function initPhotoEditor(route) {
|
||||
function () { setStatus(''); render(next); } // saved; DOM already shows it
|
||||
);
|
||||
}, function (err) {
|
||||
setStatus(editErrorMsg(err, 'Couldn’t save the new order — reverted. Try again.'), true);
|
||||
setStatus(apiErrorMsg(err, 'Couldn’t save the new order — reverted. Try again.'), true);
|
||||
render(lastGood); // revert the SortableJS move to last-known-good
|
||||
}).then(function () { setBusy(false); });
|
||||
}
|
||||
@@ -1038,7 +1017,7 @@ function initPhotoEditor(route) {
|
||||
);
|
||||
}, function (err) {
|
||||
// The DELETE request itself failed — nothing changed on disk.
|
||||
setStatus(editErrorMsg(err, 'Couldn’t delete that photo. Try again.'), true);
|
||||
setStatus(apiErrorMsg(err, 'Couldn’t delete that photo. Try again.'), true);
|
||||
render(lastGood);
|
||||
})
|
||||
.then(function () { setBusy(false); });
|
||||
|
||||
Reference in New Issue
Block a user