From 3e099a68cba3e35b100e8a718cde92799e6788b6 Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Thu, 13 Jul 2023 09:36:20 +0200 Subject: [PATCH] change style for multiple pages, change how s3 credentials are create --- typescript/Frontend/public/index.html | 44 +++--- typescript/Frontend/src/App.tsx | 56 +++++--- .../Context/S3CredentialsContextProvider.tsx | 88 ++++++++++-- .../Frontend/src/components/Groups/Groups.tsx | 28 +++- .../src/components/Groups/Tree/GroupTree.tsx | 12 +- .../components/Installations/Installation.tsx | 33 ++--- .../Installations/InstallationList.tsx | 5 +- .../Installations/InstallationPage.tsx | 12 +- .../Installations/InstallationTabs.tsx | 132 +++++++++--------- .../Installations/Installations.tsx | 41 +++++- .../src/components/Installations/LiveView.tsx | 23 ++- .../Installations/Log/CheckboxTree.tsx | 10 +- .../Installations/Log/DateRangePicker.tsx | 10 +- .../src/components/Installations/Log/Log.tsx | 21 ++- .../Installations/Log/ScalarGraph.tsx | 40 +----- .../Installations/Log/TopologyBox.tsx | 2 +- .../Installations/Log/TopologyView.tsx | 6 +- .../src/components/Layout/InnovenergyTab.tsx | 2 +- .../src/components/Layout/InnovenergyTabs.tsx | 5 +- .../Layout/InnovenergyTextfield.tsx | 23 ++- ...vigationButtons.tsx => NavigationTabs.tsx} | 16 ++- .../Frontend/src/components/Layout/Search.tsx | 31 ++-- .../Frontend/src/config/axiosConfig.tsx | 4 +- .../Frontend/src/dataCache/dataCache.ts | 7 +- .../Frontend/src/hooks/useInstallation.tsx | 43 ++++++ typescript/Frontend/src/index.tsx | 83 ++++++----- typescript/Frontend/src/resources/test.gif | Bin 9065 -> 0 bytes typescript/Frontend/src/util/types.tsx | 16 ++- 28 files changed, 481 insertions(+), 312 deletions(-) rename typescript/Frontend/src/components/Layout/{NavigationButtons.tsx => NavigationTabs.tsx} (86%) create mode 100644 typescript/Frontend/src/hooks/useInstallation.tsx delete mode 100644 typescript/Frontend/src/resources/test.gif diff --git a/typescript/Frontend/public/index.html b/typescript/Frontend/public/index.html index 1ae397d60..1ff97c832 100644 --- a/typescript/Frontend/public/index.html +++ b/typescript/Frontend/public/index.html @@ -1,20 +1,20 @@ - - - - - + + + + + - + - + Innovenergy - - - -
- - + To begin the development, run `npm start` or `yarn start`. + To create a production bundle, use `npm run build` or `yarn build`. +--> + diff --git a/typescript/Frontend/src/App.tsx b/typescript/Frontend/src/App.tsx index 067d09af0..2272c6a3e 100644 --- a/typescript/Frontend/src/App.tsx +++ b/typescript/Frontend/src/App.tsx @@ -2,7 +2,7 @@ import useToken from "./hooks/useToken"; import Login from "./Login"; import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom"; -import { Container, Grid, colors } from "@mui/material"; +import { Container, Grid, colors, Box } from "@mui/material"; import routes from "./routes.json"; import { IntlProvider, MessageFormatElement } from "react-intl"; import { useContext, useState } from "react"; @@ -12,11 +12,11 @@ import fr from "./lang/fr.json"; import LanguageSelect from "./components/Layout/LanguageSelect"; import LogoutButton from "./components/Layout/LogoutButton"; import Users from "./components/Users/Users"; -import NavigationButtons from "./components/Layout/NavigationButtons"; +import NavigationTabs from "./components/Layout/NavigationTabs"; import InstallationPage from "./components/Installations/InstallationPage"; import { UserContext } from "./components/Context/UserContextProvider"; import ResetPassword from "./ResetPassword"; -import innovenergyLogo from "./resources/test.gif"; +import innovenergyLogo from "./resources/innoveng_logo_on_orange.png"; const App = () => { const { token, setToken, removeToken } = useToken(); @@ -48,9 +48,9 @@ const App = () => { locale={language} defaultLocale="EN" > - - - + + + innovenergy logo { - - - + + + + + - - - } - /> - } - /> - } /> - + + + + + } + /> + } + /> + } /> + + + ); diff --git a/typescript/Frontend/src/components/Context/S3CredentialsContextProvider.tsx b/typescript/Frontend/src/components/Context/S3CredentialsContextProvider.tsx index c3f32d8bd..e41be783d 100644 --- a/typescript/Frontend/src/components/Context/S3CredentialsContextProvider.tsx +++ b/typescript/Frontend/src/components/Context/S3CredentialsContextProvider.tsx @@ -1,29 +1,89 @@ import { createContext, ReactNode, useState } from "react"; import { I_User } from "../../util/user.util"; +import { I_Installation, S3Credentials } from "../../util/types"; +import { UnixTime } from "../../dataCache/time"; +import { FetchResult } from "../../dataCache/dataCache"; +import { DataRecord } from "../../dataCache/data"; +import { S3Access } from "../../dataCache/S3/S3Access"; +import { parseCsv } from "../../util/graph.util"; -interface InstallationContextProviderProps { - s3Credentials?: I_User; - setS3Credentials: (value: I_User) => void; +interface S3CredentialsContextProviderProps { + s3Credentials?: S3Credentials; + saveS3Credentials: (credentials: S3Credentials, id: string) => void; + fetchData: (timestamp: UnixTime) => Promise>; } -export const UserContext = createContext({ - s3Credentials: {} as I_User, - setS3Credentials: () => {}, -}); +export const S3CredentialsContext = + createContext({ + s3Credentials: {} as S3Credentials, + saveS3Credentials: () => {}, + fetchData: () => ({} as Promise>), + }); -const UserContextProvider = ({ children }: { children: ReactNode }) => { - const [s3Credentials, setS3Credentials] = useState(); +const S3CredentialsContextProvider = ({ + children, +}: { + children: ReactNode; +}) => { + const [s3Credentials, setS3Credentials] = useState(); + + console.log("creds", s3Credentials); + const saveS3Credentials = (credentials: S3Credentials, id: string) => { + //const s3Bucket = id + "-3e5b3069-214a-43ee-8d85-57d72000c19d"; + /* const s3Bucket = "saliomameiringen"; + + setS3Credentials({ s3Bucket, ...credentials });*/ + setS3Credentials({ + s3Region: "sos-ch-dk-2", + s3Provider: "exo.io", + s3Key: "EXO15c0bf710e158e9b83270f0a", + s3Secret: "Dd5jYSiZtt_Zt5Ba5mDmaiLCdASUaKLfduSKY-SU-lg", + s3Bucket: "saliomameiringen", + }); + }; + + const fetchData = (timestamp: UnixTime): Promise> => { + const s3Path = `${timestamp.ticks}.csv`; + if (s3Credentials && s3Credentials.s3Bucket) { + const s3Access = new S3Access( + s3Credentials.s3Bucket, + s3Credentials.s3Region, + s3Credentials.s3Provider, + s3Credentials.s3Key, + s3Credentials.s3Secret + ); + return s3Access + .get(s3Path) + .then(async (r) => { + if (r.status === 404) { + return Promise.resolve(FetchResult.notAvailable); + } else if (r.status === 200) { + const text = await r.text(); + return parseCsv(text); + } else { + console.error("unexpected status code"); + return Promise.resolve(FetchResult.notAvailable); + } + }) + .catch((e) => { + console.log("catch", e); + return Promise.resolve(FetchResult.tryLater); + }); + } + return Promise.resolve(FetchResult.tryLater); + }; return ( - {children} - + ); }; -export default UserContextProvider; +export default S3CredentialsContextProvider; diff --git a/typescript/Frontend/src/components/Groups/Groups.tsx b/typescript/Frontend/src/components/Groups/Groups.tsx index 9c56e56fd..337bdd205 100644 --- a/typescript/Frontend/src/components/Groups/Groups.tsx +++ b/typescript/Frontend/src/components/Groups/Groups.tsx @@ -7,8 +7,27 @@ import GroupContextProvider from "../Context/GroupContextProvider"; import GroupTree from "./Tree/GroupTree"; import AccessManagement from "./AccessManagement/AccessManagement"; import Installation from "../Installations/Installation"; +import useRouteMatch from "../../hooks/useRouteMatch"; +import useInstallation from "../../hooks/useInstallation"; +import { useEffect } from "react"; const Groups = () => { + const routeMatch = useRouteMatch([ + routes.installations + routes.tree + ":view/:id", + ]); + const { + data: currentInstallation, + loading, + error, + getInstallation, + } = useInstallation(); + + const id = routeMatch?.params?.id; + + useEffect(() => { + // TODO remove if + getInstallation(id); + }, [id]); return ( @@ -25,7 +44,14 @@ const Groups = () => { /> } + element={ + + } /> diff --git a/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx b/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx index b839a2337..140cb219f 100644 --- a/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx +++ b/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx @@ -11,6 +11,7 @@ import { instanceOfFolder } from "../../../util/group.util"; import { Grid, CircularProgress, useTheme } from "@mui/material"; import { useIntl } from "react-intl"; import { colors } from "../../.."; +import { color } from "chart.js/helpers"; const GroupTree = () => { const { setCurrentType, fetchData, data, loading } = useContext(GroupContext); @@ -54,7 +55,14 @@ const GroupTree = () => { label={element.name} onClick={() => setCurrentType(element.type)} sx={{ - ".MuiTreeItem-content": { paddingY: "5px" }, + ".MuiTreeItem-content": { py: "10px" }, + ".Mui-selected": { + backgroundColor: theme.palette.secondary.main, + }, + ".Mui-selected:hover": { + backgroundColor: theme.palette.secondary.main, + }, + ".Mui-focused": { backgroundColor: theme.palette.secondary.main }, bgcolor: colors.greyDark, borderRadius: 2, }} @@ -68,7 +76,7 @@ const GroupTree = () => { if (loading) { return ( - + ); } diff --git a/typescript/Frontend/src/components/Installations/Installation.tsx b/typescript/Frontend/src/components/Installations/Installation.tsx index ae6a2973b..a54b3c96b 100644 --- a/typescript/Frontend/src/components/Installations/Installation.tsx +++ b/typescript/Frontend/src/components/Installations/Installation.tsx @@ -1,35 +1,24 @@ import { Alert, Box, CircularProgress, useTheme } from "@mui/material"; import { AxiosError } from "axios"; -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import axiosConfig from "../../config/axiosConfig"; import { I_Installation } from "../../util/types"; import InstallationForm from "./InstallationForm"; import { colors } from "../.."; +import { S3CredentialsContext } from "../Context/S3CredentialsContextProvider"; interface I_InstallationProps { + loading?: boolean; + values?: I_Installation; + error?: AxiosError; hasMoveButton?: boolean; } -const Installation = (props: I_InstallationProps) => { - const { id } = useParams(); - const [values, setValues] = useState(); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(); - const theme = useTheme(); - useEffect(() => { - setLoading(true); - axiosConfig - .get("/GetInstallationById?id=" + id) - .then((res) => { - setValues(res.data); - setLoading(false); - }) - .catch((err: AxiosError) => { - setError(err); - setLoading(false); - }); - }, [id]); +const Installation = (props: I_InstallationProps) => { + const { hasMoveButton, values, loading, error } = props; + const { id } = useParams(); + const theme = useTheme(); if (values && values.id && values.id.toString() === id) { return ( @@ -51,7 +40,7 @@ const Installation = (props: I_InstallationProps) => { ); @@ -60,7 +49,7 @@ const Installation = (props: I_InstallationProps) => { - + ); } else if (error) { diff --git a/typescript/Frontend/src/components/Installations/InstallationList.tsx b/typescript/Frontend/src/components/Installations/InstallationList.tsx index 810ea29db..648f2ab62 100644 --- a/typescript/Frontend/src/components/Installations/InstallationList.tsx +++ b/typescript/Frontend/src/components/Installations/InstallationList.tsx @@ -70,13 +70,12 @@ const InstallationList = (props: InstallationListProps) => { { to={ getPathWithoutId(routeMatch?.pattern?.path) + installation.id } - style={{ textDecoration: "none", color: colors.blueBlack }} + style={{ textDecoration: "none", color: colors.black }} > { return ( <> - + } /> - } /> + + + + } + /> ); diff --git a/typescript/Frontend/src/components/Installations/InstallationTabs.tsx b/typescript/Frontend/src/components/Installations/InstallationTabs.tsx index 1ebc80a36..4f69755b8 100644 --- a/typescript/Frontend/src/components/Installations/InstallationTabs.tsx +++ b/typescript/Frontend/src/components/Installations/InstallationTabs.tsx @@ -25,75 +25,71 @@ const InstallationTabs = () => { if (id) { return ( - - - + + - - - - + + + ); } diff --git a/typescript/Frontend/src/components/Installations/Installations.tsx b/typescript/Frontend/src/components/Installations/Installations.tsx index cc53ca86c..6e3b822ad 100644 --- a/typescript/Frontend/src/components/Installations/Installations.tsx +++ b/typescript/Frontend/src/components/Installations/Installations.tsx @@ -13,20 +13,47 @@ import LogContextProvider from "../Context/LogContextProvider"; import useRouteMatch from "../../hooks/useRouteMatch"; import { Background } from "reactflow"; import { red } from "@mui/material/colors"; +import S3CredentialsContextProvider, { + S3CredentialsContext, +} from "../Context/S3CredentialsContextProvider"; +import { UnixTime } from "../../dataCache/time"; +import { FetchResult } from "../../dataCache/dataCache"; +import { DataRecord } from "../../dataCache/data"; +import { S3Access } from "../../dataCache/S3/S3Access"; +import { parseCsv } from "../../util/graph.util"; +import { useParams } from "react-router-dom"; +import { useContext, useEffect, useState } from "react"; +import axiosConfig from "../../config/axiosConfig"; +import { I_Installation } from "../../util/types"; +import { AxiosError } from "axios/index"; +import useInstallation from "../../hooks/useInstallation"; const Installations = () => { const routeMatch = useRouteMatch([ - routes.installations + routes.list + routes.log + ":id", + routes.installations + routes.list + ":view/:id", ]); + const { + data: currentInstallation, + loading, + error, + getInstallation, + } = useInstallation(); + const id = routeMatch?.params?.id; + + useEffect(() => { + // TODO remove if + getInstallation(id); + }, [id]); + return ( - + @@ -35,7 +62,13 @@ const Installations = () => { } + element={ + + } index /> } /> diff --git a/typescript/Frontend/src/components/Installations/LiveView.tsx b/typescript/Frontend/src/components/Installations/LiveView.tsx index 7d01b20e7..c1702d29d 100644 --- a/typescript/Frontend/src/components/Installations/LiveView.tsx +++ b/typescript/Frontend/src/components/Installations/LiveView.tsx @@ -1,7 +1,28 @@ import TopologyView from "./Log/TopologyView"; +import { Box, useTheme } from "@mui/material"; +import { colors } from "../../index"; const LiveView = () => { - return ; + const theme = useTheme(); + return ( + + + + ); }; export default LiveView; diff --git a/typescript/Frontend/src/components/Installations/Log/CheckboxTree.tsx b/typescript/Frontend/src/components/Installations/Log/CheckboxTree.tsx index 2caba1254..a06a7488b 100644 --- a/typescript/Frontend/src/components/Installations/Log/CheckboxTree.tsx +++ b/typescript/Frontend/src/components/Installations/Log/CheckboxTree.tsx @@ -49,7 +49,6 @@ const CheckboxTree = () => { ) => { event.stopPropagation(); }; - const theme = useTheme(); const renderTree = (data: TreeElement[]): ReactNode => { return data.map((element) => { const checked = checkedToggles.find((toggle) => element.id === toggle); @@ -66,19 +65,20 @@ const CheckboxTree = () => { handleClick(e, element, checked)} - style={{ - color: theme.palette.text.primary, - }} sx={{ paddingY: 0, }} + color="secondary" /> )} {splitName[splitName.length - 1]} } sx={{ - ".MuiTreeItem-content": { paddingY: "5px" }, + "& .MuiTreeItem-content": { + paddingY: "5px", + minHeight: "52px", + }, bgcolor: colors.greyDark, }} > diff --git a/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx b/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx index 7cebdd71e..3a25c78d5 100644 --- a/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx +++ b/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx @@ -14,6 +14,7 @@ interface DateRangePickerProps { range: Date[]; getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void; } + const DateRangePicker = (props: DateRangePickerProps) => { const theme = useTheme(); const { setRange, range, getCacheSeries } = props; @@ -42,10 +43,6 @@ const DateRangePicker = (props: DateRangePickerProps) => { label="From date" value={dayjs(range[0])} sx={{ - ".MuiInputLabel-root": { - color: colors.blueBlack, - }, - ".Mui-disabled": { color: "red", }, @@ -69,13 +66,12 @@ const DateRangePicker = (props: DateRangePickerProps) => { ".MuiInputLabel-root": { color: colors.blueBlack, }, - ".Mui-disabled": { color: "red", }, ".Mui-focused fieldset.MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.secondary.main, }, - + borderColor: theme.palette.secondary.main, + }, }} onChange={(newValue) => { if (newValue) { diff --git a/typescript/Frontend/src/components/Installations/Log/Log.tsx b/typescript/Frontend/src/components/Installations/Log/Log.tsx index d1156f14e..2cc0cdb1a 100644 --- a/typescript/Frontend/src/components/Installations/Log/Log.tsx +++ b/typescript/Frontend/src/components/Installations/Log/Log.tsx @@ -1,11 +1,28 @@ import React from "react"; import ScalarGraph from "./ScalarGraph"; +import { colors } from "../../../index"; +import { Box, useTheme } from "@mui/material"; const Log = () => { + const theme = useTheme(); return ( - <> + - + ); }; diff --git a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx index e507209aa..81ff0af62 100644 --- a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx +++ b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx @@ -22,40 +22,10 @@ import { FormattedMessage } from "react-intl"; import DateRangePicker from "./DateRangePicker"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { Alert, useTheme } from "@mui/material"; +import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider"; const NUMBER_OF_NODES = 100; -const s3Access = new S3Access( - "saliomameiringen", - "sos-ch-dk-2", - "exo.io", - "EXO464a9ff62fdfa407aa742855", // key - "f2KtCWN4EHFqtvH2kotdyI0w5SjjdHVPAADdcD3ik8g" // secret -); - -export const fetchData = ( - timestamp: UnixTime -): Promise> => { - const s3Path = `${timestamp.ticks}.csv`; - return s3Access - .get(s3Path) - .then(async (r) => { - if (r.status === 404) { - return Promise.resolve(FetchResult.notAvailable); - } else if (r.status === 200) { - const text = await r.text(); - console.log("parsecsv", text, parseCsv(text)); - return parseCsv(text); - } else { - console.error("unexpected status code"); - return Promise.resolve(FetchResult.notAvailable); - } - }) - .catch((e) => { - return Promise.resolve(FetchResult.tryLater); - }); -}; - const ScalarGraph = () => { const timeRange = createTimes( UnixTime.now() /* .fromTicks(1682085650) */ @@ -70,6 +40,7 @@ const ScalarGraph = () => { const [plotTitles, setPlotTitles] = useState([]); const { toggles, setToggles, checkedToggles } = useContext(LogContext); + const { fetchData } = useContext(S3CredentialsContext); const times$ = useMemo(() => new BehaviorSubject(timeRange), []); @@ -93,10 +64,9 @@ const ScalarGraph = () => { return () => subscription.unsubscribe(); }, [toggles]); - const cache = useMemo( - () => new DataCache(fetchData, TimeSpan.fromSeconds(2)), - [] - ); + const cache = useMemo(() => { + return new DataCache(fetchData, TimeSpan.fromSeconds(2)); + }, []); const transformToGraphData = (input: RecordSeries): GraphData => { const transformedObject: any = {}; diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx index 9f6a87ac2..1a6d8c5f8 100644 --- a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx +++ b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx @@ -20,7 +20,7 @@ const isInt = (value: number) => { return value % 1 === 0; }; -export const BOX_SIZE = 85; +export const BOX_SIZE = 75; const TopologyBox = (props: TopologyBoxProps) => { const { titleColor, boxColor } = getBoxColor(props.title); return ( diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyView.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyView.tsx index de1aed4be..fb5bec340 100644 --- a/typescript/Frontend/src/components/Installations/Log/TopologyView.tsx +++ b/typescript/Frontend/src/components/Installations/Log/TopologyView.tsx @@ -7,13 +7,14 @@ import { getAmount, getHighestConnectionValue, } from "../../../util/graph.util"; -import { fetchData } from "./ScalarGraph"; -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { FetchResult } from "../../../dataCache/dataCache"; import { FormattedMessage } from "react-intl"; +import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider"; const TopologyView = () => { const [values, setValues] = useState(null); + const { fetchData } = useContext(S3CredentialsContext); useEffect(() => { const interval = setInterval(() => { @@ -229,6 +230,7 @@ const TopologyView = () => { /> ); + return
TopologyView
; }; export default TopologyView; diff --git a/typescript/Frontend/src/components/Layout/InnovenergyTab.tsx b/typescript/Frontend/src/components/Layout/InnovenergyTab.tsx index 500058971..49336713e 100644 --- a/typescript/Frontend/src/components/Layout/InnovenergyTab.tsx +++ b/typescript/Frontend/src/components/Layout/InnovenergyTab.tsx @@ -17,13 +17,13 @@ const InnovenergyTab = (props: any) => { marginRight: theme.spacing(1), background: "0 0", border: "2px solid transparent", - bgcolor: theme.palette.primary.light, borderTopLeftRadius: "0.3rem", borderTopRightRadius: "0.3rem", padding: ".5rem 1rem", textDecoration: "none", transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`, "&.Mui-selected": { + backgroundColor: "#eaecf1", color: colors.black, borderColor: theme.palette.text.disabled, marginTop: "1px", diff --git a/typescript/Frontend/src/components/Layout/InnovenergyTabs.tsx b/typescript/Frontend/src/components/Layout/InnovenergyTabs.tsx index 714afad3d..bef153708 100644 --- a/typescript/Frontend/src/components/Layout/InnovenergyTabs.tsx +++ b/typescript/Frontend/src/components/Layout/InnovenergyTabs.tsx @@ -5,7 +5,7 @@ import { colors } from "index"; interface AntTabsProps { id: string; value?: string; - sx?: SxProps; + sx?: any; children: ReactNode; } @@ -24,7 +24,7 @@ const InnovenergyTabs = (props: AntTabsProps) => { }, "&.Mui-selected": { color: colors.black, - backgroundColor: " #90A7c5", + backgroundColor: "#eaecf1", borderColor: `#90A7c5 #90A7c5 #fff`, }, "& .MuiTabs-indicator": { @@ -34,6 +34,7 @@ const InnovenergyTabs = (props: AntTabsProps) => { }, "&.MuiTabs-root": { width: "100%", + ...(props.sx ? props.sx["&.MuiTabs-root"] : {}), }, }} > diff --git a/typescript/Frontend/src/components/Layout/InnovenergyTextfield.tsx b/typescript/Frontend/src/components/Layout/InnovenergyTextfield.tsx index 7e2cd6f1f..c342118e2 100644 --- a/typescript/Frontend/src/components/Layout/InnovenergyTextfield.tsx +++ b/typescript/Frontend/src/components/Layout/InnovenergyTextfield.tsx @@ -11,6 +11,7 @@ import { TextField, useTheme, } from "@mui/material"; +import { colors } from "../../index"; export interface I_InnovenergyTextfieldProps { id: string; @@ -28,18 +29,6 @@ export interface I_InnovenergyTextfieldProps { export const IePropertyGrid = (props: { rows: I_InnovenergyTextfieldProps[]; }) => { - const theme = useTheme(); - - const findLongestLength = () => { - return ( - 11 * - props.rows.reduce( - (acc, curr) => (acc > curr.label.length ? acc : curr.label.length), - 0 - ) - ); - }; - return (
{props.rows.map((prop) => ( - {prop.label} + {prop.label} ))}
{props.rows.map((element) => { return ( { +const NavigationTabs = () => { const theme = useTheme(); const routeMatch = useRouteMatch([ routes.installations + "*", routes.users + "*", ]); - const intl = useIntl(); return ( <> @@ -25,7 +29,7 @@ const NavigationButtons = () => { sx={{ bgcolor: theme.palette.primary.main, "&.Mui-selected": { - backgroundColor: theme.palette.primary.main, + backgroundColor: "#eaecf1", borderColor: theme.palette.text.disabled, borderBottom: 0, mb: -1 / 8, @@ -46,7 +50,7 @@ const NavigationButtons = () => { sx={{ bgcolor: theme.palette.primary.main, "&.Mui-selected": { - backgroundColor: theme.palette.primary.main, + backgroundColor: "#eaecf1", borderColor: theme.palette.text.disabled, borderBottom: 0, mb: -1 / 8, @@ -63,4 +67,4 @@ const NavigationButtons = () => { ); }; -export default NavigationButtons; +export default NavigationTabs; diff --git a/typescript/Frontend/src/components/Layout/Search.tsx b/typescript/Frontend/src/components/Layout/Search.tsx index 8b510b540..851d0042f 100644 --- a/typescript/Frontend/src/components/Layout/Search.tsx +++ b/typescript/Frontend/src/components/Layout/Search.tsx @@ -10,7 +10,6 @@ import { colors } from "index"; import { FC, useState } from "react"; import { useIntl } from "react-intl"; - interface SearchSidebarProps { listComponent: FC<{ searchQuery: string }>; id: string; @@ -22,7 +21,6 @@ const SearchInputTextfield = styled((props: TextFieldProps) => ( InputProps={{ disableUnderline: true } as Partial} {...props} /> - ))(({ theme }) => ({ "& .MuiFilledInput-root": { overflow: "hidden", @@ -41,11 +39,9 @@ const SearchInputTextfield = styled((props: TextFieldProps) => ( backgroundColor: theme.palette.primary.dark, }, "&.Mui-focused": { - backgroundColor: theme.palette.primary.dark, borderColor: theme.palette.secondary.main, }, - }, })); @@ -55,28 +51,17 @@ const SearchSidebar = (props: SearchSidebarProps) => { const intl = useIntl(); const theme = useTheme(); - - return (
- {/* setSearchQuery(e.target.value)} - /> */} setSearchQuery(e.target.value)} diff --git a/typescript/Frontend/src/config/axiosConfig.tsx b/typescript/Frontend/src/config/axiosConfig.tsx index 21a907f32..75b3924a1 100644 --- a/typescript/Frontend/src/config/axiosConfig.tsx +++ b/typescript/Frontend/src/config/axiosConfig.tsx @@ -1,11 +1,11 @@ import axios from "axios"; export const axiosConfigWithoutToken = axios.create({ - baseURL: "https://monitor.innov.energy:5000/api", + baseURL: "https://localhost:7087/api", }); const axiosConfig = axios.create({ - baseURL: "https://monitor.innov.energy:5000/api", + baseURL: "https://localhost:7087/api", }); axiosConfig.defaults.params = {}; axiosConfig.interceptors.request.use( diff --git a/typescript/Frontend/src/dataCache/dataCache.ts b/typescript/Frontend/src/dataCache/dataCache.ts index 33ba43dab..7a35dd8bb 100644 --- a/typescript/Frontend/src/dataCache/dataCache.ts +++ b/typescript/Frontend/src/dataCache/dataCache.ts @@ -138,10 +138,13 @@ export default class DataCache> { const onSuccess = (data: FetchResult) => { if (data === FetchResult.tryLater) { console.warn(FetchResult.tryLater); - return; } - const value = data === FetchResult.notAvailable ? undefined : data; + const value = + data === FetchResult.notAvailable || data === FetchResult.tryLater + ? undefined + : data; + // @ts-ignore this.cache.insert(value, t); }; diff --git a/typescript/Frontend/src/hooks/useInstallation.tsx b/typescript/Frontend/src/hooks/useInstallation.tsx new file mode 100644 index 000000000..369c611c3 --- /dev/null +++ b/typescript/Frontend/src/hooks/useInstallation.tsx @@ -0,0 +1,43 @@ +import { useContext, useState } from "react"; +import axiosConfig from "../config/axiosConfig"; +import { I_Installation } from "../util/types"; +import { AxiosError } from "axios"; +import { S3CredentialsContext } from "../components/Context/S3CredentialsContextProvider"; + +const useInstallation = () => { + const [data, setData] = useState(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + + const { saveS3Credentials } = useContext(S3CredentialsContext); + + const getInstallation = (id?: string) => { + if (id) { + setLoading(true); + axiosConfig + .get("/GetInstallationById?id=" + id) + .then(({ data }: { data: I_Installation }) => { + const { s3Region, s3Provider, s3Secret, s3Key } = data; + setData(data); + setLoading(false); + // TODO remove if + if (id) { + saveS3Credentials({ s3Region, s3Provider, s3Secret, s3Key }, id); + } + }) + .catch((err: AxiosError) => { + setError(err); + setLoading(false); + }); + } + }; + + return { + data, + loading, + error, + getInstallation, + }; +}; + +export default useInstallation; diff --git a/typescript/Frontend/src/index.tsx b/typescript/Frontend/src/index.tsx index 9f610827c..e4bff8ba6 100644 --- a/typescript/Frontend/src/index.tsx +++ b/typescript/Frontend/src/index.tsx @@ -3,67 +3,66 @@ import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; -import {createTheme, ThemeProvider} from "@mui/material"; +import { createTheme, ThemeProvider } from "@mui/material"; import UserContextProvider from "./components/Context/UserContextProvider"; const root = ReactDOM.createRoot( - document.getElementById("root") as HTMLElement + document.getElementById("root") as HTMLElement ); export const colors = { - black: "#000000", - blueBlack: "#2b3e54", - borderColor: "#a8b0be", + black: "#000000", + blueBlack: "#2b3e54", + borderColor: "#a8b0be", - background: "#f3f4f7", - //change this color in index.css too + background: "#f3f4f7", + //change this color in index.css too - greyDark: "#d1d7de", - greyLight: "#e1e4e7", + greyDark: "#d1d7de", + greyLight: "#e1e4e7", - orangeSelected: "#ffd280", - orangeHover: "#ffe4b3", + orangeSelected: "#f7b34d", + orangeHover: "#fad399", - orangeDark: "#ffc04d", + orangeDark: "#ffc04d", }; const theme = createTheme({ - components: { - MuiButtonBase: { - defaultProps: { - disableRipple: true, - }, - }, + components: { + MuiButtonBase: { + defaultProps: { + disableRipple: true, + }, }, - palette: { - text: { - primary: colors.blueBlack, - secondary: "#000000", - disabled: colors.borderColor, - }, - primary: { - main: colors.background, - light: colors.greyLight, - dark: colors.greyDark, - }, - secondary: { - main: colors.orangeSelected, - light: colors.orangeHover, - dark: colors.orangeDark, - }, + }, + palette: { + text: { + primary: colors.black, + disabled: colors.borderColor, }, - typography: { - fontFamily: `"Ubuntu", sans-serif`, - fontWeightRegular: 300, + primary: { + main: colors.background, + light: colors.greyLight, + dark: colors.greyDark, }, + secondary: { + main: colors.orangeSelected, + light: colors.orangeHover, + dark: colors.orangeDark, + }, + }, + typography: { + fontFamily: `"Ubuntu", sans-serif`, + fontWeightRegular: 300, + }, }); root.render( - - - - - + + + + + ); // If you want to start measuring performance in your app, pass a function diff --git a/typescript/Frontend/src/resources/test.gif b/typescript/Frontend/src/resources/test.gif deleted file mode 100644 index 3b135931e7335538db04c2ebb33e738571fed972..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9065 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

gI!{kAj^f58D`LBAmke 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 diff --git a/typescript/Frontend/src/util/types.tsx b/typescript/Frontend/src/util/types.tsx index 5b6bfcc25..81ff48c34 100644 --- a/typescript/Frontend/src/util/types.tsx +++ b/typescript/Frontend/src/util/types.tsx @@ -1,5 +1,13 @@ // TODO add if required or not -export interface I_Installation { +export interface S3Credentials { + s3Region: string; + s3Provider: string; + s3Key: string; + s3Secret: string; + s3Bucket?: string; +} + +export interface I_Installation extends S3Credentials { type: string; title?: string; status?: number; @@ -15,12 +23,6 @@ export interface I_Installation { name: string; information: string; parentId: number; - - s3Bucket: string; - s3Region: string; - s3Provider: string; - s3Key: string; - s3Secret: string; } export interface I_Folder {