diff --git a/frontend/src/components/ButtonComponent.tsx b/frontend/src/components/ButtonComponent.tsx index a796b73..fabdda3 100644 --- a/frontend/src/components/ButtonComponent.tsx +++ b/frontend/src/components/ButtonComponent.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useRef } from 'react'; import { ToggleButton } from 'react-bootstrap'; import { DocStringComponent } from './DocStringComponent'; +import { SerializedValue } from './GenericComponent'; import { LevelName } from './NotificationsComponent'; type ButtonComponentProps = { @@ -10,12 +11,7 @@ type ButtonComponentProps = { docString: string; mapping?: [string, string]; // Enforce a tuple of two strings addNotification: (message: string, levelname?: LevelName) => void; - changeCallback?: ( - value: unknown, - attributeName?: string, - prefix?: string, - callback?: (ack: unknown) => void - ) => void; + changeCallback?: (value: SerializedValue, callback?: (ack: unknown) => void) => void; displayName: string; id: string; }; diff --git a/frontend/src/components/NumberComponent.tsx b/frontend/src/components/NumberComponent.tsx index 6763ae1..9504e94 100644 --- a/frontend/src/components/NumberComponent.tsx +++ b/frontend/src/components/NumberComponent.tsx @@ -3,6 +3,7 @@ import { Form, InputGroup } from 'react-bootstrap'; import { DocStringComponent } from './DocStringComponent'; import '../App.css'; import { LevelName } from './NotificationsComponent'; +import { SerializedValue } from './GenericComponent'; // TODO: add button functionality @@ -38,12 +39,7 @@ type NumberComponentProps = { isInstantUpdate: boolean; unit?: string; addNotification: (message: string, levelname?: LevelName) => void; - changeCallback?: ( - value: unknown, - attributeName?: string, - prefix?: string, - callback?: (ack: unknown) => void - ) => void; + changeCallback?: (value: SerializedValue, callback?: (ack: unknown) => void) => void; displayName?: string; id: string; }; @@ -249,7 +245,12 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => { selectionEnd )); } else if (key === 'Enter' && !isInstantUpdate) { - changeCallback(Number(newValue)); + changeCallback({ + type: type, + value: Number(newValue), + full_access_path: fullAccessPath, + readonly: true + }); return; } else { console.debug(key); @@ -258,7 +259,12 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => { // Update the input value and maintain the cursor position if (isInstantUpdate) { - changeCallback(Number(newValue)); + changeCallback({ + type: type, + value: Number(newValue), + full_access_path: fullAccessPath, + readonly: true + }); } setInputString(newValue); @@ -270,7 +276,12 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => { const handleBlur = () => { if (!isInstantUpdate) { // If not in "instant update" mode, emit an update when the input field loses focus - changeCallback(Number(inputString)); + changeCallback({ + type: type, + value: Number(inputString), + full_access_path: fullAccessPath, + readonly: true + }); } }; useEffect(() => { diff --git a/frontend/src/components/SliderComponent.tsx b/frontend/src/components/SliderComponent.tsx index 9296cfc..5cb003e 100644 --- a/frontend/src/components/SliderComponent.tsx +++ b/frontend/src/components/SliderComponent.tsx @@ -4,6 +4,7 @@ import { DocStringComponent } from './DocStringComponent'; import { Slider } from '@mui/material'; import { NumberComponent, NumberObject } from './NumberComponent'; import { LevelName } from './NotificationsComponent'; +import { SerializedValue } from './GenericComponent'; type SliderComponentProps = { fullAccessPath: string; @@ -15,12 +16,7 @@ type SliderComponentProps = { stepSize: NumberObject; isInstantUpdate: boolean; addNotification: (message: string, levelname?: LevelName) => void; - changeCallback?: ( - value: unknown, - attributeName?: string, - prefix?: string, - callback?: (ack: unknown) => void - ) => void; + changeCallback?: (value: SerializedValue, callback?: (ack: unknown) => void) => void; displayName: string; id: string; }; @@ -68,11 +64,25 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => { if (Array.isArray(newNumber)) { newNumber = newNumber[0]; } - changeCallback(newNumber, `${name}.value`); + changeCallback({ + type: value.type, + value: newNumber, + full_access_path: `${fullAccessPath}.value`, + readonly: value.readonly + }); }; - const handleValueChange = (newValue: number, valueType: string) => { - changeCallback(newValue, `${name}.${valueType}`); + const handleValueChange = ( + newValue: number, + name: string, + valueObject: NumberObject + ) => { + changeCallback({ + type: valueObject.type, + value: newValue, + full_access_path: `${fullAccessPath}.${name}`, + readonly: valueObject.readonly + }); }; const deconstructNumberDict = ( @@ -137,7 +147,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => { value={valueMagnitude} unit={valueUnit} addNotification={() => {}} - changeCallback={(value) => changeCallback(value, name + '.value')} + changeCallback={changeCallback} id={id + '-value'} /> @@ -175,7 +185,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => { type="number" value={minMagnitude} disabled={minReadOnly} - onChange={(e) => handleValueChange(Number(e.target.value), 'min')} + onChange={(e) => handleValueChange(Number(e.target.value), 'min', min)} /> @@ -185,7 +195,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => { type="number" value={maxMagnitude} disabled={maxReadOnly} - onChange={(e) => handleValueChange(Number(e.target.value), 'max')} + onChange={(e) => handleValueChange(Number(e.target.value), 'max', max)} /> @@ -195,7 +205,9 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => { type="number" value={stepSizeMagnitude} disabled={stepSizeReadOnly} - onChange={(e) => handleValueChange(Number(e.target.value), 'step_size')} + onChange={(e) => + handleValueChange(Number(e.target.value), 'step_size', stepSize) + } /> diff --git a/frontend/src/components/StringComponent.tsx b/frontend/src/components/StringComponent.tsx index ad56809..00f538a 100644 --- a/frontend/src/components/StringComponent.tsx +++ b/frontend/src/components/StringComponent.tsx @@ -3,6 +3,7 @@ import { Form, InputGroup } from 'react-bootstrap'; import { DocStringComponent } from './DocStringComponent'; import '../App.css'; import { LevelName } from './NotificationsComponent'; +import { SerializedValue } from './GenericComponent'; // TODO: add button functionality @@ -13,12 +14,7 @@ type StringComponentProps = { docString: string; isInstantUpdate: boolean; addNotification: (message: string, levelname?: LevelName) => void; - changeCallback?: ( - value: unknown, - attributeName?: string, - prefix?: string, - callback?: (ack: unknown) => void - ) => void; + changeCallback?: (value: SerializedValue, callback?: (ack: unknown) => void) => void; displayName: string; id: string; }; @@ -59,14 +55,24 @@ export const StringComponent = React.memo((props: StringComponentProps) => { const handleKeyDown = (event) => { if (event.key === 'Enter' && !isInstantUpdate) { - changeCallback(inputString); + changeCallback({ + type: 'str', + value: inputString, + full_access_path: fullAccessPath, + readonly: true + }); event.preventDefault(); } }; const handleBlur = () => { if (!isInstantUpdate) { - changeCallback(inputString); + changeCallback({ + type: 'str', + value: inputString, + full_access_path: fullAccessPath, + readonly: true + }); } };