2021-05-04 13:38:01 +02:00
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
2021-05-17 10:39:42 +03:00
|
|
|
import { useStyles2 } from '@grafana/ui';
|
2021-06-23 09:27:47 +03:00
|
|
|
import React, { FC, useMemo } from 'react';
|
2021-04-07 08:42:43 +03:00
|
|
|
import { css, cx } from '@emotion/css';
|
|
|
|
|
import { RuleDetails } from './RuleDetails';
|
2021-05-17 10:39:42 +03:00
|
|
|
import { isCloudRulesSource } from '../../utils/datasource';
|
2021-04-07 08:42:43 +03:00
|
|
|
import { useHasRuler } from '../../hooks/useHasRuler';
|
2021-04-16 12:08:08 +03:00
|
|
|
import { CombinedRule } from 'app/types/unified-alerting';
|
2021-05-19 18:54:03 +03:00
|
|
|
import { Annotation } from '../../utils/constants';
|
|
|
|
|
import { RuleState } from './RuleState';
|
|
|
|
|
import { RuleHealth } from './RuleHealth';
|
2021-08-16 10:12:07 +03:00
|
|
|
import { DynamicTable, DynamicTableColumnProps, DynamicTableItemProps } from '../DynamicTable';
|
2021-07-07 16:17:26 -07:00
|
|
|
import { DynamicTableWithGuidelines } from '../DynamicTableWithGuidelines';
|
2021-06-23 09:27:47 +03:00
|
|
|
|
|
|
|
|
type RuleTableColumnProps = DynamicTableColumnProps<CombinedRule>;
|
|
|
|
|
type RuleTableItemProps = DynamicTableItemProps<CombinedRule>;
|
2021-04-07 08:42:43 +03:00
|
|
|
|
|
|
|
|
interface Props {
|
2021-04-16 12:08:08 +03:00
|
|
|
rules: CombinedRule[];
|
|
|
|
|
showGuidelines?: boolean;
|
|
|
|
|
showGroupColumn?: boolean;
|
2021-05-19 18:54:03 +03:00
|
|
|
showSummaryColumn?: boolean;
|
2021-04-16 12:08:08 +03:00
|
|
|
emptyMessage?: string;
|
2021-05-17 10:39:42 +03:00
|
|
|
className?: string;
|
2021-04-07 08:42:43 +03:00
|
|
|
}
|
|
|
|
|
|
2021-04-16 12:08:08 +03:00
|
|
|
export const RulesTable: FC<Props> = ({
|
|
|
|
|
rules,
|
2021-05-17 10:39:42 +03:00
|
|
|
className,
|
2021-04-16 12:08:08 +03:00
|
|
|
showGuidelines = false,
|
|
|
|
|
emptyMessage = 'No rules found.',
|
|
|
|
|
showGroupColumn = false,
|
2021-05-19 18:54:03 +03:00
|
|
|
showSummaryColumn = false,
|
2021-04-16 12:08:08 +03:00
|
|
|
}) => {
|
2021-05-04 13:38:01 +02:00
|
|
|
const styles = useStyles2(getStyles);
|
2021-04-07 08:42:43 +03:00
|
|
|
|
2021-06-23 09:27:47 +03:00
|
|
|
const wrapperClass = cx(styles.wrapper, className, { [styles.wrapperMargin]: showGuidelines });
|
2021-04-07 08:42:43 +03:00
|
|
|
|
2021-06-23 09:27:47 +03:00
|
|
|
const items = useMemo((): RuleTableItemProps[] => {
|
|
|
|
|
const seenKeys: string[] = [];
|
|
|
|
|
return rules.map((rule, ruleIdx) => {
|
|
|
|
|
let key = JSON.stringify([rule.promRule?.type, rule.labels, rule.query, rule.name, rule.annotations]);
|
|
|
|
|
if (seenKeys.includes(key)) {
|
|
|
|
|
key += `-${ruleIdx}`;
|
|
|
|
|
}
|
|
|
|
|
seenKeys.push(key);
|
|
|
|
|
return {
|
|
|
|
|
id: key,
|
|
|
|
|
data: rule,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}, [rules]);
|
2021-04-07 08:42:43 +03:00
|
|
|
|
2021-07-07 16:17:26 -07:00
|
|
|
const columns = useColumns(showSummaryColumn, showGroupColumn);
|
2021-04-16 12:08:08 +03:00
|
|
|
|
2021-04-07 08:42:43 +03:00
|
|
|
if (!rules.length) {
|
2021-05-06 11:21:58 +03:00
|
|
|
return <div className={cx(wrapperClass, styles.emptyMessage)}>{emptyMessage}</div>;
|
2021-04-07 08:42:43 +03:00
|
|
|
}
|
|
|
|
|
|
2021-08-16 10:12:07 +03:00
|
|
|
const TableComponent = showGuidelines ? DynamicTableWithGuidelines : DynamicTable;
|
|
|
|
|
|
2021-04-07 08:42:43 +03:00
|
|
|
return (
|
2021-06-23 09:27:47 +03:00
|
|
|
<div className={wrapperClass} data-testid="rules-table">
|
2021-08-16 10:12:07 +03:00
|
|
|
<TableComponent
|
2021-06-23 09:27:47 +03:00
|
|
|
cols={columns}
|
|
|
|
|
isExpandable={true}
|
|
|
|
|
items={items}
|
2021-07-07 16:17:26 -07:00
|
|
|
renderExpandedContent={({ data: rule }) => <RuleDetails rule={rule} />}
|
2021-06-23 09:27:47 +03:00
|
|
|
/>
|
2021-04-07 08:42:43 +03:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-04 13:38:01 +02:00
|
|
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
2021-04-16 12:08:08 +03:00
|
|
|
wrapperMargin: css`
|
2021-06-23 09:27:47 +03:00
|
|
|
${theme.breakpoints.up('md')} {
|
|
|
|
|
margin-left: 36px;
|
|
|
|
|
}
|
2021-04-16 12:08:08 +03:00
|
|
|
`,
|
2021-05-06 11:21:58 +03:00
|
|
|
emptyMessage: css`
|
|
|
|
|
padding: ${theme.spacing(1)};
|
|
|
|
|
`,
|
2021-04-07 08:42:43 +03:00
|
|
|
wrapper: css`
|
|
|
|
|
width: auto;
|
2021-05-04 13:38:01 +02:00
|
|
|
background-color: ${theme.colors.background.secondary};
|
|
|
|
|
border-radius: ${theme.shape.borderRadius()};
|
2021-04-07 08:42:43 +03:00
|
|
|
`,
|
|
|
|
|
});
|
2021-06-23 09:27:47 +03:00
|
|
|
|
2021-07-07 16:17:26 -07:00
|
|
|
function useColumns(showSummaryColumn: boolean, showGroupColumn: boolean) {
|
2021-06-23 09:27:47 +03:00
|
|
|
const hasRuler = useHasRuler();
|
|
|
|
|
|
|
|
|
|
return useMemo((): RuleTableColumnProps[] => {
|
|
|
|
|
const columns: RuleTableColumnProps[] = [
|
|
|
|
|
{
|
|
|
|
|
id: 'state',
|
|
|
|
|
label: 'State',
|
|
|
|
|
// eslint-disable-next-line react/display-name
|
2021-07-07 16:17:26 -07:00
|
|
|
renderCell: ({ data: rule }) => {
|
2021-06-23 09:27:47 +03:00
|
|
|
const { namespace } = rule;
|
|
|
|
|
const { rulesSource } = namespace;
|
|
|
|
|
const { promRule, rulerRule } = rule;
|
|
|
|
|
const isDeleting = !!(hasRuler(rulesSource) && promRule && !rulerRule);
|
|
|
|
|
const isCreating = !!(hasRuler(rulesSource) && rulerRule && !promRule);
|
2021-07-07 16:17:26 -07:00
|
|
|
return <RuleState rule={rule} isDeleting={isDeleting} isCreating={isCreating} />;
|
2021-06-23 09:27:47 +03:00
|
|
|
},
|
|
|
|
|
size: '165px',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'name',
|
|
|
|
|
label: 'Name',
|
|
|
|
|
// eslint-disable-next-line react/display-name
|
|
|
|
|
renderCell: ({ data: rule }) => rule.name,
|
|
|
|
|
size: 5,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'health',
|
|
|
|
|
label: 'Health',
|
|
|
|
|
// eslint-disable-next-line react/display-name
|
|
|
|
|
renderCell: ({ data: { promRule } }) => (promRule ? <RuleHealth rule={promRule} /> : null),
|
|
|
|
|
size: '75px',
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
if (showSummaryColumn) {
|
|
|
|
|
columns.push({
|
|
|
|
|
id: 'summary',
|
|
|
|
|
label: 'Summary',
|
|
|
|
|
// eslint-disable-next-line react/display-name
|
|
|
|
|
renderCell: ({ data: rule }) => rule.annotations[Annotation.summary] ?? '',
|
|
|
|
|
size: 5,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (showGroupColumn) {
|
|
|
|
|
columns.push({
|
|
|
|
|
id: 'group',
|
|
|
|
|
label: 'Group',
|
|
|
|
|
// eslint-disable-next-line react/display-name
|
|
|
|
|
renderCell: ({ data: rule }) => {
|
|
|
|
|
const { namespace, group } = rule;
|
|
|
|
|
const { rulesSource } = namespace;
|
|
|
|
|
return isCloudRulesSource(rulesSource) ? `${namespace.name} > ${group.name}` : namespace.name;
|
|
|
|
|
},
|
|
|
|
|
size: 5,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return columns;
|
2021-07-07 16:17:26 -07:00
|
|
|
}, [hasRuler, showSummaryColumn, showGroupColumn]);
|
2021-06-23 09:27:47 +03:00
|
|
|
}
|