181 lines
6.1 KiB
TypeScript
181 lines
6.1 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { useMemo } from 'react';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { Alert, Button, LinkButton, LoadingPlaceholder, Stack, useStyles2 } from '@grafana/ui';
|
|
import { Trans, t } from 'app/core/internationalization';
|
|
import { MuteTimingActionsButtons } from 'app/features/alerting/unified/components/mute-timings/MuteTimingActionsButtons';
|
|
import {
|
|
ALL_MUTE_TIMINGS,
|
|
useExportMuteTimingsDrawer,
|
|
} from 'app/features/alerting/unified/components/mute-timings/useExportMuteTimingsDrawer';
|
|
import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext';
|
|
import { PROVENANCE_ANNOTATION } from 'app/features/alerting/unified/utils/k8s/constants';
|
|
|
|
import { Authorize } from '../../components/Authorize';
|
|
import { AlertmanagerAction, useAlertmanagerAbilities, useAlertmanagerAbility } from '../../hooks/useAbilities';
|
|
import { makeAMLink } from '../../utils/misc';
|
|
import { DynamicTable, DynamicTableColumnProps } from '../DynamicTable';
|
|
import { EmptyAreaWithCTA } from '../EmptyAreaWithCTA';
|
|
import { ProvisioningBadge } from '../Provisioning';
|
|
import { Spacer } from '../Spacer';
|
|
|
|
import { MuteTiming, useMuteTimings } from './useMuteTimings';
|
|
import { renderTimeIntervals } from './util';
|
|
|
|
type TableItem = {
|
|
id: string;
|
|
data: MuteTiming;
|
|
};
|
|
|
|
export const MuteTimingsTable = () => {
|
|
const { selectedAlertmanager: alertManagerSourceName = '', hasConfigurationAPI } = useAlertmanager();
|
|
const hideActions = !hasConfigurationAPI;
|
|
const styles = useStyles2(getStyles);
|
|
const [ExportAllDrawer, showExportAllDrawer] = useExportMuteTimingsDrawer();
|
|
|
|
const { data, isLoading, error } = useMuteTimings({ alertmanager: alertManagerSourceName ?? '' });
|
|
|
|
const items = useMemo((): TableItem[] => {
|
|
const muteTimings = data || [];
|
|
|
|
return muteTimings.map((mute) => {
|
|
return {
|
|
id: mute.id,
|
|
data: mute,
|
|
};
|
|
});
|
|
}, [data]);
|
|
|
|
const [_, allowedToCreateMuteTiming] = useAlertmanagerAbility(AlertmanagerAction.CreateMuteTiming);
|
|
|
|
const [exportMuteTimingsSupported, exportMuteTimingsAllowed] = useAlertmanagerAbility(
|
|
AlertmanagerAction.ExportMuteTimings
|
|
);
|
|
const columns = useColumns(alertManagerSourceName, hideActions);
|
|
|
|
if (isLoading) {
|
|
return <LoadingPlaceholder text="Loading mute timings..." />;
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<Alert severity="error" title={t('alerting.mute_timings.error-loading.title', 'Error loading mute timings')}>
|
|
<Trans i18nKey="alerting.mute_timings.error-loading.description">
|
|
Could not load mute timings. Please try again later.
|
|
</Trans>
|
|
</Alert>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={styles.container}>
|
|
<Stack direction="row" alignItems="center">
|
|
<Trans i18nKey="alerting.mute-timings.description">
|
|
Enter specific time intervals when not to send notifications or freeze notifications for recurring periods of
|
|
time.
|
|
</Trans>
|
|
<Spacer />
|
|
{!hideActions && items.length > 0 && (
|
|
<Authorize actions={[AlertmanagerAction.CreateMuteTiming]}>
|
|
<LinkButton
|
|
className={styles.muteTimingsButtons}
|
|
icon="plus"
|
|
variant="primary"
|
|
href={makeAMLink('alerting/routes/mute-timing/new', alertManagerSourceName)}
|
|
>
|
|
<Trans i18nKey="alerting.mute-timings.add-mute-timing">Add mute timing</Trans>
|
|
</LinkButton>
|
|
</Authorize>
|
|
)}
|
|
{exportMuteTimingsSupported && (
|
|
<>
|
|
<Button
|
|
icon="download-alt"
|
|
className={styles.muteTimingsButtons}
|
|
variant="secondary"
|
|
disabled={!exportMuteTimingsAllowed}
|
|
onClick={() => showExportAllDrawer(ALL_MUTE_TIMINGS)}
|
|
>
|
|
<Trans i18nKey="alerting.common.export-all">Export all</Trans>
|
|
</Button>
|
|
{ExportAllDrawer}
|
|
</>
|
|
)}
|
|
</Stack>
|
|
{items.length > 0 ? (
|
|
<DynamicTable items={items} cols={columns} pagination={{ itemsPerPage: 25 }} />
|
|
) : !hideActions ? (
|
|
<EmptyAreaWithCTA
|
|
text="You haven't created any mute timings yet"
|
|
buttonLabel="Add mute timing"
|
|
buttonIcon="plus"
|
|
buttonSize="lg"
|
|
href={makeAMLink('alerting/routes/mute-timing/new', alertManagerSourceName)}
|
|
showButton={allowedToCreateMuteTiming}
|
|
/>
|
|
) : (
|
|
<EmptyAreaWithCTA text="No mute timings configured" buttonLabel={''} showButton={false} />
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function useColumns(alertManagerSourceName: string, hideActions = false) {
|
|
const [[_editSupported, allowedToEdit], [_deleteSupported, allowedToDelete]] = useAlertmanagerAbilities([
|
|
AlertmanagerAction.UpdateMuteTiming,
|
|
AlertmanagerAction.DeleteMuteTiming,
|
|
]);
|
|
const showActions = !hideActions && (allowedToEdit || allowedToDelete);
|
|
|
|
return useMemo((): Array<DynamicTableColumnProps<MuteTiming>> => {
|
|
const columns: Array<DynamicTableColumnProps<MuteTiming>> = [
|
|
{
|
|
id: 'name',
|
|
label: 'Name',
|
|
renderCell: function renderName({ data }) {
|
|
return (
|
|
<div>
|
|
{data.name}{' '}
|
|
{data.provisioned && (
|
|
<ProvisioningBadge tooltip provenance={data.metadata?.annotations?.[PROVENANCE_ANNOTATION]} />
|
|
)}
|
|
</div>
|
|
);
|
|
},
|
|
size: 1,
|
|
},
|
|
{
|
|
id: 'timeRange',
|
|
label: 'Time range',
|
|
renderCell: ({ data }) => {
|
|
return renderTimeIntervals(data);
|
|
},
|
|
size: 5,
|
|
},
|
|
];
|
|
if (showActions) {
|
|
columns.push({
|
|
id: 'actions',
|
|
label: 'Actions',
|
|
alignColumn: 'end',
|
|
renderCell: ({ data }) => (
|
|
<MuteTimingActionsButtons muteTiming={data} alertManagerSourceName={alertManagerSourceName} />
|
|
),
|
|
size: 2,
|
|
});
|
|
}
|
|
return columns;
|
|
}, [showActions, alertManagerSourceName]);
|
|
}
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
container: css({
|
|
display: 'flex',
|
|
flexFlow: 'column nowrap',
|
|
}),
|
|
muteTimingsButtons: css({
|
|
marginBottom: theme.spacing(2),
|
|
}),
|
|
});
|