Catrope has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/75555


Change subject: Render check boxes from EditPage
......................................................................

Render check boxes from EditPage

EditPage has a lovely getCheckboxes() function which includes the
minor and watch checkboxes as rendered by MW core, as well as any
checkboxes extensions like FlaggedRevs might have added. Output
these in the API, render them, and send their values back.

ApiVisualEditor.php:
* Build a fake EditPage, get its checkboxes, and return them

ApiVisualEditorEdit.php:
* Pass through posted request data to ApiEdit, which passes it
  through to EditPage thanks to Idab5b524b0e3 in core

ve.init.mw.ViewPageTarget.js:
* Remove minor and watch checkboxes from the save dialog template
  and replace them with a generic checkbox container
* Have getSaveOptions() pull the state of all checkboxes in
** Special-case minor and watch, and pass the rest straight through
** Move normalization from true/false to presence/absence here, from
   ve.init.mw.Target.prototype.save(), because here we know which ones
   are checkboxes and we don't know that in save() without
   special-casing
* Remove getSaveDialogHtml(), we don't need to hide checkboxes based on
  rights anymore because in that case the API just won't send them to us.
** Moved logic for checking the watch checkbox down to where the same
   logic for the minor checkbox already is
* Unwrap getSaveDialogHtml() in setupSaveDialog()
* Access minor and watch by their new IDs throughout

ve.init.mw.Target.js:
* Get and store checkboxes from the API
* Pass all keys straight through to the API

Bug: 49699
Change-Id: I09d02a42b05146bc9b7080ab38338ae869bf15e3
---
M ApiVisualEditor.php
M ApiVisualEditorEdit.php
M modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
M modules/ve-mw/init/ve.init.mw.Target.js
4 files changed, 141 insertions(+), 175 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/55/75555/1

diff --git a/ApiVisualEditor.php b/ApiVisualEditor.php
index ba65a97..d509eaf 100644
--- a/ApiVisualEditor.php
+++ b/ApiVisualEditor.php
@@ -244,13 +244,23 @@
                                                $notices[] = wfMessage( $key 
)->parseAsBlock();
                                        }
                                }
+
+                               // HACK: Build a fake EditPage so we can get 
checkboxes from it
+                               $article = new Article( $page ); // 
Deliberately omitting ,0 so oldid comes from request
+                               $ep = new EditPage( $article );
+                               $ep->importFormData( $this->getRequest() );
+                               $tabindex = 0;
+                               $states = array( 'minor' => false, 'watch' => 
false );
+                               $checkboxes = $ep->getCheckboxes( $tabindex, 
$states );
+
                                if ( $parsed === false ) {
                                        $this->dieUsage( 'Error contacting the 
Parsoid server', 'parsoidserver' );
                                } else {
                                        $result = array_merge(
                                                array(
                                                        'result' => 'success',
-                                                       'notices' => $notices
+                                                       'notices' => $notices,
+                                                       'checkboxes' => 
$checkboxes,
                                                ),
                                                $parsed['result']
                                        );
diff --git a/ApiVisualEditorEdit.php b/ApiVisualEditorEdit.php
index 7140dea..331bfd8 100644
--- a/ApiVisualEditorEdit.php
+++ b/ApiVisualEditorEdit.php
@@ -39,7 +39,7 @@
                $api = new ApiMain(
                        new DerivativeRequest(
                                $this->getRequest(),
-                               $apiParams,
+                               $apiParams + $this->getRequest()->getValues(),
                                true // was posted
                        ),
                        true // enable write
diff --git a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js 
b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
index 8d2cdf7..3b43824 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
@@ -194,14 +194,8 @@
                                        rows="4"></textarea>\
                        </div>\
                        <div 
class="ve-init-mw-viewPageTarget-saveDialog-options">\
-                               <input type="checkbox" name="minorEdit" \
-                                       
id="ve-init-mw-viewPageTarget-saveDialog-minorEdit">\
-                               <label 
class="ve-init-mw-viewPageTarget-saveDialog-minorEdit-label"\
-                                       
for="ve-init-mw-viewPageTarget-saveDialog-minorEdit"></label>\
-                               <input type="checkbox" name="watchList"\
-                                       
id="ve-init-mw-viewPageTarget-saveDialog-watchList">\
-                               <label 
class="ve-init-mw-viewPageTarget-saveDialog-watchList-label"\
-                                       
for="ve-init-mw-viewPageTarget-saveDialog-watchList"></label>\
+                               <div 
class="ve-init-mw-viewPageTarget-saveDialog-checkboxes">\
+                               </div>\
                                <label 
class="ve-init-mw-viewPageTarget-saveDialog-editSummaryCount"></label>\
                        </div>\
                        <div 
class="ve-init-mw-viewPageTarget-saveDialog-messages"></div>\
@@ -956,14 +950,32 @@
  * @returns {Object} Save options, including summary, minor and watch 
properties
  */
 ve.init.mw.ViewPageTarget.prototype.getSaveOptions = function () {
-       return {
-               'summary': $( 
'#ve-init-mw-viewPageTarget-saveDialog-editSummary' ).val(),
-               'minor': $( '#ve-init-mw-viewPageTarget-saveDialog-minorEdit' 
).prop( 'checked' ),
-               'watch': $( '#ve-init-mw-viewPageTarget-saveDialog-watchList' 
).prop( 'checked' ),
-               'needcheck': this.sanityCheckPromise.state() === 'rejected',
+       var options = {
+               'summary': this.$saveDialog.find( 
'#ve-init-mw-viewPageTarget-saveDialog-editSummary' ).val(),
                'captchaid': this.captcha && this.captcha.id,
                'captchaword': this.captcha && this.captcha.input.getValue()
        };
+       if ( this.sanityCheckPromise.state() === 'rejected' ) {
+               options.needcheck = 1;
+       }
+       if ( this.$saveDialog.find( '#wpMinoredit' ).prop( 'checked' ) ) {
+               options.minor = 1;
+       }
+       if ( this.$saveDialog.find( '#wpWatchthis' ).prop( 'checked' ) ) {
+               options.watch = 1;
+       }
+       this.$saveDialog
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-checkboxes' )
+               .find( 'input:not(#wpMinoredit, #wpWatchthis)' )
+               .each( function () {
+                       var $this = $( this );
+                       // We can't just use $this.val() because .val() always 
returns the value attribute of
+                       // a checkbox even when it's unchecked
+                       if ( $this.prop( 'type') !== 'checkbox' || $this.prop( 
'checked' ) ) {
+                               options[$this.prop( 'name' )] = $this.val();
+                       }
+               } );
+       return options;
 };
 
 /**
@@ -1390,55 +1402,12 @@
 };
 
 /**
- * Get a template for the save dialog.
- *
- * The result of this function depends on an API call, so the result it 
provided asynchronously.
- * The template will be wrapped in a plain `<div>` jQuery collection.
- *
- * @method
- * @param {Function} callback
- */
-ve.init.mw.ViewPageTarget.prototype.getSaveDialogHtml = function ( callback ) {
-       var viewPage = this,
-               $wrap = $( '<div>' ).html( this.constructor.saveDialogTemplate 
);
-
-       // Based on EditPage::getCheckboxes and EditPage::initialiseForm
-
-       mw.user.getRights( function ( rights ) {
-               // MediaWiki only allows usage of minor flag when editing an 
existing page
-               // and the user has the right to use the feature.
-               // If either is not the case, remove it from the form.
-               if ( !viewPage.pageExists || ve.indexOf( 'minoredit', rights ) 
=== -1 ) {
-                       $wrap
-                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-minorEdit-label, 
#ve-init-mw-viewPageTarget-saveDialog-minorEdit' )
-                               .remove();
-               }
-
-               if ( mw.user.isAnon() ) {
-                       $wrap
-                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-watchList-label, 
#ve-init-mw-viewPageTarget-saveDialog-watchList' )
-                               .remove();
-               } else if (
-                       mw.user.options.get( 'watchdefault' ) ||
-                       ( mw.user.options.get( 'watchcreations' ) && 
!viewPage.pageExists ) ||
-                       mw.config.get( 'wgVisualEditor' ).isPageWatched
-               ) {
-                       $wrap
-                               .find( 
'#ve-init-mw-viewPageTarget-saveDialog-watchList' )
-                               .prop( 'checked', true );
-               }
-
-               callback( $wrap );
-       } );
-};
-
-/**
  * Add content and event bindings to the save dialog.
  *
  * @method
  */
 ve.init.mw.ViewPageTarget.prototype.setupSaveDialog = function () {
-       var viewPage = this;
+       var sectionTitle = '', viewPage = this;
 
        // Save button on "save" slide
        this.saveDialogSaveButton = new ve.ui.ButtonWidget( {
@@ -1472,109 +1441,111 @@
        } );
        this.saveDialogResolveConflictButton.connect( this, { 'click': 
'onSaveDialogResolveConflictButtonClick' } );
 
-       this.getSaveDialogHtml( function ( $wrap ) {
-               var sectionTitle = '';
-               if ( viewPage.section ) {
-                       sectionTitle = viewPage.$document.find( 'h1, h2, h3, 
h4, h5, h6' ).eq( viewPage.section - 1 ).text();
-                       sectionTitle = '/* ' + ve.graphemeSafeSubstring( 
sectionTitle, 0, 244 ) + ' */ ';
-                       viewPage.sectionTitleRestored = true;
-                       if ( viewPage.sectionPositionRestored ) {
-                               viewPage.onSectionRestored();
-                       }
+
+       if ( viewPage.section ) {
+               sectionTitle = viewPage.$document.find( 'h1, h2, h3, h4, h5, 
h6' ).eq( viewPage.section - 1 ).text();
+               sectionTitle = '/* ' + ve.graphemeSafeSubstring( sectionTitle, 
0, 244 ) + ' */ ';
+               viewPage.sectionTitleRestored = true;
+               if ( viewPage.sectionPositionRestored ) {
+                       viewPage.onSectionRestored();
                }
-               viewPage.$saveDialog
-                       // Must not use replaceWith because that can't be used 
on fragement roots,
-                       // plus, we want to preserve the reference and class 
names of the wrapper.
-                       .empty().append( $wrap.contents() )
-                       // Attach buttons
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-slide-save' )
-                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-actions' )
-                                       .prepend( 
viewPage.saveDialogSaveButton.$, viewPage.saveDialogReviewButton.$ )
-                                       .end()
-                       .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-slide-review' )
-                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-actions' )
-                                       .prepend( 
viewPage.saveDialogReviewGoodButton.$ )
-                                       .end()
-                       .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-slide-conflict' )
-                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-actions' )
-                                       .prepend( 
viewPage.saveDialogResolveConflictButton.$ )
-                                       .end()
-                       .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-closeButton' )
-                               .click( ve.bind( 
viewPage.onSaveDialogCloseButtonClick, viewPage ) )
+       }
+       viewPage.$saveDialog
+               // Must not use replaceWith because that can't be used on 
fragement roots,
+               // plus, we want to preserve the reference and class names of 
the wrapper.
+               .empty().append( this.constructor.saveDialogTemplate )
+               // Attach buttons
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-slide-save' )
+                       .find( '.ve-init-mw-viewPageTarget-saveDialog-actions' )
+                               .prepend( viewPage.saveDialogSaveButton.$, 
viewPage.saveDialogReviewButton.$ )
                                .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-prevButton' )
-                               .click( ve.bind( 
viewPage.onSaveDialogPrevButtonClick, viewPage ) )
+               .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-slide-review' )
+                       .find( '.ve-init-mw-viewPageTarget-saveDialog-actions' )
+                               .prepend( viewPage.saveDialogReviewGoodButton.$ 
)
                                .end()
-                       // Attach contents
-                       .find( 
'#ve-init-mw-viewPageTarget-saveDialog-editSummary-label' )
-                               .html( ve.init.platform.getParsedMessage( 
'summary' ) )
+               .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-slide-conflict' )
+                       .find( '.ve-init-mw-viewPageTarget-saveDialog-actions' )
+                               .prepend( 
viewPage.saveDialogResolveConflictButton.$ )
                                .end()
-                       .find( 
'#ve-init-mw-viewPageTarget-saveDialog-editSummary' )
-                               .attr( {
-                                       'placeholder': ve.msg( 
'visualeditor-editsummary' )
-                               } )
-                               .val( sectionTitle )
-                               .placeholder()
-                               .byteLimit( viewPage.editSummaryByteLimit )
-                               .on( {
-                                       'focus': function () {
-                                               $( this ).parent().addClass(
-                                                       
've-init-mw-viewPageTarget-saveDialog-summary-focused'
+               .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-closeButton' )
+                       .click( ve.bind( viewPage.onSaveDialogCloseButtonClick, 
viewPage ) )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-prevButton' )
+                       .click( ve.bind( viewPage.onSaveDialogPrevButtonClick, 
viewPage ) )
+                       .end()
+               // Attach contents
+               .find( 
'#ve-init-mw-viewPageTarget-saveDialog-editSummary-label' )
+                       .html( ve.init.platform.getParsedMessage( 'summary' ) )
+                       .end()
+               .find( '#ve-init-mw-viewPageTarget-saveDialog-editSummary' )
+                       .attr( {
+                               'placeholder': ve.msg( 
'visualeditor-editsummary' )
+                       } )
+                       .val( sectionTitle )
+                       .placeholder()
+                       .byteLimit( viewPage.editSummaryByteLimit )
+                       .on( {
+                               'focus': function () {
+                                       $( this ).parent().addClass(
+                                               
've-init-mw-viewPageTarget-saveDialog-summary-focused'
+                                       );
+                               },
+                               'blur': function () {
+                                       $( this ).parent().removeClass(
+                                               
've-init-mw-viewPageTarget-saveDialog-summary-focused'
+                                       );
+                               },
+                               'keyup keydown mouseup cut paste change focus 
blur': function () {
+                                       var $textarea = $( this ),
+                                               $editSummaryCount = $textarea
+                                                       .closest( 
'.ve-init-mw-viewPageTarget-saveDialog-slide-save' )
+                                                               .find( 
'.ve-init-mw-viewPageTarget-saveDialog-editSummaryCount' );
+                                       // TODO: This looks a bit weird, there 
is no unit in the UI, just numbers
+                                       // Users likely assume characters but 
then it seems to count down quicker
+                                       // than expected. Facing users with the 
word "byte" is bad? (bug 40035)
+                                       setTimeout( function () {
+                                               $editSummaryCount.text(
+                                                       
viewPage.editSummaryByteLimit - $.byteLength( $textarea.val() )
                                                );
-                                       },
-                                       'blur': function () {
-                                               $( this ).parent().removeClass(
-                                                       
've-init-mw-viewPageTarget-saveDialog-summary-focused'
-                                               );
-                                       },
-                                       'keyup keydown mouseup cut paste change 
focus blur': function () {
-                                               var $textarea = $( this ),
-                                                       $editSummaryCount = 
$textarea
-                                                               .closest( 
'.ve-init-mw-viewPageTarget-saveDialog-slide-save' )
-                                                                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-editSummaryCount' );
-                                               // TODO: This looks a bit 
weird, there is no unit in the UI, just numbers
-                                               // Users likely assume 
characters but then it seems to count down quicker
-                                               // than expected. Facing users 
with the word "byte" is bad? (bug 40035)
-                                               setTimeout( function () {
-                                                       $editSummaryCount.text(
-                                                               
viewPage.editSummaryByteLimit - $.byteLength( $textarea.val() )
-                                                       );
-                                               } );
-                                       }
-                               } )
+                                       } );
+                               }
+                       } )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-editSummaryCount' 
)
+                       .text( viewPage.editSummaryByteLimit )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-checkboxes' )
+                       .html( ve.getObjectValues( viewPage.checkboxes ).join( 
'\n' ) )
+                       .find( 'a' )
+                               .attr( 'target', '_blank' )
                                .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-editSummaryCount' )
-                               .text( viewPage.editSummaryByteLimit )
-                               .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-minorEdit-label' )
-                               .html( ve.init.platform.getParsedMessage( 
'minoredit' ) )
-                               .find( 'a' )
-                                       .attr( 'target', '_blank' )
-                                       .end()
-                               .end()
-                       .find( 
'#ve-init-mw-viewPageTarget-saveDialog-minorEdit' )
+                       .find( '#wpMinoredit' )
                                .prop( 'checked', +mw.user.options.get( 
'minordefault' ) )
                                .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-watchList-label' )
-                               .html( ve.init.platform.getParsedMessage( 
'watchthis' ) )
-                               .end()
-                       .find( '.ve-init-mw-viewPageTarget-saveDialog-license' )
-                               .html( ve.init.platform.getParsedMessage( 
'copyrightwarning' ) )
-                               .end()
-                       .find( '.ve-init-mw-viewPageTarget-saveDialog-conflict' 
)
-                               .html( ve.init.platform.getParsedMessage( 
'visualeditor-editconflict' ) )
-                               .end()
-                       .find( 
'.ve-init-mw-viewPageTarget-saveDialog-nochanges' )
-                               .html( ve.init.platform.getParsedMessage( 
'visualeditor-diff-nochanges' ) )
-               ;
+                       .find( '#wpWatchthis' )
+                               .prop( 'checked',
+                                       mw.user.options.get( 'watchdefault' ) ||
+                                       ( mw.user.options.get( 'watchcreations' 
) && !viewPage.pageExists ) ||
+                                       mw.config.get( 'wgVisualEditor' 
).isPageWatched
+                               )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-license' )
+                       .html( ve.init.platform.getParsedMessage( 
'copyrightwarning' ) )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-conflict' )
+                       .html( ve.init.platform.getParsedMessage( 
'visualeditor-editconflict' ) )
+                       .end()
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-nochanges' )
+                       .html( ve.init.platform.getParsedMessage( 
'visualeditor-diff-nochanges' ) )
+       ;
 
-               // Get reference to loading icon
-               viewPage.$saveDialogLoadingIcon = viewPage.$saveDialog
-                       .find( '.ve-init-mw-viewPageTarget-saveDialog-working' 
);
-       } );
+       // Get reference to loading icon
+       viewPage.$saveDialogLoadingIcon = viewPage.$saveDialog
+               .find( '.ve-init-mw-viewPageTarget-saveDialog-working' );
+
        // Hook onto the 'watch' event on by mediawiki.page.watch.ajax.js
        // Triggered when mw.page.watch.updateWatchLink(link, action) is called
        $( '#ca-watch, #ca-unwatch' )
@@ -1670,7 +1641,7 @@
                .find( '#ve-init-mw-viewPageTarget-saveDialog-editSummary' )
                        .val( '' )
                        .end()
-               .find( '#ve-init-mw-viewPageTarget-saveDialog-minorEdit' )
+               .find( '#wpMinoredit' )
                        .prop( 'checked', false )
                        .end()
                // Clear the diff
diff --git a/modules/ve-mw/init/ve.init.mw.Target.js 
b/modules/ve-mw/init/ve.init.mw.Target.js
index 7e382f8..3246912 100644
--- a/modules/ve-mw/init/ve.init.mw.Target.js
+++ b/modules/ve-mw/init/ve.init.mw.Target.js
@@ -50,6 +50,7 @@
        this.startTimeStamp = null;
        this.doc = null;
        this.editNotices = null;
+       this.checkboxes = null;
        this.remoteNotices = [];
        this.localNoticeMessages = [];
        this.isMobileDevice = (
@@ -163,6 +164,7 @@
                this.doc = ve.createDocumentFromHtml( this.originalHtml );
 
                this.remoteNotices = ve.getObjectValues( data.notices );
+               this.checkboxes = data.checkboxes;
 
                this.baseTimeStamp = data.basetimestamp;
                this.startTimeStamp = data.starttimestamp;
@@ -559,7 +561,7 @@
  *
  * @method
  * @param {HTMLDocument} doc Document to save
- * @param {Object} options Saving options
+ * @param {Object} options Saving options. All keys are passed through, 
including unrecognized ones.
  *  - {string} summary Edit summary
  *  - {boolean} minor Edit is a minor edit
  *  - {boolean} watch Watch the page
@@ -571,7 +573,7 @@
                return false;
        }
 
-       var data = {
+       var data = $.extend( {}, options, {
                'format': 'json',
                'action': 'visualeditoredit',
                'page': this.pageName,
@@ -579,25 +581,8 @@
                'basetimestamp': this.baseTimeStamp,
                'starttimestamp': this.startTimeStamp,
                'html': this.getHtml( doc ),
-               'token': this.editToken,
-               'summary': options.summary
-       };
-
-       if ( options.minor ) {
-               data.minor = 1;
-       }
-       if ( options.watch ) {
-               data.watch = 1;
-       }
-       if ( options.needcheck ) {
-               data.needcheck = 1;
-       }
-       if ( options.captchaid ) {
-               data.captchaid = options.captchaid;
-       }
-       if ( options.captchaword ) {
-               data.captchaword = options.captchaword;
-       }
+               'token': this.editToken
+       } );
 
        // Save DOM
        this.saving = true;

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I09d02a42b05146bc9b7080ab38338ae869bf15e3
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <roan.katt...@gmail.com>

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

Reply via email to