From bae40c3f5d595f76ee94ab39ed4529f8bbaa7bc6 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 06:06:10 +0200 Subject: [PATCH 01/17] 1241: Added screen status component --- src/components/screen/screen-form.jsx | 13 +- src/components/screen/screen-list.jsx | 17 +- src/components/screen/screen-status.jsx | 171 ++++++++++++++++++ src/components/screen/util/screen-columns.jsx | 28 ++- src/translations/da/common.json | 17 +- 5 files changed, 223 insertions(+), 23 deletions(-) create mode 100644 src/components/screen/screen-status.jsx diff --git a/src/components/screen/screen-form.jsx b/src/components/screen/screen-form.jsx index dc7bb20f..7f0b5fa3 100644 --- a/src/components/screen/screen-form.jsx +++ b/src/components/screen/screen-form.jsx @@ -20,6 +20,7 @@ import { import { displayError } from "../util/list/toast-component/display-toast"; import FormCheckbox from "../util/forms/form-checkbox"; import "./screen-form.scss"; +import ScreenStatus from "./screen-status"; /** * The screen form component. @@ -181,23 +182,14 @@ function ScreenForm({ {Object.prototype.hasOwnProperty.call(screen, "@id") && (

{t("bind-header")}

+ {screen?.screenUser && ( <> -
- - {t("already-bound")} - -
)} {!screen?.screenUser && ( <> -
- - {t("not-bound")} - -
{ setBindKey(target?.value); @@ -351,6 +343,7 @@ ScreenForm.propTypes = { screenUser: PropTypes.string, size: PropTypes.string, title: PropTypes.string, + status: PropTypes.shape({}), playlists: PropTypes.arrayOf( PropTypes.shape({ name: PropTypes.string, id: PropTypes.number }) ), diff --git a/src/components/screen/screen-list.jsx b/src/components/screen/screen-list.jsx index 3086f411..05c3391e 100644 --- a/src/components/screen/screen-list.jsx +++ b/src/components/screen/screen-list.jsx @@ -1,5 +1,6 @@ import { React, useEffect, useState, useContext } from "react"; import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; import UserContext from "../../context/user-context"; import List from "../util/list/list"; import { ScreenColumns } from "./util/screen-columns"; @@ -12,6 +13,7 @@ import { useGetV2ScreensQuery, useDeleteV2ScreensByIdMutation, useGetV2ScreensByIdScreenGroupsQuery, + api, } from "../../redux/api/api.generated.ts"; import { displaySuccess, @@ -110,21 +112,22 @@ function ScreenList() { setLoadingMessage(t("loading-messages.deleting-screen")); }; + // Error with retrieving list of screen + useEffect(() => { + if (screensGetError) { + displayError(t("error-messages.screens-load-error"), screensGetError); + } + }, [screensGetError]); + // The columns for the table. const columns = ScreenColumns({ handleDelete, apiCall: useGetV2ScreensByIdScreenGroupsQuery, infoModalRedirect: "/group/edit", infoModalTitle: t("info-modal.screen-in-groups"), + displayStatus: true, }); - // Error with retrieving list of screen - useEffect(() => { - if (screensGetError) { - displayError(t("error-messages.screens-load-error"), screensGetError); - } - }, [screensGetError]); - return ( <> { + if (status) { + const now = dayjs().startOf("minute").valueOf(); + + if (status?.clientMeta?.host) { + fetch(`${status.clientMeta.host}/client/release.json?ts=${now}`) + .then((res) => res.json()) + .then((data) => setClientRelease(data)); + } + } + }, ["status"]); + + if (mode === "minimal") { + if (!status || status?.clientMeta?.tokenExpired) { + return ( + + ); + } + + const latestRequest = dayjs(status.latestRequestDateTime); + const inOneHour = dayjs().add(1, "hours"); + + if (latestRequest > inOneHour) { + return ( + + ); + } + + if (clientRelease) { + if (status?.releaseVersion !== clientRelease?.releaseVersion) { + return ; + } + + if (status?.releaseTimestamp !== clientRelease?.releaseTimestamp) { + return ; + } + } + + return ( +
+ +
+ ); + } + + return ( + <> + {!status && ( +
+ + {t("not-bound")} + +
+ )} + {status?.clientMeta?.tokenExpired && ( +
+ + {t("token-expired")} + +
+ )} + {status && !status.clientMeta?.tokenExpired && ( + <> +
+ + {t("already-bound")} + +
+ + {dayjs(status?.latestRequestDateTime) < + dayjs().subtract(1, "hour") && ( + <> + {" "} + + {" "} + {t("latest-request-warning")} + + + )} + + {(clientRelease?.releaseTimestamp !== status?.releaseTimestamp || + clientRelease?.releaseVersion !== status?.releaseVersion) && ( + + {" "} + {t("release-warning")} + + )} + + +
+ {t("latest-request")}:{" "} + {dayjs(status?.latestRequestDateTime).format("D/M YYYY HH:mm")} +
+
+ {t("release-version")}: {status?.releaseVersion} +
+
+ {t("release-timestamp")}:{" "} + {dayjs(status?.releaseTimestamp * 1000).format("D/M YYYY HH:mm")} +
+
+ + )} + + ); +} + +ScreenStatus.defaultProps = { + mode: "default" +}; + +ScreenStatus.propTypes = { + screen: PropTypes.shape({ + "@id": PropTypes.string.isRequired, + status: PropTypes.shape({ + releaseVersion: PropTypes.string, + releaseTimestamp: PropTypes.number, + latestRequestDateTime: PropTypes.string, + clientMeta: PropTypes.shape({ + ip: PropTypes.string, + host: PropTypes.string, + userAgent: PropTypes.string, + tokenExpired: PropTypes.bool, + }), + }), + }).isRequired, + mode: PropTypes.string, +}; + +export default ScreenStatus; diff --git a/src/components/screen/util/screen-columns.jsx b/src/components/screen/util/screen-columns.jsx index 03d4612c..005a7432 100644 --- a/src/components/screen/util/screen-columns.jsx +++ b/src/components/screen/util/screen-columns.jsx @@ -1,10 +1,21 @@ import { React } from "react"; import { useTranslation } from "react-i18next"; +import dayjs from "dayjs"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faCheckCircle, + faExclamationCircle, + faInfoCircle, + faPlus, +} from "@fortawesome/free-solid-svg-icons"; +import { Button } from "react-bootstrap"; +import { useNavigate } from "react-router-dom"; import ListButton from "../../util/list/list-button"; import CampaignIcon from "../../screen-list/campaign-icon"; import SelectColumnHoc from "../../util/select-column-hoc"; import ColumnHoc from "../../util/column-hoc"; import idFromUrl from "../../util/helpers/id-from-url"; +import ScreenStatus from "../screen-status"; /** * Columns for screens lists. @@ -14,6 +25,7 @@ import idFromUrl from "../../util/helpers/id-from-url"; * @param {string} props.infoModalRedirect - The url for redirecting in the info modal. * @param {string} props.infoModalTitle - The info modal title. * @param {string} props.dataKey The data key for mapping the data. + * @param {bool} props.displayStatus Should status be displayed? * @returns {object} The columns for the screens lists. */ function getScreenColumns({ @@ -21,17 +33,17 @@ function getScreenColumns({ infoModalRedirect, infoModalTitle, dataKey, + displayStatus, }) { const { t } = useTranslation("common", { keyPrefix: "screen-list" }); const columns = [ { - // eslint-disable-next-line react/prop-types - content: ({ inScreenGroups }) => ( + content: (screen) => ( @@ -51,6 +63,16 @@ function getScreenColumns({ }, ]; + if (displayStatus) { + columns.push({ + path: "status", + label: t("columns.status"), + content: (screen) => { + return ; + }, + }); + } + return columns; } diff --git a/src/translations/da/common.json b/src/translations/da/common.json index c59ff732..43d6c0a1 100644 --- a/src/translations/da/common.json +++ b/src/translations/da/common.json @@ -61,11 +61,24 @@ "react-table": { "remove-row": "Fjern række" }, + "screen-status": { + "not-bound": "Skærmen er ikke tilkoblet", + "already-bound": "Skærmen er tilkoblet", + "token-expired": "Skærmens forbindelse er udløbet. Kobl på med en ny kode.", + "release-timestamp": "Udgivelsestidspunkt", + "release-version": "Version", + "latest-request": "Seneste kommunikation", + "latest-release": "Seneste udgivelse", + "latest-release-timestamp": "Seneste udgivelsestidspunkt", + "latest-request-warning": "Skærmen har ikke kommunikeret i mere end en time.", + "release-warning": "Skærmen kører ikke seneste udgivelse." + }, "screen-list": { "columns": { "campaign": "Kampagne", "on-groups": "Tilknyttede grupper", - "location": "Lokation" + "location": "Lokation", + "status": "Status" }, "info-modal": { "screen-in-groups": "Skærmen er i følgende grupper" @@ -675,8 +688,6 @@ "bind-header": "Tilkobling", "bind": "Tilkobl skærm", "unbind": "Afkobl skærm", - "not-bound": "Skærmen er ikke tilkoblet", - "already-bound": "Skærmen er tilkoblet", "bindkey-label": "Tilkoblingskode", "error-messages": { "error-binding": "Der skete en fejl ({{status}}) da skærmen skulle kobles:", From 2fcc1eb0dc4a72b9fd2f5a71d2992a4a4df9d2cb Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 11:57:54 +0200 Subject: [PATCH 02/17] 1241: Moved screen binding/unbinding to ScreenStatus component --- src/components/screen/screen-form.jsx | 79 +-------- src/components/screen/screen-status.jsx | 226 +++++++++++++++++------- src/translations/da/common.json | 11 +- 3 files changed, 174 insertions(+), 142 deletions(-) diff --git a/src/components/screen/screen-form.jsx b/src/components/screen/screen-form.jsx index 7f0b5fa3..82bbccad 100644 --- a/src/components/screen/screen-form.jsx +++ b/src/components/screen/screen-form.jsx @@ -1,9 +1,8 @@ import { React, useEffect, useState } from "react"; -import { Button, Form, Spinner, Alert } from "react-bootstrap"; +import { Button, Form, Spinner } from "react-bootstrap"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import PropTypes from "prop-types"; -import { useDispatch } from "react-redux"; import ContentBody from "../util/content-body/content-body"; import ContentFooter from "../util/content-footer/content-footer"; import FormInput from "../util/forms/form-input"; @@ -13,11 +12,9 @@ import GridGenerationAndSelect from "./util/grid-generation-and-select"; import MultiSelectComponent from "../util/forms/multiselect-dropdown/multi-dropdown"; import idFromUrl from "../util/helpers/id-from-url"; import { - api, useGetV2LayoutsQuery, useGetV2ScreensByIdScreenGroupsQuery, } from "../../redux/api/api.generated.ts"; -import { displayError } from "../util/list/toast-component/display-toast"; import FormCheckbox from "../util/forms/form-checkbox"; import "./screen-form.scss"; import ScreenStatus from "./screen-status"; @@ -50,10 +47,8 @@ function ScreenForm({ }) { const { t } = useTranslation("common", { keyPrefix: "screen-form" }); const navigate = useNavigate(); - const dispatch = useDispatch(); const [selectedLayout, setSelectedLayout] = useState(); const [layoutOptions, setLayoutOptions] = useState(); - const [bindKey, setBindKey] = useState(""); const { data: layouts } = useGetV2LayoutsQuery({ page: 1, itemsPerPage: 20, @@ -91,57 +86,6 @@ function ScreenForm({ }); }; - const handleBindScreen = () => { - if (bindKey) { - dispatch( - api.endpoints.postScreenBindKey.initiate({ - id: idFromUrl(screen["@id"]), - screenBindObject: JSON.stringify({ - bindKey, - }), - }) - ).then((response) => { - if (response.error) { - const err = response.error; - displayError( - t("error-messages.error-binding", { - status: err.status, - }), - err - ); - } else { - // Set screenUser to true, to indicate it has been set. - handleInput({ target: { id: "screenUser", value: true } }); - } - }); - } - }; - - const handleUnbindScreen = () => { - if (screen?.screenUser) { - setBindKey(""); - - dispatch( - api.endpoints.postScreenUnbind.initiate({ - id: idFromUrl(screen["@id"]), - }) - ).then((response) => { - if (response.error) { - const err = response.error; - displayError( - t("error-messages.error-unbinding", { - status: err.status, - }), - err - ); - } else { - // Set screenUser to null, to indicate it has been removed. - handleInput({ target: { id: "screenUser", value: null } }); - } - }); - } - }; - const isVertical = () => { if (screen.orientation) { return screen.orientation[0].id === "vertical"; @@ -182,26 +126,7 @@ function ScreenForm({ {Object.prototype.hasOwnProperty.call(screen, "@id") && (

{t("bind-header")}

- - {screen?.screenUser && ( - <> - - - )} - {!screen?.screenUser && ( - <> - { - setBindKey(target?.value); - }} - name="bindKey" - value={bindKey} - label={t("bindkey-label")} - className="mb-3" - /> - - - )} +
)} diff --git a/src/components/screen/screen-status.jsx b/src/components/screen/screen-status.jsx index 0e7d694c..a33982a4 100644 --- a/src/components/screen/screen-status.jsx +++ b/src/components/screen/screen-status.jsx @@ -5,6 +5,7 @@ import { Alert, Button } from "react-bootstrap"; import { useTranslation } from "react-i18next"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { + faCheck, faCheckCircle, faExclamationCircle, faExclamationTriangle, @@ -12,7 +13,11 @@ import { faPlus, } from "@fortawesome/free-solid-svg-icons"; import { useNavigate } from "react-router-dom"; +import { useDispatch } from "react-redux"; import idFromUrl from "../util/helpers/id-from-url"; +import { api } from "../../redux/api/api.generated.ts"; +import { displayError } from "../util/list/toast-component/display-toast"; +import FormInput from "../util/forms/form-input"; /** * Displays screen status. @@ -20,16 +25,70 @@ import idFromUrl from "../util/helpers/id-from-url"; * @param {object} props The props. * @param {object} props.screen The screen. * @param {string | null} props.mode The display mode: 'default' or 'minimal' + * @param props.handleInput * @returns {JSX.Element} The status element. */ -function ScreenStatus({ screen, mode = "default" }) { +function ScreenStatus({ screen, handleInput, mode = "default" }) { const { t } = useTranslation("common", { keyPrefix: "screen-status" }); const navigate = useNavigate(); + const dispatch = useDispatch(); const [clientRelease, setClientRelease] = useState(null); + const [bindKey, setBindKey] = useState(""); const { status } = screen; + const handleBindScreen = () => { + if (bindKey) { + dispatch( + api.endpoints.postScreenBindKey.initiate({ + id: idFromUrl(screen["@id"]), + screenBindObject: JSON.stringify({ + bindKey, + }), + }) + ).then((response) => { + if (response.error) { + const err = response.error; + displayError( + t("error-messages.error-binding", { + status: err.status, + }), + err + ); + } else { + // Set screenUser to true, to indicate it has been set. + handleInput({ target: { id: "screenUser", value: true } }); + } + }); + } + }; + + const handleUnbindScreen = () => { + if (screen?.screenUser) { + setBindKey(""); + + dispatch( + api.endpoints.postScreenUnbind.initiate({ + id: idFromUrl(screen["@id"]), + }) + ).then((response) => { + if (response.error) { + const err = response.error; + displayError( + t("error-messages.error-unbinding", { + status: err.status, + }), + err + ); + } else { + // Set screenUser and status to null, to indicate it has been removed. + handleInput({ target: { id: "screenUser", value: null } }); + } + }); + } + }; + useEffect(() => { if (status) { const now = dayjs().startOf("minute").valueOf(); @@ -84,75 +143,121 @@ function ScreenStatus({ screen, mode = "default" }) { ); } - return ( - <> - {!status && ( -
- - {t("not-bound")} - -
- )} - {status?.clientMeta?.tokenExpired && ( + const getStatusAlert = () => { + let message = t("already-bound"); + let variant = "success"; + let icon = ; + const screenBound = !!screen.screenUser; + const notRunningLatestRelease = + status && + (clientRelease?.releaseTimestamp !== status?.releaseTimestamp || + clientRelease?.releaseVersion !== status?.releaseVersion); + + if (!screenBound) { + message = t("not-bound"); + variant = "danger"; + } else if (status?.clientMeta?.tokenExpired) { + message = t("token-expired"); + variant = "danger"; + } else if ( + status && + dayjs(status?.latestRequestDateTime) < dayjs().subtract(1, "hour") + ) { + message = t("latest-request-warning"); + variant = "danger"; + icon = ; + } else if (notRunningLatestRelease) { + message = t("release-warning"); + variant = "warning"; + icon = ; + } + + return ( +
- - {t("token-expired")} - + {icon} + {" "} + {message}
- )} - {status && !status.clientMeta?.tokenExpired && ( - <> -
- - {t("already-bound")} - -
- - {dayjs(status?.latestRequestDateTime) < - dayjs().subtract(1, "hour") && ( - <> - {" "} - - {" "} - {t("latest-request-warning")} - - - )} - - {(clientRelease?.releaseTimestamp !== status?.releaseTimestamp || - clientRelease?.releaseVersion !== status?.releaseVersion) && ( - - {" "} - {t("release-warning")} - - )} - - -
- {t("latest-request")}:{" "} - {dayjs(status?.latestRequestDateTime).format("D/M YYYY HH:mm")} -
-
- {t("release-version")}: {status?.releaseVersion} -
-
- {t("release-timestamp")}:{" "} - {dayjs(status?.releaseTimestamp * 1000).format("D/M YYYY HH:mm")} -
-
- - )} - - ); + + {!screenBound && ( + <> + { + setBindKey(target?.value); + }} + name="bindKey" + value={bindKey} + label={t("bindkey-label")} + className="mb-3" + /> + + + )} + + {screenBound && ( + <> +
    + {status?.latestRequestDateTime && ( +
  • + {t("latest-request")}:{" "} + {dayjs(status?.latestRequestDateTime).format( + "D/M YYYY HH:mm" + )} +
  • + )} + {status?.releaseVersion && ( +
  • + {t("release-version")}: {status?.releaseVersion} + {notRunningLatestRelease && ( + <> + {" "} + ({t("newest")}: {clientRelease?.releaseVersion}) + + )} +
  • + )} + {status?.releaseTimestamp && ( +
  • + {t("release-timestamp")}:{" "} + {dayjs(status?.releaseTimestamp * 1000).format( + "D/M YYYY HH:mm" + )} + {notRunningLatestRelease && ( + <> + {" "}({t("newest")}:{" "} + {clientRelease?.releaseTimestamp && + dayjs(clientRelease?.releaseTimestamp * 1000).format( + "D/M YYYY HH:mm" + )} + ) + + )} +
  • + )} +
+ + + + )} +
+ ); + }; + + return <>{getStatusAlert()}; } ScreenStatus.defaultProps = { - mode: "default" + mode: "default", + handleInput: () => {}, }; ScreenStatus.propTypes = { screen: PropTypes.shape({ "@id": PropTypes.string.isRequired, + screenUser: PropTypes.shape({}), status: PropTypes.shape({ releaseVersion: PropTypes.string, releaseTimestamp: PropTypes.number, @@ -166,6 +271,7 @@ ScreenStatus.propTypes = { }), }).isRequired, mode: PropTypes.string, + handleInput: PropTypes.func, }; export default ScreenStatus; diff --git a/src/translations/da/common.json b/src/translations/da/common.json index 43d6c0a1..f618ff65 100644 --- a/src/translations/da/common.json +++ b/src/translations/da/common.json @@ -62,7 +62,10 @@ "remove-row": "Fjern række" }, "screen-status": { - "not-bound": "Skærmen er ikke tilkoblet", + "bind": "Tilkobl skærm", + "unbind": "Afkobl skærm", + "bindkey-label": "Tilkoblingskode", + "not-bound": "Skærmen er ikke tilkoblet.", "already-bound": "Skærmen er tilkoblet", "token-expired": "Skærmens forbindelse er udløbet. Kobl på med en ny kode.", "release-timestamp": "Udgivelsestidspunkt", @@ -71,7 +74,8 @@ "latest-release": "Seneste udgivelse", "latest-release-timestamp": "Seneste udgivelsestidspunkt", "latest-request-warning": "Skærmen har ikke kommunikeret i mere end en time.", - "release-warning": "Skærmen kører ikke seneste udgivelse." + "release-warning": "Skærmen kører ikke seneste udgivelse.", + "newest": "Nyeste" }, "screen-list": { "columns": { @@ -686,9 +690,6 @@ "touch-region": "(Touch)", "touch-region-helptext": "Touch region: En touch region fungerer anderledes end en normal region. I en touch region bliver slides der er tilføjet lavet til knapper der kan åbnes i fuld skærm.", "bind-header": "Tilkobling", - "bind": "Tilkobl skærm", - "unbind": "Afkobl skærm", - "bindkey-label": "Tilkoblingskode", "error-messages": { "error-binding": "Der skete en fejl ({{status}}) da skærmen skulle kobles:", "error-unbinding": "Der skete en fejl ({{status}}) da skærmen skulle afkobles:" From 08939f32cffb625e4b3083c2a5ae2ad9941fc855 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 11:58:55 +0200 Subject: [PATCH 03/17] 1241: Moved screen binding/unbinding to ScreenStatus component --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43f3932c..902ead4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- Added screen status to screen list. +- Refactored screen status on screen edit. + ## [2.0.2] - 2024-04-25 - [#242](https://github.com/os2display/display-admin-client/pull/242) From 169a59e3e87f33cb728d4c6be4a64127df52e5d3 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 12:24:52 +0200 Subject: [PATCH 04/17] 1241: Mode screen status configurable if it should be shown in list --- infrastructure/itkdev/etc/confd/templates/config.tmpl | 1 + .../os2display/etc/confd/templates/config.tmpl | 1 + public/example_config.json | 1 + src/components/screen/screen-list.jsx | 10 +++++++++- src/config-loader.js | 1 + 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/infrastructure/itkdev/etc/confd/templates/config.tmpl b/infrastructure/itkdev/etc/confd/templates/config.tmpl index cc563b53..1377a197 100644 --- a/infrastructure/itkdev/etc/confd/templates/config.tmpl +++ b/infrastructure/itkdev/etc/confd/templates/config.tmpl @@ -1,6 +1,7 @@ { "api": "{{ getenv "API_PATH" "/" }}", "touchButtonRegions": "{{ getenv "APP_TOUCH_BUTTON_REGIONS" "false"}}", + "showScreenStatus": "{{ getenv "APP_SHOW_SCREEN_STATUS" "false"}}", "loginMethods": [ { "type": "oidc", diff --git a/infrastructure/os2display/etc/confd/templates/config.tmpl b/infrastructure/os2display/etc/confd/templates/config.tmpl index cc563b53..1377a197 100644 --- a/infrastructure/os2display/etc/confd/templates/config.tmpl +++ b/infrastructure/os2display/etc/confd/templates/config.tmpl @@ -1,6 +1,7 @@ { "api": "{{ getenv "API_PATH" "/" }}", "touchButtonRegions": "{{ getenv "APP_TOUCH_BUTTON_REGIONS" "false"}}", + "showScreenStatus": "{{ getenv "APP_SHOW_SCREEN_STATUS" "false"}}", "loginMethods": [ { "type": "oidc", diff --git a/public/example_config.json b/public/example_config.json index cf6b23b3..5d87a196 100644 --- a/public/example_config.json +++ b/public/example_config.json @@ -1,6 +1,7 @@ { "api": "/", "touchButtonRegions": false, + "showScreenStatus": false, "loginMethods": [ { "type": "oidc", diff --git a/src/components/screen/screen-list.jsx b/src/components/screen/screen-list.jsx index 05c3391e..3c371186 100644 --- a/src/components/screen/screen-list.jsx +++ b/src/components/screen/screen-list.jsx @@ -20,6 +20,7 @@ import { displayError, } from "../util/list/toast-component/display-toast"; import "./screen-list.scss"; +import ConfigLoader from "../../config-loader"; /** * The screen list component. @@ -42,6 +43,7 @@ function ScreenList() { const [loadingMessage, setLoadingMessage] = useState( t("loading-messages.loading-screens") ); + const [showScreenStatus, setShowScreenStatus] = useState(false); // Delete call const [ @@ -62,6 +64,12 @@ function ScreenList() { createdBy, }); + useEffect(() => { + ConfigLoader.loadConfig().then((config) => { + setShowScreenStatus(config.showScreenStatus); + }); + }, []); + useEffect(() => { if (data) { setListData(data); @@ -125,7 +133,7 @@ function ScreenList() { apiCall: useGetV2ScreensByIdScreenGroupsQuery, infoModalRedirect: "/group/edit", infoModalTitle: t("info-modal.screen-in-groups"), - displayStatus: true, + displayStatus: showScreenStatus, }); return ( diff --git a/src/config-loader.js b/src/config-loader.js index 180aa9c9..bdd655b1 100644 --- a/src/config-loader.js +++ b/src/config-loader.js @@ -30,6 +30,7 @@ const ConfigLoader = { resolve({ api: "/api/", touchButtonRegions: false, + showScreenStatus: false, loginMethods: [ { type: "oidc", From 2d3b653f61a54d2095ef66013543e7257b0d51be Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 8 May 2024 12:33:22 +0200 Subject: [PATCH 05/17] 1241: Made screen status configurable for screen edit --- .../itkdev/etc/confd/templates/config.tmpl | 2 +- src/components/screen/screen-status.jsx | 93 +++++++++++-------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/infrastructure/itkdev/etc/confd/templates/config.tmpl b/infrastructure/itkdev/etc/confd/templates/config.tmpl index 1377a197..a904bce3 100644 --- a/infrastructure/itkdev/etc/confd/templates/config.tmpl +++ b/infrastructure/itkdev/etc/confd/templates/config.tmpl @@ -1,7 +1,7 @@ { "api": "{{ getenv "API_PATH" "/" }}", "touchButtonRegions": "{{ getenv "APP_TOUCH_BUTTON_REGIONS" "false"}}", - "showScreenStatus": "{{ getenv "APP_SHOW_SCREEN_STATUS" "false"}}", + "showScreenStatus": "{{ getenv "APP_SHOW_SCREEN_STATUS" "true"}}", "loginMethods": [ { "type": "oidc", diff --git a/src/components/screen/screen-status.jsx b/src/components/screen/screen-status.jsx index a33982a4..5b6107d5 100644 --- a/src/components/screen/screen-status.jsx +++ b/src/components/screen/screen-status.jsx @@ -18,6 +18,7 @@ import idFromUrl from "../util/helpers/id-from-url"; import { api } from "../../redux/api/api.generated.ts"; import { displayError } from "../util/list/toast-component/display-toast"; import FormInput from "../util/forms/form-input"; +import ConfigLoader from "../../config-loader"; /** * Displays screen status. @@ -35,6 +36,7 @@ function ScreenStatus({ screen, handleInput, mode = "default" }) { const [clientRelease, setClientRelease] = useState(null); const [bindKey, setBindKey] = useState(""); + const [showScreenStatus, setShowScreenStatus] = useState(false); const { status } = screen; @@ -99,7 +101,13 @@ function ScreenStatus({ screen, handleInput, mode = "default" }) { .then((data) => setClientRelease(data)); } } - }, ["status"]); + }, [status]); + + useEffect(() => { + ConfigLoader.loadConfig().then((config) => { + setShowScreenStatus(config.showScreenStatus); + }); + }, []); if (mode === "minimal") { if (!status || status?.clientMeta?.tokenExpired) { @@ -197,45 +205,47 @@ function ScreenStatus({ screen, handleInput, mode = "default" }) { {screenBound && ( <> -
    - {status?.latestRequestDateTime && ( -
  • - {t("latest-request")}:{" "} - {dayjs(status?.latestRequestDateTime).format( - "D/M YYYY HH:mm" - )} -
  • - )} - {status?.releaseVersion && ( -
  • - {t("release-version")}: {status?.releaseVersion} - {notRunningLatestRelease && ( - <> - {" "} - ({t("newest")}: {clientRelease?.releaseVersion}) - - )} -
  • - )} - {status?.releaseTimestamp && ( -
  • - {t("release-timestamp")}:{" "} - {dayjs(status?.releaseTimestamp * 1000).format( - "D/M YYYY HH:mm" - )} - {notRunningLatestRelease && ( - <> - {" "}({t("newest")}:{" "} - {clientRelease?.releaseTimestamp && - dayjs(clientRelease?.releaseTimestamp * 1000).format( - "D/M YYYY HH:mm" - )} - ) - - )} -
  • - )} -
+ {showScreenStatus && ( +
    + {status?.latestRequestDateTime && ( +
  • + {t("latest-request")}:{" "} + {dayjs(status?.latestRequestDateTime).format( + "D/M YYYY HH:mm" + )} +
  • + )} + {status?.releaseVersion && ( +
  • + {t("release-version")}: {status?.releaseVersion} + {notRunningLatestRelease && ( + <> + {" "} + ({t("newest")}: {clientRelease?.releaseVersion}) + + )} +
  • + )} + {status?.releaseTimestamp && ( +
  • + {t("release-timestamp")}:{" "} + {dayjs(status?.releaseTimestamp * 1000).format( + "D/M YYYY HH:mm" + )} + {notRunningLatestRelease && ( + <> + {" "}({t("newest")}:{" "} + {clientRelease?.releaseTimestamp && + dayjs(clientRelease?.releaseTimestamp * 1000).format( + "D/M YYYY HH:mm" + )} + ) + + )} +
  • + )} +
+ )} ); } diff --git a/src/translations/da/common.json b/src/translations/da/common.json index c2147a07..dc9dac2e 100644 --- a/src/translations/da/common.json +++ b/src/translations/da/common.json @@ -66,6 +66,7 @@ "remove-row": "Fjern række" }, "screen-status": { + "connect": "Tilkobl", "bind": "Tilkobl skærm", "unbind": "Afkobl skærm", "bindkey-label": "Tilkoblingskode", From 23c0c067d2f232807b3f6de6059cdab90e4e8d32 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 10 Dec 2024 07:04:54 +0100 Subject: [PATCH 14/17] 1241: Applied coding standards --- src/components/screen/screen-status.jsx | 4 ++-- src/components/screen/util/campaign-icon.jsx | 6 ++---- src/components/screen/util/screen-columns.jsx | 2 +- src/components/util/list/list-button.jsx | 2 +- src/redux/dynamic-base-query.js | 4 +++- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/screen/screen-status.jsx b/src/components/screen/screen-status.jsx index 92ff9724..df449e9c 100644 --- a/src/components/screen/screen-status.jsx +++ b/src/components/screen/screen-status.jsx @@ -26,7 +26,7 @@ import ConfigLoader from "../../config-loader"; * @param {object} props The props. * @param {object} props.screen The screen. * @param {string | null} props.mode The display mode: 'default' or 'minimal' - * @param {func} props.handleInput Handler for change in input. + * @param {Function} props.handleInput Handler for change in input. * @returns {JSX.Element} The status element. */ function ScreenStatus({ screen, handleInput = () => {}, mode = "default" }) { @@ -120,7 +120,7 @@ function ScreenStatus({ screen, handleInput = () => {}, mode = "default" }) { className="margin-right-button" size="sm" > - {t('connect')} + {t("connect")} ); } diff --git a/src/components/screen/util/campaign-icon.jsx b/src/components/screen/util/campaign-icon.jsx index b3592bb2..145bef7a 100644 --- a/src/components/screen/util/campaign-icon.jsx +++ b/src/components/screen/util/campaign-icon.jsx @@ -31,10 +31,8 @@ function CampaignIcon({ id, delay }) { { id }, { skip: !getData } ); - const { data: groups, isLoading: isLoadingScreenGroups } = useGetV2ScreensByIdScreenGroupsQuery( - { id }, - { skip: !getData } - ); + const { data: groups, isLoading: isLoadingScreenGroups } = + useGetV2ScreensByIdScreenGroupsQuery({ id }, { skip: !getData }); useEffect(() => { if (campaigns) { diff --git a/src/components/screen/util/screen-columns.jsx b/src/components/screen/util/screen-columns.jsx index d716572e..74d5e6c7 100644 --- a/src/components/screen/util/screen-columns.jsx +++ b/src/components/screen/util/screen-columns.jsx @@ -15,7 +15,7 @@ import ScreenStatus from "../screen-status"; * @param {string} props.infoModalRedirect - The url for redirecting in the info modal. * @param {string} props.infoModalTitle - The info modal title. * @param {string} props.dataKey The data key for mapping the data. - * @param {bool} props.displayStatus Should status be displayed? + * @param {boolean} props.displayStatus Should status be displayed? * @returns {object} The columns for the screens lists. */ function getScreenColumns({ diff --git a/src/components/util/list/list-button.jsx b/src/components/util/list/list-button.jsx index ea6e90d7..3b6bd8fa 100644 --- a/src/components/util/list/list-button.jsx +++ b/src/components/util/list/list-button.jsx @@ -18,7 +18,7 @@ function ListButton({ redirectTo, displayData, modalTitle, - delayApiCall= 0, + delayApiCall = 0, apiCall = () => {}, dataKey = "", }) { diff --git a/src/redux/dynamic-base-query.js b/src/redux/dynamic-base-query.js index b2b9d563..3d94b927 100644 --- a/src/redux/dynamic-base-query.js +++ b/src/redux/dynamic-base-query.js @@ -29,7 +29,9 @@ const extendedBaseQuery = async (args, api, extraOptions) => { if (newArgs.params["screenUser.latestRequest"]) { const key = Object.keys(newArgs.params["screenUser.latestRequest"])[0]; - const value = Object.values(newArgs.params["screenUser.latestRequest"])[0]; + const value = Object.values( + newArgs.params["screenUser.latestRequest"] + )[0]; newArgs.params[`screenUser.latestRequest[${key}]`] = `${value}`; } From 6af87b0d152bd2bf11f7dc5a8ce9f1fd47532e06 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:38:20 +0100 Subject: [PATCH 15/17] 1241: Removed id --- src/components/screen/screen-status.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/screen/screen-status.jsx b/src/components/screen/screen-status.jsx index df449e9c..260ff6ed 100644 --- a/src/components/screen/screen-status.jsx +++ b/src/components/screen/screen-status.jsx @@ -115,7 +115,6 @@ function ScreenStatus({ screen, handleInput = () => {}, mode = "default" }) {