update to git code before switching from fossil
This commit is contained in:
parent
9f1e1e4730
commit
dff51b0d53
|
@ -1,18 +1,114 @@
|
||||||
import Home from "./routes/Home";
|
|
||||||
import useToken from "./hooks/useToken";
|
import useToken from "./hooks/useToken";
|
||||||
import Login from "./Login";
|
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 App = () => {
|
||||||
const { token, setToken } = useToken();
|
const { token, setToken } = useToken();
|
||||||
|
const [language, setLanguage] = useState("en");
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return <Login setToken={setToken} />;
|
return <Login setToken={setToken} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const de = {
|
||||||
|
allInstallations: "Alle Installationen",
|
||||||
|
};
|
||||||
|
|
||||||
|
const en = {
|
||||||
|
allInstallations: "All installations",
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTranslations = () => {
|
||||||
|
if (language === "de") {
|
||||||
|
return de;
|
||||||
|
}
|
||||||
|
return en;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Home />
|
<IntlProvider
|
||||||
|
messages={getTranslations()}
|
||||||
|
locale={language}
|
||||||
|
defaultLocale="en"
|
||||||
|
>
|
||||||
|
<Box sx={{ padding: 2 }}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<ButtonGroup
|
||||||
|
variant="outlined"
|
||||||
|
aria-label="outlined primary button group"
|
||||||
|
sx={{ paddingBottom: 3 }}
|
||||||
|
>
|
||||||
|
<Button>
|
||||||
|
<FormattedMessage
|
||||||
|
id="allInstallations"
|
||||||
|
defaultMessage="All installations"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button>
|
||||||
|
<FormattedMessage id="users" defaultMessage="Users" />
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
<NestedList />
|
||||||
|
<Select
|
||||||
|
labelId="demo-simple-select-label"
|
||||||
|
id="demo-simple-select"
|
||||||
|
value={language}
|
||||||
|
label="Age"
|
||||||
|
onChange={(e) => setLanguage(e.target.value)}
|
||||||
|
>
|
||||||
|
<MenuItem value="en">
|
||||||
|
<FormattedMessage id="english" defaultMessage="English" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem value="de">
|
||||||
|
<FormattedMessage id="german" defaultMessage="German" />
|
||||||
|
</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={1}
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Divider orientation="vertical" variant="middle" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={8}>
|
||||||
|
<BasicTabs />
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path={routes.installationWithId}
|
||||||
|
element={<InstallationDetail />}
|
||||||
|
/>
|
||||||
|
<Route path={routes.alarmsWithId} element={<Alarms />} />
|
||||||
|
<Route path={routes.usersWithId} element={<BasicTable />} />
|
||||||
|
<Route path={routes.logWithId} element={<Log />} />
|
||||||
|
</Routes>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</IntlProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import axios from "axios";
|
import { Button, CircularProgress } from "@mui/material";
|
||||||
import { Button, CircularProgress, TextField } from "@mui/material";
|
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
|
import InnovenergyTextfield from "./components/InnovenergyTextfield";
|
||||||
|
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||||
|
|
||||||
const loginUser = async (username: string, password: string) => {
|
const loginUser = async (username: string, password: string) => {
|
||||||
return axios
|
return axiosConfigWithoutToken.post("/Login", {
|
||||||
.post("https://localhost:7087/api/Login", {
|
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
})
|
});
|
||||||
.then((data) => data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Login = ({ setToken }: { setToken: any }) => {
|
const Login = ({ setToken }: { setToken: any }) => {
|
||||||
|
@ -26,24 +25,27 @@ const Login = ({ setToken }: { setToken: any }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container maxWidth="xs" sx={{ p: 2, alignContent: "center" }}>
|
||||||
<TextField
|
<InnovenergyTextfield
|
||||||
id="outlined-basic"
|
id="username-textfield"
|
||||||
label="Username"
|
label="Username"
|
||||||
variant="outlined"
|
|
||||||
name="email"
|
name="email"
|
||||||
sx={{ my: 0.5 }}
|
value={username}
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
handleChange={(e) => setUsername(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<InnovenergyTextfield
|
||||||
id="outlined-password-input"
|
id="password-textfield"
|
||||||
label="Password"
|
label="Password"
|
||||||
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
autoComplete="current-password"
|
value={password}
|
||||||
sx={{ my: 0.5 }}
|
handleChange={(e) => setPassword(e.target.value)}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
|
||||||
/>
|
/>
|
||||||
<Button onClick={handleSubmit}>Login</Button>
|
<div>
|
||||||
|
<Button variant="outlined" onClick={handleSubmit} sx={{ my: 1 }}>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{loading && <CircularProgress />}
|
{loading && <CircularProgress />}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 (
|
||||||
|
<form onSubmit={formik.handleSubmit}>
|
||||||
|
<InnovenergyTextfield
|
||||||
|
id="name-textfield"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "customerName",
|
||||||
|
defaultMessage: "Customer name",
|
||||||
|
})}
|
||||||
|
name="name"
|
||||||
|
value={formik.values.name}
|
||||||
|
handleChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<InnovenergyTextfield
|
||||||
|
id="region-textfield"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "region",
|
||||||
|
defaultMessage: "Region",
|
||||||
|
})}
|
||||||
|
name="region"
|
||||||
|
value={formik.values.region}
|
||||||
|
handleChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<InnovenergyTextfield
|
||||||
|
id="location-textfield"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "location",
|
||||||
|
defaultMessage: "Location",
|
||||||
|
})}
|
||||||
|
name="location"
|
||||||
|
value={formik.values.location}
|
||||||
|
handleChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<InnovenergyTextfield
|
||||||
|
id="country-textfield"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "country",
|
||||||
|
defaultMessage: "Country",
|
||||||
|
})}
|
||||||
|
name="country"
|
||||||
|
value={formik.values.country}
|
||||||
|
handleChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<InnovenergyTextfield
|
||||||
|
id="orderNumber-textfield"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "orderNumber",
|
||||||
|
defaultMessage: "Order number",
|
||||||
|
})}
|
||||||
|
name="orderNumber"
|
||||||
|
value={formik.values.orderNumber}
|
||||||
|
handleChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<Button variant="outlined" type="submit">
|
||||||
|
<FormattedMessage id="applyChanges" defaultMessage="Apply changes" />
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomerForm;
|
|
@ -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<Node[]>(initialNodes);
|
||||||
|
const [edges, setEdges] = useState<Edge[]>(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 (
|
||||||
|
<ReactFlow
|
||||||
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
onConnect={onConnect}
|
||||||
|
fitView
|
||||||
|
fitViewOptions={fitViewOptions}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Flow;
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { TextField } from "@mui/material";
|
||||||
|
|
||||||
|
interface I_InnovenergyTextfieldProps {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
name: string;
|
||||||
|
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
type?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InnovenergyTextfield = (props: I_InnovenergyTextfieldProps) => {
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
id={props.id}
|
||||||
|
label={props.label}
|
||||||
|
variant="outlined"
|
||||||
|
name={props.name}
|
||||||
|
type={props.type}
|
||||||
|
fullWidth
|
||||||
|
sx={{ my: 0.5 }}
|
||||||
|
value={props.value || ""}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InnovenergyTextfield;
|
|
@ -1,14 +1,14 @@
|
||||||
import List from "@mui/material/List";
|
import List from "@mui/material/List";
|
||||||
import ListItemButton from "@mui/material/ListItemButton";
|
import ListItemButton from "@mui/material/ListItemButton";
|
||||||
import ListItemText from "@mui/material/ListItemText";
|
import ListItemText from "@mui/material/ListItemText";
|
||||||
import { Divider } from "@mui/material";
|
import { Divider, TextField } from "@mui/material";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import useRouteMatch from "../hooks/useRouteMatch";
|
import useRouteMatch from "../hooks/useRouteMatch";
|
||||||
import routes from "../routes.json";
|
import routes from "../routes.json";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import axios from "axios";
|
import { I_Installation } from "../util/installation.util";
|
||||||
import { Installation } from "../util/installation.util";
|
import axiosConfig from "../config/axiosConfig";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
const getPathWithoutId = (path?: string) => {
|
const getPathWithoutId = (path?: string) => {
|
||||||
if (path) {
|
if (path) {
|
||||||
|
@ -18,8 +18,26 @@ const getPathWithoutId = (path?: string) => {
|
||||||
return routes.installation;
|
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 NestedList = () => {
|
||||||
const [data, setData] = useState<Installation[]>();
|
const [data, setData] = useState<I_Installation[]>();
|
||||||
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
const intl = useIntl();
|
||||||
|
const filteredData = filterData(searchQuery, data);
|
||||||
|
|
||||||
const routeMatch = useRouteMatch([
|
const routeMatch = useRouteMatch([
|
||||||
routes.installationWithId,
|
routes.installationWithId,
|
||||||
routes.alarmsWithId,
|
routes.alarmsWithId,
|
||||||
|
@ -28,32 +46,41 @@ const NestedList = () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tokenString = sessionStorage.getItem("token");
|
axiosConfig
|
||||||
const token = tokenString !== null ? JSON.parse(tokenString) : "";
|
.get("https://localhost:7087/api/GetAllInstallations", {})
|
||||||
axios
|
|
||||||
.get("https://localhost:7087/api/GetAllInstallations", {
|
|
||||||
headers: {
|
|
||||||
auth: token,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setData(res.data);
|
setData(res.data);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<TextField
|
||||||
|
id="outlined-search"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: "search",
|
||||||
|
defaultMessage: "Search",
|
||||||
|
})}
|
||||||
|
type="search"
|
||||||
|
fullWidth
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
/>
|
||||||
<List
|
<List
|
||||||
sx={{ width: "100%", bgcolor: "background.paper" }}
|
sx={{ width: "100%", bgcolor: "background.paper" }}
|
||||||
component="nav"
|
component="nav"
|
||||||
aria-labelledby="nested-list-subheader"
|
aria-labelledby="nested-list-subheader"
|
||||||
>
|
>
|
||||||
{data?.map((installation) => (
|
{filteredData?.map((installation) => (
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
|
key={installation.id}
|
||||||
to={getPathWithoutId(routeMatch?.pattern?.path) + installation.id}
|
to={getPathWithoutId(routeMatch?.pattern?.path) + installation.id}
|
||||||
style={{ textDecoration: "none" }}
|
style={{ textDecoration: "none", color: "black" }}
|
||||||
|
>
|
||||||
|
<ListItemButton
|
||||||
|
selected={installation.id === Number(routeMatch?.params.id)}
|
||||||
>
|
>
|
||||||
<ListItemButton>
|
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={installation.location + " | " + installation.name}
|
primary={installation.location + " | " + installation.name}
|
||||||
/>
|
/>
|
||||||
|
@ -63,6 +90,7 @@ const NestedList = () => {
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Box from "@mui/material/Box";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import routes from "../routes.json";
|
import routes from "../routes.json";
|
||||||
import useRouteMatch from "../hooks/useRouteMatch";
|
import useRouteMatch from "../hooks/useRouteMatch";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
const BasicTabs = () => {
|
const BasicTabs = () => {
|
||||||
const routeMatch = useRouteMatch([
|
const routeMatch = useRouteMatch([
|
||||||
|
@ -15,31 +16,44 @@ const BasicTabs = () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const id = routeMatch?.params?.id;
|
const id = routeMatch?.params?.id;
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: "100%" }}>
|
<Box sx={{ width: "100%" }}>
|
||||||
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||||||
<Tabs value={routeMatch?.pattern?.path} aria-label="basic tabs example">
|
<Tabs value={routeMatch?.pattern?.path} aria-label="basic tabs example">
|
||||||
<Tab
|
<Tab
|
||||||
label="Installation"
|
label={intl.formatMessage({
|
||||||
|
id: "installation",
|
||||||
|
defaultMessage: "Installation",
|
||||||
|
})}
|
||||||
value={routes.installationWithId}
|
value={routes.installationWithId}
|
||||||
component={Link}
|
component={Link}
|
||||||
to={routes.installation + id}
|
to={routes.installation + id}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Alarms"
|
label={intl.formatMessage({
|
||||||
|
id: "alarms",
|
||||||
|
defaultMessage: "Alarms",
|
||||||
|
})}
|
||||||
value={routes.alarmsWithId}
|
value={routes.alarmsWithId}
|
||||||
component={Link}
|
component={Link}
|
||||||
to={routes.alarms + id}
|
to={routes.alarms + id}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Users"
|
label={intl.formatMessage({
|
||||||
|
id: "users",
|
||||||
|
defaultMessage: "Users",
|
||||||
|
})}
|
||||||
value={routes.usersWithId}
|
value={routes.usersWithId}
|
||||||
component={Link}
|
component={Link}
|
||||||
to={routes.users + id}
|
to={routes.users + id}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Log"
|
label={intl.formatMessage({
|
||||||
|
id: "log",
|
||||||
|
defaultMessage: "Log",
|
||||||
|
})}
|
||||||
value={routes.logWithId}
|
value={routes.logWithId}
|
||||||
component={Link}
|
component={Link}
|
||||||
to={routes.log + id}
|
to={routes.log + id}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export const axiosConfigWithoutToken = axios.create({
|
||||||
|
baseURL: "https://localhost:7087/api",
|
||||||
|
});
|
||||||
|
|
||||||
|
const axiosConfig = axios.create({
|
||||||
|
baseURL: "https://localhost:7087/api",
|
||||||
|
});
|
||||||
|
|
||||||
|
axiosConfig.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
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;
|
|
@ -1,22 +1,22 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import axiosConfig from "../config/axiosConfig";
|
||||||
const getToken = (): string => {
|
|
||||||
const tokenString = sessionStorage.getItem("token");
|
|
||||||
return tokenString !== null ? JSON.parse(tokenString).token : "";
|
|
||||||
};
|
|
||||||
|
|
||||||
const useToken = () => {
|
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) => {
|
const saveToken = (userToken: any) => {
|
||||||
setToken(userToken);
|
|
||||||
sessionStorage.setItem("token", JSON.stringify(userToken));
|
sessionStorage.setItem("token", JSON.stringify(userToken));
|
||||||
|
setToken(userToken);
|
||||||
|
axiosConfig.defaults.headers.common["auth"] = userToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setToken: saveToken,
|
setToken: saveToken,
|
||||||
token,
|
token,
|
||||||
getToken: getToken,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
const Alarms = () => {
|
||||||
|
return <div>alarms</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Alarms;
|
|
@ -1,93 +1,31 @@
|
||||||
import { Box, TextField } from "@mui/material";
|
import { Box, CircularProgress } from "@mui/material";
|
||||||
import axios from "axios";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
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 InstallationDetail = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
const [values, setValues] = useState<I_Installation>();
|
||||||
const [values, setValues] = useState<Installation>();
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tokenString = sessionStorage.getItem("token");
|
setLoading(true);
|
||||||
const token = tokenString !== null ? JSON.parse(tokenString) : "";
|
axiosConfig.get("/GetInstallationById?id=" + id).then((res) => {
|
||||||
axios
|
|
||||||
.get("https://localhost:7087/api/GetInstallationById?id=" + id, {
|
|
||||||
headers: {
|
|
||||||
auth: token,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
setValues(res.data);
|
setValues(res.data);
|
||||||
console.log(res.data);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
if (values && values.id.toString() === id) {
|
||||||
const { name, value } = e.target;
|
|
||||||
setValues({
|
|
||||||
...values,
|
|
||||||
[name]: value,
|
|
||||||
} as Installation);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (values) {
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ py: 3, width: 1 / 2 }}>
|
<Box sx={{ py: 3, width: 1 / 2 }}>
|
||||||
<TextField
|
<CustomerForm values={values} id={id} />
|
||||||
id="outlined-basic"
|
|
||||||
label="Customer name"
|
|
||||||
variant="outlined"
|
|
||||||
name="name"
|
|
||||||
type="text"
|
|
||||||
fullWidth
|
|
||||||
sx={{ my: 0.5 }}
|
|
||||||
value={values.name}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
id="outlined-basic"
|
|
||||||
label="Region"
|
|
||||||
variant="outlined"
|
|
||||||
name="region"
|
|
||||||
fullWidth
|
|
||||||
sx={{ my: 0.5 }}
|
|
||||||
value={values.region}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
id="outlined-basic"
|
|
||||||
label="Location"
|
|
||||||
variant="outlined"
|
|
||||||
name="location"
|
|
||||||
fullWidth
|
|
||||||
sx={{ my: 0.5 }}
|
|
||||||
value={values.location}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
id="outlined-basic"
|
|
||||||
label="Country"
|
|
||||||
variant="outlined"
|
|
||||||
name="country"
|
|
||||||
fullWidth
|
|
||||||
sx={{ my: 0.5 }}
|
|
||||||
value={values.country}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
id="outlined-basic"
|
|
||||||
label="Order number"
|
|
||||||
variant="outlined"
|
|
||||||
name="orderNumber"
|
|
||||||
fullWidth
|
|
||||||
sx={{ my: 0.5 }}
|
|
||||||
value={values.orderNumbers}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
} else if (loading) {
|
||||||
|
return <CircularProgress />;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 <div>log</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Log;
|
|
@ -1,5 +1,5 @@
|
||||||
// TODO add if required or not
|
// TODO add if required or not
|
||||||
export interface Installation {
|
export interface I_Installation {
|
||||||
type: string;
|
type: string;
|
||||||
title: string;
|
title: string;
|
||||||
status: number;
|
status: number;
|
||||||
|
@ -8,7 +8,7 @@ export interface Installation {
|
||||||
location: string;
|
location: string;
|
||||||
region: string;
|
region: string;
|
||||||
country: string;
|
country: string;
|
||||||
orderNumbers: string;
|
orderNumber: string;
|
||||||
lat: number;
|
lat: number;
|
||||||
long: number;
|
long: number;
|
||||||
s3Bucket: string;
|
s3Bucket: string;
|
||||||
|
@ -17,3 +17,5 @@ export interface Installation {
|
||||||
information: string;
|
information: string;
|
||||||
parentId: number;
|
parentId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue