jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/356238 )

Change subject: Make author list a ListPopupTool
......................................................................


Make author list a ListPopupTool

Change-Id: I6180216e04747e4d230bdf782422643f61e01574
---
M build/modules.json
M rebaser/demo.js
M rebaser/views/editor.ejs
A src/ui/styles/widgets/ve.ui.AuthorItemWidget.css
D src/ui/styles/widgets/ve.ui.AuthorListWidget.css
A src/ui/tools/ve.ui.AuthorListPopupTool.js
A src/ui/widgets/ve.ui.AuthorItemWidget.js
D src/ui/widgets/ve.ui.AuthorListWidget.js
M tests/index.html
9 files changed, 274 insertions(+), 155 deletions(-)

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



diff --git a/build/modules.json b/build/modules.json
index 23d662a..8d99674 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -631,10 +631,11 @@
                        "src/dm/ve.dm.RebaseServer.js",
                        "src/dm/ve.dm.RebaseClient.js",
                        "src/dm/ve.dm.SurfaceSynchronizer.js",
-                       "src/ui/widgets/ve.ui.AuthorListWidget.js"
+                       "src/ui/widgets/ve.ui.AuthorItemWidget.js",
+                       "src/ui/tools/ve.ui.AuthorListPopupTool.js"
                ],
                "styles": [
-                       "src/ui/styles/widgets/ve.ui.AuthorListWidget.css"
+                       "src/ui/styles/widgets/ve.ui.AuthorItemWidget.css"
                ],
                "dependencies": [
                        "dompurify",
diff --git a/rebaser/demo.js b/rebaser/demo.js
index b5553f5..537511a 100644
--- a/rebaser/demo.js
+++ b/rebaser/demo.js
@@ -4,21 +4,45 @@
  * @copyright 2011-2017 VisualEditor Team and others; see 
http://ve.mit-license.org
  */
 
-new ve.init.sa.Platform( ve.messagePaths ).initialize().done( function () {
-       var synchronizer, authorList,
-               $editor = $( '.ve-demo-editor' ),
-               $menu = $( '.ve-pad-menu' ),
-               // eslint-disable-next-line new-cap
-               target = new ve.demo.target();
+( function () {
+       function RebaserTarget() {
+               RebaserTarget.super.apply( this, arguments );
+       }
 
-       $editor.append( target.$element );
+       OO.inheritClass( RebaserTarget, ve.init.sa.Target );
 
-       target.addSurface( ve.dm.converter.getModelFromDom( 
ve.createDocumentFromHtml( '' ) ) );
-       synchronizer = new ve.dm.SurfaceSynchronizer( target.surface.model, 
ve.docName );
-       target.surface.view.setSynchronizer( synchronizer );
-       target.surface.view.focus();
+       RebaserTarget.static.actionGroups = ve.copy( 
RebaserTarget.static.actionGroups );
+       RebaserTarget.static.actionGroups.unshift(
+               { include: [ 'authorList' ] }
+       );
 
-       authorList = new ve.ui.AuthorListWidget( synchronizer );
+       RebaserTarget.prototype.setSurface = function ( surface ) {
+               var synchronizer, surfaceView;
 
-       $menu.append( authorList.$element );
-} );
+               if ( surface !== this.surface ) {
+                       surfaceView = surface.getView();
+
+                       synchronizer = new ve.dm.SurfaceSynchronizer(
+                               surface.getModel(),
+                               ve.docName,
+                               { server: this.rebaserUrl }
+                       );
+
+                       surfaceView.setSynchronizer( synchronizer );
+               }
+
+               // Parent method
+               RebaserTarget.super.prototype.setSurface.apply( this, arguments 
);
+       };
+
+       new ve.init.sa.Platform( ve.messagePaths ).initialize().done( function 
() {
+               var $editor = $( '.ve-demo-editor' ),
+                       // eslint-disable-next-line new-cap
+                       target = new RebaserTarget();
+
+               $editor.append( target.$element );
+
+               target.addSurface( ve.dm.converter.getModelFromDom( 
ve.createDocumentFromHtml( '' ) ) );
+               target.surface.view.focus();
+       } );
+}() );
diff --git a/rebaser/views/editor.ejs b/rebaser/views/editor.ejs
index 6914128..60526f4 100644
--- a/rebaser/views/editor.ejs
+++ b/rebaser/views/editor.ejs
@@ -40,7 +40,6 @@
        </head>
        <body>
                <div class="ve-pad-logo"></div>
-               <div class="ve-pad-menu"></div>
                <div style="clear: both;"></div>
                <div class="ve-demo-editor"></div>
 
diff --git a/src/ui/styles/widgets/ve.ui.AuthorItemWidget.css 
b/src/ui/styles/widgets/ve.ui.AuthorItemWidget.css
new file mode 100644
index 0000000..f6713ed
--- /dev/null
+++ b/src/ui/styles/widgets/ve.ui.AuthorItemWidget.css
@@ -0,0 +1,23 @@
+/*!
+ * VisualEditor AuthorInterface AuthorItemWidget styles.
+ *
+ * @copyright 2011-2017 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+.ve-ui-authorItemWidget {
+       position: relative;
+       margin: 0.2em 0;
+       padding-left: 2.5em;
+       line-height: 2em;
+}
+
+.ve-ui-authorItemWidget-color {
+       position: absolute;
+       width: 2em;
+       height: 2em;
+       left: 0;
+}
+
+.ve-ui-authorItemWidget-editable .ve-ui-authorItemWidget-color {
+       top: 0.25em;
+}
diff --git a/src/ui/styles/widgets/ve.ui.AuthorListWidget.css 
b/src/ui/styles/widgets/ve.ui.AuthorListWidget.css
deleted file mode 100644
index 929b6c6..0000000
--- a/src/ui/styles/widgets/ve.ui.AuthorListWidget.css
+++ /dev/null
@@ -1,33 +0,0 @@
-/*!
- * VisualEditor AuthorInterface AuthorListWidget styles.
- *
- * @copyright 2011-2017 VisualEditor Team and others; see 
http://ve.mit-license.org
- */
-
-.ve-ui-authorListWidget {
-       margin-right: 1em;
-}
-
-.ve-ui-authorListWidget-editName {
-       width: 20em;
-}
-
-.ve-ui-authorListWidget-editName,
-.ve-ui-authorListWidget-listPopup {
-       margin-right: 1em;
-       display: inline-block;
-       vertical-align: top;
-}
-
-.ve-ui-authorListWidget-author {
-       pointer-events: none;
-}
-
-.ve-ui-authorListWidget-author.oo-ui-iconElement .oo-ui-iconElement-icon {
-       top: 0.3em;
-       height: 1.875em;
-}
-
-.ve-ui-authorListWidget-author-self .oo-ui-labelElement-label {
-       font-weight: bold;
-}
diff --git a/src/ui/tools/ve.ui.AuthorListPopupTool.js 
b/src/ui/tools/ve.ui.AuthorListPopupTool.js
new file mode 100644
index 0000000..6e5bf51
--- /dev/null
+++ b/src/ui/tools/ve.ui.AuthorListPopupTool.js
@@ -0,0 +1,125 @@
+/*!
+ * VisualEditor UserInterface AuthorListPopupTool class.
+ *
+ * @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * UserInterface AuthorListPopupTool
+ *
+ * @class
+ * @extends OO.ui.PopupTool
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config]
+ */
+ve.ui.AuthorListPopupTool = function VeUiAuthorListPopupTool( toolGroup, 
config ) {
+       this.$authorList = $( '<div>' );
+
+       // Parent constructor
+       ve.ui.AuthorListPopupTool.super.call( this, toolGroup, ve.extendObject( 
{
+               popup: {
+                       classes: [ 've-ui-authorListWidget-listPopup' ],
+                       $content: this.$authorList,
+                       padded: true,
+                       align: 'center'
+               }
+       }, config ) );
+
+       // Events
+       this.toolbar.connect( this, { surfaceChange: 'onSurfaceChange' } );
+
+       this.setup( this.toolbar.getSurface() );
+
+       this.$element.addClass( 've-ui-authorListPopupTool' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.AuthorListPopupTool, OO.ui.PopupTool );
+
+/* Methods */
+
+ve.ui.AuthorListPopupTool.prototype.onSurfaceChange = function ( surface ) {
+       this.setup( surface );
+};
+
+/**
+ * Setup the popup which a specific surface
+ *
+ * @param {ve.ui.Surface} surface Surface
+ */
+ve.ui.AuthorListPopupTool.prototype.setup = function ( surface ) {
+       var tool = this,
+               synchronizer = surface.getView().synchronizer,
+               updatingName = false,
+               oldName = '',
+               authorItems = {};
+
+       // TODO: Unbind from an existing surface if one is set
+
+       function updateName() {
+               if ( !updatingName ) {
+                       synchronizer.changeName( tool.selfItem.input.getValue() 
);
+               }
+       }
+
+       function updateListCount() {
+               tool.setTitle( ( Object.keys( authorItems ).length + 1 
).toString() );
+       }
+
+       this.selfItem = new ve.ui.AuthorItemWidget( synchronizer, { editable: 
true } );
+       this.$authorList.prepend( this.selfItem.$element );
+       this.selfItem.input.on( 'change', ve.debounce( updateName, 250 ) );
+
+       synchronizer.on( 'authorNameChange', function ( authorId ) {
+               var authorItem = authorItems[ authorId ],
+                       newName = synchronizer.authorNames[ authorId ];
+
+               if ( authorId !== synchronizer.author ) {
+                       if ( !authorItem ) {
+                               authorItem = new ve.ui.AuthorItemWidget( 
synchronizer, { authorId: authorId } );
+                               authorItems[ authorId ] = authorItem;
+                               updateListCount();
+                               tool.$authorList.append( authorItem.$element );
+                       } else {
+                               authorItem.update();
+                       }
+               } else {
+                       // Don't update nameInput if the author is still 
changing it
+                       if ( tool.selfItem.input.getValue() === oldName ) {
+                               // Don't send this "new" name back to the server
+                               updatingName = true;
+                               tool.selfItem.setAuthor( synchronizer.author );
+                               tool.selfItem.update();
+                               updatingName = false;
+                       }
+               }
+               oldName = newName;
+       } );
+
+       synchronizer.on( 'authorDisconnect', function ( authorId ) {
+               var authorItem = authorItems[ authorId ];
+               if ( authorItem ) {
+                       authorItem.$element.remove();
+                       delete authorItems[ authorId ];
+                       updateListCount();
+               }
+       } );
+};
+
+/* Static Properties */
+
+ve.ui.AuthorListPopupTool.static.name = 'authorList';
+ve.ui.AuthorListPopupTool.static.group = 'utility';
+ve.ui.AuthorListPopupTool.static.icon = 'speechBubbles'; // TODO: Change to 
userAvatar once it is available in Apex
+ve.ui.AuthorListPopupTool.static.title = '1';
+ve.ui.AuthorListPopupTool.static.autoAddToCatchall = false;
+ve.ui.AuthorListPopupTool.static.autoAddToGroup = false;
+ve.ui.AuthorListPopupTool.static.displayBothIconAndLabel = true;
+
+/* Registration */
+
+ve.ui.toolFactory.register( ve.ui.AuthorListPopupTool );
diff --git a/src/ui/widgets/ve.ui.AuthorItemWidget.js 
b/src/ui/widgets/ve.ui.AuthorItemWidget.js
new file mode 100644
index 0000000..11f829f
--- /dev/null
+++ b/src/ui/widgets/ve.ui.AuthorItemWidget.js
@@ -0,0 +1,83 @@
+/*!
+ * VisualEditor UserInterface AuthorItemWidget class.
+ *
+ * @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * UserInterface AuthorItemWidget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {ve.dm.SurfaceSynchronizer} synchronizer Surface synchronizer
+ * @param {Object} [config] Configuration options
+ */
+ve.ui.AuthorItemWidget = function VeUiAuthorItemWidget( synchronizer, config ) 
{
+       config = config || {};
+
+       // Parent constructor
+       ve.ui.AuthorItemWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.mixin.LabelElement.call( this, config );
+
+       this.synchronizer = synchronizer;
+       this.editable = !!config.editable;
+       this.authorId = config.authorId;
+
+       this.$color = $( '<div>' ).addClass( 've-ui-authorItemWidget-color' );
+       this.$element.append( this.$color );
+
+       if ( this.editable ) {
+               this.input = new OO.ui.TextInputWidget();
+               this.$element
+                       .addClass( 've-ui-authorItemWidget-editable' )
+                       .append( this.input.$element );
+       } else {
+               this.$element.append( this.$label );
+       }
+
+       this.update();
+
+       this.$element.addClass( 've-ui-authorItemWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.AuthorItemWidget, OO.ui.Widget );
+
+OO.mixinClass( ve.ui.AuthorItemWidget, OO.ui.mixin.IconElement );
+
+OO.mixinClass( ve.ui.AuthorItemWidget, OO.ui.mixin.LabelElement );
+
+/* Methods */
+
+/**
+ * Set author ID
+ *
+ * @param {number} authorId Author ID
+ */
+ve.ui.AuthorItemWidget.prototype.setAuthor = function ( authorId ) {
+       this.authorId = authorId;
+};
+
+/**
+ * Update name and color from synchronizer
+ */
+ve.ui.AuthorItemWidget.prototype.update = function () {
+       var name = this.synchronizer.authorNames[ this.authorId ],
+               color = this.synchronizer.constructor.static.getAuthorColor( 
this.authorId );
+
+       this.$color.css( 'background-color', '#' + color );
+
+       if ( this.editable ) {
+               this.input.setValue( name );
+       } else {
+               this.setLabel( name );
+       }
+};
diff --git a/src/ui/widgets/ve.ui.AuthorListWidget.js 
b/src/ui/widgets/ve.ui.AuthorListWidget.js
deleted file mode 100644
index a58cd11..0000000
--- a/src/ui/widgets/ve.ui.AuthorListWidget.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/*!
- * VisualEditor AuthorInterface AuthorListWidget class.
- *
- * @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
- * @license The MIT License (MIT); see LICENSE.txt
- */
-
-/**
- * Creates a ve.ui.AuthorListWidget object.
- *
- * @class
- * @extends OO.ui.Element
- *
- * @constructor
- * @param {ve.dm.SurfaceSynchronizer} synchronizer Surface synchronizer
- * @param {Object} [config] Configuration options
- */
-ve.ui.AuthorListWidget = function VeUiAuthorListWidget( synchronizer, config ) 
{
-
-       var updatingName = false,
-               nameInput = new OO.ui.TextInputWidget(),
-               editNameLayout = new OO.ui.FieldLayout( nameInput, {
-                       classes: [ 've-ui-authorListWidget-editName' ],
-                       align: 'right',
-                       label: ve.msg( 'visualeditor-rebase-client-author-name' 
)
-               } ),
-               oldName = '',
-               $authorList = $( '<div>' ),
-               authorLabels = {},
-               listPopup = new OO.ui.PopupButtonWidget( {
-                       classes: [ 've-ui-authorListWidget-listPopup' ],
-                       icon: 'speechBubbles', // TODO: Change to userAvatar 
once it is available in Apex
-                       indicator: 'down',
-                       popup: {
-                               $content: $authorList,
-                               padded: true,
-                               align: 'center'
-                       }
-               } );
-
-       // Parent constructor
-       ve.ui.AuthorListWidget.super.call( this, config );
-
-       function updateName() {
-               if ( !updatingName ) {
-                       synchronizer.changeName( nameInput.getValue() );
-               }
-       }
-
-       function updateListCount() {
-               listPopup.setLabel( Object.keys( authorLabels 
).length.toString() );
-       }
-
-       synchronizer.on( 'authorNameChange', function ( authorId ) {
-               var authorLabel = authorLabels[ authorId ],
-                       newName = synchronizer.authorNames[ authorId ];
-
-               if ( !authorLabel ) {
-                       // FIXME use something more suitable than 
DecoratedOptionWidget
-                       authorLabel = new OO.ui.DecoratedOptionWidget( {
-                               classes: [ 've-ui-authorListWidget-author' ],
-                               // HACK: force the icon to show, but override 
the background with a color
-                               icon: 'none'
-                       } );
-                       authorLabel.$icon.css( 'background', '#' + 
synchronizer.constructor.static.getAuthorColor( authorId ) );
-                       authorLabels[ authorId ] = authorLabel;
-                       updateListCount();
-                       $authorList.append( authorLabel.$element );
-               }
-               authorLabel.setLabel( newName );
-               if ( authorId === synchronizer.author ) {
-                       // Ensure you are at the top of the list
-                       $authorList.prepend( authorLabel.$element.addClass( 
've-ui-authorListWidget-author-self' ) );
-                       // Don't update nameInput if the author is still 
changing it
-                       if ( nameInput.getValue() === oldName ) {
-                               // Don't send this "new" name back to the server
-                               updatingName = true;
-                               nameInput.setValue( newName );
-                               updatingName = false;
-                       }
-               }
-               oldName = newName;
-       } );
-
-       synchronizer.on( 'authorDisconnect', function ( authorId ) {
-               var authorLabel = authorLabels[ authorId ];
-               if ( authorLabel ) {
-                       authorLabel.$element.remove();
-                       delete authorLabels[ authorId ];
-                       updateListCount();
-               }
-       } );
-
-       nameInput.on( 'change', ve.debounce( updateName, 250 ) );
-
-       this.$element.addClass( 've-ui-authorListWidget' ).append(
-               editNameLayout.$element,
-               listPopup.$element
-       );
-};
-
-/* Inheritance */
-
-OO.inheritClass( ve.ui.AuthorListWidget, OO.ui.Widget );
diff --git a/tests/index.html b/tests/index.html
index 9f4d3a6..0769b6e 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -442,7 +442,8 @@
                <script src="../src/dm/ve.dm.RebaseServer.js"></script>
                <script src="../src/dm/ve.dm.RebaseClient.js"></script>
                <script src="../src/dm/ve.dm.SurfaceSynchronizer.js"></script>
-               <script 
src="../src/ui/widgets/ve.ui.AuthorListWidget.js"></script>
+               <script 
src="../src/ui/widgets/ve.ui.AuthorItemWidget.js"></script>
+               <script 
src="../src/ui/tools/ve.ui.AuthorListPopupTool.js"></script>
 
                <!-- visualEditor.test -->
                <script src="../tests/ve.qunit.js"></script>

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I6180216e04747e4d230bdf782422643f61e01574
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <esand...@wikimedia.org>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to