@aws-amplify/ui-react-storage 3.14.0 → 3.15.0
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/browser.js +8 -2
- package/dist/{createStorageBrowser-CotOvK0A.js → createStorageBrowser-CG-6mXiT.js} +392 -148
- package/dist/esm/browser.mjs +1 -0
- package/dist/esm/components/StorageBrowser/ErrorBoundary/ErrorBoundary.mjs +1 -0
- package/dist/esm/components/StorageBrowser/StorageBrowserAmplify.mjs +1 -0
- package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +1 -0
- package/dist/esm/components/StorageBrowser/actions/handlers/defaults.mjs +1 -1
- package/dist/esm/components/StorageBrowser/actions/handlers/listLocations.mjs +7 -2
- package/dist/esm/components/StorageBrowser/actions/handlers/utils.mjs +65 -1
- package/dist/esm/components/StorageBrowser/actions/handlers/zipdownload.mjs +195 -0
- package/dist/esm/components/StorageBrowser/adapters/createAmplifyAuthAdapter/createAmplifyListLocationsHandler.mjs +3 -1
- package/dist/esm/components/StorageBrowser/adapters/createManagedAuthAdapter/createManagedAuthAdapter.mjs +1 -0
- package/dist/esm/components/StorageBrowser/components/ComponentsProvider.mjs +1 -0
- package/dist/esm/components/StorageBrowser/components/base/preview/DownloadButton.mjs +1 -0
- package/dist/esm/components/StorageBrowser/controls/DataTableControl.mjs +1 -0
- package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +1 -0
- package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +1 -0
- package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +1 -0
- package/dist/esm/components/StorageBrowser/displayText/libraries/en/downloadView.mjs +2 -0
- package/dist/esm/components/StorageBrowser/displayText/libraries/en/shared.mjs +2 -0
- package/dist/esm/components/StorageBrowser/locationItems/context.mjs +1 -0
- package/dist/esm/components/StorageBrowser/tasks/constants.mjs +2 -0
- package/dist/esm/components/StorageBrowser/tasks/useProcessTasks.mjs +10 -4
- package/dist/esm/components/StorageBrowser/tasks/utils.mjs +4 -1
- package/dist/esm/components/StorageBrowser/useAction/useHandler.mjs +1 -1
- package/dist/esm/components/StorageBrowser/useAction/utils.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/FoldersMessageControl.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useCopyView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useFolders.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/CreateFolderView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/useCreateFolderView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/useDeleteView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsViewProvider.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/LocationsView/useLocationsView.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/hooks/useFilePreview/useFilePreview.mjs +1 -0
- package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/constants.mjs +4 -0
- package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/utils.mjs +1 -1
- package/dist/esm/version.mjs +1 -1
- package/dist/index.js +2 -1
- package/dist/styles.css +17 -0
- package/dist/types/components/StorageBrowser/actions/handlers/index.d.ts +1 -0
- package/dist/types/components/StorageBrowser/actions/handlers/types.d.ts +4 -2
- package/dist/types/components/StorageBrowser/actions/handlers/utils.d.ts +11 -0
- package/dist/types/components/StorageBrowser/actions/handlers/zipdownload.d.ts +3 -0
- package/dist/types/components/StorageBrowser/displayText/types.d.ts +2 -0
- package/dist/types/components/StorageBrowser/tasks/types.d.ts +3 -3
- package/dist/types/components/StorageBrowser/tasks/useProcessTasks.d.ts +1 -1
- package/dist/types/components/StorageBrowser/useAction/useHandler.d.ts +1 -1
- package/dist/types/components/StorageBrowser/views/utils/tableResolvers/constants.d.ts +4 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +11 -8
- package/dist/esm/components/StorageBrowser/actions/handlers/download.mjs +0 -38
package/dist/esm/browser.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import '@aws-amplify/storage/internals';
|
|
|
2
2
|
import 'aws-amplify';
|
|
3
3
|
import '@aws-amplify/ui';
|
|
4
4
|
export { defaultHandlers } from './components/StorageBrowser/actions/handlers/defaults.mjs';
|
|
5
|
+
import 'jszip';
|
|
5
6
|
import 'aws-amplify/storage';
|
|
6
7
|
import './components/StorageBrowser/actions/configs/context.mjs';
|
|
7
8
|
export { defaultActionConfigs } from './components/StorageBrowser/actions/configs/defaults.mjs';
|
|
@@ -12,6 +12,7 @@ import '../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../actions/configs/context.mjs';
|
|
17
18
|
import '../actions/configs/defaults.mjs';
|
|
@@ -3,6 +3,7 @@ import { createAmplifyAuthAdapter } from './adapters/createAmplifyAuthAdapter/cr
|
|
|
3
3
|
import '@aws-amplify/storage/internals';
|
|
4
4
|
import 'aws-amplify';
|
|
5
5
|
import '@aws-amplify/ui';
|
|
6
|
+
import 'jszip';
|
|
6
7
|
import 'aws-amplify/storage';
|
|
7
8
|
import './actions/configs/context.mjs';
|
|
8
9
|
import './actions/configs/defaults.mjs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { copyHandler } from './copy.mjs';
|
|
2
2
|
import { createFolderHandler } from './createFolder.mjs';
|
|
3
3
|
import { deleteHandler } from './delete.mjs';
|
|
4
|
-
import { downloadHandler } from './
|
|
4
|
+
import { zipDownloadHandler as downloadHandler } from './zipdownload.mjs';
|
|
5
5
|
import { listLocationItemsHandler } from './listLocationItems.mjs';
|
|
6
6
|
import { uploadHandler } from './upload.mjs';
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { listCallerAccessGrants } from '@aws-amplify/storage/internals';
|
|
2
2
|
import { assertAccountId } from '../../validators/assertAccountId.mjs';
|
|
3
3
|
import '@aws-amplify/ui';
|
|
4
|
-
import { getFilteredLocations } from './utils.mjs';
|
|
4
|
+
import { deduplicateLocations, getFilteredLocations } from './utils.mjs';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_PAGE_SIZE = 1000;
|
|
7
7
|
const listLocationsHandler = async (input) => {
|
|
@@ -26,7 +26,12 @@ const listLocationsHandler = async (input) => {
|
|
|
26
26
|
}
|
|
27
27
|
return { items, nextToken: output.nextToken };
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
const result = await fetchLocations([], nextToken);
|
|
30
|
+
// Deduplicate locations with the same bucket and prefix, keeping broader permissions
|
|
31
|
+
return {
|
|
32
|
+
items: deduplicateLocations(result.items),
|
|
33
|
+
nextToken: result.nextToken,
|
|
34
|
+
};
|
|
30
35
|
};
|
|
31
36
|
|
|
32
37
|
export { listLocationsHandler };
|
|
@@ -88,6 +88,70 @@ const shouldExcludeLocation = ({ permissions, type }, exclude) => {
|
|
|
88
88
|
const excludedByType = !!(exclude?.type && isSameType(exclude.type, type));
|
|
89
89
|
return excludedByPermssions || excludedByType;
|
|
90
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* Determines if permissions1 is a strict superset (broader) of permissions2.
|
|
93
|
+
* Returns true only if permissions1 contains all permissions from permissions2
|
|
94
|
+
* AND has more permissions.
|
|
95
|
+
*/
|
|
96
|
+
const hasBroaderPermissions = (permissions1, permissions2) => {
|
|
97
|
+
// permissions1 must have more permissions (strict superset, not equal)
|
|
98
|
+
if (permissions1.length <= permissions2.length) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
// permissions1 must contain all permissions from permissions2
|
|
102
|
+
return permissions2.every((perm) => permissions1.includes(perm));
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Deduplicates locations with the same bucket and prefix.
|
|
106
|
+
* Only deduplicates when one location's permissions are a superset of another's.
|
|
107
|
+
* This prevents deduplication of incompatible grants like READ + WRITE.
|
|
108
|
+
*
|
|
109
|
+
* Examples:
|
|
110
|
+
* - READ + READWRITE → Keep READWRITE (superset)
|
|
111
|
+
* - READ + READ → Keep first (identical)
|
|
112
|
+
* - READ + WRITE → Keep both (not superset, need separate locations)
|
|
113
|
+
*/
|
|
114
|
+
const deduplicateLocations = (locations) => {
|
|
115
|
+
// Group locations by bucket:prefix
|
|
116
|
+
const locationGroups = new Map();
|
|
117
|
+
for (const location of locations) {
|
|
118
|
+
const key = `${location.bucket}:${location.prefix}`;
|
|
119
|
+
const group = locationGroups.get(key) ?? [];
|
|
120
|
+
group.push(location);
|
|
121
|
+
locationGroups.set(key, group);
|
|
122
|
+
}
|
|
123
|
+
// For each group, keep only non-redundant locations
|
|
124
|
+
const result = [];
|
|
125
|
+
for (const group of locationGroups.values()) {
|
|
126
|
+
if (group.length === 1) {
|
|
127
|
+
result.push(group[0]);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Find locations that are not subsets of any other location in the group
|
|
131
|
+
const nonRedundant = [];
|
|
132
|
+
for (const location of group) {
|
|
133
|
+
// Check if this location is a subset of any other location
|
|
134
|
+
const isSubsetOfAnother = group.some((other) => {
|
|
135
|
+
if (other === location)
|
|
136
|
+
return false;
|
|
137
|
+
return hasBroaderPermissions(other.permissions, location.permissions);
|
|
138
|
+
});
|
|
139
|
+
if (!isSubsetOfAnother) {
|
|
140
|
+
// Check if we already have an identical permission set
|
|
141
|
+
const isDuplicate = nonRedundant.some((existing) => {
|
|
142
|
+
const sortedNew = [...location.permissions].sort().join(',');
|
|
143
|
+
const sortedExisting = [...existing.permissions].sort().join(',');
|
|
144
|
+
return sortedNew === sortedExisting;
|
|
145
|
+
});
|
|
146
|
+
if (!isDuplicate) {
|
|
147
|
+
nonRedundant.push(location);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
result.push(...nonRedundant);
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
};
|
|
91
155
|
const getFilteredLocations = (locations, exclude) => locations.reduce((filteredLocations, location) => {
|
|
92
156
|
const parsedLocation = parseAccessGrantLocation(location);
|
|
93
157
|
const isNonFolderLikePrefix = !parsedLocation.prefix.endsWith('/') &&
|
|
@@ -108,4 +172,4 @@ const createFileDataItem = (data) => ({
|
|
|
108
172
|
const getProgress = ({ totalBytes, transferredBytes, }) => totalBytes ? transferredBytes / totalBytes : undefined;
|
|
109
173
|
const isMultipartUpload = (file) => file.size > MULTIPART_UPLOAD_THRESHOLD_BYTES;
|
|
110
174
|
|
|
111
|
-
export { constructBucket, createFileDataItem, getBucketRegion, getFileKey, getFilteredLocations, getProgress, isMultipartUpload, parseAccessGrantLocation, shouldExcludeLocation };
|
|
175
|
+
export { constructBucket, createFileDataItem, deduplicateLocations, getBucketRegion, getFileKey, getFilteredLocations, getProgress, isMultipartUpload, parseAccessGrantLocation, shouldExcludeLocation };
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { getUrl } from '@aws-amplify/storage/internals';
|
|
2
|
+
import { isFunction } from '@aws-amplify/ui';
|
|
3
|
+
import { getProgress } from './utils.mjs';
|
|
4
|
+
import JSZip from 'jszip';
|
|
5
|
+
|
|
6
|
+
const zipProgressManager = ({ dataMap, onZipProgress, }) => {
|
|
7
|
+
const iter = (() => {
|
|
8
|
+
let f;
|
|
9
|
+
let i = 0;
|
|
10
|
+
return (str) => {
|
|
11
|
+
if (!f) {
|
|
12
|
+
f = str;
|
|
13
|
+
}
|
|
14
|
+
else if (str !== f) {
|
|
15
|
+
++i;
|
|
16
|
+
f = str;
|
|
17
|
+
}
|
|
18
|
+
return i;
|
|
19
|
+
};
|
|
20
|
+
})();
|
|
21
|
+
const progressMap = new Map(Array.from(dataMap.keys()).map((k) => [k, 0]));
|
|
22
|
+
const total = dataMap.size;
|
|
23
|
+
dataMap.forEach((data, key) => {
|
|
24
|
+
onZipProgress(key, 0, data);
|
|
25
|
+
});
|
|
26
|
+
return ({ percent, currentFile, }) => {
|
|
27
|
+
if (currentFile) {
|
|
28
|
+
const item = iter(currentFile);
|
|
29
|
+
const sliceSize = 100 / total; // when 3 this is 33.3%
|
|
30
|
+
const start = sliceSize * item; // this is 66.6% for last item of 3;
|
|
31
|
+
// take percent and calculate the percent of the slice
|
|
32
|
+
const progress = percent - start;
|
|
33
|
+
const actualPercent = (progress / sliceSize) * 100;
|
|
34
|
+
progressMap.set(currentFile, Math.max(actualPercent, progressMap.get(currentFile) ?? 0));
|
|
35
|
+
onZipProgress(currentFile, progressMap.get(currentFile), dataMap.get(currentFile));
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const zipper = (() => {
|
|
40
|
+
let zip = null;
|
|
41
|
+
const dataMap = new Map();
|
|
42
|
+
return {
|
|
43
|
+
addFile: (file, name, data) => {
|
|
44
|
+
if (!zip) {
|
|
45
|
+
zip = new JSZip();
|
|
46
|
+
}
|
|
47
|
+
dataMap.set(name, data);
|
|
48
|
+
return new Promise((ok, no) => {
|
|
49
|
+
try {
|
|
50
|
+
zip?.file(name, file);
|
|
51
|
+
ok();
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
no();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
getBlobUrl: async (onProgress) => {
|
|
59
|
+
if (!zip) {
|
|
60
|
+
throw new Error('no zip');
|
|
61
|
+
}
|
|
62
|
+
const blob = await zip.generateAsync({
|
|
63
|
+
type: 'blob',
|
|
64
|
+
streamFiles: true,
|
|
65
|
+
compression: 'DEFLATE',
|
|
66
|
+
compressionOptions: {
|
|
67
|
+
level: 5,
|
|
68
|
+
},
|
|
69
|
+
}, zipProgressManager({
|
|
70
|
+
dataMap,
|
|
71
|
+
onZipProgress: (file, progress, data) => {
|
|
72
|
+
if (isFunction(onProgress)) {
|
|
73
|
+
onProgress(progress, file, data);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
zip = null;
|
|
78
|
+
return URL.createObjectURL(blob);
|
|
79
|
+
},
|
|
80
|
+
destroy: () => {
|
|
81
|
+
dataMap.clear();
|
|
82
|
+
zip = null;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
})();
|
|
86
|
+
const constructBucket = ({ bucket: bucketName, region, }) => ({ bucketName, region });
|
|
87
|
+
const readBody = async (response, { data, options }) => {
|
|
88
|
+
let loading = true;
|
|
89
|
+
const chunks = [];
|
|
90
|
+
const reader = response.body.getReader();
|
|
91
|
+
const size = +(response.headers.get('content-length') ?? 0);
|
|
92
|
+
let received = 0;
|
|
93
|
+
while (loading) {
|
|
94
|
+
const { value, done } = await reader.read();
|
|
95
|
+
if (done) {
|
|
96
|
+
loading = false;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
chunks.push(value);
|
|
100
|
+
received += value.length;
|
|
101
|
+
if (isFunction(options?.onProgress)) {
|
|
102
|
+
options?.onProgress(data, getProgress({
|
|
103
|
+
totalBytes: size,
|
|
104
|
+
transferredBytes: received,
|
|
105
|
+
}), 'PENDING');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return new Blob(chunks);
|
|
110
|
+
};
|
|
111
|
+
const download = async ({ config, data, all, options }, abortController) => {
|
|
112
|
+
const { customEndpoint, credentials, accountId } = config;
|
|
113
|
+
const { key } = data;
|
|
114
|
+
const { url } = await getUrl({
|
|
115
|
+
path: key,
|
|
116
|
+
options: {
|
|
117
|
+
bucket: constructBucket(config),
|
|
118
|
+
customEndpoint,
|
|
119
|
+
locationCredentialsProvider: credentials,
|
|
120
|
+
validateObjectExistence: true,
|
|
121
|
+
contentDisposition: 'attachment',
|
|
122
|
+
expectedBucketOwner: accountId,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const response = await fetch(url, {
|
|
126
|
+
mode: 'cors',
|
|
127
|
+
signal: abortController.signal,
|
|
128
|
+
});
|
|
129
|
+
const blob = await readBody(response, { data, options });
|
|
130
|
+
const [filename] = key.split('/').reverse();
|
|
131
|
+
await zipper.addFile(blob, filename, data);
|
|
132
|
+
return filename;
|
|
133
|
+
};
|
|
134
|
+
const downloadHandler = (() => {
|
|
135
|
+
const fileDownloadQueue = new Map();
|
|
136
|
+
const handler = ({ config, data, all, options }) => {
|
|
137
|
+
const { key } = data;
|
|
138
|
+
const [, folder] = key.split('/').reverse();
|
|
139
|
+
fileDownloadQueue.set(key, false);
|
|
140
|
+
const abortController = new AbortController();
|
|
141
|
+
return {
|
|
142
|
+
cancel: () => {
|
|
143
|
+
abortController.abort();
|
|
144
|
+
fileDownloadQueue.set(key, true);
|
|
145
|
+
},
|
|
146
|
+
result: download({ config, data, all, options }, abortController)
|
|
147
|
+
.then(() => {
|
|
148
|
+
fileDownloadQueue.set(key, true);
|
|
149
|
+
return {
|
|
150
|
+
status: 'LOADED',
|
|
151
|
+
};
|
|
152
|
+
})
|
|
153
|
+
.catch((e) => {
|
|
154
|
+
const error = e;
|
|
155
|
+
fileDownloadQueue.set(key, true);
|
|
156
|
+
return {
|
|
157
|
+
status: 'FAILED',
|
|
158
|
+
message: error.message,
|
|
159
|
+
error,
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
.finally(() => {
|
|
163
|
+
const done = all.every(({ key }) => {
|
|
164
|
+
return fileDownloadQueue.get(key);
|
|
165
|
+
});
|
|
166
|
+
if (done) {
|
|
167
|
+
zipper
|
|
168
|
+
.getBlobUrl((percent, name, _data) => {
|
|
169
|
+
if (isFunction(options?.onProgress)) {
|
|
170
|
+
const progress = percent / 100;
|
|
171
|
+
options?.onProgress(_data, progress, progress === 1 ? 'COMPLETE' : 'FINISHING');
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
.then((blobURL) => {
|
|
175
|
+
if (blobURL) {
|
|
176
|
+
zipper.destroy();
|
|
177
|
+
const anchor = document.createElement('a');
|
|
178
|
+
const clickEvent = new MouseEvent('click');
|
|
179
|
+
anchor.href = blobURL;
|
|
180
|
+
anchor.download = `${folder || 'archive'}.zip`;
|
|
181
|
+
anchor.dispatchEvent(clickEvent);
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
.catch(() => {
|
|
185
|
+
// this catch happens, when no zip was created.
|
|
186
|
+
// it is handled by the UI showing "FAILED" for all files
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}),
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
return handler;
|
|
193
|
+
})();
|
|
194
|
+
|
|
195
|
+
export { downloadHandler as zipDownloadHandler };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { listPaths } from '@aws-amplify/storage/internals';
|
|
2
|
+
import { deduplicateLocations } from '../../actions/handlers/utils.mjs';
|
|
2
3
|
import { parseAmplifyAuthPermission } from '../permissionParsers.mjs';
|
|
3
4
|
import { getPaginatedLocations } from './getPaginatedLocations.mjs';
|
|
4
5
|
|
|
@@ -24,7 +25,8 @@ const createAmplifyListLocationsHandler = () => {
|
|
|
24
25
|
id: crypto.randomUUID(),
|
|
25
26
|
};
|
|
26
27
|
});
|
|
27
|
-
|
|
28
|
+
// Deduplicate locations with the same bucket and prefix, keeping broader permissions
|
|
29
|
+
cachedItems = deduplicateLocations(sanitizedItems);
|
|
28
30
|
return getPaginatedLocations({
|
|
29
31
|
items: cachedItems,
|
|
30
32
|
pageSize,
|
|
@@ -2,6 +2,7 @@ import { createLocationCredentialsHandler } from './createLocationCredentialsHan
|
|
|
2
2
|
import '@aws-amplify/storage/internals';
|
|
3
3
|
import 'aws-amplify';
|
|
4
4
|
import '@aws-amplify/ui';
|
|
5
|
+
import 'jszip';
|
|
5
6
|
import 'aws-amplify/storage';
|
|
6
7
|
import { listLocationsHandler } from '../../actions/handlers/listLocations.mjs';
|
|
7
8
|
import '../../actions/configs/context.mjs';
|
|
@@ -12,6 +12,7 @@ import '../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../actions/configs/context.mjs';
|
|
17
18
|
import '../actions/configs/defaults.mjs';
|
|
@@ -13,6 +13,7 @@ import '@aws-amplify/storage/internals';
|
|
|
13
13
|
import '../../../configuration/context.mjs';
|
|
14
14
|
import '@aws-amplify/ui';
|
|
15
15
|
import 'aws-amplify';
|
|
16
|
+
import 'jszip';
|
|
16
17
|
import 'aws-amplify/storage';
|
|
17
18
|
import '../../../actions/configs/context.mjs';
|
|
18
19
|
import '../../../actions/configs/defaults.mjs';
|
|
@@ -12,6 +12,7 @@ import '../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../actions/configs/context.mjs';
|
|
17
18
|
import '../actions/configs/defaults.mjs';
|
|
@@ -11,6 +11,7 @@ import '@aws-amplify/storage/internals';
|
|
|
11
11
|
import '../configuration/context.mjs';
|
|
12
12
|
import '@aws-amplify/ui-react-core';
|
|
13
13
|
import 'aws-amplify';
|
|
14
|
+
import 'jszip';
|
|
14
15
|
import 'aws-amplify/storage';
|
|
15
16
|
import '../actions/configs/context.mjs';
|
|
16
17
|
import '../actions/configs/defaults.mjs';
|
|
@@ -2,6 +2,7 @@ import React__default from 'react';
|
|
|
2
2
|
import '@aws-amplify/storage/internals';
|
|
3
3
|
import 'aws-amplify';
|
|
4
4
|
import '@aws-amplify/ui';
|
|
5
|
+
import 'jszip';
|
|
5
6
|
import 'aws-amplify/storage';
|
|
6
7
|
import { ActionConfigsProvider } from '../actions/configs/context.mjs';
|
|
7
8
|
import { defaultActionConfigs } from '../actions/configs/defaults.mjs';
|
|
@@ -10,6 +10,7 @@ import '../credentials/context.mjs';
|
|
|
10
10
|
import '@aws-amplify/storage/internals';
|
|
11
11
|
import '../configuration/context.mjs';
|
|
12
12
|
import 'aws-amplify';
|
|
13
|
+
import 'jszip';
|
|
13
14
|
import 'aws-amplify/storage';
|
|
14
15
|
import { assertRegisterAuthListener } from '../validators/assertRegisterAuthListener.mjs';
|
|
15
16
|
import '../actions/configs/context.mjs';
|
|
@@ -4,6 +4,8 @@ const DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT = {
|
|
|
4
4
|
...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
|
|
5
5
|
title: 'Download',
|
|
6
6
|
actionStartLabel: 'Download',
|
|
7
|
+
statusDisplayFinishingLabel: 'Zipping',
|
|
8
|
+
statusDisplayLoadedLabel: 'Loaded',
|
|
7
9
|
getActionCompleteMessage: (data) => {
|
|
8
10
|
const { counts } = data ?? {};
|
|
9
11
|
const { COMPLETE, FAILED, TOTAL } = counts ?? {};
|
|
@@ -4,8 +4,10 @@ const DEFAULT_ACTION_VIEW_DISPLAY_TEXT = {
|
|
|
4
4
|
actionDestinationLabel: 'Destination',
|
|
5
5
|
statusDisplayCanceledLabel: 'Canceled',
|
|
6
6
|
statusDisplayCompletedLabel: 'Completed',
|
|
7
|
+
statusDisplayLoadedLabel: 'Completed',
|
|
7
8
|
statusDisplayFailedLabel: 'Failed',
|
|
8
9
|
statusDisplayInProgressLabel: 'In progress',
|
|
10
|
+
statusDisplayFinishingLabel: 'In progress',
|
|
9
11
|
statusDisplayTotalLabel: 'Total',
|
|
10
12
|
statusDisplayQueuedLabel: 'Not started',
|
|
11
13
|
// empty by default
|
|
@@ -3,6 +3,7 @@ import { createContextUtilities } from '@aws-amplify/ui-react-core';
|
|
|
3
3
|
import { noop } from '@aws-amplify/ui';
|
|
4
4
|
import '@aws-amplify/storage/internals';
|
|
5
5
|
import { createFileDataItem } from '../actions/handlers/utils.mjs';
|
|
6
|
+
import 'jszip';
|
|
6
7
|
import 'aws-amplify/storage';
|
|
7
8
|
import '../actions/configs/context.mjs';
|
|
8
9
|
import '../actions/configs/defaults.mjs';
|
|
@@ -92,20 +92,26 @@ function useProcessTasks(handler, options) {
|
|
|
92
92
|
: [...tasksRef.current.values()].find(({ status }) => status === 'QUEUED') ?? {};
|
|
93
93
|
if (!data)
|
|
94
94
|
return;
|
|
95
|
+
const all = isSingleTask
|
|
96
|
+
? [_input.data]
|
|
97
|
+
: [...tasksRef.current.values()].map(({ data }) => data);
|
|
95
98
|
const { onTaskCancel, onTaskComplete, onTaskError, onTaskProgress, onTaskSuccess, } = callbacksRef.current;
|
|
96
99
|
const getTask = () => tasksRef.current.get(data.id);
|
|
97
100
|
const { options } = _input;
|
|
98
101
|
const { onProgress: _onProgress } = options ?? {};
|
|
99
|
-
const onProgress = ({ id }, progress) => {
|
|
100
|
-
const task = updateTask(id, {
|
|
102
|
+
const onProgress = ({ id }, progress, status = 'PENDING') => {
|
|
103
|
+
const task = updateTask(id, {
|
|
104
|
+
progress,
|
|
105
|
+
status,
|
|
106
|
+
});
|
|
101
107
|
if (task && isFunction(onTaskProgress)) {
|
|
102
108
|
onTaskProgress(task, progress);
|
|
103
109
|
}
|
|
104
110
|
if (task && isFunction(_onProgress)) {
|
|
105
|
-
_onProgress(data, progress);
|
|
111
|
+
_onProgress(data, progress, status);
|
|
106
112
|
}
|
|
107
113
|
};
|
|
108
|
-
const input = { ..._input, data, options: { ...options, onProgress } };
|
|
114
|
+
const input = { ..._input, data, all, options: { ...options, onProgress } };
|
|
109
115
|
const { cancel: _cancel, result } = handler(input);
|
|
110
116
|
const cancel = !_cancel
|
|
111
117
|
? undefined
|
|
@@ -5,7 +5,10 @@ const isProcessingTasks = (statusCounts) => {
|
|
|
5
5
|
if (statusCounts.TOTAL === 0 || statusCounts.TOTAL === statusCounts.QUEUED) {
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
8
|
-
return !(statusCounts.QUEUED === 0 &&
|
|
8
|
+
return !(statusCounts.QUEUED === 0 &&
|
|
9
|
+
statusCounts.PENDING === 0 &&
|
|
10
|
+
statusCounts.LOADED === 0 &&
|
|
11
|
+
statusCounts.FINISHING === 0);
|
|
9
12
|
};
|
|
10
13
|
const hasCompletedProcessingTasks = (statusCounts) => {
|
|
11
14
|
if (statusCounts.TOTAL === 0 || isProcessingTasks(statusCounts))
|
|
@@ -21,7 +21,7 @@ function useHandler(handler, options) {
|
|
|
21
21
|
handleProcessing({
|
|
22
22
|
config,
|
|
23
23
|
...(hasData
|
|
24
|
-
? { data: input.data }
|
|
24
|
+
? { data: input.data, all: [input.data] }
|
|
25
25
|
: // if no `data` provided, provide `concurrency` to `options`
|
|
26
26
|
{ options: { concurrency: DEFAULT_ACTION_CONCURRENCY } }),
|
|
27
27
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isFunction } from '@aws-amplify/ui';
|
|
2
2
|
import '@aws-amplify/storage/internals';
|
|
3
3
|
import 'aws-amplify';
|
|
4
|
+
import 'jszip';
|
|
4
5
|
import 'aws-amplify/storage';
|
|
5
6
|
import '../actions/configs/context.mjs';
|
|
6
7
|
import { isDefaultActionViewType } from '../actions/configs/defaults.mjs';
|
|
@@ -12,6 +12,7 @@ import '../../../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../../../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../../../actions/configs/context.mjs';
|
|
17
18
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import '../../../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../../../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../../../actions/configs/context.mjs';
|
|
17
18
|
import '../../../actions/configs/defaults.mjs';
|
|
@@ -14,6 +14,7 @@ import '../../../credentials/context.mjs';
|
|
|
14
14
|
import '@aws-amplify/storage/internals';
|
|
15
15
|
import '../../../configuration/context.mjs';
|
|
16
16
|
import 'aws-amplify';
|
|
17
|
+
import 'jszip';
|
|
17
18
|
import 'aws-amplify/storage';
|
|
18
19
|
import '../../../actions/configs/context.mjs';
|
|
19
20
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useCopyView.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import '../../../credentials/context.mjs';
|
|
|
10
10
|
import '@aws-amplify/storage/internals';
|
|
11
11
|
import '../../../configuration/context.mjs';
|
|
12
12
|
import 'aws-amplify';
|
|
13
|
+
import 'jszip';
|
|
13
14
|
import 'aws-amplify/storage';
|
|
14
15
|
import '../../../actions/configs/context.mjs';
|
|
15
16
|
import '../../../actions/configs/defaults.mjs';
|
|
@@ -7,6 +7,7 @@ import '../../../configuration/context.mjs';
|
|
|
7
7
|
import '@aws-amplify/ui';
|
|
8
8
|
import { useList } from '../../../useAction/useList.mjs';
|
|
9
9
|
import 'aws-amplify';
|
|
10
|
+
import 'jszip';
|
|
10
11
|
import 'aws-amplify/storage';
|
|
11
12
|
import '../../../actions/configs/context.mjs';
|
|
12
13
|
import '../../../actions/configs/defaults.mjs';
|
|
@@ -12,6 +12,7 @@ import '../../../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../../../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../../../actions/configs/context.mjs';
|
|
17
18
|
import '../../../actions/configs/defaults.mjs';
|
|
@@ -8,6 +8,7 @@ import '../../../credentials/context.mjs';
|
|
|
8
8
|
import '@aws-amplify/storage/internals';
|
|
9
9
|
import '../../../configuration/context.mjs';
|
|
10
10
|
import 'aws-amplify';
|
|
11
|
+
import 'jszip';
|
|
11
12
|
import 'aws-amplify/storage';
|
|
12
13
|
import '../../../actions/configs/context.mjs';
|
|
13
14
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteView.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import '../../../credentials/context.mjs';
|
|
|
19
19
|
import '@aws-amplify/storage/internals';
|
|
20
20
|
import '../../../configuration/context.mjs';
|
|
21
21
|
import 'aws-amplify';
|
|
22
|
+
import 'jszip';
|
|
22
23
|
import 'aws-amplify/storage';
|
|
23
24
|
import '../../../actions/configs/context.mjs';
|
|
24
25
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/useDeleteView.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import '../../../credentials/context.mjs';
|
|
|
10
10
|
import '@aws-amplify/storage/internals';
|
|
11
11
|
import '../../../configuration/context.mjs';
|
|
12
12
|
import 'aws-amplify';
|
|
13
|
+
import 'jszip';
|
|
13
14
|
import 'aws-amplify/storage';
|
|
14
15
|
import '../../../actions/configs/context.mjs';
|
|
15
16
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import '../../../credentials/context.mjs';
|
|
|
19
19
|
import '@aws-amplify/storage/internals';
|
|
20
20
|
import '../../../configuration/context.mjs';
|
|
21
21
|
import 'aws-amplify';
|
|
22
|
+
import 'jszip';
|
|
22
23
|
import 'aws-amplify/storage';
|
|
23
24
|
import '../../../actions/configs/context.mjs';
|
|
24
25
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import '../../../credentials/context.mjs';
|
|
|
10
10
|
import '@aws-amplify/storage/internals';
|
|
11
11
|
import '../../../configuration/context.mjs';
|
|
12
12
|
import 'aws-amplify';
|
|
13
|
+
import 'jszip';
|
|
13
14
|
import 'aws-amplify/storage';
|
|
14
15
|
import '../../../actions/configs/context.mjs';
|
|
15
16
|
import '../../../actions/configs/defaults.mjs';
|
package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import '../../../credentials/context.mjs';
|
|
|
12
12
|
import '@aws-amplify/storage/internals';
|
|
13
13
|
import '../../../configuration/context.mjs';
|
|
14
14
|
import 'aws-amplify';
|
|
15
|
+
import 'jszip';
|
|
15
16
|
import 'aws-amplify/storage';
|
|
16
17
|
import '../../../actions/configs/context.mjs';
|
|
17
18
|
import '../../../actions/configs/defaults.mjs';
|