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

Change subject: Section editing in NWE
......................................................................


Section editing in NWE

Bug: T144654
Change-Id: Ida6e721e0d980b47e3fda6a1f0744cbce1b2235a
---
M ApiVisualEditor.php
M ApiVisualEditorEdit.php
M modules/ve-mw/i18n/en.json
M modules/ve-mw/i18n/qqq.json
M modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.init.js
M modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
M modules/ve-mw/init/targets/ve.init.mw.DesktopWikitextArticleTarget.js
M modules/ve-mw/init/ve.init.MWVESwitchConfirmDialog.js
M modules/ve-mw/init/ve.init.mw.ArticleTarget.js
M modules/ve-mw/init/ve.init.mw.ArticleTargetLoader.js
10 files changed, 122 insertions(+), 55 deletions(-)

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



diff --git a/ApiVisualEditor.php b/ApiVisualEditor.php
index 960edf5..a79d5ee 100644
--- a/ApiVisualEditor.php
+++ b/ApiVisualEditor.php
@@ -190,13 +190,15 @@
                );
        }
 
-       protected function diffWikitext( $title, $wikitext ) {
+       protected function diffWikitext( $title, $wikitext, $section = null ) {
                $apiParams = [
                        'action' => 'query',
                        'prop' => 'revisions',
                        'titles' => $title->getPrefixedDBkey(),
-                       'rvdifftotext' => $this->pstWikitext( $title, $wikitext 
)
+                       'rvdifftotext' => $this->pstWikitext( $title, $wikitext 
),
+                       'rvsection' => $section
                ];
+
                $api = new ApiMain(
                        new DerivativeRequest(
                                $this->getRequest(),
@@ -345,6 +347,11 @@
                                                        'prop' => 'revisions',
                                                        'rvprop' => 'content'
                                                ];
+
+                                               if ( isset( $params['section'] 
) ) {
+                                                       $apiParams['rvsection'] 
= $params['section'];
+                                               }
+
                                                $api = new ApiMain(
                                                        new DerivativeRequest(
                                                                
$this->getRequest(),
@@ -623,7 +630,8 @@
                                        }
                                }
 
-                               $diff = $this->diffWikitext( $title, $wikitext 
);
+                               $section = isset( $params['section'] ) ? 
$params['section'] : null;
+                               $diff = $this->diffWikitext( $title, $wikitext, 
$section );
                                if ( $diff['result'] === 'fail' ) {
                                        $this->dieUsage( 'Diff failed', 
'difffailed' );
                                }
@@ -759,6 +767,7 @@
                                ],
                        ],
                        'wikitext' => null,
+                       'section' => null,
                        'oldid' => null,
                        'html' => null,
                        'etag' => null,
diff --git a/ApiVisualEditorEdit.php b/ApiVisualEditorEdit.php
index d7bee07..c52112f 100644
--- a/ApiVisualEditorEdit.php
+++ b/ApiVisualEditorEdit.php
@@ -252,6 +252,7 @@
                                ApiBase::PARAM_REQUIRED => true,
                        ],
                        'wikitext' => null,
+                       'section' => null,
                        'basetimestamp' => null,
                        'starttimestamp' => null,
                        'oldid' => null,
diff --git a/modules/ve-mw/i18n/en.json b/modules/ve-mw/i18n/en.json
index f58cb81..570d4cc 100644
--- a/modules/ve-mw/i18n/en.json
+++ b/modules/ve-mw/i18n/en.json
@@ -28,6 +28,7 @@
        "apihelp-visualeditor-param-paction": "Action to perform.",
        "apihelp-visualeditor-param-page": "The page to perform actions on.",
        "apihelp-visualeditor-param-pst": "Pre-save transform wikitext before 
sending it to Parsoid (paction=parsefragment).",
+       "apihelp-visualeditor-param-section": "The section on which to act.",
        "apihelp-visualeditor-param-starttimestamp": "When saving, set this to 
the timestamp of when the page was loaded. Used to detect edit conflicts.",
        "apihelp-visualeditor-param-wikitext": "Wikitext to send to Parsoid to 
convert to HTML (paction=parsefragment).",
        "apihelp-visualeditoredit-description": "Save an HTML5 page to 
MediaWiki (converted to wikitext via the Parsoid service).",
@@ -41,6 +42,7 @@
        "apihelp-visualeditoredit-param-needcheck": "When saving, set this 
parameter if the revision might have roundtrip problems. This will result in 
the edit being tagged.",
        "apihelp-visualeditoredit-param-oldid": "The revision number to use. 
Defaults to latest revision. Use 0 for a new page.",
        "apihelp-visualeditoredit-param-page": "The page to perform actions 
on.",
+       "apihelp-visualeditoredit-param-section": "The section on which to 
act.",
        "apihelp-visualeditoredit-param-starttimestamp": "When saving, set this 
to the timestamp of when the page was loaded. Used to detect edit conflicts.",
        "apihelp-visualeditoredit-param-summary": "Edit summary.",
        "apihelp-visualeditoredit-param-watch": "",
diff --git a/modules/ve-mw/i18n/qqq.json b/modules/ve-mw/i18n/qqq.json
index 19c3fc2..0ff1e0d 100644
--- a/modules/ve-mw/i18n/qqq.json
+++ b/modules/ve-mw/i18n/qqq.json
@@ -41,6 +41,7 @@
        "apihelp-visualeditor-param-paction": 
"{{doc-apihelp-param|visualeditor|paction}}",
        "apihelp-visualeditor-param-page": 
"{{doc-apihelp-param|visualeditor|page}}",
        "apihelp-visualeditor-param-pst": 
"{{doc-apihelp-param|visualeditor|pst}}",
+    "apihelp-visualeditor-param-section": 
"{{doc-apihelp-param|visualeditor|section}}",
        "apihelp-visualeditor-param-starttimestamp": 
"{{doc-apihelp-param|visualeditor|starttimestamp}}",
        "apihelp-visualeditor-param-wikitext": 
"{{doc-apihelp-param|visualeditor|wikitext}}",
        "apihelp-visualeditoredit-description": 
"{{doc-apihelp-description|visualeditoredit}}",
@@ -54,6 +55,7 @@
        "apihelp-visualeditoredit-param-needcheck": 
"{{doc-apihelp-param|visualeditoredit|needcheck}}",
        "apihelp-visualeditoredit-param-oldid": 
"{{doc-apihelp-param|visualeditoredit|oldid}}",
        "apihelp-visualeditoredit-param-page": 
"{{doc-apihelp-param|visualeditoredit|page}}",
+    "apihelp-visualeditoredit-param-section": 
"{{doc-apihelp-param|visualeditoredit|section}}",
        "apihelp-visualeditoredit-param-starttimestamp": 
"{{doc-apihelp-param|visualeditoredit|starttimestamp}}",
        "apihelp-visualeditoredit-param-summary": 
"{{doc-apihelp-param|visualeditoredit|summary}}\n{{Identical|Edit summary}}",
        "apihelp-visualeditoredit-param-watch": 
"{{doc-apihelp-param|visualeditoredit|watch}}",
diff --git a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.init.js 
b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.init.js
index 41cfd7b..d50c7d1 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.init.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.init.js
@@ -197,7 +197,7 @@
                                uri = veEditUri;
                        }
 
-                       activateTarget( mode, null, modified );
+                       activateTarget( mode, null, undefined, modified );
                }
        }
 
@@ -210,10 +210,11 @@
         *
         * @private
         * @param {string} mode Target mode: 'visual' or 'source'
+        * @param {number} [section] Section to edit (currently just source 
mode)
         * @param {jQuery.Promise} [targetPromise] Promise that will be 
resolved with a ve.init.mw.DesktopArticleTarget
         * @param {boolean} [modified] The page was been modified before 
loading (e.g. in source mode)
         */
-       function activateTarget( mode, targetPromise, modified ) {
+       function activateTarget( mode, section, targetPromise, modified ) {
                var dataPromise;
                // Only call requestPageData early if the target object isn't 
there yet.
                // If the target object is there, this is a second or 
subsequent load, and the
@@ -226,6 +227,7 @@
                                        return 
mw.libs.ve.targetLoader.requestPageData(
                                                mode,
                                                mw.config.get( 
'wgRelevantPageName' ),
+                                               section,
                                                oldid,
                                                'mwTarget', // 
ve.init.mw.DesktopArticleTarget.static.name
                                                modified
@@ -459,10 +461,10 @@
                                $caVeEdit.remove();
                        } else if ( pageCanLoadVE ) {
                                // Allow instant switching to edit mode, 
without refresh
-                               $caVeEdit.on( 'click', init.onEditTabClick );
+                               $caVeEdit.on( 'click', 
init.onEditTabClick.bind( init, 'visual' ) );
                        }
                        if ( conf.enableWikitext && mw.user.options.get( 
'visualeditor-newwikitext' ) ) {
-                               $caEdit.on( 'click', init.onEditSourceTabClick 
);
+                               $caEdit.on( 'click', init.onEditTabClick.bind( 
init, 'source' ) );
                        }
 
                        // Alter the edit tab (#ca-edit)
@@ -526,6 +528,7 @@
                                                                } );
                                                        } )
                                                        .addClass( 
'mw-editsection-visualeditor' );
+
                                                if ( conf.tabPosition === 
'before' ) {
                                                        $editSourceLink.before( 
$editLink, $divider );
                                                } else {
@@ -543,8 +546,13 @@
                                // and would preserve the wrong DOM with a diff 
on top.
                                $editsections
                                        .find( '.mw-editsection-visualeditor' )
-                                               .on( 'click', 
init.onEditSectionLinkClick )
-                               ;
+                                               .on( 'click', 
init.onEditSectionLinkClick.bind( init, 'visual' ) );
+                               if ( conf.enableWikitext ) {
+                                       $editsections
+                                               // TOOD: Make this less fragile
+                                               .find( 'a:not( 
.mw-editsection-visualeditor )' )
+                                                       .on( 'click', 
init.onEditSectionLinkClick.bind( init, 'source' ) );
+                               }
                        }
                },
 
@@ -562,7 +570,7 @@
                        return e && e.which && e.which === 1 && !( e.shiftKey 
|| e.altKey || e.ctrlKey || e.metaKey );
                },
 
-               onEditTabClick: function ( e ) {
+               onEditTabClick: function ( mode, e ) {
                        if ( !init.isUnmodifiedLeftClick( e ) ) {
                                return;
                        }
@@ -577,19 +585,8 @@
                                        }
                                } );
                        } else {
-                               init.activateVe( 'visual' );
+                               init.activateVe( mode );
                        }
-               },
-
-               onEditSourceTabClick: function ( e ) {
-                       if ( !init.isUnmodifiedLeftClick( e ) ) {
-                               return;
-                       }
-                       e.preventDefault();
-                       if ( isLoading ) {
-                               return;
-                       }
-                       init.activateVe( 'source' );
                },
 
                activateVe: function ( mode ) {
@@ -639,8 +636,8 @@
                        }
                },
 
-               onEditSectionLinkClick: function ( e ) {
-                       var targetPromise;
+               onEditSectionLinkClick: function ( mode, e ) {
+                       var section, targetPromise;
                        if ( !init.isUnmodifiedLeftClick( e ) ) {
                                return;
                        }
@@ -661,11 +658,20 @@
                                history.pushState( { tag: 'visualeditor' }, 
document.title, this.href );
                        }
 
-                       targetPromise = getTarget( 'visual' ).then( function ( 
target ) {
-                               target.saveEditSection( $( e.target ).closest( 
'h1, h2, h3, h4, h5, h6' ).get( 0 ) );
-                               return target;
-                       } );
-                       activateTarget( 'visual', targetPromise );
+                       targetPromise = getTarget( mode );
+                       if ( mode === 'visual' ) {
+                               targetPromise = targetPromise.then( function ( 
target ) {
+                                       target.saveEditSection( $( e.target 
).closest( 'h1, h2, h3, h4, h5, h6' ).get( 0 ) );
+                                       return target;
+                               } );
+                       } else {
+                               section = +( new mw.Uri( e.target.href 
).query.section );
+                               targetPromise = targetPromise.then( function ( 
target ) {
+                                       target.section = section;
+                                       return target;
+                               } );
+                       }
+                       activateTarget( mode, section, targetPromise );
                }
        };
 
@@ -765,6 +771,7 @@
 
        $( function () {
                var showWikitextWelcome = true,
+                       section = uri.query.vesection !== undefined ? 
uri.query.vesection : null,
                        isLoggedIn = !mw.user.isAnon(),
                        prefSaysShowWelcome = isLoggedIn && 
!mw.user.options.get( 'visualeditor-hidebetawelcome' ),
                        urlSaysHideWelcome = 'hidewelcomedialog' in new mw.Uri( 
location.href ).query,
@@ -838,7 +845,7 @@
                                ) {
                                        showWikitextWelcome = false;
                                        trackActivateStart( {
-                                               type: uri.query.vesection === 
undefined ? 'page' : 'section',
+                                               type: section === null ? 'page' 
: 'section',
                                                mechanism: 'url'
                                        } );
                                        if ( isViewPage && uri.query.veaction 
in editModes ) {
@@ -857,7 +864,7 @@
                                                ) {
                                                        action = 'editsource';
                                                }
-                                               activateTarget( editModes[ 
action ] );
+                                               activateTarget( editModes[ 
action ], section );
                                        }
                                } else if (
                                        init.isVisualAvailable &&
diff --git a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js 
b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
index fe47c30..4d4e4d2 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
@@ -56,7 +56,7 @@
        };
        this.scrollTop = null;
        this.currentUri = currentUri;
-       this.section = currentUri.query.vesection;
+       this.section = currentUri.query.vesection !== undefined ? 
+currentUri.query.vesection : null;
        if ( $( '#wpSummary' ).length ) {
                this.initialEditSummary = $( '#wpSummary' ).val();
        } else {
diff --git 
a/modules/ve-mw/init/targets/ve.init.mw.DesktopWikitextArticleTarget.js 
b/modules/ve-mw/init/targets/ve.init.mw.DesktopWikitextArticleTarget.js
index b93a893..4cdfad2 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.DesktopWikitextArticleTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.DesktopWikitextArticleTarget.js
@@ -66,19 +66,40 @@
  * Switch to the visual editor.
  */
 ve.init.mw.DesktopWikitextArticleTarget.prototype.switchToVisualEditor = 
function () {
-       var dataPromise;
+       var dataPromise, windowManager, switchWindow,
+               target = this;
 
-       dataPromise = mw.libs.ve.targetLoader.requestParsoidData(
-               this.pageName,
-               this.revid,
-               this.constructor.name,
-               this.edited,
-               this.getDocToSave()
-       );
+       if ( this.section !== null ) {
+               // WT -> VE switching is not yet supported in sections, so
+               // show a discard-only confirm dialog, then reload the whole 
page.
+               windowManager = new OO.ui.WindowManager();
+               switchWindow = new mw.libs.ve.SwitchConfirmDialog();
+               $( 'body' ).append( windowManager.$element );
+               windowManager.addWindows( [ switchWindow ] );
+               windowManager.openWindow( switchWindow, { mode: 'simple' } )
+                       .then( function ( opened ) {
+                               return opened;
+                       } )
+                       .then( function ( closing ) { return closing; } )
+                       .then( function ( data ) {
+                               if ( data && data.action === 'discard' ) {
+                                       target.setMode( 'visual' );
+                                       target.reloadSurface();
+                               }
+                               windowManager.destroy();
+                       } );
+       } else {
+               dataPromise = mw.libs.ve.targetLoader.requestParsoidData(
+                       this.pageName,
+                       this.revid,
+                       this.constructor.name,
+                       this.edited,
+                       this.getDocToSave()
+               );
 
-       this.setMode( 'visual' );
-
-       this.reloadSurface( dataPromise );
+               this.setMode( 'visual' );
+               this.reloadSurface( dataPromise );
+       }
 };
 
 /**
@@ -206,6 +227,16 @@
 };
 
 /**
+ * @inheritdoc
+ */
+ve.init.mw.DesktopWikitextArticleTarget.prototype.restoreEditSection = 
function () {
+       if ( this.mode !== 'source' ) {
+               // Parent method
+               return 
ve.init.mw.DesktopWikitextArticleTarget.super.prototype.restoreEditSection.apply(
 this, arguments );
+       }
+};
+
+/**
  * Get a wikitext fragment from a document
  *
  * @param {ve.dm.Document} doc Document
@@ -309,11 +340,17 @@
  * @inheritdoc
  */
 ve.init.mw.DesktopWikitextArticleTarget.prototype.tryWithPreparedCacheKey = 
function ( doc, options ) {
+       var data;
        if ( this.mode === 'source' ) {
-               return new mw.Api().post( ve.extendObject( {}, options, {
-                               wikitext: doc,
-                               format: 'json'
-                       } ),
+               data = {
+                       wikitext: doc,
+                       format: 'json'
+               };
+               if ( this.section !== null ) {
+                       data.section = this.section;
+               }
+               return new mw.Api().post(
+                       ve.extendObject( {}, options, data ),
                        { contentType: 'multipart/form-data' }
                );
        } else {
diff --git a/modules/ve-mw/init/ve.init.MWVESwitchConfirmDialog.js 
b/modules/ve-mw/init/ve.init.MWVESwitchConfirmDialog.js
index ce0fbd4..6efa33c 100644
--- a/modules/ve-mw/init/ve.init.MWVESwitchConfirmDialog.js
+++ b/modules/ve-mw/init/ve.init.MWVESwitchConfirmDialog.js
@@ -64,10 +64,12 @@
 /**
  * @inheritdoc
  */
-mw.libs.ve.SwitchConfirmDialog.prototype.getSetupProcess = function () {
+mw.libs.ve.SwitchConfirmDialog.prototype.getSetupProcess = function ( data ) {
        return 
mw.libs.ve.SwitchConfirmDialog.super.prototype.getSetupProcess.apply( this, 
arguments )
                .next( function () {
-                       if (
+                       if ( data && data.mode ) {
+                               this.actions.setMode( data.mode );
+                       } else if (
                                mw.config.get( 'wgVisualEditorConfig' 
).fullRestbaseUrl &&
                                !$( 'input[name=wpSection]' ).val()
                        ) {
diff --git a/modules/ve-mw/init/ve.init.mw.ArticleTarget.js 
b/modules/ve-mw/init/ve.init.mw.ArticleTarget.js
index 545dba5..ab9fed5 100644
--- a/modules/ve-mw/init/ve.init.mw.ArticleTarget.js
+++ b/modules/ve-mw/init/ve.init.mw.ArticleTarget.js
@@ -40,6 +40,7 @@
        this.pageExists = mw.config.get( 'wgRelevantArticleId', 0 ) !== 0;
        this.toolbarScrollOffset = mw.config.get( 
'wgVisualEditorToolbarScrollOffset', 0 );
        this.mode = config.mode || 'visual';
+       this.section = null;
 
        // Sometimes we actually don't want to send a useful oldid
        // if we do, PostEdit will give us a 'page restored' message
@@ -1022,6 +1023,7 @@
        this.loading = dataPromise || mw.libs.ve.targetLoader.requestPageData(
                this.mode,
                this.pageName,
+               this.section,
                this.requestedRevId,
                this.constructor.name
        );
@@ -1046,6 +1048,7 @@
        this.startTimeStamp = null;
        this.doc = null;
        this.originalHtml = null;
+       this.section = null;
        this.editNotices = [];
        this.remoteNotices = [];
        this.localNoticeMessages = [];
@@ -1704,7 +1707,7 @@
 ve.init.mw.ArticleTarget.prototype.restoreEditSection = function () {
        var surfaceView, $documentNode, $section, headingNode;
 
-       if ( this.section !== undefined && this.section > 0 ) {
+       if ( this.section !== null && this.section > 0 ) {
                surfaceView = this.getSurface().getView();
                $documentNode = 
surfaceView.getDocument().getDocumentNode().$element;
                $section = $documentNode.find( 'h1, h2, h3, h4, h5, h6' ).eq( 
this.section - 1 );
@@ -1718,8 +1721,6 @@
                if ( headingNode ) {
                        this.goToHeading( headingNode );
                }
-
-               this.section = undefined;
        }
 };
 
diff --git a/modules/ve-mw/init/ve.init.mw.ArticleTargetLoader.js 
b/modules/ve-mw/init/ve.init.mw.ArticleTargetLoader.js
index 3df202d..89b6f0a 100644
--- a/modules/ve-mw/init/ve.init.mw.ArticleTargetLoader.js
+++ b/modules/ve-mw/init/ve.init.mw.ArticleTargetLoader.js
@@ -107,14 +107,15 @@
                 *
                 * @param {string} mode Target mode: 'visual' or 'source'
                 * @param {string} pageName Page name to request
+                * @param {number} [section] Section to edit (currently just 
source mode)
                 * @param {string} [oldid] Old revision ID, current if omitted
                 * @param {string} [targetName] Optional target name for 
tracking
                 * @param {boolean} [modified] The page was been modified 
before loading (e.g. in source mode)
                 * @return {jQuery.Promise} Abortable promise resolved with a 
JSON object
                 */
-               requestPageData: function ( mode, pageName, oldid, targetName, 
modified ) {
+               requestPageData: function ( mode, pageName, section, oldid, 
targetName, modified ) {
                        if ( mode === 'source' ) {
-                               return this.requestWikitext( pageName, oldid, 
targetName, modified );
+                               return this.requestWikitext( pageName, section, 
oldid, targetName, modified );
                        } else {
                                return this.requestParsoidData( pageName, 
oldid, targetName, modified );
                        }
@@ -245,7 +246,7 @@
                        return dataPromise;
                },
 
-               requestWikitext: function ( pageName, oldid /*, targetName */ ) 
{
+               requestWikitext: function ( pageName, section, oldid /*, 
targetName */ ) {
                        var data = {
                                        action: 'visualeditor',
                                        paction: 'wikitext',
@@ -253,6 +254,11 @@
                                        uselang: mw.config.get( 
'wgUserLanguage' )
                                };
 
+                       // section should never really be undefined, but check 
just in case
+                       if ( section !== null && section !== undefined ) {
+                               data.section = section;
+                       }
+
                        if ( oldid !== undefined ) {
                                data.oldid = oldid;
                        }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ida6e721e0d980b47e3fda6a1f0744cbce1b2235a
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <esand...@wikimedia.org>
Gerrit-Reviewer: Alex Monk <a...@wikimedia.org>
Gerrit-Reviewer: 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