@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
@@ -5,13 +5,13 @@ import { createMockMutationResult, createTestWrapper, findToggleByLabel } from "
5
5
  import { BucketVersioning } from "../BucketVersioning.js";
6
6
  import { BucketOverviewContext } from "../BucketOverview.js";
7
7
  const mockShowToast = jest.fn();
8
- jest.mock("@scality/core-ui", ()=>({
9
- ...jest.requireActual("@scality/core-ui"),
8
+ jest.mock('@scality/core-ui', ()=>({
9
+ ...jest.requireActual('@scality/core-ui'),
10
10
  useToast: ()=>({
11
11
  showToast: mockShowToast
12
12
  })
13
13
  }));
14
- jest.mock("../../../hooks");
14
+ jest.mock('../../../hooks');
15
15
  const mockUseGetBucketVersioning = jest.mocked(useGetBucketVersioning);
16
16
  const mockUseGetBucketObjectLockConfiguration = jest.mocked(useGetBucketObjectLockConfiguration);
17
17
  const mockUseISVBucketStatus = jest.mocked(useISVBucketStatus);
@@ -24,7 +24,7 @@ const renderBucketVersioning = (props = {})=>{
24
24
  ...render(/*#__PURE__*/ jsx(Wrapper, {
25
25
  children: /*#__PURE__*/ jsx(BucketOverviewContext.Provider, {
26
26
  value: {
27
- bucketName: "test-bucket"
27
+ bucketName: 'test-bucket'
28
28
  },
29
29
  children: /*#__PURE__*/ jsx(BucketVersioning, {
30
30
  ...props
@@ -37,18 +37,18 @@ const renderBucketVersioning = (props = {})=>{
37
37
  const mockHookDefaults = ()=>{
38
38
  mockUseGetBucketVersioning.mockReturnValue({
39
39
  data: {
40
- Status: "Enabled"
40
+ Status: 'Enabled'
41
41
  },
42
- status: "success",
42
+ status: 'success',
43
43
  error: null
44
44
  });
45
45
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
46
46
  data: {
47
47
  ObjectLockConfiguration: {
48
- ObjectLockEnabled: "Disabled"
48
+ ObjectLockEnabled: 'Disabled'
49
49
  }
50
50
  },
51
- status: "success",
51
+ status: 'success',
52
52
  error: null
53
53
  });
54
54
  mockUseISVBucketStatus.mockReturnValue({
@@ -57,107 +57,107 @@ const mockHookDefaults = ()=>{
57
57
  isISVManaged: false,
58
58
  isvApplication: void 0,
59
59
  isLoading: false,
60
- bucketTagsStatus: "success"
60
+ bucketTagsStatus: 'success'
61
61
  });
62
62
  };
63
- describe("BucketVersioning", ()=>{
63
+ describe('BucketVersioning', ()=>{
64
64
  beforeEach(()=>{
65
65
  jest.clearAllMocks();
66
66
  mockHookDefaults();
67
67
  });
68
- it("renders toggle with Active label when versioning is enabled", ()=>{
68
+ it('renders toggle with Active label when versioning is enabled', ()=>{
69
69
  renderBucketVersioning();
70
- const toggle = findToggleByLabel("Active");
70
+ const toggle = findToggleByLabel('Active');
71
71
  expect(toggle).toBeInTheDocument();
72
72
  expect(toggle).toBeChecked();
73
73
  });
74
- it("renders toggle with Inactive label when versioning is suspended", ()=>{
74
+ it('renders toggle with Inactive label when versioning is suspended', ()=>{
75
75
  mockUseGetBucketVersioning.mockReturnValue({
76
76
  data: {
77
- Status: "Suspended"
77
+ Status: 'Suspended'
78
78
  },
79
- status: "success",
79
+ status: 'success',
80
80
  error: null
81
81
  });
82
82
  renderBucketVersioning();
83
- const toggle = findToggleByLabel("Inactive");
83
+ const toggle = findToggleByLabel('Inactive');
84
84
  expect(toggle).toBeInTheDocument();
85
85
  expect(toggle).not.toBeChecked();
86
86
  });
87
- it("calls mutation with Suspended status when disabling versioning", ()=>{
87
+ it('calls mutation with Suspended status when disabling versioning', ()=>{
88
88
  const { mutate } = renderBucketVersioning();
89
- const toggle = findToggleByLabel("Active");
89
+ const toggle = findToggleByLabel('Active');
90
90
  fireEvent.click(toggle);
91
91
  expect(mutate).toHaveBeenCalledWith({
92
- Bucket: "test-bucket",
92
+ Bucket: 'test-bucket',
93
93
  VersioningConfiguration: {
94
- Status: "Suspended"
94
+ Status: 'Suspended'
95
95
  }
96
96
  }, expect.any(Object));
97
97
  });
98
- it("calls mutation with Enabled status when enabling versioning", ()=>{
98
+ it('calls mutation with Enabled status when enabling versioning', ()=>{
99
99
  mockUseGetBucketVersioning.mockReturnValue({
100
100
  data: {
101
- Status: "Suspended"
101
+ Status: 'Suspended'
102
102
  },
103
- status: "success",
103
+ status: 'success',
104
104
  error: null
105
105
  });
106
106
  const { mutate } = renderBucketVersioning();
107
- const toggle = findToggleByLabel("Inactive");
107
+ const toggle = findToggleByLabel('Inactive');
108
108
  fireEvent.click(toggle);
109
109
  expect(mutate).toHaveBeenCalledWith({
110
- Bucket: "test-bucket",
110
+ Bucket: 'test-bucket',
111
111
  VersioningConfiguration: {
112
- Status: "Enabled"
112
+ Status: 'Enabled'
113
113
  }
114
114
  }, expect.any(Object));
115
115
  });
116
- it("disables toggle when versioning data is loading", ()=>{
116
+ it('disables toggle when versioning data is loading', ()=>{
117
117
  mockUseGetBucketVersioning.mockReturnValue({
118
118
  data: void 0,
119
- status: "pending",
119
+ status: 'pending',
120
120
  error: null
121
121
  });
122
122
  renderBucketVersioning();
123
- const toggle = screen.getByRole("checkbox");
124
- expect(toggle).toHaveAttribute("aria-disabled", "true");
123
+ const toggle = screen.getByRole('checkbox');
124
+ expect(toggle).toHaveAttribute('aria-disabled', 'true');
125
125
  });
126
- it("renders static Enabled text when Object Lock is enabled", ()=>{
126
+ it('renders static Enabled text when Object Lock is enabled', ()=>{
127
127
  mockUseGetBucketObjectLockConfiguration.mockReturnValue({
128
128
  data: {
129
129
  ObjectLockConfiguration: {
130
- ObjectLockEnabled: "Enabled"
130
+ ObjectLockEnabled: 'Enabled'
131
131
  }
132
132
  },
133
- status: "success"
133
+ status: 'success'
134
134
  });
135
135
  renderBucketVersioning();
136
- expect(screen.getByText("Enabled")).toBeInTheDocument();
136
+ expect(screen.getByText('Enabled')).toBeInTheDocument();
137
137
  expect(screen.getByText(/Versioning cannot be suspended because Object-lock is enabled/i)).toBeInTheDocument();
138
- expect(screen.queryByRole("checkbox")).not.toBeInTheDocument();
138
+ expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();
139
139
  });
140
- it("disables toggle when bucket is managed by Veeam", ()=>{
140
+ it('disables toggle when bucket is managed by Veeam', ()=>{
141
141
  mockUseISVBucketStatus.mockReturnValue({
142
142
  isVeeamBucket: true,
143
143
  isCommvaultBucket: false,
144
144
  isISVManaged: true,
145
- isvApplication: "Veeam",
145
+ isvApplication: 'Veeam',
146
146
  isLoading: false,
147
- bucketTagsStatus: "success"
147
+ bucketTagsStatus: 'success'
148
148
  });
149
149
  renderBucketVersioning();
150
- const toggle = screen.getByRole("checkbox");
151
- expect(toggle).toHaveAttribute("aria-disabled", "true");
150
+ const toggle = screen.getByRole('checkbox');
151
+ expect(toggle).toHaveAttribute('aria-disabled', 'true');
152
152
  });
153
- it("disables toggle when versioning query errors", ()=>{
153
+ it('disables toggle when versioning query errors', ()=>{
154
154
  mockUseGetBucketVersioning.mockReturnValue({
155
155
  data: void 0,
156
- status: "error",
157
- error: new Error("Failed to fetch versioning")
156
+ status: 'error',
157
+ error: new Error('Failed to fetch versioning')
158
158
  });
159
159
  renderBucketVersioning();
160
- const toggle = screen.getByRole("checkbox");
161
- expect(toggle).toHaveAttribute("aria-disabled", "true");
160
+ const toggle = screen.getByRole('checkbox');
161
+ expect(toggle).toHaveAttribute('aria-disabled', 'true');
162
162
  });
163
163
  });
@@ -6,26 +6,27 @@ import { Button, Input } from "@scality/core-ui/dist/next";
6
6
  import joi from "joi";
7
7
  import { useCallback } from "react";
8
8
  import { FormProvider, useForm } from "react-hook-form";
9
- import { useNavigate, useParams } from "react-router-dom";
9
+ import { useParams } from "react-router";
10
10
  import { useGetBucketNotification, useSetBucketNotification } from "../../../hooks/index.js";
11
+ import { useDataBrowserNavigate } from "../../../hooks/useDataBrowserNavigate.js";
11
12
  import { EventsSection } from "./EventsSection.js";
12
13
  const schema = joi.object({
13
14
  ruleName: joi.string().required().messages({
14
- "string.empty": "This field is required"
15
+ 'string.empty': 'This field is required'
15
16
  }),
16
17
  queueArn: joi.string().required().pattern(/^arn:aws:sqs:[a-z0-9-]+:\d+:.+$/).messages({
17
- "string.empty": "This field is required",
18
- "string.pattern.base": "Must be a valid ARN (e.g., arn:aws:sqs:region:account-id:queue-name)"
18
+ 'string.empty': 'This field is required',
19
+ 'string.pattern.base': 'Must be a valid ARN (e.g., arn:aws:sqs:region:account-id:queue-name)'
19
20
  }),
20
21
  events: joi.array().min(1).required().messages({
21
- "array.min": "At least one event must be selected"
22
+ 'array.min': 'At least one event must be selected'
22
23
  }),
23
- prefix: joi.string().allow("").optional(),
24
- suffix: joi.string().allow("").optional()
24
+ prefix: joi.string().allow('').optional(),
25
+ suffix: joi.string().allow('').optional()
25
26
  });
26
27
  function BucketNotificationCreatePage() {
27
28
  const { bucketName } = useParams();
28
- const navigate = useNavigate();
29
+ const navigate = useDataBrowserNavigate();
29
30
  const { showToast } = useToast();
30
31
  const { data: existingNotificationData, status: notificationStatus } = useGetBucketNotification({
31
32
  Bucket: bucketName
@@ -33,19 +34,19 @@ function BucketNotificationCreatePage() {
33
34
  const existingRuleNames = existingNotificationData?.QueueConfigurations?.map((config)=>config.Id) || [];
34
35
  const dynamicSchema = schema.keys({
35
36
  ruleName: joi.string().required().invalid(...existingRuleNames).messages({
36
- "string.empty": "This field is required",
37
- "any.invalid": "A rule with this name already exists"
37
+ 'string.empty': 'This field is required',
38
+ 'any.invalid': 'A rule with this name already exists'
38
39
  })
39
40
  });
40
41
  const methods = useForm({
41
42
  resolver: joiResolver(dynamicSchema),
42
- mode: "onChange",
43
+ mode: 'onChange',
43
44
  defaultValues: {
44
- ruleName: "",
45
- queueArn: "",
45
+ ruleName: '',
46
+ queueArn: '',
46
47
  events: [],
47
- prefix: "",
48
- suffix: ""
48
+ prefix: '',
49
+ suffix: ''
49
50
  }
50
51
  });
51
52
  const { mutate: setNotification, isPending: isSaving } = useSetBucketNotification();
@@ -61,22 +62,22 @@ function BucketNotificationCreatePage() {
61
62
  const filterRules = [
62
63
  ...data.prefix ? [
63
64
  {
64
- Name: "prefix",
65
+ Name: 'prefix',
65
66
  Value: data.prefix
66
67
  }
67
68
  ] : [],
68
69
  ...data.suffix ? [
69
70
  {
70
- Name: "suffix",
71
+ Name: 'suffix',
71
72
  Value: data.suffix
72
73
  }
73
74
  ] : []
74
75
  ];
75
76
  const filteredEvents = data.events.filter((event)=>{
76
- if (event.endsWith("*")) return true;
77
- if (event.startsWith("s3:ObjectCreated:")) return !data.events.includes("s3:ObjectCreated:*");
78
- if (event.startsWith("s3:ObjectRemoved:")) return !data.events.includes("s3:ObjectRemoved:*");
79
- if (event.startsWith("s3:LifecycleExpiration:")) return !data.events.includes("s3:LifecycleExpiration:*");
77
+ if (event.endsWith('*')) return true;
78
+ if (event.startsWith('s3:ObjectCreated:')) return !data.events.includes('s3:ObjectCreated:*');
79
+ if (event.startsWith('s3:ObjectRemoved:')) return !data.events.includes('s3:ObjectRemoved:*');
80
+ if (event.startsWith('s3:LifecycleExpiration:')) return !data.events.includes('s3:LifecycleExpiration:*');
80
81
  return true;
81
82
  });
82
83
  const newQueueConfiguration = {
@@ -103,17 +104,17 @@ function BucketNotificationCreatePage() {
103
104
  onSuccess: ()=>{
104
105
  showToast({
105
106
  open: true,
106
- message: "Notification created successfully",
107
- status: "success"
107
+ message: 'Notification created successfully',
108
+ status: 'success'
108
109
  });
109
110
  navigate(`/buckets/${bucketName}`);
110
111
  },
111
112
  onError: (error)=>{
112
- const errorMessage = error instanceof Error ? error.message : "Failed to create notification";
113
+ const errorMessage = error instanceof Error ? error.message : 'Failed to create notification';
113
114
  showToast({
114
115
  open: true,
115
116
  message: errorMessage,
116
- status: "error"
117
+ status: 'error'
117
118
  });
118
119
  }
119
120
  });
@@ -124,7 +125,7 @@ function BucketNotificationCreatePage() {
124
125
  showToast,
125
126
  existingNotificationData
126
127
  ]);
127
- if ("pending" === notificationStatus) return /*#__PURE__*/ jsx(Loader, {
128
+ if ('pending' === notificationStatus) return /*#__PURE__*/ jsx(Loader, {
128
129
  centered: true,
129
130
  children: /*#__PURE__*/ jsx(Text, {
130
131
  children: "Loading..."
@@ -134,8 +135,8 @@ function BucketNotificationCreatePage() {
134
135
  ...methods,
135
136
  children: /*#__PURE__*/ jsxs(Form, {
136
137
  layout: {
137
- kind: "page",
138
- title: "Create Bucket Notification"
138
+ kind: 'page',
139
+ title: 'Create Bucket Notification'
139
140
  },
140
141
  requireMode: "partial",
141
142
  onSubmit: handleSubmit(onSubmit),
@@ -172,7 +173,7 @@ function BucketNotificationCreatePage() {
172
173
  required: true,
173
174
  content: /*#__PURE__*/ jsx(Input, {
174
175
  id: "ruleName",
175
- ...register("ruleName")
176
+ ...register('ruleName')
176
177
  })
177
178
  })
178
179
  }),
@@ -190,13 +191,13 @@ function BucketNotificationCreatePage() {
190
191
  content: /*#__PURE__*/ jsx(Input, {
191
192
  id: "queueArn",
192
193
  placeholder: "arn:aws:sqs:us-east-1:1xx:name",
193
- ...register("queueArn")
194
+ ...register('queueArn')
194
195
  })
195
196
  })
196
197
  }),
197
198
  /*#__PURE__*/ jsx(FormSection, {
198
199
  title: {
199
- name: "Filters"
200
+ name: 'Filters'
200
201
  },
201
202
  children: /*#__PURE__*/ jsxs(Stack, {
202
203
  direction: "horizontal",
@@ -210,7 +211,7 @@ function BucketNotificationCreatePage() {
210
211
  id: "prefix",
211
212
  placeholder: "",
212
213
  size: "2/3",
213
- ...register("prefix")
214
+ ...register('prefix')
214
215
  })
215
216
  }),
216
217
  /*#__PURE__*/ jsx(FormGroup, {
@@ -221,7 +222,7 @@ function BucketNotificationCreatePage() {
221
222
  id: "suffix",
222
223
  placeholder: "",
223
224
  size: "2/3",
224
- ...register("suffix")
225
+ ...register('suffix')
225
226
  })
226
227
  })
227
228
  ]
@@ -1,39 +1,70 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Checkbox, FormGroup, FormSection, Stack, Text, Wrap } from "@scality/core-ui";
3
- import { useCallback } from "react";
3
+ import { useCallback, useMemo } from "react";
4
4
  import { Controller, useFormContext } from "react-hook-form";
5
- import { objectCreationEvents, objectDeletionEvents, othersEvents } from "./events.js";
5
+ import { getFilteredEventGroups } from "./events.js";
6
6
  import { Box } from "@scality/core-ui/dist/next";
7
+ import { useSupportedNotificationEvents } from "../../../hooks/useSupportedNotificationEvents.js";
7
8
  function EventsSection() {
8
9
  const { control, formState: { errors } } = useFormContext();
10
+ const supportedEvents = useSupportedNotificationEvents();
11
+ const eventGroups = useMemo(()=>getFilteredEventGroups(supportedEvents), [
12
+ supportedEvents
13
+ ]);
14
+ const { objectCreation, objectDeletion, objectRestoration, lifecycle, replication, objectTagging, storageAccess, testing } = eventGroups;
15
+ const getRelatedEvents = useCallback((eventValue)=>{
16
+ const basePattern = eventValue.slice(0, -1);
17
+ const eventGroupMap = {
18
+ 's3:ObjectCreated': objectCreation.events,
19
+ 's3:ObjectRemoved': objectDeletion.events,
20
+ 's3:ObjectRestore': objectRestoration.events,
21
+ 's3:Replication': replication.events,
22
+ 's3:ObjectTagging': objectTagging.events
23
+ };
24
+ for (const [prefix, events] of Object.entries(eventGroupMap))if (eventValue.startsWith(prefix)) return events;
25
+ if (eventValue.startsWith('s3:LifecycleExpiration')) return lifecycle.events.filter((e)=>e.startsWith(basePattern));
26
+ return [
27
+ eventValue
28
+ ];
29
+ }, [
30
+ objectCreation.events,
31
+ objectDeletion.events,
32
+ objectRestoration.events,
33
+ lifecycle.events,
34
+ replication.events,
35
+ objectTagging.events
36
+ ]);
9
37
  const toggleEvent = useCallback((currentEvents, eventValue, onChange)=>{
10
- const isWildcard = eventValue.endsWith("*");
38
+ const isWildcard = eventValue.endsWith('*');
11
39
  const isSelected = currentEvents.includes(eventValue);
12
- if (isWildcard) if (isSelected) {
13
- const relatedEvents = eventValue.startsWith("s3:ObjectCreated") ? objectCreationEvents.events : eventValue.startsWith("s3:ObjectRemoved") ? objectDeletionEvents.events : eventValue.startsWith("s3:LifecycleExpiration") ? othersEvents.events.filter((e)=>e.startsWith("s3:LifecycleExpiration")) : [
14
- eventValue
15
- ];
16
- onChange(currentEvents.filter((e)=>!relatedEvents.includes(e)));
17
- } else {
18
- const relatedEvents = eventValue.startsWith("s3:ObjectCreated") ? objectCreationEvents.events : eventValue.startsWith("s3:ObjectRemoved") ? objectDeletionEvents.events : eventValue.startsWith("s3:LifecycleExpiration") ? othersEvents.events.filter((e)=>e.startsWith("s3:LifecycleExpiration")) : [
40
+ if (!isWildcard) {
41
+ const newEvents = isSelected ? currentEvents.filter((e)=>e !== eventValue) : [
42
+ ...currentEvents,
19
43
  eventValue
20
44
  ];
45
+ onChange(newEvents);
46
+ return;
47
+ }
48
+ const relatedEvents = getRelatedEvents(eventValue);
49
+ if (isSelected) onChange(currentEvents.filter((e)=>!relatedEvents.includes(e)));
50
+ else {
21
51
  const newEvents = [
22
52
  ...currentEvents.filter((e)=>!relatedEvents.includes(e)),
23
53
  ...relatedEvents
24
54
  ];
25
55
  onChange(newEvents);
26
56
  }
27
- else onChange(isSelected ? currentEvents.filter((e)=>e !== eventValue) : [
28
- ...currentEvents,
29
- eventValue
30
- ]);
31
- }, []);
57
+ }, [
58
+ getRelatedEvents
59
+ ]);
32
60
  const isEventDisabled = (event, selectedEvents)=>{
33
- if (event.endsWith("*")) return false;
34
- if (event.startsWith("s3:ObjectCreated")) return selectedEvents.includes("s3:ObjectCreated:*");
35
- if (event.startsWith("s3:ObjectRemoved")) return selectedEvents.includes("s3:ObjectRemoved:*");
36
- if (event.startsWith("s3:LifecycleExpiration")) return selectedEvents.includes("s3:LifecycleExpiration:*");
61
+ if (event.endsWith('*')) return false;
62
+ if (event.startsWith('s3:ObjectCreated')) return selectedEvents.includes('s3:ObjectCreated:*');
63
+ if (event.startsWith('s3:ObjectRemoved')) return selectedEvents.includes('s3:ObjectRemoved:*');
64
+ if (event.startsWith('s3:ObjectRestore')) return selectedEvents.includes('s3:ObjectRestore:*');
65
+ if (event.startsWith('s3:LifecycleExpiration')) return selectedEvents.includes('s3:LifecycleExpiration:*');
66
+ if (event.startsWith('s3:Replication')) return selectedEvents.includes('s3:Replication:*');
67
+ else if (event.startsWith('s3:ObjectTagging')) return selectedEvents.includes('s3:ObjectTagging:*');
37
68
  return false;
38
69
  };
39
70
  return /*#__PURE__*/ jsxs(FormSection, {
@@ -62,15 +93,100 @@ function EventsSection() {
62
93
  direction: "vertical",
63
94
  gap: "r16",
64
95
  children: [
65
- /*#__PURE__*/ jsxs(Stack, {
96
+ objectCreation.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
97
+ direction: "vertical",
98
+ gap: "r8",
99
+ children: [
100
+ /*#__PURE__*/ jsx(Text, {
101
+ color: "textPrimary",
102
+ children: objectCreation.label
103
+ }),
104
+ objectCreation.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
105
+ id: event,
106
+ label: event,
107
+ checked: value.includes(event),
108
+ disabled: isEventDisabled(event, value),
109
+ onChange: ()=>toggleEvent(value, event, onChange)
110
+ }, event))
111
+ ]
112
+ }),
113
+ objectDeletion.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
114
+ direction: "vertical",
115
+ gap: "r8",
116
+ children: [
117
+ /*#__PURE__*/ jsx(Text, {
118
+ color: "textPrimary",
119
+ children: objectDeletion.label
120
+ }),
121
+ objectDeletion.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
122
+ id: event,
123
+ label: event,
124
+ checked: value.includes(event),
125
+ disabled: isEventDisabled(event, value),
126
+ onChange: ()=>toggleEvent(value, event, onChange)
127
+ }, event))
128
+ ]
129
+ }),
130
+ objectRestoration.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
131
+ direction: "vertical",
132
+ gap: "r8",
133
+ children: [
134
+ /*#__PURE__*/ jsx(Text, {
135
+ color: "textPrimary",
136
+ children: objectRestoration.label
137
+ }),
138
+ objectRestoration.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
139
+ id: event,
140
+ label: event,
141
+ checked: value.includes(event),
142
+ disabled: isEventDisabled(event, value),
143
+ onChange: ()=>toggleEvent(value, event, onChange)
144
+ }, event))
145
+ ]
146
+ }),
147
+ lifecycle.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
148
+ direction: "vertical",
149
+ gap: "r8",
150
+ children: [
151
+ /*#__PURE__*/ jsx(Text, {
152
+ color: "textPrimary",
153
+ children: lifecycle.label
154
+ }),
155
+ lifecycle.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
156
+ id: event,
157
+ label: event,
158
+ checked: value.includes(event),
159
+ disabled: isEventDisabled(event, value),
160
+ onChange: ()=>toggleEvent(value, event, onChange)
161
+ }, event))
162
+ ]
163
+ }),
164
+ replication.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
165
+ direction: "vertical",
166
+ gap: "r8",
167
+ children: [
168
+ /*#__PURE__*/ jsx(Text, {
169
+ color: "textPrimary",
170
+ children: replication.label
171
+ }),
172
+ replication.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
173
+ id: event,
174
+ label: event,
175
+ checked: value.includes(event),
176
+ disabled: isEventDisabled(event, value),
177
+ onChange: ()=>toggleEvent(value, event, onChange)
178
+ }, event))
179
+ ]
180
+ }),
181
+ objectTagging.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
66
182
  direction: "vertical",
67
183
  gap: "r8",
68
184
  children: [
69
185
  /*#__PURE__*/ jsx(Text, {
70
186
  color: "textPrimary",
71
- children: objectCreationEvents.label
187
+ children: objectTagging.label
72
188
  }),
73
- objectCreationEvents.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
189
+ objectTagging.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
74
190
  id: event,
75
191
  label: event,
76
192
  checked: value.includes(event),
@@ -79,15 +195,15 @@ function EventsSection() {
79
195
  }, event))
80
196
  ]
81
197
  }),
82
- /*#__PURE__*/ jsxs(Stack, {
198
+ storageAccess.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
83
199
  direction: "vertical",
84
200
  gap: "r8",
85
201
  children: [
86
202
  /*#__PURE__*/ jsx(Text, {
87
203
  color: "textPrimary",
88
- children: objectDeletionEvents.label
204
+ children: storageAccess.label
89
205
  }),
90
- objectDeletionEvents.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
206
+ storageAccess.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
91
207
  id: event,
92
208
  label: event,
93
209
  checked: value.includes(event),
@@ -96,15 +212,15 @@ function EventsSection() {
96
212
  }, event))
97
213
  ]
98
214
  }),
99
- /*#__PURE__*/ jsxs(Stack, {
215
+ testing.events.length > 0 && /*#__PURE__*/ jsxs(Stack, {
100
216
  direction: "vertical",
101
217
  gap: "r8",
102
218
  children: [
103
219
  /*#__PURE__*/ jsx(Text, {
104
220
  color: "textPrimary",
105
- children: othersEvents.label
221
+ children: testing.label
106
222
  }),
107
- othersEvents.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
223
+ testing.events.map((event)=>/*#__PURE__*/ jsx(Checkbox, {
108
224
  id: event,
109
225
  label: event,
110
226
  checked: value.includes(event),