Merge "Introduce MWReferenceEditPanel to extract editing UI"

This commit is contained in:
jenkins-bot 2024-07-22 10:08:34 +00:00 committed by Gerrit Code Review
commit e5b4d9edfb
4 changed files with 206 additions and 71 deletions

View file

@ -110,6 +110,7 @@
"ve.ui.MWReferencesListDialog.js",
"ve.ui.MWReferenceDialog.js",
"ve.ui.MWReferenceDialogTool.js",
"ve.ui.MWReferenceEditPanel.js",
"ve.ui.MWCitationDialogTool.js",
"ve.ui.MWReferenceContextItem.js",
"ve.ui.MWReferencesListContextItem.js",

View file

@ -154,8 +154,8 @@ ve.ui.MWReferenceDialog.prototype.documentHasContent = function () {
*/
ve.ui.MWReferenceDialog.prototype.isModified = function () {
return this.documentHasContent() &&
( this.referenceTarget.hasBeenModified() ||
this.referenceGroupInput.getValue() !== this.originalGroup );
( this.editPanel.referenceTarget.hasBeenModified() ||
this.editPanel.referenceGroupInput.getValue() !== this.originalGroup );
};
/**
@ -218,7 +218,7 @@ ve.ui.MWReferenceDialog.prototype.getReadyProcess = function ( data ) {
if ( this.reuseReference ) {
this.reuseSearch.getQuery().focus().select();
} else {
this.referenceTarget.focus();
this.editPanel.referenceTarget.focus();
}
} );
};
@ -259,13 +259,13 @@ ve.ui.MWReferenceDialog.prototype.setReferenceForEditing = function ( ref ) {
* @param {ve.dm.MWReferenceModel} ref
*/
ve.ui.MWReferenceDialog.prototype.setFormFieldsFromRef = function ( ref ) {
this.referenceTarget.setDocument( ref.getDocument() );
this.editPanel.referenceTarget.setDocument( ref.getDocument() );
this.originalGroup = ref.getGroup();
// Set the group input while it's disabled, so this doesn't pop up the group-picker menu
this.referenceGroupInput.setDisabled( true );
this.referenceGroupInput.setValue( this.originalGroup );
this.referenceGroupInput.setDisabled( false );
this.editPanel.referenceGroupInput.setDisabled( true );
this.editPanel.referenceGroupInput.setValue( this.originalGroup );
this.editPanel.referenceGroupInput.setDisabled( false );
};
/**
@ -280,7 +280,7 @@ ve.ui.MWReferenceDialog.prototype.updateReuseWarningFromRef = function ( ref ) {
( node ) => !node.findParent( ve.dm.MWReferencesListNode )
).length : 0;
this.reuseWarning
this.editPanel.reuseWarning
.toggle( usages > 1 )
.setLabel( mw.msg( 'cite-ve-dialog-reference-editing-reused-long', usages ) );
};
@ -300,7 +300,7 @@ ve.ui.MWReferenceDialog.prototype.updateExtendsWarningFromRef = function ( ref )
) );
}
this.extendsWarning.toggle( !!ref.extendsRef );
this.editPanel.extendsWarning.toggle( !!ref.extendsRef );
};
/**
@ -312,66 +312,20 @@ ve.ui.MWReferenceDialog.prototype.initialize = function () {
// Properties
this.panels = new OO.ui.StackLayout();
this.editPanel = new OO.ui.PanelLayout( {
scrollable: true, padded: true
} );
this.editPanel = new ve.ui.MWReferenceEditPanel( { $overlay: this.$overlay } );
this.reuseSearchPanel = new OO.ui.PanelLayout();
this.reuseWarning = new OO.ui.MessageWidget( {
inline: true,
icon: 'alert',
classes: [ 've-ui-mwReferenceDialog-reuseWarning' ]
} );
// Icon message widget
this.extendsWarning = new OO.ui.MessageWidget( {
icon: 'alert',
inline: true,
classes: [ 've-ui-mwReferenceDialog-extendsWarning' ]
} );
const citeCommands = Object.keys( ve.init.target.getSurface().commandRegistry.registry )
.filter( ( command ) => command.indexOf( 'cite-' ) !== -1 );
this.referenceTarget = ve.init.target.createTargetWidget(
{
includeCommands: this.constructor.static.includeCommands,
excludeCommands: this.constructor.static.excludeCommands.concat( citeCommands ),
importRules: this.constructor.static.getImportRules(),
inDialog: this.constructor.static.name,
placeholder: ve.msg( 'cite-ve-dialog-reference-placeholder' )
}
);
this.contentFieldset = new OO.ui.FieldsetLayout();
this.optionsFieldset = new OO.ui.FieldsetLayout( {
label: ve.msg( 'cite-ve-dialog-reference-options-section' ),
icon: 'settings'
} );
this.contentFieldset.$element.append( this.referenceTarget.$element );
this.referenceGroupInput = new ve.ui.MWReferenceGroupInputWidget( {
$overlay: this.$overlay,
emptyGroupName: ve.msg( 'cite-ve-dialog-reference-options-group-placeholder' )
} );
this.referenceGroupInput.connect( this, { change: 'onReferenceGroupInputChange' } );
this.referenceGroupField = new OO.ui.FieldLayout( this.referenceGroupInput, {
align: 'top',
label: ve.msg( 'cite-ve-dialog-reference-options-group-label' )
} );
this.reuseSearch = new ve.ui.MWReferenceSearchWidget();
// Events
this.reuseSearch.getResults().connect( this, { choose: 'onReuseSearchResultsChoose' } );
this.referenceTarget.connect( this, { change: 'onTargetChange' } );
this.editPanel.referenceTarget.connect( this, { change: 'onTargetChange' } );
this.editPanel.referenceGroupInput.connect( this, { change: 'onReferenceGroupInputChange' } );
// Initialization
this.$content.addClass( 've-ui-mwReferenceDialog' );
this.panels.addItems( [ this.editPanel, this.reuseSearchPanel ] );
this.editPanel.$element.append(
this.reuseWarning.$element, this.extendsWarning.$element, this.contentFieldset.$element, this.optionsFieldset.$element );
this.optionsFieldset.addItems( [ this.referenceGroupField ] );
this.reuseSearchPanel.$element.append( this.reuseSearch.$element );
this.$body.append( this.panels.$element );
};
@ -397,7 +351,7 @@ ve.ui.MWReferenceDialog.prototype.getActionProcess = function ( action ) {
return new OO.ui.Process( () => {
const surfaceModel = this.getFragment().getSurface();
this.referenceModel.setGroup( this.referenceGroupInput.getValue() );
this.referenceModel.setGroup( this.editPanel.referenceGroupInput.getValue() );
// Insert reference (will auto-create an internal item if needed)
if ( !( this.selectedNode instanceof ve.dm.MWReferenceNode ) ) {
@ -440,8 +394,8 @@ ve.ui.MWReferenceDialog.prototype.getSetupProcess = function ( data ) {
this.reuseSearch.setInternalList( this.getFragment().getDocument().getInternalList() );
const isReadOnly = this.isReadOnly();
this.referenceTarget.setReadOnly( isReadOnly );
this.referenceGroupInput.setReadOnly( isReadOnly );
this.editPanel.referenceTarget.setReadOnly( isReadOnly );
this.editPanel.referenceGroupInput.setReadOnly( isReadOnly );
this.reuseReference = !!data.reuseReference;
if ( this.reuseReference ) {
@ -451,7 +405,7 @@ ve.ui.MWReferenceDialog.prototype.getSetupProcess = function ( data ) {
done: false
} );
this.referenceGroupInput.populateMenu(
this.editPanel.referenceGroupInput.populateMenu(
this.getFragment().getDocument().getInternalList() );
this.trackedInputChange = false;
@ -464,9 +418,9 @@ ve.ui.MWReferenceDialog.prototype.getSetupProcess = function ( data ) {
ve.ui.MWReferenceDialog.prototype.getTeardownProcess = function ( data ) {
return ve.ui.MWReferenceDialog.super.prototype.getTeardownProcess.call( this, data )
.first( () => {
this.referenceTarget.getSurface().getModel().disconnect( this );
this.editPanel.referenceTarget.getSurface().getModel().disconnect( this );
this.reuseSearch.clearSearch();
this.referenceTarget.clear();
this.editPanel.referenceTarget.clear();
this.referenceModel = null;
} );
};

View file

@ -0,0 +1,179 @@
'use strict';
/*!
* VisualEditor UserInterface MWReferenceResultWidget class.
*
* @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt
* @license MIT
*/
/**
* Creates a ve.ui.MWReferenceEditPanel object.
*
* @constructor
* @extends OO.ui.PanelLayout
* @param {Object} config
* @param {jQuery} config.$overlay Layer to render options dropdown outside of the parent dialog
*/
ve.ui.MWReferenceEditPanel = function VeUiMWReferenceEditPanel( config ) {
// Configuration initialization
config = Object.assign( {
scrollable: true,
padded: true
}, config );
// Parent constructor
ve.ui.MWReferenceEditPanel.super.call( this, { scrollable: true, padded: true } );
// Initialization
this.$element.addClass( 've-ui-mwReferenceEditPanel' );
// Properties
// Create content editor
this.referenceTarget = ve.init.target.createTargetWidget(
{
includeCommands: null,
excludeCommands: this.constructor.static.getExcludeCommands(),
importRules: this.constructor.static.getImportRules(),
inDialog: 'reference',
placeholder: ve.msg( 'cite-ve-dialog-reference-placeholder' )
}
);
this.contentFieldset = new OO.ui.FieldsetLayout();
this.contentFieldset.$element.append(
this.referenceTarget.$element
);
// Create group edit
this.optionsFieldset = new OO.ui.FieldsetLayout( {
label: ve.msg( 'cite-ve-dialog-reference-options-section' ),
icon: 'settings'
} );
this.referenceGroupInput = new ve.ui.MWReferenceGroupInputWidget( {
$overlay: config.$overlay,
emptyGroupName: ve.msg( 'cite-ve-dialog-reference-options-group-placeholder' )
} );
this.referenceGroupField = new OO.ui.FieldLayout( this.referenceGroupInput, {
align: 'top',
label: ve.msg( 'cite-ve-dialog-reference-options-group-label' )
} );
this.optionsFieldset.addItems( [ this.referenceGroupField ] );
// Create warning messages
this.reuseWarning = new OO.ui.MessageWidget( {
icon: 'alert',
inline: true,
classes: [ 've-ui-mwReferenceDialog-reuseWarning' ]
} );
this.extendsWarning = new OO.ui.MessageWidget( {
icon: 'alert',
inline: true,
classes: [ 've-ui-mwReferenceDialog-extendsWarning' ]
} );
// Append to panel element
this.$element.append(
this.reuseWarning.$element,
this.extendsWarning.$element,
this.contentFieldset.$element,
this.optionsFieldset.$element
);
};
/* Inheritance */
OO.inheritClass( ve.ui.MWReferenceEditPanel, OO.ui.PanelLayout );
/* Static Properties */
ve.ui.MWReferenceEditPanel.static.excludeCommands = [
// No formatting
'paragraph',
'heading1',
'heading2',
'heading3',
'heading4',
'heading5',
'heading6',
'preformatted',
'blockquote',
// No tables
'insertTable',
'deleteTable',
'mergeCells',
'tableCaption',
'tableCellHeader',
'tableCellData',
// No structure
'bullet',
'bulletWrapOnce',
'number',
'numberWrapOnce',
'indent',
'outdent',
// References
'reference',
'reference/existing',
'citoid',
'referencesList'
];
/**
* Get the list of disallowed commands for the surface widget to edit the content. This includes
* all Cite related commands to disencourage nesting of references.
*
* @see ve.dm.ElementLinearData#sanitize
* @return {Object} Import rules
*/
ve.ui.MWReferenceEditPanel.static.getExcludeCommands = function () {
const citeCommands = Object.keys( ve.init.target.getSurface().commandRegistry.registry )
.filter( ( command ) => command.indexOf( 'cite-' ) !== -1 );
return ve.ui.MWReferenceEditPanel.static.excludeCommands.concat( citeCommands );
};
/**
* Get the import rules for the surface widget to edit the content
*
* @see ve.dm.ElementLinearData#sanitize
* @return {Object} Import rules
*/
ve.ui.MWReferenceEditPanel.static.getImportRules = function () {
const rules = ve.copy( ve.init.target.constructor.static.importRules );
return ve.extendObject(
rules,
{
all: {
blacklist: ve.extendObject(
{
// Nested references are impossible
mwReference: true,
mwReferencesList: true,
// Lists and tables are actually possible in wikitext with a leading
// line break but we prevent creating these with the UI
list: true,
listItem: true,
definitionList: true,
definitionListItem: true,
table: true,
tableCaption: true,
tableSection: true,
tableRow: true,
tableCell: true,
mwTable: true,
mwTransclusionTableCell: true
},
ve.getProp( rules, 'all', 'blacklist' )
),
// Headings are not possible in wikitext without HTML
conversions: ve.extendObject(
{
mwHeading: 'paragraph'
},
ve.getProp( rules, 'all', 'conversions' )
)
}
}
);
};

View file

@ -5,13 +5,14 @@ QUnit.module( 've.ui.MWReferenceDialog (Cite)', ve.test.utils.newMwEnvironment()
QUnit.test( 'setReferenceForEditing', ( assert ) => {
const dialog = new ve.ui.MWReferenceDialog();
dialog.referenceGroupInput = new ve.ui.MWReferenceGroupInputWidget( {} );
dialog.reuseWarning = new OO.ui.MessageWidget();
dialog.extendsWarning = new OO.ui.MessageWidget();
dialog.editPanel = {};
dialog.editPanel.referenceGroupInput = new ve.ui.MWReferenceGroupInputWidget( {} );
dialog.editPanel.reuseWarning = new OO.ui.MessageWidget();
dialog.editPanel.extendsWarning = new OO.ui.MessageWidget();
// XXX: This is a regression test with a fragile setup. Please feel free to delete this test
// when you feel like it doesn't make sense to update it.
dialog.referenceTarget = {
dialog.editPanel.referenceTarget = {
setDocument: () => null
};
dialog.fragment = {
@ -31,7 +32,7 @@ QUnit.test( 'setReferenceForEditing', ( assert ) => {
assert.strictEqual( dialog.referenceModel, ref );
assert.strictEqual( dialog.originalGroup, 'g' );
assert.strictEqual( dialog.referenceGroupInput.getValue(), 'g' );
assert.false( dialog.referenceGroupInput.isDisabled() );
assert.false( dialog.reuseWarning.isVisible() );
assert.strictEqual( dialog.editPanel.referenceGroupInput.getValue(), 'g' );
assert.false( dialog.editPanel.referenceGroupInput.isDisabled() );
assert.false( dialog.editPanel.reuseWarning.isVisible() );
} );