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

109 lines
3.1 KiB
TypeScript

import { useMemo } from 'react';
import * as React from 'react';
import { PluginExtensionPoints, dateTime, findCommonLabels } from '@grafana/data';
import { Alert, CombinedRule, PaginationProps } from 'app/types/unified-alerting';
import { alertInstanceKey } from '../../utils/rules';
import { AlertLabels } from '../AlertLabels';
import { DynamicTable, DynamicTableColumnProps, DynamicTableItemProps } from '../DynamicTable';
import { AlertInstanceExtensionPoint } from '../extensions/AlertInstanceExtensionPoint';
import { AlertInstanceDetails } from './AlertInstanceDetails';
import { AlertStateTag } from './AlertStateTag';
interface Props {
rule?: CombinedRule;
instances: Alert[];
pagination?: PaginationProps;
footerRow?: React.ReactNode;
}
interface AlertWithCommonLabels extends Alert {
commonLabels?: Record<string, string>;
}
interface RuleAndAlert {
rule?: CombinedRule;
alert: AlertWithCommonLabels;
}
type AlertTableColumnProps = DynamicTableColumnProps<RuleAndAlert>;
type AlertTableItemProps = DynamicTableItemProps<RuleAndAlert>;
export const AlertInstancesTable = ({ rule, instances, pagination, footerRow }: Props) => {
const commonLabels = useMemo(() => {
// only compute the common labels if we have more than 1 instance, if we don't then that single instance
// will have the complete set of common labels and no unique ones
return instances.length > 1 ? findCommonLabels(instances.map((instance) => instance.labels)) : {};
}, [instances]);
const items = useMemo(
(): AlertTableItemProps[] =>
instances.map((instance) => ({
data: { rule, alert: { ...instance, commonLabels } },
id: alertInstanceKey(instance),
})),
[commonLabels, instances, rule]
);
return (
<DynamicTable
cols={columns}
isExpandable={true}
items={items}
renderExpandedContent={({ data }) => <AlertInstanceDetails instance={data.alert} />}
pagination={pagination}
footerRow={footerRow}
/>
);
};
const columns: AlertTableColumnProps[] = [
{
id: 'state',
label: 'State',
// eslint-disable-next-line react/display-name
renderCell: ({
data: {
alert: { state },
},
}) => <AlertStateTag state={state} />,
size: '80px',
},
{
id: 'labels',
label: 'Labels',
// eslint-disable-next-line react/display-name
renderCell: ({
data: {
alert: { labels, commonLabels },
},
}) => <AlertLabels labels={labels} commonLabels={commonLabels} size="sm" />,
},
{
id: 'created',
label: 'Created',
// eslint-disable-next-line react/display-name
renderCell: ({
data: {
alert: { activeAt },
},
}) => <>{activeAt.startsWith('0001') ? '-' : dateTime(activeAt).format('YYYY-MM-DD HH:mm:ss')}</>,
size: '150px',
},
{
id: 'actions',
label: '',
renderCell: ({ data: { alert, rule } }) => (
<AlertInstanceExtensionPoint
rule={rule}
instance={alert}
extensionPointId={PluginExtensionPoints.AlertInstanceAction}
key="alert-instance-extension-point"
/>
),
size: '40px',
},
];