diff --git a/typescript/Frontend/src/App.tsx b/typescript/Frontend/src/App.tsx
index 3fa25c407..c13163b0c 100644
--- a/typescript/Frontend/src/App.tsx
+++ b/typescript/Frontend/src/App.tsx
@@ -1,18 +1,114 @@
-import Home from "./routes/Home";
import useToken from "./hooks/useToken";
import Login from "./Login";
-import { BrowserRouter } from "react-router-dom";
+import { BrowserRouter, Route, Routes } from "react-router-dom";
+import {
+ Box,
+ Grid,
+ ButtonGroup,
+ Button,
+ Divider,
+ Select,
+ MenuItem,
+} from "@mui/material";
+import NestedList from "./components/NestedList";
+import BasicTable from "./components/Table";
+import BasicTabs from "./components/Tabs";
+import Alarms from "./routes/Alarms";
+import InstallationDetail from "./routes/Installation";
+import Log from "./routes/Log";
+import routes from "./routes.json";
+import { FormattedMessage, IntlProvider } from "react-intl";
+import { useState } from "react";
const App = () => {
const { token, setToken } = useToken();
+ const [language, setLanguage] = useState("en");
if (!token) {
return ;
}
+ const de = {
+ allInstallations: "Alle Installationen",
+ };
+
+ const en = {
+ allInstallations: "All installations",
+ };
+
+ const getTranslations = () => {
+ if (language === "de") {
+ return de;
+ }
+ return en;
+ };
+
return (
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ />
+ } />
+ } />
+ } />
+
+
+
+
+
);
};
diff --git a/typescript/Frontend/src/Login.tsx b/typescript/Frontend/src/Login.tsx
index b6065dee3..cc81da8fc 100644
--- a/typescript/Frontend/src/Login.tsx
+++ b/typescript/Frontend/src/Login.tsx
@@ -1,15 +1,14 @@
import React, { useState } from "react";
-import axios from "axios";
-import { Button, CircularProgress, TextField } from "@mui/material";
+import { Button, CircularProgress } from "@mui/material";
import Container from "@mui/material/Container";
+import InnovenergyTextfield from "./components/InnovenergyTextfield";
+import { axiosConfigWithoutToken } from "./config/axiosConfig";
const loginUser = async (username: string, password: string) => {
- return axios
- .post("https://localhost:7087/api/Login", {
- username,
- password,
- })
- .then((data) => data);
+ return axiosConfigWithoutToken.post("/Login", {
+ username,
+ password,
+ });
};
const Login = ({ setToken }: { setToken: any }) => {
@@ -26,24 +25,27 @@ const Login = ({ setToken }: { setToken: any }) => {
};
return (
-
-
+ setUsername(e.target.value)}
+ value={username}
+ handleChange={(e) => setUsername(e.target.value)}
/>
- setPassword(e.target.value)}
+ value={password}
+ handleChange={(e) => setPassword(e.target.value)}
/>
-
+
+
+
{loading && }
);
diff --git a/typescript/Frontend/src/components/CustomerForm.tsx b/typescript/Frontend/src/components/CustomerForm.tsx
new file mode 100644
index 000000000..30689dc4d
--- /dev/null
+++ b/typescript/Frontend/src/components/CustomerForm.tsx
@@ -0,0 +1,95 @@
+import { Button } from "@mui/material";
+import { useFormik } from "formik";
+import { FormattedMessage, useIntl } from "react-intl";
+import axiosConfig from "../config/axiosConfig";
+import { I_Installation } from "../util/installation.util";
+import InnovenergyTextfield from "./InnovenergyTextfield";
+
+interface I_CustomerFormProps {
+ values: I_Installation;
+ id: string | undefined;
+}
+const CustomerForm = (props: I_CustomerFormProps) => {
+ const { values, id } = props;
+ const intl = useIntl();
+
+ const formik = useFormik({
+ initialValues: {
+ name: values.name,
+ region: values.region,
+ location: values.location,
+ country: values.country,
+ orderNumber: values.orderNumber,
+ },
+ onSubmit: (formikValues) => {
+ axiosConfig
+ .put("https://localhost:7087/api/UpdateInstallation", {
+ ...formikValues,
+ id,
+ })
+ .then((res) => {
+ console.log(res);
+ });
+ },
+ });
+
+ return (
+
+ );
+};
+
+export default CustomerForm;
diff --git a/typescript/Frontend/src/components/FlowComp.tsx b/typescript/Frontend/src/components/FlowComp.tsx
new file mode 100644
index 000000000..9868366f2
--- /dev/null
+++ b/typescript/Frontend/src/components/FlowComp.tsx
@@ -0,0 +1,57 @@
+import { useState, useCallback } from "react";
+import ReactFlow, {
+ addEdge,
+ FitViewOptions,
+ applyNodeChanges,
+ applyEdgeChanges,
+ Node,
+ Edge,
+ NodeChange,
+ EdgeChange,
+ Connection,
+} from "reactflow";
+
+const initialNodes: Node[] = [
+ { id: "1", data: { label: "Node 1" }, position: { x: 5, y: 5 } },
+ { id: "2", data: { label: "Node 2" }, position: { x: 5, y: 100 } },
+];
+
+const initialEdges: Edge[] = [{ id: "e1-2", source: "1", target: "2" }];
+
+const fitViewOptions: FitViewOptions = {
+ padding: 0.2,
+};
+
+function Flow() {
+ const [nodes, setNodes] = useState(initialNodes);
+ const [edges, setEdges] = useState(initialEdges);
+
+ const onNodesChange = useCallback(
+ (changes: NodeChange[]) =>
+ setNodes((nds) => applyNodeChanges(changes, nds)),
+ [setNodes]
+ );
+ const onEdgesChange = useCallback(
+ (changes: EdgeChange[]) =>
+ setEdges((eds) => applyEdgeChanges(changes, eds)),
+ [setEdges]
+ );
+ const onConnect = useCallback(
+ (connection: Connection) => setEdges((eds) => addEdge(connection, eds)),
+ [setEdges]
+ );
+
+ return (
+
+ );
+}
+
+export default Flow;
diff --git a/typescript/Frontend/src/components/InnovenergyTextfield.tsx b/typescript/Frontend/src/components/InnovenergyTextfield.tsx
new file mode 100644
index 000000000..6f857db14
--- /dev/null
+++ b/typescript/Frontend/src/components/InnovenergyTextfield.tsx
@@ -0,0 +1,28 @@
+import { TextField } from "@mui/material";
+
+interface I_InnovenergyTextfieldProps {
+ id: string;
+ label: string;
+ value: string;
+ name: string;
+ handleChange: (e: React.ChangeEvent) => void;
+ type?: string;
+}
+
+const InnovenergyTextfield = (props: I_InnovenergyTextfieldProps) => {
+ return (
+
+ );
+};
+
+export default InnovenergyTextfield;
diff --git a/typescript/Frontend/src/components/NestedList.tsx b/typescript/Frontend/src/components/NestedList.tsx
index 656de0d7d..02759877c 100644
--- a/typescript/Frontend/src/components/NestedList.tsx
+++ b/typescript/Frontend/src/components/NestedList.tsx
@@ -1,14 +1,14 @@
import List from "@mui/material/List";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemText from "@mui/material/ListItemText";
-import { Divider } from "@mui/material";
+import { Divider, TextField } from "@mui/material";
import { Link } from "react-router-dom";
import useRouteMatch from "../hooks/useRouteMatch";
import routes from "../routes.json";
import { useEffect, useState } from "react";
-import axios from "axios";
-import { Installation } from "../util/installation.util";
-
+import { I_Installation } from "../util/installation.util";
+import axiosConfig from "../config/axiosConfig";
+import { useIntl } from "react-intl";
const getPathWithoutId = (path?: string) => {
if (path) {
@@ -18,8 +18,26 @@ const getPathWithoutId = (path?: string) => {
return routes.installation;
};
+const filterData = (
+ searchQuery: string,
+ data: I_Installation[] | undefined
+) => {
+ if (data) {
+ return data.filter(
+ (installation) =>
+ installation.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ installation.location.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+ }
+ return data;
+};
+
const NestedList = () => {
- const [data, setData] = useState();
+ const [data, setData] = useState();
+ const [searchQuery, setSearchQuery] = useState("");
+ const intl = useIntl();
+ const filteredData = filterData(searchQuery, data);
+
const routeMatch = useRouteMatch([
routes.installationWithId,
routes.alarmsWithId,
@@ -28,41 +46,51 @@ const NestedList = () => {
]);
useEffect(() => {
- const tokenString = sessionStorage.getItem("token");
- const token = tokenString !== null ? JSON.parse(tokenString) : "";
- axios
- .get("https://localhost:7087/api/GetAllInstallations", {
- headers: {
- auth: token,
- },
- })
+ axiosConfig
+ .get("https://localhost:7087/api/GetAllInstallations", {})
.then((res) => {
setData(res.data);
});
}, []);
return (
-
- {data?.map((installation) => (
- <>
-
-
-
-
-
-
- >
- ))}
-
+ <>
+ setSearchQuery(e.target.value)}
+ />
+
+ {filteredData?.map((installation) => (
+ <>
+
+
+
+
+
+
+ >
+ ))}
+
+ >
);
};
diff --git a/typescript/Frontend/src/components/Tabs.tsx b/typescript/Frontend/src/components/Tabs.tsx
index 59ab676a6..a1eee2a9d 100644
--- a/typescript/Frontend/src/components/Tabs.tsx
+++ b/typescript/Frontend/src/components/Tabs.tsx
@@ -5,6 +5,7 @@ import Box from "@mui/material/Box";
import { Link } from "react-router-dom";
import routes from "../routes.json";
import useRouteMatch from "../hooks/useRouteMatch";
+import { useIntl } from "react-intl";
const BasicTabs = () => {
const routeMatch = useRouteMatch([
@@ -15,31 +16,44 @@ const BasicTabs = () => {
]);
const id = routeMatch?.params?.id;
+ const intl = useIntl();
return (
{
+ const tokenString = sessionStorage.getItem("token");
+ const token = tokenString !== null ? JSON.parse(tokenString) : "";
+ if (token) {
+ config.headers.auth = token;
+ }
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ }
+);
+
+export default axiosConfig;
diff --git a/typescript/Frontend/src/hooks/useToken.tsx b/typescript/Frontend/src/hooks/useToken.tsx
index c18c80138..3182dc672 100644
--- a/typescript/Frontend/src/hooks/useToken.tsx
+++ b/typescript/Frontend/src/hooks/useToken.tsx
@@ -1,22 +1,22 @@
import { useState } from "react";
-
-const getToken = (): string => {
- const tokenString = sessionStorage.getItem("token");
- return tokenString !== null ? JSON.parse(tokenString).token : "";
-};
+import axiosConfig from "../config/axiosConfig";
const useToken = () => {
- const [token, setToken] = useState(getToken());
+ const getToken = () => {
+ const tokenString = sessionStorage.getItem("token");
+ return tokenString !== null ? JSON.parse(tokenString) : "";
+ };
+ const [token, setToken] = useState(getToken());
const saveToken = (userToken: any) => {
- setToken(userToken);
sessionStorage.setItem("token", JSON.stringify(userToken));
+ setToken(userToken);
+ axiosConfig.defaults.headers.common["auth"] = userToken;
};
return {
setToken: saveToken,
token,
- getToken: getToken,
};
};
diff --git a/typescript/Frontend/src/routes/Alarms.tsx b/typescript/Frontend/src/routes/Alarms.tsx
new file mode 100644
index 000000000..a7cb1420d
--- /dev/null
+++ b/typescript/Frontend/src/routes/Alarms.tsx
@@ -0,0 +1,5 @@
+const Alarms = () => {
+ return alarms
;
+};
+
+export default Alarms;
diff --git a/typescript/Frontend/src/routes/Installation.tsx b/typescript/Frontend/src/routes/Installation.tsx
index d24a22b4d..612d71002 100644
--- a/typescript/Frontend/src/routes/Installation.tsx
+++ b/typescript/Frontend/src/routes/Installation.tsx
@@ -1,93 +1,31 @@
-import { Box, TextField } from "@mui/material";
-import axios from "axios";
+import { Box, CircularProgress } from "@mui/material";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
-import { Installation } from "../util/installation.util";
+import CustomerForm from "../components/CustomerForm";
+import axiosConfig from "../config/axiosConfig";
+import { I_Installation } from "../util/installation.util";
const InstallationDetail = () => {
const { id } = useParams();
-
- const [values, setValues] = useState();
+ const [values, setValues] = useState();
+ const [loading, setLoading] = useState(false);
useEffect(() => {
- const tokenString = sessionStorage.getItem("token");
- const token = tokenString !== null ? JSON.parse(tokenString) : "";
- axios
- .get("https://localhost:7087/api/GetInstallationById?id=" + id, {
- headers: {
- auth: token,
- },
- })
- .then((res) => {
- setValues(res.data);
- console.log(res.data);
- });
+ setLoading(true);
+ axiosConfig.get("/GetInstallationById?id=" + id).then((res) => {
+ setValues(res.data);
+ setLoading(false);
+ });
}, [id]);
- const handleChange = (e: React.ChangeEvent) => {
- const { name, value } = e.target;
- setValues({
- ...values,
- [name]: value,
- } as Installation);
- };
-
- if (values) {
+ if (values && values.id.toString() === id) {
return (
-
-
-
-
-
+
);
+ } else if (loading) {
+ return ;
}
return null;
};
diff --git a/typescript/Frontend/src/routes/Log.tsx b/typescript/Frontend/src/routes/Log.tsx
new file mode 100644
index 000000000..8b1eb817a
--- /dev/null
+++ b/typescript/Frontend/src/routes/Log.tsx
@@ -0,0 +1,156 @@
+const Log = () => {
+ const foo = {
+ TimeStamp: "1676643900",
+ Devices: [
+ {
+ "TruConvertAc 205330741": {
+ Ac: {
+ L1: {
+ Current: 2.49,
+ Voltage: 239.4,
+ Phi: 0.200334842323119592691046359,
+ },
+ L2: {
+ Current: 2.65,
+ Voltage: 239.6,
+ Phi: 0.200334842323119592691046359,
+ },
+ L3: {
+ Current: 2.63,
+ Voltage: 239.8,
+ Phi: 0,
+ },
+ Frequency: 49.98,
+ },
+ Dc: {
+ Current: 2.249388753056234718826405868,
+ Voltage: 818,
+ Power: 1840.0,
+ },
+ Alarms: [],
+ },
+ },
+ {
+ "TruConvertDc 3214": {
+ Dc: {
+ Current: -2.1173594132029339853300733496,
+ Voltage: 818,
+ Power: -1732.0,
+ },
+ Dc48: {
+ Current: -30,
+ Voltage: 56.0,
+ Power: -1680.0,
+ },
+ Warnings: [],
+ Alarms: [],
+ },
+ },
+ {
+ "EmuMeter 123": {
+ Ac: {
+ L1: {
+ Current: 3.212,
+ Voltage: 239.4,
+ Phi: 1.1483422646081408626645746948,
+ },
+ L2: {
+ Current: -2.462,
+ Voltage: 238.9,
+ Phi: 1.8441893582623698418074097834,
+ },
+ L3: {
+ Current: 2.995,
+ Voltage: 238.8,
+ Phi: 0.1415394733244272187457893568,
+ },
+ Frequency: 49.9,
+ },
+ },
+ },
+ {
+ "EmuMeter 123": {
+ Ac: {
+ L1: {
+ Current: 3.212,
+ Voltage: 239.4,
+ Phi: 1.1483422646081408626645746948,
+ },
+ L2: {
+ Current: -2.462,
+ Voltage: 238.9,
+ Phi: 1.8441893582623698418074097834,
+ },
+ L3: {
+ Current: 2.995,
+ Voltage: 238.8,
+ Phi: 0.1415394733244272187457893568,
+ },
+ Frequency: 49.9,
+ },
+ },
+ },
+ {
+ Name: "AMPT",
+ Type: "PvOnDc",
+ "Current 1": 2.098,
+ "Current 2": 2.575,
+ "Voltage 1": 822.989,
+ "Voltage 2": 823.169,
+ "Power 1": 1726.630922,
+ "Power 2": 2119.660175,
+ },
+ {
+ Name: "48TL Battery",
+ Type: "Battery",
+ Dc48: {
+ Current: 14.17,
+ Voltage: 53.41,
+ Power: 756.8197,
+ },
+ Alarms: [],
+ Warnings: [],
+ Soc: 77.4,
+ HeaterOn: true,
+ EocReached: false,
+ BatteryCold: false,
+ Temperature: 265.4,
+ },
+ {
+ Name: "48TL Battery",
+ Type: "Battery",
+ Dc48: {
+ Current: 11.3,
+ Voltage: 53.4,
+ Power: 603.42,
+ },
+ Alarms: [],
+ Warnings: ["bit44:"],
+ Soc: 77.6,
+ HeaterOn: true,
+ EocReached: false,
+ BatteryCold: false,
+ Temperature: 264.9,
+ },
+ ],
+ };
+
+ const flattenObject = (obj: any, prefix = "") =>
+ Object.keys(obj).reduce((previous: any, current: any) => {
+ const pre = prefix.length ? prefix + "/" : "";
+ if (Array.isArray(obj) || typeof obj === "string") {
+ return previous;
+ }
+ if (typeof obj[current] === "object") {
+ Object.assign(previous, flattenObject(obj[current], pre + current));
+ } else {
+ previous[pre + current] = obj[current];
+ }
+ return previous;
+ }, {});
+
+ console.log(flattenObject(foo.Devices[0]));
+ return log
;
+};
+
+export default Log;
diff --git a/typescript/Frontend/src/util/installation.util.tsx b/typescript/Frontend/src/util/installation.util.tsx
index c762d7b3e..94e106b6f 100644
--- a/typescript/Frontend/src/util/installation.util.tsx
+++ b/typescript/Frontend/src/util/installation.util.tsx
@@ -1,5 +1,5 @@
// TODO add if required or not
-export interface Installation {
+export interface I_Installation {
type: string;
title: string;
status: number;
@@ -8,7 +8,7 @@ export interface Installation {
location: string;
region: string;
country: string;
- orderNumbers: string;
+ orderNumber: string;
lat: number;
long: number;
s3Bucket: string;
@@ -17,3 +17,5 @@ export interface Installation {
information: string;
parentId: number;
}
+
+