@scality/data-browser-library 1.0.4 → 1.0.5

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 (52) hide show
  1. package/dist/components/DataBrowserUI.js +18 -8
  2. package/dist/components/__tests__/BucketList.test.js +74 -1
  3. package/dist/components/__tests__/ObjectList.test.js +94 -2
  4. package/dist/components/buckets/BucketCreate.d.ts +1 -0
  5. package/dist/components/buckets/BucketCreate.js +57 -7
  6. package/dist/components/buckets/BucketDetails.js +0 -1
  7. package/dist/components/buckets/BucketLifecycleFormPage.js +209 -213
  8. package/dist/components/buckets/BucketList.js +25 -4
  9. package/dist/components/buckets/BucketReplicationFormPage.js +9 -3
  10. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +1 -1
  11. package/dist/components/buckets/notifications/BucketNotificationList.js +1 -1
  12. package/dist/components/objects/DeleteObjectButton.d.ts +1 -0
  13. package/dist/components/objects/DeleteObjectButton.js +11 -5
  14. package/dist/components/objects/ObjectDetails/FormComponents.d.ts +9 -0
  15. package/dist/components/objects/ObjectDetails/FormComponents.js +37 -0
  16. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +182 -204
  17. package/dist/components/objects/ObjectDetails/ObjectSummary.js +22 -5
  18. package/dist/components/objects/ObjectDetails/ObjectTags.js +109 -154
  19. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +3 -3
  20. package/dist/components/objects/ObjectDetails/__tests__/ObjectMetadata.test.d.ts +1 -0
  21. package/dist/components/objects/ObjectDetails/__tests__/ObjectMetadata.test.js +230 -0
  22. package/dist/components/objects/ObjectDetails/__tests__/ObjectTags.test.d.ts +1 -0
  23. package/dist/components/objects/ObjectDetails/__tests__/ObjectTags.test.js +342 -0
  24. package/dist/components/objects/ObjectDetails/__tests__/formUtils.test.d.ts +1 -0
  25. package/dist/components/objects/ObjectDetails/__tests__/formUtils.test.js +202 -0
  26. package/dist/components/objects/ObjectDetails/index.d.ts +2 -1
  27. package/dist/components/objects/ObjectDetails/index.js +12 -16
  28. package/dist/components/objects/ObjectList.d.ts +3 -2
  29. package/dist/components/objects/ObjectList.js +204 -104
  30. package/dist/components/objects/ObjectPage.js +22 -5
  31. package/dist/components/ui/ArrayFieldActions.js +0 -2
  32. package/dist/components/ui/FilterFormSection.js +17 -36
  33. package/dist/components/ui/FormGrid.d.ts +7 -0
  34. package/dist/components/ui/FormGrid.js +37 -0
  35. package/dist/components/ui/Table.elements.js +1 -0
  36. package/dist/config/types.d.ts +45 -2
  37. package/dist/hooks/__tests__/usePresigningS3Client.test.d.ts +1 -0
  38. package/dist/hooks/__tests__/usePresigningS3Client.test.js +104 -0
  39. package/dist/hooks/factories/index.d.ts +1 -1
  40. package/dist/hooks/factories/index.js +2 -2
  41. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +2 -1
  42. package/dist/hooks/factories/useCreateS3MutationHook.js +10 -3
  43. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +1 -0
  44. package/dist/hooks/factories/useCreateS3QueryHook.js +9 -6
  45. package/dist/hooks/index.d.ts +1 -0
  46. package/dist/hooks/index.js +2 -1
  47. package/dist/hooks/presignedOperations.js +4 -4
  48. package/dist/hooks/useBucketLocations.d.ts +6 -0
  49. package/dist/hooks/useBucketLocations.js +45 -0
  50. package/dist/hooks/usePresigningS3Client.d.ts +13 -0
  51. package/dist/hooks/usePresigningS3Client.js +21 -0
  52. package/package.json +1 -1
@@ -1,13 +1,13 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Icon, Loader, Text, spacing, useToast } from "@scality/core-ui";
3
- import { convertSizeToRem } from "@scality/core-ui/dist/components/inputv2/inputv2";
4
- import { Box, Button, Input, Select } from "@scality/core-ui/dist/next";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Text, spacing, useToast } from "@scality/core-ui";
3
+ import { Box, Input, Select } from "@scality/core-ui/dist/next";
5
4
  import { useEffect, useState } from "react";
6
5
  import { Controller, useFieldArray, useForm } from "react-hook-form";
7
6
  import { useCopyObject, useObjectMetadata } from "../../../hooks/index.js";
8
7
  import { useInvalidateQueries } from "../../providers/DataBrowserProvider.js";
9
8
  import { ArrayFieldActions } from "../../ui/ArrayFieldActions.js";
10
- import { TableContainer } from "../../ui/Table.elements.js";
9
+ import { Table, TableContainer } from "../../ui/Table.elements.js";
10
+ import { FormCell, FormColumnHeaders, FormError, FormHeader, FormLoading, FormRow } from "./FormComponents.js";
11
11
  import { hasFormDataChanged } from "./formUtils.js";
12
12
  const METADATA_KEYS = [
13
13
  {
@@ -153,6 +153,7 @@ const ObjectMetadata = ({ bucketName, objectKey, versionId })=>{
153
153
  }
154
154
  ]
155
155
  });
156
+ setIsInitialized(false);
156
157
  showToast({
157
158
  open: true,
158
159
  message: 'Metadata saved successfully',
@@ -167,213 +168,190 @@ const ObjectMetadata = ({ bucketName, objectKey, versionId })=>{
167
168
  });
168
169
  }
169
170
  };
170
- if ('pending' === metadataStatus) return /*#__PURE__*/ jsx(TableContainer, {
171
- children: /*#__PURE__*/ jsx(Box, {
172
- display: "flex",
173
- justifyContent: "center",
174
- padding: spacing.r32,
175
- children: /*#__PURE__*/ jsx(Loader, {})
176
- })
177
- });
178
- if ('error' === metadataStatus) return /*#__PURE__*/ jsx(TableContainer, {
179
- children: /*#__PURE__*/ jsx(Box, {
180
- padding: spacing.r16,
181
- children: /*#__PURE__*/ jsx(Text, {
182
- color: "statusCritical",
183
- children: "Error loading metadata"
184
- })
185
- })
171
+ if ('pending' === metadataStatus) return /*#__PURE__*/ jsx(FormLoading, {});
172
+ if ('error' === metadataStatus) return /*#__PURE__*/ jsx(FormError, {
173
+ message: "Error loading metadata"
186
174
  });
187
175
  return /*#__PURE__*/ jsx(TableContainer, {
188
176
  children: /*#__PURE__*/ jsxs("form", {
189
177
  onSubmit: handleSubmit(onSubmit),
178
+ style: {
179
+ display: 'flex',
180
+ flexDirection: 'column',
181
+ minHeight: 0,
182
+ flex: 1
183
+ },
190
184
  children: [
191
- /*#__PURE__*/ jsxs(Box, {
192
- display: "flex",
193
- justifyContent: "space-between",
194
- alignItems: "center",
195
- padding: spacing.r16,
196
- borderBottom: "1px solid",
197
- borderColor: "backgroundLevel3",
198
- children: [
199
- /*#__PURE__*/ jsx(Text, {
200
- isEmphazed: true,
201
- children: "Edit Metadata"
202
- }),
203
- /*#__PURE__*/ jsx(Button, {
204
- variant: "primary",
205
- label: "Save",
206
- disabled: !isValid || isSubmitting || !hasChanges(),
207
- type: "submit",
208
- icon: /*#__PURE__*/ jsx(Icon, {
209
- name: "Save"
210
- })
211
- })
212
- ]
185
+ /*#__PURE__*/ jsx(FormHeader, {
186
+ disabled: !isValid || !hasChanges(),
187
+ isSubmitting: isSubmitting
213
188
  }),
214
- /*#__PURE__*/ jsxs(Box, {
215
- padding: spacing.r16,
216
- display: "flex",
217
- flexDirection: "column",
218
- gap: spacing.r12,
219
- children: [
220
- /*#__PURE__*/ jsxs(Box, {
221
- display: "flex",
222
- gap: spacing.r8,
223
- children: [
224
- /*#__PURE__*/ jsx(Box, {
225
- flex: "1",
226
- children: /*#__PURE__*/ jsx(Text, {
227
- color: "textSecondary",
228
- isEmphazed: true,
229
- children: "Key"
230
- })
231
- }),
232
- /*#__PURE__*/ jsx(Box, {
233
- flex: "1",
234
- children: /*#__PURE__*/ jsx(Text, {
235
- color: "textSecondary",
236
- isEmphazed: true,
237
- children: "Value"
238
- })
239
- }),
240
- /*#__PURE__*/ jsx(Box, {
241
- width: convertSizeToRem('1/3')
242
- })
243
- ]
244
- }),
245
- fields.map((field, index)=>/*#__PURE__*/ jsxs(Box, {
246
- children: [
247
- /*#__PURE__*/ jsxs(Box, {
248
- display: "flex",
249
- gap: spacing.r8,
250
- alignItems: "center",
251
- children: [
252
- /*#__PURE__*/ jsx(Controller, {
253
- control: control,
254
- name: `metadata.${index}.keyType`,
255
- rules: {
256
- validate: (value, formValues)=>{
257
- if (1 === formValues.metadata.length && !value && !formValues.metadata[0].value.trim()) return true;
258
- if (!value) return 'Please select a metadata key';
259
- const allMetadata = formValues.metadata;
260
- const usedKeys = allMetadata.map((row, idx)=>{
261
- if (idx === index) return null;
262
- if ('x-amz-meta' === row.keyType) return row.customKey ? `x-amz-meta-${row.customKey.trim()}` : null;
263
- return row.keyType;
264
- }).filter(Boolean);
265
- const currentKey = 'x-amz-meta' === value ? formValues.metadata[index].customKey ? `x-amz-meta-${formValues.metadata[index].customKey.trim()}` : null : value;
266
- if (currentKey && usedKeys.includes(currentKey)) return `Duplicate key "${currentKey}"`;
267
- return true;
268
- }
269
- },
270
- render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Select, {
271
- id: `key-${field.id}`,
272
- value: value,
273
- onChange: (newValue)=>{
274
- onChange(newValue);
275
- if ('x-amz-meta' !== newValue) setValue(`metadata.${index}.customKey`, '');
189
+ /*#__PURE__*/ jsx(Table, {
190
+ children: /*#__PURE__*/ jsxs(Box, {
191
+ paddingTop: spacing.r16,
192
+ display: "flex",
193
+ flexDirection: "column",
194
+ gap: spacing.r12,
195
+ children: [
196
+ /*#__PURE__*/ jsx(FormColumnHeaders, {
197
+ wideKey: true
198
+ }),
199
+ fields.map((field, index)=>/*#__PURE__*/ jsxs(Box, {
200
+ children: [
201
+ /*#__PURE__*/ jsxs(FormRow, {
202
+ columns: "3fr auto 2fr",
203
+ children: [
204
+ /*#__PURE__*/ jsxs(Box, {
205
+ display: "flex",
206
+ gap: spacing.r8,
207
+ alignItems: "center",
208
+ style: {
209
+ minWidth: 0
210
+ },
211
+ children: [
212
+ /*#__PURE__*/ jsx(FormCell, {
213
+ style: {
214
+ flex: 1
215
+ },
216
+ children: /*#__PURE__*/ jsx(Controller, {
217
+ control: control,
218
+ name: `metadata.${index}.keyType`,
219
+ rules: {
220
+ validate: (value, formValues)=>{
221
+ if (!value && !formValues.metadata[index].value.trim()) return true;
222
+ if (!value) return 'Please select a metadata key';
223
+ const allMetadata = formValues.metadata;
224
+ const usedKeys = allMetadata.map((row, idx)=>{
225
+ if (idx === index) return null;
226
+ if ('x-amz-meta' === row.keyType) return row.customKey ? `x-amz-meta-${row.customKey.trim()}` : null;
227
+ return row.keyType;
228
+ }).filter(Boolean);
229
+ const currentKey = 'x-amz-meta' === value ? formValues.metadata[index].customKey ? `x-amz-meta-${formValues.metadata[index].customKey.trim()}` : null : value;
230
+ if (currentKey && usedKeys.includes(currentKey)) return `Duplicate key "${currentKey}"`;
231
+ return true;
232
+ }
233
+ },
234
+ render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Select, {
235
+ id: `key-${field.id}`,
236
+ value: value,
237
+ onChange: (newValue)=>{
238
+ onChange(newValue);
239
+ if ('x-amz-meta' !== newValue) setValue(`metadata.${index}.customKey`, '');
240
+ },
241
+ placeholder: "Select key",
242
+ children: getAvailableOptions(index).map((key)=>/*#__PURE__*/ jsx(Select.Option, {
243
+ value: key.key,
244
+ children: key.label
245
+ }, key.key))
246
+ })
247
+ })
248
+ }),
249
+ 'x-amz-meta' === watch(`metadata.${index}.keyType`) && /*#__PURE__*/ jsxs(Fragment, {
250
+ children: [
251
+ /*#__PURE__*/ jsx(Text, {
252
+ color: "textSecondary",
253
+ children: "-"
254
+ }),
255
+ /*#__PURE__*/ jsx(Controller, {
256
+ control: control,
257
+ name: `metadata.${index}.customKey`,
258
+ rules: {
259
+ validate: (value, formValues)=>{
260
+ if ('x-amz-meta' === formValues.metadata[index].keyType) {
261
+ if (!value.trim()) return 'Custom key required';
262
+ }
263
+ return true;
264
+ }
265
+ },
266
+ render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Input, {
267
+ id: `customKey-${field.id}`,
268
+ value: value,
269
+ onChange: onChange,
270
+ size: "1/3"
271
+ })
272
+ })
273
+ ]
274
+ })
275
+ ]
276
+ }),
277
+ /*#__PURE__*/ jsx(Text, {
278
+ color: "textSecondary",
279
+ children: ":"
280
+ }),
281
+ /*#__PURE__*/ jsx(FormCell, {
282
+ children: /*#__PURE__*/ jsx(Controller, {
283
+ control: control,
284
+ name: `metadata.${index}.value`,
285
+ rules: {
286
+ validate: (value, formValues)=>{
287
+ if (!value.trim() && !formValues.metadata[index].keyType) return true;
288
+ if (!value.trim()) return 'Value cannot be empty';
289
+ return true;
290
+ }
276
291
  },
277
- placeholder: "Select key",
278
- children: getAvailableOptions(index).map((key)=>/*#__PURE__*/ jsx(Select.Option, {
279
- value: key.key,
280
- children: key.label
281
- }, key.key))
282
- })
283
- }),
284
- 'x-amz-meta' === watch(`metadata.${index}.keyType`) && /*#__PURE__*/ jsx(Controller, {
285
- control: control,
286
- name: `metadata.${index}.customKey`,
287
- rules: {
288
- validate: (value, formValues)=>{
289
- if ('x-amz-meta' === formValues.metadata[index].keyType) {
290
- if (!value.trim()) return 'Custom key required';
291
- }
292
- return true;
293
- }
294
- },
295
- render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Input, {
296
- id: `customKey-${field.id}`,
297
- value: value,
298
- onChange: onChange,
299
- size: "1/3"
300
- })
301
- }),
302
- /*#__PURE__*/ jsx(Text, {
303
- color: "textSecondary",
304
- children: ":"
305
- }),
306
- /*#__PURE__*/ jsx(Controller, {
307
- control: control,
308
- name: `metadata.${index}.value`,
309
- rules: {
310
- validate: (value, formValues)=>{
311
- if (1 === formValues.metadata.length && !value.trim() && !formValues.metadata[0].keyType) return true;
312
- if (!value.trim()) return 'Value cannot be empty';
313
- return true;
314
- }
315
- },
316
- render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Input, {
317
- id: `value-${field.id}`,
318
- value: value,
319
- onChange: onChange,
320
- placeholder: "Value"
292
+ render: ({ field: { onChange, value } })=>/*#__PURE__*/ jsx(Input, {
293
+ id: `value-${field.id}`,
294
+ value: value,
295
+ onChange: onChange,
296
+ placeholder: "Value"
297
+ })
321
298
  })
322
- }),
323
- /*#__PURE__*/ jsx(ArrayFieldActions, {
324
- showAdd: index === fields.length - 1,
325
- onRemove: ()=>{
326
- remove(index);
327
- if (1 === fields.length) append({
328
- keyType: '',
329
- customKey: '',
330
- value: ''
331
- });
332
- },
333
- onAdd: ()=>append({
334
- keyType: '',
335
- customKey: '',
336
- value: ''
337
- }),
338
- canRemove: (()=>{
339
- const keyType = watch(`metadata.${index}.keyType`);
340
- const customKey = watch(`metadata.${index}.customKey`);
341
- const value = watch(`metadata.${index}.value`);
342
- const hasKey = 'x-amz-meta' === keyType ? customKey : keyType;
343
- return !!hasKey && !!value;
344
- })(),
345
- canAdd: (()=>{
346
- const keyType = watch(`metadata.${index}.keyType`);
347
- const customKey = watch(`metadata.${index}.customKey`);
348
- const value = watch(`metadata.${index}.value`);
349
- const hasKey = 'x-amz-meta' === keyType ? customKey : keyType;
350
- return !!hasKey && !!value;
351
- })(),
352
- removeLabel: "Remove metadata",
353
- addLabel: "Add metadata"
354
- })
355
- ]
356
- }),
357
- (errors.metadata?.[index]?.keyType || errors.metadata?.[index]?.customKey || errors.metadata?.[index]?.value) && /*#__PURE__*/ jsxs(Box, {
358
- paddingTop: spacing.r4,
359
- children: [
360
- errors.metadata?.[index]?.keyType && /*#__PURE__*/ jsx(Text, {
361
- color: "statusCritical",
362
- children: errors.metadata[index]?.keyType?.message
363
- }),
364
- errors.metadata?.[index]?.customKey && /*#__PURE__*/ jsx(Text, {
365
- color: "statusCritical",
366
- children: errors.metadata[index]?.customKey?.message
367
- }),
368
- errors.metadata?.[index]?.value && /*#__PURE__*/ jsx(Text, {
369
- color: "statusCritical",
370
- children: errors.metadata[index]?.value?.message
371
- })
372
- ]
373
- })
374
- ]
375
- }, field.id))
376
- ]
299
+ }),
300
+ /*#__PURE__*/ jsx(ArrayFieldActions, {
301
+ showAdd: index === fields.length - 1,
302
+ onRemove: ()=>{
303
+ remove(index);
304
+ if (1 === fields.length) append({
305
+ keyType: '',
306
+ customKey: '',
307
+ value: ''
308
+ });
309
+ },
310
+ onAdd: ()=>append({
311
+ keyType: '',
312
+ customKey: '',
313
+ value: ''
314
+ }),
315
+ canRemove: (()=>{
316
+ const keyType = watch(`metadata.${index}.keyType`);
317
+ const customKey = watch(`metadata.${index}.customKey`);
318
+ const value = watch(`metadata.${index}.value`);
319
+ const hasKey = 'x-amz-meta' === keyType ? customKey : keyType;
320
+ return !!hasKey || !!value;
321
+ })(),
322
+ canAdd: (()=>{
323
+ const keyType = watch(`metadata.${index}.keyType`);
324
+ const customKey = watch(`metadata.${index}.customKey`);
325
+ const value = watch(`metadata.${index}.value`);
326
+ const hasKey = 'x-amz-meta' === keyType ? customKey : keyType;
327
+ return !!hasKey && !!value;
328
+ })(),
329
+ removeLabel: "Remove metadata",
330
+ addLabel: "Add metadata"
331
+ })
332
+ ]
333
+ }),
334
+ (errors.metadata?.[index]?.keyType || errors.metadata?.[index]?.customKey || errors.metadata?.[index]?.value) && /*#__PURE__*/ jsxs(Box, {
335
+ paddingTop: spacing.r4,
336
+ children: [
337
+ errors.metadata?.[index]?.keyType && /*#__PURE__*/ jsx(Text, {
338
+ color: "statusCritical",
339
+ children: errors.metadata[index]?.keyType?.message
340
+ }),
341
+ errors.metadata?.[index]?.customKey && /*#__PURE__*/ jsx(Text, {
342
+ color: "statusCritical",
343
+ children: errors.metadata[index]?.customKey?.message
344
+ }),
345
+ errors.metadata?.[index]?.value && /*#__PURE__*/ jsx(Text, {
346
+ color: "statusCritical",
347
+ children: errors.metadata[index]?.value?.message
348
+ })
349
+ ]
350
+ })
351
+ ]
352
+ }, field.id))
353
+ ]
354
+ })
377
355
  })
378
356
  ]
379
357
  })
@@ -165,7 +165,11 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
165
165
  width: "15rem",
166
166
  children: /*#__PURE__*/ jsx(ConstrainedText, {
167
167
  text: objectKey,
168
- lineClamp: 2
168
+ lineClamp: 2,
169
+ tooltipStyle: {
170
+ maxWidth: '20rem',
171
+ wordBreak: 'break-all'
172
+ }
169
173
  })
170
174
  })
171
175
  ]
@@ -187,7 +191,11 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
187
191
  minWidth: "0",
188
192
  children: /*#__PURE__*/ jsx(ConstrainedText, {
189
193
  text: metadata?.VersionId || versionId || 'N/A',
190
- lineClamp: 1
194
+ lineClamp: 1,
195
+ tooltipStyle: {
196
+ maxWidth: '20rem',
197
+ wordBreak: 'break-all'
198
+ }
191
199
  })
192
200
  }),
193
201
  /*#__PURE__*/ jsx(ExtraCell, {
@@ -212,7 +220,8 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
212
220
  }),
213
221
  /*#__PURE__*/ jsx(Value, {
214
222
  children: 'pending' === metadataStatus ? /*#__PURE__*/ jsx(Loader, {}) : 'error' === metadataStatus ? 'Error' : /*#__PURE__*/ jsx(PrettyBytes, {
215
- bytes: metadata?.ContentLength || 0
223
+ bytes: metadata?.ContentLength || 0,
224
+ decimals: 2
216
225
  })
217
226
  })
218
227
  ]
@@ -251,7 +260,11 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
251
260
  minWidth: "0",
252
261
  children: /*#__PURE__*/ jsx(ConstrainedText, {
253
262
  text: metadata?.ETag?.replace(/^"|"$/g, '') || 'N/A',
254
- lineClamp: 1
263
+ lineClamp: 1,
264
+ tooltipStyle: {
265
+ maxWidth: '20rem',
266
+ wordBreak: 'break-all'
267
+ }
255
268
  })
256
269
  }),
257
270
  /*#__PURE__*/ jsx(ExtraCell, {
@@ -418,7 +431,11 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
418
431
  minWidth: "0",
419
432
  children: /*#__PURE__*/ jsx(ConstrainedText, {
420
433
  text: publicUrl,
421
- lineClamp: 1
434
+ lineClamp: 1,
435
+ tooltipStyle: {
436
+ maxWidth: '20rem',
437
+ wordBreak: 'break-all'
438
+ }
422
439
  })
423
440
  }),
424
441
  /*#__PURE__*/ jsx(ExtraCell, {