@@ -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.
@@ -329,30 +345,45 @@ define([
329
345
target = $ ( e . target ) ;
330
346
331
347
if ( allowed . passed ) {
332
- target . on ( 'fileuploadsend' , function ( event , postData ) {
333
- postData . data . append ( 'param_name' , this . paramName ) ;
334
- } . bind ( data ) ) ;
335
-
336
348
target . fileupload ( 'process' , data ) . done ( function ( ) {
337
349
data . submit ( ) ;
338
350
} ) ;
339
351
} else {
340
- this . notifyError ( allowed . message ) ;
352
+ this . aggregateError ( file . name , allowed . message ) ;
353
+
354
+ // if all files in upload chain are invalid, stop callback is never called; this resolves promise
355
+ if ( this . aggregatedErrors . length === data . originalFiles . length ) {
356
+ this . uploaderConfig . stop ( ) ;
357
+ }
341
358
}
342
359
} ,
343
360
361
+ /**
362
+ * Add error message associated with filename for display when upload chain is complete
363
+ *
364
+ * @param {String } filename
365
+ * @param {String } message
366
+ */
367
+ aggregateError : function ( filename , message ) {
368
+ this . aggregatedErrors . push ( {
369
+ filename : filename ,
370
+ message : message
371
+ } ) ;
372
+ } ,
373
+
344
374
/**
345
375
* Handler of the file upload complete event.
346
376
*
347
377
* @param {Event } e
348
378
* @param {Object } data
349
379
*/
350
380
onFileUploaded : function ( e , data ) {
351
- var file = data . result ,
381
+ var uploadedFilename = data . files [ 0 ] . name ,
382
+ file = data . result ,
352
383
error = file . error ;
353
384
354
385
error ?
355
- this . notifyError ( error ) :
386
+ this . aggregateError ( uploadedFilename , error ) :
356
387
this . addFile ( file ) ;
357
388
} ,
358
389
@@ -367,7 +398,45 @@ define([
367
398
* Load stop event handler.
368
399
*/
369
400
onLoadingStop : function ( ) {
401
+ var aggregatedErrorMessages = [ ] ;
402
+
370
403
this . isLoading = false ;
404
+
405
+ if ( ! this . aggregatedErrors . length ) {
406
+ return ;
407
+ }
408
+
409
+ if ( ! this . isMultipleFiles ) { // only single file upload occurred; use first file's error message
410
+ aggregatedErrorMessages . push ( this . aggregatedErrors [ 0 ] . message ) ;
411
+ } else { // construct message from all aggregatedErrors
412
+ _ . each ( this . aggregatedErrors , function ( error ) {
413
+ notification ( ) . add ( {
414
+ error : true ,
415
+ message : '%s' + error . message , // %s to be used as placeholder for html injection
416
+
417
+ /**
418
+ * Adds constructed error notification to aggregatedErrorMessages
419
+ *
420
+ * @param {String } constructedMessage
421
+ */
422
+ insertMethod : function ( constructedMessage ) {
423
+ var errorMsgBodyHtml = '<strong>%s</strong> %s.<br>'
424
+ . replace ( '%s' , error . filename )
425
+ . replace ( '%s' , $t ( 'was not uploaded' ) ) ;
426
+
427
+ // html is escaped in message body for notification widget; prepend unescaped html here
428
+ constructedMessage = constructedMessage . replace ( '%s' , errorMsgBodyHtml ) ;
429
+
430
+ aggregatedErrorMessages . push ( constructedMessage ) ;
431
+ }
432
+ } ) ;
433
+ } ) ;
434
+ }
435
+
436
+ this . notifyError ( aggregatedErrorMessages . join ( '' ) ) ;
437
+
438
+ // clear out aggregatedErrors array for this completed upload chain
439
+ this . aggregatedErrors = [ ] ;
371
440
} ,
372
441
373
442
/**
0 commit comments