Add admin config screen (issue #14)
Deploy to Dev / Deploy & Smoke Test (push) Successful in 23s
Deploy to Dev / Deploy & Smoke Test (push) Successful in 23s
Lets the photographer edit config/site.json from /dashboard instead of SSHing in and hand-editing the file. Two tiers: - Quick-edit form for the fields actually touched day to day (site title/tagline/hero, photographer bio, contact/social, Venmo username, session pricing, theme colors) - Raw JSON textarea for everything else (portfolio categories, locations, session types, Immich settings) - the form's fields are a subset of this, not a separate source of truth Backend: GET/PUT /api/admin/config, gated by the existing requireAdmin middleware (OIDC admin session or legacy ADMIN_SECRET). PUT validates the body is an object with the required top-level sections, writes atomically (temp file + rename), and keeps one prior version as site.json.bak before overwriting. Required a docker-compose.yml change: the api service had no volume mount for config/ at all before this (only portfolio/nginx did, and read-only) - added a read-write mount so the API can actually write the file the live site reads.
This commit is contained in:
@@ -142,4 +142,25 @@ test.describe('Admin dashboard — panels', () => {
|
||||
|
||||
expect(download.suggestedFilename()).toMatch(/lisilou-bookings.*\.csv/);
|
||||
});
|
||||
|
||||
test('Config panel loads current site.json into the form', async ({ page }) => {
|
||||
await page.locator('#nav-config').click();
|
||||
await expect(page.locator('#panel-config')).toBeVisible();
|
||||
await expect(page.locator('#cfg-content')).toBeVisible({ timeout: 8_000 });
|
||||
// Title field should be populated from real config, not left blank
|
||||
await expect(page.locator('#cfg-site-title')).not.toHaveValue('');
|
||||
// Raw JSON textarea should contain valid, non-trivial JSON
|
||||
const raw = await page.locator('#cfg-raw-json').inputValue();
|
||||
expect(() => JSON.parse(raw)).not.toThrow();
|
||||
expect(JSON.parse(raw)).toHaveProperty('site');
|
||||
});
|
||||
|
||||
test('Config panel round-trips a no-op save without error', async ({ page }) => {
|
||||
// Saves the exact same content back - proves the PUT path works without
|
||||
// mutating the real config the live site depends on.
|
||||
await page.locator('#nav-config').click();
|
||||
await expect(page.locator('#cfg-content')).toBeVisible({ timeout: 8_000 });
|
||||
await page.locator('button:has-text("Save Full Config")').click();
|
||||
await expect(page.locator('#cfg-raw-status')).toHaveClass(/ok/, { timeout: 8_000 });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user