diff --git a/src/widget/toolbox-item.js b/src/widget/toolbox-item.js
deleted file mode 100644
index 4c268c5..0000000
--- a/src/widget/toolbox-item.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { DragSource } from 'react-dnd';
-import classNames from 'classnames';
-import Icon from '../common/icon';
-
-const toolboxItemSource = {
- beginDrag(props) {
- return {
- name: props.name
- };
- }
-};
-
-function collect(connect, monitor) {
- return {
- connectDragSource: connect.dragSource(),
- isDragging: monitor.isDragging()
- }
-}
-
-class ToolboxItem extends React.Component {
- static defaultProps = {
- disabled: false
- };
-
- render() {
- var itemClass = classNames({
- 'toolbox-item': true,
- 'toolbox-item-dragging': this.props.isDragging,
- 'toolbox-item-disabled': this.props.disabled
- });
- var dropEffect = 'copy';
-
- if (this.props.disabled === false) {
- return this.props.connectDragSource(
-
-
- {this.props.icon && }
- {this.props.name}
-
-
- , {dropEffect});
- }
- else {
- return (
-
-
- {this.props.icon && }
- {this.props.name}
-
-
- );
- }
- }
-}
-
-export default DragSource('widget', toolboxItemSource, collect)(ToolboxItem);
diff --git a/src/widget/toolbox-item.jsx b/src/widget/toolbox-item.jsx
new file mode 100644
index 0000000..ac5e834
--- /dev/null
+++ b/src/widget/toolbox-item.jsx
@@ -0,0 +1,74 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from "react";
+import { DragSource } from "react-dnd";
+import classNames from "classnames";
+import Icon from "../common/icon";
+
+// Drag source specification
+const toolboxItemSource = {
+ beginDrag(props) {
+ return {
+ name: props.name,
+ };
+ },
+};
+
+// The collect function gathers props for the component related to dragging
+function collect(connect, monitor) {
+ return {
+ connectDragSource: connect.dragSource(),
+ isDragging: monitor.isDragging(),
+ };
+}
+
+// The functional component for ToolboxItem
+const ToolboxItem = ({
+ connectDragSource,
+ isDragging,
+ disabled,
+ name,
+ icon,
+}) => {
+ const itemClass = classNames({
+ "toolbox-item": true,
+ "toolbox-item-dragging": isDragging,
+ "toolbox-item-disabled": disabled,
+ });
+
+ const content = (
+
+ {icon && }
+ {name}
+
+ );
+
+ return disabled ? (
+
{content}
+ ) : (
+ connectDragSource(
{content}
, {
+ dropEffect: "copy",
+ })
+ );
+};
+
+ToolboxItem.defaultProps = {
+ disabled: false,
+};
+
+export default DragSource("widget", toolboxItemSource, collect)(ToolboxItem);
diff --git a/src/widget/widget-plot/plot-legend.js b/src/widget/widget-plot/plot-legend.js
deleted file mode 100644
index 096c67b..0000000
--- a/src/widget/widget-plot/plot-legend.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { scaleOrdinal} from 'd3-scale';
-import { schemeCategory10 } from 'd3-scale-chromatic'
-
-function Legend(props){
-
- const signal = props.sig;
- const hasScalingFactor = (signal.scalingFactor !== 1);
-
- let color = typeof props.lineColor === "undefined" ? schemeCategory10[props.index % 10] : props.lineColor;
-
- return (
-
;
- }
-}
-
-export default PlotLegend;
diff --git a/src/widget/widget-plot/plot-legend.jsx b/src/widget/widget-plot/plot-legend.jsx
new file mode 100644
index 0000000..d054e18
--- /dev/null
+++ b/src/widget/widget-plot/plot-legend.jsx
@@ -0,0 +1,62 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React from "react";
+import { schemeCategory10 } from "d3-scale-chromatic";
+
+function Legend(props) {
+ const { sig: signal, lineColor, index, showUnit } = props;
+ const hasScalingFactor = signal.scalingFactor !== 1;
+ const color =
+ typeof lineColor === "undefined" ? schemeCategory10[index % 10] : lineColor;
+
+ return (
+
+ );
+};
+
+export default PlotLegend;
diff --git a/src/widget/widgets/action.js b/src/widget/widgets/action.jsx
similarity index 57%
rename from src/widget/widgets/action.js
rename to src/widget/widgets/action.jsx
index 5a69d32..7b0ecb0 100644
--- a/src/widget/widgets/action.js
+++ b/src/widget/widgets/action.jsx
@@ -15,29 +15,28 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import React, { Component } from 'react';
-import { Button, ButtonGroup } from 'react-bootstrap';
-import Icon from '../../common/icon';
+import React from "react";
+import { Button, ButtonGroup } from "react-bootstrap";
+import Icon from "../../common/icon";
-class WidgetAction extends Component {
- constructor(props) {
- super(props);
+const WidgetAction = (props) => {
+ const onClick = (e) => {
+ // Put your onClick logic here
+ };
- this.state = {
- };
- }
-
- onClick(e) {
-
- }
-
- render() {
- return
-
-
-
- ;
- }
-}
+ return (
+
+
+
+
+
+ );
+};
export default WidgetAction;
diff --git a/src/widget/widgets/box.js b/src/widget/widgets/box.jsx
similarity index 59%
rename from src/widget/widgets/box.js
rename to src/widget/widgets/box.jsx
index 3572267..3060610 100644
--- a/src/widget/widgets/box.js
+++ b/src/widget/widgets/box.jsx
@@ -15,25 +15,21 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import React, { Component } from 'react';
+import React from "react";
+const WidgetBox = (props) => {
+ let colorStyle = {
+ borderColor: props.widget.customProperties.border_color,
+ backgroundColor: props.widget.customProperties.background_color,
+ opacity: props.widget.customProperties.background_color_opacity,
+ borderWidth: props.widget.customProperties.border_width + "px",
+ };
-class WidgetBox extends Component {
- render() {
-
- let colorStyle = {
- borderColor: this.props.widget.customProperties.border_color,
- backgroundColor: this.props.widget.customProperties.background_color,
- opacity: this.props.widget.customProperties.background_color_opacity,
- borderWidth: this.props.widget.customProperties.border_width + 'px'
- }
-
- return (
-
- { }
-
- );
- }
-}
+ return (
+
+ {}
+
+ );
+};
export default WidgetBox;
diff --git a/src/widget/widgets/button.js b/src/widget/widgets/button.js
deleted file mode 100644
index ed6e02d..0000000
--- a/src/widget/widgets/button.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Button } from 'react-bootstrap';
-import AppDispatcher from '../../common/app-dispatcher';
-
-class WidgetButton extends Component {
-
- constructor(props) {
- super(props);
-
- this.state = {
- pressed: props.widget.customProperties.pressed
- }
- }
-
- componentDidMount() {
- let widget = this.props.widget
- widget.customProperties.simStartedSendValue = false
- widget.customProperties.pressed = false
-
- AppDispatcher.dispatch({
- type: 'widgets/start-edit',
- token: this.props.token,
- data: widget
- });
- }
-
- componentDidUpdate() {
- // a simulaton was started, make an update
- if (this.props.widget.customProperties.simStartedSendValue) {
- // update widget, 'unpress' button at each simulation start
- let widget = this.props.widget
- widget.customProperties.simStartedSendValue = false
- widget.customProperties.pressed = false
- AppDispatcher.dispatch({
- type: 'widgets/start-edit',
- token: this.props.token,
- data: widget
- });
-
- // send value without changing widget
- this.props.onInputChanged(widget.customProperties.off_value, '', false, false);
- }
- }
-
- static getDerivedStateFromProps(props, state){
- return {
- pressed: props.widget.customProperties.pressed
- }
- }
-
- onPress(e) {
- if (e.button === 0 && !this.props.widget.customProperties.toggle) {
- this.valueChanged(this.props.widget.customProperties.on_value, true);
- }
- }
-
- onRelease(e) {
- if (e.button === 0) {
- let nextState = false;
- if (this.props.widget.customProperties.toggle) {
- nextState = !this.state.pressed;
- }
- this.valueChanged(nextState ? this.props.widget.customProperties.on_value : this.props.widget.customProperties.off_value, nextState);
- }
- }
-
- valueChanged(newValue, pressed) {
- if (this.props.onInputChanged) {
- this.props.onInputChanged(newValue, 'pressed', pressed, true);
- }
- }
-
- render() {
- let opacity = this.props.widget.customProperties.background_color_opacity
- const buttonStyle = {
- backgroundColor: this.props.widget.customProperties.background_color,
- borderColor: this.props.widget.customProperties.border_color,
- color: this.props.widget.customProperties.font_color,
- opacity: this.state.pressed ? (opacity + 1)/4 : opacity,
- };
-
- return (
-
-
-
- );
- }
-}
-
-export default WidgetButton;
diff --git a/src/widget/widgets/button.jsx b/src/widget/widgets/button.jsx
new file mode 100644
index 0000000..7dced13
--- /dev/null
+++ b/src/widget/widgets/button.jsx
@@ -0,0 +1,108 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState, useEffect } from 'react';
+import { Button } from 'react-bootstrap';
+import AppDispatcher from '../../common/app-dispatcher';
+
+const WidgetButton = (props) => {
+ const [pressed, setPressed] = useState(props.widget.customProperties.pressed);
+
+ useEffect(() => {
+ let widget = props.widget;
+ widget.customProperties.simStartedSendValue = false;
+ widget.customProperties.pressed = false;
+
+ AppDispatcher.dispatch({
+ type: 'widgets/start-edit',
+ token: props.token,
+ data: widget
+ });
+
+ // Effect cleanup
+ return () => {
+ // Clean up if needed
+ };
+ }, [props.token, props.widget]);
+
+ useEffect(() => {
+ if (props.widget.customProperties.simStartedSendValue) {
+ let widget = props.widget;
+ widget.customProperties.simStartedSendValue = false;
+ widget.customProperties.pressed = false;
+ AppDispatcher.dispatch({
+ type: 'widgets/start-edit',
+ token: props.token,
+ data: widget
+ });
+
+ props.onInputChanged(widget.customProperties.off_value, '', false, false);
+ }
+ }, [props, setPressed]);
+
+ useEffect(() => {
+ setPressed(props.widget.customProperties.pressed);
+ }, [props.widget.customProperties.pressed]);
+
+ const onPress = (e) => {
+ if (e.button === 0 && !props.widget.customProperties.toggle) {
+ valueChanged(props.widget.customProperties.on_value, true);
+ }
+ };
+
+ const onRelease = (e) => {
+ if (e.button === 0) {
+ let nextState = false;
+ if (props.widget.customProperties.toggle) {
+ nextState = !pressed;
+ }
+ valueChanged(nextState ? props.widget.customProperties.on_value : props.widget.customProperties.off_value, nextState);
+ }
+ };
+
+ const valueChanged = (newValue, newPressed) => {
+ if (props.onInputChanged) {
+ props.onInputChanged(newValue, 'pressed', newPressed, true);
+ }
+ setPressed(newPressed);
+ };
+
+ let opacity = props.widget.customProperties.background_color_opacity;
+ const buttonStyle = {
+ backgroundColor: props.widget.customProperties.background_color,
+ borderColor: props.widget.customProperties.border_color,
+ color: props.widget.customProperties.font_color,
+ opacity: pressed ? (opacity + 1) / 4 : opacity,
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default WidgetButton;
diff --git a/src/widget/widgets/custom-action.js b/src/widget/widgets/custom-action.js
deleted file mode 100644
index cdd8078..0000000
--- a/src/widget/widgets/custom-action.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { Button } from 'react-bootstrap';
-import Icon from '../../common/icon';
-import ICStore from '../../ic/ic-store';
-import AppDispatcher from '../../common/app-dispatcher';
-
-class WidgetCustomAction extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- ic: null
- };
- }
-
- static getStores() {
- return [ ICStore ];
- }
-
- static getDerivedStateFromProps(props, state){
- if(props.widget.signalIDs.length === 0){
- return null;
- }
-
- return{
- ic: ICStore.getState().find(s => s.id === props.icIDs[0]),
- sessionToken: localStorage.getItem("token")
- };
- }
-
- onClick() {
- AppDispatcher.dispatch({
- type: 'ics/start-action',
- ic: this.state.ic,
- data: this.props.widget.customProperties.actions,
- token: this.state.sessionToken
- });
- }
-
- render() {
- return
-
-
;
- }
-}
-
-export default WidgetCustomAction;
diff --git a/src/widget/widgets/custom-action.jsx b/src/widget/widgets/custom-action.jsx
new file mode 100644
index 0000000..1073249
--- /dev/null
+++ b/src/widget/widgets/custom-action.jsx
@@ -0,0 +1,118 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+import React, { useState, useEffect } from "react";
+import { Button } from "react-bootstrap";
+import Icon from "../../common/icon";
+import ICStore from "../../ic/ic-store";
+import AppDispatcher from "../../common/app-dispatcher";
+
+const WidgetCustomAction = (props) => {
+ const [ic, setIC] = useState(null);
+ const [sessionToken, setSessionToken] = useState(
+ localStorage.getItem("token")
+ );
+
+ useEffect(() => {
+ const handleStoresChanged = () => {
+ if (props.widget.signalIDs.length === 0) {
+ setIC(null);
+ return;
+ }
+
+ const newIC = ICStore.getState().find((s) => s.id === props.icIDs[0]);
+ setIC(newIC);
+ };
+
+ // Subscribe to store changes
+ const unsubscribe = ICStore.subscribe(handleStoresChanged);
+ handleStoresChanged(); // Also call it to set initial state
+
+ return () => {
+ unsubscribe(); // Clean up the subscription when the component is unmounted
+ };
+ }, [props.widget.signalIDs, props.icIDs]);
+
+ const onClick = () => {
+ AppDispatcher.dispatch({
+ type: "ics/start-action",
+ ic: ic,
+ data: props.widget.customProperties.actions,
+ token: sessionToken,
+ });
+ };
+
+ return (
+
;
+// }
+// }
+
+// export default WidgetCustomAction;
diff --git a/src/widget/widgets/html.js b/src/widget/widgets/html.jsx
similarity index 80%
rename from src/widget/widgets/html.js
rename to src/widget/widgets/html.jsx
index e5c18a0..1f3774f 100644
--- a/src/widget/widgets/html.js
+++ b/src/widget/widgets/html.jsx
@@ -15,12 +15,16 @@
* along with VILLASweb. If not, see .
******************************************************************************/
-import React from 'react';
+import React from "react";
-class WidgetHTML extends React.Component {
- render() {
- return
- }
-}
+const WidgetHTML = (props) => {
+ return (
+
+ );
+};
export default WidgetHTML;
diff --git a/src/widget/widgets/icstatus.js b/src/widget/widgets/icstatus.js
deleted file mode 100644
index 2bb9d9b..0000000
--- a/src/widget/widgets/icstatus.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-import { Badge } from 'react-bootstrap';
-import { stateLabelStyle } from "../../ic/ics";
-import AppDispatcher from '../../common/app-dispatcher';
-
-
-class WidgetICstatus extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- sessionToken: localStorage.getItem("token")
- };
- }
-
- componentDidMount() {
- // Start timer for periodic refresh
- this.timer = window.setInterval(() => this.refresh(), 3000);
- }
-
- componentWillUnmount() {
- window.clearInterval(this.timer);
- }
-
- refresh() {
- if (this.props.ics) {
- this.props.ics.forEach(ic => {
- let icID = parseInt(ic.id, 10);
- AppDispatcher.dispatch({
- type: 'ics/start-load',
- data: icID,
- token: this.state.sessionToken,
- });
- })
- }
- }
-
- render() {
- let badges = []
- let checkedICs = []
- if (this.props.widget) {
- checkedICs = this.props.widget.customProperties.checkedIDs
- }
- if (this.props.ics && checkedICs) {
- this.props.ics.forEach(ic => {
- if (!checkedICs.includes(ic.id)) {
- return
- }
- let badgeStyle = stateLabelStyle(ic.state, ic)
- badges.push(
- {ic.name + ": " + ic.state})
- })
- }
-
- return (
{badges}
);
- }
-}
-
-export default WidgetICstatus;
diff --git a/src/widget/widgets/icstatus.jsx b/src/widget/widgets/icstatus.jsx
new file mode 100644
index 0000000..19b7dba
--- /dev/null
+++ b/src/widget/widgets/icstatus.jsx
@@ -0,0 +1,71 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState, useEffect } from "react";
+import { Badge } from "react-bootstrap";
+import { stateLabelStyle } from "../../ic/ics";
+import AppDispatcher from "../../common/app-dispatcher";
+
+const WidgetICstatus = (props) => {
+ const [sessionToken, setSessionToken] = useState(
+ localStorage.getItem("token")
+ );
+
+ useEffect(() => {
+ // Function to refresh data
+ const refresh = () => {
+ if (props.ics) {
+ props.ics.forEach((ic) => {
+ let icID = parseInt(ic.id, 10);
+ AppDispatcher.dispatch({
+ type: "ics/start-load",
+ data: icID,
+ token: sessionToken,
+ });
+ });
+ }
+ };
+
+ // Start timer for periodic refresh
+ const timer = window.setInterval(() => refresh(), 3000);
+
+ // Cleanup function equivalent to componentWillUnmount
+ return () => {
+ window.clearInterval(timer);
+ };
+ }, [props.ics, sessionToken]);
+
+ let badges = [];
+ let checkedICs = props.widget ? props.widget.customProperties.checkedIDs : [];
+
+ if (props.ics && checkedICs) {
+ badges = props.ics
+ .filter((ic) => checkedICs.includes(ic.id))
+ .map((ic) => {
+ let badgeStyle = stateLabelStyle(ic.state, ic);
+ return (
+
+ {ic.name + ": " + ic.state}
+
+ );
+ });
+ }
+
+ return
{badges}
;
+};
+
+export default WidgetICstatus;
diff --git a/src/widget/widgets/image.js b/src/widget/widgets/image.js
deleted file mode 100644
index f289324..0000000
--- a/src/widget/widgets/image.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-
-import AppDispatcher from '../../common/app-dispatcher';
-
-class WidgetImage extends React.Component {
-
- constructor(props) {
- super(props);
-
- this.state = {
- file: undefined,
- }
- }
-
- componentDidMount() {
- // Query the image referenced by the widget
- let widgetFile = this.props.widget.customProperties.file;
- if (widgetFile !== -1 && this.state.file === undefined) {
- AppDispatcher.dispatch({
- type: 'files/start-download',
- data: widgetFile,
- token: this.props.token
- });
- }
- }
-
- componentDidUpdate(prevProps: Readonly
- );
- }
-}
-
-export default WidgetImage;
diff --git a/src/widget/widgets/image.jsx b/src/widget/widgets/image.jsx
new file mode 100644
index 0000000..8b658d8
--- /dev/null
+++ b/src/widget/widgets/image.jsx
@@ -0,0 +1,78 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState, useEffect } from "react";
+import AppDispatcher from "../../common/app-dispatcher";
+
+const WidgetImage = (props) => {
+ const [file, setFile] = useState(undefined);
+
+ useEffect(() => {
+ let widgetFile = props.widget.customProperties.file;
+ if (widgetFile !== -1 && file === undefined) {
+ AppDispatcher.dispatch({
+ type: "files/start-download",
+ data: widgetFile,
+ token: props.token,
+ });
+ }
+ }, [file, props.token, props.widget.customProperties.file]);
+
+ useEffect(() => {
+ if (props.widget.customProperties.file === -1) {
+ props.widget.customProperties.update = false;
+ if (file !== undefined) setFile(undefined);
+ } else {
+ let foundFile = props.files.find(
+ (f) => f.id === parseInt(props.widget.customProperties.file, 10)
+ );
+ if (foundFile && props.widget.customProperties.update) {
+ props.widget.customProperties.update = false;
+ AppDispatcher.dispatch({
+ type: "files/start-download",
+ data: foundFile.id,
+ token: props.token,
+ });
+ setFile(foundFile);
+ }
+ }
+ }, [props.widget.customProperties, props.files, props.token, file]);
+
+ const imageError = (e) => {
+ console.error("Image error:", e);
+ };
+
+ let objectURL = file && file.objectURL ? file.objectURL : "";
+
+ return (
+
+ );
+};
export default WidgetLabel;
diff --git a/src/widget/widgets/lamp.js b/src/widget/widgets/lamp.js
deleted file mode 100644
index 43603e4..0000000
--- a/src/widget/widgets/lamp.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-
-
-class WidgetLamp extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- value: '',
- };
- }
-
- static getDerivedStateFromProps(props, state){
- if(props.widget.signalIDs.length === 0){
- return{ value: ''};
- }
-
- // get the signal with the selected signal ID
- let signalID = props.widget.signalIDs[0];
- let signal = props.signals.filter(s => s.id === signalID)
-
- if(signal.length>0) {
- // determine ID of infrastructure component related to signal[0] (there is only one signal for a lamp widget)
- let icID = props.icIDs[signal[0].id];
-
- // check if data available
- if (props.data == null
- || props.data[icID] == null
- || props.data[icID].output == null
- || props.data[icID].output.values == null) {
- return {value: ''};
- }
-
- // check if value has changed
- const data = props.data[icID].output.values[signal[0].index];
- if (data != null && Number(state.value) !== signal[0].scalingFactor * data[data.length - 1].y) {
- return {value: signal[0].scalingFactor * data[data.length - 1].y};
- }
- }
-
- return null;
- }
-
- render() {
-
- let color;
- let opacity;
-
- if (Number(this.state.value) > Number(this.props.widget.customProperties.threshold)){
- color = this.props.widget.customProperties.on_color;
- opacity = this.props.widget.customProperties.on_color_opacity;
- }
- else{
- color = this.props.widget.customProperties.off_color;
- opacity = this.props.widget.customProperties.off_color_opacity;
- }
-
- let style = {
- backgroundColor: color,
- opacity: opacity
- }
-
- return (
-
- );
- }
-}
-
-export default WidgetLamp;
diff --git a/src/widget/widgets/lamp.jsx b/src/widget/widgets/lamp.jsx
new file mode 100644
index 0000000..c44cdd0
--- /dev/null
+++ b/src/widget/widgets/lamp.jsx
@@ -0,0 +1,72 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState, useEffect } from 'react';
+
+const WidgetLamp = (props) => {
+ const [value, setValue] = useState('');
+
+ useEffect(() => {
+ if(props.widget.signalIDs.length === 0){
+ setValue('');
+ return;
+ }
+
+ let signalID = props.widget.signalIDs[0];
+ let signal = props.signals.find(s => s.id === signalID);
+
+ if(signal) {
+ let icID = props.icIDs[signal.id];
+
+ if (!(props.data &&
+ props.data[icID] &&
+ props.data[icID].output &&
+ props.data[icID].output.values)) {
+ setValue('');
+ return;
+ }
+
+ const data = props.data[icID].output.values[signal.index];
+ if(data) {
+ const newValue = String(signal.scalingFactor * data[data.length - 1].y);
+ if (value !== newValue) {
+ setValue(newValue);
+ }
+ }
+ }
+ }, [props.widget.signalIDs, props.signals, props.icIDs, props.data, value]);
+
+ let color, opacity;
+ if (Number(value) > Number(props.widget.customProperties.threshold)) {
+ color = props.widget.customProperties.on_color;
+ opacity = props.widget.customProperties.on_color_opacity;
+ } else {
+ color = props.widget.customProperties.off_color;
+ opacity = props.widget.customProperties.off_color_opacity;
+ }
+
+ let style = {
+ backgroundColor: color,
+ opacity: opacity
+ };
+
+ return (
+
+ );
+};
+
+export default WidgetLamp;
\ No newline at end of file
diff --git a/src/widget/widgets/line.js b/src/widget/widgets/line.js
deleted file mode 100644
index 2250907..0000000
--- a/src/widget/widgets/line.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-
-class WidgetLine extends Component {
- // WidgetLine is newly created when widget props are changed and saved
- constructor(props) {
- super(props);
- this.illustrateDuringEdit = this.illustrateDuringEdit.bind(this);
-
- this.state = {
- width: 0,
- height: 0,
- editing: false
- }
- }
-
- // needed to update the looks of the line in edit mode
- illustrateDuringEdit(newwidth, newheight) {
- this.setState({width: newwidth, height: newheight, editing: true});
- }
-
- render() {
- let rotation = this.props.widget.customProperties.rotation;
- let rad = rotation * (Math.PI / 180);
-
- // get the dimensions either from props (saved widget)
- // or from the state (widget in edit mode)
- let width = this.props.widget.width;
- let height = this.props.widget.height;
-
- if (this.state.editing) {
- width = this.state.width;
- height = this.state.height;
- }
-
- let length = width;
- rotation = Math.abs(parseInt(rotation,10));
- if(rotation % 90 === 0 && (rotation/90) % 2 === 1){
- length = height;
- }
-
- // calculate line coordinates (in percent)
- const x1 = width * 0.5 - 0.5 * Math.cos(rad) * length;
- const x1p = '' + Math.round(100 * x1 / width) + '%';
-
- const x2 = width * 0.5 + 0.5 * Math.cos(rad) * length;
- const x2p = '' + Math.round(100 * x2/width) + '%';
-
- const y1 = height * 0.5 + 0.5 * Math.sin(rad) * length;
- const y1p = '' + Math.round(100 * y1/height) + '%';
-
- const y2 = height * 0.5 - 0.5 * Math.sin(rad) * length;
- const y2p = '' + Math.round(100 * y2/height) + '%';
-
-
- const lineStyle = {
- stroke: '' + this.props.widget.customProperties.border_color,
- strokeWidth: '' + this.props.widget.customProperties.border_width + 'px'
- };
-
- return ;
- }
-}
-
-export default WidgetLine;
diff --git a/src/widget/widgets/line.jsx b/src/widget/widgets/line.jsx
new file mode 100644
index 0000000..d1f6648
--- /dev/null
+++ b/src/widget/widgets/line.jsx
@@ -0,0 +1,70 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState } from "react";
+
+const WidgetLine = (props) => {
+ const [dimensions, setDimensions] = useState({
+ width: props.widget.width || 0,
+ height: props.widget.height || 0,
+ editing: false,
+ });
+
+ const illustrateDuringEdit = (newWidth, newHeight) => {
+ setDimensions({ width: newWidth, height: newHeight, editing: true });
+ };
+
+ // Assuming illustrateDuringEdit may be called from outside to update the dimensions.
+ // If not, you can remove this line.
+ props.illustrateDuringEditRef &&
+ props.illustrateDuringEditRef(illustrateDuringEdit);
+
+ let { rotation } = props.widget.customProperties;
+ let rad = rotation * (Math.PI / 180);
+ let length = dimensions.editing ? dimensions.width : props.widget.width;
+
+ rotation = Math.abs(parseInt(rotation, 10));
+ if (rotation % 90 === 0 && (rotation / 90) % 2 === 1) {
+ length = dimensions.editing ? dimensions.height : props.widget.height;
+ }
+
+ // calculate line coordinates (in percent)
+ const x1 = length * 0.5 - 0.5 * Math.cos(rad) * length;
+ const x1p = `${Math.round((100 * x1) / length)}%`;
+
+ const x2 = length * 0.5 + 0.5 * Math.cos(rad) * length;
+ const x2p = `${Math.round((100 * x2) / length)}%`;
+
+ const y1 = length * 0.5 + 0.5 * Math.sin(rad) * length;
+ const y1p = `${Math.round((100 * y1) / length)}%`;
+
+ const y2 = length * 0.5 - 0.5 * Math.sin(rad) * length;
+ const y2p = `${Math.round((100 * y2) / length)}%`;
+
+ const lineStyle = {
+ stroke: props.widget.customProperties.border_color,
+ strokeWidth: `${props.widget.customProperties.border_width}px`,
+ };
+
+ return (
+
+ );
+};
+
+export default WidgetLine;
diff --git a/src/widget/widgets/plot.js b/src/widget/widgets/plot.js
deleted file mode 100644
index 27041b0..0000000
--- a/src/widget/widgets/plot.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React from 'react';
-
-import Plot from '../widget-plot/plot';
-import PlotLegend from '../widget-plot/plot-legend';
-
-class WidgetPlot extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- data: [],
- signals: []
- };
- }
-
-
- static getDerivedStateFromProps(props, state){
-
- let intersection = []
- let data = [];
- let signalID, sig;
- for (signalID of props.widget.signalIDs) {
- for (sig of props.signals) {
- if (signalID === sig.id) {
- intersection.push(sig);
-
- // sig is a selected signal, get data
- // determine ID of infrastructure component related to signal (via config)
- let icID = props.icIDs[sig.id]
-
- // distinguish between input and output signals
- if (sig.direction === "out") {
- if (props.data[icID] != null && props.data[icID].output != null && props.data[icID].output.values != null) {
- if (props.data[icID].output.values[sig.index] !== undefined) {
- let values = props.data[icID].output.values[sig.index];
- if(sig.scalingFactor !== 1) {
- let scaledValues = JSON.parse(JSON.stringify(values));
- for (let i=0; i< scaledValues.length; i++){
- scaledValues[i].y = scaledValues[i].y * sig.scalingFactor;
- }
- data.push(scaledValues);
- } else {
- data.push(values);
- }
- }
- }
- } else if (sig.direction === "in") {
- if (props.data[icID] != null && props.data[icID].input != null && props.data[icID].input.values != null) {
- if (props.data[icID].input.values[sig.index] !== undefined) {
- let values = props.data[icID].output.values[sig.index];
- if(sig.scalingFactor !== 1) {
- let scaledValues = JSON.parse(JSON.stringify(values));
- for (let i=0; i< scaledValues.length; i++){
- scaledValues[i].y = scaledValues[i].y * sig.scalingFactor;
- }
- data.push(scaledValues);
- } else {
- data.push(values);
- }
- }
- }
- }
- } // sig is selected signal
- } // loop over props.signals
- } // loop over selected signals
-
- return {signals: intersection, data: data}
-
- }
-
- //do we need this function?
- scaleData(data, scaleFactor){
- // data is an array of value pairs x,y
- }
-
- render() {
- return
-
-
-
-
-
;
- }
-}
-
-export default WidgetPlot;
diff --git a/src/widget/widgets/plot.jsx b/src/widget/widgets/plot.jsx
new file mode 100644
index 0000000..74d5a16
--- /dev/null
+++ b/src/widget/widgets/plot.jsx
@@ -0,0 +1,96 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+
+import React, { useState, useEffect } from "react";
+import Plot from "../widget-plot/plot";
+import PlotLegend from "../widget-plot/plot-legend";
+
+const WidgetPlot = (props) => {
+ const [data, setData] = useState([]);
+ const [signals, setSignals] = useState([]);
+
+ useEffect(() => {
+ const intersection = [];
+ const plotData = [];
+ let signalID, sig;
+ for (signalID of props.widget.signalIDs) {
+ for (sig of props.signals) {
+ if (signalID === sig.id) {
+ intersection.push(sig);
+
+ // Signal is a selected signal, get data
+ let icID = props.icIDs[sig.id];
+ let values = null;
+
+ if (
+ sig.direction === "out" &&
+ props.data[icID]?.output?.values?.[sig.index] !== undefined
+ ) {
+ values = props.data[icID].output.values[sig.index];
+ } else if (
+ sig.direction === "in" &&
+ props.data[icID]?.input?.values?.[sig.index] !== undefined
+ ) {
+ values = props.data[icID].input.values[sig.index];
+ }
+
+ if (values) {
+ if (sig.scalingFactor !== 1) {
+ values = values.map((v) => ({
+ ...v,
+ y: v.y * sig.scalingFactor,
+ }));
+ }
+ plotData.push(values);
+ }
+ }
+ }
+ }
+
+ setData(plotData);
+ setSignals(intersection);
+ }, [props.widget.signalIDs, props.signals, props.icIDs, props.data]);
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default WidgetPlot;
diff --git a/src/widget/widgets/slider.js b/src/widget/widgets/slider.js
deleted file mode 100644
index ea7be28..0000000
--- a/src/widget/widgets/slider.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { format } from 'd3';
-import classNames from 'classnames';
-import Slider from 'rc-slider';
-import 'rc-slider/assets/index.css';
-import AppDispatcher from '../../common/app-dispatcher';
-
-
-class WidgetSlider extends Component {
-
- static get OrientationTypes() {
- return ({
- HORIZONTAL: {value: 0, name: 'Horizontal'},
- VERTICAL: {value: 1, name: 'Vertical'}
- })
- }
-
- constructor(props) {
- super(props);
-
- this.state = {
- unit: '',
- value: '',
- };
- }
-
- componentDidMount() {
- let widget = this.props.widget
- widget.customProperties.simStartedSendValue = false
- AppDispatcher.dispatch({
- type: 'widgets/start-edit',
- token: this.props.token,
- data: widget
- });
- }
-
- componentDidUpdate() {
- // a simulaton was started, make an update
- if (this.props.widget.customProperties.simStartedSendValue) {
- let widget = this.props.widget
- widget.customProperties.simStartedSendValue = false
- AppDispatcher.dispatch({
- type: 'widgets/start-edit',
- token: this.props.token,
- data: widget
- });
-
- // send value without changing widget
- this.props.onInputChanged(widget.customProperties.value , '', '', false);
- }
- }
-
- static getDerivedStateFromProps(props, state){
-
- let value = ''
- let unit = ''
-
- if(props.widget.customProperties.hasOwnProperty('value') && props.widget.customProperties.value !== state.value){
- // set value to customProperties.value if this property exists and the value is different from current state
- value = Number(props.widget.customProperties.value);
- } else if (state.value === '') {
- value = 0.0;
- }
-
- // Update unit (assuming there is exactly one signal for this widget)
- if (props.widget.signalIDs.length > 0) {
- let signalID = props.widget.signalIDs[0];
- let signal = props.signals.find(sig => sig.id === signalID);
- if (signal !== undefined) {
- unit = signal.unit;
- }
- }
-
- if (unit !== '' && value !== ''){
- // unit and value have changed
- return {unit: unit, value: value};
- } else if (unit !== ''){
- // only unit has changed
- return {unit: unit}
- } else if (value !== ''){
- // only value has changed
- return {value: value}
- } else {
- // nothing has changed
- return null
- }
- }
-
- valueIsChanging(newValue) {
- this.props.widget.customProperties.value = newValue;
- if (this.props.widget.customProperties.continous_update)
- this.valueChanged(newValue, false);
-
- this.setState({ value: newValue });
- }
-
- valueChanged(newValue, isFinalChange) {
- if (this.props.onInputChanged) {
- this.props.onInputChanged(newValue, 'value', newValue, isFinalChange);
- }
- }
-
- render() {
-
- let isVertical = this.props.widget.customProperties.orientation === WidgetSlider.OrientationTypes.VERTICAL.value;
- let fields = {
- name: this.props.widget.name,
- control: this.valueIsChanging(v) }
- onAfterChange={ (v) => this.valueChanged(v, true)
- }/>,
- value: { format('.2f')(Number.parseFloat(this.state.value)) },
- unit: { this.state.unit }
- }
-
- let widgetClasses = classNames({
- 'slider-widget': true,
- 'full': true,
- 'vertical': isVertical,
- 'horizontal': !isVertical
- });
-
- return (
- <>
-
+ >
+ );
+};
+
+WidgetSlider.OrientationTypes = {
+ HORIZONTAL: { value: 0, name: "Horizontal" },
+ VERTICAL: { value: 1, name: "Vertical" },
+};
+
+export default WidgetSlider;
diff --git a/src/widget/widgets/table.js b/src/widget/widgets/table.js
deleted file mode 100644
index 7e0f8d0..0000000
--- a/src/widget/widgets/table.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * This file is part of VILLASweb.
- *
- * VILLASweb is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * VILLASweb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with VILLASweb. If not, see .
- ******************************************************************************/
-
-import React, { Component } from 'react';
-import { format } from 'd3';
-
-import { Table, DataColumn } from '../../common/table';
-
-class WidgetTable extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- rows: [],
- };
- }
-
- static getDerivedStateFromProps(props, state){
-
- let rows = [];
- let signalID, sig;
- for (signalID of props.widget.signalIDs) {
- for (sig of props.signals) {
- if (signalID === sig.id) {
- // sig is a selected signal, get data
- // determine ID of infrastructure component related to signal (via config)
- let icID = props.icIDs[sig.id]
-
- // distinguish between input and output signals
- if (sig.direction === "out") {
- if (props.data[icID] != null && props.data[icID].output != null && props.data[icID].output.values != null) {
- if (props.data[icID].output.values[sig.index] !== undefined) {
- let data = props.data[icID].output.values[sig.index];
- rows.push({
- name: sig.name,
- unit: sig.unit,
- value: data[data.length - 1].y * sig.scalingFactor,
- scalingFactor: sig.scalingFactor
- });
-
- } else {
- // no data available
- rows.push({
- name: sig.name,
- unit: sig.unit,
- value: NaN,
- scalingFactor: sig.scalingFactor
- })
- }
- }
- } else if (sig.direction === "in") {
- if (props.data[icID] != null && props.data[icID].input != null && props.data[icID].input.values != null) {
- if (props.data[icID].input.values[sig.index] !== undefined) {
- let data = props.data[icID].input.values[sig.index];
- rows.push({
- name: sig.name,
- unit: sig.unit,
- value: data[data.length - 1].y * sig.scalingFactor,
- scalingFactor: sig.scalingFactor
- });
- } else {
- // no data available
- rows.push({
- name: sig.name,
- unit: sig.unit,
- value: NaN,
- scalingFactor: sig.scalingFactor
- })
- }
- }
- }
- } // sig is selected signal
- } // loop over props.signals
- } // loop over selected signals
-
- return {rows: rows}
-
- }
-
- render() {
-
-
- let showScalingFactor;
- if (this.props.widget.customProperties.showScalingFactor !== undefined){ // this line ensures backwards compatibility with older versions of VILLASweb
- showScalingFactor = this.props.widget.customProperties.showScalingFactor;
- } else {
- showScalingFactor = true;
- }
-
- let rows = this.state.rows;
-
- if(rows.length === 0){
- rows.push({
- name: "no entries"
- })
- }
-
- let columns = [
- ,
- ,
- ];
-
- let nextKey = 3;
- if (showScalingFactor) {
- columns.push();
- nextKey++;
- }
- if (this.props.widget.customProperties.showUnit) {
- columns.push();
- }
-
- return (
-
-
- { columns }
-
-
- );
- }
-}
-
-export default WidgetTable;
diff --git a/src/widget/widgets/table.jsx b/src/widget/widgets/table.jsx
new file mode 100644
index 0000000..e87fce7
--- /dev/null
+++ b/src/widget/widgets/table.jsx
@@ -0,0 +1,111 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see .
+ ******************************************************************************/
+import React, { useState, useEffect } from "react";
+import { format } from "d3";
+import { Table, DataColumn } from "../../common/table";
+
+const WidgetTable = (props) => {
+ const [rows, setRows] = useState([]);
+
+ useEffect(() => {
+ let newRows = [];
+ let signalID, sig;
+ for (signalID of props.widget.signalIDs) {
+ for (sig of props.signals) {
+ if (signalID === sig.id) {
+ let icID = props.icIDs[sig.id];
+
+ let direction = sig.direction === "out" ? "output" : "input";
+ if (
+ props.data[icID] &&
+ props.data[icID][direction] &&
+ props.data[icID][direction].values
+ ) {
+ if (props.data[icID][direction].values[sig.index] !== undefined) {
+ let data = props.data[icID][direction].values[sig.index];
+ newRows.push({
+ name: sig.name,
+ unit: sig.unit,
+ value: data[data.length - 1].y * sig.scalingFactor,
+ scalingFactor: sig.scalingFactor,
+ });
+ } else {
+ newRows.push({
+ name: sig.name,
+ unit: sig.unit,
+ value: NaN,
+ scalingFactor: sig.scalingFactor,
+ });
+ }
+ }
+ }
+ }
+ }
+
+ if (newRows.length === 0) {
+ newRows.push({ name: "no entries" });
+ }
+
+ setRows(newRows);
+ }, [props.widget.signalIDs, props.signals, props.icIDs, props.data]);
+
+ let showScalingFactor =
+ props.widget.customProperties.showScalingFactor !== undefined
+ ? props.widget.customProperties.showScalingFactor
+ : true;
+
+ let columns = [
+ ,
+ ,
+ ];
+
+ let nextKey = 3;
+ if (showScalingFactor) {
+ columns.push(
+
+ );
+ nextKey++;
+ }
+ if (props.widget.customProperties.showUnit) {
+ columns.push();
+ }
+
+ return (
+