From 1e472d8974628d5813a6ed91c8724270c781fcce Mon Sep 17 00:00:00 2001 From: Daryl Koopersmith Date: Thu, 22 Nov 2012 09:32:21 +0000 Subject: [PATCH] Media: Add global upload progress to the sidebar. see #21390. git-svn-id: http://core.svn.wordpress.org/trunk@22816 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/css/media-views.css | 44 ++++++--- wp-includes/js/media-models.js | 12 +++ wp-includes/js/media-views.js | 120 +++++++++++++++++++++---- wp-includes/js/plupload/wp-plupload.js | 8 ++ wp-includes/media.php | 14 +++ 5 files changed, 170 insertions(+), 28 deletions(-) diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css index 84308bc342..ed3dd91602 100644 --- a/wp-includes/css/media-views.css +++ b/wp-includes/css/media-views.css @@ -715,20 +715,20 @@ a.media-modal-close { */ .media-progress-bar { position: relative; - height: 8px; + height: 10px; width: 70%; margin: 10px auto; - padding: 2px; - border: 2px solid #ccc; - border-radius: 8px; - background: #fff; + border-radius: 10px; + background: #dfdfdf; + background: rgba( 0, 0, 0, 0.1 ); } .media-progress-bar div { - height: 8px; - min-width: 8px; + height: 10px; + min-width: 20px; width: 0; - background: #ccc; + background: #aaa; + background: rgba( 0, 0, 0, 0.2 ); border-radius: 10px; -webkit-transition: width 300ms; -moz-transition: width 300ms; @@ -737,12 +737,36 @@ a.media-modal-close { transition: width 300ms; } +.media-uploader-status .media-progress-bar { + width: 100%; +} + .attachment-preview .media-progress-bar { position: absolute; top: 50%; left: 15%; width: 70%; - margin: -8px 0 0 -4px; + margin: -5px 0 0 0; +} + +.media-uploader-status { + padding-bottom: 10px; + border-bottom: 1px solid #dfdfdf; + box-shadow: 0 1px 0 #fff; +} + +.media-uploader-status .upload-details { + font-size: 12px; + color: #666; + text-shadow: 0 1px 0 #fff; +} + +.media-uploader-status .upload-detail-separator { + padding: 0 4px; +} + +.media-uploader-status .upload-count { + color: #464646; } .uploader-window { @@ -1059,7 +1083,7 @@ a.media-modal-close { } .uploading .attachment-info .media-progress-bar { - margin-top: 32px; + margin-top: 35px; } .attachment-info .thumbnail:after { diff --git a/wp-includes/js/media-models.js b/wp-includes/js/media-models.js index 716522808f..0ec33270e9 100644 --- a/wp-includes/js/media-models.js +++ b/wp-includes/js/media-models.js @@ -191,6 +191,18 @@ window.wp = window.wp || {}; height: height }; } + }, + + // Truncates a string by injecting an ellipsis into the middle. + // Useful for filenames. + truncate: function( string, length, replacement ) { + length = length || 30; + replacement = replacement || '…'; + + if ( string.length <= length ) + return string; + + return string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 ); } }); diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js index a492bd0436..798a143af9 100644 --- a/wp-includes/js/media-views.js +++ b/wp-includes/js/media-views.js @@ -255,7 +255,8 @@ toolbar: 'main-attachments', sidebar: 'settings', searchable: true, - filterable: false + filterable: false, + uploads: true }, initialize: function() { @@ -476,6 +477,7 @@ id: 'upload', content: 'upload', toolbar: 'empty', + uploads: true, // The state to navigate to when files are uploading. libraryState: 'library' @@ -1290,7 +1292,7 @@ model: state, sortable: state.get('sortable'), search: state.get('searchable'), - upload: state.get('upload'), + uploads: state.get('uploads'), filters: state.get('filterable'), display: state.get('displaySettings'), @@ -1826,6 +1828,85 @@ } }); + /** + * wp.media.view.UploaderStatus + */ + media.view.UploaderStatus = media.View.extend({ + className: 'media-uploader-status', + template: media.template('uploader-status'), + + initialize: function() { + this.controller = this.options.controller; + + this.queue = wp.Uploader.queue; + this.queue.on( 'add remove reset', this.visibility, this ); + this.queue.on( 'add remove reset change:percent', this.progress, this ); + this.queue.on( 'add remove reset change:uploading', this.info, this ); + + this.errors = wp.Uploader.errors; + }, + + dispose: function() { + wp.Uploader.queue.off( null, null, this ); + media.View.prototype.dispose.apply( this, arguments ); + return this; + }, + + visibility: function() { + this.$el.toggleClass( 'uploading', !! this.queue.length ); + this.$el.toggle( !! this.queue.length || !! this.errors.length ); + }, + + ready: function() { + _.each({ + '$bar': '.media-progress-bar div', + '$index': '.upload-index', + '$total': '.upload-total', + '$filename': '.upload-filename' + }, function( selector, key ) { + this[ key ] = this.$( selector ); + }, this ); + + this.visibility(); + this.progress(); + this.info(); + }, + + progress: function() { + var queue = this.queue, + $bar = this.$bar, + memo = 0; + + if ( ! $bar || ! queue.length ) + return; + + $bar.width( ( queue.reduce( function( memo, attachment ) { + if ( ! attachment.get('uploading') ) + return memo + 100; + + var percent = attachment.get('percent'); + return memo + ( _.isNumber( percent ) ? percent : 100 ); + }, 0 ) / queue.length ) + '%' ); + }, + + info: function() { + var queue = this.queue, + index = 0, active; + + if ( ! queue.length ) + return; + + active = this.queue.find( function( attachment, i ) { + index = i; + return attachment.get('uploading'); + }); + + this.$index.text( index + 1 ); + this.$total.text( queue.length ); + this.$filename.html( active ? media.truncate( _.escape( active.get('filename') ), 24 ) : '' ); + } + }); + /** * wp.media.view.Toolbar */ @@ -2860,7 +2941,7 @@ _.defaults( this.options, { filters: false, search: true, - upload: false, + uploads: false, display: false, AttachmentView: media.view.Attachment.Library @@ -2914,15 +2995,6 @@ priority: -40 }) ); } - - if ( this.options.upload && this.controller.uploader ) { - this.toolbar.set( 'upload', new media.view.Button( _.extend({ - el: this.controller.uploader.$browser.detach()[0], - priority: -60, - size: 'large', - text: l10n.selectFiles - }, this.options.upload ) ).render() ); - } }, createAttachments: function() { @@ -2941,14 +3013,26 @@ }, createSidebar: function() { - this.sidebar = new media.view.Sidebar({ - controller: this.controller - }); + var options = this.options, + selection = options.selection, + sidebar = this.sidebar = new media.view.Sidebar({ + controller: this.controller + }); - this.views.add( this.sidebar ); + this.views.add( sidebar ); - this.options.selection.on( 'selection:single', this.createSingle, this ); - this.options.selection.on( 'selection:unsingle', this.disposeSingle, this ); + if ( options.uploads && this.controller.uploader ) { + sidebar.set( 'uploads', new media.view.UploaderStatus({ + controller: this.controller, + priority: 40 + }) ); + } + + selection.on( 'selection:single', this.createSingle, this ); + selection.on( 'selection:unsingle', this.disposeSingle, this ); + + if ( selection.single() ) + this.createSingle(); }, createSingle: function() { diff --git a/wp-includes/js/plupload/wp-plupload.js b/wp-includes/js/plupload/wp-plupload.js index 2c826085d5..79522e59c5 100644 --- a/wp-includes/js/plupload/wp-plupload.js +++ b/wp-includes/js/plupload/wp-plupload.js @@ -86,6 +86,13 @@ window.wp = window.wp || {}; error = function( message, data, file ) { if ( file.attachment ) file.attachment.destroy(); + + Uploader.errors.unshift({ + message: message, + data: data, + file: file + }); + self.error( message, data, file ); }; @@ -284,6 +291,7 @@ window.wp = window.wp || {}; }); Uploader.queue = new wp.media.model.Attachments( [], { query: false }); + Uploader.errors = new Backbone.Collection(); exports.Uploader = Uploader; })( wp, jQuery ); diff --git a/wp-includes/media.php b/wp-includes/media.php index 5078b9f0e7..9a24e68599 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -1443,6 +1443,20 @@ function wp_print_media_templates( $attachment ) { + +