2019-01-17 13:02:43 -06:00
|
|
|
// Libraries
|
2020-10-20 11:18:14 -05:00
|
|
|
import React, { ChangeEvent, FormEvent, useMemo } from 'react';
|
2020-10-14 05:08:35 -05:00
|
|
|
import { useAsync } from 'react-use';
|
2019-01-17 13:02:43 -06:00
|
|
|
|
|
|
|
// Components
|
2020-10-14 05:08:35 -05:00
|
|
|
import { selectors as editorSelectors } from '@grafana/e2e-selectors';
|
2021-01-21 08:49:38 -06:00
|
|
|
import { Input, InlineFieldRow, InlineField, Select, TextArea, InlineSwitch } from '@grafana/ui';
|
2019-10-31 04:48:05 -05:00
|
|
|
import { QueryEditorProps, SelectableValue } from '@grafana/data';
|
2020-10-14 05:08:35 -05:00
|
|
|
import { StreamingClientEditor, ManualEntryEditor, RandomWalkEditor } from './components';
|
2019-01-17 13:02:43 -06:00
|
|
|
|
|
|
|
// Types
|
2019-08-06 11:17:12 -05:00
|
|
|
import { TestDataDataSource } from './datasource';
|
2021-04-27 15:35:43 -05:00
|
|
|
import { TestDataQuery, Scenario, NodesQuery, CSVWave } from './types';
|
2020-10-14 05:08:35 -05:00
|
|
|
import { PredictablePulseEditor } from './components/PredictablePulseEditor';
|
2021-04-27 15:35:43 -05:00
|
|
|
import { CSVWavesEditor } from './components/CSVWaveEditor';
|
2021-03-29 00:51:15 -05:00
|
|
|
import { defaultCSVWaveQuery, defaultPulseQuery, defaultQuery } from './constants';
|
2020-10-22 02:10:26 -05:00
|
|
|
import { GrafanaLiveEditor } from './components/GrafanaLiveEditor';
|
2021-01-19 09:34:43 -06:00
|
|
|
import { NodeGraphEditor } from './components/NodeGraphEditor';
|
2021-03-29 00:51:15 -05:00
|
|
|
import { defaultStreamQuery } from './runStreams';
|
2020-10-14 05:08:35 -05:00
|
|
|
|
2021-04-27 15:35:43 -05:00
|
|
|
const showLabelsFor = ['random_walk', 'predictable_pulse'];
|
2020-10-14 05:08:35 -05:00
|
|
|
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;
|
2019-01-17 10:37:34 -06:00
|
|
|
}
|
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
export type Props = QueryEditorProps<TestDataDataSource, TestDataQuery>;
|
|
|
|
|
|
|
|
export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props) => {
|
|
|
|
query = { ...defaultQuery, ...query };
|
2019-01-18 10:19:35 -06:00
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
const { loading, value: scenarioList } = useAsync<Scenario[]>(async () => {
|
|
|
|
return datasource.getScenarios();
|
|
|
|
}, []);
|
2019-01-17 13:02:43 -06:00
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
const onUpdate = (query: TestDataQuery) => {
|
|
|
|
onChange(query);
|
|
|
|
onRunQuery();
|
2019-01-17 13:02:43 -06:00
|
|
|
};
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
const currentScenario = useMemo(() => scenarioList?.find((scenario) => scenario.id === query.scenarioId), [
|
2020-10-14 05:08:35 -05:00
|
|
|
scenarioList,
|
|
|
|
query,
|
|
|
|
]);
|
|
|
|
const scenarioId = currentScenario?.id;
|
2019-01-17 13:02:43 -06:00
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
const onScenarioChange = (item: SelectableValue<string>) => {
|
2021-01-20 00:59:48 -06:00
|
|
|
const scenario = scenarioList?.find((sc) => sc.id === item.value);
|
2019-01-17 13:02:43 -06:00
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
if (!scenario) {
|
|
|
|
return;
|
|
|
|
}
|
2019-01-17 13:02:43 -06:00
|
|
|
|
2021-03-29 00:51:15 -05:00
|
|
|
// Clear model from existing props that belong to other scenarios
|
|
|
|
const update: TestDataQuery = {
|
|
|
|
scenarioId: item.value!,
|
|
|
|
refId: query.refId,
|
|
|
|
alias: query.alias,
|
|
|
|
};
|
2020-10-22 02:10:26 -05:00
|
|
|
|
|
|
|
if (scenario.stringInput) {
|
|
|
|
update.stringInput = scenario.stringInput;
|
|
|
|
}
|
2020-10-14 05:08:35 -05:00
|
|
|
|
2021-03-29 00:51:15 -05:00
|
|
|
switch (scenario.id) {
|
|
|
|
case 'grafana_api':
|
|
|
|
update.stringInput = 'datasources';
|
|
|
|
break;
|
|
|
|
case 'streaming_client':
|
|
|
|
update.stream = defaultStreamQuery;
|
|
|
|
break;
|
|
|
|
case 'live':
|
2020-10-22 02:10:26 -05:00
|
|
|
update.channel = 'random-2s-stream'; // default stream
|
2021-03-29 00:51:15 -05:00
|
|
|
break;
|
|
|
|
case 'predictable_pulse':
|
|
|
|
update.pulseWave = defaultPulseQuery;
|
|
|
|
break;
|
|
|
|
case 'predictable_csv_wave':
|
|
|
|
update.csvWave = defaultCSVWaveQuery;
|
|
|
|
break;
|
2020-10-14 05:08:35 -05:00
|
|
|
}
|
|
|
|
|
2020-10-22 02:10:26 -05:00
|
|
|
onUpdate(update);
|
2019-02-13 04:14:53 -06:00
|
|
|
};
|
2019-01-17 13:02:43 -06:00
|
|
|
|
2020-10-14 05:08:35 -05:00
|
|
|
const onInputChange = (e: FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
2020-11-09 07:48:08 -06:00
|
|
|
const { name, value, type } = e.target as HTMLInputElement | HTMLTextAreaElement;
|
|
|
|
let newValue: any = value;
|
|
|
|
|
|
|
|
if (type === 'number') {
|
|
|
|
newValue = Number(value);
|
|
|
|
}
|
2020-10-14 05:08:35 -05:00
|
|
|
|
|
|
|
if (name === 'levelColumn') {
|
2020-11-09 07:48:08 -06:00
|
|
|
newValue = (e.target as HTMLInputElement).checked;
|
2020-10-14 05:08:35 -05:00
|
|
|
}
|
|
|
|
|
2020-11-09 07:48:08 -06:00
|
|
|
onUpdate({ ...query, [name]: newValue });
|
2020-10-14 05:08:35 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
const onFieldChange = (field: string) => (e: ChangeEvent<HTMLInputElement>) => {
|
2020-11-09 07:48:08 -06:00
|
|
|
const { name, value, type } = e.target as HTMLInputElement;
|
|
|
|
let newValue: any = value;
|
|
|
|
|
|
|
|
if (type === 'number') {
|
|
|
|
newValue = Number(value);
|
|
|
|
}
|
|
|
|
|
2021-04-27 15:35:43 -05:00
|
|
|
onUpdate({ ...query, [field]: { ...(query as any)[field], [name]: newValue } });
|
2020-10-14 05:08:35 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
const onEndPointChange = ({ value }: SelectableValue) => {
|
|
|
|
onUpdate({ ...query, stringInput: value });
|
|
|
|
};
|
|
|
|
|
|
|
|
const onStreamClientChange = onFieldChange('stream');
|
|
|
|
const onPulseWaveChange = onFieldChange('pulseWave');
|
2021-04-27 15:35:43 -05:00
|
|
|
|
|
|
|
const onCSVWaveChange = (csvWave?: CSVWave[]) => {
|
|
|
|
onUpdate({ ...query, csvWave });
|
|
|
|
};
|
2020-10-14 05:08:35 -05:00
|
|
|
|
|
|
|
const options = useMemo(
|
|
|
|
() =>
|
|
|
|
(scenarioList || [])
|
2021-01-20 00:59:48 -06:00
|
|
|
.map((item) => ({ label: item.name, value: item.id }))
|
2020-10-14 05:08:35 -05:00
|
|
|
.sort((a, b) => a.label.localeCompare(b.label)),
|
|
|
|
[scenarioList]
|
|
|
|
);
|
|
|
|
const showLabels = useMemo(() => showLabelsFor.includes(query.scenarioId), [query]);
|
|
|
|
|
|
|
|
if (loading) {
|
|
|
|
return null;
|
2019-01-17 10:37:34 -06:00
|
|
|
}
|
2020-10-14 05:08:35 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<InlineFieldRow aria-label={selectors.scenarioSelectContainer}>
|
|
|
|
<InlineField labelWidth={14} label="Scenario">
|
|
|
|
<Select
|
|
|
|
options={options}
|
2021-01-20 00:59:48 -06:00
|
|
|
value={options.find((item) => item.value === query.scenarioId)}
|
2020-10-14 05:08:35 -05:00
|
|
|
onChange={onScenarioChange}
|
|
|
|
width={32}
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
{currentScenario?.stringInput && (
|
|
|
|
<InlineField label="String Input">
|
|
|
|
<Input
|
|
|
|
width={32}
|
2020-10-19 10:56:57 -05:00
|
|
|
id={`stringInput-${query.refId}`}
|
2020-10-14 05:08:35 -05:00
|
|
|
name="stringInput"
|
|
|
|
placeholder={query.stringInput}
|
|
|
|
value={query.stringInput}
|
|
|
|
onChange={onInputChange}
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
)}
|
|
|
|
<InlineField label="Alias" labelWidth={14}>
|
|
|
|
<Input
|
|
|
|
width={32}
|
2020-10-19 10:56:57 -05:00
|
|
|
id={`alias-${query.refId}`}
|
2020-10-14 05:08:35 -05:00
|
|
|
type="text"
|
|
|
|
placeholder="optional"
|
|
|
|
pattern='[^<>&\\"]+'
|
|
|
|
name="alias"
|
|
|
|
value={query.alias}
|
|
|
|
onChange={onInputChange}
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
{showLabels && (
|
|
|
|
<InlineField
|
|
|
|
label="Labels"
|
|
|
|
labelWidth={14}
|
|
|
|
tooltip={
|
|
|
|
<>
|
|
|
|
Set labels using a key=value syntax:
|
|
|
|
<br />
|
|
|
|
{`{ key = "value", key2 = "value" }`}
|
|
|
|
<br />
|
2020-12-02 03:03:37 -06:00
|
|
|
key="value", key2="value"
|
2020-10-14 05:08:35 -05:00
|
|
|
<br />
|
|
|
|
key=value, key2=value
|
|
|
|
<br />
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Input
|
|
|
|
width={32}
|
2020-10-19 10:56:57 -05:00
|
|
|
id={`labels-${query.refId}`}
|
2020-10-14 05:08:35 -05:00
|
|
|
name="labels"
|
|
|
|
onChange={onInputChange}
|
|
|
|
value={query?.labels}
|
|
|
|
placeholder="key=value, key2=value2"
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
)}
|
|
|
|
</InlineFieldRow>
|
|
|
|
|
|
|
|
{scenarioId === 'manual_entry' && <ManualEntryEditor onChange={onUpdate} query={query} onRunQuery={onRunQuery} />}
|
|
|
|
{scenarioId === 'random_walk' && <RandomWalkEditor onChange={onInputChange} query={query} />}
|
|
|
|
{scenarioId === 'streaming_client' && <StreamingClientEditor onChange={onStreamClientChange} query={query} />}
|
2020-10-22 02:10:26 -05:00
|
|
|
{scenarioId === 'live' && <GrafanaLiveEditor onChange={onUpdate} query={query} />}
|
2020-10-14 05:08:35 -05:00
|
|
|
{scenarioId === 'logs' && (
|
|
|
|
<InlineFieldRow>
|
|
|
|
<InlineField label="Lines" labelWidth={14}>
|
|
|
|
<Input
|
|
|
|
type="number"
|
|
|
|
name="lines"
|
|
|
|
value={query.lines}
|
|
|
|
width={32}
|
|
|
|
onChange={onInputChange}
|
|
|
|
placeholder="10"
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
<InlineField label="Level" labelWidth={14}>
|
2021-01-21 08:49:38 -06:00
|
|
|
<InlineSwitch onChange={onInputChange} name="levelColumn" value={!!query.levelColumn} />
|
2020-10-14 05:08:35 -05:00
|
|
|
</InlineField>
|
|
|
|
</InlineFieldRow>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{scenarioId === 'grafana_api' && (
|
|
|
|
<InlineField labelWidth={14} label="Endpoint">
|
|
|
|
<Select
|
|
|
|
options={endpoints}
|
|
|
|
onChange={onEndPointChange}
|
|
|
|
width={32}
|
2021-01-20 00:59:48 -06:00
|
|
|
value={endpoints.find((ep) => ep.value === query.stringInput)}
|
2020-10-14 05:08:35 -05:00
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{scenarioId === 'arrow' && (
|
|
|
|
<InlineField grow>
|
|
|
|
<TextArea
|
|
|
|
name="stringInput"
|
|
|
|
value={query.stringInput}
|
|
|
|
rows={10}
|
|
|
|
placeholder="Copy base64 text data from query result"
|
|
|
|
onChange={onInputChange}
|
|
|
|
/>
|
|
|
|
</InlineField>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{scenarioId === 'predictable_pulse' && <PredictablePulseEditor onChange={onPulseWaveChange} query={query} />}
|
2021-04-27 15:35:43 -05:00
|
|
|
{scenarioId === 'predictable_csv_wave' && <CSVWavesEditor onChange={onCSVWaveChange} waves={query.csvWave} />}
|
2021-01-19 09:34:43 -06:00
|
|
|
{scenarioId === 'node_graph' && (
|
|
|
|
<NodeGraphEditor onChange={(val: NodesQuery) => onChange({ ...query, nodes: val })} query={query} />
|
|
|
|
)}
|
2020-10-14 05:08:35 -05:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|