forked from grafana.jool/grafana-jool
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.2 KiB
118 lines
4.2 KiB
import React, { FC } from 'react';
|
|
import { useFieldArray, useFormContext } from 'react-hook-form';
|
|
import { MuteTimingFields } from '../../types/mute-timing-form';
|
|
import { Field, InlineFieldRow, InlineField, Input, Button, IconButton, useStyles2 } from '@grafana/ui';
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { css } from '@emotion/css';
|
|
|
|
interface Props {
|
|
intervalIndex: number;
|
|
}
|
|
|
|
export const MuteTimingTimeRange: FC<Props> = ({ intervalIndex }) => {
|
|
const styles = useStyles2(getStyles);
|
|
const { register, formState } = useFormContext<MuteTimingFields>();
|
|
|
|
const { fields: timeRanges, append: addTimeRange, remove: removeTimeRange } = useFieldArray<MuteTimingFields>({
|
|
name: `time_intervals.${intervalIndex}.times`,
|
|
});
|
|
|
|
const validateTime = (timeString: string) => {
|
|
if (!timeString) {
|
|
return true;
|
|
}
|
|
const [hour, minutes] = timeString.split(':').map((x) => parseInt(x, 10));
|
|
const isHourValid = hour > 0 && hour < 25;
|
|
const isMinuteValid = minutes > -1 && minutes < 60;
|
|
const isTimeValid = hour === 24 ? minutes === 0 : isHourValid && isMinuteValid;
|
|
|
|
return isTimeValid || 'Time is invalid';
|
|
};
|
|
|
|
const formErrors = formState.errors.time_intervals?.[intervalIndex];
|
|
const timeRangeInvalid = formErrors?.times?.some((value) => value?.start_time || value?.end_time) ?? false;
|
|
|
|
return (
|
|
<div>
|
|
<Field
|
|
className={styles.field}
|
|
label="Time range"
|
|
description="The time inclusive of the starting time and exclusive of the end time in UTC"
|
|
invalid={timeRangeInvalid}
|
|
error={timeRangeInvalid ? 'Times must be between 00:00 and 24:00 UTC' : ''}
|
|
>
|
|
<>
|
|
{timeRanges.map((timeRange, index) => {
|
|
return (
|
|
<div className={styles.timeRange} key={timeRange.id}>
|
|
<InlineFieldRow>
|
|
<InlineField label="Start time" invalid={!!formErrors?.times?.[index]?.start_time}>
|
|
<Input
|
|
{...register(`time_intervals.${intervalIndex}.times.${index}.start_time`, {
|
|
validate: validateTime,
|
|
})}
|
|
className={styles.timeRangeInput}
|
|
// @ts-ignore react-hook-form doesn't handle nested field arrays well
|
|
defaultValue={timeRange.start_time}
|
|
placeholder="HH:MM"
|
|
data-testid="mute-timing-starts-at"
|
|
/>
|
|
</InlineField>
|
|
<InlineField label="End time" invalid={!!formErrors?.times?.[index]?.end_time}>
|
|
<Input
|
|
{...register(`time_intervals.${intervalIndex}.times.${index}.end_time`, {
|
|
validate: validateTime,
|
|
})}
|
|
className={styles.timeRangeInput}
|
|
// @ts-ignore react-hook-form doesn't handle nested field arrays well
|
|
defaultValue={timeRange.end_time}
|
|
placeholder="HH:MM"
|
|
data-testid="mute-timing-ends-at"
|
|
/>
|
|
</InlineField>
|
|
<IconButton
|
|
className={styles.deleteTimeRange}
|
|
title={'Remove'}
|
|
name={'trash-alt'}
|
|
type="button"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
removeTimeRange(index);
|
|
}}
|
|
/>
|
|
</InlineFieldRow>
|
|
</div>
|
|
);
|
|
})}
|
|
</>
|
|
</Field>
|
|
<Button
|
|
className={styles.addTimeRange}
|
|
variant="secondary"
|
|
type="button"
|
|
icon={'plus'}
|
|
onClick={() => addTimeRange({ start_time: '', end_time: '' })}
|
|
>
|
|
Add another time range
|
|
</Button>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
field: css`
|
|
margin-bottom: 0;
|
|
`,
|
|
timeRange: css`
|
|
margin-bottom: ${theme.spacing(1)};
|
|
`,
|
|
timeRangeInput: css`
|
|
width: 120px;
|
|
`,
|
|
deleteTimeRange: css`
|
|
margin: ${theme.spacing(1)} 0 0 ${theme.spacing(0.5)};
|
|
`,
|
|
addTimeRange: css`
|
|
margin-bottom: ${theme.spacing(2)};
|
|
`,
|
|
});
|
|
|