From b24d62a6952cd640770506d580a8a5453789a419 Mon Sep 17 00:00:00 2001 From: Daniel Valdivia Date: Tue, 8 Dec 2020 10:31:04 -0800 Subject: [PATCH] Refactor React Classes to Functions (#483) --- portal-ui/src/icons/AddIcon.tsx | 26 +- portal-ui/src/icons/AllBucketsIcon.tsx | 105 ++- portal-ui/src/icons/BucketsIcon.tsx | 21 +- portal-ui/src/icons/ClustersIcon.tsx | 198 +++-- .../src/icons/ConfigurationsListIcon.tsx | 43 +- portal-ui/src/icons/ConsoleIcon.tsx | 32 +- portal-ui/src/icons/CopyIcon.tsx | 35 +- portal-ui/src/icons/CreateIcon.tsx | 54 +- portal-ui/src/icons/DashboardIcon.tsx | 55 +- portal-ui/src/icons/DeleteIcon.tsx | 27 +- portal-ui/src/icons/DownloadIcon.tsx | 22 +- portal-ui/src/icons/EgressIcon.tsx | 104 ++- portal-ui/src/icons/GroupsIcon.tsx | 39 +- portal-ui/src/icons/HealIcon.tsx | 49 +- portal-ui/src/icons/IAMPoliciesIcon.tsx | 27 +- .../src/icons/LambdaNotificationsIcon.tsx | 24 +- portal-ui/src/icons/LicenseIcon.tsx | 50 +- portal-ui/src/icons/LogoutIcon.tsx | 52 +- portal-ui/src/icons/MirroringIcon.tsx | 28 +- portal-ui/src/icons/PermissionIcon.tsx | 34 +- portal-ui/src/icons/RemoveIcon.tsx | 25 +- portal-ui/src/icons/ServiceAccountIcon.tsx | 34 +- portal-ui/src/icons/ServiceAccountsIcon.tsx | 41 +- portal-ui/src/icons/ShareIcon.tsx | 34 +- portal-ui/src/icons/TraceIcon.tsx | 73 +- portal-ui/src/icons/UploadFile.tsx | 38 +- portal-ui/src/icons/UsageIcon.tsx | 87 +- portal-ui/src/icons/UsersIcon.tsx | 47 +- portal-ui/src/icons/WarpIcon.tsx | 37 +- portal-ui/src/icons/WatchIcon.tsx | 75 +- .../Buckets/ListBuckets/DeleteBucket.tsx | 175 ++-- .../Objects/ListObjects/DeleteObject.tsx | 180 ++-- .../Console/Buckets/ViewBucket/AddEvent.tsx | 431 +++++----- .../Buckets/ViewBucket/DeleteEvent.tsx | 197 ++--- .../ViewBucket/EnableBucketEncryption.tsx | 227 +++-- .../Buckets/ViewBucket/SetAccessPolicy.tsx | 204 ++--- .../Console/Buckets/ViewBucket/ViewBucket.tsx | 798 +++++++++--------- .../screens/Console/Policies/AddPolicy.tsx | 254 +++--- .../screens/Console/Policies/DeletePolicy.tsx | 170 ++-- .../src/screens/Console/Users/AddUser.tsx | 443 +++++----- .../src/screens/Console/Users/DeleteUser.tsx | 178 ++-- portal-ui/src/screens/Console/Users/Users.tsx | 418 +++++---- 42 files changed, 2403 insertions(+), 2788 deletions(-) diff --git a/portal-ui/src/icons/AddIcon.tsx b/portal-ui/src/icons/AddIcon.tsx index c2a7aac06..f05d3febc 100644 --- a/portal-ui/src/icons/AddIcon.tsx +++ b/portal-ui/src/icons/AddIcon.tsx @@ -16,19 +16,17 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class AddIcon extends React.Component { - render() { - return ( - - - - ); - } -} +const AddIcon = () => { + return ( + + + + ); +}; export default AddIcon; diff --git a/portal-ui/src/icons/AllBucketsIcon.tsx b/portal-ui/src/icons/AllBucketsIcon.tsx index d55770242..38ac2de70 100644 --- a/portal-ui/src/icons/AllBucketsIcon.tsx +++ b/portal-ui/src/icons/AllBucketsIcon.tsx @@ -16,60 +16,59 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class AllBucketsIcon extends React.Component { - render() { - return ( - - - - - - - - - - { + return ( + + + + + + + + + + + + + - - - - - - ); - } -} + + + ); +}; export default AllBucketsIcon; diff --git a/portal-ui/src/icons/BucketsIcon.tsx b/portal-ui/src/icons/BucketsIcon.tsx index 1d769ccce..0adf44925 100644 --- a/portal-ui/src/icons/BucketsIcon.tsx +++ b/portal-ui/src/icons/BucketsIcon.tsx @@ -16,16 +16,15 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class BucketsIcon extends React.Component { - render() { - return ( - - - - - - ); - } -} + +const BucketsIcon = () => { + return ( + + + + + + ); +}; export default BucketsIcon; diff --git a/portal-ui/src/icons/ClustersIcon.tsx b/portal-ui/src/icons/ClustersIcon.tsx index 000ac2ea1..26bd93883 100644 --- a/portal-ui/src/icons/ClustersIcon.tsx +++ b/portal-ui/src/icons/ClustersIcon.tsx @@ -16,108 +16,106 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class ClustersIcon extends React.Component { - render() { - return ( - - - +const ClustersIcon = () => { + return ( + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - ); - } -} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; export default ClustersIcon; diff --git a/portal-ui/src/icons/ConfigurationsListIcon.tsx b/portal-ui/src/icons/ConfigurationsListIcon.tsx index 572f43fe8..89b3735ae 100644 --- a/portal-ui/src/icons/ConfigurationsListIcon.tsx +++ b/portal-ui/src/icons/ConfigurationsListIcon.tsx @@ -16,27 +16,26 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class ConfigurationsListIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - - - - - ); - } -} + +const ConfigurationsListIcon = () => { + return ( + + + + + + + + + + + + + + + + + ); +}; export default ConfigurationsListIcon; diff --git a/portal-ui/src/icons/ConsoleIcon.tsx b/portal-ui/src/icons/ConsoleIcon.tsx index a4bff4207..0a6f08928 100644 --- a/portal-ui/src/icons/ConsoleIcon.tsx +++ b/portal-ui/src/icons/ConsoleIcon.tsx @@ -16,22 +16,20 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class ConsoleIcon extends React.Component { - render() { - return ( - - - - - - - - - ); - } -} +const ConsoleIcon = () => { + return ( + + + + + + + + + ); +}; export default ConsoleIcon; diff --git a/portal-ui/src/icons/CopyIcon.tsx b/portal-ui/src/icons/CopyIcon.tsx index adac587a6..d6697d6e7 100644 --- a/portal-ui/src/icons/CopyIcon.tsx +++ b/portal-ui/src/icons/CopyIcon.tsx @@ -16,24 +16,23 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class CopyIcon extends React.Component { - render() { - return ( - - - ic_h_copy-new_sl - - - - + +const CopyIcon = () => { + return ( + + + ic_h_copy-new_sl + + + - - - ); - } -} + + + + ); +}; export default CopyIcon; diff --git a/portal-ui/src/icons/CreateIcon.tsx b/portal-ui/src/icons/CreateIcon.tsx index 2c5660751..dfbe646d9 100644 --- a/portal-ui/src/icons/CreateIcon.tsx +++ b/portal-ui/src/icons/CreateIcon.tsx @@ -16,35 +16,29 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class CreateIcon extends React.Component { - render() { - return ( - - - - - - - - - ); - } -} +const CreateIcon = () => { + return ( + + + + + + + + + ); +}; export default CreateIcon; diff --git a/portal-ui/src/icons/DashboardIcon.tsx b/portal-ui/src/icons/DashboardIcon.tsx index 5c741949f..3b9fbed6b 100644 --- a/portal-ui/src/icons/DashboardIcon.tsx +++ b/portal-ui/src/icons/DashboardIcon.tsx @@ -16,33 +16,32 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class DashboardIcon extends React.Component { - render() { - return ( - - - - - - - - - - - ); - } -} + +const DashboardIcon = () => { + return ( + + + + + + + + + + + ); +}; export default DashboardIcon; diff --git a/portal-ui/src/icons/DeleteIcon.tsx b/portal-ui/src/icons/DeleteIcon.tsx index 3a913f39a..6ef75154a 100644 --- a/portal-ui/src/icons/DeleteIcon.tsx +++ b/portal-ui/src/icons/DeleteIcon.tsx @@ -16,19 +16,18 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class DeleteIcon extends React.Component { - render() { - return ( - - - - - - ); - } -} + +const DeleteIcon = () => { + return ( + + + + + + ); +}; export default DeleteIcon; diff --git a/portal-ui/src/icons/DownloadIcon.tsx b/portal-ui/src/icons/DownloadIcon.tsx index 6e2822422..f4cd41fca 100644 --- a/portal-ui/src/icons/DownloadIcon.tsx +++ b/portal-ui/src/icons/DownloadIcon.tsx @@ -17,17 +17,15 @@ import React from "react"; import SvgIcon from "@material-ui/core/SvgIcon"; -class DownloadIcon extends React.Component { - render() { - return ( - - - - - - - ); - } -} +const DownloadIcon = () => { + return ( + + + + + + + ); +}; export default DownloadIcon; diff --git a/portal-ui/src/icons/EgressIcon.tsx b/portal-ui/src/icons/EgressIcon.tsx index 5d6c2bbc9..c22a36374 100644 --- a/portal-ui/src/icons/EgressIcon.tsx +++ b/portal-ui/src/icons/EgressIcon.tsx @@ -16,58 +16,56 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class EgressIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - - - ); - } -} +const EgressIcon = () => { + return ( + + + + + + + + + + + + + + + ); +}; export default EgressIcon; diff --git a/portal-ui/src/icons/GroupsIcon.tsx b/portal-ui/src/icons/GroupsIcon.tsx index bb2ea37c6..ad5528907 100644 --- a/portal-ui/src/icons/GroupsIcon.tsx +++ b/portal-ui/src/icons/GroupsIcon.tsx @@ -16,26 +16,25 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class GroupsIcon extends React.Component { - render() { - return ( - - - - - - - - - + +const GroupsIcon = () => { + return ( + + + + + + + + - - - ); - } -} + + + + ); +}; export default GroupsIcon; diff --git a/portal-ui/src/icons/HealIcon.tsx b/portal-ui/src/icons/HealIcon.tsx index 09c1fc1b0..f0c42317c 100644 --- a/portal-ui/src/icons/HealIcon.tsx +++ b/portal-ui/src/icons/HealIcon.tsx @@ -16,38 +16,21 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class HealIcon extends React.Component { - render() { - return ( - - - - - - - - - ); - } -} +const HealIcon = () => { + return ( + + + + + + + + + ); +}; export default HealIcon; diff --git a/portal-ui/src/icons/IAMPoliciesIcon.tsx b/portal-ui/src/icons/IAMPoliciesIcon.tsx index 2beaea359..3553aadd6 100644 --- a/portal-ui/src/icons/IAMPoliciesIcon.tsx +++ b/portal-ui/src/icons/IAMPoliciesIcon.tsx @@ -16,19 +16,18 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class BucketsIcon extends React.Component { - render() { - return ( - - - - - - ); - } -} + +const BucketsIcon = () => { + return ( + + + + + + ); +}; export default BucketsIcon; diff --git a/portal-ui/src/icons/LambdaNotificationsIcon.tsx b/portal-ui/src/icons/LambdaNotificationsIcon.tsx index 33b25c16e..f42ce3abb 100644 --- a/portal-ui/src/icons/LambdaNotificationsIcon.tsx +++ b/portal-ui/src/icons/LambdaNotificationsIcon.tsx @@ -16,19 +16,17 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class LambdaNotificationsIcon extends React.Component { - render() { - return ( - - - + - - - ); - } -} + /> + + + ); +}; export default LambdaNotificationsIcon; diff --git a/portal-ui/src/icons/LicenseIcon.tsx b/portal-ui/src/icons/LicenseIcon.tsx index a92c8dd7b..78e9df21f 100644 --- a/portal-ui/src/icons/LicenseIcon.tsx +++ b/portal-ui/src/icons/LicenseIcon.tsx @@ -17,31 +17,29 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class LicenseIcon extends React.Component { - render() { - return ( - - - - - - - - - - - ); - } -} +const LicenseIcon = () => { + return ( + + + + + + + + + + + ); +}; export default LicenseIcon; diff --git a/portal-ui/src/icons/LogoutIcon.tsx b/portal-ui/src/icons/LogoutIcon.tsx index ab9d4ac75..0e711ba1b 100644 --- a/portal-ui/src/icons/LogoutIcon.tsx +++ b/portal-ui/src/icons/LogoutIcon.tsx @@ -16,32 +16,30 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class LogoutIcon extends React.Component { - render() { - return ( - - - - - - - - - - ); - } -} +const LogoutIcon = () => { + return ( + + + + + + + + + + ); +}; export default LogoutIcon; diff --git a/portal-ui/src/icons/MirroringIcon.tsx b/portal-ui/src/icons/MirroringIcon.tsx index 57e5f240a..3e657b0d1 100644 --- a/portal-ui/src/icons/MirroringIcon.tsx +++ b/portal-ui/src/icons/MirroringIcon.tsx @@ -16,20 +16,18 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class MirroringIcon extends React.Component { - render() { - return ( - - - - - - - - - - ); - } -} +const MirroringIcon = () => { + return ( + + + + + + + + + + ); +}; export default MirroringIcon; diff --git a/portal-ui/src/icons/PermissionIcon.tsx b/portal-ui/src/icons/PermissionIcon.tsx index ff91d84eb..053c28f57 100644 --- a/portal-ui/src/icons/PermissionIcon.tsx +++ b/portal-ui/src/icons/PermissionIcon.tsx @@ -16,24 +16,22 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class PermissionIcon extends React.Component { - render() { - return ( - - - ic_permissions - - - - +const PermissionIcon = () => { + return ( + + + ic_permissions + + + - - - ); - } -} + + + + ); +}; export default PermissionIcon; diff --git a/portal-ui/src/icons/RemoveIcon.tsx b/portal-ui/src/icons/RemoveIcon.tsx index 8053b04d8..4fdc7168b 100644 --- a/portal-ui/src/icons/RemoveIcon.tsx +++ b/portal-ui/src/icons/RemoveIcon.tsx @@ -16,18 +16,17 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class RemoveIcon extends React.Component { - render() { - return ( - - - - ); - } -} + +const RemoveIcon = () => { + return ( + + + + ); +}; export default RemoveIcon; diff --git a/portal-ui/src/icons/ServiceAccountIcon.tsx b/portal-ui/src/icons/ServiceAccountIcon.tsx index 9094acdcb..be8ba482e 100644 --- a/portal-ui/src/icons/ServiceAccountIcon.tsx +++ b/portal-ui/src/icons/ServiceAccountIcon.tsx @@ -16,24 +16,22 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class ServiceAccountIcon extends React.Component { - render() { - return ( - - - ic_service-accounts - - - - +const ServiceAccountIcon = () => { + return ( + + + ic_service-accounts + + + - - - ); - } -} + + + + ); +}; export default ServiceAccountIcon; diff --git a/portal-ui/src/icons/ServiceAccountsIcon.tsx b/portal-ui/src/icons/ServiceAccountsIcon.tsx index 345e452e1..fd6856be1 100644 --- a/portal-ui/src/icons/ServiceAccountsIcon.tsx +++ b/portal-ui/src/icons/ServiceAccountsIcon.tsx @@ -16,26 +16,25 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class ServiceAccountsIcon extends React.Component { - render() { - return ( - - - - - - - - - - ); - } -} + +const ServiceAccountsIcon = () => { + return ( + + + + + + + + + + ); +}; export default ServiceAccountsIcon; diff --git a/portal-ui/src/icons/ShareIcon.tsx b/portal-ui/src/icons/ShareIcon.tsx index f1b245434..bfd30640b 100644 --- a/portal-ui/src/icons/ShareIcon.tsx +++ b/portal-ui/src/icons/ShareIcon.tsx @@ -17,23 +17,21 @@ import React from "react"; import SvgIcon from "@material-ui/core/SvgIcon"; -class ShareIcon extends React.Component { - render() { - return ( - - - - - - - ); - } -} +const ShareIcon = () => { + return ( + + + + + + + ); +}; export default ShareIcon; diff --git a/portal-ui/src/icons/TraceIcon.tsx b/portal-ui/src/icons/TraceIcon.tsx index f0f3fed85..f79743633 100644 --- a/portal-ui/src/icons/TraceIcon.tsx +++ b/portal-ui/src/icons/TraceIcon.tsx @@ -16,47 +16,38 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class TraceIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - + +const TraceIcon = () => { + return ( + + + + + + + + + + + + - - - ); - } -} + + + + ); +}; export default TraceIcon; diff --git a/portal-ui/src/icons/UploadFile.tsx b/portal-ui/src/icons/UploadFile.tsx index 4f0083e8b..8b6489e94 100644 --- a/portal-ui/src/icons/UploadFile.tsx +++ b/portal-ui/src/icons/UploadFile.tsx @@ -17,25 +17,23 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class UploadFile extends React.Component { - render() { - return ( - - - - - - - - - ); - } -} +const UploadFile = () => { + return ( + + + + + + + + + ); +}; export default UploadFile; diff --git a/portal-ui/src/icons/UsageIcon.tsx b/portal-ui/src/icons/UsageIcon.tsx index 0a5c21586..92b58e937 100644 --- a/portal-ui/src/icons/UsageIcon.tsx +++ b/portal-ui/src/icons/UsageIcon.tsx @@ -16,49 +16,48 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class UsageIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - ); - } -} + +const UsageIcon = () => { + return ( + + + + + + + + + + + + + ); +}; export default UsageIcon; diff --git a/portal-ui/src/icons/UsersIcon.tsx b/portal-ui/src/icons/UsersIcon.tsx index ee645b6be..01b95624c 100644 --- a/portal-ui/src/icons/UsersIcon.tsx +++ b/portal-ui/src/icons/UsersIcon.tsx @@ -16,30 +16,29 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class UsersIcon extends React.Component { - render() { - return ( - - - - - - - + +const UsersIcon = () => { + return ( + + + + + + - - - ); - } -} + + + + ); +}; export default UsersIcon; diff --git a/portal-ui/src/icons/WarpIcon.tsx b/portal-ui/src/icons/WarpIcon.tsx index e6aeab055..537f92283 100644 --- a/portal-ui/src/icons/WarpIcon.tsx +++ b/portal-ui/src/icons/WarpIcon.tsx @@ -16,24 +16,23 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class WarpIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - - ); - } -} + +const WarpIcon = () => { + return ( + + + + + + + + + + + + + + ); +}; export default WarpIcon; diff --git a/portal-ui/src/icons/WatchIcon.tsx b/portal-ui/src/icons/WatchIcon.tsx index f1df2f648..fa8f18056 100644 --- a/portal-ui/src/icons/WatchIcon.tsx +++ b/portal-ui/src/icons/WatchIcon.tsx @@ -16,44 +16,43 @@ import React from "react"; import { SvgIcon } from "@material-ui/core"; -class WatchIcon extends React.Component { - render() { - return ( - - - - - - - - - - - - - - + +const WatchIcon = () => { + return ( + + + + + + + + + + + + + - - - ); - } -} + + + + ); +}; export default WatchIcon; diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/DeleteBucket.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/DeleteBucket.tsx index 6761a2dcf..f87df36ba 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/DeleteBucket.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/DeleteBucket.tsx @@ -15,7 +15,7 @@ // along with this program. If not, see . import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import React from "react"; +import React, { useState } from "react"; import { Button, Dialog, @@ -48,106 +48,89 @@ interface IDeleteBucketState { deleteError: string; } -class DeleteBucket extends React.Component< - IDeleteBucketProps, - IDeleteBucketState -> { - state: IDeleteBucketState = { - deleteLoading: false, - deleteError: "", - }; +const DeleteBucket = ({ + classes, + closeDeleteModalAndRefresh, + deleteOpen, + selectedBucket, +}: IDeleteBucketProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [deleteError, setDeleteError] = useState(""); - removeRecord() { - const { deleteLoading } = this.state; - const { selectedBucket } = this.props; + const removeRecord = () => { if (deleteLoading) { return; } - this.setState({ deleteLoading: true }, () => { - api - .invoke("DELETE", `/api/v1/buckets/${selectedBucket}`, { - name: selectedBucket, - }) - .then((res: BucketList) => { - this.setState( - { - deleteLoading: false, - deleteError: "", - }, - () => { - this.props.closeDeleteModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - deleteLoading: false, - deleteError: err, - }); - }); - }); - } + setDeleteLoading(true); - render() { - const { classes, deleteOpen, selectedBucket } = this.props; - const { deleteLoading, deleteError } = this.state; + api + .invoke("DELETE", `/api/v1/buckets/${selectedBucket}`, { + name: selectedBucket, + }) + .then((res: BucketList) => { + setDeleteLoading(false); + setDeleteError(""); + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setDeleteError(err); + }); + }; - return ( - { - this.setState({ deleteError: "" }, () => { - this.props.closeDeleteModalAndRefresh(false); - }); - }} - aria-labelledby="alert-dialog-title" - aria-describedby="alert-dialog-description" - > - Delete Bucket - - {deleteLoading && } - - Are you sure you want to delete bucket {selectedBucket}?{" "} -
A bucket can only be deleted if it's empty. - {deleteError !== "" && ( - -
- - {deleteError} - -
- )} -
-
- - - - -
- ); - } -} + return ( + { + setDeleteError(""); + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete Bucket + + {deleteLoading && } + + Are you sure you want to delete bucket {selectedBucket}?
+ A bucket can only be deleted if it's empty. + {deleteError !== "" && ( + +
+ + {deleteError} + +
+ )} +
+
+ + + + +
+ ); +}; export default withStyles(styles)(DeleteBucket); diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/DeleteObject.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/DeleteObject.tsx index 01ae1aff6..face75d36 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/DeleteObject.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/DeleteObject.tsx @@ -15,7 +15,7 @@ // along with this program. If not, see . import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import React from "react"; +import React, { useState } from "react"; import { Button, Dialog, @@ -48,18 +48,17 @@ interface IDeleteObjectState { deleteError: string; } -class DeleteObject extends React.Component< - IDeleteObjectProps, - IDeleteObjectState -> { - state: IDeleteObjectState = { - deleteLoading: false, - deleteError: "", - }; +const DeleteObject = ({ + classes, + closeDeleteModalAndRefresh, + deleteOpen, + selectedBucket, + selectedObject, +}: IDeleteObjectProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [deleteError, setDeleteError] = useState(""); - removeRecord() { - const { deleteLoading } = this.state; - const { selectedObject, selectedBucket } = this.props; + const removeRecord = () => { if (deleteLoading) { return; } @@ -67,94 +66,77 @@ class DeleteObject extends React.Component< if (selectedObject.endsWith("/")) { recursive = true; } + setDeleteLoading(true); + api + .invoke( + "DELETE", + `/api/v1/buckets/${selectedBucket}/objects?path=${selectedObject}&recursive=${recursive}` + ) + .then((res: any) => { + setDeleteLoading(false); + setDeleteError(""); - this.setState({ deleteLoading: true }, () => { - api - .invoke( - "DELETE", - `/api/v1/buckets/${selectedBucket}/objects?path=${selectedObject}&recursive=${recursive}` - ) - .then((res: any) => { - this.setState( - { - deleteLoading: false, - deleteError: "", - }, - () => { - this.props.closeDeleteModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - deleteLoading: false, - deleteError: err, - }); - }); - }); - } + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setDeleteError(err); + }); + }; - render() { - const { classes, deleteOpen, selectedObject } = this.props; - const { deleteLoading, deleteError } = this.state; - - return ( - { - this.setState({ deleteError: "" }, () => { - this.props.closeDeleteModalAndRefresh(false); - }); - }} - aria-labelledby="alert-dialog-title" - aria-describedby="alert-dialog-description" - > - Delete - - {deleteLoading && } - - Are you sure you want to delete: {selectedObject}?{" "} - {deleteError !== "" && ( - -
- - {deleteError} - -
- )} -
-
- - - - -
- ); - } -} + return ( + { + setDeleteError(""); + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete + + {deleteLoading && } + + Are you sure you want to delete: {selectedObject}?{" "} + {deleteError !== "" && ( + +
+ + {deleteError} + +
+ )} +
+
+ + + + +
+ ); +}; export default withStyles(styles)(DeleteObject); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/AddEvent.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/AddEvent.tsx index 4aa16d5f9..b76b51fa3 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/AddEvent.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/AddEvent.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { ChangeEvent } from "react"; +import React, { ChangeEvent, useEffect, useState } from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import { Button, LinearProgress } from "@material-ui/core"; @@ -68,250 +68,225 @@ interface IAddEventState { arnList: string[]; } -class AddEvent extends React.Component { - state: IAddEventState = { - addLoading: false, - addError: "", - prefix: "", - suffix: "", - arn: "", - selectedEvents: [], - arnList: [], - }; +const AddEvent = ({ + classes, + open, + selectedBucket, + closeModalAndRefresh, +}: IAddEventProps) => { + const [addLoading, setAddLoading] = useState(false); + const [addError, setAddError] = useState(""); + const [prefix, setPrefix] = useState(""); + const [suffix, setSuffix] = useState(""); + const [arn, setArn] = useState(""); + const [selectedEvents, setSelectedEvents] = useState([]); + const [arnList, setArnList] = useState([]); - addRecord(event: React.FormEvent) { + const addRecord = (event: React.FormEvent) => { event.preventDefault(); - const { prefix, suffix, addLoading, arn, selectedEvents } = this.state; - const { selectedBucket } = this.props; if (addLoading) { return; } - this.setState({ addLoading: true }, () => { - api - .invoke("POST", `/api/v1/buckets/${selectedBucket}/events`, { - configuration: { - arn: arn, - events: selectedEvents, - prefix: prefix, - suffix: suffix, - }, - ignoreExisting: true, - }) - .then((res) => { - this.setState( - { - addLoading: false, - addError: "", - }, - () => { - this.props.closeModalAndRefresh(); - } - ); - }) - .catch((err) => { - this.setState({ - addLoading: false, - addError: err, - }); - }); - }); - } + setAddLoading(true); + api + .invoke("POST", `/api/v1/buckets/${selectedBucket}/events`, { + configuration: { + arn: arn, + events: selectedEvents, + prefix: prefix, + suffix: suffix, + }, + ignoreExisting: true, + }) + .then((res) => { + setAddLoading(false); + setAddError(""); + closeModalAndRefresh(); + }) + .catch((err) => { + setAddLoading(false); + setAddError(err); + }); + }; - fetchArnList() { - this.setState({ addLoading: true }, () => { - api - .invoke("GET", `/api/v1/admin/arns`) - .then((res: ArnList) => { - let arns: string[] = []; - if (res.arns !== null) { - arns = res.arns; - } - this.setState({ - addLoading: false, - arnList: arns, - addError: "", - }); - }) - .catch((err: any) => { - this.setState({ addLoading: false, addError: err }); - }); - }); - } + const fetchArnList = () => { + setAddLoading(true); + api + .invoke("GET", `/api/v1/admin/arns`) + .then((res: ArnList) => { + let arns: string[] = []; + if (res.arns !== null) { + arns = res.arns; + } + setAddLoading(false); + setAddError(""); + setArnList(arns); + }) + .catch((err: any) => { + setAddLoading(false); + setAddError(err); + }); + }; - componentDidMount(): void { - this.fetchArnList(); - } + useEffect(() => { + fetchArnList(); + }, []); - render() { - const { classes, open } = this.props; - const { - addLoading, - addError, - arn, - selectedEvents, - arnList, - prefix, - suffix, - } = this.state; + const events = [ + { label: "PUT - Object Uploaded", value: "put" }, + { label: "GET - Object accessed", value: "get" }, + { label: "DELETE - Object Deleted", value: "delete" }, + ]; - const events = [ - { label: "PUT - Object Uploaded", value: "put" }, - { label: "GET - Object accessed", value: "get" }, - { label: "DELETE - Object Deleted", value: "delete" }, - ]; + const handleClick = ( + event: React.MouseEvent | ChangeEvent, + name: string + ) => { + const selectedIndex = selectedEvents.indexOf(name); + let newSelected: string[] = []; - const handleClick = ( - event: React.MouseEvent | ChangeEvent, - name: string - ) => { - const selectedIndex = selectedEvents.indexOf(name); - let newSelected: string[] = []; + if (selectedIndex === -1) { + newSelected = newSelected.concat(selectedEvents, name); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(selectedEvents.slice(1)); + } else if (selectedIndex === selectedEvents.length - 1) { + newSelected = newSelected.concat(selectedEvents.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + selectedEvents.slice(0, selectedIndex), + selectedEvents.slice(selectedIndex + 1) + ); + } + setSelectedEvents(newSelected); + }; - if (selectedIndex === -1) { - newSelected = newSelected.concat(selectedEvents, name); - } else if (selectedIndex === 0) { - newSelected = newSelected.concat(selectedEvents.slice(1)); - } else if (selectedIndex === selectedEvents.length - 1) { - newSelected = newSelected.concat(selectedEvents.slice(0, -1)); - } else if (selectedIndex > 0) { - newSelected = newSelected.concat( - selectedEvents.slice(0, selectedIndex), - selectedEvents.slice(selectedIndex + 1) - ); - } + const arnValues = arnList.map((arnConstant) => ({ + label: arnConstant, + value: arnConstant, + })); - this.setState({ selectedEvents: newSelected }); - }; - - const arnValues = arnList.map((arnConstant) => ({ - label: arnConstant, - value: arnConstant, - })); - - return ( - { - this.setState({ addError: "" }, () => { - this.props.closeModalAndRefresh(); - }); + return ( + { + setAddError(""); + closeModalAndRefresh(); + }} + title="Subscribe To Event" + > +
) => { + addRecord(e); }} - title="Subscribe To Event" > - ) => { - this.addRecord(e); - }} - > - - - {addError !== "" && ( - - - {addError} - - - )} + + + {addError !== "" && ( - ) => { - this.setState({ arn: e.target.value as string }); - }} - id="select-access-policy" - name="select-access-policy" - label={"ARN"} - value={arn} - options={arnValues} - /> - - - - - - Select - Event - - - - {events.map((row) => ( - handleClick(event, row.value)} - > - - handleClick(event, row.value)} - checked={selectedEvents.includes(row.value)} - /> - - - {row.label} - - - ))} - -
-
- -
-
- - ) => { - this.setState({ prefix: e.target.value }); - }} - /> - - - ) => { - this.setState({ suffix: e.target.value }); - }} - /> - - -
-
-
- - - - {addLoading && ( - - + + {addError} + )} + + ) => { + setArn(e.target.value as string); + }} + id="select-access-policy" + name="select-access-policy" + label={"ARN"} + value={arn} + options={arnValues} + /> + + + + + + Select + Event + + + + {events.map((row) => ( + handleClick(event, row.value)} + > + + handleClick(event, row.value)} + checked={selectedEvents.includes(row.value)} + /> + + + {row.label} + + + ))} + +
+
+ +
+
+ + ) => { + setPrefix(e.target.value); + }} + /> + + + ) => { + setSuffix(e.target.value); + }} + /> + + +
+
- -
- ); - } -} + + + + {addLoading && ( + + + + )} + + +
+ ); +}; export default withStyles(styles)(AddEvent); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/DeleteEvent.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/DeleteEvent.tsx index 0f02046a2..378e81192 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/DeleteEvent.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/DeleteEvent.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useState } from "react"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import get from "lodash/get"; import { @@ -45,23 +45,17 @@ interface IDeleteEventProps { bucketEvent: BucketEvent | null; } -interface IDeleteEventState { - deleteLoading: boolean; - deleteError: string; -} +const DeleteEvent = ({ + classes, + closeDeleteModalAndRefresh, + deleteOpen, + selectedBucket, + bucketEvent, +}: IDeleteEventProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [deleteError, setDeleteError] = useState(""); -class DeleteEvent extends React.Component< - IDeleteEventProps, - IDeleteEventState -> { - state: IDeleteEventState = { - deleteLoading: false, - deleteError: "", - }; - - removeRecord() { - const { deleteLoading } = this.state; - const { selectedBucket, bucketEvent } = this.props; + const removeRecord = () => { if (deleteLoading) { return; } @@ -69,99 +63,84 @@ class DeleteEvent extends React.Component< return; } - this.setState({ deleteLoading: true }, () => { - const events = get(bucketEvent, "events", []); - const prefix = get(bucketEvent, "prefix", ""); - const suffix = get(bucketEvent, "suffix", ""); - api - .invoke( - "DELETE", - `/api/v1/buckets/${selectedBucket}/events/${bucketEvent.arn}`, - { - events, - prefix, - suffix, - } - ) - .then((res: BucketList) => { - this.setState( - { - deleteLoading: false, - deleteError: "", - }, - () => { - this.props.closeDeleteModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - deleteLoading: false, - deleteError: err, - }); - }); - }); - } + setDeleteLoading(true); - render() { - const { classes, deleteOpen } = this.props; - const { deleteLoading, deleteError } = this.state; + const events = get(bucketEvent, "events", []); + const prefix = get(bucketEvent, "prefix", ""); + const suffix = get(bucketEvent, "suffix", ""); + api + .invoke( + "DELETE", + `/api/v1/buckets/${selectedBucket}/events/${bucketEvent.arn}`, + { + events, + prefix, + suffix, + } + ) + .then((res: BucketList) => { + setDeleteLoading(false); + setDeleteError(""); + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setDeleteError(err); + }); + }; - return ( - { - this.setState({ deleteError: "" }, () => { - this.props.closeDeleteModalAndRefresh(false); - }); - }} - aria-labelledby="alert-dialog-title" - aria-describedby="alert-dialog-description" - > - Delete Bucket - - {deleteLoading && } - - Are you sure you want to delete this event? - {deleteError !== "" && ( - -
- - {deleteError} - -
- )} -
-
- - - - -
- ); - } -} + return ( + { + setDeleteError(""); + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete Bucket + + {deleteLoading && } + + Are you sure you want to delete this event? + {deleteError !== "" && ( + +
+ + {deleteError} + +
+ )} +
+
+ + + + +
+ ); +}; export default withStyles(styles)(DeleteEvent); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx index 5a259c0b7..a3125d744 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useState } from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import { Button, LinearProgress } from "@material-ui/core"; @@ -51,30 +51,19 @@ interface IEnableBucketEncryptionProps { closeModalAndRefresh: () => void; } -interface IEnableBucketEncryptionState { - loading: boolean; - encryptionError: string; - kmsKeyID: string; - suffix: string; - encryptionType: string; -} +const EnableBucketEncryption = ({ + classes, + open, + selectedBucket, + closeModalAndRefresh, +}: IEnableBucketEncryptionProps) => { + const [loading, setLoading] = useState(false); + const [encryptionError, setEncryptionError] = useState(""); + const [kmsKeyID, setKmsKeyID] = useState(""); + const [encryptionType, setEncryptionType] = useState("sse-s3"); -class EnableBucketEncryption extends React.Component< - IEnableBucketEncryptionProps, - IEnableBucketEncryptionState -> { - state: IEnableBucketEncryptionState = { - loading: false, - encryptionError: "", - kmsKeyID: "", - suffix: "", - encryptionType: "sse-s3", - }; - - enableBucketEncryption(event: React.FormEvent) { + const enableBucketEncryption = (event: React.FormEvent) => { event.preventDefault(); - const { kmsKeyID, loading, encryptionType } = this.state; - const { selectedBucket } = this.props; if (loading) { return; } @@ -84,116 +73,106 @@ class EnableBucketEncryption extends React.Component< kmsKeyID: kmsKeyID, }) .then(() => { - this.setState( - { - loading: false, - encryptionError: "", - }, - () => { - this.props.closeModalAndRefresh(); - } - ); + setLoading(false); + setEncryptionError(""); + + closeModalAndRefresh(); }) .catch((err: any) => { - this.setState({ encryptionError: err }); + setLoading(false); + setEncryptionError(err); }); - } + }; - render() { - const { classes, open } = this.props; - const { loading, encryptionError, kmsKeyID, encryptionType } = this.state; - - return ( - { - this.setState({ encryptionError: "" }, () => { - this.props.closeModalAndRefresh(); - }); + return ( + { + setEncryptionError(""); + closeModalAndRefresh(); + }} + title="Enable Bucket Encryption" + > +
) => { + enableBucketEncryption(e); }} - title="Enable Bucket Encryption" > - ) => { - this.enableBucketEncryption(e); - }} - > - - - {encryptionError !== "" && ( - - - {encryptionError} - - - )} + + + {encryptionError !== "" && ( - ) => { - this.setState({ encryptionType: e.target.value as string }); - }} - id="select-encryption-type" - name="select-encryption-type" - label={"Encryption Type"} - value={encryptionType} - options={[ - { - label: "SSE-S3", - value: "sse-s3", - }, - { - label: "SSE-KMS", - value: "sse-kms", - }, - ]} - /> - - -
-
- {encryptionType === "sse-kms" && ( - - ) => { - this.setState({ kmsKeyID: e.target.value }); - }} - /> - - )} - -
-
-
- - - - {loading && ( - - + + {encryptionError} + )} + + ) => { + setEncryptionType(e.target.value as string); + }} + id="select-encryption-type" + name="select-encryption-type" + label={"Encryption Type"} + value={encryptionType} + options={[ + { + label: "SSE-S3", + value: "sse-s3", + }, + { + label: "SSE-KMS", + value: "sse-kms", + }, + ]} + /> + + +
+
+ {encryptionType === "sse-kms" && ( + + ) => { + setKmsKeyID(e.target.value); + }} + /> + + )} + +
+
- -
- ); - } -} + + + + {loading && ( + + + + )} + + +
+ ); +}; export default withStyles(styles)(EnableBucketEncryption); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/SetAccessPolicy.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/SetAccessPolicy.tsx index 3916d0211..739363343 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/SetAccessPolicy.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/SetAccessPolicy.tsx @@ -13,7 +13,7 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useEffect, useState } from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import { Button, LinearProgress } from "@material-ui/core"; @@ -39,130 +39,106 @@ interface ISetAccessPolicyProps { closeModalAndRefresh: () => void; } -interface ISetAccessPolicyState { - addLoading: boolean; - addError: string; - accessPolicy: string; -} - -class SetAccessPolicy extends React.Component< - ISetAccessPolicyProps, - ISetAccessPolicyState -> { - state: ISetAccessPolicyState = { - addLoading: false, - addError: "", - accessPolicy: "", - }; - - addRecord(event: React.FormEvent) { +const SetAccessPolicy = ({ + classes, + open, + bucketName, + actualPolicy, + closeModalAndRefresh, +}: ISetAccessPolicyProps) => { + const [addLoading, setAddLoading] = useState(false); + const [addError, setAddError] = useState(""); + const [accessPolicy, setAccessPolicy] = useState(""); + const addRecord = (event: React.FormEvent) => { event.preventDefault(); - const { addLoading, accessPolicy } = this.state; - const { bucketName } = this.props; if (addLoading) { return; } - this.setState({ addLoading: true }, () => { - api - .invoke("PUT", `/api/v1/buckets/${bucketName}/set-policy`, { - access: accessPolicy, - }) - .then((res) => { - this.setState( - { - addLoading: false, - addError: "", - }, - () => { - this.props.closeModalAndRefresh(); - } - ); - }) - .catch((err) => { - this.setState({ - addLoading: false, - addError: err, - }); - }); - }); - } + setAddLoading(true); + api + .invoke("PUT", `/api/v1/buckets/${bucketName}/set-policy`, { + access: accessPolicy, + }) + .then((res) => { + setAddLoading(false); + setAddError(""); + closeModalAndRefresh(); + }) + .catch((err) => { + setAddLoading(false); + setAddError(err); + }); + }; - componentDidMount() { - const { actualPolicy } = this.props; + useEffect(() => { + setAccessPolicy(actualPolicy); + }, []); - this.setState({ accessPolicy: actualPolicy }); - } - - render() { - const { classes, open } = this.props; - const { addLoading, addError, accessPolicy } = this.state; - return ( - { - this.setState({ addError: "" }, () => { - this.props.closeModalAndRefresh(); - }); + return ( + { + setAddError(""); + closeModalAndRefresh(); + }} + > +
) => { + addRecord(e); }} > - ) => { - this.addRecord(e); - }} - > - - - {addError !== "" && ( - - - {addError} - - - )} + + + {addError !== "" && ( - ) => { - this.setState({ accessPolicy: e.target.value as string }); - }} - options={[ - { value: "PRIVATE", label: "Private" }, - { value: "PUBLIC", label: "Public" }, - ]} - /> - - - - - - {addLoading && ( - - + + {addError} + )} + + ) => { + setAccessPolicy(e.target.value as string); + }} + options={[ + { value: "PRIVATE", label: "Private" }, + { value: "PUBLIC", label: "Public" }, + ]} + /> + - -
- ); - } -} + + + + {addLoading && ( + + + + )} + + +
+ ); +}; export default withStyles(styles)(SetAccessPolicy); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx index 69836c5e4..4d331f1a8 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useEffect, useState } from "react"; import get from "lodash/get"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; @@ -201,455 +201,417 @@ interface IViewBucketState { encryptionEnabled: boolean; } -class ViewBucket extends React.Component { - state: IViewBucketState = { - info: null, - records: [], - replicationRules: [], - loadingBucket: true, - loadingEvents: true, - loadingSize: true, - error: "", - deleteError: "", - errBucket: "", - setAccessPolicyScreenOpen: false, - curTab: 0, - addScreenOpen: false, - enableEncryptionScreenOpen: false, - deleteOpen: false, - selectedBucket: "", - selectedEvent: null, - bucketSize: "0", - errorSize: "", - replicationSet: false, - openSetReplication: false, - isVersioned: false, - encryptionEnabled: false, +const ViewBucket = ({ classes, match }: IViewBucketProps) => { + const [info, setInfo] = useState(null); + const [records, setRecords] = useState([]); + const [replicationRules, setReplicationRules] = useState< + BucketReplicationRule[] + >([]); + const [loadingBucket, setLoadingBucket] = useState(true); + const [loadingEvents, setLoadingEvents] = useState(true); + const [loadingSize, setLoadingSize] = useState(true); + const [error, setError] = useState(""); + const [deleteError, setDeleteError] = useState(""); + const [errBucket, setErrBucket] = useState(""); + const [accessPolicyScreenOpen, setAccessPolicyScreenOpen] = useState( + false + ); + const [curTab, setCurTab] = useState(0); + const [addScreenOpen, setAddScreenOpen] = useState(false); + const [ + enableEncryptionScreenOpen, + setEnableEncryptionScreenOpen, + ] = useState(false); + const [deleteOpen, setDeleteOpen] = useState(false); + const [selectedBucket, setSelectedBucket] = useState(""); + const [selectedEvent, setSelectedEvent] = useState(null); + const [bucketSize, setBucketSize] = useState("0"); + const [errorSize, setErrorSize] = useState(""); + const [replicationSet, setReplicationSet] = useState(false); + const [openSetReplication, setOpenSetReplication] = useState(false); + const [isVersioned, setIsVersioned] = useState(false); + const [encryptionEnabled, setEncryptionEnabled] = useState(false); + + const fetchEvents = () => { + setLoadingBucket(true); + const bucketName = match.params["bucketName"]; + api + .invoke("GET", `/api/v1/buckets/${bucketName}/events`) + .then((res: BucketEventList) => { + const events = get(res, "events", []); + setLoadingEvents(false); + setError(""); + setRecords(events || []); + }) + .catch((err: any) => { + setLoadingEvents(false); + setError(err); + }); + + api + .invoke("GET", `/api/v1/buckets/${bucketName}/versioning`) + .then((res: BucketVersioning) => { + setIsVersioned(res.is_versioned); + }) + .catch((err: any) => { + setError(err); + }); + + api + .invoke("GET", `/api/v1/buckets/${bucketName}/replication`) + .then((res: BucketReplication) => { + const r = res.rules ? res.rules : []; + setReplicationRules(r); + }) + .catch((err: any) => { + setError(err); + }); }; - fetchEvents() { - this.setState({ loadingBucket: true }, () => { - const { match } = this.props; - const bucketName = match.params["bucketName"]; - api - .invoke("GET", `/api/v1/buckets/${bucketName}/events`) - .then((res: BucketEventList) => { - const events = get(res, "events", []); - - this.setState({ - loadingEvents: false, - records: events || [], - error: "", - }); - }) - .catch((err: any) => { - this.setState({ loadingEvents: false, error: err }); - }); - - api - .invoke("GET", `/api/v1/buckets/${bucketName}/versioning`) - .then((res: BucketVersioning) => { - this.setState({ - isVersioned: res.is_versioned, - }); - }) - .catch((err: any) => { - this.setState({ error: err }); - }); - - api - .invoke("GET", `/api/v1/buckets/${bucketName}/replication`) - .then((res: BucketReplication) => { - const r = res.rules ? res.rules : []; - this.setState({ - replicationRules: r, - }); - }) - .catch((err: any) => { - this.setState({ error: err }); - }); - }); - } - - fetchBucketsSize() { - const { match } = this.props; + const fetchBucketsSize = () => { const bucketName = match.params["bucketName"]; + setLoadingSize(true); + api + .invoke("GET", `/api/v1/buckets`) + .then((res: BucketList) => { + const resBuckets = get(res, "buckets", []); - this.setState({ loadingSize: true }, () => { - api - .invoke("GET", `/api/v1/buckets`) - .then((res: BucketList) => { - const resBuckets = get(res, "buckets", []); + const bucketInfo = resBuckets.find( + (bucket) => bucket.name === bucketName + ); - const bucketInfo = resBuckets.find( - (bucket) => bucket.name === bucketName - ); + const size = get(bucketInfo, "size", "0"); - const size = get(bucketInfo, "size", "0"); + setLoadingSize(false); + setErrorSize(""); + setBucketSize(size); + }) + .catch((err: any) => { + setLoadingSize(false); + setErrorSize(err); + }); + }; - this.setState({ - loadingSize: false, - errorSize: "", - bucketSize: size, - }); - }) - .catch((err: any) => { - this.setState({ loadingSize: false, errorSize: err }); - }); - }); - } - - loadInfo() { - const { match } = this.props; + const loadInfo = () => { const bucketName = match.params["bucketName"]; - this.setState({ loadingBucket: true }, () => { - api - .invoke("GET", `/api/v1/buckets/${bucketName}`) - .then((res: BucketInfo) => { - this.setState({ loadingBucket: false, info: res }); - }) - .catch((err) => { - this.setState({ loadingBucket: false, errBucket: err }); - }); - }); - } + setLoadingBucket(true); - fetchBucketEncryptionInfo() { - const { match } = this.props; + api + .invoke("GET", `/api/v1/buckets/${bucketName}`) + .then((res: BucketInfo) => { + setLoadingBucket(false); + setInfo(res); + }) + .catch((err) => { + setLoadingBucket(false); + setErrBucket(err); + }); + }; + + const fetchBucketEncryptionInfo = () => { const bucketName = match.params["bucketName"]; api .invoke("GET", `/api/v1/buckets/${bucketName}/encryption/info`) .then((res: BucketEncryptionInfo) => { if (res.algorithm) { - this.setState({ encryptionEnabled: true }); + setEncryptionEnabled(true); } }) .catch((err) => { console.log(err); }); - } + }; - closeAddModalAndRefresh() { - this.setState({ setAccessPolicyScreenOpen: false }, () => { - this.loadInfo(); - }); - } + const closeAddModalAndRefresh = () => { + setAccessPolicyScreenOpen(false); + loadInfo(); + }; - closeDeleteModalAndRefresh(refresh: boolean) { - this.setState({ deleteOpen: false }, () => { - if (refresh) { - this.fetchEvents(); - } - }); - } - - componentDidMount(): void { - this.loadInfo(); - this.fetchEvents(); - this.fetchBucketsSize(); - this.fetchBucketEncryptionInfo(); - } - - bucketFilter(): void {} - - render() { - const { classes, match } = this.props; - const { - info, - records, - setAccessPolicyScreenOpen, - loadingEvents, - loadingBucket, - deleteOpen, - addScreenOpen, - enableEncryptionScreenOpen, - selectedEvent, - bucketSize, - loadingSize, - openSetReplication, - isVersioned, - replicationRules, - curTab, - encryptionEnabled, - } = this.state; - - const bucketName = match.params["bucketName"]; - - const confirmDeleteEvent = (evnt: BucketEvent) => { - this.setState({ deleteOpen: true, selectedEvent: evnt }); - }; - - let accessPolicy = "n/a"; - - if (info !== null) { - accessPolicy = info.access; + const closeDeleteModalAndRefresh = (refresh: boolean) => { + setDeleteOpen(false); + if (refresh) { + fetchEvents(); } + }; - const eventsDisplay = (events: string[]) => { - return {events.join(", ")}; - }; + useEffect(() => { + loadInfo(); + fetchEvents(); + fetchBucketsSize(); + fetchBucketEncryptionInfo(); + }, []); - const ruleDestDisplay = (events: BucketReplicationDestination) => { - return ( - - {events.bucket.replace("arn:aws:s3:::", "")} - - ); - }; + const bucketName = match.params["bucketName"]; - const ruleDelDisplay = (events: BucketReplicationRuleDeleteMarker) => { - return {events.status}; - }; + const confirmDeleteEvent = (evnt: BucketEvent) => { + setDeleteOpen(true); + setSelectedEvent(evnt); + }; - const setOpenReplicationOpen = (open = false) => { - this.setState({ openSetReplication: open }); - }; + let accessPolicy = "n/a"; - const handleEncryptionCheckbox = ( - event: React.ChangeEvent - ) => { - if (event.target.checked) { - this.setState({ enableEncryptionScreenOpen: true }); - } else { - api - .invoke("POST", `/api/v1/buckets/${bucketName}/encryption/disable`) - .then(() => { - this.setState({ encryptionEnabled: false }); - }) - .catch((err: any) => { - this.setState({ error: err }); - }); - } - }; + if (info !== null) { + accessPolicy = info.access; + } - const tableActions = [{ type: "delete", onClick: confirmDeleteEvent }]; + const eventsDisplay = (events: string[]) => { + return {events.join(", ")}; + }; + const ruleDestDisplay = (events: BucketReplicationDestination) => { return ( - {addScreenOpen && ( - { - this.setState({ addScreenOpen: false }); - this.fetchEvents(); - }} - /> - )} - {enableEncryptionScreenOpen && ( - { - this.setState({ enableEncryptionScreenOpen: false }); - this.fetchBucketEncryptionInfo(); - }} - /> - )} - {setAccessPolicyScreenOpen && ( - { - this.closeAddModalAndRefresh(); - }} - /> - )} - {openSetReplication && ( - { - setOpenReplicationOpen(false); - this.fetchEvents(); - }} - open={openSetReplication} - bucketName={bucketName} - /> - )} - ${match.params["bucketName"]}`} /> - - - -
-
- -
-
Access Policy:
-
- {loadingBucket ? ( - - ) : ( - accessPolicy.toLowerCase() - )} -
-
Reported Usage:
-
- {loadingSize ? ( - - ) : ( - niceBytes(bucketSize) - )} -
-
Replication:
-
- {replicationRules.length ? "Yes" : "No"} -
-
Versioning:
-
{isVersioned ? "Yes" : "No"} 
-
Encryption:
-
- handleEncryptionCheckbox(event)} - checked={encryptionEnabled} - /> -
-
-
-
-
-
- -
-
-
-
- -
-
- - - , newValue: number) => { - this.setState({ curTab: newValue }); - }} - indicatorColor="primary" - textColor="primary" - aria-label="cluster-tabs" - > - - - - - - {curTab === 0 && ( - - )} - {curTab === 1 && ( - - )} - - - - - - - - - - -
-
- - { - this.closeDeleteModalAndRefresh(refresh); - }} - /> + {events.bucket.replace("arn:aws:s3:::", "")}
); - } -} + }; + + const ruleDelDisplay = (events: BucketReplicationRuleDeleteMarker) => { + return {events.status}; + }; + + const setOpenReplicationOpen = (open = false) => { + setOpenSetReplication(open); + }; + + const handleEncryptionCheckbox = ( + event: React.ChangeEvent + ) => { + if (event.target.checked) { + setEnableEncryptionScreenOpen(true); + } else { + api + .invoke("POST", `/api/v1/buckets/${bucketName}/encryption/disable`) + .then(() => { + setEncryptionEnabled(false); + }) + .catch((err: any) => { + setError(err); + }); + } + }; + + const tableActions = [{ type: "delete", onClick: confirmDeleteEvent }]; + + return ( + + {addScreenOpen && ( + { + setAddScreenOpen(false); + fetchEvents(); + }} + /> + )} + {enableEncryptionScreenOpen && ( + { + setEnableEncryptionScreenOpen(false); + fetchBucketEncryptionInfo(); + }} + /> + )} + {accessPolicyScreenOpen && ( + { + closeAddModalAndRefresh(); + }} + /> + )} + {openSetReplication && ( + { + setOpenReplicationOpen(false); + fetchEvents(); + }} + open={openSetReplication} + bucketName={bucketName} + /> + )} + ${match.params["bucketName"]}`} /> + + + +
+
+ +
+
Access Policy:
+
+ {loadingBucket ? ( + + ) : ( + accessPolicy.toLowerCase() + )} +
+
Reported Usage:
+
+ {loadingSize ? ( + + ) : ( + niceBytes(bucketSize) + )} +
+
Replication:
+
+ {replicationRules.length ? "Yes" : "No"} +
+
Versioning:
+
{isVersioned ? "Yes" : "No"} 
+
Encryption:
+
+ handleEncryptionCheckbox(event)} + checked={encryptionEnabled} + /> +
+
+
+
+
+
+ +
+
+
+
+ +
+
+ + + , newValue: number) => { + setCurTab(newValue); + }} + indicatorColor="primary" + textColor="primary" + aria-label="cluster-tabs" + > + + + + + + {curTab === 0 && ( + + )} + {curTab === 1 && ( + + )} + + + + + + + + + + +
+
+ + { + closeDeleteModalAndRefresh(refresh); + }} + /> +
+ ); +}; export default withStyles(styles)(ViewBucket); diff --git a/portal-ui/src/screens/Console/Policies/AddPolicy.tsx b/portal-ui/src/screens/Console/Policies/AddPolicy.tsx index 4fd8dbebd..8edee5727 100644 --- a/portal-ui/src/screens/Console/Policies/AddPolicy.tsx +++ b/portal-ui/src/screens/Console/Policies/AddPolicy.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useEffect, useState } from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import { Button, LinearProgress } from "@material-ui/core"; @@ -59,159 +59,141 @@ interface IAddPolicyState { policyDefinition: string; } -class AddPolicy extends React.Component { - state: IAddPolicyState = { - addLoading: false, - addError: "", - policyName: "", - policyDefinition: "", - }; +const AddPolicy = ({ + classes, + open, + closeModalAndRefresh, + policyEdit, +}: IAddPolicyProps) => { + const [addLoading, setAddLoading] = useState(false); + const [addError, setAddError] = useState(""); + const [policyName, setPolicyName] = useState(""); + const [policyDefinition, setPolicyDefinition] = useState(""); - addRecord(event: React.FormEvent) { + const addRecord = (event: React.FormEvent) => { event.preventDefault(); - const { policyName, addLoading, policyDefinition } = this.state; if (addLoading) { return; } - this.setState({ addLoading: true }, () => { - api - .invoke("POST", "/api/v1/policies", { - name: policyName, - policy: policyDefinition, - }) - .then((res) => { - this.setState( - { - addLoading: false, - addError: "", - }, - () => { - this.props.closeModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - addLoading: false, - addError: err, - }); - }); - }); - } + setAddLoading(true); + api + .invoke("POST", "/api/v1/policies", { + name: policyName, + policy: policyDefinition, + }) + .then((res) => { + setAddLoading(false); + setAddError(""); - componentDidMount() { - const { policyEdit } = this.props; - - if (policyEdit) { - this.setState({ - policyName: policyEdit.name, - policyDefinition: policyEdit - ? JSON.stringify(JSON.parse(policyEdit.policy), null, 4) - : "", + closeModalAndRefresh(true); + }) + .catch((err) => { + setAddLoading(false); + setAddError(err); }); + }; + + useEffect(() => { + if (policyEdit) { + setPolicyName(policyEdit.name); + setPolicyDefinition( + policyEdit ? JSON.stringify(JSON.parse(policyEdit.policy), null, 4) : "" + ); } - } + }, []); - resetForm() { - this.setState({ - policyName: "", - policyDefinition: "", - }); - } + const resetForm = () => { + setPolicyName(""); + setPolicyDefinition(""); + }; - render() { - const { classes, open, policyEdit } = this.props; - const { addLoading, addError, policyName, policyDefinition } = this.state; + const validSave = policyName.trim() !== ""; - const validSave = policyName.trim() !== ""; - - return ( - { - this.setState({ addError: "" }, () => { - this.props.closeModalAndRefresh(false); - }); + return ( + { + setAddError(""); + closeModalAndRefresh(false); + }} + title={`${policyEdit ? "Info" : "Create"} Policy`} + > +
) => { + addRecord(e); }} - title={`${policyEdit ? "Info" : "Create"} Policy`} > - ) => { - this.addRecord(e); - }} - > - - - {addError !== "" && ( - - - {addError} - - - )} + + + {addError !== "" && ( - ) => { - this.setState({ policyName: e.target.value }); - }} - value={policyName} - disabled={!!policyEdit} - /> + + {addError} + - -
-
- { - this.setState({ policyDefinition: value }); + )} + + ) => { + setPolicyName(e.target.value); }} - readOnly={!!policyEdit} + value={policyName} + disabled={!!policyEdit} /> - {!policyEdit && ( - - - - - )} - {addLoading && ( - - - - )} + +
+
+ { + setPolicyDefinition(value); + }} + readOnly={!!policyEdit} + />
- -
- ); - } -} + {!policyEdit && ( + + + + + )} + {addLoading && ( + + + + )} + + +
+ ); +}; export default withStyles(styles)(AddPolicy); diff --git a/portal-ui/src/screens/Console/Policies/DeletePolicy.tsx b/portal-ui/src/screens/Console/Policies/DeletePolicy.tsx index 5bb78e99a..3ece81326 100644 --- a/portal-ui/src/screens/Console/Policies/DeletePolicy.tsx +++ b/portal-ui/src/screens/Console/Policies/DeletePolicy.tsx @@ -15,7 +15,7 @@ // along with this program. If not, see . import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import React from "react"; +import React, { useState } from "react"; import { Button, Dialog, @@ -48,100 +48,84 @@ interface IDeletePolicyState { deleteError: string; } -class DeletePolicy extends React.Component< - IDeletePolicyProps, - IDeletePolicyState -> { - state: IDeletePolicyState = { - deleteLoading: false, - deleteError: "", - }; - removeRecord() { - const { deleteLoading } = this.state; - const { selectedPolicy } = this.props; +const DeletePolicy = ({ + classes, + closeDeleteModalAndRefresh, + deleteOpen, + selectedPolicy, +}: IDeletePolicyProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [deleteError, setDeleteError] = useState(""); + const removeRecord = () => { if (deleteLoading) { return; } - this.setState({ deleteLoading: true }, () => { - api - .invoke("DELETE", `/api/v1/policies/${selectedPolicy}`) - .then((res: PolicyList) => { - this.setState( - { - deleteLoading: false, - deleteError: "", - }, - () => { - this.props.closeDeleteModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - deleteLoading: false, - deleteError: err, - }); - }); - }); - } - render() { - const { classes, deleteOpen, selectedPolicy } = this.props; - const { deleteLoading, deleteError } = this.state; - return ( - { - this.setState({ deleteError: "" }, () => { - this.props.closeDeleteModalAndRefresh(false); - }); - }} - aria-labelledby="alert-dialog-title" - aria-describedby="alert-dialog-description" - > - Delete Policy - - {deleteLoading && } - - Are you sure you want to delete policy {selectedPolicy}?. - {deleteError !== "" && ( - -
- - {deleteError} - -
- )} -
-
- - - - -
- ); - } -} + setDeleteLoading(true); + api + .invoke("DELETE", `/api/v1/policies/${selectedPolicy}`) + .then((res: PolicyList) => { + setDeleteLoading(false); + setDeleteError(""); + + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setDeleteError(err); + }); + }; + return ( + { + setDeleteError(""); + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete Policy + + {deleteLoading && } + + Are you sure you want to delete policy {selectedPolicy}?. + {deleteError !== "" && ( + +
+ + {deleteError} + +
+ )} +
+
+ + + + +
+ ); +}; export default withStyles(styles)(DeletePolicy); diff --git a/portal-ui/src/screens/Console/Users/AddUser.tsx b/portal-ui/src/screens/Console/Users/AddUser.tsx index 1ee3b67d5..8f9a2ad3f 100644 --- a/portal-ui/src/screens/Console/Users/AddUser.tsx +++ b/portal-ui/src/screens/Console/Users/AddUser.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useEffect, useState } from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import { Button, LinearProgress } from "@material-ui/core"; @@ -52,112 +52,74 @@ interface IAddUserContentProps { open: boolean; } -interface IAddUserContentState { - addLoading: boolean; - addError: string; - accessKey: string; - secretKey: string; - selectedGroups: string[]; - currentGroups: string[]; - enabled: boolean; -} +const AddUserContent = ({ + classes, + closeModalAndRefresh, + selectedUser, + open, +}: IAddUserContentProps) => { + const [addLoading, setAddLoading] = useState(false); + const [addError, setAddError] = useState(""); + const [accessKey, setAccessKey] = useState(""); + const [secretKey, setSecretKey] = useState(""); + const [enabled, setEnabled] = useState(false); + const [selectedGroups, setSelectedGroups] = useState([]); + const [currentGroups, setCurrentGroups] = useState([]); -class AddUserContent extends React.Component< - IAddUserContentProps, - IAddUserContentState -> { - state: IAddUserContentState = { - addLoading: false, - addError: "", - accessKey: "", - secretKey: "", - enabled: false, - selectedGroups: [], - currentGroups: [], - }; - - componentDidMount(): void { - const { selectedUser } = this.props; + useEffect(() => { if (selectedUser == null) { - this.setState({ - accessKey: "", - secretKey: "", - selectedGroups: [], - }); + setAccessKey(""); + setSecretKey(""); + setSelectedGroups([]); } else { - this.getUserInformation(); + getUserInformation(); } - } + }, []); - saveRecord(event: React.FormEvent) { + const saveRecord = (event: React.FormEvent) => { event.preventDefault(); - const { - accessKey, - addLoading, - secretKey, - selectedGroups, - enabled, - } = this.state; - const { selectedUser } = this.props; + if (addLoading) { return; } - this.setState({ addLoading: true }, () => { - if (selectedUser !== null) { - api - .invoke("PUT", `/api/v1/users/${selectedUser.accessKey}`, { - status: enabled ? "enabled" : "disabled", - groups: selectedGroups, - }) - .then((res) => { - this.setState( - { - addLoading: false, - addError: "", - }, - () => { - this.props.closeModalAndRefresh(); - } - ); - }) - .catch((err) => { - this.setState({ - addLoading: false, - addError: err, - }); - }); - } else { - api - .invoke("POST", "/api/v1/users", { - accessKey, - secretKey, - groups: selectedGroups, - }) - .then((res) => { - this.setState( - { - addLoading: false, - addError: "", - }, - () => { - this.props.closeModalAndRefresh(); - } - ); - }) - .catch((err) => { - console.log(err); - this.setState({ - addLoading: false, - addError: err, - }); - }); - } - }); - } + setAddLoading(true); + if (selectedUser !== null) { + api + .invoke("PUT", `/api/v1/users/${selectedUser.accessKey}`, { + status: enabled ? "enabled" : "disabled", + groups: selectedGroups, + }) + .then((res) => { + setAddLoading(false); + setAddError(""); - getUserInformation() { - const { selectedUser } = this.props; + closeModalAndRefresh(); + }) + .catch((err) => { + setAddLoading(false); + setAddError(err); + }); + } else { + api + .invoke("POST", "/api/v1/users", { + accessKey, + secretKey, + groups: selectedGroups, + }) + .then((res) => { + setAddLoading(false); + setAddError(""); + closeModalAndRefresh(); + }) + .catch((err) => { + console.log(err); + setAddLoading(false); + setAddError(err); + }); + } + }; + const getUserInformation = () => { if (!selectedUser) { return null; } @@ -165,167 +127,148 @@ class AddUserContent extends React.Component< api .invoke("GET", `/api/v1/users/${selectedUser.accessKey}`) .then((res) => { - this.setState({ - addLoading: false, - addError: "", - accessKey: res.accessKey, - selectedGroups: res.memberOf || [], - currentGroups: res.memberOf || [], - enabled: res.status === "enabled", - }); + setAddLoading(false); + setAddError(""); + setAccessKey(res.accessKey); + setSelectedGroups(res.memberOf || []); + setCurrentGroups(res.memberOf || []); + setEnabled(res.status === "enabled"); }) .catch((err) => { - this.setState({ - addLoading: false, - addError: err, - }); + setAddLoading(false); + setAddError(err); }); - } - - resetForm() { - if (this.props.selectedUser !== null) { - this.setState({ selectedGroups: [] }); + }; + const resetForm = () => { + if (selectedUser !== null) { + setSelectedGroups([]); return; } + setAccessKey(""); + setSecretKey(""); + setSelectedGroups([]); + }; - this.setState({ accessKey: "", secretKey: "", selectedGroups: [] }); - } - - render() { - const { classes, selectedUser } = this.props; - const { - addLoading, - addError, - accessKey, - secretKey, - selectedGroups, - currentGroups, - enabled, - } = this.state; - - const sendEnabled = - accessKey.trim() !== "" && - ((secretKey.trim() !== "" && selectedUser === null) || - selectedUser !== null); - return ( - { - this.props.closeModalAndRefresh(); - }} - modalOpen={this.props.open} - title={selectedUser !== null ? "Edit User" : "Create User"} - > - {selectedUser !== null && ( -
- { - this.setState({ enabled: e.target.checked }); - }} - switchOnly - /> -
- )} - - -
) => { - this.saveRecord(e); + const sendEnabled = + accessKey.trim() !== "" && + ((secretKey.trim() !== "" && selectedUser === null) || + selectedUser !== null); + return ( + { + closeModalAndRefresh(); + }} + modalOpen={open} + title={selectedUser !== null ? "Edit User" : "Create User"} + > + {selectedUser !== null && ( +
+ { + setEnabled(e.target.checked); }} - > - - - {addError !== "" && ( - - - {addError} - - - )} + switchOnly + /> +
+ )} - ) => { - this.setState({ accessKey: e.target.value }); - }} - disabled={selectedUser !== null} - /> - - {selectedUser !== null ? ( - - ) : ( - ) => { - this.setState({ secretKey: e.target.value }); - }} - autoComplete="current-password" - /> - )} + + ) => { + saveRecord(e); + }} + > + + + {addError !== "" && ( - { - this.setState({ - selectedGroups: elements, - }); - }} - /> - - - - - - - {addLoading && ( - - + + {addError} + )} + + ) => { + setAccessKey(e.target.value); + }} + disabled={selectedUser !== null} + /> + + {selectedUser !== null ? ( + + ) : ( + ) => { + setSecretKey(e.target.value); + }} + autoComplete="current-password" + /> + )} + + { + setSelectedGroups(elements); + }} + /> + - - -
- ); - } -} + + + + + {addLoading && ( + + + + )} + + +
+
+ ); +}; const AddUserWrapper = withStyles(styles)(AddUserContent); @@ -335,14 +278,8 @@ interface IAddUserProps { selectedUser: User | null; } -interface IAddUserState {} - -class AddUser extends React.Component { - state: IAddUserState = {}; - - render() { - return ; - } -} +const AddUser = (props: IAddUserProps) => { + return ; +}; export default AddUser; diff --git a/portal-ui/src/screens/Console/Users/DeleteUser.tsx b/portal-ui/src/screens/Console/Users/DeleteUser.tsx index 123baeaae..93c64d9c3 100644 --- a/portal-ui/src/screens/Console/Users/DeleteUser.tsx +++ b/portal-ui/src/screens/Console/Users/DeleteUser.tsx @@ -15,7 +15,7 @@ // along with this program. If not, see . import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import React from "react"; +import React, { useState } from "react"; import { Button, Dialog, @@ -48,110 +48,94 @@ interface IDeleteUserState { deleteError: string; } -class DeleteUser extends React.Component { - state: IDeleteUserState = { - deleteLoading: false, - deleteError: "", - }; +const DeleteUser = ({ + classes, + closeDeleteModalAndRefresh, + deleteOpen, + selectedUser, +}: IDeleteUserProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [deleteError, setDeleteError] = useState(""); - removeRecord() { - const { deleteLoading } = this.state; - const { selectedUser } = this.props; + const removeRecord = () => { if (deleteLoading) { return; } if (selectedUser == null) { return; } - this.setState({ deleteLoading: true }, () => { - api - .invoke("DELETE", `/api/v1/users/${selectedUser.accessKey}`, { - id: selectedUser.id, - }) - .then((res: UsersList) => { - this.setState( - { - deleteLoading: false, - deleteError: "", - }, - () => { - this.props.closeDeleteModalAndRefresh(true); - } - ); - }) - .catch((err) => { - this.setState({ - deleteLoading: false, - deleteError: err, - }); - }); - }); + setDeleteLoading(true); + api + .invoke("DELETE", `/api/v1/users/${selectedUser.accessKey}`, { + id: selectedUser.id, + }) + .then((res: UsersList) => { + setDeleteLoading(false); + setDeleteError(""); + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setDeleteError(err); + }); + }; + + if (selectedUser === null) { + return
; } - render() { - const { classes, deleteOpen, selectedUser } = this.props; - const { deleteLoading, deleteError } = this.state; - - if (selectedUser === null) { - return
; - } - - return ( - { - this.setState({ deleteError: "" }, () => { - this.props.closeDeleteModalAndRefresh(false); - }); - }} - aria-labelledby="alert-dialog-title" - aria-describedby="alert-dialog-description" - > - Delete User - - {deleteLoading && } - - Are you sure you want to delete user {selectedUser.accessKey} - ? - {deleteError !== "" && ( - -
- - {deleteError} - -
- )} -
-
- - - - -
- ); - } -} + return ( + { + setDeleteError(""); + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete User + + {deleteLoading && } + + Are you sure you want to delete user {selectedUser.accessKey}? + {deleteError !== "" && ( + +
+ + {deleteError} + +
+ )} +
+
+ + + + +
+ ); +}; export default withStyles(styles)(DeleteUser); diff --git a/portal-ui/src/screens/Console/Users/Users.tsx b/portal-ui/src/screens/Console/Users/Users.tsx index 46e8aa882..f275a18f1 100644 --- a/portal-ui/src/screens/Console/Users/Users.tsx +++ b/portal-ui/src/screens/Console/Users/Users.tsx @@ -14,10 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { useEffect, useState } from "react"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import api from "../../../common/api"; -import { Button, Grid, TextField, InputAdornment } from "@material-ui/core"; +import { Button, Grid, InputAdornment, TextField } from "@material-ui/core"; import SearchIcon from "@material-ui/icons/Search"; import GroupIcon from "@material-ui/icons/Group"; import { User, UsersList } from "./types"; @@ -93,246 +93,210 @@ interface IUsersState { setPolicyOpen: boolean; } -class Users extends React.Component { - state: IUsersState = { - records: [], - loading: false, - error: "", - deleteError: "", - addScreenOpen: false, - deleteOpen: false, - selectedUser: null, - addGroupOpen: false, - filter: "", - checkedUsers: [], - setPolicyOpen: false, +const Users = ({ classes }: IUsersProps) => { + const [records, setRecords] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + const [deleteError, setDeleteError] = useState(""); + const [addScreenOpen, setAddScreenOpen] = useState(false); + const [deleteOpen, setDeleteOpen] = useState(false); + const [selectedUser, setSelectedUser] = useState(null); + const [addGroupOpen, setAddGroupOpen] = useState(false); + const [filter, setFilter] = useState(""); + const [checkedUsers, setCheckedUsers] = useState([]); + const [policyOpen, setPolicyOpen] = useState(false); + + const fetchRecords = () => { + setLoading(true); + api + .invoke("GET", `/api/v1/users`) + .then((res: UsersList) => { + const users = res.users === null ? [] : res.users; + + setLoading(false); + setError(""); + setRecords(users.sort(usersSort)); + }) + .catch((err) => { + setLoading(false); + setError(err); + }); }; - fetchRecords() { - this.setState({ loading: true }, () => { - api - .invoke("GET", `/api/v1/users`) - .then((res: UsersList) => { - const users = res.users === null ? [] : res.users; - this.setState({ - loading: false, - records: users.sort(usersSort), - error: "", - }); - }) - .catch((err) => { - this.setState({ loading: false, error: err }); - }); - }); - } + const closeAddModalAndRefresh = () => { + setAddScreenOpen(false); + fetchRecords(); + }; - closeAddModalAndRefresh() { - this.setState({ addScreenOpen: false }, () => { - this.fetchRecords(); - }); - } - - closeDeleteModalAndRefresh(refresh: boolean) { - this.setState({ deleteOpen: false }, () => { - if (refresh) { - this.fetchRecords(); - } - }); - } - - closeAddGroupBulk(unCheckAll: boolean = false) { - let newStates = { addGroupOpen: false }; - let addUsers = {}; + const closeDeleteModalAndRefresh = (refresh: boolean) => { + setDeleteOpen(false); + if (refresh) { + fetchRecords(); + } + }; + const closeAddGroupBulk = (unCheckAll: boolean = false) => { + setAddGroupOpen(false); if (unCheckAll) { - addUsers = { checkedUsers: [] }; + setCheckedUsers([]); + } + }; + + useEffect(() => { + fetchRecords(); + }, []); + + const filteredRecords = records.filter((elementItem) => + elementItem.accessKey.includes(filter) + ); + + const selectionChanged = (e: React.ChangeEvent) => { + const targetD = e.target; + const value = targetD.value; + const checked = targetD.checked; + + let elements: string[] = [...checkedUsers]; // We clone the checkedUsers array + + if (checked) { + // If the user has checked this field we need to push this to checkedUsersList + elements.push(value); + } else { + // User has unchecked this field, we need to remove it from the list + elements = elements.filter((element) => element !== value); } - this.setState({ ...newStates, ...addUsers }); - } + setCheckedUsers(elements); - componentDidMount(): void { - this.fetchRecords(); - } + return elements; + }; - render() { - const { classes } = this.props; - const { - records, - addScreenOpen, - loading, - deleteOpen, - selectedUser, - filter, - checkedUsers, - addGroupOpen, - setPolicyOpen, - } = this.state; + const viewAction = (selectionElement: any): void => { + setAddScreenOpen(true); + setSelectedUser(selectionElement); + }; - const filteredRecords = records.filter((elementItem) => - elementItem.accessKey.includes(filter) - ); + const setPolicyAction = (selectionElement: any): void => { + setPolicyOpen(true); + setSelectedUser(selectionElement); + }; - const selectionChanged = (e: React.ChangeEvent) => { - const targetD = e.target; - const value = targetD.value; - const checked = targetD.checked; + const deleteAction = (selectionElement: any): void => { + setDeleteOpen(true); + setSelectedUser(selectionElement); + }; - let elements: string[] = [...checkedUsers]; // We clone the checkedUsers array + const tableActions = [ + { type: "view", onClick: viewAction }, + { type: "description", onClick: setPolicyAction }, + { type: "delete", onClick: deleteAction }, + ]; - if (checked) { - // If the user has checked this field we need to push this to checkedUsersList - elements.push(value); - } else { - // User has unchecked this field, we need to remove it from the list - elements = elements.filter((element) => element !== value); - } + return ( + + {addScreenOpen && ( + { + closeAddModalAndRefresh(); + }} + /> + )} + {policyOpen && ( + { + setPolicyOpen(false); + fetchRecords(); + }} + /> + )} + {deleteOpen && ( + { + closeDeleteModalAndRefresh(refresh); + }} + /> + )} + {addGroupOpen && ( + { + closeAddGroupBulk(close); + }} + /> + )} + + + + + + + + ), + }} + onChange={(e) => { + setFilter(e.target.value); + }} + /> + + + - this.setState({ - checkedUsers: elements, - }); - - return elements; - }; - - const viewAction = (selectionElement: any): void => { - this.setState({ - addScreenOpen: true, - selectedUser: selectionElement, - }); - }; - - const setPolicyAction = (selectionElement: any): void => { - this.setState({ - setPolicyOpen: true, - selectedUser: selectionElement, - }); - }; - - const deleteAction = (selectionElement: any): void => { - this.setState({ - deleteOpen: true, - selectedUser: selectionElement, - }); - }; - - const tableActions = [ - { type: "view", onClick: viewAction }, - { type: "description", onClick: setPolicyAction }, - { type: "delete", onClick: deleteAction }, - ]; - - return ( - - {addScreenOpen && ( - { - this.closeAddModalAndRefresh(); - }} - /> - )} - {setPolicyOpen && ( - { - this.setState({ setPolicyOpen: false }); - this.fetchRecords(); - }} - /> - )} - {deleteOpen && ( - { - this.closeDeleteModalAndRefresh(refresh); - }} - /> - )} - {addGroupOpen && ( - { - this.closeAddGroupBulk(close); - }} - /> - )} - - - - - - - - ), - }} - onChange={(e) => { - this.setState({ filter: e.target.value }); - }} - /> - - - - - -
-
- - - + +
+
+ +
-
- ); - } -} +
+
+ ); +}; export default withStyles(styles)(Users);