Code refactoring, styling
This commit is contained in:
parent
6bf6399ed2
commit
1cb78f7a05
|
@ -78,7 +78,7 @@ const App = () => {
|
||||||
bgcolor={colors.greyLight}
|
bgcolor={colors.greyLight}
|
||||||
pt={3}
|
pt={3}
|
||||||
borderTop="2px solid"
|
borderTop="2px solid"
|
||||||
borderColor={colors.darkGrey}
|
borderColor={colors.borderColor}
|
||||||
flex="1 0 auto"
|
flex="1 0 auto"
|
||||||
>
|
>
|
||||||
<Container maxWidth="xl">
|
<Container maxWidth="xl">
|
||||||
|
|
|
@ -2,8 +2,9 @@ import { createContext, ReactNode, useCallback, useState } from "react";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
import { transformArrayToTree } from "../../util/group.util";
|
import { transformArrayToTree } from "../../util/group.util";
|
||||||
import { I_Folder, I_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
|
|
||||||
interface GroupContextProviderProps {
|
interface I_GroupContextProviderProps {
|
||||||
currentType: string;
|
currentType: string;
|
||||||
setCurrentType: (value: string) => void;
|
setCurrentType: (value: string) => void;
|
||||||
data: (I_Folder | I_Installation)[];
|
data: (I_Folder | I_Installation)[];
|
||||||
|
@ -11,10 +12,10 @@ interface GroupContextProviderProps {
|
||||||
fetchData: () => Promise<void>;
|
fetchData: () => Promise<void>;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
setLoading: (value: boolean) => void;
|
setLoading: (value: boolean) => void;
|
||||||
getError: boolean;
|
getError?: AxiosError;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GroupContext = createContext<GroupContextProviderProps>({
|
export const GroupContext = createContext<I_GroupContextProviderProps>({
|
||||||
currentType: "",
|
currentType: "",
|
||||||
setCurrentType: () => {},
|
setCurrentType: () => {},
|
||||||
data: [],
|
data: [],
|
||||||
|
@ -22,14 +23,14 @@ export const GroupContext = createContext<GroupContextProviderProps>({
|
||||||
fetchData: () => Promise.resolve(),
|
fetchData: () => Promise.resolve(),
|
||||||
loading: false,
|
loading: false,
|
||||||
setLoading: () => {},
|
setLoading: () => {},
|
||||||
getError: false,
|
getError: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const GroupContextProvider = ({ children }: { children: ReactNode }) => {
|
const GroupContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [currentType, setCurrentType] = useState("");
|
const [currentType, setCurrentType] = useState("");
|
||||||
const [data, setData] = useState<(I_Folder | I_Installation)[]>([]);
|
const [data, setData] = useState<(I_Folder | I_Installation)[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [getError, setGetError] = useState(false);
|
const [getError, setGetError] = useState<AxiosError>();
|
||||||
|
|
||||||
const fetchData = useCallback(async () => {
|
const fetchData = useCallback(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { createContext, ReactNode, useCallback, useState } from "react";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
import { I_Installation } from "../../util/types";
|
import { I_Installation } from "../../util/types";
|
||||||
|
|
||||||
interface InstallationContextProviderProps {
|
interface I_InstallationContextProviderProps {
|
||||||
data: I_Installation[];
|
data: I_Installation[];
|
||||||
setData: (value: I_Installation[]) => void;
|
setData: (value: I_Installation[]) => void;
|
||||||
fetchData: () => Promise<void>;
|
fetchData: () => Promise<void>;
|
||||||
|
@ -14,7 +14,7 @@ interface InstallationContextProviderProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InstallationsContext =
|
export const InstallationsContext =
|
||||||
createContext<InstallationContextProviderProps>({
|
createContext<I_InstallationContextProviderProps>({
|
||||||
data: [],
|
data: [],
|
||||||
setData: () => {},
|
setData: () => {},
|
||||||
fetchData: () => Promise.resolve(),
|
fetchData: () => Promise.resolve(),
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { createContext, ReactNode, useState } from "react";
|
import { createContext, ReactNode, useState } from "react";
|
||||||
import { TreeElement } from "../Installations/Log/CheckboxTree";
|
import { I_TreeElement } from "../Installations/Log/CheckboxTree";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
interface LogContextProviderProps {
|
interface I_LogContextProviderProps {
|
||||||
toggles: TreeElement[] | null;
|
toggles: I_TreeElement[] | null;
|
||||||
setToggles: (value: TreeElement[]) => void;
|
setToggles: (value: I_TreeElement[]) => void;
|
||||||
checkedToggles: string[];
|
checkedToggles: string[];
|
||||||
setChecked: (newValue: string) => void;
|
setChecked: (newValue: string) => void;
|
||||||
removeChecked: (value: string) => void;
|
removeChecked: (value: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogContext = createContext<LogContextProviderProps>({
|
export const LogContext = createContext<I_LogContextProviderProps>({
|
||||||
toggles: [],
|
toggles: [],
|
||||||
setToggles: () => {},
|
setToggles: () => {},
|
||||||
checkedToggles: [],
|
checkedToggles: [],
|
||||||
|
@ -19,7 +19,7 @@ export const LogContext = createContext<LogContextProviderProps>({
|
||||||
});
|
});
|
||||||
|
|
||||||
const LogContextProvider = ({ children }: { children: ReactNode }) => {
|
const LogContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [toggles, setToggles] = useState<TreeElement[] | null>(null);
|
const [toggles, setToggles] = useState<I_TreeElement[] | null>(null);
|
||||||
const [checkedToggles, setCheckedToggles] = useState<string[]>([]);
|
const [checkedToggles, setCheckedToggles] = useState<string[]>([]);
|
||||||
|
|
||||||
const setChecked = (newValue: string) => {
|
const setChecked = (newValue: string) => {
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
import { createContext, ReactNode, useState } from "react";
|
import { createContext, ReactNode, useState } from "react";
|
||||||
import { I_User } from "../../util/user.util";
|
import { I_S3Credentials } from "../../util/types";
|
||||||
import { I_Installation, S3Credentials } from "../../util/types";
|
|
||||||
import { UnixTime } from "../../dataCache/time";
|
import { UnixTime } from "../../dataCache/time";
|
||||||
import { FetchResult } from "../../dataCache/dataCache";
|
import { FetchResult } from "../../dataCache/dataCache";
|
||||||
import { DataRecord } from "../../dataCache/data";
|
import { DataRecord } from "../../dataCache/data";
|
||||||
import { S3Access } from "../../dataCache/S3/S3Access";
|
import { S3Access } from "../../dataCache/S3/S3Access";
|
||||||
import { parseCsv } from "../../util/graph.util";
|
import { parseCsv } from "../../util/graph.util";
|
||||||
|
|
||||||
interface S3CredentialsContextProviderProps {
|
interface I_S3CredentialsContextProviderProps {
|
||||||
s3Credentials?: S3Credentials;
|
s3Credentials?: I_S3Credentials;
|
||||||
saveS3Credentials: (credentials: S3Credentials, id: string) => void;
|
saveS3Credentials: (credentials: I_S3Credentials, id: string) => void;
|
||||||
fetchData: (timestamp: UnixTime) => Promise<FetchResult<DataRecord>>;
|
fetchData: (timestamp: UnixTime) => Promise<FetchResult<DataRecord>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const S3CredentialsContext =
|
export const S3CredentialsContext =
|
||||||
createContext<S3CredentialsContextProviderProps>({
|
createContext<I_S3CredentialsContextProviderProps>({
|
||||||
s3Credentials: {} as S3Credentials,
|
s3Credentials: {} as I_S3Credentials,
|
||||||
saveS3Credentials: () => {},
|
saveS3Credentials: () => {},
|
||||||
fetchData: () => ({} as Promise<FetchResult<DataRecord>>),
|
fetchData: () => ({} as Promise<FetchResult<DataRecord>>),
|
||||||
});
|
});
|
||||||
|
@ -25,9 +24,9 @@ const S3CredentialsContextProvider = ({
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
const [s3Credentials, setS3Credentials] = useState<S3Credentials>();
|
const [s3Credentials, setS3Credentials] = useState<I_S3Credentials>();
|
||||||
|
|
||||||
const saveS3Credentials = (credentials: S3Credentials, id: string) => {
|
const saveS3Credentials = (credentials: I_S3Credentials, id: string) => {
|
||||||
const s3Bucket = id + "-3e5b3069-214a-43ee-8d85-57d72000c19d";
|
const s3Bucket = id + "-3e5b3069-214a-43ee-8d85-57d72000c19d";
|
||||||
setS3Credentials({ s3Bucket, ...credentials });
|
setS3Credentials({ s3Bucket, ...credentials });
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { createContext, ReactNode, useState } from "react";
|
import { createContext, ReactNode, useState } from "react";
|
||||||
import { I_User } from "../../util/user.util";
|
import { I_User } from "../../util/user.util";
|
||||||
|
|
||||||
interface InstallationContextProviderProps {
|
interface I_InstallationContextProviderProps {
|
||||||
currentUser?: I_User;
|
currentUser?: I_User;
|
||||||
setCurrentUser: (value: I_User) => void;
|
setCurrentUser: (value: I_User) => void;
|
||||||
saveCurrentUser: (user: I_User) => void;
|
saveCurrentUser: (user: I_User) => void;
|
||||||
getCurrentUser: () => I_User;
|
getCurrentUser: () => I_User;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserContext = createContext<InstallationContextProviderProps>({
|
export const UserContext = createContext<I_InstallationContextProviderProps>({
|
||||||
currentUser: {} as I_User,
|
currentUser: {} as I_User,
|
||||||
setCurrentUser: () => {},
|
setCurrentUser: () => {},
|
||||||
saveCurrentUser: () => {},
|
saveCurrentUser: () => {},
|
||||||
|
|
|
@ -8,14 +8,14 @@ import {
|
||||||
} from "react";
|
} from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
import { I_User, UserWithInheritedAccess } from "../../util/user.util";
|
import { I_User, I_UserWithInheritedAccess } from "../../util/user.util";
|
||||||
import { GroupContext } from "./GroupContextProvider";
|
import { GroupContext } from "./GroupContextProvider";
|
||||||
|
|
||||||
interface UsersContextProviderProps {
|
interface I_UsersContextProviderProps {
|
||||||
directAccessUsers: I_User[];
|
directAccessUsers: I_User[];
|
||||||
setDirectAccessUsers: (value: I_User[]) => void;
|
setDirectAccessUsers: (value: I_User[]) => void;
|
||||||
inheritedAccessUsers: UserWithInheritedAccess[];
|
inheritedAccessUsers: I_UserWithInheritedAccess[];
|
||||||
setInheritedAccessUsers: (value: UserWithInheritedAccess[]) => void;
|
setInheritedAccessUsers: (value: I_UserWithInheritedAccess[]) => void;
|
||||||
availableUsers: I_User[];
|
availableUsers: I_User[];
|
||||||
setAvailableUsers: (value: I_User[]) => void;
|
setAvailableUsers: (value: I_User[]) => void;
|
||||||
getAvailableUsersForResource: () => I_User[];
|
getAvailableUsersForResource: () => I_User[];
|
||||||
|
@ -24,7 +24,7 @@ interface UsersContextProviderProps {
|
||||||
fetchAvailableUsers: () => Promise<void>;
|
fetchAvailableUsers: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UsersContext = createContext<UsersContextProviderProps>({
|
export const UsersContext = createContext<I_UsersContextProviderProps>({
|
||||||
directAccessUsers: [],
|
directAccessUsers: [],
|
||||||
setDirectAccessUsers: () => {},
|
setDirectAccessUsers: () => {},
|
||||||
inheritedAccessUsers: [],
|
inheritedAccessUsers: [],
|
||||||
|
@ -48,7 +48,7 @@ export const UsersContext = createContext<UsersContextProviderProps>({
|
||||||
const UsersContextProvider = ({ children }: { children: ReactNode }) => {
|
const UsersContextProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [directAccessUsers, setDirectAccessUsers] = useState<I_User[]>([]);
|
const [directAccessUsers, setDirectAccessUsers] = useState<I_User[]>([]);
|
||||||
const [inheritedAccessUsers, setInheritedAccessUsers] = useState<
|
const [inheritedAccessUsers, setInheritedAccessUsers] = useState<
|
||||||
UserWithInheritedAccess[]
|
I_UserWithInheritedAccess[]
|
||||||
>([]);
|
>([]);
|
||||||
const [availableUsers, setAvailableUsers] = useState<I_User[]>([]);
|
const [availableUsers, setAvailableUsers] = useState<I_User[]>([]);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Fragment, useContext, useEffect } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
filterDuplicateUsers,
|
filterDuplicateUsers,
|
||||||
UserWithInheritedAccess,
|
I_UserWithInheritedAccess,
|
||||||
} from "../../../util/user.util";
|
} from "../../../util/user.util";
|
||||||
import routes from "../../../routes.json";
|
import routes from "../../../routes.json";
|
||||||
import PersonIcon from "@mui/icons-material/Person";
|
import PersonIcon from "@mui/icons-material/Person";
|
||||||
|
@ -29,7 +29,7 @@ const UsersWithInheritedAccess = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{filterDuplicateUsers(inheritedAccessUsers).map(
|
{filterDuplicateUsers(inheritedAccessUsers).map(
|
||||||
({ user, folderName }: UserWithInheritedAccess) => {
|
({ user, folderName }: I_UserWithInheritedAccess) => {
|
||||||
return (
|
return (
|
||||||
<Fragment key={user.id}>
|
<Fragment key={user.id}>
|
||||||
<ListItem id={"inherited-access-user-list-item" + user.id}>
|
<ListItem id={"inherited-access-user-list-item" + user.id}>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { useState } from "react";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
import { I_Folder, I_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
import FolderForm from "./Detail/FolderForm";
|
import FolderForm from "./Detail/FolderForm";
|
||||||
|
|
|
@ -5,13 +5,13 @@ import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { ReactNode, useState } from "react";
|
import { ReactNode, useState } from "react";
|
||||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||||
|
|
||||||
interface AddNewDialogProps {
|
interface I_AddNewDialogProps {
|
||||||
form: ReactNode;
|
form: ReactNode;
|
||||||
message: ReactNode;
|
message: ReactNode;
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddNewDialog = (props: AddNewDialogProps) => {
|
const AddNewDialog = (props: I_AddNewDialogProps) => {
|
||||||
const { form, id, message } = props;
|
const { form, id, message } = props;
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
|
@ -53,7 +53,6 @@ const Folder = () => {
|
||||||
borderBottomLeftRadius: 4,
|
borderBottomLeftRadius: 4,
|
||||||
borderBottomRightRadius: 4,
|
borderBottomRightRadius: 4,
|
||||||
borderColor: theme.palette.text.disabled,
|
borderColor: theme.palette.text.disabled,
|
||||||
marginTop: 0.05,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FolderForm
|
<FolderForm
|
||||||
|
|
|
@ -9,11 +9,11 @@ import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
import InnovenergyButton from "../../Layout/InnovenergyButton";
|
import InnovenergyButton from "../../Layout/InnovenergyButton";
|
||||||
import MoveTree from "./MoveTree";
|
import MoveTree from "./MoveTree";
|
||||||
|
|
||||||
interface MoveDialogProps {
|
interface I_MoveDialogProps {
|
||||||
values: I_Folder;
|
values: I_Folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MoveDialog = (props: MoveDialogProps) => {
|
const MoveDialog = (props: I_MoveDialogProps) => {
|
||||||
const { values } = props;
|
const { values } = props;
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
|
@ -8,12 +8,12 @@ import { instanceOfFolder } from "../../../util/group.util";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import InnovenergyTreeItem from "../../Layout/InnovenergyTreeItem";
|
import InnovenergyTreeItem from "../../Layout/InnovenergyTreeItem";
|
||||||
|
|
||||||
interface MoveTreeProps {
|
interface I_MoveTreeProps {
|
||||||
setSelectedParentId: (value: number) => void;
|
setSelectedParentId: (value: number) => void;
|
||||||
parentId: number;
|
parentId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MoveTree = (props: MoveTreeProps) => {
|
const MoveTree = (props: I_MoveTreeProps) => {
|
||||||
const { data } = useContext(GroupContext);
|
const { data } = useContext(GroupContext);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ const GroupTabs = () => {
|
||||||
|
|
||||||
const id = routeMatch?.params?.id;
|
const id = routeMatch?.params?.id;
|
||||||
|
|
||||||
|
console.log("fuck", routeMatch?.pattern?.path, currentType);
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: "100%" }}>
|
<Box sx={{ width: "100%" }}>
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import TreeView from "@mui/lab/TreeView";
|
import TreeView from "@mui/lab/TreeView";
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
import { ReactNode, useContext, useEffect, useState } from "react";
|
import React, { ReactNode, useContext, useEffect, useState } from "react";
|
||||||
import { I_Folder, I_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import routes from "../../routes.json";
|
import routes from "../../routes.json";
|
||||||
import { GroupContext } from "../Context/GroupContextProvider";
|
import { GroupContext } from "../Context/GroupContextProvider";
|
||||||
import { instanceOfFolder } from "../../util/group.util";
|
import { instanceOfFolder } from "../../util/group.util";
|
||||||
import { Grid, CircularProgress, useTheme } from "@mui/material";
|
import { Grid, CircularProgress, useTheme, Alert } from "@mui/material";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import InnovenergyTreeItem from "../Layout/InnovenergyTreeItem";
|
import InnovenergyTreeItem from "../Layout/InnovenergyTreeItem";
|
||||||
import TypeIcon from "./TypeIcon";
|
import TypeIcon from "./TypeIcon";
|
||||||
|
|
||||||
const GroupTree = () => {
|
const GroupTree = () => {
|
||||||
const { setCurrentType, fetchData, data, loading } = useContext(GroupContext);
|
const { setCurrentType, fetchData, data, loading, getError } =
|
||||||
|
useContext(GroupContext);
|
||||||
const [openNodes, setOpenNodes] = useState<string[]>([]);
|
const [openNodes, setOpenNodes] = useState<string[]>([]);
|
||||||
const [selected, setSelected] = useState<string>("");
|
const [selected, setSelected] = useState<string>("");
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
@ -56,7 +57,11 @@ const GroupTree = () => {
|
||||||
<TypeIcon type={element.type} /> {element.name}
|
<TypeIcon type={element.type} /> {element.name}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
onClick={() => setCurrentType(element.type)}
|
onClick={() => {
|
||||||
|
console.log("fuck", element.type);
|
||||||
|
setCurrentType(element.type);
|
||||||
|
}}
|
||||||
|
sx={{ ".MuiTreeItem-label": { display: "flex" } }}
|
||||||
>
|
>
|
||||||
{getNodes(element)}
|
{getNodes(element)}
|
||||||
</InnovenergyTreeItem>
|
</InnovenergyTreeItem>
|
||||||
|
@ -100,6 +105,8 @@ const GroupTree = () => {
|
||||||
{renderTree(data)}
|
{renderTree(data)}
|
||||||
</TreeView>
|
</TreeView>
|
||||||
);
|
);
|
||||||
|
} else if (getError) {
|
||||||
|
return <Alert severity="error">{getError.message} </Alert>;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import FolderIcon from "@mui/icons-material/Folder";
|
import FolderIcon from "@mui/icons-material/Folder";
|
||||||
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
|
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
|
||||||
|
|
||||||
interface TypeIconProps {
|
interface I_TypeIconProps {
|
||||||
type: string | undefined;
|
type: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeIcon = (props: TypeIconProps) => {
|
const TypeIcon = (props: I_TypeIconProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{props.type === "Folder" ? (
|
{props.type === "Folder" ? (
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import { Alert, Box, CircularProgress, useTheme } from "@mui/material";
|
import { Alert, Box, CircularProgress, useTheme } from "@mui/material";
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
import { useContext, useEffect, useState } from "react";
|
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import axiosConfig from "../../../config/axiosConfig";
|
import axiosConfig from "../../../config/axiosConfig";
|
||||||
import { I_Folder, I_Installation } from "../../../util/types";
|
import { I_Folder, I_Installation } from "../../../util/types";
|
||||||
import InstallationForm from "./InstallationForm";
|
import InstallationForm from "./InstallationForm";
|
||||||
import { colors } from "../../../index";
|
|
||||||
import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider";
|
|
||||||
import MoveDialog from "../../Groups/Detail/MoveDialog";
|
import MoveDialog from "../../Groups/Detail/MoveDialog";
|
||||||
|
|
||||||
interface I_InstallationProps {
|
interface I_InstallationProps {
|
||||||
|
@ -46,7 +43,7 @@ const Installation = (props: I_InstallationProps) => {
|
||||||
<InstallationForm
|
<InstallationForm
|
||||||
values={values}
|
values={values}
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
additionalButtons={props.hasMoveButton ? [moveDialog] : []}
|
additionalButtons={props.hasMoveButton ? [moveDialog] : undefined}
|
||||||
/>
|
/>
|
||||||
<Box>
|
<Box>
|
||||||
{values.s3WriteKey && <div>{`Write key: ${values.s3WriteKey}`}</div>}
|
{values.s3WriteKey && <div>{`Write key: ${values.s3WriteKey}`}</div>}
|
||||||
|
|
|
@ -8,8 +8,9 @@ import InnovenergyButton from "../../Layout/InnovenergyButton";
|
||||||
import { I_InnovenergyTextfieldProps } from "../../Layout/InnovenergyTextfield";
|
import { I_InnovenergyTextfieldProps } from "../../Layout/InnovenergyTextfield";
|
||||||
import { UserContext } from "../../Context/UserContextProvider";
|
import { UserContext } from "../../Context/UserContextProvider";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosError, AxiosResponse } from "axios";
|
||||||
import InnovenergyPropertyGrid from "../../Layout/InnovenergyPropertyGrid";
|
import InnovenergyPropertyGrid from "../../Layout/InnovenergyPropertyGrid";
|
||||||
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
|
|
||||||
interface I_InstallationFormProps {
|
interface I_InstallationFormProps {
|
||||||
values: I_Installation;
|
values: I_Installation;
|
||||||
|
@ -23,8 +24,11 @@ interface I_InstallationFormProps {
|
||||||
const InstallationForm = (props: I_InstallationFormProps) => {
|
const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
const { values, additionalButtons, handleSubmit } = props;
|
const { values, additionalButtons, handleSubmit } = props;
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [error, setError] = useState<AxiosError>();
|
||||||
|
|
||||||
|
const { fetchData: fetchInstallations } = useContext(InstallationsContext);
|
||||||
|
const { fetchData: fetchGroups } = useContext(GroupContext);
|
||||||
|
|
||||||
const { fetchData } = useContext(InstallationsContext);
|
|
||||||
const { getCurrentUser } = useContext(UserContext);
|
const { getCurrentUser } = useContext(UserContext);
|
||||||
|
|
||||||
const readOnly = !getCurrentUser().hasWriteAccess;
|
const readOnly = !getCurrentUser().hasWriteAccess;
|
||||||
|
@ -62,9 +66,16 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
onSubmit: (formikValues) => {
|
onSubmit: (formikValues) => {
|
||||||
handleSubmit(values, formikValues)
|
handleSubmit(values, formikValues)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
fetchData();
|
setOpen(true);
|
||||||
|
console.log(additionalButtons, "addbuttons");
|
||||||
|
additionalButtons && additionalButtons.length > 0
|
||||||
|
? fetchGroups()
|
||||||
|
: fetchInstallations();
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {
|
||||||
|
setError(err);
|
||||||
|
setOpen(true);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
});
|
});
|
||||||
|
@ -171,10 +182,14 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
>
|
>
|
||||||
<Alert onClose={handleClose} severity="success" sx={{ width: "100%" }}>
|
<Alert onClose={handleClose} severity="success" sx={{ width: "100%" }}>
|
||||||
<FormattedMessage
|
{error ? (
|
||||||
id="updatedSuccessfully"
|
error.message
|
||||||
defaultMessage="Updated successfully"
|
) : (
|
||||||
/>
|
<FormattedMessage
|
||||||
|
id="updatedSuccessfully"
|
||||||
|
defaultMessage="Updated successfully"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
</Snackbar>
|
</Snackbar>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Grid, colors } from "@mui/material";
|
import { Grid } from "@mui/material";
|
||||||
import { Routes, Route } from "react-router";
|
import { Routes, Route } from "react-router";
|
||||||
import LiveView from "./LiveView/LiveView";
|
import LiveView from "./LiveView/LiveView";
|
||||||
import InstallationTabs from "./InstallationTabs";
|
import InstallationTabs from "./InstallationTabs";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import TopologyView from "./TopologyView";
|
import TopologyView from "./TopologyView";
|
||||||
import { Box, useTheme } from "@mui/material";
|
import { Box, useTheme } from "@mui/material";
|
||||||
import { colors } from "../../../index";
|
|
||||||
|
|
||||||
const LiveView = () => {
|
const LiveView = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { getBoxColor } from "../../../util/graph.util";
|
import { getBoxColor } from "../../../util/graph.util";
|
||||||
|
|
||||||
export interface BoxDataValue {
|
export interface I_BoxDataValue {
|
||||||
unit: string;
|
unit: string;
|
||||||
value: string | number;
|
value: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BoxData = {
|
export type BoxData = {
|
||||||
label: string;
|
label: string;
|
||||||
values: BoxDataValue[];
|
values: I_BoxDataValue[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TopologyBoxProps = {
|
export type TopologyBoxProps = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Alert, Box, useTheme } from "@mui/material";
|
import { Alert, Box } from "@mui/material";
|
||||||
import TopologyColumn from "./TopologyColumn";
|
import TopologyColumn from "./TopologyColumn";
|
||||||
import { TimeSpan, UnixTime } from "../../../dataCache/time";
|
import { TimeSpan, UnixTime } from "../../../dataCache/time";
|
||||||
import {
|
import {
|
||||||
|
@ -224,7 +224,6 @@ const TopologyView = () => {
|
||||||
/>
|
/>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
return <div>TopologyView</div>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TopologyView;
|
export default TopologyView;
|
||||||
|
|
|
@ -9,10 +9,10 @@ import routes from "../../../routes.json";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import InnovenergyTreeItem from "../../Layout/InnovenergyTreeItem";
|
import InnovenergyTreeItem from "../../Layout/InnovenergyTreeItem";
|
||||||
|
|
||||||
export interface TreeElement {
|
export interface I_TreeElement {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
children: TreeElement[];
|
children: I_TreeElement[];
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ const CheckboxTree = () => {
|
||||||
routes.installations + routes.list + routes.log + ":id",
|
routes.installations + routes.list + routes.log + ":id",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const getNodes = (element: TreeElement): null | ReactNode => {
|
const getNodes = (element: I_TreeElement): null | ReactNode => {
|
||||||
return element.children.length > 0 ? renderTree(element.children) : null;
|
return element.children.length > 0 ? renderTree(element.children) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = (
|
const handleClick = (
|
||||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||||
element: TreeElement,
|
element: I_TreeElement,
|
||||||
checked?: string
|
checked?: string
|
||||||
) => {
|
) => {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
@ -46,7 +46,7 @@ const CheckboxTree = () => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderTree = (data: TreeElement[]): ReactNode => {
|
const renderTree = (data: I_TreeElement[]): ReactNode => {
|
||||||
return data.map((element) => {
|
return data.map((element) => {
|
||||||
const checked = checkedToggles.find((toggle) => element.id === toggle);
|
const checked = checkedToggles.find((toggle) => element.id === toggle);
|
||||||
const splitName = element.name.split("/");
|
const splitName = element.name.split("/");
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { useTheme } from "@mui/material";
|
||||||
import { colors } from "../../../../index";
|
import { colors } from "../../../../index";
|
||||||
import ShortcutButton from "./ShortcutButton";
|
import ShortcutButton from "./ShortcutButton";
|
||||||
|
|
||||||
interface DateRangePickerProps {
|
interface I_DateRangePickerProps {
|
||||||
setRange: (value: Date[]) => void;
|
setRange: (value: Date[]) => void;
|
||||||
range: Date[];
|
range: Date[];
|
||||||
getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void;
|
getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DateRangePicker = (props: DateRangePickerProps) => {
|
const DateRangePicker = (props: I_DateRangePickerProps) => {
|
||||||
const { setRange, range, getCacheSeries } = props;
|
const { setRange, range, getCacheSeries } = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { UnixTime, TimeSpan } from "../../../../dataCache/time";
|
||||||
import { createTimes } from "../../../../util/graph.util";
|
import { createTimes } from "../../../../util/graph.util";
|
||||||
import InnovenergyButton from "../../../Layout/InnovenergyButton";
|
import InnovenergyButton from "../../../Layout/InnovenergyButton";
|
||||||
|
|
||||||
interface ShortcutButtonProps {
|
interface I_ShortcutButtonProps {
|
||||||
setRange: (value: Date[]) => void;
|
setRange: (value: Date[]) => void;
|
||||||
getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void;
|
getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void;
|
||||||
dayRange: number;
|
dayRange: number;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortcutButton = (props: ShortcutButtonProps) => {
|
const ShortcutButton = (props: I_ShortcutButtonProps) => {
|
||||||
return (
|
return (
|
||||||
<InnovenergyButton
|
<InnovenergyButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Plot from "react-plotly.js";
|
import Plot from "react-plotly.js";
|
||||||
import { RecordSeries } from "../../../dataCache/data";
|
import { RecordSeries } from "../../../dataCache/data";
|
||||||
import {
|
import {
|
||||||
GraphData,
|
I_GraphData,
|
||||||
createTimes,
|
createTimes,
|
||||||
getTreeElements,
|
getTreeElements,
|
||||||
isNumeric,
|
isNumeric,
|
||||||
|
@ -11,15 +11,15 @@ import {
|
||||||
import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time";
|
import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time";
|
||||||
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||||
import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs";
|
import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs";
|
||||||
import DataCache, { FetchResult } from "../../../dataCache/dataCache";
|
import DataCache from "../../../dataCache/dataCache";
|
||||||
import { LogContext } from "../../Context/LogContextProvider";
|
import { LogContext } from "../../Context/LogContextProvider";
|
||||||
import { isDefined } from "../../../dataCache/utils/maybe";
|
import { isDefined } from "../../../dataCache/utils/maybe";
|
||||||
import { Data, Icons, Layout, PlotRelayoutEvent } from "plotly.js";
|
import { Data, Layout, PlotRelayoutEvent } from "plotly.js";
|
||||||
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
|
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import DateRangePicker from "./DatePicker/DateRangePicker";
|
import DateRangePicker from "./DatePicker/DateRangePicker";
|
||||||
import { LocalizationProvider } from "@mui/x-date-pickers";
|
import { LocalizationProvider } from "@mui/x-date-pickers";
|
||||||
import { Alert, useTheme } from "@mui/material";
|
import { Alert } from "@mui/material";
|
||||||
import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider";
|
import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider";
|
||||||
|
|
||||||
const NUMBER_OF_NODES = 100;
|
const NUMBER_OF_NODES = 100;
|
||||||
|
@ -66,7 +66,7 @@ const ScalarGraph = () => {
|
||||||
return () => subscription.unsubscribe();
|
return () => subscription.unsubscribe();
|
||||||
}, [toggles]);
|
}, [toggles]);
|
||||||
|
|
||||||
const transformToGraphData = (input: RecordSeries): GraphData => {
|
const transformToGraphData = (input: RecordSeries): I_GraphData => {
|
||||||
const transformedObject: any = {};
|
const transformedObject: any = {};
|
||||||
|
|
||||||
input.forEach((item) => {
|
input.forEach((item) => {
|
||||||
|
@ -101,7 +101,7 @@ const ScalarGraph = () => {
|
||||||
y: [],
|
y: [],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{} as GraphData
|
{} as I_GraphData
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Button, SxProps, Theme, colors, useTheme } from "@mui/material";
|
import { Button, SxProps, Theme, useTheme } from "@mui/material";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
interface I_InnovenergyButtonProps {
|
interface I_InnovenergyButtonProps {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { List, useTheme } from "@mui/material";
|
import { List, useTheme } from "@mui/material";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
interface InnovenergyListProps {
|
interface I_InnovenergyListProps {
|
||||||
id: string;
|
id: string;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnovenergyList = (props: InnovenergyListProps) => {
|
const InnovenergyList = (props: I_InnovenergyListProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
|
|
|
@ -2,12 +2,12 @@ import { InputLabel, TextField } from "@mui/material";
|
||||||
import { colors } from "../../index";
|
import { colors } from "../../index";
|
||||||
import { I_InnovenergyTextfieldProps } from "./InnovenergyTextfield";
|
import { I_InnovenergyTextfieldProps } from "./InnovenergyTextfield";
|
||||||
|
|
||||||
interface InnovenergyPropertyGridProps {
|
interface I_InnovenergyPropertyGridProps {
|
||||||
rows: I_InnovenergyTextfieldProps[];
|
rows: I_InnovenergyTextfieldProps[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InnovenergyPropertyGrid = (
|
export const InnovenergyPropertyGrid = (
|
||||||
props: InnovenergyPropertyGridProps
|
props: I_InnovenergyPropertyGridProps
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { Alert, Snackbar } from "@mui/material";
|
import { Alert, Snackbar } from "@mui/material";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
interface InnovenergySnackbarProps {
|
interface I_InnovenergySnackbarProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (value: boolean) => void;
|
setOpen: (value: boolean) => void;
|
||||||
error?: any;
|
error?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnovenergySnackbar = (props: InnovenergySnackbarProps) => {
|
const InnovenergySnackbar = (props: I_InnovenergySnackbarProps) => {
|
||||||
const { open, setOpen, error } = props;
|
const { open, setOpen, error } = props;
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { SxProps, Tabs, useTheme } from "@mui/material";
|
import { Tabs, useTheme } from "@mui/material";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { colors } from "index";
|
import { colors } from "index";
|
||||||
|
|
||||||
interface AntTabsProps {
|
interface I_AntTabsProps {
|
||||||
id: string;
|
id: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
sx?: any;
|
sx?: any;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnovenergyTabs = (props: AntTabsProps) => {
|
const InnovenergyTabs = (props: I_AntTabsProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|
|
@ -9,7 +9,7 @@ const InnovenergyTreeItem = (props: TreeItemProps) => {
|
||||||
id={props.id}
|
id={props.id}
|
||||||
nodeId={props.nodeId}
|
nodeId={props.nodeId}
|
||||||
label={props.label}
|
label={props.label}
|
||||||
onClick={() => props.onClick}
|
onClick={props.onClick}
|
||||||
sx={{
|
sx={{
|
||||||
".MuiTreeItem-content": {
|
".MuiTreeItem-content": {
|
||||||
py: "10px",
|
py: "10px",
|
||||||
|
@ -30,6 +30,7 @@ const InnovenergyTreeItem = (props: TreeItemProps) => {
|
||||||
},
|
},
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
bgcolor: colors.greyDark,
|
bgcolor: colors.greyDark,
|
||||||
|
...props.sx,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { MenuItem, Select } from "@mui/material";
|
import { MenuItem, Select } from "@mui/material";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
interface LanguageSelectProps {
|
interface I_LanguageSelectProps {
|
||||||
language: string;
|
language: string;
|
||||||
setLanguage: (language: string) => void;
|
setLanguage: (language: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LanguageSelect = (props: LanguageSelectProps) => {
|
const LanguageSelect = (props: I_LanguageSelectProps) => {
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|
|
@ -4,11 +4,11 @@ import axiosConfig from "../../config/axiosConfig";
|
||||||
import InnovenergyButton from "./InnovenergyButton";
|
import InnovenergyButton from "./InnovenergyButton";
|
||||||
import { useTheme } from "@mui/material";
|
import { useTheme } from "@mui/material";
|
||||||
|
|
||||||
interface LogoutButtonProps {
|
interface I_LogoutButtonProps {
|
||||||
removeToken: () => void;
|
removeToken: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LogoutButton = (props: LogoutButtonProps) => {
|
const LogoutButton = (props: I_LogoutButtonProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
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";
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {
|
||||||
OutlinedInputProps,
|
OutlinedInputProps,
|
||||||
TextField,
|
TextField,
|
||||||
TextFieldProps,
|
TextFieldProps,
|
||||||
alpha,
|
|
||||||
styled,
|
styled,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
@ -10,7 +9,7 @@ import { colors } from "index";
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
interface SearchSidebarProps {
|
interface I_SearchSidebarProps {
|
||||||
listComponent: FC<{ searchQuery: string }>;
|
listComponent: FC<{ searchQuery: string }>;
|
||||||
id: string;
|
id: string;
|
||||||
height?: string;
|
height?: string;
|
||||||
|
@ -45,11 +44,10 @@ const SearchInputTextfield = styled((props: TextFieldProps) => (
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const SearchSidebar = (props: SearchSidebarProps) => {
|
const SearchSidebar = (props: I_SearchSidebarProps) => {
|
||||||
const { listComponent: ListComponent, id, height } = props;
|
const { listComponent: ListComponent, id, height } = props;
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: height ?? "750px", overflow: "hidden" }}>
|
<div style={{ height: height ?? "750px", overflow: "hidden" }}>
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { Dialog, DialogTitle, IconButton, DialogContent } from "@mui/material";
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
IconButton,
|
|
||||||
DialogContent,
|
|
||||||
colors,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { Box, CircularProgress, Alert, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
CircularProgress,
|
|
||||||
Alert,
|
|
||||||
collapseClasses,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
|
@ -28,11 +28,11 @@ const filterData = (searchQuery: string, data: I_User[] | undefined) => {
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface UserListProps {
|
interface I_UserListProps {
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserList = (props: UserListProps) => {
|
const UserList = (props: I_UserListProps) => {
|
||||||
const { availableUsers } = useContext(UsersContext);
|
const { availableUsers } = useContext(UsersContext);
|
||||||
const filteredData = filterData(props.searchQuery, availableUsers);
|
const filteredData = filterData(props.searchQuery, availableUsers);
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { Maybe } from "yup";
|
import { Maybe } from "yup";
|
||||||
import { Timestamped } from "./types";
|
import { Timestamped } from "./types";
|
||||||
import { isDefined } from "./utils/maybe";
|
import { isDefined } from "./utils/maybe";
|
||||||
import { CsvEntry } from "../util/graph.util";
|
import { I_CsvEntry } from "../util/graph.util";
|
||||||
|
|
||||||
export type DataRecord = Record<string, CsvEntry>;
|
export type DataRecord = Record<string, I_CsvEntry>;
|
||||||
|
|
||||||
export type DataPoint = Timestamped<Maybe<DataRecord>>;
|
export type DataPoint = Timestamped<Maybe<DataRecord>>;
|
||||||
export type RecordSeries = Array<DataPoint>;
|
export type RecordSeries = Array<DataPoint>;
|
||||||
export type PointSeries = Array<Timestamped<Maybe<CsvEntry>>>;
|
export type PointSeries = Array<Timestamped<Maybe<I_CsvEntry>>>;
|
||||||
export type DataSeries = Array<Maybe<CsvEntry>>;
|
export type DataSeries = Array<Maybe<I_CsvEntry>>;
|
||||||
|
|
||||||
export function getPoints(
|
export function getPoints(
|
||||||
recordSeries: RecordSeries,
|
recordSeries: RecordSeries,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SkipListNode } from "./skipList/skipListNode";
|
||||||
import { RecordSeries } from "./data";
|
import { RecordSeries } from "./data";
|
||||||
import { isUndefined, Maybe } from "./utils/maybe";
|
import { isUndefined, Maybe } from "./utils/maybe";
|
||||||
import { isNumber } from "./utils/runtimeTypeChecking";
|
import { isNumber } from "./utils/runtimeTypeChecking";
|
||||||
import { CsvEntry } from "../util/graph.util";
|
import { I_CsvEntry } from "../util/graph.util";
|
||||||
|
|
||||||
export const FetchResult = {
|
export const FetchResult = {
|
||||||
notAvailable: "N/A",
|
notAvailable: "N/A",
|
||||||
|
@ -31,7 +31,7 @@ function reverseBits(x: number): number {
|
||||||
return x >>> 0;
|
return x >>> 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class DataCache<T extends Record<string, CsvEntry>> {
|
export default class DataCache<T extends Record<string, I_CsvEntry>> {
|
||||||
private readonly cache: SkipList<Maybe<T>> = new SkipList<Maybe<T>>();
|
private readonly cache: SkipList<Maybe<T>> = new SkipList<Maybe<T>>();
|
||||||
private readonly resolution: TimeSpan;
|
private readonly resolution: TimeSpan;
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ export default class DataCache<T extends Record<string, CsvEntry>> {
|
||||||
const n = after.index - t;
|
const n = after.index - t;
|
||||||
const pn = p + n;
|
const pn = p + n;
|
||||||
|
|
||||||
let interpolated: Record<string, CsvEntry> = {};
|
let interpolated: Record<string, I_CsvEntry> = {};
|
||||||
|
|
||||||
//What about string nodes? like Alarms
|
//What about string nodes? like Alarms
|
||||||
for (const k of Object.keys(dataBefore)) {
|
for (const k of Object.keys(dataBefore)) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
|
monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f3f4f7;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
import "./index.css";
|
||||||
import reportWebVitals from "./reportWebVitals";
|
import reportWebVitals from "./reportWebVitals";
|
||||||
import { createTheme, ThemeProvider } from "@mui/material";
|
import { createTheme, ThemeProvider } from "@mui/material";
|
||||||
import UserContextProvider from "./components/Context/UserContextProvider";
|
import UserContextProvider from "./components/Context/UserContextProvider";
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
|
import { t } from "testcafe";
|
||||||
import {Selector, t} from 'testcafe';
|
|
||||||
|
|
||||||
export async function login(name, pw) {
|
export async function login(name, pw) {
|
||||||
await t
|
await t
|
||||||
.typeText('#username-textfield', name)
|
.typeText("#username-textfield", name)
|
||||||
.typeText('#password-textfield', pw)
|
.typeText("#password-textfield", pw)
|
||||||
.click('.MuiButtonBase-root') //todo id
|
.click(".MuiButtonBase-root"); //todo id
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logout() {
|
export async function logout() {
|
||||||
await t
|
await t.click(".MuiButtonBase-root");
|
||||||
.click('.MuiButtonBase-root');
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { Datum, TypedArray } from "plotly.js";
|
import { Datum, TypedArray } from "plotly.js";
|
||||||
import { TreeElement } from "../components/Installations/Log/CheckboxTree";
|
import { I_TreeElement } from "../components/Installations/Log/CheckboxTree";
|
||||||
import { TimeRange, UnixTime } from "../dataCache/time";
|
import { TimeRange, UnixTime } from "../dataCache/time";
|
||||||
import { DataPoint, DataRecord } from "../dataCache/data";
|
import { DataPoint, DataRecord } from "../dataCache/data";
|
||||||
import { isDefined } from "../dataCache/utils/maybe";
|
import { isDefined } from "../dataCache/utils/maybe";
|
||||||
import {
|
import {
|
||||||
BoxData,
|
BoxData,
|
||||||
BoxDataValue,
|
I_BoxDataValue,
|
||||||
} from "../components/Installations/LiveView/TopologyBox";
|
} from "../components/Installations/LiveView/TopologyBox";
|
||||||
|
|
||||||
export interface GraphCoordinates {
|
export interface I_GraphCoordinates {
|
||||||
x: Datum[] | Datum[][] | TypedArray;
|
x: Datum[] | Datum[][] | TypedArray;
|
||||||
y: Datum[] | Datum[][] | TypedArray;
|
y: Datum[] | Datum[][] | TypedArray;
|
||||||
xaxis?: string;
|
xaxis?: string;
|
||||||
|
@ -32,8 +32,8 @@ export const createTimes = (
|
||||||
return roundedRange.sample(oneSpan);
|
return roundedRange.sample(oneSpan);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface GraphData {
|
export interface I_GraphData {
|
||||||
[path: string]: GraphCoordinates;
|
[path: string]: I_GraphCoordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
// connections must have the word Connection in the prop name, so the topology works correctly
|
// connections must have the word Connection in the prop name, so the topology works correctly
|
||||||
|
@ -141,7 +141,7 @@ export const extractTopologyValues = (
|
||||||
const timeSeriesValue = timeSeriesData.value;
|
const timeSeriesValue = timeSeriesData.value;
|
||||||
if (isDefined(timeSeriesValue)) {
|
if (isDefined(timeSeriesValue)) {
|
||||||
return Object.keys(topologyPaths).reduce((acc, topologyKey) => {
|
return Object.keys(topologyPaths).reduce((acc, topologyKey) => {
|
||||||
let topologyValues: BoxDataValue[];
|
let topologyValues: I_BoxDataValue[];
|
||||||
const values = topologyPaths[topologyKey as keyof TopologyValues].map(
|
const values = topologyPaths[topologyKey as keyof TopologyValues].map(
|
||||||
(topologyPath) => timeSeriesValue[topologyPath]
|
(topologyPath) => timeSeriesValue[topologyPath]
|
||||||
);
|
);
|
||||||
|
@ -196,12 +196,12 @@ export const getHighestConnectionValue = (values: TopologyValues) =>
|
||||||
|
|
||||||
export const getAmount = (
|
export const getAmount = (
|
||||||
highestConnectionValue: number,
|
highestConnectionValue: number,
|
||||||
values: BoxDataValue[]
|
values: I_BoxDataValue[]
|
||||||
) => {
|
) => {
|
||||||
return Math.abs(values[0].value as number) / highestConnectionValue;
|
return Math.abs(values[0].value as number) / highestConnectionValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface CsvEntry {
|
export interface I_CsvEntry {
|
||||||
value: string | number;
|
value: string | number;
|
||||||
unit: string;
|
unit: string;
|
||||||
}
|
}
|
||||||
|
@ -225,9 +225,9 @@ export const parseCsv = (text: string): DataRecord => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const insertTreeElements = (
|
export const insertTreeElements = (
|
||||||
children: TreeElement[] = [],
|
children: I_TreeElement[] = [],
|
||||||
[head, ...tail]: string[]
|
[head, ...tail]: string[]
|
||||||
): TreeElement[] => {
|
): I_TreeElement[] => {
|
||||||
let child = children.find((child) => child.name === head);
|
let child = children.find((child) => child.name === head);
|
||||||
|
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
@ -249,7 +249,7 @@ export const isText = (data: any): data is string => {
|
||||||
return typeof data === "string";
|
return typeof data === "string";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const flattenBarGraphData = (arr: any): GraphCoordinates[] => {
|
export const flattenBarGraphData = (arr: any): I_GraphCoordinates[] => {
|
||||||
return arr.reduce((flat: any, toFlatten: any) => {
|
return arr.reduce((flat: any, toFlatten: any) => {
|
||||||
return flat.concat(
|
return flat.concat(
|
||||||
Array.isArray(toFlatten) ? flattenBarGraphData(toFlatten) : toFlatten
|
Array.isArray(toFlatten) ? flattenBarGraphData(toFlatten) : toFlatten
|
||||||
|
@ -277,7 +277,7 @@ export const isNumeric = (value: any) => {
|
||||||
return !isNaN(value) && !isNaN(parseFloat(value));
|
return !isNaN(value) && !isNaN(parseFloat(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformToBarGraphData = (data: GraphCoordinates) => {
|
export const transformToBarGraphData = (data: I_GraphCoordinates) => {
|
||||||
let names: string[] = [];
|
let names: string[] = [];
|
||||||
const barGraphData = data.y.map((text, i) => {
|
const barGraphData = data.y.map((text, i) => {
|
||||||
if (isText(text)) {
|
if (isText(text)) {
|
||||||
|
@ -313,6 +313,6 @@ export const getTreeElements = (toggleValues: DataRecord) => {
|
||||||
)
|
)
|
||||||
.reduce(
|
.reduce(
|
||||||
(children, path) => insertTreeElements(children, path),
|
(children, path) => insertTreeElements(children, path),
|
||||||
[] as TreeElement[]
|
[] as I_TreeElement[]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// TODO add if required or not
|
export interface I_S3Credentials {
|
||||||
export interface S3Credentials {
|
|
||||||
s3Region: string;
|
s3Region: string;
|
||||||
s3Provider: string;
|
s3Provider: string;
|
||||||
s3Key: string;
|
s3Key: string;
|
||||||
|
@ -7,7 +6,7 @@ export interface S3Credentials {
|
||||||
s3Bucket?: string;
|
s3Bucket?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface I_Installation extends S3Credentials {
|
export interface I_Installation extends I_S3Credentials {
|
||||||
type: string;
|
type: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
status?: number;
|
status?: number;
|
||||||
|
@ -35,37 +34,3 @@ export interface I_Folder {
|
||||||
type: string;
|
type: string;
|
||||||
children?: (I_Installation | I_Folder)[];
|
children?: (I_Installation | I_Folder)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface I_Ac {
|
|
||||||
Current: number;
|
|
||||||
Voltage: number;
|
|
||||||
Phi?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface I_Dc {
|
|
||||||
Current: number;
|
|
||||||
Voltage: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface I_Device {
|
|
||||||
Name: string;
|
|
||||||
Type: string;
|
|
||||||
Ac?: I_Ac[];
|
|
||||||
Dc?: I_Dc;
|
|
||||||
Dc48?: I_Dc;
|
|
||||||
Frequency?: number;
|
|
||||||
Alarms?: any[];
|
|
||||||
Warnings?: any[];
|
|
||||||
MainState?: string;
|
|
||||||
"DC Power"?: number;
|
|
||||||
Soc?: number;
|
|
||||||
HeaterOn?: boolean;
|
|
||||||
EocReached?: boolean;
|
|
||||||
BatteryCold?: boolean;
|
|
||||||
Temperature?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface I_GraphData {
|
|
||||||
TimeStamp: string;
|
|
||||||
Devices: I_Device[];
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export interface I_User {
|
||||||
mustResetPassword: boolean;
|
mustResetPassword: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserWithInheritedAccess {
|
export interface I_UserWithInheritedAccess {
|
||||||
folderId: number;
|
folderId: number;
|
||||||
folderName: string;
|
folderName: string;
|
||||||
user: I_User;
|
user: I_User;
|
||||||
|
@ -20,7 +20,7 @@ export interface UserWithInheritedAccess {
|
||||||
|
|
||||||
export const filterDuplicateUsers = (data: any[]) => {
|
export const filterDuplicateUsers = (data: any[]) => {
|
||||||
return data.reduce(
|
return data.reduce(
|
||||||
(prev: UserWithInheritedAccess[], curr: UserWithInheritedAccess) => {
|
(prev: I_UserWithInheritedAccess[], curr: I_UserWithInheritedAccess) => {
|
||||||
const foundUser = prev.find(({ user }) => user.id === curr.user.id);
|
const foundUser = prev.find(({ user }) => user.id === curr.user.id);
|
||||||
if (foundUser) {
|
if (foundUser) {
|
||||||
const prevIds = foundUser.user.folderIds
|
const prevIds = foundUser.user.folderIds
|
||||||
|
|
Loading…
Reference in New Issue