mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-24 10:48:42 +00:00
Introduce visual differ in the save dialog
Bug: T143350 Change-Id: I1297d0f4bb87e69be3b50220c1830a22dac1bbae
This commit is contained in:
parent
a3a4ff3d20
commit
335b56728a
|
@ -403,7 +403,8 @@
|
|||
"modules/ve-mw/ui/tools/ve.ui.MWMobileLinkInspectorTool.js"
|
||||
],
|
||||
"styles": [
|
||||
"modules/ve-mw/init/styles/ve.init.mw.MobileArticleTarget.css"
|
||||
"modules/ve-mw/init/styles/ve.init.mw.MobileArticleTarget.css",
|
||||
"modules/ve-mw/ui/styles/dialogs/ve.ui.MWMobileSaveDialog.css"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.visualEditor.base",
|
||||
|
@ -513,7 +514,8 @@
|
|||
"ext.visualEditor.mediawiki",
|
||||
"ext.visualEditor.core",
|
||||
"ext.visualEditor.mwcore",
|
||||
"ext.visualEditor.mwextensions"
|
||||
"ext.visualEditor.mwextensions",
|
||||
"oojs-ui.styles.icons-alerts"
|
||||
],
|
||||
"messages": [
|
||||
"accesskey-diff",
|
||||
|
@ -1283,6 +1285,9 @@
|
|||
"visualeditor-savedialog-label-review-good",
|
||||
"visualeditor-savedialog-label-save-short",
|
||||
"visualeditor-savedialog-label-warning",
|
||||
"visualeditor-savedialog-review-nosummary",
|
||||
"visualeditor-savedialog-review-visual",
|
||||
"visualeditor-savedialog-review-wikitext",
|
||||
"visualeditor-savedialog-title-conflict",
|
||||
"visualeditor-savedialog-title-nochanges",
|
||||
"visualeditor-savedialog-title-preview",
|
||||
|
@ -1318,6 +1323,7 @@
|
|||
"ext.visualEditor.mwtransclusion",
|
||||
"ext.visualEditor.mwgallery",
|
||||
"ext.visualEditor.mwalienextension",
|
||||
"ext.visualEditor.diffing",
|
||||
"ext.visualEditor.language",
|
||||
"ext.visualEditor.icons"
|
||||
],
|
||||
|
@ -1732,6 +1738,56 @@
|
|||
"mobile"
|
||||
]
|
||||
},
|
||||
"treeDiffer": {
|
||||
"scripts": [
|
||||
"lib/ve/lib/treeDiffer/treeDiffer-dist.js"
|
||||
],
|
||||
"targets": [
|
||||
"desktop",
|
||||
"mobile"
|
||||
]
|
||||
},
|
||||
"diffMatchPatch": {
|
||||
"scripts": [
|
||||
"lib/ve/lib/diff-match-patch/diff_match_patch_uncompressed.js"
|
||||
],
|
||||
"targets": [
|
||||
"desktop",
|
||||
"mobile"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.diffing": {
|
||||
"debugScripts": [
|
||||
"lib/ve/src/ve.DiffTreeNode.js",
|
||||
"lib/ve/src/ve.DiffMatchPatch.js",
|
||||
"lib/ve/src/dm/ve.dm.VisualDiff.js",
|
||||
"lib/ve/src/ui/elements/ve.ui.DiffElement.js",
|
||||
"lib/ve/src/ui/widgets/ve.ui.ChangeDescriptionsSelectWidget.js"
|
||||
],
|
||||
"styles": [
|
||||
"lib/ve/src/ui/styles/elements/ve.ui.DiffElement.css"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.visualEditor.core",
|
||||
"treeDiffer",
|
||||
"diffMatchPatch"
|
||||
],
|
||||
"messages": [
|
||||
"visualeditor-changedesc-changed",
|
||||
"visualeditor-changedesc-image-size",
|
||||
"visualeditor-changedesc-language",
|
||||
"visualeditor-changedesc-link-href",
|
||||
"visualeditor-changedesc-no-key",
|
||||
"visualeditor-changedesc-set",
|
||||
"visualeditor-changedesc-unknown",
|
||||
"visualeditor-changedesc-unset",
|
||||
"visualeditor-diff-no-changes"
|
||||
],
|
||||
"targets": [
|
||||
"desktop",
|
||||
"mobile"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.language": {
|
||||
"scripts": [
|
||||
"lib/ve/src/dm/annotations/ve.dm.LanguageAnnotation.js",
|
||||
|
|
|
@ -359,6 +359,9 @@
|
|||
"visualeditor-savedialog-label-review-good": "Return to save form",
|
||||
"visualeditor-savedialog-label-save-short": "Save",
|
||||
"visualeditor-savedialog-label-warning": "Warning",
|
||||
"visualeditor-savedialog-review-nosummary": "No edit summary",
|
||||
"visualeditor-savedialog-review-visual": "Visual",
|
||||
"visualeditor-savedialog-review-wikitext": "Wikitext",
|
||||
"visualeditor-savedialog-title-conflict": "Conflict",
|
||||
"visualeditor-savedialog-title-nochanges": "No changes to review",
|
||||
"visualeditor-savedialog-title-preview": "Preview your changes",
|
||||
|
|
|
@ -372,6 +372,9 @@
|
|||
"visualeditor-savedialog-label-review-good": "Label for button to go back to a page in order to save form",
|
||||
"visualeditor-savedialog-label-save-short": "Short label text for save button on private wikis for use on width-restricted devices like mobile phones. This should be as short as possible.\n{{Identical|Save}}",
|
||||
"visualeditor-savedialog-label-warning": "Label in front of a save dialog warning sentence, separated by {{msg-mw|colon-separator}}.\n{{Identical|Warning}}",
|
||||
"visualeditor-savedialog-review-nosummary": "Message shown when no edit summary was provided.",
|
||||
"visualeditor-savedialog-review-visual": "Label for button to select visual diff mode.",
|
||||
"visualeditor-savedialog-review-wikitext": "Label for button to select wikitext diff mode.",
|
||||
"visualeditor-savedialog-title-conflict": "Title for save dialog slide if there is an edit conflict\n{{Identical|Conflict}}",
|
||||
"visualeditor-savedialog-title-nochanges": "Title for save dialog slide for the wikitext diff if there are no changes",
|
||||
"visualeditor-savedialog-title-preview": "Title for save dialog slide for the HTML preview from wikitext mode",
|
||||
|
|
|
@ -35,6 +35,7 @@ ve.init.mw.ArticleTarget = function VeInitMwArticleTarget( pageName, revisionId,
|
|||
this.saveDeferred = null;
|
||||
this.captcha = null;
|
||||
this.docToSave = null;
|
||||
this.originalDmDoc = null;
|
||||
this.toolbarSaveButton = null;
|
||||
this.pageName = pageName;
|
||||
this.pageExists = mw.config.get( 'wgRelevantArticleId', 0 ) !== 0;
|
||||
|
@ -743,7 +744,7 @@ ve.init.mw.ArticleTarget.prototype.showChangesDiff = function ( diffHtml ) {
|
|||
this.getSurface().getModel().getDocument().once( 'transact',
|
||||
this.saveDialog.clearDiff.bind( this.saveDialog )
|
||||
);
|
||||
this.saveDialog.setDiffAndReview( diffHtml );
|
||||
this.saveDialog.setDiffAndReview( diffHtml, this.getVisualDiff() );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1066,7 +1067,7 @@ ve.init.mw.ArticleTarget.prototype.serializeFail = function () {
|
|||
* @fires saveReview
|
||||
*/
|
||||
ve.init.mw.ArticleTarget.prototype.onSaveDialogReview = function () {
|
||||
if ( !this.saveDialog.$reviewViewer.find( 'table, pre' ).length ) {
|
||||
if ( !this.saveDialog.hasDiff ) {
|
||||
this.emit( 'saveReview' );
|
||||
this.saveDialog.getActions().setAbilities( { approve: false } );
|
||||
this.saveDialog.pushPending();
|
||||
|
@ -1153,7 +1154,24 @@ ve.init.mw.ArticleTarget.prototype.bindSaveDialogClearDiff = function () {
|
|||
*/
|
||||
ve.init.mw.ArticleTarget.prototype.onSaveDialogReviewComplete = function ( wikitext ) {
|
||||
this.bindSaveDialogClearDiff();
|
||||
this.saveDialog.setDiffAndReview( $( '<pre>' ).text( wikitext ) );
|
||||
this.saveDialog.setDiffAndReview( $( '<pre>' ).text( wikitext ), this.getVisualDiff() );
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a visual diff object for the current document state
|
||||
*
|
||||
* @return {ve.dm.VisualDiff|null} Visual diff, or null if not known
|
||||
*/
|
||||
ve.init.mw.ArticleTarget.prototype.getVisualDiff = function () {
|
||||
if ( this.getSurface().getMode() === 'source' ) {
|
||||
return null;
|
||||
}
|
||||
if ( !this.originalDmDoc ) {
|
||||
// TODO: If switching from source - we need to fetch the original doc
|
||||
// from the server.
|
||||
this.originalDmDoc = this.createModelFromDom( this.doc, 'visual' );
|
||||
}
|
||||
return new ve.dm.VisualDiff( this.originalDmDoc, this.getSurface().getModel().getDocument() );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1250,6 +1268,7 @@ ve.init.mw.ArticleTarget.prototype.clearState = function () {
|
|||
this.startTimeStamp = null;
|
||||
this.checkboxes = null;
|
||||
this.doc = null;
|
||||
this.originalDmDoc = null;
|
||||
this.originalHtml = null;
|
||||
this.section = null;
|
||||
this.editNotices = [];
|
||||
|
|
|
@ -29,6 +29,18 @@ ve.ui.MWMobileSaveDialog = function VeUiMwMobileSaveDialog() {
|
|||
|
||||
OO.inheritClass( ve.ui.MWMobileSaveDialog, ve.ui.MWSaveDialog );
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWMobileSaveDialog.prototype.initialize = function () {
|
||||
// Parent method
|
||||
ve.ui.MWMobileSaveDialog.super.prototype.initialize.call( this );
|
||||
|
||||
this.$reviewVisualDiff.addClass( 'content' );
|
||||
};
|
||||
|
||||
/* Registration */
|
||||
|
||||
ve.ui.windowFactory.register( ve.ui.MWMobileSaveDialog );
|
||||
|
|
|
@ -30,6 +30,7 @@ ve.ui.MWSaveDialog = function VeUiMwSaveDialog( config ) {
|
|||
this.changedEditSummary = false;
|
||||
this.canReview = false;
|
||||
this.canPreview = false;
|
||||
this.hasDiff = false;
|
||||
|
||||
// Initialization
|
||||
this.$element.addClass( 've-ui-mwSaveDialog' );
|
||||
|
@ -117,11 +118,27 @@ ve.ui.MWSaveDialog.static.actions = [
|
|||
/**
|
||||
* Set review content and show review panel.
|
||||
*
|
||||
* @param {string} content Diff HTML or wikitext
|
||||
* @param {string} wikitextDiff Diff HTML or wikitext
|
||||
* @param {ve.dm.VisualDiff} [visualDiff] Visual diff
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.setDiffAndReview = function ( content ) {
|
||||
this.$reviewViewer.empty().append( content );
|
||||
ve.ui.MWSaveDialog.prototype.setDiffAndReview = function ( wikitextDiff, visualDiff ) {
|
||||
this.$reviewVisualDiff.empty();
|
||||
if ( visualDiff ) {
|
||||
this.diffElement = new ve.ui.DiffElement( visualDiff );
|
||||
this.diffElement.$document.addClass( 'mw-body-content' );
|
||||
// TODO: Remove when fixed upstream in Parsoid (T58756)
|
||||
this.diffElement.$element.find( 'a[rel="mw:ExtLink"]' ).addClass( 'external' );
|
||||
this.$reviewVisualDiff.append( this.diffElement.$element );
|
||||
this.reviewModeButtonSelect.getItemFromData( 'visual' ).setDisabled( false );
|
||||
} else {
|
||||
// TODO: Support visual diffs in source mode (epic)
|
||||
this.reviewModeButtonSelect.getItemFromData( 'visual' ).setDisabled( true );
|
||||
this.reviewModeButtonSelect.selectItemByData( 'source' );
|
||||
}
|
||||
|
||||
this.$reviewWikitextDiff.empty().append( wikitextDiff );
|
||||
this.actions.setAbilities( { approve: true } );
|
||||
this.hasDiff = true;
|
||||
this.popPending();
|
||||
this.swapPanel( 'review' );
|
||||
};
|
||||
|
@ -164,8 +181,9 @@ ve.ui.MWSaveDialog.prototype.popPending = function () {
|
|||
* Clear the diff displayed in the review panel, if any.
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.clearDiff = function () {
|
||||
this.$reviewViewer.empty();
|
||||
this.$reviewWikitextDiff.empty();
|
||||
this.$previewViewer.empty();
|
||||
this.hasDiff = false;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -173,7 +191,6 @@ ve.ui.MWSaveDialog.prototype.clearDiff = function () {
|
|||
*
|
||||
* @param {string} panel One of 'save', 'review', 'conflict' or 'nochanges'
|
||||
* @param {boolean} [noFocus] Don't attempt to focus anything (e.g. while setting up)
|
||||
* @return {jQuery} The now active panel
|
||||
* @throws {Error} Unknown saveDialog panel
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel, noFocus ) {
|
||||
|
@ -233,7 +250,7 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel, noFocus ) {
|
|||
|
||||
if ( !currentEditSummaryWikitext || currentEditSummaryWikitext.trim() === '' ) {
|
||||
// Don't bother with an API request for an empty summary
|
||||
this.$reviewEditSummary.parent().addClass( 'oo-ui-element-hidden' );
|
||||
this.$reviewEditSummary.text( ve.msg( 'visualeditor-savedialog-review-nosummary' ) );
|
||||
} else {
|
||||
this.$reviewEditSummary.parent()
|
||||
.removeClass( 'oo-ui-element-hidden' )
|
||||
|
@ -256,6 +273,9 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel, noFocus ) {
|
|||
} );
|
||||
}
|
||||
}
|
||||
setTimeout( function () {
|
||||
dialog.updateReviewMode();
|
||||
} );
|
||||
break;
|
||||
case 'nochanges':
|
||||
mode = 'review';
|
||||
|
@ -280,8 +300,6 @@ ve.ui.MWSaveDialog.prototype.swapPanel = function ( panel, noFocus ) {
|
|||
} );
|
||||
|
||||
mw.hook( 've.saveDialog.stateChanged' ).fire();
|
||||
|
||||
return dialog;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -483,15 +501,31 @@ ve.ui.MWSaveDialog.prototype.initialize = function () {
|
|||
scrollable: true,
|
||||
padded: true
|
||||
} );
|
||||
this.$reviewViewer = $( '<div>' ).addClass( 've-ui-mwSaveDialog-viewer' );
|
||||
|
||||
this.$reviewVisualDiff = $( '<div>' ).addClass( 've-ui-mwSaveDialog-viewer' );
|
||||
this.$reviewWikitextDiff = $( '<div>' ).addClass( 've-ui-mwSaveDialog-viewer' );
|
||||
|
||||
this.reviewModeButtonSelect = new OO.ui.ButtonSelectWidget( {
|
||||
items: [
|
||||
new OO.ui.ButtonOptionWidget( { data: 'visual', icon: 'eye', label: ve.msg( 'visualeditor-savedialog-review-visual' ) } ),
|
||||
new OO.ui.ButtonOptionWidget( { data: 'source', icon: 'wikiText', label: ve.msg( 'visualeditor-savedialog-review-wikitext' ) } )
|
||||
],
|
||||
classes: [ 've-ui-mwSaveDialog-reviewMode' ]
|
||||
} );
|
||||
this.reviewModeButtonSelect.connect( this, { select: 'updateReviewMode' } );
|
||||
// TODO: Make 'visual' the default
|
||||
this.reviewModeButtonSelect.selectItemByData( 'source' );
|
||||
|
||||
this.$reviewEditSummary = $( '<span>' ).addClass( 've-ui-mwSaveDialog-summaryPreview' ).addClass( 'comment' );
|
||||
this.$reviewActions = $( '<div>' ).addClass( 've-ui-mwSaveDialog-actions' );
|
||||
this.reviewPanel.$element.append(
|
||||
this.reviewModeButtonSelect.$element,
|
||||
$( '<div>' )
|
||||
.addClass( 'mw-summary-preview' )
|
||||
.text( ve.msg( 'summary-preview' ) )
|
||||
.append( $( '<br>' ), this.$reviewEditSummary ),
|
||||
this.$reviewViewer,
|
||||
this.$reviewVisualDiff,
|
||||
this.$reviewWikitextDiff,
|
||||
this.$reviewActions
|
||||
);
|
||||
|
||||
|
@ -552,6 +586,17 @@ ve.ui.MWSaveDialog.prototype.initialize = function () {
|
|||
this.setupDeferred.resolve();
|
||||
};
|
||||
|
||||
ve.ui.MWSaveDialog.prototype.updateReviewMode = function () {
|
||||
var isVisual = this.reviewModeButtonSelect.getSelectedItem().getData() === 'visual';
|
||||
this.$reviewVisualDiff.toggleClass( 'oo-ui-element-hidden', !isVisual );
|
||||
this.$reviewWikitextDiff.toggleClass( 'oo-ui-element-hidden', isVisual );
|
||||
this.updateSize();
|
||||
if ( isVisual ) {
|
||||
this.diffElement.positionDescriptions();
|
||||
this.updateSize();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @param {Object} [data]
|
||||
|
|
10
modules/ve-mw/ui/styles/dialogs/ve.ui.MWMobileSaveDialog.css
Normal file
10
modules/ve-mw/ui/styles/dialogs/ve.ui.MWMobileSaveDialog.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki UserInterface MWMobileSaveDialog styles.
|
||||
*
|
||||
* @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
.ve-ui-mwMobileSaveDialog .content {
|
||||
margin: 0;
|
||||
}
|
|
@ -74,3 +74,13 @@
|
|||
.ve-ui-mwSaveDialog-messages:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ve-ui-mwSaveDialog-reviewMode {
|
||||
float: right;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.ve-ui-mwSaveDialog-viewer {
|
||||
margin-top: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue