@@ -13,13 +13,16 @@ define([
13
13
'Magento_Ui/js/modal/alert' ,
14
14
'Magento_Ui/js/lib/validation/validator' ,
15
15
'Magento_Ui/js/form/element/abstract' ,
16
+ 'mage/backend/notification' ,
17
+ 'mage/translate' ,
16
18
'jquery/file-uploader'
17
- ] , function ( $ , _ , utils , uiAlert , validator , Element ) {
19
+ ] , function ( $ , _ , utils , uiAlert , validator , Element , notification , $t ) {
18
20
'use strict' ;
19
21
20
22
return Element . extend ( {
21
23
defaults : {
22
24
value : [ ] ,
25
+ aggregatedErrors : [ ] ,
23
26
maxFileSize : false ,
24
27
isMultipleFiles : false ,
25
28
placeholderType : 'document' , // 'image', 'video'
@@ -278,9 +281,15 @@ define([
278
281
* @returns {FileUploader } Chainable.
279
282
*/
280
283
notifyError : function ( msg ) {
281
- uiAlert ( {
284
+ var data = {
282
285
content : msg
283
- } ) ;
286
+ } ;
287
+
288
+ if ( this . isMultipleFiles ) {
289
+ data . modalClass = '_image-box' ;
290
+ }
291
+
292
+ uiAlert ( data ) ;
284
293
285
294
return this ;
286
295
} ,
@@ -309,13 +318,19 @@ define([
309
318
} ,
310
319
311
320
/**
312
- * Abstract handler which is invoked when files are choosed for upload.
321
+ * Handler which is invoked when files are choosed for upload.
313
322
* May be used for implementation of aditional validation rules,
314
323
* e.g. total files and a total size rules.
315
324
*
316
- * @abstract
325
+ * @param {Event } e - Event object.
326
+ * @param {Object } data - File data that will be uploaded.
317
327
*/
318
- onFilesChoosed : function ( ) { } ,
328
+ onFilesChoosed : function ( e , data ) {
329
+ // no option exists in fileuploader for restricting upload chains to single files; this enforces that policy
330
+ if ( ! this . isMultipleFiles ) {
331
+ data . files . splice ( 1 ) ;
332
+ }
333
+ } ,
319
334
320
335
/**
321
336
* Handler which is invoked prior to the start of a file upload.
@@ -337,22 +352,41 @@ define([
337
352
data . submit ( ) ;
338
353
} ) ;
339
354
} else {
340
- this . notifyError ( allowed . message ) ;
355
+ this . aggregateError ( file . name , allowed . message ) ;
356
+
357
+ // if all files in upload chain are invalid, stop callback is never called; this resolves promise
358
+ if ( this . aggregatedErrors . length === data . originalFiles . length ) {
359
+ this . uploaderConfig . stop ( ) ;
360
+ }
341
361
}
342
362
} ,
343
363
364
+ /**
365
+ * Add error message associated with filename for display when upload chain is complete
366
+ *
367
+ * @param {String } filename
368
+ * @param {String } message
369
+ */
370
+ aggregateError : function ( filename , message ) {
371
+ this . aggregatedErrors . push ( {
372
+ filename : filename ,
373
+ message : message
374
+ } ) ;
375
+ } ,
376
+
344
377
/**
345
378
* Handler of the file upload complete event.
346
379
*
347
380
* @param {Event } e
348
381
* @param {Object } data
349
382
*/
350
383
onFileUploaded : function ( e , data ) {
351
- var file = data . result ,
384
+ var uploadedFilename = data . files [ 0 ] . name ,
385
+ file = data . result ,
352
386
error = file . error ;
353
387
354
388
error ?
355
- this . notifyError ( error ) :
389
+ this . aggregateError ( uploadedFilename , error ) :
356
390
this . addFile ( file ) ;
357
391
} ,
358
392
@@ -367,7 +401,45 @@ define([
367
401
* Load stop event handler.
368
402
*/
369
403
onLoadingStop : function ( ) {
404
+ var aggregatedErrorMessages = [ ] ;
405
+
370
406
this . isLoading = false ;
407
+
408
+ if ( ! this . aggregatedErrors . length ) {
409
+ return ;
410
+ }
411
+
412
+ if ( ! this . isMultipleFiles ) { // only single file upload occurred; use first file's error message
413
+ aggregatedErrorMessages . push ( this . aggregatedErrors [ 0 ] . message ) ;
414
+ } else { // construct message from all aggregatedErrors
415
+ _ . each ( this . aggregatedErrors , function ( error ) {
416
+ notification ( ) . add ( {
417
+ error : true ,
418
+ message : '%s' + error . message , // %s to be used as placeholder for html injection
419
+
420
+ /**
421
+ * Adds constructed error notification to aggregatedErrorMessages
422
+ *
423
+ * @param {String } constructedMessage
424
+ */
425
+ insertMethod : function ( constructedMessage ) {
426
+ var errorMsgBodyHtml = '<strong>%s</strong> %s.<br>'
427
+ . replace ( '%s' , error . filename )
428
+ . replace ( '%s' , $t ( 'was not uploaded' ) ) ;
429
+
430
+ // html is escaped in message body for notification widget; prepend unescaped html here
431
+ constructedMessage = constructedMessage . replace ( '%s' , errorMsgBodyHtml ) ;
432
+
433
+ aggregatedErrorMessages . push ( constructedMessage ) ;
434
+ }
435
+ } ) ;
436
+ } ) ;
437
+ }
438
+
439
+ this . notifyError ( aggregatedErrorMessages . join ( '' ) ) ;
440
+
441
+ // clear out aggregatedErrors array for this completed upload chain
442
+ this . aggregatedErrors = [ ] ;
371
443
} ,
372
444
373
445
/**
0 commit comments