Files
openmaxio-object-browser/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketLifecyclePanel.tsx
Daryl White bebe860903 Updating documentation links to new URLs (#2325)
The new doc site has launched, and all docs have new URLs.
This PR updates the documentation URLs in the Console to point to the
new locations.
2022-09-22 22:37:32 -07:00

351 lines
11 KiB
TypeScript

// This file is part of MinIO Console Server
// Copyright (c) 2021 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, { Fragment, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import get from "lodash/get";
import Grid from "@mui/material/Grid";
import { LifeCycleItem } from "../types";
import { AddIcon, TiersIcon } from "../../../../icons";
import {
actionsTray,
searchField,
} from "../../Common/FormComponents/common/styleLibrary";
import { ErrorResponseHandler } from "../../../../common/types";
import api from "../../../../common/api";
import EditLifecycleConfiguration from "./EditLifecycleConfiguration";
import AddLifecycleModal from "./AddLifecycleModal";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import HelpBox from "../../../../common/HelpBox";
import PanelTitle from "../../Common/PanelTitle/PanelTitle";
import {
hasPermission,
SecureComponent,
} from "../../../../common/SecureComponent";
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
import DeleteBucketLifecycleRule from "./DeleteBucketLifecycleRule";
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
import { useParams } from "react-router-dom";
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
import { Button } from "mds";
const styles = (theme: Theme) =>
createStyles({
...searchField,
...actionsTray,
twHeight: {
minHeight: 400,
},
});
interface IBucketLifecyclePanelProps {
classes: any;
}
const BucketLifecyclePanel = ({ classes }: IBucketLifecyclePanelProps) => {
const loadingBucket = useSelector(selBucketDetailsLoading);
const params = useParams();
const [loadingLifecycle, setLoadingLifecycle] = useState<boolean>(true);
const [lifecycleRecords, setLifecycleRecords] = useState<LifeCycleItem[]>([]);
const [addLifecycleOpen, setAddLifecycleOpen] = useState<boolean>(false);
const [editLifecycleOpen, setEditLifecycleOpen] = useState<boolean>(false);
const [selectedLifecycleRule, setSelectedLifecycleRule] =
useState<LifeCycleItem | null>(null);
const [deleteLifecycleOpen, setDeleteLifecycleOpen] =
useState<boolean>(false);
const [selectedID, setSelectedID] = useState<string | null>(null);
const bucketName = params.bucketName || "";
const displayLifeCycleRules = hasPermission(bucketName, [
IAM_SCOPES.S3_GET_LIFECYCLE_CONFIGURATION,
]);
useEffect(() => {
if (loadingBucket) {
setLoadingLifecycle(true);
}
}, [loadingBucket, setLoadingLifecycle]);
useEffect(() => {
if (loadingLifecycle) {
if (displayLifeCycleRules) {
api
.invoke("GET", `/api/v1/buckets/${bucketName}/lifecycle`)
.then((res: any) => {
const records = get(res, "lifecycle", []);
setLifecycleRecords(records || []);
setLoadingLifecycle(false);
})
.catch((err: ErrorResponseHandler) => {
console.error(err);
setLifecycleRecords([]);
setLoadingLifecycle(false);
});
} else {
setLoadingLifecycle(false);
}
}
}, [
loadingLifecycle,
setLoadingLifecycle,
bucketName,
displayLifeCycleRules,
]);
const closeEditLCAndRefresh = (refresh: boolean) => {
setEditLifecycleOpen(false);
setSelectedLifecycleRule(null);
if (refresh) {
setLoadingLifecycle(true);
}
};
const closeAddLCAndRefresh = (refresh: boolean) => {
setAddLifecycleOpen(false);
if (refresh) {
setLoadingLifecycle(true);
}
};
const closeDelLCRefresh = (refresh: boolean) => {
setDeleteLifecycleOpen(false);
setSelectedID(null);
if (refresh) {
setLoadingLifecycle(true);
}
};
const renderStorageClass = (objectST: any) => {
let stClass = get(objectST, "transition.storage_class", "");
stClass = get(objectST, "transition.noncurrent_storage_class", stClass);
return stClass;
};
const lifecycleColumns = [
{
label: "Type",
renderFullObject: true,
renderFunction: (el: LifeCycleItem) => {
if (!el) {
return <Fragment />;
}
if (
el.expiration &&
(el.expiration.days > 0 || el.expiration.noncurrent_expiration_days)
) {
return <span>Expiry</span>;
}
if (
el.transition &&
(el.transition.days > 0 || el.transition.noncurrent_transition_days)
) {
return <span>Transition</span>;
}
return <Fragment />;
},
},
{
label: "Version",
renderFullObject: true,
renderFunction: (el: LifeCycleItem) => {
if (!el) {
return <Fragment />;
}
if (el.expiration) {
if (el.expiration.days > 0) {
return <span>Current</span>;
} else if (el.expiration.noncurrent_expiration_days) {
return <span>Non-Current</span>;
}
}
if (el.transition) {
if (el.transition.days > 0) {
return <span>Current</span>;
} else if (el.transition.noncurrent_transition_days) {
return <span>Non-Current</span>;
}
}
},
},
{
label: "Tier",
elementKey: "storage_class",
renderFunction: renderStorageClass,
renderFullObject: true,
},
{
label: "Prefix",
elementKey: "prefix",
},
{
label: "After",
renderFullObject: true,
renderFunction: (el: LifeCycleItem) => {
if (!el) {
return <Fragment />;
}
if (el.expiration) {
if (el.expiration.days > 0) {
return <span>{el.expiration.days} days</span>;
} else if (el.expiration.noncurrent_expiration_days) {
return <span>{el.expiration.noncurrent_expiration_days} days</span>;
}
}
if (el.transition) {
if (el.transition.days > 0) {
return <span>{el.transition.days} days</span>;
} else if (el.transition.noncurrent_transition_days) {
return <span>{el.transition.noncurrent_transition_days} days</span>;
}
}
},
},
{
label: "Status",
elementKey: "status",
},
];
const lifecycleActions = [
{
type: "view",
onClick(valueToSend: any): any {
setSelectedLifecycleRule(valueToSend);
setEditLifecycleOpen(true);
},
},
{
type: "delete",
onClick(valueToDelete: string): any {
setSelectedID(valueToDelete);
setDeleteLifecycleOpen(true);
},
sendOnlyId: true,
},
];
return (
<Fragment>
{editLifecycleOpen && selectedLifecycleRule && (
<EditLifecycleConfiguration
open={editLifecycleOpen}
closeModalAndRefresh={closeEditLCAndRefresh}
selectedBucket={bucketName}
lifecycleRule={selectedLifecycleRule}
/>
)}
{addLifecycleOpen && (
<AddLifecycleModal
open={addLifecycleOpen}
bucketName={bucketName}
closeModalAndRefresh={closeAddLCAndRefresh}
/>
)}
{deleteLifecycleOpen && selectedID && (
<DeleteBucketLifecycleRule
id={selectedID}
bucket={bucketName}
deleteOpen={deleteLifecycleOpen}
onCloseAndRefresh={closeDelLCRefresh}
/>
)}
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<PanelTitle>Lifecycle Rules</PanelTitle>
<SecureComponent
scopes={[
IAM_SCOPES.S3_PUT_LIFECYCLE_CONFIGURATION,
IAM_SCOPES.ADMIN_LIST_TIERS,
]}
resource={bucketName}
matchAll
errorProps={{ disabled: true }}
>
<TooltipWrapper tooltip={"Add Lifecycle Rule"}>
<Button
id={"add-bucket-lifecycle-rule"}
onClick={() => {
setAddLifecycleOpen(true);
}}
label={"Add Lifecycle Rule"}
icon={<AddIcon />}
variant={"callAction"}
/>
</TooltipWrapper>
</SecureComponent>
</Grid>
<Grid item xs={12}>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_LIFECYCLE_CONFIGURATION]}
resource={bucketName}
errorProps={{ disabled: true }}
>
<TableWrapper
itemActions={lifecycleActions}
columns={lifecycleColumns}
isLoading={loadingLifecycle}
records={lifecycleRecords}
entityName="Lifecycle"
customEmptyMessage="There are no Lifecycle rules yet"
idField="id"
customPaperHeight={classes.twHeight}
/>
</SecureComponent>
</Grid>
{!loadingLifecycle && (
<Grid item xs={12}>
<br />
<HelpBox
title={"Lifecycle Rules"}
iconComponent={<TiersIcon />}
help={
<Fragment>
MinIO Object Lifecycle Management allows creating rules for
time or date based automatic transition or expiry of objects.
For object transition, MinIO automatically moves the object to
a configured remote storage tier.
<br />
<br />
You can learn more at our{" "}
<a
href="https://min.io/docs/minio/linux/administration/object-management/object-lifecycle-management.html?ref=con"
target="_blank"
rel="noreferrer"
>
documentation
</a>
.
</Fragment>
}
/>
</Grid>
)}
</Grid>
</Fragment>
);
};
export default withStyles(styles)(BucketLifecyclePanel);