From 7d5f6e26d8e6bb93d8a951066f210ea99d5c3cbf Mon Sep 17 00:00:00 2001 From: TJ Date: Mon, 27 Jul 2026 16:15:19 -0700 Subject: [PATCH 1/5] feat(site): rename Dismiss warnings to Mute warnings and make health callouts dismissible The header button toggles whether error/warning health checks surface in the top-nav status indicator; it does not dismiss the in-page callout. Rename it to "Mute warnings" / "Unmute warnings" to reflect what it actually does, and make the warning/error callouts themselves dismissible via the Alert component's built-in close button. --- site/src/pages/HealthPage/AccessURLPage.tsx | 7 +++- site/src/pages/HealthPage/DERPPage.tsx | 1 + site/src/pages/HealthPage/DatabasePage.tsx | 1 + .../pages/HealthPage/DismissWarningButton.tsx | 32 +++++++++---------- .../HealthPage/ProvisionerDaemonsPage.tsx | 3 +- site/src/pages/HealthPage/WebsocketPage.tsx | 4 +-- .../pages/HealthPage/WorkspaceProxyPage.tsx | 3 +- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/site/src/pages/HealthPage/AccessURLPage.tsx b/site/src/pages/HealthPage/AccessURLPage.tsx index 5cb885c5343..b45b30a6018 100644 --- a/site/src/pages/HealthPage/AccessURLPage.tsx +++ b/site/src/pages/HealthPage/AccessURLPage.tsx @@ -31,7 +31,11 @@ const AccessURLPage = () => {
- {accessUrl.error && {accessUrl.error}} + {accessUrl.error && ( + + {accessUrl.error} + + )} {accessUrl.warnings.map((warning) => { return ( @@ -40,6 +44,7 @@ const AccessURLPage = () => { key={warning.code} severity="warning" prominent + dismissible > {warning.message} diff --git a/site/src/pages/HealthPage/DERPPage.tsx b/site/src/pages/HealthPage/DERPPage.tsx index 5874f8d83e8..1801bf916f5 100644 --- a/site/src/pages/HealthPage/DERPPage.tsx +++ b/site/src/pages/HealthPage/DERPPage.tsx @@ -159,6 +159,7 @@ const DERPPage: FC = () => { key={warning.code} severity="warning" prominent + dismissible > {warning.message} diff --git a/site/src/pages/HealthPage/DatabasePage.tsx b/site/src/pages/HealthPage/DatabasePage.tsx index b892f924a1e..2d035878788 100644 --- a/site/src/pages/HealthPage/DatabasePage.tsx +++ b/site/src/pages/HealthPage/DatabasePage.tsx @@ -38,6 +38,7 @@ const DatabasePage = () => { key={warning.code} severity="warning" prominent + dismissible > {warning.message} diff --git a/site/src/pages/HealthPage/DismissWarningButton.tsx b/site/src/pages/HealthPage/DismissWarningButton.tsx index 43f48ac869a..dae05071930 100644 --- a/site/src/pages/HealthPage/DismissWarningButton.tsx +++ b/site/src/pages/HealthPage/DismissWarningButton.tsx @@ -11,59 +11,59 @@ export const DismissWarningButton = (props: { healthcheck: HealthSection }) => { const queryClient = useQueryClient(); const healthSettingsQuery = useQuery(healthSettings()); // They call the same mutation but are used in diff contexts so we don't want - // to merge their states. Eg. You dismiss a warning and when it is done it - // will show the enable button but since the mutation is still invalidating + // to merge their states. Eg. You mute a warning and when it is done it + // will show the unmute button but since the mutation is still invalidating // other queries it will be in the loading state when it should be idle. - const enableMutation = useMutation(updateHealthSettings(queryClient)); - const dismissMutation = useMutation(updateHealthSettings(queryClient)); + const unmuteMutation = useMutation(updateHealthSettings(queryClient)); + const muteMutation = useMutation(updateHealthSettings(queryClient)); if (!healthSettingsQuery.data) { return ; } const { dismissed_healthchecks } = healthSettingsQuery.data; - const isDismissed = dismissed_healthchecks.includes(props.healthcheck); + const isMuted = dismissed_healthchecks.includes(props.healthcheck); - if (isDismissed) { + if (isMuted) { return ( ); } return ( ); }; diff --git a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx index 71b2d6a3197..e99c887034f 100644 --- a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx +++ b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx @@ -31,7 +31,7 @@ const ProvisionerDaemonsPage: FC = () => {
{daemons.error && ( - + {daemons.error} )} @@ -41,6 +41,7 @@ const ProvisionerDaemonsPage: FC = () => { actions={} key={warning.code} severity="warning" + dismissible > {warning.message} diff --git a/site/src/pages/HealthPage/WebsocketPage.tsx b/site/src/pages/HealthPage/WebsocketPage.tsx index 5a2c5928b25..15cd0e1202d 100644 --- a/site/src/pages/HealthPage/WebsocketPage.tsx +++ b/site/src/pages/HealthPage/WebsocketPage.tsx @@ -36,14 +36,14 @@ const WebsocketPage = () => {
{websocket.error && ( - + {websocket.error} )} {websocket.warnings.map((warning) => { return ( - + {warning.message} ); diff --git a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx index fba577132d5..79d0d782526 100644 --- a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx +++ b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx @@ -42,7 +42,7 @@ const WorkspaceProxyPage: FC = () => {
{workspace_proxy.error && ( - + {workspace_proxy.error} )} @@ -53,6 +53,7 @@ const WorkspaceProxyPage: FC = () => { key={warning.code} severity="warning" prominent + dismissible > {warning.message} From bd3d7a443e0fa677e1ea9c7e50586401281fc2e0 Mon Sep 17 00:00:00 2001 From: Tracy Johnson Date: Tue, 28 Jul 2026 00:10:55 +0000 Subject: [PATCH 2/5] chore: retrigger CI From 55d96722ab50227ea10d2a49f464a1f77fde7096 Mon Sep 17 00:00:00 2001 From: Tracy Johnson Date: Tue, 28 Jul 2026 00:57:29 +0000 Subject: [PATCH 3/5] fix(site/src/pages/HealthPage): don't allow dismissing error alerts, trim comment Address coder-agents-review feedback: - P2: error s were dismissible with local useState. HealthLayout refetches every 30s and reuses the mounted subpage, so a dismissed error would suppress subsequent (possibly different) error messages until reload. Remove dismissible from all severity=error alerts; warning alerts stay dismissible. - Nit: trim the two-instance mutation comment to just the load-bearing detail. --- site/src/pages/HealthPage/AccessURLPage.tsx | 6 +----- site/src/pages/HealthPage/DismissWarningButton.tsx | 7 +++---- site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx | 2 +- site/src/pages/HealthPage/WebsocketPage.tsx | 2 +- site/src/pages/HealthPage/WorkspaceProxyPage.tsx | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/site/src/pages/HealthPage/AccessURLPage.tsx b/site/src/pages/HealthPage/AccessURLPage.tsx index b45b30a6018..fa5015e3b45 100644 --- a/site/src/pages/HealthPage/AccessURLPage.tsx +++ b/site/src/pages/HealthPage/AccessURLPage.tsx @@ -31,11 +31,7 @@ const AccessURLPage = () => {
- {accessUrl.error && ( - - {accessUrl.error} - - )} + {accessUrl.error && {accessUrl.error}} {accessUrl.warnings.map((warning) => { return ( diff --git a/site/src/pages/HealthPage/DismissWarningButton.tsx b/site/src/pages/HealthPage/DismissWarningButton.tsx index dae05071930..50651a86e9f 100644 --- a/site/src/pages/HealthPage/DismissWarningButton.tsx +++ b/site/src/pages/HealthPage/DismissWarningButton.tsx @@ -10,10 +10,9 @@ import { Spinner } from "#/components/Spinner/Spinner"; export const DismissWarningButton = (props: { healthcheck: HealthSection }) => { const queryClient = useQueryClient(); const healthSettingsQuery = useQuery(healthSettings()); - // They call the same mutation but are used in diff contexts so we don't want - // to merge their states. Eg. You mute a warning and when it is done it - // will show the unmute button but since the mutation is still invalidating - // other queries it will be in the loading state when it should be idle. + // Separate mutation instances so unmuting isn't stuck pending while + // muting's query invalidation resolves (a shared mutation would share + // isPending and spin the wrong button). const unmuteMutation = useMutation(updateHealthSettings(queryClient)); const muteMutation = useMutation(updateHealthSettings(queryClient)); diff --git a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx index e99c887034f..2d95928e83d 100644 --- a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx +++ b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx @@ -31,7 +31,7 @@ const ProvisionerDaemonsPage: FC = () => {
{daemons.error && ( - + {daemons.error} )} diff --git a/site/src/pages/HealthPage/WebsocketPage.tsx b/site/src/pages/HealthPage/WebsocketPage.tsx index 15cd0e1202d..51adf277436 100644 --- a/site/src/pages/HealthPage/WebsocketPage.tsx +++ b/site/src/pages/HealthPage/WebsocketPage.tsx @@ -36,7 +36,7 @@ const WebsocketPage = () => {
{websocket.error && ( - + {websocket.error} )} diff --git a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx index 79d0d782526..39abe985982 100644 --- a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx +++ b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx @@ -42,7 +42,7 @@ const WorkspaceProxyPage: FC = () => {
{workspace_proxy.error && ( - + {workspace_proxy.error} )} From a2afadb980a12d2b87eccf14e2950720c45cd8fc Mon Sep 17 00:00:00 2001 From: Tracy Johnson Date: Tue, 28 Jul 2026 01:08:10 +0000 Subject: [PATCH 4/5] refactor(site/src/pages/HealthPage): rename DismissWarningButton to MuteWarningsButton, dismissible DERP region warnings Address round-2 coder-agents-review feedback: - CRF-3 (P3): file/component name still said Dismiss while every string and identifier had moved to mute; "dismiss" is now the callout X. Rename to MuteWarningsButton and update the six import sites. - CRF-4 (P3): DERPRegionPage renders the same warning callouts as DERPPage. Mark them dismissible to match. --- site/src/pages/HealthPage/AccessURLPage.tsx | 4 ++-- site/src/pages/HealthPage/DERPPage.tsx | 4 ++-- site/src/pages/HealthPage/DERPRegionPage.tsx | 1 + site/src/pages/HealthPage/DatabasePage.tsx | 4 ++-- .../{DismissWarningButton.tsx => MuteWarningsButton.tsx} | 2 +- site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx | 4 ++-- site/src/pages/HealthPage/WebsocketPage.tsx | 4 ++-- site/src/pages/HealthPage/WorkspaceProxyPage.tsx | 4 ++-- 8 files changed, 14 insertions(+), 13 deletions(-) rename site/src/pages/HealthPage/{DismissWarningButton.tsx => MuteWarningsButton.tsx} (96%) diff --git a/site/src/pages/HealthPage/AccessURLPage.tsx b/site/src/pages/HealthPage/AccessURLPage.tsx index fa5015e3b45..b35bb77487f 100644 --- a/site/src/pages/HealthPage/AccessURLPage.tsx +++ b/site/src/pages/HealthPage/AccessURLPage.tsx @@ -12,7 +12,7 @@ import { HealthyDot, Main, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; const AccessURLPage = () => { const healthStatus = useOutletContext(); @@ -27,7 +27,7 @@ const AccessURLPage = () => { Access URL - +
diff --git a/site/src/pages/HealthPage/DERPPage.tsx b/site/src/pages/HealthPage/DERPPage.tsx index 1801bf916f5..f732c27ac06 100644 --- a/site/src/pages/HealthPage/DERPPage.tsx +++ b/site/src/pages/HealthPage/DERPPage.tsx @@ -25,7 +25,7 @@ import { SectionLabel, StatusIcon, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; type BooleanKeys = { [K in keyof T]: T[K] extends boolean | null ? K : never; @@ -148,7 +148,7 @@ const DERPPage: FC = () => { DERP - +
diff --git a/site/src/pages/HealthPage/DERPRegionPage.tsx b/site/src/pages/HealthPage/DERPRegionPage.tsx index 4f3e8e9299a..9acc304ca80 100644 --- a/site/src/pages/HealthPage/DERPRegionPage.tsx +++ b/site/src/pages/HealthPage/DERPRegionPage.tsx @@ -83,6 +83,7 @@ const DERPRegionPage: FC = () => { key={warning.code} severity="warning" prominent + dismissible > {warning.message} diff --git a/site/src/pages/HealthPage/DatabasePage.tsx b/site/src/pages/HealthPage/DatabasePage.tsx index 2d035878788..0413e169ecf 100644 --- a/site/src/pages/HealthPage/DatabasePage.tsx +++ b/site/src/pages/HealthPage/DatabasePage.tsx @@ -12,7 +12,7 @@ import { HealthyDot, Main, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; const DatabasePage = () => { const healthStatus = useOutletContext(); @@ -27,7 +27,7 @@ const DatabasePage = () => { Database - +
diff --git a/site/src/pages/HealthPage/DismissWarningButton.tsx b/site/src/pages/HealthPage/MuteWarningsButton.tsx similarity index 96% rename from site/src/pages/HealthPage/DismissWarningButton.tsx rename to site/src/pages/HealthPage/MuteWarningsButton.tsx index 50651a86e9f..025fd6dafe8 100644 --- a/site/src/pages/HealthPage/DismissWarningButton.tsx +++ b/site/src/pages/HealthPage/MuteWarningsButton.tsx @@ -7,7 +7,7 @@ import { Button } from "#/components/Button/Button"; import { Skeleton } from "#/components/Skeleton/Skeleton"; import { Spinner } from "#/components/Spinner/Spinner"; -export const DismissWarningButton = (props: { healthcheck: HealthSection }) => { +export const MuteWarningsButton = (props: { healthcheck: HealthSection }) => { const queryClient = useQueryClient(); const healthSettingsQuery = useQuery(healthSettings()); // Separate mutation instances so unmuting isn't stuck pending while diff --git a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx index 2d95928e83d..378011c5c4c 100644 --- a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx +++ b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx @@ -11,7 +11,7 @@ import { HealthyDot, Main, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; const ProvisionerDaemonsPage: FC = () => { const healthStatus = useOutletContext(); @@ -26,7 +26,7 @@ const ProvisionerDaemonsPage: FC = () => { Provisioner Daemons - +
diff --git a/site/src/pages/HealthPage/WebsocketPage.tsx b/site/src/pages/HealthPage/WebsocketPage.tsx index 51adf277436..ca70478326b 100644 --- a/site/src/pages/HealthPage/WebsocketPage.tsx +++ b/site/src/pages/HealthPage/WebsocketPage.tsx @@ -16,7 +16,7 @@ import { Pill, SectionLabel, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; const WebsocketPage = () => { const healthStatus = useOutletContext(); @@ -31,7 +31,7 @@ const WebsocketPage = () => { Websocket - +
diff --git a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx index 39abe985982..b6422d8ec34 100644 --- a/site/src/pages/HealthPage/WorkspaceProxyPage.tsx +++ b/site/src/pages/HealthPage/WorkspaceProxyPage.tsx @@ -21,7 +21,7 @@ import { Main, Pill, } from "./Content"; -import { DismissWarningButton } from "./DismissWarningButton"; +import { MuteWarningsButton } from "./MuteWarningsButton"; const WorkspaceProxyPage: FC = () => { const healthStatus = useOutletContext(); @@ -37,7 +37,7 @@ const WorkspaceProxyPage: FC = () => { Workspace Proxy - +
From c61c76b8c1d7df4a069381390c00a6897771eae2 Mon Sep 17 00:00:00 2001 From: Tracy Johnson Date: Tue, 28 Jul 2026 01:25:05 +0000 Subject: [PATCH 5/5] fix(site/src/pages/HealthPage): mark ProvisionerDaemonsPage warning callout prominent Align with the other five Health pages, which already set prominent on their warning callouts. Addresses coder-agents-review CRF-9. --- site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx index 378011c5c4c..d3466241ed1 100644 --- a/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx +++ b/site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx @@ -41,6 +41,7 @@ const ProvisionerDaemonsPage: FC = () => { actions={} key={warning.code} severity="warning" + prominent dismissible > {warning.message}