Removed unused pagination items (#470)

Removed unused pagination items, also updated dependencies of material-ui

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
This commit is contained in:
Alex
2020-12-07 12:13:12 -06:00
committed by GitHub
parent 3c0e3a1208
commit 8404baecd8
22 changed files with 293 additions and 1745 deletions

File diff suppressed because one or more lines are too long

View File

@@ -3,9 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.7.4",
"@babel/plugin-transform-react-jsx-development": "^7.9.0",
"@hot-loader/react-dom": "^16.9.0",
"@hot-loader/react-dom": "17.0.1",
"@material-ui/core": "^4.9.12",
"@material-ui/icons": "^4.9.1",
"@types/history": "^4.7.3",
@@ -30,14 +28,14 @@
"local-storage-fallback": "^4.1.1",
"lodash": "^4.17.19",
"moment": "^2.24.0",
"react": "17.0.0",
"react": "17.0.1",
"react-app-rewire-hot-loader": "^2.0.1",
"react-app-rewired": "^2.1.6",
"react-async-hook": "^3.6.1",
"react-chartjs-2": "^2.9.0",
"react-codemirror2": "^7.1.0",
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "17.0.0",
"react-dom": "17.0.1",
"react-hot-loader": "^4.13.0",
"react-moment": "^0.9.7",
"react-redux": "^7.1.3",

View File

@@ -20,7 +20,6 @@ import { connect } from "react-redux";
import { AppState } from "./store";
import { userLoggedIn } from "./actions";
import api from "./common/api";
import { clearSession } from "./common/utils";
import { saveSessionResponse } from "./screens/Console/actions";
const mapState = (state: AppState) => ({

View File

@@ -15,8 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { createStyles, Theme } from "@material-ui/core/styles";
import history from "../../../history";
import { Route, Router, Switch, withRouter } from "react-router-dom";
import { connect } from "react-redux";

View File

@@ -27,7 +27,6 @@ import { Bucket, BucketList } from "../types";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import AddBucket from "./AddBucket";
import DeleteBucket from "./DeleteBucket";
import { MinTablePaginationActions } from "../../../../common/MinTablePaginationActions";
import { CreateIcon } from "../../../../icons";
import { niceBytes } from "../../../../common/utils";
import { AppState } from "../../../../store";
@@ -89,11 +88,8 @@ const ListBuckets = ({
addBucketReset,
}: IListBucketsProps) => {
const [records, setRecords] = useState<Bucket[]>([]);
const [totalRecords, setTotalRecords] = useState<number>(0);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>("");
const [page, setPage] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
const [selectedBucket, setSelectedBucket] = useState<string>("");
const [filterBuckets, setFilterBuckets] = useState<string>("");
@@ -102,28 +98,12 @@ const ListBuckets = ({
if (loading) {
const fetchRecords = () => {
setLoading(true);
const offset = page * rowsPerPage;
api
.invoke(
"GET",
`/api/v1/buckets?offset=${offset}&limit=${rowsPerPage}`
)
.invoke("GET", `/api/v1/buckets`)
.then((res: BucketList) => {
setLoading(false);
setRecords(res.buckets || []);
setTotalRecords(!res.buckets ? 0 : res.total);
setError("");
// if we get 0 results, and page > 0 , go down 1 page
if (
(res.buckets === undefined ||
res.buckets == null ||
res.buckets.length === 0) &&
page > 0
) {
const newPage = page - 1;
setPage(newPage);
setLoading(true);
}
})
.catch((err: any) => {
setLoading(false);
@@ -132,7 +112,7 @@ const ListBuckets = ({
};
fetchRecords();
}
}, [loading, page, rowsPerPage]);
}, [loading]);
const closeAddModalAndRefresh = (refresh: boolean) => {
addBucketOpen(false);
@@ -156,31 +136,18 @@ const ListBuckets = ({
useEffect(() => {
setLoading(true);
}, [page, rowsPerPage]);
}, []);
const confirmDeleteBucket = (bucket: string) => {
setDeleteOpen(true);
setSelectedBucket(bucket);
};
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
const tableActions = [
{ type: "view", to: `/buckets`, sendOnlyId: true },
{ type: "delete", onClick: confirmDeleteBucket, sendOnlyId: true },
];
const offset = page * rowsPerPage;
const displayParsedDate = (date: string) => {
return <Moment>{date}</Moment>;
};
@@ -197,8 +164,6 @@ const ListBuckets = ({
}
});
const showInPage = filteredRecords;
return (
<React.Fragment>
{addBucketModalOpen && (
@@ -271,7 +236,7 @@ const ListBuckets = ({
},
]}
isLoading={loading}
records={showInPage}
records={filteredRecords}
entityName="Buckets"
idField="name"
/>

View File

@@ -1,3 +1,19 @@
// This file is part of MinIO Console Server
// Copyright (c) 2020 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, { useState } from "react";
import {
Button,

View File

@@ -37,7 +37,6 @@ import {
} from "../types";
import { Button } from "@material-ui/core";
import SetAccessPolicy from "./SetAccessPolicy";
import { MinTablePaginationActions } from "../../../../common/MinTablePaginationActions";
import { CreateIcon } from "../../../../icons";
import AddEvent from "./AddEvent";
import DeleteEvent from "./DeleteEvent";
@@ -181,7 +180,6 @@ interface IViewBucketState {
info: BucketInfo | null;
records: BucketEvent[];
replicationRules: BucketReplicationRule[];
totalRecords: number;
loadingBucket: boolean;
loadingEvents: boolean;
loadingSize: boolean;
@@ -189,8 +187,6 @@ interface IViewBucketState {
deleteError: string;
errBucket: string;
setAccessPolicyScreenOpen: boolean;
page: number;
rowsPerPage: number;
curTab: number;
addScreenOpen: boolean;
enableEncryptionScreenOpen: boolean;
@@ -210,7 +206,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
info: null,
records: [],
replicationRules: [],
totalRecords: 0,
loadingBucket: true,
loadingEvents: true,
loadingSize: true,
@@ -218,9 +213,7 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
deleteError: "",
errBucket: "",
setAccessPolicyScreenOpen: false,
page: 0,
curTab: 0,
rowsPerPage: 10,
addScreenOpen: false,
enableEncryptionScreenOpen: false,
deleteOpen: false,
@@ -236,28 +229,18 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
fetchEvents() {
this.setState({ loadingBucket: true }, () => {
const { page } = this.state;
const { match } = this.props;
const bucketName = match.params["bucketName"];
api
.invoke("GET", `/api/v1/buckets/${bucketName}/events`)
.then((res: BucketEventList) => {
const events = get(res, "events", []);
const total = get(res, "total", 0);
this.setState({
loadingEvents: false,
records: events || [],
totalRecords: total,
error: "",
});
// if we get 0 results, and page > 0 , go down 1 page
if ((!events || res.events.length === 0) && page > 0) {
const newPage = page - 1;
this.setState({ page: newPage }, () => {
this.fetchEvents();
});
}
})
.catch((err: any) => {
this.setState({ loadingEvents: false, error: err });
@@ -374,12 +357,9 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
const {
info,
records,
totalRecords,
setAccessPolicyScreenOpen,
loadingEvents,
loadingBucket,
page,
rowsPerPage,
deleteOpen,
addScreenOpen,
enableEncryptionScreenOpen,
@@ -393,21 +373,8 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
encryptionEnabled,
} = this.state;
const offset = page * rowsPerPage;
const bucketName = match.params["bucketName"];
const handleChangePage = (event: unknown, newPage: number) => {
this.setState({ page: newPage });
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
this.setState({ page: 0, rowsPerPage: rPP });
};
const confirmDeleteEvent = (evnt: BucketEvent) => {
this.setState({ deleteOpen: true, selectedEvent: evnt });
};
@@ -457,9 +424,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
const tableActions = [{ type: "delete", onClick: confirmDeleteEvent }];
const filteredRecords = records.slice(offset, offset + rowsPerPage);
const filteredRules = replicationRules.slice(offset, offset + rowsPerPage);
return (
<React.Fragment>
{addScreenOpen && (
@@ -639,7 +603,7 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
{ label: "Suffix", elementKey: "suffix" },
]}
isLoading={loadingEvents}
records={filteredRecords}
records={records}
entityName="Events"
idField="id"
/>
@@ -666,7 +630,7 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
{ label: "Status", elementKey: "status" },
]}
isLoading={loadingEvents}
records={filteredRules}
records={replicationRules}
entityName="Replication Rules"
idField="id"
/>

View File

@@ -14,7 +14,7 @@
// 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, { useEffect } from "react";
import React from "react";
import clsx from "clsx";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
@@ -31,7 +31,6 @@ import {
} from "../../actions";
import Buckets from "./Buckets/Buckets";
import Policies from "./Policies/Policies";
import Permissions from "./Permissions/Permissions";
import Dashboard from "./Dashboard/Dashboard";
import Menu from "./Menu/Menu";
import api from "../../common/api";
@@ -46,8 +45,6 @@ import ListTenants from "./Tenants/ListTenants/ListTenants";
import { ISessionResponse } from "./types";
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
import ObjectBrowser from "./ObjectBrowser/ObjectBrowser";
import ListObjects from "./Buckets/ListBuckets/Objects/ListObjects/ListObjects";
import ObjectDetails from "./Buckets/ListBuckets/Objects/ObjectDetails/ObjectDetails";
import ObjectRouting from "./Buckets/ListBuckets/Objects/ListObjects/ObjectRouting";
import License from "./License/License";
@@ -239,10 +236,6 @@ const Console = ({
component: ConfigurationsList,
path: "/configurations-list",
},
{
component: Permissions,
path: "/permissions",
},
{
component: ServiceAccounts,
path: "/service-accounts",

View File

@@ -23,7 +23,6 @@ import SearchIcon from "@material-ui/icons/Search";
import { Button } from "@material-ui/core";
import { CreateIcon } from "../../../icons";
import api from "../../../common/api";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import { GroupsList } from "./types";
import { stringSort } from "../../../utils/sortFunctions";
import AddGroup from "../Groups/AddGroup";
@@ -88,55 +87,31 @@ const Groups = ({ classes }: IGroupsProps) => {
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
const [loading, isLoading] = useState<boolean>(false);
const [records, setRecords] = useState<any[]>([]);
const [totalRecords, setTotalRecords] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [page, setPage] = useState<number>(0);
const [error, setError] = useState<string>("");
const [filter, setFilter] = useState<string>("");
const [policyOpen, setPolicyOpen] = useState<boolean>(false);
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
useEffect(() => {
isLoading(true);
}, []);
useEffect(() => {
isLoading(true);
}, [page, rowsPerPage]);
}, []);
useEffect(() => {
if (loading) {
const fetchRecords = () => {
const offset = page * rowsPerPage;
api
.invoke("GET", `/api/v1/groups?offset=${offset}&limit=${rowsPerPage}`)
.invoke("GET", `/api/v1/groups`)
.then((res: GroupsList) => {
let resGroups: string[] = [];
if (res.groups !== null) {
resGroups = res.groups.sort(stringSort);
}
setRecords(resGroups);
const total = !res.total ? 0 : res.total;
setTotalRecords(total);
setError("");
isLoading(false);
// if we get 0 results, and page > 0 , go down 1 page
if ((!res.groups || res.groups.length === 0) && page > 0) {
const newPage = page - 1;
setPage(newPage);
}
})
.catch((err) => {
setError(err);
@@ -145,7 +120,7 @@ const Groups = ({ classes }: IGroupsProps) => {
};
fetchRecords();
}
}, [loading, page, rowsPerPage]);
}, [loading]);
const closeAddModalAndRefresh = () => {
setGroupOpen(false);

View File

@@ -30,7 +30,6 @@ import logo from "../../../icons/minio_console_logo.svg";
import { AppState } from "../../../store";
import { userLoggedIn } from "../../../actions";
import api from "../../../common/api";
import WatchIcon from "../../../icons/WatchIcon";
import { menuGroups } from "./utils";
import { IMenuProps } from "./types";
import {
@@ -47,7 +46,6 @@ import {
WarpIcon,
} from "../../../icons";
import { clearSession } from "../../../common/utils";
import HealIcon from "../../../icons/HealIcon";
import LicenseIcon from "../../../icons/LicenseIcon";
import LogoutIcon from "../../../icons/LogoutIcon";

View File

@@ -22,7 +22,6 @@ import Grid from "@material-ui/core/Grid";
import Button from "@material-ui/core/Button";
import InputAdornment from "@material-ui/core/InputAdornment";
import SearchIcon from "@material-ui/icons/Search";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import {
NotificationEndpointItem,
NotificationEndpointsList,
@@ -67,9 +66,6 @@ const styles = (theme: Theme) =>
const ListNotificationEndpoints = ({ classes }: IListNotificationEndpoints) => {
//Local States
const [records, setRecords] = useState<TransformedEndpointItem[]>([]);
const [totalRecords, setTotalRecords] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [page, setPage] = useState<number>(0);
const [filter, setFilter] = useState<string>("");
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
@@ -88,7 +84,6 @@ const ListNotificationEndpoints = ({ classes }: IListNotificationEndpoints) => {
resNotEndList = res.notification_endpoints;
}
setRecords(notificationTransform(resNotEndList));
setTotalRecords(resNotEndList.length);
setError("");
setIsLoading(false);
})

View File

@@ -26,7 +26,6 @@ import SearchIcon from "@material-ui/icons/Search";
import { Button } from "@material-ui/core";
import { CreateIcon } from "../../../icons";
import { niceBytes } from "../../../common/utils";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import { Bucket, BucketList } from "../Buckets/types";
import {
actionsTray,
@@ -116,15 +115,11 @@ const BrowseBuckets = ({
resetRoutesList,
}: IBrowseBucketsProps) => {
const [loading, setLoading] = useState<boolean>(true);
const [page, setPage] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [error, setError] = useState<string>("");
const [records, setRecords] = useState<Bucket[]>([]);
const [addScreenOpen, setAddScreenOpen] = useState<boolean>(false);
const [filterBuckets, setFilterBuckets] = useState<string>("");
const offset = page * rowsPerPage;
useEffect(() => {
resetRoutesList(true);
}, [match]);
@@ -132,29 +127,18 @@ const BrowseBuckets = ({
useEffect(() => {
if (loading) {
api
.invoke("GET", `/api/v1/buckets?offset=${offset}&limit=${rowsPerPage}`)
.invoke("GET", `/api/v1/buckets`)
.then((res: BucketList) => {
setLoading(false);
setRecords(res.buckets || []);
setError("");
// if we get 0 results, and page > 0 , go down 1 page
if (
(res.buckets === undefined ||
res.buckets == null ||
res.buckets.length === 0) &&
page > 0
) {
const newPage = page - 1;
setPage(newPage);
setLoading(true);
}
})
.catch((err: any) => {
setLoading(false);
setError(err);
});
}
}, [loading, offset, rowsPerPage, page]);
}, [loading]);
const closeAddModalAndRefresh = (refresh: boolean) => {
setAddScreenOpen(false);
@@ -171,18 +155,6 @@ const BrowseBuckets = ({
return b.name.indexOf(filterBuckets) >= 0;
});
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
const handleViewChange = (idElement: string) => {
const currentPath = get(match, "url", "/object-browser");
const newPath = `${currentPath}/${idElement}`;

View File

@@ -1,610 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2019 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 from "react";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import {
Button,
Dialog,
DialogContent,
DialogTitle,
FormControl,
FormControlLabel,
FormLabel,
InputLabel,
LinearProgress,
MenuItem,
Radio,
RadioGroup,
Select,
TextField,
} from "@material-ui/core";
import {
createStyles,
lighten,
makeStyles,
Theme,
withStyles,
} from "@material-ui/core/styles";
import api from "../../../common/api";
import clsx from "clsx";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TablePagination from "@material-ui/core/TablePagination";
import TableRow from "@material-ui/core/TableRow";
import Toolbar from "@material-ui/core/Toolbar";
import Checkbox from "@material-ui/core/Checkbox";
import IconButton from "@material-ui/core/IconButton";
import Tooltip from "@material-ui/core/Tooltip";
import FilterListIcon from "@material-ui/icons/FilterList";
import { Bucket, BucketList } from "../Buckets/types";
import { Permission } from "./types";
const useToolbarStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
},
highlight:
theme.palette.type === "light"
? {
color: theme.palette.secondary.main,
backgroundColor: lighten(theme.palette.secondary.light, 0.85),
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.secondary.dark,
},
title: {
flex: "1 1 100%",
},
})
);
interface EnhancedTableToolbarProps {
numSelected: number;
}
const EnhancedTableToolbar = (props: EnhancedTableToolbarProps) => {
const classes = useToolbarStyles();
const { numSelected } = props;
return (
<Toolbar
className={clsx(classes.root, {
[classes.highlight]: numSelected > 0,
})}
>
{numSelected > 0 ? (
<Typography
className={classes.title}
color="inherit"
variant="subtitle1"
>
{numSelected} selected
</Typography>
) : (
<Typography className={classes.title} variant="h6" id="tableTitle">
Buckets
</Typography>
)}
{numSelected > 0 ? (
<span />
) : (
<Tooltip title="Filter list">
<IconButton aria-label="filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)}
</Toolbar>
);
};
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red",
},
});
interface IAddPermissionContentProps {
classes: any;
open: boolean;
closeModalAndRefresh: () => void;
selectedPermission: Permission | null;
}
interface IAddPermissionContentState {
addLoading: boolean;
addError: string;
name: string;
description: string;
effect: string;
action: string;
rowsPerPage: number;
page: number;
resources: string[];
buckets: Bucket[];
bucketsError: string;
loadingBuckets: boolean;
}
class AddPermissionContent extends React.Component<
IAddPermissionContentProps,
IAddPermissionContentState
> {
state: IAddPermissionContentState = {
addLoading: false,
addError: "",
name: "",
description: "",
effect: "Allow",
action: "readwrite",
rowsPerPage: 5,
page: 0,
resources: [],
buckets: [],
bucketsError: "",
loadingBuckets: false,
};
componentDidMount(): void {
// load a list of buckets
this.setState({ loadingBuckets: true }, () => {
api
.invoke("GET", `/api/v1/buckets`)
.then((res: BucketList) => {
this.setState({
loadingBuckets: false,
buckets: res.buckets,
bucketsError: "",
});
})
.catch((err) => {
this.setState({ loadingBuckets: false, bucketsError: err });
});
});
const { selectedPermission } = this.props;
if (selectedPermission !== null) {
this.setState({
name: selectedPermission.name,
description: selectedPermission.description,
effect: selectedPermission.effect,
resources: selectedPermission.resources.map((r) => r.bucket_name),
action: selectedPermission.actions[0].type,
});
}
}
saveRecord(event: React.FormEvent) {
event.preventDefault();
const {
name,
addLoading,
resources,
description,
effect,
action,
} = this.state;
const { selectedPermission } = this.props;
if (addLoading) {
return;
}
this.setState({ addLoading: true }, () => {
if (selectedPermission !== null) {
api
.invoke("PUT", `/api/v1/permissions/${selectedPermission.id}`, {
id: selectedPermission.id,
name: name,
description: description,
effect: effect,
resources: resources,
actions: [action],
})
.then((res) => {
this.setState(
{
addLoading: false,
addError: "",
},
() => {
this.props.closeModalAndRefresh();
}
);
})
.catch((err) => {
this.setState({
addLoading: false,
addError: err,
});
});
} else {
api
.invoke("POST", "/api/v1/permissions", {
name: name,
description: description,
effect: effect,
resources: resources,
actions: [action],
})
.then((res) => {
this.setState(
{
addLoading: false,
addError: "",
},
() => {
this.props.closeModalAndRefresh();
}
);
})
.catch((err) => {
this.setState({
addLoading: false,
addError: err,
});
});
}
});
}
render() {
const { classes, selectedPermission, open } = this.props;
const {
addLoading,
addError,
resources,
page,
rowsPerPage,
buckets,
name,
description,
effect,
action,
} = this.state;
const handleSelectAllClick = (
event: React.ChangeEvent<HTMLInputElement>
) => {
if (event.target.checked) {
const newSelecteds = buckets.map((n) => n.name);
this.setState({ resources: newSelecteds });
return;
}
this.setState({ resources: [] });
};
const handleClick = (event: React.MouseEvent<unknown>, name: string) => {
const selectedIndex = resources.indexOf(name);
let newSelected: string[] = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(resources, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(resources.slice(1));
} else if (selectedIndex === resources.length - 1) {
newSelected = newSelected.concat(resources.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
resources.slice(0, selectedIndex),
resources.slice(selectedIndex + 1)
);
}
this.setState({ resources: newSelected });
};
const handleChangePage = (event: unknown, newPage: number) => {
this.setState({ page: newPage });
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
this.setState({ page: 0, rowsPerPage: parseInt(event.target.value, 10) });
};
const isSelected = (name: string) => resources.indexOf(name) !== -1;
const emptyRows =
rowsPerPage - Math.min(rowsPerPage, buckets.length - page * rowsPerPage);
return (
<Dialog
open={open}
onClose={() => {
this.setState({ addError: "" }, () => {
this.props.closeModalAndRefresh();
});
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{selectedPermission !== null ? (
<span>Edit Permission</span>
) : (
<span>Create Permission</span>
)}
</DialogTitle>
<DialogContent>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
this.saveRecord(e);
}}
>
<Grid container>
{addError !== "" && (
<Grid item xs={12}>
<Typography
component="p"
variant="body1"
className={classes.errorBlock}
>
{addError}
</Typography>
</Grid>
)}
<Grid item xs={12}>
<TextField
id="standard-basic"
fullWidth
label="Name"
value={name}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ name: e.target.value });
}}
/>
</Grid>
<Grid item xs={12}>
<TextField
id="standard-multiline-static"
label="Description"
fullWidth
multiline
rows="4"
value={description}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ description: e.target.value });
}}
/>
</Grid>
<Grid item xs={12}>
<FormControl className={classes.formControl} fullWidth>
<InputLabel id="select-effect">Effect</InputLabel>
<Select
labelId="select-effect"
id="select-effect"
value={effect}
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
this.setState({ effect: e.target.value as string });
}}
>
<MenuItem value="Allow">Allow</MenuItem>
<MenuItem value="Deny">Deny</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<div className={classes.root}>
<EnhancedTableToolbar numSelected={resources.length} />
<TableContainer>
<Table
className={classes.table}
aria-labelledby="tableTitle"
size={"small"}
aria-label="enhanced table"
>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
indeterminate={
resources.length > 0 &&
resources.length < buckets.length
}
checked={
buckets.length > 0 &&
resources.length === buckets.length
}
onChange={handleSelectAllClick}
inputProps={{
"aria-label": "select all desserts",
}}
/>
</TableCell>
<TableCell>Name</TableCell>
</TableRow>
</TableHead>
<TableBody>
{buckets
.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
)
.map((row, index) => {
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover
onClick={(event) =>
handleClick(event, row.name)
}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.name}
selected={isItemSelected}
>
<TableCell padding="checkbox">
<Checkbox
checked={isItemSelected}
inputProps={{ "aria-labelledby": labelId }}
/>
</TableCell>
<TableCell id={labelId}>{row.name}</TableCell>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 33 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={buckets.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
</Grid>
<Grid item xs={12}>
<FormControl
component="fieldset"
className={classes.formControl}
>
<FormLabel component="legend">Action</FormLabel>
<RadioGroup
aria-label="action"
name="action"
value={action}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({
action: (event.target as HTMLInputElement).value,
});
}}
>
<FormControlLabel
value="readwrite"
control={<Radio />}
label="All Actions"
/>
<FormControlLabel
value="read"
control={<Radio />}
label="Read Only"
/>
<FormControlLabel
value="write"
control={<Radio />}
label="Write Only"
/>
<FormControlLabel
value="trace"
control={<Radio />}
label="Trace"
/>
</RadioGroup>
</FormControl>
</Grid>
{action === "trace" && (
<React.Fragment>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12}>
<Typography
component="p"
variant="body1"
className={classes.errorBlock}
>
Trace displays tracing information for all buckets.
</Typography>
</Grid>
</React.Fragment>
)}
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12}>
<Button
type="submit"
variant="contained"
color="primary"
fullWidth
disabled={addLoading}
>
Save
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
</Grid>
</form>
</DialogContent>
</Dialog>
);
}
}
const AddPermissionWrapper = withStyles(styles)(AddPermissionContent);
interface IAddPermissionProps {
open: boolean;
closeModalAndRefresh: () => void;
selectedPermission: Permission | null;
}
interface IAddPermissionState {}
class AddPermission extends React.Component<
IAddPermissionProps,
IAddPermissionState
> {
state: IAddPermissionState = {};
render() {
const { open } = this.props;
return (
<Dialog
open={open}
onClose={() => {
this.setState({ addError: "" }, () => {
this.props.closeModalAndRefresh();
});
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<AddPermissionWrapper {...this.props} />
</Dialog>
);
}
}
export default AddPermission;

View File

@@ -1,160 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2019 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 { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import React from "react";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress,
} from "@material-ui/core";
import api from "../../../common/api";
import { Permission, PermissionList } from "./types";
import Typography from "@material-ui/core/Typography";
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red",
},
});
interface IDeletePermissionProps {
classes: any;
closeDeleteModalAndRefresh: (refresh: boolean) => void;
deleteOpen: boolean;
selectedPermission: Permission | null;
}
interface IDeletePermissionState {
deleteLoading: boolean;
deleteError: string;
}
class DeletePermission extends React.Component<
IDeletePermissionProps,
IDeletePermissionState
> {
state: IDeletePermissionState = {
deleteLoading: false,
deleteError: "",
};
removeRecord() {
const { deleteLoading } = this.state;
const { selectedPermission } = this.props;
if (deleteLoading) {
return;
}
if (selectedPermission == null) {
return;
}
this.setState({ deleteLoading: true }, () => {
api
.invoke("DELETE", `/api/v1/permissions/${selectedPermission.id}`, {
id: selectedPermission.id,
})
.then((res: PermissionList) => {
this.setState(
{
deleteLoading: false,
deleteError: "",
},
() => {
this.props.closeDeleteModalAndRefresh(true);
}
);
})
.catch((err) => {
this.setState({
deleteLoading: false,
deleteError: err,
});
});
});
}
render() {
const { classes, deleteOpen, selectedPermission } = this.props;
const { deleteLoading, deleteError } = this.state;
if (selectedPermission === null) {
return <div />;
}
return (
<Dialog
open={deleteOpen}
onClose={() => {
this.setState({ deleteError: "" }, () => {
this.props.closeDeleteModalAndRefresh(false);
});
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">Delete Permission</DialogTitle>
<DialogContent>
{deleteLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete permission{" "}
<b>{selectedPermission.name}</b>?
{deleteError !== "" && (
<React.Fragment>
<br />
<Typography
component="p"
variant="body1"
className={classes.errorBlock}
>
{deleteError}
</Typography>
</React.Fragment>
)}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
this.setState({ deleteError: "" }, () => {
this.props.closeDeleteModalAndRefresh(false);
});
}}
color="primary"
disabled={deleteLoading}
>
Cancel
</Button>
<Button
onClick={() => {
this.removeRecord();
}}
color="secondary"
autoFocus
>
Delete
</Button>
</DialogActions>
</Dialog>
);
}
}
export default withStyles(styles)(DeletePermission);

View File

@@ -1,398 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2019 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 from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import api from "../../../common/api";
import {
Button,
IconButton,
LinearProgress,
TableFooter,
TablePagination,
} from "@material-ui/core";
import Typography from "@material-ui/core/Typography";
import DeleteIcon from "@material-ui/icons/Delete";
import { Permission, PermissionList } from "./types";
import AddPermission from "./AddPermission";
import DeletePermission from "./DeletePermission";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import EditIcon from "@material-ui/icons/Edit";
import Checkbox from "@material-ui/core/Checkbox";
import { CreateIcon } from "../../../icons";
import TextField from "@material-ui/core/TextField";
import SearchIcon from "@material-ui/icons/Search";
import InputAdornment from "@material-ui/core/InputAdornment";
import PlayArrowRoundedIcon from "@material-ui/icons/PlayArrowRounded";
const styles = (theme: Theme) =>
createStyles({
seeMore: {
marginTop: theme.spacing(3),
},
paper: {
display: "flex",
overflow: "auto",
flexDirection: "column",
},
addSideBar: {
width: "320px",
padding: "20px",
},
errorBlock: {
color: "red",
},
tableToolbar: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(0),
},
wrapCell: {
maxWidth: "200px",
whiteSpace: "normal",
wordWrap: "break-word",
},
minTableHeader: {
color: "#393939",
"& tr": {
"& th": {
fontWeight: "bold",
},
},
},
actionsTray: {
textAlign: "right",
"& button": {
marginLeft: 10,
},
},
searchField: {
background: "#FFFFFF",
padding: 12,
borderRadius: 5,
boxShadow: "0px 3px 6px #00000012",
},
});
interface IPermissionsProps {
classes: any;
}
interface IPermissionsState {
records: Permission[];
totalRecords: number;
loading: boolean;
error: string;
deleteError: string;
addScreenOpen: boolean;
page: number;
rowsPerPage: number;
deleteOpen: boolean;
selectedPermission: Permission | null;
}
class Permissions extends React.Component<
IPermissionsProps,
IPermissionsState
> {
state: IPermissionsState = {
records: [],
totalRecords: 0,
loading: false,
error: "",
deleteError: "",
addScreenOpen: false,
page: 0,
rowsPerPage: 10,
deleteOpen: false,
selectedPermission: null,
};
fetchRecords() {
this.setState({ loading: true }, () => {
const { page, rowsPerPage } = this.state;
const offset = page * rowsPerPage;
api
.invoke(
"GET",
`/api/v1/permissions?offset=${offset}&limit=${rowsPerPage}`
)
.then((res: PermissionList) => {
this.setState({
loading: false,
records: res.permissions,
totalRecords: res.total,
error: "",
});
// if we get 0 results, and page > 0 , go down 1 page
if (
(res.permissions === undefined ||
res.permissions == null ||
res.permissions.length === 0) &&
page > 0
) {
const newPage = page - 1;
this.setState({ page: newPage }, () => {
this.fetchRecords();
});
}
})
.catch((err) => {
this.setState({ loading: false, error: err });
});
});
}
closeAddModalAndRefresh() {
this.setState({ addScreenOpen: false, selectedPermission: null }, () => {
this.fetchRecords();
});
}
closeDeleteModalAndRefresh(refresh: boolean) {
this.setState({ deleteOpen: false }, () => {
if (refresh) {
this.fetchRecords();
}
});
}
componentDidMount(): void {
this.fetchRecords();
}
render() {
const { classes } = this.props;
const {
records,
totalRecords,
addScreenOpen,
loading,
page,
rowsPerPage,
deleteOpen,
selectedPermission,
} = this.state;
const handleChangePage = (event: unknown, newPage: number) => {
this.setState({ page: newPage }, () => {
this.fetchRecords();
});
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
this.setState({ page: 0, rowsPerPage: rPP }, () => {
this.fetchRecords();
});
};
const confirmDeletePermission = (selectedPermission: Permission) => {
this.setState({
deleteOpen: true,
selectedPermission: selectedPermission,
});
};
const editPermission = (selectedPermission: Permission) => {
this.setState({
addScreenOpen: true,
selectedPermission: selectedPermission,
});
};
const actionLabel = (action: string) => {
switch (action) {
case "readwrite":
return "All Actions";
case "read":
return "Read Only";
case "write":
return "Write Only";
case "trace":
return "Tracing";
default:
return "n/a";
}
};
return (
<React.Fragment>
<AddPermission
open={addScreenOpen}
selectedPermission={selectedPermission}
closeModalAndRefresh={() => {
this.closeAddModalAndRefresh();
}}
/>
<Grid container>
<Grid item xs={12}>
<Typography variant="h6">Permissions</Typography>
</Grid>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Permissions"
className={classes.searchField}
id="search-resource"
label=""
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
<Button
variant="contained"
color="primary"
startIcon={<CreateIcon />}
onClick={() => {
this.setState({
addScreenOpen: true,
selectedPermission: null,
});
}}
>
Create Permission
</Button>
<Button
variant="contained"
color="primary"
startIcon={<PlayArrowRoundedIcon />}
onClick={() => {
this.setState({
addScreenOpen: true,
});
}}
>
Assign Permissions
</Button>
</Grid>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12}>
<Paper className={classes.paper}>
{loading && <LinearProgress />}
{records != null && records.length > 0 ? (
<Table size="medium">
<TableHead className={classes.minTableHeader}>
<TableRow>
<TableCell>Select</TableCell>
<TableCell>Name</TableCell>
<TableCell>Description</TableCell>
<TableCell>Effect</TableCell>
<TableCell>Resources</TableCell>
<TableCell>Action</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{records.map((row) => (
<TableRow key={row.name}>
<TableCell padding="checkbox">
<Checkbox
value="secondary"
color="primary"
inputProps={{ "aria-label": "secondary checkbox" }}
/>
</TableCell>
<TableCell className={classes.wrapCell}>
{row.name}
</TableCell>
<TableCell className={classes.wrapCell}>
{row.description}
</TableCell>
<TableCell>{row.effect}</TableCell>
<TableCell className={classes.wrapCell}>
{row.resources.map((r) => r.bucket_name).join(", ")}
</TableCell>
<TableCell>
{actionLabel(row.actions[0].type)}
</TableCell>
<TableCell align="right">
<IconButton
aria-label="edit"
onClick={() => {
editPermission(row);
}}
>
<EditIcon />
</IconButton>
<IconButton
aria-label="delete"
onClick={() => {
confirmDeletePermission(row);
}}
>
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
colSpan={6}
count={totalRecords}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { "aria-label": "rows per page" },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={MinTablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
) : (
<div>No Permissions</div>
)}
</Paper>
</Grid>
</Grid>
<DeletePermission
deleteOpen={deleteOpen}
selectedPermission={selectedPermission}
closeDeleteModalAndRefresh={(refresh: boolean) => {
this.closeDeleteModalAndRefresh(refresh);
}}
/>
</React.Fragment>
);
}
}
export default withStyles(styles)(Permissions);

View File

@@ -1,30 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2019 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/>.
export interface Permission {
id: string;
name: string;
slug: string;
description: string;
effect: string;
resources: any[];
actions: any[];
}
export interface PermissionList {
permissions: Permission[];
total: number;
}

View File

@@ -24,7 +24,6 @@ import InputAdornment from "@material-ui/core/InputAdornment";
import SearchIcon from "@material-ui/icons/Search";
import { Policy, PolicyList } from "./types";
import { CreateIcon } from "../../../icons";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import AddPolicy from "./AddPolicy";
import DeletePolicy from "./DeletePolicy";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
@@ -80,8 +79,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>("");
const [addScreenOpen, setAddScreenOpen] = useState<boolean>(false);
const [page, setPage] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
const [selectedPolicy, setSelectedPolicy] = useState<string>("");
const [filterPolicies, setFilterPolicies] = useState<string>("");
@@ -93,9 +90,8 @@ const Policies = ({ classes }: IPoliciesProps) => {
useEffect(() => {
if (loading) {
const offset = page * rowsPerPage;
api
.invoke("GET", `/api/v1/policies?offset=${offset}&limit=${rowsPerPage}`)
.invoke("GET", `/api/v1/policies`)
.then((res: PolicyList) => {
const policies = get(res, "policies", []);
@@ -114,26 +110,13 @@ const Policies = ({ classes }: IPoliciesProps) => {
setLoading(false);
setRecords(policies);
setError("");
// if we get 0 results, and page > 0 , go down 1 page
if (
(res.policies === undefined ||
res.policies == null ||
res.policies.length === 0) &&
page > 0
) {
const newPage = page - 1;
setPage(newPage);
fetchRecords();
}
})
.catch((err) => {
setLoading(false);
setError(err);
});
}
}, [loading, setLoading, setRecords, setError, setPage, page, rowsPerPage]);
}, [loading, setLoading, setRecords, setError]);
const fetchRecords = () => {
setLoading(true);
@@ -155,18 +138,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
}
};
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
const confirmDeletePolicy = (policy: string) => {
setDeleteOpen(true);
setSelectedPolicy(policy);
@@ -186,11 +157,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
elementItem.name.includes(filterPolicies)
);
const beginRecord = page * rowsPerPage;
const endRecords = beginRecord + rowsPerPage;
const paginatedRecords = filteredRecords.slice(beginRecord, endRecords);
return (
<React.Fragment>
{addScreenOpen && (
@@ -217,7 +183,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
id="search-resource"
label=""
onChange={(val) => {
setPage(0);
setFilterPolicies(val.target.value);
}}
InputProps={{
@@ -254,7 +219,7 @@ const Policies = ({ classes }: IPoliciesProps) => {
itemActions={tableActions}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={loading}
records={paginatedRecords}
records={filteredRecords}
entityName="Policies"
idField="name"
/>

View File

@@ -21,7 +21,6 @@ import api from "../../../common/api";
import { Button } from "@material-ui/core";
import Typography from "@material-ui/core/Typography";
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import AddServiceAccount from "./AddServiceAccount";
import DeleteServiceAccount from "./DeleteServiceAccount";
import CredentialsPrompt from "../Common/CredentialsPrompt/CredentialsPrompt";
@@ -94,8 +93,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
const [error, setError] = useState<string>("");
const [filter, setFilter] = useState<string>("");
const [addScreenOpen, setAddScreenOpen] = useState<boolean>(false);
const [page, setPage] = useState<number>(0);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
const [selectedServiceAccount, setSelectedServiceAccount] = useState<
string | null
@@ -120,20 +117,13 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
setLoading(false);
setRecords(serviceAccounts);
setError("");
// if we get 0 results, and page > 0 , go down 1 page
if ((!serviceAccounts || serviceAccounts.length === 0) && page > 0) {
const newPage = page - 1;
setPage(newPage);
fetchRecords();
}
})
.catch((err) => {
setError(err);
setLoading(false);
});
}
}, [loading, setLoading, setRecords, setError, page, setPage]);
}, [loading, setLoading, setRecords, setError]);
const fetchRecords = () => {
setLoading(true);
@@ -162,19 +152,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
setNewServiceAccount(null);
};
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
const confirmDeleteServiceAccount = (selectedServiceAccount: string) => {
setSelectedServiceAccount(selectedServiceAccount);
setDeleteOpen(true);
@@ -188,11 +165,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
elementItem.toLowerCase().includes(filter.toLowerCase())
);
const beginRecord = page * rowsPerPage;
const endRecords = beginRecord + rowsPerPage;
const paginatedRecords = filteredRecords.slice(beginRecord, endRecords);
return (
<React.Fragment>
{addScreenOpen && (
@@ -241,7 +213,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
}}
onChange={(e) => {
setFilter(e.target.value);
setPage(0);
}}
/>
<Button
@@ -273,7 +244,7 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
<Grid item xs={12}>
<TableWrapper
isLoading={loading}
records={paginatedRecords}
records={filteredRecords}
entityName={"Service Accounts"}
idField={""}
columns={[{ label: "Service Account", elementKey: "" }]}

View File

@@ -22,7 +22,6 @@ import SearchIcon from "@material-ui/icons/Search";
import { Button, IconButton } from "@material-ui/core";
import { CreateIcon } from "../../../../icons";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import { MinTablePaginationActions } from "../../../../common/MinTablePaginationActions";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import api from "../../../../common/api";
import { ITenant, ITenantsResponse } from "./types";
@@ -86,8 +85,6 @@ const ListTenants = ({ classes }: ITenantsList) => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [filterTenants, setFilterTenants] = useState<string>("");
const [records, setRecords] = useState<any[]>([]);
const [rowsPerPage, setRowsPerPage] = useState<number>(10);
const [page, setPage] = useState<number>(0);
const [error, setError] = useState<string>("");
const [showNewCredentials, setShowNewCredentials] = useState<boolean>(false);
const [
@@ -134,48 +131,28 @@ const ListTenants = ({ classes }: ITenantsList) => {
setCreatedAccount(null);
};
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setPage(0);
setRowsPerPage(rPP);
};
const tableActions = [
{ type: "view", onClick: redirectToTenantDetails },
{ type: "delete", onClick: confirmDeleteTenant },
];
const globalOffset = 0;
const filteredRecords = records
.slice(globalOffset, globalOffset + rowsPerPage)
.filter((b: any) => {
if (filterTenants === "") {
const filteredRecords = records.filter((b: any) => {
if (filterTenants === "") {
return true;
} else {
if (b.name.indexOf(filterTenants) >= 0) {
return true;
} else {
if (b.name.indexOf(filterTenants) >= 0) {
return true;
} else {
return false;
}
return false;
}
});
}
});
useEffect(() => {
if (isLoading) {
const fetchRecords = () => {
const offset = page * rowsPerPage;
api
.invoke(
"GET",
`/api/v1/tenants?offset=${offset}&limit=${rowsPerPage}`
)
.invoke("GET", `/api/v1/tenants`)
.then((res: ITenantsResponse) => {
if (res === null) {
setIsLoading(false);
@@ -193,12 +170,6 @@ const ListTenants = ({ classes }: ITenantsList) => {
setRecords(resTenants);
setError("");
setIsLoading(false);
// if we get 0 results, and page > 0 , go down 1 page
if ((!res.tenants || res.tenants.length === 0) && page > 0) {
const newPage = page - 1;
setPage(newPage);
}
})
.catch((err) => {
setError(err);
@@ -207,7 +178,7 @@ const ListTenants = ({ classes }: ITenantsList) => {
};
fetchRecords();
}
}, [isLoading, page, rowsPerPage]);
}, [isLoading]);
useEffect(() => {
setIsLoading(true);

View File

@@ -9,13 +9,11 @@ import { FormControl, MenuItem, Select } from "@material-ui/core";
import { BucketList, Bucket } from "../Watch/types";
import { HealStatus, colorH } from "./types";
import { niceBytes } from "../../../../../common/utils";
import InputLabel from "@material-ui/core/InputLabel";
import {
actionsTray,
containerForHeader,
searchField,
} from "../../../Common/FormComponents/common/styleLibrary";
import PageHeader from "../../../Common/PageHeader/PageHeader";
import CheckboxWrapper from "../../../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
const styles = (theme: Theme) =>

View File

@@ -22,7 +22,6 @@ import SearchIcon from "@material-ui/icons/Search";
import GroupIcon from "@material-ui/icons/Group";
import { User, UsersList } from "./types";
import { usersSort } from "../../../utils/sortFunctions";
import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions";
import { CreateIcon } from "../../../icons";
import AddUser from "./AddUser";
import DeleteUser from "./DeleteUser";
@@ -82,13 +81,10 @@ interface IUsersProps {
interface IUsersState {
records: User[];
totalRecords: number;
loading: boolean;
error: string;
deleteError: string;
addScreenOpen: boolean;
page: number;
rowsPerPage: number;
deleteOpen: boolean;
selectedUser: User | null;
addGroupOpen: boolean;
@@ -100,13 +96,10 @@ interface IUsersState {
class Users extends React.Component<IUsersProps, IUsersState> {
state: IUsersState = {
records: [],
totalRecords: 0,
loading: false,
error: "",
deleteError: "",
addScreenOpen: false,
page: 0,
rowsPerPage: 10,
deleteOpen: false,
selectedUser: null,
addGroupOpen: false,
@@ -117,25 +110,15 @@ class Users extends React.Component<IUsersProps, IUsersState> {
fetchRecords() {
this.setState({ loading: true }, () => {
const { page, rowsPerPage } = this.state;
const offset = page * rowsPerPage;
api
.invoke("GET", `/api/v1/users?offset=${offset}&limit=${rowsPerPage}`)
.invoke("GET", `/api/v1/users`)
.then((res: UsersList) => {
const users = res.users === null ? [] : res.users;
this.setState({
loading: false,
records: users.sort(usersSort),
totalRecords: users.length,
error: "",
});
// if we get 0 results, and page > 0 , go down 1 page
if ((!users || users.length === 0) && page > 0) {
const newPage = page - 1;
this.setState({ page: newPage }, () => {
this.fetchRecords();
});
}
})
.catch((err) => {
this.setState({ loading: false, error: err });
@@ -178,8 +161,6 @@ class Users extends React.Component<IUsersProps, IUsersState> {
records,
addScreenOpen,
loading,
page,
rowsPerPage,
deleteOpen,
selectedUser,
filter,
@@ -188,26 +169,10 @@ class Users extends React.Component<IUsersProps, IUsersState> {
setPolicyOpen,
} = this.state;
const handleChangePage = (event: unknown, newPage: number) => {
this.setState({ page: newPage });
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
this.setState({ page: 0, rowsPerPage: rPP });
};
const filteredRecords = records.filter((elementItem) =>
elementItem.accessKey.includes(filter)
);
const beginRecord = page * rowsPerPage;
const endRecords = beginRecord + rowsPerPage;
const paginatedRecords = filteredRecords.slice(beginRecord, endRecords);
const selectionChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const targetD = e.target;
const value = targetD.value;
@@ -315,7 +280,7 @@ class Users extends React.Component<IUsersProps, IUsersState> {
),
}}
onChange={(e) => {
this.setState({ filter: e.target.value, page: 0 });
this.setState({ filter: e.target.value });
}}
/>
<Button
@@ -358,7 +323,7 @@ class Users extends React.Component<IUsersProps, IUsersState> {
onSelect={selectionChanged}
selectedItems={checkedUsers}
isLoading={loading}
records={paginatedRecords}
records={filteredRecords}
entityName="Users"
idField="accessKey"
/>

View File

@@ -127,7 +127,7 @@
"@babel/helper-replace-supers" "^7.12.1"
"@babel/helper-split-export-declaration" "^7.10.4"
"@babel/helper-create-regexp-features-plugin@^7.12.1", "@babel/helper-create-regexp-features-plugin@^7.7.4":
"@babel/helper-create-regexp-features-plugin@^7.12.1":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f"
integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==
@@ -1188,15 +1188,14 @@
dependencies:
"@hapi/hoek" "^8.3.0"
"@hot-loader/react-dom@^16.9.0":
version "16.14.0"
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.14.0.tgz#3cfc64e40bb78fa623e59b582b8f09dcdaad648a"
integrity sha512-EN9czvcLsMYmSDo5yRKZOAq3ZGRlDpad1gPtX0NdMMomJXcPE3yFSeFzE94X/NjOaiSVimB7LuqPYpkWVaIi4Q==
"@hot-loader/react-dom@17.0.1":
version "17.0.1"
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-17.0.1.tgz#0c75b4dd068f819435dafb3e8809ca1749695656"
integrity sha512-QttzEibkIFkl/WV1dsLXg73YIweNo9ySbB0/26068RqFGWyv7pKyictWsaQXqSj1y66/BDn3kglCHgroGrv3vA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.19.1"
scheduler "^0.20.1"
"@jest/console@^24.7.1", "@jest/console@^24.9.0":
version "24.9.0"
@@ -1347,39 +1346,39 @@
"@types/yargs" "^13.0.0"
"@material-ui/core@^4.9.12":
version "4.11.1"
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.1.tgz#5bb94adc4257165d6ca1670fd71923a27f07d478"
integrity sha512-aesI8lOaaw0DRIfNG+Anepf61NH5Q+cmkxJOZvI1oHkmD5cKubkZ0C7INqFKjfFpSFlFnqHkTasoM7ogFAvzOg==
version "4.11.2"
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.2.tgz#f8276dfa40d88304e6ceb98962af73803d27d42d"
integrity sha512-/D1+AQQeYX/WhT/FUk78UCRj8ch/RCglsQLYujYTIqPSJlwZHKcvHidNeVhODXeApojeXjkl0tWdk5C9ofwOkQ==
dependencies:
"@babel/runtime" "^7.4.4"
"@material-ui/styles" "^4.11.1"
"@material-ui/system" "^4.9.14"
"@material-ui/styles" "^4.11.2"
"@material-ui/system" "^4.11.2"
"@material-ui/types" "^5.1.0"
"@material-ui/utils" "^4.10.2"
"@material-ui/utils" "^4.11.2"
"@types/react-transition-group" "^4.2.0"
clsx "^1.0.4"
hoist-non-react-statics "^3.3.2"
popper.js "1.16.1-lts"
prop-types "^15.7.2"
react-is "^16.8.0"
react-is "^16.8.0 || ^17.0.0"
react-transition-group "^4.4.0"
"@material-ui/icons@^4.9.1":
version "4.9.1"
resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.9.1.tgz#fdeadf8cb3d89208945b33dbc50c7c616d0bd665"
integrity sha512-GBitL3oBWO0hzBhvA9KxqcowRUsA0qzwKkURyC8nppnC3fw54KPKZ+d4V1Eeg/UnDRSzDaI9nGCdel/eh9AQMg==
version "4.11.2"
resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.11.2.tgz#b3a7353266519cd743b6461ae9fdfcb1b25eb4c5"
integrity sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==
dependencies:
"@babel/runtime" "^7.4.4"
"@material-ui/styles@^4.11.1":
version "4.11.1"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.1.tgz#089338637e9c358eddccd75c32f0bafd0237d573"
integrity sha512-GqzsFsVWT8jXa8OWAd1WD6WIaqtXr2mUPbRZ1EjkiM3Dlta4mCRaToDxkFVv6ZHfXlFjMJzdaIEvCpZOCvZTvg==
"@material-ui/styles@^4.11.2":
version "4.11.2"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.2.tgz#e70558be3f41719e8c0d63c7a3c9ae163fdc84cb"
integrity sha512-xbItf8zkfD3FuGoD9f2vlcyPf9jTEtj9YTJoNNV+NMWaSAHXgrW6geqRoo/IwBuMjqpwqsZhct13e2nUyU9Ljw==
dependencies:
"@babel/runtime" "^7.4.4"
"@emotion/hash" "^0.8.0"
"@material-ui/types" "^5.1.0"
"@material-ui/utils" "^4.9.6"
"@material-ui/utils" "^4.11.2"
clsx "^1.0.4"
csstype "^2.5.2"
hoist-non-react-statics "^3.3.2"
@@ -1393,13 +1392,13 @@
jss-plugin-vendor-prefixer "^10.0.3"
prop-types "^15.7.2"
"@material-ui/system@^4.9.14":
version "4.9.14"
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.14.tgz#4b00c48b569340cefb2036d0596b93ac6c587a5f"
integrity sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w==
"@material-ui/system@^4.11.2":
version "4.11.2"
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.2.tgz#7f0a754bba3673ed5fdbfa02fe438096c104b1f6"
integrity sha512-BELFJEel5E+5DMiZb6XXT3peWRn6UixRvBtKwSxqntmD0+zwbbfCij6jtGwwdJhN1qX/aXrKu10zX31GBaeR7A==
dependencies:
"@babel/runtime" "^7.4.4"
"@material-ui/utils" "^4.9.6"
"@material-ui/utils" "^4.11.2"
csstype "^2.5.2"
prop-types "^15.7.2"
@@ -1408,14 +1407,14 @@
resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2"
integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==
"@material-ui/utils@^4.10.2", "@material-ui/utils@^4.9.6":
version "4.10.2"
resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.10.2.tgz#3fd5470ca61b7341f1e0468ac8f29a70bf6df321"
integrity sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw==
"@material-ui/utils@^4.11.2":
version "4.11.2"
resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.11.2.tgz#f1aefa7e7dff2ebcb97d31de51aecab1bb57540a"
integrity sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==
dependencies:
"@babel/runtime" "^7.4.4"
prop-types "^15.7.2"
react-is "^16.8.0"
react-is "^16.8.0 || ^17.0.0"
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
@@ -2143,9 +2142,9 @@ ansi-styles@^4.1.0:
color-convert "^2.0.1"
ansi-to-react@^6.0.5:
version "6.0.10"
resolved "https://registry.yarnpkg.com/ansi-to-react/-/ansi-to-react-6.0.10.tgz#769d239e2632e1390a6e0cfb8b2f23189b5c1324"
integrity sha512-X6AOBVCTiKZrTcrHXj3S88HCa2KVi2qlHM0vX8zoRKMokzJYw8QbFPWHwdJcfWu0xv6hYIw8ADEH9aGjJVNo2w==
version "6.1.0"
resolved "https://registry.yarnpkg.com/ansi-to-react/-/ansi-to-react-6.1.0.tgz#43d3e6c4ff852aff19d249085500e00f6283ed42"
integrity sha512-ISQAXASCGTcJ0kUzLB0IXpBraI2FnlG0j/EVi9Xg0ZWo8Pbw47IQnPZkps0Ohsd9Rgim+2nAWg6gjS9inlp65A==
dependencies:
anser "^1.4.1"
escape-carriage "^1.3.0"
@@ -2748,15 +2747,15 @@ browserslist@4.10.0:
pkg-up "^3.1.0"
browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.14.7, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.9.1:
version "4.14.7"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6"
integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==
version "4.15.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.15.0.tgz#3d48bbca6a3f378e86102ffd017d9a03f122bdb0"
integrity sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==
dependencies:
caniuse-lite "^1.0.30001157"
caniuse-lite "^1.0.30001164"
colorette "^1.2.1"
electron-to-chromium "^1.3.591"
electron-to-chromium "^1.3.612"
escalade "^3.1.1"
node-releases "^1.1.66"
node-releases "^1.1.67"
bser@2.1.1:
version "2.1.1"
@@ -2909,12 +2908,12 @@ callsites@^3.0.0:
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camel-case@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547"
integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==
version "4.1.2"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
dependencies:
pascal-case "^3.1.1"
tslib "^1.10.0"
pascal-case "^3.1.2"
tslib "^2.0.3"
camelcase@5.3.1, camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
@@ -2931,10 +2930,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157:
version "1.0.30001164"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz#5bbfd64ca605d43132f13cc7fdabb17c3036bfdc"
integrity sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001164:
version "1.0.30001165"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz#32955490d2f60290bb186bb754f2981917fa744f"
integrity sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==
capture-exit@^2.0.0:
version "2.0.0"
@@ -4087,9 +4086,9 @@ domelementtype@1, domelementtype@^1.3.1:
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
domelementtype@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971"
integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==
version "2.1.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e"
integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==
domexception@^1.0.1:
version "1.0.1"
@@ -4121,13 +4120,13 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0"
domelementtype "1"
dot-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==
dot-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
dependencies:
no-case "^3.0.3"
tslib "^1.10.0"
no-case "^3.0.4"
tslib "^2.0.3"
dot-prop@^5.2.0:
version "5.3.0"
@@ -4174,10 +4173,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.591:
version "1.3.612"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.612.tgz#4a49864b9de694403a69d5a9f439cbceca543e48"
integrity sha512-CdrdX1B6mQqxfw+51MPWB5qA6TKWjza9f5voBtUlRfEZEwZiFaxJLrhFI8zHE9SBAuGt4h84rQU6Ho9Bauo1LA==
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.612:
version "1.3.616"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.616.tgz#de63d1c79bb8eb61168774df0c11c9e1af69f9e8"
integrity sha512-CI8L38UN2BEnqXw3/oRIQTmde0LiSeqWSRlPA42ZTYgJQ8fYenzAM2Z3ni+jtILTcrs5aiXZCGJ96Pm+3/yGyQ==
elliptic@^6.5.3:
version "6.5.3"
@@ -5822,9 +5821,11 @@ is-accessor-descriptor@^1.0.0:
kind-of "^6.0.0"
is-arguments@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9"
integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==
dependencies:
call-bind "^1.0.0"
is-arrayish@^0.2.1:
version "0.2.1"
@@ -5985,9 +5986,9 @@ is-in-browser@^1.0.2, is-in-browser@^1.1.3:
integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=
is-negative-zero@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
is-number@^3.0.0:
version "3.0.0"
@@ -7069,12 +7070,12 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lower-case@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7"
integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
dependencies:
tslib "^1.10.0"
tslib "^2.0.3"
lru-cache@^5.1.1:
version "5.1.1"
@@ -7130,9 +7131,9 @@ map-visit@^1.0.0:
object-visit "^1.0.0"
math-expression-evaluator@^1.2.14:
version "1.3.3"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.3.3.tgz#8b61badc2aadffb166c3847707057ca955c1684f"
integrity sha512-geKTlqoxnjqHoWqB71h0kchWIC23a3yfwwbZu4E2amjvGLF+fTjCCwBQOHkE0/oHc6KdnSVmMt3QB82KaPmKEA==
version "1.3.6"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.3.6.tgz#fb8c447110093dd5f32e7aec877dd247e3c98eb1"
integrity sha512-gbzsZEUgefao+OqOUOr03GlpjkdOySxVNHQDuiUZXPbLHgDZqiMtOgDSxuzBEtyt9BDXWS503a16bAmlJW/oFA==
md5.js@^1.3.4:
version "1.3.5"
@@ -7478,13 +7479,13 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
no-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8"
integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==
no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
dependencies:
lower-case "^2.0.1"
tslib "^1.10.0"
lower-case "^2.0.2"
tslib "^2.0.3"
node-forge@^0.10.0:
version "0.10.0"
@@ -7546,7 +7547,7 @@ node-notifier@^5.4.2:
shellwords "^0.1.1"
which "^1.3.0"
node-releases@^1.1.52, node-releases@^1.1.66:
node-releases@^1.1.52, node-releases@^1.1.67:
version "1.1.67"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12"
integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==
@@ -7901,12 +7902,12 @@ parallel-transform@^1.1.0:
readable-stream "^2.1.5"
param-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238"
integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==
version "3.0.4"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==
dependencies:
dot-case "^3.0.3"
tslib "^1.10.0"
dot-case "^3.0.4"
tslib "^2.0.3"
parent-module@^1.0.0:
version "1.0.1"
@@ -7966,13 +7967,13 @@ parseurl@~1.3.2, parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
pascal-case@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f"
integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==
pascal-case@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
dependencies:
no-case "^3.0.3"
tslib "^1.10.0"
no-case "^3.0.4"
tslib "^2.0.3"
pascalcase@^0.1.1:
version "0.1.1"
@@ -9095,9 +9096,9 @@ react-app-rewire-hot-loader@^2.0.1:
integrity sha512-XTUPOv5q0zJeEtXECfilDPfqCiktSVbIyupiqigIHOO8EMZec2YfNpwZzqDWMu3yfaEHRs54qRCcCgRR/1w3EQ==
react-app-rewired@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/react-app-rewired/-/react-app-rewired-2.1.6.tgz#33ee3076a7f34d6a7c94e649cac67e7c8c580de8"
integrity sha512-06flj0kK5tf/RN4naRv/sn6j3sQd7rsURoRLKLpffXDzJeNiAaTNic+0I8Basojy5WDwREkTqrMLewSAjcb13w==
version "2.1.7"
resolved "https://registry.yarnpkg.com/react-app-rewired/-/react-app-rewired-2.1.7.tgz#b229d32b93b076059e62b06e8117109b92599e18"
integrity sha512-SIq7yRIohZzeO432WHlfvEEzOYs4JfOIoUIU663eIFt/ucUoqJxQwW1FClhhL21V6F8bqI+8URJoBlB0yUEKaA==
dependencies:
semver "^5.6.0"
@@ -9157,14 +9158,14 @@ react-dev-utils@^10.2.1:
strip-ansi "6.0.0"
text-table "0.2.0"
react-dom@17.0.0:
version "17.0.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.0.tgz#f8266e4d9861584553ccbd186d596a1c7dd8dcb4"
integrity sha512-OGnFbxCjI2TMAZYMVxi4hqheJiN8rCEVVrL7XIGzCB6beNc4Am8M47HtkvxODZw9QgjmAPKpLba9FTu4fC1byA==
react-dom@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler "^0.20.0"
scheduler "^0.20.1"
react-error-overlay@^6.0.7:
version "6.0.8"
@@ -9185,11 +9186,16 @@ react-hot-loader@^4.13.0:
shallowequal "^1.1.0"
source-map "^0.7.3"
react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4:
react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
"react-is@^16.8.0 || ^17.0.0":
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@@ -9357,10 +9363,10 @@ react-window-infinite-loader@^1.0.5:
resolved "https://registry.yarnpkg.com/react-window-infinite-loader/-/react-window-infinite-loader-1.0.5.tgz#6fe094d538a88978c2c9b623052bc50cb28c2abc"
integrity sha512-IcPIq8lADK3zsAcqoLqQGyduicqR6jWkiK2VUX5sKSI9X/rou6OWlOEexnGyujdNTG7hSG8OVBFEhLSDs4qrxg==
react@17.0.0:
version "17.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.0.tgz#ad96d5fa1a33bb9b06d0cc52672f7992d84aa662"
integrity sha512-rG9bqS3LMuetoSUKHN8G3fMNuQOePKDThK6+2yXFWtoeTDLVNh/QCaxT+Jr+rNf4lwNXpx+atdn3Aa0oi8/6eQ==
react@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
@@ -9896,15 +9902,7 @@ saxes@^3.1.9:
dependencies:
xmlchars "^2.1.1"
scheduler@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler@^0.20.0:
scheduler@^0.20.1:
version "0.20.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c"
integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==
@@ -10850,11 +10848,16 @@ ts-pnp@^1.1.6:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"