Files
object-browser/portal-ui/src/screens/Console/Console.tsx
Alex 6b11d403a6 Add Tenant page refactor (#617)
Refactored add tenant page to be working with reducers & settings styles
2021-03-02 20:18:53 -08:00

432 lines
12 KiB
TypeScript

// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useState, useEffect } from "react";
import clsx from "clsx";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { Button, LinearProgress } from "@material-ui/core";
import CssBaseline from "@material-ui/core/CssBaseline";
import Drawer from "@material-ui/core/Drawer";
import Container from "@material-ui/core/Container";
import Snackbar from "@material-ui/core/Snackbar";
import history from "../../history";
import { Redirect, Route, Router, Switch } from "react-router-dom";
import { connect } from "react-redux";
import { AppState } from "../../store";
import {
serverIsLoading,
serverNeedsRestart,
setMenuOpen,
setSnackBarMessage,
} from "../../actions";
import { ISessionResponse } from "./types";
import { snackBarMessage } from "../../types";
import { snackBarCommon } from "./Common/FormComponents/common/styleLibrary";
import Buckets from "./Buckets/Buckets";
import Policies from "./Policies/Policies";
import Dashboard from "./Dashboard/Dashboard";
import Menu from "./Menu/Menu";
import api from "../../common/api";
import Account from "./Account/Account";
import Users from "./Users/Users";
import Groups from "./Groups/Groups";
import ConfigurationMain from "./Configurations/ConfigurationMain";
import WebhookPanel from "./Configurations/ConfigurationPanels/WebhookPanel";
import TenantsMain from "./Tenants/TenantsMain";
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
import ObjectBrowser from "./ObjectBrowser/ObjectBrowser";
import ObjectRouting from "./Buckets/ListBuckets/Objects/ListObjects/ObjectRouting";
import License from "./License/License";
import Trace from "./Trace/Trace";
import LogsMain from "./Logs/LogsMain";
import Heal from "./Heal/Heal";
import Watch from "./Watch/Watch";
import HealthInfo from "./HealthInfo/HealthInfo";
const drawerWidth = 245;
const styles = (theme: Theme) =>
createStyles({
root: {
display: "flex",
"& .MuiPaper-root.MuiSnackbarContent-root": {
borderRadius: "0px 0px 5px 5px",
boxShadow: "none",
},
},
toolbar: {
background: theme.palette.background.default,
color: "black",
paddingRight: 24, // keep right padding when drawer closed
},
toolbarIcon: {
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
padding: "0 8px",
...theme.mixins.toolbar,
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
appBarShift: {
marginLeft: drawerWidth,
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
menuButton: {
marginRight: 36,
},
menuButtonHidden: {
display: "none",
},
title: {
flexGrow: 1,
},
drawerPaper: {
position: "relative",
whiteSpace: "nowrap",
width: drawerWidth,
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
overflowX: "hidden",
background:
"transparent linear-gradient(90deg, #073052 0%, #081C42 100%) 0% 0% no-repeat padding-box",
boxShadow: "0px 3px 7px #00000014",
},
drawerPaperClose: {
overflowX: "hidden",
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
width: theme.spacing(7),
[theme.breakpoints.up("sm")]: {
width: theme.spacing(9),
},
},
content: {
flexGrow: 1,
height: "100vh",
overflow: "auto",
position: "relative",
},
container: {
paddingBottom: theme.spacing(4),
margin: 0,
width: "100%",
maxWidth: "initial",
},
paper: {
padding: theme.spacing(2),
display: "flex",
overflow: "auto",
flexDirection: "column",
},
fixedHeight: {
minHeight: 240,
},
warningBar: {
background: theme.palette.primary.main,
color: "white",
heigh: "60px",
widht: "100%",
lineHeight: "60px",
textAlign: "center",
},
progress: {
height: "3px",
backgroundColor: "#eaeaea",
},
...snackBarCommon,
});
interface IConsoleProps {
open: boolean;
needsRestart: boolean;
isServerLoading: boolean;
title: string;
classes: any;
setMenuOpen: typeof setMenuOpen;
serverNeedsRestart: typeof serverNeedsRestart;
serverIsLoading: typeof serverIsLoading;
session: ISessionResponse;
loadingProgress: number;
snackBarMessage: snackBarMessage;
setSnackBarMessage: typeof setSnackBarMessage;
}
const Console = ({
classes,
open,
needsRestart,
isServerLoading,
serverNeedsRestart,
serverIsLoading,
session,
loadingProgress,
snackBarMessage,
setSnackBarMessage,
}: IConsoleProps) => {
const [openSnackbar, setOpenSnackbar] = useState<boolean>(false);
const restartServer = () => {
serverIsLoading(true);
api
.invoke("POST", "/api/v1/service/restart", {})
.then((res) => {
console.log("success restarting service");
console.log(res);
serverIsLoading(false);
serverNeedsRestart(false);
})
.catch((err) => {
serverIsLoading(false);
console.log("failure restarting service");
console.log(err);
});
};
const allowedPages = session.pages.reduce(
(result: any, item: any, index: any) => {
result[item] = true;
return result;
},
{}
);
const routes = [
{
component: Dashboard,
path: "/dashboard",
},
{
component: Buckets,
path: "/buckets",
},
{
component: Buckets,
path: "/buckets/:bucketName",
},
{
component: ObjectBrowser,
path: "/object-browser",
},
{
component: ObjectRouting,
path: "/object-browser/:bucket",
},
{
component: ObjectRouting,
path: "/object-browser/:bucket/*",
},
{
component: Watch,
path: "/watch",
},
{
component: Users,
path: "/users",
},
{
component: Groups,
path: "/groups",
},
{
component: Policies,
path: "/policies",
},
{
component: Heal,
path: "/heal",
},
{
component: Trace,
path: "/trace",
},
{
component: LogsMain,
path: "/logs",
},
{
component: HealthInfo,
path: "/health-info",
},
{
component: ConfigurationMain,
path: "/settings",
},
{
component: Account,
path: "/account",
},
{
component: WebhookPanel,
path: "/webhook/logger",
},
{
component: WebhookPanel,
path: "/webhook/audit",
},
{
component: TenantsMain,
path: "/tenants",
},
{
component: TenantDetails,
path: "/namespaces/:tenantNamespace/tenants/:tenantName",
},
{
component: License,
path: "/license",
},
];
const allowedRoutes = routes.filter((route: any) => allowedPages[route.path]);
const closeSnackBar = () => {
setOpenSnackbar(false);
setSnackBarMessage("");
};
useEffect(() => {
if (snackBarMessage.message === "") {
setOpenSnackbar(false);
return;
}
// Open SnackBar
setOpenSnackbar(true);
}, [snackBarMessage]);
return (
<Fragment>
{session.status === "ok" ? (
<div className={classes.root}>
<CssBaseline />
<Drawer
variant="permanent"
classes={{
paper: clsx(
classes.drawerPaper,
!open && classes.drawerPaperClose
),
}}
open={open}
>
<Menu pages={session.pages} />
</Drawer>
<main className={classes.content}>
{needsRestart && (
<div className={classes.warningBar}>
{isServerLoading ? (
<Fragment>
The server is restarting.
<LinearProgress className={classes.progress} />
</Fragment>
) : (
<Fragment>
The instance needs to be restarted for configuration changes
to take effect.{" "}
<Button
color="secondary"
size="small"
onClick={() => {
restartServer();
}}
>
Restart
</Button>
</Fragment>
)}
</div>
)}
{loadingProgress < 100 && (
<LinearProgress
className={classes.progress}
variant="determinate"
value={loadingProgress}
/>
)}
<div className={classes.snackDiv}>
<Snackbar
open={openSnackbar}
onClose={() => {
closeSnackBar();
}}
autoHideDuration={
snackBarMessage.type === "error" ? 10000 : 5000
}
message={snackBarMessage.message}
className={classes.snackBarExternal}
ContentProps={{
className: `${classes.snackBar} ${
snackBarMessage.type === "error"
? classes.errorSnackBar
: ""
}`,
}}
/>
</div>
<Container className={classes.container}>
<Router history={history}>
<Switch>
{allowedRoutes.map((route: any) => (
<Route
key={route.path}
exact
path={route.path}
component={route.component}
/>
))}
{allowedRoutes.length > 0 ? (
<Redirect to={allowedRoutes[0].path} />
) : null}
</Switch>
</Router>
</Container>
</main>
</div>
) : null}
</Fragment>
);
};
const mapState = (state: AppState) => ({
open: state.system.sidebarOpen,
needsRestart: state.system.serverNeedsRestart,
isServerLoading: state.system.serverIsLoading,
session: state.console.session,
loadingProgress: state.system.loadingProgress,
snackBarMessage: state.system.snackBar,
});
const connector = connect(mapState, {
setMenuOpen,
serverNeedsRestart,
serverIsLoading,
setSnackBarMessage,
});
export default withStyles(styles)(connector(Console));