quasar-ui-danx 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/dist/danx.es.js +7127 -6615
  2. package/dist/danx.es.js.map +1 -1
  3. package/dist/danx.umd.js +11 -5
  4. package/dist/danx.umd.js.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +3 -1
  7. package/src/components/ActionTable/ActionTable.vue +28 -41
  8. package/src/components/ActionTable/Columns/ActionTableColumn.vue +19 -18
  9. package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +6 -6
  10. package/src/components/ActionTable/Filters/{FilterFieldList.vue → FilterList.vue} +26 -26
  11. package/src/components/ActionTable/Filters/FilterableField.vue +28 -31
  12. package/src/components/ActionTable/Filters/index.ts +2 -2
  13. package/src/components/ActionTable/Form/Fields/EditOnClickTextField.vue +71 -0
  14. package/src/components/ActionTable/Form/Fields/FieldLabel.vue +8 -13
  15. package/src/components/ActionTable/Form/Fields/MultiFileField.vue +48 -44
  16. package/src/components/ActionTable/Form/Fields/SelectField.vue +24 -38
  17. package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +28 -33
  18. package/src/components/ActionTable/Form/Fields/SingleFileField.vue +15 -15
  19. package/src/components/ActionTable/Form/Fields/SliderNumberField.vue +45 -0
  20. package/src/components/ActionTable/Form/Fields/TextField.vue +47 -66
  21. package/src/components/ActionTable/Form/Fields/index.ts +2 -0
  22. package/src/components/ActionTable/Form/RenderedForm.vue +50 -9
  23. package/src/components/ActionTable/Form/Utilities/MaxLengthCounter.vue +17 -0
  24. package/src/components/ActionTable/Form/Utilities/index.ts +1 -0
  25. package/src/components/ActionTable/Form/index.ts +1 -0
  26. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +16 -15
  27. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +6 -6
  28. package/src/components/ActionTable/listControls.ts +106 -166
  29. package/src/components/ActionTable/listHelpers.ts +2 -3
  30. package/src/components/ActionTable/tableColumns.ts +3 -27
  31. package/src/components/AuditHistory/AuditHistoryItemValue.vue +26 -26
  32. package/src/components/PanelsDrawer/PanelsDrawer.vue +17 -4
  33. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +6 -11
  34. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +20 -20
  35. package/src/components/Utility/Dialogs/ConfirmActionDialog.vue +39 -0
  36. package/src/components/Utility/Dialogs/ConfirmDialog.vue +10 -24
  37. package/src/components/Utility/Dialogs/DialogLayout.vue +10 -28
  38. package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +42 -36
  39. package/src/components/Utility/Dialogs/index.ts +1 -0
  40. package/src/components/Utility/Files/FilePreview.vue +76 -73
  41. package/src/components/Utility/Layouts/ContentDrawer.vue +24 -31
  42. package/src/components/Utility/Tools/ActionVnode.vue +3 -3
  43. package/src/components/Utility/Tools/RenderVnode.vue +1 -1
  44. package/src/components/Utility/Transitions/MaxHeightTransition.vue +26 -0
  45. package/src/components/Utility/Transitions/index.ts +1 -0
  46. package/src/config/index.ts +36 -31
  47. package/src/helpers/FileUpload.ts +295 -297
  48. package/src/helpers/FlashMessages.ts +80 -71
  49. package/src/helpers/actions.ts +102 -82
  50. package/src/helpers/download.ts +189 -189
  51. package/src/helpers/downloadPdf.ts +55 -52
  52. package/src/helpers/formats.ts +151 -109
  53. package/src/helpers/index.ts +2 -0
  54. package/src/helpers/multiFileUpload.ts +72 -58
  55. package/src/helpers/objectStore.ts +52 -0
  56. package/src/helpers/request.ts +70 -51
  57. package/src/helpers/routes.ts +29 -0
  58. package/src/helpers/storage.ts +7 -3
  59. package/src/helpers/utils.ts +47 -29
  60. package/src/styles/quasar-reset.scss +16 -1
  61. package/src/styles/themes/danx/dialogs.scss +4 -0
  62. package/src/types/actions.d.ts +43 -0
  63. package/src/types/config.d.ts +15 -0
  64. package/src/types/controls.d.ts +99 -0
  65. package/src/types/dialogs.d.ts +32 -0
  66. package/src/types/fields.d.ts +20 -0
  67. package/src/types/files.d.ts +54 -0
  68. package/src/types/formats.d.ts +4 -0
  69. package/src/{components/ActionTable/Form/form.d.ts → types/forms.d.ts} +6 -0
  70. package/src/types/index.d.ts +12 -0
  71. package/src/types/requests.d.ts +13 -0
  72. package/src/types/shared.d.ts +15 -0
  73. package/src/types/tables.d.ts +27 -0
  74. package/types/index.d.ts +1 -1
  75. /package/src/components/ActionTable/Filters/{FilterFieldItem.vue → FilterItem.vue} +0 -0
@@ -1,305 +1,303 @@
1
1
  import { uid } from "quasar";
2
2
  import { danxOptions } from "../config";
3
+ import {
4
+ FileUploadAllCompleteCallback,
5
+ FileUploadCompleteCallback,
6
+ FileUploadErrorCallback,
7
+ FileUploadOptions,
8
+ FileUploadProgressCallback,
9
+ UploadedFile,
10
+ XHRFileUpload
11
+ } from "../types";
3
12
  import { resolveFileLocation } from "./files";
4
13
  import { FlashMessages } from "./FlashMessages";
5
14
 
6
- export type FileUploadOptions = {
7
- directory?: string,
8
- presignedUploadUrl?: Function | null;
9
- uploadCompletedUrl?: Function | null;
10
- };
11
-
12
- export type UploadedFile = {
13
- id: string,
14
- name: string,
15
- size: number,
16
- type: string,
17
- progress: number,
18
- location: string,
19
- blobUrl: string,
20
- url: string,
21
- }
22
15
 
23
16
  export class FileUpload {
24
- files: UploadedFile[] = [];
25
- fileUploads: UploadedFile[] = [];
26
- onErrorCb: Function | null = null;
27
- onProgressCb: Function | null = null;
28
- onCompleteCb: Function | null = null;
29
- onAllCompleteCb: Function | null = null;
30
- options: FileUploadOptions | null = {};
31
-
32
- constructor(files: UploadedFile[] | UploadedFile, options: FileUploadOptions | null = {}) {
33
- this.files = !Array.isArray(files) && !(files instanceof FileList) ? [files] : files;
34
- this.fileUploads = [];
35
- this.onErrorCb = null;
36
- this.onProgressCb = null;
37
- this.onCompleteCb = null;
38
- this.onAllCompleteCb = null;
39
-
40
- this.options = {
41
- ...danxOptions.value.fileUpload,
42
- ...options
43
- };
44
-
45
- if (!this.options.presignedUploadUrl) {
46
- throw new Error("Please configure the danxOptions: import { configure } from 'quasar-ui-danx';");
47
- }
48
- this.prepare();
49
- }
50
-
51
- /**
52
- * Prepares all files for upload and provides an id and blobUrl for each file
53
- */
54
- prepare() {
55
- // Prepare required attributes
56
- for (const file of this.files) {
57
- if (!(file instanceof File)) {
58
- throw Error(
59
- "FileUpload constructor requires a File object or a list of File objects"
60
- );
61
- }
62
-
63
- file.id = uid();
64
- file.blobUrl = URL.createObjectURL(file);
65
-
66
- // Prepare FormData
67
- const formData = new FormData();
68
- formData.append("file", file);
69
-
70
- this.fileUploads.push({
71
- file,
72
- xhr: null, // NOTE: The XHR will be setup asynchronously right before sending file uploads
73
- formData,
74
- isComplete: false
75
- });
76
- }
77
- }
78
-
79
- /**
80
- * Callback for when all files have been uploaded
81
- */
82
- onAllComplete(cb: Function) {
83
- this.onAllCompleteCb = cb;
84
- return this;
85
- }
86
-
87
- /**
88
- * Callback fired once for each file upon successful completion of upload
89
- * @param cb
90
- * @returns {FileUpload}
91
- */
92
- onComplete(cb: Function) {
93
- this.onCompleteCb = cb;
94
- return this;
95
- }
96
-
97
- /**
98
- * Callback fired each time there is an upload progress update for a file
99
- * @param cb
100
- * @returns {FileUpload}
101
- */
102
- onProgress(cb: Function) {
103
- this.onProgressCb = cb;
104
- return this;
105
- }
106
-
107
- /**
108
- * Callback fired when an error occurs during upload
109
- * @param cb
110
- * @returns {FileUpload}
111
- */
112
- onError(cb: Function) {
113
- this.onErrorCb = cb;
114
- return this;
115
- }
116
-
117
- /**
118
- * Handles the error events / fires the callback if it is set
119
- * @param e
120
- * @param file
121
- * @param error
122
- */
123
- errorHandler(e: InputEvent, file: UploadedFile, error = null) {
124
- if (this.onErrorCb) {
125
- this.onErrorCb({ e, file, error });
126
- }
127
- }
128
-
129
- /**
130
- * Resolve the locations of all the files
131
- * @returns {Promise<FileUpload>}
132
- */
133
- async resolveLocation(waitMessage = null) {
134
- for (const fileUpload of this.fileUploads) {
135
- fileUpload.file.location = await resolveFileLocation(
136
- fileUpload.file,
137
- waitMessage
138
- );
139
- fileUpload.formData.append(
140
- "meta",
141
- JSON.stringify(fileUpload.file.location)
142
- );
143
- }
144
- return this;
145
- }
146
-
147
- /**
148
- * Fires the progress callback
149
- * @param fileUpload
150
- * @param progress
151
- */
152
- fireProgressCallback(fileUpload, progress) {
153
- fileUpload.file.progress = progress;
154
- this.onProgressCb && this.onProgressCb({ file: this.wrapFile(fileUpload.file), progress });
155
- }
156
-
157
- /**
158
- * Fires the complete callback
159
- * @param fileUpload
160
- * @param uploadedFile
161
- */
162
- fireCompleteCallback(fileUpload, uploadedFile) {
163
- fileUpload.isComplete = true;
164
- fileUpload.file.progress = 1;
165
- this.onCompleteCb && this.onCompleteCb({ file: this.wrapFile(fileUpload.file), uploadedFile });
166
- }
167
-
168
- /**
169
- * Check if all files have been uploaded and call the callback if they have
170
- */
171
- checkAllComplete() {
172
- if (this.onAllCompleteCb) {
173
- if (this.fileUploads.every((fileUpload) => fileUpload.isComplete)) {
174
- this.onAllCompleteCb({ files: this.fileUploads });
175
- }
176
- }
177
- }
178
-
179
- /**
180
- * Returns a native JS object that is easier to work with than the File objects (no weird behavior of missing
181
- * properties, easily printable, etc.)
182
- * @param file
183
- * @returns {{size, name, progress, location, blobUrl: *, id, type}}
184
- */
185
- wrapFile(file) {
186
- return {
187
- id: file.id,
188
- name: file.name,
189
- size: file.size,
190
- type: file.type,
191
- progress: file.progress,
192
- location: file.location,
193
- blobUrl: file.blobUrl
194
- };
195
- }
196
-
197
- /**
198
- * Registers all the callbacks requested for the XHR / post-processing of file uploads
199
- */
200
- setXhrCallbacks() {
201
- // Set the error callbacks
202
- for (const fileUpload of this.fileUploads) {
203
- fileUpload.xhr.addEventListener(
204
- "error",
205
- (e) => this.errorHandler(e, fileUpload.file),
206
- false
207
- );
208
- }
209
-
210
- // Set the progress callbacks
211
- if (this.onProgressCb) {
212
- for (const fileUpload of this.fileUploads) {
213
- fileUpload.xhr.upload.addEventListener(
214
- "progress",
215
- (e) => {
216
- // Max of 95%, so we can indicate we are completing the signed URL process
217
- const progress = Math.min(.95, e.loaded / e.total);
218
- this.fireProgressCallback(fileUpload, progress);
219
- },
220
- false
221
- );
222
- }
223
- }
224
-
225
- // Set the load callbacks which registers the Complete / All Complete callbacks and handles non-xhr related
226
- // errors
227
- for (const fileUpload of this.fileUploads) {
228
- fileUpload.xhr.addEventListener(
229
- "load",
230
- async (e) => {
231
- try {
232
- // First complete the presigned upload to get the updated file resource data
233
- const uploadedFile = await this.completePresignedUpload(fileUpload);
234
-
235
- // Fire the file complete callbacks
236
- this.fireCompleteCallback(fileUpload, uploadedFile);
237
- this.checkAllComplete();
238
- } catch (error) {
239
- this.errorHandler(e, fileUpload.file, error);
240
- }
241
- },
242
- false
243
- );
244
- }
245
- }
246
-
247
- /**
248
- * Mark the presigned upload as completed and return the file resource from the platform server
249
- * @param fileUpload
250
- * @returns {Promise<void>}
251
- */
252
- async completePresignedUpload(fileUpload) {
253
- // Show 95% as the last 5% will be to complete the presigned upload
254
- this.fireProgressCallback(fileUpload, .95);
255
-
256
- // Let the platform know the presigned upload is complete
257
- return await fetch(this.options.uploadCompletedUrl(fileUpload.file.resource_id), { method: "POST" }).then(r => r.json());
258
- }
259
-
260
- /**
261
- * Start uploading all files
262
- */
263
- async upload() {
264
- for (const fileUpload of this.fileUploads) {
265
- const mimeType = fileUpload.file.mimeType || fileUpload.file.type;
266
- const presignedUrl = this.options.presignedUploadUrl(this.options.directory, fileUpload.file.name, mimeType);
267
-
268
- // Fetch presigned upload URL
269
- const fileResource = await fetch(presignedUrl).then(r => r.json());
270
-
271
- if (!fileResource.url) {
272
- FlashMessages.error("Could not fetch presigned upload URL for file " + fileUpload.file.name);
273
- continue;
274
- }
275
-
276
- const isS3Upload = !fileResource.url.match("upload-presigned-url-contents");
277
-
278
- // We need the file resource ID to complete the presigned upload
279
- fileUpload.file.resource_id = fileResource.id;
280
-
281
- // Prepare XHR request
282
- const xhr = new XMLHttpRequest();
283
-
284
- // The XHR request is different based on weather we're sending to S3 or the platform server
285
- if (isS3Upload) {
286
- xhr.open("PUT", fileResource.url);
287
- xhr.setRequestHeader("Content-Type", mimeType);
288
- fileUpload.body = fileUpload.file;
289
- } else {
290
- xhr.open("POST", fileResource.url);
291
- fileUpload.body = fileUpload.formData;
292
- }
293
-
294
- fileUpload.xhr = xhr;
295
- }
296
-
297
- // Set all the callbacks on the XHR requests
298
- this.setXhrCallbacks();
299
-
300
- // Send all the XHR file uploads
301
- for (const fileUpload of this.fileUploads) {
302
- fileUpload.xhr.send(fileUpload.body);
303
- }
304
- }
17
+ files: UploadedFile[] = [];
18
+ fileUploads: XHRFileUpload[] = [];
19
+ onErrorCb: FileUploadErrorCallback | null = null;
20
+ onProgressCb: FileUploadProgressCallback | null = null;
21
+ onCompleteCb: FileUploadCompleteCallback | null = null;
22
+ onAllCompleteCb: FileUploadAllCompleteCallback | null = null;
23
+ options: FileUploadOptions;
24
+
25
+ constructor(files: UploadedFile[] | UploadedFile, options?: FileUploadOptions) {
26
+ this.files = !Array.isArray(files) && !(files instanceof FileList) ? [files] : files;
27
+ this.fileUploads = [];
28
+ this.onErrorCb = null;
29
+ this.onProgressCb = null;
30
+ this.onCompleteCb = null;
31
+ this.onAllCompleteCb = null;
32
+
33
+ this.options = {
34
+ createPresignedUpload: null,
35
+ completePresignedUpload: null,
36
+ ...danxOptions.value.fileUpload,
37
+ ...options
38
+ };
39
+
40
+ if (!this.options.createPresignedUpload || !this.options.completePresignedUpload) {
41
+ throw new Error("Please configure danxOptions.fileUpload: import { configure } from 'quasar-ui-danx';");
42
+ }
43
+ this.prepare();
44
+ }
45
+
46
+ /**
47
+ * Prepares all files for upload and provides an id and blobUrl for each file
48
+ */
49
+ prepare() {
50
+ // Prepare required attributes
51
+ for (const file of this.files) {
52
+ if (!(file instanceof File)) {
53
+ throw Error(
54
+ "FileUpload constructor requires a File object or a list of File objects"
55
+ );
56
+ }
57
+
58
+ file.id = uid();
59
+ file.blobUrl = URL.createObjectURL(file);
60
+
61
+ // Prepare FormData
62
+ const formData = new FormData();
63
+ formData.append("file", file);
64
+
65
+ this.fileUploads.push({
66
+ file,
67
+ xhr: null, // NOTE: The XHR will be setup asynchronously right before sending file uploads
68
+ formData,
69
+ isComplete: false
70
+ });
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Callback for when all files have been uploaded
76
+ */
77
+ onAllComplete(cb: FileUploadAllCompleteCallback) {
78
+ this.onAllCompleteCb = cb;
79
+ return this;
80
+ }
81
+
82
+ /**
83
+ * Callback fired once for each file upon successful completion of upload
84
+ * @param cb
85
+ * @returns {FileUpload}
86
+ */
87
+ onComplete(cb: FileUploadCompleteCallback) {
88
+ this.onCompleteCb = cb;
89
+ return this;
90
+ }
91
+
92
+ /**
93
+ * Callback fired each time there is an upload progress update for a file
94
+ * @param cb
95
+ * @returns {FileUpload}
96
+ */
97
+ onProgress(cb: FileUploadProgressCallback) {
98
+ this.onProgressCb = cb;
99
+ return this;
100
+ }
101
+
102
+ /**
103
+ * Callback fired when an error occurs during upload
104
+ */
105
+ onError(cb: FileUploadErrorCallback) {
106
+ this.onErrorCb = cb;
107
+ return this;
108
+ }
109
+
110
+ /**
111
+ * Handles the error events / fires the callback if it is set
112
+ */
113
+ errorHandler(e: InputEvent, file: UploadedFile, error = null) {
114
+ if (this.onErrorCb) {
115
+ this.onErrorCb({ e, file, error });
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Resolve the locations of all the files
121
+ * @returns {Promise<FileUpload>}
122
+ */
123
+ async resolveLocation(waitMessage = null) {
124
+ for (const fileUpload of this.fileUploads) {
125
+ fileUpload.file.location = await resolveFileLocation(
126
+ fileUpload.file,
127
+ waitMessage
128
+ );
129
+ fileUpload.formData.append(
130
+ "meta",
131
+ JSON.stringify(fileUpload.file.location)
132
+ );
133
+ }
134
+ return this;
135
+ }
136
+
137
+ /**
138
+ * Fires the progress callback
139
+ * @param fileUpload
140
+ * @param progress
141
+ */
142
+ fireProgressCallback(fileUpload: XHRFileUpload, progress: number) {
143
+ fileUpload.file.progress = progress;
144
+ this.onProgressCb && this.onProgressCb({ file: this.wrapFile(fileUpload.file), progress });
145
+ }
146
+
147
+ /**
148
+ * Fires the complete callback
149
+ * @param fileUpload
150
+ * @param uploadedFile
151
+ */
152
+ fireCompleteCallback(fileUpload: XHRFileUpload, uploadedFile: UploadedFile) {
153
+ fileUpload.isComplete = true;
154
+ fileUpload.file.progress = 1;
155
+ this.onCompleteCb && this.onCompleteCb({ file: this.wrapFile(fileUpload.file), uploadedFile });
156
+ }
157
+
158
+ /**
159
+ * Check if all files have been uploaded and call the callback if they have
160
+ */
161
+ checkAllComplete() {
162
+ if (this.onAllCompleteCb) {
163
+ if (this.fileUploads.every((fileUpload) => fileUpload.isComplete)) {
164
+ this.onAllCompleteCb({ files: this.fileUploads });
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Returns a native JS object that is easier to work with than the File objects (no weird behavior of missing
171
+ * properties, easily printable, etc.)
172
+ */
173
+ wrapFile(file: UploadedFile) {
174
+ return {
175
+ id: file.id,
176
+ name: file.name,
177
+ size: file.size,
178
+ type: file.type,
179
+ progress: file.progress,
180
+ location: file.location,
181
+ blobUrl: file.blobUrl,
182
+ url: ""
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Registers all the callbacks requested for the XHR / post-processing of file uploads
188
+ */
189
+ setXhrCallbacks() {
190
+ // Set the error callbacks
191
+ for (const fileUpload of this.fileUploads) {
192
+ fileUpload.xhr?.addEventListener(
193
+ "error",
194
+ (e) => this.errorHandler(e, fileUpload.file),
195
+ false
196
+ );
197
+ }
198
+
199
+ // Set the progress callbacks
200
+ if (this.onProgressCb) {
201
+ for (const fileUpload of this.fileUploads) {
202
+ fileUpload.xhr?.upload.addEventListener(
203
+ "progress",
204
+ (e) => {
205
+ // Max of 95%, so we can indicate we are completing the signed URL process
206
+ const progress = Math.min(.95, e.loaded / e.total);
207
+ this.fireProgressCallback(fileUpload, progress);
208
+ },
209
+ false
210
+ );
211
+ }
212
+ }
213
+
214
+ // Set the load callbacks which registers the Complete / All Complete callbacks and handles non-xhr related
215
+ // errors
216
+ for (const fileUpload of this.fileUploads) {
217
+ fileUpload.xhr?.addEventListener(
218
+ "load",
219
+ async (e) => {
220
+ try {
221
+ // First complete the presigned upload to get the updated file resource data
222
+ const uploadedFile = await this.completePresignedUpload(fileUpload);
223
+
224
+ // Fire the file complete callbacks
225
+ this.fireCompleteCallback(fileUpload, uploadedFile);
226
+ this.checkAllComplete();
227
+ } catch (error) {
228
+ this.errorHandler(e, fileUpload.file, error);
229
+ }
230
+ },
231
+ false
232
+ );
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Mark the presigned upload as completed and return the file resource from the platform server
238
+ */
239
+ async completePresignedUpload(fileUpload: XHRFileUpload) {
240
+ // Show 95% as the last 5% will be to complete the presigned upload
241
+ this.fireProgressCallback(fileUpload, .95);
242
+
243
+ if (!fileUpload.file.resource_id) {
244
+ throw new Error("File resource ID is required to complete presigned upload");
245
+ }
246
+
247
+ if (!this.options.completePresignedUpload) {
248
+ throw new Error("Please configure danxOptions.fileUpload.completePresignedUpload");
249
+ }
250
+
251
+ // Let the platform know the presigned upload is complete
252
+ return await this.options.completePresignedUpload(fileUpload.file.resource_id);
253
+ }
254
+
255
+ /**
256
+ * Start uploading all files
257
+ */
258
+ async upload() {
259
+ for (const fileUpload of this.fileUploads) {
260
+ const mimeType = fileUpload.file.mimeType || fileUpload.file.type;
261
+
262
+ if (!this.options.createPresignedUpload) {
263
+ throw new Error("Please configure danxOptions.fileUpload.createPresignedUpload");
264
+ }
265
+
266
+ // Fetch presigned upload URL
267
+ const fileResource = await this.options.createPresignedUpload(this.options.directory || "", fileUpload.file.name, mimeType);
268
+
269
+ if (!fileResource.url) {
270
+ FlashMessages.error("Could not fetch presigned upload URL for file " + fileUpload.file.name);
271
+ continue;
272
+ }
273
+
274
+ const isS3Upload = !fileResource.url.match("upload-presigned-url-contents");
275
+
276
+ // We need the file resource ID to complete the presigned upload
277
+ fileUpload.file.resource_id = fileResource.id;
278
+
279
+ // Prepare XHR request
280
+ const xhr = new XMLHttpRequest();
281
+
282
+ // The XHR request is different based on weather we're sending to S3 or the platform server
283
+ if (isS3Upload) {
284
+ xhr.open("PUT", fileResource.url);
285
+ xhr.setRequestHeader("Content-Type", mimeType);
286
+ fileUpload.body = fileUpload.file;
287
+ } else {
288
+ xhr.open("POST", fileResource.url);
289
+ fileUpload.body = fileUpload.formData;
290
+ }
291
+
292
+ fileUpload.xhr = xhr;
293
+ }
294
+
295
+ // Set all the callbacks on the XHR requests
296
+ this.setXhrCallbacks();
297
+
298
+ // Send all the XHR file uploads
299
+ for (const fileUpload of this.fileUploads) {
300
+ fileUpload.xhr?.send(fileUpload.body);
301
+ }
302
+ }
305
303
  }