Files
object-browser/portal-ui/src/screens/Console/Buckets/ViewBucket/AddEvent.tsx
2020-04-07 11:56:52 -07:00

315 lines
9.3 KiB
TypeScript

// 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, { ChangeEvent } from "react";
import Grid from "@material-ui/core/Grid";
import Title from "../../../../common/Title";
import Typography from "@material-ui/core/Typography";
import {
Button,
Dialog,
DialogContent,
DialogTitle,
FormControl,
InputLabel,
LinearProgress,
MenuItem,
Select,
TextField
} from "@material-ui/core";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import api from "../../../../common/api";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import TableBody from "@material-ui/core/TableBody";
import Checkbox from "@material-ui/core/Checkbox";
import Table from "@material-ui/core/Table";
import { ArnList } from "../types";
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red"
},
minTableHeader: {
color: "#393939",
"& tr": {
"& th": {
fontWeight: "bold"
}
}
}
});
interface IAddEventProps {
classes: any;
open: boolean;
selectedBucket: string;
closeModalAndRefresh: () => void;
}
interface IAddEventState {
addLoading: boolean;
addError: string;
prefix: string;
suffix: string;
arn: string;
selectedEvents: string[];
arnList: string[];
}
class AddEvent extends React.Component<IAddEventProps, IAddEventState> {
state: IAddEventState = {
addLoading: false,
addError: "",
prefix: "",
suffix: "",
arn: "",
selectedEvents: [],
arnList: []
};
addRecord(event: React.FormEvent) {
event.preventDefault();
const { prefix, suffix, addLoading, arn, selectedEvents } = this.state;
const { selectedBucket } = this.props;
if (addLoading) {
return;
}
this.setState({ addLoading: true }, () => {
api
.invoke("POST", `/api/v1/buckets/${selectedBucket}/events`, {
configuration: {
arn: arn,
events: selectedEvents,
prefix: prefix,
suffix: suffix
},
ignoreExisting: true
})
.then(res => {
this.setState(
{
addLoading: false,
addError: ""
},
() => {
this.props.closeModalAndRefresh();
}
);
})
.catch(err => {
this.setState({
addLoading: false,
addError: err
});
});
});
}
fetchArnList() {
this.setState({ addLoading: true }, () => {
api
.invoke("GET", `/api/v1/admin/arns`)
.then((res: ArnList) => {
let arns: string[] = [];
if (res.arns !== null) {
arns = res.arns;
}
this.setState({
addLoading: false,
arnList: arns,
addError: ""
});
})
.catch((err: any) => {
this.setState({ addLoading: false, addError: err });
});
});
}
componentDidMount(): void {
this.fetchArnList();
}
render() {
const { classes, open } = this.props;
const { addLoading, addError, arn, selectedEvents, arnList } = this.state;
const events = [
{ label: "PUT - Object Uploaded", value: "put" },
{ label: "GET - Object accessed", value: "get" },
{ label: "DELETE - Object Deleted", value: "delete" }
];
const handleClick = (
event: React.MouseEvent<unknown> | ChangeEvent<unknown>,
name: string
) => {
const selectedIndex = selectedEvents.indexOf(name);
let newSelected: string[] = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selectedEvents, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selectedEvents.slice(1));
} else if (selectedIndex === selectedEvents.length - 1) {
newSelected = newSelected.concat(selectedEvents.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selectedEvents.slice(0, selectedIndex),
selectedEvents.slice(selectedIndex + 1)
);
}
this.setState({ selectedEvents: newSelected });
};
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">
<Title>Subscribe To Event</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}>
<FormControl className={classes.formControl} fullWidth>
<InputLabel id="select-access-policy">ARN</InputLabel>
<Select
labelId="select-access-policy"
id="select-access-policy"
value={arn}
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
this.setState({ arn: e.target.value as string });
}}
>
{arnList.map(arn => (
<MenuItem value={arn}>{arn}</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<Table size="medium">
<TableHead className={classes.minTableHeader}>
<TableRow>
<TableCell>Select</TableCell>
<TableCell>Event</TableCell>
</TableRow>
</TableHead>
<TableBody>
{events.map(row => (
<TableRow
key={`group-${row.value}`}
onClick={event => handleClick(event, row.value)}
>
<TableCell padding="checkbox">
<Checkbox
value={row.value}
color="primary"
inputProps={{
"aria-label": "secondary checkbox"
}}
onChange={event => handleClick(event, row.value)}
checked={selectedEvents.includes(row.value)}
/>
</TableCell>
<TableCell className={classes.wrapCell}>
{row.label}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Grid>
<Grid item xs={12}>
<TextField
id="standard-basic"
fullWidth
label="Prefix"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ prefix: e.target.value });
}}
/>
</Grid>
<Grid item xs={12}>
<TextField
id="standard-basic"
fullWidth
label="Suffix"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ suffix: e.target.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)(AddEvent);