jenkins-bot has submitted this change and it was merged.

Change subject: Refactoring mw.Feedback to work with OOUI elements
......................................................................


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
---
M languages/i18n/en.json
M languages/i18n/qqq.json
M maintenance/jsduck/categories.json
M resources/Resources.php
M resources/src/mediawiki/mediawiki.feedback.css
M resources/src/mediawiki/mediawiki.feedback.js
D resources/src/mediawiki/templates/dialog.html
7 files changed, 504 insertions(+), 299 deletions(-)

Approvals:
  Jforrester: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index 31c766f..7ff3b25 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-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-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-cancel": "Cancel",
+       "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 6253fc9..3fab943 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-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-cancel": "Button label\n{{Identical|Cancel}}",
-       "feedback-submit": "Button label\n{{Identical|Submit}}",
        "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-external-bug-report-button": "A button for submitting an 
external technical bug report.",
+       "feedback-cancel": "Button label\n{{Identical|Cancel}}",
+       "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 145905f..c0d0499 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 965c783..a9f383c 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -856,31 +856,36 @@
                '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-bugornote',
-                       'feedback-subject',
-                       'feedback-message',
-                       'feedback-cancel',
-                       'feedback-submit',
                        'feedback-adding',
+                       'feedback-back',
+                       'feedback-bugcheck',
+                       'feedback-dialog-intro',
+                       'feedback-external-bug-report-button',
+                       'feedback-bugnew',
+                       'feedback-bugornote',
+                       'feedback-cancel',
+                       '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 6bd47bb..f2859db 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 867134c..da17222 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 
||
+                       $( '<p>' )
+                               .append( mw.msg( 'feedback-terms' ) )
+                               .add( $( '<p>' ).append( mw.message( 
'feedback-termsofuse' ).parse() ) );
 
-               if ( options.bugsListLink === undefined ) {
-                       options.bugsListLink = 
'//bugzilla.wikimedia.org/query.cgi';
-               }
-
-               $.extend( this, options );
-               this.setup();
+               // Message dialog
+               this.thankYouDialog = new OO.ui.MessageDialog();
        };
 
-       mw.Feedback.prototype = {
-               /**
-                * Sets up interface
-                */
-               setup: function () {
-                       var $feedbackPageLink,
-                               $bugNoteLink,
-                               $bugsListLink,
-                               fb = this;
+       /* Initialize */
+       OO.initClass( mw.Feedback );
 
-                       $feedbackPageLink = $( '<a>' )
-                               .attr( {
-                                       href: fb.title.getUrl(),
-                                       target: '_blank'
-                               } )
-                               .css( {
-                                       whiteSpace: 'nowrap'
-                               } );
+       /* Static Properties */
+       mw.Feedback.static.windowManager = null;
+       mw.Feedback.static.dialog = null;
 
-                       $bugNoteLink = $( '<a>' ).attr( { href: '#' } ).click( 
function () {
-                               fb.displayBugs();
-                       } );
+       /* Methods */
 
-                       $bugsListLink = $( '<a>' ).attr( {
-                               href: fb.bugsListLink,
-                               target: '_blank'
-                       } );
+       /**
+        * 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: $( '<span>' ).append(
+                                               mw.message(
+                                                       'feedback-thanks',
+                                                       
this.feedbackPageTitle.getNameText(),
+                                                       $( '<a>' )
+                                                               .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;
+               }
 
-                       // 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()
+               // Show the message dialog
+               if ( !$.isEmptyObject( dialogConfig ) ) {
+                       this.constructor.static.windowManager.openWindow(
+                               this.thankYouDialog,
+                               dialogConfig
                        );
-                       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 );
-               },
-
-               /**
-                * 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();
-               },
-
-               /**
-                * Display the submitting section.
-                */
-               displaySubmitting: function () {
-                       this.display( 'submitting' );
-               },
-
-               /**
-                * 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
-                       } );
-               },
-
-               /**
-                * 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
-                       } );
-               },
-
-               /**
-                * 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
-               },
-
-               /**
-                * 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 } );
-               },
-
-               /**
-                * Close the feedback form.
-                */
-               cancel: function () {
-                       this.$dialog.dialog( 'close' );
-               },
-
-               /**
-                * 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 += ' ~~~~';
-                       }
-
-                       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' );
-                               }
-                       } )
-                       .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 );
-                               }
-                       } );
-               },
-
-               /**
-                * 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();
                }
        };
+
+       /**
+        * 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
+                       }
+               );
+       };
+
+       /**
+        * 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' );
+       };
+
+       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' ]
+               },
+               {
+                       action: 'external',
+                       label: mw.msg( 'feedback-external-bug-report-button' ),
+                       flags: 'constructive'
+               },
+               {
+                       action: 'cancel',
+                       label: mw.msg( 'feedback-cancel' ),
+                       flags: 'safe'
+               }
+       ];
+
+       /**
+        * @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 = $( '<div>' )
+                       .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 );
+       };
+
+       /**
+        * Validate the feedback form
+        */
+       mw.Feedback.Dialog.prototype.validateFeedbackForm = function () {
+               var isValid = (
+                               (
+                                       !this.useragentMandatory ||
+                                       this.useragentCheckbox.isSelected()
+                               ) &&
+                               (
+                                       !!this.feedbackMessageInput.getValue() 
||
+                                       !!this.feedbackSubjectInput.getValue()
+                               )
+                       );
+
+               this.actions.setAbilities( { submit:  isValid } );
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.Feedback.Dialog.prototype.getBodyHeight = function () {
+               return this.feedbackPanel.$element.outerHeight( true );
+       };
+
+       /**
+        * @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':
+                                               '<a href="' + 
this.feedbackPageUrl + '" target="_blank">' + this.feedbackPageName + '</a>'
+                               } );
+                               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
+                                       $( '<span>' )
+                                               .append( mw.message( 
'feedback-dialog-intro', parsedMsg ).parse() )
+                               );
+
+                               this.validateFeedbackForm();
+                       }, this );
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.Feedback.Dialog.prototype.getReadyProcess = function ( data ) {
+               return mw.Feedback.Dialog.super.prototype.getReadyProcess.call( 
this, data )
+                       .next( function () {
+                               this.feedbackSubjectInput.focus();
+                       }, this );
+       };
+
+       /**
+        * @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 = ':' +
+                                               '<small>' +
+                                               mw.msg( 'feedback-useragent' ) +
+                                               ' ' +
+                                               mw.html.escape( 
navigator.userAgent ) +
+                                               '</small>\n\n',
+                                       subject = 
this.feedbackSubjectInput.getValue(),
+                                       message = 
this.feedbackMessageInput.getValue();
+
+                               // Add user agent if checkbox is selected
+                               if ( this.useragentCheckbox.isSelected() ) {
+                                       message = userAgentMessage + message;
+                               }
+
+                               // Add signature if needed
+                               if ( message.indexOf( '~~~' ) === -1 ) {
+                                       message += '\n\n~~~~';
+                               }
+
+                               // 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 e116f3e..0000000
--- a/resources/src/mediawiki/templates/dialog.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<div style="position: relative; display: block;" class="ui-dialog-content 
ui-widget-content">
-       <div class="feedback-mode feedback-form">
-               <small><p></p></small>
-               <div class="subject" style="margin-top: 1em;">
-                       <span></span><br>
-                       <input type="text" class="feedback-subject" 
name="subject" maxlength="60"
-                               style="width: 100%; -moz-box-sizing: 
border-box; -webkit-box-sizing: border-box; box-sizing: border-box;">
-               </div>
-               <div class="message" style="margin-top: 0.4em;">
-                       <span></span><br>
-                       <textarea name="message" class="feedback-message" 
rows="5" cols="60"></textarea>
-               </div>
-       </div>
-       <div class="feedback-mode feedback-bugs">
-               <p></p>
-       </div>
-       <div class="feedback-mode feedback-submitting" style="text-align: 
center; margin: 3em 0;">
-               <span></span><br>
-               <span class="feedback-spinner"></span>
-       </div>
-       <div class="feedback-mode feedback-thanks" style="text-align: center; 
margin:1em"></div>
-       <div class="feedback-mode feedback-error" style="position: relative;">
-               <div class="feedback-error-msg" style=" color:#990000; 
margin-top:0.4em;"></div>
-       </div>
-</div>

-- 
To view, visit https://gerrit.wikimedia.org/r/192749
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id1967a83a502f689c40f1af71398c3be99e30640
Gerrit-PatchSet: 13
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Mooeypoo <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jack Phoenix <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: Mooeypoo <[email protected]>
Gerrit-Reviewer: Ricordisamoa <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to