@@ -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,20 @@ 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.
327
+ * @returns {Boolean|void } - false if further processing should halt or undefined if processing should continue
317
328
*/
318
- onFilesChoosed : function ( ) { } ,
329
+ onFilesChoosed : function ( e , data ) {
330
+ // no option exists in fileuploader for restricting upload chains to single files; this enforces that policy
331
+ if ( ! this . isMultipleFiles ) {
332
+ data . files . splice ( 1 ) ;
333
+ }
334
+ } ,
319
335
320
336
/**
321
337
* Handler which is invoked prior to the start of a file upload.
@@ -337,22 +353,41 @@ define([
337
353
data . submit ( ) ;
338
354
} ) ;
339
355
} else {
340
- this . notifyError ( allowed . message ) ;
356
+ this . aggregateError ( file . name , allowed . message ) ;
357
+
358
+ // if all files in upload chain are invalid, stop callback is never called; this resolves promise
359
+ if ( this . aggregatedErrors . length === data . originalFiles . length ) {
360
+ this . uploaderConfig . stop ( ) ;
361
+ }
341
362
}
342
363
} ,
343
364
365
+ /**
366
+ * Add error message associated with filename for display when upload chain is complete
367
+ *
368
+ * @param {String } filename
369
+ * @param {String } message
370
+ */
371
+ aggregateError : function ( filename , message ) {
372
+ this . aggregatedErrors . push ( {
373
+ filename : filename ,
374
+ message : message
375
+ } ) ;
376
+ } ,
377
+
344
378
/**
345
379
* Handler of the file upload complete event.
346
380
*
347
381
* @param {Event } e
348
382
* @param {Object } data
349
383
*/
350
384
onFileUploaded : function ( e , data ) {
351
- var file = data . result ,
385
+ var uploadedFilename = data . files [ 0 ] . name ,
386
+ file = data . result ,
352
387
error = file . error ;
353
388
354
389
error ?
355
- this . notifyError ( error ) :
390
+ this . aggregateError ( uploadedFilename , error ) :
356
391
this . addFile ( file ) ;
357
392
} ,
358
393
@@ -367,7 +402,45 @@ define([
367
402
* Load stop event handler.
368
403
*/
369
404
onLoadingStop : function ( ) {
405
+ var aggregatedErrorMessages = [ ] ;
406
+
370
407
this . isLoading = false ;
408
+
409
+ if ( ! this . aggregatedErrors . length ) {
410
+ return ;
411
+ }
412
+
413
+ if ( ! this . isMultipleFiles ) { // only single file upload occurred; use first file's error message
414
+ aggregatedErrorMessages . push ( this . aggregatedErrors [ 0 ] . message ) ;
415
+ } else { // construct message from all aggregatedErrors
416
+ _ . each ( this . aggregatedErrors , function ( error ) {
417
+ notification ( ) . add ( {
418
+ error : true ,
419
+ message : '%s' + error . message , // %s to be used as placeholder for html injection
420
+
421
+ /**
422
+ * Adds constructed error notification to aggregatedErrorMessages
423
+ *
424
+ * @param {String } constructedMessage
425
+ */
426
+ insertMethod : function ( constructedMessage ) {
427
+ var errorMsgBodyHtml = '<strong>%s</strong> %s.<br>'
428
+ . replace ( '%s' , error . filename )
429
+ . replace ( '%s' , $t ( 'was not uploaded' ) ) ;
430
+
431
+ // html is escaped in message body for notification widget; prepend unescaped html here
432
+ constructedMessage = constructedMessage . replace ( '%s' , errorMsgBodyHtml ) ;
433
+
434
+ aggregatedErrorMessages . push ( constructedMessage ) ;
435
+ }
436
+ } ) ;
437
+ } ) ;
438
+ }
439
+
440
+ this . notifyError ( aggregatedErrorMessages . join ( '' ) ) ;
441
+
442
+ // clear out aggregatedErrors array for this completed upload chain
443
+ this . aggregatedErrors = [ ] ;
371
444
} ,
372
445
373
446
/**
0 commit comments