Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 92988bd46de8d84b2c4b56d1b907f59eb0796b0b
parent 4bcd156b67f4f3228bdec05152097c4ad7053fb7
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Tue, 26 May 2026 14:44:26 -0400

Move export build to deploy page

Diffstat:
Meditor/CHANGELOG.md | 1+
Meditor/app/build/components/BuildButtons.tsx | 28----------------------------
Aeditor/app/deploy/components/BuildExportButton.tsx | 35+++++++++++++++++++++++++++++++++++
Meditor/app/deploy/page.tsx | 19+++++++++++++++++--
Meditor/e2e/build.spec.ts | 32+++++++++++++++++++++++++++++---
5 files changed, 82 insertions(+), 33 deletions(-)

diff --git a/editor/CHANGELOG.md b/editor/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] +- **"Build static export" moved from the Build page to the top of the Deploy page**, co-locating it with the export changelog preview, "Cut release", and "Deploy static export" so the whole build → review → cut → deploy sequence lives on one page. - **The embedded single-video view on the channel page is now collapsed by default**, keeping the channel view compact. Clicking a video in the list expands the panel and scrolls to it; navigating away from a video (no video selected) collapses it again. A manual collapse/expand toggle is available on the panel, mirroring the video list's existing collapse. - **Unlisted videos now get their own clickable list in the channel availability diagnostics**, alongside Deleted/Private/Members-only/Needs-auth/Error. Previously unlisted videos were only shown as a count, so there was no way to jump to the specific videos. - **Cutting a release now clears `## [Unreleased]` entirely** instead of leaving an empty heading sitting above the new dated section. The `/changelog` and `/deploy` pages stop showing a blank Unreleased block after a release; the heading reappears the next time somebody hand-adds a pending bullet to the file. diff --git a/editor/app/build/components/BuildButtons.tsx b/editor/app/build/components/BuildButtons.tsx @@ -13,7 +13,6 @@ import { archiveCombinedTranscriptsAction, archiveLiveChatAction, archiveTranscriptsAction, - buildExportAction, buildIndexAction, normalizeLiveChatAction, normalizeTranscriptsAction, @@ -28,7 +27,6 @@ const DEFAULT_BUILD_QUEUE = "build"; export function BuildButtons({ existingQueues }: Props) { const [indexQueue, setIndexQueue] = useState(DEFAULT_BUILD_QUEUE); - const [exportQueue, setExportQueue] = useState(DEFAULT_BUILD_QUEUE); const [normalizeQueue, setNormalizeQueue] = useState(DEFAULT_BUILD_QUEUE); const [archiveQueue, setArchiveQueue] = useState(DEFAULT_BUILD_QUEUE); const [combinedQueue, setCombinedQueue] = useState(DEFAULT_BUILD_QUEUE); @@ -82,32 +80,6 @@ export function BuildButtons({ existingQueues }: Props) { <section className="flex flex-col gap-3 border-t border-zinc-200 dark:border-zinc-800 pt-6"> <div> - <h2 className="text-lg font-semibold">Build static export</h2> - <p className="text-sm text-zinc-500"> - Spawns <code>pnpm run build</code> in <code>export/</code> — runs - the index build, then <code>next build</code> to produce the - static site at <code>export/out/</code>. - </p> - </div> - <StreamActionLog - trigger={() => buildExportAction(exportQueue)} - cancelAction={cancelJobAction} - buttonLabel="Build static export" - runningLabel="Building static export…" - extraControls={ - <QueueControl - value={exportQueue} - onChange={setExportQueue} - defaultQueueKey={DEFAULT_BUILD_QUEUE} - existingQueues={existingQueues} - actionLabel="Build static export" - /> - } - /> - </section> - - <section className="flex flex-col gap-3 border-t border-zinc-200 dark:border-zinc-800 pt-6"> - <div> <h2 className="text-lg font-semibold">Normalize transcripts</h2> <p className="text-sm text-zinc-500"> Walks every video and writes{" "} diff --git a/editor/app/deploy/components/BuildExportButton.tsx b/editor/app/deploy/components/BuildExportButton.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { useState } from "react"; +import { StreamActionLog } from "yt-dlp-transcript-common/components/StreamActionLog"; +import { buildExportAction } from "../../build/buildAction"; +import { QueueControl } from "../../components/QueueControl"; +import { cancelJobAction } from "../../jobs/actions"; + +type Props = { + existingQueues: string[]; +}; + +const DEFAULT_BUILD_QUEUE = "build"; + +export function BuildExportButton({ existingQueues }: Props) { + const [exportQueue, setExportQueue] = useState(DEFAULT_BUILD_QUEUE); + + return ( + <StreamActionLog + trigger={() => buildExportAction(exportQueue)} + cancelAction={cancelJobAction} + buttonLabel="Build static export" + runningLabel="Building static export…" + extraControls={ + <QueueControl + value={exportQueue} + onChange={setExportQueue} + defaultQueueKey={DEFAULT_BUILD_QUEUE} + existingQueues={existingQueues} + actionLabel="Build static export" + /> + } + /> + ); +} diff --git a/editor/app/deploy/page.tsx b/editor/app/deploy/page.tsx @@ -8,6 +8,8 @@ import { suggestNextVersion, } from "yt-dlp-transcript-common/lib/changelog"; import { getPaths } from "yt-dlp-transcript-common/lib/paths"; +import { getRegistry } from "yt-dlp-transcript-common/jobs/registry"; +import { BuildExportButton } from "./components/BuildExportButton"; import { CutReleaseForm } from "./components/CutReleaseForm"; import { DeployButton } from "./components/DeployButton"; @@ -41,6 +43,7 @@ export default function DeployPage() { const unreleased = source ? extractUnreleasedSection(source) : ""; const hasUnreleased = unreleased.length > 0; const lastDeployedAt = getLastDeployedAt(); + const existingQueues = getRegistry().activeQueueNames(); return ( <div className="flex flex-col gap-8 max-w-3xl"> @@ -48,6 +51,18 @@ export default function DeployPage() { <section className="flex flex-col gap-3"> <div> + <h2 className="text-lg font-semibold">Build static export</h2> + <p className="text-sm text-zinc-500"> + Spawns <code>pnpm run build</code> in <code>export/</code> — runs + the index build, then <code>next build</code> to produce the + static site at <code>export/out/</code>. + </p> + </div> + <BuildExportButton existingQueues={existingQueues} /> + </section> + + <section className="flex flex-col gap-3 border-t border-zinc-200 dark:border-zinc-800 pt-6"> + <div> <h2 className="text-lg font-semibold">Pending export changes</h2> <p className="text-sm text-zinc-500"> Bullets currently sitting under <code>## [Unreleased]</code> in{" "} @@ -88,8 +103,8 @@ export default function DeployPage() { <p className="text-sm text-zinc-500"> Runs <code>pnpm run deploy</code> in <code>export/</code>, publishing the most recently built static site at{" "} - <code>export/out/</code>. Build first if needed ( - <code>Build → Build static export</code>). + <code>export/out/</code>. Build first if needed using{" "} + <code>Build static export</code> at the top of this page. </p> <p className="text-sm text-zinc-500 mt-1"> Last deployed:{" "} diff --git a/editor/e2e/build.spec.ts b/editor/e2e/build.spec.ts @@ -38,10 +38,36 @@ test("build index ingests synthetic video data and emits a transcript page", asy ).toBe(true); }); -test("build static export button renders and is enabled", async ({ page }) => { +test("build static export lives on the deploy page, not the build page", async ({ + page, +}) => { await resetData("empty"); + + // No longer on the build page. await page.goto("/build"); - const exportButton = page.getByRole("button", { name: "Build static export" }); + await expect( + page.getByRole("heading", { name: "Build static export" }), + ).toHaveCount(0); + await expect(page.getByRole("heading", { name: "Build index" })).toBeVisible(); + + // Now at the top of the deploy page, above the changelog preview. + await page.goto("/deploy"); + const exportHeading = page.getByRole("heading", { + name: "Build static export", + }); + const pendingHeading = page.getByRole("heading", { + name: "Pending export changes", + }); + await expect(exportHeading).toBeVisible(); + await expect(pendingHeading).toBeVisible(); + + // The export section comes before the pending-changes section. + const exportBox = await exportHeading.boundingBox(); + const pendingBox = await pendingHeading.boundingBox(); + expect(exportBox!.y).toBeLessThan(pendingBox!.y); + + const exportButton = page.getByRole("button", { + name: "Build static export", + }); await expect(exportButton).toBeEnabled(); - await expect(exportButton).toContainText("Build static export"); });