diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx index adebb06ec..a53c2ac99 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx @@ -99,6 +99,8 @@ import { import UploadFilesButton from "../../UploadFilesButton"; import DetailsListPanel from "./DetailsListPanel"; import ObjectDetailPanel from "./ObjectDetailPanel"; +import RBIconButton from "../../../BucketDetails/SummaryItems/RBIconButton"; +import MultiSelectionPanel from "./MultiSelectionPanel"; const AddFolderIcon = React.lazy( () => import("../../../../../../icons/AddFolderIcon") @@ -346,6 +348,17 @@ const ListObjects = ({ } }, [quota, bucketName]); + useEffect(() => { + if (selectedObjects.length > 0) { + setDetailsOpen(true); + return; + } + + if (selectedObjects.length === 0 && selectedInternalPaths === null) { + setDetailsOpen(false); + } + }, [selectedObjects, selectedInternalPaths]); + const displayDeleteObject = hasPermission(bucketName, [ IAM_SCOPES.S3_DELETE_OBJECT, ]); @@ -713,6 +726,7 @@ const ListObjects = ({ }; const openPath = (idElement: string) => { + setSelectedObjects([]); if (idElement.endsWith("/")) { const newPath = `/buckets/${bucketName}/browse${ idElement ? `/${encodeFileName(idElement)}` : `` @@ -995,6 +1009,7 @@ const ListObjects = ({ elements = elements.filter((element) => element !== value); } setSelectedObjects(elements); + setSelectedInternalPaths(null); return elements; }; @@ -1115,6 +1130,42 @@ const ListObjects = ({ uploadPath = uploadPath.concat(currentPath); } + const multiActionButtons = [ + { + action: downloadSelected, + label: "Download", + disabled: selectedObjects.length === 0, + icon: , + tooltip: "Download Selected", + }, + { + action: openShare, + label: "Share", + disabled: selectedObjects.length !== 1 || !canShareFile, + icon: , + tooltip: "Share Selected File", + }, + { + action: openPreview, + label: "Preview", + disabled: selectedObjects.length !== 1 || !canPreviewFile, + icon: , + tooltip: "Preview Selected File", + }, + { + action: () => { + setDeleteMultipleOpen(true); + }, + label: "Delete", + icon: , + disabled: + !hasPermission(bucketName, [IAM_SCOPES.S3_DELETE_OBJECT]) || + selectedObjects.length === 0 || + !displayDeleteObject, + tooltip: "Delete Selected Files", + }, + ]; + return ( {shareFileModalOpen && selectedPreview && ( @@ -1215,6 +1266,61 @@ const ListObjects = ({ } actions={ + } + color="primary" + variant={"outlined"} + onClick={() => { + setCreateFolderOpen(true); + }} + disabled={ + rewindEnabled || + !hasPermission(bucketName, [IAM_SCOPES.S3_PUT_OBJECT]) + } + /> + + + + } + color="primary" + variant={"outlined"} + onClick={() => { + setRewindSelect(true); + }} + disabled={ + !isVersioned || + !hasPermission(bucketName, [IAM_SCOPES.S3_PUT_OBJECT]) + } + /> + } + color="primary" + variant={"outlined"} + onClick={() => { + setLoading(true); + }} + disabled={ + !hasPermission(bucketName, [IAM_SCOPES.S3_LIST_BUCKET]) || + rewindEnabled + } + /> , - tooltip: "Download Selected", - }, - { - action: openShare, - label: "Share", - disabled: selectedObjects.length !== 1 || !canShareFile, - icon: , - tooltip: "Share Selected File", - }, - { - action: openPreview, - label: "Preview", - disabled: selectedObjects.length !== 1 || !canPreviewFile, - icon: , - tooltip: "Preview Selected File", - }, - { - action: () => { - setDeleteMultipleOpen(true); - }, - label: "Delete", - icon: , - disabled: - !hasPermission(bucketName, [ - IAM_SCOPES.S3_DELETE_OBJECT, - ]) || - selectedObjects.length === 0 || - !displayDeleteObject, - tooltip: "Delete Selected Files", - }, - { - action: () => { - setRewindSelect(true); - }, - label: "Rewind", - disabled: - !isVersioned || - !hasPermission(bucketName, [IAM_SCOPES.S3_PUT_OBJECT]), - icon: ( - - - - ), - tooltip: "Rewind Bucket", - }, - { - action: () => { - setCreateFolderOpen(true); - }, - label: "New Path", - icon: , - disabled: - rewindEnabled || - !hasPermission(bucketName, [IAM_SCOPES.S3_PUT_OBJECT]), - tooltip: "Choose or create a new path", - }, - ]} - globalActions={[ - { - action: () => { - setLoading(true); - }, - label: "Reload", - icon: , - disabled: - !hasPermission(bucketName, [IAM_SCOPES.S3_LIST_BUCKET]) || - rewindEnabled, - tooltip: "Reload List", - }, - ]} /> { setDetailsOpen(false); setSelectedInternalPaths(null); + setSelectedObjects([]); }} > + {selectedObjects.length > 0 && ( + + )} {selectedInternalPaths !== null && ( . + +import React, { Fragment } from "react"; +import ObjectActionButton from "./ObjectActionButton"; +import { withStyles } from "@mui/styles"; +import createStyles from "@mui/styles/createStyles"; +import { detailsPanel } from "../../../../Common/FormComponents/common/styleLibrary"; + +const styles = () => + createStyles({ + ...detailsPanel, + }); + +export interface MultiSelectionItem { + action: () => void; + label: string; + disabled: boolean; + icon: React.ReactNode; + tooltip: string; +} + +interface IMultiSelectionPanelProps { + items: MultiSelectionItem[]; + title: string; + classes: any; +} + +const MultiSelectionPanel = ({ + items, + classes, + title, +}: IMultiSelectionPanelProps) => { + return ( + +
{title}
+
    +
  • Actions:
  • + {items.map((actionItem) => { + return ( +
  • + +
  • + ); + })} +
+
+ ); +}; + +export default withStyles(styles)(MultiSelectionPanel); diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ObjectActionButton.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ObjectActionButton.tsx index b216c6cb4..ff1316662 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ObjectActionButton.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ObjectActionButton.tsx @@ -65,6 +65,7 @@ const ObjectActionButton = ({ return ( - - - ); -}; - -export default withStyles(styles)(TopActionButton);