diff --git a/.github/workflows/README.md b/.github/workflows/README.md
index fe74f65..7bfa79c 100644
--- a/.github/workflows/README.md
+++ b/.github/workflows/README.md
@@ -8,6 +8,11 @@ Compose validation, and the deployment script test suite
selection, the transactional Nginx switch and its restore-on-failure paths, and
the preflight checks.
+`ci.yml`'s `swagger-docs` job regenerates `server/docs` with the pinned `swag`
+version from `server/Dockerfile` and fails on any diff. The image build already
+regenerates the spec, so the binary is always current; this guards the
+*committed* copy, which is what `pages.yml` publishes.
+
`publish.yml` runs only from a successful `CI` workflow run on `main` that was
triggered by a trusted push. It validates
`github.event.workflow_run.head_sha` as a 40-character hexadecimal SHA and
@@ -27,3 +32,10 @@ deployment. `slot: auto` targets whichever slot is currently inactive; `blue` or
`green` names one explicitly. To recover an *older* image SHA instead, run
`deploy.yml` manually with that SHA — rollback only moves traffic between the two
slots that are already up.
+
+`pages.yml` publishes the committed Swagger spec as a static Swagger UI site on
+GitHub Pages (
Loading…
+Loading...
{page}
-This page is coming soon.
+This screen is not available yet.
Loading…
+Loading...
Loading…
+Loading...
Finalizing sign-in…
+Finalizing sign-in...
- This change needs an admin account, so it was not saved. Ask a web admin to make it - for you. + This action requires an admin account. Nothing was saved.
diff --git a/frontend/src/components/FooterMenuEditor.tsx b/frontend/src/components/FooterMenuEditor.tsx index 31c80aa..eb52f78 100644 --- a/frontend/src/components/FooterMenuEditor.tsx +++ b/frontend/src/components/FooterMenuEditor.tsx @@ -39,6 +39,15 @@ const inputClass = "w-full px-2.5 py-1.5 rounded-md border border-border bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/40" const iconButtonClass = "p-1 rounded-md hover:bg-muted disabled:opacity-30 disabled:hover:bg-transparent" +async function readErrorMessage(res: Response, fallback: string) { + try { + const body = await res.json() as { error?: string } + return body.error?.trim() || fallback + } catch { + return fallback + } +} + function normalizeEntry(raw: unknown): FooterEntry { const entry = (raw ?? {}) as PartialLoading…
+Loading...
) : columns.length === 0 ? (- The footer menu is empty. Add a column to build it, or save as-is to restore the built-in - default footer. + The footer menu is empty. Add a column, or save to restore the default footer.
{dirty && !saving && Unsaved changes} {message && {message}} diff --git a/frontend/src/components/MediaPicker.tsx b/frontend/src/components/MediaPicker.tsx index 01a4eb8..d3e4608 100644 --- a/frontend/src/components/MediaPicker.tsx +++ b/frontend/src/components/MediaPicker.tsx @@ -107,7 +107,7 @@ function MediaPicker({ onSelect, onClose, title = "Insert image", onUseUrl, init const response = await apiFetch(`/v1/media/gallery?${params.toString()}`, { signal: controller.signal, }) - if (!response.ok) throw new Error(await errorMessage(response, `Request failed (${response.status})`)) + if (!response.ok) throw new Error(await errorMessage(response, `Could not load media (${response.status})`)) const payload = (await response.json()) as GalleryResponse if (controller.signal.aborted) return const page = payload.media ?? [] @@ -228,7 +228,7 @@ function MediaPicker({ onSelect, onClose, title = "Insert image", onUseUrl, init autoFocus className="w-full rounded-lg border border-border bg-background py-2 pl-9 pr-4 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/40" onChange={(e) => setSearchInput(e.target.value)} - placeholder="Search by file name, alt text, or caption..." + placeholder="Search file name, alt text, or caption" type="search" value={searchInput} /> @@ -316,7 +316,7 @@ function MediaPicker({ onSelect, onClose, title = "Insert image", onUseUrl, init aria-label="Image URL" className="flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/40" onChange={(e) => setUrlInput(e.target.value)} - placeholder="Or paste image URL" + placeholder="Paste image URL" type="url" value={urlInput} /> diff --git a/frontend/src/pages/AuthCallback.tsx b/frontend/src/pages/AuthCallback.tsx index 85441e6..3bf9d28 100644 --- a/frontend/src/pages/AuthCallback.tsx +++ b/frontend/src/pages/AuthCallback.tsx @@ -27,7 +27,7 @@ export default function AuthCallback() { return (Signing you in…
+Signing you in...
- COMMAND CENTER -
+Dashboard
- Here's what's happening at The Triangle today. + Recent CMS activity and quick drafting tools.