diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 63a106f..d45ea29 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,37 +1,15 @@ import { useEffect, useReducer } from 'react'; -import { ButtonComponent } from './components/ButtonComponent'; -import { NumberComponent } from './components/NumberComponent'; -import { SliderComponent } from './components/SliderComponent'; -import { EnumComponent } from './components/EnumComponent'; import { socket } from './socket'; -import { MethodComponent } from './components/MethodComponent'; -import { AsyncMethodComponent } from './components/AsyncMethodComponent'; - -type AttributeType = - | 'str' - | 'bool' - | 'float' - | 'int' - | 'method' - | 'DataService' - | 'Enum' - | 'NumberSlider'; +import { + DataServiceComponent, + DataServiceJSON +} from './components/DataServiceComponent'; type ValueType = boolean | string | number | object; -interface Attribute { - type: AttributeType; - value?: ValueType; - readonly: boolean; - doc?: string | null; - parameters?: Record; - async?: boolean; - enum?: Record; -} -type MyData = Record; -type State = MyData | null; +type State = DataServiceJSON | null; type Action = - | { type: 'SET_DATA'; data: MyData } + | { type: 'SET_DATA'; data: DataServiceJSON } | { type: 'UPDATE_ATTRIBUTE'; parent_path: string; name: string; value: ValueType }; type NotificationElement = { data: { parent_path: string; name: string; value: object }; @@ -96,7 +74,7 @@ const App = () => { // Fetch data from the API when the component mounts fetch('http://localhost:8001/service-properties') .then((response) => response.json()) - .then((data: MyData) => dispatch({ type: 'SET_DATA', data })); + .then((data: DataServiceJSON) => dispatch({ type: 'SET_DATA', data })); function onNotify(value: NotificationElement) { dispatch({ @@ -120,88 +98,7 @@ const App = () => { } return (
- {Object.entries(state).map(([key, value]) => { - if (value.type === 'bool') { - return ( -
- -
- ); - } else if (value.type === 'float' || value.type === 'int') { - return ( -
- -
- ); - } else if (value.type === 'NumberSlider') { - return ( -
- -
- ); - } else if (value.type === 'Enum') { - return ( -
- -
- ); - } else if (value.type === 'method') { - if (!value.async) { - return ( -
- -
- ); - } else { - return ( -
- } - /> -
- ); - } - } else { - return
; - } - })} +
); }; diff --git a/frontend/src/components/DataServiceComponent.tsx b/frontend/src/components/DataServiceComponent.tsx new file mode 100644 index 0000000..4c4771f --- /dev/null +++ b/frontend/src/components/DataServiceComponent.tsx @@ -0,0 +1,153 @@ +import { useState } from 'react'; +import { ButtonComponent } from './ButtonComponent'; +import { NumberComponent } from './NumberComponent'; +import { SliderComponent } from './SliderComponent'; +import { EnumComponent } from './EnumComponent'; +import { MethodComponent } from './MethodComponent'; +import { AsyncMethodComponent } from './AsyncMethodComponent'; +import React from 'react'; +import { Card, Collapse } from 'react-bootstrap'; +import { ChevronDown, ChevronRight } from 'react-bootstrap-icons'; + +type AttributeType = + | 'str' + | 'bool' + | 'float' + | 'int' + | 'method' + | 'DataService' + | 'Enum' + | 'NumberSlider'; + +type ValueType = boolean | string | number | object; +interface Attribute { + type: AttributeType; + value?: ValueType; + readonly: boolean; + doc?: string | null; + parameters?: Record; + async?: boolean; + enum?: Record; +} +type DataServiceProps = { + props: DataServiceJSON; + parentPath?: string; +}; + +export type DataServiceJSON = Record; + +export const DataServiceComponent = React.memo( + ({ props, parentPath = 'DataService' }: DataServiceProps) => { + const [open, setOpen] = useState(true); + // useEffect(() => {}, []); + + // While the data is loading + return ( +
+ + setOpen(!open)} + style={{ cursor: 'pointer' }} // Change cursor style on hover + > + {parentPath} {open ? : } + + + + {Object.entries(props).map(([key, value]) => { + if (value.type === 'bool') { + return ( +
+ +
+ ); + } else if (value.type === 'float' || value.type === 'int') { + return ( +
+ +
+ ); + } else if (value.type === 'NumberSlider') { + return ( +
+ +
+ ); + } else if (value.type === 'Enum') { + return ( +
+ +
+ ); + } else if (value.type === 'method') { + if (!value.async) { + return ( +
+ +
+ ); + } else { + return ( +
+ } + /> +
+ ); + } + } else if (value.type === 'DataService') { + return ( +
+ +
+ ); + } else { + return
; + } + })} +
+
+
+
+ ); + } +);