mirror of
https://github.com/grafana/grafana.git
synced 2025-01-18 12:33:37 -06:00
Testdata: show settings for current simulation (#48017)
Co-authored-by: An Le <an.le@grafana.com>
This commit is contained in:
parent
0da50294fe
commit
5294a2af48
@ -224,7 +224,6 @@ func (s *SimulationEngine) GetSimulationHandler(rw http.ResponseWriter, req *htt
|
||||
}
|
||||
result = v
|
||||
} else if strings.HasPrefix(path, "/sim/") {
|
||||
rw.WriteHeader(400)
|
||||
sim, err := s.getSimFromPath(path)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusNotFound)
|
||||
|
@ -98,11 +98,11 @@ func newFlightSimInfo() simulationInfo {
|
||||
df.Fields = append(df.Fields, f)
|
||||
|
||||
return simulationInfo{
|
||||
Type: "flight",
|
||||
Name: "Flight",
|
||||
Description: "simple circling airplain",
|
||||
SetupFields: df,
|
||||
OnlyForward: false,
|
||||
Type: "flight",
|
||||
Name: "Flight",
|
||||
Description: "simple circling airplain",
|
||||
ConfigFields: df,
|
||||
OnlyForward: false,
|
||||
create: func(cfg simulationState) (Simulation, error) {
|
||||
s := &flightSim{
|
||||
key: cfg.Key,
|
||||
|
@ -134,11 +134,11 @@ func newTankSimInfo() simulationInfo {
|
||||
df.Fields = append(df.Fields, data.NewField("pumpOn", nil, []bool{tc.PumpOn}))
|
||||
|
||||
return simulationInfo{
|
||||
Type: "tank",
|
||||
Name: "Tank",
|
||||
Description: "Fill and drain a water tank",
|
||||
SetupFields: df,
|
||||
OnlyForward: false,
|
||||
Type: "tank",
|
||||
Name: "Tank",
|
||||
Description: "Fill and drain a water tank",
|
||||
ConfigFields: df,
|
||||
OnlyForward: false,
|
||||
create: func(cfg simulationState) (Simulation, error) {
|
||||
s := &tankSim{
|
||||
key: cfg.Key,
|
||||
|
@ -32,11 +32,11 @@ type simulationState struct {
|
||||
}
|
||||
|
||||
type simulationInfo struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
OnlyForward bool `json:"forward"`
|
||||
SetupFields *data.Frame `json:"setup"` // the default setup fields (and types)
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
OnlyForward bool `json:"forward"`
|
||||
ConfigFields *data.Frame `json:"config"`
|
||||
|
||||
// Create a simulation instance
|
||||
create func(q simulationState) (Simulation, error)
|
||||
|
@ -93,11 +93,11 @@ func newSinewaveInfo() simulationInfo {
|
||||
df.Fields = append(df.Fields, f)
|
||||
|
||||
return simulationInfo{
|
||||
Type: "sine",
|
||||
Name: "Sine",
|
||||
Description: "Sinewave generator",
|
||||
SetupFields: df,
|
||||
OnlyForward: false,
|
||||
Type: "sine",
|
||||
Name: "Sine",
|
||||
Description: "Sinewave generator",
|
||||
ConfigFields: df,
|
||||
OnlyForward: false,
|
||||
create: func(cfg simulationState) (Simulation, error) {
|
||||
s := &waveformSim{
|
||||
key: cfg.Key,
|
||||
|
@ -33,6 +33,7 @@ const selectors = editorSelectors.components.DataSource.TestData.QueryTab;
|
||||
export interface EditorProps {
|
||||
onChange: (value: any) => void;
|
||||
query: TestDataQuery;
|
||||
ds: TestDataDataSource;
|
||||
}
|
||||
|
||||
export type Props = QueryEditorProps<TestDataDataSource, TestDataQuery>;
|
||||
@ -243,13 +244,15 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
|
||||
)}
|
||||
</InlineFieldRow>
|
||||
|
||||
{scenarioId === 'random_walk' && <RandomWalkEditor onChange={onInputChange} query={query} />}
|
||||
{scenarioId === 'streaming_client' && <StreamingClientEditor onChange={onStreamClientChange} query={query} />}
|
||||
{scenarioId === 'live' && <GrafanaLiveEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'simulation' && <SimulationQueryEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'raw_frame' && <RawFrameEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'csv_file' && <CSVFileEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'csv_content' && <CSVContentEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'random_walk' && <RandomWalkEditor onChange={onInputChange} query={query} ds={datasource} />}
|
||||
{scenarioId === 'streaming_client' && (
|
||||
<StreamingClientEditor onChange={onStreamClientChange} query={query} ds={datasource} />
|
||||
)}
|
||||
{scenarioId === 'live' && <GrafanaLiveEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
{scenarioId === 'simulation' && <SimulationQueryEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
{scenarioId === 'raw_frame' && <RawFrameEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
{scenarioId === 'csv_file' && <CSVFileEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
{scenarioId === 'csv_content' && <CSVContentEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
{scenarioId === 'logs' && (
|
||||
<InlineFieldRow>
|
||||
<InlineField label="Lines" labelWidth={14}>
|
||||
@ -293,12 +296,14 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
|
||||
</InlineField>
|
||||
)}
|
||||
|
||||
{scenarioId === 'predictable_pulse' && <PredictablePulseEditor onChange={onPulseWaveChange} query={query} />}
|
||||
{scenarioId === 'predictable_pulse' && (
|
||||
<PredictablePulseEditor onChange={onPulseWaveChange} query={query} ds={datasource} />
|
||||
)}
|
||||
{scenarioId === 'predictable_csv_wave' && <CSVWavesEditor onChange={onCSVWaveChange} waves={query.csvWave} />}
|
||||
{scenarioId === 'node_graph' && (
|
||||
<NodeGraphEditor onChange={(val: NodesQuery) => onChange({ ...query, nodes: val })} query={query} />
|
||||
)}
|
||||
{scenarioId === 'server_error_500' && <ErrorEditor onChange={onUpdate} query={query} />}
|
||||
{scenarioId === 'server_error_500' && <ErrorEditor onChange={onUpdate} query={query} ds={datasource} />}
|
||||
|
||||
{description && <p>{description}</p>}
|
||||
</>
|
||||
|
@ -1,19 +1,70 @@
|
||||
import React, { FormEvent } from 'react';
|
||||
import React, { FormEvent, useMemo } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, InlineSwitch, Input, Label, Select } from '@grafana/ui';
|
||||
import { DataFrameJSON, SelectableValue } from '@grafana/data';
|
||||
import {
|
||||
InlineField,
|
||||
InlineFieldRow,
|
||||
Button,
|
||||
FieldSet,
|
||||
InlineSwitch,
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
Form,
|
||||
TextArea,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { EditorProps } from '../QueryEditor';
|
||||
import { SimulationQuery } from '../types';
|
||||
|
||||
export const SimulationQueryEditor = ({ onChange, query }: EditorProps) => {
|
||||
// Type string `json:"type"`
|
||||
// Name string `json:"name"`
|
||||
// Description string `json:"description"`
|
||||
// OnlyForward bool `json:"forward"`
|
||||
// ConfigFields *data.Frame `json:"config"`
|
||||
|
||||
interface SimInfo {
|
||||
type: string;
|
||||
name: string;
|
||||
description: string;
|
||||
forward: boolean;
|
||||
config: DataFrameJSON;
|
||||
}
|
||||
interface FormDTO {
|
||||
config: string;
|
||||
}
|
||||
export const SimulationQueryEditor = ({ onChange, query, ds }: EditorProps) => {
|
||||
const simQuery = query.sim ?? ({} as SimulationQuery);
|
||||
const simKey = simQuery.key ?? ({} as typeof simQuery.key);
|
||||
const options = [
|
||||
{ label: 'Flight', value: 'flight' },
|
||||
{ label: 'Sine', value: 'sine' },
|
||||
{ label: 'Tank', value: 'tank' },
|
||||
];
|
||||
|
||||
// This only changes once
|
||||
const info = useAsync(async () => {
|
||||
const v = (await ds.getResource('sims')) as SimInfo[];
|
||||
return {
|
||||
sims: v,
|
||||
options: v.map((s) => ({ label: s.name, value: s.type, description: s.description })),
|
||||
};
|
||||
}, [ds]);
|
||||
|
||||
const current = useMemo(() => {
|
||||
const type = simKey.type;
|
||||
if (!type || !info.value) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
details: info.value.sims.find((v) => v.type === type),
|
||||
option: info.value.options.find((v) => v.value === type),
|
||||
};
|
||||
}, [info.value, simKey?.type]);
|
||||
|
||||
let config = useAsync(async () => {
|
||||
let path = simKey.type + '/' + simKey.tick + 'hz';
|
||||
if (simKey.uid) {
|
||||
path += '/' + simKey.uid;
|
||||
}
|
||||
return (await ds.getResource('sim/' + path))?.config;
|
||||
}, [simKey.type, simKey.tick, simKey.uid]);
|
||||
|
||||
const onUpdateKey = (key: typeof simQuery.key) => {
|
||||
onChange({ ...query, sim: { ...simQuery, key } });
|
||||
@ -40,15 +91,23 @@ export const SimulationQueryEditor = ({ onChange, query }: EditorProps) => {
|
||||
const onToggleLast = () => {
|
||||
onChange({ ...query, sim: { ...simQuery, last: !simQuery.last } });
|
||||
};
|
||||
const onSubmitChange = (data: FormDTO) => {
|
||||
let path = simKey.type + '/' + simKey.tick + 'hz';
|
||||
if (simKey.uid) {
|
||||
path += '/' + simKey.uid;
|
||||
}
|
||||
ds.postResource('sim/' + path, JSON.parse(data.config));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InlineFieldRow>
|
||||
<InlineField labelWidth={14} label="Simulation" tooltip="">
|
||||
<Select
|
||||
isLoading={info.loading}
|
||||
menuShouldPortal
|
||||
options={options}
|
||||
value={options.find((item) => item.value === simQuery.key?.type)}
|
||||
options={info.value?.options ?? []}
|
||||
value={current.option}
|
||||
onChange={onTypeChange}
|
||||
width={32}
|
||||
/>
|
||||
@ -81,6 +140,18 @@ export const SimulationQueryEditor = ({ onChange, query }: EditorProps) => {
|
||||
<Input type="text" placeholder="optional" value={simQuery.key.uid} onChange={onUIDChanged} />
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
<div>
|
||||
<Form onSubmit={onSubmitChange}>
|
||||
{({ register }) => (
|
||||
<FieldSet>
|
||||
<TextArea {...register('config')} defaultValue={JSON.stringify(config.value, null, 2)} rows={7} />
|
||||
<Button type="submit">Submit</Button>
|
||||
</FieldSet>
|
||||
)}
|
||||
</Form>
|
||||
SCHEMA:
|
||||
<pre>{JSON.stringify(current.details?.config.schema, null, 2)}</pre>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user