Santhosh has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/333894 )

Change subject: WIP: Category adaptation and display
......................................................................

WIP: Category adaptation and display

TODO: Listing of categories at end of columns.

Bug: T152586
Change-Id: Icfc26460a2cb83301c5788614b5cc0e44a5e5ea0
---
M extension.json
A modules/cache/mw.cx.CategoryCache.js
M modules/dm/mw.cx.dm.SourcePage.js
M modules/dm/mw.cx.dm.TargetPage.js
M modules/dm/mw.cx.dm.Translation.js
M modules/mw.cx.MwApiRequestManager.js
A modules/ui/mw.cx.ui.Categories.js
M modules/ui/mw.cx.ui.Columns.js
M modules/ui/mw.cx.ui.SourceColumn.js
M modules/ui/mw.cx.ui.ToolsColumn.js
M modules/ui/mw.cx.ui.TranslationColumn.js
M modules/ui/mw.cx.ui.TranslationView.js
12 files changed, 259 insertions(+), 65 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation 
refs/changes/94/333894/1

diff --git a/extension.json b/extension.json
index c61ee27..6b86ced 100644
--- a/extension.json
+++ b/extension.json
@@ -1293,6 +1293,7 @@
                "mw.cx.cache": {
                        "scripts": [
                                "cache/mw.cx.ApiResponseCache.js",
+                               "cache/mw.cx.CategoryCache.js",
                                "cache/mw.cx.LinkCache.js",
                                "cache/mw.cx.ImageInfoCache.js",
                                "cache/mw.cx.TitlePairCache.js"
@@ -1445,7 +1446,8 @@
                        ],
                        "dependencies": [
                                "mw.cx.ui",
-                               "ext.cx.widgets.spinner"
+                               "ext.cx.widgets.spinner",
+                               "mw.cx.ui.Categories"
                        ]
                },
                "mw.cx.ui.SourceColumn.legacy": {
@@ -1520,6 +1522,17 @@
                                "mw.cx.tools.SearchTool"
                        ]
                },
+               "mw.cx.ui.Categories": {
+                       "scripts": [
+                               "ui/mw.cx.ui.Categories.js"
+                       ],
+                       "dependencies": [
+                               "mw.cx.ui"
+                       ],
+                       "messages": [
+                               "cx-tools-categories-count-message"
+                       ]
+               },
                "mw.cx.ui.TranslationUnit": {
                        "scripts": [
                                
"ui/translationunits/mw.cx.ui.TranslationUnit.js",
diff --git a/modules/cache/mw.cx.CategoryCache.js 
b/modules/cache/mw.cx.CategoryCache.js
new file mode 100644
index 0000000..50f18e1
--- /dev/null
+++ b/modules/cache/mw.cx.CategoryCache.js
@@ -0,0 +1,51 @@
+/**
+ * ContentTranslation Category request cache
+ *
+ */
+
+'use strict';
+/**
+ * Caches information about title pairs.
+ *
+ * @class
+ * @extends mw.cx.ApiResponseCache
+ * @constructor
+ * @param {Object} config Configuration
+ */
+mw.cx.CategoryCache = function CXCategoryCache( config ) {
+       // Call parent constructor
+       mw.cx.CategoryCache.super.call( this, config );
+       this.language = config.language;
+       this.cacheValues = {};
+};
+
+/* Inheritance */
+
+OO.inheritClass( mw.cx.CategoryCache, mw.cx.ApiResponseCache );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+mw.cx.CategoryCache.static.processPage = function ( page ) {
+       return {
+               categories: $.map( OO.getProp( page, 'categories' ), function( 
item ) {
+                       return item.title;
+               } )
+       };
+};
+
+/**
+ * @inheritdoc
+ */
+mw.cx.CategoryCache.prototype.getRequestPromise = function ( subqueue ) {
+       return this.siteMapper.getApi( this.language ).get( {
+               formatversion: 2,
+               action: 'query',
+               prop: 'categories',
+               clshow: '!hidden',
+               cllimit: 100,
+               titles: subqueue.join( '|' )
+       } );
+};
diff --git a/modules/dm/mw.cx.dm.SourcePage.js 
b/modules/dm/mw.cx.dm.SourcePage.js
index ffbaf7b..ce567d2 100644
--- a/modules/dm/mw.cx.dm.SourcePage.js
+++ b/modules/dm/mw.cx.dm.SourcePage.js
@@ -26,6 +26,7 @@
        this.direction = null;
        this.title = config.sourceTitle;
        this.sourceRevision = config.sourceRevision;
+       this.requestManager = config.requestManager;
        this.sections = [];
        this.categories = [];
 };
@@ -35,15 +36,9 @@
 OO.mixinClass( mw.cx.dm.SourcePage, OO.EventEmitter );
 
 mw.cx.dm.SourcePage.prototype.init = function () {
-       var self = this;
-
        this.direction = $.uls.data.getDir( this.language );
 
-       return this.fetchPage( this.title, this.language, this.sourceRevision 
).then( function () {
-               return self.getCategories().then( function ( categories ) {
-                       self.categories = categories;
-               } );
-       } );
+       return this.fetchPage( this.title, this.language, this.sourceRevision );
 };
 
 /**
@@ -154,19 +149,9 @@
  * @return {jQuery.Promise}
  */
 mw.cx.dm.SourcePage.prototype.getCategories = function () {
-       return this.config.siteMapper.getApi( this.language ).get( {
-               action: 'query',
-               prop: 'categories',
-               clshow: '!hidden',
-               cllimit: 100,
-               indexpageids: true,
-               titles: this.title
-       } ).then( function ( response ) {
-               var pageId;
-
-               if ( response.query ) {
-                       pageId = response.query.pageids[ 0 ];
-                       return response.query.pages[ pageId ].categories || [];
-               }
-       } );
+       return this.requestManager.getCategories( this.language, this.title )
+               .then( function ( categoriesResult ) {
+                       this.categories = categoriesResult.categories;
+                       return this.categories;
+               }.bind( this ) );
 };
diff --git a/modules/dm/mw.cx.dm.TargetPage.js 
b/modules/dm/mw.cx.dm.TargetPage.js
index d48d730..f8e7a28 100644
--- a/modules/dm/mw.cx.dm.TargetPage.js
+++ b/modules/dm/mw.cx.dm.TargetPage.js
@@ -13,10 +13,11 @@
        // Mixin constructor
        OO.EventEmitter.call( this );
        this.config = config;
-       this.language = config.sourceLanguage;
+       this.language = config.targetLanguage;
        this.direction = null;
        this.title = config.sourceTitle;
        this.revisionId = config.revision;
+       this.requestManager = config.requestManager;
        this.section = [];
        this.categories = [];
 };
@@ -32,3 +33,55 @@
 };
 
 mw.cx.dm.TargetPage.prototype.publish = function () {};
+
+/**
+ * Get categories for the target article.
+ * @return {string[]} Array of category titles with namespace prefix
+ */
+mw.cx.dm.TargetPage.prototype.getCategories = function () {
+       return this.categories;
+};
+
+/**
+ * Add a category to target article
+ * @param {string} categoryTitle Category title with namespace prefix
+ */
+mw.cx.dm.TargetPage.prototype.addCategory = function ( categoryTitle ) {
+       this.categories.push( categoryTitle );
+};
+
+/**
+ * Remove a category to target article
+ * @param {string} categoryTitle Category title with namespace prefix
+ */
+mw.cx.dm.TargetPage.prototype.removeCategory = function ( categoryTitle ) {
+       var index = this.categories.indexOf( categoryTitle );
+       if ( index > -1 ) {
+               this.categories.splice( index, 1 );
+       }
+};
+
+/**
+ * Adapt and add categories from an array of categories
+ * @param {string} sourceLanguage Source language
+ * @param {string[]} sourceCategories Array of source category titles, with 
namespace prefix
+ * @return {jQuery.Promise}
+ */
+mw.cx.dm.TargetPage.prototype.adaptCategoriesFrom = function ( sourceLanguage, 
sourceCategories ) {
+       var i, category,
+               deferreds = [];
+
+       for ( i = 0; i < sourceCategories.length; i++ ) {
+               category = sourceCategories[ i ];
+               deferreds.push( this.requestManager.getTitlePair( 
sourceLanguage, category )
+                       .then( function ( pairInfo ) {
+                               if ( pairInfo.targetTitle ) {
+                                       this.addCategory( pairInfo.targetTitle 
);
+                               }
+                       }.bind( this ) )
+               );
+       }
+       // Note that requestManager will take care of combining all these 
categories
+       // to a single network request.
+       return $.when.apply( $, deferreds );
+};
diff --git a/modules/dm/mw.cx.dm.Translation.js 
b/modules/dm/mw.cx.dm.Translation.js
index 0267e85..9f199bb 100644
--- a/modules/dm/mw.cx.dm.Translation.js
+++ b/modules/dm/mw.cx.dm.Translation.js
@@ -37,21 +37,26 @@
  * @return {jQuery.Promise}
  */
 mw.cx.dm.Translation.prototype.init = function () {
-       var self = this;
        this.sourcePage = new mw.cx.dm.SourcePage( this.config );
-       return this.sourcePage.init().done( function () {
-               self.onSourcePageReady();
-       } );
+       return this.sourcePage.init().then( function () {
+               return this.onSourcePageReady().then( function() {
+                       this.emit( 'sourcePageReady' );
+               }.bind( this ) );
+       }.bind( this ) );
 };
 
 /**
  * Handler for onSourcePageReady event.
+ * @return {jQuery.Promise}
  */
 mw.cx.dm.Translation.prototype.onSourcePageReady = function () {
        mw.log( '[CX] Translation loaded', this );
        this.setRevisionId( this.sourcePage.revisionId );
        this.prepareTranslationUnits();
        this.targetPage = new mw.cx.dm.TargetPage( this.config );
+       return this.sourcePage.getCategories().then( function( sourceCategories 
) {
+               return this.targetPage.adaptCategoriesFrom( 
this.sourceLanguage, sourceCategories );
+       }.bind( this ) );
 };
 
 /**
diff --git a/modules/mw.cx.MwApiRequestManager.js 
b/modules/mw.cx.MwApiRequestManager.js
index 864a917..3fe41bf 100644
--- a/modules/mw.cx.MwApiRequestManager.js
+++ b/modules/mw.cx.MwApiRequestManager.js
@@ -25,6 +25,7 @@
        this.linkCache = {};
        this.imageCache = {};
        this.titlePairCache = {};
+       this.categoryCache = {};
 };
 
 /**
@@ -56,6 +57,14 @@
        this.titlePairCache[ this.targetLanguage ] = new mw.cx.TitlePairCache( {
                sourceLanguage: this.targetLanguage,
                targetLanguage: this.sourceLanguage,
+               siteMapper: this.siteMapper
+       } );
+       this.categoryCache[ this.sourceLanguage ] = new mw.cx.CategoryCache( {
+               language: this.sourceLanguage,
+               siteMapper: this.siteMapper
+       } );
+       this.categoryCache[ this.targetLanguage ] = new mw.cx.CategoryCache( {
+               language: this.targetLanguage,
                siteMapper: this.siteMapper
        } );
 };
@@ -107,3 +116,17 @@
        }
        return this.titlePairCache[ language ].get( title );
 };
+
+mw.cx.MwApiRequestManager.prototype.getTitlePairs = function ( language, title 
) {
+       if ( !this.titlePairCache[ language ] ) {
+               throw Error( '[CX] TitlePairCache not initialized for ' + 
language );
+       }
+       return this.titlePairCache[ language ].get( title );
+};
+
+mw.cx.MwApiRequestManager.prototype.getCategories = function ( language, title 
) {
+       if ( !this.categoryCache[ language ] ) {
+               throw Error( '[CX] CategoryCache not initialized for ' + 
language );
+       }
+       return this.categoryCache[ language ].get( title );
+};
diff --git a/modules/ui/mw.cx.ui.Categories.js 
b/modules/ui/mw.cx.ui.Categories.js
new file mode 100644
index 0000000..0564c47
--- /dev/null
+++ b/modules/ui/mw.cx.ui.Categories.js
@@ -0,0 +1,34 @@
+'use strict';
+
+/**
+ * @class
+ * @param {Object} [config] Configuration object
+ */
+mw.cx.ui.Categories = function ( config ) {
+       this.categoryCount = null;
+       this.categoryListing = null;
+       this.page = config.page;
+};
+
+mw.cx.ui.Categories.prototype.getCategoryCount = function () {
+       var count;
+
+       count = this.page.categories.length;
+       this.categoryCount = new OO.ui.ButtonWidget( {
+               label: mw.msg( 'cx-tools-categories-count-message', count ),
+               icon: 'tag',
+               framed: false
+       } );
+       return this.categoryCount;
+};
+
+mw.cx.ui.Categories.prototype.getCategoryListing = function () {
+       return this.categoryListing;
+};
+
+mw.cx.ui.Categories.prototype.listen = function () {
+       this.categoryCount.on( 'click', function () {
+               // Scroll to categoryListing
+               this.categoryListing.scrollElementIntoView();
+       } );
+};
diff --git a/modules/ui/mw.cx.ui.Columns.js b/modules/ui/mw.cx.ui.Columns.js
index d164962..ecff3cd 100644
--- a/modules/ui/mw.cx.ui.Columns.js
+++ b/modules/ui/mw.cx.ui.Columns.js
@@ -3,13 +3,14 @@
 /**
  *
  * @class
+ * @param {mw.cx.dm.Translation} translation
  * @param {Object} config
  */
-mw.cx.ui.Columns = function ( config ) {
+mw.cx.ui.Columns = function ( translation, config ) {
        // Configuration initialization
        this.config = config || {};
-       this.sourceColumn = new mw.cx.ui.SourceColumn( this.config );
-       this.translationColumn = new mw.cx.ui.TranslationColumn( this.config );
+       this.sourceColumn = new mw.cx.ui.SourceColumn( translation, this.config 
);
+       this.translationColumn = new mw.cx.ui.TranslationColumn( translation, 
this.config );
        this.ToolsColumn = new mw.cx.ui.ToolsColumn( this.config );
 
        // Parent constructor
diff --git a/modules/ui/mw.cx.ui.SourceColumn.js 
b/modules/ui/mw.cx.ui.SourceColumn.js
index f4c2f25..ba793da 100644
--- a/modules/ui/mw.cx.ui.SourceColumn.js
+++ b/modules/ui/mw.cx.ui.SourceColumn.js
@@ -4,9 +4,10 @@
  * Source article container
  *
  * @class
+ * @param {mw.cx.dm.Translation} translation
  * @param {Object} [config] Configuration object
  */
-mw.cx.ui.SourceColumn = function ( config ) {
+mw.cx.ui.SourceColumn = function ( translation, config ) {
        // Configuration initialization
        this.config = $.extend( {}, config, {
                continuous: true,
@@ -17,9 +18,13 @@
        // Parent constructor
        mw.cx.ui.SourceColumn.parent.call( this, this.config );
        this.siteMapper = config.siteMapper;
+       this.translation = translation;
        this.loading = true;
        this.$loadingIndicator = null;
        this.init();
+       this.translation.connect( this, {
+               sourcePageReady: 'onSourcePageReady'
+       } );
 };
 
 /* Setup */
@@ -33,8 +38,8 @@
 };
 
 mw.cx.ui.SourceColumn.prototype.render = function () {
-       var sourceLanguageDir,
-               $languageLabel, $articleLink, userLanguage, $subHeading;
+       var sourceLanguageDir, $languageLabel, $articleLink,
+               userLanguage, $subHeading, categoryUI;
 
        sourceLanguageDir = $.uls.data.getDir( this.config.sourceLanguage );
        this.$element.prop( {
@@ -76,10 +81,25 @@
                .addClass( 'cx-column__sub-heading' )
                .append( $languageLabel, $articleLink );
 
+
        this.$content = $( '<div>' )
                .addClass( 'cx-column__content' );
-       this.$element.append( this.$title, $subHeading, this.$content );
+
+       this.$element.append(
+               this.$title,
+               $subHeading,
+               this.$content
+       );
        this.showLoadingIndicator();
+};
+
+mw.cx.ui.SourceColumn.prototype.onSourcePageReady = function() {
+       var categoryUI = new mw.cx.ui.Categories( {
+               page: this.translation.sourcePage
+       } );
+       this.loading = false;
+       this.$loadingIndicator.remove();
+       this.$content.before( categoryUI.getCategoryCount().$element );
 };
 
 /**
@@ -87,10 +107,6 @@
  * @param {integer} position
  */
 mw.cx.ui.SourceColumn.prototype.add = function ( $translationUnit, position ) {
-       if ( this.loading ) {
-               this.loading = false;
-               this.$loadingIndicator.remove();
-       }
        this.insertAt( position, $translationUnit );
 };
 
diff --git a/modules/ui/mw.cx.ui.ToolsColumn.js 
b/modules/ui/mw.cx.ui.ToolsColumn.js
index 8e2299b..a71d4b6 100644
--- a/modules/ui/mw.cx.ui.ToolsColumn.js
+++ b/modules/ui/mw.cx.ui.ToolsColumn.js
@@ -36,7 +36,8 @@
 mw.cx.ui.ToolsColumn.prototype.init = function () {
        mw.loader.using( 'mw.cx.tools', function () {
                mw.log( '[CX] Initializing translation tool system' );
-       } );
+               this.showInstructions();
+       }.bind( this ) );
        this.listen();
 };
 
@@ -44,6 +45,18 @@
        $( window ).on( 'scroll resize', this.onWindowScroll.bind( this ) );
 };
 
+
+/**
+ * Show the instructions card when translation is loaded.
+ */
+mw.cx.ui.ToolsColumn.prototype.showInstructions = function () {
+       var instructions = mw.cx.tools.translationToolFactory.create(
+               'instructions', null, this,     this.config
+       );
+
+       this.showTool( instructions );
+};
+
 /**
  * Show the tools associated with the translationUnit.
  *
diff --git a/modules/ui/mw.cx.ui.TranslationColumn.js 
b/modules/ui/mw.cx.ui.TranslationColumn.js
index 88131ef..1af2d24 100644
--- a/modules/ui/mw.cx.ui.TranslationColumn.js
+++ b/modules/ui/mw.cx.ui.TranslationColumn.js
@@ -4,9 +4,10 @@
  * Translation column
  *
  * @class
+ * @param {mw.cx.dm.Translation} translation
  * @param {Object} [config] Configuration object
  */
-mw.cx.ui.TranslationColumn = function ( config ) {
+mw.cx.ui.TranslationColumn = function ( translation, config ) {
        // Configuration initialization
        this.config = $.extend( {}, config, {
                continuous: true,
@@ -17,7 +18,11 @@
        // Parent constructor
        mw.cx.ui.TranslationColumn.parent.call( this, this.config );
        this.siteMapper = config.siteMapper;
+       this.translation = translation;
        this.init();
+       this.translation.connect( this, {
+               sourcePageReady: 'onSourcePageReady'
+       } );
 };
 /* Setup */
 
@@ -90,6 +95,13 @@
        mw.hook( 'mw.cx.translation.ready' ).fire();
 };
 
+mw.cx.ui.TranslationColumn.prototype.onSourcePageReady = function() {
+       var categoryUI = new mw.cx.ui.Categories( {
+               page: this.translation.targetPage
+       } );
+       this.$content.before( categoryUI.getCategoryCount().$element );
+};
+
 /**
  * @param {jQuery} $translationUnit
  * @param {integer} position
diff --git a/modules/ui/mw.cx.ui.TranslationView.js 
b/modules/ui/mw.cx.ui.TranslationView.js
index 5a7d8a3..2e6377f 100644
--- a/modules/ui/mw.cx.ui.TranslationView.js
+++ b/modules/ui/mw.cx.ui.TranslationView.js
@@ -7,13 +7,10 @@
  */
 
 mw.cx.ui.TranslationView = function ( config ) {
-       this.header = new mw.cx.ui.Header( config );
-       this.columns = new mw.cx.ui.Columns( config );
        // Configuration initialization
        this.config = $.extend( {}, config, {
                continuous: true,
                expanded: false,
-               items: [ this.header, this.columns ],
                classes: [ 'cx-widget' ],
                scrollable: false,
                padded: false
@@ -21,9 +18,6 @@
        // Parent constructor
        mw.cx.ui.TranslationView.parent.call( this, this.config );
        this.publishButton = null;
-       this.connect( this, {
-               change: 'onChange'
-       } );
        this.init();
 };
 
@@ -33,8 +27,6 @@
 OO.mixinClass( mw.cx.ui.TranslationUnit, OO.EventEmitter );
 
 mw.cx.ui.TranslationView.prototype.init = function () {
-       var self = this;
-
        if ( mw.user.isAnon() ) {
                mw.hook( 'mw.cx.error.anonuser' ).fire();
                return;
@@ -52,12 +44,19 @@
                mw.hook( 'mw.cx.cta.accept' ).fire( this.config.campaign, 
this.config.sourceLanguage, this.config.targetLanguage );
        }
 
-       this.translation = new mw.cx.dm.Translation( this.config );
-       this.translation.init().then( function () {
-               self.loadTranslation();
-               self.showInstructions();
-       } );
+       this.header = new mw.cx.ui.Header( this.config );
        this.preparePublishButton();
+
+       this.translation = new mw.cx.dm.Translation( this.config );
+       this.columns = new mw.cx.ui.Columns( this.translation, this.config );
+       this.addItems( [ this.header, this.columns ] );
+
+       this.translation.init().then( function () {
+               this.loadTranslation();
+       }.bind( this ) );
+       this.connect( this, {
+               change: 'onChange'
+       } );
 };
 
 /**
@@ -88,17 +87,6 @@
 mw.cx.ui.TranslationView.prototype.preparePublishButton = function () {
        this.setupPublishButton();
        this.attachPublishButton();
-};
-
-/**
- * Show the instructions card when translation is loaded.
- */
-mw.cx.ui.TranslationView.prototype.showInstructions = function () {
-       var instructions = mw.cx.tools.translationToolFactory.create(
-               'instructions', null, this,     this.config
-       );
-
-       this.columns.ToolsColumn.showTool( instructions );
 };
 
 mw.cx.ui.TranslationView.prototype.setupPublishButton = function () {

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icfc26460a2cb83301c5788614b5cc0e44a5e5ea0
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Santhosh <santhosh.thottin...@gmail.com>

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

Reply via email to