diff --git a/landing/js/landing.js b/landing/js/landing.js index 32870df..a2e9951 100644 --- a/landing/js/landing.js +++ b/landing/js/landing.js @@ -429,8 +429,22 @@ function openArchiveWith(names) { if (!names || names.length === 0) return; var base = location.pathname.replace(/\/[^\/]*$/, '/'); - var params = ['projects=' + names.map(encodeURIComponent).join(',')]; var v = new URLSearchParams(location.search).get('v'); + + if (names.length === 1) { + // Single project → canonical project-subtree URL so the user + // can edit the address bar to swap archive.html for + // working/, staging/, reviewing/, etc. zddc-server's + // availability.go auto-serves the right tool at each. + // Multi-project (the `else` branch) keeps the ?projects= + // form because there's no single subtree root. + var url = base + encodeURIComponent(names[0]) + '/archive.html'; + if (v) url += '?v=' + encodeURIComponent(v); + navigate(url); + return; + } + + var params = ['projects=' + names.map(encodeURIComponent).join(',')]; if (v) params.push('v=' + encodeURIComponent(v)); navigate(base + 'archive.html?' + params.join('&')); } diff --git a/tests/landing.spec.js b/tests/landing.spec.js index a5bc044..ac0f5dc 100644 --- a/tests/landing.spec.js +++ b/tests/landing.spec.js @@ -66,7 +66,10 @@ test.describe('Landing page', () => { await page.locator('.project-table-row[data-name="197072"]').click(); const navTo = await page.evaluate(() => window.__navTo); - expect(navTo).toContain('archive.html?projects=197072'); + // Single-project click navigates to the project's canonical subtree + // (so the user can swap archive.html for working/, staging/, etc.). + expect(navTo).toContain('/197072/archive.html'); + expect(navTo).not.toContain('?projects='); }); test('column filters narrow the table; filters persist in URL', async ({ page }) => { @@ -217,8 +220,11 @@ test.describe('Landing page', () => { await page.locator('#openSelectedBtn').click(); const navTo = await page.evaluate(() => window.__navTo); - expect(navTo).toContain('archive.html?projects=176109'); + // After the visibility-filter trims to one project, this collapses + // to the single-project path (no ?projects= form). + expect(navTo).toContain('/176109/archive.html'); expect(navTo).not.toContain('197072'); + expect(navTo).not.toContain('?projects='); }); test('legacy presets are migrated to groups on first load', async ({ page }) => {