fix(archive): normalize trailing slash in multi-project server listing
GET / Accept:application/json changed shape in the May-2026 reshape: it returns listing.FileInfo entries (directory names carry a trailing '/', and the array can include non-directory entries) instead of the legacy ProjectInfo array (bare names). archive.html's multi-project mode (?projects=A,B) intersected those server names against the projectFilter parsed from the URL — which is slash-free — so every listed project missed the intersection, projectFilter emptied, the "you don't have access" banner showed, and nothing scanned: empty projects dropdown, no parties/transmittal folders. Normalise serverNames (and the projectTitles keys) to bare directory names and filter the listing to is_dir entries before intersecting. The scan in source.js already uses the slash-free projectFilter directly, so this single normalization restores the whole flow. Verified headless against a 2-project fixture, old vs new binary: old -> projectFilter [], no-access warning, no parties rendered; new -> projectFilter [182246,197072], no warning, ACME/BETACO parties rendered. Reaches prod via the next zddc-server release (archive.html is //go:embed'd). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d4f35d9927
commit
fab44542bc
2 changed files with 18 additions and 7 deletions
|
|
@ -138,11 +138,22 @@
|
|||
var serverProjects = await resp.json();
|
||||
if (Array.isArray(serverProjects) && serverProjects.length > 0
|
||||
&& serverProjects[0] && typeof serverProjects[0].name === 'string') {
|
||||
serverNames = new Set(serverProjects.map(function(p) { return p.name; }));
|
||||
// GET / Accept: application/json returns listing.FileInfo
|
||||
// entries (not the legacy ProjectInfo shape): directory
|
||||
// names carry a trailing "/", and the listing can include
|
||||
// non-directory entries. Normalise to bare directory names
|
||||
// so they match the slash-free projectFilter parsed from
|
||||
// ?projects= (url-state.js). Without this, every URL-listed
|
||||
// project misses the intersection below → "no access"
|
||||
// banner + empty scan.
|
||||
var bareName = function (p) { return p.name.replace(/\/+$/, ''); };
|
||||
var isProjectDir = function (p) { return p.is_dir === true || /\/$/.test(p.name); };
|
||||
var projectEntries = serverProjects.filter(isProjectDir);
|
||||
serverNames = new Set(projectEntries.map(bareName));
|
||||
var titles = {};
|
||||
serverProjects.forEach(function (p) {
|
||||
projectEntries.forEach(function (p) {
|
||||
if (p && typeof p.title === 'string' && p.title) {
|
||||
titles[p.name] = p.title;
|
||||
titles[bareName(p)] = p.title;
|
||||
}
|
||||
});
|
||||
window.app.projectTitles = titles;
|
||||
|
|
|
|||
|
|
@ -402,10 +402,10 @@
|
|||
}
|
||||
|
||||
async function scanHttpRoot(scanRootUrl, rootUrl, callbacks) {
|
||||
// Mode 1 — multi-project (?projects= set). Skip listing scanRootUrl entirely:
|
||||
// the zddc-server returns a ProjectInfo array there (not a Caddy fileInfo
|
||||
// listing), so iterating it as if it were a directory listing wouldn't work.
|
||||
// Project URLs are deterministic — go straight to each one.
|
||||
// Mode 1 — multi-project (?projects= set). Skip listing scanRootUrl
|
||||
// entirely: project URLs are deterministic, so go straight to each one
|
||||
// (the names in projectFilter, slash-normalised in app.js against the
|
||||
// server's root listing). Avoids depending on the root listing's shape.
|
||||
if (window.app.projectFilter && window.app.projectFilter.size > 0) {
|
||||
const tasks = [];
|
||||
for (const name of window.app.projectFilter) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue