fix: component ids adhere to html guidelines now

This commit is contained in:
Mose Müller 2023-10-30 14:05:39 +01:00
parent 7e5861ec22
commit b149c1b411
12 changed files with 55 additions and 34 deletions

View File

@ -258,6 +258,7 @@ const App = () => {
<div className="App navbarOffset"> <div className="App navbarOffset">
<DataServiceComponent <DataServiceComponent
name={''}
props={state as DataServiceJSON} props={state as DataServiceJSON}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react';
import { emit_update } from '../socket'; import { emit_update } 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';
interface AsyncMethodProps { interface AsyncMethodProps {
name: string; name: string;
@ -17,6 +18,7 @@ export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
const { name, parentPath, docString, value: runningTask, addNotification } = props; const { name, parentPath, docString, value: runningTask, addNotification } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const formRef = useRef(null); const formRef = useRef(null);
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -87,9 +89,7 @@ export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
}); });
return ( return (
<div <div className="align-items-center asyncMethodComponent" id={id}>
className="align-items-center asyncMethodComponent"
id={parentPath.concat('.' + name)}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}
@ -99,11 +99,7 @@ export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
</h5> </h5>
<Form onSubmit={execute} ref={formRef}> <Form onSubmit={execute} ref={formRef}>
{args} {args}
<Button <Button id={`button-${id}`} name={name} value={parentPath} type="submit">
id={`button-${parentPath}.${name}`}
name={name}
value={parentPath}
type="submit">
{runningTask ? 'Stop' : 'Start'} {runningTask ? 'Stop' : 'Start'}
</Button> </Button>
</Form> </Form>

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react';
import { ToggleButton } from 'react-bootstrap'; import { ToggleButton } from 'react-bootstrap';
import { emit_update } from '../socket'; import { emit_update } from '../socket';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
interface ButtonComponentProps { interface ButtonComponentProps {
name: string; name: string;
@ -17,6 +18,7 @@ export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
const { name, parentPath, value, readOnly, docString, mapping, addNotification } = const { name, parentPath, value, readOnly, docString, mapping, addNotification } =
props; props;
const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name; const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name;
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
const renderCount = useRef(0); const renderCount = useRef(0);
@ -33,14 +35,14 @@ export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
}; };
return ( return (
<div className={'buttonComponent'} id={parentPath.concat('.' + name)}> <div className={'buttonComponent'} id={id}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}
<DocStringComponent docString={docString} /> <DocStringComponent docString={docString} />
<ToggleButton <ToggleButton
id={`toggle-check-${parentPath}.${name}`} id={`toggle-check-${id}`}
type="checkbox" type="checkbox"
variant={value ? 'success' : 'secondary'} variant={value ? 'success' : 'secondary'}
checked={value} checked={value}

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react';
import { InputGroup, Form, Row, Col } from 'react-bootstrap'; import { InputGroup, Form, Row, Col } from 'react-bootstrap';
import { emit_update } from '../socket'; import { emit_update } from '../socket';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
interface ColouredEnumComponentProps { interface ColouredEnumComponentProps {
name: string; name: string;
@ -24,6 +25,7 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
addNotification addNotification
} = props; } = props;
const renderCount = useRef(0); const renderCount = useRef(0);
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -33,13 +35,12 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${parentPath}.${name} changed to ${value}.`);
}, [props.value]); }, [props.value]);
const handleValueChange = (newValue) => { const handleValueChange = (newValue: string) => {
console.log(newValue);
emit_update(name, parentPath, newValue); emit_update(name, parentPath, newValue);
}; };
return ( return (
<div className={'enumComponent'} id={parentPath.concat('.' + name)}> <div className={'enumComponent'} id={id}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}

View File

@ -3,8 +3,10 @@ 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 { Attribute, GenericComponent } from './GenericComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
type DataServiceProps = { type DataServiceProps = {
name: string;
props: DataServiceJSON; props: DataServiceJSON;
parentPath?: string; parentPath?: string;
isInstantUpdate: boolean; isInstantUpdate: boolean;
@ -15,21 +17,29 @@ export type DataServiceJSON = Record<string, Attribute>;
export const DataServiceComponent = React.memo( export const DataServiceComponent = React.memo(
({ ({
name,
props, props,
parentPath = 'DataService', parentPath = 'DataService',
isInstantUpdate, isInstantUpdate,
addNotification addNotification
}: DataServiceProps) => { }: DataServiceProps) => {
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
let fullAccessPath = parentPath;
if (name) {
fullAccessPath = parentPath.concat('.' + name);
}
console.log(fullAccessPath);
const id = getIdFromFullAccessPath(fullAccessPath);
console.log(id);
return ( return (
<div className="dataServiceComponent"> <div className="dataServiceComponent" id={id}>
<Card className="mb-3"> <Card className="mb-3">
<Card.Header <Card.Header
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
style={{ cursor: 'pointer' }} // Change cursor style on hover style={{ cursor: 'pointer' }} // Change cursor style on hover
> >
{parentPath} {open ? <ChevronDown /> : <ChevronRight />} {fullAccessPath} {open ? <ChevronDown /> : <ChevronRight />}
</Card.Header> </Card.Header>
<Collapse in={open}> <Collapse in={open}>
<Card.Body> <Card.Body>
@ -39,7 +49,7 @@ export const DataServiceComponent = React.memo(
key={key} key={key}
attribute={value} attribute={value}
name={key} name={key}
parentPath={parentPath} parentPath={fullAccessPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
/> />

View File

@ -153,8 +153,9 @@ export const GenericComponent = React.memo(
} else if (attribute.type === 'DataService') { } else if (attribute.type === 'DataService') {
return ( return (
<DataServiceComponent <DataServiceComponent
name={name}
props={attribute.value as DataServiceJSON} props={attribute.value as DataServiceJSON}
parentPath={parentPath.concat('.', name)} parentPath={parentPath}
isInstantUpdate={isInstantUpdate} isInstantUpdate={isInstantUpdate}
addNotification={addNotification} addNotification={addNotification}
/> />

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
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';
interface ImageComponentProps { interface ImageComponentProps {
name: string; name: string;
@ -18,6 +19,7 @@ export const ImageComponent = React.memo((props: ImageComponentProps) => {
const renderCount = useRef(0); const renderCount = useRef(0);
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -28,7 +30,7 @@ export const ImageComponent = React.memo((props: ImageComponentProps) => {
}, [props.value]); }, [props.value]);
return ( return (
<div className={'imageComponent'} id={parentPath.concat('.' + name)}> <div className={'imageComponent'} id={id}>
<Card> <Card>
<Card.Header <Card.Header
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}

View File

@ -1,6 +1,7 @@
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 { Attribute, GenericComponent } from './GenericComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
interface ListComponentProps { interface ListComponentProps {
name: string; name: string;
@ -16,13 +17,14 @@ export const ListComponent = React.memo((props: ListComponentProps) => {
props; props;
const renderCount = useRef(0); const renderCount = useRef(0);
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
}, [props]); }, [props]);
return ( return (
<div className={'listComponent'} id={parentPath.concat('.' + name)}> <div className={'listComponent'} id={id}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import { emit_update } from '../socket'; import { emit_update } from '../socket';
import { Button, InputGroup, Form, Collapse } from 'react-bootstrap'; import { Button, InputGroup, Form, Collapse } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
interface MethodProps { interface MethodProps {
name: string; name: string;
@ -19,6 +20,7 @@ export const MethodComponent = React.memo((props: MethodProps) => {
const [hideOutput, setHideOutput] = useState(false); const [hideOutput, setHideOutput] = useState(false);
// Add a new state variable to hold the list of function calls // Add a new state variable to hold the list of function calls
const [functionCalls, setFunctionCalls] = useState([]); const [functionCalls, setFunctionCalls] = useState([]);
const id = getIdFromFullAccessPath(parentPath.concat('.' + name));
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -69,9 +71,7 @@ export const MethodComponent = React.memo((props: MethodProps) => {
}); });
return ( return (
<div <div className="align-items-center methodComponent" id={id}>
className="align-items-center methodComponent"
id={parentPath.concat('.' + name)}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}

View File

@ -3,6 +3,7 @@ import { Form, InputGroup } from 'react-bootstrap';
import { emit_update } from '../socket'; import { emit_update } from '../socket';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import '../App.css'; import '../App.css';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
// TODO: add button functionality // TODO: add button functionality
@ -131,14 +132,14 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
const [cursorPosition, setCursorPosition] = useState(null); const [cursorPosition, setCursorPosition] = useState(null);
// Create a state for the input string // Create a state for the input string
const [inputString, setInputString] = useState(props.value.toString()); const [inputString, setInputString] = useState(props.value.toString());
const fullAccessPath = parentPath.concat('.' + name);
const id = getIdFromFullAccessPath(fullAccessPath);
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
// Set the cursor position after the component re-renders // Set the cursor position after the component re-renders
const inputElement = document.getElementsByName( const inputElement = document.getElementsByName(id)[0] as HTMLInputElement;
parentPath.concat('.' + name)
)[0] as HTMLInputElement;
if (inputElement && cursorPosition !== null) { if (inputElement && cursorPosition !== null) {
inputElement.setSelectionRange(cursorPosition, cursorPosition); inputElement.setSelectionRange(cursorPosition, cursorPosition);
} }
@ -275,7 +276,7 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
}; };
return ( return (
<div className="numberComponent" id={parentPath.concat('.' + name)}> <div className="numberComponent" id={id}>
{process.env.NODE_ENV === 'development' && showName && ( {process.env.NODE_ENV === 'development' && showName && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}
@ -287,7 +288,7 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
type="text" type="text"
value={inputString} value={inputString}
disabled={readOnly} disabled={readOnly}
name={parentPath.concat('.' + name)} name={fullAccessPath}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onBlur={handleBlur} onBlur={handleBlur}
className={isInstantUpdate && !readOnly ? 'instantUpdate' : ''} className={isInstantUpdate && !readOnly ? 'instantUpdate' : ''}

View File

@ -4,6 +4,7 @@ import { emit_update } from '../socket';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import { Slider } from '@mui/material'; import { Slider } from '@mui/material';
import { NumberComponent } from './NumberComponent'; import { NumberComponent } from './NumberComponent';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
interface SliderComponentProps { interface SliderComponentProps {
name: string; name: string;
@ -21,11 +22,6 @@ interface SliderComponentProps {
export const SliderComponent = React.memo((props: SliderComponentProps) => { export const SliderComponent = React.memo((props: SliderComponentProps) => {
const renderCount = useRef(0); const renderCount = useRef(0);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
useEffect(() => {
renderCount.current++;
});
const { const {
name, name,
parentPath, parentPath,
@ -38,6 +34,12 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
isInstantUpdate, isInstantUpdate,
addNotification addNotification
} = props; } = props;
const fullAccessPath = parentPath.concat('.' + name);
const id = getIdFromFullAccessPath(fullAccessPath);
useEffect(() => {
renderCount.current++;
});
useEffect(() => { useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`); addNotification(`${parentPath}.${name} changed to ${value}.`);
@ -102,7 +104,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
}; };
return ( return (
<div className="sliderComponent" id={parentPath.concat('.' + name)}> <div className="sliderComponent" id={id}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}

View File

@ -3,6 +3,7 @@ import { Form, InputGroup } from 'react-bootstrap';
import { emit_update } from '../socket'; import { emit_update } from '../socket';
import { DocStringComponent } from './DocStringComponent'; import { DocStringComponent } from './DocStringComponent';
import '../App.css'; import '../App.css';
import { getIdFromFullAccessPath } from '../utils/stringUtils';
// TODO: add button functionality // TODO: add button functionality
@ -22,6 +23,8 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
const renderCount = useRef(0); const renderCount = useRef(0);
const [inputString, setInputString] = useState(props.value); const [inputString, setInputString] = useState(props.value);
const fullAccessPath = parentPath.concat('.' + name);
const id = getIdFromFullAccessPath(fullAccessPath);
useEffect(() => { useEffect(() => {
renderCount.current++; renderCount.current++;
@ -55,7 +58,7 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
}; };
return ( return (
<div className={'stringComponent'} id={parentPath.concat('.' + name)}> <div className={'stringComponent'} id={id}>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
<p>Render count: {renderCount.current}</p> <p>Render count: {renderCount.current}</p>
)} )}