Skip to content

Commit ece3b28

Browse files
paulfitzclaude
andcommitted
add Server section to the admin panel and setup wizard
Fills in the Server piece of the `/admin/setup` wizard and its admin-panel counterpart -- Base URL and Edition -- plus the shared apply/restart plumbing the other wizard steps can plug into. Highlights: - `BaseUrlSection` with a Test-URL-then-Confirm flow. "Leave automatic" actually clears a manually-set APP_HOME_URL via PATCH /install/prefs rather than being a no-op skip, so the label matches the effect. - `EditionSection` reusing the existing `ToggleEnterpriseWidget` in admin-panel mode; a simple Community vs Full Grist picker in wizard mode. Availability is a constructor option so storybook can drive variants without runtime tricks. - `PendingChangesManager` + `PartialApplyError`: sections implement a small `ConfigSection` interface, the manager batches apply()s, restarts the server once at the end when needed, and surfaces partial failures with labelled per-section errors. - Writes go through `PATCH /api/install/prefs` (the consolidated envVars write path from c73044a), not a dedicated POST. - `GET /api/config/server` reads activation prefs + process.env directly, bypassing the memoized `getHomeUrl()` so the admin panel reflects persisted writes without waiting for the restart. - The Enterprise admin-panel stub now surfaces the installation ID via a shared `buildInstallationIdDisplay` helper extracted from `ToggleEnterpriseWidget`. Community builds omit the row since the activation-status endpoint isn't mounted there. - `AdminPanelCss` gains a couple of shared helpers (`buildConfirmedRow`, moved `cssDangerText`/`cssErrorText`/`cssHappyText`) that other sections can reuse. - Storybook stories for `BaseUrlSection` and `EditionSection` so UI states can be previewed without standing up a server. Aligns with the convention in other in-flight wizard branches. - Browser tests in `test/nbrowser/AdminPanelServer.ts` covering the admin-panel item, the Test-and-Confirm flow, persistence through the install/prefs endpoint, and the wizard getting-through-without-changes and Apply-and-Continue paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ab1a336 commit ece3b28

14 files changed

Lines changed: 1921 additions & 78 deletions

app/client/ui/AdminLeftPanel.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AppHeader } from "app/client/ui/AppHeader";
55
import * as css from "app/client/ui/LeftPanelCommon";
66
import { PageSidePanel } from "app/client/ui/PagePanels";
77
import { infoTooltip } from "app/client/ui/tooltips";
8+
import { theme } from "app/client/ui2018/cssVars";
89
import { IconName } from "app/client/ui2018/IconList";
910
import { cssLink } from "app/client/ui2018/links";
1011
import { AdminPanelPage } from "app/common/gristUrls";
@@ -14,6 +15,7 @@ import { getAdminConfig } from "app/common/urlUtils";
1415
import { Computed, dom, DomContents, MultiHolder, Observable, styled } from "grainjs";
1516

1617
import type { AppModel } from "app/client/models/AppModel";
18+
import type { RestartBannerController } from "app/client/ui/AdminPanel";
1719

1820
const t = makeT("AdminPanel");
1921
const testId = makeTestId("test-admin-controls-");
@@ -42,7 +44,11 @@ export function getPageNames() {
4244
};
4345
}
4446

45-
export function buildAdminLeftPanel(owner: MultiHolder, appModel: AppModel): PageSidePanel {
47+
export function buildAdminLeftPanel(
48+
owner: MultiHolder,
49+
appModel: AppModel,
50+
restartBanner?: RestartBannerController,
51+
): PageSidePanel {
4652
const pageObs = Computed.create(owner, use => use(urlState().state).adminPanel);
4753

4854
const isSetup = pageObs.get() === "setup";
@@ -77,6 +83,16 @@ export function buildAdminLeftPanel(owner: MultiHolder, appModel: AppModel): Pag
7783
buildPageEntry("admin", "Home"),
7884
// TODO: Uncomment when setup page is ready.
7985
// buildPageEntry("setup", "Settings"),
86+
restartBanner ? dom.maybe(restartBanner.isVisible, () =>
87+
cssApplyChangesEntry(
88+
css.cssPageLink(
89+
css.cssPageIcon("Warning"),
90+
css.cssLinkText(t("Apply changes")),
91+
dom.on("click", () => restartBanner.focus()),
92+
),
93+
testId("page-apply-changes"),
94+
),
95+
) : null,
8096
css.cssSectionHeader(css.cssSectionHeaderText(pageNames.adminControls),
8197
(adminControlsAvailable ?
8298
infoTooltip("adminControls", { popupOptions: { placement: "bottom-start" } }) :
@@ -118,3 +134,12 @@ const cssLearnMoreLink = styled(cssLink, `
118134
gap: 8px;
119135
align-items: center;
120136
`);
137+
138+
const cssApplyChangesEntry = styled(css.cssPageEntry, `
139+
color: ${theme.dangerText};
140+
--icon-color: ${theme.dangerText};
141+
cursor: pointer;
142+
& .${css.cssPageLink.className} {
143+
color: inherit;
144+
}
145+
`);

0 commit comments

Comments
 (0)