@scality/data-browser-library 1.0.0-preview.7 → 1.0.0-preview.9

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 (90) hide show
  1. package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
  2. package/dist/components/__tests__/BucketCreate.test.js +408 -0
  3. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
  5. package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
  6. package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
  7. package/dist/components/__tests__/BucketList.test.js +190 -0
  8. package/dist/components/__tests__/BucketOverview.test.js +298 -8
  9. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +1 -0
  10. package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
  11. package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
  12. package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
  13. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
  14. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
  15. package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
  16. package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
  17. package/dist/components/buckets/BucketCreate.d.ts +49 -0
  18. package/dist/components/buckets/BucketCreate.js +237 -0
  19. package/dist/components/buckets/BucketDetails.js +62 -10
  20. package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
  21. package/dist/components/buckets/BucketLifecycleFormPage.js +1070 -0
  22. package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
  23. package/dist/components/buckets/BucketLifecycleList.js +270 -0
  24. package/dist/components/buckets/BucketList.d.ts +5 -2
  25. package/dist/components/buckets/BucketList.js +38 -28
  26. package/dist/components/buckets/BucketOverview.d.ts +65 -4
  27. package/dist/components/buckets/BucketOverview.js +261 -179
  28. package/dist/components/buckets/BucketPage.js +1 -1
  29. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  30. package/dist/components/buckets/BucketReplicationFormPage.js +834 -0
  31. package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
  32. package/dist/components/buckets/BucketReplicationList.js +189 -0
  33. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
  34. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
  35. package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
  36. package/dist/components/buckets/EmptyBucketButton.js +232 -0
  37. package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
  38. package/dist/components/buckets/EmptyBucketSummary.js +60 -0
  39. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
  40. package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
  41. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +8 -8
  42. package/dist/components/index.d.ts +8 -1
  43. package/dist/components/index.js +9 -2
  44. package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
  45. package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
  46. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
  47. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
  48. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
  49. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +158 -0
  50. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
  51. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
  52. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
  53. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
  54. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
  55. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
  56. package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
  57. package/dist/components/ui/ArrayFieldActions.js +38 -0
  58. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
  59. package/dist/components/ui/ConfirmDeleteRuleModal.js +43 -0
  60. package/dist/components/ui/FilterFormSection.d.ts +44 -0
  61. package/dist/components/ui/FilterFormSection.js +159 -0
  62. package/dist/config/factory.d.ts +13 -2
  63. package/dist/config/factory.js +9 -6
  64. package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
  65. package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
  66. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +44 -1
  67. package/dist/hooks/factories/useCreateS3QueryHook.js +22 -1
  68. package/dist/hooks/index.d.ts +4 -0
  69. package/dist/hooks/index.js +5 -1
  70. package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
  71. package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
  72. package/dist/hooks/useEmptyBucket.d.ts +27 -0
  73. package/dist/hooks/useEmptyBucket.js +116 -0
  74. package/dist/hooks/useISVBucketDetection.d.ts +15 -0
  75. package/dist/hooks/useISVBucketDetection.js +27 -0
  76. package/dist/hooks/useTableRowSelection.d.ts +9 -0
  77. package/dist/hooks/useTableRowSelection.js +45 -0
  78. package/dist/test/setup.js +8 -0
  79. package/dist/test/testUtils.d.ts +99 -17
  80. package/dist/test/testUtils.js +64 -16
  81. package/dist/test/utils/errorHandling.test.js +39 -1
  82. package/dist/utils/constants.d.ts +12 -0
  83. package/dist/utils/constants.js +9 -0
  84. package/dist/utils/errorHandling.d.ts +9 -0
  85. package/dist/utils/errorHandling.js +6 -1
  86. package/dist/utils/index.d.ts +2 -0
  87. package/dist/utils/index.js +2 -0
  88. package/dist/utils/s3RuleUtils.d.ts +53 -0
  89. package/dist/utils/s3RuleUtils.js +101 -0
  90. package/package.json +1 -1
@@ -0,0 +1,140 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { BasicText, Icon, IconHelp, Stack, Text } from "@scality/core-ui";
3
+ import { Table } from "@scality/core-ui/dist/components/tablev2/Tablev2.component";
4
+ import { useMemo } from "react";
5
+ const getUniqueErrorMessages = (errorMessages)=>{
6
+ const uniqueArray = errorMessages.reduce((acc, message)=>{
7
+ const existingItem = acc.find((item)=>item.message === message);
8
+ if (existingItem) existingItem.errorNumbers++;
9
+ else acc.push({
10
+ message,
11
+ errorNumbers: 1
12
+ });
13
+ return acc;
14
+ }, []);
15
+ return uniqueArray;
16
+ };
17
+ const ErrorsTable = ({ messages })=>{
18
+ const messagesColumns = [
19
+ {
20
+ Header: "Error Message",
21
+ accessor: "message",
22
+ cellStyle: {
23
+ minWidth: "8rem"
24
+ },
25
+ Cell ({ value }) {
26
+ return /*#__PURE__*/ jsx(Text, {
27
+ children: value
28
+ });
29
+ }
30
+ },
31
+ {
32
+ Header: "Number of errors",
33
+ accessor: "errorNumbers",
34
+ cellStyle: {
35
+ minWidth: "8rem"
36
+ },
37
+ Cell ({ value }) {
38
+ return /*#__PURE__*/ jsx(Text, {
39
+ children: value
40
+ });
41
+ }
42
+ }
43
+ ];
44
+ const list = getUniqueErrorMessages(messages);
45
+ const TABLE_HEIGHT = 5 * list.length;
46
+ return /*#__PURE__*/ jsx(IconHelp, {
47
+ placement: "top",
48
+ overlayStyle: {
49
+ width: "30rem"
50
+ },
51
+ tooltipMessage: /*#__PURE__*/ jsx("div", {
52
+ style: {
53
+ height: `${TABLE_HEIGHT}rem`
54
+ },
55
+ children: /*#__PURE__*/ jsx(Table, {
56
+ columns: messagesColumns,
57
+ data: list,
58
+ children: /*#__PURE__*/ jsx(Table.SingleSelectableContent, {
59
+ rowHeight: "h32",
60
+ separationLineVariant: "backgroundLevel3"
61
+ })
62
+ })
63
+ })
64
+ });
65
+ };
66
+ const SummaryCell = (value, isFailed = false, withIcon = false, messages)=>{
67
+ const text = 1 === value ? "1 object" : `${value} objects`;
68
+ if (withIcon) return /*#__PURE__*/ jsxs(Stack, {
69
+ children: [
70
+ /*#__PURE__*/ jsx(Icon, {
71
+ name: isFailed ? "Exclamation-circle" : "Check-circle",
72
+ color: isFailed ? "statusCritical" : "statusHealthy"
73
+ }),
74
+ /*#__PURE__*/ jsx(BasicText, {
75
+ children: text
76
+ }),
77
+ messages?.length ? /*#__PURE__*/ jsx(ErrorsTable, {
78
+ messages: messages
79
+ }) : null
80
+ ]
81
+ });
82
+ return /*#__PURE__*/ jsx(BasicText, {
83
+ children: text
84
+ });
85
+ };
86
+ const useCreateDeleteSummaryColumns = ()=>useMemo(()=>[
87
+ {
88
+ Header: "Total attempts",
89
+ accessor: "attempts",
90
+ cellStyle: {
91
+ minWidth: "12rem"
92
+ },
93
+ Cell ({ value }) {
94
+ return SummaryCell(value);
95
+ }
96
+ },
97
+ {
98
+ Header: "Successfully deleted",
99
+ accessor: "deleted",
100
+ cellStyle: {
101
+ minWidth: "12rem"
102
+ },
103
+ Cell ({ value }) {
104
+ return SummaryCell(value, false, true);
105
+ }
106
+ },
107
+ {
108
+ Header: "Deletion failed",
109
+ accessor: "errors",
110
+ cellStyle: {
111
+ minWidth: "12rem"
112
+ },
113
+ Cell ({ value }) {
114
+ return SummaryCell(value.nbErrors, true, true, value.messages);
115
+ }
116
+ }
117
+ ], []);
118
+ const EmptyBucketSummaryList = ({ summaryData })=>{
119
+ const summaryColumns = useCreateDeleteSummaryColumns();
120
+ return /*#__PURE__*/ jsx("div", {
121
+ style: {
122
+ height: "15rem"
123
+ },
124
+ children: /*#__PURE__*/ jsx(Table, {
125
+ columns: summaryColumns,
126
+ data: summaryData,
127
+ children: /*#__PURE__*/ jsx("div", {
128
+ style: {
129
+ height: "10rem",
130
+ paddingBottom: "5rem"
131
+ },
132
+ children: /*#__PURE__*/ jsx(Table.SingleSelectableContent, {
133
+ rowHeight: "h40",
134
+ separationLineVariant: "backgroundLevel1"
135
+ })
136
+ })
137
+ })
138
+ });
139
+ };
140
+ export { EmptyBucketSummaryList };
@@ -3,25 +3,25 @@ import { joiResolver } from "@hookform/resolvers/joi";
3
3
  import { Form, FormGroup, FormSection, Loader, Stack, Text, useToast } from "@scality/core-ui";
4
4
  import { convertRemToPixels } from "@scality/core-ui/dist/components/tablev2/TableUtils";
5
5
  import { Button, Input } from "@scality/core-ui/dist/next";
6
- import { array, object, string } from "joi";
6
+ import joi from "joi";
7
7
  import { useCallback } from "react";
8
8
  import { FormProvider, useForm } from "react-hook-form";
9
9
  import { useNavigate, useParams } from "react-router-dom";
10
10
  import { useGetBucketNotification, useSetBucketNotification } from "../../../hooks/index.js";
11
11
  import { EventsSection } from "./EventsSection.js";
12
- const schema = object({
13
- ruleName: string().required().messages({
12
+ const schema = joi.object({
13
+ ruleName: joi.string().required().messages({
14
14
  "string.empty": "This field is required"
15
15
  }),
16
- queueArn: string().required().pattern(/^arn:aws:sqs:[a-z0-9-]+:\d+:.+$/).messages({
16
+ queueArn: joi.string().required().pattern(/^arn:aws:sqs:[a-z0-9-]+:\d+:.+$/).messages({
17
17
  "string.empty": "This field is required",
18
18
  "string.pattern.base": "Must be a valid ARN (e.g., arn:aws:sqs:region:account-id:queue-name)"
19
19
  }),
20
- events: array().min(1).required().messages({
20
+ events: joi.array().min(1).required().messages({
21
21
  "array.min": "At least one event must be selected"
22
22
  }),
23
- prefix: string().allow("").optional(),
24
- suffix: string().allow("").optional()
23
+ prefix: joi.string().allow("").optional(),
24
+ suffix: joi.string().allow("").optional()
25
25
  });
26
26
  function BucketNotificationCreatePage() {
27
27
  const { bucketName } = useParams();
@@ -32,7 +32,7 @@ function BucketNotificationCreatePage() {
32
32
  });
33
33
  const existingRuleNames = existingNotificationData?.QueueConfigurations?.map((config)=>config.Id) || [];
34
34
  const dynamicSchema = schema.keys({
35
- ruleName: string().required().invalid(...existingRuleNames).messages({
35
+ ruleName: joi.string().required().invalid(...existingRuleNames).messages({
36
36
  "string.empty": "This field is required",
37
37
  "any.invalid": "A rule with this name already exists"
38
38
  })
@@ -1,13 +1,20 @@
1
1
  export { DeleteBucketButton } from "./buckets/DeleteBucketButton";
2
2
  export { BucketList } from "./buckets/BucketList";
3
- export { BucketOverview } from "./buckets/BucketOverview";
3
+ export { BucketOverview, BucketOverviewSection, BucketOverviewField, } from "./buckets/BucketOverview";
4
4
  export { BucketPage } from "./buckets/BucketPage";
5
5
  export { BucketPolicyPage } from "./buckets/BucketPolicyPage";
6
+ export { BucketLifecycleFormPage } from "./buckets/BucketLifecycleFormPage";
7
+ export { BucketReplicationFormPage } from "./buckets/BucketReplicationFormPage";
6
8
  export { BucketNotificationCreatePage } from "./buckets/notifications/BucketNotificationCreatePage";
9
+ export { EmptyBucketButton } from "./buckets/EmptyBucketButton";
10
+ export { BucketCreate, baseBucketCreateSchema, bucketNameValidationSchema, bucketErrorMessage, type BucketCreateFormData, } from "./buckets/BucketCreate";
7
11
  export { UploadButton } from "./objects/UploadButton";
8
12
  export { CreateFolderButton } from "./objects/CreateFolderButton";
9
13
  export { ObjectDetails } from "./objects/ObjectDetails";
10
14
  export { ObjectList } from "./objects/ObjectList";
11
15
  export { ObjectPage } from "./objects/ObjectPage";
16
+ export { ObjectLockSettings } from "./objects/ObjectLock/ObjectLockSettings";
17
+ export { EditRetentionButton } from "./objects/ObjectLock/EditRetentionButton";
12
18
  export { MetadataSearch } from "./search/MetadataSearch";
19
+ export { ArrayFieldActions } from "./ui/ArrayFieldActions";
13
20
  export { DataBrowserProvider, useDataBrowserContext, useDataBrowserTheme, } from "./providers/DataBrowserProvider";
@@ -1,14 +1,21 @@
1
1
  import { DeleteBucketButton } from "./buckets/DeleteBucketButton.js";
2
2
  import { BucketList } from "./buckets/BucketList.js";
3
- import { BucketOverview } from "./buckets/BucketOverview.js";
3
+ import { BucketOverview, BucketOverviewField, BucketOverviewSection } from "./buckets/BucketOverview.js";
4
4
  import { BucketPage } from "./buckets/BucketPage.js";
5
5
  import { BucketPolicyPage } from "./buckets/BucketPolicyPage.js";
6
+ import { BucketLifecycleFormPage } from "./buckets/BucketLifecycleFormPage.js";
7
+ import { BucketReplicationFormPage } from "./buckets/BucketReplicationFormPage.js";
6
8
  import { BucketNotificationCreatePage } from "./buckets/notifications/BucketNotificationCreatePage.js";
9
+ import { EmptyBucketButton } from "./buckets/EmptyBucketButton.js";
10
+ import { BucketCreate, baseBucketCreateSchema, bucketErrorMessage, bucketNameValidationSchema } from "./buckets/BucketCreate.js";
7
11
  import { UploadButton } from "./objects/UploadButton.js";
8
12
  import { CreateFolderButton } from "./objects/CreateFolderButton.js";
9
13
  import { ObjectDetails } from "./objects/ObjectDetails/index.js";
10
14
  import { ObjectList } from "./objects/ObjectList.js";
11
15
  import { ObjectPage } from "./objects/ObjectPage.js";
16
+ import { ObjectLockSettings } from "./objects/ObjectLock/ObjectLockSettings.js";
17
+ import { EditRetentionButton } from "./objects/ObjectLock/EditRetentionButton.js";
12
18
  import { MetadataSearch } from "./search/MetadataSearch.js";
19
+ import { ArrayFieldActions } from "./ui/ArrayFieldActions.js";
13
20
  import { DataBrowserProvider, useDataBrowserContext, useDataBrowserTheme } from "./providers/DataBrowserProvider.js";
14
- export { BucketList, BucketNotificationCreatePage, BucketOverview, BucketPage, BucketPolicyPage, CreateFolderButton, DataBrowserProvider, DeleteBucketButton, MetadataSearch, ObjectDetails, ObjectList, ObjectPage, UploadButton, useDataBrowserContext, useDataBrowserTheme };
21
+ export { ArrayFieldActions, BucketCreate, BucketLifecycleFormPage, BucketList, BucketNotificationCreatePage, BucketOverview, BucketOverviewField, BucketOverviewSection, BucketPage, BucketPolicyPage, BucketReplicationFormPage, CreateFolderButton, DataBrowserProvider, DeleteBucketButton, EditRetentionButton, EmptyBucketButton, MetadataSearch, ObjectDetails, ObjectList, ObjectLockSettings, ObjectPage, UploadButton, baseBucketCreateSchema, bucketErrorMessage, bucketNameValidationSchema, useDataBrowserContext, useDataBrowserTheme };
@@ -0,0 +1,4 @@
1
+ export declare const EditRetentionButton: ({ bucketName }: {
2
+ bucketName: string;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export default EditRetentionButton;
@@ -0,0 +1,32 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useISVBucketStatus } from "../../../hooks/index.js";
3
+ import { Icon } from "@scality/core-ui";
4
+ import { Button } from "@scality/core-ui/dist/next";
5
+ import { useNavigate } from "react-router-dom";
6
+ const EditRetentionButton = ({ bucketName })=>{
7
+ const navigate = useNavigate();
8
+ const { isVeeamBucket, isCommvaultBucket, isISVManaged, isLoading } = useISVBucketStatus(bucketName);
9
+ const tooltipOverlay = isCommvaultBucket ? "Edition is disabled as it is managed by Commvault." : isVeeamBucket ? "Edition is disabled as it is managed by Veeam." : void 0;
10
+ return /*#__PURE__*/ jsx(Button, {
11
+ id: "edit-retention-btn",
12
+ variant: "outline",
13
+ label: "Edit",
14
+ "aria-label": "Edit default retention",
15
+ icon: /*#__PURE__*/ jsx(Icon, {
16
+ name: "Pencil"
17
+ }),
18
+ type: "button",
19
+ onClick: ()=>{
20
+ navigate(`/buckets/${bucketName}/objects/object-lock-settings`);
21
+ },
22
+ disabled: isISVManaged,
23
+ ...tooltipOverlay && {
24
+ tooltip: {
25
+ overlay: tooltipOverlay
26
+ }
27
+ },
28
+ isLoading: isLoading
29
+ });
30
+ };
31
+ const ObjectLock_EditRetentionButton = EditRetentionButton;
32
+ export { EditRetentionButton, ObjectLock_EditRetentionButton as default };
@@ -0,0 +1,3 @@
1
+ export default function ObjectLockRetentionSettings({ isEditRetentionSettings, }: {
2
+ isEditRetentionSettings?: boolean;
3
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,211 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Checkbox, FormGroup, FormSection, Stack, Text } from "@scality/core-ui";
3
+ import { convertRemToPixels } from "@scality/core-ui/dist/components/tablev2/TableUtils";
4
+ import { Controller, useFormContext } from "react-hook-form";
5
+ import { Input, Select } from "@scality/core-ui/dist/next";
6
+ function ObjectLockRetentionSettings({ isEditRetentionSettings = false }) {
7
+ const { control, register, watch, formState: { errors }, setValue } = useFormContext();
8
+ const isDefaultRetentionEnabled = watch("isDefaultRetentionEnabled");
9
+ const isObjectLockEnabled = watch("isObjectLockEnabled");
10
+ const matchVersioning = (checked)=>{
11
+ if (checked) setValue("isVersioning", true);
12
+ };
13
+ return /*#__PURE__*/ jsxs(FormSection, {
14
+ title: isEditRetentionSettings ? void 0 : {
15
+ name: "Object-lock"
16
+ },
17
+ forceLabelWidth: convertRemToPixels(17.5),
18
+ children: [
19
+ /*#__PURE__*/ jsx(FormGroup, {
20
+ id: "isObjectLockEnabled",
21
+ label: "Object-lock",
22
+ content: /*#__PURE__*/ jsx(Checkbox, {
23
+ id: "isObjectLockEnabled",
24
+ label: isObjectLockEnabled ? "Enabled" : "Disabled",
25
+ disabled: isEditRetentionSettings && isObjectLockEnabled,
26
+ ...register("isObjectLockEnabled", {
27
+ onChange (e) {
28
+ matchVersioning(e.target.checked);
29
+ }
30
+ })
31
+ }),
32
+ labelHelpTooltip: /*#__PURE__*/ jsxs("ul", {
33
+ children: [
34
+ /*#__PURE__*/ jsx("li", {
35
+ children: "Permanently allows objects in this bucket to be locked"
36
+ }),
37
+ /*#__PURE__*/ jsx("li", {
38
+ children: "Object-lock option cannot be removed after bucket creation, but you will be able to disable the retention itself on edition."
39
+ }),
40
+ /*#__PURE__*/ jsx("li", {
41
+ children: "Once the bucket is created, you might be blocked from deleting the objects and the bucket."
42
+ }),
43
+ /*#__PURE__*/ jsx("li", {
44
+ children: "Enabling Object-lock automatically activates Versioning for the bucket, and you won’t be able to suspend Versioning."
45
+ })
46
+ ]
47
+ }),
48
+ helpErrorPosition: "bottom",
49
+ disabled: isEditRetentionSettings
50
+ }),
51
+ isObjectLockEnabled && /*#__PURE__*/ jsxs(Fragment, {
52
+ children: [
53
+ /*#__PURE__*/ jsx(FormGroup, {
54
+ id: "isDefaultRetentionEnabled",
55
+ label: "Default Retention",
56
+ helpErrorPosition: "bottom",
57
+ labelHelpTooltip: isEditRetentionSettings ? /*#__PURE__*/ jsxs("ul", {
58
+ children: [
59
+ /*#__PURE__*/ jsx("li", {
60
+ children: "These settings apply only to new objects placed into the bucket without any specific object-lock parameters."
61
+ }),
62
+ /*#__PURE__*/ jsx("li", {
63
+ children: "Automatically protect objects put into this bucket from being deleted or overwritten."
64
+ }),
65
+ /*#__PURE__*/ jsx("li", {
66
+ children: "If objects are uploaded into the bucket with their own Retention settings, these will override the Default Retention setting placed on the bucket."
67
+ })
68
+ ]
69
+ }) : /*#__PURE__*/ jsxs("ul", {
70
+ children: [
71
+ /*#__PURE__*/ jsx("li", {
72
+ children: "Automatically protect objects put into this bucket from being deleted or overwritten."
73
+ }),
74
+ /*#__PURE__*/ jsx("li", {
75
+ children: "These settings apply only to new objects placed into the bucket without any specific object-lock parameters."
76
+ }),
77
+ /*#__PURE__*/ jsx("li", {
78
+ children: "You can activate this option after the bucket creation."
79
+ }),
80
+ /*#__PURE__*/ jsx("li", {
81
+ children: "If objects are uploaded into the bucket with their own Retention settings, these will override the Default Retention setting placed on the bucket."
82
+ })
83
+ ]
84
+ }),
85
+ content: /*#__PURE__*/ jsx(Checkbox, {
86
+ id: "isDefaultRetentionEnabled",
87
+ label: isDefaultRetentionEnabled ? "Active" : "Inactive",
88
+ ...register("isDefaultRetentionEnabled")
89
+ })
90
+ }),
91
+ /*#__PURE__*/ jsx(FormGroup, {
92
+ id: "objectlockMode",
93
+ label: "Retention mode",
94
+ direction: "vertical",
95
+ disabled: !isDefaultRetentionEnabled,
96
+ helpErrorPosition: "bottom",
97
+ content: /*#__PURE__*/ jsx("div", {
98
+ style: {
99
+ opacity: isDefaultRetentionEnabled ? 1 : 0.5
100
+ },
101
+ children: /*#__PURE__*/ jsxs(Stack, {
102
+ direction: "vertical",
103
+ children: [
104
+ /*#__PURE__*/ jsxs(Stack, {
105
+ direction: "vertical",
106
+ children: [
107
+ /*#__PURE__*/ jsxs(Stack, {
108
+ children: [
109
+ /*#__PURE__*/ jsx("input", {
110
+ id: "locktype-governance",
111
+ type: "radio",
112
+ value: "GOVERNANCE",
113
+ disabled: !isDefaultRetentionEnabled,
114
+ ...register("retentionMode")
115
+ }),
116
+ /*#__PURE__*/ jsx("label", {
117
+ htmlFor: "locktype-governance",
118
+ children: "Governance"
119
+ })
120
+ ]
121
+ }),
122
+ /*#__PURE__*/ jsx(Text, {
123
+ color: "textSecondary",
124
+ isEmphazed: true,
125
+ variant: "Smaller",
126
+ children: "A user with a specific IAM permissions can overwrite/delete protected object versions during the retention period."
127
+ })
128
+ ]
129
+ }),
130
+ /*#__PURE__*/ jsxs(Stack, {
131
+ children: [
132
+ /*#__PURE__*/ jsx("input", {
133
+ id: "locktype-compliance",
134
+ type: "radio",
135
+ value: "COMPLIANCE",
136
+ disabled: !isDefaultRetentionEnabled,
137
+ ...register("retentionMode")
138
+ }),
139
+ /*#__PURE__*/ jsx("label", {
140
+ htmlFor: "locktype-compliance",
141
+ children: "Compliance"
142
+ })
143
+ ]
144
+ }),
145
+ /*#__PURE__*/ jsx(Text, {
146
+ color: "textSecondary",
147
+ isEmphazed: true,
148
+ variant: "Smaller",
149
+ children: "No one can overwrite protected object versions during the retention period."
150
+ })
151
+ ]
152
+ })
153
+ })
154
+ }),
155
+ /*#__PURE__*/ jsx(FormGroup, {
156
+ id: "retentionPeriod",
157
+ label: "Retention period",
158
+ direction: "horizontal",
159
+ helpErrorPosition: "bottom",
160
+ help: "Must be a positive whole number.",
161
+ error: errors.retentionPeriod?.message,
162
+ disabled: !isDefaultRetentionEnabled,
163
+ content: /*#__PURE__*/ jsxs(Stack, {
164
+ direction: "horizontal",
165
+ children: [
166
+ /*#__PURE__*/ jsx(Controller, {
167
+ control: control,
168
+ name: "retentionPeriod",
169
+ render: ({ field: { onChange, value: retentionPeriod } })=>/*#__PURE__*/ jsx(Input, {
170
+ id: "retentionPeriod",
171
+ name: "retentionPeriod",
172
+ value: retentionPeriod,
173
+ onChange: (e)=>onChange(e.target.valueAsNumber),
174
+ type: "number",
175
+ step: "1",
176
+ min: "1",
177
+ size: "2/3"
178
+ })
179
+ }),
180
+ /*#__PURE__*/ jsx(Controller, {
181
+ control: control,
182
+ name: "retentionPeriodFrequencyChoice",
183
+ defaultValue: "DAYS",
184
+ render: ({ field: { onChange, value: retentionPeriodFrequencyChoice } })=>/*#__PURE__*/ jsxs(Select, {
185
+ id: "retentionPeriodFrequencyChoice",
186
+ onChange: onChange,
187
+ placeholder: "retentionPeriodFrequencyChoice",
188
+ value: retentionPeriodFrequencyChoice,
189
+ disabled: !isDefaultRetentionEnabled,
190
+ size: "1/3",
191
+ children: [
192
+ /*#__PURE__*/ jsx(Select.Option, {
193
+ value: "DAYS",
194
+ children: "Days"
195
+ }),
196
+ /*#__PURE__*/ jsx(Select.Option, {
197
+ value: "YEARS",
198
+ children: "Years"
199
+ })
200
+ ]
201
+ })
202
+ })
203
+ ]
204
+ })
205
+ })
206
+ ]
207
+ })
208
+ ]
209
+ });
210
+ }
211
+ export { ObjectLockRetentionSettings as default };
@@ -0,0 +1,9 @@
1
+ import Joi from "joi";
2
+ export declare const objectLockRetentionSettingsValidationRules: {
3
+ isObjectLockEnabled: Joi.BooleanSchema<boolean>;
4
+ isDefaultRetentionEnabled: Joi.BooleanSchema<boolean>;
5
+ retentionMode: Joi.AlternativesSchema<any>;
6
+ retentionPeriod: Joi.AlternativesSchema<any>;
7
+ retentionPeriodFrequencyChoice: Joi.AlternativesSchema<any>;
8
+ };
9
+ export declare function ObjectLockSettings(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,158 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import { useNavigate, useParams } from "react-router-dom";
4
+ import { FormProvider, useForm } from "react-hook-form";
5
+ import { joiResolver } from "@hookform/resolvers/joi";
6
+ import joi from "joi";
7
+ import { Form, Icon, Loader, Stack, Text, useToast } from "@scality/core-ui";
8
+ import { Button } from "@scality/core-ui/dist/next";
9
+ import { useGetBucketObjectLockConfiguration, useSetBucketObjectLockConfiguration } from "../../../hooks/index.js";
10
+ import ObjectLockRetentionSettings from "./ObjectLockRetentionSettings.js";
11
+ const objectLockRetentionSettingsValidationRules = {
12
+ isObjectLockEnabled: joi.boolean(),
13
+ isDefaultRetentionEnabled: joi.boolean().default(false),
14
+ retentionMode: joi.when("isDefaultRetentionEnabled", {
15
+ is: joi.equal(true),
16
+ then: joi.string().valid("GOVERNANCE", "COMPLIANCE").required(),
17
+ otherwise: joi.any()
18
+ }),
19
+ retentionPeriod: joi.when("isDefaultRetentionEnabled", {
20
+ is: joi.equal(true),
21
+ then: joi.number().integer().min(1).required(),
22
+ otherwise: joi.any()
23
+ }),
24
+ retentionPeriodFrequencyChoice: joi.when("isDefaultRetentionEnabled", {
25
+ is: joi.equal(true),
26
+ then: joi.string().valid("DAYS", "YEARS").required(),
27
+ otherwise: joi.any()
28
+ })
29
+ };
30
+ const schema = joi.object(objectLockRetentionSettingsValidationRules);
31
+ function ObjectLockSettings() {
32
+ const { bucketName } = useParams();
33
+ const navigate = useNavigate();
34
+ const { showToast } = useToast();
35
+ const { data: objectLockData, status: objectLockStatus } = useGetBucketObjectLockConfiguration({
36
+ Bucket: bucketName
37
+ });
38
+ const setBucketObjectLockMutation = useSetBucketObjectLockConfiguration();
39
+ const isObjectLockEnabled = objectLockData?.ObjectLockConfiguration?.ObjectLockEnabled === "Enabled";
40
+ const defaultRetention = objectLockData?.ObjectLockConfiguration?.Rule?.DefaultRetention;
41
+ const useFormMethods = useForm({
42
+ mode: "all",
43
+ resolver: joiResolver(schema),
44
+ defaultValues: {
45
+ isObjectLockEnabled: isObjectLockEnabled,
46
+ isDefaultRetentionEnabled: !!defaultRetention,
47
+ retentionMode: defaultRetention?.Mode || "GOVERNANCE",
48
+ retentionPeriod: defaultRetention?.Days || defaultRetention?.Years || 1,
49
+ retentionPeriodFrequencyChoice: defaultRetention ? defaultRetention?.Days ? "DAYS" : "YEARS" : "DAYS"
50
+ }
51
+ });
52
+ const { watch, setValue, handleSubmit, formState: { isValid } } = useFormMethods;
53
+ const isObjectLockEnabledValue = watch("isObjectLockEnabled");
54
+ const isFormInitialized = useRef(false);
55
+ useEffect(()=>{
56
+ if ("success" === objectLockStatus && objectLockData && !isFormInitialized.current) {
57
+ const isEnabled = objectLockData.ObjectLockConfiguration?.ObjectLockEnabled === "Enabled";
58
+ const defaultRet = objectLockData.ObjectLockConfiguration?.Rule?.DefaultRetention;
59
+ setValue("isObjectLockEnabled", isEnabled);
60
+ setValue("isDefaultRetentionEnabled", !!defaultRet);
61
+ if (defaultRet) {
62
+ setValue("retentionMode", defaultRet.Mode);
63
+ setValue("retentionPeriod", defaultRet.Days || defaultRet.Years || 1);
64
+ setValue("retentionPeriodFrequencyChoice", defaultRet.Days ? "DAYS" : "YEARS");
65
+ }
66
+ isFormInitialized.current = true;
67
+ }
68
+ }, [
69
+ objectLockData,
70
+ objectLockStatus,
71
+ setValue
72
+ ]);
73
+ const handleCancel = ()=>{
74
+ navigate(`/buckets/${bucketName}`);
75
+ };
76
+ const onSubmit = (data)=>{
77
+ setBucketObjectLockMutation.mutate({
78
+ Bucket: bucketName,
79
+ ObjectLockConfiguration: data.isObjectLockEnabled ? {
80
+ ObjectLockEnabled: "Enabled",
81
+ ...data.isDefaultRetentionEnabled && {
82
+ Rule: {
83
+ DefaultRetention: {
84
+ Mode: data.retentionMode,
85
+ ..."DAYS" === data.retentionPeriodFrequencyChoice ? {
86
+ Days: data.retentionPeriod
87
+ } : {
88
+ Years: data.retentionPeriod
89
+ }
90
+ }
91
+ }
92
+ }
93
+ } : void 0
94
+ }, {
95
+ onSuccess: ()=>{
96
+ showToast({
97
+ open: true,
98
+ message: "Object Lock settings saved successfully",
99
+ status: "success"
100
+ });
101
+ navigate(`/buckets/${bucketName}`);
102
+ },
103
+ onError: (error)=>{
104
+ const errorMessage = error instanceof Error ? error.message : "Failed to save Object Lock settings";
105
+ showToast({
106
+ open: true,
107
+ message: errorMessage,
108
+ status: "error"
109
+ });
110
+ }
111
+ });
112
+ };
113
+ if ("pending" === objectLockStatus) return /*#__PURE__*/ jsx(Loader, {
114
+ centered: true,
115
+ children: /*#__PURE__*/ jsx(Text, {
116
+ children: "Loading retention settings..."
117
+ })
118
+ });
119
+ return /*#__PURE__*/ jsx(FormProvider, {
120
+ ...useFormMethods,
121
+ children: /*#__PURE__*/ jsx(Form, {
122
+ onSubmit: handleSubmit(onSubmit),
123
+ requireMode: "partial",
124
+ layout: {
125
+ kind: "page",
126
+ title: "Object-lock settings"
127
+ },
128
+ rightActions: /*#__PURE__*/ jsxs(Stack, {
129
+ gap: "r16",
130
+ children: [
131
+ /*#__PURE__*/ jsx(Button, {
132
+ id: "cancel-btn",
133
+ variant: "outline",
134
+ onClick: handleCancel,
135
+ type: "button",
136
+ label: "Cancel",
137
+ disabled: setBucketObjectLockMutation.isPending
138
+ }),
139
+ /*#__PURE__*/ jsx(Button, {
140
+ disabled: !isValid || !isObjectLockEnabledValue || setBucketObjectLockMutation.isPending,
141
+ id: "edit-retention-setting-btn",
142
+ type: "submit",
143
+ variant: "primary",
144
+ label: "Save",
145
+ icon: /*#__PURE__*/ jsx(Icon, {
146
+ name: "Save"
147
+ }),
148
+ isLoading: setBucketObjectLockMutation.isPending
149
+ })
150
+ ]
151
+ }),
152
+ children: /*#__PURE__*/ jsx(ObjectLockRetentionSettings, {
153
+ isEditRetentionSettings: true
154
+ })
155
+ })
156
+ });
157
+ }
158
+ export { ObjectLockSettings, objectLockRetentionSettingsValidationRules };