@scality/data-browser-library 1.0.0-preview.13 → 1.0.0-preview.16

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 (212) hide show
  1. package/dist/components/DataBrowserUI.d.ts +6 -14
  2. package/dist/components/DataBrowserUI.js +79 -55
  3. package/dist/components/Editor.d.ts +1 -1
  4. package/dist/components/Editor.js +3 -3
  5. package/dist/components/__tests__/BucketCreate.test.js +102 -102
  6. package/dist/components/__tests__/BucketDetails.test.js +122 -123
  7. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +177 -177
  8. package/dist/components/__tests__/BucketLifecycleList.test.js +85 -85
  9. package/dist/components/__tests__/BucketList.test.js +175 -176
  10. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +84 -84
  11. package/dist/components/__tests__/BucketOverview.test.js +257 -201
  12. package/dist/components/__tests__/BucketPolicyPage.test.js +62 -62
  13. package/dist/components/__tests__/BucketReplicationFormPage.test.js +542 -542
  14. package/dist/components/__tests__/BucketReplicationList.test.js +106 -106
  15. package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
  16. package/dist/components/__tests__/DeleteBucketButton.test.js +62 -62
  17. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +47 -47
  18. package/dist/components/__tests__/DeleteObjectButton.test.js +63 -63
  19. package/dist/components/__tests__/EmptyBucketButton.test.js +56 -56
  20. package/dist/components/__tests__/MetadataSearch.test.js +65 -65
  21. package/dist/components/__tests__/ObjectList.test.js +252 -251
  22. package/dist/components/__tests__/UploadButton.test.js +45 -45
  23. package/dist/components/buckets/BucketCreate.d.ts +2 -2
  24. package/dist/components/buckets/BucketCreate.js +41 -41
  25. package/dist/components/buckets/BucketDetails.d.ts +2 -2
  26. package/dist/components/buckets/BucketDetails.js +48 -36
  27. package/dist/components/buckets/BucketLifecycleFormPage.js +161 -160
  28. package/dist/components/buckets/BucketLifecycleList.d.ts +2 -2
  29. package/dist/components/buckets/BucketLifecycleList.js +46 -46
  30. package/dist/components/buckets/BucketList.d.ts +2 -2
  31. package/dist/components/buckets/BucketList.js +28 -27
  32. package/dist/components/buckets/BucketLocation.js +3 -3
  33. package/dist/components/buckets/BucketOverview.d.ts +1 -1
  34. package/dist/components/buckets/BucketOverview.js +64 -65
  35. package/dist/components/buckets/BucketPage.js +19 -11
  36. package/dist/components/buckets/BucketPolicyButton.js +2 -2
  37. package/dist/components/buckets/BucketPolicyPage.js +27 -25
  38. package/dist/components/buckets/BucketReplicationFormPage.js +133 -132
  39. package/dist/components/buckets/BucketReplicationList.d.ts +2 -2
  40. package/dist/components/buckets/BucketReplicationList.js +41 -41
  41. package/dist/components/buckets/BucketVersioning.js +11 -11
  42. package/dist/components/buckets/DeleteBucketButton.js +5 -5
  43. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +2 -2
  44. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +1 -1
  45. package/dist/components/buckets/EmptyBucketButton.js +19 -19
  46. package/dist/components/buckets/EmptyBucketSummary.d.ts +1 -1
  47. package/dist/components/buckets/EmptyBucketSummary.js +1 -1
  48. package/dist/components/buckets/EmptyBucketSummaryList.js +22 -22
  49. package/dist/components/buckets/__tests__/BucketVersioning.test.js +45 -45
  50. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +34 -33
  51. package/dist/components/buckets/notifications/EventsSection.js +144 -28
  52. package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
  53. package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
  54. package/dist/components/buckets/notifications/events.d.ts +71 -7
  55. package/dist/components/buckets/notifications/events.js +98 -16
  56. package/dist/components/index.d.ts +24 -22
  57. package/dist/components/index.js +5 -3
  58. package/dist/components/layouts/ArrowNavigation.d.ts +1 -2
  59. package/dist/components/layouts/ArrowNavigation.js +3 -3
  60. package/dist/components/layouts/BrowserPageLayout.d.ts +2 -3
  61. package/dist/components/layouts/BrowserPageLayout.js +1 -1
  62. package/dist/components/objects/CreateFolderButton.d.ts +2 -2
  63. package/dist/components/objects/CreateFolderButton.js +9 -9
  64. package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
  65. package/dist/components/objects/DeleteObjectButton.js +20 -20
  66. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +1 -1
  67. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +56 -56
  68. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +1 -1
  69. package/dist/components/objects/ObjectDetails/ObjectSummary.js +39 -39
  70. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +1 -1
  71. package/dist/components/objects/ObjectDetails/ObjectTags.js +25 -25
  72. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +119 -119
  73. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +211 -211
  74. package/dist/components/objects/ObjectDetails/index.d.ts +1 -1
  75. package/dist/components/objects/ObjectDetails/index.js +30 -30
  76. package/dist/components/objects/ObjectList.d.ts +5 -5
  77. package/dist/components/objects/ObjectList.js +113 -112
  78. package/dist/components/objects/ObjectLock/EditRetentionButton.js +3 -3
  79. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +14 -14
  80. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +1 -1
  81. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +29 -28
  82. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +1 -1
  83. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +6 -6
  84. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +50 -50
  85. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +77 -77
  86. package/dist/components/objects/ObjectPage.js +5 -4
  87. package/dist/components/objects/UploadButton.d.ts +3 -3
  88. package/dist/components/objects/UploadButton.js +5 -5
  89. package/dist/components/providers/DataBrowserProvider.d.ts +23 -12
  90. package/dist/components/providers/DataBrowserProvider.js +60 -38
  91. package/dist/components/providers/QueryProvider.d.ts +9 -0
  92. package/dist/components/providers/QueryProvider.js +22 -0
  93. package/dist/components/search/MetadataSearch.js +26 -25
  94. package/dist/components/search/SearchHints.js +1 -1
  95. package/dist/components/ui/ArrayFieldActions.js +4 -4
  96. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +1 -1
  97. package/dist/components/ui/ConfirmDeleteRuleModal.js +1 -1
  98. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  99. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  100. package/dist/components/ui/FilterFormSection.d.ts +2 -2
  101. package/dist/components/ui/FilterFormSection.js +29 -29
  102. package/dist/components/ui/Search.elements.d.ts +1 -1
  103. package/dist/components/ui/Search.elements.js +7 -7
  104. package/dist/components/ui/Table.elements.js +5 -5
  105. package/dist/config/factory.d.ts +23 -10
  106. package/dist/config/factory.js +22 -7
  107. package/dist/config/types.d.ts +20 -3
  108. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +2 -2
  109. package/dist/hooks/__tests__/useISVBucketDetection.test.js +42 -42
  110. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +25 -25
  111. package/dist/hooks/bucketConfiguration.d.ts +1 -1
  112. package/dist/hooks/bucketConfiguration.js +48 -48
  113. package/dist/hooks/bucketOperations.d.ts +1 -1
  114. package/dist/hooks/bucketOperations.js +6 -6
  115. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +78 -78
  116. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +78 -78
  117. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +42 -42
  118. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +61 -61
  119. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +63 -63
  120. package/dist/hooks/factories/index.d.ts +4 -4
  121. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  122. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +15 -12
  123. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  124. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  125. package/dist/hooks/factories/useCreateS3MutationHook.js +6 -1
  126. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  127. package/dist/hooks/factories/useCreateS3QueryHook.js +8 -5
  128. package/dist/hooks/index.d.ts +16 -13
  129. package/dist/hooks/index.js +4 -1
  130. package/dist/hooks/loginOperations.d.ts +1 -1
  131. package/dist/hooks/loginOperations.js +1 -1
  132. package/dist/hooks/objectOperations.d.ts +2 -2
  133. package/dist/hooks/objectOperations.js +49 -49
  134. package/dist/hooks/presignedOperations.d.ts +2 -2
  135. package/dist/hooks/presignedOperations.js +3 -3
  136. package/dist/hooks/useBatchObjectLegalHold.js +7 -4
  137. package/dist/hooks/useDataBrowserNavigate.d.ts +28 -0
  138. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  139. package/dist/hooks/useDeleteBucketConfigRule.d.ts +2 -2
  140. package/dist/hooks/useDeleteBucketConfigRule.js +4 -4
  141. package/dist/hooks/useEmptyBucket.js +10 -10
  142. package/dist/hooks/useFeatures.d.ts +7 -0
  143. package/dist/hooks/useFeatures.js +8 -0
  144. package/dist/hooks/useISVBucketDetection.js +5 -5
  145. package/dist/hooks/useIsBucketEmpty.js +4 -4
  146. package/dist/hooks/useLoginMutation.d.ts +1 -1
  147. package/dist/hooks/useLoginMutation.js +1 -1
  148. package/dist/hooks/useS3Client.d.ts +6 -0
  149. package/dist/hooks/useS3Client.js +3 -2
  150. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  151. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  152. package/dist/hooks/useSupportedNotificationEvents.d.ts +6 -0
  153. package/dist/hooks/useSupportedNotificationEvents.js +8 -0
  154. package/dist/index.d.ts +6 -6
  155. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  156. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  157. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  158. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  159. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  160. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  161. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  162. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  163. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  164. package/dist/test/msw/handlers/headObject.js +31 -13
  165. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  166. package/dist/test/msw/handlers/listBuckets.js +5 -3
  167. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  168. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  169. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  170. package/dist/test/msw/handlers/listObjects.js +35 -23
  171. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  172. package/dist/test/msw/handlers/objectLegalHold.js +31 -16
  173. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  174. package/dist/test/msw/handlers/objectRetention.js +31 -17
  175. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  176. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  177. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  178. package/dist/test/msw/handlers/putObject.js +27 -12
  179. package/dist/test/msw/handlers.d.ts +3 -3
  180. package/dist/test/msw/handlers.js +72 -49
  181. package/dist/test/msw/index.d.ts +2 -2
  182. package/dist/test/msw/server.d.ts +1 -1
  183. package/dist/test/msw/server.js +1 -1
  184. package/dist/test/msw/utils.js +2 -2
  185. package/dist/test/setup.d.ts +1 -1
  186. package/dist/test/setup.js +19 -19
  187. package/dist/test/testUtils.d.ts +9 -15
  188. package/dist/test/testUtils.js +73 -91
  189. package/dist/test/utils/errorHandling.test.js +119 -119
  190. package/dist/types/index.d.ts +6 -31
  191. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  192. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +429 -0
  193. package/dist/utils/constants.js +8 -8
  194. package/dist/utils/deletion/index.d.ts +2 -2
  195. package/dist/utils/deletion/messages.d.ts +1 -1
  196. package/dist/utils/deletion/messages.js +4 -4
  197. package/dist/utils/errorHandling.d.ts +3 -3
  198. package/dist/utils/errorHandling.js +6 -6
  199. package/dist/utils/hooks.js +8 -8
  200. package/dist/utils/index.d.ts +5 -4
  201. package/dist/utils/index.js +2 -0
  202. package/dist/utils/proxyMiddleware.d.ts +1 -1
  203. package/dist/utils/proxyMiddleware.js +6 -11
  204. package/dist/utils/s3Client.d.ts +2 -2
  205. package/dist/utils/s3Client.js +1 -1
  206. package/dist/utils/s3ConfigIdentifier.d.ts +68 -0
  207. package/dist/utils/s3ConfigIdentifier.js +55 -0
  208. package/dist/utils/s3RuleUtils.d.ts +5 -5
  209. package/dist/utils/s3RuleUtils.js +17 -17
  210. package/package.json +2 -2
  211. package/dist/utils/useFeatures.d.ts +0 -1
  212. package/dist/utils/useFeatures.js +0 -7
@@ -1,22 +1,22 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
3
  import user_event from "@testing-library/user-event";
4
- import { MemoryRouter, Route, Routes } from "react-router-dom";
4
+ import { MemoryRouter, Route, Routes } from "react-router";
5
5
  import { createTestWrapper } from "../../../../test/testUtils.js";
6
6
  import { ObjectLockSettings } from "../ObjectLockSettings.js";
7
7
  import { useGetBucketObjectLockConfiguration, useSetBucketObjectLockConfiguration } from "../../../../hooks/index.js";
8
- jest.mock("../../../../hooks", ()=>({
8
+ jest.mock('../../../../hooks', ()=>({
9
9
  useGetBucketObjectLockConfiguration: jest.fn(),
10
10
  useSetBucketObjectLockConfiguration: jest.fn()
11
11
  }));
12
12
  const mockUseGetBucketObjectLockConfiguration = jest.mocked(useGetBucketObjectLockConfiguration);
13
13
  const mockUseSetBucketObjectLockConfiguration = jest.mocked(useSetBucketObjectLockConfiguration);
14
14
  const mockNavigate = jest.fn();
15
- jest.mock("react-router-dom", ()=>({
16
- ...jest.requireActual("react-router-dom"),
15
+ jest.mock('react-router', ()=>({
16
+ ...jest.requireActual('react-router'),
17
17
  useNavigate: ()=>mockNavigate
18
18
  }));
19
- const renderObjectLockSettings = (bucketName = "test-bucket")=>{
19
+ const renderObjectLockSettings = (bucketName = 'test-bucket')=>{
20
20
  const Wrapper = createTestWrapper();
21
21
  return render(/*#__PURE__*/ jsx(MemoryRouter, {
22
22
  initialEntries: [
@@ -32,74 +32,74 @@ const renderObjectLockSettings = (bucketName = "test-bucket")=>{
32
32
  })
33
33
  }));
34
34
  };
35
- describe("ObjectLockSettings", ()=>{
35
+ describe('ObjectLockSettings', ()=>{
36
36
  const mockMutate = jest.fn();
37
37
  beforeEach(()=>{
38
38
  jest.clearAllMocks();
39
39
  mockNavigate.mockClear();
40
40
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
41
41
  data: void 0,
42
- status: "success"
42
+ status: 'success'
43
43
  });
44
44
  mockUseSetBucketObjectLockConfiguration.mockReturnValue({
45
45
  mutate: mockMutate,
46
46
  isPending: false
47
47
  });
48
48
  });
49
- it("displays loading state while fetching bucket configuration", ()=>{
49
+ it('displays loading state while fetching bucket configuration', ()=>{
50
50
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
51
51
  data: void 0,
52
- status: "pending"
52
+ status: 'pending'
53
53
  });
54
54
  renderObjectLockSettings();
55
- expect(screen.getByText("Loading retention settings...")).toBeInTheDocument();
55
+ expect(screen.getByText('Loading retention settings...')).toBeInTheDocument();
56
56
  });
57
- it("renders form with Object Lock checkbox", async ()=>{
57
+ it('renders form with Object Lock checkbox', async ()=>{
58
58
  renderObjectLockSettings();
59
59
  await waitFor(()=>{
60
- expect(screen.getByText("Object-lock settings")).toBeInTheDocument();
60
+ expect(screen.getByText('Object-lock settings')).toBeInTheDocument();
61
61
  });
62
62
  expect(screen.getByLabelText(/object-lock/i)).toBeInTheDocument();
63
63
  });
64
- it("disables save button when Object Lock is not enabled", async ()=>{
64
+ it('disables save button when Object Lock is not enabled', async ()=>{
65
65
  renderObjectLockSettings();
66
66
  await waitFor(()=>{
67
- const saveButton = screen.getByRole("button", {
67
+ const saveButton = screen.getByRole('button', {
68
68
  name: /save/i
69
69
  });
70
70
  expect(saveButton).toBeDisabled();
71
71
  });
72
72
  });
73
- it("shows Default Retention fields when Object Lock is enabled", async ()=>{
73
+ it('shows Default Retention fields when Object Lock is enabled', async ()=>{
74
74
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
75
75
  data: {
76
76
  ObjectLockConfiguration: {
77
- ObjectLockEnabled: "Enabled"
77
+ ObjectLockEnabled: 'Enabled'
78
78
  }
79
79
  },
80
- status: "success"
80
+ status: 'success'
81
81
  });
82
82
  renderObjectLockSettings();
83
83
  await waitFor(()=>{
84
- expect(screen.getByText("Default Retention")).toBeInTheDocument();
85
- expect(screen.getByText("Retention mode")).toBeInTheDocument();
86
- expect(screen.getByText("Retention period")).toBeInTheDocument();
84
+ expect(screen.getByText('Default Retention')).toBeInTheDocument();
85
+ expect(screen.getByText('Retention mode')).toBeInTheDocument();
86
+ expect(screen.getByText('Retention period')).toBeInTheDocument();
87
87
  }, {
88
88
  timeout: 3000
89
89
  });
90
90
  });
91
- it("enables save button when Object Lock is enabled", async ()=>{
91
+ it('enables save button when Object Lock is enabled', async ()=>{
92
92
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
93
93
  data: {
94
94
  ObjectLockConfiguration: {
95
- ObjectLockEnabled: "Enabled"
95
+ ObjectLockEnabled: 'Enabled'
96
96
  }
97
97
  },
98
- status: "success"
98
+ status: 'success'
99
99
  });
100
100
  renderObjectLockSettings();
101
101
  await waitFor(()=>{
102
- const saveButton = screen.getByRole("button", {
102
+ const saveButton = screen.getByRole('button', {
103
103
  name: /save/i
104
104
  });
105
105
  expect(saveButton).toBeEnabled();
@@ -107,18 +107,18 @@ describe("ObjectLockSettings", ()=>{
107
107
  timeout: 3000
108
108
  });
109
109
  });
110
- it("enables retention fields when Default Retention is checked", async ()=>{
110
+ it('enables retention fields when Default Retention is checked', async ()=>{
111
111
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
112
112
  data: {
113
113
  ObjectLockConfiguration: {
114
- ObjectLockEnabled: "Enabled"
114
+ ObjectLockEnabled: 'Enabled'
115
115
  }
116
116
  },
117
- status: "success"
117
+ status: 'success'
118
118
  });
119
119
  renderObjectLockSettings();
120
120
  await waitFor(()=>{
121
- expect(screen.getByText("Default Retention")).toBeInTheDocument();
121
+ expect(screen.getByText('Default Retention')).toBeInTheDocument();
122
122
  });
123
123
  const defaultRetentionCheckbox = screen.getByLabelText(/default retention/i);
124
124
  expect(defaultRetentionCheckbox).not.toBeChecked();
@@ -130,20 +130,20 @@ describe("ObjectLockSettings", ()=>{
130
130
  timeout: 3000
131
131
  });
132
132
  });
133
- it("disables retention fields when Default Retention is unchecked", async ()=>{
133
+ it('disables retention fields when Default Retention is unchecked', async ()=>{
134
134
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
135
135
  data: {
136
136
  ObjectLockConfiguration: {
137
- ObjectLockEnabled: "Enabled",
137
+ ObjectLockEnabled: 'Enabled',
138
138
  Rule: {
139
139
  DefaultRetention: {
140
- Mode: "GOVERNANCE",
140
+ Mode: 'GOVERNANCE',
141
141
  Days: 30
142
142
  }
143
143
  }
144
144
  }
145
145
  },
146
- status: "success"
146
+ status: 'success'
147
147
  });
148
148
  renderObjectLockSettings();
149
149
  await waitFor(()=>{
@@ -155,18 +155,18 @@ describe("ObjectLockSettings", ()=>{
155
155
  expect(governanceRadio).toBeDisabled();
156
156
  });
157
157
  });
158
- it("shows validation error when retention period is invalid", async ()=>{
158
+ it('shows validation error when retention period is invalid', async ()=>{
159
159
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
160
160
  data: {
161
161
  ObjectLockConfiguration: {
162
- ObjectLockEnabled: "Enabled"
162
+ ObjectLockEnabled: 'Enabled'
163
163
  }
164
164
  },
165
- status: "success"
165
+ status: 'success'
166
166
  });
167
167
  renderObjectLockSettings();
168
168
  await waitFor(()=>{
169
- expect(screen.getByText("Default Retention")).toBeInTheDocument();
169
+ expect(screen.getByText('Default Retention')).toBeInTheDocument();
170
170
  });
171
171
  const defaultRetentionCheckbox = screen.getByLabelText(/default retention/i);
172
172
  fireEvent.click(defaultRetentionCheckbox);
@@ -176,9 +176,9 @@ describe("ObjectLockSettings", ()=>{
176
176
  });
177
177
  const retentionPeriodInput = screen.getByLabelText(/retention period/i);
178
178
  await user_event.clear(retentionPeriodInput);
179
- await user_event.type(retentionPeriodInput, "0");
179
+ await user_event.type(retentionPeriodInput, '0');
180
180
  await waitFor(()=>{
181
- const saveButton = screen.getByRole("button", {
181
+ const saveButton = screen.getByRole('button', {
182
182
  name: /save/i
183
183
  });
184
184
  expect(saveButton).toBeDisabled();
@@ -186,18 +186,18 @@ describe("ObjectLockSettings", ()=>{
186
186
  timeout: 3000
187
187
  });
188
188
  });
189
- it("saves Object Lock configuration with Default Retention and navigates on success", async ()=>{
189
+ it('saves Object Lock configuration with Default Retention and navigates on success', async ()=>{
190
190
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
191
191
  data: {
192
192
  ObjectLockConfiguration: {
193
- ObjectLockEnabled: "Enabled"
193
+ ObjectLockEnabled: 'Enabled'
194
194
  }
195
195
  },
196
- status: "success"
196
+ status: 'success'
197
197
  });
198
198
  renderObjectLockSettings();
199
199
  await waitFor(()=>{
200
- expect(screen.getByText("Default Retention")).toBeInTheDocument();
200
+ expect(screen.getByText('Default Retention')).toBeInTheDocument();
201
201
  });
202
202
  const defaultRetentionCheckbox = screen.getByLabelText(/default retention/i);
203
203
  fireEvent.click(defaultRetentionCheckbox);
@@ -207,13 +207,13 @@ describe("ObjectLockSettings", ()=>{
207
207
  });
208
208
  const retentionPeriodInput = screen.getByLabelText(/retention period/i);
209
209
  await user_event.clear(retentionPeriodInput);
210
- await user_event.type(retentionPeriodInput, "30");
210
+ await user_event.type(retentionPeriodInput, '30');
211
211
  const governanceRadio = screen.getByLabelText(/governance/i);
212
212
  fireEvent.click(governanceRadio);
213
213
  mockMutate.mockImplementation((_, options)=>{
214
214
  options?.onSuccess?.();
215
215
  });
216
- const saveButton = screen.getByRole("button", {
216
+ const saveButton = screen.getByRole('button', {
217
217
  name: /save/i
218
218
  });
219
219
  await waitFor(()=>expect(saveButton).toBeEnabled(), {
@@ -223,25 +223,25 @@ describe("ObjectLockSettings", ()=>{
223
223
  await waitFor(()=>{
224
224
  expect(mockMutate).toHaveBeenCalled();
225
225
  const callArgs = mockMutate.mock.calls[0][0];
226
- expect(callArgs.Bucket).toBe("test-bucket");
227
- expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe("Enabled");
228
- expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Mode).toBe("GOVERNANCE");
226
+ expect(callArgs.Bucket).toBe('test-bucket');
227
+ expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe('Enabled');
228
+ expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Mode).toBe('GOVERNANCE');
229
229
  expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Days || callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Years).toBe(30);
230
- expect(mockNavigate).toHaveBeenCalledWith("/buckets/test-bucket");
230
+ expect(mockNavigate).toHaveBeenCalledWith('/buckets/test-bucket');
231
231
  });
232
232
  });
233
- it("saves Object Lock configuration with Years frequency", async ()=>{
233
+ it('saves Object Lock configuration with Years frequency', async ()=>{
234
234
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
235
235
  data: {
236
236
  ObjectLockConfiguration: {
237
- ObjectLockEnabled: "Enabled"
237
+ ObjectLockEnabled: 'Enabled'
238
238
  }
239
239
  },
240
- status: "success"
240
+ status: 'success'
241
241
  });
242
242
  renderObjectLockSettings();
243
243
  await waitFor(()=>{
244
- expect(screen.getByText("Default Retention")).toBeInTheDocument();
244
+ expect(screen.getByText('Default Retention')).toBeInTheDocument();
245
245
  });
246
246
  const defaultRetentionCheckbox = screen.getByLabelText(/default retention/i);
247
247
  fireEvent.click(defaultRetentionCheckbox);
@@ -251,11 +251,11 @@ describe("ObjectLockSettings", ()=>{
251
251
  });
252
252
  const retentionPeriodInput = screen.getByLabelText(/retention period/i);
253
253
  await user_event.clear(retentionPeriodInput);
254
- await user_event.type(retentionPeriodInput, "2");
254
+ await user_event.type(retentionPeriodInput, '2');
255
255
  mockMutate.mockImplementation((_, options)=>{
256
256
  options?.onSuccess?.();
257
257
  });
258
- const saveButton = screen.getByRole("button", {
258
+ const saveButton = screen.getByRole('button', {
259
259
  name: /save/i
260
260
  });
261
261
  await waitFor(()=>expect(saveButton).toBeEnabled(), {
@@ -265,24 +265,24 @@ describe("ObjectLockSettings", ()=>{
265
265
  await waitFor(()=>{
266
266
  expect(mockMutate).toHaveBeenCalled();
267
267
  const callArgs = mockMutate.mock.calls[0][0];
268
- expect(callArgs.Bucket).toBe("test-bucket");
269
- expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe("Enabled");
270
- expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Mode).toBe("GOVERNANCE");
268
+ expect(callArgs.Bucket).toBe('test-bucket');
269
+ expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe('Enabled');
270
+ expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Mode).toBe('GOVERNANCE');
271
271
  expect(callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Days || callArgs.ObjectLockConfiguration.Rule.DefaultRetention.Years).toBe(2);
272
272
  });
273
273
  });
274
- it("saves Object Lock configuration without Default Retention", async ()=>{
274
+ it('saves Object Lock configuration without Default Retention', async ()=>{
275
275
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
276
276
  data: {
277
277
  ObjectLockConfiguration: {
278
- ObjectLockEnabled: "Enabled"
278
+ ObjectLockEnabled: 'Enabled'
279
279
  }
280
280
  },
281
- status: "success"
281
+ status: 'success'
282
282
  });
283
283
  renderObjectLockSettings();
284
284
  await waitFor(()=>{
285
- const saveButton = screen.getByRole("button", {
285
+ const saveButton = screen.getByRole('button', {
286
286
  name: /save/i
287
287
  });
288
288
  expect(saveButton).toBeEnabled();
@@ -292,41 +292,41 @@ describe("ObjectLockSettings", ()=>{
292
292
  mockMutate.mockImplementation((_, options)=>{
293
293
  options?.onSuccess?.();
294
294
  });
295
- const saveButton = screen.getByRole("button", {
295
+ const saveButton = screen.getByRole('button', {
296
296
  name: /save/i
297
297
  });
298
298
  fireEvent.click(saveButton);
299
299
  await waitFor(()=>{
300
300
  expect(mockMutate).toHaveBeenCalled();
301
301
  const callArgs = mockMutate.mock.calls[0][0];
302
- expect(callArgs.Bucket).toBe("test-bucket");
303
- expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe("Enabled");
302
+ expect(callArgs.Bucket).toBe('test-bucket');
303
+ expect(callArgs.ObjectLockConfiguration.ObjectLockEnabled).toBe('Enabled');
304
304
  expect(callArgs.ObjectLockConfiguration.Rule).toBeUndefined();
305
305
  });
306
306
  });
307
- it("displays error toast when save fails", async ()=>{
307
+ it('displays error toast when save fails', async ()=>{
308
308
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
309
309
  data: {
310
310
  ObjectLockConfiguration: {
311
- ObjectLockEnabled: "Enabled"
311
+ ObjectLockEnabled: 'Enabled'
312
312
  }
313
313
  },
314
- status: "success"
314
+ status: 'success'
315
315
  });
316
316
  renderObjectLockSettings();
317
317
  await waitFor(()=>{
318
- const saveButton = screen.getByRole("button", {
318
+ const saveButton = screen.getByRole('button', {
319
319
  name: /save/i
320
320
  });
321
321
  expect(saveButton).toBeEnabled();
322
322
  }, {
323
323
  timeout: 3000
324
324
  });
325
- const error = new Error("Access Denied");
325
+ const error = new Error('Access Denied');
326
326
  mockMutate.mockImplementation((_, options)=>{
327
327
  options?.onError?.(error);
328
328
  });
329
- const saveButton = screen.getByRole("button", {
329
+ const saveButton = screen.getByRole('button', {
330
330
  name: /save/i
331
331
  });
332
332
  fireEvent.click(saveButton);
@@ -334,30 +334,30 @@ describe("ObjectLockSettings", ()=>{
334
334
  expect(mockNavigate).not.toHaveBeenCalled();
335
335
  });
336
336
  });
337
- it("navigates back when cancel button is clicked", async ()=>{
337
+ it('navigates back when cancel button is clicked', async ()=>{
338
338
  renderObjectLockSettings();
339
339
  await waitFor(()=>{
340
- const cancelButton = screen.getByRole("button", {
340
+ const cancelButton = screen.getByRole('button', {
341
341
  name: /cancel/i
342
342
  });
343
343
  fireEvent.click(cancelButton);
344
344
  });
345
- expect(mockNavigate).toHaveBeenCalledWith("/buckets/test-bucket");
345
+ expect(mockNavigate).toHaveBeenCalledWith('/buckets/test-bucket');
346
346
  });
347
- it("populates form with existing bucket configuration", async ()=>{
347
+ it('populates form with existing bucket configuration', async ()=>{
348
348
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
349
349
  data: {
350
350
  ObjectLockConfiguration: {
351
- ObjectLockEnabled: "Enabled",
351
+ ObjectLockEnabled: 'Enabled',
352
352
  Rule: {
353
353
  DefaultRetention: {
354
- Mode: "COMPLIANCE",
354
+ Mode: 'COMPLIANCE',
355
355
  Days: 60
356
356
  }
357
357
  }
358
358
  }
359
359
  },
360
- status: "success"
360
+ status: 'success'
361
361
  });
362
362
  renderObjectLockSettings();
363
363
  await waitFor(()=>{
@@ -1,18 +1,19 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useNavigate, useParams, useSearchParams } from "react-router-dom";
2
+ import { useParams, useSearchParams } from "react-router";
3
3
  import { useCallback, useState } from "react";
4
4
  import { ObjectList } from "./ObjectList.js";
5
5
  import { ObjectDetails } from "./ObjectDetails/index.js";
6
6
  import { BrowserPageLayout } from "../layouts/BrowserPageLayout.js";
7
+ import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
7
8
  const ObjectPage = ()=>{
8
9
  const { bucketName } = useParams();
9
- const navigate = useNavigate();
10
+ const navigate = useDataBrowserNavigate();
10
11
  const [searchParams] = useSearchParams();
11
12
  const [item, setItem] = useState(null);
12
- const prefix = searchParams.get("prefix") || "";
13
+ const prefix = searchParams.get('prefix') || '';
13
14
  const handlePrefixChange = useCallback((newPrefix)=>{
14
15
  const newSearchParams = new URLSearchParams(searchParams);
15
- newSearchParams.set("prefix", newPrefix);
16
+ newSearchParams.set('prefix', newPrefix);
16
17
  setItem(null);
17
18
  navigate(`?${newSearchParams.toString()}`, {
18
19
  replace: true
@@ -1,5 +1,5 @@
1
- import React from "react";
2
- import type { PutObjectCommandInput } from "@aws-sdk/client-s3";
1
+ import React from 'react';
2
+ import type { PutObjectCommandInput } from '@aws-sdk/client-s3';
3
3
  interface UploadButtonProps {
4
4
  /**
5
5
  * The S3 bucket name where files will be uploaded
@@ -16,7 +16,7 @@ interface UploadButtonProps {
16
16
  /**
17
17
  * Button variant
18
18
  */
19
- variant?: "primary" | "secondary" | "outline";
19
+ variant?: 'primary' | 'secondary' | 'outline';
20
20
  /**
21
21
  * Upload options to configure metadata, encryption, etc.
22
22
  */
@@ -51,7 +51,7 @@ const RemoveButton = styled_components.button`
51
51
  }
52
52
  `;
53
53
  const maybePluralize = (count, word)=>1 === count ? `1 ${word}` : `${count} ${word}s`;
54
- const getTitle = (fileCount)=>0 === fileCount ? "Upload Files" : `Upload ${maybePluralize(fileCount, "file")}`;
54
+ const getTitle = (fileCount)=>0 === fileCount ? 'Upload Files' : `Upload ${maybePluralize(fileCount, 'file')}`;
55
55
  const FileList = ({ acceptedFiles, open, removeFile })=>/*#__PURE__*/ jsxs("div", {
56
56
  children: [
57
57
  /*#__PURE__*/ jsx(Button, {
@@ -111,7 +111,7 @@ const NoFile = ({ open })=>/*#__PURE__*/ jsxs(EmptyFile, {
111
111
  })
112
112
  ]
113
113
  });
114
- const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, onUploadSuccess, onUploadError })=>{
114
+ const UploadButton_UploadButton = ({ bucket, prefix = '', uploadOptions = {}, onUploadSuccess, onUploadError })=>{
115
115
  const [isModalOpen, setIsModalOpen] = useState(false);
116
116
  const [acceptedFiles, setAcceptedFiles] = useState([]);
117
117
  const uploadMutation = useUploadObjects();
@@ -177,8 +177,8 @@ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, on
177
177
  icon: /*#__PURE__*/ jsx(Icon, {
178
178
  name: "Simple-upload"
179
179
  }),
180
- label: "Upload",
181
- variant: "secondary",
180
+ label: 'Upload',
181
+ variant: 'secondary',
182
182
  onClick: openModal
183
183
  }),
184
184
  isModalOpen && /*#__PURE__*/ jsx(Modal, {
@@ -198,7 +198,7 @@ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, on
198
198
  disabled: 0 === acceptedFiles.length || uploadMutation.isPending,
199
199
  variant: "primary",
200
200
  onClick: handleUpload,
201
- label: uploadMutation.isPending ? "Uploading..." : "Upload"
201
+ label: uploadMutation.isPending ? 'Uploading...' : 'Upload'
202
202
  })
203
203
  ]
204
204
  })
@@ -1,20 +1,31 @@
1
- import React from "react";
2
- import { QueryClient } from "@tanstack/react-query";
3
- import { GetConfigFunction } from "../../types";
4
- import { CoreUITheme } from "@scality/core-ui/dist/style/theme";
1
+ import React from 'react';
2
+ import { QueryClient, InvalidateQueryFilters, QueryKey } from '@tanstack/react-query';
3
+ import { GetConfigFunction } from '../../types';
4
+ import { CoreUITheme } from '@scality/core-ui/dist/next';
5
5
  export interface DataBrowserContextValue {
6
- getS3Config: GetConfigFunction;
7
- theme: CoreUITheme;
6
+ getS3Config: GetConfigFunction | null;
7
+ s3ConfigIdentifier: string;
8
8
  }
9
- export declare const DataBrowserContext: React.Context<DataBrowserContextValue | null>;
9
+ export declare const DataBrowserContext: React.Context<DataBrowserContextValue>;
10
10
  export declare const useDataBrowserContext: () => DataBrowserContextValue;
11
- export declare const useDataBrowserTheme: () => CoreUITheme;
12
- interface DataBrowserProviderProps {
11
+ export interface DataBrowserProviderProps {
13
12
  children: React.ReactNode;
14
- queryClient?: QueryClient;
15
- enableDevtools?: boolean;
16
13
  getS3Config?: GetConfigFunction;
14
+ queryClient?: QueryClient;
17
15
  theme?: CoreUITheme;
16
+ enableDevtools?: boolean;
18
17
  }
19
18
  export declare const DataBrowserProvider: React.FC<DataBrowserProviderProps>;
20
- export {};
19
+ export declare const useDataBrowserConfig: () => import("../../types").S3BrowserConfig & {
20
+ credentials: import("../../types").S3Credentials;
21
+ };
22
+ /**
23
+ * Hook to invalidate queries with automatic S3 config identifier prefixing.
24
+ *
25
+ * @example
26
+ * const invalidateQueries = useInvalidateQueries();
27
+ * await invalidateQueries({ queryKey: ['ListObjects', { Bucket: 'my-bucket' }] });
28
+ */
29
+ export declare const useInvalidateQueries: () => (filters: Omit<InvalidateQueryFilters, "queryKey"> & {
30
+ queryKey: QueryKey;
31
+ }) => Promise<void>;
@@ -1,42 +1,64 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { createContext, useContext } from "react";
3
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
- import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
5
- const DataBrowserContext = /*#__PURE__*/ createContext(null);
6
- const useDataBrowserContext = ()=>{
7
- const context = useContext(DataBrowserContext);
8
- if (!context) throw new Error("useDataBrowserContext must be used within a DataBrowserProvider component");
9
- return context;
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useMemo } from "react";
3
+ import { useQueryClient } from "@tanstack/react-query";
4
+ import { ANONYMOUS_S3_CONFIG_IDENTIFIER, computeS3ConfigIdentifier } from "../../utils/s3ConfigIdentifier.js";
5
+ import { QueryProvider } from "./QueryProvider.js";
6
+ import { CoreUiThemeProvider } from "@scality/core-ui/dist/next";
7
+ import { coreUIAvailableThemes } from "@scality/core-ui/dist/style/theme";
8
+ const DEFAULT_CONTEXT_VALUE = {
9
+ getS3Config: null,
10
+ s3ConfigIdentifier: ANONYMOUS_S3_CONFIG_IDENTIFIER
10
11
  };
11
- const useDataBrowserTheme = ()=>{
12
- const { theme } = useDataBrowserContext();
13
- return theme;
14
- };
15
- const defaultQueryClient = new QueryClient({
16
- defaultOptions: {
17
- queries: {
18
- staleTime: 300000,
19
- retry: 2
20
- }
21
- }
22
- });
23
- const DataBrowserProvider = ({ children, queryClient = defaultQueryClient, enableDevtools = "development" === process.env.NODE_ENV, getS3Config, theme })=>{
24
- const content = /*#__PURE__*/ jsxs(QueryClientProvider, {
25
- client: queryClient,
26
- children: [
27
- children,
28
- enableDevtools && /*#__PURE__*/ jsx(ReactQueryDevtools, {
29
- initialIsOpen: false
12
+ const DataBrowserContext = /*#__PURE__*/ createContext(DEFAULT_CONTEXT_VALUE);
13
+ const useDataBrowserContext = ()=>useContext(DataBrowserContext);
14
+ const DataBrowserProvider = ({ children, queryClient, theme, enableDevtools, getS3Config })=>{
15
+ const currentConfig = getS3Config?.();
16
+ const s3ConfigIdentifier = useMemo(()=>currentConfig ? computeS3ConfigIdentifier(currentConfig) : ANONYMOUS_S3_CONFIG_IDENTIFIER, [
17
+ currentConfig?.credentials?.accessKeyId,
18
+ currentConfig?.credentials?.roleArn,
19
+ currentConfig?.credentials?.sessionToken,
20
+ currentConfig?.region,
21
+ currentConfig?.endpoint
22
+ ]);
23
+ const contextValue = useMemo(()=>({
24
+ getS3Config: getS3Config ?? null,
25
+ s3ConfigIdentifier
26
+ }), [
27
+ getS3Config,
28
+ s3ConfigIdentifier
29
+ ]);
30
+ return /*#__PURE__*/ jsx(CoreUiThemeProvider, {
31
+ theme: theme ?? coreUIAvailableThemes.darkRebrand,
32
+ children: /*#__PURE__*/ jsx(QueryProvider, {
33
+ queryClient: queryClient,
34
+ enableDevtools: enableDevtools,
35
+ children: /*#__PURE__*/ jsx(DataBrowserContext.Provider, {
36
+ value: contextValue,
37
+ children: children
30
38
  })
31
- ]
32
- });
33
- if (getS3Config && theme) return /*#__PURE__*/ jsx(DataBrowserContext.Provider, {
34
- value: {
35
- getS3Config,
36
- theme
37
- },
38
- children: content
39
+ })
39
40
  });
40
- return content;
41
41
  };
42
- export { DataBrowserContext, DataBrowserProvider, useDataBrowserContext, useDataBrowserTheme };
42
+ const useDataBrowserConfig = ()=>{
43
+ const { getS3Config } = useDataBrowserContext();
44
+ if (!getS3Config) throw new Error("useDataBrowserConfig: S3 config not available. Ensure DataBrowserProvider has getS3Config prop set.");
45
+ return getS3Config();
46
+ };
47
+ const useInvalidateQueries = ()=>{
48
+ const { s3ConfigIdentifier } = useDataBrowserContext();
49
+ const queryClient = useQueryClient();
50
+ return useCallback((filters)=>{
51
+ const { queryKey, ...rest } = filters;
52
+ return queryClient.invalidateQueries({
53
+ ...rest,
54
+ queryKey: [
55
+ s3ConfigIdentifier,
56
+ ...queryKey
57
+ ]
58
+ });
59
+ }, [
60
+ queryClient,
61
+ s3ConfigIdentifier
62
+ ]);
63
+ };
64
+ export { DataBrowserContext, DataBrowserProvider, useDataBrowserConfig, useDataBrowserContext, useInvalidateQueries };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { QueryClient } from '@tanstack/react-query';
3
+ export interface QueryProviderProps {
4
+ children: React.ReactNode;
5
+ queryClient?: QueryClient;
6
+ enableDevtools?: boolean;
7
+ }
8
+ export declare const defaultQueryClient: QueryClient;
9
+ export declare const QueryProvider: React.FC<QueryProviderProps>;