jenkins-bot has submitted this change and it was merged.

Change subject: Generic progress dialog for drag and drop uploads
......................................................................


Generic progress dialog for drag and drop uploads

Change-Id: I1e3f2218868b3de6db07b9b576e5ade60e68bfa0
---
M .docs/eg-iframe.html
M build/modules.json
M demos/ve/desktop.html
M demos/ve/mobile.html
A src/ui/dialogs/ve.ui.ProgressDialog.js
A src/ui/styles/dialogs/ve.ui.ProgressDialog.css
M src/ui/ve.ui.FileDropHandler.js
M src/ui/ve.ui.PlainTextFileDropHandler.js
M src/ui/ve.ui.Surface.js
M tests/index.html
10 files changed, 267 insertions(+), 0 deletions(-)

Approvals:
  Trevor Parscal: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/.docs/eg-iframe.html b/.docs/eg-iframe.html
index 6d489de..3d66d1f 100644
--- a/.docs/eg-iframe.html
+++ b/.docs/eg-iframe.html
@@ -25,6 +25,7 @@
                <link rel=stylesheet href="../src/ce/styles/ve.ce.css">
                <link rel=stylesheet href="../src/ce/styles/ve.ce.Surface.css">
                <link rel=stylesheet 
href="../src/ui/styles/dialogs/ve.ui.CommandHelpDialog.css">
+               <link rel=stylesheet 
href="../src/ui/styles/dialogs/ve.ui.ProgressDialog.css">
                <link rel=stylesheet 
href="../src/ui/styles/tools/ve.ui.FormatTool.css">
                <link rel=stylesheet 
href="../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css">
                <link rel=stylesheet 
href="../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css">
@@ -296,6 +297,7 @@
                <script 
src="../src/ui/dialogs/ve.ui.CommandHelpDialog.js"></script>
                <script 
src="../src/ui/dialogs/ve.ui.FragmentDialog.js"></script>
                <script src="../src/ui/dialogs/ve.ui.NodeDialog.js"></script>
+               <script 
src="../src/ui/dialogs/ve.ui.ProgressDialog.js"></script>
                <script 
src="../src/ui/widgets/ve.ui.LanguageSearchWidget.js"></script>
                <script 
src="../src/ui/widgets/ve.ui.LanguageResultWidget.js"></script>
                <script 
src="../src/ui/dialogs/ve.ui.LanguageSearchDialog.js"></script>
diff --git a/build/modules.json b/build/modules.json
index 4aeffb9..36feddf 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -320,6 +320,7 @@
                        "src/ui/dialogs/ve.ui.CommandHelpDialog.js",
                        "src/ui/dialogs/ve.ui.FragmentDialog.js",
                        "src/ui/dialogs/ve.ui.NodeDialog.js",
+                       "src/ui/dialogs/ve.ui.ProgressDialog.js",
                        "src/ui/widgets/ve.ui.LanguageSearchWidget.js",
                        "src/ui/widgets/ve.ui.LanguageResultWidget.js",
                        "src/ui/dialogs/ve.ui.LanguageSearchDialog.js",
@@ -363,6 +364,7 @@
                        "src/ce/styles/ve.ce.css",
                        "src/ce/styles/ve.ce.Surface.css",
                        "src/ui/styles/dialogs/ve.ui.CommandHelpDialog.css",
+                       "src/ui/styles/dialogs/ve.ui.ProgressDialog.css",
                        "src/ui/styles/tools/ve.ui.FormatTool.css",
                        "src/ui/styles/widgets/ve.ui.LanguageInputWidget.css",
                        "src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css",
diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html
index 8d38ad2..9657a7a 100644
--- a/demos/ve/desktop.html
+++ b/demos/ve/desktop.html
@@ -34,6 +34,7 @@
                <link rel=stylesheet href="../../src/ce/styles/ve.ce.css">
                <link rel=stylesheet 
href="../../src/ce/styles/ve.ce.Surface.css">
                <link rel=stylesheet 
href="../../src/ui/styles/dialogs/ve.ui.CommandHelpDialog.css">
+               <link rel=stylesheet 
href="../../src/ui/styles/dialogs/ve.ui.ProgressDialog.css">
                <link rel=stylesheet 
href="../../src/ui/styles/tools/ve.ui.FormatTool.css">
                <link rel=stylesheet 
href="../../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css">
                <link rel=stylesheet 
href="../../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css">
@@ -309,6 +310,7 @@
                <script 
src="../../src/ui/dialogs/ve.ui.CommandHelpDialog.js"></script>
                <script 
src="../../src/ui/dialogs/ve.ui.FragmentDialog.js"></script>
                <script src="../../src/ui/dialogs/ve.ui.NodeDialog.js"></script>
+               <script 
src="../../src/ui/dialogs/ve.ui.ProgressDialog.js"></script>
                <script 
src="../../src/ui/widgets/ve.ui.LanguageSearchWidget.js"></script>
                <script 
src="../../src/ui/widgets/ve.ui.LanguageResultWidget.js"></script>
                <script 
src="../../src/ui/dialogs/ve.ui.LanguageSearchDialog.js"></script>
diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html
index d8cedce..1d771f9 100644
--- a/demos/ve/mobile.html
+++ b/demos/ve/mobile.html
@@ -34,6 +34,7 @@
                <link rel=stylesheet href="../../src/ce/styles/ve.ce.css">
                <link rel=stylesheet 
href="../../src/ce/styles/ve.ce.Surface.css">
                <link rel=stylesheet 
href="../../src/ui/styles/dialogs/ve.ui.CommandHelpDialog.css">
+               <link rel=stylesheet 
href="../../src/ui/styles/dialogs/ve.ui.ProgressDialog.css">
                <link rel=stylesheet 
href="../../src/ui/styles/tools/ve.ui.FormatTool.css">
                <link rel=stylesheet 
href="../../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css">
                <link rel=stylesheet 
href="../../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css">
@@ -310,6 +311,7 @@
                <script 
src="../../src/ui/dialogs/ve.ui.CommandHelpDialog.js"></script>
                <script 
src="../../src/ui/dialogs/ve.ui.FragmentDialog.js"></script>
                <script src="../../src/ui/dialogs/ve.ui.NodeDialog.js"></script>
+               <script 
src="../../src/ui/dialogs/ve.ui.ProgressDialog.js"></script>
                <script 
src="../../src/ui/widgets/ve.ui.LanguageSearchWidget.js"></script>
                <script 
src="../../src/ui/widgets/ve.ui.LanguageResultWidget.js"></script>
                <script 
src="../../src/ui/dialogs/ve.ui.LanguageSearchDialog.js"></script>
diff --git a/src/ui/dialogs/ve.ui.ProgressDialog.js 
b/src/ui/dialogs/ve.ui.ProgressDialog.js
new file mode 100644
index 0000000..ff35f99
--- /dev/null
+++ b/src/ui/dialogs/ve.ui.ProgressDialog.js
@@ -0,0 +1,140 @@
+/*!
+ * VisualEditor UserInterface ProgressDialog class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * Dialog for showing operations in progress.
+ *
+ * @class
+ * @extends OO.ui.MessageDialog
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ve.ui.ProgressDialog = function VeUiProgressDialog( config ) {
+       // Parent constructor
+       ve.ui.ProgressDialog.super.call( this, config );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.ProgressDialog, OO.ui.MessageDialog );
+
+/* Static Properties */
+
+ve.ui.ProgressDialog.static.name = 'progress';
+
+ve.ui.ProgressDialog.static.size = 'medium';
+
+ve.ui.ProgressDialog.static.actions = [
+       {
+               action: 'cancel',
+               label: OO.ui.deferMsg( 'visualeditor-dialog-action-cancel' ),
+               flags: 'destructive'
+       }
+];
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+ve.ui.ProgressDialog.prototype.initialize = function () {
+       // Parent method
+       ve.ui.ProgressDialog.super.prototype.initialize.call( this );
+
+       // Properties
+       this.inProgress = 0;
+       this.cancelDeferreds = [];
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.ProgressDialog.prototype.getSetupProcess = function ( data ) {
+       data = data || {};
+
+       // Parent method
+       return ve.ui.ProgressDialog.super.prototype.getSetupProcess.call( this, 
data )
+               .next( function () {
+                       var i, l, $row, progressBar, fieldLayout, cancelButton, 
cancelDeferred,
+                               progresses = data.progresses;
+
+                       this.inProgress = progresses.length;
+                       this.text.$element.empty();
+                       this.cancelDeferreds = [];
+
+                       for ( i = 0, l = progresses.length; i < l; i++ ) {
+                               cancelDeferred = $.Deferred();
+                               $row = this.$( '<div>' ).addClass( 
've-ui-progressDialog-row' );
+                               progressBar = new OO.ui.ProgressBarWidget( { $: 
this.$ } );
+                               fieldLayout = new OO.ui.FieldLayout(
+                                       progressBar,
+                                       {
+                                               $: this.$,
+                                               label: progresses[i].label,
+                                               align: 'top'
+                                       }
+                               );
+                               cancelButton = new OO.ui.ButtonWidget( {
+                                       $: this.$,
+                                       framed: false,
+                                       icon: 'clear',
+                                       iconTitle: OO.ui.deferMsg( 
'visualeditor-dialog-action-cancel' )
+                               } ).on( 'click', cancelDeferred.reject.bind( 
cancelDeferred ) );
+
+                               this.text.$element.append(
+                                       $row.append(
+                                               fieldLayout.$element, 
cancelButton.$element
+                                       )
+                               );
+                               progresses[i].progressBarDeferred.resolve( 
progressBar, cancelDeferred.promise() );
+                               /*jshint loopfunc:true */
+                               progresses[i].progressCompletePromise.then(
+                                       this.progressComplete.bind( this, $row, 
false ),
+                                       this.progressComplete.bind( this, $row, 
true )
+                               );
+                               this.cancelDeferreds.push( cancelDeferred );
+                       }
+               }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.ProgressDialog.prototype.getActionProcess = function ( action ) {
+       return new OO.ui.Process( function () {
+               var i, l;
+               if ( action === 'cancel' ) {
+                       for ( i = 0, l = this.cancelDeferreds.length; i < l; 
i++ ) {
+                               this.cancelDeferreds[i].reject();
+                       }
+               }
+               this.close( { action: action } );
+       }, this );
+};
+
+/**
+ * Progress has completed for an item
+ *
+ * @param {jQuery} $row Row containing progress bar which has completed
+ * @param {boolean} failed The item failed
+ */
+ve.ui.ProgressDialog.prototype.progressComplete = function ( $row, failed ) {
+       this.inProgress--;
+       if ( !this.inProgress ) {
+               this.close();
+       }
+       if ( failed ) {
+               $row.remove();
+               this.manager.updateWindowSize( this );
+       }
+};
+
+/* Static methods */
+
+/* Registration */
+
+ve.ui.windowFactory.register( ve.ui.ProgressDialog );
diff --git a/src/ui/styles/dialogs/ve.ui.ProgressDialog.css 
b/src/ui/styles/dialogs/ve.ui.ProgressDialog.css
new file mode 100644
index 0000000..752752b
--- /dev/null
+++ b/src/ui/styles/dialogs/ve.ui.ProgressDialog.css
@@ -0,0 +1,23 @@
+/*!
+ * VisualEditor UserInterface ProgressDialog styles.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+.ve-ui-progressDialog-row {
+       display: table;
+       width: 100%;
+       margin-bottom: 1em;
+}
+
+.ve-ui-progressDialog-row .oo-ui-fieldLayout {
+       display: table-cell;
+       padding-bottom: 0.45em;
+}
+
+.ve-ui-progressDialog-row .oo-ui-buttonWidget {
+       display: table-cell;
+       vertical-align: bottom;
+       width: 1.9em;
+       padding-left: 1em;
+}
diff --git a/src/ui/ve.ui.FileDropHandler.js b/src/ui/ve.ui.FileDropHandler.js
index 4da35cf..1248c03 100644
--- a/src/ui/ve.ui.FileDropHandler.js
+++ b/src/ui/ve.ui.FileDropHandler.js
@@ -23,6 +23,9 @@
 
        this.reader = new FileReader();
 
+       this.progress = false;
+       this.progessBar = null;
+
        // Events
        this.reader.addEventListener( 'progress', this.onFileProgress.bind( 
this ) );
        this.reader.addEventListener( 'load', this.onFileLoad.bind( this ) );
@@ -95,3 +98,41 @@
  * @param {Event} e Load end event
  */
 ve.ui.FileDropHandler.prototype.onFileLoadEnd = function () {};
+
+/**
+ * Abort the file drop handler
+ */
+ve.ui.FileDropHandler.prototype.abort = function () {
+       this.insertableDataDeferred.reject();
+};
+
+/**
+ * Create a progress bar with a specified label
+ *
+ * @param {jQuery.Promise} progressCompletePromise Promise which resolves when 
the progress action is complete
+ * @param {jQuery|string|Function} [label] Progress bar label, defaults to 
file name
+ */
+ve.ui.FileDropHandler.prototype.createProgress = function ( 
progressCompletePromise, label ) {
+       var handler = this;
+
+       this.surface.createProgress( progressCompletePromise, label || 
this.file.name ).done( function ( progessBar, cancelPromise ) {
+               // Set any progress that was achieved before this resolved
+               progessBar.setProgress( handler.progress );
+               handler.progressBar = progessBar;
+               cancelPromise.fail( handler.abort.bind( handler ) );
+       } );
+};
+
+/**
+ * Set progress bar progress
+ *
+ * Progress is stored in a property in case the progress bar doesn't exist yet.
+ *
+ * @param {number} progress Progess percent
+ */
+ve.ui.FileDropHandler.prototype.setProgress = function ( progress ) {
+       this.progress = progress;
+       if ( this.progressBar ) {
+               this.progressBar.setProgress( this.progress );
+       }
+};
diff --git a/src/ui/ve.ui.PlainTextFileDropHandler.js 
b/src/ui/ve.ui.PlainTextFileDropHandler.js
index 64f298b..589ab64 100644
--- a/src/ui/ve.ui.PlainTextFileDropHandler.js
+++ b/src/ui/ve.ui.PlainTextFileDropHandler.js
@@ -35,7 +35,19 @@
  * @inheritdoc
  */
 ve.ui.PlainTextFileDropHandler.prototype.process = function () {
+       this.createProgress( this.insertableDataDeferred.promise() );
        this.reader.readAsText( this.file );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.PlainTextFileDropHandler.prototype.onFileProgress = function ( e ) {
+       if ( e.lengthComputable ) {
+               this.setProgress( 100 * e.loaded / e.total );
+       } else {
+               this.setProgress( false );
+       }
 };
 
 /**
@@ -54,6 +66,7 @@
                }
        }
        this.insertableDataDeferred.resolve( data );
+       this.setProgress( 100 );
 };
 
 /**
@@ -65,6 +78,16 @@
        this.insertableDataDeferred.reject();
 };
 
+/**
+ * @inheritdoc
+ */
+ve.ui.PlainTextFileDropHandler.prototype.abort = function () {
+       // Parent method
+       ve.ui.PlainTextFileDropHandler.super.prototype.abort.call( this );
+
+       this.reader.abort();
+};
+
 /* Registration */
 
 ve.ui.fileDropHandlerFactory.register( ve.ui.PlainTextFileDropHandler );
diff --git a/src/ui/ve.ui.Surface.js b/src/ui/ve.ui.Surface.js
index 600537d..806ec85 100644
--- a/src/ui/ve.ui.Surface.js
+++ b/src/ui/ve.ui.Surface.js
@@ -48,6 +48,8 @@
        this.pasteRules = {};
        this.enabled = true;
        this.context = this.createContext();
+       this.progresses = [];
+       this.showProgressDebounced = ve.debounce( this.showProgress.bind( this 
) );
        this.filibuster = null;
 
        // Events
@@ -381,6 +383,35 @@
 };
 
 /**
+ * Create a progress bar in the progres dialog
+ *
+ * @param {jQuery.Promise} progressCompletePromise Promise which resolves when 
the progress action is complete
+ * @param {jQuery|string|Function} label Progress bar label
+ * @return {jQuery.Promise} Promise which resolves with a progress bar widget 
and a promise which fails if cancelled
+ */
+ve.ui.Surface.prototype.createProgress = function ( progressCompletePromise, 
label ) {
+       var progressBarDeferred = $.Deferred();
+
+       this.progresses.push( {
+               label: label,
+               progressCompletePromise: progressCompletePromise,
+               progressBarDeferred: progressBarDeferred
+       } );
+
+       this.showProgressDebounced();
+
+       return progressBarDeferred.promise();
+};
+
+ve.ui.Surface.prototype.showProgress = function () {
+       var dialogs = this.dialogs,
+               progresses = this.progresses;
+
+       dialogs.openWindow( 'progress', { progresses: progresses } );
+       this.progresses = [];
+};
+
+/**
  * Get sanitization rules for rich paste
  *
  * @returns {Object} Paste rules
diff --git a/tests/index.html b/tests/index.html
index 23e4d74..ae9e90a 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -260,6 +260,7 @@
                <script 
src="../src/ui/dialogs/ve.ui.CommandHelpDialog.js"></script>
                <script 
src="../src/ui/dialogs/ve.ui.FragmentDialog.js"></script>
                <script src="../src/ui/dialogs/ve.ui.NodeDialog.js"></script>
+               <script 
src="../src/ui/dialogs/ve.ui.ProgressDialog.js"></script>
                <script 
src="../src/ui/widgets/ve.ui.LanguageSearchWidget.js"></script>
                <script 
src="../src/ui/widgets/ve.ui.LanguageResultWidget.js"></script>
                <script 
src="../src/ui/dialogs/ve.ui.LanguageSearchDialog.js"></script>

-- 
To view, visit https://gerrit.wikimedia.org/r/171770
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I1e3f2218868b3de6db07b9b576e5ade60e68bfa0
Gerrit-PatchSet: 3
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to