Add Bucket slice refactor to reduce re-renders (#2087)

* Add Bucket slice refactor to reduce re-renders
* Fix Button on object browser
* Update Logo

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2022-06-03 21:39:12 -07:00
committed by GitHub
parent 6e205fa8ae
commit 41e1b4a5d5
10 changed files with 380 additions and 365 deletions

File diff suppressed because one or more lines are too long

View File

@@ -27,7 +27,7 @@ const BucketDetails = React.lazy(() => import("./BucketDetails/BucketDetails"));
const BrowserHandler = React.lazy(
() => import("./BucketDetails/BrowserHandler")
);
const AddBucket = React.lazy(() => import("./ListBuckets/AddBucket"));
const AddBucket = React.lazy(() => import("./ListBuckets/AddBucket/AddBucket"));
const Buckets = () => {
return (

View File

@@ -1,5 +1,5 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
// Copyright (c) 2022 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
@@ -14,51 +14,43 @@
// 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, useEffect, useState } from "react";
import React, { Fragment } from "react";
import Grid from "@mui/material/Grid";
import { Button, LinearProgress } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { containerForHeader } from "../../Common/FormComponents/common/styleLibrary";
import api from "../../../../common/api";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import RadioGroupSelector from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
import { getBytes, k8sScalarUnitsExcluding } from "../../../../common/utils";
import { AppState } from "../../../../store";
import history from "../../../../history";
import { containerForHeader } from "../../../Common/FormComponents/common/styleLibrary";
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
import { k8sScalarUnitsExcluding } from "../../../../../common/utils";
import { AppState } from "../../../../../store";
import { useDispatch, useSelector } from "react-redux";
import { useDebounce } from "use-debounce";
import { MakeBucketRequest } from "../types";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import { ErrorResponseHandler } from "../../../../common/types";
import PageHeader from "../../Common/PageHeader/PageHeader";
import BackLink from "../../../../common/BackLink";
import { BucketsIcon, InfoIcon } from "../../../../icons";
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import PageHeader from "../../../Common/PageHeader/PageHeader";
import BackLink from "../../../../../common/BackLink";
import { BucketsIcon, InfoIcon } from "../../../../../icons";
import PageLayout from "../../Common/Layout/PageLayout";
import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
import FormLayout from "../../Common/FormLayout";
import HelpBox from "../../../../common/HelpBox";
import SectionTitle from "../../Common/SectionTitle";
import PageLayout from "../../../Common/Layout/PageLayout";
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
import FormLayout from "../../../Common/FormLayout";
import HelpBox from "../../../../../common/HelpBox";
import SectionTitle from "../../../Common/SectionTitle";
import { selDistSet, selSiteRep } from "../../../../../systemSlice";
import {
selDistSet,
selSiteRep,
setErrorSnackMessage,
} from "../../../../systemSlice";
import {
addBucketEnableObjectLocking,
addBucketName,
addBucketQuota,
addBucketQuotaSize,
addBucketQuotaType,
addBucketQuotaUnit,
addBucketRetention,
addBucketRetentionMode,
addBucketRetentionUnit,
addBucketRetentionValidity,
addBucketVersioning,
} from "../bucketsSlice";
resetForm,
setEnableObjectLocking,
setQuota,
setQuotaSize,
setQuotaUnit,
setRetention,
setRetentionMode,
setRetentionUnit,
setRetentionValidity,
setVersioning,
} from "./addBucketsSlice";
import { addBucketAsync } from "./addBucketThunks";
import AddBucketName from "./AddBucketName";
const styles = (theme: Theme) =>
createStyles({
@@ -105,172 +97,48 @@ const styles = (theme: Theme) =>
...containerForHeader(theme.spacing(4)),
});
interface IAddBucketProps {
interface IsetProps {
classes: any;
}
const AddBucket = ({ classes }: IAddBucketProps) => {
const AddBucket = ({ classes }: IsetProps) => {
const dispatch = useDispatch();
const bucketName = useSelector(
(state: AppState) => state.buckets.addBucketName
);
const versioningEnabled = useSelector(
(state: AppState) => state.buckets.addBucketVersioningEnabled
(state: AppState) => state.addBucket.versioningEnabled
);
const lockingEnabled = useSelector(
(state: AppState) => state.buckets.addBucketLockingEnabled
(state: AppState) => state.addBucket.lockingEnabled
);
const quotaEnabled = useSelector(
(state: AppState) => state.buckets.addBucketQuotaEnabled
);
const quotaType = useSelector(
(state: AppState) => state.buckets.addBucketQuotaType
);
const quotaSize = useSelector(
(state: AppState) => state.buckets.addBucketQuotaSize
);
const quotaUnit = useSelector(
(state: AppState) => state.buckets.addBucketQuotaUnit
(state: AppState) => state.addBucket.quotaEnabled
);
const quotaSize = useSelector((state: AppState) => state.addBucket.quotaSize);
const quotaUnit = useSelector((state: AppState) => state.addBucket.quotaUnit);
const retentionEnabled = useSelector(
(state: AppState) => state.buckets.addBucketRetentionEnabled
(state: AppState) => state.addBucket.retentionEnabled
);
const retentionMode = useSelector(
(state: AppState) => state.buckets.addBucketRetentionMode
(state: AppState) => state.addBucket.retentionMode
);
const retentionUnit = useSelector(
(state: AppState) => state.buckets.addBucketRetentionUnit
(state: AppState) => state.addBucket.retentionUnit
);
const retentionValidity = useSelector(
(state: AppState) => state.buckets.addBucketRetentionValidity
(state: AppState) => state.addBucket.retentionValidity
);
const addLoading = useSelector((state: AppState) => state.addBucket.loading);
const valid = useSelector((state: AppState) => state.addBucket.valid);
const lockingFieldDisabled = useSelector(
(state: AppState) => state.addBucket.lockingFieldDisabled
);
const distributedSetup = useSelector(selDistSet);
const siteReplicationInfo = useSelector(selSiteRep);
const [addLoading, setAddLoading] = useState<boolean>(false);
const [sendEnabled, setSendEnabled] = useState<boolean>(false);
const [lockingFieldDisabled, setLockingFieldDisabled] =
useState<boolean>(false);
const addRecord = (event: React.FormEvent) => {
event.preventDefault();
if (addLoading) {
return;
}
setAddLoading(true);
let request: MakeBucketRequest = {
name: bucketName,
versioning:
distributedSetup && !siteReplicationInfo.enabled
? versioningEnabled
: false,
locking: distributedSetup ? lockingEnabled : false,
};
if (distributedSetup) {
if (quotaEnabled) {
const amount = getBytes(quotaSize, quotaUnit, true);
request.quota = {
enabled: true,
quota_type: quotaType,
amount: parseInt(amount),
};
}
if (retentionEnabled) {
request.retention = {
mode: retentionMode,
unit: retentionUnit,
validity: retentionValidity,
};
}
}
api
.invoke("POST", "/api/v1/buckets", request)
.then((res) => {
setAddLoading(false);
const newBucketName = `${bucketName}`;
resetForm();
history.push(`/buckets/${newBucketName}/browse`);
})
.catch((err: ErrorResponseHandler) => {
setAddLoading(false);
dispatch(setErrorSnackMessage(err));
});
const resForm = () => {
dispatch(resetForm());
};
const [value] = useDebounce(bucketName, 1000);
useEffect(() => {
dispatch(addBucketName(value));
}, [value, dispatch]);
const resetForm = () => {
dispatch(addBucketName(""));
dispatch(addBucketVersioning(false));
dispatch(addBucketEnableObjectLocking(false));
dispatch(addBucketQuota(false));
dispatch(addBucketQuotaType("hard"));
dispatch(addBucketQuotaSize("1"));
dispatch(addBucketQuotaUnit("Ti"));
dispatch(addBucketRetention(false));
dispatch(addBucketRetentionMode("compliance"));
dispatch(addBucketRetentionUnit("days"));
dispatch(addBucketRetentionValidity(180));
};
useEffect(() => {
let valid = false;
if (bucketName.trim() !== "") {
valid = true;
}
if (quotaEnabled && valid) {
if (quotaSize.trim() === "" || parseInt(quotaSize) === 0) {
valid = false;
}
}
if (!versioningEnabled || !retentionEnabled) {
dispatch(addBucketRetention(false));
dispatch(addBucketRetentionMode("compliance"));
dispatch(addBucketRetentionUnit("days"));
dispatch(addBucketRetentionValidity(180));
}
if (retentionEnabled) {
// if retention is enabled, then objec locking should be enabled as well
dispatch(addBucketEnableObjectLocking(true));
setLockingFieldDisabled(true);
} else {
setLockingFieldDisabled(false);
}
if (
retentionEnabled &&
(Number.isNaN(retentionValidity) || retentionValidity < 1)
) {
valid = false;
}
setSendEnabled(valid);
}, [
bucketName,
retentionEnabled,
lockingEnabled,
quotaType,
quotaSize,
quotaUnit,
quotaEnabled,
dispatch,
retentionValidity,
versioningEnabled,
]);
return (
<Fragment>
<PageHeader label={<BackLink to={"/buckets"} label={"Buckets"} />} />
@@ -312,21 +180,13 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
addRecord(e);
e.preventDefault();
dispatch(addBucketAsync());
}}
>
<Grid container marginTop={1} spacing={2}>
<Grid item xs={12}>
<InputBoxWrapper
id="bucket-name"
name="bucket-name"
autoFocus={true}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketName(event.target.value));
}}
label="Bucket Name"
value={bucketName}
/>
<AddBucketName />
</Grid>
<Grid item xs={12}>
<SectionTitle>Features</SectionTitle>
@@ -368,7 +228,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
name="versioned"
checked={versioningEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketVersioning(event.target.checked));
dispatch(setVersioning(event.target.checked));
}}
label={"Versioning"}
disabled={
@@ -386,11 +246,9 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
disabled={lockingFieldDisabled || !distributedSetup}
checked={lockingEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(
addBucketEnableObjectLocking(event.target.checked)
);
dispatch(setEnableObjectLocking(event.target.checked));
if (event.target.checked && !siteReplicationInfo.enabled) {
dispatch(addBucketVersioning(true));
dispatch(setVersioning(true));
}
}}
label={"Object Locking"}
@@ -404,7 +262,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
name="bucket_quota"
checked={quotaEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketQuota(event.target.checked));
dispatch(setQuota(event.target.checked));
}}
label={"Quota"}
disabled={!distributedSetup}
@@ -419,7 +277,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
name="quota_size"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.validity.valid) {
dispatch(addBucketQuotaSize(e.target.value));
dispatch(setQuotaSize(e.target.value));
}
}}
label="Capacity"
@@ -431,7 +289,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
<InputUnitMenu
id={"quota_unit"}
onUnitChange={(newValue) => {
dispatch(addBucketQuotaUnit(newValue));
dispatch(setQuotaUnit(newValue));
}}
unitSelected={quotaUnit}
unitsList={k8sScalarUnitsExcluding(["Ki"])}
@@ -450,7 +308,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
name="bucket_retention"
checked={retentionEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketRetention(event.target.checked));
dispatch(setRetention(event.target.checked));
}}
label={"Retention"}
/>
@@ -465,9 +323,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
name="retention_mode"
label="Mode"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
dispatch(
addBucketRetentionMode(e.target.value as string)
);
dispatch(setRetentionMode(e.target.value as string));
}}
selectorOptions={[
{ value: "compliance", label: "Compliance" },
@@ -481,9 +337,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
id="retention_validity"
name="retention_validity"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
dispatch(
addBucketRetentionValidity(e.target.valueAsNumber)
);
dispatch(setRetentionValidity(e.target.valueAsNumber));
}}
label="Validity"
value={String(retentionValidity)}
@@ -492,7 +346,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
<InputUnitMenu
id={"retention_unit"}
onUnitChange={(newValue) => {
dispatch(addBucketRetentionUnit(newValue));
dispatch(setRetentionUnit(newValue));
}}
unitSelected={retentionUnit}
unitsList={[
@@ -512,7 +366,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
type="button"
variant={"outlined"}
className={classes.clearButton}
onClick={resetForm}
onClick={resForm}
>
Clear
</Button>
@@ -520,7 +374,7 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !sendEnabled}
disabled={addLoading || valid}
>
Create Bucket
</Button>

View File

@@ -0,0 +1,41 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 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 { setName } from "./addBucketsSlice";
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import { useDispatch, useSelector } from "react-redux";
import { AppState } from "../../../../../store";
const AddBucketName = () => {
const dispatch = useDispatch();
const bucketName = useSelector((state: AppState) => state.addBucket.name);
return (
<InputBoxWrapper
id="bucket-name"
name="bucket-name"
autoFocus={true}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(setName(event.target.value));
}}
label="Bucket Name"
value={bucketName}
/>
);
};
export default AddBucketName;

View File

@@ -0,0 +1,85 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 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 { MakeBucketRequest } from "../../types";
import { getBytes } from "../../../../../common/utils";
import api from "../../../../../common/api";
import history from "../../../../../history";
import { ErrorResponseHandler } from "../../../../../common/types";
import { setErrorSnackMessage } from "../../../../../systemSlice";
import { createAsyncThunk } from "@reduxjs/toolkit";
import { AppState } from "../../../../../store";
import { resetForm } from "./addBucketsSlice";
export const addBucketAsync = createAsyncThunk(
"buckets/addBucketAsync",
async (_, { getState, rejectWithValue, dispatch }) => {
const state = getState() as AppState;
const bucketName = state.addBucket.name;
const versioningEnabled = state.addBucket.versioningEnabled;
const lockingEnabled = state.addBucket.lockingEnabled;
const quotaEnabled = state.addBucket.quotaEnabled;
const quotaSize = state.addBucket.quotaSize;
const quotaUnit = state.addBucket.quotaUnit;
const retentionEnabled = state.addBucket.retentionEnabled;
const retentionMode = state.addBucket.retentionMode;
const retentionUnit = state.addBucket.retentionUnit;
const retentionValidity = state.addBucket.retentionValidity;
const distributedSetup = state.system.distributedSetup;
const siteReplicationInfo = state.system.siteReplicationInfo;
let request: MakeBucketRequest = {
name: bucketName,
versioning:
distributedSetup && !siteReplicationInfo.enabled
? versioningEnabled
: false,
locking: distributedSetup ? lockingEnabled : false,
};
if (distributedSetup) {
if (quotaEnabled) {
const amount = getBytes(quotaSize, quotaUnit, true);
request.quota = {
enabled: true,
quota_type: "hard",
amount: parseInt(amount),
};
}
if (retentionEnabled) {
request.retention = {
mode: retentionMode,
unit: retentionUnit,
validity: retentionValidity,
};
}
}
return api
.invoke("POST", "/api/v1/buckets", request)
.then((res) => {
const newBucketName = `${bucketName}`;
dispatch(resetForm());
history.push(`/buckets/${newBucketName}/browse`);
})
.catch((err: ErrorResponseHandler) => {
dispatch(setErrorSnackMessage(err));
return rejectWithValue(err);
});
}
);

View File

@@ -0,0 +1,159 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 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 { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { addBucketAsync } from "./addBucketThunks";
export interface AddBucketState {
loading: boolean;
valid: boolean;
name: string;
versioningEnabled: boolean;
lockingEnabled: boolean;
lockingFieldDisabled: boolean;
quotaEnabled: boolean;
quotaSize: string;
quotaUnit: string;
retentionEnabled: boolean;
retentionMode: string;
retentionUnit: string;
retentionValidity: number;
}
const initialState: AddBucketState = {
loading: false,
valid: false,
name: "",
versioningEnabled: false,
lockingEnabled: false,
lockingFieldDisabled: false,
quotaEnabled: false,
quotaSize: "1",
quotaUnit: "Ti",
retentionEnabled: false,
retentionMode: "compliance",
retentionUnit: "days",
retentionValidity: 180,
};
export const addBucketsSlice = createSlice({
name: "addBuckets",
initialState,
reducers: {
setName: (state, action: PayloadAction<string>) => {
state.name = action.payload;
if (state.name.trim() === "") {
state.valid = false;
}
},
setVersioning: (state, action: PayloadAction<boolean>) => {
state.versioningEnabled = action.payload;
if (!state.versioningEnabled || !state.retentionEnabled) {
state.retentionEnabled = false;
state.retentionMode = "compliance";
state.retentionUnit = "days";
state.retentionValidity = 180;
}
},
setEnableObjectLocking: (state, action: PayloadAction<boolean>) => {
state.lockingEnabled = action.payload;
},
setQuota: (state, action: PayloadAction<boolean>) => {
state.quotaEnabled = action.payload;
},
setQuotaSize: (state, action: PayloadAction<string>) => {
state.quotaSize = action.payload;
if (state.quotaEnabled && state.valid) {
if (state.quotaSize.trim() === "" || parseInt(state.quotaSize) === 0) {
state.valid = false;
}
}
},
setQuotaUnit: (state, action: PayloadAction<string>) => {
state.quotaUnit = action.payload;
},
setRetention: (state, action: PayloadAction<boolean>) => {
state.retentionEnabled = action.payload;
if (!state.versioningEnabled || !state.retentionEnabled) {
state.retentionEnabled = false;
state.retentionMode = "compliance";
state.retentionUnit = "days";
state.retentionValidity = 180;
}
if (state.retentionEnabled) {
// if retention is enabled, then object locking should be enabled as well
state.lockingEnabled = true;
state.lockingFieldDisabled = true;
} else {
state.lockingFieldDisabled = false;
}
if (
state.retentionEnabled &&
(Number.isNaN(state.retentionValidity) || state.retentionValidity < 1)
) {
state.valid = false;
}
},
setRetentionMode: (state, action: PayloadAction<string>) => {
state.retentionMode = action.payload;
},
setRetentionUnit: (state, action: PayloadAction<string>) => {
state.retentionUnit = action.payload;
},
setRetentionValidity: (state, action: PayloadAction<number>) => {
state.retentionValidity = action.payload;
if (
state.retentionEnabled &&
(Number.isNaN(state.retentionValidity) || state.retentionValidity < 1)
) {
state.valid = false;
}
},
resetForm: (state) => initialState,
},
extraReducers: (builder) => {
builder
.addCase(addBucketAsync.pending, (state) => {
state.loading = true;
})
.addCase(addBucketAsync.rejected, (state) => {
state.loading = false;
})
.addCase(addBucketAsync.fulfilled, (state, action) => {
state.loading = false;
});
},
});
export const {
setName,
setVersioning,
setEnableObjectLocking,
setQuota,
setQuotaSize,
setQuotaUnit,
resetForm,
setRetention,
setRetentionMode,
setRetentionUnit,
setRetentionValidity,
} = addBucketsSlice.actions;
export default addBucketsSlice.reducer;

View File

@@ -1,122 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 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 { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface BucketsState {
open: boolean;
addBucketName: string;
addBucketVersioningEnabled: boolean;
addBucketLockingEnabled: boolean;
addBucketQuotaEnabled: boolean;
addBucketQuotaType: string;
addBucketQuotaSize: string;
addBucketQuotaUnit: string;
addBucketRetentionEnabled: boolean;
addBucketRetentionMode: string;
addBucketRetentionUnit: string;
addBucketRetentionValidity: number;
}
const initialState: BucketsState = {
open: false,
addBucketName: "",
addBucketVersioningEnabled: false,
addBucketLockingEnabled: false,
addBucketQuotaEnabled: false,
addBucketQuotaType: "hard",
addBucketQuotaSize: "1",
addBucketQuotaUnit: "Ti",
addBucketRetentionEnabled: false,
addBucketRetentionMode: "compliance",
addBucketRetentionUnit: "days",
addBucketRetentionValidity: 180,
};
export const bucketsSlice = createSlice({
name: "buckets",
initialState,
reducers: {
addBucketOpen: (state, action: PayloadAction<boolean>) => {
state.open = action.payload;
},
addBucketName: (state, action: PayloadAction<string>) => {
state.addBucketName = action.payload;
},
addBucketVersioning: (state, action: PayloadAction<boolean>) => {
state.addBucketVersioningEnabled = action.payload;
},
addBucketEnableObjectLocking: (state, action: PayloadAction<boolean>) => {
state.addBucketLockingEnabled = action.payload;
},
addBucketQuota: (state, action: PayloadAction<boolean>) => {
state.addBucketQuotaEnabled = action.payload;
},
addBucketQuotaType: (state, action: PayloadAction<string>) => {
state.addBucketQuotaType = action.payload;
},
addBucketQuotaSize: (state, action: PayloadAction<string>) => {
state.addBucketQuotaSize = action.payload;
},
addBucketQuotaUnit: (state, action: PayloadAction<string>) => {
state.addBucketQuotaUnit = action.payload;
},
addBucketRetention: (state, action: PayloadAction<boolean>) => {
state.addBucketRetentionEnabled = action.payload;
},
addBucketRetentionMode: (state, action: PayloadAction<string>) => {
state.addBucketRetentionMode = action.payload;
},
addBucketRetentionUnit: (state, action: PayloadAction<string>) => {
state.addBucketRetentionUnit = action.payload;
},
addBucketRetentionValidity: (state, action: PayloadAction<number>) => {
state.addBucketRetentionValidity = action.payload;
},
addBucketReset: (state) => {
state.addBucketName = "";
state.addBucketVersioningEnabled = false;
state.addBucketLockingEnabled = false;
state.addBucketQuotaEnabled = false;
state.addBucketQuotaType = "hard";
state.addBucketQuotaSize = "1";
state.addBucketQuotaUnit = "Ti";
state.addBucketRetentionEnabled = false;
state.addBucketRetentionMode = "compliance";
state.addBucketRetentionUnit = "days";
state.addBucketRetentionValidity = 180;
},
},
});
export const {
addBucketOpen,
addBucketName,
addBucketVersioning,
addBucketEnableObjectLocking,
addBucketQuota,
addBucketQuotaType,
addBucketQuotaSize,
addBucketQuotaUnit,
addBucketReset,
addBucketRetention,
addBucketRetentionMode,
addBucketRetentionUnit,
addBucketRetentionValidity,
} = bucketsSlice.actions;
export default bucketsSlice.reducer;

View File

@@ -36,7 +36,7 @@ const LicensedConsoleLogo = ({
} else if (plan === "ENTERPRISE") {
licenseLogo = <ConsoleEnterprise />;
} else {
licenseLogo = <ConsoleAgpl />;
licenseLogo = <ConsoleAgpl style={{ width: 170 }} />;
}
return licenseLogo;

View File

@@ -34,6 +34,7 @@ import withSuspense from "../Common/Components/withSuspense";
import { setSnackBarMessage } from "../../../systemSlice";
import { AppState } from "../../../store";
import { setVersionsModeEnabled } from "./objectBrowserSlice";
import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton";
const CreatePathModal = withSuspense(
React.lazy(
@@ -191,9 +192,9 @@ const BrowserBreadcrumbs = ({
{listBreadcrumbs}
</div>
<CopyToClipboard text={`${bucketName}/${splitPaths.join("/")}`}>
<Button
<RBIconButton
id={"copy-path"}
startIcon={<CopyIcon />}
icon={<CopyIcon />}
disableTouchRipple
disableRipple
focusRipple={false}
@@ -206,17 +207,15 @@ const BrowserBreadcrumbs = ({
padding: "0",
color: "#969FA8",
border: "#969FA8 1px solid",
width: "20px",
height: "20px",
minHeight: "20px",
minWidth: "28px",
"&.MuiButton-root": {
width: "28px",
height: "28px",
"& .MuiButton-root": {
height: "28px",
},
"& .min-icon": {
width: "12px",
height: "12px",
marginLeft: "12px",
},
}}
/>

View File

@@ -20,7 +20,7 @@ import logReducer from "./screens/Console/Logs/logsSlice";
import healthInfoReducer from "./screens/Console/HealthInfo/healthInfoSlice";
import watchReducer from "./screens/Console/Watch/watchSlice";
import consoleReducer from "./screens/Console/consoleSlice";
import bucketsReducer from "./screens/Console/Buckets/bucketsSlice";
import bucketsReducer from "./screens/Console/Buckets/ListBuckets/AddBucket/addBucketsSlice";
import bucketDetailsReducer from "./screens/Console/Buckets/BucketDetails/bucketDetailsSlice";
import objectBrowserReducer from "./screens/Console/ObjectBrowser/objectBrowserSlice";
import tenantsReducer from "./screens/Console/Tenants/tenantsSlice";
@@ -36,7 +36,7 @@ const rootReducer = combineReducers({
logs: logReducer,
watch: watchReducer,
console: consoleReducer,
buckets: bucketsReducer,
addBucket: bucketsReducer,
bucketDetails: bucketDetailsReducer,
objectBrowser: objectBrowserReducer,
healthInfo: healthInfoReducer,