diff --git a/package.json b/package.json index 1e8cd18a..b666cf9b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "react-dnd": "^14.0.5", "react-dnd-html5-backend": "^14.1.0", "react-dom": "^17.0.2", - "react-fullscreenable": "^2.5.1-0", "react-json-view": "^1.21.3", "react-notification-system": "^0.4.0", "react-redux": "^7.2.8", @@ -52,7 +51,6 @@ "react-router-dom": "^5.3.1", "react-svg-pan-zoom": "^3.11.0", "react-syntax-highlighter": "^15.5.0", - "react-trafficlight": "^5.2.1", "superagent": "^7.1.2", "swagger-client": "3.19.10", "swagger-ui-react": "4.13.0", diff --git a/src/app.js b/src/app.js index ab9c4a71..a2308126 100644 --- a/src/app.js +++ b/src/app.js @@ -35,6 +35,7 @@ import Dashboard from "./pages/dashboards/dashboard.jsx"; import Account from "./pages/account/account"; import "./styles/app.css"; import "./styles/login.css"; +import "./styles/Trafficlight.css"; import branding from "./branding/branding"; import Logout from "./pages/login/logout"; import Infrastructure from "./pages/infrastructure/infrastructure"; @@ -65,7 +66,6 @@ const App = () => { console.log("APP redirecting to logout/login"); return ; } else { - console.log("APP rendering app"); const pages = branding.values.pages; diff --git a/src/pages/dashboards/dashboard-layout.js b/src/pages/dashboards/dashboard-layout.js index 69e5a2c5..93735ed9 100644 --- a/src/pages/dashboards/dashboard-layout.js +++ b/src/pages/dashboards/dashboard-layout.js @@ -27,7 +27,6 @@ import { useUpdateWidgetMutation, } from "../../store/apiSlice"; import { sessionToken } from "../../localStorage"; -import Fullscreenable from "react-fullscreenable"; import DashboardButtonGroup from "./grid/dashboard-button-group"; import Widget from "./widget/widget"; import WidgetContainer from "./widget/widget-container"; @@ -38,6 +37,7 @@ import EditWidgetDialog from "./widget/edit-widget/edit-widget"; import EditSignalMappingDialog from "../scenarios/dialogs/edit-signal-mapping"; import classNames from "classnames"; import { Spinner } from "react-bootstrap"; +import useFullscreen from "../../utils/fullscreen.js"; //this component handles the UI of the dashboard const DashboardLayout = ({ isFullscreen, toggleFullscreen }) => { @@ -451,4 +451,19 @@ const DashboardLayout = ({ isFullscreen, toggleFullscreen }) => { ); }; -export default Fullscreenable()(DashboardLayout); +//wrap into fullscreen +const DashboardFullscreenable = () => { + const { fullscreenTargetRef, isFullscreen, toggleFullscreen } = + useFullscreen(); + + return ( +
+ +
+ ); +}; + +export default DashboardFullscreenable; diff --git a/src/pages/dashboards/dashboard-old.js b/src/pages/dashboards/dashboard-old.js index 50910304..520781c3 100644 --- a/src/pages/dashboards/dashboard-old.js +++ b/src/pages/dashboards/dashboard-old.js @@ -18,7 +18,6 @@ import React, { useState, useEffect, useCallback, useRef, act } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useParams } from "react-router-dom"; -import Fullscreenable from "react-fullscreenable"; import classNames from "classnames"; import "react-contexify/dist/ReactContexify.min.css"; import EditWidget from "./widget/edit-widget/edit-widget"; @@ -29,6 +28,7 @@ import DashboardButtonGroup from "./grid/dashboard-button-group"; import IconToggleButton from "../../common/buttons/icon-toggle-button"; import WidgetContainer from "./widget/widget-container"; import Widget from "./widget/widget-old"; +import useFullscreen from "../../utils/fullscreen.js"; import { connectWebSocket, disconnect } from "../../store/websocketSlice"; @@ -615,4 +615,19 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { ); }; -export default Fullscreenable()(Dashboard); +//wrap into fullscreen +const DashboardFullscreenable = () => { + const { fullscreenTargetRef, isFullscreen, toggleFullscreen } = + useFullscreen(); + + return ( +
+ +
+ ); +}; + +export default DashboardFullscreenable; diff --git a/src/pages/dashboards/dashboard.jsx b/src/pages/dashboards/dashboard.jsx index 8daafbf1..06250d1f 100644 --- a/src/pages/dashboards/dashboard.jsx +++ b/src/pages/dashboards/dashboard.jsx @@ -18,7 +18,6 @@ import React, { useState, useEffect, useCallback, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useParams } from "react-router-dom"; -import Fullscreenable from "react-fullscreenable"; import "react-contexify/dist/ReactContexify.min.css"; import EditWidget from "./widget/edit-widget/edit-widget"; import EditSignalMappingDialog from "./dialogs/edit-signal-mapping.jsx"; @@ -29,6 +28,7 @@ import IconToggleButton from "../../common/buttons/icon-toggle-button"; import WidgetContainer from "./widget/widget-container"; import Widget from "./widget/widget.jsx"; import EditFilesDialog from "./dialogs/edit-files-dialog.jsx"; +import useFullscreen from "../../utils/fullscreen.js"; import { disconnect } from "../../store/websocketSlice"; import { useDashboardData } from "./hooks/use-dashboard-data.js"; @@ -609,4 +609,19 @@ const Dashboard = ({ isFullscreen, toggleFullscreen }) => { ); }; -export default Fullscreenable()(Dashboard); +//wrap into fullscreen +const DashboardFullscreenable = () => { + const { fullscreenTargetRef, isFullscreen, toggleFullscreen } = + useFullscreen(); + + return ( +
+ +
+ ); +}; + +export default DashboardFullscreenable; diff --git a/src/pages/dashboards/widget/widget-time-offset/trafficlight.jsx b/src/pages/dashboards/widget/widget-time-offset/trafficlight.jsx new file mode 100644 index 00000000..5c7497c8 --- /dev/null +++ b/src/pages/dashboards/widget/widget-time-offset/trafficlight.jsx @@ -0,0 +1,64 @@ +/** + * 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 { forwardRef } from "react"; + +const TrafficLight = ({ + isHorizontal, + height, + isRedOn, + isYellowOn, + isGreenOn, +}) => { + const lamps = [ + { color: "red", on: isRedOn }, + { color: "yellow", on: isYellowOn }, + { color: "green", on: isGreenOn }, + ]; + + const width = height * 2.5; + const lampGap = height * 0.15; + const lampSize = ((isHorizontal ? width : height) - 4 * lampGap) / 3.5; + const borderRadius = height * 0.2; + + return ( +
+ {lamps.map((lamp, i) => ( +
+ ))} +
+ ); +}; + +export default TrafficLight; diff --git a/src/pages/dashboards/widget/widgets/time-offset.jsx b/src/pages/dashboards/widget/widgets/time-offset.jsx index e5f3cd5c..2881b215 100644 --- a/src/pages/dashboards/widget/widgets/time-offset.jsx +++ b/src/pages/dashboards/widget/widgets/time-offset.jsx @@ -15,7 +15,7 @@ * along with VILLASweb. If not, see . ******************************************************************************/ import React, { useState, useEffect } from "react"; -import TrafficLight from "react-trafficlight"; +import TrafficLight from "../widget-time-offset/trafficlight"; import { OverlayTrigger, Tooltip } from "react-bootstrap"; function WidgetTimeOffset(props) { @@ -79,7 +79,15 @@ function WidgetTimeOffset(props) { setState((prevState) => ({ ...prevState, ...derivedState })); // eslint-disable-next-line - }, [props.widget, props.ics, props.websockets, props.data]); + }, [ + props.widget.customProperties.icID, + props.widget.customProperties.showOffset, + props.widget.customProperties.threshold_red, + props.widget.customProperties.threshold_yellow, + props.data && state.icID ? props.data[state.icID]?.output?.timestamp : null, + props.websockets?.length, + props.ics?.length, + ]); const { timeOffset, icID, icName, websocketOpen } = state; @@ -123,20 +131,20 @@ function WidgetTimeOffset(props) { } > 0 && timeOffset < props.widget.customProperties.threshold_yellow && websocketOpen diff --git a/src/styles/Trafficlight.css b/src/styles/Trafficlight.css new file mode 100644 index 00000000..aecd3df1 --- /dev/null +++ b/src/styles/Trafficlight.css @@ -0,0 +1,53 @@ +/** + * 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 . + ******************************************************************************/ + +.traffic-light { + box-sizing: border-box; + background-color: #000; + border-radius: 16px; + display: flex; + align-items: center; + justify-content: center; +} + +.traffic-light.horizontal { + flex-direction: row; +} +.traffic-light.vertical { + flex-direction: column; +} + +.lamp { + border-radius: 50%; + box-shadow: inset 0 0 3px #000; +} + +.lamp.red.on { + background: #cc3232; + box-shadow: 0 0 6px #cc3232, 0 0 12px #cc3232, 0 0 24px #cc3232; +} +.lamp.yellow.on { + background: #e7b416; + box-shadow: 0 0 6px #e7b416, 0 0 12px #e7b416, 0 0 24px #e7b416; +} +.lamp.green.on { + background: #2dc937; + box-shadow: 0 0 6px #2dc937, 0 0 12px #2dc937, 0 0 24px #2dc937; +} +.off { + background: grey; +} diff --git a/src/utils/fullscreen.js b/src/utils/fullscreen.js new file mode 100644 index 00000000..12ca2251 --- /dev/null +++ b/src/utils/fullscreen.js @@ -0,0 +1,54 @@ +/** + * 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 { useState, useEffect, useRef } from "react"; + +// this is essentially a wrapper around standart Fullscreen API + +const useFullscreen = () => { + const fullscreenTargetRef = useRef(null); + const [isFullscreen, setIsFullscreen] = useState(false); + + useEffect(() => { + const updateFullscreenState = () => + setIsFullscreen(!!document.fullscreenElement); + + document.addEventListener("fullscreenchange", updateFullscreenState); + document.addEventListener("webkitfullscreenchange", updateFullscreenState); + + return () => { + document.removeEventListener("fullscreenchange", updateFullscreenState); + document.removeEventListener( + "webkitfullscreenchange", + updateFullscreenState + ); + }; + }, []); + + const toggleFullscreen = () => { + if (isFullscreen) { + if (document.exitFullscreen) document.exitFullscreen(); + } else { + if (fullscreenTargetRef.current.requestFullscreen) + fullscreenTargetRef.current.requestFullscreen(); + } + }; + + return { fullscreenTargetRef, isFullscreen, toggleFullscreen }; +}; + +export default useFullscreen;