list policies screen (#9)
delete policy modal add policy editor modal uncommenting chart removing comments from chart
This commit is contained in:
@@ -18,10 +18,12 @@
|
||||
"@types/recharts": "^1.8.9",
|
||||
"@types/superagent": "^4.1.4",
|
||||
"@types/webpack-env": "^1.14.1",
|
||||
"codemirror": "^5.52.2",
|
||||
"history": "^4.10.1",
|
||||
"local-storage-fallback": "^4.1.1",
|
||||
"moment": "^2.24.0",
|
||||
"react": "^16.13.1",
|
||||
"react-codemirror2": "^7.1.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-moment": "^0.9.7",
|
||||
"react-redux": "^7.1.3",
|
||||
|
||||
@@ -43,6 +43,7 @@ import { AppState } from "../../store";
|
||||
import { setMenuOpen } from "../../actions";
|
||||
import { ThemedComponentProps } from "@material-ui/core/styles/withTheme";
|
||||
import Buckets from "./Buckets/Buckets";
|
||||
import Policies from "./Policies/Policies";
|
||||
import Permissions from "./Permissions/Permissions";
|
||||
import Dashboard from "./Dashboard/Dashboard";
|
||||
import Menu from "./Menu";
|
||||
@@ -213,6 +214,7 @@ class Console extends React.Component<
|
||||
<Switch>
|
||||
<Route exact path="/buckets" component={Buckets} />
|
||||
<Route exact path="/permissions" component={Permissions} />
|
||||
<Route exact path="/policies" component={Policies} />
|
||||
<Route
|
||||
exact
|
||||
path="/service_accounts"
|
||||
|
||||
@@ -122,6 +122,12 @@ class Menu extends React.Component<MenuProps> {
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Permissions" />
|
||||
</ListItem>
|
||||
<ListItem button component={NavLink} to="/policies">
|
||||
<ListItemIcon>
|
||||
<PermissionIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="policies" />
|
||||
</ListItem>
|
||||
<ListItem button component={NavLink} to="/service_accounts">
|
||||
<ListItemIcon>
|
||||
<ServiceAccountIcon />
|
||||
|
||||
193
portal-ui/src/screens/Console/Policies/AddPolicy.tsx
Normal file
193
portal-ui/src/screens/Console/Policies/AddPolicy.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// 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 from "react";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import {UnControlled as CodeMirror} from 'react-codemirror2'
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
LinearProgress,
|
||||
TextField
|
||||
} from "@material-ui/core";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import Title from "../../../common/Title";
|
||||
import api from "../../../common/api";
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
import 'codemirror/theme/material.css';
|
||||
require('codemirror/mode/javascript/javascript');
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red"
|
||||
},
|
||||
jsonPolicyEditor: {
|
||||
minHeight: 400,
|
||||
width: "100%",
|
||||
},
|
||||
codeMirror: {
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
|
||||
interface IAddPolicyProps {
|
||||
classes: any;
|
||||
open: boolean;
|
||||
closeModalAndRefresh: () => void;
|
||||
}
|
||||
|
||||
interface IAddPolicyState {
|
||||
addLoading: boolean;
|
||||
addError: string;
|
||||
policyName: string;
|
||||
policyDefinition: string;
|
||||
}
|
||||
|
||||
class AddPolicy extends React.Component<IAddPolicyProps, IAddPolicyState> {
|
||||
state: IAddPolicyState = {
|
||||
addLoading: false,
|
||||
addError: "",
|
||||
policyName: "",
|
||||
policyDefinition: "",
|
||||
};
|
||||
addRecord(event: React.FormEvent) {
|
||||
event.preventDefault();
|
||||
const { policyName, addLoading, policyDefinition } = this.state;
|
||||
if (addLoading) {
|
||||
return;
|
||||
}
|
||||
this.setState({ addLoading: true }, () => {
|
||||
api
|
||||
.invoke("POST", "/api/v1/policies", {
|
||||
name: policyName,
|
||||
definition: policyDefinition,
|
||||
})
|
||||
.then(res => {
|
||||
this.setState(
|
||||
{
|
||||
addLoading: false,
|
||||
addError: ""
|
||||
},
|
||||
() => {
|
||||
this.props.closeModalAndRefresh();
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch(err => {
|
||||
this.setState({
|
||||
addLoading: false,
|
||||
addError: err
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { classes, open } = this.props;
|
||||
const { addLoading, addError, policyName, policyDefinition} = this.state;
|
||||
return (
|
||||
<Dialog
|
||||
fullWidth
|
||||
open={open}
|
||||
onClose={() => {
|
||||
this.setState({ addError: "" }, () => {
|
||||
this.props.closeModalAndRefresh();
|
||||
});
|
||||
}}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
<Title>Create Policy</Title>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<form
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
|
||||
this.addRecord(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="Policy Name"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
this.setState({ policyName: e.target.value });
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<CodeMirror
|
||||
className={classes.codeMirror}
|
||||
value=""
|
||||
options={{
|
||||
mode: 'javascript',
|
||||
theme: 'material',
|
||||
lineNumbers: true
|
||||
}}
|
||||
onChange={(editor, data, value) => {
|
||||
this.setState({ policyDefinition: value });
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(AddPolicy);
|
||||
144
portal-ui/src/screens/Console/Policies/DeletePolicy.tsx
Normal file
144
portal-ui/src/screens/Console/Policies/DeletePolicy.tsx
Normal file
@@ -0,0 +1,144 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// 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 { 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 { PolicyList } from "./types";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red"
|
||||
}
|
||||
});
|
||||
|
||||
interface IDeletePolicyProps {
|
||||
classes: any;
|
||||
closeDeleteModalAndRefresh: (refresh: boolean) => void;
|
||||
deleteOpen: boolean;
|
||||
selectedPolicy: string;
|
||||
}
|
||||
|
||||
interface IDeletePolicyState {
|
||||
deleteLoading: boolean;
|
||||
deleteError: string;
|
||||
}
|
||||
|
||||
class DeletePolicy extends React.Component<IDeletePolicyProps, IDeletePolicyState> {
|
||||
state: IDeletePolicyState = {
|
||||
deleteLoading: false,
|
||||
deleteError: ""
|
||||
};
|
||||
removeRecord() {
|
||||
const { deleteLoading } = this.state;
|
||||
const { selectedPolicy } = this.props;
|
||||
if (deleteLoading) {
|
||||
return;
|
||||
}
|
||||
this.setState({ deleteLoading: true }, () => {
|
||||
api
|
||||
.invoke("DELETE", `/api/v1/policies/${selectedPolicy}`)
|
||||
.then((res: PolicyList) => {
|
||||
this.setState(
|
||||
{
|
||||
deleteLoading: false,
|
||||
deleteError: ""
|
||||
},
|
||||
() => {
|
||||
this.props.closeDeleteModalAndRefresh(true);
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch(err => {
|
||||
this.setState({
|
||||
deleteLoading: false,
|
||||
deleteError: err
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { classes, deleteOpen, selectedPolicy } = this.props;
|
||||
const { deleteLoading, deleteError } = this.state;
|
||||
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 Bucket</DialogTitle>
|
||||
<DialogContent>
|
||||
{deleteLoading && <LinearProgress />}
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to delete policy <b>{selectedPolicy}</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)(DeletePolicy);
|
||||
345
portal-ui/src/screens/Console/Policies/Policies.tsx
Normal file
345
portal-ui/src/screens/Console/Policies/Policies.tsx
Normal file
@@ -0,0 +1,345 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// 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 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 {
|
||||
Button,
|
||||
IconButton,
|
||||
LinearProgress,
|
||||
TableFooter,
|
||||
TablePagination
|
||||
} from "@material-ui/core";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import Moment from "react-moment";
|
||||
import {PolicyList, Policy} from "./types";
|
||||
import AddPolicy from "./AddPolicy";
|
||||
import DeletePolicy from "./DeletePolicy";
|
||||
import api from "../../../common/api";
|
||||
import {CreateIcon} from "../../../icons";
|
||||
import {MinTablePaginationActions} from "../../../common/MinTablePaginationActions";
|
||||
import VisibilityIcon from '@material-ui/icons/Visibility';
|
||||
|
||||
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)
|
||||
},
|
||||
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 IPoliciesProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
interface IPoliciesState {
|
||||
records: Policy[];
|
||||
totalRecords: number;
|
||||
loading: boolean;
|
||||
error: string;
|
||||
deleteError: string;
|
||||
addScreenOpen: boolean;
|
||||
page: number;
|
||||
rowsPerPage: number;
|
||||
deleteOpen: boolean;
|
||||
selectedPolicy: string;
|
||||
filterPolicies: string;
|
||||
}
|
||||
|
||||
class Policies extends React.Component<IPoliciesProps, IPoliciesState> {
|
||||
state: IPoliciesState = {
|
||||
records: [],
|
||||
totalRecords: 0,
|
||||
loading: false,
|
||||
error: "",
|
||||
deleteError: "",
|
||||
addScreenOpen: false,
|
||||
page: 0,
|
||||
rowsPerPage: 10,
|
||||
deleteOpen: false,
|
||||
selectedPolicy: "",
|
||||
filterPolicies: ""
|
||||
};
|
||||
|
||||
fetchRecords() {
|
||||
this.setState({ loading: true }, () => {
|
||||
const { page, rowsPerPage } = this.state;
|
||||
const offset = page * rowsPerPage;
|
||||
api
|
||||
.invoke("GET", `/api/v1/policies?offset=${offset}&limit=${rowsPerPage}`)
|
||||
.then((res: PolicyList) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
records: res.policies,
|
||||
totalRecords: res.total,
|
||||
error: ""
|
||||
});
|
||||
// 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;
|
||||
this.setState({ page: newPage }, () => {
|
||||
this.fetchRecords();
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.setState({ loading: false, error: err });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
closeAddModalAndRefresh() {
|
||||
this.setState({ addScreenOpen: false }, () => {
|
||||
this.fetchRecords();
|
||||
});
|
||||
}
|
||||
|
||||
closeDeleteModalAndRefresh(refresh: boolean) {
|
||||
this.setState({ deleteOpen: false }, () => {
|
||||
if (refresh) {
|
||||
this.fetchRecords();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
policyFilter(): void {}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.fetchRecords();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const {
|
||||
records,
|
||||
totalRecords,
|
||||
addScreenOpen,
|
||||
loading,
|
||||
page,
|
||||
rowsPerPage,
|
||||
deleteOpen,
|
||||
selectedPolicy,
|
||||
filterPolicies
|
||||
} = this.state;
|
||||
|
||||
const offset = page * rowsPerPage;
|
||||
|
||||
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 confirmDeletePolicy = (policy: string) => {
|
||||
this.setState({ deleteOpen: true, selectedPolicy: policy });
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<AddPolicy
|
||||
open={addScreenOpen}
|
||||
closeModalAndRefresh={() => {
|
||||
this.closeAddModalAndRefresh();
|
||||
}}
|
||||
/>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6">Policies</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.actionsTray}>
|
||||
<TextField
|
||||
placeholder="Search Policies"
|
||||
className={classes.searchField}
|
||||
id="search-resource"
|
||||
label=""
|
||||
onChange={val => {
|
||||
this.setState({
|
||||
filterPolicies: val.target.value
|
||||
});
|
||||
}}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CreateIcon />}
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
addScreenOpen: true
|
||||
});
|
||||
}}
|
||||
>
|
||||
Create Policy
|
||||
</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>Name</TableCell>
|
||||
<TableCell align="right">Actions</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{records
|
||||
.slice(offset, offset + rowsPerPage)
|
||||
.filter((b: Policy) => {
|
||||
if (filterPolicies === "") {
|
||||
return true;
|
||||
} else {
|
||||
if (b.name.indexOf(filterPolicies) >= 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})
|
||||
.map(row => (
|
||||
<TableRow key={row.name}>
|
||||
<TableCell>{row.name}</TableCell>
|
||||
<TableCell align="right">
|
||||
<IconButton
|
||||
aria-label="view"
|
||||
onClick={() => {
|
||||
confirmDeletePolicy(row.name);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
onClick={() => {
|
||||
confirmDeletePolicy(row.name);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
<TableFooter>
|
||||
<TableRow>
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
colSpan={3}
|
||||
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 Policies</div>
|
||||
)}
|
||||
</Paper>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<DeletePolicy
|
||||
deleteOpen={deleteOpen}
|
||||
selectedPolicy={selectedPolicy}
|
||||
closeDeleteModalAndRefresh={(refresh: boolean) => {
|
||||
this.closeDeleteModalAndRefresh(refresh);
|
||||
}}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(Policies);
|
||||
32
portal-ui/src/screens/Console/Policies/types.ts
Normal file
32
portal-ui/src/screens/Console/Policies/types.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// 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/>.
|
||||
|
||||
export interface Statement {
|
||||
effect: string;
|
||||
actions: string[];
|
||||
resources: string[];
|
||||
}
|
||||
|
||||
export interface Policy {
|
||||
name: string;
|
||||
version: string;
|
||||
statements: Statement[]
|
||||
}
|
||||
|
||||
export interface PolicyList {
|
||||
policies: Policy[];
|
||||
total: number;
|
||||
}
|
||||
@@ -2915,6 +2915,11 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codemirror@^5.52.2:
|
||||
version "5.52.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.52.2.tgz#c29e1f7179f85eb0dd17c0586fa810e4838ff584"
|
||||
integrity sha512-WCGCixNUck2HGvY8/ZNI1jYfxPG5cRHv0VjmWuNzbtCLz8qYA5d+je4QhSSCtCaagyeOwMi/HmmPTjBgiTm2lQ==
|
||||
|
||||
collection-visit@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
|
||||
@@ -3903,9 +3908,9 @@ ee-first@1.1.1:
|
||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.390:
|
||||
version "1.3.393"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.393.tgz#d13fa4cbf5065e18451c84465d22aef6aca9a911"
|
||||
integrity sha512-Ko3/VdhZAaMaJBLBFqEJ+M1qMiBI8sJfPY/hSJvDrkB3Do8LJsL9tmXy4w7o9nPXif/jFaZGSlXTQWU8XVsYtg==
|
||||
version "1.3.394"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.394.tgz#50e927bb9f6a559ed21d284e7683ec5e2c784835"
|
||||
integrity sha512-AEbSKBF49P+GgEP34w0VdYWn9SiMHgWUJbOkPEE1WZMIpWXtvfT9N0sd4Lv4jjD6DeSFjRuzm6+btn/yCz6h2Q==
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.5.2"
|
||||
@@ -8795,6 +8800,11 @@ react-app-polyfill@^1.0.6:
|
||||
regenerator-runtime "^0.13.3"
|
||||
whatwg-fetch "^3.0.0"
|
||||
|
||||
react-codemirror2@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-7.1.0.tgz#b874a275ad4f6f2ee5adb23b550c0f4b8b82776d"
|
||||
integrity sha512-Rel0QbPnCTjHxgZYt6TkGw4icSZXNyONHb72a+1wWA+PlYJIvzFAv4pZlDPG0rpKpKmy4kSUlkoWgneH7w3A0g==
|
||||
|
||||
react-dev-utils@^10.2.1:
|
||||
version "10.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19"
|
||||
@@ -10568,10 +10578,10 @@ typeface-roboto@^0.0.75:
|
||||
resolved "https://registry.yarnpkg.com/typeface-roboto/-/typeface-roboto-0.0.75.tgz#98d5ba35ec234bbc7172374c8297277099cc712b"
|
||||
integrity sha512-VrR/IiH00Z1tFP4vDGfwZ1esNqTiDMchBEXYY9kilT6wRGgFoCAlgkEUMHb1E3mB0FsfZhv756IF0+R+SFPfdg==
|
||||
|
||||
typescript@3.8.3:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
||||
typescript@3.6.4:
|
||||
version "3.6.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
|
||||
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||
version "1.0.4"
|
||||
|
||||
Reference in New Issue
Block a user