Nikerabbit has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/345513 )
Change subject: Some refactoring in the initialization code
......................................................................
Some refactoring in the initialization code
I was debugging a JS error that was happening on draft restoration.
I found the initialization code a bit hard to follow, so I refactored
it into clear chain.
This patch also contains some cleanups to constructor parameters,
documentation etc. which make it harder to review.
Change-Id: Ie68d3b46b6cd0eae22282288ab0158bb2f5d8bef
---
M extension.json
M modules/dm/mw.cx.dm.SourcePage.js
M modules/dm/mw.cx.dm.Translation.js
M modules/mw.cx.MwApiRequestManager.js
M modules/mw.cx.Translation.js
M modules/mw.cx.init.Translation.js
M modules/mw.cx.init.js
M modules/tests/dm/mw.cx.dm.LinkTranslationUnit.test.js
M modules/ui/mw.cx.ui.Columns.js
M modules/ui/mw.cx.ui.SourceColumn.js
M modules/ui/mw.cx.ui.TranslationView.js
11 files changed, 333 insertions(+), 267 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation
refs/changes/13/345513/1
diff --git a/extension.json b/extension.json
index 6adc640..d64de02 100644
--- a/extension.json
+++ b/extension.json
@@ -1239,6 +1239,10 @@
"mw.cx.dm"
]
},
+ "mw.cx.dm.WikiPage": {
+ "scripts": "dm/mw.cx.dm.WikiPage.js",
+ "dependencies": "mw.cx.dm"
+ },
"mw.cx.dm.TranslationUnits": {
"dependencies": [
"mw.cx.dm.TranslationUnit",
@@ -1346,8 +1350,9 @@
],
"dependencies": [
"ext.cx.model",
- "mw.cx.ui",
+ "ext.cx.sitemapper",
"mw.cx.MwApiRequestManager",
+ "mw.cx.dm.WikiPage",
"mw.cx.init.Translation"
],
"targets": [
@@ -1357,6 +1362,13 @@
"mw.cx.init.Translation": {
"scripts": [
"mw.cx.init.Translation.js"
+ ],
+ "messages": [
+ "cx-draft-restore-failed",
+ "cx-draft-restored",
+ "cx-draft-restoring",
+ "cx-error-page-not-found",
+ "cx-error-server-connection"
],
"dependencies": [
"mw.cx.dm.Translation",
@@ -1386,14 +1398,10 @@
"cx-save-draft-save-success",
"cx-save-draft-saving",
"cx-save-draft-tooltip",
- "cx-draft-restoring",
- "cx-draft-restored",
- "cx-draft-restore-failed",
"cx-page-old-revision-loaded"
],
"dependencies": [
"easy-deflate.deflate",
- "ext.cx.model",
"mediawiki.api",
"mediawiki.api.edit",
"mediawiki.user",
@@ -1522,8 +1530,6 @@
"ui/styles/mw.cx.ui.Infobar.less"
],
"messages": [
- "cx-error-server-connection",
- "cx-error-page-not-found",
"cx-header-new-translation",
"cx-header-all-translations",
"cx-special-login-error",
diff --git a/modules/dm/mw.cx.dm.SourcePage.js
b/modules/dm/mw.cx.dm.SourcePage.js
index 1e90bed..0cdd9b4 100644
--- a/modules/dm/mw.cx.dm.SourcePage.js
+++ b/modules/dm/mw.cx.dm.SourcePage.js
@@ -3,7 +3,6 @@
/**
* CX Source page
*
- * @abstract
* @mixins OO.EventEmitter
*
* @constructor
@@ -14,9 +13,7 @@
* @cfg {string} sourceLanguage Source language code
* @cfg {string} targetLanguage Target language code
* @cfg {string} [sourceRevision] Source revision id
- * @cfg {string} [campaign] Campaign identifier
* @cfg {Object} requestManager The MediaWiki api request manager instance
- * @cfg {string[]} removableSections Sections that can be removed from source
page
*/
mw.cx.dm.SourcePage = function SourcePage( config ) {
// Mixin constructor
diff --git a/modules/dm/mw.cx.dm.Translation.js
b/modules/dm/mw.cx.dm.Translation.js
index 723d71b..9893a15 100644
--- a/modules/dm/mw.cx.dm.Translation.js
+++ b/modules/dm/mw.cx.dm.Translation.js
@@ -57,7 +57,8 @@
model,
this.config,
this,
- translatableSections[ i ] );
+ translatableSections[ i ]
+ );
}
};
diff --git a/modules/mw.cx.MwApiRequestManager.js
b/modules/mw.cx.MwApiRequestManager.js
index 5a8a3d0..4939be5 100644
--- a/modules/mw.cx.MwApiRequestManager.js
+++ b/modules/mw.cx.MwApiRequestManager.js
@@ -16,12 +16,14 @@
/**
* @class
- * @param {Object} config Configuration
+ * @param {string} sourceLanguage Language code
+ * @param {string} targetLanguage Language code
+ * @param {mw.cx.SiteMapper} siteMapper
*/
-mw.cx.MwApiRequestManager = function MwApiRequestManager( config ) {
- this.sourceLanguage = config.sourceLanguage;
- this.targetLanguage = config.targetLanguage;
- this.siteMapper = config.siteMapper;
+mw.cx.MwApiRequestManager = function MwApiRequestManager( sourceLanguage,
targetLanguage, siteMapper ) {
+ this.sourceLanguage = sourceLanguage;
+ this.targetLanguage = targetLanguage;
+ this.siteMapper = siteMapper;
this.linkCache = {};
this.imageCache = {};
this.titlePairCache = {};
diff --git a/modules/mw.cx.Translation.js b/modules/mw.cx.Translation.js
index c9ccab5..7af20cb 100644
--- a/modules/mw.cx.Translation.js
+++ b/modules/mw.cx.Translation.js
@@ -228,30 +228,6 @@
return records;
};
-mw.cx.Translation.prototype.getSavedTranslation = function () {
- return this.find().then( function( translation ) {
- if ( !translation ) {
- return $.Deferred().reject( false ).resolve();
- }
-
- // Do not allow two users to start a draft at the same time.
The API only
- // returns a translation with different translatorName if this
is the case.
- if ( translation.translatorName !== mw.user.getName() ) {
- this.view.showConflictWarning( translation );
- return $.Deferred().reject( false ).resolve();
- }
-
- if ( translation.status === 'deleted' ) {
- // Deleted translation
- return $.Deferred().reject( false ).resolve();
- }
- // Fetch the translation content
- return this.fetch( translation.id ).then( function(
fetchedTranslation ) {
- return fetchedTranslation;
- } );
- }.bind( this ) );
-};
-
/**
* Restore the translation from database to translation view to continue.
* @param {Object} savedTranslation
@@ -259,7 +235,6 @@
mw.cx.Translation.prototype.restore = function ( savedTranslation ) {
var i, translationUnits, sectionId, savedTranslationUnits,
savedTranslationUnit, translationContent;
- this.emit( 'restorestart' );
translationUnits = this.translation.getTranslationUnits();
savedTranslationUnits = savedTranslation.translationUnits;
for ( i = 0; i < translationUnits.length; i++ ) {
@@ -276,73 +251,4 @@
translationUnits[ i ].setTargetDocument(
translationContent.content );
}
// TODO: Find out orphan translation units and handle them.
- this.view.setStatusMessage( mw.msg( 'cx-draft-restored' ) );
-};
-
-/**
- * Fetch the translation from database to translation view to continue.
- * @param {string} translationId Translation id
- * @return {jQuery.Promise}
- */
-mw.cx.Translation.prototype.fetch = function ( translationId ) {
- var api = new mw.Api();
-
- this.emit( 'fetchstart' );
- this.view.setStatusMessage( mw.msg( 'cx-draft-restoring' ) );
- return api.get( {
- action: 'query',
- list: 'contenttranslation',
- translationid: translationId
- } ).then(
- // Success handler
- this.onFetchSuccess.bind( this ),
- // Failure handler
- this.onFetchFail.bind( this )
- );
-};
-
-mw.cx.Translation.prototype.onFetchSuccess = function ( response ) {
- var fetchedTranslation;
- fetchedTranslation = response.query.contenttranslation.translation;
- this.emit( 'fetchsuccess' );
- return fetchedTranslation;
-};
-
-mw.cx.Translation.prototype.onFetchFail = function ( errorCode, details ) {
- if ( details.exception instanceof Error ) {
- details.exception = details.exception.toString();
- }
- details.errorCode = errorCode;
- this.emit( 'fetcherror', this.translation, details );
- this.view.setStatusMessage( mw.msg( 'cx-draft-restore-failed' ) );
-};
-
-/**
- * Find if there is a draft existing for the current title and language pair.
- *
- * @return {jQuery.Promise}
- */
-mw.cx.Translation.prototype.find = function () {
- var api = new mw.Api();
-
- return api.get( {
- action: 'query',
- list: 'contenttranslation',
- sourcetitle: this.sourceTitle,
- from: this.sourceLanguage,
- to: this.targetLanguage
- } ).then( function ( response ) {
- return response.query &&
response.query.contenttranslation.translation;
- } );
-};
-
-mw.cx.Translation.prototype.showOldRevisionWarning = function () {
- var diffUrl;
-
- diffUrl = this.siteMapper.getPageUrl( this.sourceLanguage,
this.sourceTitle, {
- type: 'revision',
- diff: 'cur',
- oldid: this.translation.sourceRevisionId
- } );
- this.view.showMessage( 'warning', mw.message(
'cx-page-old-revision-loaded', diffUrl ) );
};
diff --git a/modules/mw.cx.init.Translation.js
b/modules/mw.cx.init.Translation.js
index a5e404a..4d7bb71 100644
--- a/modules/mw.cx.init.Translation.js
+++ b/modules/mw.cx.init.Translation.js
@@ -1,155 +1,308 @@
mw.cx.init = {};
/**
- * Translation Initialization
- * @param {object} config Translation configuration
+ * This class loads translation documents (source and target) and sets up the
main views and models.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {mw.cx.dm.WikiPage} sourceWikiPage
+ * @param {mw.cx.dm.WikiPage} targetWikiPage
+ * @param {Object} services Standard services
*/
-mw.cx.init.Translation = function MWCXInitTranslation( config ) {
- this.config = config;
- this.siteMapper = config.siteMapper;
- this.sourceTitle = config.sourceTitle;
- this.targetTitle = config.targetTitle;
- this.sourceLanguage = config.sourceLanguage;
- this.targetLanguage = config.targetLanguage;
- this.sourceRevision = config.sourceRevision;
+mw.cx.init.Translation = function MwCXInitTranslation( sourceWikiPage,
targetWikiPage, services ) {
+ this.sourceWikiPage = sourceWikiPage;
+ this.targetWikiPage = targetWikiPage;
+ this.services = services;
+
+ // BC with other code
+ this.config = services;
+ this.config.sourceTitle = sourceWikiPage.getTitle();
+ this.config.sourceLanguage = sourceWikiPage.getLanguage();
+ this.config.sourceRevision = sourceWikiPage.getRevision();
+ this.config.targetTitle = targetWikiPage.getTitle();
+ this.config.targetLanguage = targetWikiPage.getLanguage();
+
+ // @var {mw.cx.ui.TranslationView}
this.translationView = null;
+ // @var {mw.cx.dm.Translation}
this.translationModel = null;
+ // @var {mw.cx.Translation}
this.translation = null;
+ // @var {mw.cx.dm.SourcePage}
+ this.sourcePage = null;
+ // @var {mw.cx.dm.TargetPage}
+ this.targetPage = null;
};
/**
- * Initialize translation feature
- * @return {jQuery.Promise}
+ * Load all data necessary to start a translation.
*/
mw.cx.init.Translation.prototype.init = function () {
this.translationView = new mw.cx.ui.TranslationView( this.config );
// Paint the initial UI.
this.attachToDOM( this.translationView );
- return this.fetchCXConfiguration( this.sourceLanguage,
this.targetLanguage ).then( function( response ) {
- $.extend( this.config, response.configuration );
- return this.initTranslation();
- }.bind( this ) );
-};
-
-/**
- * Initialize the data models, fetch source page and present it to user.
- * @return {jQuery.Promise}
- */
-mw.cx.init.Translation.prototype.initTranslation = function () {
- this.sourcePage = new mw.cx.dm.SourcePage( this.config );
- this.targetPage = new mw.cx.dm.TargetPage( this.config );
- this.translationModel = new mw.cx.dm.Translation( this.config );
- this.translationModel.setSourcePage( this.sourcePage );
- this.translationModel.setTargetPage( this.targetPage );
-
- this.translation = new mw.cx.Translation( this.translationModel,
this.translationView, this.config );
- // Fetch the source page from cxserver. The content is segmented.
- return this.fetchSourcePageContent(
- this.sourceTitle, this.sourceLanguage, this.sourceRevision
- ).then( function( segmentedSourcePage ) {
- this.loadTranslation( segmentedSourcePage );
- return this.fetchAndAdaptCategories();
- }.bind( this ) );
-};
-
-/**
- * Load the translation from the fetched source page and present to translator
- * @param {object} segmentedSourcePage
- */
-mw.cx.init.Translation.prototype.loadTranslation = function (
segmentedSourcePage ) {
- this.sourcePage.setSections( $.parseHTML(
segmentedSourcePage.segmentedContent ) );
- this.sourcePage.setSourceRevision( segmentedSourcePage.revision );
- this.config.sourceRevision = segmentedSourcePage.revision;
- this.translationModel.setSourceRevisionId(
this.sourcePage.getSourceRevision() );
- this.translationModel.prepareTranslationUnits();
-
- // Get the saved translation and set the properties in translation model
- this.translation.getSavedTranslation().then( function( savedTranslation
) {
- this.translationModel.setTargetURL( savedTranslation.targetURL
);
- this.translationModel.setStatus( savedTranslation.status );
- this.translationModel.setTargetRevisionId(
savedTranslation.targetRevisionId );
- this.translationModel.setProgress( JSON.parse(
savedTranslation.progress ) );
- this.translationModel.setId( savedTranslation.id );
- this.translationModel.setTargetTitle(
savedTranslation.targetTitle );
- // Restore each translation storage units against the source
sections.
- this.translation.restore( savedTranslation );
- }.bind( this ) ).always( function() {
- this.translationView.setTranslation( this.translationModel );
- this.translationView.loadTranslation();
- }.bind( this ) );
-};
-
-/**
- * Fetch and adapt the categories for target language
- * @return {jQuery.Promise}
- */
-mw.cx.init.Translation.prototype.fetchAndAdaptCategories = function () {
- return this.sourcePage.getCategories().then( function( sourceCategories
) {
- return this.targetPage.adaptCategoriesFrom(
this.sourceLanguage, sourceCategories )
- .then( function() {
- this.translationView.showCategories();
+ // Deferred.done is used to stop errors from bubbling to other error
handlers.
+ // Can be rewritten when we have proper promises.
+ this.fetchConfiguration(
+ this.sourceWikiPage.getLanguage(),
+ this.targetWikiPage.getLanguage()
+ ).then(
+ this.fetchConfigurationSuccess.bind( this ),
+ this.fetchConfigurationError.bind( this )
+ ).done( function () {
+ this.fetchSourcePageContent( this.sourceWikiPage,
this.services.siteMapper ).then(
+ this.fetchSourcePageContentSuccess.bind( this ),
+ this.fetchSourcePageContentError.bind( this )
+ ).done( function () {
+ this.fetchDraftInformation(
+ this.sourceWikiPage,
+ this.targetWikiPage
+ ).then(
+ this.fetchDraftInformationSuccess.bind( this ),
+ this.fetchDraftInformationError.bind( this )
+ ).done( function ( draftId ) {
+ this.fetchDraft( draftId ).then(
+ this.fetchDraftSuccess.bind( this ),
+ this.fetchDraftError.bind( this )
+ ).done( this.enableTranslation.bind( this ) );
}.bind( this ) );
+ }.bind( this ) );
}.bind( this ) );
};
/**
- * Attach the translation view to DOM
- * @param {mw.cx.ui.TranslationView} cxview
- */
-mw.cx.init.Translation.prototype.attachToDOM = function ( cxview ) {
- $( 'body' ).append( cxview.$element );
-};
-
-/**
- * Fetch the page with given title and language.
- * Response contains
+ * Attach the translation view to DOM.
*
- * @param {string} title Title of the page to be fetched
- * @param {string} language Language of the page requested. This will be used
to
- * identify the host wiki.
- * @param {string} revision Source page revision id.
- * @return {jQuery.Promise}
+ * @private
+ * @param {mw.cx.ui.TranslationView} view
*/
-mw.cx.init.Translation.prototype.fetchSourcePageContent = function ( title,
language, revision ) {
- var fetchParams, apiURL, fetchPageUrl;
-
- fetchParams = {
- $language: this.siteMapper.getWikiDomainCode( language ),
- // Manual normalisation to avoid redirects on spaces but not to
break namespaces
- $title: title.replace( / /g, '_' )
- };
- apiURL = '/page/$language/$title';
-
- // If revision is requested, load that revision of page.
- if ( revision ) {
- fetchParams.$revision = revision;
- apiURL += '/$revision';
- }
-
- fetchPageUrl = this.config.siteMapper.getCXServerUrl( apiURL,
fetchParams );
-
- return $.get( fetchPageUrl ).fail( function ( xhr ) {
- if ( xhr.status === 404 ) {
- mw.hook( 'mw.cx.error' ).fire(
- mw.msg( 'cx-error-page-not-found', title,
$.uls.data.getAutonym( language ) )
- );
- } else {
- mw.hook( 'mw.cx.error' ).fire( mw.msg(
'cx-error-server-connection' ) );
- }
- } );
+mw.cx.init.Translation.prototype.attachToDOM = function ( view ) {
+ $( 'body' ).append( view.$element );
};
/**
- * Fetch CX Language pair configuration
+ * Fetch language pair configuration from ContentTranslation extension API.
+ *
+ * @private
* @param {string} sourceLanguage Source language
* @param {string} targetLanguage Target language
- * @return {jQuery.Promise}
+ * @return {jQuery.Promise} Configuration settings as returned by the API.
*/
-mw.cx.init.Translation.prototype.fetchCXConfiguration = function (
sourceLanguage, targetLanguage ) {
+mw.cx.init.Translation.prototype.fetchConfiguration = function (
sourceLanguage, targetLanguage ) {
return new mw.Api().get( {
action: 'cxconfiguration',
from: sourceLanguage,
to: targetLanguage
} );
};
+
+mw.cx.init.Translation.prototype.fetchConfigurationSuccess = function (
response ) {
+ $.extend( this.config, response.configuration );
+};
+
+mw.cx.init.Translation.prototype.fetchConfigurationError = function () {
+ // XXX
+ mw.hook( 'mw.cx.error' ).fire( 'Unable to fetch configuration for this
language pair.' );
+};
+
+/**
+ * Fetch the source page content from cxserver.
+ *
+ * @private
+ * @param {mw.cx.dm.WikiPage} wikiPage
+ * @param {ext.cx.SiteMapper} siteMapper
+ * @return {jQuery.Promise}
+ */
+mw.cx.init.Translation.prototype.fetchSourcePageContent = function ( wikiPage,
siteMapper ) {
+ var fetchParams, apiURL, fetchPageUrl;
+
+ fetchParams = {
+ $language: siteMapper.getWikiDomainCode( wikiPage.getLanguage()
),
+ // Manual normalisation to avoid redirects on spaces but not to
break namespaces
+ $title: wikiPage.getTitle().replace( / /g, '_' )
+ };
+
+ apiURL = '/page/$language/$title';
+
+ // If revision is requested, load that revision of page.
+ if ( wikiPage.getRevision() ) {
+ fetchParams.$revision = wikiPage.getRevision();
+ apiURL += '/$revision';
+ }
+
+ fetchPageUrl = siteMapper.getCXServerUrl( apiURL, fetchParams );
+
+ return $.get( fetchPageUrl );
+};
+
+mw.cx.init.Translation.prototype.fetchSourcePageContentSuccess = function (
content ) {
+ // Update with revision information
+ this.sourceWikiPage = new mw.cx.dm.WikiPage(
+ this.sourceWikiPage.getTitle(),
+ this.sourceWikiPage.getLanguage(),
+ content.revision
+ );
+ // BC
+ this.config.sourceRevision = content.revision;
+
+ this.sourcePage = new mw.cx.dm.SourcePage( this.config );
+ this.sourcePage.setSections( $.parseHTML( content.segmentedContent ) );
+
+ this.targetPage = new mw.cx.dm.TargetPage( this.config );
+
+ this.translationModel = new mw.cx.dm.Translation( this.config );
+ this.translationModel.setSourcePage( this.sourcePage );
+ this.translationModel.setTargetPage( this.targetPage );
+ this.translationModel.setSourceRevisionId(
this.sourcePage.getSourceRevision() );
+ this.translationModel.prepareTranslationUnits();
+
+ this.translation = new mw.cx.Translation( this.translationModel,
this.translationView, this.config );
+};
+
+mw.cx.init.Translation.prototype.fetchSourcePageContentError = function ( xhr
) {
+ if ( xhr.status === 404 ) {
+ mw.hook( 'mw.cx.error' ).fire(
+ mw.msg(
+ 'cx-error-page-not-found',
+ this.sourceWikiPage.getTitle(),
+ $.uls.data.getAutonym(
this.sourceWikiPage.getLanguage() )
+ )
+ );
+ } else {
+ mw.hook( 'mw.cx.error' ).fire( mw.msg(
'cx-error-server-connection' ) );
+ }
+};
+
+/**
+ * Find if there is a draft existing for the current title and language pair.
+ *
+ * @private
+ * @param {mw.cx.dm.WikiPage} sourceWikiPage
+ * @param {mw.cx.dm.WikiPage} targetWikiPage
+ * @return {jQuery.Promise} Information about an existing draft (if any) as
returned by the API.
+ */
+mw.cx.init.Translation.prototype.fetchDraftInformation = function (
sourceWikiPage, targetWikiPage ) {
+ return new mw.Api().get( {
+ action: 'query',
+ list: 'contenttranslation',
+ sourcetitle: sourceWikiPage.getTitle(),
+ from: sourceWikiPage.getLanguage(),
+ to: targetWikiPage.getLanguage()
+ } ).then( function ( response ) {
+ return response.query &&
response.query.contenttranslation.translation;
+ } );
+};
+
+/**
+ * Check whether an existing draft can be used.
+ *
+ * @private
+ * @param {Object} draft
+ * @return {jQuery.Promise} Draft id or null.
+ */
+mw.cx.init.Translation.prototype.fetchDraftInformationSuccess = function (
draft ) {
+ if ( !draft ) {
+ // No draft exists
+ return $.Deferred().resolve( null ).promise();
+ }
+
+ // Do not allow two users to start a draft at the same time. The API
only
+ // returns a translation with different translatorName if this is the
case.
+ if ( draft.translatorName !== mw.user.getName() ) {
+ this.translationView.showConflictWarning( draft );
+ // Stop further processing!
+ return $.Deferred().reject().promise();
+ }
+
+ // Don't restore deleted drafts
+ if ( draft.status !== 'deleted' ) {
+ return $.Deferred().resolve( draft.id ).promise();
+ }
+
+ return $.Deferred().resolve( null ).promise();
+};
+
+mw.cx.init.Translation.prototype.fetchDraftInformationError = function () {
+ // XXX
+ mw.hook( 'mw.cx.error' ).fire( 'Unable to fetch draft information.' );
+ mw.log( '[CX]', arguments );
+};
+
+/**
+ * Fetch the translation from database (if any exists)
+ *
+ * @private
+ * @param {string|null} draftId Id for saved draft
+ * @return {jQuery.Promise}
+ */
+mw.cx.init.Translation.prototype.fetchDraft = function ( draftId ) {
+ // In case there is no draft, skip loading it
+ if ( draftId === null ) {
+ return $.Deferred().resolve().promise();
+ }
+
+ this.translationView.setStatusMessage( mw.msg( 'cx-draft-restoring' ) );
+
+ return new mw.Api().get( {
+ action: 'query',
+ list: 'contenttranslation',
+ translationid: draftId
+ } ).then( function ( response ) {
+ return response.query.contenttranslation.translation;
+ } );
+};
+
+mw.cx.init.Translation.prototype.fetchDraftSuccess = function ( draft ) {
+ // In case there is no draft (see fetchDraft), there is nothing for us
to do
+ if ( !draft ) {
+ return;
+ }
+
+ this.translationModel.setTargetURL( draft.targetURL );
+ this.translationModel.setStatus( draft.status );
+ this.translationModel.setTargetRevisionId( draft.targetRevisionId );
+ this.translationModel.setProgress( JSON.parse( draft.progress ) );
+ this.translationModel.setId( draft.id );
+ this.translationModel.setTargetTitle( draft.targetTitle );
+
+ // Restore each translation storage units against the source sections.
+ this.translation.restore( draft );
+ this.translationView.setStatusMessage( mw.msg( 'cx-draft-restored' ) );
+};
+
+mw.cx.init.Translation.prototype.fetchDraftError = function ( errorCode,
details ) {
+ if ( details.exception instanceof Error ) {
+ details.exception = details.exception.toString();
+ }
+ details.errorCode = errorCode;
+ this.translationView.setStatusMessage( mw.msg(
'cx-draft-restore-failed' ) );
+
+};
+
+/**
+ * Enables translation and starts post-load processes.
+ *
+ * @private
+ */
+mw.cx.init.Translation.prototype.enableTranslation = function () {
+ this.translationView.setTranslation( this.translationModel );
+ this.translationView.loadTranslation();
+ this.fetchAndAdaptCategories();
+};
+
+/**
+ * Fetch and adapt the categories.
+ * @return {jQuery.Promise}
+ */
+mw.cx.init.Translation.prototype.fetchAndAdaptCategories = function () {
+ return this.sourcePage.getCategories().then( function( sourceCategories
) {
+ return this.targetPage.adaptCategoriesFrom(
+ this.sourceWikiPage.getLanguage(),
+ sourceCategories
+ ).then( function() {
+ this.translationView.showCategories();
+ }.bind( this ) );
+ }.bind( this ) );
+};
diff --git a/modules/mw.cx.init.js b/modules/mw.cx.init.js
index 7be8a71..86e3338 100644
--- a/modules/mw.cx.init.js
+++ b/modules/mw.cx.init.js
@@ -6,40 +6,42 @@
'use strict';
function initCX() {
- var translation, query, requestManager, config;
+ var query, services = {}, sourceWikiPage, targetWikiPage,
translation;
+
+ query = new mw.Uri().query;
+ if (
+ !query.page || !query.from || !query.to ||
+ ( mw.Title.newFromText( query.page ) === null )
+ ) {
+ location.href = mw.util.getUrl(
'Special:ContentTranslation' );
+ return;
+ }
// Set the global siteMapper for code which we cannot inject it
+ // All these configuration in mw.cx is just for supporting
legacy code.
+ // New code should get them from config injected to classes.
mw.cx.siteMapper = new mw.cx.SiteMapper( mw.config.get(
'wgContentTranslationSiteTemplates' ) );
- query = new mw.Uri().query;
mw.cx.sourceTitle = query.page;
mw.cx.targetLanguage = query.to;
mw.cx.sourceLanguage = query.from;
mw.cx.sourceRevision = query.revision;
mw.cx.targetTitle = query.targettitle || query.page;
- // All these configuration in mw.cx is just for supporting
legacy code.
- // New code should get them from config injected to classes.
- // Make them available in config.
- config = {
- siteMapper: mw.cx.siteMapper,
- sourceTitle: mw.cx.sourceTitle,
- targetTitle: mw.cx.targetTitle,
- targetLanguage: mw.cx.targetLanguage,
- sourceLanguage: mw.cx.sourceLanguage,
- sourceRevision: mw.cx.sourceRevision,
- campaign: query.campaign
+ // Global services that every class can expect to have
+ services = {
+ siteMapper: mw.cx.siteMapper
};
- requestManager = new mw.cx.MwApiRequestManager( config );
- requestManager.init();
- config.requestManager = requestManager;
- if ( !config.sourceTitle || !config.sourceLanguage ||
!config.targetLanguage ||
- ( mw.Title.newFromText( config.sourceTitle ) === null )
- ) {
- location.href = mw.util.getUrl(
'Special:ContentTranslation' );
- } else {
- translation = new mw.cx.init.Translation( config );
- translation.init();
+ services.requestManager = new mw.cx.MwApiRequestManager(
query.from, query.to, services.siteMapper );
+ services.requestManager.init();
+
+ sourceWikiPage = new mw.cx.dm.WikiPage( query.page, query.from,
query.revision );
+ targetWikiPage = new mw.cx.dm.WikiPage( query.targettitle ||
query.page, query.to );
+ translation = new mw.cx.init.Translation( sourceWikiPage,
targetWikiPage, services );
+ translation.init();
+
+ if ( query.campaign ) {
+ mw.hook( 'mw.cx.cta.accept' ).fire( query.campaign,
query.from, query.page, query.to );
}
}
diff --git a/modules/tests/dm/mw.cx.dm.LinkTranslationUnit.test.js
b/modules/tests/dm/mw.cx.dm.LinkTranslationUnit.test.js
index 067c8b6..e944ab8 100644
--- a/modules/tests/dm/mw.cx.dm.LinkTranslationUnit.test.js
+++ b/modules/tests/dm/mw.cx.dm.LinkTranslationUnit.test.js
@@ -1,12 +1,8 @@
QUnit.module( 'mw.cx.dm.LinkTranslationUnit', QUnit.newMwEnvironment( {
setup: function () {
- var sitemapper;
-
- sitemapper = new mw.cx.SiteMapper(
+ this.siteMapper = new mw.cx.SiteMapper(
mw.config.get( 'wgContentTranslationSiteTemplates' )
);
- this.config = {};
- this.config.siteMapper = sitemapper;
}
} ) );
@@ -50,10 +46,12 @@
sourceLinkDoc.title = tests[ i ].title;
sourceLinkDoc.href = tests[ i ].title;
- config = $.extend( {}, this.config, {
+ // BC
+ config = {
sourceLanguage: tests[ i ].sourceLanguage,
- targetLanguage: tests[ i ].targetLanguage
- } );
+ targetLanguage: tests[ i ].targetLanguage,
+ siteMapper: this.siteMapper
+ };
// Set the response in cache so that network requests wont be
initiated.
mockResponse = {};
@@ -63,7 +61,11 @@
missing: false
};
- requestManager = new mw.cx.MwApiRequestManager( config );
+ requestManager = new mw.cx.MwApiRequestManager(
+ tests[ i ].sourceLanguage,
+ tests[ i ].targetLanguage,
+ this.siteMapper
+ );
requestManager.init();
requestManager.titlePairCache[ tests[ i ].sourceLanguage ].set(
mockResponse );
config.requestManager = requestManager;
diff --git a/modules/ui/mw.cx.ui.Columns.js b/modules/ui/mw.cx.ui.Columns.js
index b453faa..506fe12 100644
--- a/modules/ui/mw.cx.ui.Columns.js
+++ b/modules/ui/mw.cx.ui.Columns.js
@@ -6,7 +6,7 @@
* @param {mw.cx.dm.Translation} translation
* @param {Object} config
*/
-mw.cx.ui.Columns = function ( translation, config ) {
+mw.cx.ui.Columns = function MwCxUiColumns( translation, config ) {
// Configuration initialization
this.config = config || {};
this.sourceColumn = new mw.cx.ui.SourceColumn( translation, this.config
);
diff --git a/modules/ui/mw.cx.ui.SourceColumn.js
b/modules/ui/mw.cx.ui.SourceColumn.js
index 494a42b..b2f6fa8 100644
--- a/modules/ui/mw.cx.ui.SourceColumn.js
+++ b/modules/ui/mw.cx.ui.SourceColumn.js
@@ -32,6 +32,7 @@
this.render();
// Try to load Cite styles. Silently ignored if not installed.
mw.loader.load( 'ext.cite.style' );
+ mw.hook( 'mw.cx.error' ).add( $.proxy( this.removeLoadingIndicator,
this ) );
};
mw.cx.ui.SourceColumn.prototype.render = function () {
diff --git a/modules/ui/mw.cx.ui.TranslationView.js
b/modules/ui/mw.cx.ui.TranslationView.js
index 6047a45..051e4f6 100644
--- a/modules/ui/mw.cx.ui.TranslationView.js
+++ b/modules/ui/mw.cx.ui.TranslationView.js
@@ -32,12 +32,8 @@
mw.cx.ui.TranslationView.prototype.init = function () {
if ( mw.user.isAnon() ) {
mw.hook( 'mw.cx.error.anonuser' ).fire();
- return;
}
- if ( this.config.campaign ) {
- mw.hook( 'mw.cx.cta.accept' ).fire( this.config.campaign,
this.config.sourceLanguage, this.config.targetLanguage );
- }
this.render();
};
--
To view, visit https://gerrit.wikimedia.org/r/345513
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie68d3b46b6cd0eae22282288ab0158bb2f5d8bef
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Nikerabbit <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits