diff --git a/public/locales/en/translations.json b/public/locales/en/translations.json index f268ff2..7f204fc 100644 --- a/public/locales/en/translations.json +++ b/public/locales/en/translations.json @@ -69,6 +69,13 @@ "ReleaseNotes": { "Version": "Version", "Date": "Date" + }, + "SystemVersion": { + "Title": "Component versions", + "Server": "Server: {{version}}", + "Api": "API: {{version}}", + "Frontend": "UI: {{version}}", + "LastReleaseDate": "Last update date: {{date}}" } } } diff --git a/public/locales/ro/translations.json b/public/locales/ro/translations.json index 64adf04..1e62f63 100644 --- a/public/locales/ro/translations.json +++ b/public/locales/ro/translations.json @@ -60,6 +60,13 @@ "ReleaseNotes": { "Version": "Versiune", "Date": "Dată" + }, + "SystemVersion": { + "Title": "Versiuni componente", + "Server": "Server: {{version}}", + "Api": "API: {{version}}", + "Frontend": "UI: {{version}}", + "LastReleaseDate": "Data ultimei actualizări: {{date}}" } } } diff --git a/src/api/useApi.js b/src/api/useApi.js index e47ed2c..ddad59b 100644 --- a/src/api/useApi.js +++ b/src/api/useApi.js @@ -43,6 +43,14 @@ const useApi = () => { } }; + const getSystemVersion = (options = defaultOptions) => { + const releaseNotesPromise = call( + () => get(`${systemRoute}/version`), + options + ); + return releaseNotesPromise; + }; + const readReleaseNotes = (options = defaultOptions) => { const releaseNotesPromise = call( () => get(`${systemRoute}/release-notes`), @@ -102,6 +110,7 @@ const useApi = () => { }; return { + getSystemVersion, readReleaseNotes, readMachines, wakeMachine, diff --git a/src/features/about/system/AboutSystemContainer.js b/src/features/about/system/AboutSystemContainer.js index b508a0b..8b64878 100644 --- a/src/features/about/system/AboutSystemContainer.js +++ b/src/features/about/system/AboutSystemContainer.js @@ -1,6 +1,7 @@ import React from "react"; +import SystemVersionContainer from "./SystemVersionContainer"; const AboutSystemContainer = () => { - return <>AboutSystemContainer; + return ; }; export default AboutSystemContainer; diff --git a/src/features/about/system/SystemVersionComponent.js b/src/features/about/system/SystemVersionComponent.js new file mode 100644 index 0000000..c5ec506 --- /dev/null +++ b/src/features/about/system/SystemVersionComponent.js @@ -0,0 +1,154 @@ +import React, { useMemo, useEffect, useState } from "react"; +import PropTypes from "prop-types"; +import { makeStyles } from "@material-ui/core/styles"; +import { + Typography, + List, + ListItem, + ListItemText, + ListItemAvatar +} from "@material-ui/core"; +import Avatar from "@material-ui/core/Avatar"; +import WebAssetIcon from "@material-ui/icons/WebAsset"; +import DeveloperBoardIcon from "@material-ui/icons/DeveloperBoard"; +import SettingsInputSvideoIcon from "@material-ui/icons/SettingsInputSvideo"; +import { useTranslation } from "react-i18next"; +import packageData from "../../../../package.json"; + +const useStyles = makeStyles(theme => { + return { + horizontally: { + display: "flex", + flexDirection: "row", + padding: 0 + }, + vertical: { + width: "100%" + }, + value: { + fontSize: "0.9rem", + fontWeight: theme.typography.fontWeightMedium + } + }; +}); + +const SystemVersionComponent = ({ data }) => { + const classes = useStyles(); + const [listClass, setListClass] = useState(classes.horizontally); + const { t } = useTranslation(); + + useEffect(() => { + const mediaQuery = window.matchMedia("(max-width: 800px)"); + + function handleMatches(event) { + const cssClass = event.matches ? classes.vertical : classes.horizontally; + setListClass(cssClass); + } + + handleMatches(mediaQuery); + mediaQuery.addListener(handleMatches); + + return () => { + mediaQuery.removeListener(handleMatches); + }; + }, [classes.horizontally, classes.vertical]); + + const lastReleaseDate = useMemo(() => { + const format = "DD-MM-YYYY HH:mm:ss"; + const server = t("DATE_FORMAT", { + date: { + value: data.server.lastReleaseDate, + format + } + }); + + const api = t("DATE_FORMAT", { + date: { + value: data.api.lastReleaseDate, + format + } + }); + + const frontend = t("DATE_FORMAT", { + date: { + value: process.env.APP_DATE ?? new Date(), + format + } + }); + + return { server, api, frontend }; + }, [data, t]); + + return ( + <> + + {t("About.SystemVersion.Title")} + + + + + + + + + + {t("About.SystemVersion.Server", { + version: data.server.version + })} + + } + secondary={t("About.SystemVersion.LastReleaseDate", { + date: lastReleaseDate.server + })} + /> + + + + + + + + + {t("About.SystemVersion.Api", { + version: data.api.version + })} + + } + secondary={t("About.SystemVersion.LastReleaseDate", { + date: lastReleaseDate.api + })} + /> + + + + + + + + + {t("About.SystemVersion.Frontend", { + version: process.env.APP_VERSION ?? packageData.version + })} + + } + secondary={t("About.SystemVersion.LastReleaseDate", { + date: lastReleaseDate.frontend + })} + /> + + + + ); +}; + +SystemVersionComponent.propTypes = { + data: PropTypes.object.isRequired +}; + +export default SystemVersionComponent; diff --git a/src/features/about/system/SystemVersionContainer.js b/src/features/about/system/SystemVersionContainer.js new file mode 100644 index 0000000..a990954 --- /dev/null +++ b/src/features/about/system/SystemVersionContainer.js @@ -0,0 +1,22 @@ +import React, { useState, useEffect } from "react"; +import SystemVersionComponent from "./SystemVersionComponent"; +import useApi from "../../../api"; + +const SystemVersionContainer = () => { + const [state, setState] = useState({ data: {}, loaded: false }); + + const api = useApi(); + + useEffect(() => { + if (state.loaded) return; + api.getSystemVersion({ + onCompleted: data => { + setState({ data, loaded: true }); + } + }); + }, [api, state.loaded]); + + return <>{state.loaded && }; +}; + +export default SystemVersionContainer;