@maas/payload-plugin-media-cloud 0.0.31 → 0.0.33
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/adapter/handleDelete.d.mts +3 -3
- package/dist/adapter/handleDelete.mjs +6 -6
- package/dist/adapter/handleDelete.mjs.map +1 -1
- package/dist/adapter/handleUpload.mjs.map +1 -1
- package/dist/adapter/staticHandler.d.mts +5 -3
- package/dist/adapter/staticHandler.mjs +8 -7
- package/dist/adapter/staticHandler.mjs.map +1 -1
- package/dist/adapter/storageAdapter.d.mts +3 -3
- package/dist/adapter/storageAdapter.mjs +4 -4
- package/dist/adapter/storageAdapter.mjs.map +1 -1
- package/dist/collectionHooks/afterChange.d.mts +7 -0
- package/dist/collectionHooks/afterChange.mjs +39 -0
- package/dist/collectionHooks/afterChange.mjs.map +1 -0
- package/dist/collectionHooks/beforeChange.d.mts +7 -0
- package/dist/collectionHooks/beforeChange.mjs +33 -0
- package/dist/collectionHooks/beforeChange.mjs.map +1 -0
- package/dist/collections/mediaCollection.d.mts +3 -2
- package/dist/collections/mediaCollection.mjs +36 -187
- package/dist/collections/mediaCollection.mjs.map +1 -1
- package/dist/components/folderFileCard/folderFileCard.d.mts +13 -0
- package/dist/components/folderFileCard/folderFileCard.mjs +75 -0
- package/dist/components/folderFileCard/folderFileCard.mjs.map +1 -0
- package/dist/components/gridContext/gridContext.d.mts +51 -0
- package/dist/components/gridContext/gridContext.mjs +227 -0
- package/dist/components/gridContext/gridContext.mjs.map +1 -0
- package/dist/components/gridView/gridView.css +50 -0
- package/dist/components/gridView/gridView.d.mts +16 -0
- package/dist/components/gridView/gridView.mjs +283 -0
- package/dist/components/gridView/gridView.mjs.map +1 -0
- package/dist/components/gridView/index.d.mts +2 -0
- package/dist/components/gridView/index.mjs +3 -0
- package/dist/components/index.d.mts +9 -7
- package/dist/components/index.mjs +5 -4
- package/dist/components/itemCardGrid/itemCardGrid.css +12 -0
- package/dist/components/itemCardGrid/itemCardGrid.d.mts +18 -0
- package/dist/components/itemCardGrid/itemCardGrid.mjs +42 -0
- package/dist/components/itemCardGrid/itemCardGrid.mjs.map +1 -0
- package/dist/components/muxPreview/index.d.mts +2 -0
- package/dist/components/muxPreview/index.mjs +3 -0
- package/dist/components/{mux-preview/mux-preview.d.mts → muxPreview/muxPreview.d.mts} +2 -2
- package/dist/components/muxPreview/muxPreview.mjs +65 -0
- package/dist/components/muxPreview/muxPreview.mjs.map +1 -0
- package/dist/components/uploadHandler/index.d.mts +2 -0
- package/dist/components/uploadHandler/index.mjs +3 -0
- package/dist/components/uploadHandler/uploadHandler.d.mts +20 -0
- package/dist/components/{upload-handler/upload-handler.mjs → uploadHandler/uploadHandler.mjs} +82 -52
- package/dist/components/uploadHandler/uploadHandler.mjs.map +1 -0
- package/dist/components/uploadManager/index.d.mts +2 -0
- package/dist/components/uploadManager/index.mjs +3 -0
- package/dist/components/{upload-manager/upload-manager.d.mts → uploadManager/uploadManager.d.mts} +3 -3
- package/dist/components/uploadManager/uploadManager.mjs +363 -0
- package/dist/components/uploadManager/uploadManager.mjs.map +1 -0
- package/dist/endpoints/fileExistsHandler.d.mts +12 -0
- package/dist/endpoints/{tusFileExistsHandler.mjs → fileExistsHandler.mjs} +7 -7
- package/dist/endpoints/fileExistsHandler.mjs.map +1 -0
- package/dist/endpoints/muxAssetHandler.d.mts +1 -0
- package/dist/endpoints/muxAssetHandler.mjs +3 -3
- package/dist/endpoints/muxAssetHandler.mjs.map +1 -1
- package/dist/endpoints/muxCreateUploadHandler.mjs.map +1 -1
- package/dist/endpoints/muxWebhookHandler.d.mts +1 -0
- package/dist/endpoints/muxWebhookHandler.mjs +6 -5
- package/dist/endpoints/muxWebhookHandler.mjs.map +1 -1
- package/dist/endpoints/tusCleanupHandler.d.mts +3 -2
- package/dist/endpoints/tusCleanupHandler.mjs +4 -4
- package/dist/endpoints/tusCleanupHandler.mjs.map +1 -1
- package/dist/endpoints/tusFolderHandler.d.mts +12 -0
- package/dist/endpoints/tusFolderHandler.mjs +39 -0
- package/dist/endpoints/tusFolderHandler.mjs.map +1 -0
- package/dist/endpoints/tusPostProcessorHandler.d.mts +3 -2
- package/dist/endpoints/tusPostProcessorHandler.mjs +6 -5
- package/dist/endpoints/tusPostProcessorHandler.mjs.map +1 -1
- package/dist/fields/alt.d.mts +7 -0
- package/dist/fields/alt.mjs +10 -0
- package/dist/fields/alt.mjs.map +1 -0
- package/dist/fields/filename.d.mts +7 -0
- package/dist/fields/filename.mjs +14 -0
- package/dist/fields/filename.mjs.map +1 -0
- package/dist/fields/height.d.mts +7 -0
- package/dist/fields/height.mjs +15 -0
- package/dist/fields/height.mjs.map +1 -0
- package/dist/fields/mux.d.mts +7 -0
- package/dist/fields/mux.mjs +149 -0
- package/dist/fields/mux.mjs.map +1 -0
- package/dist/fields/path.d.mts +7 -0
- package/dist/fields/path.mjs +14 -0
- package/dist/fields/path.mjs.map +1 -0
- package/dist/fields/storage.d.mts +7 -0
- package/dist/fields/storage.mjs +18 -0
- package/dist/fields/storage.mjs.map +1 -0
- package/dist/fields/thumbnail.d.mts +7 -0
- package/dist/fields/thumbnail.mjs +17 -0
- package/dist/fields/thumbnail.mjs.map +1 -0
- package/dist/fields/width.d.mts +7 -0
- package/dist/fields/width.mjs +15 -0
- package/dist/fields/width.mjs.map +1 -0
- package/dist/hooks/useErrorHandler.d.mts +1 -1
- package/dist/hooks/useErrorHandler.mjs +26 -7
- package/dist/hooks/useErrorHandler.mjs.map +1 -1
- package/dist/hooks/useMediaCloudEmitter.mjs.map +1 -1
- package/dist/plugin.d.mts +5 -4
- package/dist/plugin.mjs +53 -29
- package/dist/plugin.mjs.map +1 -1
- package/dist/tus/stores/s3/{expiration-manager.d.mts → expirationManager.d.mts} +4 -3
- package/dist/tus/stores/s3/{expiration-manager.mjs → expirationManager.mjs} +6 -3
- package/dist/tus/stores/s3/expirationManager.mjs.map +1 -0
- package/dist/tus/stores/s3/{file-operations.d.mts → fileOperations.d.mts} +2 -2
- package/dist/tus/stores/s3/{file-operations.mjs → fileOperations.mjs} +2 -2
- package/dist/tus/stores/s3/fileOperations.mjs.map +1 -0
- package/dist/tus/stores/s3/index.d.mts +1 -1
- package/dist/tus/stores/s3/index.mjs +20 -9
- package/dist/tus/stores/s3/index.mjs.map +1 -1
- package/dist/tus/stores/s3/{metadata-manager.d.mts → metadataManager.d.mts} +4 -2
- package/dist/tus/stores/s3/{metadata-manager.mjs → metadataManager.mjs} +6 -5
- package/dist/tus/stores/s3/metadataManager.mjs.map +1 -0
- package/dist/tus/stores/s3/{parts-manager.d.mts → partsManager.d.mts} +4 -4
- package/dist/tus/stores/s3/{parts-manager.mjs → partsManager.mjs} +67 -29
- package/dist/tus/stores/s3/partsManager.mjs.map +1 -0
- package/dist/tus/stores/s3/{s3-store.d.mts → s3Store.d.mts} +38 -32
- package/dist/tus/stores/s3/{s3-store.mjs → s3Store.mjs} +104 -59
- package/dist/tus/stores/s3/s3Store.mjs.map +1 -0
- package/dist/tus/stores/s3/semaphore.mjs.map +1 -1
- package/dist/types/errors.d.mts +32 -0
- package/dist/types/errors.mjs +32 -0
- package/dist/types/errors.mjs.map +1 -1
- package/dist/types/index.d.mts +42 -4
- package/dist/utils/buildS3Path.d.mts +10 -0
- package/dist/utils/buildS3Path.mjs +16 -0
- package/dist/utils/buildS3Path.mjs.map +1 -0
- package/dist/utils/buildThumbnailURL.d.mts +14 -0
- package/dist/utils/buildThumbnailURL.mjs +10 -0
- package/dist/utils/buildThumbnailURL.mjs.map +1 -0
- package/dist/utils/defaultOptions.d.mts +7 -0
- package/dist/utils/defaultOptions.mjs +12 -0
- package/dist/utils/defaultOptions.mjs.map +1 -0
- package/dist/utils/file.d.mts +16 -2
- package/dist/utils/file.mjs +58 -6
- package/dist/utils/file.mjs.map +1 -1
- package/dist/utils/mux.mjs +19 -8
- package/dist/utils/mux.mjs.map +1 -1
- package/dist/utils/tus.d.mts +9 -6
- package/dist/utils/tus.mjs +31 -11
- package/dist/utils/tus.mjs.map +1 -1
- package/package.json +11 -4
- package/dist/components/mux-preview/index.d.mts +0 -2
- package/dist/components/mux-preview/index.mjs +0 -3
- package/dist/components/mux-preview/mux-preview.mjs +0 -29
- package/dist/components/mux-preview/mux-preview.mjs.map +0 -1
- package/dist/components/upload-handler/index.d.mts +0 -2
- package/dist/components/upload-handler/index.mjs +0 -3
- package/dist/components/upload-handler/upload-handler.d.mts +0 -22
- package/dist/components/upload-handler/upload-handler.mjs.map +0 -1
- package/dist/components/upload-manager/index.d.mts +0 -2
- package/dist/components/upload-manager/index.mjs +0 -3
- package/dist/components/upload-manager/upload-manager.mjs +0 -273
- package/dist/components/upload-manager/upload-manager.mjs.map +0 -1
- package/dist/endpoints/tusFileExistsHandler.d.mts +0 -11
- package/dist/endpoints/tusFileExistsHandler.mjs.map +0 -1
- package/dist/tus/stores/s3/expiration-manager.mjs.map +0 -1
- package/dist/tus/stores/s3/file-operations.mjs.map +0 -1
- package/dist/tus/stores/s3/metadata-manager.mjs.map +0 -1
- package/dist/tus/stores/s3/parts-manager.mjs.map +0 -1
- package/dist/tus/stores/s3/s3-store.mjs.map +0 -1
- /package/dist/components/{upload-manager/upload-manager.css → uploadManager/uploadManager.css} +0 -0
package/dist/components/{upload-handler/upload-handler.mjs → uploadHandler/uploadHandler.mjs}
RENAMED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { MediaCloudErrors, MediaCloudLogs } from "../../types/errors.mjs";
|
|
4
|
+
import { useMagicError } from "../../error-handler/dist/index.mjs";
|
|
4
5
|
import { useErrorHandler } from "../../hooks/useErrorHandler.mjs";
|
|
5
|
-
import { generateUniqueFilename,
|
|
6
|
+
import { generateUniqueFilename, getMimeType, isVideo, sanitizeFilename } from "../../utils/file.mjs";
|
|
6
7
|
import { useMediaCloudEmitter } from "../../hooks/useMediaCloudEmitter.mjs";
|
|
7
8
|
import * as upchunk from "@mux/upchunk";
|
|
8
9
|
import * as tus from "tus-js-client";
|
|
9
|
-
import { toast } from "@payloadcms/ui";
|
|
10
10
|
import { createClientUploadHandler } from "@payloadcms/plugin-cloud-storage/client";
|
|
11
11
|
|
|
12
|
-
//#region src/components/
|
|
13
|
-
const { logError, throwError } = useErrorHandler();
|
|
14
|
-
const emitter = useMediaCloudEmitter();
|
|
12
|
+
//#region src/components/uploadHandler/uploadHandler.tsx
|
|
15
13
|
const MUX_CHUNK_SIZE = 30720;
|
|
16
14
|
const TUS_CHUNK_SIZE = 1024 * 1024;
|
|
17
15
|
const TUS_RETRY_DELAYS = [
|
|
@@ -20,6 +18,9 @@ const TUS_RETRY_DELAYS = [
|
|
|
20
18
|
2e3,
|
|
21
19
|
5e3
|
|
22
20
|
];
|
|
21
|
+
const magicError = useMagicError({ prefix: "PLUGIN-MEDIA-CLOUD" });
|
|
22
|
+
const { throwError } = magicError;
|
|
23
|
+
const emitter = useMediaCloudEmitter();
|
|
23
24
|
/**
|
|
24
25
|
* Handles Mux video upload with progress tracking
|
|
25
26
|
* @param args - The upload arguments including file, server URL, and callbacks
|
|
@@ -27,9 +28,10 @@ const TUS_RETRY_DELAYS = [
|
|
|
27
28
|
*/
|
|
28
29
|
async function muxUpload(args) {
|
|
29
30
|
const { file, serverURL, apiRoute, mimeType } = args;
|
|
31
|
+
const endpoint = `${serverURL}${apiRoute}`;
|
|
30
32
|
const filename = file.name;
|
|
31
33
|
try {
|
|
32
|
-
const { url, uploadId } = await (await fetch(`${
|
|
34
|
+
const { url, uploadId } = await (await fetch(`${endpoint}/mux/upload`, {
|
|
33
35
|
body: JSON.stringify({
|
|
34
36
|
filename,
|
|
35
37
|
mimeType
|
|
@@ -47,12 +49,11 @@ async function muxUpload(args) {
|
|
|
47
49
|
filename,
|
|
48
50
|
uploadId,
|
|
49
51
|
polling: false,
|
|
50
|
-
pollingUrl: `${
|
|
52
|
+
pollingUrl: `${endpoint}/mux/asset`
|
|
51
53
|
});
|
|
52
54
|
uploader.on("error", function() {
|
|
53
|
-
logError(MediaCloudErrors.MUX_UPLOAD_ERROR.message);
|
|
54
|
-
toast.error("Video upload failed");
|
|
55
55
|
emitter.emit("removeUpload", { uploadId });
|
|
56
|
+
throwError(MediaCloudErrors.MUX_UPLOAD_ERROR);
|
|
56
57
|
});
|
|
57
58
|
uploader.on("progress", function(progress) {
|
|
58
59
|
emitter.emit("updateUpload", {
|
|
@@ -69,9 +70,12 @@ async function muxUpload(args) {
|
|
|
69
70
|
mimeType,
|
|
70
71
|
storage: "mux"
|
|
71
72
|
};
|
|
72
|
-
} catch
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
} catch {
|
|
74
|
+
throwError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR);
|
|
75
|
+
emitter.emit("uploadError", {
|
|
76
|
+
filename,
|
|
77
|
+
error: "Video upload failed"
|
|
78
|
+
});
|
|
75
79
|
return null;
|
|
76
80
|
}
|
|
77
81
|
}
|
|
@@ -81,10 +85,11 @@ async function muxUpload(args) {
|
|
|
81
85
|
* @returns Promise that resolves to upload result or null if upload fails
|
|
82
86
|
*/
|
|
83
87
|
async function tusUpload(args) {
|
|
84
|
-
const { apiRoute, serverURL, file, mimeType } = args;
|
|
88
|
+
const { apiRoute, serverURL, file, prefix = "", mimeType } = args;
|
|
85
89
|
const filename = file.name;
|
|
86
90
|
const filetype = file.type;
|
|
87
91
|
const filesize = file.size.toString();
|
|
92
|
+
const endpoint = `${serverURL}${apiRoute}/uploads`;
|
|
88
93
|
Object.keys(localStorage).filter((key) => key.startsWith("tus::")).forEach((key) => localStorage.removeItem(key));
|
|
89
94
|
let uploadUrlAvailable = false;
|
|
90
95
|
let eventListenerAdded = false;
|
|
@@ -94,11 +99,11 @@ async function tusUpload(args) {
|
|
|
94
99
|
}
|
|
95
100
|
function onPageUnload() {
|
|
96
101
|
window.removeEventListener("unload", onPageUnload);
|
|
97
|
-
navigator.sendBeacon(`${
|
|
102
|
+
navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }));
|
|
98
103
|
}
|
|
99
104
|
return new Promise((resolve) => {
|
|
100
105
|
new tus.Upload(file, {
|
|
101
|
-
endpoint
|
|
106
|
+
endpoint,
|
|
102
107
|
retryDelays: TUS_RETRY_DELAYS,
|
|
103
108
|
chunkSize: TUS_CHUNK_SIZE,
|
|
104
109
|
storeFingerprintForResuming: false,
|
|
@@ -106,16 +111,22 @@ async function tusUpload(args) {
|
|
|
106
111
|
filetype,
|
|
107
112
|
filesize,
|
|
108
113
|
filename,
|
|
114
|
+
prefix,
|
|
109
115
|
contentType: filetype,
|
|
110
116
|
contentLength: filesize,
|
|
111
117
|
contentDisposition: "inline"
|
|
112
118
|
},
|
|
113
119
|
onError(error) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }));
|
|
121
|
+
emitter.emit("uploadError", {
|
|
122
|
+
filename,
|
|
123
|
+
error: error.message
|
|
124
|
+
});
|
|
117
125
|
emitter.emit("removeUpload", { filename });
|
|
118
|
-
|
|
126
|
+
throwError({
|
|
127
|
+
...MediaCloudErrors.TUS_UPLOAD_ERROR,
|
|
128
|
+
cause: error
|
|
129
|
+
});
|
|
119
130
|
resolve(null);
|
|
120
131
|
},
|
|
121
132
|
onBeforeRequest() {
|
|
@@ -132,11 +143,12 @@ async function tusUpload(args) {
|
|
|
132
143
|
progress: percentage
|
|
133
144
|
});
|
|
134
145
|
},
|
|
135
|
-
onSuccess() {
|
|
146
|
+
async onSuccess() {
|
|
136
147
|
window.removeEventListener("beforeunload", onBeforeUnload);
|
|
137
148
|
window.removeEventListener("unload", onPageUnload);
|
|
138
149
|
emitter.emit("uploadComplete", { filename });
|
|
139
|
-
fetch(`${
|
|
150
|
+
await fetch(`${endpoint}/${filename}/process`);
|
|
151
|
+
await fetch(`${endpoint}/${filename}/folder`);
|
|
140
152
|
},
|
|
141
153
|
onUploadUrlAvailable: async function() {
|
|
142
154
|
if (uploadUrlAvailable) return;
|
|
@@ -152,42 +164,60 @@ async function tusUpload(args) {
|
|
|
152
164
|
});
|
|
153
165
|
}
|
|
154
166
|
const { log } = useErrorHandler();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
function UploadHandler(props) {
|
|
168
|
+
return createClientUploadHandler({ handler: async function(args) {
|
|
169
|
+
const { serverURL, apiRoute, file, prefix, updateFilename, extra } = args;
|
|
170
|
+
const { pluginOptions } = extra;
|
|
171
|
+
const mimeType = await getMimeType(file);
|
|
172
|
+
magicError.assert(mimeType, MediaCloudErrors.FILE_TYPE_UNKNOWN);
|
|
173
|
+
if (!(pluginOptions.limits?.mimeTypes ?? []).some((allowed) => allowed.endsWith("/*") ? mimeType?.startsWith(allowed.replace("/*", "/")) : mimeType === allowed)) {
|
|
174
|
+
throwError(MediaCloudErrors.FILE_TYPE_NOT_ALLOWED);
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
if (file.size > (pluginOptions.limits?.fileSize ?? Infinity)) {
|
|
178
|
+
throwError(MediaCloudErrors.FILE_SIZE_EXCEEDED);
|
|
161
179
|
return null;
|
|
162
180
|
}
|
|
163
|
-
const isVideoFile = await isVideo(file);
|
|
164
181
|
let mappedFile = file;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
182
|
+
try {
|
|
183
|
+
const endpoint = `${serverURL}${apiRoute}/uploads`;
|
|
184
|
+
const response = await fetch(`${endpoint}/${file.name}/exists`);
|
|
185
|
+
if (response?.status === 200) log(MediaCloudLogs.S3_STORE_FILE_FOUND);
|
|
186
|
+
const newFilename = response?.status === 200 ? generateUniqueFilename(file.name) : sanitizeFilename(file.name);
|
|
187
|
+
mappedFile = new File([file], newFilename, { type: file.type });
|
|
188
|
+
await updateFilename(newFilename);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
throwError({
|
|
191
|
+
...MediaCloudErrors.NAMING_FUNCTION_ERROR,
|
|
192
|
+
cause: error
|
|
193
|
+
});
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const uploadArgs = {
|
|
198
|
+
file: mappedFile,
|
|
199
|
+
serverURL,
|
|
200
|
+
apiRoute,
|
|
201
|
+
mimeType,
|
|
202
|
+
prefix
|
|
203
|
+
};
|
|
204
|
+
const storageForMimeType = pluginOptions.storage && Object.prototype.hasOwnProperty.call(pluginOptions.storage, mimeType) ? pluginOptions.storage[mimeType] : void 0;
|
|
205
|
+
const isVideoFile = await isVideo(file);
|
|
206
|
+
const storeOnMux = pluginOptions.storage?.["video/*"] === "mux" || storageForMimeType === "mux";
|
|
207
|
+
switch (true) {
|
|
208
|
+
case storeOnMux && isVideoFile: return await muxUpload(uploadArgs);
|
|
209
|
+
default: return await tusUpload(uploadArgs);
|
|
171
210
|
}
|
|
172
|
-
} catch (
|
|
173
|
-
|
|
211
|
+
} catch (error) {
|
|
212
|
+
throwError({
|
|
213
|
+
...MediaCloudErrors.UPLOAD_HANDLER_ERROR,
|
|
214
|
+
cause: error
|
|
215
|
+
});
|
|
216
|
+
return null;
|
|
174
217
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
serverURL,
|
|
178
|
-
apiRoute,
|
|
179
|
-
mimeType
|
|
180
|
-
};
|
|
181
|
-
if (isVideoFile) return await muxUpload(uploadArgs);
|
|
182
|
-
else return await tusUpload(uploadArgs);
|
|
183
|
-
} catch (error) {
|
|
184
|
-
console.error("[PLUGIN-MEDIA-CLOUD] Upload handler detailed error:", error);
|
|
185
|
-
logError(MediaCloudErrors.UPLOAD_HANDLER_ERROR.message);
|
|
186
|
-
toast.error(`Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
} });
|
|
218
|
+
} })(props);
|
|
219
|
+
}
|
|
190
220
|
|
|
191
221
|
//#endregion
|
|
192
222
|
export { UploadHandler };
|
|
193
|
-
//# sourceMappingURL=
|
|
223
|
+
//# sourceMappingURL=uploadHandler.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadHandler.mjs","names":["upchunk","tus","createClientUploadHandler","MediaCloudErrors","MediaCloudLogs","useMediaCloudEmitter","useErrorHandler","isVideo","getMimeType","generateUniqueFilename","sanitizeFilename","MediaCloudPluginOptions","Storage","MimeType","ReactNode","UploadCollectionSlug","useMagicError","UseMagicErrorReturn","UploadArgs","serverURL","apiRoute","file","File","mimeType","prefix","UploadResult","storage","filename","uploadId","MuxCreateUploadResponse","url","MUX_CHUNK_SIZE","TUS_CHUNK_SIZE","TUS_RETRY_DELAYS","magicError","throwError","emitter","muxUpload","args","Promise","endpoint","name","response","fetch","body","JSON","stringify","credentials","method","headers","json","uploader","createUpload","chunkSize","emit","polling","pollingUrl","on","MUX_UPLOAD_ERROR","progress","detail","MUX_DIRECT_UPLOAD_ERROR","error","tusUpload","filetype","type","filesize","size","toString","Object","keys","localStorage","filter","key","startsWith","forEach","removeItem","uploadUrlAvailable","eventListenerAdded","onBeforeUnload","e","BeforeUnloadEvent","window","removeEventListener","preventDefault","onPageUnload","navigator","sendBeacon","resolve","upload","Upload","retryDelays","storeFingerprintForResuming","metadata","contentType","contentLength","contentDisposition","onError","message","TUS_UPLOAD_ERROR","cause","onBeforeRequest","addEventListener","onProgress","bytesUploaded","bytesTotal","percentage","Math","round","onSuccess","onUploadUrlAvailable","start","log","Extra","pluginOptions","ClientUploadHandlerProps","Record","children","collectionSlug","enabled","extra","T","serverHandlerPath","UploadHandler","props","handler","updateFilename","assert","FILE_TYPE_UNKNOWN","allowedMimeTypes","limits","mimeTypes","mimeTypeMatches","some","allowed","endsWith","replace","FILE_TYPE_NOT_ALLOWED","fileSize","Infinity","FILE_SIZE_EXCEEDED","mappedFile","status","S3_STORE_FILE_FOUND","newFilename","NAMING_FUNCTION_ERROR","uploadArgs","StorageMap","NonNullable","storageForMimeType","prototype","hasOwnProperty","call","undefined","isVideoFile","storeOnMux","UPLOAD_HANDLER_ERROR"],"sources":["../../../src/components/uploadHandler/uploadHandler.tsx"],"sourcesContent":["'use client'\n\nimport * as upchunk from '@mux/upchunk'\nimport * as tus from 'tus-js-client'\n\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\n\nimport { MediaCloudErrors, MediaCloudLogs } from '../../types/errors'\nimport { useMediaCloudEmitter } from '../../hooks/useMediaCloudEmitter'\nimport { useErrorHandler } from '../../hooks/useErrorHandler'\nimport {\n isVideo,\n getMimeType,\n generateUniqueFilename,\n sanitizeFilename,\n} from '../../utils/file'\n\nimport type {\n MediaCloudPluginOptions,\n Storage,\n MimeType,\n} from '../../types/index'\nimport type { ReactNode } from 'react'\nimport type { UploadCollectionSlug } from 'payload'\nimport { useMagicError, UseMagicErrorReturn } from '@maas/error-handler'\n\ninterface UploadArgs {\n serverURL: string\n apiRoute: string\n file: File\n mimeType: MimeType\n prefix?: string\n}\n\ninterface UploadResult {\n storage: Storage\n mimeType: MimeType\n filename: string\n uploadId?: string\n}\n\ninterface MuxCreateUploadResponse {\n url: string\n uploadId: string\n filename: string\n}\n\nconst MUX_CHUNK_SIZE = 30720\nconst TUS_CHUNK_SIZE = 1024 * 1024\nconst TUS_RETRY_DELAYS = [0, 1000, 2000, 5000]\n\nconst magicError: UseMagicErrorReturn = useMagicError({\n prefix: 'PLUGIN-MEDIA-CLOUD',\n})\n\nconst { throwError } = magicError\nconst emitter = useMediaCloudEmitter()\n\n/**\n * Handles Mux video upload with progress tracking\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function muxUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { file, serverURL, apiRoute, mimeType } = args\n\n const endpoint = `${serverURL}${apiRoute}`\n const filename = file.name\n\n try {\n // Request upload URL from Mux\n const response = await fetch(`${endpoint}/mux/upload`, {\n body: JSON.stringify({ filename, mimeType }),\n credentials: 'include',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n\n const { url, uploadId } = (await response.json()) as MuxCreateUploadResponse\n\n // Create upchunk uploader\n const uploader = await upchunk.createUpload({\n endpoint: url,\n file,\n chunkSize: MUX_CHUNK_SIZE,\n })\n\n // Add upload to tracker\n emitter.emit('addUpload', {\n filename,\n uploadId,\n polling: false,\n pollingUrl: `${endpoint}/mux/asset`,\n })\n\n // Set up event handlers\n uploader.on('error', function () {\n emitter.emit('removeUpload', { uploadId })\n throwError(MediaCloudErrors.MUX_UPLOAD_ERROR)\n })\n\n uploader.on('progress', function (progress) {\n emitter.emit('updateUpload', {\n filename,\n progress: progress.detail,\n })\n })\n\n uploader.on('success', function () {\n emitter.emit('uploadComplete', { filename })\n })\n\n // Update collection entry\n // with filename, uploadId, mimeType, and storage\n return {\n filename,\n uploadId,\n mimeType,\n storage: 'mux',\n }\n } catch {\n throwError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR)\n emitter.emit('uploadError', { filename, error: 'Video upload failed' })\n return null\n }\n}\n\n/**\n * Handles TUS file upload with resumable capabilities\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function tusUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { apiRoute, serverURL, file, prefix = '', mimeType } = args\n\n const filename = file.name\n const filetype = file.type\n const filesize = file.size.toString()\n\n const endpoint = `${serverURL}${apiRoute}/uploads`\n\n // Clear any stale TUS uploads from localStorage\n Object.keys(localStorage)\n .filter((key) => key.startsWith('tus::'))\n .forEach((key) => localStorage.removeItem(key))\n\n // Flag to prevent multiple onUploadUrlAvailable calls\n let uploadUrlAvailable = false\n let eventListenerAdded = false\n\n function onBeforeUnload(e: BeforeUnloadEvent) {\n window.removeEventListener('beforeunload', onBeforeUnload)\n e.preventDefault()\n }\n\n function onPageUnload() {\n window.removeEventListener('unload', onPageUnload)\n navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }))\n }\n\n return new Promise((resolve) => {\n const upload = new tus.Upload(file, {\n endpoint,\n retryDelays: TUS_RETRY_DELAYS,\n chunkSize: TUS_CHUNK_SIZE,\n storeFingerprintForResuming: false,\n metadata: {\n filetype,\n filesize,\n filename,\n prefix,\n contentType: filetype,\n contentLength: filesize,\n contentDisposition: 'inline',\n },\n onError(error) {\n // Clean up\n navigator.sendBeacon(\n `${endpoint}/cleanup`,\n JSON.stringify({ filename })\n )\n\n // Inform user\n emitter.emit('uploadError', { filename, error: error.message })\n emitter.emit('removeUpload', { filename })\n throwError({ ...MediaCloudErrors.TUS_UPLOAD_ERROR, cause: error })\n resolve(null)\n },\n onBeforeRequest() {\n if (!eventListenerAdded) {\n window.addEventListener('beforeunload', onBeforeUnload)\n window.addEventListener('unload', onPageUnload)\n eventListenerAdded = true\n }\n },\n onProgress: function (bytesUploaded, bytesTotal) {\n const percentage = Math.round((bytesUploaded / bytesTotal) * 100)\n emitter.emit('updateUpload', {\n filename,\n progress: percentage,\n })\n },\n async onSuccess() {\n // Clean up beforeunload listener\n window.removeEventListener('beforeunload', onBeforeUnload)\n window.removeEventListener('unload', onPageUnload)\n\n // Mark upload as complete in UI\n emitter.emit('uploadComplete', { filename })\n\n // Trigger post upload processing\n await fetch(`${endpoint}/${filename}/process`)\n\n // Move file to correct folder\n await fetch(`${endpoint}/${filename}/folder`)\n },\n onUploadUrlAvailable: async function () {\n // Prevent multiple callbacks\n if (uploadUrlAvailable) {\n return\n }\n\n // Update flag\n uploadUrlAvailable = true\n\n // Add upload to UI\n emitter.emit('addUpload', { filename })\n\n // Update collection entry\n // with filename, mimeType, and storage\n resolve({\n filename,\n mimeType,\n storage: 's3',\n })\n },\n })\n\n upload.start()\n })\n}\n\nconst { log } = useErrorHandler()\n\ninterface Extra {\n pluginOptions: MediaCloudPluginOptions\n}\n\ntype ClientUploadHandlerProps<T extends Record<string, unknown>> = {\n children: ReactNode\n collectionSlug: UploadCollectionSlug\n enabled?: boolean\n extra: T\n prefix?: string\n serverHandlerPath: `/${string}`\n}\n\nexport function UploadHandler(\n props: ClientUploadHandlerProps<{ pluginOptions: MediaCloudPluginOptions }>\n) {\n return createClientUploadHandler({\n handler: async function (args) {\n const { serverURL, apiRoute, file, prefix, updateFilename, extra } = args\n const { pluginOptions } = extra as unknown as Extra\n\n // Check mime type\n const mimeType = await getMimeType(file)\n\n magicError.assert(mimeType, MediaCloudErrors.FILE_TYPE_UNKNOWN)\n\n const allowedMimeTypes = pluginOptions.limits?.mimeTypes ?? []\n const mimeTypeMatches = allowedMimeTypes.some((allowed) =>\n allowed.endsWith('/*')\n ? mimeType?.startsWith(allowed.replace('/*', '/'))\n : mimeType === allowed\n )\n\n if (!mimeTypeMatches) {\n throwError(MediaCloudErrors.FILE_TYPE_NOT_ALLOWED)\n return null\n }\n\n // Check file size limit\n if (file.size > (pluginOptions.limits?.fileSize ?? Infinity)) {\n throwError(MediaCloudErrors.FILE_SIZE_EXCEEDED)\n return null\n }\n\n // Clone file\n let mappedFile = file\n\n try {\n // Check if file with same name exists\n const endpoint = `${serverURL}${apiRoute}/uploads`\n const response = await fetch(`${endpoint}/${file.name}/exists`)\n\n if (response?.status === 200) {\n log(MediaCloudLogs.S3_STORE_FILE_FOUND)\n }\n\n // If file exists, generate a cloned file with a unique filename\n // If not, generate a cloned file with a sanitized filename\n const newFilename =\n response?.status === 200\n ? generateUniqueFilename(file.name)\n : sanitizeFilename(file.name)\n\n mappedFile = new File([file], newFilename, {\n type: file.type,\n })\n\n await updateFilename(newFilename)\n } catch (error) {\n throwError({\n ...MediaCloudErrors.NAMING_FUNCTION_ERROR,\n cause: error,\n })\n return null\n }\n\n try {\n const uploadArgs: UploadArgs = {\n file: mappedFile,\n serverURL,\n apiRoute,\n mimeType,\n prefix,\n }\n\n // Check storage mapping for mime type\n type StorageMap = NonNullable<typeof pluginOptions.storage>\n\n const storageForMimeType =\n pluginOptions.storage &&\n Object.prototype.hasOwnProperty.call(pluginOptions.storage, mimeType)\n ? pluginOptions.storage[mimeType as keyof StorageMap]\n : undefined\n\n const isVideoFile = await isVideo(file)\n const storeOnMux =\n pluginOptions.storage?.['video/*'] === 'mux' ||\n storageForMimeType === 'mux'\n\n switch (true) {\n case storeOnMux && isVideoFile:\n return await muxUpload(uploadArgs)\n default:\n return await tusUpload(uploadArgs)\n }\n } catch (error) {\n throwError({ ...MediaCloudErrors.UPLOAD_HANDLER_ERROR, cause: error })\n return null\n }\n },\n })(props)\n}\n"],"mappings":"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"}
|
package/dist/components/{upload-manager/upload-manager.d.mts → uploadManager/uploadManager.d.mts}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MediaCloudEmitterEvents } from "../../types/index.mjs";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import "./
|
|
3
|
+
import "./uploadManager.css";
|
|
4
4
|
|
|
5
|
-
//#region src/components/
|
|
5
|
+
//#region src/components/uploadManager/uploadManager.d.ts
|
|
6
6
|
interface Upload {
|
|
7
7
|
filename: string;
|
|
8
8
|
progress: number;
|
|
@@ -30,4 +30,4 @@ declare function UploadManagerProvider(args: UploadManagerProviderArgs): React.J
|
|
|
30
30
|
declare const useUploadManagerContext: () => UploadManagerContextType;
|
|
31
31
|
//#endregion
|
|
32
32
|
export { UploadManagerProvider, useUploadManagerContext };
|
|
33
|
-
//# sourceMappingURL=
|
|
33
|
+
//# sourceMappingURL=uploadManager.d.mts.map
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { MediaCloudErrors } from "../../types/errors.mjs";
|
|
4
|
+
import { useErrorHandler } from "../../hooks/useErrorHandler.mjs";
|
|
5
|
+
import { useMediaCloudEmitter } from "../../hooks/useMediaCloudEmitter.mjs";
|
|
6
|
+
import { c } from "react/compiler-runtime";
|
|
7
|
+
import { createContext, use, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { Button } from "@payloadcms/ui";
|
|
9
|
+
import "./uploadManager.css";
|
|
10
|
+
|
|
11
|
+
//#region src/components/uploadManager/uploadManager.tsx
|
|
12
|
+
const UploadManagerContext = createContext({
|
|
13
|
+
showUploadManager: false,
|
|
14
|
+
activeUploads: [],
|
|
15
|
+
addUpload: () => {},
|
|
16
|
+
updateUpload: () => {}
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Provider component for upload management context
|
|
20
|
+
* @param args - Arguments including children to wrap
|
|
21
|
+
* @returns JSX element providing upload management context
|
|
22
|
+
*/
|
|
23
|
+
function UploadManagerProvider(args) {
|
|
24
|
+
const $ = c(40);
|
|
25
|
+
const { children } = args;
|
|
26
|
+
const [showUploadManager, setShowUploadManager] = useState(false);
|
|
27
|
+
let t0;
|
|
28
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
29
|
+
t0 = [];
|
|
30
|
+
$[0] = t0;
|
|
31
|
+
} else t0 = $[0];
|
|
32
|
+
const [activeUploads, setActiveUploads] = useState(t0);
|
|
33
|
+
const [activeTab, setActiveTab] = useState("uploading");
|
|
34
|
+
const emitter = useMediaCloudEmitter();
|
|
35
|
+
const activeTabRef = useRef(activeTab);
|
|
36
|
+
const activeUploadsRef = useRef(activeUploads);
|
|
37
|
+
const { logError } = useErrorHandler();
|
|
38
|
+
let t1;
|
|
39
|
+
let t2;
|
|
40
|
+
if ($[1] !== activeTab) {
|
|
41
|
+
t1 = () => {
|
|
42
|
+
activeTabRef.current = activeTab;
|
|
43
|
+
};
|
|
44
|
+
t2 = [activeTab];
|
|
45
|
+
$[1] = activeTab;
|
|
46
|
+
$[2] = t1;
|
|
47
|
+
$[3] = t2;
|
|
48
|
+
} else {
|
|
49
|
+
t1 = $[2];
|
|
50
|
+
t2 = $[3];
|
|
51
|
+
}
|
|
52
|
+
useEffect(t1, t2);
|
|
53
|
+
let t3;
|
|
54
|
+
let t4;
|
|
55
|
+
if ($[4] !== activeUploads) {
|
|
56
|
+
t3 = () => {
|
|
57
|
+
activeUploadsRef.current = activeUploads;
|
|
58
|
+
};
|
|
59
|
+
t4 = [activeUploads];
|
|
60
|
+
$[4] = activeUploads;
|
|
61
|
+
$[5] = t3;
|
|
62
|
+
$[6] = t4;
|
|
63
|
+
} else {
|
|
64
|
+
t3 = $[5];
|
|
65
|
+
t4 = $[6];
|
|
66
|
+
}
|
|
67
|
+
useEffect(t3, t4);
|
|
68
|
+
let t5;
|
|
69
|
+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
|
70
|
+
t5 = (uploads) => {
|
|
71
|
+
const hasActiveUploads = uploads.some(_temp);
|
|
72
|
+
const hasProcessingUploads = uploads.some(_temp2);
|
|
73
|
+
const hasCompletedUploads = uploads.some(_temp3);
|
|
74
|
+
if (!hasActiveUploads && !hasProcessingUploads && hasCompletedUploads && activeTabRef.current !== "completed") setActiveTab("completed");
|
|
75
|
+
};
|
|
76
|
+
$[7] = t5;
|
|
77
|
+
} else t5 = $[7];
|
|
78
|
+
const checkAutoSwitchToCompleted = t5;
|
|
79
|
+
let t6;
|
|
80
|
+
let t7;
|
|
81
|
+
if ($[8] !== activeUploads || $[9] !== logError) {
|
|
82
|
+
t6 = () => {
|
|
83
|
+
const pollingUploads = activeUploads.filter(_temp4);
|
|
84
|
+
if (pollingUploads.length === 0) return;
|
|
85
|
+
const pollAssets = async () => {
|
|
86
|
+
for (const pollingUpload of pollingUploads) try {
|
|
87
|
+
const response = await fetch(`${pollingUpload.pollingUrl}?upload_id=${pollingUpload.uploadId}`, {
|
|
88
|
+
method: "GET",
|
|
89
|
+
credentials: "include"
|
|
90
|
+
});
|
|
91
|
+
if (response.ok) {
|
|
92
|
+
if ((await response.json()).ready) setActiveUploads((prev) => {
|
|
93
|
+
const updatedUploads = prev.map((upload_3) => upload_3.uploadId === pollingUpload.uploadId ? {
|
|
94
|
+
...upload_3,
|
|
95
|
+
polling: false,
|
|
96
|
+
progress: 100,
|
|
97
|
+
status: "completed"
|
|
98
|
+
} : upload_3);
|
|
99
|
+
setTimeout(() => checkAutoSwitchToCompleted(updatedUploads), 0);
|
|
100
|
+
return updatedUploads;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
} catch (t8$1) {
|
|
104
|
+
logError(MediaCloudErrors.UPLOAD_POLLING_ERROR.message);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const intervalId = setInterval(pollAssets, 2e3);
|
|
108
|
+
return () => clearInterval(intervalId);
|
|
109
|
+
};
|
|
110
|
+
t7 = [
|
|
111
|
+
activeUploads,
|
|
112
|
+
checkAutoSwitchToCompleted,
|
|
113
|
+
logError
|
|
114
|
+
];
|
|
115
|
+
$[8] = activeUploads;
|
|
116
|
+
$[9] = logError;
|
|
117
|
+
$[10] = t6;
|
|
118
|
+
$[11] = t7;
|
|
119
|
+
} else {
|
|
120
|
+
t6 = $[10];
|
|
121
|
+
t7 = $[11];
|
|
122
|
+
}
|
|
123
|
+
useEffect(t6, t7);
|
|
124
|
+
let t8;
|
|
125
|
+
if ($[12] !== logError) {
|
|
126
|
+
t8 = (event) => {
|
|
127
|
+
const { filename, error } = event;
|
|
128
|
+
logError(MediaCloudErrors.TUS_UPLOAD_ERROR.message);
|
|
129
|
+
setActiveUploads((prev_0) => prev_0.map((upload_4) => upload_4.filename === filename ? {
|
|
130
|
+
...upload_4,
|
|
131
|
+
error,
|
|
132
|
+
status: "completed"
|
|
133
|
+
} : upload_4));
|
|
134
|
+
};
|
|
135
|
+
$[12] = logError;
|
|
136
|
+
$[13] = t8;
|
|
137
|
+
} else t8 = $[13];
|
|
138
|
+
const onUploadError = t8;
|
|
139
|
+
let t9;
|
|
140
|
+
if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
|
|
141
|
+
t9 = (event_0) => {
|
|
142
|
+
const upload_5 = {
|
|
143
|
+
filename: event_0.filename,
|
|
144
|
+
uploadId: event_0.uploadId,
|
|
145
|
+
progress: 0,
|
|
146
|
+
polling: event_0.polling,
|
|
147
|
+
pollingUrl: event_0.pollingUrl,
|
|
148
|
+
status: "uploading"
|
|
149
|
+
};
|
|
150
|
+
setActiveUploads((prev_1) => [...prev_1, upload_5]);
|
|
151
|
+
setShowUploadManager(true);
|
|
152
|
+
if (activeTabRef.current !== "uploading") setActiveTab("uploading");
|
|
153
|
+
};
|
|
154
|
+
$[14] = t9;
|
|
155
|
+
} else t9 = $[14];
|
|
156
|
+
const onAddUpload = t9;
|
|
157
|
+
let t10;
|
|
158
|
+
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
|
159
|
+
t10 = (event_1) => {
|
|
160
|
+
const { filename: filename_0, progress, polling } = event_1;
|
|
161
|
+
setActiveUploads((prev_2) => prev_2.map((upload_6) => upload_6.filename === filename_0 ? {
|
|
162
|
+
...upload_6,
|
|
163
|
+
progress,
|
|
164
|
+
...polling !== void 0 && { polling },
|
|
165
|
+
status: polling ? "processing" : progress >= 100 ? "completed" : "uploading"
|
|
166
|
+
} : upload_6));
|
|
167
|
+
};
|
|
168
|
+
$[15] = t10;
|
|
169
|
+
} else t10 = $[15];
|
|
170
|
+
const onUpdateUpload = t10;
|
|
171
|
+
let t11;
|
|
172
|
+
if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
|
|
173
|
+
t11 = (event_2) => {
|
|
174
|
+
setActiveUploads((prev_3) => prev_3.filter((upload_7) => upload_7.filename !== event_2.filename));
|
|
175
|
+
};
|
|
176
|
+
$[16] = t11;
|
|
177
|
+
} else t11 = $[16];
|
|
178
|
+
const onRemoveUpload = t11;
|
|
179
|
+
let t12;
|
|
180
|
+
if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
|
|
181
|
+
t12 = (event_3) => {
|
|
182
|
+
if (activeUploadsRef.current.find((upload_8) => upload_8.filename === event_3.filename)?.pollingUrl) setActiveUploads((prev_4) => prev_4.map((upload_10) => upload_10.filename === event_3.filename ? {
|
|
183
|
+
...upload_10,
|
|
184
|
+
polling: true,
|
|
185
|
+
progress: 100,
|
|
186
|
+
status: "processing"
|
|
187
|
+
} : upload_10));
|
|
188
|
+
else setActiveUploads((prev_5) => {
|
|
189
|
+
const updatedUploads_0 = prev_5.map((upload_11) => upload_11.filename === event_3.filename ? {
|
|
190
|
+
...upload_11,
|
|
191
|
+
progress: 100,
|
|
192
|
+
status: "completed"
|
|
193
|
+
} : upload_11);
|
|
194
|
+
setTimeout(() => checkAutoSwitchToCompleted(updatedUploads_0), 0);
|
|
195
|
+
return updatedUploads_0;
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
$[17] = t12;
|
|
199
|
+
} else t12 = $[17];
|
|
200
|
+
const onUploadComplete = t12;
|
|
201
|
+
let t13;
|
|
202
|
+
let t14;
|
|
203
|
+
if ($[18] !== emitter || $[19] !== onUploadError) {
|
|
204
|
+
t13 = () => {
|
|
205
|
+
emitter.on("addUpload", onAddUpload);
|
|
206
|
+
emitter.on("updateUpload", onUpdateUpload);
|
|
207
|
+
emitter.on("removeUpload", onRemoveUpload);
|
|
208
|
+
emitter.on("uploadError", onUploadError);
|
|
209
|
+
emitter.on("uploadComplete", onUploadComplete);
|
|
210
|
+
return () => {
|
|
211
|
+
emitter.off("addUpload", onAddUpload);
|
|
212
|
+
emitter.off("updateUpload", onUpdateUpload);
|
|
213
|
+
emitter.off("removeUpload", onRemoveUpload);
|
|
214
|
+
emitter.off("uploadError", onUploadError);
|
|
215
|
+
emitter.off("uploadComplete", onUploadComplete);
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
t14 = [
|
|
219
|
+
emitter,
|
|
220
|
+
onAddUpload,
|
|
221
|
+
onUpdateUpload,
|
|
222
|
+
onRemoveUpload,
|
|
223
|
+
onUploadError,
|
|
224
|
+
onUploadComplete
|
|
225
|
+
];
|
|
226
|
+
$[18] = emitter;
|
|
227
|
+
$[19] = onUploadError;
|
|
228
|
+
$[20] = t13;
|
|
229
|
+
$[21] = t14;
|
|
230
|
+
} else {
|
|
231
|
+
t13 = $[20];
|
|
232
|
+
t14 = $[21];
|
|
233
|
+
}
|
|
234
|
+
useEffect(t13, t14);
|
|
235
|
+
let t15;
|
|
236
|
+
if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
|
|
237
|
+
t15 = (args_0) => {
|
|
238
|
+
const { filename: filename_1, polling: t16$1, pollingUrl } = args_0;
|
|
239
|
+
const upload_12 = {
|
|
240
|
+
filename: filename_1,
|
|
241
|
+
progress: 0,
|
|
242
|
+
polling: t16$1 === void 0 ? false : t16$1,
|
|
243
|
+
pollingUrl,
|
|
244
|
+
status: "uploading"
|
|
245
|
+
};
|
|
246
|
+
setActiveUploads((prev_6) => [...prev_6, upload_12]);
|
|
247
|
+
};
|
|
248
|
+
$[22] = t15;
|
|
249
|
+
} else t15 = $[22];
|
|
250
|
+
const addUpload = t15;
|
|
251
|
+
let t16;
|
|
252
|
+
if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
|
|
253
|
+
t16 = (args_1) => {
|
|
254
|
+
const { filename: filename_2, progress: progress_0, polling: polling_1 } = args_1;
|
|
255
|
+
setActiveUploads((prev_7) => prev_7.map((upload_13) => upload_13.filename === filename_2 ? {
|
|
256
|
+
...upload_13,
|
|
257
|
+
progress: progress_0,
|
|
258
|
+
...polling_1 !== void 0 && { polling: polling_1 },
|
|
259
|
+
status: polling_1 ? "processing" : progress_0 >= 100 ? "completed" : "uploading"
|
|
260
|
+
} : upload_13));
|
|
261
|
+
};
|
|
262
|
+
$[23] = t16;
|
|
263
|
+
} else t16 = $[23];
|
|
264
|
+
const updateUpload = t16;
|
|
265
|
+
let T0;
|
|
266
|
+
let t17;
|
|
267
|
+
let t18;
|
|
268
|
+
if ($[24] !== activeTab || $[25] !== activeUploads || $[26] !== showUploadManager) {
|
|
269
|
+
const uploadingFiles = activeUploads.filter(_temp5);
|
|
270
|
+
const processingFiles = activeUploads.filter(_temp6);
|
|
271
|
+
const completedFiles = activeUploads.filter(_temp7);
|
|
272
|
+
let t19$1;
|
|
273
|
+
if ($[30] === Symbol.for("react.memo_cache_sentinel")) {
|
|
274
|
+
t19$1 = function renderUploadList$1(args_2) {
|
|
275
|
+
const { uploads: uploads_0 } = args_2;
|
|
276
|
+
return <ul>{uploads_0.map(_temp8)}</ul>;
|
|
277
|
+
};
|
|
278
|
+
$[30] = t19$1;
|
|
279
|
+
} else t19$1 = $[30];
|
|
280
|
+
const renderUploadList = t19$1;
|
|
281
|
+
let t20;
|
|
282
|
+
if ($[31] !== activeUploads) {
|
|
283
|
+
t20 = function closeUploadManager$1() {
|
|
284
|
+
if (!activeUploads.some(_temp9)) {
|
|
285
|
+
setActiveUploads([]);
|
|
286
|
+
setShowUploadManager(false);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
$[31] = activeUploads;
|
|
290
|
+
$[32] = t20;
|
|
291
|
+
} else t20 = $[32];
|
|
292
|
+
const closeUploadManager = t20;
|
|
293
|
+
let t21;
|
|
294
|
+
if ($[33] !== activeUploads) {
|
|
295
|
+
t21 = {
|
|
296
|
+
activeUploads,
|
|
297
|
+
addUpload,
|
|
298
|
+
updateUpload
|
|
299
|
+
};
|
|
300
|
+
$[33] = activeUploads;
|
|
301
|
+
$[34] = t21;
|
|
302
|
+
} else t21 = $[34];
|
|
303
|
+
const value = t21;
|
|
304
|
+
T0 = UploadManagerContext.Provider;
|
|
305
|
+
t17 = value;
|
|
306
|
+
t18 = showUploadManager && <div className="upload-manager"><div className="upload-manager__header"><h4>Uploads</h4><Button buttonStyle="icon-label" icon="x" margin={false} onClick={closeUploadManager} /></div><div className="upload-manager__tabs"><button data-active={activeTab === "uploading"} className="upload-tab" onClick={() => setActiveTab("uploading")}>Uploading ({uploadingFiles.length})</button><button data-active={activeTab === "processing"} className="upload-tab" onClick={() => setActiveTab("processing")}>Processing ({processingFiles.length})</button><button data-active={activeTab === "completed"} className="upload-tab" onClick={() => setActiveTab("completed")}>Completed ({completedFiles.length})</button></div><div className="upload-manager__content">{activeTab === "uploading" && uploadingFiles.length > 0 && <div>{renderUploadList({ uploads: uploadingFiles })}</div>}{activeTab === "processing" && processingFiles.length > 0 && <div>{renderUploadList({ uploads: processingFiles })}</div>}{activeTab === "completed" && completedFiles.length > 0 && <div>{renderUploadList({ uploads: completedFiles })}<div className="upload-manager__footer"><Button buttonStyle="subtle" size="small" margin={false} onClick={_temp0}>Refresh</Button></div></div>}{(activeTab === "uploading" && uploadingFiles.length === 0 || activeTab === "processing" && processingFiles.length === 0 || activeTab === "completed" && completedFiles.length === 0) && <p className="upload-empty-state">No {activeTab} files</p>}</div></div>;
|
|
307
|
+
$[24] = activeTab;
|
|
308
|
+
$[25] = activeUploads;
|
|
309
|
+
$[26] = showUploadManager;
|
|
310
|
+
$[27] = T0;
|
|
311
|
+
$[28] = t17;
|
|
312
|
+
$[29] = t18;
|
|
313
|
+
} else {
|
|
314
|
+
T0 = $[27];
|
|
315
|
+
t17 = $[28];
|
|
316
|
+
t18 = $[29];
|
|
317
|
+
}
|
|
318
|
+
let t19;
|
|
319
|
+
if ($[35] !== T0 || $[36] !== children || $[37] !== t17 || $[38] !== t18) {
|
|
320
|
+
t19 = <T0 value={t17}>{t18}{children}</T0>;
|
|
321
|
+
$[35] = T0;
|
|
322
|
+
$[36] = children;
|
|
323
|
+
$[37] = t17;
|
|
324
|
+
$[38] = t18;
|
|
325
|
+
$[39] = t19;
|
|
326
|
+
} else t19 = $[39];
|
|
327
|
+
return t19;
|
|
328
|
+
}
|
|
329
|
+
function _temp0() {
|
|
330
|
+
return window?.location?.reload();
|
|
331
|
+
}
|
|
332
|
+
function _temp9(upload_18) {
|
|
333
|
+
return upload_18.polling;
|
|
334
|
+
}
|
|
335
|
+
function _temp8(upload_17) {
|
|
336
|
+
return <li key={upload_17.filename} data-status={upload_17.status}><div className="upload-info"><span className="upload-filename">{upload_17.filename}</span><span className="upload-meta">{upload_17.status === "processing" ? "Processing..." : upload_17.progress < 100 ? `${Math.ceil(upload_17.progress)}%` : "Completed"}</span></div><div className="upload-progress-bar" style={{ "--progress": upload_17.status === "processing" ? "1" : `${upload_17.progress / 100}` }}><div data-active={upload_17.status === "processing"} className="upload-progress" /></div></li>;
|
|
337
|
+
}
|
|
338
|
+
function _temp7(upload_16) {
|
|
339
|
+
return upload_16.status === "completed";
|
|
340
|
+
}
|
|
341
|
+
function _temp6(upload_15) {
|
|
342
|
+
return upload_15.status === "processing";
|
|
343
|
+
}
|
|
344
|
+
function _temp5(upload_14) {
|
|
345
|
+
return upload_14.status === "uploading";
|
|
346
|
+
}
|
|
347
|
+
function _temp4(upload_2) {
|
|
348
|
+
return upload_2.polling && upload_2.pollingUrl;
|
|
349
|
+
}
|
|
350
|
+
function _temp3(upload_1) {
|
|
351
|
+
return upload_1.status === "completed";
|
|
352
|
+
}
|
|
353
|
+
function _temp2(upload_0) {
|
|
354
|
+
return upload_0.status === "processing";
|
|
355
|
+
}
|
|
356
|
+
function _temp(upload) {
|
|
357
|
+
return upload.status === "uploading";
|
|
358
|
+
}
|
|
359
|
+
const useUploadManagerContext = () => use(UploadManagerContext);
|
|
360
|
+
|
|
361
|
+
//#endregion
|
|
362
|
+
export { UploadManagerProvider, useUploadManagerContext };
|
|
363
|
+
//# sourceMappingURL=uploadManager.mjs.map
|