@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.
Files changed (41) hide show
  1. package/dist/components/__tests__/BucketCorsPage.test.js +67 -9
  2. package/dist/components/__tests__/BucketDetails.test.js +1 -0
  3. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +16 -11
  4. package/dist/components/__tests__/BucketNotificationFormPage.test.js +45 -0
  5. package/dist/components/__tests__/BucketOverview.test.js +92 -2
  6. package/dist/components/__tests__/BucketPolicyPage.test.js +70 -51
  7. package/dist/components/__tests__/BucketReplicationFormPage.test.js +51 -24
  8. package/dist/components/__tests__/ObjectList.test.js +43 -2
  9. package/dist/components/buckets/BucketConfigEditButton.d.ts +2 -0
  10. package/dist/components/buckets/BucketConfigEditButton.js +9 -3
  11. package/dist/components/buckets/BucketCorsPage.js +57 -20
  12. package/dist/components/buckets/BucketDetails.js +27 -2
  13. package/dist/components/buckets/BucketLifecycleFormPage.js +310 -270
  14. package/dist/components/buckets/BucketOverview.js +21 -18
  15. package/dist/components/buckets/BucketPolicyPage.js +119 -83
  16. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  17. package/dist/components/buckets/BucketReplicationFormPage.js +165 -129
  18. package/dist/components/buckets/BucketVersioning.js +16 -10
  19. package/dist/components/buckets/__tests__/BucketVersioning.test.js +76 -23
  20. package/dist/components/buckets/notifications/BucketNotificationFormPage.js +13 -5
  21. package/dist/components/index.d.ts +1 -1
  22. package/dist/components/index.js +2 -2
  23. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +3 -3
  24. package/dist/components/objects/ObjectList.js +22 -25
  25. package/dist/components/objects/ObjectLock/EditRetentionButton.js +2 -2
  26. package/dist/config/types.d.ts +11 -0
  27. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +2 -0
  28. package/dist/hooks/index.d.ts +1 -1
  29. package/dist/hooks/objectOperations.d.ts +3 -3
  30. package/dist/hooks/objectOperations.js +3 -3
  31. package/dist/hooks/useBucketConfigEditor.d.ts +4 -4
  32. package/dist/hooks/useBucketConfigEditor.js +16 -31
  33. package/dist/test/mocks/esmOnlyModules.js +4 -0
  34. package/dist/types/index.d.ts +0 -1
  35. package/dist/utils/__tests__/proxyMiddleware.test.js +34 -0
  36. package/dist/utils/proxyMiddleware.js +2 -0
  37. package/package.json +4 -4
  38. package/dist/components/Editor.d.ts +0 -12
  39. package/dist/components/Editor.js +0 -28
  40. package/dist/types/monaco.d.ts +0 -13
  41. 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(screen.getByLabelText(/status/i)).toBeInTheDocument();
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 select field', async ()=>{
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 statusElement = document.querySelector('[id="status"]');
267
- expect(statusElement).toBeInTheDocument();
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 statusSelect = screen.getByLabelText(/status/i);
896
- await user_event.click(statusSelect);
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 statusSelect = screen.getByLabelText(/status/i);
946
- await user_event.click(statusSelect);
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 statusSelect = screen.getByLabelText(/status/i);
991
- await user_event.click(statusSelect);
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 statusSelect = screen.getByLabelText(/status/i);
1040
- await user_event.click(statusSelect);
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 { createTestWrapper, mockOffsetSize, setupMswServer } from "../../test/testUtils.js";
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>&quot;abc123&quot;</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 ()=>{
@@ -3,6 +3,8 @@ interface BucketConfigEditButtonProps {
3
3
  isLoading?: boolean;
4
4
  onEdit: () => void;
5
5
  configName: string;
6
+ disabled?: boolean;
7
+ tooltipOverlay?: string;
6
8
  }
7
9
  export declare const BucketConfigEditButton: React.FC<BucketConfigEditButtonProps>;
8
10
  export {};
@@ -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 ? 'Pen' : 'Create-add'
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 { Editor } from "../Editor.js";
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, handleBeforeMount, navigateToBucket } = useBucketConfigEditor({
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
- const hasUnexpectedError = corsError && 'NoSuchCORSConfiguration' !== corsError.name;
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__*/ jsx(Box, {
220
- alignSelf: "baseline",
221
- children: /*#__PURE__*/ jsx(CopyButton, {
222
- textToCopy: content,
223
- label: "CORS",
224
- variant: "outline"
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
  }), []);