From bdcf36badaaf5db2368ee3e8f0fa4b950a28afa1 Mon Sep 17 00:00:00 2001 From: YanJin Date: Mon, 6 Nov 2023 18:07:04 +0100 Subject: [PATCH 1/3] ZKUI-397: implement the logic of getBucketTagging and add use-case session in bucket overview --- src/js/mock/S3ClientMSWHandlers.ts | 67 ++++++++++ .../databrowser/buckets/details/Overview.tsx | 115 ++++++++++++++---- .../details/__tests__/Overview.test.tsx | 76 ++++++++++-- .../domain/business/buckets.test.tsx | 58 ++++++++- .../domain/business/buckets.ts | 44 +++++++ .../domain/entities/bucket.ts | 4 + src/react/reducers/initialConstants.ts | 2 +- src/react/ui-elements/Veeam/VeeamTable.tsx | 8 ++ src/react/ui-elements/Veeam/useMockData.ts | 12 +- src/react/utils/testUtil.tsx | 10 +- 10 files changed, 358 insertions(+), 38 deletions(-) diff --git a/src/js/mock/S3ClientMSWHandlers.ts b/src/js/mock/S3ClientMSWHandlers.ts index 789986f0c..84e2a3ca9 100644 --- a/src/js/mock/S3ClientMSWHandlers.ts +++ b/src/js/mock/S3ClientMSWHandlers.ts @@ -118,6 +118,43 @@ export function mockBucketOperations( ); } + if (req.url.searchParams.has('cors')) { + return res( + ctx.xml(` + + + + `), + ); + } + + if (req.url.searchParams.has('acl')) { + return res( + ctx.xml(` + + + + 1234 + test + + + + + `), + ); + } + + if (req.url.searchParams.has('object-lock')) { + return res( + ctx.xml(` + + + Enabled + + `), + ); + } + return res(ctx.status(404)); }, ); @@ -178,3 +215,33 @@ export const mockObjectEmpty = (bucketName: string) => { }, ); }; + +export const mockGetBucketTagging = (bucketName: string) => { + return rest.get( + `${zenkoUITestConfig.zenkoEndpoint}/${bucketName}`, + (req, res, ctx) => { + if (req.url.searchParams.has('tagging')) { + return res( + ctx.xml(` + + + + X-Scality-UsecaseVeeam 12 + + `), + ); + } + }, + ); +}; + +export const mockGetBucketTaggingError = (bucketName: string) => { + return rest.get( + `${zenkoUITestConfig.zenkoEndpoint}/${bucketName}`, + (req, res, ctx) => { + if (req.url.searchParams.has('tagging')) { + return res(ctx.status(500)); + } + }, + ); +}; diff --git a/src/react/databrowser/buckets/details/Overview.tsx b/src/react/databrowser/buckets/details/Overview.tsx index ba11b3c9e..a890b38f0 100644 --- a/src/react/databrowser/buckets/details/Overview.tsx +++ b/src/react/databrowser/buckets/details/Overview.tsx @@ -1,4 +1,10 @@ -import { ConstrainedText, Icon, Toggle, Tooltip } from '@scality/core-ui'; +import { + ConstrainedText, + Icon, + Toast, + Toggle, + Tooltip, +} from '@scality/core-ui'; import { SmallerText } from '@scality/core-ui/dist/components/text/Text.component'; import { useHistory } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; @@ -10,7 +16,10 @@ import type { BucketInfo } from '../../../../types/s3'; import type { AppState } from '../../../../types/state'; import { useCurrentAccount } from '../../../DataServiceRoleProvider'; import { getBucketInfo, toggleBucketVersioning } from '../../../actions'; -import { useChangeBucketVersionning } from '../../../next-architecture/domain/business/buckets'; +import { + useBucketTagging, + useChangeBucketVersionning, +} from '../../../next-architecture/domain/business/buckets'; import { Bucket } from '../../../next-architecture/domain/entities/bucket'; import { ButtonContainer } from '../../../ui-elements/Container'; import { DeleteBucket } from '../../../ui-elements/DeleteBucket'; @@ -26,6 +35,11 @@ import { import { useWorkflows } from '../../../workflow/Workflows'; import { useEffect, useState } from 'react'; import { Button } from '@scality/core-ui/dist/next'; +import { + BUCKET_TAG_USECASE, + VEEAMVERSION11, + VEEAMVERSION12, +} from '../../../ui-elements/Veeam/VeeamConstants'; function capitalize(string: string) { return string.toLowerCase().replace(/^\w/, (c) => { @@ -88,6 +102,17 @@ function Overview({ bucket, ingestionStates }: Props) { const features = useSelector((state: AppState) => state.auth.config.features); const { account } = useCurrentAccount(); const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); + const [bucketTaggingToast, setBucketTaggingToast] = useState(true); + const { tags } = useBucketTagging({ bucketName: bucket.name }); + const VEEAM_FEATURE_FLAG_ENABLED = features.includes('Veeam'); + const isVeeamBucket = + tags.status === 'success' && + (tags.value?.[BUCKET_TAG_USECASE] === VEEAMVERSION11 || + tags.value?.[BUCKET_TAG_USECASE] === VEEAMVERSION12) && + VEEAM_FEATURE_FLAG_ENABLED; + + const isVeeam12 = + isVeeamBucket && tags.value?.[BUCKET_TAG_USECASE] === VEEAMVERSION12; useEffect(() => { dispatch(getBucketInfo(bucket.name)); @@ -136,6 +161,14 @@ function Overview({ bucket, ingestionStates }: Props) { : null } /> + { + setBucketTaggingToast(false); + }} + /> @@ -208,6 +241,58 @@ function Overview({ bucket, ingestionStates }: Props) { )} + + Location + + {bucketInfo.locationConstraint || 'us-east-1'} + {' / '} + + {locations && + getLocationType(locations[bucketInfo.locationConstraint])} + + + + {features.includes(XDM_FEATURE) && ( + + Async Metadata updates + + {ingestionValue} + {isIngestion && } + + + )} + + + {isVeeamBucket && ( + + Use-case + + Use-case + Backup - {tags.value?.[BUCKET_TAG_USECASE]} + + {isVeeam12 && ( + + Max repository Capacity + + {/* TODO */} + <>5TB +