mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-19 16:10:01 +02:00
defines changeCallback function in GenericComponent and passes it to components (instead of setAttribute)
The components do not use the setAttribute method themselves anymore. This way, you can provide the changeCallback function if you want and thus reuse the components.
This commit is contained in:
parent
2bb02a5558
commit
fffe679bf0
@ -1,7 +1,6 @@
|
||||
import React, { useContext, useEffect, useRef } from 'react';
|
||||
import { WebSettingsContext } from '../WebSettings';
|
||||
import { ToggleButton } from 'react-bootstrap';
|
||||
import { setAttribute } from '../socket';
|
||||
import { DocStringComponent } from './DocStringComponent';
|
||||
import { getIdFromFullAccessPath } from '../utils/stringUtils';
|
||||
import { LevelName } from './NotificationsComponent';
|
||||
@ -14,10 +13,24 @@ 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;
|
||||
};
|
||||
|
||||
export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
|
||||
const { name, parentPath, value, readOnly, docString, addNotification } = props;
|
||||
const {
|
||||
name,
|
||||
parentPath,
|
||||
value,
|
||||
readOnly,
|
||||
docString,
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
// const buttonName = props.mapping ? (value ? props.mapping[0] : props.mapping[1]) : name;
|
||||
const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
|
||||
const id = getIdFromFullAccessPath(fullAccessPath);
|
||||
@ -39,7 +52,7 @@ export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
|
||||
}, [props.value]);
|
||||
|
||||
const setChecked = (checked: boolean) => {
|
||||
setAttribute(name, parentPath, checked);
|
||||
changeCallback(checked);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useContext, useEffect, useRef } from 'react';
|
||||
import { WebSettingsContext } from '../WebSettings';
|
||||
import { InputGroup, Form, Row, Col } from 'react-bootstrap';
|
||||
import { setAttribute } from '../socket';
|
||||
import { DocStringComponent } from './DocStringComponent';
|
||||
import { getIdFromFullAccessPath } from '../utils/stringUtils';
|
||||
import { LevelName } from './NotificationsComponent';
|
||||
@ -14,6 +13,12 @@ type ColouredEnumComponentProps = {
|
||||
readOnly: boolean;
|
||||
enumDict: Record<string, string>;
|
||||
addNotification: (message: string, levelname?: LevelName) => void;
|
||||
changeCallback?: (
|
||||
value: unknown,
|
||||
attributeName?: string,
|
||||
prefix?: string,
|
||||
callback?: (ack: unknown) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentProps) => {
|
||||
@ -24,7 +29,8 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
|
||||
docString,
|
||||
enumDict,
|
||||
readOnly,
|
||||
addNotification
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
const renderCount = useRef(0);
|
||||
const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
|
||||
@ -44,10 +50,6 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
|
||||
addNotification(`${parentPath}.${name} changed to ${value}.`);
|
||||
}, [props.value]);
|
||||
|
||||
const handleValueChange = (newValue: string) => {
|
||||
setAttribute(name, parentPath, newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={'component enumComponent'} id={id}>
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
@ -72,7 +74,7 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
|
||||
aria-label="coloured-enum-select"
|
||||
value={value}
|
||||
style={{ backgroundColor: enumDict[value] }}
|
||||
onChange={(event) => handleValueChange(event.target.value)}>
|
||||
onChange={(event) => changeCallback(event.target.value)}>
|
||||
{Object.entries(enumDict).map(([key]) => (
|
||||
<option key={key} value={key}>
|
||||
{key}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useContext, useEffect, useRef } from 'react';
|
||||
import { WebSettingsContext } from '../WebSettings';
|
||||
import { InputGroup, Form, Row, Col } from 'react-bootstrap';
|
||||
import { setAttribute } from '../socket';
|
||||
import { getIdFromFullAccessPath } from '../utils/stringUtils';
|
||||
import { DocStringComponent } from './DocStringComponent';
|
||||
import { LevelName } from './NotificationsComponent';
|
||||
@ -13,6 +12,12 @@ type EnumComponentProps = {
|
||||
docString?: string;
|
||||
enumDict: Record<string, string>;
|
||||
addNotification: (message: string, levelname?: LevelName) => void;
|
||||
changeCallback?: (
|
||||
value: unknown,
|
||||
attributeName?: string,
|
||||
prefix?: string,
|
||||
callback?: (ack: unknown) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const EnumComponent = React.memo((props: EnumComponentProps) => {
|
||||
@ -22,7 +27,8 @@ export const EnumComponent = React.memo((props: EnumComponentProps) => {
|
||||
value,
|
||||
docString,
|
||||
enumDict,
|
||||
addNotification
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
|
||||
const renderCount = useRef(0);
|
||||
@ -43,10 +49,6 @@ export const EnumComponent = React.memo((props: EnumComponentProps) => {
|
||||
addNotification(`${parentPath}.${name} changed to ${value}.`);
|
||||
}, [props.value]);
|
||||
|
||||
const handleValueChange = (newValue: string) => {
|
||||
setAttribute(name, parentPath, newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={'component enumComponent'} id={id}>
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
@ -61,7 +63,7 @@ export const EnumComponent = React.memo((props: EnumComponentProps) => {
|
||||
<Form.Select
|
||||
aria-label="Default select example"
|
||||
value={value}
|
||||
onChange={(event) => handleValueChange(event.target.value)}>
|
||||
onChange={(event) => changeCallback(event.target.value)}>
|
||||
{Object.entries(enumDict).map(([key, val]) => (
|
||||
<option key={key} value={key}>
|
||||
{key} - {val}
|
||||
|
@ -12,6 +12,7 @@ import { DeviceConnectionComponent } from './DeviceConnection';
|
||||
import { ImageComponent } from './ImageComponent';
|
||||
import { ColouredEnumComponent } from './ColouredEnumComponent';
|
||||
import { LevelName } from './NotificationsComponent';
|
||||
import { setAttribute } from '../socket';
|
||||
|
||||
type AttributeType =
|
||||
| 'str'
|
||||
@ -54,6 +55,16 @@ export const GenericComponent = React.memo(
|
||||
isInstantUpdate,
|
||||
addNotification
|
||||
}: GenericComponentProps) => {
|
||||
|
||||
function changeCallback(
|
||||
value: unknown,
|
||||
attributeName: string = name,
|
||||
prefix: string = parentPath,
|
||||
callback: (ack: unknown) => void = undefined
|
||||
) {
|
||||
setAttribute(attributeName, prefix, value, callback);
|
||||
}
|
||||
|
||||
if (attribute.type === 'bool') {
|
||||
return (
|
||||
<ButtonComponent
|
||||
@ -63,6 +74,7 @@ export const GenericComponent = React.memo(
|
||||
readOnly={attribute.readonly}
|
||||
value={Boolean(attribute.value)}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'float' || attribute.type === 'int') {
|
||||
@ -76,6 +88,7 @@ export const GenericComponent = React.memo(
|
||||
value={Number(attribute.value)}
|
||||
isInstantUpdate={isInstantUpdate}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'Quantity') {
|
||||
@ -90,6 +103,7 @@ export const GenericComponent = React.memo(
|
||||
unit={attribute.value['unit']}
|
||||
isInstantUpdate={isInstantUpdate}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'NumberSlider') {
|
||||
@ -105,6 +119,7 @@ export const GenericComponent = React.memo(
|
||||
stepSize={attribute.value['step_size']}
|
||||
isInstantUpdate={isInstantUpdate}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'Enum') {
|
||||
@ -116,6 +131,7 @@ export const GenericComponent = React.memo(
|
||||
value={String(attribute.value)}
|
||||
enumDict={attribute.enum}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'method') {
|
||||
@ -151,6 +167,7 @@ export const GenericComponent = React.memo(
|
||||
parentPath={parentPath}
|
||||
isInstantUpdate={isInstantUpdate}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else if (attribute.type === 'DataService') {
|
||||
@ -207,6 +224,7 @@ export const GenericComponent = React.memo(
|
||||
readOnly={attribute.readonly}
|
||||
enumDict={attribute.enum}
|
||||
addNotification={addNotification}
|
||||
changeCallback={changeCallback}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
@ -4,7 +4,6 @@ import '../App.css';
|
||||
import { getIdFromFullAccessPath } from '../utils/stringUtils';
|
||||
import { LevelName } from './NotificationsComponent';
|
||||
import { NumberInputField } from './NumberInputField';
|
||||
import { setAttribute } from '../socket';
|
||||
|
||||
// TODO: add button functionality
|
||||
|
||||
@ -42,6 +41,12 @@ type NumberComponentProps = {
|
||||
unit?: string;
|
||||
showName?: boolean;
|
||||
addNotification: (message: string, levelname?: LevelName) => void;
|
||||
changeCallback?: (
|
||||
value: unknown,
|
||||
attributeName?: string,
|
||||
prefix?: string,
|
||||
callback?: (ack: unknown) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const NumberComponent = React.memo((props: NumberComponentProps) => {
|
||||
@ -53,12 +58,10 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
|
||||
docString,
|
||||
isInstantUpdate,
|
||||
unit,
|
||||
addNotification
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
|
||||
function changeCallback(value: number) {
|
||||
setAttribute(name, parentPath, value);
|
||||
}
|
||||
// Whether to show the name infront of the component (false if used with a slider)
|
||||
const showName = props.showName !== undefined ? props.showName : true;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import { WebSettingsContext } from '../WebSettings';
|
||||
import { InputGroup, Form, Row, Col, Collapse, ToggleButton } from 'react-bootstrap';
|
||||
import { setAttribute } from '../socket';
|
||||
import { DocStringComponent } from './DocStringComponent';
|
||||
import { Slider } from '@mui/material';
|
||||
import { NumberComponent, NumberObject } from './NumberComponent';
|
||||
@ -19,6 +18,12 @@ type SliderComponentProps = {
|
||||
stepSize: NumberObject;
|
||||
isInstantUpdate: boolean;
|
||||
addNotification: (message: string, levelname?: LevelName) => void;
|
||||
changeCallback?: (
|
||||
value: unknown,
|
||||
attributeName?: string,
|
||||
prefix?: string,
|
||||
callback?: (ack: unknown) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const SliderComponent = React.memo((props: SliderComponentProps) => {
|
||||
@ -33,7 +38,8 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
|
||||
stepSize,
|
||||
docString,
|
||||
isInstantUpdate,
|
||||
addNotification
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
|
||||
const id = getIdFromFullAccessPath(fullAccessPath);
|
||||
@ -70,11 +76,11 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
|
||||
if (Array.isArray(newNumber)) {
|
||||
newNumber = newNumber[0];
|
||||
}
|
||||
setAttribute(`${name}.value`, parentPath, newNumber);
|
||||
changeCallback(newNumber, `${name}.value`);
|
||||
};
|
||||
|
||||
const handleValueChange = (newValue: number, valueType: string) => {
|
||||
setAttribute(`${name}.${valueType}`, parentPath, newValue);
|
||||
changeCallback(newValue, `${name}.${valueType}`);
|
||||
};
|
||||
|
||||
const deconstructNumberDict = (
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import { Form, InputGroup } from 'react-bootstrap';
|
||||
import { setAttribute } from '../socket';
|
||||
import { DocStringComponent } from './DocStringComponent';
|
||||
import '../App.css';
|
||||
import { getIdFromFullAccessPath } from '../utils/stringUtils';
|
||||
@ -17,11 +16,24 @@ type StringComponentProps = {
|
||||
docString: string;
|
||||
isInstantUpdate: boolean;
|
||||
addNotification: (message: string, levelname?: LevelName) => void;
|
||||
changeCallback?: (
|
||||
value: unknown,
|
||||
attributeName?: string,
|
||||
prefix?: string,
|
||||
callback?: (ack: unknown) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const StringComponent = React.memo((props: StringComponentProps) => {
|
||||
const { name, parentPath, readOnly, docString, isInstantUpdate, addNotification } =
|
||||
props;
|
||||
const {
|
||||
name,
|
||||
parentPath,
|
||||
readOnly,
|
||||
docString,
|
||||
isInstantUpdate,
|
||||
addNotification,
|
||||
changeCallback = () => {}
|
||||
} = props;
|
||||
|
||||
const renderCount = useRef(0);
|
||||
const [inputString, setInputString] = useState(props.value);
|
||||
@ -49,19 +61,19 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
|
||||
const handleChange = (event) => {
|
||||
setInputString(event.target.value);
|
||||
if (isInstantUpdate) {
|
||||
setAttribute(name, parentPath, event.target.value);
|
||||
changeCallback(event.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === 'Enter' && !isInstantUpdate) {
|
||||
setAttribute(name, parentPath, inputString);
|
||||
changeCallback(inputString);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
if (!isInstantUpdate) {
|
||||
setAttribute(name, parentPath, inputString);
|
||||
changeCallback(inputString);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user