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

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 (206) hide show
  1. package/dist/components/DataBrowserUI.d.ts +15 -8
  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 +121 -122
  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 +256 -200
  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 +251 -250
  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 +62 -62
  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 +23 -22
  57. package/dist/components/index.js +3 -2
  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 +112 -111
  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 +15 -4
  90. package/dist/components/providers/DataBrowserProvider.js +33 -11
  91. package/dist/components/search/MetadataSearch.js +26 -25
  92. package/dist/components/search/SearchHints.js +1 -1
  93. package/dist/components/ui/ArrayFieldActions.js +4 -4
  94. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +1 -1
  95. package/dist/components/ui/ConfirmDeleteRuleModal.js +1 -1
  96. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  97. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  98. package/dist/components/ui/FilterFormSection.d.ts +2 -2
  99. package/dist/components/ui/FilterFormSection.js +29 -29
  100. package/dist/components/ui/Search.elements.d.ts +1 -1
  101. package/dist/components/ui/Search.elements.js +7 -7
  102. package/dist/components/ui/Table.elements.js +5 -5
  103. package/dist/config/factory.d.ts +23 -10
  104. package/dist/config/factory.js +22 -7
  105. package/dist/config/types.d.ts +20 -3
  106. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +2 -2
  107. package/dist/hooks/__tests__/useISVBucketDetection.test.js +41 -41
  108. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +25 -25
  109. package/dist/hooks/bucketConfiguration.d.ts +1 -1
  110. package/dist/hooks/bucketConfiguration.js +48 -48
  111. package/dist/hooks/bucketOperations.d.ts +1 -1
  112. package/dist/hooks/bucketOperations.js +6 -6
  113. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +78 -78
  114. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +78 -78
  115. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +42 -42
  116. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +61 -61
  117. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +63 -63
  118. package/dist/hooks/factories/index.d.ts +4 -4
  119. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  120. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +15 -12
  121. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  122. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  123. package/dist/hooks/factories/useCreateS3MutationHook.js +6 -1
  124. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  125. package/dist/hooks/factories/useCreateS3QueryHook.js +8 -5
  126. package/dist/hooks/index.d.ts +14 -13
  127. package/dist/hooks/index.js +2 -1
  128. package/dist/hooks/loginOperations.d.ts +1 -1
  129. package/dist/hooks/loginOperations.js +1 -1
  130. package/dist/hooks/objectOperations.d.ts +2 -2
  131. package/dist/hooks/objectOperations.js +49 -49
  132. package/dist/hooks/presignedOperations.d.ts +2 -2
  133. package/dist/hooks/presignedOperations.js +3 -3
  134. package/dist/hooks/useBatchObjectLegalHold.js +7 -4
  135. package/dist/hooks/useDataBrowserNavigate.d.ts +14 -0
  136. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  137. package/dist/hooks/useDeleteBucketConfigRule.d.ts +2 -2
  138. package/dist/hooks/useDeleteBucketConfigRule.js +4 -4
  139. package/dist/hooks/useEmptyBucket.js +10 -10
  140. package/dist/hooks/useISVBucketDetection.js +3 -3
  141. package/dist/hooks/useIsBucketEmpty.js +4 -4
  142. package/dist/hooks/useLoginMutation.d.ts +1 -1
  143. package/dist/hooks/useLoginMutation.js +1 -1
  144. package/dist/hooks/useS3Client.d.ts +5 -0
  145. package/dist/hooks/useS3Client.js +3 -2
  146. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  147. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  148. package/dist/index.d.ts +6 -6
  149. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  150. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  151. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  152. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  153. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  154. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  155. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  156. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  157. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  158. package/dist/test/msw/handlers/headObject.js +31 -13
  159. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  160. package/dist/test/msw/handlers/listBuckets.js +5 -3
  161. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  162. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  163. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  164. package/dist/test/msw/handlers/listObjects.js +35 -23
  165. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  166. package/dist/test/msw/handlers/objectLegalHold.js +31 -16
  167. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  168. package/dist/test/msw/handlers/objectRetention.js +31 -17
  169. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  170. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  171. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  172. package/dist/test/msw/handlers/putObject.js +27 -12
  173. package/dist/test/msw/handlers.d.ts +3 -3
  174. package/dist/test/msw/handlers.js +72 -49
  175. package/dist/test/msw/index.d.ts +2 -2
  176. package/dist/test/msw/server.d.ts +1 -1
  177. package/dist/test/msw/server.js +1 -1
  178. package/dist/test/msw/utils.js +2 -2
  179. package/dist/test/setup.d.ts +1 -1
  180. package/dist/test/setup.js +19 -19
  181. package/dist/test/testUtils.d.ts +9 -15
  182. package/dist/test/testUtils.js +78 -92
  183. package/dist/test/utils/errorHandling.test.js +119 -119
  184. package/dist/types/index.d.ts +6 -31
  185. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  186. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +429 -0
  187. package/dist/utils/constants.js +8 -8
  188. package/dist/utils/deletion/index.d.ts +2 -2
  189. package/dist/utils/deletion/messages.d.ts +1 -1
  190. package/dist/utils/deletion/messages.js +4 -4
  191. package/dist/utils/errorHandling.d.ts +3 -3
  192. package/dist/utils/errorHandling.js +6 -6
  193. package/dist/utils/hooks.js +8 -8
  194. package/dist/utils/index.d.ts +5 -4
  195. package/dist/utils/index.js +2 -0
  196. package/dist/utils/proxyMiddleware.d.ts +1 -1
  197. package/dist/utils/proxyMiddleware.js +6 -11
  198. package/dist/utils/s3Client.d.ts +2 -2
  199. package/dist/utils/s3Client.js +1 -1
  200. package/dist/utils/s3ConfigIdentifier.d.ts +68 -0
  201. package/dist/utils/s3ConfigIdentifier.js +55 -0
  202. package/dist/utils/s3RuleUtils.d.ts +5 -5
  203. package/dist/utils/s3RuleUtils.js +17 -17
  204. package/dist/utils/useSupportedNotificationEvents.d.ts +6 -0
  205. package/dist/utils/useSupportedNotificationEvents.js +7 -0
  206. package/package.json +2 -2
@@ -1,7 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { usePrefixWithSlash, useQueryParams } from "../../utils/hooks.js";
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
- import { useLocation, useNavigate } from "react-router-dom";
4
+ import { useLocation } from "react-router";
5
+ import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
5
6
  import { SearchContainer, SearchInputContainer, searchIcon } from "../ui/Search.elements.js";
6
7
  import { Box, Button, Input } from "@scality/core-ui/dist/next";
7
8
  import { Icon } from "@scality/core-ui";
@@ -9,43 +10,43 @@ import { SearchHints } from "./SearchHints.js";
9
10
  const METADATA_SEARCH_HINT_ITEMS = [
10
11
  {
11
12
  label: 'files with extension ".pdf"',
12
- query: "key like /pdf$/"
13
+ query: 'key like /pdf$/'
13
14
  },
14
15
  {
15
- label: "files bigger than 1MB",
16
- query: "content-length > 1000000"
16
+ label: 'files bigger than 1MB',
17
+ query: 'content-length > 1000000'
17
18
  },
18
19
  {
19
- label: "file names that contain scality (case insensitive)",
20
- query: "key like /scality/i"
20
+ label: 'file names that contain scality (case insensitive)',
21
+ query: 'key like /scality/i'
21
22
  },
22
23
  {
23
- label: "files with metadata field color set to green",
24
+ label: 'files with metadata field color set to green',
24
25
  query: 'x-amz-meta-color="green"'
25
26
  },
26
27
  {
27
- label: "files tagged with color blue",
28
- query: "tags.color=blue"
28
+ label: 'files tagged with color blue',
29
+ query: 'tags.color=blue'
29
30
  },
30
31
  {
31
- label: "PDF files (from content-type)",
32
- query: "content-type=application/pdf"
32
+ label: 'PDF files (from content-type)',
33
+ query: 'content-type=application/pdf'
33
34
  },
34
35
  {
35
- label: "file names that contain the word Report (case sensitive)",
36
- query: "key like Report"
36
+ label: 'file names that contain the word Report (case sensitive)',
37
+ query: 'key like Report'
37
38
  },
38
39
  {
39
- label: "files waiting to be replicated",
40
+ label: 'files waiting to be replicated',
40
41
  query: 'replication-status="PENDING"'
41
42
  }
42
43
  ];
43
44
  const MetadataSearch = ({ isError })=>{
44
- const navigate = useNavigate();
45
+ const navigate = useDataBrowserNavigate();
45
46
  const location = useLocation();
46
47
  const query = useQueryParams();
47
- const searchInput = query.get("metadatasearch");
48
- const [inputText, setInputText] = useState(searchInput || "");
48
+ const searchInput = query.get('metadatasearch');
49
+ const [inputText, setInputText] = useState(searchInput || '');
49
50
  const [hintsShown, setHintsShown] = useState(false);
50
51
  const prefixWithSlash = usePrefixWithSlash();
51
52
  const inputRef = useRef(null);
@@ -54,8 +55,8 @@ const MetadataSearch = ({ isError })=>{
54
55
  e.preventDefault();
55
56
  if (!inputText || prefixWithSlash) return;
56
57
  const newQuery = new URLSearchParams(location.search);
57
- newQuery.set("metadatasearch", inputText);
58
- navigate(`${location.pathname}?${newQuery.toString()}`);
58
+ newQuery.set('metadatasearch', inputText);
59
+ navigate(`?${newQuery.toString()}`);
59
60
  }, [
60
61
  inputText,
61
62
  prefixWithSlash,
@@ -80,19 +81,19 @@ const MetadataSearch = ({ isError })=>{
80
81
  const handleClickOutside = (event)=>{
81
82
  if (hintsShown && inputRef.current && hintsRef.current && !inputRef.current.contains(event.target) && !hintsRef.current.contains(event.target)) setHintsShown(false);
82
83
  };
83
- document.addEventListener("mousedown", handleClickOutside);
84
+ document.addEventListener('mousedown', handleClickOutside);
84
85
  return ()=>{
85
- document.removeEventListener("mousedown", handleClickOutside);
86
+ document.removeEventListener('mousedown', handleClickOutside);
86
87
  };
87
88
  }, [
88
89
  hintsShown
89
90
  ]);
90
91
  const reset = useCallback(()=>{
91
92
  setHintsShown(false);
92
- setInputText("");
93
+ setInputText('');
93
94
  const newQuery = new URLSearchParams(location.search);
94
- newQuery.delete("metadatasearch");
95
- navigate(`${location.pathname}?${newQuery.toString()}`);
95
+ newQuery.delete('metadatasearch');
96
+ navigate(`?${newQuery.toString()}`);
96
97
  }, [
97
98
  location,
98
99
  navigate
@@ -135,7 +136,7 @@ const MetadataSearch = ({ isError })=>{
135
136
  name: "Close"
136
137
  }),
137
138
  tooltip: {
138
- overlay: "Reset search"
139
+ overlay: 'Reset search'
139
140
  },
140
141
  onClick: reset,
141
142
  "aria-label": "Clear search input"
@@ -17,5 +17,5 @@ const SearchHints = /*#__PURE__*/ forwardRef(({ hints, onHintClick }, ref)=>/*#_
17
17
  }, index))
18
18
  ]
19
19
  }));
20
- SearchHints.displayName = "SearchHints";
20
+ SearchHints.displayName = 'SearchHints';
21
21
  export { SearchHints };
@@ -2,10 +2,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Box, Button } from "@scality/core-ui/dist/next";
3
3
  import { Icon, spacing } from "@scality/core-ui";
4
4
  import { convertSizeToRem } from "@scality/core-ui/dist/components/inputv2/inputv2";
5
- function ArrayFieldActions({ onRemove, onAdd, canRemove, canAdd = true, showAdd, removeLabel = "Remove", addLabel = "Add" }) {
5
+ function ArrayFieldActions({ onRemove, onAdd, canRemove, canAdd = true, showAdd, removeLabel = 'Remove', addLabel = 'Add' }) {
6
6
  return /*#__PURE__*/ jsxs(Box, {
7
7
  display: "flex",
8
- width: convertSizeToRem("1/2"),
8
+ width: convertSizeToRem('1/2'),
9
9
  gap: spacing.r8,
10
10
  justifyContent: "flex-start",
11
11
  children: [
@@ -20,7 +20,7 @@ function ArrayFieldActions({ onRemove, onAdd, canRemove, canAdd = true, showAdd,
20
20
  disabled: !canRemove,
21
21
  tooltip: {
22
22
  overlay: removeLabel,
23
- placement: "top"
23
+ placement: 'top'
24
24
  }
25
25
  }),
26
26
  showAdd && /*#__PURE__*/ jsx(Button, {
@@ -33,7 +33,7 @@ function ArrayFieldActions({ onRemove, onAdd, canRemove, canAdd = true, showAdd,
33
33
  "aria-label": addLabel,
34
34
  tooltip: {
35
35
  overlay: addLabel,
36
- placement: "top"
36
+ placement: 'top'
37
37
  },
38
38
  disabled: !canAdd
39
39
  })
@@ -4,7 +4,7 @@ interface ConfirmDeleteRuleModalProps {
4
4
  /** Rule ID to display in confirmation message */
5
5
  ruleId: string;
6
6
  /** Type of rule (e.g., "lifecycle", "replication") */
7
- ruleType: "lifecycle" | "replication";
7
+ ruleType: 'lifecycle' | 'replication';
8
8
  /** Whether deletion is in progress */
9
9
  isDeleting: boolean;
10
10
  /** Callback when user confirms deletion */
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Loader, Modal, Stack, Wrap } from "@scality/core-ui";
3
3
  import { Button } from "@scality/core-ui/dist/next";
4
4
  function ConfirmDeleteRuleModal({ isOpen, ruleId, ruleType, isDeleting, onConfirm, onCancel }) {
5
- const ruleTypeLabel = "lifecycle" === ruleType ? "Lifecycle" : "Replication";
5
+ const ruleTypeLabel = 'lifecycle' === ruleType ? 'Lifecycle' : 'Replication';
6
6
  return /*#__PURE__*/ jsxs(Modal, {
7
7
  close: onCancel,
8
8
  isOpen: isOpen,
@@ -1,4 +1,4 @@
1
- import { Objects } from "../objects/DeleteObjectButton";
1
+ import { Objects } from '../objects/DeleteObjectButton';
2
2
  export declare const DeleteObjectModalContent: ({ objects, onRemove, }: {
3
3
  objects: Objects;
4
4
  onRemove: (key: string) => void;
@@ -12,30 +12,30 @@ const Container = styled_components(Box)`
12
12
  const DeleteObjectModalContent = ({ objects, onRemove })=>{
13
13
  const columns = useMemo(()=>[
14
14
  {
15
- Header: "Name",
16
- accessor: "Key",
15
+ Header: 'Name',
16
+ accessor: 'Key',
17
17
  Cell: ({ value })=>/*#__PURE__*/ jsx(ConstrainedText, {
18
18
  text: value,
19
19
  lineClamp: 1
20
20
  }),
21
- id: "name"
21
+ id: 'name'
22
22
  },
23
23
  {
24
- Header: "Size",
25
- accessor: "Size",
24
+ Header: 'Size',
25
+ accessor: 'Size',
26
26
  cellStyle: {
27
- textAlign: "right"
27
+ textAlign: 'right'
28
28
  },
29
29
  Cell: ({ value })=>/*#__PURE__*/ jsx(PrettyBytes, {
30
30
  bytes: Number(value)
31
31
  }),
32
- id: "size"
32
+ id: 'size'
33
33
  },
34
34
  {
35
- Header: "",
36
- accessor: "type",
35
+ Header: '',
36
+ accessor: 'type',
37
37
  cellStyle: {
38
- width: "0.625rem"
38
+ width: '0.625rem'
39
39
  },
40
40
  Cell: (row)=>{
41
41
  const objectKey = row.row.original.Key;
@@ -52,7 +52,7 @@ const DeleteObjectModalContent = ({ objects, onRemove })=>{
52
52
  onRemove
53
53
  ]);
54
54
  const HEADER_AND_SPACING_ROWS = 3;
55
- const rowHeight = "h40";
55
+ const rowHeight = 'h40';
56
56
  const tableRowHeightInRem = tableRowHeight[rowHeight];
57
57
  return /*#__PURE__*/ jsx(Container, {
58
58
  height: `calc(${objects.length + HEADER_AND_SPACING_ROWS} * (${tableRowHeightInRem}rem + 1px))`,
@@ -62,7 +62,7 @@ const DeleteObjectModalContent = ({ objects, onRemove })=>{
62
62
  children: /*#__PURE__*/ jsx(Table.SingleSelectableContent, {
63
63
  rowHeight: "h40",
64
64
  separationLineVariant: "backgroundLevel3",
65
- selectedId: "Name",
65
+ selectedId: 'Name',
66
66
  onRowSelected: ()=>{}
67
67
  })
68
68
  })
@@ -1,6 +1,6 @@
1
- import { UseFormRegisterReturn } from "react-hook-form";
1
+ import { UseFormRegisterReturn } from 'react-hook-form';
2
2
  export interface FilterFormValues {
3
- filterType: "none" | "prefix" | "tags" | "and";
3
+ filterType: 'none' | 'prefix' | 'tags' | 'and';
4
4
  prefix: string;
5
5
  tags: Array<{
6
6
  key: string;
@@ -5,28 +5,28 @@ import { Box, Input, Select } from "@scality/core-ui/dist/next";
5
5
  import { ArrayFieldActions } from "./ArrayFieldActions.js";
6
6
  const filterTypeOptions = [
7
7
  {
8
- value: "none",
9
- label: "All objects"
8
+ value: 'none',
9
+ label: 'All objects'
10
10
  },
11
11
  {
12
- value: "prefix",
13
- label: "Prefix filter"
12
+ value: 'prefix',
13
+ label: 'Prefix filter'
14
14
  },
15
15
  {
16
- value: "tags",
17
- label: "Tags filter"
16
+ value: 'tags',
17
+ label: 'Tags filter'
18
18
  },
19
19
  {
20
- value: "and",
21
- label: "Prefix and tags filter"
20
+ value: 'and',
21
+ label: 'Prefix and tags filter'
22
22
  }
23
23
  ];
24
- const shouldShowPrefix = (filterType)=>"prefix" === filterType || "and" === filterType;
25
- const shouldShowTags = (filterType)=>"tags" === filterType || "and" === filterType;
24
+ const shouldShowPrefix = (filterType)=>'prefix' === filterType || 'and' === filterType;
25
+ const shouldShowTags = (filterType)=>'tags' === filterType || 'and' === filterType;
26
26
  function FilterFormSection({ filterType, onFilterTypeChange, prefixRegister, tagFields, tagKeyRegister, tagValueRegister, getTagKeyValue, getTagValueValue, appendTag, removeTag, errors, forceLabelWidth = convertRemToPixels(15) }) {
27
27
  return /*#__PURE__*/ jsxs(FormSection, {
28
28
  title: {
29
- name: "Filter"
29
+ name: 'Filter'
30
30
  },
31
31
  forceLabelWidth: forceLabelWidth,
32
32
  children: [
@@ -50,7 +50,7 @@ function FilterFormSection({ filterType, onFilterTypeChange, prefixRegister, tag
50
50
  direction: "horizontal",
51
51
  error: errors?.prefix?.message,
52
52
  helpErrorPosition: "bottom",
53
- required: "prefix" === filterType,
53
+ required: 'prefix' === filterType,
54
54
  content: /*#__PURE__*/ jsx(Input, {
55
55
  id: "prefix",
56
56
  placeholder: "folder/",
@@ -109,8 +109,8 @@ function FilterFormSection({ filterType, onFilterTypeChange, prefixRegister, tag
109
109
  showAdd: index === tagFields.length - 1,
110
110
  onRemove: ()=>removeTag(index),
111
111
  onAdd: ()=>appendTag({
112
- key: "",
113
- value: ""
112
+ key: '',
113
+ value: ''
114
114
  }),
115
115
  canRemove: tagFields.length > 1,
116
116
  canAdd: !!getTagKeyValue(index) && !!getTagValueValue(index),
@@ -126,32 +126,32 @@ function FilterFormSection({ filterType, onFilterTypeChange, prefixRegister, tag
126
126
  });
127
127
  }
128
128
  const createFilterValidationSchema = (Joi)=>({
129
- filterType: Joi.string().valid("none", "prefix", "tags", "and").required(),
130
- prefix: Joi.when("filterType", {
131
- is: "prefix",
129
+ filterType: Joi.string().valid('none', 'prefix', 'tags', 'and').required(),
130
+ prefix: Joi.when('filterType', {
131
+ is: 'prefix',
132
132
  then: Joi.string().required().min(1).messages({
133
- "string.empty": "Prefix is required when using prefix filter",
134
- "string.min": "Prefix is required when using prefix filter"
133
+ 'string.empty': 'Prefix is required when using prefix filter',
134
+ 'string.min': 'Prefix is required when using prefix filter'
135
135
  }),
136
- otherwise: Joi.when("filterType", {
137
- is: "and",
138
- then: Joi.string().allow("").optional(),
136
+ otherwise: Joi.when('filterType', {
137
+ is: 'and',
138
+ then: Joi.string().allow('').optional(),
139
139
  otherwise: Joi.any()
140
140
  })
141
141
  }),
142
- tags: Joi.when("filterType", {
143
- is: Joi.valid("tags", "and"),
142
+ tags: Joi.when('filterType', {
143
+ is: Joi.valid('tags', 'and'),
144
144
  then: Joi.array().items(Joi.object({
145
145
  key: Joi.string().required().max(128).messages({
146
- "string.empty": "Tag key is required",
147
- "string.max": "Tag key must not exceed 128 characters"
146
+ 'string.empty': 'Tag key is required',
147
+ 'string.max': 'Tag key must not exceed 128 characters'
148
148
  }),
149
149
  value: Joi.string().required().max(256).messages({
150
- "string.empty": "Tag value is required",
151
- "string.max": "Tag value must not exceed 256 characters"
150
+ 'string.empty': 'Tag value is required',
151
+ 'string.max': 'Tag value must not exceed 256 characters'
152
152
  })
153
153
  })).min(1).messages({
154
- "array.min": "At least one tag is required when using tag filter"
154
+ 'array.min': 'At least one tag is required when using tag filter'
155
155
  }),
156
156
  otherwise: Joi.array().optional()
157
157
  })
@@ -1,4 +1,4 @@
1
- import { IconColor, IconName } from "@scality/core-ui/dist/components/icon/Icon.component";
1
+ import { IconColor, IconName } from '@scality/core-ui/dist/components/icon/Icon.component';
2
2
  export declare const SearchContainer: import("styled-components").StyledComponent<"form", any, {
3
3
  isHidden?: boolean;
4
4
  }, never>;
@@ -5,7 +5,7 @@ const SearchContainer = styled_components.form`
5
5
  display: flex;
6
6
  max-width: 600px;
7
7
  margin-right: ${spacing.r20};
8
- visibility: ${(props)=>props.isHidden ? "hidden" : "visible"};
8
+ visibility: ${(props)=>props.isHidden ? 'hidden' : 'visible'};
9
9
  gap: ${spacing.r8};
10
10
  `;
11
11
  const SearchInputContainer = styled_components.div`
@@ -44,16 +44,16 @@ const HintsTitle = styled_components.div`
44
44
  `;
45
45
  const searchIcon = ({ isMetadata, isError })=>{
46
46
  if (isError) return {
47
- name: "Close",
48
- color: "statusCritical"
47
+ name: 'Close',
48
+ color: 'statusCritical'
49
49
  };
50
50
  if (isMetadata) return {
51
- name: "Check",
52
- color: "statusHealthy"
51
+ name: 'Check',
52
+ color: 'statusHealthy'
53
53
  };
54
54
  return {
55
- name: "Search",
56
- color: "textSecondary"
55
+ name: 'Search',
56
+ color: 'textSecondary'
57
57
  };
58
58
  };
59
59
  export { HintItem, HintsContainer, HintsTitle, SearchContainer, SearchInputContainer, searchIcon };
@@ -47,16 +47,16 @@ const Row = ({ children, ...props })=>/*#__PURE__*/ jsx(Box, {
47
47
  });
48
48
  const RawKey = styled_components.div`
49
49
  color: ${(props)=>props.principal ? props.theme.textPrimary : props.theme?.textSecondary};
50
- font-weight: ${(props)=>props.principal ? "bold" : "normal"};
50
+ font-weight: ${(props)=>props.principal ? 'bold' : 'normal'};
51
51
  ${(props)=>props.required ? `
52
52
  &:after {
53
53
  content: '*';
54
54
  }
55
- ` : ""}
55
+ ` : ''}
56
56
  `;
57
57
  const Key = styled_components(RawKey)`
58
58
  && {
59
- flex: ${(props)=>props.size || "0.35"};
59
+ flex: ${(props)=>props.size || '0.35'};
60
60
  min-width: 0;
61
61
  }
62
62
  `;
@@ -76,12 +76,12 @@ const TableContainer = ({ children, ...props })=>/*#__PURE__*/ jsx(Box, {
76
76
  });
77
77
  const GroupValues = styled_components.div`
78
78
  display: flex;
79
- flex: ${(props)=>props.size || "0.65"};
79
+ flex: ${(props)=>props.size || '0.65'};
80
80
  justify-content: space-between;
81
81
  align-items: center;
82
82
  min-width: 0;
83
83
  `;
84
84
  const ExtraCell = styled_components.div`
85
- margin-left: ${(props)=>props.marginLeft || "1.429rem"};
85
+ margin-left: ${(props)=>props.marginLeft || '1.429rem'};
86
86
  `;
87
87
  export { Body, ExtraCell, Group, GroupContent, GroupName, GroupValues, Key, Row, Table, TableContainer, Value };
@@ -1,15 +1,14 @@
1
- import type { S3ClientConfiguration } from "./types";
2
- import type { S3BrowserConfig, S3Credentials } from "../types";
3
- import { CoreUIThemeName } from "@scality/core-ui/dist/style/theme";
4
- interface RuntimeConfig {
1
+ import Joi from 'joi';
2
+ import type { S3BrowserConfig, S3Credentials } from '../types';
3
+ import type { S3ClientConfiguration } from './types';
4
+ export type S3RuntimeConfig = {
5
5
  s3: {
6
6
  endpoint?: string;
7
7
  region: string;
8
8
  forcePathStyle?: boolean;
9
9
  };
10
- theme?: CoreUIThemeName;
11
- basePath?: string;
12
- }
10
+ };
11
+ export declare const s3RuntimeConfigSchema: Joi.ObjectSchema<any>;
13
12
  /**
14
13
  * Configuration factory that uses build-time constants
15
14
  * No runtime environment detection or hardcoded values
@@ -18,8 +17,23 @@ export declare class S3ConfigurationFactory {
18
17
  /**
19
18
  * Load runtime configuration from config.json
20
19
  * Should be called at app startup
20
+ *
21
+ * @template T - Extended runtime config type that must include S3RuntimeConfig
22
+ * @param configUrl - URL to fetch the config.json from
23
+ * @returns Promise resolving to the loaded config or null if loading failed
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * type MyConfig = S3RuntimeConfig & {
28
+ * theme?: string;
29
+ * basePath?: string;
30
+ * more: "type";
31
+ * };
32
+ *
33
+ * const config = await loadRuntimeConfig<MyConfig>("/config.json");
34
+ * ```
21
35
  */
22
- static loadRuntimeConfig(configUrl: string): Promise<RuntimeConfig | null>;
36
+ static loadRuntimeConfig<T extends S3RuntimeConfig = S3RuntimeConfig>(configUrl: string): Promise<T>;
23
37
  private static getBuildTimeConfig;
24
38
  /**
25
39
  * Create S3 client configuration based on build-time settings
@@ -59,5 +73,4 @@ export declare const getBuildInfo: () => {
59
73
  s3Endpoint: string;
60
74
  proxyEndpoint: string | undefined;
61
75
  };
62
- export declare const loadRuntimeConfig: (configUrl: string) => Promise<RuntimeConfig | null>;
63
- export {};
76
+ export declare const loadRuntimeConfig: <T extends S3RuntimeConfig = S3RuntimeConfig>(configUrl: string) => Promise<T>;
@@ -1,3 +1,11 @@
1
+ import joi from "joi";
2
+ const s3RuntimeConfigSchema = joi.object({
3
+ s3: joi.object({
4
+ endpoint: joi.string().optional(),
5
+ region: joi.string().required(),
6
+ forcePathStyle: joi.boolean().optional()
7
+ })
8
+ });
1
9
  let runtimeConfig = null;
2
10
  class S3ConfigurationFactory {
3
11
  static async loadRuntimeConfig(configUrl) {
@@ -6,14 +14,21 @@ class S3ConfigurationFactory {
6
14
  if (response.ok) {
7
15
  const data = await response.json();
8
16
  runtimeConfig = data;
9
- if (runtimeConfig?.s3?.endpoint === "origin") runtimeConfig.s3.endpoint = window.location.origin;
10
- console.log("Loaded runtime configuration:", runtimeConfig);
17
+ const { error } = s3RuntimeConfigSchema.validate(data, {
18
+ allowUnknown: true,
19
+ stripUnknown: false,
20
+ abortEarly: false
21
+ });
22
+ if (error) {
23
+ const errorMessages = error.details.map((detail)=>detail.message).join(`\n`);
24
+ throw new Error(`Invalid runtime configuration, please check your config.json: \n${errorMessages}`);
25
+ }
26
+ if (runtimeConfig?.s3?.endpoint === 'origin') runtimeConfig.s3.endpoint = window.location.origin;
11
27
  return data;
12
28
  }
13
- return null;
29
+ throw new Error('Failed to load runtime configuration');
14
30
  } catch (error) {
15
- console.warn("Could not load runtime config, using build-time config:", error);
16
- return null;
31
+ throw error;
17
32
  }
18
33
  }
19
34
  static getBuildTimeConfig() {
@@ -59,7 +74,7 @@ class S3ConfigurationFactory {
59
74
  static getBuildInfo() {
60
75
  const buildConfig = this.getBuildTimeConfig();
61
76
  return {
62
- environment: buildConfig.isDevelopment ? "development" : "production",
77
+ environment: buildConfig.isDevelopment ? 'development' : 'production',
63
78
  useProxy: buildConfig.dev.useProxy,
64
79
  s3Endpoint: buildConfig.s3.endpoint,
65
80
  proxyEndpoint: buildConfig.dev.proxyEndpoint
@@ -71,4 +86,4 @@ const shouldUseProxy = ()=>S3ConfigurationFactory.shouldUseProxyMiddleware();
71
86
  const getProxyConfig = ()=>S3ConfigurationFactory.createProxyConfiguration();
72
87
  const getBuildInfo = ()=>S3ConfigurationFactory.getBuildInfo();
73
88
  const loadRuntimeConfig = (configUrl)=>S3ConfigurationFactory.loadRuntimeConfig(configUrl);
74
- export { S3ConfigurationFactory, createS3Config, getBuildInfo, getProxyConfig, loadRuntimeConfig, shouldUseProxy };
89
+ export { S3ConfigurationFactory, createS3Config, getBuildInfo, getProxyConfig, loadRuntimeConfig, s3RuntimeConfigSchema, shouldUseProxy };
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Build-time configuration types injected by RSBuild
3
3
  */
4
- import type { Bucket } from "@aws-sdk/client-s3";
5
- import type { TableItem } from "../components/objects/ObjectList";
4
+ import type { Bucket } from '@aws-sdk/client-s3';
5
+ import type { TableItem } from '../components/objects/ObjectList';
6
6
  export interface S3Configuration {
7
7
  endpoint: string;
8
8
  region: string;
@@ -56,6 +56,7 @@ export interface ColumnConfig<T = unknown> {
56
56
  render: React.ComponentType<{
57
57
  data: T;
58
58
  }>;
59
+ cellStyle?: React.CSSProperties;
59
60
  }
60
61
  /**
61
62
  * Action configuration for list-level actions (buttons at top of list)
@@ -90,6 +91,14 @@ export interface FieldConfig {
90
91
  entityName: string;
91
92
  }>;
92
93
  }
94
+ /**
95
+ * Section configuration for overview pages
96
+ */
97
+ export interface SectionConfig {
98
+ id: string;
99
+ title: string;
100
+ render: () => React.ReactNode;
101
+ }
93
102
  /**
94
103
  * Storage class selector props
95
104
  */
@@ -101,6 +110,12 @@ export interface StorageClassSelectorProps {
101
110
  * Main DataBrowserUI component props
102
111
  */
103
112
  export interface DataBrowserUIProps {
113
+ basePath?: string;
114
+ /**
115
+ * Custom header component to render above the main content.
116
+ * Typically used for breadcrumbs or navigation.
117
+ */
118
+ header?: React.ReactNode;
104
119
  storageClassSelector?: React.ComponentType<StorageClassSelectorProps>;
105
120
  extraBucketListColumns?: ColumnConfig<Bucket>[];
106
121
  extraBucketListActions?: ActionConfig[];
@@ -108,6 +123,7 @@ export interface DataBrowserUIProps {
108
123
  extraBucketOverviewGeneral?: FieldConfig[];
109
124
  extraBucketOverviewDataProtection?: FieldConfig[];
110
125
  extraBucketOverviewPermissions?: FieldConfig[];
126
+ extraBucketOverviewSections?: SectionConfig[];
111
127
  /**
112
128
  * Extra columns for object list.
113
129
  *
@@ -160,4 +176,5 @@ export interface DataBrowserUIProps {
160
176
  */
161
177
  extraObjectSummaryDataProtection?: FieldConfig[];
162
178
  }
163
- export type S3EventType = "s3:ObjectCreated:*" | "s3:ObjectCreated:Put" | "s3:ObjectCreated:Post" | "s3:ObjectCreated:Copy" | "s3:ObjectCreated:CompleteMultipartUpload" | "s3:ObjectRemoved:*" | "s3:ObjectRemoved:Delete" | "s3:ObjectRemoved:DeleteMarkerCreated" | "s3:ObjectRestore:*" | "s3:ObjectRestore:Post" | "s3:ObjectRestore:Completed" | "s3:ObjectRestore:Delete" | "s3:LifecycleExpiration:*" | "s3:LifecycleExpiration:Delete" | "s3:LifecycleExpiration:DeleteMarkerCreated" | "s3:LifecycleTransition" | "s3:Replication:*" | "s3:Replication:OperationFailedReplication" | "s3:Replication:OperationMissedThreshold" | "s3:Replication:OperationReplicatedAfterThreshold" | "s3:Replication:OperationNotTracked" | "s3:ObjectTagging:*" | "s3:ObjectTagging:Put" | "s3:ObjectTagging:Delete" | "s3:ReducedRedundancyLostObject" | "s3:IntelligentTiering" | "s3:ObjectAcl:Put" | "s3:TestEvent";
179
+ export type S3EventType = 's3:ObjectCreated:*' | 's3:ObjectCreated:Put' | 's3:ObjectCreated:Post' | 's3:ObjectCreated:Copy' | 's3:ObjectCreated:CompleteMultipartUpload' | 's3:ObjectRemoved:*' | 's3:ObjectRemoved:Delete' | 's3:ObjectRemoved:DeleteMarkerCreated' | 's3:ObjectRestore:*' | 's3:ObjectRestore:Post' | 's3:ObjectRestore:Completed' | 's3:ObjectRestore:Delete' | 's3:LifecycleExpiration:*' | 's3:LifecycleExpiration:Delete' | 's3:LifecycleExpiration:DeleteMarkerCreated' | 's3:LifecycleTransition' | 's3:Replication:*' | 's3:Replication:OperationFailedReplication' | 's3:Replication:OperationMissedThreshold' | 's3:Replication:OperationReplicatedAfterThreshold' | 's3:Replication:OperationNotTracked' | 's3:ObjectTagging:*' | 's3:ObjectTagging:Put' | 's3:ObjectTagging:Delete' | 's3:ReducedRedundancyLostObject' | 's3:IntelligentTiering' | 's3:ObjectAcl:Put' | 's3:TestEvent';
180
+ export type S3EventCategory = 'Object Creation' | 'Object Deletion' | 'Object Restoration' | 'Lifecycle' | 'Replication' | 'Object Tagging' | 'Storage & Access' | 'Testing';
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * @internal
6
6
  */
7
- import React from "react";
8
- import type { DataBrowserUIProps } from "../config/types";
7
+ import React from 'react';
8
+ import type { DataBrowserUIProps } from '../config/types';
9
9
  interface DataBrowserUICustomizationProviderProps {
10
10
  config: DataBrowserUIProps;
11
11
  children: React.ReactNode;