@scality/data-browser-library 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/__tests__/BucketCorsPage.test.js +67 -9
- package/dist/components/__tests__/BucketDetails.test.js +1 -0
- package/dist/components/__tests__/BucketLifecycleFormPage.test.js +16 -11
- package/dist/components/__tests__/BucketNotificationFormPage.test.js +45 -0
- package/dist/components/__tests__/BucketOverview.test.js +92 -2
- package/dist/components/__tests__/BucketPolicyPage.test.js +70 -51
- package/dist/components/__tests__/BucketReplicationFormPage.test.js +51 -24
- package/dist/components/__tests__/ObjectList.test.js +43 -2
- package/dist/components/buckets/BucketConfigEditButton.d.ts +2 -0
- package/dist/components/buckets/BucketConfigEditButton.js +9 -3
- package/dist/components/buckets/BucketCorsPage.js +57 -20
- package/dist/components/buckets/BucketDetails.js +27 -2
- package/dist/components/buckets/BucketLifecycleFormPage.js +310 -270
- package/dist/components/buckets/BucketOverview.js +21 -18
- package/dist/components/buckets/BucketPolicyPage.js +119 -83
- package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
- package/dist/components/buckets/BucketReplicationFormPage.js +165 -129
- package/dist/components/buckets/BucketVersioning.js +16 -10
- package/dist/components/buckets/__tests__/BucketVersioning.test.js +76 -23
- package/dist/components/buckets/notifications/BucketNotificationFormPage.js +13 -5
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +3 -3
- package/dist/components/objects/ObjectList.js +22 -25
- package/dist/components/objects/ObjectLock/EditRetentionButton.js +2 -2
- package/dist/config/types.d.ts +11 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +2 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/objectOperations.d.ts +3 -3
- package/dist/hooks/objectOperations.js +3 -3
- package/dist/hooks/useBucketConfigEditor.d.ts +4 -4
- package/dist/hooks/useBucketConfigEditor.js +16 -31
- package/dist/test/mocks/esmOnlyModules.js +4 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/utils/__tests__/proxyMiddleware.test.js +34 -0
- package/dist/utils/proxyMiddleware.js +2 -0
- package/package.json +4 -4
- package/dist/components/Editor.d.ts +0 -12
- package/dist/components/Editor.js +0 -28
- package/dist/types/monaco.d.ts +0 -13
- package/dist/types/monaco.js +0 -0
|
@@ -4,6 +4,7 @@ import user_event from "@testing-library/user-event";
|
|
|
4
4
|
import { MemoryRouter, Route, Routes } from "react-router";
|
|
5
5
|
import { useGetBucketReplication, useSetBucketReplication } from "../../hooks/bucketConfiguration.js";
|
|
6
6
|
import { useBuckets } from "../../hooks/bucketOperations.js";
|
|
7
|
+
import { useFeatures } from "../../hooks/useFeatures.js";
|
|
7
8
|
import { useISVBucketStatus } from "../../hooks/useISVBucketDetection.js";
|
|
8
9
|
import { createTestWrapper, findToggleByLabel, mockErrorSubmit, mockOffsetSize, mockSuccessSubmit, submitForm } from "../../test/testUtils.js";
|
|
9
10
|
import { BucketReplicationFormPage } from "../buckets/BucketReplicationFormPage.js";
|
|
@@ -14,12 +15,16 @@ jest.mock('../../hooks/bucketConfiguration', ()=>({
|
|
|
14
15
|
jest.mock('../../hooks/bucketOperations', ()=>({
|
|
15
16
|
useBuckets: jest.fn()
|
|
16
17
|
}));
|
|
18
|
+
jest.mock('../../hooks/useFeatures', ()=>({
|
|
19
|
+
useFeatures: jest.fn()
|
|
20
|
+
}));
|
|
17
21
|
jest.mock('../../hooks/useISVBucketDetection', ()=>({
|
|
18
22
|
useISVBucketStatus: jest.fn()
|
|
19
23
|
}));
|
|
20
24
|
const mockUseGetBucketReplication = jest.mocked(useGetBucketReplication);
|
|
21
25
|
const mockUseSetBucketReplication = jest.mocked(useSetBucketReplication);
|
|
22
26
|
const mockUseBuckets = jest.mocked(useBuckets);
|
|
27
|
+
const mockUseFeatures = jest.mocked(useFeatures);
|
|
23
28
|
const mockUseISVBucketStatus = jest.mocked(useISVBucketStatus);
|
|
24
29
|
const mockNavigate = jest.fn();
|
|
25
30
|
const mockShowToast = jest.fn();
|
|
@@ -56,6 +61,12 @@ const renderBucketReplicationFormPage = (bucketName = 'test-bucket', ruleId)=>{
|
|
|
56
61
|
})
|
|
57
62
|
}));
|
|
58
63
|
};
|
|
64
|
+
const findStatusToggle = ()=>{
|
|
65
|
+
const label = document.querySelector('[for="status"]');
|
|
66
|
+
let current = label?.parentElement;
|
|
67
|
+
while(current && !current.querySelector('input[type="checkbox"]'))current = current.parentElement;
|
|
68
|
+
return current?.querySelector('input[type="checkbox"]');
|
|
69
|
+
};
|
|
59
70
|
describe('BucketReplicationFormPage', ()=>{
|
|
60
71
|
const mockMutate = jest.fn();
|
|
61
72
|
const fillRequiredFields = async (options)=>{
|
|
@@ -101,6 +112,7 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
101
112
|
},
|
|
102
113
|
status: 'success'
|
|
103
114
|
});
|
|
115
|
+
mockUseFeatures.mockReturnValue(true);
|
|
104
116
|
mockUseISVBucketStatus.mockReturnValue({
|
|
105
117
|
isVeeamBucket: false,
|
|
106
118
|
isCommvaultBucket: false,
|
|
@@ -185,7 +197,7 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
185
197
|
expect(screen.getByRole('textbox', {
|
|
186
198
|
name: /rule id/i
|
|
187
199
|
})).toBeInTheDocument();
|
|
188
|
-
expect(
|
|
200
|
+
expect(document.querySelector('[id="label-status"]')).toBeInTheDocument();
|
|
189
201
|
expect(screen.getByLabelText(/target bucket/i)).toBeInTheDocument();
|
|
190
202
|
});
|
|
191
203
|
it('shows Role ARN input when no existing rules', ()=>{
|
|
@@ -256,15 +268,15 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
256
268
|
name: /rule id/i
|
|
257
269
|
})).not.toBeInTheDocument();
|
|
258
270
|
});
|
|
259
|
-
it('renders Status
|
|
271
|
+
it('renders Status toggle field', async ()=>{
|
|
260
272
|
renderBucketReplicationFormPage();
|
|
261
273
|
await waitFor(()=>{
|
|
262
274
|
expect(screen.getByRole('textbox', {
|
|
263
275
|
name: /rule id/i
|
|
264
276
|
})).toBeInTheDocument();
|
|
265
277
|
});
|
|
266
|
-
const
|
|
267
|
-
expect(
|
|
278
|
+
const statusToggle = findStatusToggle();
|
|
279
|
+
expect(statusToggle).toBeInTheDocument();
|
|
268
280
|
});
|
|
269
281
|
it('renders Priority number input with auto-assigned placeholder', ()=>{
|
|
270
282
|
renderBucketReplicationFormPage();
|
|
@@ -892,11 +904,8 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
892
904
|
await waitFor(()=>{
|
|
893
905
|
expect(screen.getByText('Edit Replication Rule')).toBeInTheDocument();
|
|
894
906
|
});
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
await user_event.click(screen.getByRole('option', {
|
|
898
|
-
name: 'Disabled'
|
|
899
|
-
}));
|
|
907
|
+
const statusToggle = findStatusToggle();
|
|
908
|
+
fireEvent.click(statusToggle);
|
|
900
909
|
mockMutate.mockImplementation((_, options)=>{
|
|
901
910
|
options?.onSuccess?.();
|
|
902
911
|
});
|
|
@@ -942,11 +951,8 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
942
951
|
await waitFor(()=>{
|
|
943
952
|
expect(screen.getByText('Edit Replication Rule')).toBeInTheDocument();
|
|
944
953
|
});
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
await user_event.click(screen.getByRole('option', {
|
|
948
|
-
name: 'Disabled'
|
|
949
|
-
}));
|
|
954
|
+
const statusToggle = findStatusToggle();
|
|
955
|
+
fireEvent.click(statusToggle);
|
|
950
956
|
mockMutate.mockImplementation((_, options)=>{
|
|
951
957
|
options?.onSuccess?.();
|
|
952
958
|
});
|
|
@@ -987,11 +993,8 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
987
993
|
await waitFor(()=>{
|
|
988
994
|
expect(screen.getByText('Edit Replication Rule')).toBeInTheDocument();
|
|
989
995
|
});
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
await user_event.click(screen.getByRole('option', {
|
|
993
|
-
name: 'Disabled'
|
|
994
|
-
}));
|
|
996
|
+
const statusToggle = findStatusToggle();
|
|
997
|
+
fireEvent.click(statusToggle);
|
|
995
998
|
mockMutate.mockImplementation((_, options)=>{
|
|
996
999
|
options?.onSuccess?.();
|
|
997
1000
|
});
|
|
@@ -1036,11 +1039,8 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
1036
1039
|
await waitFor(()=>{
|
|
1037
1040
|
expect(screen.getByText('Edit Replication Rule')).toBeInTheDocument();
|
|
1038
1041
|
});
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
await user_event.click(screen.getByRole('option', {
|
|
1042
|
-
name: 'Disabled'
|
|
1043
|
-
}));
|
|
1042
|
+
const statusToggle = findStatusToggle();
|
|
1043
|
+
fireEvent.click(statusToggle);
|
|
1044
1044
|
const error = new Error('Network Error');
|
|
1045
1045
|
mockMutate.mockImplementation((_, options)=>{
|
|
1046
1046
|
options?.onError?.(error);
|
|
@@ -1952,4 +1952,31 @@ describe('BucketReplicationFormPage', ()=>{
|
|
|
1952
1952
|
expect(screen.getByText(/bucket used for external integration with Kasten/i)).toBeInTheDocument();
|
|
1953
1953
|
});
|
|
1954
1954
|
});
|
|
1955
|
+
describe('Feature Flag - replicationAdvanced', ()=>{
|
|
1956
|
+
it('hides Additional Options section when replicationAdvanced is disabled', ()=>{
|
|
1957
|
+
mockUseFeatures.mockReturnValue(false);
|
|
1958
|
+
renderBucketReplicationFormPage();
|
|
1959
|
+
expect(screen.queryByText('Replication Time Control (RTC)')).not.toBeInTheDocument();
|
|
1960
|
+
expect(screen.queryByText('RTC metrics and notifications')).not.toBeInTheDocument();
|
|
1961
|
+
expect(screen.queryByText('Replica modification sync')).not.toBeInTheDocument();
|
|
1962
|
+
expect(screen.queryByText('Delete marker replication')).not.toBeInTheDocument();
|
|
1963
|
+
});
|
|
1964
|
+
it('hides switchObjectOwnership toggle when replicationAdvanced is disabled', async ()=>{
|
|
1965
|
+
mockUseFeatures.mockReturnValue(false);
|
|
1966
|
+
renderBucketReplicationFormPage();
|
|
1967
|
+
const sameAccountToggle = findToggleByLabel('Same account destination');
|
|
1968
|
+
await user_event.click(sameAccountToggle);
|
|
1969
|
+
await waitFor(()=>{
|
|
1970
|
+
expect(screen.queryByText('Switch Object ownership')).not.toBeInTheDocument();
|
|
1971
|
+
});
|
|
1972
|
+
});
|
|
1973
|
+
it('shows Additional Options section when replicationAdvanced is enabled', ()=>{
|
|
1974
|
+
mockUseFeatures.mockReturnValue(true);
|
|
1975
|
+
renderBucketReplicationFormPage();
|
|
1976
|
+
expect(screen.getByText('Replication Time Control (RTC)')).toBeInTheDocument();
|
|
1977
|
+
expect(screen.getByText('RTC metrics and notifications')).toBeInTheDocument();
|
|
1978
|
+
expect(screen.getByText('Replica modification sync')).toBeInTheDocument();
|
|
1979
|
+
expect(screen.getByText('Delete marker replication')).toBeInTheDocument();
|
|
1980
|
+
});
|
|
1981
|
+
});
|
|
1955
1982
|
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { act, fireEvent, render, renderHook, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import { HttpResponse, http } from "msw";
|
|
3
4
|
import { MemoryRouter } from "react-router";
|
|
4
5
|
import { DataBrowserUICustomizationProvider } from "../../contexts/DataBrowserUICustomizationContext.js";
|
|
5
|
-
import { useListObjectVersions, useListObjects } from "../../hooks/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { useListObjectVersions, useListObjects, useSearchObjects } from "../../hooks/index.js";
|
|
7
|
+
import { getS3BaseUrl } from "../../test/msw/utils.js";
|
|
8
|
+
import { createTestWrapper, mockOffsetSize, overrideHandlers, setupMswServer } from "../../test/testUtils.js";
|
|
7
9
|
import { ObjectList } from "../objects/ObjectList.js";
|
|
8
10
|
import * as __rspack_external__hooks_useFeatures_js_a6a84786 from "../../hooks/useFeatures.js";
|
|
9
11
|
setupMswServer();
|
|
@@ -391,6 +393,45 @@ describe('ObjectList', ()=>{
|
|
|
391
393
|
});
|
|
392
394
|
jest.useRealTimers();
|
|
393
395
|
});
|
|
396
|
+
it('passes the search query parameter to the S3 request when metadata search is active', async ()=>{
|
|
397
|
+
let capturedSearchParam = null;
|
|
398
|
+
overrideHandlers(http.get(`${getS3BaseUrl()}/:bucketName`, async ({ request })=>{
|
|
399
|
+
const url = new URL(request.url);
|
|
400
|
+
if ('2' !== url.searchParams.get('list-type')) return;
|
|
401
|
+
capturedSearchParam = url.searchParams.get('search');
|
|
402
|
+
return HttpResponse.xml(`<?xml version="1.0" encoding="UTF-8"?>
|
|
403
|
+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
404
|
+
<Name>test-bucket</Name>
|
|
405
|
+
<Prefix></Prefix>
|
|
406
|
+
<Delimiter>/</Delimiter>
|
|
407
|
+
<MaxKeys>100</MaxKeys>
|
|
408
|
+
<IsTruncated>false</IsTruncated>
|
|
409
|
+
<Contents>
|
|
410
|
+
<Key>matched-file.pdf</Key>
|
|
411
|
+
<LastModified>2023-10-12T17:50:00.000Z</LastModified>
|
|
412
|
+
<ETag>"abc123"</ETag>
|
|
413
|
+
<Size>2048</Size>
|
|
414
|
+
<StorageClass>STANDARD</StorageClass>
|
|
415
|
+
</Contents>
|
|
416
|
+
</ListBucketResult>`, {
|
|
417
|
+
status: 200
|
|
418
|
+
});
|
|
419
|
+
}));
|
|
420
|
+
const searchQuery = 'key like /pdf$/';
|
|
421
|
+
const { result } = renderHook(()=>useSearchObjects({
|
|
422
|
+
Bucket: 'test-bucket',
|
|
423
|
+
Prefix: '',
|
|
424
|
+
MaxKeys: 100,
|
|
425
|
+
Delimiter: '/',
|
|
426
|
+
Query: searchQuery
|
|
427
|
+
}), {
|
|
428
|
+
wrapper: createTestWrapper()
|
|
429
|
+
});
|
|
430
|
+
await waitFor(()=>{
|
|
431
|
+
expect(result.current.isSuccess).toBe(true);
|
|
432
|
+
});
|
|
433
|
+
expect(capturedSearchParam).toBe(searchQuery);
|
|
434
|
+
});
|
|
394
435
|
});
|
|
395
436
|
describe('Multi-Selection', ()=>{
|
|
396
437
|
it('integrates with MultiSelectableContent', async ()=>{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Icon, spacing } from "@scality/core-ui";
|
|
3
3
|
import { Box, Button } from "@scality/core-ui/dist/next";
|
|
4
|
-
const BucketConfigEditButton = ({ hasConfig, isLoading, onEdit, configName })=>{
|
|
4
|
+
const BucketConfigEditButton = ({ hasConfig, isLoading, onEdit, configName, disabled, tooltipOverlay })=>{
|
|
5
5
|
const action = hasConfig ? 'Edit' : 'Create';
|
|
6
6
|
return /*#__PURE__*/ jsx(Box, {
|
|
7
7
|
display: "flex",
|
|
@@ -12,10 +12,16 @@ const BucketConfigEditButton = ({ hasConfig, isLoading, onEdit, configName })=>{
|
|
|
12
12
|
variant: "outline",
|
|
13
13
|
label: action,
|
|
14
14
|
icon: /*#__PURE__*/ jsx(Icon, {
|
|
15
|
-
name: hasConfig ? '
|
|
15
|
+
name: hasConfig ? 'Pencil' : 'Create-add'
|
|
16
16
|
}),
|
|
17
17
|
onClick: onEdit,
|
|
18
|
-
"aria-label": `${action} ${configName}
|
|
18
|
+
"aria-label": `${action} ${configName}`,
|
|
19
|
+
disabled: disabled,
|
|
20
|
+
...tooltipOverlay && {
|
|
21
|
+
tooltip: {
|
|
22
|
+
overlay: tooltipOverlay
|
|
23
|
+
}
|
|
24
|
+
}
|
|
19
25
|
})
|
|
20
26
|
});
|
|
21
27
|
};
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Form, FormGroup, FormSection, Icon, Loader, Stack, Text, useToast } from "@scality/core-ui";
|
|
3
|
-
import { Box, Button, CopyButton } from "@scality/core-ui/dist/next";
|
|
4
|
-
import { useCallback, useMemo } from "react";
|
|
3
|
+
import { Box, Button, CopyButton, Editor } from "@scality/core-ui/dist/next";
|
|
4
|
+
import { useCallback, useEffect, useMemo } from "react";
|
|
5
5
|
import { Controller } from "react-hook-form";
|
|
6
6
|
import { useParams } from "react-router";
|
|
7
|
-
import { useBucketConfigEditor, useDeleteBucketCors, useGetBucketCors, useSetBucketCors } from "../../hooks/index.js";
|
|
8
|
-
import {
|
|
7
|
+
import { useBucketConfigEditor, useDeleteBucketCors, useGetBucketCors, useISVBucketStatus, useSetBucketCors } from "../../hooks/index.js";
|
|
8
|
+
import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
|
|
9
|
+
import { isNotFoundError } from "../../utils/errorHandling.js";
|
|
9
10
|
const DEFAULT_CORS_TEMPLATE = `[
|
|
10
11
|
{
|
|
11
12
|
"AllowedHeaders": [
|
|
12
13
|
"Authorization"
|
|
13
14
|
],
|
|
14
15
|
"AllowedMethods": [
|
|
15
|
-
"GET"
|
|
16
|
+
"GET",
|
|
17
|
+
"PUT"
|
|
16
18
|
],
|
|
17
19
|
"AllowedOrigins": [
|
|
18
20
|
"*"
|
|
@@ -47,22 +49,35 @@ const validateCorsConfig = (content)=>{
|
|
|
47
49
|
const BucketCorsPage = ()=>{
|
|
48
50
|
const { bucketName } = useParams();
|
|
49
51
|
const { showToast } = useToast();
|
|
52
|
+
const { isISVManaged, isLoading: isISVLoading } = useISVBucketStatus(bucketName);
|
|
53
|
+
const navigate = useDataBrowserNavigate();
|
|
54
|
+
useEffect(()=>{
|
|
55
|
+
if (isISVManaged) navigate(`/buckets/${bucketName}`, {
|
|
56
|
+
replace: true
|
|
57
|
+
});
|
|
58
|
+
}, [
|
|
59
|
+
isISVManaged,
|
|
60
|
+
bucketName,
|
|
61
|
+
navigate
|
|
62
|
+
]);
|
|
63
|
+
const shouldFetchData = !isISVManaged && !isISVLoading;
|
|
50
64
|
const { data: corsData, status: corsStatus, error: corsError } = useGetBucketCors({
|
|
51
65
|
Bucket: bucketName
|
|
66
|
+
}, {
|
|
67
|
+
enabled: shouldFetchData
|
|
52
68
|
});
|
|
53
69
|
const initialContent = useMemo(()=>{
|
|
70
|
+
if (isNotFoundError(corsError)) return;
|
|
54
71
|
if (corsData?.CORSRules && corsData.CORSRules.length > 0) return JSON.stringify(corsData.CORSRules);
|
|
55
72
|
}, [
|
|
56
|
-
corsData
|
|
73
|
+
corsData,
|
|
74
|
+
corsError
|
|
57
75
|
]);
|
|
58
|
-
const { form, content, isCreateMode, isValidFormat,
|
|
76
|
+
const { form, content, isCreateMode, isValidFormat, navigateToBucket, loadTemplate } = useBucketConfigEditor({
|
|
59
77
|
bucketName: bucketName,
|
|
60
78
|
initialContent,
|
|
61
79
|
defaultTemplate: DEFAULT_CORS_TEMPLATE,
|
|
62
80
|
isLoading: 'pending' === corsStatus,
|
|
63
|
-
notFoundErrorNames: [
|
|
64
|
-
'NoSuchCORSConfiguration'
|
|
65
|
-
],
|
|
66
81
|
errorInstance: corsError,
|
|
67
82
|
validate: validateCorsConfig
|
|
68
83
|
});
|
|
@@ -121,7 +136,8 @@ const BucketCorsPage = ()=>{
|
|
|
121
136
|
setError
|
|
122
137
|
]);
|
|
123
138
|
const isPending = isSaving || isDeleting;
|
|
124
|
-
|
|
139
|
+
if (isISVManaged || isISVLoading) return null;
|
|
140
|
+
const hasUnexpectedError = corsError && !isNotFoundError(corsError);
|
|
125
141
|
if ('pending' === corsStatus) return /*#__PURE__*/ jsx(Loader, {
|
|
126
142
|
centered: true,
|
|
127
143
|
size: "massive",
|
|
@@ -200,6 +216,11 @@ const BucketCorsPage = ()=>{
|
|
|
200
216
|
direction: "vertical",
|
|
201
217
|
error: errors.content?.message,
|
|
202
218
|
content: /*#__PURE__*/ jsxs(Stack, {
|
|
219
|
+
direction: "horizontal",
|
|
220
|
+
gap: "r16",
|
|
221
|
+
style: {
|
|
222
|
+
alignItems: 'flex-start'
|
|
223
|
+
},
|
|
203
224
|
children: [
|
|
204
225
|
/*#__PURE__*/ jsx(Controller, {
|
|
205
226
|
control: control,
|
|
@@ -212,17 +233,33 @@ const BucketCorsPage = ()=>{
|
|
|
212
233
|
},
|
|
213
234
|
language: "json",
|
|
214
235
|
height: "60vh",
|
|
215
|
-
width: "33rem"
|
|
216
|
-
beforeMount: handleBeforeMount
|
|
236
|
+
width: "33rem"
|
|
217
237
|
})
|
|
218
238
|
}),
|
|
219
|
-
/*#__PURE__*/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
239
|
+
/*#__PURE__*/ jsxs(Stack, {
|
|
240
|
+
direction: "vertical",
|
|
241
|
+
gap: "r8",
|
|
242
|
+
children: [
|
|
243
|
+
/*#__PURE__*/ jsx(CopyButton, {
|
|
244
|
+
textToCopy: content,
|
|
245
|
+
label: "CORS",
|
|
246
|
+
variant: "outline"
|
|
247
|
+
}),
|
|
248
|
+
isCreateMode && !content && /*#__PURE__*/ jsx(Text, {
|
|
249
|
+
variant: "Smaller",
|
|
250
|
+
color: "textSecondary",
|
|
251
|
+
children: "Empty CORS rule"
|
|
252
|
+
}),
|
|
253
|
+
isCreateMode && !content && /*#__PURE__*/ jsx(Button, {
|
|
254
|
+
variant: "outline",
|
|
255
|
+
label: "Load a template",
|
|
256
|
+
onClick: loadTemplate,
|
|
257
|
+
type: "button",
|
|
258
|
+
style: {
|
|
259
|
+
minWidth: '9rem'
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
]
|
|
226
263
|
})
|
|
227
264
|
]
|
|
228
265
|
})
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
2
3
|
import { Tabs } from "@scality/core-ui/dist/next";
|
|
3
4
|
import { createContext, memo, useCallback, useContext, useMemo } from "react";
|
|
4
5
|
import { useParams } from "react-router";
|
|
6
|
+
import { useDataBrowserContext } from "../providers/DataBrowserProvider.js";
|
|
5
7
|
import { useDataBrowserUICustomization } from "../../contexts/DataBrowserUICustomizationContext.js";
|
|
6
8
|
import { useGetBucketLifecycle, useGetBucketNotification, useGetBucketReplication } from "../../hooks/bucketConfiguration.js";
|
|
7
9
|
import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
|
|
@@ -30,12 +32,35 @@ const ExtraSectionContent = /*#__PURE__*/ memo(({ render })=>/*#__PURE__*/ jsx(F
|
|
|
30
32
|
children: render()
|
|
31
33
|
}));
|
|
32
34
|
ExtraSectionContent.displayName = 'BucketDetails.ExtraSectionContent';
|
|
35
|
+
const LIST_BUCKETS_QUERY_KEY = 'ListBuckets';
|
|
33
36
|
const OverviewTab = /*#__PURE__*/ memo(()=>{
|
|
34
37
|
const { bucketName, navigate } = useBucketDetailsContext();
|
|
35
38
|
const { extraBucketOverviewSections } = useDataBrowserUICustomization();
|
|
39
|
+
const queryClient = useQueryClient();
|
|
40
|
+
const { s3ConfigIdentifier } = useDataBrowserContext();
|
|
41
|
+
const handleDeleteSuccess = useCallback(()=>{
|
|
42
|
+
queryClient.setQueriesData({
|
|
43
|
+
queryKey: [
|
|
44
|
+
s3ConfigIdentifier,
|
|
45
|
+
LIST_BUCKETS_QUERY_KEY
|
|
46
|
+
]
|
|
47
|
+
}, (prev)=>prev?.Buckets ? {
|
|
48
|
+
...prev,
|
|
49
|
+
Buckets: prev.Buckets.filter((b)=>b.Name !== bucketName)
|
|
50
|
+
} : prev);
|
|
51
|
+
navigate('/buckets');
|
|
52
|
+
}, [
|
|
53
|
+
queryClient,
|
|
54
|
+
s3ConfigIdentifier,
|
|
55
|
+
navigate,
|
|
56
|
+
bucketName
|
|
57
|
+
]);
|
|
36
58
|
const renderDeleteButton = useCallback((name)=>/*#__PURE__*/ jsx(DeleteBucketButton, {
|
|
37
|
-
bucketName: name
|
|
38
|
-
|
|
59
|
+
bucketName: name,
|
|
60
|
+
onDeleteSuccess: handleDeleteSuccess
|
|
61
|
+
}), [
|
|
62
|
+
handleDeleteSuccess
|
|
63
|
+
]);
|
|
39
64
|
const renderEmptyButton = useCallback((name)=>/*#__PURE__*/ jsx(EmptyBucketButton, {
|
|
40
65
|
bucketName: name
|
|
41
66
|
}), []);
|