// 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 .
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(true);
const [lifecycleRecords, setLifecycleRecords] = useState([]);
const [addLifecycleOpen, setAddLifecycleOpen] = useState(false);
const [editLifecycleOpen, setEditLifecycleOpen] = useState(false);
const [selectedLifecycleRule, setSelectedLifecycleRule] =
useState(null);
const [deleteLifecycleOpen, setDeleteLifecycleOpen] =
useState(false);
const [selectedID, setSelectedID] = useState(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 ;
}
if (
el.expiration &&
(el.expiration.days > 0 || el.expiration.noncurrent_expiration_days)
) {
return Expiry;
}
if (
el.transition &&
(el.transition.days > 0 || el.transition.noncurrent_transition_days)
) {
return Transition;
}
return ;
},
},
{
label: "Version",
renderFullObject: true,
renderFunction: (el: LifeCycleItem) => {
if (!el) {
return ;
}
if (el.expiration) {
if (el.expiration.days > 0) {
return Current;
} else if (el.expiration.noncurrent_expiration_days) {
return Non-Current;
}
}
if (el.transition) {
if (el.transition.days > 0) {
return Current;
} else if (el.transition.noncurrent_transition_days) {
return Non-Current;
}
}
},
},
{
label: "Tier",
elementKey: "storage_class",
renderFunction: renderStorageClass,
renderFullObject: true,
},
{
label: "Prefix",
elementKey: "prefix",
},
{
label: "After",
renderFullObject: true,
renderFunction: (el: LifeCycleItem) => {
if (!el) {
return ;
}
if (el.expiration) {
if (el.expiration.days > 0) {
return {el.expiration.days} days;
} else if (el.expiration.noncurrent_expiration_days) {
return {el.expiration.noncurrent_expiration_days} days;
}
}
if (el.transition) {
if (el.transition.days > 0) {
return {el.transition.days} days;
} else if (el.transition.noncurrent_transition_days) {
return {el.transition.noncurrent_transition_days} days;
}
}
},
},
{
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 (
{editLifecycleOpen && selectedLifecycleRule && (
)}
{addLifecycleOpen && (
)}
{deleteLifecycleOpen && selectedID && (
)}
Lifecycle Rules
{!loadingLifecycle && (
}
help={
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.
You can learn more at our{" "}
documentation
.
}
/>
)}
);
};
export default withStyles(styles)(BucketLifecyclePanel);