moves displayName and id to GenericComponent and pass them as props

This commit is contained in:
Mose Müller 2024-02-21 09:50:04 +01:00
parent 2f2544b978
commit 2d98ba51f4
12 changed files with 148 additions and 168 deletions

View File

@ -1,10 +1,8 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { runMethod } from '../socket'; import { runMethod } from '../socket';
import { InputGroup, Form, Button } from 'react-bootstrap'; import { InputGroup, Form, Button } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { WebSettingsContext } from '../WebSettings';
type AsyncMethodProps = { type AsyncMethodProps = {
name: string; name: string;
@ -14,20 +12,23 @@ type AsyncMethodProps = {
docString?: string; docString?: string;
hideOutput?: boolean; hideOutput?: boolean;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
displayName: string;
id: string;
}; };
export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => { export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
const { name, parentPath, docString, value: runningTask, addNotification } = props; const {
name,
parentPath,
docString,
value: runningTask,
addNotification,
displayName,
id
} = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const formRef = useRef(null); const formRef = useRef(null);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
const id = getIdFromFullAccessPath(fullAccessPath);
const webSettings = useContext(WebSettingsContext);
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -51,13 +52,13 @@ export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
let message: string; let message: string;
if (runningTask === null) { if (runningTask === null) {
message = `${parentPath}.${name} task was stopped.`; message = `${fullAccessPath} task was stopped.`;
} else { } else {
const runningTaskEntries = Object.entries(runningTask) const runningTaskEntries = Object.entries(runningTask)
.map(([key, value]) => `${key}: "${value}"`) .map(([key, value]) => `${key}: "${value}"`)
.join(', '); .join(', ');
message = `${parentPath}.${name} was started with parameters { ${runningTaskEntries} }.`; message = `${fullAccessPath} was started with parameters { ${runningTaskEntries} }.`;
} }
addNotification(message); addNotification(message);
}, [props.value]); }, [props.value]);

View File

@ -1,8 +1,6 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { WebSettingsContext } from '../WebSettings';
import { ToggleButton } from 'react-bootstrap'; import { ToggleButton } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
type ButtonComponentProps = { type ButtonComponentProps = {
@ -19,27 +17,24 @@ type ButtonComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName: string;
id: string;
}; };
export const ButtonComponent = React.memo((props: ButtonComponentProps) => { export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
const { const {
name,
parentPath,
value, value,
readOnly, readOnly,
docString, docString,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
// const buttonName = props.mapping ? (value ? props.mapping[0] : props.mapping[1]) : name; // const buttonName = props.mapping ? (value ? props.mapping[0] : props.mapping[1]) : name;
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
const renderCount = useRef(0); const renderCount = useRef(0);
@ -48,7 +43,7 @@ export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
}); });
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${fullAccessPath} changed to ${value}.`);
}, [props.value]); }, [props.value]);
const setChecked = (checked: boolean) => { const setChecked = (checked: boolean) => {
@ -66,7 +61,7 @@ export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
type="checkbox" type="checkbox"
variant={value ? 'success' : 'secondary'} variant={value ? 'success' : 'secondary'}
checked={value} checked={value}
value={parentPath} value={displayName}
disabled={readOnly} disabled={readOnly}
onChange={(e) => setChecked(e.currentTarget.checked)}> onChange={(e) => setChecked(e.currentTarget.checked)}>
{displayName} {displayName}

View File

@ -1,8 +1,6 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { WebSettingsContext } from '../WebSettings';
import { InputGroup, Form, Row, Col } from 'react-bootstrap'; import { InputGroup, Form, Row, Col } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
type ColouredEnumComponentProps = { type ColouredEnumComponentProps = {
@ -19,35 +17,32 @@ type ColouredEnumComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName: string;
id: string;
}; };
export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentProps) => { export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentProps) => {
const { const {
name,
parentPath: parentPath,
value, value,
docString, docString,
enumDict, enumDict,
readOnly, readOnly,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
}); });
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${fullAccessPath} changed to ${value}.`);
}, [props.value]); }, [props.value]);
return ( return (

View File

@ -1,11 +1,9 @@
import { useContext, useState } from 'react'; import { useState } from 'react';
import React from 'react'; import React from 'react';
import { Card, Collapse } from 'react-bootstrap'; import { Card, Collapse } from 'react-bootstrap';
import { ChevronDown, ChevronRight } from 'react-bootstrap-icons'; import { ChevronDown, ChevronRight } from 'react-bootstrap-icons';
import { Attribute, GenericComponent } from './GenericComponent'; import { SerializedValue, GenericComponent } from './GenericComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { WebSettingsContext } from '../WebSettings';
type DataServiceProps = { type DataServiceProps = {
name: string; name: string;
@ -13,31 +11,24 @@ type DataServiceProps = {
parentPath?: string; parentPath?: string;
isInstantUpdate: boolean; isInstantUpdate: boolean;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
displayName: string;
id: string;
}; };
export type DataServiceJSON = Record<string, Attribute>; export type DataServiceJSON = Record<string, SerializedValue>;
export const DataServiceComponent = React.memo( export const DataServiceComponent = React.memo(
({ ({
name, name,
props, props,
parentPath = '', parentPath = undefined,
isInstantUpdate, isInstantUpdate,
addNotification addNotification,
displayName,
id
}: DataServiceProps) => { }: DataServiceProps) => {
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
let fullAccessPath = parentPath; const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
if (name) {
fullAccessPath = [parentPath, name].filter((element) => element).join('.');
}
const id = getIdFromFullAccessPath(fullAccessPath);
const webSettings = useContext(WebSettingsContext);
let displayName = fullAccessPath;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
if (displayName !== '') { if (displayName !== '') {
return ( return (

View File

@ -1,8 +1,5 @@
import { useContext } from 'react';
import React from 'react'; import React from 'react';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { WebSettingsContext } from '../WebSettings';
import { DataServiceComponent, DataServiceJSON } from './DataServiceComponent'; import { DataServiceComponent, DataServiceJSON } from './DataServiceComponent';
import { MethodComponent } from './MethodComponent'; import { MethodComponent } from './MethodComponent';
@ -12,6 +9,8 @@ type DeviceConnectionProps = {
parentPath: string; parentPath: string;
isInstantUpdate: boolean; isInstantUpdate: boolean;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
displayName: string;
id: string;
}; };
export const DeviceConnectionComponent = React.memo( export const DeviceConnectionComponent = React.memo(
@ -20,23 +19,14 @@ export const DeviceConnectionComponent = React.memo(
props, props,
parentPath, parentPath,
isInstantUpdate, isInstantUpdate,
addNotification addNotification,
displayName,
id
}: DeviceConnectionProps) => { }: DeviceConnectionProps) => {
const { connected, connect, ...updatedProps } = props; const { connected, connect, ...updatedProps } = props;
const connectedVal = connected.value; const connectedVal = connected.value;
let fullAccessPath = parentPath; const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
if (name) {
fullAccessPath = [parentPath, name].filter((element) => element).join('.');
}
const id = getIdFromFullAccessPath(fullAccessPath);
const webSettings = useContext(WebSettingsContext);
let displayName = fullAccessPath;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
return ( return (
<div className="deviceConnectionComponent" id={id}> <div className="deviceConnectionComponent" id={id}>
@ -51,6 +41,8 @@ export const DeviceConnectionComponent = React.memo(
parameters={connect.parameters} parameters={connect.parameters}
docString={connect.doc} docString={connect.doc}
addNotification={addNotification} addNotification={addNotification}
displayName={'reconnect'}
id={id + '-connect'}
/> />
</div> </div>
)} )}
@ -60,6 +52,8 @@ export const DeviceConnectionComponent = React.memo(
parentPath={parentPath} parentPath={parentPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
</div> </div>
); );

View File

@ -1,7 +1,5 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { WebSettingsContext } from '../WebSettings';
import { InputGroup, Form, Row, Col } from 'react-bootstrap'; import { InputGroup, Form, Row, Col } from 'react-bootstrap';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
@ -18,35 +16,32 @@ type EnumComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName: string;
id: string;
}; };
export const EnumComponent = React.memo((props: EnumComponentProps) => { export const EnumComponent = React.memo((props: EnumComponentProps) => {
const { const {
name,
parentPath: parentPath,
value, value,
docString, docString,
enumDict, enumDict,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
}); });
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${fullAccessPath} changed to ${value}.`);
}, [props.value]); }, [props.value]);
return ( return (

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useContext } from 'react';
import { ButtonComponent } from './ButtonComponent'; import { ButtonComponent } from './ButtonComponent';
import { NumberComponent } from './NumberComponent'; import { NumberComponent } from './NumberComponent';
import { SliderComponent } from './SliderComponent'; import { SliderComponent } from './SliderComponent';
@ -12,6 +12,8 @@ import { DeviceConnectionComponent } from './DeviceConnection';
import { ImageComponent } from './ImageComponent'; import { ImageComponent } from './ImageComponent';
import { ColouredEnumComponent } from './ColouredEnumComponent'; import { ColouredEnumComponent } from './ColouredEnumComponent';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { WebSettingsContext } from '../WebSettings';
import { setAttribute } from '../socket'; import { setAttribute } from '../socket';
type AttributeType = type AttributeType =
@ -35,7 +37,7 @@ export type SerializedValue = {
value?: ValueType | ValueType[]; value?: ValueType | ValueType[];
readonly: boolean; readonly: boolean;
doc?: string | null; doc?: string | null;
parameters?: Record<string, string>; parameters?: Record<string, SerializedValue>;
async?: boolean; async?: boolean;
enum?: Record<string, string>; enum?: Record<string, string>;
}; };
@ -55,6 +57,14 @@ export const GenericComponent = React.memo(
isInstantUpdate, isInstantUpdate,
addNotification addNotification
}: GenericComponentProps) => { }: GenericComponentProps) => {
const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
const id = getIdFromFullAccessPath(fullAccessPath);
const webSettings = useContext(WebSettingsContext);
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
function changeCallback( function changeCallback(
value: unknown, value: unknown,
@ -75,6 +85,8 @@ export const GenericComponent = React.memo(
value={Boolean(attribute.value)} value={Boolean(attribute.value)}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'float' || attribute.type === 'int') { } else if (attribute.type === 'float' || attribute.type === 'int') {
@ -89,6 +101,8 @@ export const GenericComponent = React.memo(
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'Quantity') { } else if (attribute.type === 'Quantity') {
@ -104,6 +118,8 @@ export const GenericComponent = React.memo(
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'NumberSlider') { } else if (attribute.type === 'NumberSlider') {
@ -120,6 +136,8 @@ export const GenericComponent = React.memo(
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'Enum') { } else if (attribute.type === 'Enum') {
@ -132,6 +150,8 @@ export const GenericComponent = React.memo(
enumDict={attribute.enum} enumDict={attribute.enum}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'method') { } else if (attribute.type === 'method') {
@ -143,6 +163,8 @@ export const GenericComponent = React.memo(
docString={attribute.doc} docString={attribute.doc}
parameters={attribute.parameters} parameters={attribute.parameters}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
); );
} else { } else {
@ -154,6 +176,8 @@ export const GenericComponent = React.memo(
parameters={attribute.parameters} parameters={attribute.parameters}
value={attribute.value as Record<string, string>} value={attribute.value as Record<string, string>}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
); );
} }
@ -168,6 +192,8 @@ export const GenericComponent = React.memo(
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'DataService') { } else if (attribute.type === 'DataService') {
@ -178,6 +204,8 @@ export const GenericComponent = React.memo(
parentPath={parentPath} parentPath={parentPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'DeviceConnection') { } else if (attribute.type === 'DeviceConnection') {
@ -188,6 +216,8 @@ export const GenericComponent = React.memo(
parentPath={parentPath} parentPath={parentPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'list') { } else if (attribute.type === 'list') {
@ -199,6 +229,7 @@ export const GenericComponent = React.memo(
parentPath={parentPath} parentPath={parentPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
id={id}
/> />
); );
} else if (attribute.type === 'Image') { } else if (attribute.type === 'Image') {
@ -212,6 +243,8 @@ export const GenericComponent = React.memo(
// Add any other specific props for the ImageComponent here // Add any other specific props for the ImageComponent here
format={attribute.value['format']['value'] as string} format={attribute.value['format']['value'] as string}
addNotification={addNotification} addNotification={addNotification}
displayName={displayName}
id={id}
/> />
); );
} else if (attribute.type === 'ColouredEnum') { } else if (attribute.type === 'ColouredEnum') {
@ -225,6 +258,8 @@ export const GenericComponent = React.memo(
enumDict={attribute.enum} enumDict={attribute.enum}
addNotification={addNotification} addNotification={addNotification}
changeCallback={changeCallback} changeCallback={changeCallback}
displayName={displayName}
id={id}
/> />
); );
} else { } else {

View File

@ -1,9 +1,7 @@
import React, { useContext, useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { WebSettingsContext } from '../WebSettings';
import { Card, Collapse, Image } from 'react-bootstrap'; import { Card, Collapse, Image } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { ChevronDown, ChevronRight } from 'react-bootstrap-icons'; import { ChevronDown, ChevronRight } from 'react-bootstrap-icons';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
type ImageComponentProps = { type ImageComponentProps = {
@ -14,28 +12,25 @@ type ImageComponentProps = {
docString: string; docString: string;
format: string; format: string;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
displayName: string;
id: string;
}; };
export const ImageComponent = React.memo((props: ImageComponentProps) => { export const ImageComponent = React.memo((props: ImageComponentProps) => {
const { name, parentPath, value, docString, format, addNotification } = props; const { value, docString, format, addNotification, displayName, id } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
}); });
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed.`); addNotification(`${fullAccessPath} changed.`);
}, [props.value]); }, [props.value]);
return ( return (

View File

@ -1,25 +1,23 @@
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { Attribute, GenericComponent } from './GenericComponent'; import { SerializedValue, GenericComponent } from './GenericComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
type ListComponentProps = { type ListComponentProps = {
name: string; name: string;
parentPath?: string; parentPath?: string;
value: Attribute[]; value: SerializedValue[];
docString: string; docString: string;
isInstantUpdate: boolean; isInstantUpdate: boolean;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
id: string;
}; };
export const ListComponent = React.memo((props: ListComponentProps) => { export const ListComponent = React.memo((props: ListComponentProps) => {
const { name, parentPath, value, docString, isInstantUpdate, addNotification } = const { name, parentPath, value, docString, isInstantUpdate, addNotification, id } =
props; props;
const renderCount = useRef(0); const renderCount = useRef(0);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
const id = getIdFromFullAccessPath(fullAccessPath);
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;

View File

@ -1,7 +1,5 @@
import React, { useContext, useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { WebSettingsContext } from '../WebSettings';
import '../App.css'; import '../App.css';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { NumberInputField } from './NumberInputField'; import { NumberInputField } from './NumberInputField';
@ -39,7 +37,6 @@ type NumberComponentProps = {
docString: string; docString: string;
isInstantUpdate: boolean; isInstantUpdate: boolean;
unit?: string; unit?: string;
showName?: boolean;
addNotification: (message: string, levelname?: LevelName) => void; addNotification: (message: string, levelname?: LevelName) => void;
changeCallback?: ( changeCallback?: (
value: unknown, value: unknown,
@ -47,37 +44,31 @@ type NumberComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName?: string;
id: string;
}; };
export const NumberComponent = React.memo((props: NumberComponentProps) => { export const NumberComponent = React.memo((props: NumberComponentProps) => {
const { const {
name,
value, value,
parentPath,
readOnly, readOnly,
docString, docString,
isInstantUpdate, isInstantUpdate,
unit, unit,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
// Whether to show the name infront of the component (false if used with a slider)
const showName = props.showName !== undefined ? props.showName : true;
const renderCount = useRef(0); const renderCount = useRef(0);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
// emitting notification // emitting notification
let notificationMsg = `${parentPath}.${name} changed to ${props.value}`; let notificationMsg = `${fullAccessPath} changed to ${props.value}`;
if (unit === undefined) { if (unit === undefined) {
notificationMsg += '.'; notificationMsg += '.';
} else { } else {
@ -94,7 +85,7 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
<NumberInputField <NumberInputField
name={fullAccessPath} name={fullAccessPath}
value={value} value={value}
displayName={showName === true ? displayName : null} displayName={displayName}
unit={unit} unit={unit}
readOnly={readOnly} readOnly={readOnly}
type={props.type} type={props.type}

View File

@ -1,10 +1,8 @@
import React, { useContext, useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { WebSettingsContext } from '../WebSettings';
import { InputGroup, Form, Row, Col, Collapse, ToggleButton } from 'react-bootstrap'; import { InputGroup, Form, Row, Col, Collapse, ToggleButton } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { Slider } from '@mui/material'; import { Slider } from '@mui/material';
import { NumberComponent, NumberObject } from './NumberComponent'; import { NumberComponent, NumberObject } from './NumberComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
type SliderComponentProps = { type SliderComponentProps = {
@ -24,6 +22,8 @@ type SliderComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName: string;
id: string;
}; };
export const SliderComponent = React.memo((props: SliderComponentProps) => { export const SliderComponent = React.memo((props: SliderComponentProps) => {
@ -39,35 +39,30 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
docString, docString,
isInstantUpdate, isInstantUpdate,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [parentPath, name].filter((element) => element).join('.');
const id = getIdFromFullAccessPath(fullAccessPath);
const webSettings = useContext(WebSettingsContext);
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
}); });
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${fullAccessPath} changed to ${value.value}.`);
}, [props.value]); }, [props.value]);
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name}.min changed to ${min}.`); addNotification(`${fullAccessPath}.min changed to ${min.value}.`);
}, [props.min]); }, [props.min]);
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name}.max changed to ${max}.`); addNotification(`${fullAccessPath}.max changed to ${max.value}.`);
}, [props.max]); }, [props.max]);
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name}.stepSize changed to ${stepSize}.`); addNotification(`${fullAccessPath}.stepSize changed to ${stepSize.value}.`);
}, [props.stepSize]); }, [props.stepSize]);
const handleOnChange = (event, newNumber: number | number[]) => { const handleOnChange = (event, newNumber: number | number[]) => {
@ -145,8 +140,9 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
type="float" type="float"
value={valueMagnitude} value={valueMagnitude}
unit={valueUnit} unit={valueUnit}
showName={false} addNotification={() => {}}
addNotification={() => null} changeCallback={(value) => changeCallback(value, name + '.value')}
id={id + '-value'}
/> />
</Col> </Col>
<Col xs="auto"> <Col xs="auto">

View File

@ -1,10 +1,8 @@
import React, { useContext, useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Form, InputGroup } from 'react-bootstrap'; import { Form, InputGroup } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import '../App.css'; import '../App.css';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
import { LevelName } from './NotificationsComponent'; import { LevelName } from './NotificationsComponent';
import { WebSettingsContext } from '../WebSettings';
// TODO: add button functionality // TODO: add button functionality
@ -22,29 +20,26 @@ type StringComponentProps = {
prefix?: string, prefix?: string,
callback?: (ack: unknown) => void callback?: (ack: unknown) => void
) => void; ) => void;
displayName: string;
id: string;
}; };
export const StringComponent = React.memo((props: StringComponentProps) => { export const StringComponent = React.memo((props: StringComponentProps) => {
const { const {
name,
parentPath,
readOnly, readOnly,
docString, docString,
isInstantUpdate, isInstantUpdate,
addNotification, addNotification,
changeCallback = () => {} changeCallback = () => {},
displayName,
id
} = props; } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const [inputString, setInputString] = useState(props.value); const [inputString, setInputString] = useState(props.value);
const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const fullAccessPath = [props.parentPath, props.name]
const id = getIdFromFullAccessPath(fullAccessPath); .filter((element) => element)
const webSettings = useContext(WebSettingsContext); .join('.');
let displayName = name;
if (webSettings[fullAccessPath] && webSettings[fullAccessPath].displayName) {
displayName = webSettings[fullAccessPath].displayName;
}
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -55,7 +50,7 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
if (props.value !== inputString) { if (props.value !== inputString) {
setInputString(props.value); setInputString(props.value);
} }
addNotification(`${parentPath}.${name} changed to ${props.value}.`); addNotification(`${fullAccessPath} changed to ${props.value}.`);
}, [props.value]); }, [props.value]);
const handleChange = (event) => { const handleChange = (event) => {
@ -91,7 +86,6 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
type="text" type="text"
value={inputString} value={inputString}
disabled={readOnly} disabled={readOnly}
name={name}
onChange={handleChange} onChange={handleChange}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onBlur={handleBlur} onBlur={handleBlur}