Add Bucket as a page (#1220)

* Add Bucket as a page

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* goimports

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Redirect to bucket browse

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Address comment

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2021-11-12 12:44:23 -08:00
committed by GitHub
parent 258a9400d9
commit 2b34fbae47
12 changed files with 330 additions and 318 deletions

View File

@@ -39,6 +39,7 @@ var (
dashboard = "/dashboard"
metrics = "/metrics"
profiling = "/profiling"
addBucket = "/add-bucket"
buckets = "/buckets"
bucketsGeneral = "/buckets/*"
bucketsAdmin = "/buckets/:bucketName/admin/*"
@@ -335,6 +336,7 @@ var endpointRules = map[string]ConfigurationActionSet{
dashboard: dashboardActionSet,
metrics: dashboardActionSet,
profiling: profilingActionSet,
addBucket: bucketsActionSet,
buckets: bucketsActionSet,
bucketsGeneral: bucketsActionSet,
bucketsAdmin: bucketsActionSet,

View File

@@ -79,7 +79,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"s3:*",
},
},
want: 9,
want: 10,
},
{
name: "all admin and s3 endpoints",
@@ -89,7 +89,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"s3:*",
},
},
want: 36,
want: 37,
},
{
name: "Console User - default endpoints",

View File

@@ -16,7 +16,7 @@
import React from "react";
import history from "../../../history";
import { Route, Router, Switch, withRouter, Redirect } from "react-router-dom";
import { Redirect, Route, Router, Switch, withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { AppState } from "../../../store";
import { setMenuOpen } from "../../../actions";
@@ -24,6 +24,7 @@ import NotFoundPage from "../../NotFoundPage";
import ListBuckets from "./ListBuckets/ListBuckets";
import BucketDetails from "./BucketDetails/BucketDetails";
import BrowserHandler from "./BucketDetails/BrowserHandler";
import AddBucket from "./ListBuckets/AddBucket";
const mapState = (state: AppState) => ({
open: state.system.sidebarOpen,
@@ -35,6 +36,7 @@ const Buckets = () => {
return (
<Router history={history}>
<Switch>
<Route path="/add-bucket" component={AddBucket} />
<Route path="/buckets/:bucketName/admin/*" component={BucketDetails} />
<Route path="/buckets/:bucketName/admin" component={BucketDetails} />
<Route

View File

@@ -16,23 +16,18 @@
import React, { Fragment, useEffect, useState } from "react";
import Grid from "@mui/material/Grid";
import {
Button,
LinearProgress,
SelectChangeEvent,
Typography,
} from "@mui/material";
import { Button, LinearProgress, SelectChangeEvent } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
import { containerForHeader } from "../../Common/FormComponents/common/styleLibrary";
import api from "../../../../common/api";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
import RadioGroupSelector from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
import { factorForDropdown, getBytes } from "../../../../common/utils";
import { AppState } from "../../../../store";
import history from "../../../../history";
import { connect } from "react-redux";
import {
addBucketEnableObjectLocking,
@@ -50,13 +45,20 @@ import {
import { useDebounce } from "use-debounce";
import { MakeBucketRequest } from "../types";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import { setModalErrorSnackMessage } from "../../../../actions";
import { ErrorResponseHandler } from "../../../../common/types";
import PageHeader from "../../Common/PageHeader/PageHeader";
import BackLink from "../../../../common/BackLink";
import { BucketsIcon } from "../../../../icons";
import { setErrorSnackMessage } from "../../../../actions";
const styles = (theme: Theme) =>
createStyles({
buttonContainer: {
marginTop: 24,
textAlign: "right",
"& .MuiButton-root": {
marginLeft: 8,
},
},
multiContainer: {
display: "flex",
@@ -78,13 +80,26 @@ const styles = (theme: Theme) =>
padding: 8,
borderRadius: 3,
},
...modalBasic,
title: {
marginBottom: 8,
},
headTitle: {
fontWeight: "bold",
fontSize: 16,
paddingLeft: 8,
},
h6title: {
fontWeight: "bold",
color: "#000000",
fontSize: 20,
paddingBottom: 8,
},
...containerForHeader(theme.spacing(4)),
});
interface IAddBucketProps {
classes: any;
open: boolean;
closeModalAndRefresh: (refresh: boolean) => void;
addBucketName: typeof addBucketName;
addBucketVersioned: typeof addBucketVersioning;
enableObjectLocking: typeof addBucketEnableObjectLocking;
@@ -96,7 +111,7 @@ interface IAddBucketProps {
addBucketRetentionMode: typeof addBucketRetentionMode;
addBucketRetentionUnit: typeof addBucketRetentionUnit;
addBucketRetentionValidity: typeof addBucketRetentionValidity;
setModalError: typeof setModalErrorSnackMessage;
setErrorSnackMessage: typeof setErrorSnackMessage;
bucketName: string;
versioningEnabled: boolean;
lockingEnabled: boolean;
@@ -113,8 +128,6 @@ interface IAddBucketProps {
const AddBucket = ({
classes,
open,
closeModalAndRefresh,
addBucketName,
addBucketVersioned,
enableObjectLocking,
@@ -126,7 +139,7 @@ const AddBucket = ({
addBucketRetentionMode,
addBucketRetentionUnit,
addBucketRetentionValidity,
setModalError,
setErrorSnackMessage,
bucketName,
versioningEnabled,
lockingEnabled,
@@ -181,14 +194,14 @@ const AddBucket = ({
.invoke("POST", "/api/v1/buckets", request)
.then((res) => {
setAddLoading(false);
closeModalAndRefresh(true);
const newBucketName = `${bucketName}`;
resetForm();
history.push(`/buckets/${newBucketName}/browse`);
})
.catch((err: ErrorResponseHandler) => {
setAddLoading(false);
setModalError(err);
setErrorSnackMessage(err);
});
resetForm();
};
const [value] = useDebounce(bucketName, 1000);
@@ -265,251 +278,267 @@ const AddBucket = ({
]);
return (
<ModalWrapper
title="Create Bucket"
modalOpen={open}
onClose={() => {
closeModalAndRefresh(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
addRecord(e);
}}
>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<Grid item xs={12}>
<InputBoxWrapper
id="bucket-name"
name="bucket-name"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketName(event.target.value);
}}
label="Bucket Name"
value={bucketName}
/>
</Grid>
<Grid item xs={12}>
<Typography component="h6" variant="h6">
Features
</Typography>
<br />
{!distributedSetup && (
<Fragment>
<div className={classes.error}>
These features are unavailable in a single-disk setup.
<br />
Please deploy a server in{" "}
<a
href="https://docs.min.io/minio/baremetal/installation/deploy-minio-distributed.html?ref=con"
target="_blank"
rel="noreferrer"
>
Distributed Mode
</a>{" "}
to use these features.
</div>
<br />
<br />
</Fragment>
)}
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="versioned"
id="versioned"
name="versioned"
checked={versioningEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketVersioned(event.target.checked);
}}
description={
"Allows to keep multiple versions of the same object under the same key."
}
label={"Versioning"}
disabled={!distributedSetup}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="locking"
id="locking"
name="locking"
disabled={lockingFieldDisabled || !distributedSetup}
checked={lockingEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
enableObjectLocking(event.target.checked);
}}
label={"Object Locking"}
description={
"Required to support retention and legal hold. Can only be enabled at bucket creation."
}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_quota"
id="bucket_quota"
name="bucket_quota"
checked={quotaEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketQuota(event.target.checked);
}}
label={"Quota"}
description={"Limit the amount of data in the bucket."}
disabled={!distributedSetup}
/>
</Grid>
{quotaEnabled && distributedSetup && (
<React.Fragment>
<Fragment>
<PageHeader label={"Create a Bucket"} />
<Grid container className={classes.container}>
<Grid item xs={12}>
<BackLink to="/buckets" label="Return to Buckets" />
</Grid>
<Grid item xs={12} className={classes.boxy}>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
addRecord(e);
}}
>
<Grid container>
<Grid item xs={12} container className={classes.title}>
<Grid item xs={"auto"}>
<BucketsIcon />
</Grid>
<Grid item xs className={classes.headTitle}>
Create Bucket
</Grid>
</Grid>
<Grid item xs={12} container>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={quotaType}
id="quota_type"
name="quota_type"
label="Quota Type"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
addBucketQuotaType(e.target.value as string);
<InputBoxWrapper
id="bucket-name"
name="bucket-name"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketName(event.target.value);
}}
selectorOptions={[
{ value: "hard", label: "Hard" },
{ value: "fifo", label: "FIFO" },
]}
label="Bucket Name"
value={bucketName}
/>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item xs={10}>
<div className={classes.h6title}>Features</div>
<br />
{!distributedSetup && (
<Fragment>
<div className={classes.error}>
These features are unavailable in a single-disk setup.
<br />
Please deploy a server in{" "}
<a
href="https://docs.min.io/minio/baremetal/installation/deploy-minio-distributed.html?ref=con"
target="_blank"
rel="noreferrer"
>
Distributed Mode
</a>{" "}
to use these features.
</div>
<br />
<br />
</Fragment>
)}
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="versioned"
id="versioned"
name="versioned"
checked={versioningEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketVersioned(event.target.checked);
}}
description={
"Allows to keep multiple versions of the same object under the same key."
}
label={"Versioning"}
disabled={!distributedSetup}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="locking"
id="locking"
name="locking"
disabled={lockingFieldDisabled || !distributedSetup}
checked={lockingEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
enableObjectLocking(event.target.checked);
}}
label={"Object Locking"}
description={
"Required to support retention and legal hold. Can only be enabled at bucket creation."
}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_quota"
id="bucket_quota"
name="bucket_quota"
checked={quotaEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketQuota(event.target.checked);
}}
label={"Quota"}
description={"Limit the amount of data in the bucket."}
disabled={!distributedSetup}
/>
</Grid>
{quotaEnabled && distributedSetup && (
<React.Fragment>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={quotaType}
id="quota_type"
name="quota_type"
label="Quota Type"
onChange={(
e: React.ChangeEvent<{ value: unknown }>
) => {
addBucketQuotaType(e.target.value as string);
}}
selectorOptions={[
{ value: "hard", label: "Hard" },
{ value: "fifo", label: "FIFO" },
]}
/>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item xs={10}>
<InputBoxWrapper
type="number"
id="quota_size"
name="quota_size"
onChange={(
e: React.ChangeEvent<HTMLInputElement>
) => {
addBucketQuotaSize(e.target.value);
}}
label="Quota"
value={quotaSize}
required
min="1"
/>
</Grid>
<Grid item xs={2}>
<div style={{ width: 100 }}>
<SelectWrapper
label=""
id="quota_unit"
name="quota_unit"
value={quotaUnit}
onChange={(e: SelectChangeEvent<string>) => {
addBucketQuotaUnit(e.target.value as string);
}}
options={factorForDropdown()}
/>
</div>
</Grid>
</Grid>
</Grid>
</React.Fragment>
)}
{versioningEnabled && distributedSetup && (
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_retention"
id="bucket_retention"
name="bucket_retention"
checked={retentionEnabled}
onChange={(
event: React.ChangeEvent<HTMLInputElement>
) => {
addBucketRetention(event.target.checked);
}}
label={"Retention"}
description={
"Impose rules to prevent object deletion for a period of time."
}
/>
</Grid>
)}
{retentionEnabled && distributedSetup && (
<React.Fragment>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={retentionMode}
id="retention_mode"
name="retention_mode"
label="Retention Mode"
onChange={(
e: React.ChangeEvent<{ value: unknown }>
) => {
addBucketRetentionMode(e.target.value as string);
}}
selectorOptions={[
{ value: "compliance", label: "Compliance" },
{ value: "governance", label: "Governance" },
]}
/>
</Grid>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={retentionUnit}
id="retention_unit"
name="retention_unit"
label="Retention Unit"
onChange={(
e: React.ChangeEvent<{ value: unknown }>
) => {
addBucketRetentionUnit(e.target.value as string);
}}
selectorOptions={[
{ value: "days", label: "Days" },
{ value: "years", label: "Years" },
]}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="quota_size"
name="quota_size"
id="retention_validity"
name="retention_validity"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
addBucketQuotaSize(e.target.value);
addBucketRetentionValidity(e.target.valueAsNumber);
}}
label="Quota"
value={quotaSize}
label="Retention Validity"
value={String(retentionValidity)}
required
min="1"
/>
</Grid>
<Grid item xs={2}>
<div style={{ width: 100 }}>
<SelectWrapper
label=""
id="quota_unit"
name="quota_unit"
value={quotaUnit}
onChange={(e: SelectChangeEvent<string>) => {
addBucketQuotaUnit(e.target.value as string);
}}
options={factorForDropdown()}
/>
</div>
</Grid>
</Grid>
</Grid>
</React.Fragment>
)}
{versioningEnabled && distributedSetup && (
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_retention"
id="bucket_retention"
name="bucket_retention"
checked={retentionEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
addBucketRetention(event.target.checked);
}}
label={"Retention"}
description={
"Impose rules to prevent object deletion for a period of time."
}
/>
</React.Fragment>
)}
</Grid>
)}
{retentionEnabled && distributedSetup && (
<React.Fragment>
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="button"
variant={"outlined"}
className={classes.clearButton}
onClick={resetForm}
>
Clear
</Button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !sendEnabled}
>
Create Bucket
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={retentionMode}
id="retention_mode"
name="retention_mode"
label="Retention Mode"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
addBucketRetentionMode(e.target.value as string);
}}
selectorOptions={[
{ value: "compliance", label: "Compliance" },
{ value: "governance", label: "Governance" },
]}
/>
<LinearProgress />
</Grid>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={retentionUnit}
id="retention_unit"
name="retention_unit"
label="Retention Unit"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
addBucketRetentionUnit(e.target.value as string);
}}
selectorOptions={[
{ value: "days", label: "Days" },
{ value: "years", label: "Years" },
]}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="retention_validity"
name="retention_validity"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
addBucketRetentionValidity(e.target.valueAsNumber);
}}
label="Retention Validity"
value={String(retentionValidity)}
required
min="1"
/>
</Grid>
</React.Fragment>
)}
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
<button
type="button"
color="primary"
className={classes.clearButton}
onClick={resetForm}
>
Clear
</button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !sendEnabled}
>
Save
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
)}
</Grid>
)}
</form>
</Grid>
</form>
</ModalWrapper>
</Grid>
</Fragment>
);
};
@@ -541,7 +570,7 @@ const connector = connect(mapState, {
addBucketRetentionMode: addBucketRetentionMode,
addBucketRetentionUnit: addBucketRetentionUnit,
addBucketRetentionValidity: addBucketRetentionValidity,
setModalError: setModalErrorSnackMessage,
setErrorSnackMessage: setErrorSnackMessage,
});
export default connector(withStyles(styles)(AddBucket));

View File

@@ -25,7 +25,6 @@ import FileCopyIcon from "@mui/icons-material/FileCopy";
import { Bucket, BucketList, HasPermissionResponse } from "../types";
import { AddIcon, BucketsIcon, WatchIcon } from "../../../../icons";
import { AppState } from "../../../../store";
import { addBucketOpen, addBucketReset } from "../actions";
import { setErrorSnackMessage } from "../../../../actions";
import {
containerForHeader,
@@ -33,7 +32,6 @@ import {
} from "../../Common/FormComponents/common/styleLibrary";
import { ErrorResponseHandler } from "../../../../common/types";
import api from "../../../../common/api";
import AddBucket from "./AddBucket";
import DeleteBucket from "./DeleteBucket";
import PageHeader from "../../Common/PageHeader/PageHeader";
import BucketListItem from "./BucketListItem";
@@ -136,9 +134,6 @@ const styles = (theme: Theme) =>
interface IListBucketsProps {
classes: any;
history: any;
addBucketOpen: typeof addBucketOpen;
addBucketModalOpen: boolean;
addBucketReset: typeof addBucketReset;
setErrorSnackMessage: typeof setErrorSnackMessage;
session: ISessionResponse;
}
@@ -146,9 +141,6 @@ interface IListBucketsProps {
const ListBuckets = ({
classes,
history,
addBucketOpen,
addBucketModalOpen,
addBucketReset,
setErrorSnackMessage,
session,
}: IListBucketsProps) => {
@@ -219,16 +211,6 @@ const ListBuckets = ({
}
}, [loading, setErrorSnackMessage]);
const closeAddModalAndRefresh = (refresh: boolean) => {
addBucketOpen(false);
addBucketReset();
if (refresh) {
setLoading(true);
setSelectedBuckets([]);
}
};
const closeDeleteModalAndRefresh = (refresh: boolean) => {
setDeleteOpen(false);
if (refresh) {
@@ -283,12 +265,6 @@ const ListBuckets = ({
return (
<Fragment>
{addBucketModalOpen && (
<AddBucket
open={addBucketModalOpen}
closeModalAndRefresh={closeAddModalAndRefresh}
/>
)}
{deleteOpen && (
<DeleteBucket
deleteOpen={deleteOpen}
@@ -369,7 +345,7 @@ const ListBuckets = ({
color="primary"
endIcon={<AddIcon />}
onClick={() => {
addBucketOpen(true);
history.push("/add-bucket");
}}
className={classes.addBucket}
>
@@ -439,7 +415,7 @@ const ListBuckets = ({
To get started,&nbsp;
<AButton
onClick={() => {
addBucketOpen(true);
history.push("/add-bucket");
}}
>
Create a Bucket.
@@ -459,13 +435,10 @@ const ListBuckets = ({
};
const mapState = (state: AppState) => ({
addBucketModalOpen: state.buckets.open,
session: state.console.session,
});
const connector = connect(mapState, {
addBucketOpen,
addBucketReset,
setErrorSnackMessage,
});

View File

@@ -104,7 +104,6 @@ const styles = (theme: Theme) =>
},
divContainer: {
marginBottom: 20,
maxWidth: 840,
},
indicatorLabelOn: {
fontWeight: "bold",
@@ -227,31 +226,36 @@ const FormSwitchWrapper = ({
<div className={classes.divContainer}>
<Grid container alignItems={"center"}>
<Grid item xs>
{label !== "" && (
<InputLabel htmlFor={id} className={classes.inputLabel}>
<span>{label}</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<div>
<HelpIcon className={classes.tooltip} />
<Grid container>
<Grid item xs={12} sm={4} md={3}>
{label !== "" && (
<InputLabel htmlFor={id} className={classes.inputLabel}>
<span>{label}</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<div>
<HelpIcon className={classes.tooltip} />
</div>
</Tooltip>
</div>
</Tooltip>
</div>
)}
</InputLabel>
)}
</InputLabel>
)}
</Grid>
<Grid item xs={12} sm textAlign={"left"}>
{description !== "" && (
<Typography component="p" className={classes.fieldDescription}>
{description}
</Typography>
)}
</Grid>
</Grid>
</Grid>
<Grid item xs textAlign={"right"}>
<Grid item xs={12} sm={2} textAlign={"right"}>
{switchComponent}
</Grid>
{description !== "" && (
<Grid item xs={12}>
<Typography component="p" className={classes.fieldDescription}>
{description}
</Typography>
</Grid>
)}
</Grid>
</div>
);

View File

@@ -146,11 +146,8 @@ const InputBoxWrapper = ({
return (
<React.Fragment>
<Grid
item
xs={12}
className={`${classes.fieldContainer} ${
error !== "" ? classes.errorInField : ""
}`}
container
className={` ${error !== "" ? classes.errorInField : ""}`}
>
{label !== "" && (
<InputLabel

View File

@@ -184,6 +184,12 @@ export const containerForHeader = (bottomSpacing: any) => ({
topSpacer: {
height: "8px",
},
boxy: {
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 40,
backgroundColor: "#fff",
},
});
export const actionsTray = {

View File

@@ -239,6 +239,10 @@ const Console = ({
component: Metrics,
path: "/metrics",
},
{
component: Buckets,
path: "/add-bucket",
},
{
component: Buckets,
path: "/buckets",

View File

@@ -13,7 +13,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, { Fragment, useState, useEffect } from "react";
import React, { Fragment, useEffect, useState } from "react";
import {
ICloseEvent,
IMessageEvent,
@@ -68,12 +68,6 @@ const styles = (theme: Theme) =>
justifyContent: "flex-start",
gap: 20,
},
boxy: {
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 40,
backgroundColor: "#fff",
},
localMessage: {
fontSize: 24,
color: "#07193E",

View File

@@ -42,12 +42,6 @@ interface ISpeedtest {
const styles = (theme: Theme) =>
createStyles({
boxy: {
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 40,
backgroundColor: "#fff",
},
advancedConfiguration: {
color: "#2781B0",
fontSize: 10,

View File

@@ -5,6 +5,8 @@ import (
"runtime"
"strings"
"github.com/minio/minio-go/v7"
"github.com/go-openapi/swag"
"github.com/minio/console/models"
"github.com/minio/madmin-go"
@@ -171,6 +173,11 @@ func prepareError(err ...error) *models.Error {
errorCode = 403
errorMessage = err[0].Error()
}
// bucket already exists
if minio.ToErrorResponse(err[0]).Code == "BucketAlreadyOwnedByYou" {
errorCode = 400
errorMessage = "Bucket already exists"
}
}
return &models.Error{Code: errorCode, Message: swag.String(errorMessage), DetailedMessage: swag.String(err[0].Error())}
}