Skip to content

Commit 42d617c

Browse files
authored
Add list objects UI and integrate with listing and delete api (#310)
1 parent 28eb878 commit 42d617c

File tree

11 files changed

+579
-145
lines changed

11 files changed

+579
-145
lines changed

pkg/acl/endpoints.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ var (
4040
heal = "/heal"
4141
remoteBuckets = "/remote-buckets"
4242
replication = "/replication"
43-
objectBrowser = "/object-browser/:bucket?/*"
43+
objectBrowser = "/object-browser/:bucket?"
4444
mainObjectBrowser = "/object-browser"
4545
)
4646

portal-ui/bindata_assetfs.go

Lines changed: 98 additions & 121 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/src/screens/Console/Buckets/Buckets.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// This file is part of MinIO Buckets Server
1+
// This file is part of MinIO Console Server
22
// Copyright (c) 2020 MinIO, Inc.
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -19,7 +19,7 @@ import {
1919
createStyles,
2020
StyledProps,
2121
Theme,
22-
withStyles
22+
withStyles,
2323
} from "@material-ui/core/styles";
2424

2525
import history from "../../../history";
@@ -28,7 +28,7 @@ import {
2828
RouteComponentProps,
2929
Router,
3030
Switch,
31-
withRouter
31+
withRouter,
3232
} from "react-router-dom";
3333
import { connect } from "react-redux";
3434
import { AppState } from "../../../store";
@@ -41,62 +41,62 @@ import ViewBucket from "./ViewBucket/ViewBucket";
4141
const styles = (theme: Theme) =>
4242
createStyles({
4343
root: {
44-
display: "flex"
44+
display: "flex",
4545
},
4646
toolbar: {
4747
background: theme.palette.background.default,
4848
color: "black",
49-
paddingRight: 24 // keep right padding when drawer closed
49+
paddingRight: 24, // keep right padding when drawer closed
5050
},
5151
toolbarIcon: {
5252
display: "flex",
5353
alignItems: "center",
5454
justifyContent: "flex-end",
5555
padding: "0 8px",
56-
...theme.mixins.toolbar
56+
...theme.mixins.toolbar,
5757
},
5858
appBar: {
5959
zIndex: theme.zIndex.drawer + 1,
6060
transition: theme.transitions.create(["width", "margin"], {
6161
easing: theme.transitions.easing.sharp,
62-
duration: theme.transitions.duration.leavingScreen
63-
})
62+
duration: theme.transitions.duration.leavingScreen,
63+
}),
6464
},
6565

6666
menuButton: {
67-
marginRight: 36
67+
marginRight: 36,
6868
},
6969
menuButtonHidden: {
70-
display: "none"
70+
display: "none",
7171
},
7272
title: {
73-
flexGrow: 1
73+
flexGrow: 1,
7474
},
7575
appBarSpacer: {
76-
height: "5px"
76+
height: "5px",
7777
},
7878
content: {
7979
flexGrow: 1,
8080
height: "100vh",
81-
overflow: "auto"
81+
overflow: "auto",
8282
},
8383
container: {
8484
paddingTop: theme.spacing(4),
85-
paddingBottom: theme.spacing(4)
85+
paddingBottom: theme.spacing(4),
8686
},
8787
paper: {
8888
padding: theme.spacing(2),
8989
display: "flex",
9090
overflow: "auto",
91-
flexDirection: "column"
91+
flexDirection: "column",
9292
},
9393
fixedHeight: {
94-
minHeight: 240
95-
}
94+
minHeight: 240,
95+
},
9696
});
9797

9898
const mapState = (state: AppState) => ({
99-
open: state.system.sidebarOpen
99+
open: state.system.sidebarOpen,
100100
});
101101

102102
const connector = connect(mapState, { setMenuOpen });
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2020 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
18+
import React from "react";
19+
import {
20+
Button,
21+
Dialog,
22+
DialogActions,
23+
DialogContent,
24+
DialogContentText,
25+
DialogTitle,
26+
LinearProgress,
27+
} from "@material-ui/core";
28+
import api from "../../../../../../common/api";
29+
import { BucketObjectsList } from "../ListObjects/types";
30+
import Typography from "@material-ui/core/Typography";
31+
32+
const styles = (theme: Theme) =>
33+
createStyles({
34+
errorBlock: {
35+
color: "red",
36+
},
37+
});
38+
39+
interface IDeleteObjectProps {
40+
classes: any;
41+
closeDeleteModalAndRefresh: (refresh: boolean) => void;
42+
deleteOpen: boolean;
43+
selectedObject: string;
44+
selectedBucket: string;
45+
}
46+
47+
interface IDeleteObjectState {
48+
deleteLoading: boolean;
49+
deleteError: string;
50+
}
51+
52+
class DeleteObject extends React.Component<
53+
IDeleteObjectProps,
54+
IDeleteObjectState
55+
> {
56+
state: IDeleteObjectState = {
57+
deleteLoading: false,
58+
deleteError: "",
59+
};
60+
61+
removeRecord() {
62+
const { deleteLoading } = this.state;
63+
const { selectedObject, selectedBucket } = this.props;
64+
if (deleteLoading) {
65+
return;
66+
}
67+
var recursive = false;
68+
if (selectedObject.endsWith("/")) {
69+
recursive = true;
70+
}
71+
this.setState({ deleteLoading: true }, () => {
72+
api
73+
.invoke(
74+
"DELETE",
75+
`/api/v1/buckets/${selectedBucket}/objects?path=${selectedObject}&recursive=${recursive}`
76+
)
77+
.then((res: BucketObjectsList) => {
78+
this.setState(
79+
{
80+
deleteLoading: false,
81+
deleteError: "",
82+
},
83+
() => {
84+
this.props.closeDeleteModalAndRefresh(true);
85+
}
86+
);
87+
})
88+
.catch((err) => {
89+
this.setState({
90+
deleteLoading: false,
91+
deleteError: err,
92+
});
93+
});
94+
});
95+
}
96+
97+
render() {
98+
const { classes, deleteOpen, selectedObject } = this.props;
99+
const { deleteLoading, deleteError } = this.state;
100+
101+
return (
102+
<Dialog
103+
open={deleteOpen}
104+
onClose={() => {
105+
this.setState({ deleteError: "" }, () => {
106+
this.props.closeDeleteModalAndRefresh(false);
107+
});
108+
}}
109+
aria-labelledby="alert-dialog-title"
110+
aria-describedby="alert-dialog-description"
111+
>
112+
<DialogTitle id="alert-dialog-title">Delete</DialogTitle>
113+
<DialogContent>
114+
{deleteLoading && <LinearProgress />}
115+
<DialogContentText id="alert-dialog-description">
116+
Are you sure you want to delete: <b>{selectedObject}</b>?{" "}
117+
{deleteError !== "" && (
118+
<React.Fragment>
119+
<br />
120+
<Typography
121+
component="p"
122+
variant="body1"
123+
className={classes.errorBlock}
124+
>
125+
{deleteError}
126+
</Typography>
127+
</React.Fragment>
128+
)}
129+
</DialogContentText>
130+
</DialogContent>
131+
<DialogActions>
132+
<Button
133+
onClick={() => {
134+
this.setState({ deleteError: "" }, () => {
135+
this.props.closeDeleteModalAndRefresh(false);
136+
});
137+
}}
138+
color="primary"
139+
disabled={deleteLoading}
140+
>
141+
Cancel
142+
</Button>
143+
<Button
144+
onClick={() => {
145+
this.removeRecord();
146+
}}
147+
color="secondary"
148+
autoFocus
149+
>
150+
Delete
151+
</Button>
152+
</DialogActions>
153+
</Dialog>
154+
);
155+
}
156+
}
157+
158+
export default withStyles(styles)(DeleteObject);

0 commit comments

Comments
 (0)