mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-21 16:50:02 +02:00
Merge pull request #54 from tiqi-group/fix/frontend-div-ids
Fix: frontend div ids adhere to html guidelines now
This commit is contained in:
commit
61c6585ac6
@ -113,6 +113,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;
|
||||||
@ -130,6 +131,8 @@ export const ImageComponent = React.memo((props: ImageComponentProps) => {
|
|||||||
|
|
||||||
const renderCount = useRef(0);
|
const renderCount = useRef(0);
|
||||||
const [open, setOpen] = useState(true); // add this if you want to expand/collapse your component
|
const [open, setOpen] = useState(true); // add this if you want to expand/collapse your component
|
||||||
|
const fullAccessPath = parentPath.concat('.' + name);
|
||||||
|
const id = getIdFromFullAccessPath(fullAccessPath);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
renderCount.current++;
|
renderCount.current++;
|
||||||
@ -143,7 +146,7 @@ export const ImageComponent = React.memo((props: ImageComponentProps) => {
|
|||||||
// Your component logic here
|
// Your component logic here
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'imageComponent'} id={parentPath.concat('.' + name)}>
|
<div className={'imageComponent'} id={id}>
|
||||||
{/* Add the Card and Collapse components here if you want to be able to expand and
|
{/* Add the Card and Collapse components here if you want to be able to expand and
|
||||||
collapse your component. */}
|
collapse your component. */}
|
||||||
<Card>
|
<Card>
|
||||||
|
@ -7,12 +7,10 @@
|
|||||||
],
|
],
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"prettier"
|
"prettier"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": 1, // Means warning
|
"prettier/prettier": "error"
|
||||||
"prettier/prettier": 2 // Means error }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
6519
frontend/package-lock.json
generated
6519
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -46,9 +46,12 @@
|
|||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"@typescript-eslint/parser": "^6.9.0",
|
||||||
"prettier": "^3.0.0",
|
"eslint": "^8.52.0",
|
||||||
"@babel/plugin-proposal-private-property-in-object": "7.21.11"
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"typescript": "^4.9.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}
|
||||||
|
@ -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>
|
||||||
|
@ -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}
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
@ -61,7 +62,7 @@ export const ColouredEnumComponent = React.memo((props: ColouredEnumComponentPro
|
|||||||
value={value}
|
value={value}
|
||||||
style={{ backgroundColor: enumDict[value] }}
|
style={{ backgroundColor: enumDict[value] }}
|
||||||
onChange={(event) => handleValueChange(event.target.value)}>
|
onChange={(event) => handleValueChange(event.target.value)}>
|
||||||
{Object.entries(enumDict).map(([key, val]) => (
|
{Object.entries(enumDict).map(([key]) => (
|
||||||
<option key={key} value={key}>
|
<option key={key} value={key}>
|
||||||
{key}
|
{key}
|
||||||
</option>
|
</option>
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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)}
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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
|
||||||
|
|
||||||
@ -30,8 +31,8 @@ interface NumberComponentProps {
|
|||||||
const handleArrowKey = (
|
const handleArrowKey = (
|
||||||
key: string,
|
key: string,
|
||||||
value: string,
|
value: string,
|
||||||
selectionStart: number,
|
selectionStart: number
|
||||||
selectionEnd: number
|
// selectionEnd: number
|
||||||
) => {
|
) => {
|
||||||
// Split the input value into the integer part and decimal part
|
// Split the input value into the integer part and decimal part
|
||||||
const parts = value.split('.');
|
const parts = value.split('.');
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
@ -233,8 +234,8 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
|
|||||||
({ value: newValue, selectionStart } = handleArrowKey(
|
({ value: newValue, selectionStart } = handleArrowKey(
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
selectionStart,
|
selectionStart
|
||||||
selectionEnd
|
// selectionEnd
|
||||||
));
|
));
|
||||||
} else if (key === 'Backspace') {
|
} else if (key === 'Backspace') {
|
||||||
({ value: newValue, selectionStart } = handleBackspaceKey(
|
({ value: newValue, selectionStart } = handleBackspaceKey(
|
||||||
@ -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' : ''}
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
@ -145,6 +147,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col xs="auto">
|
<Col xs="auto">
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
|
id={`button-${id}`}
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => setOpen(!open)}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={open}
|
checked={open}
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
12
frontend/src/utils/stringUtils.ts
Normal file
12
frontend/src/utils/stringUtils.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export function getIdFromFullAccessPath(fullAccessPath: string) {
|
||||||
|
// Replace '].' with a single dash
|
||||||
|
let id = fullAccessPath.replace(/\]\./g, '-');
|
||||||
|
|
||||||
|
// Replace any character that is not a word character or underscore with a dash
|
||||||
|
id = id.replace(/[^\w_]+/g, '-');
|
||||||
|
|
||||||
|
// Remove any trailing dashes
|
||||||
|
id = id.replace(/-+$/, '');
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"files": {
|
"files": {
|
||||||
"main.css": "/static/css/main.398bc7f8.css",
|
"main.css": "/static/css/main.c444b055.css",
|
||||||
"main.js": "/static/js/main.6d7a3319.js",
|
"main.js": "/static/js/main.afebc391.js",
|
||||||
"index.html": "/index.html",
|
"index.html": "/index.html",
|
||||||
"main.398bc7f8.css.map": "/static/css/main.398bc7f8.css.map",
|
"main.c444b055.css.map": "/static/css/main.c444b055.css.map",
|
||||||
"main.6d7a3319.js.map": "/static/js/main.6d7a3319.js.map"
|
"main.afebc391.js.map": "/static/js/main.afebc391.js.map"
|
||||||
},
|
},
|
||||||
"entrypoints": [
|
"entrypoints": [
|
||||||
"static/css/main.398bc7f8.css",
|
"static/css/main.c444b055.css",
|
||||||
"static/js/main.6d7a3319.js"
|
"static/js/main.afebc391.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1 +1 @@
|
|||||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site displaying a pydase UI."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>pydase App</title><script defer="defer" src="/static/js/main.6d7a3319.js"></script><link href="/static/css/main.398bc7f8.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site displaying a pydase UI."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>pydase App</title><script defer="defer" src="/static/js/main.afebc391.js"></script><link href="/static/css/main.c444b055.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
src/pydase/frontend/static/css/main.c444b055.css
Normal file
6
src/pydase/frontend/static/css/main.c444b055.css
Normal file
File diff suppressed because one or more lines are too long
1
src/pydase/frontend/static/css/main.c444b055.css.map
Normal file
1
src/pydase/frontend/static/css/main.c444b055.css.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
src/pydase/frontend/static/js/main.afebc391.js
Normal file
3
src/pydase/frontend/static/js/main.afebc391.js
Normal file
File diff suppressed because one or more lines are too long
@ -45,11 +45,3 @@
|
|||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @mui/styled-engine v5.13.2
|
|
||||||
*
|
|
||||||
* @license MIT
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
1
src/pydase/frontend/static/js/main.afebc391.js.map
Normal file
1
src/pydase/frontend/static/js/main.afebc391.js.map
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user