@scality/data-browser-library 1.0.0-preview.2

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 (176) hide show
  1. package/dist/components/Editor.d.ts +12 -0
  2. package/dist/components/Editor.js +28 -0
  3. package/dist/components/__tests__/BucketList.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketList.test.js +225 -0
  5. package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
  6. package/dist/components/__tests__/BucketOverview.test.js +479 -0
  7. package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
  8. package/dist/components/__tests__/BucketPolicyPage.test.js +213 -0
  9. package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
  10. package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
  11. package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
  12. package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
  13. package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
  14. package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
  15. package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
  16. package/dist/components/__tests__/MetadataSearch.test.js +201 -0
  17. package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
  18. package/dist/components/__tests__/ObjectList.test.js +283 -0
  19. package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
  20. package/dist/components/__tests__/UploadButton.test.js +144 -0
  21. package/dist/components/buckets/BucketDetails.d.ts +1 -0
  22. package/dist/components/buckets/BucketDetails.js +51 -0
  23. package/dist/components/buckets/BucketList.d.ts +12 -0
  24. package/dist/components/buckets/BucketList.js +136 -0
  25. package/dist/components/buckets/BucketLocation.d.ts +3 -0
  26. package/dist/components/buckets/BucketLocation.js +16 -0
  27. package/dist/components/buckets/BucketOverview.d.ts +14 -0
  28. package/dist/components/buckets/BucketOverview.js +209 -0
  29. package/dist/components/buckets/BucketPage.d.ts +2 -0
  30. package/dist/components/buckets/BucketPage.js +47 -0
  31. package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
  32. package/dist/components/buckets/BucketPolicyButton.js +18 -0
  33. package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
  34. package/dist/components/buckets/BucketPolicyPage.js +205 -0
  35. package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
  36. package/dist/components/buckets/DeleteBucketButton.js +78 -0
  37. package/dist/components/index.d.ts +12 -0
  38. package/dist/components/index.js +13 -0
  39. package/dist/components/layouts/BrowserPageLayout.d.ts +9 -0
  40. package/dist/components/layouts/BrowserPageLayout.js +46 -0
  41. package/dist/components/objects/CreateFolderButton.d.ts +29 -0
  42. package/dist/components/objects/CreateFolderButton.js +118 -0
  43. package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
  44. package/dist/components/objects/DeleteObjectButton.js +191 -0
  45. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
  46. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +323 -0
  47. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
  48. package/dist/components/objects/ObjectDetails/ObjectSummary.js +193 -0
  49. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
  50. package/dist/components/objects/ObjectDetails/ObjectTags.js +300 -0
  51. package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
  52. package/dist/components/objects/ObjectDetails/index.js +49 -0
  53. package/dist/components/objects/ObjectList.d.ts +40 -0
  54. package/dist/components/objects/ObjectList.js +407 -0
  55. package/dist/components/objects/ObjectPage.d.ts +1 -0
  56. package/dist/components/objects/ObjectPage.js +43 -0
  57. package/dist/components/objects/UploadButton.d.ts +34 -0
  58. package/dist/components/objects/UploadButton.js +229 -0
  59. package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
  60. package/dist/components/providers/DataBrowserProvider.js +42 -0
  61. package/dist/components/search/MetadataSearch.d.ts +5 -0
  62. package/dist/components/search/MetadataSearch.js +162 -0
  63. package/dist/components/search/SearchHints.d.ts +8 -0
  64. package/dist/components/search/SearchHints.js +21 -0
  65. package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
  66. package/dist/components/ui/DeleteObjectModalContent.js +71 -0
  67. package/dist/components/ui/Search.elements.d.ts +17 -0
  68. package/dist/components/ui/Search.elements.js +59 -0
  69. package/dist/components/ui/Table.elements.d.ts +36 -0
  70. package/dist/components/ui/Table.elements.js +87 -0
  71. package/dist/config/factory.d.ts +52 -0
  72. package/dist/config/factory.js +70 -0
  73. package/dist/config/types.d.ts +46 -0
  74. package/dist/config/types.js +0 -0
  75. package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
  76. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
  77. package/dist/hooks/bucketConfiguration.d.ts +147 -0
  78. package/dist/hooks/bucketConfiguration.js +59 -0
  79. package/dist/hooks/bucketOperations.d.ts +36 -0
  80. package/dist/hooks/bucketOperations.js +12 -0
  81. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
  82. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
  83. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
  84. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
  85. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
  86. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
  87. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
  88. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
  89. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
  90. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +136 -0
  91. package/dist/hooks/factories/index.d.ts +18 -0
  92. package/dist/hooks/factories/index.js +5 -0
  93. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
  94. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
  95. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
  96. package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
  97. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
  98. package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
  99. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
  100. package/dist/hooks/factories/useCreateS3QueryHook.js +30 -0
  101. package/dist/hooks/index.d.ts +8 -0
  102. package/dist/hooks/index.js +8 -0
  103. package/dist/hooks/loginOperations.d.ts +21 -0
  104. package/dist/hooks/loginOperations.js +9 -0
  105. package/dist/hooks/objectOperations.d.ts +190 -0
  106. package/dist/hooks/objectOperations.js +66 -0
  107. package/dist/hooks/presignedOperations.d.ts +73 -0
  108. package/dist/hooks/presignedOperations.js +72 -0
  109. package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
  110. package/dist/hooks/useIsBucketEmpty.js +36 -0
  111. package/dist/hooks/useLoginMutation.d.ts +21 -0
  112. package/dist/hooks/useLoginMutation.js +9 -0
  113. package/dist/hooks/useS3Client.d.ts +1 -0
  114. package/dist/hooks/useS3Client.js +13 -0
  115. package/dist/index.d.ts +6 -0
  116. package/dist/index.js +6 -0
  117. package/dist/schemas/bucketPolicySchema.json +321 -0
  118. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
  119. package/dist/test/msw/handlers/deleteBucket.js +14 -0
  120. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
  121. package/dist/test/msw/handlers/getBucketAcl.js +96 -0
  122. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
  123. package/dist/test/msw/handlers/getBucketLocation.js +23 -0
  124. package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
  125. package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
  126. package/dist/test/msw/handlers/headObject.d.ts +1 -0
  127. package/dist/test/msw/handlers/headObject.js +17 -0
  128. package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
  129. package/dist/test/msw/handlers/listBuckets.js +24 -0
  130. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
  131. package/dist/test/msw/handlers/listObjectVersions.js +83 -0
  132. package/dist/test/msw/handlers/listObjects.d.ts +1 -0
  133. package/dist/test/msw/handlers/listObjects.js +66 -0
  134. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
  135. package/dist/test/msw/handlers/objectLegalHold.js +24 -0
  136. package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
  137. package/dist/test/msw/handlers/objectRetention.js +27 -0
  138. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
  139. package/dist/test/msw/handlers/putBucketAcl.js +18 -0
  140. package/dist/test/msw/handlers/putObject.d.ts +1 -0
  141. package/dist/test/msw/handlers/putObject.js +16 -0
  142. package/dist/test/msw/handlers.d.ts +4 -0
  143. package/dist/test/msw/handlers.js +109 -0
  144. package/dist/test/msw/index.d.ts +2 -0
  145. package/dist/test/msw/index.js +3 -0
  146. package/dist/test/msw/server.d.ts +4 -0
  147. package/dist/test/msw/server.js +20 -0
  148. package/dist/test/msw/utils.d.ts +2 -0
  149. package/dist/test/msw/utils.js +13 -0
  150. package/dist/test/setup.d.ts +1 -0
  151. package/dist/test/setup.js +82 -0
  152. package/dist/test/testUtils.d.ts +82 -0
  153. package/dist/test/testUtils.js +236 -0
  154. package/dist/test/utils/errorHandling.test.d.ts +1 -0
  155. package/dist/test/utils/errorHandling.test.js +385 -0
  156. package/dist/types/index.d.ts +48 -0
  157. package/dist/types/index.js +0 -0
  158. package/dist/utils/deletion/index.d.ts +2 -0
  159. package/dist/utils/deletion/index.js +2 -0
  160. package/dist/utils/deletion/messages.d.ts +5 -0
  161. package/dist/utils/deletion/messages.js +29 -0
  162. package/dist/utils/deletion/types.d.ts +11 -0
  163. package/dist/utils/deletion/types.js +0 -0
  164. package/dist/utils/errorHandling.d.ts +54 -0
  165. package/dist/utils/errorHandling.js +79 -0
  166. package/dist/utils/hooks.d.ts +2 -0
  167. package/dist/utils/hooks.js +26 -0
  168. package/dist/utils/index.d.ts +2 -0
  169. package/dist/utils/index.js +2 -0
  170. package/dist/utils/proxyMiddleware.d.ts +18 -0
  171. package/dist/utils/proxyMiddleware.js +56 -0
  172. package/dist/utils/s3Client.d.ts +5 -0
  173. package/dist/utils/s3Client.js +35 -0
  174. package/dist/utils/useFeatures.d.ts +1 -0
  175. package/dist/utils/useFeatures.js +7 -0
  176. package/package.json +79 -0
@@ -0,0 +1,229 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useState } from "react";
3
+ import { useDropzone } from "react-dropzone";
4
+ import { Icon, Modal, PrettyBytes, Stack, Wrap, spacing } from "@scality/core-ui";
5
+ import { Button } from "@scality/core-ui/dist/components/buttonv2/Buttonv2.component";
6
+ import styled_components from "styled-components";
7
+ import { useUploadObjects } from "../../hooks/index.js";
8
+ const DropZone = styled_components.div`
9
+ flex: 1;
10
+ display: flex;
11
+ flex-direction: column;
12
+ height: 300px;
13
+ width: 500px;
14
+ padding: ${spacing.r20};
15
+ border-width: ${spacing.r2};
16
+ border-radius: ${spacing.r2};
17
+ border-color: ${(props)=>props.theme.border};
18
+ border-style: dashed;
19
+ `;
20
+ const Files = styled_components.div`
21
+ height: 250px;
22
+ overflow-y: scroll;
23
+ margin: ${spacing.r8} 0px;
24
+ `;
25
+ const EmptyFile = styled_components.div`
26
+ text-align: center;
27
+ margin-top: 60px;
28
+ & > * {
29
+ margin-bottom: ${spacing.r16};
30
+ }
31
+ `;
32
+ const FileRow = styled_components.div`
33
+ display: flex;
34
+ justify-content: space-between;
35
+ align-items: center;
36
+ padding: ${spacing.r8};
37
+ border-bottom: 1px solid ${(props)=>props.theme.border};
38
+ `;
39
+ const FileInfo = styled_components.div`
40
+ flex: 1;
41
+ `;
42
+ const RemoveButton = styled_components.button`
43
+ background: none;
44
+ border: none;
45
+ cursor: pointer;
46
+ padding: ${spacing.r4};
47
+ color: ${(props)=>props.theme.textPrimary};
48
+
49
+ &:hover {
50
+ color: ${(props)=>props.theme.textSecondary};
51
+ }
52
+ `;
53
+ const maybePluralize = (count, word)=>1 === count ? `1 ${word}` : `${count} ${word}s`;
54
+ const getTitle = (fileCount)=>0 === fileCount ? "Upload Files" : `Upload ${maybePluralize(fileCount, "file")}`;
55
+ const FileList = ({ acceptedFiles, open, removeFile })=>/*#__PURE__*/ jsxs("div", {
56
+ children: [
57
+ /*#__PURE__*/ jsx(Button, {
58
+ icon: /*#__PURE__*/ jsx(Icon, {
59
+ name: "Create-add"
60
+ }),
61
+ label: "Add more files",
62
+ variant: "secondary",
63
+ onClick: open
64
+ }),
65
+ /*#__PURE__*/ jsx(Files, {
66
+ children: acceptedFiles.map((file)=>/*#__PURE__*/ jsxs(FileRow, {
67
+ children: [
68
+ /*#__PURE__*/ jsx(FileInfo, {
69
+ children: /*#__PURE__*/ jsxs("div", {
70
+ children: [
71
+ file.name,
72
+ /*#__PURE__*/ jsx("br", {}),
73
+ /*#__PURE__*/ jsx("small", {
74
+ children: /*#__PURE__*/ jsx(PrettyBytes, {
75
+ bytes: file.size
76
+ })
77
+ })
78
+ ]
79
+ })
80
+ }),
81
+ /*#__PURE__*/ jsx(RemoveButton, {
82
+ onClick: ()=>removeFile(file.name),
83
+ children: /*#__PURE__*/ jsx(Icon, {
84
+ name: "Close"
85
+ })
86
+ })
87
+ ]
88
+ }, file.name))
89
+ })
90
+ ]
91
+ });
92
+ const NoFile = ({ open })=>/*#__PURE__*/ jsxs(EmptyFile, {
93
+ children: [
94
+ /*#__PURE__*/ jsx(Icon, {
95
+ name: "Upload",
96
+ size: "3x"
97
+ }),
98
+ /*#__PURE__*/ jsx("div", {
99
+ children: "Drag and drop files and folders here"
100
+ }),
101
+ /*#__PURE__*/ jsx("div", {
102
+ children: "OR"
103
+ }),
104
+ /*#__PURE__*/ jsx(Button, {
105
+ icon: /*#__PURE__*/ jsx(Icon, {
106
+ name: "Create-add"
107
+ }),
108
+ label: "Add files",
109
+ variant: "secondary",
110
+ onClick: open
111
+ })
112
+ ]
113
+ });
114
+ const UploadButton_UploadButton = ({ bucket, prefix = "", uploadOptions = {}, onUploadSuccess, onUploadError })=>{
115
+ const [isModalOpen, setIsModalOpen] = useState(false);
116
+ const [acceptedFiles, setAcceptedFiles] = useState([]);
117
+ const uploadMutation = useUploadObjects();
118
+ const onDrop = useCallback((accepted)=>{
119
+ if (accepted.length > 0) setAcceptedFiles((prevFiles)=>{
120
+ const filtered = accepted.filter((newFile)=>!prevFiles.find((existingFile)=>existingFile.name === newFile.name));
121
+ return filtered.length > 0 ? [
122
+ ...prevFiles,
123
+ ...filtered
124
+ ] : prevFiles;
125
+ });
126
+ }, []);
127
+ const { getRootProps, getInputProps, open } = useDropzone({
128
+ noClick: true,
129
+ noKeyboard: true,
130
+ onDrop
131
+ });
132
+ const openModal = useCallback(()=>{
133
+ setIsModalOpen(true);
134
+ }, []);
135
+ const closeModal = useCallback(()=>{
136
+ setAcceptedFiles([]);
137
+ setIsModalOpen(false);
138
+ }, []);
139
+ const removeFile = useCallback((fileName)=>{
140
+ setAcceptedFiles((prevFiles)=>prevFiles.filter((file)=>file.name !== fileName));
141
+ }, []);
142
+ const handleUpload = useCallback(async ()=>{
143
+ if (0 === acceptedFiles.length) return;
144
+ const successfulFiles = [];
145
+ const failedFiles = [];
146
+ for (const file of acceptedFiles)try {
147
+ const fileBuffer = await file.arrayBuffer();
148
+ await uploadMutation.mutateAsync({
149
+ Bucket: bucket,
150
+ Key: prefix ? `${prefix}/${file.name}` : file.name,
151
+ Body: new Uint8Array(fileBuffer),
152
+ ContentType: file.type,
153
+ ...uploadOptions
154
+ });
155
+ successfulFiles.push(file);
156
+ } catch (error) {
157
+ failedFiles.push(file);
158
+ if (1 === failedFiles.length) onUploadError?.(error, [
159
+ file
160
+ ]);
161
+ }
162
+ if (successfulFiles.length > 0) onUploadSuccess?.(successfulFiles);
163
+ setAcceptedFiles([]);
164
+ setIsModalOpen(false);
165
+ }, [
166
+ acceptedFiles,
167
+ bucket,
168
+ prefix,
169
+ uploadMutation,
170
+ uploadOptions,
171
+ onUploadSuccess,
172
+ onUploadError
173
+ ]);
174
+ return /*#__PURE__*/ jsxs(Fragment, {
175
+ children: [
176
+ /*#__PURE__*/ jsx(Button, {
177
+ icon: /*#__PURE__*/ jsx(Icon, {
178
+ name: "Simple-upload"
179
+ }),
180
+ label: "Upload",
181
+ variant: "secondary",
182
+ onClick: openModal
183
+ }),
184
+ isModalOpen && /*#__PURE__*/ jsx(Modal, {
185
+ close: closeModal,
186
+ footer: /*#__PURE__*/ jsxs(Wrap, {
187
+ children: [
188
+ /*#__PURE__*/ jsx("p", {}),
189
+ /*#__PURE__*/ jsxs(Stack, {
190
+ children: [
191
+ /*#__PURE__*/ jsx(Button, {
192
+ variant: "outline",
193
+ onClick: closeModal,
194
+ label: "Cancel",
195
+ disabled: uploadMutation.isPending
196
+ }),
197
+ /*#__PURE__*/ jsx(Button, {
198
+ disabled: 0 === acceptedFiles.length || uploadMutation.isPending,
199
+ variant: "secondary",
200
+ onClick: handleUpload,
201
+ label: uploadMutation.isPending ? "Uploading..." : "Upload"
202
+ })
203
+ ]
204
+ })
205
+ ]
206
+ }),
207
+ isOpen: true,
208
+ title: getTitle(acceptedFiles.length),
209
+ children: /*#__PURE__*/ jsxs(DropZone, {
210
+ ...getRootProps(),
211
+ children: [
212
+ /*#__PURE__*/ jsx("input", {
213
+ ...getInputProps()
214
+ }),
215
+ acceptedFiles.length > 0 ? /*#__PURE__*/ jsx(FileList, {
216
+ acceptedFiles: acceptedFiles,
217
+ open: open,
218
+ removeFile: removeFile
219
+ }) : /*#__PURE__*/ jsx(NoFile, {
220
+ open: open
221
+ })
222
+ ]
223
+ })
224
+ })
225
+ ]
226
+ });
227
+ };
228
+ const UploadButton = UploadButton_UploadButton;
229
+ export { UploadButton_UploadButton as UploadButton, UploadButton as default };
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { QueryClient } from "@tanstack/react-query";
3
+ import { GetConfigFunction } from "../../types";
4
+ import { CoreUITheme } from "@scality/core-ui/dist/style/theme";
5
+ export interface DataBrowserContextValue {
6
+ getS3Config: GetConfigFunction;
7
+ theme: CoreUITheme;
8
+ }
9
+ export declare const DataBrowserContext: React.Context<DataBrowserContextValue | null>;
10
+ export declare const useDataBrowserContext: () => DataBrowserContextValue;
11
+ export declare const useDataBrowserTheme: () => CoreUITheme;
12
+ interface DataBrowserProviderProps {
13
+ children: React.ReactNode;
14
+ queryClient?: QueryClient;
15
+ enableDevtools?: boolean;
16
+ getS3Config?: GetConfigFunction;
17
+ theme?: CoreUITheme;
18
+ }
19
+ export declare const DataBrowserProvider: React.FC<DataBrowserProviderProps>;
20
+ export {};
@@ -0,0 +1,42 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
+ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
5
+ const DataBrowserContext = /*#__PURE__*/ createContext(null);
6
+ const useDataBrowserContext = ()=>{
7
+ const context = useContext(DataBrowserContext);
8
+ if (!context) throw new Error("useDataBrowserContext must be used within a DataBrowserProvider component");
9
+ return context;
10
+ };
11
+ const useDataBrowserTheme = ()=>{
12
+ const { theme } = useDataBrowserContext();
13
+ return theme;
14
+ };
15
+ const defaultQueryClient = new QueryClient({
16
+ defaultOptions: {
17
+ queries: {
18
+ staleTime: 300000,
19
+ retry: 2
20
+ }
21
+ }
22
+ });
23
+ const DataBrowserProvider = ({ children, queryClient = defaultQueryClient, enableDevtools = "development" === process.env.NODE_ENV, getS3Config, theme })=>{
24
+ const content = /*#__PURE__*/ jsxs(QueryClientProvider, {
25
+ client: queryClient,
26
+ children: [
27
+ children,
28
+ enableDevtools && /*#__PURE__*/ jsx(ReactQueryDevtools, {
29
+ initialIsOpen: false
30
+ })
31
+ ]
32
+ });
33
+ if (getS3Config && theme) return /*#__PURE__*/ jsx(DataBrowserContext.Provider, {
34
+ value: {
35
+ getS3Config,
36
+ theme
37
+ },
38
+ children: content
39
+ });
40
+ return content;
41
+ };
42
+ export { DataBrowserContext, DataBrowserProvider, useDataBrowserContext, useDataBrowserTheme };
@@ -0,0 +1,5 @@
1
+ type MetadataSearchProps = {
2
+ isError: boolean;
3
+ };
4
+ export declare const MetadataSearch: ({ isError }: MetadataSearchProps) => import("react/jsx-runtime").JSX.Element;
5
+ export default MetadataSearch;
@@ -0,0 +1,162 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { usePrefixWithSlash, useQueryParams } from "../../utils/hooks.js";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { useLocation, useNavigate } from "react-router-dom";
5
+ import { SearchContainer, SearchInputContainer, searchIcon } from "../ui/Search.elements.js";
6
+ import { Box, Button, Input } from "@scality/core-ui/dist/next";
7
+ import { Icon } from "@scality/core-ui";
8
+ import { SearchHints } from "./SearchHints.js";
9
+ const METADATA_SEARCH_HINT_ITEMS = [
10
+ {
11
+ label: 'files with extension ".pdf"',
12
+ query: "key like /pdf$/"
13
+ },
14
+ {
15
+ label: "files bigger than 1MB",
16
+ query: "content-length > 1000000"
17
+ },
18
+ {
19
+ label: "file names that contain scality (case insensitive)",
20
+ query: "key like /scality/i"
21
+ },
22
+ {
23
+ label: "files with metadata field color set to green",
24
+ query: 'x-amz-meta-color="green"'
25
+ },
26
+ {
27
+ label: "files tagged with color blue",
28
+ query: "tags.color=blue"
29
+ },
30
+ {
31
+ label: "PDF files (from content-type)",
32
+ query: "content-type=application/pdf"
33
+ },
34
+ {
35
+ label: "file names that contain the word Report (case sensitive)",
36
+ query: "key like Report"
37
+ },
38
+ {
39
+ label: "files waiting to be replicated",
40
+ query: 'replication-status="PENDING"'
41
+ }
42
+ ];
43
+ const MetadataSearch = ({ isError })=>{
44
+ const navigate = useNavigate();
45
+ const location = useLocation();
46
+ const query = useQueryParams();
47
+ const searchInput = query.get("metadatasearch");
48
+ const [inputText, setInputText] = useState(searchInput || "");
49
+ const [hintsShown, setHintsShown] = useState(false);
50
+ const prefixWithSlash = usePrefixWithSlash();
51
+ const inputRef = useRef(null);
52
+ const hintsRef = useRef(null);
53
+ const handleSubmit = useCallback((e)=>{
54
+ e.preventDefault();
55
+ if (!inputText || prefixWithSlash) return;
56
+ const newQuery = new URLSearchParams(location.search);
57
+ newQuery.set("metadatasearch", inputText);
58
+ navigate(`${location.pathname}?${newQuery.toString()}`);
59
+ }, [
60
+ inputText,
61
+ prefixWithSlash,
62
+ location,
63
+ navigate
64
+ ]);
65
+ const handleChange = useCallback((e)=>{
66
+ setInputText(e.target.value);
67
+ }, []);
68
+ const handleHintClicked = useCallback((queryText)=>{
69
+ setInputText(queryText);
70
+ setHintsShown(false);
71
+ }, []);
72
+ const handleInputClick = useCallback(()=>{
73
+ if (inputText || hintsShown) return;
74
+ setHintsShown(true);
75
+ }, [
76
+ inputText,
77
+ hintsShown
78
+ ]);
79
+ useEffect(()=>{
80
+ const handleClickOutside = (event)=>{
81
+ if (hintsShown && inputRef.current && hintsRef.current && !inputRef.current.contains(event.target) && !hintsRef.current.contains(event.target)) setHintsShown(false);
82
+ };
83
+ document.addEventListener("mousedown", handleClickOutside);
84
+ return ()=>{
85
+ document.removeEventListener("mousedown", handleClickOutside);
86
+ };
87
+ }, [
88
+ hintsShown
89
+ ]);
90
+ const reset = useCallback(()=>{
91
+ setHintsShown(false);
92
+ setInputText("");
93
+ const newQuery = new URLSearchParams(location.search);
94
+ newQuery.delete("metadatasearch");
95
+ navigate(`${location.pathname}?${newQuery.toString()}`);
96
+ }, [
97
+ location,
98
+ navigate
99
+ ]);
100
+ const handleHintClickWithFocus = useCallback((query)=>{
101
+ handleHintClicked(query);
102
+ if (inputRef.current) inputRef.current.focus();
103
+ }, [
104
+ handleHintClicked
105
+ ]);
106
+ const isSearchDisabled = !inputText || !!prefixWithSlash;
107
+ const shouldShowHints = hintsShown && !inputText;
108
+ const shouldShowResetButton = !!inputText;
109
+ const leftIcon = searchIcon({
110
+ isMetadata: !!searchInput,
111
+ isError
112
+ });
113
+ return /*#__PURE__*/ jsxs(SearchContainer, {
114
+ isHidden: !!prefixWithSlash,
115
+ onSubmit: handleSubmit,
116
+ children: [
117
+ /*#__PURE__*/ jsxs(SearchInputContainer, {
118
+ children: [
119
+ /*#__PURE__*/ jsx(Input, {
120
+ id: "metadata-search-input",
121
+ ref: inputRef,
122
+ onChange: handleChange,
123
+ placeholder: "Metadata Search",
124
+ value: inputText,
125
+ onClick: handleInputClick,
126
+ leftIcon: leftIcon.name,
127
+ leftIconColor: leftIcon.color
128
+ }),
129
+ shouldShowResetButton && /*#__PURE__*/ jsx(Box, {
130
+ position: "absolute",
131
+ right: "1px",
132
+ top: "0px",
133
+ children: /*#__PURE__*/ jsx(Button, {
134
+ icon: /*#__PURE__*/ jsx(Icon, {
135
+ name: "Close"
136
+ }),
137
+ tooltip: {
138
+ overlay: "Reset search"
139
+ },
140
+ onClick: reset,
141
+ "aria-label": "Clear search input"
142
+ })
143
+ })
144
+ ]
145
+ }),
146
+ shouldShowHints && /*#__PURE__*/ jsx(SearchHints, {
147
+ ref: hintsRef,
148
+ hints: METADATA_SEARCH_HINT_ITEMS,
149
+ onHintClick: handleHintClickWithFocus
150
+ }),
151
+ /*#__PURE__*/ jsx(Button, {
152
+ variant: "primary",
153
+ type: "submit",
154
+ label: "Search",
155
+ disabled: isSearchDisabled,
156
+ "aria-label": "Execute metadata search"
157
+ })
158
+ ]
159
+ });
160
+ };
161
+ const search_MetadataSearch = MetadataSearch;
162
+ export { MetadataSearch, search_MetadataSearch as default };
@@ -0,0 +1,8 @@
1
+ export interface SearchHintItem {
2
+ label: string;
3
+ query: string;
4
+ }
5
+ export declare const SearchHints: import("react").ForwardRefExoticComponent<{
6
+ hints: SearchHintItem[];
7
+ onHintClick: (query: string) => void;
8
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,21 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { HintItem, HintsContainer, HintsTitle } from "../ui/Search.elements.js";
4
+ const SearchHints = /*#__PURE__*/ forwardRef(({ hints, onHintClick }, ref)=>/*#__PURE__*/ jsxs(HintsContainer, {
5
+ ref: ref,
6
+ role: "listbox",
7
+ "aria-label": "Suggestions",
8
+ children: [
9
+ /*#__PURE__*/ jsx(HintsTitle, {
10
+ children: "Suggestions"
11
+ }),
12
+ hints.map((item, index)=>/*#__PURE__*/ jsx(HintItem, {
13
+ onClick: ()=>onHintClick(item.query),
14
+ role: "option",
15
+ tabIndex: 0,
16
+ children: item.label
17
+ }, index))
18
+ ]
19
+ }));
20
+ SearchHints.displayName = "SearchHints";
21
+ export { SearchHints };
@@ -0,0 +1,5 @@
1
+ import { Objects } from "../objects/DeleteObjectButton";
2
+ export declare const DeleteObjectModalContent: ({ objects, onRemove, }: {
3
+ objects: Objects;
4
+ onRemove: (key: string) => void;
5
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,71 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { ConstrainedText, Icon, PrettyBytes, spacing } from "@scality/core-ui";
3
+ import { tableRowHeight } from "@scality/core-ui/dist/components/tablev2/TableUtils";
4
+ import { Box, Table } from "@scality/core-ui/dist/next";
5
+ import { useMemo } from "react";
6
+ import styled_components from "styled-components";
7
+ const Container = styled_components(Box)`
8
+ height: ${({ height })=>height};
9
+ min-height: 15.63rem;
10
+ margin: ${spacing.r8} 0rem;
11
+ `;
12
+ const DeleteObjectModalContent = ({ objects, onRemove })=>{
13
+ const columns = useMemo(()=>[
14
+ {
15
+ Header: "Name",
16
+ accessor: "Key",
17
+ Cell: ({ value })=>/*#__PURE__*/ jsx(ConstrainedText, {
18
+ text: value,
19
+ lineClamp: 1
20
+ }),
21
+ id: "name"
22
+ },
23
+ {
24
+ Header: "Size",
25
+ accessor: "Size",
26
+ cellStyle: {
27
+ textAlign: "right"
28
+ },
29
+ Cell: ({ value })=>/*#__PURE__*/ jsx(PrettyBytes, {
30
+ bytes: Number(value)
31
+ }),
32
+ id: "size"
33
+ },
34
+ {
35
+ Header: "",
36
+ accessor: "type",
37
+ cellStyle: {
38
+ width: "0.625rem"
39
+ },
40
+ Cell: (row)=>{
41
+ const objectKey = row.row.original.Key;
42
+ return /*#__PURE__*/ jsx("div", {
43
+ onClick: ()=>onRemove(objectKey),
44
+ children: /*#__PURE__*/ jsx(Icon, {
45
+ name: "Close",
46
+ color: "buttonSecondary"
47
+ })
48
+ });
49
+ }
50
+ }
51
+ ], [
52
+ onRemove
53
+ ]);
54
+ const HEADER_AND_SPACING_ROWS = 3;
55
+ const rowHeight = "h40";
56
+ const tableRowHeightInRem = tableRowHeight[rowHeight];
57
+ return /*#__PURE__*/ jsx(Container, {
58
+ height: `calc(${objects.length + HEADER_AND_SPACING_ROWS} * (${tableRowHeightInRem}rem + 1px))`,
59
+ children: /*#__PURE__*/ jsx(Table, {
60
+ columns: columns,
61
+ data: objects,
62
+ children: /*#__PURE__*/ jsx(Table.SingleSelectableContent, {
63
+ rowHeight: "h40",
64
+ separationLineVariant: "backgroundLevel3",
65
+ selectedId: "Name",
66
+ onRowSelected: ()=>{}
67
+ })
68
+ })
69
+ });
70
+ };
71
+ export { DeleteObjectModalContent };
@@ -0,0 +1,17 @@
1
+ import { IconColor, IconName } from "@scality/core-ui/dist/components/icon/Icon.component";
2
+ export declare const SearchContainer: import("styled-components").StyledComponent<"form", any, {
3
+ isHidden?: boolean;
4
+ }, never>;
5
+ export declare const SearchInputContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
6
+ export declare const HintsContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
7
+ export declare const HintItem: import("styled-components").StyledComponent<"div", any, {}, never>;
8
+ export declare const HintsTitle: import("styled-components").StyledComponent<"div", any, {}, never>;
9
+ type SearchIcon = {
10
+ name: IconName;
11
+ color: IconColor;
12
+ };
13
+ export declare const searchIcon: ({ isMetadata, isError, }: {
14
+ isMetadata: boolean;
15
+ isError: boolean;
16
+ }) => SearchIcon;
17
+ export {};
@@ -0,0 +1,59 @@
1
+ import { spacing } from "@scality/core-ui/dist/spacing";
2
+ import styled_components from "styled-components";
3
+ const SearchContainer = styled_components.form`
4
+ flex: 1 0 auto;
5
+ display: flex;
6
+ max-width: 600px;
7
+ margin-right: ${spacing.r20};
8
+ visibility: ${(props)=>props.isHidden ? "hidden" : "visible"};
9
+ gap: ${spacing.r8};
10
+ `;
11
+ const SearchInputContainer = styled_components.div`
12
+ position: relative;
13
+ display: flex;
14
+ flex-direction: row;
15
+ margin-right: ${spacing.r4};
16
+ align-items: center;
17
+ `;
18
+ const HintsContainer = styled_components.div`
19
+ position: absolute;
20
+ z-index: 1;
21
+ background-color: ${(props)=>props.theme.backgroundLevel1};
22
+ padding: ${spacing.r16};
23
+ margin-top: ${spacing.r40};
24
+ `;
25
+ const HintItem = styled_components.div`
26
+ padding: ${spacing.r8} ${spacing.r12};
27
+ cursor: pointer;
28
+ color: ${(props)=>props.theme.textPrimary};
29
+ font-size: 0.875rem;
30
+ transition: background-color 0.2s ease;
31
+
32
+ &:hover {
33
+ background: ${(props)=>props.theme.backgroundLevel2};
34
+ }
35
+
36
+ &:last-child {
37
+ border-bottom: none;
38
+ }
39
+ `;
40
+ const HintsTitle = styled_components.div`
41
+ font-style: italic;
42
+ padding: ${spacing.r2} 0px ${spacing.r8} ${spacing.r8};
43
+ color: ${(props)=>props.theme.textSecondary};
44
+ `;
45
+ const searchIcon = ({ isMetadata, isError })=>{
46
+ if (isError) return {
47
+ name: "Close",
48
+ color: "statusCritical"
49
+ };
50
+ if (isMetadata) return {
51
+ name: "Check",
52
+ color: "statusHealthy"
53
+ };
54
+ return {
55
+ name: "Search",
56
+ color: "textSecondary"
57
+ };
58
+ };
59
+ export { HintItem, HintsContainer, HintsTitle, SearchContainer, SearchInputContainer, searchIcon };
@@ -0,0 +1,36 @@
1
+ export declare const Table: ({ children, ...props }: {
2
+ children: React.ReactNode;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export declare const Body: ({ children, ...props }: {
5
+ children: React.ReactNode;
6
+ }) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const Group: ({ children, ...props }: {
8
+ children: React.ReactNode;
9
+ }) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const GroupName: ({ children, ...props }: {
11
+ children: React.ReactNode;
12
+ }) => import("react/jsx-runtime").JSX.Element;
13
+ export declare const GroupContent: ({ children, ...props }: {
14
+ children: React.ReactNode;
15
+ }) => import("react/jsx-runtime").JSX.Element;
16
+ export declare const Row: ({ children, ...props }: {
17
+ children: React.ReactNode;
18
+ }) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const Key: import("styled-components").StyledComponent<"div", any, {
20
+ principal?: boolean;
21
+ required?: boolean;
22
+ } & {
23
+ size?: string;
24
+ }, never>;
25
+ export declare const Value: import("styled-components").StyledComponent<"div", any, {
26
+ width?: string;
27
+ }, never>;
28
+ export declare const TableContainer: ({ children, ...props }: {
29
+ children: React.ReactNode;
30
+ }) => import("react/jsx-runtime").JSX.Element;
31
+ export declare const GroupValues: import("styled-components").StyledComponent<"div", any, {
32
+ size?: string;
33
+ }, never>;
34
+ export declare const ExtraCell: import("styled-components").StyledComponent<"div", any, {
35
+ marginLeft?: string;
36
+ }, never>;