123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- 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<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
- value={valueOptions.find(v => v.value === mapping.source) || valueOptions[0]}
- options={valueOptions}
- onChange={(v: SelectableValue<AnnotationEventFieldSource>) => {
- this.onFieldSourceChange(row.key, v);
- }}
- />
- </td> */}
- <td>
- <Select
- 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>
- );
- }
- }
|