Skip to content

Commit 0eac8af

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 6d962c0 commit 0eac8af

2 files changed

Lines changed: 75 additions & 3 deletions

File tree

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { useFolders } from 'hooks/api/useFolders';
3232
import { useUpdates } from 'contexts/updates';
3333
import { useLocalStorage } from 'hooks/utils/useLocalStorage';
3434
import { useHaInfo } from 'hooks/api/useHA';
35+
import { ServiceType } from 'types/services.types';
3536

3637
export const NavigationProvider: FC<PropsWithChildren> = ({ children }) => {
3738
const { user } = useUser();
@@ -95,8 +96,15 @@ export const NavigationProvider: FC<PropsWithChildren> = ({ children }) => {
9596
// is established; role/flag gating comes with real auth (Option B).
9697
items.push(...addSepApps());
9798

98-
// Served by pmm-managed, so it is not gated with the SEP group.
99-
items.push(...addOm());
99+
// Served by pmm-managed, so it is not gated with the SEP group -- gated on the
100+
// settings flag instead, and on a MongoDB service being monitored (OM has
101+
// nothing to show otherwise).
102+
if (
103+
settings.omEnabled &&
104+
currentServiceTypes.includes(ServiceType.mongodb)
105+
) {
106+
items.push(...addOm());
107+
}
100108

101109
if (settings.backupManagementEnabled) {
102110
items.push(NAV_BACKUPS);

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

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

1818
import { FC, PropsWithChildren } from 'react';
19+
import Alert from '@mui/material/Alert';
20+
import Card from '@mui/material/Card';
1921
import Stack from '@mui/material/Stack';
22+
import Typography from '@mui/material/Typography';
2023
import { Page } from 'components/page';
2124
import { useUser } from 'contexts/user';
25+
import { useReadonlySettings } from 'hooks/api/useSettings';
26+
import { useLocalStorage } from 'hooks/utils/useLocalStorage';
2227
import { OrgRole } from 'types/user.types';
2328

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

4481
return (
4582
<Page
4683
maxWidth="full"
4784
roles={user?.isPMMAdmin ? undefined : [OrgRole.Admin]}
4885
>
4986
<Stack gap={3} sx={{ flex: 1 }}>
50-
<div>{children}</div>
87+
{settings && !settings.omEnabled ? (
88+
<Card variant="outlined" sx={{ p: 2 }}>
89+
<Alert severity="info" data-testid="om-switched-off">
90+
{Messages.switchedOff}
91+
</Alert>
92+
</Card>
93+
) : (
94+
<>
95+
{!previewDismissed && (
96+
<Alert
97+
severity="warning"
98+
onClose={() => setPreviewDismissed(true)}
99+
data-testid="om-technical-preview"
100+
sx={{
101+
'& .MuiAlert-action': {
102+
color: (theme) => theme.palette.warning.contrastText,
103+
},
104+
}}
105+
>
106+
<Typography variant="body2">
107+
<strong>{Messages.technicalPreview}</strong>{' '}
108+
{Messages.technicalPreviewBody}
109+
</Typography>
110+
</Alert>
111+
)}
112+
<div>{children}</div>
113+
</>
114+
)}
51115
</Stack>
52116
</Page>
53117
);

0 commit comments

Comments
 (0)