import { css } from '@emotion/css'; import { useMemo } from 'react'; import * as React from 'react'; import { useAsync } from 'react-use'; import { AnnotationQuery, DataSourceInstanceSettings, getDataSourceRef, GrafanaTheme2, SelectableValue, } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { config, getDataSourceSrv } from '@grafana/runtime'; import { VizPanel } from '@grafana/scenes'; import { AnnotationPanelFilter } from '@grafana/schema/src/raw/dashboard/x/dashboard_types.gen'; import { Button, Checkbox, Field, FieldSet, Input, MultiSelect, Select, useStyles2, Stack, Alert } from '@grafana/ui'; import { ColorValueEditor } from 'app/core/components/OptionsUI/color'; import { Trans } from 'app/core/internationalization'; import StandardAnnotationQueryEditor from 'app/features/annotations/components/StandardAnnotationQueryEditor'; import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; import { getPanelIdForVizPanel } from '../../utils/utils'; import { AngularEditorLoader } from './AngularEditorLoader'; type Props = { annotation: AnnotationQuery; editIndex: number; panels: VizPanel[]; onUpdate: (annotation: AnnotationQuery, editIndex: number) => void; onBackToList: () => void; onDelete: (index: number) => void; }; export const newAnnotationName = 'New annotation'; export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate, onBackToList, onDelete }: Props) => { const styles = useStyles2(getStyles); const panelFilter = useMemo(() => { if (!annotation.filter) { return PanelFilterType.AllPanels; } return annotation.filter.exclude ? PanelFilterType.ExcludePanels : PanelFilterType.IncludePanels; }, [annotation.filter]); const { value: ds } = useAsync(() => { return getDataSourceSrv().get(annotation.datasource); }, [annotation.datasource]); const dsi = getDataSourceSrv().getInstanceSettings(annotation.datasource); const onNameChange = (ev: React.FocusEvent) => { onUpdate( { ...annotation, name: ev.currentTarget.value, }, editIndex ); }; const onDataSourceChange = (ds: DataSourceInstanceSettings) => { const dsRef = getDataSourceRef(ds); if (annotation.datasource?.type !== dsRef.type) { onUpdate( { datasource: dsRef, builtIn: annotation.builtIn, enable: annotation.enable, iconColor: annotation.iconColor, name: annotation.name, hide: annotation.hide, filter: annotation.filter, mappings: annotation.mappings, type: annotation.type, }, editIndex ); } else { onUpdate( { ...annotation, datasource: dsRef, }, editIndex ); } }; const onChange = (ev: React.FocusEvent) => { const target = ev.currentTarget; onUpdate( { ...annotation, [target.name]: target.type === 'checkbox' ? target.checked : target.value, }, editIndex ); }; const onColorChange = (color?: string) => { onUpdate( { ...annotation, iconColor: color!, }, editIndex ); }; const onFilterTypeChange = (v: SelectableValue) => { let filter = v.value === PanelFilterType.AllPanels ? undefined : { exclude: v.value === PanelFilterType.ExcludePanels, ids: annotation.filter?.ids ?? [], }; onUpdate({ ...annotation, filter }, editIndex); }; const onAddFilterPanelID = (selections: Array>) => { if (!Array.isArray(selections)) { return; } const filter: AnnotationPanelFilter = { exclude: panelFilter === PanelFilterType.ExcludePanels, ids: [], }; selections.forEach((selection) => selection.value && filter.ids.push(selection.value)); onUpdate({ ...annotation, filter }, editIndex); }; const onDeleteAndLeavePage = () => { onDelete(editIndex); onBackToList(); }; const isNewAnnotation = annotation.name === newAnnotationName; const sortFn = (a: SelectableValue, b: SelectableValue) => { if (a.label && b.label) { return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); } return -1; }; const selectablePanels: Array> = useMemo( () => panels // Filtering out rows at the moment, revisit to only include panels that support annotations // However the information to know if a panel supports annotations requires it to be already loaded // panel.plugin?.dataSupport?.annotations .filter((panel) => config.panels[panel.state.pluginId]) .map((panel) => ({ value: getPanelIdForVizPanel(panel), label: panel.state.title ?? `Panel ${getPanelIdForVizPanel(panel)}`, description: panel.state.description, imgUrl: config.panels[panel.state.pluginId].info.logos.small, })) .sort(sortFn) ?? [], [panels] ); return (
{!ds?.meta.annotations && ( The selected data source does not support annotations. Please select a different data source. )} <>