Skip to content

Commit eb0ae4e

Browse files
committed
PMM-15360: Gate OpenManager's nav and page on the switch
Adds the settings flag as a second gate alongside the MongoDB-monitored check for OpenManager's nav entry, reusing the existing pattern for hiding MongoDB-only nav entries rather than inventing a second mechanism. OmPage now fails closed on the settings flag too, not just isPMMAdmin: a saved or shared link has to answer "switched off" rather than the API's raw FailedPrecondition or the unauthorized card, which would misreport a disabled feature as a permissions problem to an admin who has every right to be here. Also adds the technical-preview banner (dismissible per browser via localStorage, not a setting), with an explicit color override on its close button -- @percona/peak-ui's MuiAlert theme colors the icon/message slots via theme.palette[severity].contrastText but not .MuiAlert-action, so the default close button was rendering almost invisibly against the warning background. Stacks on PMM-15326-om-ui-nav (needs OmPage/navigation.provider.tsx) and this ticket's own settings-flag PR, merged in here since neither is available on a single common upstream branch yet. Signed-off-by: Pawel Lebioda <pawel.lebioda@percona.com>
1 parent 04f695f commit eb0ae4e

2 files changed

Lines changed: 75 additions & 3 deletions

File tree

ui/apps/pmm/src/contexts/navigation/navigation.provider.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,11 @@ export const NavigationProvider: FC<PropsWithChildren> = ({ children }) => {
9595
// is established; role/flag gating comes with real auth (Option B).
9696
items.push(...addSepApps());
9797

98-
// Served by pmm-managed, so it is not gated with the SEP group.
99-
items.push(...addOm());
98+
// Served by pmm-managed, so it is not gated with the SEP group -- gated
99+
// on the settings flag alone.
100+
if (settings.omEnabled) {
101+
items.push(...addOm());
102+
}
100103

101104
if (settings.backupManagementEnabled) {
102105
items.push(NAV_BACKUPS);

ui/apps/pmm/src/om/OmPage.tsx

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,27 @@
1616
*/
1717

1818
import { FC, PropsWithChildren } from 'react';
19+
import Alert from '@mui/material/Alert';
20+
import Card from '@mui/material/Card';
21+
import CircularProgress from '@mui/material/CircularProgress';
1922
import Stack from '@mui/material/Stack';
23+
import Typography from '@mui/material/Typography';
2024
import { Page } from 'components/page';
2125
import { useUser } from 'contexts/user';
26+
import { useReadonlySettings } from 'hooks/api/useSettings';
27+
import { useLocalStorage } from 'hooks/utils/useLocalStorage';
2228
import { OrgRole } from 'types/user.types';
2329

30+
const TECHNICAL_PREVIEW_DISMISSED_KEY = 'pmm-ui.om.technicalPreviewDismissed';
31+
32+
const Messages = {
33+
switchedOff:
34+
'OpenManager is switched off. A PMM admin can turn it on in Configuration → Settings → Advanced Settings.',
35+
technicalPreview: 'Technical preview',
36+
technicalPreviewBody:
37+
'OpenManager is a technical preview. It is still under development and may change.',
38+
};
39+
2440
/**
2541
* Host chrome for the OM page.
2642
*
@@ -37,17 +53,70 @@ import { OrgRole } from 'types/user.types';
3753
* `isGrafanaAdmin || orgRole === Admin`, and `roles` (org-role only) cannot express the
3854
* Grafana-admin half on its own, so it gates the remaining case and `Page` renders its
3955
* standard unauthorized card.
56+
*
57+
* The settings gate is enforced here for the same reason: a saved or shared link to
58+
* this page has to answer "switched off", not the API's raw FailedPrecondition, and
59+
* not the unauthorized card above, which would misreport a disabled feature as a
60+
* permissions problem to an admin who has every right to be here (PMM-15360 AC1/AC2/AC7).
61+
*
62+
* The technical-preview banner is dismissible, and remembered per browser rather than
63+
* per PMM account or installation -- it is a "you've seen this" acknowledgement, not a
64+
* setting with a right answer for every viewer, so localStorage is enough and needs no
65+
* round trip to pmm-managed.
66+
*
67+
* The close button's `sx` override exists because `@percona/peak-ui`'s MuiAlert theme
68+
* (`styleOverrides.icon`/`.message`) sets `color: theme.palette[severity].contrastText`
69+
* on the icon and message slots, but not on `.MuiAlert-action` -- so the close button
70+
* MUI renders for `onClose` falls back to the alert root's own `color`, which this
71+
* theme leaves close to the warning background itself. Nothing else in this app uses a
72+
* dismissible Alert, which is presumably why that gap was never hit before.
4073
*/
4174
export const OmPage: FC<PropsWithChildren> = ({ children }) => {
4275
const { user } = useUser();
76+
const { data: settings, isLoading } = useReadonlySettings();
77+
const [previewDismissed, setPreviewDismissed] = useLocalStorage<boolean>(
78+
TECHNICAL_PREVIEW_DISMISSED_KEY,
79+
false
80+
);
4381

4482
return (
4583
<Page
4684
maxWidth="full"
4785
roles={user?.isPMMAdmin ? undefined : [OrgRole.Admin]}
4886
>
4987
<Stack gap={3} sx={{ flex: 1 }}>
50-
<div>{children}</div>
88+
{isLoading ? (
89+
<Stack alignItems="center" py={4}>
90+
<CircularProgress data-testid="om-loading" />
91+
</Stack>
92+
) : settings?.omEnabled ? (
93+
<>
94+
{!previewDismissed && (
95+
<Alert
96+
severity="warning"
97+
onClose={() => setPreviewDismissed(true)}
98+
data-testid="om-technical-preview"
99+
sx={{
100+
'& .MuiAlert-action': {
101+
color: (theme) => theme.palette.warning.contrastText,
102+
},
103+
}}
104+
>
105+
<Typography variant="body2">
106+
<strong>{Messages.technicalPreview}</strong>{' '}
107+
{Messages.technicalPreviewBody}
108+
</Typography>
109+
</Alert>
110+
)}
111+
<div>{children}</div>
112+
</>
113+
) : (
114+
<Card variant="outlined" sx={{ p: 2 }}>
115+
<Alert severity="info" data-testid="om-switched-off">
116+
{Messages.switchedOff}
117+
</Alert>
118+
</Card>
119+
)}
51120
</Stack>
52121
</Page>
53122
);

0 commit comments

Comments
 (0)