mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { useStyles2 } from '@grafana/ui';
|
|
import { AlertingRule } from 'app/types/unified-alerting';
|
|
import { css, cx } from '@emotion/css';
|
|
import React, { FC, Fragment, useState } from 'react';
|
|
import { getAlertTableStyles } from '../../styles/table';
|
|
import { alertInstanceKey } from '../../utils/rules';
|
|
import { AlertLabels } from '../AlertLabels';
|
|
import { CollapseToggle } from '../CollapseToggle';
|
|
import { AlertInstanceDetails } from './AlertInstanceDetails';
|
|
import { AlertStateTag } from './AlertStateTag';
|
|
|
|
interface Props {
|
|
instances: AlertingRule['alerts'];
|
|
}
|
|
|
|
export const AlertInstancesTable: FC<Props> = ({ instances }) => {
|
|
const styles = useStyles2(getStyles);
|
|
const tableStyles = useStyles2(getAlertTableStyles);
|
|
|
|
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
|
|
|
|
const toggleExpandedState = (ruleKey: string) =>
|
|
setExpandedKeys(
|
|
expandedKeys.includes(ruleKey) ? expandedKeys.filter((key) => key !== ruleKey) : [...expandedKeys, ruleKey]
|
|
);
|
|
|
|
return (
|
|
<table className={cx(tableStyles.table, styles.table)}>
|
|
<colgroup>
|
|
<col className={styles.colExpand} />
|
|
<col className={styles.colState} />
|
|
<col />
|
|
<col />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th></th>
|
|
<th>State</th>
|
|
<th>Labels</th>
|
|
<th>Created</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{instances.map((instance, idx) => {
|
|
const key = alertInstanceKey(instance);
|
|
const isExpanded = expandedKeys.includes(key);
|
|
|
|
// don't allow expanding if there's nothing to show
|
|
const isExpandable = instance.value || !!Object.keys(instance.annotations ?? {}).length;
|
|
return (
|
|
<Fragment key={key}>
|
|
<tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
|
|
<td>
|
|
{isExpandable && (
|
|
<CollapseToggle
|
|
isCollapsed={!isExpanded}
|
|
onToggle={() => toggleExpandedState(key)}
|
|
data-testid="alert-collapse-toggle"
|
|
/>
|
|
)}
|
|
</td>
|
|
<td>
|
|
<AlertStateTag state={instance.state} />
|
|
</td>
|
|
<td className={styles.labelsCell}>
|
|
<AlertLabels labels={instance.labels} />
|
|
</td>
|
|
<td className={styles.createdCell}>
|
|
{instance.activeAt.startsWith('0001') ? '-' : instance.activeAt.substr(0, 19).replace('T', ' ')}
|
|
</td>
|
|
</tr>
|
|
{isExpanded && isExpandable && (
|
|
<tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
|
|
<td></td>
|
|
<td colSpan={3}>
|
|
<AlertInstanceDetails instance={instance} />
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</Fragment>
|
|
);
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
};
|
|
|
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
|
colExpand: css`
|
|
width: 36px;
|
|
`,
|
|
colState: css`
|
|
width: 110px;
|
|
`,
|
|
labelsCell: css`
|
|
padding-top: ${theme.spacing(0.5)} !important;
|
|
padding-bottom: ${theme.spacing(0.5)} !important;
|
|
`,
|
|
createdCell: css`
|
|
white-space: nowrap;
|
|
`,
|
|
table: css`
|
|
td {
|
|
vertical-align: top;
|
|
padding-top: ${theme.spacing(1)};
|
|
padding-bottom: ${theme.spacing(1)};
|
|
}
|
|
`,
|
|
});
|