TestData: Add schema-based form for simulation (#49637)

* add inputs for corresponding schema

* change input to default value

* reformat inline fields and keep local state

* add comment on state

* show input on default
This commit is contained in:
An 2022-06-02 12:48:07 -04:00 committed by GitHub
parent 15b3bbad6b
commit 104c4a7630
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 33 deletions

View File

@ -1,23 +1,14 @@
import React, { FormEvent, useMemo } from 'react';
import React, { FormEvent, useMemo, useState } from 'react';
import { useAsync } from 'react-use';
import { DataFrameJSON, SelectableValue } from '@grafana/data';
import {
InlineField,
InlineFieldRow,
Button,
FieldSet,
InlineSwitch,
Input,
Label,
Select,
Form,
TextArea,
} from '@grafana/ui';
import { InlineField, InlineFieldRow, InlineSwitch, Input, Label, Select } from '@grafana/ui';
import { EditorProps } from '../QueryEditor';
import { SimulationQuery } from '../types';
import { SimulationSchemaForm } from './SimulationSchemaForm';
// Type string `json:"type"`
// Name string `json:"name"`
// Description string `json:"description"`
@ -31,12 +22,12 @@ interface SimInfo {
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);
// keep track of updated config state to pass down to form
const [cfgValue, setCfgValue] = useState<Record<string, any>>({});
// This only changes once
const info = useAsync(async () => {
@ -63,7 +54,9 @@ export const SimulationQueryEditor = ({ onChange, query, ds }: EditorProps) => {
if (simKey.uid) {
path += '/' + simKey.uid;
}
return (await ds.getResource('sim/' + path))?.config;
let config = (await ds.getResource('sim/' + path))?.config;
setCfgValue(config.value);
return config;
}, [simKey.type, simKey.tick, simKey.uid]);
const onUpdateKey = (key: typeof simQuery.key) => {
@ -91,14 +84,16 @@ export const SimulationQueryEditor = ({ onChange, query, ds }: EditorProps) => {
const onToggleLast = () => {
onChange({ ...query, sim: { ...simQuery, last: !simQuery.last } });
};
const onSubmitChange = (data: FormDTO) => {
const onSchemaFormChange = (config: Record<string, any>) => {
let path = simKey.type + '/' + simKey.tick + 'hz';
if (simKey.uid) {
path += '/' + simKey.uid;
}
ds.postResource('sim/' + path, JSON.parse(data.config));
ds.postResource('sim/' + path, config).then((res) => {
setCfgValue(res.config);
});
};
return (
<>
<InlineFieldRow>
@ -112,7 +107,6 @@ export const SimulationQueryEditor = ({ onChange, query, ds }: EditorProps) => {
/>
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<InlineField labelWidth={14} label="Stream" tooltip="connect to the live channel">
<InlineSwitch value={Boolean(simQuery.stream)} onChange={onToggleStream} />
@ -139,18 +133,11 @@ export const SimulationQueryEditor = ({ onChange, query, ds }: 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>
<SimulationSchemaForm
onChange={onSchemaFormChange}
config={cfgValue ?? config.value}
schema={current.details?.config.schema ?? { fields: [] }}
/>
</>
);
};

View File

@ -0,0 +1,89 @@
import { css } from '@emotion/css';
import React, { FormEvent, useState, ChangeEvent } from 'react';
import { DataFrameSchema, FieldSchema, GrafanaTheme2 } from '@grafana/data';
import { useStyles2, TextArea, InlineField, Input, FieldSet, InlineSwitch } from '@grafana/ui';
interface SchemaFormProps {
config: Record<string, any>;
schema: DataFrameSchema;
onChange: (config: Record<string, any>) => void;
}
const renderInput = (field: FieldSchema, onChange: SchemaFormProps['onChange'], config: SchemaFormProps['config']) => {
switch (field.type) {
case 'number':
return (
<Input
type="number"
defaultValue={config?.[field.name]}
onChange={(e: FormEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.valueAsNumber;
onChange({ ...config, [field.name]: newValue });
}}
/>
);
case 'boolean':
return (
<InlineSwitch
value={config?.[field.name] ?? true}
onChange={() => {
onChange({ ...config, [field.name]: !config[field.name] });
}}
/>
);
default:
return (
<Input
type="string"
value={config?.[field.name]}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
onChange({ ...config, [field.name]: newValue });
}}
/>
);
}
};
const getStyles = (theme: GrafanaTheme2) => {
return {
jsonView: css`
margin-bottom: ${theme.spacing(1)};
`,
};
};
export const SimulationSchemaForm = ({ config, schema, onChange }: SchemaFormProps) => {
const [jsonView, setJsonView] = useState<boolean>(false);
const styles = useStyles2(getStyles);
const onUpdateTextArea = (event: FormEvent<HTMLTextAreaElement>) => {
const element = event.target as HTMLInputElement;
onChange(JSON.parse(element.value));
};
return (
<FieldSet label="Config">
<InlineSwitch
className={styles.jsonView}
label="JSON View"
showLabel
value={jsonView}
onChange={() => setJsonView(!jsonView)}
/>
{jsonView ? (
<TextArea defaultValue={JSON.stringify(config, null, 2)} rows={7} onChange={onUpdateTextArea} />
) : (
<>
{schema.fields.map((field) => (
<InlineField label={field.name} key={field.name} labelWidth={14}>
{renderInput(field, onChange, config)}
</InlineField>
))}
</>
)}
</FieldSet>
);
};