2025-04-01 10:38:02 +09:00

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),
}),
});