mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-24 02:38:40 +00:00
Port MWSaveDialog to use ActionDialog
Relies on Id17d150d Change-Id: I80dd89fa7ad55daa3ae7e9c01c4a78f6e54105ca
This commit is contained in:
parent
c92285e75f
commit
143c21999e
|
@ -522,6 +522,7 @@ $wgResourceModules += array(
|
|||
'visualeditor-dialog-action-goback',
|
||||
'visualeditor-dialog-command-help-title',
|
||||
'visualeditor-dialog-error',
|
||||
'visualeditor-dialog-error-dismiss',
|
||||
'visualeditor-dialog-media-size-originalsize-error',
|
||||
'visualeditor-dimensionswidget-px',
|
||||
'visualeditor-dimensionswidget-times',
|
||||
|
|
|
@ -88,8 +88,6 @@ ve.init.mw.ViewPageTarget = function VeInitMwViewPageTarget() {
|
|||
this.connect( this, {
|
||||
'save': 'onSave',
|
||||
'saveErrorEmpty': 'onSaveErrorEmpty',
|
||||
'saveAsyncBegin': 'onSaveAsyncBegin',
|
||||
'saveAsyncComplete': 'onSaveAsyncComplete',
|
||||
'saveErrorSpamBlacklist': 'onSaveErrorSpamBlacklist',
|
||||
'saveErrorAbuseFilter': 'onSaveErrorAbuseFilter',
|
||||
'saveErrorBadToken': 'onSaveErrorBadToken',
|
||||
|
@ -425,6 +423,7 @@ ve.init.mw.ViewPageTarget.prototype.onSurfaceReady = function () {
|
|||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSave = function ( html, categoriesHtml, newid, isRedirect ) {
|
||||
var newUrlParams, watchChecked;
|
||||
this.saveDeferred.resolve();
|
||||
if ( !this.pageExists || this.restoring ) {
|
||||
// This is a page creation or restoration, refresh the page
|
||||
this.tearDownBeforeUnloadHandler();
|
||||
|
@ -477,34 +476,13 @@ ve.init.mw.ViewPageTarget.prototype.onSave = function ( html, categoriesHtml, ne
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update save dialog when async begins
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveAsyncBegin = function () {
|
||||
this.saveDialog.saveButton.setDisabled( true );
|
||||
this.saveDialog.pushPending();
|
||||
};
|
||||
|
||||
/**
|
||||
* Update save dialog when async completes
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveAsyncComplete = function () {
|
||||
this.saveDialog.saveButton.setDisabled( false );
|
||||
this.saveDialog.popPending();
|
||||
};
|
||||
|
||||
/**
|
||||
* Update save dialog message on general error
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveErrorEmpty = function () {
|
||||
this.showSaveError( ve.msg( 'visualeditor-saveerror', 'Empty server response' ) );
|
||||
this.saveDialog.saveButton.setDisabled( true );
|
||||
this.showSaveError( ve.msg( 'visualeditor-saveerror', 'Empty server response' ), false /* prevents reapply */ );
|
||||
this.events.trackSaveError( 'empty' );
|
||||
};
|
||||
|
||||
|
@ -517,9 +495,9 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorEmpty = function () {
|
|||
ve.init.mw.ViewPageTarget.prototype.onSaveErrorSpamBlacklist = function ( editApi ) {
|
||||
this.showSaveError(
|
||||
// TODO: Use mediawiki.language equivalant of Language.php::listToText once it exists
|
||||
ve.msg( 'spamprotectiontext' ) + ' ' + ve.msg( 'spamprotectionmatch', editApi.spamblacklist.split( '|' ).join( ', ' ) )
|
||||
ve.msg( 'spamprotectiontext' ) + ' ' + ve.msg( 'spamprotectionmatch', editApi.spamblacklist.split( '|' ).join( ', ' ) ),
|
||||
false // prevents reapply
|
||||
);
|
||||
this.saveDialog.saveButton.setDisabled( true );
|
||||
this.events.trackSaveError( 'spamblacklist' );
|
||||
};
|
||||
|
||||
|
@ -530,7 +508,7 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorSpamBlacklist = function ( editAp
|
|||
* @param {Object} editApi
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveErrorAbuseFilter = function ( editApi ) {
|
||||
this.showSaveError( $.parseHTML( editApi.warning ), false );
|
||||
this.showSaveError( $( $.parseHTML( editApi.warning ) ) );
|
||||
// Don't disable the save button. If the action is not disallowed the user may save the
|
||||
// edit by pressing Save again. The AbuseFilter API currently has no way to distinguish
|
||||
// between filter triggers that are and aren't disallowing the action.
|
||||
|
@ -563,10 +541,8 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorNewUser = function ( isAnon ) {
|
|||
userMsg = 'visualeditor-savedialog-identify-user---' + mw.config.get( 'wgUserName' );
|
||||
}
|
||||
this.showSaveError(
|
||||
$( badToken ).add( $.parseHTML( mw.message( userMsg ).parse() ) ),
|
||||
'warning'
|
||||
$( badToken ).add( $.parseHTML( mw.message( userMsg ).parse() ) )
|
||||
);
|
||||
this.saveDialog.saveButton.setDisabled( false );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -612,7 +588,13 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorCaptcha = function ( editApi ) {
|
|||
}
|
||||
|
||||
$captchaDiv.append( this.captcha.input.$element );
|
||||
this.showSaveError( $captchaDiv, false );
|
||||
|
||||
// ActionDialog's error system isn't great for this yet.
|
||||
//this.showSaveError( $captchaDiv );
|
||||
this.saveDialog.clearMessage( 'api-save-error' );
|
||||
this.saveDialog.showMessage( 'api-save-error', $captchaDiv );
|
||||
this.saveDialog.popPending();
|
||||
|
||||
this.events.trackSaveError( 'captcha' );
|
||||
};
|
||||
|
||||
|
@ -625,15 +607,15 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorCaptcha = function ( editApi ) {
|
|||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveErrorUnknown = function ( editApi, data ) {
|
||||
this.showSaveError(
|
||||
document.createTextNode(
|
||||
$( document.createTextNode(
|
||||
( editApi && editApi.info ) ||
|
||||
( data.error && data.error.info ) ||
|
||||
( editApi && editApi.code ) ||
|
||||
( data.error && data.error.code ) ||
|
||||
'Unknown error'
|
||||
)
|
||||
) ),
|
||||
false // prevents reapply
|
||||
);
|
||||
this.saveDialog.saveButton.setDisabled( true );
|
||||
this.events.trackSaveError( 'unknown' );
|
||||
};
|
||||
|
||||
|
@ -643,13 +625,11 @@ ve.init.mw.ViewPageTarget.prototype.onSaveErrorUnknown = function ( editApi, dat
|
|||
* @method
|
||||
* @param {string|jQuery|Node[]} msg Message content (string of HTML, jQuery object or array of
|
||||
* Node objects)
|
||||
* @param {string|boolean} wrap Whether to wrap the message in a paragraph and if
|
||||
* so, how. One of "warning", "error" or false.
|
||||
* @param {boolean} [allowReapply=true] Whether or not to allow the user to reapply.
|
||||
* Reset when swapping panels. Assumed to be true unless explicitly set to false.
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.showSaveError = function ( msg, wrap ) {
|
||||
wrap = wrap || 'error';
|
||||
this.saveDialog.clearMessage( 'api-save-error' );
|
||||
this.saveDialog.showMessage( 'api-save-error', msg, { 'wrap': wrap } );
|
||||
ve.init.mw.ViewPageTarget.prototype.showSaveError = function ( msg, allowReapply ) {
|
||||
this.saveDeferred.reject( [ msg ], allowReapply );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -870,8 +850,10 @@ ve.init.mw.ViewPageTarget.prototype.onSaveDialogReviewComplete = function ( wiki
|
|||
/**
|
||||
* Try to save the current document.
|
||||
* @fires saveInitiated
|
||||
* @param {jQuery.Deferred} saveDeferred Deferred object to resolve/reject when the save
|
||||
* succeeds/fails.
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.saveDocument = function () {
|
||||
ve.init.mw.ViewPageTarget.prototype.saveDocument = function ( saveDeferred ) {
|
||||
var saveOptions = this.getSaveOptions();
|
||||
this.emit( 'saveInitiated' );
|
||||
|
||||
|
@ -893,9 +875,8 @@ ve.init.mw.ViewPageTarget.prototype.saveDocument = function () {
|
|||
{ wrap: false }
|
||||
);
|
||||
} else {
|
||||
this.saveDialog.saveButton.setDisabled( true );
|
||||
this.saveDialog.pushPending();
|
||||
this.save( this.docToSave, saveOptions );
|
||||
this.saveDeferred = saveDeferred;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -556,8 +556,6 @@ ve.init.mw.Target.onSave = function ( doc, saveData, response ) {
|
|||
* @param {Object} jqXHR
|
||||
* @param {string} status Text status message
|
||||
* @param {Object|null} data API response data
|
||||
* @fires saveAsyncBegin
|
||||
* @fires saveAsyncComplete
|
||||
* @fires saveErrorEmpty
|
||||
* @fires saveErrorSpamBlacklist
|
||||
* @fires saveErrorAbuseFilter
|
||||
|
@ -570,7 +568,6 @@ ve.init.mw.Target.prototype.onSaveError = function ( doc, saveData, jqXHR, statu
|
|||
var api, editApi,
|
||||
viewPage = this;
|
||||
this.saving = false;
|
||||
this.emit( 'saveAsyncComplete' );
|
||||
|
||||
// Handle empty response
|
||||
if ( !data ) {
|
||||
|
@ -595,7 +592,6 @@ ve.init.mw.Target.prototype.onSaveError = function ( doc, saveData, jqXHR, statu
|
|||
// Handle token errors
|
||||
if ( data.error && data.error.code === 'badtoken' ) {
|
||||
api = new mw.Api();
|
||||
this.emit( 'saveAsyncBegin' );
|
||||
api.get( {
|
||||
// action=query&meta=userinfo and action=tokens&type=edit can't be combined
|
||||
// but action=query&meta=userinfo and action=query&prop=info can, however
|
||||
|
@ -611,7 +607,6 @@ ve.init.mw.Target.prototype.onSaveError = function ( doc, saveData, jqXHR, statu
|
|||
} )
|
||||
.always( function () {
|
||||
viewPage.emit( 'saveErrorBadToken' );
|
||||
viewPage.emit( 'saveAsyncComplete' );
|
||||
} )
|
||||
.done( function ( data ) {
|
||||
var userMsg,
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
* noted otherwise.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.Dialog
|
||||
* @extends ve.ui.ActionDialog
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} [config] Config options
|
||||
*/
|
||||
ve.ui.MWSaveDialog = function VeUiMWSaveDialog( config ) {
|
||||
// Parent constructor
|
||||
ve.ui.Dialog.call( this, config );
|
||||
ve.ui.MWSaveDialog.super.call( this, config );
|
||||
|
||||
// Properties
|
||||
this.sanityCheckVerified = false;
|
||||
|
@ -33,7 +33,7 @@ ve.ui.MWSaveDialog = function VeUiMWSaveDialog( config ) {
|
|||
|
||||
/* Inheritance */
|
||||
|
||||
OO.inheritClass( ve.ui.MWSaveDialog, ve.ui.Dialog );
|
||||
OO.inheritClass( ve.ui.MWSaveDialog, ve.ui.ActionDialog );
|
||||
|
||||
/* Static Properties */
|
||||
|
||||
|
@ -46,6 +46,8 @@ ve.ui.MWSaveDialog.static.title =
|
|||
|
||||
/**
|
||||
* @event save
|
||||
* @param {jQuery.Deferred} saveDeferred Deferred object to resolve/reject when the save
|
||||
* succeeds/fails.
|
||||
* Emitted when the user clicks the save button
|
||||
*/
|
||||
|
||||
|
@ -111,14 +113,15 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel ) {
|
|||
this.setTitle( ve.msg( 'visualeditor-savedialog-title-' + panel ) );
|
||||
|
||||
// Reset save button if we disabled it for e.g. unrecoverable spam error
|
||||
this.saveButton.setDisabled( false );
|
||||
this.applyButton.setDisabled( false );
|
||||
|
||||
switch ( panel ) {
|
||||
case 'save':
|
||||
this.isApplyable = true;
|
||||
if ( !this.sanityCheckVerified ) {
|
||||
this.showMessage( 'dirtywarning', mw.msg( 'visualeditor-savedialog-warning-dirty' ) );
|
||||
}
|
||||
this.saveButton.$element.show();
|
||||
this.applyButton.$element.show();
|
||||
this.reviewButton.$element.show();
|
||||
this.reviewGoodButton.$element.hide();
|
||||
this.resolveConflictButton.$element.hide();
|
||||
|
@ -133,7 +136,7 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel ) {
|
|||
} );
|
||||
break;
|
||||
case 'conflict':
|
||||
this.saveButton.setDisabled( true ).$element.hide();
|
||||
this.applyButton.setDisabled( true ).$element.hide();
|
||||
this.reviewButton.$element.hide();
|
||||
this.reviewGoodButton.$element.hide();
|
||||
this.resolveConflictButton.$element.show();
|
||||
|
@ -165,7 +168,7 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel ) {
|
|||
}
|
||||
/* falls through */
|
||||
case 'nochanges':
|
||||
this.saveButton.$element.hide();
|
||||
this.applyButton.$element.hide();
|
||||
this.reviewButton.$element.hide();
|
||||
this.reviewGoodButton.$element.show();
|
||||
this.resolveConflictButton.$element.hide();
|
||||
|
@ -379,17 +382,9 @@ ve.ui.MWSaveDialog.prototype.initialize = function () {
|
|||
/* Buttons */
|
||||
|
||||
// Save button for "save" panel
|
||||
this.saveButton = new OO.ui.ButtonWidget( {
|
||||
'label': ve.msg(
|
||||
// visualeditor-savedialog-label-restore, visualeditor-savedialog-label-save
|
||||
'visualeditor-savedialog-label-' + ( this.restoring ? 'restore' : 'save' )
|
||||
),
|
||||
'flags': ['constructive']
|
||||
} );
|
||||
if ( ve.msg( 'accesskey-save' ) !== '-' && ve.msg( 'accesskey-save' ) !== '' ) {
|
||||
this.saveButton.$button.attr( 'accesskey', ve.msg( 'accesskey-save' ) );
|
||||
this.applyButton.$button.attr( 'accesskey', ve.msg( 'accesskey-save' ) );
|
||||
}
|
||||
this.saveButton.connect( this, { 'click': [ 'emit', 'save' ] } );
|
||||
|
||||
// Review button for "save" panel
|
||||
this.reviewButton = new OO.ui.ButtonWidget( {
|
||||
|
@ -413,7 +408,7 @@ ve.ui.MWSaveDialog.prototype.initialize = function () {
|
|||
this.$body.append( this.panel.$element );
|
||||
this.$foot.append(
|
||||
this.reviewButton.$element,
|
||||
this.saveButton.$element,
|
||||
this.applyButton.$element,
|
||||
this.reviewGoodButton.$element,
|
||||
this.resolveConflictButton.$element
|
||||
);
|
||||
|
@ -443,6 +438,67 @@ ve.ui.MWSaveDialog.prototype.getReadyProcess = function ( data ) {
|
|||
}, this );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.getApplyButtonFlags = function () {
|
||||
return [ 'constructive' ];
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.getApplyButtonLabel = function () {
|
||||
return ve.msg(
|
||||
// visualeditor-savedialog-label-restore, visualeditor-savedialog-label-save
|
||||
'visualeditor-savedialog-label-' + ( this.restoring ? 'restore' : 'save' )
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.pushPending = function () {
|
||||
// Parent method
|
||||
ve.ui.MWSaveDialog.super.prototype.pushPending.call( this );
|
||||
|
||||
this.applyButton.setDisabled( !this.isApplyable || this.isPending() );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.popPending = function () {
|
||||
// Parent method
|
||||
ve.ui.MWSaveDialog.super.prototype.popPending.call( this );
|
||||
|
||||
this.applyButton.setDisabled( !this.isApplyable || this.isPending() );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.applyChanges = function () {
|
||||
var saveDeferred = $.Deferred();
|
||||
this.emit( 'save', saveDeferred );
|
||||
return saveDeferred.promise();
|
||||
};
|
||||
|
||||
/*
|
||||
* @inheritdoc
|
||||
* @param {boolean} [allowReapply=true] Whether or not to allow the user to reapply.
|
||||
* Reset when swapping panels. Assumed to be true unless explicitly set to false.
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.onApplyChangesFail = function ( errors, allowReapply ) {
|
||||
if ( allowReapply === false ) {
|
||||
this.isApplyable = false;
|
||||
}
|
||||
this.dismissErrors();
|
||||
|
||||
// Parent method
|
||||
ve.ui.MWSaveDialog.super.prototype.onApplyChangesFail.call( this, errors );
|
||||
};
|
||||
|
||||
/* Registration */
|
||||
|
||||
ve.ui.windowFactory.register( ve.ui.MWSaveDialog );
|
||||
|
|
Loading…
Reference in a new issue