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

Change subject: DesktopArticleTarget: Rebuild the category links when they're 
edited
......................................................................


DesktopArticleTarget: Rebuild the category links when they're edited

This has to go to the API, because it's skinnable. Also, separates out a few
of the initial page setup functions so they can be re-applied to the new
content inserted.

Bug: T151651
Change-Id: I8d5a6504edc2e0486a0b4f016d8ee6d9a6228de9
---
M modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
1 file changed, 124 insertions(+), 49 deletions(-)

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



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 7860bba..783ba95 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js
@@ -597,6 +597,7 @@
 
                // Move original content back out of the target
                target.$element.parent().append( 
target.$originalContent.children() );
+               $( '#catlinks' ).replaceWith( target.$originalCategories );
                $( '.ve-init-mw-desktopArticleTarget-uneditableContent' )
                        .off( '.ve-target' )
                        .removeClass( 
've-init-mw-desktopArticleTarget-uneditableContent' );
@@ -742,45 +743,51 @@
  * @param {boolean} [loading=false] Whether VE is loading.
  */
 ve.init.mw.DesktopArticleTarget.prototype.onMetaItemInserted = function ( 
metaItem, loading ) {
-       var title, target, $link;
-       if ( metaItem.getType() === 'mwRedirect' ) {
-               target = this;
-               title = metaItem.getAttribute( 'title' );
-               $link = $( '<a>' )
-                       .attr( 'title', mw.msg( 
'visualeditor-redirect-description', title ) )
-                       .text( title );
-               ve.init.platform.linkCache.styleElement( title, $link );
+       var title, target, $link,
+               metaList = this.surface.getModel().getMetaList();
+       switch ( metaItem.getType() ) {
+               case 'mwRedirect':
+                       target = this;
+                       title = metaItem.getAttribute( 'title' );
+                       $link = $( '<a>' )
+                               .attr( 'title', mw.msg( 
'visualeditor-redirect-description', title ) )
+                               .text( title );
+                       ve.init.platform.linkCache.styleElement( title, $link );
 
-               if ( loading ) {
-                       this.$originalRedirectMsg = $( '.redirectMsg' ).clone();
-                       this.$originalRedirectSub = $( '#redirectsub, 
#redirectsub + br' ).clone();
-               }
-               // Add redirect target header
-               if ( !$( '#redirectsub' ).length ) {
-                       $( '#contentSub' ).append(
-                               $( '<span>' )
-                                       .text( mw.msg( 'redirectpagesub' ) )
-                                       .attr( 'id', 'redirectsub' ),
-                               $( '<br>' )
-                       );
-               }
-               $( '<div>' )
-                       // Bit of a hack: Make sure any redirect note is styled
-                       .addClass( 'redirectMsg mw-content-' + $( 'html' 
).attr( 'dir' ) )
+                       if ( loading ) {
+                               this.$originalRedirectMsg = $( '.redirectMsg' 
).clone();
+                               this.$originalRedirectSub = $( '#redirectsub, 
#redirectsub + br' ).clone();
+                       }
+                       // Add redirect target header
+                       if ( !$( '#redirectsub' ).length ) {
+                               $( '#contentSub' ).append(
+                                       $( '<span>' )
+                                               .text( mw.msg( 
'redirectpagesub' ) )
+                                               .attr( 'id', 'redirectsub' ),
+                                       $( '<br>' )
+                               );
+                       }
+                       $( '<div>' )
+                               // Bit of a hack: Make sure any redirect note 
is styled
+                               .addClass( 'redirectMsg mw-content-' + $( 
'html' ).attr( 'dir' ) )
 
-                       .addClass( 've-redirect-header' )
-                       .append(
-                               $( '<p>' ).text( mw.msg( 'redirectto' ) ),
-                               $( '<ul>' )
-                                       .addClass( 'redirectText' )
-                                       .append( $( '<li>' ).append( $link ) )
-                       )
-                       .click( function ( e ) {
-                               var windowAction = ve.ui.actionFactory.create( 
'window', target.getSurface() );
-                               windowAction.open( 'meta', { page: 'settings' } 
);
-                               e.preventDefault();
-                       } )
-                       .insertAfter( $( '.mw-jump' ) );
+                               .addClass( 've-redirect-header' )
+                               .append(
+                                       $( '<p>' ).text( mw.msg( 'redirectto' ) 
),
+                                       $( '<ul>' )
+                                               .addClass( 'redirectText' )
+                                               .append( $( '<li>' ).append( 
$link ) )
+                               )
+                               .click( function ( e ) {
+                                       var windowAction = 
ve.ui.actionFactory.create( 'window', target.getSurface() );
+                                       windowAction.open( 'meta', { page: 
'settings' } );
+                                       e.preventDefault();
+                               } )
+                               .insertAfter( $( '.mw-jump' ) );
+                       break;
+               case 'mwCategory':
+                       this.rebuildCategories( metaList.getItemsInGroup( 
'mwCategory' ) );
+                       break;
        }
 };
 
@@ -792,10 +799,53 @@
  * @param {number} index Index within that offset the item was at
  */
 ve.init.mw.DesktopArticleTarget.prototype.onMetaItemRemoved = function ( 
metaItem ) {
-       if ( metaItem.getType() === 'mwRedirect' ) {
-               this.$originalContent.find( '.redirectMsg' ).remove();
-               $( '#contentSub #redirectsub, #contentSub #redirectsub + br' 
).remove();
+       var metaList = this.surface.getModel().getMetaList();
+       switch ( metaItem.getType() ) {
+               case 'mwRedirect':
+                       this.$originalContent.find( '.redirectMsg' ).remove();
+                       $( '#contentSub #redirectsub, #contentSub #redirectsub 
+ br' ).remove();
+                       break;
+               case 'mwCategory':
+                       this.rebuildCategories( metaList.getItemsInGroup( 
'mwCategory' ) );
+                       break;
        }
+};
+
+/**
+ * Redisplay the category list on the page
+ *
+ * @param {ve.dm.MetaItem[]} categoryItems Array of category metaitems to 
display
+ */
+ve.init.mw.DesktopArticleTarget.prototype.rebuildCategories = function ( 
categoryItems ) {
+       var target = this;
+       // We need to fetch this from the API because the category list is skin-
+       // dependent, so the HTML output could be absolutely anything.
+       new mw.Api().post( {
+               formatversion: 2,
+               action: 'parse',
+               contentmodel: 'wikitext',
+               text: categoryItems.map( function ( categoryItem ) {
+                       // TODO: wikitext-building is a bad smell here, but is 
done
+                       // because there's no other API call that will get the 
category
+                       // markup. Adding such an API, if other use cases for 
it emerge,
+                       // might make sense.
+                       if ( categoryItem.getAttribute( 'sortkey' ) ) {
+                               return '[[' + categoryItem.getAttribute( 
'category' ) + '|' + categoryItem.getAttribute( 'sortkey' ) + ']]';
+                       }
+                       return '[[' + categoryItem.getAttribute( 'category' ) + 
']]';
+               } ).join( '\n' ),
+               prop: 'categorieshtml'
+       } ).then( function ( response ) {
+               var $categories;
+               if ( !response || !response.parse || 
!response.parse.categorieshtml ) {
+                       return;
+               }
+               $categories = $( $.parseHTML( response.parse.categorieshtml ) );
+               target.transformCategoryLinks( $categories );
+               target.disableUneditableContent( $categories );
+               mw.hook( 'wikipage.categories' ).fire( $categories );
+               $( '#catlinks' ).replaceWith( $categories );
+       } );
 };
 
 /**
@@ -1126,8 +1176,7 @@
  * Page modifications for switching to edit mode.
  */
 ve.init.mw.DesktopArticleTarget.prototype.transformPage = function () {
-       var target = this,
-               $content;
+       var $content;
 
        this.updateTabs( true );
        this.emit( 'transformPage' );
@@ -1136,6 +1185,7 @@
 
        // Move all native content inside the target
        this.$originalContent.append( this.$element.siblings() );
+       this.$originalCategories = $( '#catlinks' ).clone( true );
 
        // Mark every non-direct ancestor between editableContent and the 
container as uneditable
        $content = this.$editableContent;
@@ -1145,22 +1195,41 @@
                $content = $content.parent();
        }
 
+       this.transformCategoryLinks( $( '.catlinks' ) );
+
+       this.disableUneditableContent();
+
+       this.updateHistoryState();
+};
+
+/**
+ * Category link section transformations for switching to edit mode. Broken out
+ * so it can be re-applied when displaying changes to the categories.
+ *
+ * @param {jQuery} $catlinks Category links container element
+ */
+ve.init.mw.DesktopArticleTarget.prototype.transformCategoryLinks = function ( 
$catlinks ) {
+       var target = this;
        // Un-disable the catlinks wrapper, but not the links
-       $( '.catlinks' )
-               .removeClass( 
've-init-mw-desktopArticleTarget-uneditableContent' )
+       $catlinks.removeClass( 
've-init-mw-desktopArticleTarget-uneditableContent' )
                .on( 'click.ve-target', function () {
                        var windowAction = ve.ui.actionFactory.create( 
'window', target.getSurface() );
                        windowAction.open( 'meta', { page: 'categories' } );
                        return false;
                } )
                .find( 'a' ).addClass( 
've-init-mw-desktopArticleTarget-uneditableContent' );
+};
 
-       $( '.ve-init-mw-desktopArticleTarget-uneditableContent' ).on( 
'click.ve-target', function ( e ) {
+/**
+ * Disabling of non-editable content, in a given context
+ *
+ * @param {jQuery|string} [context] Context to disable in
+ */
+ve.init.mw.DesktopArticleTarget.prototype.disableUneditableContent = function 
( context ) {
+       $( '.ve-init-mw-desktopArticleTarget-uneditableContent', context ).on( 
'click.ve-target', function ( e ) {
                // Support IE9: Prevent default, but don't stop propagation
                e.preventDefault();
        } );
-
-       this.updateHistoryState();
 };
 
 /**
@@ -1221,6 +1290,10 @@
                this.$originalRedirectSub.prependTo( $( '#contentSub' ) );
                this.$originalRedirectMsg = undefined;
                this.$originalRedirectSub = undefined;
+       }
+
+       if ( this.$originalCategories ) {
+               $( '#catlinks' ).replaceWith( this.$originalCategories );
        }
 
        mw.hook( 've.deactivate' ).fire();
@@ -1306,7 +1379,7 @@
        html, categoriesHtml, displayTitle, lastModified, contentSub, isRedirect
 ) {
        var $content = $( $.parseHTML( html ) ),
-               $veSectionLinks;
+               $veSectionLinks, $categories;
 
        if ( lastModified ) {
                // If we were not viewing the most recent revision before (a 
requirement
@@ -1346,7 +1419,9 @@
        if ( displayTitle ) {
                $( '#content #firstHeading' ).html( displayTitle );
        }
-       $( '#catlinks' ).replaceWith( categoriesHtml );
+       $categories = $( $.parseHTML( categoriesHtml ) );
+       mw.hook( 'wikipage.categories' ).fire( $categories );
+       $( '#catlinks' ).replaceWith( $categories );
        $( '#contentSub' ).html( contentSub );
 
        if ( isRedirect ) {

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

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