Santhosh has uploaded a new change for review.
https://gerrit.wikimedia.org/r/192786
Change subject: Publish module refactoring for title collision
......................................................................
Publish module refactoring for title collision
Better module restructuring for publishing error handling and
title validations
Bug: T85138
Change-Id: I95b904d9ab2f7ca882c32e91b2441d7cc5e796ab
---
M modules/publish/ext.cx.publish.dialog.js
M modules/publish/ext.cx.publish.js
2 files changed, 191 insertions(+), 158 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation
refs/changes/86/192786/1
diff --git a/modules/publish/ext.cx.publish.dialog.js
b/modules/publish/ext.cx.publish.dialog.js
index 6860adc..20ff9b7 100644
--- a/modules/publish/ext.cx.publish.dialog.js
+++ b/modules/publish/ext.cx.publish.dialog.js
@@ -21,22 +21,18 @@
this.$dialog = null;
this.$close = null;
this.$message = null;
+ this.$publishButton = null;
+ this.$keepButton = null;
this.init();
}
/**
* Initializes the publishing dialog instance.
- * @param {string} title The title of the existing article
*/
CXPublishingDialog.prototype.init = function () {
var title = $( '.cx-column--translation > h2' ).text();
- if ( this.$dialog ) {
- this.setMessage( title );
- } else {
- this.render( title );
- }
- this.listen();
+ this.render( title );
this.position();
this.show();
};
@@ -46,8 +42,7 @@
* @param {string} title The title of the existing article
*/
CXPublishingDialog.prototype.render = function ( title ) {
- var $buttons, $keepButton, $publishAnywayButton, username,
namespace,
- cxPublishingDialog = this;
+ var $buttons, username, namespace;
username = mw.user.getName();
namespace = mw.config.get(
'wgContentTranslationTargetNamespace' );
@@ -57,49 +52,33 @@
.hide();
this.$close = $( '<div>' )
- .addClass( 'cx-publishing-dialog__close' )
- .on( 'click', function () {
- cxPublishingDialog.$dialog.hide();
- } );
+ .addClass( 'cx-publishing-dialog__close' );
this.$message = $( '<p>' )
.addClass( 'cx-publishing-dialog__message' );
- $( '.cx-publishing-dialog__message > a' ).prop( 'target',
'_blank' );
+ this.$dialog.find( '.cx-publishing-dialog__message > a' ).prop(
'target', '_blank' );
$buttons = $( '<div>' )
.addClass( 'cx-publishing-dialog__buttons' );
- $keepButton = $( '<button>' )
+ this.$keepButton = $( '<button>' )
.addClass( 'cx-publishing-dialog__buttons-keep
mw-ui-button mw-ui-quiet' );
if ( namespace === 'User' ) {
- $keepButton.text( mw.msg(
'cx-publishing-dialog-keep-button' ) );
+ this.$keepButton.text( mw.msg(
'cx-publishing-dialog-keep-button' ) );
} else {
- $keepButton.text( mw.msg(
'cx-publishing-dialog-publish-draft-button' ) );
+ this.$keepButton.text( mw.msg(
'cx-publishing-dialog-publish-draft-button' ) );
}
- $keepButton.on( 'click', function () {
- cxPublishingDialog.$dialog.hide();
- mw.hook( 'mw.cx.publish' ).fire( false );
- } );
-
- $publishAnywayButton = $( '<button>' )
+ this.$publishButton = $( '<button>' )
.addClass( 'cx-publishing-dialog__buttons-publishanyway
mw-ui-button mw-ui-progressive' )
- .text( mw.msg(
'cx-publishing-dialog-publish-anyway-button' ) )
- .on( 'click', function () {
- cxPublishingDialog.$dialog.hide();
- mw.hook( 'mw.cx.publish' ).fire( true );
- } );
+ .text( mw.msg(
'cx-publishing-dialog-publish-anyway-button' ) );
this.setMessage( title );
-
- $buttons.append( $publishAnywayButton, $keepButton );
-
+ $buttons.append( this.$publishButton, this.$keepButton );
this.$dialog.append( this.$close, this.$message, $buttons );
-
$( 'body' ).append( this.$dialog );
-
};
/**
@@ -129,10 +108,7 @@
buttonPosition = this.$trigger.position();
buttonCenter = buttonPosition.left + (
this.$trigger.outerWidth() / 2 );
dialogLeft = buttonCenter - ( this.$dialog.outerWidth() / 2 );
- dialogTop = $( window ).scrollTop() +
- buttonPosition.top +
- this.$trigger.height() + 20;
-
+ dialogTop = $( window ).scrollTop() + buttonPosition.top +
this.$trigger.height() + 20;
this.$dialog.css( {
top: dialogTop,
left: dialogLeft,
@@ -142,11 +118,28 @@
};
/**
- * A listener that adjust the positioning when the page is scrolled
- * Necessary because the publishing button moves to the left on window
scroll
+ * Listen for events
+ * @return {jQuery.Promise}
*/
CXPublishingDialog.prototype.listen = function () {
+ var deferred = $.Deferred(),
+ self = this;
+
$( window ).on( 'scroll', $.proxy( this.position, this ) );
+ this.$keepButton.on( 'click', function () {
+ deferred.resolve( false );
+ self.$dialog.remove();
+ } );
+ this.$publishButton.on( 'click', function () {
+ deferred.resolve( true );
+ self.$dialog.remove();
+ } );
+ this.$close.on( 'click', function () {
+ deferred.reject();
+ self.$dialog.remove();
+ } );
+
+ return deferred.promise();
};
/**
@@ -161,16 +154,8 @@
*/
$.fn.cxPublishingDialog = function () {
return this.each( function () {
- /*jshint validthis:true */
- var $this = $( this ),
- data = $this.data( 'cxPublishingDialog' );
-
- if ( !data ) {
- $this.data( 'cxPublishingDialog', ( data = new
CXPublishingDialog( this ) ) );
- }
-
- data.init();
-
+ var $this = $( this );
+ $this.data( 'cxPublishingDialog', new
CXPublishingDialog( this ) );
} );
};
} )( jQuery, mediaWiki );
diff --git a/modules/publish/ext.cx.publish.js
b/modules/publish/ext.cx.publish.js
index c6a6c75..be4918e 100644
--- a/modules/publish/ext.cx.publish.js
+++ b/modules/publish/ext.cx.publish.js
@@ -16,6 +16,7 @@
*/
function CXPublish( $trigger ) {
this.$trigger = $trigger;
+ this.targetTitle = null;
}
/**
@@ -26,28 +27,49 @@
var apiParams,
self = this;
+ this.targetTitle = $( '.cx-column--translation > h2' ).text();
apiParams = $.extend( {}, params, {
- action: 'cxpublish'
+ action: 'cxpublish',
+ from: mw.cx.sourceLanguage,
+ to: mw.cx.targetLanguage,
+ sourcetitle: mw.cx.sourceTitle,
+ html: self.getContent(),
+ status: 'published',
+ sourcerevision: mw.cx.sourceRevision,
+ categories: this.getCategories(),
+ progress: JSON.stringify( mw.cx.getProgress() )
} );
- return new mw.Api().postWithToken( 'edit', apiParams, {
- // A bigger timeout since publishing after converting
html to wikitext
- // parsoid is not a fast operation.
- timeout: 100 * 1000 // in milliseconds
- } ).then( function ( response ) {
- if ( response.cxpublish.result === 'success' ) {
- return;
- }
+ // Disable the trigger button
+ this.$trigger.prop( 'disabled', true ).text( mw.msg(
'cx-publish-button-publishing' ) );
- if ( response.cxpublish.edit.captcha ) {
- return self.captchaHandler(
response.cxpublish.edit.captcha )
- .then( function ( captchaResult ) {
- return self.publish( $.extend(
params, captchaResult ) );
- } );
- }
+ this.checkTargetTitle( this.targetTitle ).then( function (
title ) {
+ apiParams.title = self.targetTitle = title;
- // If it's a different error, log it
- mw.log( '[CX] Unexpected error while publishing: ',
response.cxpublish );
+ new mw.Api().postWithToken( 'edit', apiParams, {
+ // A bigger timeout since publishing after
converting html to wikitext
+ // parsoid is not a fast operation.
+ timeout: 100 * 1000 // in milliseconds
+ } ).done( function ( response ) {
+ if ( response.cxpublish.result === 'success' ) {
+ self.success();
+ return;
+ }
+
+ if ( response.cxpublish.edit.captcha ) {
+ return self.captchaHandler(
response.cxpublish.edit.captcha )
+ .then( function ( captchaResult
) {
+ return self.publish(
$.extend( params, captchaResult ) );
+ } );
+ }
+
+ // If it's a different error, log it
+ mw.log( '[CX] Unexpected error while
publishing: ', response.cxpublish );
+ } ).fail( function ( code, details ) {
+ self.fail( code, details );
+ } ).always( function () {
+ self.$trigger.prop( 'disabled', true ).text(
mw.msg( 'cx-publish-button' ) );
+ } );
} );
};
@@ -108,8 +130,9 @@
/**
* Checks to see if there is already a published article with the title
* @param {string} title The title to check
+ * @return {jQuery.promise}
*/
- function checkTargetTitle( title ) {
+ function getTitle( title ) {
var api,
$deferred = $.Deferred();
@@ -131,8 +154,59 @@
}
/**
+ * Generate an alternate title in case of title collision
+ * @param {string} title The title
+ * @return {string}
+ */
+ function getAlternateTitle( title ) {
+ var username = mw.user.getName();
+
+ if ( new mw.Title( title ).getNamespaceId() === 2 ) {
+ return increaseVersion( title );
+ } else {
+ return 'User:' + username + '/' + title;
+ }
+ }
+
+ /**
+ * Checks to see if there is already a published article with the title
+ * @param {string} title The title to check
+ * @return {jQuery.promise}
+ */
+ CXPublish.prototype.checkTargetTitle = function ( title ) {
+ var deferred = $.Deferred(),
+ self = this;
+
+ title = mw.cx.SiteMapper.prototype.getTargetTitle( title );
+
+ getTitle( title ).done( function ( titleExists ) {
+ var $dialog;
+
+ if ( titleExists ) {
+ // Show a dialog to decide what to do now
+ self.$trigger.cxPublishingDialog();
+ $dialog = self.$trigger.data(
'cxPublishingDialog' );
+ $dialog.listen().done( function ( overwrite ) {
+ if ( !overwrite ) {
+ title = getAlternateTitle(
title );
+ }
+
+ deferred.resolve( title );
+ } ).fail( function () {
+ deferred.reject();
+ } );
+ } else {
+ deferred.resolve( title );
+ }
+ } );
+
+ return deferred.promise();
+ };
+
+ /**
* Increase the version number of a title starting with 1.
* @param {string} title The title to increase the version on.
+ * @return {string}
*/
function increaseVersion( title ) {
var match, version;
@@ -148,110 +222,79 @@
}
/**
- * Publish the translation
- * @param {boolean} overwrite Flag to overwrite translation
- * @param {string} title [optional], Optional title for the translation
+ * Get categories for the current translation pair
+ * @return {string} Category titles with '|' delimiter
*/
- function publish( overwrite, title ) {
- var $publishArea, $publishButton, publisher,
- translatedContent, targetCategories, targetTitle,
- sortedKeys, i, categoryTitles, categories,
publishedTitle;
+ CXPublish.prototype.getCategories = function () {
+ var i, categories, sortedKeys, categoryTitles, targetCategories;
- $publishArea = $( '.cx-header__publish' );
- $publishButton = $publishArea.find(
'.cx-header__publish-button' );
- targetTitle = title || $( '.cx-column--translation > h2'
).text();
- translatedContent = prepareTranslationForPublish(
+ targetCategories = mw.cx.categoryTool.categories.target;
+ sortedKeys = Object.keys( targetCategories ).sort();
+ categoryTitles = [];
+ for ( i = 0; i < sortedKeys.length; i++ ) {
+ categoryTitles.push( targetCategories[ sortedKeys[ i ]
] );
+ }
+ categories = categoryTitles.join( '|' );
+ return categories;
+ };
+
+ /**
+ * Get the current translation content
+ * @return {string}
+ */
+ CXPublish.prototype.getContent = function () {
+ return this.prepareTranslationForPublish(
$( '.cx-column--translation .cx-column__content'
).clone()
);
+ };
- publishedTitle = mw.cx.SiteMapper.prototype.getTargetTitle(
targetTitle );
+ /**
+ * Success handler for publishing
+ */
+ CXPublish.prototype.success = function () {
+ $( '.cx-column--translation > h2' )
+ .text( this.targetTitle )
+ .keepAlignment();
+ mw.hook( 'mw.cx.success' )
+ .fire( mw.message( 'cx-publish-page-success',
+ $( '<a>' ).attr( {
+ href: mw.util.getUrl( this.targetTitle
),
+ target: '_blank'
+ } ).text( this.targetTitle )[ 0 ].outerHTML
+ ) );
+ mw.hook( 'mw.cx.translation.published' ).fire(
+ mw.cx.sourceLanguage,
+ mw.cx.targetLanguage,
+ this.targetTitle
+ );
+ mw.cx.dirty = false;
+ };
- checkTargetTitle( publishedTitle )
- .done( function ( titleExists ) {
- var username;
-
- username = mw.user.getName();
-
- if ( titleExists === false || overwrite ===
true ) {
- $publishButton
- .prop( 'disabled', true )
- .text( mw.msg(
'cx-publish-button-publishing' ) );
-
- targetCategories =
mw.cx.categoryTool.categories.target;
- sortedKeys = Object.keys(
targetCategories ).sort();
- categoryTitles = [];
- for ( i = 0; i < sortedKeys.length; i++
) {
- categoryTitles.push(
targetCategories[ sortedKeys[ i ] ] );
- }
- categories = categoryTitles.join( '|' );
-
- publisher = new CXPublish( $publishArea
);
- publisher.publish( {
- from: mw.cx.sourceLanguage,
- to: mw.cx.targetLanguage,
- sourcetitle: mw.cx.sourceTitle,
- title: targetTitle,
- html: translatedContent,
- status: 'published',
- sourcerevision:
mw.cx.sourceRevision,
- categories: categories,
- progress: JSON.stringify(
mw.cx.getProgress() )
- } ).done( function () {
- $( '.cx-column--translation >
h2' )
- .text( publishedTitle )
- .keepAlignment();
- mw.hook( 'mw.cx.success' )
- .fire( mw.message(
'cx-publish-page-success',
- $( '<a>'
).attr( {
- href:
mw.util.getUrl( publishedTitle ),
- target:
'_blank'
- } ).text(
publishedTitle )[ 0 ].outerHTML
- ) );
- mw.hook(
'mw.cx.translation.published' ).fire(
- mw.cx.sourceLanguage,
- mw.cx.targetLanguage,
- targetTitle
- );
- mw.cx.dirty = false;
- } ).fail( function ( code, details ) {
- var trace = {
- sourceLanguage:
mw.cx.sourceLanguage,
- targetLanguage:
mw.cx.targetLanguage,
- sourceTitle:
mw.cx.sourceTitle,
- sourceRevision:
mw.cx.sourceRevision,
- targetTitle:
targetTitle,
- error: details
- };
- mw.hook( 'mw.cx.error' ).fire(
mw.msg( 'cx-publish-page-error' ) );
- mw.log( '[CX] Error while
publishing:', code, trace );
- } ).always( function () {
- $publishButton
- .prop( 'disabled', true
)
- .text( mw.msg(
'cx-publish-button' ) );
- } );
- } else if ( overwrite === false ) {
- if ( new mw.Title( publishedTitle
).getNamespaceId() === 2 ) {
- publishedTitle =
increaseVersion( publishedTitle );
- } else {
- publishedTitle = 'User:' +
username + '/' + publishedTitle;
- }
- publish( false, publishedTitle );
- } else {
- $publishButton.cxPublishingDialog();
- }
- } );
- }
+ /**
+ * Failure handler for publishing
+ */
+ CXPublish.prototype.fail = function ( code, details ) {
+ var trace = {
+ sourceLanguage: mw.cx.sourceLanguage,
+ targetLanguage: mw.cx.targetLanguage,
+ sourceTitle: mw.cx.sourceTitle,
+ sourceRevision: mw.cx.sourceRevision,
+ targetTitle: this.targetTitle,
+ error: details
+ };
+ mw.hook( 'mw.cx.error' ).fire( mw.msg( 'cx-publish-page-error'
) );
+ mw.log( '[CX] Error while publishing:', code, trace );
+ };
/**
* Prepare the translated content for publishing by removing
* unwanted parts.
* @return {string} processed html
*/
- function prepareTranslationForPublish( $content ) {
+ CXPublish.prototype.prepareTranslationForPublish = function ( $content
) {
$content.find( '.cx-segment' ).replaceWith( function () {
return $( this ).html();
} );
- // TODO: This clean up should be done even before segmentation
at server.
$content.find( 'link, title' ).remove();
// Remove placeholder sections
@@ -266,12 +309,17 @@
} );
return $content.html();
- }
+ };
// Expose the CXPublish
mw.cx.publish = CXPublish;
$( function () {
- mw.hook( 'mw.cx.publish' ).add( $.proxy( publish, this ) );
+ var cxPublish, $publishButton;
+
+ $publishButton = $( '.cx-header__publish
.cx-header__publish-button' );
+ cxPublish = new mw.cx.publish( $publishButton );
+
+ mw.hook( 'mw.cx.publish' ).add( $.proxy( cxPublish.publish,
cxPublish ) );
} );
}( jQuery, mediaWiki ) );
--
To view, visit https://gerrit.wikimedia.org/r/192786
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I95b904d9ab2f7ca882c32e91b2441d7cc5e796ab
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Santhosh <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits