From e75605bc0e0c14592a919e9193c93f9465d14317 Mon Sep 17 00:00:00 2001 From: Moriel Schottlender Date: Tue, 24 Feb 2015 14:59:33 -0800 Subject: [PATCH] Refactoring mw.Feedback to work with OOUI elements Transform mw.Feedback into an ooui dialog. * Added a configurable checkbox for useragent and terms of servvice options. The checkbox can be configured to be visible or not, and to be mandatory or optional. (useragent addition based largely on the unmerged fix I37b1a271af115) * Transformed the 'feedback-bugornote' message to a configurable intro message with a link to the feedback page. * Added a 'thank you' or 'error' dialog at the end of the operation indicating whether the feedback was sent or if there was some error. Bug: T89878 Bug: T43291 Bug: T35365 Bug: T54588 Bug: T65290 Change-Id: Id1967a83a502f689c40f1af71398c3be99e30640 --- languages/i18n/en.json | 23 +- languages/i18n/qqq.json | 23 +- maintenance/jsduck/categories.json | 3 +- resources/Resources.php | 29 +- .../src/mediawiki/mediawiki.feedback.css | 13 + resources/src/mediawiki/mediawiki.feedback.js | 659 +++++++++++------- resources/src/mediawiki/templates/dialog.html | 25 - 7 files changed, 490 insertions(+), 285 deletions(-) delete mode 100644 resources/src/mediawiki/templates/dialog.html diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 31c766fdb1..7ff3b25ef8 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -3519,19 +3519,28 @@ "newuserlog-autocreate-entry": "Account created automatically", "rightslogentry": "changed group membership for $1 from $2 to $3", "rightslogentry-autopromote": "was automatically promoted from $2 to $3", + "feedback-adding": "Adding feedback to page...", + "feedback-back": "Back", + "feedback-bugcheck": "Great! Just check that it is not already one of the [$1 known bugs].", + "feedback-bugnew": "I checked. Report a new bug", "feedback-bugornote": "If you are ready to describe a technical problem in detail please [$1 report a bug].\nOtherwise, you can use the easy form below. Your comment will be added to the page \"[$3 $2]\", along with your username.", - "feedback-subject": "Subject:", - "feedback-message": "Message:", "feedback-cancel": "Cancel", - "feedback-submit": "Submit Feedback", - "feedback-adding": "Adding feedback to page...", + "feedback-close": "Done", + "feedback-external-bug-report-button": "File a technical task", + "feedback-dialog-title": "Submit feedback", + "feedback-dialog-intro": "You can use the easy form below to submit your feedback. Your comment will be added to the page \"$1\", along with your username.", + "feedback-error-title": "Error", "feedback-error1": "Error: Unrecognized result from API", "feedback-error2": "Error: Edit failed", "feedback-error3": "Error: No response from API", + "feedback-message": "Message:", + "feedback-subject": "Subject:", + "feedback-submit": "Submit", + "feedback-terms": "I understand that my user agent information includes information about my exact browser and operating system version and will be shared publicly alongside my feedback.", + "feedback-termsofuse": "I agree to provide feedback in accordance with the Terms of Use.", "feedback-thanks": "Thanks! Your feedback has been posted to the page \"[$2 $1]\".", - "feedback-close": "Done", - "feedback-bugcheck": "Great! Just check that it is not already one of the [$1 known bugs].", - "feedback-bugnew": "I checked. Report a new bug", + "feedback-thanks-title": "Thank you!", + "feedback-useragent": "User agent:", "searchsuggest-search": "Search", "searchsuggest-containing": "containing...", "api-error-badaccess-groups": "You are not permitted to upload files to this wiki.", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 6253fc986c..3fab94361a 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -3683,19 +3683,28 @@ "newuserlog-autocreate-entry": "This message is used in the [[:mw:Extension:Newuserlog|new user log]] to mark an account that was created by MediaWiki as part of a [[:mw:Extension:CentralAuth|CentralAuth]] global account.", "rightslogentry": "This message is displayed in the [[Special:Log/rights|User Rights Log]] when a bureaucrat changes the user groups for a user.\n\nParameters:\n* $1 - the username\n* $2 - list of user groups or {{msg-mw|Rightsnone}}\n* $3 - list of user groups or {{msg-mw|Rightsnone}}\n\nThe name of the bureaucrat who did this task appears before this message.\n\nSimilar to {{msg-mw|Gur-rightslog-entry}}", "rightslogentry-autopromote": "This message is displayed in the [[Special:Log/rights|User Rights Log]] when a user is automatically promoted to a user group.\n\nParameters:\n* $1 - (Unused)\n* $2 - a comma separated list of old user groups or {{msg-mw|Rightsnone}}\n* $3 - a comma separated list of new user groups", + "feedback-adding": "Progress notice", + "feedback-back": "Button to go back to the previous action in the feedback dialog.", + "feedback-bugcheck": "Message that appears before the user submits a bug, reminding them to check for known bugs.\n\nParameters:\n* $1 - bug list page URL", + "feedback-bugnew": "Button label - asserts that the user has checked for existing bugs. When clicked will launch an external form to add a new bug in a new tab or window", "feedback-bugornote": "When feedback dialog box is opened, this introductory message in small print explains the options to report a bug or add simple feedback.\n\nWe expect that people in a hurry will not read this.\n\nParameters:\n* $1 - Bug note URL\n* $2 - \"Feedback\"\n* $3 - Feedback page URL", - "feedback-subject": "Label for a text input\n{{Identical|Subject}}", - "feedback-message": "Label for a textarea; signature referrs to a Wikitext signature.\n{{Identical|Message}}", + "feedback-external-bug-report-button": "A button for submitting an external technical bug report.", "feedback-cancel": "Button label\n{{Identical|Cancel}}", - "feedback-submit": "Button label\n{{Identical|Submit}}", - "feedback-adding": "Progress notice", + "feedback-close": "Button label\n{{Identical|Done}}", + "feedback-dialog-title": "Title of the feedback dialog", "feedback-error1": "Error message, appears when an unknown error occurs submitting feedback", "feedback-error2": "Error message, appears when we could not add feedback", "feedback-error3": "Error message, appears when we lose our connection to the wiki", + "feedback-dialog-intro": "An introduction at the top of the feedback dialog. $1 - Feedback page link", + "feedback-message": "Label for a textarea; signature refers to a Wikitext signature.\n{{Identical|Message}}", + "feedback-subject": "Label for a text input\n{{Identical|Subject}}", + "feedback-submit": "Button label\n{{Identical|Submit}}", + "feedback-terms": "Label for a checkbox asking for permissions to submit browser information.", + "feedback-termsofuse": "Label with an agreement about the terms of use.", "feedback-thanks": "Thanks message, appears if feedback was successful. Parameters:\n* $1 - \"Feedback\"\n* $2 - Feedback page URL", - "feedback-close": "Button label\n{{Identical|Done}}", - "feedback-bugcheck": "Message that appears before the user submits a bug, reminding them to check for known bugs.\n\nParameters:\n* $1 - bug list page URL", - "feedback-bugnew": "Button label - asserts that the user has checked for existing bugs. When clicked will launch a bugzilla form to add a new bug in a new tab or window", + "feedback-thanks-title": "The title of the message dialog at the end of the submission process that shows error in submitting the feedback.", + "feedback-thanks-title": "The title of the thank you dialog at the end of the submission process.", + "feedback-useragent": "A label denoting the user agent in the feedback that is posted to the feedback page.", "searchsuggest-search": "Greyed out default text in the simple search box in the Vector skin. (It disappears and lets the user enter the requested search terms when the search box receives focus.)\n\n{{Identical|Search}}", "searchsuggest-containing": "Label used in the special item of the search suggestions list which gives the user an option to perform a full text search for the term.", "api-error-badaccess-groups": "API error message that can be used for client side localisation of API errors.", diff --git a/maintenance/jsduck/categories.json b/maintenance/jsduck/categories.json index 145905fdec..c0d04998a7 100644 --- a/maintenance/jsduck/categories.json +++ b/maintenance/jsduck/categories.json @@ -55,7 +55,8 @@ { "name": "Interfaces", "classes": [ - "mw.Feedback" + "mw.Feedback", + "mw.Feedback.Dialog" ] }, { diff --git a/resources/Resources.php b/resources/Resources.php index 965c78330a..a9f383ce4a 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -856,31 +856,36 @@ return array( 'position' => 'bottom', ), 'mediawiki.feedback' => array( - 'templates' => array( - 'dialog.html' => 'resources/src/mediawiki/templates/dialog.html', - ), 'scripts' => 'resources/src/mediawiki/mediawiki.feedback.js', 'styles' => 'resources/src/mediawiki/mediawiki.feedback.css', 'dependencies' => array( 'mediawiki.api.edit', 'mediawiki.Title', - 'mediawiki.jqueryMsg', - 'jquery.ui.dialog', + 'oojs-ui', ), 'messages' => array( + 'feedback-adding', + 'feedback-back', + 'feedback-bugcheck', + 'feedback-dialog-intro', + 'feedback-external-bug-report-button', + 'feedback-bugnew', 'feedback-bugornote', - 'feedback-subject', - 'feedback-message', 'feedback-cancel', - 'feedback-submit', - 'feedback-adding', + 'feedback-close', + 'feedback-dialog-title', + 'feedback-error-title', 'feedback-error1', 'feedback-error2', 'feedback-error3', + 'feedback-message', + 'feedback-subject', + 'feedback-submit', + 'feedback-terms', + 'feedback-termsofuse', 'feedback-thanks', - 'feedback-close', - 'feedback-bugcheck', - 'feedback-bugnew', + 'feedback-thanks-title', + 'feedback-useragent' ), ), 'mediawiki.hidpi' => array( diff --git a/resources/src/mediawiki/mediawiki.feedback.css b/resources/src/mediawiki/mediawiki.feedback.css index 6bd47bb20e..f2859db3c8 100644 --- a/resources/src/mediawiki/mediawiki.feedback.css +++ b/resources/src/mediawiki/mediawiki.feedback.css @@ -7,3 +7,16 @@ width: 18px; height: 18px; } + +.mw-feedbackDialog-welcome-message, +.mw-feedbackDialog-feedback-terms { + line-height: 1.2em; +} + +.mw-feedbackDialog-feedback-form { + margin-top: 1em; +} + +.mw-feedbackDialog-feedback-termsofuse { + margin-left: 2.5em; +} diff --git a/resources/src/mediawiki/mediawiki.feedback.js b/resources/src/mediawiki/mediawiki.feedback.js index 867134c3ef..da172225c3 100644 --- a/resources/src/mediawiki/mediawiki.feedback.js +++ b/resources/src/mediawiki/mediawiki.feedback.js @@ -3,8 +3,11 @@ * * @author Ryan Kaldari, 2010 * @author Neil Kandalgaonkar, 2010-11 + * @author Moriel Schottlender, 2015 * @since 1.19 */ +/*jshint es3:false */ +/*global OO*/ ( function ( mw, $ ) { /** * This is a way of getting simple feedback from users. It's useful @@ -32,263 +35,453 @@ * * @class * @constructor - * @param {Object} [options] - * @param {mw.Api} [options.api] if omitted, will just create a standard API - * @param {mw.Title} [options.title="Feedback"] The title of the page where you collect - * feedback. - * @param {string} [options.dialogTitleMessageKey="feedback-submit"] Message key for the - * title of the dialog box - * @param {string} [options.bugsLink="//bugzilla.wikimedia.org/enter_bug.cgi"] URL where - * bugs can be posted - * @param {mw.Uri|string} [options.bugsListLink="//bugzilla.wikimedia.org/query.cgi"] - * URL where bugs can be listed + * @param {Object} [config] Configuration object + * @cfg {mw.Api} [api] if omitted, will just create a standard API + * @cfg {mw.Title} [title="Feedback"] The title of the page where you collect + * feedback. + * @cfg {string} [dialogTitleMessageKey="feedback-dialog-title"] Message key for the + * title of the dialog box + * @cfg {mw.Uri|string} [bugsLink="//phabricator.wikimedia.org/maniphest/task/create/"] URL where + * bugs can be posted + * @cfg {mw.Uri|string} [bugsListLink="//phabricator.wikimedia.org/maniphest/query/advanced"] URL + * where bugs can be listed + * @cfg {boolean} [showUseragentCheckbox=false] Show a Useragent agreement checkbox as part of the form. + * @cfg {boolean} [useragentCheckboxMandatory=false] Make the Useragent checkbox mandatory. + * @cfg {string|jQuery} [useragentCheckboxMessage] Supply a custom message for the useragent checkbox. + * defaults to a combination of 'feedback-terms' and 'feedback-termsofuse' which includes a link to the + * wiki's Term of Use page. */ - mw.Feedback = function ( options ) { - if ( options === undefined ) { - options = {}; - } + mw.Feedback = function MwFeedback( config ) { + config = config || {}; - if ( options.api === undefined ) { - options.api = new mw.Api(); - } + this.api = config.api || new mw.Api(); + this.dialogTitleMessageKey = config.dialogTitleMessageKey || 'feedback-dialog-title'; - if ( options.title === undefined ) { - options.title = new mw.Title( 'Feedback' ); - } + // Feedback page title + this.feedbackPageTitle = config.title || new mw.Title( 'Feedback' ); - if ( options.dialogTitleMessageKey === undefined ) { - options.dialogTitleMessageKey = 'feedback-submit'; - } + // Links + this.bugsTaskSubmissionLink = config.bugsLink || '//phabricator.wikimedia.org/maniphest/task/create/'; + this.bugsTaskListLink = config.bugsListLink || '//phabricator.wikimedia.org/maniphest/query/advanced'; - if ( options.bugsLink === undefined ) { - options.bugsLink = '//bugzilla.wikimedia.org/enter_bug.cgi'; - } + // Terms of use + this.useragentCheckboxShow = !!config.showUseragentCheckbox; + this.useragentCheckboxMandatory = !!config.useragentCheckboxMandatory; + this.useragentCheckboxMessage = config.useragentCheckboxMessage || + $( '

' ) + .append( mw.msg( 'feedback-terms' ) ) + .add( $( '

' ).append( mw.message( 'feedback-termsofuse' ).parse() ) ); + + // Message dialog + this.thankYouDialog = new OO.ui.MessageDialog(); + }; + + /* Initialize */ + OO.initClass( mw.Feedback ); + + /* Static Properties */ + mw.Feedback.static.windowManager = null; + mw.Feedback.static.dialog = null; + + /* Methods */ - if ( options.bugsListLink === undefined ) { - options.bugsListLink = '//bugzilla.wikimedia.org/query.cgi'; + /** + * Respond to dialog submit event. If the information was + * submitted, either successfully or with an error, open + * a MessageDialog to thank the user. + * @param {string} [status] A status of the end of operation + * of the main feedback dialog. Empty if the dialog was + * dismissed with no action or the user followed the button + * to the external task reporting site. + */ + mw.Feedback.prototype.onDialogSubmit = function ( status ) { + var dialogConfig = {}; + switch ( status ) { + case 'submitted': + dialogConfig = { + title: mw.msg( 'feedback-thanks-title' ), + message: $( '' ).append( + mw.message( + 'feedback-thanks', + this.feedbackPageTitle.getNameText(), + $( '' ) + .attr( { + target: '_blank', + href: this.feedbackPageTitle.getUrl() + } ) + ).parse() + ), + actions: [ + { + action: 'accept', + label: mw.msg( 'feedback-close' ), + flags: 'primary' + } + ] + }; + break; + case 'error1': + case 'error2': + case 'error3': + dialogConfig = { + title: mw.msg( 'feedback-error-title' ), + message: mw.msg( 'feedback-' + status ), + actions: [ + { + action: 'accept', + label: mw.msg( 'feedback-close' ), + flags: 'primary' + } + ] + }; + break; } - $.extend( this, options ); - this.setup(); + // Show the message dialog + if ( !$.isEmptyObject( dialogConfig ) ) { + this.constructor.static.windowManager.openWindow( + this.thankYouDialog, + dialogConfig + ); + } }; - mw.Feedback.prototype = { - /** - * Sets up interface - */ - setup: function () { - var $feedbackPageLink, - $bugNoteLink, - $bugsListLink, - fb = this; - - $feedbackPageLink = $( '' ) - .attr( { - href: fb.title.getUrl(), - target: '_blank' - } ) - .css( { - whiteSpace: 'nowrap' - } ); + /** + * Modify the display form, and then open it, focusing interface on the subject. + * + * @param {Object} [contents] Prefilled contents for the feedback form. + * @param {string} [contents.subject] The subject of the feedback + * @param {string} [contents.message] The content of the feedback + */ + mw.Feedback.prototype.launch = function ( contents ) { + // Dialog + if ( !this.constructor.static.dialog ) { + this.constructor.static.dialog = new mw.Feedback.Dialog(); + this.constructor.static.dialog.connect( this, { submit: 'onDialogSubmit' } ); + } + if ( !this.constructor.static.windowManager ) { + this.constructor.static.windowManager = new OO.ui.WindowManager(); + this.constructor.static.windowManager.addWindows( [ + this.constructor.static.dialog, + this.thankYouDialog + ] ); + $( 'body' ) + .append( this.constructor.static.windowManager.$element ); + } + // Open the dialog + this.constructor.static.windowManager.openWindow( + this.constructor.static.dialog, + { + title: mw.msg( this.dialogTitleMessageKey ), + settings: { + api: this.api, + title: this.feedbackPageTitle, + dialogTitleMessageKey: this.dialogTitleMessageKey, + bugsTaskSubmissionLink: this.bugsTaskSubmissionLink, + bugsTaskListLink: this.bugsTaskListLink, + useragentCheckbox: { + show: this.useragentCheckboxShow, + mandatory: this.useragentCheckboxMandatory, + message: this.useragentCheckboxMessage + } + }, + contents: contents + } + ); + }; - $bugNoteLink = $( '' ).attr( { href: '#' } ).click( function () { - fb.displayBugs(); - } ); - - $bugsListLink = $( '' ).attr( { - href: fb.bugsListLink, - target: '_blank' - } ); - - // TODO: Use a stylesheet instead of these inline styles in the template - this.$dialog = mw.template.get( 'mediawiki.feedback', 'dialog.html' ).render(); - this.$dialog.find( '.feedback-mode small p' ).msg( - 'feedback-bugornote', - $bugNoteLink, - fb.title.getNameText(), - $feedbackPageLink.clone() - ); - this.$dialog.find( '.feedback-form .subject span' ).msg( 'feedback-subject' ); - this.$dialog.find( '.feedback-form .message span' ).msg( 'feedback-message' ); - this.$dialog.find( '.feedback-bugs p' ).msg( 'feedback-bugcheck', $bugsListLink ); - this.$dialog.find( '.feedback-submitting span' ).msg( 'feedback-adding' ); - this.$dialog.find( '.feedback-thanks' ).msg( 'feedback-thanks', fb.title.getNameText(), - $feedbackPageLink.clone() ); - - this.$dialog.dialog( { - width: 500, - autoOpen: false, - title: mw.message( this.dialogTitleMessageKey ).escaped(), - modal: true, - buttons: fb.buttons - } ); - - this.subjectInput = this.$dialog.find( 'input.feedback-subject' ).get( 0 ); - this.messageInput = this.$dialog.find( 'textarea.feedback-message' ).get( 0 ); - }, + /** + * mw.Feedback Dialog + * + * @class + * @extends OO.ui.ProcessDialog + * + * @constructor + * @param {Object} config Configuration object + */ + mw.Feedback.Dialog = function mwFeedbackDialog( config ) { + // Parent constructor + mw.Feedback.Dialog.super.call( this, config ); + + this.status = ''; + this.feedbackPageTitle = null; + // Initialize + this.$element.addClass( 'mwFeedback-Dialog' ); + }; - /** - * Displays a section of the dialog. - * - * @param {"form"|"bugs"|"submitting"|"thanks"|"error"} s - * The section of the dialog to show. - */ - display: function ( s ) { - // Hide the buttons - this.$dialog.dialog( { buttons: {} } ); - // Hide everything - this.$dialog.find( '.feedback-mode' ).hide(); - // Show the desired div - this.$dialog.find( '.feedback-' + s ).show(); + OO.inheritClass( mw.Feedback.Dialog, OO.ui.ProcessDialog ); + + /* Static properties */ + mw.Feedback.Dialog.static.name = 'mwFeedbackDialog'; + mw.Feedback.Dialog.static.title = mw.msg( 'feedback-dialog-title' ); + mw.Feedback.Dialog.static.size = 'medium'; + mw.Feedback.Dialog.static.actions = [ + { + action: 'submit', + label: mw.msg( 'feedback-submit' ), + flags: [ 'primary', 'constructive' ] }, - - /** - * Display the submitting section. - */ - displaySubmitting: function () { - this.display( 'submitting' ); + { + action: 'external', + label: mw.msg( 'feedback-external-bug-report-button' ), + flags: 'constructive' }, + { + action: 'cancel', + label: mw.msg( 'feedback-cancel' ), + flags: 'safe' + } + ]; - /** - * Display the bugs section. - */ - displayBugs: function () { - var fb = this, - bugsButtons = {}; - - this.display( 'bugs' ); - bugsButtons[ mw.msg( 'feedback-bugnew' ) ] = function () { - window.open( fb.bugsLink, '_blank' ); - }; - bugsButtons[ mw.msg( 'feedback-cancel' ) ] = function () { - fb.cancel(); - }; - this.$dialog.dialog( { - buttons: bugsButtons - } ); - }, + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.initialize = function () { + var feedbackSubjectFieldLayout, feedbackMessageFieldLayout, + feedbackFieldsetLayout; + + // Parent method + mw.Feedback.Dialog.super.prototype.initialize.call( this ); + + this.feedbackPanel = new OO.ui.PanelLayout( { + scrollable: false, + expanded: false, + padded: true + } ); + + this.$spinner = $( '

' ) + .addClass( 'feedback-spinner' ); + + // Feedback form + this.feedbackMessageLabel = new OO.ui.LabelWidget( { + classes: [ 'mw-feedbackDialog-welcome-message' ] + } ); + this.feedbackSubjectInput = new OO.ui.TextInputWidget( { + multiline: false + } ); + this.feedbackMessageInput = new OO.ui.TextInputWidget( { + multiline: true + } ); + feedbackSubjectFieldLayout = new OO.ui.FieldLayout( this.feedbackSubjectInput, { + label: mw.msg( 'feedback-subject' ) + } ); + feedbackMessageFieldLayout = new OO.ui.FieldLayout( this.feedbackMessageInput, { + label: mw.msg( 'feedback-message' ) + } ); + feedbackFieldsetLayout = new OO.ui.FieldsetLayout( { + items: [ feedbackSubjectFieldLayout, feedbackMessageFieldLayout ], + classes: [ 'mw-feedbackDialog-feedback-form' ] + } ); + + // Useragent terms of use + this.useragentCheckbox = new OO.ui.CheckboxInputWidget(); + this.useragentFieldLayout = new OO.ui.FieldLayout( this.useragentCheckbox, { + classes: [ 'mw-feedbackDialog-feedback-terms' ], + align: 'inline' + } ); + + this.feedbackPanel.$element.append( + this.feedbackMessageLabel.$element, + feedbackFieldsetLayout.$element, + this.useragentFieldLayout.$element + ); + + // Events + this.feedbackSubjectInput.connect( this, { change: 'validateFeedbackForm' } ); + this.feedbackMessageInput.connect( this, { change: 'validateFeedbackForm' } ); + this.useragentCheckbox.connect( this, { change: 'validateFeedbackForm' } ); + + this.$body.append( this.feedbackPanel.$element ); + }; - /** - * Display the thanks section. - */ - displayThanks: function () { - var fb = this, - closeButton = {}; - - this.display( 'thanks' ); - closeButton[ mw.msg( 'feedback-close' ) ] = function () { - fb.$dialog.dialog( 'close' ); - }; - this.$dialog.dialog( { - buttons: closeButton - } ); - }, + /** + * Validate the feedback form + */ + mw.Feedback.Dialog.prototype.validateFeedbackForm = function () { + var isValid = ( + ( + !this.useragentMandatory || + this.useragentCheckbox.isSelected() + ) && + ( + !!this.feedbackMessageInput.getValue() || + !!this.feedbackSubjectInput.getValue() + ) + ); - /** - * Display the feedback form - * @param {Object} [contents] Prefilled contents for the feedback form. - * @param {string} [contents.subject] The subject of the feedback - * @param {string} [contents.message] The content of the feedback - */ - displayForm: function ( contents ) { - var fb = this, - formButtons = {}; - - this.subjectInput.value = ( contents && contents.subject ) ? contents.subject : ''; - this.messageInput.value = ( contents && contents.message ) ? contents.message : ''; - - this.display( 'form' ); - - // Set up buttons for dialog box. We have to do it the hard way since the json keys are localized - formButtons[ mw.msg( 'feedback-submit' ) ] = function () { - fb.submit(); - }; - formButtons[ mw.msg( 'feedback-cancel' ) ] = function () { - fb.cancel(); - }; - this.$dialog.dialog( { buttons: formButtons } ); // put the buttons back - }, + this.actions.setAbilities( { submit: isValid } ); + }; - /** - * Display an error on the form. - * - * @param {string} message Should be a valid message key. - */ - displayError: function ( message ) { - var fb = this, - closeButton = {}; - - this.display( 'error' ); - this.$dialog.find( '.feedback-error-msg' ).msg( message ); - closeButton[ mw.msg( 'feedback-close' ) ] = function () { - fb.$dialog.dialog( 'close' ); - }; - this.$dialog.dialog( { buttons: closeButton } ); - }, + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.getBodyHeight = function () { + return this.feedbackPanel.$element.outerHeight( true ); + }; - /** - * Close the feedback form. - */ - cancel: function () { - this.$dialog.dialog( 'close' ); - }, + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.getSetupProcess = function ( data ) { + return mw.Feedback.Dialog.super.prototype.getSetupProcess.call( this, data ) + .next( function () { + var plainMsg, parsedMsg, + settings = data.settings; + data.contents = data.contents || {}; + + // Prefill subject/message + this.feedbackSubjectInput.setValue( data.contents.subject ); + this.feedbackMessageInput.setValue( data.contents.message ); + + this.status = ''; + this.api = settings.api; + this.setBugReportLink( settings.bugsTaskSubmissionLink ); + this.feedbackPageTitle = settings.title; + this.feedbackPageName = settings.title.getNameText(); + this.feedbackPageUrl = settings.title.getUrl(); + + // Useragent checkbox + if ( settings.useragentCheckbox.show ) { + this.useragentFieldLayout.setLabel( settings.useragentCheckbox.message ); + } + this.useragentMandatory = settings.useragentCheckbox.mandatory; + this.useragentFieldLayout.toggle( settings.useragentCheckbox.show ); + + // HACK: Setting a link in the messages doesn't work. There is already a report + // about this, and the bug report offers a somewhat hacky work around that + // includes setting a separate message to be parsed. + // We want to make sure the user can configure both the title of the page and + // a separate url, so this must be allowed to parse correctly. + // See https://phabricator.wikimedia.org/T49395#490610 + mw.messages.set( { + 'feedback-dialog-temporary-message': + '' + this.feedbackPageName + '' + } ); + plainMsg = mw.message( 'feedback-dialog-temporary-message' ).plain(); + mw.messages.set( { 'feedback-dialog-temporary-message-parsed': plainMsg } ); + parsedMsg = mw.message( 'feedback-dialog-temporary-message-parsed' ); + this.feedbackMessageLabel.setLabel( + // Double-parse + $( '' ) + .append( mw.message( 'feedback-dialog-intro', parsedMsg ).parse() ) + ); + + this.validateFeedbackForm(); + }, this ); + }; - /** - * Submit the feedback form. - */ - submit: function () { - var subject, message, - fb = this; - - // Get the values to submit. - subject = $.trim( this.subjectInput.value ); - - // We used to include "mw.html.escape( navigator.userAgent )" but there are legal issues - // with posting this without their explicit consent - message = $.trim( this.messageInput.value ); - if ( message.indexOf( '~~~' ) === -1 ) { - message += ' ~~~~'; - } + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.getReadyProcess = function ( data ) { + return mw.Feedback.Dialog.super.prototype.getReadyProcess.call( this, data ) + .next( function () { + this.feedbackSubjectInput.focus(); + }, this ); + }; - this.displaySubmitting(); - - // Post the message, resolving redirects - this.api.newSection( - this.title, - subject, - message, - { redirect: true } - ) - .done( function ( result ) { - if ( result.edit.result === 'Success' ) { - fb.displayThanks(); - } else { - // unknown API result - fb.displayError( 'feedback-error1' ); + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.getActionProcess = function ( action ) { + if ( action === 'cancel' ) { + return new OO.ui.Process( function () { + this.close( { action: action } ); + }, this ); + } else if ( action === 'external' ) { + return new OO.ui.Process( function () { + // Open in a new window + window.open( this.getBugReportLink(), '_blank' ); + // Close the dialog + this.close(); + }, this ); + } else if ( action === 'submit' ) { + return new OO.ui.Process( function () { + var fb = this, + userAgentMessage = ':' + + '' + + mw.msg( 'feedback-useragent' ) + + ' ' + + mw.html.escape( navigator.userAgent ) + + '\n\n', + subject = this.feedbackSubjectInput.getValue(), + message = this.feedbackMessageInput.getValue(); + + // Add user agent if checkbox is selected + if ( this.useragentCheckbox.isSelected() ) { + message = userAgentMessage + message; } - } ) - .fail( function ( code, result ) { - if ( code === 'http' ) { - // ajax request failed - fb.displayError( 'feedback-error3' ); - mw.log.warn( 'Feedback report failed with HTTP error: ' + result.textStatus ); - } else { - fb.displayError( 'feedback-error2' ); - mw.log.warn( 'Feedback report failed with API error: ' + code ); + + // Add signature if needed + if ( message.indexOf( '~~~' ) === -1 ) { + message += '\n\n~~~~'; } - } ); - }, - /** - * Modify the display form, and then open it, focusing interface on the subject. - * @param {Object} [contents] Prefilled contents for the feedback form. - * @param {string} [contents.subject] The subject of the feedback - * @param {string} [contents.message] The content of the feedback - */ - launch: function ( contents ) { - this.displayForm( contents ); - this.$dialog.dialog( 'open' ); - this.subjectInput.focus(); + // Post the message, resolving redirects + this.pushPending(); + this.api.newSection( + this.feedbackPageTitle, + subject, + message, + { redirect: true } + ) + .done( function ( result ) { + if ( result.edit.result === 'Success' ) { + fb.status = 'submitted'; + } else { + fb.status = 'error1'; + } + fb.popPending(); + fb.close(); + } ) + .fail( function ( code, result ) { + if ( code === 'http' ) { + fb.status = 'error3'; + // ajax request failed + mw.log.warn( 'Feedback report failed with HTTP error: ' + result.textStatus ); + } else { + fb.status = 'error2'; + mw.log.warn( 'Feedback report failed with API error: ' + code ); + } + fb.popPending(); + fb.close(); + } ); + }, this ); } + // Fallback to parent handler + return mw.Feedback.Dialog.super.prototype.getActionProcess.call( this, action ); + }; + + /** + * @inheritdoc + */ + mw.Feedback.Dialog.prototype.getTeardownProcess = function ( data ) { + return mw.Feedback.Dialog.super.prototype.getTeardownProcess.call( this, data ) + .first( function () { + this.emit( 'submit', this.status, this.feedbackPageName, this.feedbackPageUrl ); + // Cleanup + this.status = ''; + this.feedbackPageTitle = null; + this.feedbackSubjectInput.setValue( '' ); + this.feedbackMessageInput.setValue( '' ); + this.useragentCheckbox.setSelected( false ); + }, this ); }; + + /** + * Set the bug report link + * @param {string} link Link to the external bug report form + */ + mw.Feedback.Dialog.prototype.setBugReportLink = function ( link ) { + this.bugReportLink = link; + }; + + /** + * Get the bug report link + * @returns {string} Link to the external bug report form + */ + mw.Feedback.Dialog.prototype.getBugReportLink = function () { + return this.bugReportLink; + }; + }( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki/templates/dialog.html b/resources/src/mediawiki/templates/dialog.html deleted file mode 100644 index e116f3eecf..0000000000 --- a/resources/src/mediawiki/templates/dialog.html +++ /dev/null @@ -1,25 +0,0 @@ -
- - - - - -
-- 2.20.1