@scality/data-browser-library 1.0.0-preview.8 → 1.0.1

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 (303) hide show
  1. package/dist/components/DataBrowserUI.d.ts +12 -0
  2. package/dist/components/DataBrowserUI.js +99 -0
  3. package/dist/components/Editor.d.ts +1 -1
  4. package/dist/components/Editor.js +3 -3
  5. package/dist/components/__tests__/BucketAccessor.test.js +214 -0
  6. package/dist/components/__tests__/BucketCorsPage.test.d.ts +1 -0
  7. package/dist/components/__tests__/BucketCorsPage.test.js +263 -0
  8. package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
  9. package/dist/components/__tests__/BucketCreate.test.js +574 -0
  10. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  11. package/dist/components/__tests__/BucketDetails.test.js +421 -0
  12. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +14 -0
  13. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
  14. package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
  15. package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
  16. package/dist/components/__tests__/BucketList.test.js +495 -81
  17. package/dist/components/__tests__/BucketNotificationFormPage.test.d.ts +1 -0
  18. package/dist/components/__tests__/BucketNotificationFormPage.test.js +348 -0
  19. package/dist/components/__tests__/BucketNotificationList.test.d.ts +1 -0
  20. package/dist/components/__tests__/BucketNotificationList.test.js +379 -0
  21. package/dist/components/__tests__/BucketOverview.test.js +484 -179
  22. package/dist/components/__tests__/BucketPolicyPage.test.js +151 -99
  23. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +16 -0
  24. package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
  25. package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
  26. package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
  27. package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
  28. package/dist/components/__tests__/DeleteBucketButton.test.js +64 -64
  29. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
  30. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
  31. package/dist/components/__tests__/DeleteObjectButton.test.js +64 -64
  32. package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
  33. package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
  34. package/dist/components/__tests__/MetadataSearch.test.js +65 -65
  35. package/dist/components/__tests__/ObjectList.test.js +741 -240
  36. package/dist/components/__tests__/UploadButton.test.js +45 -45
  37. package/dist/components/breadcrumb/Breadcrumb.d.ts +6 -0
  38. package/dist/components/breadcrumb/Breadcrumb.js +37 -0
  39. package/dist/components/breadcrumb/DataBrowserBreadcrumb.d.ts +1 -0
  40. package/dist/components/breadcrumb/DataBrowserBreadcrumb.js +10 -0
  41. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.d.ts +1 -0
  42. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.js +196 -0
  43. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.d.ts +1 -0
  44. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.js +153 -0
  45. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.d.ts +1 -0
  46. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.js +134 -0
  47. package/dist/components/breadcrumb/index.d.ts +8 -0
  48. package/dist/components/breadcrumb/index.js +4 -0
  49. package/dist/components/breadcrumb/useBreadcrumbPaths.d.ts +2 -0
  50. package/dist/components/breadcrumb/useBreadcrumbPaths.js +82 -0
  51. package/dist/components/buckets/BucketAccessor.d.ts +2 -0
  52. package/dist/components/buckets/BucketAccessor.js +125 -0
  53. package/dist/components/buckets/BucketConfigEditButton.d.ts +8 -0
  54. package/dist/components/buckets/{BucketPolicyButton.js → BucketConfigEditButton.js} +9 -5
  55. package/dist/components/buckets/BucketCorsPage.d.ts +1 -0
  56. package/dist/components/buckets/BucketCorsPage.js +234 -0
  57. package/dist/components/buckets/BucketCreate.d.ts +50 -0
  58. package/dist/components/buckets/BucketCreate.js +279 -0
  59. package/dist/components/buckets/BucketDetails.d.ts +42 -0
  60. package/dist/components/buckets/BucketDetails.js +256 -40
  61. package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
  62. package/dist/components/buckets/BucketLifecycleFormPage.js +1086 -0
  63. package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
  64. package/dist/components/buckets/BucketLifecycleList.js +270 -0
  65. package/dist/components/buckets/BucketList.d.ts +6 -4
  66. package/dist/components/buckets/BucketList.js +161 -94
  67. package/dist/components/buckets/BucketLocation.js +4 -4
  68. package/dist/components/buckets/BucketOverview.d.ts +86 -5
  69. package/dist/components/buckets/BucketOverview.js +481 -192
  70. package/dist/components/buckets/BucketPage.js +44 -22
  71. package/dist/components/buckets/BucketPolicyPage.js +155 -127
  72. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  73. package/dist/components/buckets/BucketReplicationFormPage.js +835 -0
  74. package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
  75. package/dist/components/buckets/BucketReplicationList.js +189 -0
  76. package/dist/components/buckets/BucketVersioning.d.ts +4 -0
  77. package/dist/components/buckets/BucketVersioning.js +76 -0
  78. package/dist/components/buckets/DeleteBucketButton.js +8 -8
  79. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
  80. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
  81. package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
  82. package/dist/components/buckets/EmptyBucketButton.js +232 -0
  83. package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
  84. package/dist/components/buckets/EmptyBucketSummary.js +60 -0
  85. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
  86. package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
  87. package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
  88. package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
  89. package/dist/components/buckets/notifications/BucketNotificationFormPage.d.ts +1 -0
  90. package/dist/components/buckets/notifications/BucketNotificationFormPage.js +316 -0
  91. package/dist/components/buckets/notifications/BucketNotificationList.d.ts +10 -0
  92. package/dist/components/buckets/notifications/BucketNotificationList.js +267 -0
  93. package/dist/components/buckets/notifications/EventsSection.js +145 -29
  94. package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
  95. package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
  96. package/dist/components/buckets/notifications/events.d.ts +71 -7
  97. package/dist/components/buckets/notifications/events.js +98 -16
  98. package/dist/components/index.d.ts +27 -13
  99. package/dist/components/index.js +20 -6
  100. package/dist/components/layouts/ArrowNavigation.d.ts +3 -0
  101. package/dist/components/layouts/ArrowNavigation.js +28 -0
  102. package/dist/components/layouts/BrowserPageLayout.d.ts +5 -1
  103. package/dist/components/layouts/BrowserPageLayout.js +10 -5
  104. package/dist/components/objects/CreateFolderButton.d.ts +2 -2
  105. package/dist/components/objects/CreateFolderButton.js +12 -12
  106. package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
  107. package/dist/components/objects/DeleteObjectButton.js +19 -21
  108. package/dist/components/objects/GetPresignedUrlButton.d.ts +7 -0
  109. package/dist/components/objects/GetPresignedUrlButton.js +255 -0
  110. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -2
  111. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +263 -230
  112. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +2 -2
  113. package/dist/components/objects/ObjectDetails/ObjectSummary.js +540 -138
  114. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +2 -2
  115. package/dist/components/objects/ObjectDetails/ObjectTags.js +95 -123
  116. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  117. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  118. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  119. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +1064 -0
  120. package/dist/components/objects/ObjectDetails/index.d.ts +18 -2
  121. package/dist/components/objects/ObjectDetails/index.js +152 -40
  122. package/dist/components/objects/ObjectList.d.ts +12 -10
  123. package/dist/components/objects/ObjectList.js +590 -263
  124. package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
  125. package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
  126. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
  127. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
  128. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
  129. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +159 -0
  130. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
  131. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
  132. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
  133. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
  134. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
  135. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
  136. package/dist/components/objects/ObjectPage.js +12 -8
  137. package/dist/components/objects/UploadButton.d.ts +3 -3
  138. package/dist/components/objects/UploadButton.js +10 -10
  139. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.d.ts +1 -0
  140. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.js +531 -0
  141. package/dist/components/providers/DataBrowserProvider.d.ts +23 -12
  142. package/dist/components/providers/DataBrowserProvider.js +60 -38
  143. package/dist/components/providers/QueryProvider.d.ts +9 -0
  144. package/dist/components/providers/QueryProvider.js +21 -0
  145. package/dist/components/search/MetadataSearch.js +29 -28
  146. package/dist/components/search/SearchHints.js +1 -1
  147. package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
  148. package/dist/components/ui/ArrayFieldActions.js +43 -0
  149. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
  150. package/dist/components/ui/ConfirmDeleteRuleModal.js +48 -0
  151. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  152. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  153. package/dist/components/ui/FilterFormSection.d.ts +44 -0
  154. package/dist/components/ui/FilterFormSection.js +159 -0
  155. package/dist/components/ui/Search.elements.d.ts +2 -2
  156. package/dist/components/ui/Search.elements.js +7 -7
  157. package/dist/components/ui/Table.elements.d.ts +2 -1
  158. package/dist/components/ui/Table.elements.js +18 -12
  159. package/dist/config/__tests__/factory.test.d.ts +1 -0
  160. package/dist/config/__tests__/factory.test.js +311 -0
  161. package/dist/config/factory.d.ts +14 -49
  162. package/dist/config/factory.js +23 -68
  163. package/dist/config/types.d.ts +212 -34
  164. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  165. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  166. package/dist/hooks/__tests__/useAccessibleBuckets.test.d.ts +1 -0
  167. package/dist/hooks/__tests__/useAccessibleBuckets.test.js +145 -0
  168. package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
  169. package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
  170. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +27 -27
  171. package/dist/hooks/__tests__/useLoginMutation.test.d.ts +1 -0
  172. package/dist/hooks/__tests__/useLoginMutation.test.js +194 -0
  173. package/dist/hooks/bucketConfiguration.d.ts +8 -1
  174. package/dist/hooks/bucketConfiguration.js +52 -51
  175. package/dist/hooks/bucketOperations.d.ts +10 -1
  176. package/dist/hooks/bucketOperations.js +10 -9
  177. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +80 -80
  178. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +80 -80
  179. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +44 -44
  180. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +63 -63
  181. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +95 -52
  182. package/dist/hooks/factories/index.d.ts +4 -4
  183. package/dist/hooks/factories/index.js +2 -2
  184. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  185. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +16 -13
  186. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  187. package/dist/hooks/factories/useCreateS3LoginHook.js +1 -1
  188. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  189. package/dist/hooks/factories/useCreateS3MutationHook.js +7 -2
  190. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  191. package/dist/hooks/factories/useCreateS3QueryHook.js +29 -3
  192. package/dist/hooks/index.d.ts +19 -8
  193. package/dist/hooks/index.js +16 -5
  194. package/dist/hooks/loginOperations.d.ts +1 -1
  195. package/dist/hooks/loginOperations.js +1 -1
  196. package/dist/hooks/objectOperations.d.ts +2 -2
  197. package/dist/hooks/objectOperations.js +50 -49
  198. package/dist/hooks/presignedOperations.d.ts +4 -4
  199. package/dist/hooks/presignedOperations.js +5 -5
  200. package/dist/hooks/useAccessibleBuckets.d.ts +11 -0
  201. package/dist/hooks/useAccessibleBuckets.js +115 -0
  202. package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
  203. package/dist/hooks/useBatchObjectLegalHold.js +48 -0
  204. package/dist/hooks/useBucketConfigEditor.d.ts +31 -0
  205. package/dist/hooks/useBucketConfigEditor.js +82 -0
  206. package/dist/hooks/useDataBrowserNavigate.d.ts +28 -0
  207. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  208. package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
  209. package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
  210. package/dist/hooks/useEmptyBucket.d.ts +27 -0
  211. package/dist/hooks/useEmptyBucket.js +116 -0
  212. package/dist/hooks/useFeatures.d.ts +7 -0
  213. package/dist/hooks/useFeatures.js +8 -0
  214. package/dist/hooks/useISVBucketDetection.d.ts +15 -0
  215. package/dist/hooks/useISVBucketDetection.js +27 -0
  216. package/dist/hooks/useIsBucketEmpty.js +4 -4
  217. package/dist/hooks/useLimitedAccessFlow.d.ts +48 -0
  218. package/dist/hooks/useLimitedAccessFlow.js +23 -0
  219. package/dist/hooks/useS3Client.d.ts +6 -0
  220. package/dist/hooks/useS3Client.js +3 -2
  221. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  222. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  223. package/dist/hooks/useSupportedNotificationEvents.d.ts +6 -0
  224. package/dist/hooks/useSupportedNotificationEvents.js +8 -0
  225. package/dist/hooks/useTableRowSelection.d.ts +9 -0
  226. package/dist/hooks/useTableRowSelection.js +45 -0
  227. package/dist/index.d.ts +6 -6
  228. package/dist/index.js +2 -2
  229. package/dist/schemas/bucketPolicySchema.json +3 -13
  230. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  231. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  232. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  233. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  234. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  235. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  236. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  237. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  238. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  239. package/dist/test/msw/handlers/headObject.js +31 -13
  240. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  241. package/dist/test/msw/handlers/listBuckets.js +5 -3
  242. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  243. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  244. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  245. package/dist/test/msw/handlers/listObjects.js +35 -23
  246. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  247. package/dist/test/msw/handlers/objectLegalHold.js +32 -17
  248. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  249. package/dist/test/msw/handlers/objectRetention.js +31 -17
  250. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  251. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  252. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  253. package/dist/test/msw/handlers/putObject.js +27 -12
  254. package/dist/test/msw/handlers.d.ts +3 -3
  255. package/dist/test/msw/handlers.js +77 -54
  256. package/dist/test/msw/index.d.ts +2 -2
  257. package/dist/test/msw/index.js +1 -1
  258. package/dist/test/msw/server.d.ts +1 -1
  259. package/dist/test/msw/server.js +1 -1
  260. package/dist/test/msw/utils.js +2 -2
  261. package/dist/test/setup.d.ts +1 -1
  262. package/dist/test/setup.js +13 -30
  263. package/dist/test/testUtils.d.ts +170 -36
  264. package/dist/test/testUtils.js +229 -116
  265. package/dist/test/utils/errorHandling.test.js +146 -108
  266. package/dist/types/index.d.ts +49 -36
  267. package/dist/types/monaco.d.ts +13 -0
  268. package/dist/types/monaco.js +0 -0
  269. package/dist/utils/__tests__/proxyMiddleware.test.d.ts +1 -0
  270. package/dist/utils/__tests__/proxyMiddleware.test.js +579 -0
  271. package/dist/utils/__tests__/s3Client.test.d.ts +1 -0
  272. package/dist/utils/__tests__/s3Client.test.js +340 -0
  273. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  274. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +437 -0
  275. package/dist/utils/constants.d.ts +22 -0
  276. package/dist/utils/constants.js +19 -0
  277. package/dist/utils/deletion/index.d.ts +2 -2
  278. package/dist/utils/deletion/index.js +1 -1
  279. package/dist/utils/deletion/messages.d.ts +1 -1
  280. package/dist/utils/deletion/messages.js +4 -4
  281. package/dist/utils/errorHandling.d.ts +12 -3
  282. package/dist/utils/errorHandling.js +12 -7
  283. package/dist/utils/hooks.js +8 -8
  284. package/dist/utils/index.d.ts +5 -2
  285. package/dist/utils/index.js +5 -1
  286. package/dist/utils/proxyMiddleware.d.ts +32 -13
  287. package/dist/utils/proxyMiddleware.js +90 -36
  288. package/dist/utils/s3Client.d.ts +14 -4
  289. package/dist/utils/s3Client.js +5 -26
  290. package/dist/utils/s3ConfigIdentifier.d.ts +79 -0
  291. package/dist/utils/s3ConfigIdentifier.js +57 -0
  292. package/dist/utils/s3RuleUtils.d.ts +53 -0
  293. package/dist/utils/s3RuleUtils.js +101 -0
  294. package/package.json +10 -8
  295. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +0 -316
  296. package/dist/components/buckets/BucketPolicyButton.d.ts +0 -7
  297. package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +0 -1
  298. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +0 -234
  299. package/dist/hooks/useLoginMutation.d.ts +0 -21
  300. package/dist/hooks/useLoginMutation.js +0 -9
  301. package/dist/utils/useFeatures.d.ts +0 -1
  302. package/dist/utils/useFeatures.js +0 -7
  303. /package/dist/components/__tests__/{BucketNotificationCreatePage.test.d.ts → BucketAccessor.test.d.ts} +0 -0
@@ -1,31 +1,325 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { ConstrainedText, FormattedDateTime, Icon, Link, PrettyBytes, Text, Toggle, Wrap, spacing } from "@scality/core-ui";
2
+ import { ConstrainedText, FormattedDateTime, Icon, Link, PrettyBytes, Text, Toggle, Wrap, spacing, useToast } from "@scality/core-ui";
3
3
  import { Box, Table } from "@scality/core-ui/dist/next";
4
- import { useCallback, useEffect, useMemo, useState } from "react";
4
+ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
5
+ import { useDataBrowserUICustomization } from "../../contexts/DataBrowserUICustomizationContext.js";
5
6
  import { useSearchObjects, useSearchObjectsVersions } from "../../hooks/index.js";
7
+ import { useGetPresignedDownload } from "../../hooks/presignedOperations.js";
8
+ import { useBatchObjectLegalHold } from "../../hooks/useBatchObjectLegalHold.js";
9
+ import { useFeatures } from "../../hooks/useFeatures.js";
6
10
  import { useQueryParams } from "../../utils/hooks.js";
7
- import { useFeatures } from "../../utils/useFeatures.js";
8
- import CreateFolderButton from "./CreateFolderButton.js";
11
+ import { useInvalidateQueries } from "../providers/DataBrowserProvider.js";
9
12
  import MetadataSearch from "../search/MetadataSearch.js";
10
- import UploadButton from "./UploadButton.js";
13
+ import CreateFolderButton from "./CreateFolderButton.js";
11
14
  import DeleteObjectButton from "./DeleteObjectButton.js";
15
+ import UploadButton from "./UploadButton.js";
12
16
  const DEFAULT_PAGE_SIZE = 20;
17
+ const SEARCH_QUERY_PARAM = 'search';
18
+ const NAME_COLUMN_FLEX = '2';
19
+ const VERSION_ID_COLUMN_FLEX = '1.5';
20
+ const LAST_MODIFIED_COLUMN_FLEX = '1';
21
+ const SIZE_COLUMN_FLEX = '1';
22
+ const STORAGE_CLASS_COLUMN_FLEX = '1';
23
+ const isObjectLike = (item)=>'folder' !== item.type;
13
24
  const getVersionTextColor = (row)=>{
14
25
  const isLatest = row.original.IsLatest;
15
- const isVersion = "version" === row.original.type;
16
- return !isLatest && isVersion ? "infoPrimary" : "textPrimary";
26
+ const isVersion = 'version' === row.original.type;
27
+ return !isLatest && isVersion ? 'infoPrimary' : 'textPrimary';
28
+ };
29
+ const removePrefix = (path, prefix)=>{
30
+ if (!prefix) return path;
31
+ if (path.startsWith(prefix)) return path.slice(prefix.length);
32
+ return path;
17
33
  };
34
+ const createLegalHoldKey = (key, versionId)=>`${key}:${versionId ?? 'null'}`;
35
+ const downloadFile = (url, filename, onCleanup)=>{
36
+ try {
37
+ new URL(url);
38
+ const link = document.createElement('a');
39
+ link.href = url;
40
+ link.download = filename;
41
+ link.style.display = 'none';
42
+ link.rel = 'noopener noreferrer';
43
+ document.body.appendChild(link);
44
+ link.click();
45
+ const timeoutId = setTimeout(()=>{
46
+ if (document.body.contains(link)) document.body.removeChild(link);
47
+ }, 100);
48
+ onCleanup?.(timeoutId);
49
+ } catch (error) {
50
+ console.error('Invalid download URL:', url, error);
51
+ throw new Error('Failed to initiate download: Invalid URL');
52
+ }
53
+ };
54
+ const createNameColumn = (onPrefixChange, onDownload)=>({
55
+ Header: 'Name',
56
+ accessor: 'displayName',
57
+ id: 'name',
58
+ sortType: (rowA, rowB)=>{
59
+ const aIsFolder = 'folder' === rowA.original.type;
60
+ const bIsFolder = 'folder' === rowB.original.type;
61
+ if (aIsFolder && !bIsFolder) return -1;
62
+ if (!aIsFolder && bIsFolder) return 1;
63
+ const aName = String(rowA.values.displayName || '');
64
+ const bName = String(rowB.values.displayName || '');
65
+ return aName.localeCompare(bName, 'en', {
66
+ sensitivity: 'base'
67
+ });
68
+ },
69
+ Cell: ({ value, row })=>{
70
+ const isFolder = 'folder' === row.original.type;
71
+ const isVersion = 'version' === row.original.type;
72
+ const isDeleteMarker = 'deleteMarker' === row.original.type;
73
+ const isLatest = row.original.IsLatest;
74
+ let iconName;
75
+ iconName = isFolder ? 'Folder' : isDeleteMarker ? 'Deletion-marker' : 'File';
76
+ const shouldIndent = isVersion && !isLatest;
77
+ const isLegalHoldEnabled = isObjectLike(row.original) && Boolean(row.original.isLegalHoldEnabled);
78
+ return /*#__PURE__*/ jsx(ConstrainedText, {
79
+ text: /*#__PURE__*/ jsxs(Box, {
80
+ display: "flex",
81
+ alignItems: "center",
82
+ gap: spacing.r8,
83
+ paddingLeft: shouldIndent ? spacing.r24 : 0,
84
+ children: [
85
+ /*#__PURE__*/ jsx(Icon, {
86
+ name: iconName,
87
+ size: "sm",
88
+ color: getVersionTextColor(row)
89
+ }),
90
+ isLegalHoldEnabled && /*#__PURE__*/ jsx(Icon, {
91
+ name: "Rebalance",
92
+ size: "sm",
93
+ color: getVersionTextColor(row)
94
+ }),
95
+ isDeleteMarker ? /*#__PURE__*/ jsx(Text, {
96
+ color: getVersionTextColor(row),
97
+ children: value
98
+ }) : /*#__PURE__*/ jsx(Text, {
99
+ color: getVersionTextColor(row),
100
+ children: /*#__PURE__*/ jsx(Link, {
101
+ onClick: (e)=>{
102
+ e.stopPropagation();
103
+ if (isFolder) onPrefixChange?.(row.original.Key ?? '');
104
+ else onDownload?.(row.original);
105
+ },
106
+ children: value
107
+ })
108
+ })
109
+ ]
110
+ }),
111
+ lineClamp: 2
112
+ });
113
+ },
114
+ cellStyle: {
115
+ flex: NAME_COLUMN_FLEX,
116
+ width: 'unset'
117
+ }
118
+ });
119
+ const createVersionIdColumn = ()=>({
120
+ Header: 'Version ID',
121
+ accessor: 'VersionId',
122
+ id: 'versionId',
123
+ Cell: ({ row })=>{
124
+ const isFolder = 'folder' === row.original.type;
125
+ const isDeleteMarker = 'deleteMarker' === row.original.type;
126
+ const isLatest = row.original.IsLatest;
127
+ if (isFolder || isDeleteMarker) return /*#__PURE__*/ jsx(Text, {
128
+ children: "-"
129
+ });
130
+ const versionId = 'version' === row.original.type ? row.original.VersionId ?? '-' : '-';
131
+ const textColor = isLatest ? void 0 : 'infoPrimary';
132
+ return /*#__PURE__*/ jsx(ConstrainedText, {
133
+ text: versionId,
134
+ lineClamp: 1,
135
+ color: textColor
136
+ });
137
+ },
138
+ cellStyle: {
139
+ flex: VERSION_ID_COLUMN_FLEX,
140
+ textAlign: 'left',
141
+ paddingRight: spacing.r16,
142
+ width: 'unset',
143
+ maxWidth: '8rem'
144
+ }
145
+ });
146
+ const createLastModifiedColumn = ()=>({
147
+ Header: 'Modified on',
148
+ accessor: 'LastModified',
149
+ id: 'lastModified',
150
+ Cell: ({ value, row })=>{
151
+ if ('folder' === row.original.type || null == value) return /*#__PURE__*/ jsx(Text, {
152
+ children: "-"
153
+ });
154
+ return /*#__PURE__*/ jsx(Text, {
155
+ color: getVersionTextColor(row),
156
+ children: /*#__PURE__*/ jsx(FormattedDateTime, {
157
+ format: "date-time-second",
158
+ value: new Date(value)
159
+ })
160
+ });
161
+ },
162
+ cellStyle: {
163
+ flex: LAST_MODIFIED_COLUMN_FLEX,
164
+ textAlign: 'right',
165
+ paddingRight: spacing.r16,
166
+ width: 'unset',
167
+ minWidth: '10rem'
168
+ }
169
+ });
170
+ const createSizeColumn = ()=>({
171
+ Header: 'Size',
172
+ accessor: 'Size',
173
+ id: 'size',
174
+ Cell: ({ value, row })=>{
175
+ if ('folder' === row.original.type || null == value) return /*#__PURE__*/ jsx(Text, {
176
+ children: "-"
177
+ });
178
+ return /*#__PURE__*/ jsx(Box, {
179
+ display: "flex",
180
+ justifyContent: "flex-end",
181
+ children: /*#__PURE__*/ jsx(Text, {
182
+ color: getVersionTextColor(row),
183
+ children: /*#__PURE__*/ jsx(PrettyBytes, {
184
+ bytes: value,
185
+ decimals: 2
186
+ })
187
+ })
188
+ });
189
+ },
190
+ cellStyle: {
191
+ flex: SIZE_COLUMN_FLEX,
192
+ textAlign: 'right',
193
+ paddingRight: spacing.r16,
194
+ width: 'unset'
195
+ }
196
+ });
197
+ const createStorageClassColumn = ()=>({
198
+ Header: 'Storage Location',
199
+ accessor: 'StorageClass',
200
+ id: 'storageClass',
201
+ Cell: ({ value, row })=>{
202
+ if (null == value) return /*#__PURE__*/ jsx(Text, {
203
+ children: "-"
204
+ });
205
+ return /*#__PURE__*/ jsx(Box, {
206
+ display: "flex",
207
+ justifyContent: "flex-end",
208
+ children: /*#__PURE__*/ jsx(Text, {
209
+ color: getVersionTextColor(row),
210
+ children: 'STANDARD' === value ? 'default' : value
211
+ })
212
+ });
213
+ },
214
+ cellStyle: {
215
+ flex: STORAGE_CLASS_COLUMN_FLEX,
216
+ textAlign: 'right',
217
+ paddingRight: spacing.r16,
218
+ width: 'unset'
219
+ }
220
+ });
221
+ const buildCustomColumn = (columnConfig)=>({
222
+ Header: columnConfig.header,
223
+ id: String(columnConfig.id),
224
+ Cell: ({ row })=>{
225
+ const RenderComponent = columnConfig.render;
226
+ return /*#__PURE__*/ jsx(RenderComponent, {
227
+ data: row.original
228
+ });
229
+ },
230
+ cellStyle: {
231
+ width: columnConfig.width ?? 'unset',
232
+ flex: columnConfig.width ? void 0 : '1',
233
+ ...columnConfig.cellStyle
234
+ }
235
+ });
236
+ function createOverrideMap(customItems) {
237
+ return new Map(customItems.filter((item)=>item.id).map((item)=>[
238
+ String(item.id),
239
+ item
240
+ ]));
241
+ }
18
242
  const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
243
+ const { extraObjectListColumns, extraObjectListActions } = useDataBrowserUICustomization();
244
+ const invalidateQueries = useInvalidateQueries();
19
245
  const [showVersions, setShowVersions] = useState(false);
20
- const isMetadataSearchEnabled = useFeatures("metadatasearch");
21
- const metadataSearchQuery = useQueryParams().get("metadatasearch");
246
+ const isMetadataSearchEnabled = useFeatures('metadatasearch');
247
+ const metadataSearchQuery = useQueryParams().get('metadatasearch');
22
248
  const [selectedObjects, setSelectedObjects] = useState([]);
249
+ const { mutateAsync: getPresignedDownload } = useGetPresignedDownload();
250
+ const downloadingRef = useRef(new Set());
251
+ const downloadTimeoutsRef = useRef(new Map());
252
+ const { showToast } = useToast();
253
+ const onObjectSelectRef = useRef(onObjectSelect);
254
+ const onPrefixChangeRef = useRef(onPrefixChange);
255
+ useEffect(()=>{
256
+ onObjectSelectRef.current = onObjectSelect;
257
+ }, [
258
+ onObjectSelect
259
+ ]);
260
+ useEffect(()=>{
261
+ onPrefixChangeRef.current = onPrefixChange;
262
+ }, [
263
+ onPrefixChange
264
+ ]);
265
+ useEffect(()=>()=>{
266
+ downloadTimeoutsRef.current.forEach((timeout)=>clearTimeout(timeout));
267
+ downloadTimeoutsRef.current.clear();
268
+ }, []);
269
+ const handleObjectSelect = useCallback((object)=>{
270
+ onObjectSelectRef.current(object);
271
+ }, []);
272
+ const handlePrefixChange = useCallback((newPrefix)=>{
273
+ onPrefixChangeRef.current(newPrefix);
274
+ }, []);
275
+ const handleDownload = useCallback(async (object)=>{
276
+ if (!object.Key) return void console.warn('Cannot download object: missing Key');
277
+ const versionId = isObjectLike(object) ? object.VersionId : void 0;
278
+ const downloadKey = versionId ? `${object.Key}:${versionId}` : object.Key;
279
+ if (downloadingRef.current.has(downloadKey)) return void console.debug(`Download already in progress for: ${object.Key}`);
280
+ downloadingRef.current.add(downloadKey);
281
+ try {
282
+ const rawFilename = object.displayName || object.Key.split('/').pop() || 'download';
283
+ const sanitized = rawFilename.replace(/["\r\n\t]/g, '');
284
+ const encoded = encodeURIComponent(sanitized);
285
+ const result = await getPresignedDownload({
286
+ Bucket: bucketName,
287
+ Key: object.Key,
288
+ ResponseContentDisposition: `attachment; filename="${sanitized}"; filename*=UTF-8''${encoded}`,
289
+ ...versionId ? {
290
+ VersionId: versionId
291
+ } : {}
292
+ });
293
+ if (!result?.Url) throw new Error('Failed to generate presigned URL: No URL returned');
294
+ downloadFile(result.Url, sanitized, (timeoutId)=>{
295
+ downloadTimeoutsRef.current.set(`${downloadKey}_link`, timeoutId);
296
+ });
297
+ } catch (error) {
298
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
299
+ showToast({
300
+ open: true,
301
+ message: errorMessage,
302
+ status: 'error'
303
+ });
304
+ } finally{
305
+ const timeoutId = setTimeout(()=>{
306
+ downloadingRef.current.delete(downloadKey);
307
+ downloadTimeoutsRef.current.delete(downloadKey);
308
+ downloadTimeoutsRef.current.delete(`${downloadKey}_link`);
309
+ }, 1000);
310
+ downloadTimeoutsRef.current.set(downloadKey, timeoutId);
311
+ }
312
+ }, [
313
+ bucketName,
314
+ getPresignedDownload,
315
+ showToast
316
+ ]);
23
317
  const searchParams = useMemo(()=>{
24
318
  const baseParams = {
25
319
  Bucket: bucketName,
26
320
  Prefix: prefix,
27
321
  MaxKeys: DEFAULT_PAGE_SIZE,
28
- Delimiter: "/"
322
+ Delimiter: '/'
29
323
  };
30
324
  if (isMetadataSearchEnabled && metadataSearchQuery) return {
31
325
  ...baseParams,
@@ -39,48 +333,121 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
39
333
  metadataSearchQuery
40
334
  ]);
41
335
  const listObjectsQuery = useSearchObjects(searchParams, {
42
- enabled: !showVersions
336
+ enabled: Boolean(bucketName)
43
337
  });
44
- const listVersionsQuery = useSearchObjectsVersions(searchParams, {
45
- enabled: showVersions
338
+ const versionSearchParams = useMemo(()=>({
339
+ Bucket: bucketName,
340
+ Prefix: prefix,
341
+ MaxKeys: DEFAULT_PAGE_SIZE
342
+ }), [
343
+ bucketName,
344
+ prefix
345
+ ]);
346
+ const listVersionsQuery = useSearchObjectsVersions(versionSearchParams, {
347
+ enabled: showVersions && Boolean(bucketName)
46
348
  });
47
- const activeQuery = showVersions ? listVersionsQuery : listObjectsQuery;
48
349
  useEffect(()=>{
49
350
  setSelectedObjects([]);
50
351
  }, [
51
352
  prefix,
52
353
  showVersions
53
354
  ]);
54
- const { data, error, hasNextPage, fetchNextPage, isFetchingNextPage, isLoading } = activeQuery;
55
- const tableData = useMemo(()=>{
355
+ const data = showVersions ? listVersionsQuery.data : listObjectsQuery.data;
356
+ const error = showVersions ? listVersionsQuery.error : listObjectsQuery.error;
357
+ const hasNextPage = showVersions ? listVersionsQuery.hasNextPage : listObjectsQuery.hasNextPage;
358
+ const fetchNextPage = showVersions ? listVersionsQuery.fetchNextPage : listObjectsQuery.fetchNextPage;
359
+ const isFetchingNextPage = showVersions ? listVersionsQuery.isFetchingNextPage : listObjectsQuery.isFetchingNextPage;
360
+ const isLoading = showVersions ? listVersionsQuery.isLoading : listObjectsQuery.isLoading;
361
+ const objectsForLegalHold = useMemo(()=>{
362
+ const objects = [];
363
+ const currentData = showVersions ? listVersionsQuery.data : listObjectsQuery.data;
364
+ if (!currentData?.pages) return objects;
365
+ let count = 0;
366
+ if (showVersions) for (const page of currentData.pages){
367
+ if (count >= 100) break;
368
+ if (page.Versions) for (const version of page.Versions){
369
+ if (count >= 100) break;
370
+ if (version.Key) {
371
+ objects.push({
372
+ Key: version.Key,
373
+ VersionId: version.VersionId
374
+ });
375
+ count++;
376
+ }
377
+ }
378
+ }
379
+ else for (const page of currentData.pages){
380
+ if (count >= 100) break;
381
+ if (page.Contents) for (const obj of page.Contents){
382
+ if (count >= 100) break;
383
+ if (obj.Key) {
384
+ objects.push({
385
+ Key: obj.Key
386
+ });
387
+ count++;
388
+ }
389
+ }
390
+ }
391
+ return objects;
392
+ }, [
393
+ showVersions,
394
+ listVersionsQuery.data,
395
+ listObjectsQuery.data
396
+ ]);
397
+ const shouldFetchLegalHold = useMemo(()=>Boolean(bucketName) && objectsForLegalHold.length > 0, [
398
+ bucketName,
399
+ objectsForLegalHold.length
400
+ ]);
401
+ const { data: legalHoldData } = useBatchObjectLegalHold(bucketName, objectsForLegalHold, shouldFetchLegalHold);
402
+ const processFolders = useCallback((pages)=>{
56
403
  const folders = [];
404
+ pages.forEach((page)=>{
405
+ if (page.CommonPrefixes) page.CommonPrefixes.forEach((cp)=>{
406
+ if (cp.Prefix) {
407
+ const folderName = removePrefix(cp.Prefix, prefix).replace(/\/$/, '');
408
+ folders.push({
409
+ Key: cp.Prefix,
410
+ displayName: folderName + '/',
411
+ type: 'folder'
412
+ });
413
+ }
414
+ });
415
+ });
416
+ return folders;
417
+ }, [
418
+ prefix
419
+ ]);
420
+ const createObjectItem = useCallback((obj, legalHoldData)=>{
421
+ const legalHoldKey = createLegalHoldKey(obj.Key, null);
422
+ const isLegalHoldEnabled = legalHoldData?.[legalHoldKey]?.isLegalHoldEnabled ?? false;
423
+ return {
424
+ ...obj,
425
+ displayName: removePrefix(obj.Key, prefix),
426
+ type: 'object',
427
+ isLegalHoldEnabled
428
+ };
429
+ }, [
430
+ prefix
431
+ ]);
432
+ const tableData = useMemo(()=>{
433
+ let folders = [];
57
434
  const items = [];
58
435
  if (showVersions) {
59
- if (listObjectsQuery.data?.pages) listObjectsQuery.data.pages.forEach((page)=>{
60
- if (page.CommonPrefixes) page.CommonPrefixes.forEach((cp)=>{
61
- if (cp.Prefix) {
62
- const folderName = cp.Prefix.replace(prefix, "").replace(/\/$/, "");
63
- folders.push({
64
- Key: cp.Prefix,
65
- displayName: folderName + "/",
66
- type: "folder",
67
- LastModified: void 0,
68
- Size: void 0
69
- });
70
- }
71
- });
72
- });
436
+ folders = listObjectsQuery.data?.pages ? processFolders(listObjectsQuery.data.pages) : [];
437
+ const objectsWithVersions = new Set();
73
438
  if (listVersionsQuery.data?.pages) {
74
439
  const itemsByKey = {};
75
440
  listVersionsQuery.data.pages.forEach((page)=>{
76
441
  if (page.Versions) page.Versions.forEach((version)=>{
77
- if (version.Key) {
442
+ if (version.Key && !version.Key.endsWith('/')) {
443
+ objectsWithVersions.add(version.Key);
78
444
  if (!itemsByKey[version.Key]) itemsByKey[version.Key] = [];
79
445
  itemsByKey[version.Key].push(version);
80
446
  }
81
447
  });
82
448
  if (page.DeleteMarkers) page.DeleteMarkers.forEach((marker)=>{
83
- if (marker.Key) {
449
+ if (marker.Key && !marker.Key.endsWith('/')) {
450
+ objectsWithVersions.add(marker.Key);
84
451
  if (!itemsByKey[marker.Key]) itemsByKey[marker.Key] = [];
85
452
  itemsByKey[marker.Key].push({
86
453
  ...marker,
@@ -89,236 +456,201 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
89
456
  }
90
457
  });
91
458
  });
92
- Object.keys(itemsByKey).sort().forEach((key)=>{
459
+ Object.keys(itemsByKey).sort((a, b)=>a.localeCompare(b, 'en', {
460
+ sensitivity: 'base'
461
+ })).forEach((key)=>{
93
462
  const allItems = itemsByKey[key];
94
463
  allItems.sort((a, b)=>{
95
464
  if (a.IsLatest) return -1;
96
465
  if (b.IsLatest) return 1;
97
- const aDate = a.LastModified ? new Date(a.LastModified).getTime() : 0;
98
- const bDate = b.LastModified ? new Date(b.LastModified).getTime() : 0;
99
- return bDate - aDate;
466
+ const aTime = a.LastModified?.getTime() ?? 0;
467
+ const bTime = b.LastModified?.getTime() ?? 0;
468
+ return bTime - aTime;
100
469
  });
101
470
  allItems.forEach((item)=>{
102
- const baseName = item.Key.replace(prefix, "");
471
+ if (!item.Key) return;
472
+ if (item.Key.endsWith('/')) return;
473
+ const baseName = removePrefix(item.Key, prefix);
103
474
  const isLatest = item.IsLatest;
104
- const isDeleteMarker = "isDeleteMarker" in item && item.isDeleteMarker;
475
+ const isDeleteMarker = 'isDeleteMarker' in item && item.isDeleteMarker;
476
+ const legalHoldKey = createLegalHoldKey(item.Key, item.VersionId);
477
+ const isLegalHoldEnabled = legalHoldData?.[legalHoldKey]?.isLegalHoldEnabled ?? false;
105
478
  if (isDeleteMarker) items.push({
106
479
  ...item,
107
480
  displayName: baseName,
108
- type: "deleteMarker",
481
+ type: 'deleteMarker',
109
482
  IsLatest: isLatest,
110
- isDeleteMarker: true
483
+ isDeleteMarker: true,
484
+ isLegalHoldEnabled
111
485
  });
112
486
  else items.push({
113
487
  ...item,
114
488
  displayName: baseName,
115
- type: "version",
116
- IsLatest: isLatest
489
+ type: 'version',
490
+ IsLatest: isLatest,
491
+ isLegalHoldEnabled
117
492
  });
118
493
  });
119
494
  });
120
495
  }
121
- } else if (data?.pages) data.pages.forEach((page)=>{
122
- if (page.CommonPrefixes) page.CommonPrefixes.forEach((cp)=>{
123
- if (cp.Prefix) {
124
- const folderName = cp.Prefix.replace(prefix, "").replace(/\/$/, "");
125
- folders.push({
126
- Key: cp.Prefix,
127
- displayName: folderName + "/",
128
- type: "folder",
129
- LastModified: void 0,
130
- Size: void 0
131
- });
132
- }
496
+ if (listObjectsQuery.data?.pages) listObjectsQuery.data.pages.forEach((page)=>{
497
+ if (page.Contents) page.Contents.forEach((obj)=>{
498
+ if (obj.Key && !obj.Key.endsWith('/') && !objectsWithVersions.has(obj.Key)) items.push(createObjectItem(obj, legalHoldData));
499
+ });
133
500
  });
134
- if (page.Contents) page.Contents.forEach((obj)=>{
135
- if (obj.Key) items.push({
136
- ...obj,
137
- displayName: obj.Key.replace(prefix, ""),
138
- type: "object"
501
+ } else {
502
+ folders = data?.pages ? processFolders(data.pages) : [];
503
+ if (data?.pages) data.pages.forEach((page)=>{
504
+ if (page.Contents) page.Contents.forEach((obj)=>{
505
+ if (obj.Key && !obj.Key.endsWith('/')) items.push(createObjectItem(obj, legalHoldData));
139
506
  });
140
507
  });
141
- });
508
+ }
142
509
  const allItems = [
143
510
  ...folders,
144
511
  ...items
145
512
  ];
146
513
  return allItems;
147
514
  }, [
148
- data,
149
- prefix,
150
515
  showVersions,
151
516
  listObjectsQuery.data,
152
- listVersionsQuery.data
517
+ listVersionsQuery.data,
518
+ legalHoldData,
519
+ processFolders,
520
+ createObjectItem
521
+ ]);
522
+ const versionIdColumn = useMemo(()=>createVersionIdColumn(), []);
523
+ const lastModifiedColumn = useMemo(()=>createLastModifiedColumn(), []);
524
+ const sizeColumn = useMemo(()=>createSizeColumn(), []);
525
+ const storageClassColumn = useMemo(()=>createStorageClassColumn(), []);
526
+ const nameColumn = useMemo(()=>createNameColumn(handlePrefixChange, handleDownload), [
527
+ handlePrefixChange,
528
+ handleDownload
153
529
  ]);
154
530
  const columns = useMemo(()=>{
155
- const cols = [
156
- {
157
- Header: "Name",
158
- accessor: "displayName",
159
- id: "name",
160
- sortType: (rowA, rowB)=>{
161
- const aIsFolder = "folder" === rowA.original.type;
162
- const bIsFolder = "folder" === rowB.original.type;
163
- if (aIsFolder && !bIsFolder) return -1;
164
- if (!aIsFolder && bIsFolder) return 1;
165
- const aName = String(rowA.values.displayName || "");
166
- const bName = String(rowB.values.displayName || "");
167
- return aName.localeCompare(bName);
168
- },
169
- Cell: ({ value, row })=>{
170
- const displayValue = value;
171
- const isFolder = "folder" === row.original.type;
172
- const isVersion = "version" === row.original.type;
173
- const isDeleteMarker = "deleteMarker" === row.original.type;
174
- const isLatest = row.original.IsLatest;
175
- let iconName;
176
- iconName = isFolder ? "Folder" : isDeleteMarker ? "Deletion-marker" : "File";
177
- const shouldIndent = isVersion && !isLatest;
178
- return /*#__PURE__*/ jsx(ConstrainedText, {
179
- text: /*#__PURE__*/ jsxs("div", {
180
- style: {
181
- display: "flex",
182
- alignItems: "center",
183
- gap: spacing.r8,
184
- paddingLeft: shouldIndent ? spacing.r24 : 0
185
- },
186
- children: [
187
- /*#__PURE__*/ jsx(Icon, {
188
- name: iconName,
189
- size: "sm"
190
- }),
191
- isDeleteMarker ? /*#__PURE__*/ jsx(Text, {
192
- children: displayValue
193
- }) : /*#__PURE__*/ jsx(Link, {
194
- onClick: (e)=>{
195
- e.stopPropagation();
196
- if (isFolder) onPrefixChange?.(row.original.Key || "");
197
- else onObjectSelect(row.original);
198
- },
199
- children: displayValue
200
- })
201
- ]
202
- }),
203
- lineClamp: 2
204
- });
205
- },
206
- cellStyle: {
207
- flex: "2",
208
- width: "unset"
209
- }
210
- }
531
+ const defaultColumnsMap = {
532
+ name: nameColumn,
533
+ versionId: versionIdColumn,
534
+ lastModified: lastModifiedColumn,
535
+ size: sizeColumn,
536
+ storageClass: storageClassColumn
537
+ };
538
+ const customColumns = (extraObjectListColumns || []).map((config)=>buildCustomColumn(config));
539
+ const customColumnsMap = createOverrideMap(customColumns);
540
+ const getColumn = (id)=>customColumnsMap.get(id) || defaultColumnsMap[id];
541
+ const extraColumns = customColumns.filter((col)=>col.id && !(col.id in defaultColumnsMap));
542
+ const finalColumns = [
543
+ getColumn('name'),
544
+ ...showVersions ? [
545
+ getColumn('versionId')
546
+ ] : [],
547
+ ...extraColumns,
548
+ getColumn('lastModified'),
549
+ getColumn('size'),
550
+ getColumn('storageClass')
211
551
  ];
212
- if (showVersions) cols.push({
213
- Header: "Version ID",
214
- accessor: "VersionId",
215
- id: "versionId",
216
- Cell: ({ row })=>{
217
- const isFolder = "folder" === row.original.type;
218
- const isDeleteMarker = "deleteMarker" === row.original.type;
219
- const isLatest = row.original.IsLatest;
220
- if (isFolder || isDeleteMarker) return /*#__PURE__*/ jsx(Text, {
221
- children: "-"
222
- });
223
- const versionId = "version" === row.original.type ? row.original.VersionId || "-" : "-";
224
- const textColor = isLatest ? void 0 : "infoPrimary";
225
- return /*#__PURE__*/ jsx(ConstrainedText, {
226
- text: versionId,
227
- lineClamp: 1,
228
- color: textColor
229
- });
230
- },
231
- cellStyle: {
232
- flex: "1.5",
233
- textAlign: "left",
234
- paddingRight: spacing.r16,
235
- width: "unset",
236
- maxWidth: "8rem"
237
- }
552
+ return finalColumns;
553
+ }, [
554
+ showVersions,
555
+ extraObjectListColumns,
556
+ nameColumn,
557
+ versionIdColumn,
558
+ lastModifiedColumn,
559
+ sizeColumn,
560
+ storageClassColumn
561
+ ]);
562
+ const handleUploadSuccess = useCallback(()=>{
563
+ invalidateQueries({
564
+ queryKey: [
565
+ 'ListObjects'
566
+ ]
238
567
  });
239
- cols.push({
240
- Header: "Modified on",
241
- accessor: "LastModified",
242
- id: "lastModified",
243
- Cell: ({ value, row })=>{
244
- if ("folder" === row.original.type || !value) return /*#__PURE__*/ jsx(Text, {
245
- children: "-"
246
- });
247
- const dateValue = value;
248
- return /*#__PURE__*/ jsx(Text, {
249
- color: getVersionTextColor(row),
250
- children: /*#__PURE__*/ jsx(FormattedDateTime, {
251
- format: "date-time-second",
252
- value: new Date(dateValue)
253
- })
254
- });
255
- },
256
- cellStyle: {
257
- flex: "1",
258
- textAlign: "right",
259
- paddingRight: spacing.r16,
260
- width: "unset",
261
- minWidth: "10rem"
262
- }
263
- }, {
264
- Header: "Size",
265
- accessor: "Size",
266
- id: "size",
267
- Cell: ({ value, row })=>{
268
- if ("folder" === row.original.type || null == value) return /*#__PURE__*/ jsx(Text, {
269
- children: "-"
270
- });
271
- const sizeValue = value;
272
- return /*#__PURE__*/ jsx(Wrap, {
273
- style: {
274
- justifyContent: "flex-end"
275
- },
276
- children: /*#__PURE__*/ jsx(Text, {
277
- color: getVersionTextColor(row),
278
- children: /*#__PURE__*/ jsx(PrettyBytes, {
279
- bytes: sizeValue,
280
- decimals: 2
281
- })
282
- })
283
- });
568
+ invalidateQueries({
569
+ queryKey: [
570
+ 'ListObjectVersions'
571
+ ]
572
+ });
573
+ }, [
574
+ invalidateQueries
575
+ ]);
576
+ const handleFolderSuccess = useCallback(()=>{
577
+ invalidateQueries({
578
+ queryKey: [
579
+ 'ListObjects'
580
+ ]
581
+ });
582
+ invalidateQueries({
583
+ queryKey: [
584
+ 'ListObjectVersions'
585
+ ]
586
+ });
587
+ }, [
588
+ invalidateQueries
589
+ ]);
590
+ const handleUploadError = useCallback(()=>{}, []);
591
+ const handleFolderError = useCallback(()=>{}, []);
592
+ const renderUploadAction = useCallback(()=>/*#__PURE__*/ jsx(UploadButton, {
593
+ bucket: bucketName,
594
+ prefix: prefix,
595
+ onUploadSuccess: handleUploadSuccess,
596
+ onUploadError: handleUploadError
597
+ }), [
598
+ bucketName,
599
+ prefix,
600
+ handleUploadSuccess,
601
+ handleUploadError
602
+ ]);
603
+ const renderCreateFolderAction = useCallback(()=>/*#__PURE__*/ jsx(CreateFolderButton, {
604
+ bucket: bucketName,
605
+ prefix: prefix,
606
+ onFolderSuccess: handleFolderSuccess,
607
+ onFolderError: handleFolderError
608
+ }), [
609
+ bucketName,
610
+ prefix,
611
+ handleFolderSuccess,
612
+ handleFolderError
613
+ ]);
614
+ const renderDeleteAction = useCallback(()=>/*#__PURE__*/ jsx(DeleteObjectButton, {
615
+ objects: selectedObjects,
616
+ bucketName: bucketName
617
+ }), [
618
+ selectedObjects,
619
+ bucketName
620
+ ]);
621
+ const actions = useMemo(()=>{
622
+ const defaultActionsMap = {
623
+ upload: {
624
+ id: 'upload',
625
+ render: renderUploadAction
284
626
  },
285
- cellStyle: {
286
- flex: "1",
287
- textAlign: "right",
288
- paddingRight: spacing.r16,
289
- width: "unset"
290
- }
291
- }, {
292
- Header: "Storage Location",
293
- accessor: "StorageClass",
294
- id: "storageClass",
295
- Cell: ({ value, row })=>{
296
- if (!value) return /*#__PURE__*/ jsx(Text, {
297
- children: "-"
298
- });
299
- const storageClass = value;
300
- return /*#__PURE__*/ jsx(Wrap, {
301
- style: {
302
- justifyContent: "flex-end"
303
- },
304
- children: /*#__PURE__*/ jsx(Text, {
305
- color: getVersionTextColor(row),
306
- children: "STANDARD" === storageClass ? "default" : storageClass
307
- })
308
- });
627
+ createFolder: {
628
+ id: 'createFolder',
629
+ render: renderCreateFolderAction
309
630
  },
310
- cellStyle: {
311
- flex: "1",
312
- textAlign: "right",
313
- paddingRight: spacing.r16,
314
- width: "unset"
631
+ delete: {
632
+ id: 'delete',
633
+ render: renderDeleteAction
315
634
  }
316
- });
317
- return cols;
635
+ };
636
+ const customActions = (extraObjectListActions || []).map((config)=>({
637
+ id: config.id,
638
+ render: config.render
639
+ }));
640
+ const customActionsMap = createOverrideMap(customActions);
641
+ const getAction = (id)=>customActionsMap.get(id) || defaultActionsMap[id];
642
+ const extraActions = customActions.filter((action)=>!(action.id in defaultActionsMap));
643
+ return [
644
+ getAction('upload'),
645
+ getAction('createFolder'),
646
+ getAction('delete'),
647
+ ...extraActions
648
+ ];
318
649
  }, [
319
- onObjectSelect,
320
- onPrefixChange,
321
- showVersions
650
+ renderUploadAction,
651
+ renderCreateFolderAction,
652
+ renderDeleteAction,
653
+ extraObjectListActions
322
654
  ]);
323
655
  const handleReachBottom = useCallback(()=>{
324
656
  if (hasNextPage && !isFetchingNextPage) fetchNextPage();
@@ -327,18 +659,33 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
327
659
  isFetchingNextPage,
328
660
  fetchNextPage
329
661
  ]);
330
- const tableStatus = isLoading ? "loading" : error ? "error" : "success";
662
+ const handleMultiSelectionChanged = useCallback((rows)=>{
663
+ const objects = rows.map((row)=>row.original);
664
+ setSelectedObjects(objects);
665
+ }, []);
666
+ const handleSingleRowSelected = useCallback((row)=>{
667
+ handleObjectSelect(row.original);
668
+ }, [
669
+ handleObjectSelect
670
+ ]);
671
+ const handleToggleAll = useCallback((selected)=>{
672
+ selected ? setSelectedObjects(tableData) : setSelectedObjects([]);
673
+ }, [
674
+ tableData
675
+ ]);
676
+ const tableStatus = isLoading ? 'loading' : error ? 'error' : 'success';
677
+ const entityName = useMemo(()=>({
678
+ en: {
679
+ singular: 'object',
680
+ plural: 'objects'
681
+ }
682
+ }), []);
331
683
  return /*#__PURE__*/ jsxs(Table, {
332
684
  columns: columns,
333
685
  data: tableData,
334
686
  status: tableStatus,
335
687
  onBottom: handleReachBottom,
336
- entityName: {
337
- en: {
338
- singular: "object",
339
- plural: "objects"
340
- }
341
- },
688
+ entityName: entityName,
342
689
  children: [
343
690
  /*#__PURE__*/ jsxs(Wrap, {
344
691
  padding: spacing.r16,
@@ -346,7 +693,7 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
346
693
  isMetadataSearchEnabled ? /*#__PURE__*/ jsx(MetadataSearch, {
347
694
  isError: !!error
348
695
  }) : /*#__PURE__*/ jsx(Table.SearchWithQueryParams, {
349
- queryParams: "search"
696
+ queryParams: SEARCH_QUERY_PARAM
350
697
  }),
351
698
  /*#__PURE__*/ jsxs(Box, {
352
699
  display: "flex",
@@ -354,33 +701,20 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
354
701
  alignItems: "center",
355
702
  gap: spacing.r8,
356
703
  children: [
357
- /*#__PURE__*/ jsxs(Box, {
704
+ /*#__PURE__*/ jsx(Box, {
358
705
  display: "flex",
359
706
  alignItems: "center",
360
707
  gap: spacing.r8,
361
- children: [
362
- /*#__PURE__*/ jsx(UploadButton, {
363
- bucket: bucketName,
364
- prefix: prefix,
365
- onUploadSuccess: ()=>{},
366
- onUploadError: ()=>{}
367
- }),
368
- /*#__PURE__*/ jsx(CreateFolderButton, {
369
- bucket: bucketName,
370
- prefix: prefix,
371
- onFolderSuccess: ()=>{},
372
- onFolderError: ()=>{}
373
- }),
374
- /*#__PURE__*/ jsx(DeleteObjectButton, {
375
- objects: selectedObjects,
376
- bucketName: bucketName
377
- })
378
- ]
708
+ children: actions.map((action)=>/*#__PURE__*/ jsx(Fragment, {
709
+ children: action.render()
710
+ }, action.id))
379
711
  }),
380
712
  /*#__PURE__*/ jsx(Toggle, {
381
713
  toggle: showVersions,
382
714
  onChange: (e)=>setShowVersions(e.target.checked),
383
- label: "List Versions"
715
+ label: "List Versions",
716
+ "aria-label": showVersions ? 'Hide object versions' : 'Show object versions',
717
+ "aria-pressed": showVersions
384
718
  })
385
719
  ]
386
720
  })
@@ -388,20 +722,13 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange })=>{
388
722
  }),
389
723
  /*#__PURE__*/ jsx(Table.MultiSelectableContent, {
390
724
  rowHeight: "h40",
391
- onMultiSelectionChanged: (rows)=>{
392
- const objects = rows.map((row)=>row.original);
393
- setSelectedObjects(objects);
394
- },
395
- onSingleRowSelected: (row)=>{
396
- onObjectSelect(row.original);
397
- },
398
- onToggleAll: (selected)=>{
399
- console.log("Toggle all", selected);
400
- },
725
+ onMultiSelectionChanged: handleMultiSelectionChanged,
726
+ onSingleRowSelected: handleSingleRowSelected,
727
+ onToggleAll: handleToggleAll,
401
728
  separationLineVariant: "backgroundLevel1",
402
729
  isLoadingMoreItems: isFetchingNextPage
403
730
  })
404
731
  ]
405
732
  });
406
733
  };
407
- export { ObjectList };
734
+ export { ObjectList, isObjectLike };