Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
66da08b407
File diff suppressed because it is too large
Load Diff
|
@ -3,43 +3,30 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.316.0",
|
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
"@minoru/react-dnd-treeview": "^3.4.1",
|
|
||||||
"@mui/icons-material": "^5.11.0",
|
"@mui/icons-material": "^5.11.0",
|
||||||
"@mui/lab": "^5.0.0-alpha.120",
|
"@mui/lab": "^5.0.0-alpha.120",
|
||||||
"@mui/material": "^5.11.7",
|
"@mui/material": "^5.11.7",
|
||||||
"@mui/x-date-pickers": "^6.5.0",
|
"@mui/x-date-pickers": "^6.5.0",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
|
||||||
"@types/jest": "^27.5.2",
|
|
||||||
"@types/node": "^16.18.11",
|
"@types/node": "^16.18.11",
|
||||||
"@types/react": "^18.0.27",
|
"@types/react": "^18.0.27",
|
||||||
"@types/react-dom": "^18.0.10",
|
"@types/react-dom": "^18.0.10",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"axios": "^1.3.1",
|
"axios": "^1.3.1",
|
||||||
"chart.js": "^4.2.1",
|
"chart.js": "^4.2.1",
|
||||||
"css-loader": "^6.7.3",
|
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"linq-to-typescript": "^11.0.0",
|
"linq-to-typescript": "^11.0.0",
|
||||||
"package.json": "^2.0.1",
|
|
||||||
"plotly.js": "^2.20.0",
|
"plotly.js": "^2.20.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-chartjs-2": "^5.2.0",
|
|
||||||
"react-dnd": "^16.0.1",
|
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
|
||||||
"react-dnd-scrolling": "^1.3.3",
|
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-intl": "^6.2.10",
|
"react-intl": "^6.2.10",
|
||||||
"react-plotly.js": "^2.6.0",
|
"react-plotly.js": "^2.6.0",
|
||||||
"react-router-dom": "^6.8.0",
|
"react-router-dom": "^6.8.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"reactflow": "^11.5.6",
|
|
||||||
"rxjs": "^7.8.0",
|
"rxjs": "^7.8.0",
|
||||||
"sass": "^1.58.3",
|
|
||||||
"sass-loader": "^13.2.0",
|
|
||||||
"simplytyped": "^3.3.0",
|
"simplytyped": "^3.3.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"testcafe": "^2.4.0",
|
"testcafe": "^2.4.0",
|
||||||
|
@ -83,7 +70,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@formatjs/cli": "^6.0.3",
|
"@formatjs/cli": "^6.0.3",
|
||||||
"@types/react-plotly.js": "^2.6.0",
|
"@types/react-plotly.js": "^2.6.0",
|
||||||
"@types/react-window": "^1.8.5",
|
"depcheck": "^1.4.3",
|
||||||
"eslint-plugin-formatjs": "^4.10.1",
|
"eslint-plugin-formatjs": "^4.10.1",
|
||||||
"prettier": "^2.8.8"
|
"prettier": "^2.8.8"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import useToken from "./hooks/useToken";
|
||||||
import Login from "./Login";
|
import Login from "./Login";
|
||||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
import { Container, Grid, colors, Box } from "@mui/material";
|
import { Container, Grid, Box } from "@mui/material";
|
||||||
import routes from "./routes.json";
|
import routes from "./routes.json";
|
||||||
import { IntlProvider, MessageFormatElement } from "react-intl";
|
import { IntlProvider, MessageFormatElement } from "react-intl";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
|
@ -17,20 +17,21 @@ import InstallationPage from "./components/Installations/InstallationPage";
|
||||||
import { UserContext } from "./components/Context/UserContextProvider";
|
import { UserContext } from "./components/Context/UserContextProvider";
|
||||||
import ResetPassword from "./ResetPassword";
|
import ResetPassword from "./ResetPassword";
|
||||||
import innovenergyLogo from "./resources/innoveng_logo_on_orange.png";
|
import innovenergyLogo from "./resources/innoveng_logo_on_orange.png";
|
||||||
|
import { colors } from "./index";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const { token, setToken, removeToken } = useToken();
|
const { token, setToken, removeToken } = useToken();
|
||||||
const [language, setLanguage] = useState("EN");
|
const [language, setLanguage] = useState("en");
|
||||||
|
|
||||||
const { getCurrentUser } = useContext(UserContext);
|
const { getCurrentUser } = useContext(UserContext);
|
||||||
|
|
||||||
const getTranslations = () => {
|
const getTranslations = () => {
|
||||||
switch (language) {
|
switch (language) {
|
||||||
case "DE":
|
case "en":
|
||||||
return de;
|
return de;
|
||||||
case "EN":
|
case "de":
|
||||||
return en;
|
return en;
|
||||||
case "FR":
|
case "fr":
|
||||||
return fr;
|
return fr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -41,12 +42,13 @@ const App = () => {
|
||||||
if (token && getCurrentUser()?.mustResetPassword) {
|
if (token && getCurrentUser()?.mustResetPassword) {
|
||||||
return <ResetPassword />;
|
return <ResetPassword />;
|
||||||
}
|
}
|
||||||
|
console.log("lang", language);
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<IntlProvider
|
<IntlProvider
|
||||||
messages={getTranslations()}
|
messages={getTranslations()}
|
||||||
locale={language}
|
locale={language}
|
||||||
defaultLocale="EN"
|
defaultLocale="en"
|
||||||
>
|
>
|
||||||
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
|
@ -73,7 +75,7 @@ const App = () => {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
<Box
|
<Box
|
||||||
bgcolor="#eaecf1"
|
bgcolor={colors.greyLight}
|
||||||
pt={3}
|
pt={3}
|
||||||
borderTop="2px solid"
|
borderTop="2px solid"
|
||||||
borderColor=" #a8b0be"
|
borderColor=" #a8b0be"
|
||||||
|
|
|
@ -1,89 +1,113 @@
|
||||||
import React, { useContext, useState } from "react";
|
import React, { useContext, useState } from "react";
|
||||||
import { Alert, CircularProgress, Grid, useTheme } from "@mui/material";
|
import {
|
||||||
import Container from "@mui/material/Container";
|
Alert,
|
||||||
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
CircularProgress,
|
||||||
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
Grid,
|
||||||
import InnovenergyButton from "./components/Layout/InnovenergyButton";
|
Typography,
|
||||||
import { UserContext } from "./components/Context/UserContextProvider";
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
const loginUser = async (username: string, password: string) => {
|
import Container from "@mui/material/Container";
|
||||||
return axiosConfigWithoutToken.post("/Login", null, {
|
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||||
params: { username, password },
|
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
||||||
});
|
import InnovenergyButton from "./components/Layout/InnovenergyButton";
|
||||||
};
|
import { UserContext } from "./components/Context/UserContextProvider";
|
||||||
|
import innovenergyLogo from "./resources/innoveng_logo_on_orange.png";
|
||||||
interface I_LoginProps {
|
|
||||||
setToken: (value: string) => void;
|
const loginUser = async (username: string, password: string) => {
|
||||||
setLanguage: (value: string) => void;
|
return axiosConfigWithoutToken.post("/Login", null, {
|
||||||
}
|
params: { username, password },
|
||||||
|
});
|
||||||
const Login = ({ setToken, setLanguage }: I_LoginProps) => {
|
};
|
||||||
const [username, setUsername] = useState("");
|
|
||||||
const [password, setPassword] = useState("");
|
interface I_LoginProps {
|
||||||
const [loading, setLoading] = useState(false);
|
setToken: (value: string) => void;
|
||||||
const [error, setError] = useState();
|
setLanguage: (value: string) => void;
|
||||||
const { saveCurrentUser } = useContext(UserContext);
|
}
|
||||||
const theme = useTheme();
|
|
||||||
|
const Login = ({ setToken, setLanguage }: I_LoginProps) => {
|
||||||
const verifyToken = async (token: string) => {
|
const [username, setUsername] = useState("");
|
||||||
axiosConfigWithoutToken.get("/GetAllInstallations", {
|
const [password, setPassword] = useState("");
|
||||||
params: { authToken: token },
|
const [loading, setLoading] = useState(false);
|
||||||
});
|
const [error, setError] = useState();
|
||||||
};
|
const { saveCurrentUser } = useContext(UserContext);
|
||||||
|
const theme = useTheme();
|
||||||
const handleSubmit = () => {
|
|
||||||
setLoading(true);
|
const verifyToken = async (token: string) => {
|
||||||
loginUser(username, password)
|
axiosConfigWithoutToken.get("/GetAllInstallations", {
|
||||||
.then(({ data }) => {
|
params: { authToken: token },
|
||||||
// TODO change this if they return err codes from backend
|
});
|
||||||
if (data && data.token) {
|
};
|
||||||
verifyToken(data.token)
|
|
||||||
.then(() => {
|
const handleSubmit = () => {
|
||||||
setToken(data.token);
|
setLoading(true);
|
||||||
saveCurrentUser(data.user);
|
loginUser(username, password)
|
||||||
setLoading(false);
|
.then(({ data }) => {
|
||||||
setLanguage(data.user.language);
|
// TODO change this if they return err codes from backend
|
||||||
})
|
if (data && data.token) {
|
||||||
.catch((err) => {
|
verifyToken(data.token)
|
||||||
setError(err);
|
.then(() => {
|
||||||
setLoading(false);
|
setToken(data.token);
|
||||||
});
|
saveCurrentUser(data.user);
|
||||||
}
|
setLoading(false);
|
||||||
setError(data);
|
setLanguage(data.user.language);
|
||||||
setLoading(false);
|
})
|
||||||
})
|
.catch((err) => {
|
||||||
.catch((err) => {
|
setError(err);
|
||||||
setError(err);
|
setLoading(false);
|
||||||
setLoading(false);
|
});
|
||||||
});
|
}
|
||||||
};
|
setError(data);
|
||||||
|
setLoading(false);
|
||||||
return (
|
})
|
||||||
<Container maxWidth="sm" sx={{ p: 2, alignContent: "center" }}>
|
.catch((err) => {
|
||||||
<InnovenergyTextfield
|
setError(err);
|
||||||
id="username-textfield"
|
setLoading(false);
|
||||||
label="Username"
|
});
|
||||||
name="email"
|
};
|
||||||
value={username}
|
|
||||||
handleChange={(e) => setUsername(e.target.value)}
|
return (
|
||||||
/>
|
<>
|
||||||
<InnovenergyTextfield
|
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
||||||
id="password-textfield"
|
<Grid container>
|
||||||
label="Password"
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
name="password"
|
<img src={innovenergyLogo} alt="innovenergy logo" height="100" />
|
||||||
type="password"
|
</Grid>
|
||||||
value={password}
|
</Grid>
|
||||||
handleChange={(e) => setPassword(e.target.value)}
|
</Container>
|
||||||
/>
|
<Container maxWidth="sm" sx={{ p: 2, alignContent: "center" }}>
|
||||||
{error && <Alert severity="error">Incorrect username or password</Alert>}
|
<InnovenergyTextfield
|
||||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
id="username-textfield"
|
||||||
<InnovenergyButton onClick={handleSubmit} sx={{ my: 1 }}>
|
label="Username"
|
||||||
Login
|
name="email"
|
||||||
</InnovenergyButton>
|
value={username}
|
||||||
</Grid>
|
handleChange={(e) => setUsername(e.target.value)}
|
||||||
{loading && <CircularProgress sx={{color: theme.palette.secondary.main}} />}
|
/>
|
||||||
</Container>
|
<InnovenergyTextfield
|
||||||
);
|
id="password-textfield"
|
||||||
};
|
label="Password"
|
||||||
|
name="password"
|
||||||
export default Login;
|
type="password"
|
||||||
|
value={password}
|
||||||
|
handleChange={(e) => setPassword(e.target.value)}
|
||||||
|
/>
|
||||||
|
{error && (
|
||||||
|
<Alert severity="error">Incorrect username or password</Alert>
|
||||||
|
)}
|
||||||
|
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||||
|
<InnovenergyButton
|
||||||
|
onClick={handleSubmit}
|
||||||
|
sx={{ my: 1 }}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</InnovenergyButton>
|
||||||
|
</Grid>
|
||||||
|
{loading && (
|
||||||
|
<CircularProgress sx={{ color: theme.palette.secondary.main }} />
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Login;
|
||||||
|
|
|
@ -27,19 +27,16 @@ const S3CredentialsContextProvider = ({
|
||||||
}) => {
|
}) => {
|
||||||
const [s3Credentials, setS3Credentials] = useState<S3Credentials>();
|
const [s3Credentials, setS3Credentials] = useState<S3Credentials>();
|
||||||
|
|
||||||
console.log("creds", s3Credentials);
|
|
||||||
const saveS3Credentials = (credentials: S3Credentials, id: string) => {
|
const saveS3Credentials = (credentials: S3Credentials, id: string) => {
|
||||||
//const s3Bucket = id + "-3e5b3069-214a-43ee-8d85-57d72000c19d";
|
const s3Bucket = id + "-3e5b3069-214a-43ee-8d85-57d72000c19d";
|
||||||
/* const s3Bucket = "saliomameiringen";
|
setS3Credentials({ s3Bucket, ...credentials });
|
||||||
|
/* setS3Credentials({
|
||||||
setS3Credentials({ s3Bucket, ...credentials });*/
|
s3Region: "sos-ch-dk-2",
|
||||||
setS3Credentials({
|
s3Provider: "exo.io",
|
||||||
s3Region: "sos-ch-dk-2",
|
s3Key: "EXO15c0bf710e158e9b83270f0a",
|
||||||
s3Provider: "exo.io",
|
s3Secret: "Dd5jYSiZtt_Zt5Ba5mDmaiLCdASUaKLfduSKY-SU-lg",
|
||||||
s3Key: "EXO15c0bf710e158e9b83270f0a",
|
s3Bucket: "saliomameiringen",
|
||||||
s3Secret: "Dd5jYSiZtt_Zt5Ba5mDmaiLCdASUaKLfduSKY-SU-lg",
|
});*/
|
||||||
s3Bucket: "saliomameiringen",
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchData = (timestamp: UnixTime): Promise<FetchResult<DataRecord>> => {
|
const fetchData = (timestamp: UnixTime): Promise<FetchResult<DataRecord>> => {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
TextField,
|
TextField,
|
||||||
colors,
|
colors,
|
||||||
|
Alert,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import DialogActions from "@mui/material/DialogActions";
|
import DialogActions from "@mui/material/DialogActions";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
|
@ -19,6 +20,7 @@ import InnovenergyButton from "../../Layout/InnovenergyButton";
|
||||||
const AvailableUserDialog = () => {
|
const AvailableUserDialog = () => {
|
||||||
const [selectedUsers, setSelectedUsers] = useState<I_User[]>([]);
|
const [selectedUsers, setSelectedUsers] = useState<I_User[]>([]);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [errors, setErrors] = useState<string[]>([]);
|
||||||
|
|
||||||
const { currentType } = useContext(GroupContext);
|
const { currentType } = useContext(GroupContext);
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
@ -42,7 +44,8 @@ const AvailableUserDialog = () => {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
fetchUsersWithDirectAccessForResource();
|
fetchUsersWithDirectAccessForResource();
|
||||||
fetchUsersWithInheritedAccessForResource();
|
fetchUsersWithInheritedAccessForResource();
|
||||||
});
|
})
|
||||||
|
.catch(() => setErrors((errors) => [...errors, user.name]));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,6 +66,17 @@ const AvailableUserDialog = () => {
|
||||||
<FormattedMessage id="manageAccess" defaultMessage="Manage access" />
|
<FormattedMessage id="manageAccess" defaultMessage="Manage access" />
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent id="available-user-dialog-content">
|
<DialogContent id="available-user-dialog-content">
|
||||||
|
{errors.length > 0 && (
|
||||||
|
<Alert sx={{ my: 1 }} severity="error">
|
||||||
|
<FormattedMessage
|
||||||
|
id="grantAccessError"
|
||||||
|
defaultMessage="Couldn't grant access to the following users: "
|
||||||
|
/>
|
||||||
|
{errors.map((error, index) =>
|
||||||
|
errors.length === index + 1 ? error : error + ", "
|
||||||
|
)}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
sx={{ width: "500px", pt: 1 }}
|
sx={{ width: "500px", pt: 1 }}
|
||||||
multiple
|
multiple
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { List } from "@mui/material";
|
import { List, useTheme } from "@mui/material";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
interface InnovenergyListProps {
|
interface InnovenergyListProps {
|
||||||
|
@ -7,10 +7,11 @@ interface InnovenergyListProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnovenergyList = (props: InnovenergyListProps) => {
|
const InnovenergyList = (props: InnovenergyListProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: "white",
|
bgcolor: theme.palette.primary.dark,
|
||||||
position: "relative",
|
position: "relative",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
maxHeight: 500,
|
maxHeight: 500,
|
||||||
|
|
|
@ -44,7 +44,7 @@ const UsersWithDirectAccess = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (directAccessUsers && directAccessUsers.length) {
|
if (directAccessUsers && directAccessUsers.length > 0) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{error && (
|
{error && (
|
||||||
|
@ -90,7 +90,14 @@ const UsersWithDirectAccess = () => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return (
|
||||||
|
<Alert severity="info" sx={{ mx: 2 }}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="noDirectAccessUsers"
|
||||||
|
defaultMessage="No direct access users were found"
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UsersWithDirectAccess;
|
export default UsersWithDirectAccess;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
Divider,
|
Divider,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
Avatar,
|
Avatar,
|
||||||
|
Alert,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { Fragment, useContext, useEffect } from "react";
|
import { Fragment, useContext, useEffect } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
@ -24,7 +25,7 @@ const UsersWithInheritedAccess = () => {
|
||||||
fetchUsersWithInheritedAccessForResource();
|
fetchUsersWithInheritedAccessForResource();
|
||||||
}, [fetchUsersWithInheritedAccessForResource]);
|
}, [fetchUsersWithInheritedAccessForResource]);
|
||||||
|
|
||||||
if (inheritedAccessUsers && inheritedAccessUsers.length) {
|
if (inheritedAccessUsers && inheritedAccessUsers.length > 0) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{filterDuplicateUsers(inheritedAccessUsers).map(
|
{filterDuplicateUsers(inheritedAccessUsers).map(
|
||||||
|
@ -73,7 +74,14 @@ const UsersWithInheritedAccess = () => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return (
|
||||||
|
<Alert severity="info" sx={{ m: 2 }}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="noInheritedAccessUsers"
|
||||||
|
defaultMessage="No inherited access users were found"
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UsersWithInheritedAccess;
|
export default UsersWithInheritedAccess;
|
||||||
|
|
|
@ -1,43 +1,31 @@
|
||||||
import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
|
import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
|
||||||
import { useState } from "react";
|
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
|
||||||
import { I_Folder } from "../../util/types";
|
|
||||||
import FolderForm from "./FolderForm";
|
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
|
||||||
|
import { ReactNode, useState } from "react";
|
||||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||||
|
|
||||||
interface AddNewDialogProps {
|
interface AddNewDialogProps {
|
||||||
values: I_Folder;
|
form: ReactNode;
|
||||||
|
message: ReactNode;
|
||||||
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddNewDialog = (props: AddNewDialogProps) => {
|
const AddNewDialog = (props: AddNewDialogProps) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const { form, id, message } = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleSubmit = (data: I_Folder, childData: Partial<I_Folder>) => {
|
|
||||||
return axiosConfig
|
|
||||||
.post("/CreateFolder", {
|
|
||||||
...childData,
|
|
||||||
parentId: data.id,
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
setOpen(false);
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<InnovenergyButton
|
<InnovenergyButton
|
||||||
id={"add-new-child-dialog-button-" + props.values.id}
|
id={"add-new-child-dialog-button-" + id}
|
||||||
sx={{ ml: 2 }}
|
sx={{ ml: 2 }}
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => setOpen(true)}
|
||||||
>
|
>
|
||||||
<FormattedMessage id="addNewChild" defaultMessage="Add new child" />
|
{message}
|
||||||
</InnovenergyButton>
|
</InnovenergyButton>
|
||||||
<Dialog
|
<Dialog
|
||||||
id={"add-new-child-dialog-" + props.values.id}
|
id={"add-new-child-dialog-" + id}
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
aria-labelledby="customized-dialog-title"
|
aria-labelledby="customized-dialog-title"
|
||||||
open={open}
|
open={open}
|
||||||
|
@ -50,12 +38,9 @@ const AddNewDialog = (props: AddNewDialogProps) => {
|
||||||
maxWidth="sm"
|
maxWidth="sm"
|
||||||
>
|
>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<FormattedMessage
|
<FormattedMessage id="createNew" defaultMessage="Create new" />
|
||||||
id="createNewFolder"
|
|
||||||
defaultMessage="Create new folder"
|
|
||||||
/>
|
|
||||||
<IconButton
|
<IconButton
|
||||||
id={"add-new-child-dialog-icon-button-" + props.values.id}
|
id={"add-new-child-dialog-icon-button-" + id}
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
|
@ -69,14 +54,10 @@ const AddNewDialog = (props: AddNewDialogProps) => {
|
||||||
top: 8,
|
top: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseIcon
|
<CloseIcon id={"add-new-child-dialog-close-icon-" + id} />
|
||||||
id={"add-new-child-dialog-close-icon-" + props.values.id}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>{form}</DialogContent>
|
||||||
<FolderForm values={props.values} handleSubmit={handleSubmit} />
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
|
import FolderForm from "./FolderForm";
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||||
|
import InstallationForm from "../Installations/InstallationForm";
|
||||||
|
import AddNewDialog from "./AddNew";
|
||||||
|
|
||||||
|
interface AddNewDialogProps {
|
||||||
|
values: I_Folder | I_Installation;
|
||||||
|
isFolder: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddNewButtons = (props: AddNewDialogProps) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleFolderSubmit = (data: I_Folder, childData: Partial<I_Folder>) => {
|
||||||
|
return axiosConfig
|
||||||
|
.post("/CreateFolder", {
|
||||||
|
...childData,
|
||||||
|
parentId: data.id,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
setOpen(false);
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInstallationSubmit = (
|
||||||
|
data: I_Installation,
|
||||||
|
childData: Partial<I_Installation>
|
||||||
|
) => {
|
||||||
|
return axiosConfig
|
||||||
|
.post("/CreateInstallation", {
|
||||||
|
...childData,
|
||||||
|
parentId: data.id,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
setOpen(false);
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const folderForm = (
|
||||||
|
<FolderForm
|
||||||
|
values={props.values as I_Folder}
|
||||||
|
handleSubmit={handleFolderSubmit}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const installationForm = (
|
||||||
|
<InstallationForm
|
||||||
|
values={props.values as I_Installation}
|
||||||
|
handleSubmit={handleInstallationSubmit}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AddNewDialog
|
||||||
|
form={installationForm}
|
||||||
|
message={
|
||||||
|
<FormattedMessage
|
||||||
|
id="addNewInstallation"
|
||||||
|
defaultMessage="Add new installation"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
id={props.values.id}
|
||||||
|
/>
|
||||||
|
<AddNewDialog
|
||||||
|
form={folderForm}
|
||||||
|
message={
|
||||||
|
<FormattedMessage id="addNewFolder" defaultMessage="Add new folder" />
|
||||||
|
}
|
||||||
|
id={props.values.id}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddNewButtons;
|
|
@ -4,7 +4,7 @@ import { useState, useEffect } 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 } from "../../util/types";
|
import { I_Folder } from "../../util/types";
|
||||||
import AddNewDialog from "./AddNewDialog";
|
import AddNewButtons from "./AddNewButtons";
|
||||||
import FolderForm from "./FolderForm";
|
import FolderForm from "./FolderForm";
|
||||||
import MoveDialog from "./Tree/MoveDialog";
|
import MoveDialog from "./Tree/MoveDialog";
|
||||||
import { colors } from "index";
|
import { colors } from "index";
|
||||||
|
@ -36,7 +36,7 @@ const Folder = () => {
|
||||||
|
|
||||||
if (values && values.id && values.id.toString() === id) {
|
if (values && values.id && values.id.toString() === id) {
|
||||||
const moveDialog = <MoveDialog values={values} />;
|
const moveDialog = <MoveDialog values={values} />;
|
||||||
const addNewDialog = <AddNewDialog values={values} />;
|
const addNewDialog = <AddNewButtons values={values} isFolder />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { I_Folder } from "../../util/types";
|
||||||
import { GroupContext } from "../Context/GroupContextProvider";
|
import { GroupContext } from "../Context/GroupContextProvider";
|
||||||
import InnovenergySnackbar from "../InnovenergySnackbar";
|
import InnovenergySnackbar from "../InnovenergySnackbar";
|
||||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||||
import InnovenergyTextfield, {
|
import {
|
||||||
I_InnovenergyTextfieldProps,
|
I_InnovenergyTextfieldProps,
|
||||||
IePropertyGrid,
|
IePropertyGrid,
|
||||||
} from "../Layout/InnovenergyTextfield";
|
} from "../Layout/InnovenergyTextfield";
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { instanceOfFolder } from "../../../util/group.util";
|
||||||
import { Grid, CircularProgress, useTheme } from "@mui/material";
|
import { Grid, CircularProgress, useTheme } from "@mui/material";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import { colors } from "../../..";
|
import { colors } from "../../..";
|
||||||
import { color } from "chart.js/helpers";
|
import InnovEnergyTreeItem from "../../Layout/InnovEnergyTreeItem";
|
||||||
|
|
||||||
const GroupTree = () => {
|
const GroupTree = () => {
|
||||||
const { setCurrentType, fetchData, data, loading } = useContext(GroupContext);
|
const { setCurrentType, fetchData, data, loading } = useContext(GroupContext);
|
||||||
|
@ -48,27 +48,15 @@ const GroupTree = () => {
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
>
|
>
|
||||||
<TreeItem
|
<InnovEnergyTreeItem
|
||||||
id={"group-tree-item-" + element.id}
|
id={"group-tree-item-" + element.id}
|
||||||
key={element.type + element.id}
|
key={element.type + element.id}
|
||||||
nodeId={element.type + element.id}
|
nodeId={element.type + element.id}
|
||||||
label={element.name}
|
label={element.name}
|
||||||
onClick={() => setCurrentType(element.type)}
|
onClick={() => setCurrentType(element.type)}
|
||||||
sx={{
|
|
||||||
".MuiTreeItem-content": { py: "10px" },
|
|
||||||
".Mui-selected": {
|
|
||||||
backgroundColor: theme.palette.secondary.main,
|
|
||||||
},
|
|
||||||
".Mui-selected:hover": {
|
|
||||||
backgroundColor: theme.palette.secondary.main,
|
|
||||||
},
|
|
||||||
".Mui-focused": { backgroundColor: theme.palette.secondary.main },
|
|
||||||
bgcolor: colors.greyDark,
|
|
||||||
borderRadius: 2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{getNodes(element)}
|
{getNodes(element)}
|
||||||
</TreeItem>
|
</InnovEnergyTreeItem>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -94,6 +82,9 @@ const GroupTree = () => {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
|
".Mui-selected": {
|
||||||
|
borderRadius: "4px",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
expanded={openNodes}
|
expanded={openNodes}
|
||||||
onNodeToggle={(e, ids) => {
|
onNodeToggle={(e, ids) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DialogActions, Dialog, DialogTitle } from "@mui/material";
|
import { DialogActions, Dialog, DialogTitle, Alert } from "@mui/material";
|
||||||
import DialogContent from "@mui/material/DialogContent";
|
import DialogContent from "@mui/material/DialogContent";
|
||||||
import { useContext, useState } from "react";
|
import React, { useContext, useState } from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import axiosConfig from "../../../config/axiosConfig";
|
import axiosConfig from "../../../config/axiosConfig";
|
||||||
|
@ -12,15 +12,18 @@ import MoveTree from "./MoveTree";
|
||||||
interface MoveDialogProps {
|
interface MoveDialogProps {
|
||||||
values: I_Folder;
|
values: I_Folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MoveDialog = (props: MoveDialogProps) => {
|
const MoveDialog = (props: MoveDialogProps) => {
|
||||||
const { values } = props;
|
const { values } = props;
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const [selectedParentId, setSelectedParentId] = useState<number>(
|
const [selectedParentId, setSelectedParentId] = useState<number>(
|
||||||
values.parentId
|
values.parentId
|
||||||
);
|
);
|
||||||
const { fetchData, currentType } = useContext(GroupContext);
|
const { fetchData, currentType } = useContext(GroupContext);
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
const [error, setError] = useState();
|
||||||
|
|
||||||
const handleMove = () => {
|
const handleMove = () => {
|
||||||
const route =
|
const route =
|
||||||
|
@ -33,9 +36,9 @@ const MoveDialog = (props: MoveDialogProps) => {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
fetchData();
|
fetchData();
|
||||||
});
|
})
|
||||||
|
.catch((err) => setError(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<InnovenergyButton
|
<InnovenergyButton
|
||||||
|
@ -59,7 +62,16 @@ const MoveDialog = (props: MoveDialogProps) => {
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<FormattedMessage id="moveTo" defaultMessage="Move to" />
|
<FormattedMessage id="moveTo" defaultMessage="Move to" />
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
|
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
{error && (
|
||||||
|
<Alert severity={"error"}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="moveInstallationError"
|
||||||
|
defaultMessage="Couldn't move element, an error occured"
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<MoveTree
|
<MoveTree
|
||||||
parentId={selectedParentId}
|
parentId={selectedParentId}
|
||||||
setSelectedParentId={setSelectedParentId}
|
setSelectedParentId={setSelectedParentId}
|
||||||
|
|
|
@ -2,11 +2,11 @@ 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 } from "react";
|
import { ReactNode, useContext } from "react";
|
||||||
import { TreeItem } from "@mui/lab";
|
|
||||||
import { I_Folder, I_Installation } from "../../../util/types";
|
import { I_Folder, I_Installation } from "../../../util/types";
|
||||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
import { instanceOfFolder } from "../../../util/group.util";
|
import { instanceOfFolder } from "../../../util/group.util";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
import InnovEnergyTreeItem from "../../Layout/InnovEnergyTreeItem";
|
||||||
|
|
||||||
interface MoveTreeProps {
|
interface MoveTreeProps {
|
||||||
setSelectedParentId: (value: number) => void;
|
setSelectedParentId: (value: number) => void;
|
||||||
|
@ -29,14 +29,15 @@ const MoveTree = (props: MoveTreeProps) => {
|
||||||
.filter((element) => element.type === "Folder")
|
.filter((element) => element.type === "Folder")
|
||||||
.map((element) => {
|
.map((element) => {
|
||||||
return (
|
return (
|
||||||
<TreeItem
|
<InnovEnergyTreeItem
|
||||||
id={"move-tree-item-" + element.id}
|
id={"move-tree-item-" + element.id}
|
||||||
key={"move-tree-item-" + element.id}
|
key={"move-tree-item-" + element.id}
|
||||||
nodeId={element.id.toString()}
|
nodeId={element.id.toString()}
|
||||||
|
color="primary"
|
||||||
label={element.name}
|
label={element.name}
|
||||||
>
|
>
|
||||||
{getNodes(element)}
|
{getNodes(element)}
|
||||||
</TreeItem>
|
</InnovEnergyTreeItem>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@ interface InnovenergySnackbarProps {
|
||||||
setOpen: (value: boolean) => void;
|
setOpen: (value: boolean) => void;
|
||||||
error?: any;
|
error?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnovenergySnackbar = (props: InnovenergySnackbarProps) => {
|
const InnovenergySnackbar = (props: InnovenergySnackbarProps) => {
|
||||||
const { open, setOpen, error } = props;
|
const { open, setOpen, error } = props;
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { AxiosError } from "axios";
|
||||||
import { useContext, useEffect, useState } from "react";
|
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_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
import InstallationForm from "./InstallationForm";
|
import InstallationForm from "./InstallationForm";
|
||||||
import { colors } from "../..";
|
import { colors } from "../..";
|
||||||
import { S3CredentialsContext } from "../Context/S3CredentialsContextProvider";
|
import { S3CredentialsContext } from "../Context/S3CredentialsContextProvider";
|
||||||
|
import MoveDialog from "../Groups/Tree/MoveDialog";
|
||||||
|
|
||||||
interface I_InstallationProps {
|
interface I_InstallationProps {
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
@ -16,11 +17,16 @@ interface I_InstallationProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Installation = (props: I_InstallationProps) => {
|
const Installation = (props: I_InstallationProps) => {
|
||||||
const { hasMoveButton, values, loading, error } = props;
|
const { values, loading, error } = props;
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const handleSubmit = (data: I_Folder, formikValues: Partial<I_Folder>) => {
|
||||||
|
return axiosConfig.put("/UpdateInstallation", { ...data, ...formikValues });
|
||||||
|
};
|
||||||
|
|
||||||
if (values && values.id && values.id.toString() === id) {
|
if (values && values.id && values.id.toString() === id) {
|
||||||
|
const moveDialog = <MoveDialog values={values} />;
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -39,9 +45,15 @@ const Installation = (props: I_InstallationProps) => {
|
||||||
>
|
>
|
||||||
<InstallationForm
|
<InstallationForm
|
||||||
values={values}
|
values={values}
|
||||||
id={id}
|
handleSubmit={handleSubmit}
|
||||||
hasMoveButton={hasMoveButton}
|
additionalButtons={props.hasMoveButton ? [moveDialog] : []}
|
||||||
/>
|
/>
|
||||||
|
<Box>
|
||||||
|
{values.s3WriteKey && <div>{`Write key: ${values.s3WriteKey}`}</div>}
|
||||||
|
{values.s3WriteSecret && (
|
||||||
|
<div>{`Write secret: ${values.s3WriteSecret}`}</div>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
} else if (loading) {
|
} else if (loading) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Alert, Grid, Snackbar } from "@mui/material";
|
import { Alert, Grid, Snackbar } from "@mui/material";
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
import { useContext, useState } from "react";
|
import { ReactNode, useContext, 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";
|
||||||
import { I_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../util/types";
|
||||||
import { InstallationsContext } from "../Context/InstallationsContextProvider";
|
import { InstallationsContext } from "../Context/InstallationsContextProvider";
|
||||||
import MoveDialog from "../Groups/Tree/MoveDialog";
|
import MoveDialog from "../Groups/Tree/MoveDialog";
|
||||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||||
|
@ -13,15 +13,19 @@ import InnovenergyTextfield, {
|
||||||
} from "../Layout/InnovenergyTextfield";
|
} 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";
|
||||||
|
|
||||||
interface I_InstallationFormProps {
|
interface I_InstallationFormProps {
|
||||||
values: I_Installation;
|
values: I_Installation;
|
||||||
id: string | undefined;
|
handleSubmit: (
|
||||||
hasMoveButton?: boolean;
|
data: I_Installation,
|
||||||
|
formikValues: Partial<I_Installation>
|
||||||
|
) => Promise<AxiosResponse>;
|
||||||
|
additionalButtons?: ReactNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstallationForm = (props: I_InstallationFormProps) => {
|
const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
const { values, id, hasMoveButton } = props;
|
const { values, additionalButtons, handleSubmit } = props;
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const { fetchData } = useContext(InstallationsContext);
|
const { fetchData } = useContext(InstallationsContext);
|
||||||
|
@ -53,22 +57,18 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name: values.name,
|
name: values.region ? values.name : "",
|
||||||
region: values.region,
|
region: values.region,
|
||||||
location: values.location,
|
location: values.location,
|
||||||
country: values.country,
|
country: values.country,
|
||||||
orderNumbers: values.orderNumbers,
|
orderNumbers: values.orderNumbers,
|
||||||
},
|
},
|
||||||
onSubmit: (formikValues) => {
|
onSubmit: (formikValues) => {
|
||||||
axiosConfig
|
handleSubmit(values, formikValues)
|
||||||
.put("/UpdateInstallation", {
|
|
||||||
...formikValues,
|
|
||||||
id,
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setOpen(true);
|
|
||||||
fetchData();
|
fetchData();
|
||||||
});
|
})
|
||||||
|
.catch((err) => {});
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
});
|
});
|
||||||
|
@ -152,7 +152,10 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
<IePropertyGrid rows={rows} />
|
<IePropertyGrid rows={rows} />
|
||||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||||
{hasMoveButton && !readOnly && <MoveDialog values={values} />}
|
{/*{hasMoveButton && !readOnly && <MoveDialog values={values} />}*/}
|
||||||
|
{!readOnly &&
|
||||||
|
additionalButtons &&
|
||||||
|
additionalButtons.map((button) => button)}
|
||||||
{!readOnly && (
|
{!readOnly && (
|
||||||
<InnovenergyButton id="installation-form-submit-button" type="submit">
|
<InnovenergyButton id="installation-form-submit-button" type="submit">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { Fragment, useContext, useEffect } from "react";
|
||||||
import { I_Installation } from "../../util/types";
|
import { I_Installation } from "../../util/types";
|
||||||
import { InstallationsContext } from "../Context/InstallationsContextProvider";
|
import { InstallationsContext } from "../Context/InstallationsContextProvider";
|
||||||
import { colors } from "../..";
|
import { colors } from "../..";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
interface InstallationListProps {
|
interface InstallationListProps {
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
|
@ -65,7 +66,7 @@ const InstallationList = (props: InstallationListProps) => {
|
||||||
<CircularProgress sx={{ m: 6, color: theme.palette.secondary.main }} />
|
<CircularProgress sx={{ m: 6, color: theme.palette.secondary.main }} />
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
} else if (data && data.length) {
|
} else if (data && data.length > 0) {
|
||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -90,7 +91,10 @@ const InstallationList = (props: InstallationListProps) => {
|
||||||
<Link
|
<Link
|
||||||
id={"installation-list-link-" + installation.id}
|
id={"installation-list-link-" + installation.id}
|
||||||
to={
|
to={
|
||||||
getPathWithoutId(routeMatch?.pattern?.path) + installation.id
|
routes.installations +
|
||||||
|
routes.list +
|
||||||
|
routes.installation +
|
||||||
|
installation.id
|
||||||
}
|
}
|
||||||
style={{ textDecoration: "none", color: colors.black }}
|
style={{ textDecoration: "none", color: colors.black }}
|
||||||
>
|
>
|
||||||
|
@ -131,6 +135,12 @@ const InstallationList = (props: InstallationListProps) => {
|
||||||
{error.message}
|
{error.message}
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
|
} else if (data.length === 0) {
|
||||||
|
return (
|
||||||
|
<Alert severity="info" sx={{ mt: 1 }}>
|
||||||
|
<FormattedMessage id="noData" defaultMessage="No data found" />
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,22 +11,8 @@ import Installation from "./Installation";
|
||||||
import CheckboxTree from "./Log/CheckboxTree";
|
import CheckboxTree from "./Log/CheckboxTree";
|
||||||
import LogContextProvider from "../Context/LogContextProvider";
|
import LogContextProvider from "../Context/LogContextProvider";
|
||||||
import useRouteMatch from "../../hooks/useRouteMatch";
|
import useRouteMatch from "../../hooks/useRouteMatch";
|
||||||
import { Background } from "reactflow";
|
|
||||||
import { red } from "@mui/material/colors";
|
|
||||||
import S3CredentialsContextProvider, {
|
|
||||||
S3CredentialsContext,
|
|
||||||
} from "../Context/S3CredentialsContextProvider";
|
|
||||||
import { UnixTime } from "../../dataCache/time";
|
|
||||||
import { FetchResult } from "../../dataCache/dataCache";
|
|
||||||
import { DataRecord } from "../../dataCache/data";
|
|
||||||
import { S3Access } from "../../dataCache/S3/S3Access";
|
|
||||||
import { parseCsv } from "../../util/graph.util";
|
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
import { useContext, useEffect, useState } from "react";
|
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
|
||||||
import { I_Installation } from "../../util/types";
|
|
||||||
import { AxiosError } from "axios/index";
|
|
||||||
import useInstallation from "../../hooks/useInstallation";
|
import useInstallation from "../../hooks/useInstallation";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
const Installations = () => {
|
const Installations = () => {
|
||||||
const routeMatch = useRouteMatch([
|
const routeMatch = useRouteMatch([
|
||||||
|
|
|
@ -18,6 +18,7 @@ const LiveView = () => {
|
||||||
borderBottomLeftRadius: 4,
|
borderBottomLeftRadius: 4,
|
||||||
borderBottomRightRadius: 4,
|
borderBottomRightRadius: 4,
|
||||||
borderColor: theme.palette.text.disabled,
|
borderColor: theme.palette.text.disabled,
|
||||||
|
overflowX: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TopologyView />
|
<TopologyView />
|
||||||
|
|
|
@ -8,6 +8,7 @@ import useRouteMatch from "../../../hooks/useRouteMatch";
|
||||||
import routes from "../../../routes.json";
|
import routes from "../../../routes.json";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { colors } from "index";
|
import { colors } from "index";
|
||||||
|
import InnovEnergyTreeItem from "../../Layout/InnovEnergyTreeItem";
|
||||||
|
|
||||||
export interface ToggleElement {
|
export interface ToggleElement {
|
||||||
[key: string]: boolean;
|
[key: string]: boolean;
|
||||||
|
@ -54,7 +55,7 @@ const CheckboxTree = () => {
|
||||||
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("/");
|
||||||
return (
|
return (
|
||||||
<TreeItem
|
<InnovEnergyTreeItem
|
||||||
id={"checkbox-tree-" + element.name}
|
id={"checkbox-tree-" + element.name}
|
||||||
key={element.name}
|
key={element.name}
|
||||||
nodeId={element.name}
|
nodeId={element.name}
|
||||||
|
@ -74,16 +75,9 @@ const CheckboxTree = () => {
|
||||||
{splitName[splitName.length - 1]}
|
{splitName[splitName.length - 1]}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
sx={{
|
|
||||||
"& .MuiTreeItem-content": {
|
|
||||||
paddingY: "5px",
|
|
||||||
minHeight: "52px",
|
|
||||||
},
|
|
||||||
bgcolor: colors.greyDark,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{getNodes(element)}
|
{getNodes(element)}
|
||||||
</TreeItem>
|
</InnovEnergyTreeItem>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,8 +28,9 @@ const NUMBER_OF_NODES = 100;
|
||||||
|
|
||||||
const ScalarGraph = () => {
|
const ScalarGraph = () => {
|
||||||
const timeRange = createTimes(
|
const timeRange = createTimes(
|
||||||
UnixTime.now() /* .fromTicks(1682085650) */
|
UnixTime.now()
|
||||||
.rangeBefore(TimeSpan.fromDays(10)),
|
/* .fromTicks(1682085650) */
|
||||||
|
.rangeBefore(TimeSpan.fromDays(1)),
|
||||||
NUMBER_OF_NODES
|
NUMBER_OF_NODES
|
||||||
);
|
);
|
||||||
const [timeSeries, setTimeSeries] = useState<RecordSeries>([]);
|
const [timeSeries, setTimeSeries] = useState<RecordSeries>([]);
|
||||||
|
@ -56,6 +57,8 @@ const ScalarGraph = () => {
|
||||||
setTimeSeries(timeSeries);
|
setTimeSeries(timeSeries);
|
||||||
|
|
||||||
const toggleValues = timeSeries.find((timeStamp) => timeStamp.value);
|
const toggleValues = timeSeries.find((timeStamp) => timeStamp.value);
|
||||||
|
console.log("toggles", timeSeries, toggleValues);
|
||||||
|
|
||||||
if (toggles === null && toggleValues && toggleValues.value) {
|
if (toggles === null && toggleValues && toggleValues.value) {
|
||||||
const treeElements = getTreeElements(toggleValues.value);
|
const treeElements = getTreeElements(toggleValues.value);
|
||||||
setToggles(treeElements);
|
setToggles(treeElements);
|
||||||
|
@ -123,7 +126,6 @@ const ScalarGraph = () => {
|
||||||
|
|
||||||
const handleRelayout = useCallback(
|
const handleRelayout = useCallback(
|
||||||
(params: PlotRelayoutEvent) => {
|
(params: PlotRelayoutEvent) => {
|
||||||
console.log("relayout");
|
|
||||||
const xaxisRange0 = params["xaxis.range[0]"];
|
const xaxisRange0 = params["xaxis.range[0]"];
|
||||||
const xaxisRange1 = params["xaxis.range[1]"];
|
const xaxisRange1 = params["xaxis.range[1]"];
|
||||||
if (xaxisRange0 && xaxisRange1) {
|
if (xaxisRange0 && xaxisRange1) {
|
||||||
|
@ -138,6 +140,7 @@ const ScalarGraph = () => {
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const renderGraphs = () => {
|
const renderGraphs = () => {
|
||||||
|
console.log("toggles", toggles);
|
||||||
if (checkedToggles.length > 0) {
|
if (checkedToggles.length > 0) {
|
||||||
const coordinateTimeSeries = transformToGraphData(timeSeries);
|
const coordinateTimeSeries = transformToGraphData(timeSeries);
|
||||||
const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => {
|
const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => {
|
||||||
|
@ -209,18 +212,22 @@ const ScalarGraph = () => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (toggles === null) {
|
||||||
return (
|
return (
|
||||||
<Alert sx={{ mt: 2 }} severity="info">
|
<Alert sx={{ mt: 2 }} severity="error">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="makeASelection"
|
id="noGraphData"
|
||||||
defaultMessage="Please make a selection on the left"
|
defaultMessage="Couldn't find any graph data"
|
||||||
/>
|
/>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Alert sx={{ mt: 2 }} severity="error">
|
<Alert sx={{ mt: 2 }} severity="info">
|
||||||
<FormattedMessage id="error" defaultMessage="There was an error" />
|
<FormattedMessage
|
||||||
|
id="makeASelection"
|
||||||
|
defaultMessage="Please make a selection on the left"
|
||||||
|
/>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,62 +24,68 @@ export const BOX_SIZE = 75;
|
||||||
const TopologyBox = (props: TopologyBoxProps) => {
|
const TopologyBox = (props: TopologyBoxProps) => {
|
||||||
const { titleColor, boxColor } = getBoxColor(props.title);
|
const { titleColor, boxColor } = getBoxColor(props.title);
|
||||||
return (
|
return (
|
||||||
<Box
|
<div style={{ height: BOX_SIZE, width: BOX_SIZE }}>
|
||||||
sx={{
|
<Box
|
||||||
visibility: props.title ? "visible" : "hidden",
|
sx={{
|
||||||
height: BOX_SIZE + "px",
|
visibility: props.title ? "visible" : "hidden",
|
||||||
width: BOX_SIZE + "px",
|
height: BOX_SIZE + "px",
|
||||||
borderRadius: "4px",
|
width: BOX_SIZE + "px",
|
||||||
color: "white",
|
maxHeight: BOX_SIZE + "px",
|
||||||
}}
|
borderRadius: "4px",
|
||||||
>
|
color: "white",
|
||||||
<p
|
overflow: "hidden",
|
||||||
style={{
|
|
||||||
marginBlockStart: "0",
|
|
||||||
marginBlockEnd: "0",
|
|
||||||
backgroundColor: titleColor,
|
|
||||||
padding: "5px",
|
|
||||||
borderTopLeftRadius: "4px",
|
|
||||||
borderTopRightRadius: "4px",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.title}
|
<p
|
||||||
</p>
|
style={{
|
||||||
<div
|
marginBlockStart: "0",
|
||||||
style={{
|
marginBlockEnd: "0",
|
||||||
backgroundColor: boxColor,
|
backgroundColor: titleColor,
|
||||||
borderBottomLeftRadius: "4px",
|
padding: "5px",
|
||||||
borderBottomRightRadius: "4px",
|
borderTopLeftRadius: "4px",
|
||||||
padding: "5px",
|
borderTopRightRadius: "4px",
|
||||||
height: "51px",
|
display: "flex",
|
||||||
}}
|
justifyContent: "center",
|
||||||
>
|
textOverflow: "ellipsis",
|
||||||
{props.data && (
|
whiteSpace: "nowrap",
|
||||||
<>
|
overflow: "hidden",
|
||||||
{props.data.values.map((boxData, index) => {
|
}}
|
||||||
console.log("boxData", boxData);
|
>
|
||||||
return (
|
{props.title}
|
||||||
<p
|
</p>
|
||||||
key={props.title + "-" + index}
|
<div
|
||||||
style={{ marginBlockStart: "0", marginBlockEnd: "2px" }}
|
style={{
|
||||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
backgroundColor: boxColor,
|
||||||
>{`${
|
borderBottomLeftRadius: "4px",
|
||||||
props.data && props.data.values.length === 3
|
borderBottomRightRadius: "4px",
|
||||||
? "L" + (index + 1) + " "
|
padding: "5px",
|
||||||
: ""
|
height: BOX_SIZE - 34,
|
||||||
}${
|
}}
|
||||||
!isInt(Number(boxData.value))
|
>
|
||||||
? Number(boxData.value).toPrecision(4)
|
{props.data && (
|
||||||
: boxData.value
|
<>
|
||||||
}${boxData.unit}`}</p>
|
{props.data.values.map((boxData, index) => {
|
||||||
);
|
return (
|
||||||
})}
|
<p
|
||||||
</>
|
key={props.title + "-" + index}
|
||||||
)}
|
style={{ marginBlockStart: "0", marginBlockEnd: "2px" }}
|
||||||
</div>
|
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||||
</Box>
|
>{`${
|
||||||
|
props.data && props.data.values.length === 3
|
||||||
|
? "L" + (index + 1) + " "
|
||||||
|
: ""
|
||||||
|
}${
|
||||||
|
!isInt(Number(boxData.value))
|
||||||
|
? Number(boxData.value).toPrecision(4)
|
||||||
|
: boxData.value
|
||||||
|
}${boxData.unit}`}</p>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ type TopologyColumnProps = {
|
||||||
centerConnection?: TopologyFlowProps;
|
centerConnection?: TopologyFlowProps;
|
||||||
bottomBox?: TopologyBoxProps;
|
bottomBox?: TopologyBoxProps;
|
||||||
bottomConnection?: TopologyFlowProps;
|
bottomConnection?: TopologyFlowProps;
|
||||||
|
isLastColumn?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TopologyColumn = (props: TopologyColumnProps) => {
|
const TopologyColumn = (props: TopologyColumnProps) => {
|
||||||
|
@ -37,13 +38,15 @@ const TopologyColumn = (props: TopologyColumnProps) => {
|
||||||
/>
|
/>
|
||||||
<TopologyBox {...props.bottomBox} />
|
<TopologyBox {...props.bottomBox} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
{!props.isLastColumn && (
|
||||||
<TopologyFlow
|
<div>
|
||||||
{...props.centerConnection}
|
<TopologyFlow
|
||||||
orientation="horizontal"
|
{...props.centerConnection}
|
||||||
hidden={!props.centerBox}
|
orientation="horizontal"
|
||||||
/>
|
hidden={!props.centerBox}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,9 @@ export type TopologyFlowProps = {
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
};
|
};
|
||||||
const TopologyFlow = (props: TopologyFlowProps) => {
|
const TopologyFlow = (props: TopologyFlowProps) => {
|
||||||
const length = Math.abs((props.amount ?? 1) * BOX_SIZE);
|
const length = Math.abs(
|
||||||
|
((props.amount && props.amount < 0.1 ? 0.1 : props.amount) ?? 0) * BOX_SIZE
|
||||||
|
);
|
||||||
const values = props.data?.values;
|
const values = props.data?.values;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -45,7 +47,8 @@ const TopologyFlow = (props: TopologyFlowProps) => {
|
||||||
{values
|
{values
|
||||||
?.filter((boxData) => (boxData.value as number) !== 0)
|
?.filter((boxData) => (boxData.value as number) !== 0)
|
||||||
.map(
|
.map(
|
||||||
(boxData) => `${Math.round(boxData.value as number)} ${boxData.unit}`
|
(boxData) =>
|
||||||
|
`${Math.round(boxData.value as number)} ${boxData.unit}`
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { S3CredentialsContext } from "../../Context/S3CredentialsContextProvider
|
||||||
const TopologyView = () => {
|
const TopologyView = () => {
|
||||||
const [values, setValues] = useState<TopologyValues | null>(null);
|
const [values, setValues] = useState<TopologyValues | null>(null);
|
||||||
const { fetchData } = useContext(S3CredentialsContext);
|
const { fetchData } = useContext(S3CredentialsContext);
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
|
@ -37,8 +38,7 @@ const TopologyView = () => {
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, []);
|
}, [fetchData]);
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
if (values) {
|
if (values) {
|
||||||
const highestConnectionValue = getHighestConnectionValue(values);
|
const highestConnectionValue = getHighestConnectionValue(values);
|
||||||
|
@ -47,19 +47,13 @@ const TopologyView = () => {
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
paddingTop: 3,
|
padding: 3,
|
||||||
paddingBottom: 3,
|
|
||||||
bgcolor: "white",
|
bgcolor: "white",
|
||||||
px: 3 / 8,
|
|
||||||
border: 2,
|
|
||||||
borderTop: 0,
|
|
||||||
borderBottomLeftRadius: 4,
|
|
||||||
borderBottomRightRadius: 4,
|
|
||||||
borderColor: theme.palette.text.disabled,
|
|
||||||
borderTopColor: "white",
|
|
||||||
marginTop: 0.05,
|
marginTop: 0.05,
|
||||||
fontFamily: `"Ubuntu", sans-serif`,
|
fontFamily: `"Ubuntu", sans-serif`,
|
||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "fit-content",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
@ -217,6 +211,7 @@ const TopologyView = () => {
|
||||||
title: "Battery",
|
title: "Battery",
|
||||||
data: values.battery,
|
data: values.battery,
|
||||||
}}
|
}}
|
||||||
|
isLastColumn
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
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,40 @@
|
||||||
|
import { TreeItem, TreeItemProps } from "@mui/lab";
|
||||||
|
import { colors } from "../../index";
|
||||||
|
import { useTheme } from "@mui/material";
|
||||||
|
|
||||||
|
const InnovEnergyTreeItem = (props: TreeItemProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<TreeItem
|
||||||
|
id={props.id}
|
||||||
|
nodeId={props.nodeId}
|
||||||
|
label={props.label}
|
||||||
|
onClick={() => props.onClick}
|
||||||
|
sx={{
|
||||||
|
".MuiTreeItem-content": {
|
||||||
|
py: "10px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
width: "inherit",
|
||||||
|
},
|
||||||
|
".Mui-selected": {
|
||||||
|
backgroundColor: theme.palette.secondary.main + "!important",
|
||||||
|
borderRadius: "4px",
|
||||||
|
},
|
||||||
|
".MuiTreeItem-content:hover": {
|
||||||
|
borderRadius: "4px",
|
||||||
|
backgroundColor: theme.palette.secondary.light + "!important",
|
||||||
|
},
|
||||||
|
".MuiTreeItem-content.Mui-selected:hover": {
|
||||||
|
borderRadius: "4px",
|
||||||
|
backgroundColor: theme.palette.secondary.main + "!important",
|
||||||
|
},
|
||||||
|
borderRadius: "4px",
|
||||||
|
bgcolor: colors.greyDark,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</TreeItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InnovEnergyTreeItem;
|
|
@ -1,12 +1,11 @@
|
||||||
import { Button, SxProps, Theme, colors, useTheme } from "@mui/material";
|
import { Button, SxProps, Theme, colors, useTheme } from "@mui/material";
|
||||||
import { DAY_MARGIN } from "@mui/x-date-pickers/internals";
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { Background } from "reactflow";
|
|
||||||
|
|
||||||
interface I_InnovenergyButtonProps {
|
interface I_InnovenergyButtonProps {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
type?: "button" | "submit" | "reset" | undefined;
|
type?: "button" | "submit" | "reset" | undefined;
|
||||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;
|
||||||
sx?: SxProps<Theme> | undefined;
|
sx?: SxProps<Theme> | undefined;
|
||||||
id?: string;
|
id?: string;
|
||||||
}
|
}
|
||||||
|
@ -19,13 +18,14 @@ const InnovenergyButton = (props: I_InnovenergyButtonProps) => {
|
||||||
variant="contained"
|
variant="contained"
|
||||||
type={props.type}
|
type={props.type}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
sx={{...props.sx,
|
onKeyDown={props.onKeyDown}
|
||||||
|
sx={{
|
||||||
|
...props.sx,
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
bgcolor: theme.palette.secondary.main,
|
bgcolor: theme.palette.secondary.main,
|
||||||
":hover":{
|
":hover": {
|
||||||
bgcolor: theme.palette.secondary.dark,
|
bgcolor: theme.palette.secondary.dark,
|
||||||
}
|
},
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -33,6 +33,4 @@ const InnovenergyButton = (props: I_InnovenergyButtonProps) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default InnovenergyButton;
|
export default InnovenergyButton;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { styled, SxProps, Tab, Tabs, Theme, useTheme } from "@mui/material";
|
import { Tab, useTheme } from "@mui/material";
|
||||||
import { TabProps } from "@mui/material/Tab/Tab";
|
|
||||||
import { colors } from "index";
|
import { colors } from "index";
|
||||||
|
|
||||||
const InnovenergyTab = (props: any) => {
|
const InnovenergyTab = (props: any) => {
|
||||||
|
@ -21,43 +20,8 @@ const InnovenergyTab = (props: any) => {
|
||||||
borderTopRightRadius: "0.3rem",
|
borderTopRightRadius: "0.3rem",
|
||||||
padding: ".5rem 1rem",
|
padding: ".5rem 1rem",
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
|
||||||
backgroundColor: "#eaecf1",
|
|
||||||
color: colors.black,
|
|
||||||
borderColor: theme.palette.text.disabled,
|
|
||||||
marginTop: "1px",
|
|
||||||
bottom: -1,
|
|
||||||
...(props.sx ? props.sx["&.Mui-selected"] : {}),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const InnovenergyTabBorder = (props: any) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<Tab
|
|
||||||
{...props}
|
|
||||||
disableRipple
|
|
||||||
sx={{
|
|
||||||
textTransform: "none",
|
|
||||||
...props.sx,
|
|
||||||
bottom: 0,
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
fontSize: theme.typography.pxToRem(14),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
background: "0 0",
|
|
||||||
border: "2px solid",
|
|
||||||
borderColor: "#c0c6d0",
|
|
||||||
bgcolor: theme.palette.primary.light,
|
|
||||||
borderTopLeftRadius: "0.3rem",
|
|
||||||
borderTopRightRadius: "0.3rem",
|
|
||||||
padding: ".5rem 1rem",
|
|
||||||
textDecoration: "none",
|
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
"&.Mui-selected": {
|
||||||
|
backgroundColor: theme.palette.primary.light,
|
||||||
color: colors.black,
|
color: colors.black,
|
||||||
borderColor: theme.palette.text.disabled,
|
borderColor: theme.palette.text.disabled,
|
||||||
marginTop: "1px",
|
marginTop: "1px",
|
||||||
|
|
|
@ -24,7 +24,7 @@ const InnovenergyTabs = (props: AntTabsProps) => {
|
||||||
},
|
},
|
||||||
"&.Mui-selected": {
|
"&.Mui-selected": {
|
||||||
color: colors.black,
|
color: colors.black,
|
||||||
backgroundColor: "#eaecf1",
|
backgroundColor: theme.palette.primary.light,
|
||||||
borderColor: `#90A7c5 #90A7c5 #fff`,
|
borderColor: `#90A7c5 #90A7c5 #fff`,
|
||||||
},
|
},
|
||||||
"& .MuiTabs-indicator": {
|
"& .MuiTabs-indicator": {
|
||||||
|
|
|
@ -15,13 +15,13 @@ const LanguageSelect = (props: LanguageSelectProps) => {
|
||||||
label="Age"
|
label="Age"
|
||||||
onChange={(e) => props.setLanguage(e.target.value)}
|
onChange={(e) => props.setLanguage(e.target.value)}
|
||||||
>
|
>
|
||||||
<MenuItem id="english-menu-item" value="EN">
|
<MenuItem id="english-menu-item" value="en">
|
||||||
<FormattedMessage id="english" defaultMessage="English" />
|
<FormattedMessage id="english" defaultMessage="English" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem id="german-menu-item" value="DE">
|
<MenuItem id="german-menu-item" value="de">
|
||||||
<FormattedMessage id="german" defaultMessage="German" />
|
<FormattedMessage id="german" defaultMessage="German" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem id="german-menu-item" value="FR">
|
<MenuItem id="german-menu-item" value="fr">
|
||||||
<FormattedMessage id="french" defaultMessage="French" />
|
<FormattedMessage id="french" defaultMessage="French" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -29,7 +29,6 @@ const NavigationTabs = () => {
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: theme.palette.primary.main,
|
bgcolor: theme.palette.primary.main,
|
||||||
"&.Mui-selected": {
|
"&.Mui-selected": {
|
||||||
backgroundColor: "#eaecf1",
|
|
||||||
borderColor: theme.palette.text.disabled,
|
borderColor: theme.palette.text.disabled,
|
||||||
borderBottom: 0,
|
borderBottom: 0,
|
||||||
mb: -1 / 8,
|
mb: -1 / 8,
|
||||||
|
@ -50,7 +49,6 @@ const NavigationTabs = () => {
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: theme.palette.primary.main,
|
bgcolor: theme.palette.primary.main,
|
||||||
"&.Mui-selected": {
|
"&.Mui-selected": {
|
||||||
backgroundColor: "#eaecf1",
|
|
||||||
borderColor: theme.palette.text.disabled,
|
borderColor: theme.palette.text.disabled,
|
||||||
borderBottom: 0,
|
borderBottom: 0,
|
||||||
mb: -1 / 8,
|
mb: -1 / 8,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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, useTheme } from "@mui/material";
|
import { Alert, Divider, useTheme } 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";
|
||||||
|
@ -9,6 +9,7 @@ import { Fragment, useContext } from "react";
|
||||||
import { UsersContext } from "../Context/UsersContextProvider";
|
import { UsersContext } from "../Context/UsersContextProvider";
|
||||||
import { I_User } from "../../util/user.util";
|
import { I_User } from "../../util/user.util";
|
||||||
import { colors } from "../..";
|
import { colors } from "../..";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
const getPathWithoutId = (path?: string) => {
|
const getPathWithoutId = (path?: string) => {
|
||||||
if (path) {
|
if (path) {
|
||||||
|
@ -38,7 +39,7 @@ const UserList = (props: UserListProps) => {
|
||||||
const routeMatch = useRouteMatch([routes.users + routes.user + ":id"]);
|
const routeMatch = useRouteMatch([routes.users + routes.user + ":id"]);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
if (filteredData && filteredData.length) {
|
if (filteredData && filteredData.length > 0) {
|
||||||
return (
|
return (
|
||||||
<List
|
<List
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -87,6 +88,12 @@ const UserList = (props: UserListProps) => {
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
|
} else if (filteredData?.length === 0) {
|
||||||
|
return (
|
||||||
|
<Alert severity="info" sx={{ mt: 1 }}>
|
||||||
|
<FormattedMessage id="noData" defaultMessage="No data found" />
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,77 +1,78 @@
|
||||||
import {sha1Hmac} from "./Sha1";
|
import { sha1Hmac } from "./Sha1";
|
||||||
import {Utf8} from "./Utf8";
|
import { Utf8 } from "./Utf8";
|
||||||
import {toBase64} from "./UInt8Utils";
|
import { toBase64 } from "./UInt8Utils";
|
||||||
|
|
||||||
export class S3Access
|
export class S3Access {
|
||||||
{
|
constructor(
|
||||||
constructor
|
readonly bucket: string,
|
||||||
(
|
readonly region: string,
|
||||||
readonly bucket: string,
|
readonly provider: string,
|
||||||
readonly region: string,
|
readonly key: string,
|
||||||
readonly provider: string,
|
readonly secret: string
|
||||||
readonly key: string,
|
) {}
|
||||||
readonly secret: string
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
get host() : string { return `${this.bucket}.${this.region}.${this.provider}` }
|
get host(): string {
|
||||||
get url() : string { return `https://${this.host}` }
|
return `${this.region}.${this.provider}`;
|
||||||
|
}
|
||||||
|
|
||||||
public get(s3Path : string): Promise<Response>
|
get url(): string {
|
||||||
{
|
return `https://${this.host}`;
|
||||||
const method = "GET";
|
}
|
||||||
const auth = this.createAuthorizationHeader(method, s3Path, "");
|
|
||||||
const url = this.url + "/" + s3Path
|
|
||||||
const headers = {"Host": this.host, "Authorization": auth};
|
|
||||||
|
|
||||||
try
|
public get(s3Path: string): Promise<Response> {
|
||||||
{
|
const method = "GET";
|
||||||
return fetch(url, {method: method, mode: "cors", headers: headers})
|
const auth = this.createAuthorizationHeader(method, s3Path, "");
|
||||||
}
|
const url = this.url + "/" + this.bucket + "/" + s3Path;
|
||||||
catch
|
const headers = { Host: this.host, Authorization: auth };
|
||||||
{
|
|
||||||
return Promise.reject()
|
try {
|
||||||
}
|
return fetch(url, { method: method, mode: "cors", headers: headers });
|
||||||
|
} catch {
|
||||||
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private createAuthorizationHeader(method: string,
|
private createAuthorizationHeader(
|
||||||
s3Path: string,
|
method: string,
|
||||||
date: string)
|
s3Path: string,
|
||||||
{
|
date: string
|
||||||
return createAuthorizationHeader
|
) {
|
||||||
(
|
return createAuthorizationHeader(
|
||||||
method,
|
method,
|
||||||
this.bucket,
|
this.bucket,
|
||||||
s3Path,
|
s3Path,
|
||||||
date,
|
date,
|
||||||
this.key,
|
this.key,
|
||||||
this.secret
|
this.secret
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAuthorizationHeader(method: string,
|
function createAuthorizationHeader(
|
||||||
bucket: string,
|
method: string,
|
||||||
s3Path: string,
|
bucket: string,
|
||||||
date: string,
|
s3Path: string,
|
||||||
s3Key: string,
|
date: string,
|
||||||
s3Secret: string,
|
s3Key: string,
|
||||||
contentType: string = "",
|
s3Secret: string,
|
||||||
md5Hash: string = "")
|
contentType: string = "",
|
||||||
{
|
md5Hash: string = ""
|
||||||
// StringToSign = HTTP-Verb + "\n" +
|
) {
|
||||||
// Content-MD5 + "\n" +
|
// StringToSign = HTTP-Verb + "\n" +
|
||||||
// Content-Type + "\n" +
|
// Content-MD5 + "\n" +
|
||||||
// Date + "\n" +
|
// Content-Type + "\n" +
|
||||||
// CanonicalizedAmzHeaders +
|
// Date + "\n" +
|
||||||
// CanonicalizedResource;
|
// CanonicalizedAmzHeaders +
|
||||||
|
// CanonicalizedResource;
|
||||||
|
|
||||||
const payload = Utf8.encode(`${method}\n${md5Hash}\n${contentType}\n${date}\n/${bucket}/${s3Path}`)
|
const payload = Utf8.encode(
|
||||||
|
`${method}\n${md5Hash}\n${contentType}\n${date}\n/${bucket}/${s3Path}`
|
||||||
|
);
|
||||||
|
|
||||||
//console.log(`${method}\n${md5Hash}\n${contentType}\n${date}\n/${bucket}/${s3Path}`)
|
//console.log(`${method}\n${md5Hash}\n${contentType}\n${date}\n/${bucket}/${s3Path}`)
|
||||||
|
|
||||||
const secret = Utf8.encode(s3Secret)
|
const secret = Utf8.encode(s3Secret);
|
||||||
const signature = toBase64(sha1Hmac(payload, secret));
|
const signature = toBase64(sha1Hmac(payload, secret));
|
||||||
|
|
||||||
return `AWS ${s3Key}:${signature}`
|
return `AWS ${s3Key}:${signature}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const colors = {
|
||||||
//change this color in index.css too
|
//change this color in index.css too
|
||||||
|
|
||||||
greyDark: "#d1d7de",
|
greyDark: "#d1d7de",
|
||||||
greyLight: "#e1e4e7",
|
greyLight: "#eaecf1",
|
||||||
|
|
||||||
orangeSelected: "#f7b34d",
|
orangeSelected: "#f7b34d",
|
||||||
orangeHover: "#fad399",
|
orangeHover: "#fad399",
|
||||||
|
|
|
@ -197,12 +197,6 @@ export const getAmount = (
|
||||||
highestConnectionValue: number,
|
highestConnectionValue: number,
|
||||||
values: BoxDataValue[]
|
values: BoxDataValue[]
|
||||||
) => {
|
) => {
|
||||||
console.log(
|
|
||||||
"getamount",
|
|
||||||
Math.abs(values[0].value as number) / highestConnectionValue,
|
|
||||||
Math.abs(values[0].value as number),
|
|
||||||
highestConnectionValue
|
|
||||||
);
|
|
||||||
return Math.abs(values[0].value as number) / highestConnectionValue;
|
return Math.abs(values[0].value as number) / highestConnectionValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
import { styled, Tab, Tabs } from "@mui/material";
|
|
||||||
import { colors } from "index";
|
|
||||||
|
|
||||||
|
|
||||||
export const StyledTab = styled((props: any) => (
|
|
||||||
<Tab disableRipple {...props} />
|
|
||||||
))(({ theme }) => ({
|
|
||||||
bottom: -1,
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
fontSize: theme.typography.pxToRem(14),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
background: "0 0",
|
|
||||||
border: "1px solid transparent",
|
|
||||||
borderTopLeftRadius: "0.3rem",
|
|
||||||
borderTopRightRadius: "0.3rem",
|
|
||||||
padding: ".5rem 1rem",
|
|
||||||
textDecoration: "none",
|
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "#F2F4F8",
|
|
||||||
borderColor: "#90A7c5 #90A7c5 #F2F4F8",
|
|
||||||
marginTop: "1px",
|
|
||||||
bottom: -1,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledTabBlue = styled((props: any) => (
|
|
||||||
<Tab disableRipple {...props} />
|
|
||||||
))(({ theme }) => ({
|
|
||||||
bottom: -1,
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
fontSize: theme.typography.pxToRem(14),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
background: "0 0",
|
|
||||||
border: "1px solid transparent",
|
|
||||||
borderBottom: "0px",
|
|
||||||
borderTopLeftRadius: "0.3rem",
|
|
||||||
borderTopRightRadius: "0.3rem",
|
|
||||||
padding: ".5rem 1rem",
|
|
||||||
textDecoration: "none",
|
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
|
||||||
bottom: -1,
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "#CCD6E4",
|
|
||||||
borderColor: "#90A7c5 #90A7c5 #CCD6E4",
|
|
||||||
marginTop: "1px",
|
|
||||||
},
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledTabBig = styled((props: any) => (
|
|
||||||
<Tab disableRipple {...props} />
|
|
||||||
))(({ theme }) => ({
|
|
||||||
bottom: -2,
|
|
||||||
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
fontSize: theme.typography.pxToRem(14),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
background: "0 0",
|
|
||||||
border: "2px solid transparent",
|
|
||||||
borderTopLeftRadius: "0.3rem",
|
|
||||||
borderTopRightRadius: "0.3rem",
|
|
||||||
padding: ".5rem 1rem",
|
|
||||||
textDecoration: "none",
|
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "#F2F4F8",
|
|
||||||
borderColor: "#90A7c5 #90A7c5 #F2F4F8",
|
|
||||||
marginTop: "1px",
|
|
||||||
bottom: -2,
|
|
||||||
},
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledTabWhite = styled((props: any) => (
|
|
||||||
<Tab disableRipple {...props} />
|
|
||||||
))(({ theme }) => ({
|
|
||||||
bottom: -1,
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
fontSize: theme.typography.pxToRem(14),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
background: "0 0",
|
|
||||||
border: "1px solid transparent",
|
|
||||||
borderTopLeftRadius: "0.3rem",
|
|
||||||
borderTopRightRadius: "0.3rem",
|
|
||||||
padding: ".5rem 1rem",
|
|
||||||
textDecoration: "none",
|
|
||||||
transition: `color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out`,
|
|
||||||
"&.Mui-selected": {
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "White",
|
|
||||||
borderColor: "#90A7c5 #90A7c5 White",
|
|
||||||
marginTop: "1px",
|
|
||||||
bottom: -1,
|
|
||||||
},
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const AntTabsBig = styled(Tabs)({
|
|
||||||
borderBottom: "2px solid #90A7c5",
|
|
||||||
overflow: "visible!important",
|
|
||||||
"& div.MuiTabs-scroller": {
|
|
||||||
overflow: "visible!important",
|
|
||||||
},
|
|
||||||
"&.Mui-selected": {
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "red",
|
|
||||||
borderColor: `#90A7c5 #90A7c5 #fff`,
|
|
||||||
},
|
|
||||||
"& .MuiTabs-indicator": {
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
},
|
|
||||||
"&.MuiTabs-root": {
|
|
||||||
width: "100%",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AntTabs = styled(Tabs)({
|
|
||||||
borderBottom: "1px solid #90A7c5",
|
|
||||||
overflow: "visible!important",
|
|
||||||
"& div.MuiTabs-scroller": {
|
|
||||||
overflow: "visible!important",
|
|
||||||
},
|
|
||||||
"&.Mui-selected": {
|
|
||||||
color: colors.black,
|
|
||||||
backgroundColor: "red",
|
|
||||||
borderColor: `#90A7c5 #90A7c5 #fff`,
|
|
||||||
},
|
|
||||||
"& .MuiTabs-indicator": {
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
},
|
|
||||||
"&.MuiTabs-root": {
|
|
||||||
width: "100%",
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -23,6 +23,8 @@ export interface I_Installation extends S3Credentials {
|
||||||
name: string;
|
name: string;
|
||||||
information: string;
|
information: string;
|
||||||
parentId: number;
|
parentId: number;
|
||||||
|
s3WriteKey: string;
|
||||||
|
s3WriteSecret: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface I_Folder {
|
export interface I_Folder {
|
||||||
|
|
Loading…
Reference in New Issue