@scality/data-browser-library 1.1.4 → 1.1.6
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.
- package/dist/components/__tests__/CreateFolderButton.test.js +67 -0
- package/dist/components/__tests__/DeleteObjectButton.test.js +249 -26
- package/dist/components/__tests__/ObjectList.test.js +65 -22
- package/dist/components/__tests__/UploadButton.test.js +80 -0
- package/dist/components/buckets/BucketList.js +1 -2
- package/dist/components/objects/CreateFolderButton.js +2 -1
- package/dist/components/objects/DeleteObjectButton.js +89 -43
- package/dist/components/objects/ObjectList.js +21 -0
- package/dist/components/objects/UploadButton.js +2 -1
- package/dist/components/ui/DeleteObjectModalContent.d.ts +4 -1
- package/dist/components/ui/DeleteObjectModalContent.js +57 -18
- package/dist/hooks/__tests__/useDeleteFolder.test.d.ts +1 -0
- package/dist/hooks/__tests__/useDeleteFolder.test.js +203 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useDeleteFolder.d.ts +6 -0
- package/dist/hooks/useDeleteFolder.js +40 -0
- package/package.json +1 -1
|
@@ -3,11 +3,31 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
|
3
3
|
import user_event from "@testing-library/user-event";
|
|
4
4
|
import { createTestWrapper } from "../../test/testUtils.js";
|
|
5
5
|
import { UploadButton } from "../objects/UploadButton.js";
|
|
6
|
+
const mockMutateAsync = jest.fn();
|
|
7
|
+
jest.mock('../../hooks', ()=>({
|
|
8
|
+
...jest.requireActual('../../hooks'),
|
|
9
|
+
useUploadObjects: ()=>({
|
|
10
|
+
mutate: jest.fn(),
|
|
11
|
+
mutateAsync: mockMutateAsync,
|
|
12
|
+
reset: jest.fn(),
|
|
13
|
+
isPending: false,
|
|
14
|
+
isIdle: true,
|
|
15
|
+
isError: false,
|
|
16
|
+
isSuccess: false,
|
|
17
|
+
status: 'idle',
|
|
18
|
+
data: void 0,
|
|
19
|
+
error: null
|
|
20
|
+
})
|
|
21
|
+
}));
|
|
6
22
|
describe('UploadButton - Core Functionality', ()=>{
|
|
7
23
|
const defaultProps = {
|
|
8
24
|
bucket: 'test-bucket',
|
|
9
25
|
prefix: 'test-prefix'
|
|
10
26
|
};
|
|
27
|
+
beforeEach(()=>{
|
|
28
|
+
mockMutateAsync.mockClear();
|
|
29
|
+
mockMutateAsync.mockResolvedValue({});
|
|
30
|
+
});
|
|
11
31
|
const renderUploadButton = (props = {})=>{
|
|
12
32
|
const Wrapper = createTestWrapper();
|
|
13
33
|
return render(/*#__PURE__*/ jsx(Wrapper, {
|
|
@@ -141,4 +161,64 @@ describe('UploadButton - Core Functionality', ()=>{
|
|
|
141
161
|
expect(screen.getByText('Drag and drop files and folders here')).toBeInTheDocument();
|
|
142
162
|
});
|
|
143
163
|
});
|
|
164
|
+
const addFileAndUpload = async ()=>{
|
|
165
|
+
const fileInput = screen.getByRole('presentation').querySelector('input[type="file"]');
|
|
166
|
+
const testFile = new File([
|
|
167
|
+
'test content'
|
|
168
|
+
], 'test.txt', {
|
|
169
|
+
type: 'text/plain'
|
|
170
|
+
});
|
|
171
|
+
await user_event.upload(fileInput, testFile);
|
|
172
|
+
await waitFor(()=>expect(screen.getByText('test.txt')).toBeInTheDocument());
|
|
173
|
+
const uploadButtons = screen.getAllByRole('button', {
|
|
174
|
+
name: 'Upload'
|
|
175
|
+
});
|
|
176
|
+
const modalUploadButton = uploadButtons.find((button)=>!button.querySelector('svg'));
|
|
177
|
+
fireEvent.click(modalUploadButton);
|
|
178
|
+
};
|
|
179
|
+
it('constructs correct key when prefix has trailing slash', async ()=>{
|
|
180
|
+
renderUploadButton({
|
|
181
|
+
prefix: 'documents/'
|
|
182
|
+
});
|
|
183
|
+
fireEvent.click(screen.getByRole('button', {
|
|
184
|
+
name: /upload/i
|
|
185
|
+
}));
|
|
186
|
+
await waitFor(()=>expect(screen.getByText('Upload Files')).toBeInTheDocument());
|
|
187
|
+
await addFileAndUpload();
|
|
188
|
+
await waitFor(()=>{
|
|
189
|
+
expect(mockMutateAsync).toHaveBeenCalledWith(expect.objectContaining({
|
|
190
|
+
Key: 'documents/test.txt'
|
|
191
|
+
}));
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
it('constructs correct key when prefix has no trailing slash', async ()=>{
|
|
195
|
+
renderUploadButton({
|
|
196
|
+
prefix: 'documents'
|
|
197
|
+
});
|
|
198
|
+
fireEvent.click(screen.getByRole('button', {
|
|
199
|
+
name: /upload/i
|
|
200
|
+
}));
|
|
201
|
+
await waitFor(()=>expect(screen.getByText('Upload Files')).toBeInTheDocument());
|
|
202
|
+
await addFileAndUpload();
|
|
203
|
+
await waitFor(()=>{
|
|
204
|
+
expect(mockMutateAsync).toHaveBeenCalledWith(expect.objectContaining({
|
|
205
|
+
Key: 'documents/test.txt'
|
|
206
|
+
}));
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
it('constructs correct key when prefix is empty', async ()=>{
|
|
210
|
+
renderUploadButton({
|
|
211
|
+
prefix: ''
|
|
212
|
+
});
|
|
213
|
+
fireEvent.click(screen.getByRole('button', {
|
|
214
|
+
name: /upload/i
|
|
215
|
+
}));
|
|
216
|
+
await waitFor(()=>expect(screen.getByText('Upload Files')).toBeInTheDocument());
|
|
217
|
+
await addFileAndUpload();
|
|
218
|
+
await waitFor(()=>{
|
|
219
|
+
expect(mockMutateAsync).toHaveBeenCalledWith(expect.objectContaining({
|
|
220
|
+
Key: 'test.txt'
|
|
221
|
+
}));
|
|
222
|
+
});
|
|
223
|
+
});
|
|
144
224
|
});
|
|
@@ -215,8 +215,7 @@ function BucketList({ buckets, bucketStatus, selectedBucketName, onBucketSelect,
|
|
|
215
215
|
rowHeight: "h40",
|
|
216
216
|
selectedId: selectedId,
|
|
217
217
|
onRowSelected: handleRowSelected,
|
|
218
|
-
separationLineVariant: "backgroundLevel1"
|
|
219
|
-
autoScrollToSelected: true
|
|
218
|
+
separationLineVariant: "backgroundLevel1"
|
|
220
219
|
})
|
|
221
220
|
]
|
|
222
221
|
});
|
|
@@ -21,7 +21,8 @@ const CreateFolderButton = ({ bucket, prefix = '', label = 'Folder', variant = '
|
|
|
21
21
|
}, []);
|
|
22
22
|
const handleSave = useCallback(()=>{
|
|
23
23
|
if (!folderName.trim()) return;
|
|
24
|
-
const
|
|
24
|
+
const normalizedPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
|
|
25
|
+
const folderKey = normalizedPrefix ? `${normalizedPrefix}/${folderName}/` : `${folderName}/`;
|
|
25
26
|
createFolderMutation.mutate({
|
|
26
27
|
Bucket: bucket,
|
|
27
28
|
Key: folderKey,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Banner, Icon, Modal, PrettyBytes, Stack, Text, Wrap, spacing, useToast } from "@scality/core-ui";
|
|
2
|
+
import { Banner, Checkbox, Icon, Modal, PrettyBytes, Stack, Text, Wrap, spacing, useToast } from "@scality/core-ui";
|
|
3
3
|
import { Box, Button } from "@scality/core-ui/dist/next";
|
|
4
4
|
import { useCallback, useEffect, useState } from "react";
|
|
5
5
|
import { useDeleteObjects, useGetBucketVersioning } from "../../hooks/index.js";
|
|
6
|
+
import { useDeleteFolder } from "../../hooks/useDeleteFolder.js";
|
|
6
7
|
import { getDeletionMessages } from "../../utils/deletion/index.js";
|
|
8
|
+
import { useInvalidateQueries } from "../providers/DataBrowserProvider.js";
|
|
7
9
|
import { DeleteObjectModalContent } from "../ui/DeleteObjectModalContent.js";
|
|
8
10
|
const Title = ({ objects, isCurrentSelectionPermanentlyDeleted })=>{
|
|
9
11
|
const foldersSize = objects.filter((object)=>'folder' === object.type).length;
|
|
@@ -43,14 +45,18 @@ const Title = ({ objects, isCurrentSelectionPermanentlyDeleted })=>{
|
|
|
43
45
|
const DeleteObjectButton = ({ objects, bucketName, onDeleteSuccess })=>{
|
|
44
46
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
45
47
|
const [selectedObjects, setSelectedObjects] = useState(objects);
|
|
48
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
46
49
|
const { data: versioningData } = useGetBucketVersioning({
|
|
47
50
|
Bucket: bucketName
|
|
48
51
|
});
|
|
49
|
-
const {
|
|
52
|
+
const { mutateAsync: deleteObjects } = useDeleteObjects();
|
|
53
|
+
const { mutateAsync: deleteFolder } = useDeleteFolder();
|
|
54
|
+
const invalidateQueries = useInvalidateQueries();
|
|
50
55
|
const { showToast } = useToast();
|
|
51
56
|
const isVersioningEnabled = versioningData?.Status === 'Enabled';
|
|
52
57
|
const isCurrentSelectionPermanentlyDeleted = !isVersioningEnabled || selectedObjects.some((object)=>!!object.VersionId);
|
|
53
|
-
const
|
|
58
|
+
const [isCheckboxToggled, setIsCheckboxToggled] = useState(false);
|
|
59
|
+
const { info: notificationText, checkboxRequired } = getDeletionMessages({
|
|
54
60
|
numberOfObjects: selectedObjects.length,
|
|
55
61
|
selectedObjectsAreSpecificVersions: isCurrentSelectionPermanentlyDeleted,
|
|
56
62
|
isBucketVersioned: isVersioningEnabled
|
|
@@ -61,51 +67,82 @@ const DeleteObjectButton = ({ objects, bucketName, onDeleteSuccess })=>{
|
|
|
61
67
|
const cancel = useCallback(()=>{
|
|
62
68
|
setIsModalOpen(false);
|
|
63
69
|
setSelectedObjects(objects);
|
|
70
|
+
setIsCheckboxToggled(false);
|
|
64
71
|
}, [
|
|
65
72
|
objects
|
|
66
73
|
]);
|
|
67
|
-
const deleteSelectedFiles = useCallback(()=>{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
}, {
|
|
87
|
-
onSuccess: ()=>{
|
|
88
|
-
showToast({
|
|
89
|
-
open: true,
|
|
90
|
-
message: 'Objects deleted successfully',
|
|
91
|
-
status: 'success'
|
|
92
|
-
});
|
|
93
|
-
setIsModalOpen(false);
|
|
94
|
-
onDeleteSuccess?.();
|
|
95
|
-
},
|
|
96
|
-
onError: (error)=>{
|
|
97
|
-
showToast({
|
|
98
|
-
open: true,
|
|
99
|
-
message: error instanceof Error ? error.message : 'Objects deleted failed',
|
|
100
|
-
status: 'error'
|
|
74
|
+
const deleteSelectedFiles = useCallback(async ()=>{
|
|
75
|
+
setIsDeleting(true);
|
|
76
|
+
try {
|
|
77
|
+
const folderItems = selectedObjects.filter((object)=>'folder' === object.type && object.Key);
|
|
78
|
+
const nonFolderItems = selectedObjects.filter((object)=>'folder' !== object.type && object.Key);
|
|
79
|
+
if (nonFolderItems.length > 0) {
|
|
80
|
+
const result = await deleteObjects({
|
|
81
|
+
Bucket: bucketName,
|
|
82
|
+
Delete: {
|
|
83
|
+
Objects: nonFolderItems.map((object)=>{
|
|
84
|
+
const deleteItem = {
|
|
85
|
+
Key: object.Key
|
|
86
|
+
};
|
|
87
|
+
if (object.VersionId && 'string' == typeof object.VersionId) deleteItem.VersionId = object.VersionId;
|
|
88
|
+
return deleteItem;
|
|
89
|
+
})
|
|
90
|
+
}
|
|
101
91
|
});
|
|
102
|
-
|
|
92
|
+
if (result.Errors && result.Errors.length > 0) {
|
|
93
|
+
const firstError = result.Errors[0];
|
|
94
|
+
throw new Error(firstError.Message ?? 'Failed to delete objects');
|
|
95
|
+
}
|
|
103
96
|
}
|
|
104
|
-
|
|
97
|
+
for (const folder of folderItems)await deleteFolder({
|
|
98
|
+
Bucket: bucketName,
|
|
99
|
+
FolderKey: folder.Key
|
|
100
|
+
});
|
|
101
|
+
const hasFolders = folderItems.length > 0;
|
|
102
|
+
const hasObjects = nonFolderItems.length > 0;
|
|
103
|
+
const message = hasFolders && hasObjects ? 'Objects and folders deleted successfully' : hasFolders ? 'Folders deleted successfully' : 'Objects deleted successfully';
|
|
104
|
+
showToast({
|
|
105
|
+
open: true,
|
|
106
|
+
message,
|
|
107
|
+
status: 'success'
|
|
108
|
+
});
|
|
109
|
+
onDeleteSuccess?.();
|
|
110
|
+
} catch (error) {
|
|
111
|
+
showToast({
|
|
112
|
+
open: true,
|
|
113
|
+
message: error instanceof Error ? error.message : 'Failed to delete objects',
|
|
114
|
+
status: 'error'
|
|
115
|
+
});
|
|
116
|
+
} finally{
|
|
117
|
+
invalidateQueries({
|
|
118
|
+
queryKey: [
|
|
119
|
+
'ListObjects'
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
invalidateQueries({
|
|
123
|
+
queryKey: [
|
|
124
|
+
'ListObjectVersions'
|
|
125
|
+
]
|
|
126
|
+
});
|
|
127
|
+
invalidateQueries({
|
|
128
|
+
queryKey: [
|
|
129
|
+
'SearchObjects'
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
invalidateQueries({
|
|
133
|
+
queryKey: [
|
|
134
|
+
'SearchObjectsVersions'
|
|
135
|
+
]
|
|
136
|
+
});
|
|
137
|
+
setIsModalOpen(false);
|
|
138
|
+
setIsDeleting(false);
|
|
139
|
+
}
|
|
105
140
|
}, [
|
|
106
141
|
bucketName,
|
|
107
142
|
selectedObjects,
|
|
108
143
|
deleteObjects,
|
|
144
|
+
deleteFolder,
|
|
145
|
+
invalidateQueries,
|
|
109
146
|
showToast,
|
|
110
147
|
onDeleteSuccess
|
|
111
148
|
]);
|
|
@@ -142,11 +179,11 @@ const DeleteObjectButton = ({ objects, bucketName, onDeleteSuccess })=>{
|
|
|
142
179
|
label: "Cancel"
|
|
143
180
|
}),
|
|
144
181
|
/*#__PURE__*/ jsx(Button, {
|
|
145
|
-
isLoading:
|
|
182
|
+
isLoading: isDeleting,
|
|
146
183
|
id: "object-delete-delete-button",
|
|
147
184
|
variant: "danger",
|
|
148
185
|
onClick: deleteSelectedFiles,
|
|
149
|
-
disabled: 0 === selectedObjects.length,
|
|
186
|
+
disabled: 0 === selectedObjects.length || checkboxRequired && !isCheckboxToggled,
|
|
150
187
|
label: "Delete"
|
|
151
188
|
})
|
|
152
189
|
]
|
|
@@ -164,8 +201,8 @@ const DeleteObjectButton = ({ objects, bucketName, onDeleteSuccess })=>{
|
|
|
164
201
|
}),
|
|
165
202
|
/*#__PURE__*/ jsx(DeleteObjectModalContent, {
|
|
166
203
|
objects: selectedObjects,
|
|
167
|
-
onRemove: (
|
|
168
|
-
setSelectedObjects(selectedObjects.filter((object)
|
|
204
|
+
onRemove: (item)=>{
|
|
205
|
+
setSelectedObjects(selectedObjects.filter((object)=>!(object.Key === item.Key && object.VersionId === item.VersionId)));
|
|
169
206
|
}
|
|
170
207
|
}),
|
|
171
208
|
/*#__PURE__*/ jsxs(Box, {
|
|
@@ -185,6 +222,15 @@ const DeleteObjectButton = ({ objects, bucketName, onDeleteSuccess })=>{
|
|
|
185
222
|
children: /*#__PURE__*/ jsx("span", {
|
|
186
223
|
children: notificationText
|
|
187
224
|
})
|
|
225
|
+
}),
|
|
226
|
+
checkboxRequired && selectedObjects.length > 0 && /*#__PURE__*/ jsx(Box, {
|
|
227
|
+
mt: spacing.r12,
|
|
228
|
+
children: /*#__PURE__*/ jsx(Checkbox, {
|
|
229
|
+
id: "confirm-deletion-checkbox",
|
|
230
|
+
label: "Confirm the deletion",
|
|
231
|
+
checked: isCheckboxToggled,
|
|
232
|
+
onChange: ()=>setIsCheckboxToggled((prev)=>!prev)
|
|
233
|
+
})
|
|
188
234
|
})
|
|
189
235
|
]
|
|
190
236
|
})
|
|
@@ -275,7 +275,27 @@ function createOverrideMap(customItems) {
|
|
|
275
275
|
const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange, onSelectedObjectsChange })=>{
|
|
276
276
|
const { extraObjectListColumns, extraObjectListActions } = useDataBrowserUICustomization();
|
|
277
277
|
const invalidateQueries = useInvalidateQueries();
|
|
278
|
+
const versionCheck = useListObjectVersions({
|
|
279
|
+
Bucket: bucketName,
|
|
280
|
+
MaxKeys: 10
|
|
281
|
+
}, {
|
|
282
|
+
enabled: Boolean(bucketName)
|
|
283
|
+
});
|
|
284
|
+
const hasObjectVersions = useMemo(()=>{
|
|
285
|
+
const firstPage = versionCheck.data?.pages?.[0];
|
|
286
|
+
if (!firstPage) return false;
|
|
287
|
+
const versions = firstPage.Versions || [];
|
|
288
|
+
const deleteMarkers = firstPage.DeleteMarkers || [];
|
|
289
|
+
return versions.some((v)=>v.VersionId && 'null' !== v.VersionId) || deleteMarkers.length > 0;
|
|
290
|
+
}, [
|
|
291
|
+
versionCheck.data
|
|
292
|
+
]);
|
|
278
293
|
const [showVersions, setShowVersions] = useState(false);
|
|
294
|
+
useEffect(()=>{
|
|
295
|
+
if (!hasObjectVersions) setShowVersions(false);
|
|
296
|
+
}, [
|
|
297
|
+
hasObjectVersions
|
|
298
|
+
]);
|
|
279
299
|
const isMetadataSearchEnabled = useFeatures('metadatasearch');
|
|
280
300
|
const queryParams = useQueryParams();
|
|
281
301
|
const metadataSearchQuery = queryParams.get('metadatasearch');
|
|
@@ -787,6 +807,7 @@ const ObjectList = ({ bucketName, prefix, onObjectSelect, onPrefixChange, onSele
|
|
|
787
807
|
toggle: showVersions,
|
|
788
808
|
onChange: (e)=>setShowVersions(e.target.checked),
|
|
789
809
|
label: "List Versions",
|
|
810
|
+
disabled: !hasObjectVersions,
|
|
790
811
|
"aria-label": showVersions ? 'Hide object versions' : 'Show object versions',
|
|
791
812
|
"aria-pressed": showVersions
|
|
792
813
|
})
|
|
@@ -155,9 +155,10 @@ const UploadButton = ({ bucket, prefix = '', uploadOptions = {}, onUploadSuccess
|
|
|
155
155
|
const failedFiles = [];
|
|
156
156
|
for (const file of acceptedFiles)try {
|
|
157
157
|
const fileBuffer = await file.arrayBuffer();
|
|
158
|
+
const normalizedPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
|
|
158
159
|
await uploadMutation.mutateAsync({
|
|
159
160
|
Bucket: bucket,
|
|
160
|
-
Key:
|
|
161
|
+
Key: normalizedPrefix ? `${normalizedPrefix}/${file.name}` : file.name,
|
|
161
162
|
Body: new Uint8Array(fileBuffer),
|
|
162
163
|
ContentType: file.type,
|
|
163
164
|
...uploadOptions
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Objects } from '../objects/DeleteObjectButton';
|
|
2
2
|
export declare const DeleteObjectModalContent: ({ objects, onRemove, }: {
|
|
3
3
|
objects: Objects;
|
|
4
|
-
onRemove: (
|
|
4
|
+
onRemove: (item: {
|
|
5
|
+
Key: string;
|
|
6
|
+
VersionId?: string;
|
|
7
|
+
}) => void;
|
|
5
8
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,46 +1,89 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ConstrainedText, Icon, PrettyBytes, spacing } from "@scality/core-ui";
|
|
3
|
-
import { tableRowHeight } from "@scality/core-ui/dist/components/tablev2/TableUtils";
|
|
4
3
|
import { Box, Table } from "@scality/core-ui/dist/next";
|
|
5
4
|
import { useMemo } from "react";
|
|
6
5
|
import styled_components from "styled-components";
|
|
6
|
+
const NAME_COLUMN_FLEX = '3';
|
|
7
|
+
const SIZE_COLUMN_FLEX = '1';
|
|
7
8
|
const Container = styled_components(Box)`
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
width: 31.25rem;
|
|
10
|
+
height: 15.63rem;
|
|
11
|
+
overflow-y: auto;
|
|
12
|
+
border: 1px solid ${({ theme })=>theme.border};
|
|
10
13
|
margin: ${spacing.r8} 0rem;
|
|
11
14
|
`;
|
|
15
|
+
const VersionId = styled_components.div`
|
|
16
|
+
font-size: 0.75rem;
|
|
17
|
+
color: ${({ theme })=>theme.textSecondary};
|
|
18
|
+
`;
|
|
12
19
|
const DeleteObjectModalContent = ({ objects, onRemove })=>{
|
|
13
20
|
const columns = useMemo(()=>[
|
|
14
21
|
{
|
|
15
22
|
Header: 'Name',
|
|
16
23
|
accessor: 'Key',
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
cellStyle: {
|
|
25
|
+
flex: NAME_COLUMN_FLEX,
|
|
26
|
+
minWidth: 0
|
|
27
|
+
},
|
|
28
|
+
Cell: ({ value, row })=>{
|
|
29
|
+
const versionId = 'VersionId' in row.original ? row.original.VersionId : void 0;
|
|
30
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
31
|
+
style: {
|
|
32
|
+
minWidth: 0
|
|
33
|
+
},
|
|
34
|
+
children: [
|
|
35
|
+
/*#__PURE__*/ jsx(ConstrainedText, {
|
|
36
|
+
text: value,
|
|
37
|
+
lineClamp: 1
|
|
38
|
+
}),
|
|
39
|
+
versionId && /*#__PURE__*/ jsx(VersionId, {
|
|
40
|
+
children: versionId
|
|
41
|
+
})
|
|
42
|
+
]
|
|
43
|
+
});
|
|
44
|
+
},
|
|
21
45
|
id: 'name'
|
|
22
46
|
},
|
|
23
47
|
{
|
|
24
48
|
Header: 'Size',
|
|
25
49
|
accessor: 'Size',
|
|
26
50
|
cellStyle: {
|
|
51
|
+
flex: SIZE_COLUMN_FLEX,
|
|
27
52
|
textAlign: 'right'
|
|
28
53
|
},
|
|
29
|
-
Cell: ({ value })
|
|
30
|
-
|
|
31
|
-
|
|
54
|
+
Cell: ({ value, row })=>{
|
|
55
|
+
const isLegalHoldEnabled = 'isLegalHoldEnabled' in row.original && row.original.isLegalHoldEnabled;
|
|
56
|
+
return /*#__PURE__*/ jsxs(Box, {
|
|
57
|
+
display: "flex",
|
|
58
|
+
alignItems: "center",
|
|
59
|
+
gap: spacing.r4,
|
|
60
|
+
justifyContent: "flex-end",
|
|
61
|
+
children: [
|
|
62
|
+
void 0 !== value && /*#__PURE__*/ jsx(PrettyBytes, {
|
|
63
|
+
bytes: Number(value)
|
|
64
|
+
}),
|
|
65
|
+
isLegalHoldEnabled && /*#__PURE__*/ jsx(Icon, {
|
|
66
|
+
name: "Rebalance",
|
|
67
|
+
size: "sm"
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
},
|
|
32
72
|
id: 'size'
|
|
33
73
|
},
|
|
34
74
|
{
|
|
35
75
|
Header: '',
|
|
36
76
|
accessor: 'type',
|
|
37
77
|
cellStyle: {
|
|
38
|
-
|
|
78
|
+
flex: '0 0 2rem'
|
|
39
79
|
},
|
|
40
80
|
Cell: (row)=>{
|
|
41
|
-
const
|
|
81
|
+
const item = row.row.original;
|
|
42
82
|
return /*#__PURE__*/ jsx("div", {
|
|
43
|
-
onClick: ()=>onRemove(
|
|
83
|
+
onClick: ()=>onRemove({
|
|
84
|
+
Key: item.Key,
|
|
85
|
+
VersionId: 'VersionId' in item ? item.VersionId : void 0
|
|
86
|
+
}),
|
|
44
87
|
children: /*#__PURE__*/ jsx(Icon, {
|
|
45
88
|
name: "Close",
|
|
46
89
|
color: "buttonSecondary"
|
|
@@ -51,11 +94,7 @@ const DeleteObjectModalContent = ({ objects, onRemove })=>{
|
|
|
51
94
|
], [
|
|
52
95
|
onRemove
|
|
53
96
|
]);
|
|
54
|
-
const HEADER_AND_SPACING_ROWS = 3;
|
|
55
|
-
const rowHeight = 'h40';
|
|
56
|
-
const tableRowHeightInRem = tableRowHeight[rowHeight];
|
|
57
97
|
return /*#__PURE__*/ jsx(Container, {
|
|
58
|
-
height: `calc(${objects.length + HEADER_AND_SPACING_ROWS} * (${tableRowHeightInRem}rem + 1px))`,
|
|
59
98
|
children: /*#__PURE__*/ jsx(Table, {
|
|
60
99
|
columns: columns,
|
|
61
100
|
data: objects,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|