grafana/public/app/features/annotations/components/AnnotationResultMapper.tsx
Ashley Harrison 8aa3845f70
Select: Make portalling the menu opt-in, but opt-in *everywhere* (#37501)
* Select: Don't portal by default

* Select: Portal all the Selects

* Fix indendentation in this comment

* Select: Remove @example docs until formatting is correct

* Docs: Add some documentation for the Select changes

* Update docs/sources/whatsnew/whats-new-in-v8-1.md

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update docs/sources/whatsnew/whats-new-in-v8-1.md

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update packages/grafana-ui/src/components/Select/types.ts

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update public/app/core/components/TransformersUI/configFromQuery/ConfigFromQueryTransformerEditor.tsx

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update public/app/core/components/TransformersUI/configFromQuery/ConfigFromQueryTransformerEditor.tsx

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update public/app/core/components/TransformersUI/configFromQuery/ConfigFromQueryTransformerEditor.tsx

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Update public/app/core/components/TransformersUI/prepareTimeSeries/PrepareTimeSeriesEditor.tsx

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

* Docs: Variants instead of varients

* Update public/app/core/components/TransformersUI/configFromQuery/ConfigFromQueryTransformerEditor.tsx

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>

Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>
2021-08-04 15:47:53 +01:00

198 lines
5.2 KiB
TypeScript

import React, { PureComponent } from 'react';
import {
SelectableValue,
getFieldDisplayName,
AnnotationEvent,
AnnotationEventMappings,
AnnotationEventFieldMapping,
formattedValueToString,
AnnotationEventFieldSource,
getValueFormat,
} from '@grafana/data';
import { annotationEventNames, AnnotationFieldInfo } from '../standardAnnotationSupport';
import { Select, Tooltip, Icon } from '@grafana/ui';
import { AnnotationQueryResponse } from '../types';
// const valueOptions: Array<SelectableValue<AnnotationEventFieldSource>> = [
// { 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<SelectableValue<string>>;
}
export class AnnotationFieldMapper extends PureComponent<Props, State> {
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<AnnotationEventFieldSource>) => {
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<string>) => {
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 (
<tr key={row.key}>
<td>
{row.key}{' '}
{row.help && (
<Tooltip content={row.help}>
<Icon name="info-circle" />
</Tooltip>
)}
</td>
{/* <td>
<Select
menuShouldPortal
value={valueOptions.find(v => v.value === mapping.source) || valueOptions[0]}
options={valueOptions}
onChange={(v: SelectableValue<AnnotationEventFieldSource>) => {
this.onFieldSourceChange(row.key, v);
}}
/>
</td> */}
<td>
<Select
menuShouldPortal
value={currentValue}
options={picker}
placeholder={row.placeholder || row.key}
onChange={(v: SelectableValue<string>) => {
this.onFieldNameChange(row.key, v);
}}
noOptionsMessage="Unknown field names"
allowCustomValue={true}
/>
</td>
<td>{`${value}`}</td>
</tr>
);
}
render() {
const first = this.props.response?.events?.[0];
const mappings = this.props.mappings || {};
return (
<table className="filter-table">
<thead>
<tr>
<th>Annotation</th>
<th>From</th>
<th>First Value</th>
</tr>
</thead>
<tbody>
{annotationEventNames.map((row) => {
return this.renderRow(row, mappings[row.key] || {}, first);
})}
</tbody>
</table>
);
}
}