Files
grafana/public/app/features/alerting/unified/components/silences/SilenceTableRow.tsx
Nathan Rodman 1913d304a3 Alerting: Add silences table (#33138)
* Create table for silences

* Style table to figma designs

* Add rules table to silences

* Rebase with new rules table

* Remove redundant reducer

* fetch alertmanager alerts (#33142)

* fetch alertmanager alerts

* show the alerts json

* Use matching alerts from alertmanager api

* Add handle to expire silence

* Get silenced alerts closer to figma designs

* fix expire silence endpoint typo

* Style affected alerts table

* Add default empty string for alertmanager source

Co-authored-by: Domas <domasx2@gmail.com>
2021-04-27 13:46:34 -07:00

128 lines
4.0 KiB
TypeScript

import React, { FC, Fragment, useState } from 'react';
import { dateMath, GrafanaTheme, toDuration } from '@grafana/data';
import { css, cx } from '@emotion/css';
import { Silence, AlertmanagerAlert } from 'app/plugins/datasource/alertmanager/types';
import { AlertLabel } from '../AlertLabel';
import { StateTag } from '../StateTag';
import { CollapseToggle } from '../CollapseToggle';
import { ActionButton } from '../rules/ActionButton';
import { ActionIcon } from '../rules/ActionIcon';
import { useStyles } from '@grafana/ui';
import SilencedAlertsTable from './SilencedAlertsTable';
import { expireSilenceAction } from '../../state/actions';
import { useDispatch } from 'react-redux';
interface Props {
className?: string;
silence: Silence;
silencedAlerts: AlertmanagerAlert[];
alertManagerSourceName: string;
}
const SilenceTableRow: FC<Props> = ({ silence, className, silencedAlerts, alertManagerSourceName }) => {
const [isCollapsed, setIsCollapsed] = useState<boolean>(true);
const dispatch = useDispatch();
const styles = useStyles(getStyles);
const { status, matchers, startsAt, endsAt, comment, createdBy } = silence;
const dateDisplayFormat = 'YYYY-MM-DD HH:mm';
const startsAtDate = dateMath.parse(startsAt);
const endsAtDate = dateMath.parse(endsAt);
const duration = toDuration(endsAtDate?.diff(startsAtDate || '')).asSeconds();
const handleExpireSilenceClick = () => {
dispatch(expireSilenceAction(alertManagerSourceName, silence.id));
};
return (
<Fragment>
<tr className={className}>
<td>
<CollapseToggle isCollapsed={isCollapsed} onToggle={(value) => setIsCollapsed(value)} />
</td>
<td>
<StateTag status={status.state}>{status.state}</StateTag>
</td>
<td className={styles.matchersCell}>
{matchers?.map(({ name, value, isRegex }) => {
return <AlertLabel key={`${name}-${value}`} labelKey={name} value={value} isRegex={isRegex} />;
})}
</td>
<td>{silencedAlerts.length}</td>
<td>
{startsAtDate?.format(dateDisplayFormat)} {'-'}
<br />
{endsAtDate?.format(dateDisplayFormat)}
</td>
<td className={styles.actionsCell}>
{status.state === 'expired' ? (
<ActionButton icon="sync">Recreate</ActionButton>
) : (
<ActionButton icon="bell" onClick={handleExpireSilenceClick}>
Unsilence
</ActionButton>
)}
<ActionIcon icon="pen" tooltip="edit" />
</td>
</tr>
{!isCollapsed && (
<>
<tr className={className}>
<td />
<td>Comment</td>
<td colSpan={4}>{comment}</td>
</tr>
<tr className={className}>
<td />
<td>Schedule</td>
<td colSpan={4}>{`${startsAtDate?.format(dateDisplayFormat)} - ${endsAtDate?.format(
dateDisplayFormat
)}`}</td>
</tr>
<tr className={className}>
<td />
<td>Duration</td>
<td colSpan={4}>{duration} seconds</td>
</tr>
<tr className={className}>
<td />
<td>Created by</td>
<td colSpan={4}>{createdBy}</td>
</tr>
{!!silencedAlerts.length && (
<tr className={cx(className, styles.alertRulesCell)}>
<td />
<td>Affected alerts</td>
<td colSpan={4}>
<SilencedAlertsTable silencedAlerts={silencedAlerts} />
</td>
</tr>
)}
</>
)}
</Fragment>
);
};
const getStyles = (theme: GrafanaTheme) => ({
matchersCell: css`
& > * + * {
margin-left: ${theme.spacing.xs};
}
`,
actionsCell: css`
text-align: right;
width: 1%;
white-space: nowrap;
& > * + * {
margin-left: ${theme.spacing.sm};
}
`,
alertRulesCell: css`
vertical-align: top;
`,
});
export default SilenceTableRow;