diff --git a/extension.json b/extension.json index fd7ebc8c81..3dda2315f2 100644 --- a/extension.json +++ b/extension.json @@ -170,6 +170,10 @@ }, "VisualEditorUseSingleEditTab": { "value": false + }, + "VisualEditorTransclusionDialogSuggestedValues": { + "description": "Temporary flag to enable suggested values in the transclusion dialog.", + "value": false } }, "APIModules": { @@ -2152,6 +2156,7 @@ "visualeditor-dialog-transclusion-add-template", "visualeditor-dialog-transclusion-content", "visualeditor-dialog-transclusion-contextitem-description", + "visualeditor-dialog-transclusion-suggestedvalues-warning", "visualeditor-dialog-transclusion-deprecated-parameter", "visualeditor-dialog-transclusion-deprecated-parameter-description", "visualeditor-dialog-transclusion-loading", diff --git a/i18n/ve-mw/en.json b/i18n/ve-mw/en.json index 800f4bb722..f91b3c24fe 100644 --- a/i18n/ve-mw/en.json +++ b/i18n/ve-mw/en.json @@ -174,6 +174,7 @@ "visualeditor-dialog-transclusion-add-template": "Add template", "visualeditor-dialog-transclusion-content": "Content", "visualeditor-dialog-transclusion-contextitem-description": "Generated from: $1", + "visualeditor-dialog-transclusion-suggestedvalues-warning": "This is not one of the suggested values and may not work with the template.", "visualeditor-dialog-transclusion-deprecated-parameter": "Deprecated field", "visualeditor-dialog-transclusion-deprecated-parameter-description": "Field is deprecated. $1", "visualeditor-dialog-transclusion-loading": "Loading...", diff --git a/i18n/ve-mw/qqq.json b/i18n/ve-mw/qqq.json index 2519b99bd0..f64c7e7991 100644 --- a/i18n/ve-mw/qqq.json +++ b/i18n/ve-mw/qqq.json @@ -192,6 +192,7 @@ "visualeditor-dialog-transclusion-add-template": "Label for button that adds the specified template to the page.\n{{Identical|Add template}}", "visualeditor-dialog-transclusion-content": "Label for editor of content between transclusion parts.\n{{Identical|Content}}", "visualeditor-dialog-transclusion-contextitem-description": "Message shown to an editor when they click on a template or group of templates that form a transclusion, listing the template(s) from which the transclusion is constructed.\n\n* $1 – the name of the template, or a list of the names of the templates if there are multiple.\n* $2 - number of templates for PLURAL support.", + "visualeditor-dialog-transclusion-suggestedvalues-warning": "Message shown to an editor when they manually add a value that is not a suggested value for a parameter.", "visualeditor-dialog-transclusion-deprecated-parameter": "Tooltip for deprecated parameter indicator", "visualeditor-dialog-transclusion-deprecated-parameter-description": "Label describing that a parameter is deprecated.\n\nParameters:\n* $1 - Description given in TemplateData for why parameter is deprecated, which may be empty.", "visualeditor-dialog-transclusion-loading": "Title for the transclusion dialog while its contents are loading.\n{{Identical|Loading}}", diff --git a/includes/VisualEditorHooks.php b/includes/VisualEditorHooks.php index 7d149cf3e3..8697a5233c 100644 --- a/includes/VisualEditorHooks.php +++ b/includes/VisualEditorHooks.php @@ -1047,6 +1047,7 @@ class VisualEditorHooks { 'feedbackApiUrl' => $veConfig->get( 'VisualEditorFeedbackAPIURL' ), 'feedbackTitle' => $veConfig->get( 'VisualEditorFeedbackTitle' ), 'sourceFeedbackTitle' => $veConfig->get( 'VisualEditorSourceFeedbackTitle' ), + 'transclusionDialogSuggestedValues' => $veConfig->get( 'VisualEditorTransclusionDialogSuggestedValues' ), ]; } diff --git a/modules/ve-mw/dm/models/ve.dm.MWParameterModel.js b/modules/ve-mw/dm/models/ve.dm.MWParameterModel.js index c264462e73..f49f48f64d 100644 --- a/modules/ve-mw/dm/models/ve.dm.MWParameterModel.js +++ b/modules/ve-mw/dm/models/ve.dm.MWParameterModel.js @@ -114,6 +114,15 @@ ve.dm.MWParameterModel.prototype.getValue = function () { return this.value || this.getAutoValue() || ''; }; +/** + * Get parameter suggested values. + * + * @return {string[]} Parameter suggested values + */ +ve.dm.MWParameterModel.prototype.getSuggestedValues = function () { + return this.template.getSpec().getParameterSuggestedValues( this.name ); +}; + /** * Get default parameter value. * diff --git a/modules/ve-mw/dm/models/ve.dm.MWTemplateSpecModel.js b/modules/ve-mw/dm/models/ve.dm.MWTemplateSpecModel.js index 8d056f200d..15c01abb2f 100644 --- a/modules/ve-mw/dm/models/ve.dm.MWTemplateSpecModel.js +++ b/modules/ve-mw/dm/models/ve.dm.MWTemplateSpecModel.js @@ -207,6 +207,16 @@ ve.dm.MWTemplateSpecModel.prototype.getParameterDescription = function ( name, l return this.constructor.static.getLocalValue( this.params[ name ].description, lang ); }; +/** + * Get a parameter suggested values. + * + * @param {string} name Parameter name + * @return {string[]} Parameter suggested values + */ +ve.dm.MWTemplateSpecModel.prototype.getParameterSuggestedValues = function ( name ) { + return this.params[ name ].suggestedvalues || []; +}; + /** * Get a parameter value. * diff --git a/modules/ve-mw/ui/pages/ve.ui.MWParameterPage.js b/modules/ve-mw/ui/pages/ve.ui.MWParameterPage.js index 2243d69032..913cd3ffcb 100644 --- a/modules/ve-mw/ui/pages/ve.ui.MWParameterPage.js +++ b/modules/ve-mw/ui/pages/ve.ui.MWParameterPage.js @@ -19,7 +19,8 @@ * @cfg {boolean} [readOnly] Parameter is read-only */ ve.ui.MWParameterPage = function VeUiMWParameterPage( parameter, name, config ) { - var paramName = parameter.getName(); + var paramName = parameter.getName(), + veConfig = mw.config.get( 'wgVisualEditorConfig' ); // Configuration initialization config = ve.extendObject( { @@ -187,6 +188,16 @@ ve.ui.MWParameterPage = function VeUiMWParameterPage( parameter, name, config ) .append( this.valueInput.$element ); + if ( + veConfig.transclusionDialogSuggestedValues && + this.parameter.getSuggestedValues().length + ) { + this.warningMessage = new OO.ui.MessageWidget( { + inline: true, + classes: [ 've-ui-mwParameterPage-warning' ] + } ).toggle( false ); + this.$field.append( this.warningMessage.$element ); + } this.$more .addClass( 've-ui-mwParameterPage-more' ) .append( this.addButton.$element ); @@ -242,7 +253,8 @@ ve.ui.MWParameterPage.prototype.getDefaultInputConfig = function () { ve.ui.MWParameterPage.prototype.createValueInput = function () { var type = this.parameter.getType(), value = this.parameter.getValue(), - valueInputConfig = this.getDefaultInputConfig(); + valueInputConfig = this.getDefaultInputConfig(), + veConfig = mw.config.get( 'wgVisualEditorConfig' ); this.rawValueInput = false; delete valueInputConfig.validate; @@ -299,6 +311,17 @@ ve.ui.MWParameterPage.prototype.createValueInput = function () { ) ) { return ve.ui.MWExternalLinkAnnotationWidget.static.createExternalLinkInputWidget( valueInputConfig ); + } else if ( + veConfig.transclusionDialogSuggestedValues && + this.parameter.getSuggestedValues().length && + this.isSuggestedValueType( type ) + ) { + valueInputConfig.options = + this.parameter.getSuggestedValues().map( function ( suggestedValue ) { + return { data: suggestedValue }; + } ); + this.rawValueInput = true; + return new OO.ui.ComboBoxInputWidget( valueInputConfig ); } else if ( type !== 'line' || value.indexOf( '\n' ) !== -1 ) { // If the type is line, but there are already newlines in the provided // value, don't break the existing content by only providing a single- @@ -311,6 +334,16 @@ ve.ui.MWParameterPage.prototype.createValueInput = function () { return new OO.ui.TextInputWidget( valueInputConfig ); }; +/** + * Whether or not to show suggested values for a given parameter type + * + * @param {string} type Parameter type + * @returns {boolean} True if suggested values should be shown + */ +ve.ui.MWParameterPage.prototype.isSuggestedValueType = function ( type ) { + return [ 'unknown', 'content', 'line', 'string', 'number', 'unbalanced-wikitext' ].indexOf( type ) > -1; +}; + /** * Check if the parameter is empty * @@ -326,7 +359,8 @@ ve.ui.MWParameterPage.prototype.isEmpty = function () { * @param {string} value Value */ ve.ui.MWParameterPage.prototype.onValueInputChange = function () { - var value = this.valueInput.getValue(); + var value = this.valueInput.getValue(), + isNotSuggestedValue; if ( !this.edited ) { ve.track( 'activity.transclusion', { action: 'edit-parameter-value' } ); @@ -337,6 +371,16 @@ ve.ui.MWParameterPage.prototype.onValueInputChange = function () { if ( this.outlineItem ) { this.outlineItem.setFlags( { empty: this.isEmpty() } ); } + + if ( this.warningMessage ) { + isNotSuggestedValue = value && + this.parameter.getSuggestedValues().length > 0 && + this.parameter.getSuggestedValues().indexOf( value ) === -1; + if ( isNotSuggestedValue ) { + this.warningMessage.setLabel( ve.msg( 'visualeditor-dialog-transclusion-suggestedvalues-warning' ) ); + } + this.warningMessage.toggle( isNotSuggestedValue ); + } }; /** diff --git a/modules/ve-mw/ui/styles/pages/ve.ui.MWParameterPage.css b/modules/ve-mw/ui/styles/pages/ve.ui.MWParameterPage.css index efb7147d03..8bb57855b9 100644 --- a/modules/ve-mw/ui/styles/pages/ve.ui.MWParameterPage.css +++ b/modules/ve-mw/ui/styles/pages/ve.ui.MWParameterPage.css @@ -11,3 +11,13 @@ font-family: monospace, monospace; background-color: #c8ccd1; } + +.ve-ui-mwParameterPage-warning { + color: #202122; /* @wmui-color-base10 */ + font-weight: normal; + margin-top: 0.5em; +} + +.ve-ui-mwParameterPage-warning .oo-ui-iconElement-icon { + opacity: 0.87; +}