// Libraries import React, { ChangeEvent, FormEvent, useMemo } from 'react'; import { useAsync } from 'react-use'; // Components import { selectors as editorSelectors } from '@grafana/e2e-selectors'; import { InlineField, InlineFieldRow, InlineSwitch, Input, Select, TextArea } from '@grafana/ui'; import { QueryEditorProps, SelectableValue } from '@grafana/data'; import { RandomWalkEditor, StreamingClientEditor } from './components'; // Types import { TestDataDataSource } from './datasource'; import { CSVWave, NodesQuery, TestDataQuery, USAQuery } from './types'; import { PredictablePulseEditor } from './components/PredictablePulseEditor'; import { CSVWavesEditor } from './components/CSVWaveEditor'; import { defaultCSVWaveQuery, defaultPulseQuery, defaultQuery } from './constants'; import { GrafanaLiveEditor } from './components/GrafanaLiveEditor'; import { NodeGraphEditor } from './components/NodeGraphEditor'; import { RawFrameEditor } from './components/RawFrameEditor'; import { defaultStreamQuery } from './runStreams'; import { CSVFileEditor } from './components/CSVFileEditor'; import { CSVContentEditor } from './components/CSVContentEditor'; import { USAQueryEditor, usaQueryModes } from './components/USAQueryEditor'; import ErrorEditor from './components/ErrorEditor'; import { SimulationQueryEditor } from './components/SimulationQueryEditor'; const showLabelsFor = ['random_walk', 'predictable_pulse']; const endpoints = [ { value: 'datasources', label: 'Data Sources' }, { value: 'search', label: 'Search' }, { value: 'annotations', label: 'Annotations' }, ]; const selectors = editorSelectors.components.DataSource.TestData.QueryTab; export interface EditorProps { onChange: (value: any) => void; query: TestDataQuery; } export type Props = QueryEditorProps; export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props) => { query = { ...defaultQuery, ...query }; const { loading, value: scenarioList } = useAsync(async () => { // migrate manual_entry (unusable since 7, removed in 8) if (query.scenarioId === 'manual_entry' && (query as any).points) { let csvContent = 'Time,Value\n'; for (const point of (query as any).points) { csvContent += `${point[1]},${point[0]}\n`; } onChange({ refId: query.refId, datasource: query.datasource, scenarioId: 'csv_content', csvContent, }); } const vals = await datasource.getScenarios(); const hideAlias = ['simulation']; return vals.map((v) => ({ ...v, hideAliasField: hideAlias.includes(v.id), })); }, []); const onUpdate = (query: TestDataQuery) => { onChange(query); onRunQuery(); }; const currentScenario = useMemo( () => scenarioList?.find((scenario) => scenario.id === query.scenarioId), [scenarioList, query] ); const scenarioId = currentScenario?.id; const description = currentScenario?.description; const onScenarioChange = (item: SelectableValue) => { const scenario = scenarioList?.find((sc) => sc.id === item.value); if (!scenario) { return; } // Clear model from existing props that belong to other scenarios const update: TestDataQuery = { scenarioId: item.value!, refId: query.refId, alias: query.alias, datasource: query.datasource, }; if (scenario.stringInput) { update.stringInput = scenario.stringInput; } switch (scenario.id) { case 'grafana_api': update.stringInput = 'datasources'; break; case 'streaming_client': update.stream = defaultStreamQuery; break; case 'live': update.channel = 'random-2s-stream'; // default stream break; case 'simulation': update.sim = { key: { type: 'flight', tick: 10 } }; // default stream break; case 'predictable_pulse': update.pulseWave = defaultPulseQuery; break; case 'predictable_csv_wave': update.csvWave = defaultCSVWaveQuery; break; case 'usa': update.usa = { mode: usaQueryModes[0].value, }; } onUpdate(update); }; const onInputChange = (e: FormEvent) => { const { name, value, type } = e.target as HTMLInputElement | HTMLTextAreaElement; let newValue: any = value; if (type === 'number') { newValue = Number(value); } if (name === 'levelColumn') { newValue = (e.target as HTMLInputElement).checked; } onUpdate({ ...query, [name]: newValue }); }; const onFieldChange = (field: string) => (e: ChangeEvent) => { const { name, value, type } = e.target as HTMLInputElement; let newValue: any = value; if (type === 'number') { newValue = Number(value); } onUpdate({ ...query, [field]: { ...(query as any)[field], [name]: newValue } }); }; const onEndPointChange = ({ value }: SelectableValue) => { onUpdate({ ...query, stringInput: value }); }; const onStreamClientChange = onFieldChange('stream'); const onPulseWaveChange = onFieldChange('pulseWave'); const onUSAStatsChange = (usa?: USAQuery) => { onUpdate({ ...query, usa }); }; const onCSVWaveChange = (csvWave?: CSVWave[]) => { onUpdate({ ...query, csvWave }); }; const options = useMemo( () => (scenarioList || []) .map((item) => ({ label: item.name, value: item.id })) .sort((a, b) => a.label.localeCompare(b.label)), [scenarioList] ); const showLabels = useMemo(() => showLabelsFor.includes(query.scenarioId ?? ''), [query]); if (loading) { return null; } return ( <> )} {Boolean(!currentScenario?.hideAliasField) && ( )} {showLabels && ( Set labels using a key=value syntax:
{`{ key = "value", key2 = "value" }`}
key="value", key2="value"
key=value, key2=value
} >
)}
{scenarioId === 'random_walk' && } {scenarioId === 'streaming_client' && } {scenarioId === 'live' && } {scenarioId === 'simulation' && } {scenarioId === 'raw_frame' && } {scenarioId === 'csv_file' && } {scenarioId === 'csv_content' && } {scenarioId === 'logs' && ( )} {scenarioId === 'usa' && } {scenarioId === 'grafana_api' && (