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

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 (40) hide show
  1. package/dist/components/DataBrowserUI.d.ts +20 -0
  2. package/dist/components/DataBrowserUI.js +64 -0
  3. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketDetails.test.js +421 -0
  5. package/dist/components/__tests__/BucketList.test.js +389 -164
  6. package/dist/components/__tests__/BucketOverview.test.js +19 -63
  7. package/dist/components/__tests__/ObjectList.test.js +719 -219
  8. package/dist/components/buckets/BucketDetails.d.ts +40 -0
  9. package/dist/components/buckets/BucketDetails.js +194 -86
  10. package/dist/components/buckets/BucketList.d.ts +5 -6
  11. package/dist/components/buckets/BucketList.js +152 -97
  12. package/dist/components/buckets/BucketOverview.d.ts +6 -0
  13. package/dist/components/buckets/BucketOverview.js +363 -179
  14. package/dist/components/buckets/BucketPage.js +1 -5
  15. package/dist/components/buckets/BucketVersioning.js +3 -0
  16. package/dist/components/buckets/EmptyBucketButton.js +1 -1
  17. package/dist/components/index.d.ts +2 -1
  18. package/dist/components/index.js +2 -1
  19. package/dist/components/layouts/ArrowNavigation.js +20 -8
  20. package/dist/components/objects/CreateFolderButton.js +1 -1
  21. package/dist/components/objects/ObjectDetails/ObjectSummary.js +287 -157
  22. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  23. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  24. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  25. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +813 -0
  26. package/dist/components/objects/ObjectDetails/index.d.ts +16 -0
  27. package/dist/components/objects/ObjectDetails/index.js +132 -46
  28. package/dist/components/objects/ObjectList.d.ts +7 -5
  29. package/dist/components/objects/ObjectList.js +566 -286
  30. package/dist/components/objects/UploadButton.js +1 -1
  31. package/dist/config/types.d.ts +117 -0
  32. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  33. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  34. package/dist/test/testUtils.d.ts +64 -0
  35. package/dist/test/testUtils.js +100 -1
  36. package/dist/types/index.d.ts +5 -3
  37. package/dist/utils/constants.d.ts +7 -0
  38. package/dist/utils/constants.js +8 -1
  39. package/dist/utils/useFeatures.js +1 -1
  40. package/package.json +2 -2
@@ -4,6 +4,22 @@ export interface ObjectCommonProps {
4
4
  objectKey: string;
5
5
  versionId?: string;
6
6
  }
7
+ interface ObjectDetailsContextValue {
8
+ bucketName: string;
9
+ objectKey: string;
10
+ versionId?: string;
11
+ }
12
+ /**
13
+ * Context for ObjectDetails component.
14
+ *
15
+ * **Important**: Always use `useObjectDetailsContext()` hook instead of accessing this context directly.
16
+ * The hook provides proper error handling if the context is not available.
17
+ *
18
+ * This context is exported for testing purposes only.
19
+ */
20
+ export declare const ObjectDetailsContext: import("react").Context<ObjectDetailsContextValue | null>;
21
+ export declare function useObjectDetailsContext(): ObjectDetailsContextValue;
7
22
  export declare const ObjectDetails: ({ item }: {
8
23
  item: TableItem | null;
9
24
  }) => import("react/jsx-runtime").JSX.Element;
25
+ export {};
@@ -1,26 +1,52 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { createContext, memo, useContext, useMemo } from "react";
2
3
  import { useParams } from "react-router-dom";
3
4
  import { Text, spacing } from "@scality/core-ui";
4
5
  import { Box, Tabs } from "@scality/core-ui/dist/next";
6
+ import { useDataBrowserUICustomization } from "../../../contexts/DataBrowserUICustomizationContext.js";
5
7
  import { ObjectSummary } from "./ObjectSummary.js";
6
8
  import { ObjectMetadata } from "./ObjectMetadata.js";
7
9
  import { ObjectTags } from "./ObjectTags.js";
10
+ const ObjectDetailsContext = /*#__PURE__*/ createContext(null);
11
+ function useObjectDetailsContext() {
12
+ const context = useContext(ObjectDetailsContext);
13
+ if (!context) throw new Error("ObjectDetails components must be used within ObjectDetails");
14
+ return context;
15
+ }
16
+ const SummaryTab = /*#__PURE__*/ memo(()=>{
17
+ const { bucketName, objectKey, versionId } = useObjectDetailsContext();
18
+ return /*#__PURE__*/ jsx(ObjectSummary, {
19
+ bucketName: bucketName,
20
+ objectKey: objectKey,
21
+ versionId: versionId
22
+ });
23
+ });
24
+ SummaryTab.displayName = "ObjectDetails.SummaryTab";
25
+ const MetadataTab = /*#__PURE__*/ memo(()=>{
26
+ const { bucketName, objectKey, versionId } = useObjectDetailsContext();
27
+ return /*#__PURE__*/ jsx(ObjectMetadata, {
28
+ bucketName: bucketName,
29
+ objectKey: objectKey,
30
+ versionId: versionId
31
+ });
32
+ });
33
+ MetadataTab.displayName = "ObjectDetails.MetadataTab";
34
+ const TagsTab = /*#__PURE__*/ memo(()=>{
35
+ const { bucketName, objectKey, versionId } = useObjectDetailsContext();
36
+ return /*#__PURE__*/ jsx(ObjectTags, {
37
+ bucketName: bucketName,
38
+ objectKey: objectKey,
39
+ versionId: versionId
40
+ });
41
+ });
42
+ TagsTab.displayName = "ObjectDetails.TagsTab";
43
+ const CustomTab = ({ config })=>/*#__PURE__*/ jsx(Fragment, {
44
+ children: config.render()
45
+ });
46
+ CustomTab.displayName = "ObjectDetails.CustomTab";
8
47
  const ObjectDetails = ({ item })=>{
9
48
  const { bucketName } = useParams();
10
- const mainTabs = [
11
- {
12
- label: "Summary",
13
- query: ""
14
- },
15
- {
16
- label: "Metadata",
17
- query: "metadata"
18
- },
19
- {
20
- label: "Tags",
21
- query: "tags"
22
- }
23
- ];
49
+ const { extraObjectTabs } = useDataBrowserUICustomization();
24
50
  const getPlaceholderMessage = ()=>{
25
51
  if (!bucketName || !item || !item.Key) return /*#__PURE__*/ jsx(Text, {
26
52
  children: "Select an object to view details"
@@ -35,41 +61,101 @@ const ObjectDetails = ({ item })=>{
35
61
  children: "Select an object to view details"
36
62
  });
37
63
  };
38
- if (!bucketName || !item || !item.Key || "deleteMarker" === item.type || "folder" === item.type) {
39
- const placeholderMessage = getPlaceholderMessage();
40
- return /*#__PURE__*/ jsx(Tabs, {
41
- children: mainTabs.map((tab)=>/*#__PURE__*/ jsx(Tabs.Tab, {
42
- label: tab.label,
43
- path: "",
44
- query: {
45
- tab: tab.query
46
- },
47
- children: /*#__PURE__*/ jsx(Box, {
48
- padding: spacing.r16,
49
- display: "flex",
50
- justifyContent: "center",
51
- children: placeholderMessage
52
- })
53
- }, tab.query || "summary"))
54
- });
55
- }
56
- const versionId = "version" === item.type ? item.VersionId : void 0;
57
- return /*#__PURE__*/ jsx(Tabs, {
58
- children: mainTabs.map((tab)=>{
59
- const Component = "Summary" === tab.label ? ObjectSummary : "Metadata" === tab.label ? ObjectMetadata : ObjectTags;
60
- return /*#__PURE__*/ jsx(Tabs.Tab, {
61
- label: tab.label,
64
+ const defaultTabsMap = useMemo(()=>({
65
+ summary: {
66
+ id: "summary",
67
+ label: "Summary",
62
68
  path: "",
69
+ withoutPadding: false,
63
70
  query: {
64
- tab: tab.query
71
+ tab: ""
65
72
  },
66
- children: /*#__PURE__*/ jsx(Component, {
67
- bucketName: bucketName,
68
- objectKey: item.Key,
69
- versionId: versionId
73
+ type: "default",
74
+ Component: SummaryTab
75
+ },
76
+ metadata: {
77
+ id: "metadata",
78
+ label: "Metadata",
79
+ path: "",
80
+ withoutPadding: false,
81
+ query: {
82
+ tab: "metadata"
83
+ },
84
+ type: "default",
85
+ Component: MetadataTab
86
+ },
87
+ tags: {
88
+ id: "tags",
89
+ label: "Tags",
90
+ path: "",
91
+ withoutPadding: false,
92
+ query: {
93
+ tab: "tags"
94
+ },
95
+ type: "default",
96
+ Component: TagsTab
97
+ }
98
+ }), []);
99
+ const allTabs = useMemo(()=>{
100
+ const customTabConfigs = extraObjectTabs ? extraObjectTabs.map((tabConfig)=>({
101
+ id: tabConfig.id,
102
+ label: tabConfig.title,
103
+ path: tabConfig.path || "",
104
+ query: {
105
+ tab: tabConfig.id
106
+ },
107
+ withoutPadding: tabConfig.withoutPadding || false,
108
+ type: "custom",
109
+ config: tabConfig
110
+ })) : [];
111
+ const overrideIds = new Set(customTabConfigs.filter((t)=>t.id in defaultTabsMap).map((t)=>t.id));
112
+ const defaults = Object.values(defaultTabsMap).filter((tab)=>!overrideIds.has(tab.id));
113
+ return [
114
+ ...defaults,
115
+ ...customTabConfigs
116
+ ];
117
+ }, [
118
+ extraObjectTabs,
119
+ defaultTabsMap
120
+ ]);
121
+ const versionId = item?.type === "version" ? item.VersionId : void 0;
122
+ const objectKey = item?.Key || "";
123
+ const contextValue = useMemo(()=>({
124
+ bucketName: bucketName || "",
125
+ objectKey,
126
+ versionId
127
+ }), [
128
+ bucketName,
129
+ objectKey,
130
+ versionId
131
+ ]);
132
+ const isPlaceholder = !bucketName || !item || !item.Key || "deleteMarker" === item.type || "folder" === item.type;
133
+ const placeholderMessage = isPlaceholder ? getPlaceholderMessage() : null;
134
+ const tabsContent = useMemo(()=>allTabs.map((tab)=>/*#__PURE__*/ jsx(Tabs.Tab, {
135
+ label: tab.label,
136
+ path: tab.path,
137
+ query: tab.query,
138
+ withoutPadding: tab.withoutPadding,
139
+ children: isPlaceholder ? /*#__PURE__*/ jsx(Box, {
140
+ padding: spacing.r16,
141
+ display: "flex",
142
+ justifyContent: "center",
143
+ children: placeholderMessage
144
+ }) : "default" === tab.type ? /*#__PURE__*/ jsx(tab.Component, {}) : /*#__PURE__*/ jsx(CustomTab, {
145
+ config: tab.config
70
146
  })
71
- }, tab.query || "summary");
147
+ }, tab.id)), [
148
+ allTabs,
149
+ isPlaceholder,
150
+ placeholderMessage
151
+ ]);
152
+ return isPlaceholder ? /*#__PURE__*/ jsx(Tabs, {
153
+ children: tabsContent
154
+ }) : /*#__PURE__*/ jsx(ObjectDetailsContext.Provider, {
155
+ value: contextValue,
156
+ children: /*#__PURE__*/ jsx(Tabs, {
157
+ children: tabsContent
72
158
  })
73
159
  });
74
160
  };
75
- export { ObjectDetails };
161
+ export { ObjectDetails, ObjectDetailsContext, useObjectDetailsContext };
@@ -1,4 +1,4 @@
1
- import type { _Object, DeleteMarkerEntry, ObjectVersion } from "@aws-sdk/client-s3";
1
+ import type { _Object as S3Object, DeleteMarkerEntry, ObjectVersion } from "@aws-sdk/client-s3";
2
2
  type FolderItem = {
3
3
  Key: string;
4
4
  displayName: string;
@@ -9,16 +9,18 @@ type FolderItem = {
9
9
  VersionId?: undefined;
10
10
  IsLatest?: undefined;
11
11
  };
12
- type ObjectItem = _Object & {
12
+ type ObjectItem = S3Object & {
13
13
  displayName: string;
14
14
  type: "object";
15
15
  IsLatest?: boolean;
16
16
  VersionId?: string;
17
+ isLegalHoldEnabled?: boolean;
17
18
  };
18
19
  type VersionItem = ObjectVersion & {
19
20
  displayName: string;
20
21
  type: "version";
21
22
  IsLatest?: boolean;
23
+ isLegalHoldEnabled?: boolean;
22
24
  };
23
25
  type DeleteMarkerItem = DeleteMarkerEntry & {
24
26
  displayName: string;
@@ -26,10 +28,10 @@ type DeleteMarkerItem = DeleteMarkerEntry & {
26
28
  isDeleteMarker: true;
27
29
  IsLatest?: boolean;
28
30
  Size?: number;
31
+ isLegalHoldEnabled?: boolean;
29
32
  };
30
- export type TableItem = (FolderItem | ObjectItem | VersionItem | DeleteMarkerItem) & {
31
- [key: string]: unknown;
32
- };
33
+ export type TableItem = FolderItem | ObjectItem | VersionItem | DeleteMarkerItem;
34
+ export declare const isObjectLike: (item: TableItem) => item is ObjectItem | VersionItem | DeleteMarkerItem;
33
35
  interface ObjectListProps {
34
36
  bucketName: string;
35
37
  prefix: string;