Alerting: Remove CTA button from read-only notification policy page (#41096)

* don't show cta button for read-only prometheus alertmanager

* grammar fix

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>

Co-authored-by: Peter Holmberg <peterholmberg@users.noreply.github.com>
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
Co-authored-by: Peter Holmberg <peter.hlmbrg@gmail.com>
pull/41202/head^2
Domas 4 years ago committed by GitHub
parent 01bc59e432
commit 345af8374c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      public/app/features/alerting/unified/AmRoutes.test.tsx
  2. 45
      public/app/features/alerting/unified/components/EmptyArea.tsx
  3. 61
      public/app/features/alerting/unified/components/EmptyAreaWithCTA.tsx
  4. 25
      public/app/features/alerting/unified/components/amroutes/AmSpecificRouting.tsx

@ -79,6 +79,7 @@ const ui = {
editRouteButton: byLabelText('Edit route'),
deleteRouteButton: byLabelText('Delete route'),
newPolicyButton: byRole('button', { name: /New policy/ }),
newPolicyCTAButton: byRole('button', { name: /New specific policy/ }),
receiverSelect: byTestId('am-receiver-select'),
groupSelect: byTestId('am-group-select'),
@ -508,6 +509,25 @@ describe('AmRoutes', () => {
expect(mocks.api.fetchAlertManagerConfig).not.toHaveBeenCalled();
expect(mocks.api.fetchStatus).toHaveBeenCalledTimes(1);
});
it('Prometheus Alertmanager has no CTA button if there are no specific policies', async () => {
mocks.api.fetchStatus.mockResolvedValue({
...someCloudAlertManagerStatus,
config: {
...someCloudAlertManagerConfig.alertmanager_config,
route: {
...someCloudAlertManagerConfig.alertmanager_config.route,
routes: undefined,
},
},
});
await renderAmRoutes(dataSources.promAlertManager.name);
const rootRouteContainer = await ui.rootRouteContainer.find();
expect(ui.editButton.query(rootRouteContainer)).not.toBeInTheDocument();
expect(ui.newPolicyCTAButton.query()).not.toBeInTheDocument();
expect(mocks.api.fetchAlertManagerConfig).not.toHaveBeenCalled();
expect(mocks.api.fetchStatus).toHaveBeenCalledTimes(1);
});
});
const clickSelectOption = async (selectElement: HTMLElement, optionText: string): Promise<void> => {

@ -1,43 +1,12 @@
import React, { ButtonHTMLAttributes, FC } from 'react';
import React, { FC } from 'react';
import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { Button, ButtonVariant, IconName, useStyles } from '@grafana/ui';
import { useStyles } from '@grafana/ui';
export interface EmptyAreaProps {
buttonLabel: string;
onButtonClick: ButtonHTMLAttributes<HTMLButtonElement>['onClick'];
text: string;
buttonIcon?: IconName;
buttonSize?: 'xs' | 'sm' | 'md' | 'lg';
buttonVariant?: ButtonVariant;
}
export const EmptyArea: FC<EmptyAreaProps> = ({
buttonIcon,
buttonLabel,
buttonSize = 'lg',
buttonVariant = 'primary',
onButtonClick,
text,
}) => {
export const EmptyArea: FC = ({ children }) => {
const styles = useStyles(getStyles);
return (
<div className={styles.container}>
<p className={styles.text}>{text}</p>
<Button
className={styles.button}
icon={buttonIcon}
onClick={onButtonClick}
size={buttonSize}
type="button"
variant={buttonVariant}
>
{buttonLabel}
</Button>
</div>
);
return <div className={styles.container}>{children}</div>;
};
const getStyles = (theme: GrafanaTheme) => {
@ -48,11 +17,5 @@ const getStyles = (theme: GrafanaTheme) => {
padding: ${theme.spacing.xl};
text-align: center;
`,
text: css`
margin-bottom: ${theme.spacing.md};
`,
button: css`
margin: ${theme.spacing.md} 0 ${theme.spacing.sm};
`,
};
};

@ -0,0 +1,61 @@
import React, { ButtonHTMLAttributes, FC } from 'react';
import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { Button, ButtonVariant, IconName, useStyles } from '@grafana/ui';
import { EmptyArea } from './EmptyArea';
export interface EmptyAreaWithCTAProps {
buttonLabel: string;
onButtonClick: ButtonHTMLAttributes<HTMLButtonElement>['onClick'];
text: string;
buttonIcon?: IconName;
buttonSize?: 'xs' | 'sm' | 'md' | 'lg';
buttonVariant?: ButtonVariant;
}
export const EmptyAreaWithCTA: FC<EmptyAreaWithCTAProps> = ({
buttonIcon,
buttonLabel,
buttonSize = 'lg',
buttonVariant = 'primary',
onButtonClick,
text,
}) => {
const styles = useStyles(getStyles);
return (
<EmptyArea>
<>
<p className={styles.text}>{text}</p>
<Button
className={styles.button}
icon={buttonIcon}
onClick={onButtonClick}
size={buttonSize}
type="button"
variant={buttonVariant}
>
{buttonLabel}
</Button>
</>
</EmptyArea>
);
};
const getStyles = (theme: GrafanaTheme) => {
return {
container: css`
background-color: ${theme.colors.bg2};
color: ${theme.colors.textSemiWeak};
padding: ${theme.spacing.xl};
text-align: center;
`,
text: css`
margin-bottom: ${theme.spacing.md};
`,
button: css`
margin: ${theme.spacing.md} 0 ${theme.spacing.sm};
`,
};
};

@ -6,6 +6,7 @@ import { AmRouteReceiver, FormAmRoute } from '../../types/amroutes';
import { emptyArrayFieldMatcher, emptyRoute } from '../../utils/amroutes';
import { EmptyArea } from '../EmptyArea';
import { AmRoutesTable } from './AmRoutesTable';
import { EmptyAreaWithCTA } from '../EmptyAreaWithCTA';
export interface AmSpecificRoutingProps {
onChange: (routes: FormAmRoute) => void;
@ -43,12 +44,18 @@ export const AmSpecificRouting: FC<AmSpecificRoutingProps> = ({
<h5>Specific routing</h5>
<p>Send specific alerts to chosen contact points, based on matching criteria</p>
{!routes.receiver ? (
<EmptyArea
buttonIcon="rocket"
buttonLabel="Set a default contact point"
onButtonClick={onRootRouteEdit}
text="You haven't set a default contact point for the root route yet."
/>
readOnly ? (
<EmptyArea>
<p>There is no default contact point configured for the root route.</p>
</EmptyArea>
) : (
<EmptyAreaWithCTA
buttonIcon="rocket"
buttonLabel="Set a default contact point"
onButtonClick={onRootRouteEdit}
text="You haven't set a default contact point for the root route yet."
/>
)
) : actualRoutes.length > 0 ? (
<>
{!isAddMode && !readOnly && (
@ -82,8 +89,12 @@ export const AmSpecificRouting: FC<AmSpecificRoutingProps> = ({
routes={actualRoutes}
/>
</>
) : readOnly ? (
<EmptyArea>
<p>There are no specific policies configured.</p>
</EmptyArea>
) : (
<EmptyArea
<EmptyAreaWithCTA
buttonIcon="plus"
buttonLabel="New specific policy"
onButtonClick={addNewRoute}

Loading…
Cancel
Save