mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
199 lines
7.5 KiB
TypeScript
199 lines
7.5 KiB
TypeScript
import React, { FC, useState } from 'react';
|
|
import { cx } from '@emotion/css';
|
|
import { Button, Collapse, Field, Form, Input, InputControl, Link, MultiSelect, Select, useStyles2 } from '@grafana/ui';
|
|
import { AmRouteReceiver, FormAmRoute } from '../../types/amroutes';
|
|
import {
|
|
mapMultiSelectValueToStrings,
|
|
mapSelectValueToString,
|
|
optionalPositiveInteger,
|
|
stringToSelectableValue,
|
|
stringsToSelectableValues,
|
|
} from '../../utils/amroutes';
|
|
import { makeAMLink } from '../../utils/misc';
|
|
import { timeOptions } from '../../utils/time';
|
|
import { getFormStyles } from './formStyles';
|
|
|
|
export interface AmRootRouteFormProps {
|
|
alertManagerSourceName: string;
|
|
onCancel: () => void;
|
|
onSave: (data: FormAmRoute) => void;
|
|
receivers: AmRouteReceiver[];
|
|
routes: FormAmRoute;
|
|
}
|
|
|
|
export const AmRootRouteForm: FC<AmRootRouteFormProps> = ({
|
|
alertManagerSourceName,
|
|
onCancel,
|
|
onSave,
|
|
receivers,
|
|
routes,
|
|
}) => {
|
|
const styles = useStyles2(getFormStyles);
|
|
const [isTimingOptionsExpanded, setIsTimingOptionsExpanded] = useState(false);
|
|
const [groupByOptions, setGroupByOptions] = useState(stringsToSelectableValues(routes.groupBy));
|
|
|
|
return (
|
|
<Form defaultValues={routes} onSubmit={onSave}>
|
|
{({ control, errors, setValue }) => (
|
|
<>
|
|
<Field label="Default contact point">
|
|
<div className={styles.container}>
|
|
<InputControl
|
|
render={({ field: { onChange, ref, ...field } }) => (
|
|
<Select
|
|
{...field}
|
|
className={styles.input}
|
|
onChange={(value) => onChange(mapSelectValueToString(value))}
|
|
options={receivers}
|
|
/>
|
|
)}
|
|
control={control}
|
|
name="receiver"
|
|
/>
|
|
<span>or</span>
|
|
<Link href={makeAMLink('/alerting/notifications/receivers/new', alertManagerSourceName)}>
|
|
Create a contact point
|
|
</Link>
|
|
</div>
|
|
</Field>
|
|
<Field label="Group by" description="Group alerts when you receive a notification based on labels.">
|
|
{/* @ts-ignore-check: react-hook-form made me do this */}
|
|
<InputControl
|
|
render={({ field: { onChange, ref, ...field } }) => (
|
|
<MultiSelect
|
|
{...field}
|
|
allowCustomValue
|
|
className={styles.input}
|
|
onCreateOption={(opt: string) => {
|
|
setGroupByOptions((opts) => [...opts, stringToSelectableValue(opt)]);
|
|
|
|
// @ts-ignore-check: react-hook-form made me do this
|
|
setValue('groupBy', [...field.value, opt]);
|
|
}}
|
|
onChange={(value) => onChange(mapMultiSelectValueToStrings(value))}
|
|
options={groupByOptions}
|
|
/>
|
|
)}
|
|
control={control}
|
|
name="groupBy"
|
|
/>
|
|
</Field>
|
|
<Collapse
|
|
collapsible
|
|
isOpen={isTimingOptionsExpanded}
|
|
label="Timing options"
|
|
onToggle={setIsTimingOptionsExpanded}
|
|
>
|
|
<Field
|
|
label="Group wait"
|
|
description="The waiting time until the initial notification is sent for a new group created by an incoming alert."
|
|
invalid={!!errors.groupWaitValue}
|
|
error={errors.groupWaitValue?.message}
|
|
>
|
|
<>
|
|
<div className={cx(styles.container, styles.timingContainer)}>
|
|
<InputControl
|
|
render={({ field, fieldState: { invalid } }) => (
|
|
<Input {...field} className={styles.smallInput} invalid={invalid} />
|
|
)}
|
|
control={control}
|
|
name="groupWaitValue"
|
|
rules={{
|
|
validate: optionalPositiveInteger,
|
|
}}
|
|
/>
|
|
<InputControl
|
|
render={({ field: { onChange, ref, ...field } }) => (
|
|
<Select
|
|
{...field}
|
|
className={styles.input}
|
|
onChange={(value) => onChange(mapSelectValueToString(value))}
|
|
options={timeOptions}
|
|
/>
|
|
)}
|
|
control={control}
|
|
name="groupWaitValueType"
|
|
/>
|
|
</div>
|
|
</>
|
|
</Field>
|
|
<Field
|
|
label="Group interval"
|
|
description="The waiting time to send a batch of new alerts for that group after the first notification was sent."
|
|
invalid={!!errors.groupIntervalValue}
|
|
error={errors.groupIntervalValue?.message}
|
|
>
|
|
<>
|
|
<div className={cx(styles.container, styles.timingContainer)}>
|
|
<InputControl
|
|
render={({ field, fieldState: { invalid } }) => (
|
|
<Input {...field} className={styles.smallInput} invalid={invalid} />
|
|
)}
|
|
control={control}
|
|
name="groupIntervalValue"
|
|
rules={{
|
|
validate: optionalPositiveInteger,
|
|
}}
|
|
/>
|
|
<InputControl
|
|
render={({ field: { onChange, ref, ...field } }) => (
|
|
<Select
|
|
{...field}
|
|
className={styles.input}
|
|
onChange={(value) => onChange(mapSelectValueToString(value))}
|
|
options={timeOptions}
|
|
/>
|
|
)}
|
|
control={control}
|
|
name="groupIntervalValueType"
|
|
/>
|
|
</div>
|
|
</>
|
|
</Field>
|
|
<Field
|
|
label="Repeat interval"
|
|
description="The waiting time to resend an alert after they have successfully been sent."
|
|
invalid={!!errors.repeatIntervalValue}
|
|
error={errors.repeatIntervalValue?.message}
|
|
>
|
|
<>
|
|
<div className={cx(styles.container, styles.timingContainer)}>
|
|
<InputControl
|
|
render={({ field, fieldState: { invalid } }) => (
|
|
<Input {...field} className={styles.smallInput} invalid={invalid} />
|
|
)}
|
|
control={control}
|
|
name="repeatIntervalValue"
|
|
rules={{
|
|
validate: optionalPositiveInteger,
|
|
}}
|
|
/>
|
|
<InputControl
|
|
render={({ field: { onChange, ref, ...field } }) => (
|
|
<Select
|
|
{...field}
|
|
className={styles.input}
|
|
menuPlacement="top"
|
|
onChange={(value) => onChange(mapSelectValueToString(value))}
|
|
options={timeOptions}
|
|
/>
|
|
)}
|
|
control={control}
|
|
name="repeatIntervalValueType"
|
|
/>
|
|
</div>
|
|
</>
|
|
</Field>
|
|
</Collapse>
|
|
<div className={styles.container}>
|
|
<Button type="submit">Save</Button>
|
|
<Button onClick={onCancel} type="reset" variant="secondary" fill="outline">
|
|
Cancel
|
|
</Button>
|
|
</div>
|
|
</>
|
|
)}
|
|
</Form>
|
|
);
|
|
};
|