From 9b54df8feed4ae3e94cc6e10306c4c2f2c371e86 Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Sat, 19 Sep 2026 21:44:11 +0000 Subject: [PATCH 1/8] fix(webapp): improve preview branch auto-archive settings UI --- .../preview-auto-archive-settings-ui.md | 6 + .../route.tsx | 104 +++--- .../resources.branches.auto-archive.tsx | 330 +++++++++++------- 3 files changed, 264 insertions(+), 176 deletions(-) create mode 100644 .server-changes/preview-auto-archive-settings-ui.md diff --git a/.server-changes/preview-auto-archive-settings-ui.md b/.server-changes/preview-auto-archive-settings-ui.md new file mode 100644 index 00000000000..3c69a43040e --- /dev/null +++ b/.server-changes/preview-auto-archive-settings-ui.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: improvement +--- + +Simplify preview branch auto-archive settings with clearer descriptions, individual fields for branches to keep, and an option to disable auto-archiving in the settings dialog. diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx index 48a31788eb7..baf236d19c7 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx @@ -287,57 +287,67 @@ export default function Page() { Branches docs - - {limits.isAtLimit ? ( - - ) : ( - - New branch… - - } - env="preview" - /> - )} -
-
- - {autoArchiveAvailable && ( - + {hasBranches && ( +
+ + {autoArchiveAvailable && ( + + )} + +
+ - )} - - -
+ {limits.isAtLimit ? ( + + ) : ( + + New branch… + + } + env="preview" + /> + )} +
+
+ )} {!hasBranches ? ( (); - const toggleRef = useRef(null); + const triggerRef = useRef(null); const enabled = environment.previewAutoArchiveAfterDays !== null; - function handleToggle(checked: boolean) { - if (checked) { - setOpen(true); - } else { - fetcher.submit( - { - environmentId: environment.id, - intent: "save", - excludedBranches: environment.previewAutoArchiveExcludedBranches.join("\n"), - }, - { method: "post", action: "/resources/branches/auto-archive" } - ); - } - } - return ( -
-
- + - - )} -
- {fetcher.data && !fetcher.data.ok && {fetcher.data.error}} -
+ LeadingIcon={Cog6ToothIcon} + className="shrink-0 whitespace-nowrap" + disabled={!canManage} + > + Manage auto-archive + + + ) : ( + setOpen(true)} + disabled={!canManage} + /> + )} { event.preventDefault(); - toggleRef.current?.focus(); + triggerRef.current?.focus(); }} > - Auto-archive preview branches + + Auto-archive preview branches + {open && setOpen(false)} />}
@@ -216,9 +210,40 @@ function AutoArchiveForm({ }>({ pending: false }); const [requestedKey, setRequestedKey] = useState(null); const [days, setDays] = useState(String(environment.previewAutoArchiveAfterDays ?? 14)); - const [excluded, setExcluded] = useState( - environment.previewAutoArchiveExcludedBranches.join("\n") + const [excludedRows, setExcludedRows] = useState(() => + [...environment.previewAutoArchiveExcludedBranches, ""].map((name, id) => ({ id, name })) ); + const nextRowId = useRef(excludedRows.length); + const excluded = excludedRows.map(({ name }) => name).join("\n"); + const enabled = environment.previewAutoArchiveAfterDays !== null; + + function updateExcludedBranch(id: number, name: string) { + const rows = excludedRows.map((row) => (row.id === id ? { ...row, name } : row)); + if (rows.every((row) => row.name.trim() !== "") && rows.length < 100) { + rows.push({ id: nextRowId.current++, name: "" }); + } + setExcludedRows(rows); + } + + function removeExcludedBranch(id: number) { + const rows = excludedRows.filter((row) => row.id !== id); + if (rows.length === 0 || rows.every((row) => row.name.trim() !== "")) { + rows.push({ id: nextRowId.current++, name: "" }); + } + setExcludedRows(rows); + } + + function disableAutoArchive() { + crumb("disable preview auto-archive", { environmentId: environment.id }); // @crumbs + fetcher.submit( + { + environmentId: environment.id, + intent: "save", + excludedBranches: environment.previewAutoArchiveExcludedBranches.join("\n"), + }, + { method: "post", action: "/resources/branches/auto-archive" } + ); + } const policyKey = JSON.stringify({ days: Number(days), excludedBranches: [ @@ -283,89 +308,136 @@ function AutoArchiveForm({ > -
- - setDays(event.target.value)} - /> -
-
- -