import React, { PureComponent } from 'react'; import { SelectableValue, getFieldDisplayName, AnnotationEvent, AnnotationEventMappings, AnnotationEventFieldMapping, formattedValueToString, AnnotationEventFieldSource, getValueFormat, } from '@grafana/data'; import { Select, Tooltip, Icon } from '@grafana/ui'; import { annotationEventNames, AnnotationFieldInfo } from '../standardAnnotationSupport'; import { AnnotationQueryResponse } from '../types'; // const valueOptions: Array> = [ // { value: AnnotationEventFieldSource.Field, label: 'Field', description: 'Set the field value from a response field' }, // { value: AnnotationEventFieldSource.Text, label: 'Text', description: 'Enter direct text for the value' }, // { value: AnnotationEventFieldSource.Skip, label: 'Skip', description: 'Hide this field' }, // ]; interface Props { response?: AnnotationQueryResponse; mappings?: AnnotationEventMappings; change: (mappings?: AnnotationEventMappings) => void; } interface State { fieldNames: Array>; } export class AnnotationFieldMapper extends PureComponent { constructor(props: Props) { super(props); this.state = { fieldNames: [], }; } updateFields = () => { const frame = this.props.response?.panelData?.series[0]; if (frame && frame.fields) { const fieldNames = frame.fields.map((f) => { const name = getFieldDisplayName(f, frame); let description = ''; for (let i = 0; i < frame.length; i++) { if (i > 0) { description += ', '; } if (i > 2) { description += '...'; break; } description += f.values.get(i); } if (description.length > 50) { description = description.substring(0, 50) + '...'; } return { label: `${name} (${f.type})`, value: name, description, }; }); this.setState({ fieldNames }); } }; componentDidMount() { this.updateFields(); } componentDidUpdate(oldProps: Props) { if (oldProps.response !== this.props.response) { this.updateFields(); } } onFieldSourceChange = (k: keyof AnnotationEvent, v: SelectableValue) => { const mappings = this.props.mappings || {}; const mapping = mappings[k] || {}; this.props.change({ ...mappings, [k]: { ...mapping, source: v.value || AnnotationEventFieldSource.Field, }, }); }; onFieldNameChange = (k: keyof AnnotationEvent, v: SelectableValue) => { const mappings = this.props.mappings || {}; const mapping = mappings[k] || {}; this.props.change({ ...mappings, [k]: { ...mapping, value: v.value, source: AnnotationEventFieldSource.Field, }, }); }; renderRow(row: AnnotationFieldInfo, mapping: AnnotationEventFieldMapping, first?: AnnotationEvent) { const { fieldNames } = this.state; let picker = fieldNames; const current = mapping.value; let currentValue = fieldNames.find((f) => current === f.value); if (current) { picker = [...fieldNames]; if (!currentValue) { picker.push({ label: current, value: current, }); } } let value = first ? first[row.key] : ''; if (value && row.key.startsWith('time')) { const fmt = getValueFormat('dateTimeAsIso'); value = formattedValueToString(fmt(value as number)); } if (value === null || value === undefined) { value = ''; // empty string } return ( {row.key}{' '} {row.help && ( )} {/* ) => { this.onFieldNameChange(row.key, v); }} noOptionsMessage="Unknown field names" allowCustomValue={true} /> {`${value}`} ); } render() { const first = this.props.response?.events?.[0]; const mappings = this.props.mappings || {}; return ( {annotationEventNames.map((row) => { return this.renderRow(row, mappings[row.key] || {}, first); })}
Annotation From First Value
); } }