Added quota metric to buckets list & objects list (#1595)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net> Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
//
|
||||
// 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 React, {Fragment} from "react";
|
||||
import get from "lodash/get";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
@@ -26,7 +27,7 @@ import {
|
||||
} from "../../../../icons";
|
||||
import { Bucket } from "../types";
|
||||
import { Box, Grid, Typography } from "@mui/material";
|
||||
import { niceBytes, prettyNumber } from "../../../../common/utils";
|
||||
import {calculateBytes, niceBytes, prettyNumber} from "../../../../common/utils";
|
||||
import CheckboxWrapper from "../../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
|
||||
import { Link } from "react-router-dom";
|
||||
import {
|
||||
@@ -163,7 +164,6 @@ const styles = (theme: Theme) =>
|
||||
interface IBucketListItem {
|
||||
bucket: Bucket;
|
||||
classes: any;
|
||||
onDelete: (bucketName: string) => void;
|
||||
onSelect: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
selected: boolean;
|
||||
bulkSelect: boolean;
|
||||
@@ -172,7 +172,6 @@ interface IBucketListItem {
|
||||
const BucketListItem = ({
|
||||
classes,
|
||||
bucket,
|
||||
onDelete,
|
||||
onSelect,
|
||||
selected,
|
||||
bulkSelect,
|
||||
@@ -181,6 +180,10 @@ const BucketListItem = ({
|
||||
const usageScalar = usage.split(" ")[0];
|
||||
const usageUnit = usage.split(" ")[1];
|
||||
|
||||
const quota = get(bucket, "details.quota.quota", "0");
|
||||
const quotaForString = calculateBytes(quota);
|
||||
|
||||
|
||||
const accessToStr = (bucket: Bucket): string => {
|
||||
if (bucket.rw_access?.read && !bucket.rw_access?.write) {
|
||||
return "R";
|
||||
@@ -287,6 +290,11 @@ const BucketListItem = ({
|
||||
<div className={classes.metricText}>
|
||||
{usageScalar}
|
||||
<span className={classes.unit}>{usageUnit}</span>
|
||||
{quota !== "0" && (
|
||||
<Fragment>
|
||||
{" "}/{" "}{quotaForString.total}<span className={classes.unit}>{quotaForString.unit}</span>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item textAlign={"left"} className={classes.metric}>
|
||||
|
||||
@@ -23,7 +23,6 @@ import { LinearProgress } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Bucket, BucketList } from "../types";
|
||||
import { AddIcon, BucketsIcon, LifecycleConfigIcon } from "../../../../icons";
|
||||
import { AppState } from "../../../../store";
|
||||
import { setErrorSnackMessage } from "../../../../actions";
|
||||
import {
|
||||
containerForHeader,
|
||||
@@ -31,12 +30,10 @@ import {
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import api from "../../../../common/api";
|
||||
import DeleteBucket from "./DeleteBucket";
|
||||
import PageHeader from "../../Common/PageHeader/PageHeader";
|
||||
import BucketListItem from "./BucketListItem";
|
||||
import BulkReplicationModal from "./BulkReplicationModal";
|
||||
import HelpBox from "../../../../common/HelpBox";
|
||||
import { ISessionResponse } from "../../types";
|
||||
import RefreshIcon from "../../../../icons/RefreshIcon";
|
||||
import AButton from "../../Common/AButton/AButton";
|
||||
import MultipleBucketsIcon from "../../../../icons/MultipleBucketsIcon";
|
||||
@@ -85,19 +82,15 @@ interface IListBucketsProps {
|
||||
classes: any;
|
||||
history: any;
|
||||
setErrorSnackMessage: typeof setErrorSnackMessage;
|
||||
session: ISessionResponse;
|
||||
}
|
||||
|
||||
const ListBuckets = ({
|
||||
classes,
|
||||
history,
|
||||
setErrorSnackMessage,
|
||||
session,
|
||||
}: IListBucketsProps) => {
|
||||
const [records, setRecords] = useState<Bucket[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
||||
const [selectedBucket, setSelectedBucket] = useState<string>("");
|
||||
const [filterBuckets, setFilterBuckets] = useState<string>("");
|
||||
const [selectedBuckets, setSelectedBuckets] = useState<string[]>([]);
|
||||
const [replicationModalOpen, setReplicationModalOpen] =
|
||||
@@ -125,28 +118,11 @@ const ListBuckets = ({
|
||||
}
|
||||
}, [loading, setErrorSnackMessage]);
|
||||
|
||||
const closeDeleteModalAndRefresh = (refresh: boolean) => {
|
||||
setDeleteOpen(false);
|
||||
if (refresh) {
|
||||
setLoading(true);
|
||||
setSelectedBuckets([]);
|
||||
}
|
||||
};
|
||||
|
||||
const confirmDeleteBucket = (bucket: string) => {
|
||||
setDeleteOpen(true);
|
||||
setSelectedBucket(bucket);
|
||||
};
|
||||
|
||||
const filteredRecords = records.filter((b: Bucket) => {
|
||||
if (filterBuckets === "") {
|
||||
return true;
|
||||
} else {
|
||||
if (b.name.indexOf(filterBuckets) >= 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return b.name.indexOf(filterBuckets) >= 0;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -191,7 +167,6 @@ const ListBuckets = ({
|
||||
return (
|
||||
<BucketListItem
|
||||
bucket={bucket}
|
||||
onDelete={confirmDeleteBucket}
|
||||
onSelect={selectListBuckets}
|
||||
selected={selectedBuckets.includes(bucket.name)}
|
||||
bulkSelect={bulkSelect}
|
||||
@@ -205,15 +180,6 @@ const ListBuckets = ({
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{deleteOpen && (
|
||||
<DeleteBucket
|
||||
deleteOpen={deleteOpen}
|
||||
selectedBucket={selectedBucket}
|
||||
closeDeleteModalAndRefresh={(refresh: boolean) => {
|
||||
closeDeleteModalAndRefresh(refresh);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{replicationModalOpen && (
|
||||
<BulkReplicationModal
|
||||
open={replicationModalOpen}
|
||||
@@ -378,11 +344,7 @@ const ListBuckets = ({
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
session: state.console.session,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
const connector = connect(null, {
|
||||
setErrorSnackMessage,
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import React, {
|
||||
} from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
@@ -74,7 +73,7 @@ import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../../../actions";
|
||||
import { BucketInfo, BucketVersioning } from "../../../types";
|
||||
import { BucketInfo, BucketQuota, BucketVersioning } from "../../../types";
|
||||
import { ErrorResponseHandler } from "../../../../../../common/types";
|
||||
|
||||
import ScreenTitle from "../../../../Common/ScreenTitle/ScreenTitle";
|
||||
@@ -292,6 +291,7 @@ const ListObjects = ({
|
||||
const [selectedInternalPaths, setSelectedInternalPaths] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [quota, setQuota] = useState<BucketQuota | null>(null);
|
||||
|
||||
const internalPaths = get(match.params, "subpaths", "");
|
||||
const bucketName = match.params["bucketName"];
|
||||
@@ -327,6 +327,25 @@ const ListObjects = ({
|
||||
}
|
||||
}, [selectedObjects]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!quota) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets/${bucketName}/quota`)
|
||||
.then((res: BucketQuota) => {
|
||||
let quotaVals = null;
|
||||
|
||||
if (res.quota) {
|
||||
quotaVals = res;
|
||||
}
|
||||
|
||||
setQuota(quotaVals);
|
||||
})
|
||||
.catch(() => {
|
||||
setQuota(null);
|
||||
});
|
||||
}
|
||||
}, [quota, bucketName]);
|
||||
|
||||
const displayDeleteObject = hasPermission(bucketName, [
|
||||
IAM_SCOPES.S3_DELETE_OBJECT,
|
||||
]);
|
||||
@@ -1176,7 +1195,10 @@ const ListObjects = ({
|
||||
{bucketInfo.size && (
|
||||
<Fragment>{niceBytesInt(bucketInfo.size)}</Fragment>
|
||||
)}
|
||||
{bucketInfo.size && bucketInfo.objects ? " / " : ""}
|
||||
{bucketInfo.size && quota && (
|
||||
<Fragment> / {niceBytesInt(quota.quota)}</Fragment>
|
||||
)}
|
||||
{bucketInfo.size && bucketInfo.objects ? " - " : ""}
|
||||
{bucketInfo.objects && (
|
||||
<Fragment>
|
||||
{bucketInfo.objects} Object
|
||||
|
||||
Reference in New Issue
Block a user