The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
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.
grafana/public/app/features/alerting/unified/components/rule-editor/AnnotationsField.tsx

177 lines
5.8 KiB

import { css, cx } from '@emotion/css';
import produce from 'immer';
import React, { useCallback } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { useToggle } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { Stack } from '@grafana/experimental';
import { Button, Field, Input, InputControl, Label, TextArea, useStyles2 } from '@grafana/ui';
import { RuleFormValues } from '../../types/rule-form';
import { Annotation } from '../../utils/constants';
import { AnnotationKeyInput } from './AnnotationKeyInput';
import { DashboardPicker } from './DashboardPicker';
const AnnotationsField = () => {
const styles = useStyles2(getStyles);
const [showPanelSelector, setShowPanelSelector] = useToggle(false);
Grafana-UI: Update React Hook Form to v7 (#33328) * Update hook form * Update Form component * Update ChangePassword.tsx * Update custom types * Update SaveDashboardForm * Update form story * Update FieldArray.story.tsx * Bump hook form version * Update typescript to v4.2.4 * Update ForgottenPassword.tsx * Update LoginForm.tsx * Update SignupPage.tsx * Update VerifyEmail.tsx * Update AdminEditOrgPage.tsx * Update UserCreatePage.tsx * Update BasicSettings.tsx * Update NotificationChannelForm.tsx * Update NotificationChannelOptions.tsx * Update NotificationSettings.tsx * Update OptionElement.tsx * Update AlertRuleForm.tsx * Update AlertTypeStep.tsx * Update AnnotationsField.tsx * Update ConditionField.tsx * Update ConditionsStep.tsx * Update GroupAndNamespaceFields.tsx * Update LabelsField.tsx * Update QueryStep.tsx * Update RowOptionsForm.tsx * Update SaveDashboardAsForm.tsx * Update NewDashboardsFolder.tsx * Update ImportDashboardForm.tsx * Update DashboardImportPage.tsx * Update NewOrgPage.tsx * Update OrgProfile.tsx * Update UserInviteForm.tsx * Update PlaylistForm.tsx * Update ChangePasswordForm.tsx * Update UserProfileEditForm.tsx * Update TeamSettings.tsx * Update SignupInvited.tsx * Expose setValue from the Form * Update typescript to v4.2.4 * Remove ref from field props * Fix tests * Revert TS update * Use exact version * Update latest batch of changes * Reduce the number of strict TS errors * Fix defaults * more type error fixes * Update CreateTeam * fix folder picker in rule form * fixes for hook form 7 * Update docs Co-authored-by: Domas <domasx2@gmail.com>
5 years ago
const {
control,
register,
watch,
formState: { errors },
setValue,
} = useFormContext<RuleFormValues>();
const annotations = watch('annotations');
const existingKeys = useCallback(
Grafana-UI: Update React Hook Form to v7 (#33328) * Update hook form * Update Form component * Update ChangePassword.tsx * Update custom types * Update SaveDashboardForm * Update form story * Update FieldArray.story.tsx * Bump hook form version * Update typescript to v4.2.4 * Update ForgottenPassword.tsx * Update LoginForm.tsx * Update SignupPage.tsx * Update VerifyEmail.tsx * Update AdminEditOrgPage.tsx * Update UserCreatePage.tsx * Update BasicSettings.tsx * Update NotificationChannelForm.tsx * Update NotificationChannelOptions.tsx * Update NotificationSettings.tsx * Update OptionElement.tsx * Update AlertRuleForm.tsx * Update AlertTypeStep.tsx * Update AnnotationsField.tsx * Update ConditionField.tsx * Update ConditionsStep.tsx * Update GroupAndNamespaceFields.tsx * Update LabelsField.tsx * Update QueryStep.tsx * Update RowOptionsForm.tsx * Update SaveDashboardAsForm.tsx * Update NewDashboardsFolder.tsx * Update ImportDashboardForm.tsx * Update DashboardImportPage.tsx * Update NewOrgPage.tsx * Update OrgProfile.tsx * Update UserInviteForm.tsx * Update PlaylistForm.tsx * Update ChangePasswordForm.tsx * Update UserProfileEditForm.tsx * Update TeamSettings.tsx * Update SignupInvited.tsx * Expose setValue from the Form * Update typescript to v4.2.4 * Remove ref from field props * Fix tests * Revert TS update * Use exact version * Update latest batch of changes * Reduce the number of strict TS errors * Fix defaults * more type error fixes * Update CreateTeam * fix folder picker in rule form * fixes for hook form 7 * Update docs Co-authored-by: Domas <domasx2@gmail.com>
5 years ago
(index: number): string[] => annotations.filter((_, idx: number) => idx !== index).map(({ key }) => key),
[annotations]
);
const { fields, append, remove } = useFieldArray({ control, name: 'annotations' });
const selectedDashboardUid = annotations.find((annotation) => annotation.key === Annotation.dashboardUID)?.value;
const selectedPanelId = annotations.find((annotation) => annotation.key === Annotation.panelID)?.value;
const setSelectedDashboardAndPanelId = (dashboardUid: string, panelId: string) => {
const updatedAnnotations = produce(annotations, (draft) => {
const dashboardAnnotation = draft.find((a) => a.key === Annotation.dashboardUID);
const panelAnnotation = draft.find((a) => a.key === Annotation.panelID);
if (dashboardAnnotation) {
dashboardAnnotation.value = dashboardUid;
} else {
draft.push({ key: Annotation.dashboardUID, value: dashboardUid });
}
if (panelAnnotation) {
panelAnnotation.value = panelId;
} else {
draft.push({ key: Annotation.panelID, value: panelId });
}
});
setValue('annotations', updatedAnnotations);
setShowPanelSelector(false);
};
return (
<>
<Label>Summary and annotations</Label>
<div className={styles.flexColumn}>
{fields.map((annotationField, index) => {
const isUrl = annotations[index]?.key?.toLocaleLowerCase().endsWith('url');
const ValueInputComponent = isUrl ? Input : TextArea;
return (
<div key={annotationField.id} className={styles.flexRow}>
<Field
className={styles.field}
invalid={!!errors.annotations?.[index]?.key?.message}
error={errors.annotations?.[index]?.key?.message}
data-testid={`annotation-key-${index}`}
>
<InputControl
name={`annotations.${index}.key`}
defaultValue={annotationField.key}
render={({ field: { ref, ...field } }) => (
<AnnotationKeyInput
{...field}
aria-label={`Annotation detail ${index + 1}`}
existingKeys={existingKeys(index)}
width={18}
/>
)}
control={control}
rules={{ required: { value: !!annotations[index]?.value, message: 'Required.' } }}
/>
</Field>
<Field
className={cx(styles.flexRowItemMargin, styles.field)}
invalid={!!errors.annotations?.[index]?.value?.message}
error={errors.annotations?.[index]?.value?.message}
>
<ValueInputComponent
data-testid={`annotation-value-${index}`}
className={cx(styles.annotationValueInput, { [styles.textarea]: !isUrl })}
{...register(`annotations.${index}.value`)}
placeholder={isUrl ? 'https://' : `Text`}
defaultValue={annotationField.value}
/>
</Field>
<Button
type="button"
className={styles.flexRowItemMargin}
aria-label="delete annotation"
icon="trash-alt"
variant="secondary"
onClick={() => remove(index)}
/>
</div>
);
})}
<Stack direction="row" gap={1}>
<Button
className={styles.addAnnotationsButton}
icon="plus-circle"
type="button"
variant="secondary"
onClick={() => {
append({ key: '', value: '' });
}}
>
Add annotation
</Button>
<Button type="button" variant="secondary" icon="dashboard" onClick={() => setShowPanelSelector(true)}>
Set dashboard and panel
</Button>
</Stack>
{showPanelSelector && (
<DashboardPicker
isOpen={true}
dashboardUid={selectedDashboardUid}
panelId={selectedPanelId}
onChange={setSelectedDashboardAndPanelId}
onDismiss={() => setShowPanelSelector(false)}
/>
)}
</div>
</>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
annotationValueInput: css`
Alerting: Improve UI for making more clear that evaluation interval belongs to the group (#56397) * In GrafanaEvaluationBehaviour component : Split evaluation interval from for duration and add button to edit to allow editing it and warning * Move folder and group fields to the evaluation section in the alert form * Include 'Group behaviour' info in a card and fix 'Edit group behaviour' button onClick. * Create hook for getting groups for a particular folder * Use dropdown in group instead of input and fill it with groups that belong to the selected folder * Add evaluation interval for each group in dropdown , and show warning in case user wants to update it * Avoid saving evaluation interval when some rules in the same group would have invalid For with this change * Clear group value when reseting the drop down * Remove evaluationEvery from form values, show this as a label and add a button to edit the group * Open EditRuleGroupModal for editing evaluation interval form the alert rule form * Fix aligment in group behaviour card * compact space in evaluation behaviour card and change group drop down label * In EditgroupModal, in case of grafana managed group, show folder instead of namespcace label and disable the folder name input * Add edge case in rulesInSameGroupHaveInvalidFor method when For value is zero * Vertically align annotations input to the evaluation section in alert rule form * Fix width when editing new group * Add placeholder for group input * Make folder and group in modal readonly from alert form and disable edit group button when new group * Update texts * Don't show evaluation behaviour section until folder and group are selected * Update texts * Fix merge conflits * Fix wrong margin in evaluation label * Remove non-used isRulerGrafanaRuleDTO method * Remove negative margin to avoid overlaping on Firefox
3 years ago
width: 394px;
`,
textarea: css`
height: 76px;
`,
addAnnotationsButton: css`
flex-grow: 0;
align-self: flex-start;
margin-left: 148px;
`,
flexColumn: css`
display: flex;
flex-direction: column;
`,
field: css`
margin-bottom: ${theme.spacing(0.5)};
`,
flexRow: css`
display: flex;
flex-direction: row;
justify-content: flex-start;
`,
flexRowItemMargin: css`
margin-left: ${theme.spacing(0.5)};
`,
});
export default AnnotationsField;