Robert Vogel has submitted this change and it was merged. Change subject: [WIP] Question dialog and API tests ......................................................................
[WIP] Question dialog and API tests * Question dialog improvements * Proof of concept implementation of "save" functionality TODO: * Improve validation * Move "save" functionality out of dialog implementation Change-Id: Ia3c4dc5aeed4c30a02e48c9fce79aecef29f2462 --- M Teahouse.php M gadgetize.json M i18n/de.json M i18n/en.json M i18n/qqq.json M resources/mediawiki.teahouse.css M resources/mediawiki.teahouse.dialog.js M resources/mediawiki.teahouse.gadget.development.js M resources/mediawiki.teahouse.js M resources/ui/dialogs/th.ui.QuestionDialog.js 10 files changed, 292 insertions(+), 73 deletions(-) Approvals: Robert Vogel: Verified; Looks good to me, approved diff --git a/Teahouse.php b/Teahouse.php index b55d790..bab9afc 100644 --- a/Teahouse.php +++ b/Teahouse.php @@ -25,7 +25,7 @@ 'author' => array( 'Robert Vogel' ), - //'url' => 'https://www.mediawiki.org/wiki/Extension:Teahouse', + 'url' => 'https://www.mediawiki.org/wiki/Extension:Teahouse', 'description' => '', 'version' => 1.24 ); @@ -35,21 +35,14 @@ $wgResourceModules['ext.teahouse'] = array( 'scripts' => array( 'mediawiki.teahouse.js', + 'mediawiki.teahouse.board.js', + 'mediawiki.teahouse.notifications.js', 'mediawiki.teahouse.dialog.js', //'mediawiki.teahouse.gadget.js', 'mediawiki.teahouse.gadget.development.js' ), 'styles' => array( 'mediawiki.teahouse.css' - ), - 'messages' => array( - 'th-button-text', - 'th-dialog-title', - 'th-dialog-description-top', - 'th-dialog-label-summary', - 'th-dialog-label-text', - 'th-dialog-btn-ok', - 'th-dialog-btn-cancel', ), 'localBasePath' => __DIR__.'/resources', 'remoteExtPath' => 'Teahouse/resources', diff --git a/gadgetize.json b/gadgetize.json index e903531..08b15a9 100644 --- a/gadgetize.json +++ b/gadgetize.json @@ -3,6 +3,8 @@ "MediaWiki:Gadget-teahouse/main.js": [ "resources/mediawiki.teahouse.js", + "resources/mediawiki.teahouse.notifications.js", + "resources/mediawiki.teahouse.board.js", "resources/mediawiki.teahouse.dialog.js", "resources/mediawiki.teahouse.gadget.js" ], @@ -15,8 +17,9 @@ "resources/mediawiki.teahouse.css" ], - "Template:Pending_Question": [ "assets/Template_Pending_Questions.wiki" ], - "Template:Answered_Question": [ "assets/Template_Answered_Questions.wiki" ], + "Template:Teahouse/Pending_Question": [ "assets/Template_Pending_Questions.wiki" ], + "Template:Teahouse/Answered_Question": [ "assets/Template_Answered_Questions.wiki" ], + "Template:Teahouse/Question_ListItem": [ "assets/Template_Answered_Questions.wiki" ], "Module:Teahouse_Questions": [ "assets/Module_Teahouse_Questions.lua" ], "Help:Teahouse": [ "assets/Help_Teahouse.wiki" ] } \ No newline at end of file diff --git a/i18n/de.json b/i18n/de.json index 84d5f47..3c1edf0 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -7,9 +7,15 @@ "th-desc": "Entwicklungserweiterung für das 'Teahouse' Gadget", "th-button-text": "Stelle deine Frage", "th-dialog-title": "Stelle deine Frage", - "th-dialog-description-top": "Bitte schreibe eine kurze Frage in das Textfeld. Wenn du weitere Informationen angeben willst, verwende bitte die große Textbox.", + "th-dialog-description-top": "Stelle deine Frage an die Wikipedia Community! Auf $1 kannst du dir die Fragen anderer Benutzer ansehen.", "th-dialog-label-summary": "Deine Frage", - "th-dialog-label-text": "Genauere Beschreibung der Frage (Du kannst WikiText verwenden)", - "th-dialog-btn-ok": "Frage abschicken", - "th-dialog-btn-cancel": "Abbrechen" + "th-dialog-label-text": "Genauere Beschreibung (Du kannst WikiText verwenden)", + "th-dialog-btn-ok": "Veröffentlichen", + "th-dialog-btn-cancel": "Abbrechen", + "th-dialog-disclaimer": "Veröffentlichung unter den Nutzungsbedingungen der Wikipedia", + "th-dialog-anon-ip-hint": "Deine IP Adresse wird zusammen mit der Frage veröffentlicht", + "th-dialog-msg-title-save": "Frage veröffentlicht", + "th-dialog-msg-text-save": "Deine Frage wurde unter $1 veröffentlicht. Möchtest du die komplette Liste der Fragen sehen?", + "th-dialog-msg-btn-yes": "Ja", + "th-dialog-msg-btn-no": "Nein" } diff --git a/i18n/en.json b/i18n/en.json index bc5e111..7faee83 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -7,9 +7,15 @@ "th-desc": "Development extension for \"Teahouse\" gadget", "th-button-text": "Ask your question", "th-dialog-title": "Ask your question", - "th-dialog-description-top": "Please provide a short question within the textfield. If you have additional information you want to submit, please use the large textbox.", + "th-dialog-description-top": "Ask your question to the Wikipedia Community! You can see the questions of other users on $1", "th-dialog-label-summary": "Your question", - "th-dialog-label-text": "Full text of your question (You may use wikitext)", - "th-dialog-btn-ok": "Send question", - "th-dialog-btn-cancel": "Cancel" + "th-dialog-label-text": "Further description (You may use wikitext)", + "th-dialog-btn-ok": "Publish", + "th-dialog-btn-cancel": "Cancel", + "th-dialog-disclaimer": "Published under Wikipedia's Terms of Use", + "th-dialog-anon-ip-hint": "Your IP address will be published with the question", + "th-dialog-msg-title-save": "Question published", + "th-dialog-msg-text-save": "Your question has been published on $1. Do you wand to see the complete list of questions?", + "th-dialog-msg-btn-yes": "Yes", + "th-dialog-msg-btn-no": "No" } diff --git a/i18n/qqq.json b/i18n/qqq.json index 54b2d98..2030733 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -10,6 +10,8 @@ "th-dialog-description-top": "A short description of how to use teh dialog at the beginning", "th-dialog-label-summary": "Label of a text field that contains the question itself", "th-dialog-label-text": "Label of a textarea that allows an additional information for the question", - "th-dialog-btn-ok": "Text of the button that sends the question", - "th-dialog-btn-cancel": "Text of the button that resets the form and closes the dialog" + "th-dialog-btn-ok": "Text of the button that sends the question. It should be clear that the action makes the question available to the public.", + "th-dialog-btn-cancel": "Text of the button that resets the form and closes the dialog", + "th-dialog-disclaimer": "Hint to the Terms of Use. Links to https://wikimediafoundation.org/wiki/Terms_of_Use", + "th-dialog-anon-ip-hint": "Hint that the IP adress of an anonymous user will be saved" } diff --git a/resources/mediawiki.teahouse.css b/resources/mediawiki.teahouse.css index a0f59d4..8434c3c 100644 --- a/resources/mediawiki.teahouse.css +++ b/resources/mediawiki.teahouse.css @@ -3,4 +3,20 @@ color: #F0F0F0; background-color: #27AA65; /* https://www.mediawiki.org/wiki/Wikimedia_Foundation_Design/Color_usage */ padding: 0 0.5em; +} + +.th-question-dialog-body .th-inputWidget { + width: 100%; +} + +.th-question-dialog-body .th-tiDesc > textarea { + height: 8em; +} + +.th-question-dialog-body .th-pseudoButton a { + cursor: initial; +} + +.th-question-dialog-body .th-similar-questions-list { + list-style-type: none; } \ No newline at end of file diff --git a/resources/mediawiki.teahouse.dialog.js b/resources/mediawiki.teahouse.dialog.js index 43d99c4..9c3497d 100644 --- a/resources/mediawiki.teahouse.dialog.js +++ b/resources/mediawiki.teahouse.dialog.js @@ -2,19 +2,24 @@ function _setupDialog( config ) { - _windowManager = new OO.ui.WindowManager(); + _windowManager = new OO.ui.WindowManager({ + modal: true, + isolate: true + }); $( 'body' ).append( _windowManager.$element ); - _window = new th.ui.QuestionDialog(config); - _windowManager.addWindows( [ _window ] ); + _window = new th.ui.QuestionDialog( config ); + _messageDialog = new OO.ui.MessageDialog(); + _windowManager.addWindows( [ _window, _messageDialog ] ); return; } var _windowManager = undefined; var _window = undefined; + var _messageDialog = undefined; - mw.teahouse.openDialog = function( data ) { + mw.teahouse.openQuestionDialog = function( data ) { mw.loader.using( ['oojs-ui', 'mediawiki.Uri'], function(){ var config = mw.teahouse.getConfig(); @@ -26,21 +31,21 @@ $.getScript( url.toString(), function(){ _setupDialog(); - mw.teahouse.openDialog(); + mw.teahouse.openQuestionDialog( data ); //re-call after dependency is loaded }); return; } - _windowManager - .openWindow( _window, data ) - .then( function ( opening ) { - opening.then( function ( opened ) { - opened.then( function ( data ) { - console.log(data); - //todo: submit question to board using API call - }); - }); - }); + data = $.extend( data, { + config: config, + board: mw.teahouse.board + }); + _windowManager.openWindow( _window, data ); }); }; + + mw.teahouse.openMessageDialog = function( data ) { + //TODO: make sure _windowManager is available... + return _windowManager.openWindow( _messageDialog, data ); + }; })( mediaWiki, jQuery, document ); diff --git a/resources/mediawiki.teahouse.gadget.development.js b/resources/mediawiki.teahouse.gadget.development.js index 96c9ec2..251129a 100644 --- a/resources/mediawiki.teahouse.gadget.development.js +++ b/resources/mediawiki.teahouse.gadget.development.js @@ -1,5 +1,19 @@ mw.teahouse.init({ - linkLabel: 'Frage stellen', - linkDescription: 'Hier klicken um der Community eine Frage über die Wikipedia zu stellen', + basePage: 'Projekt:Teehaus/Fragen', + i18n: { + "th-button-text": "Stelle deine Frage", + "th-dialog-title": "Stelle deine Frage", + "th-dialog-description-top": "Stelle deine Frage an die Wikipedia Community! Auf $1 kannst du dir die Fragen anderer Benutzer ansehen.", + "th-dialog-label-summary": "Deine Frage", + "th-dialog-label-text": "Genauere Beschreibung (Du kannst WikiText verwenden)", + "th-dialog-btn-ok": "Veröffentlichen", + "th-dialog-btn-cancel": "Abbrechen", + "th-dialog-disclaimer": "Veröffentlichung unter den Nutzungsbedingungen der Wikipedia", + "th-dialog-anon-ip-hint": "Deine IP Adresse wird zusammen mit der Frage veröffentlicht", + "th-dialog-msg-title-save": "Frage veröffentlicht", + "th-dialog-msg-text-save": "Deine Frage wurde unter $1 veröffentlicht. Möchtest du die komplette Liste der Fragen sehen?", + "th-dialog-msg-btn-yes": "Ja", + "th-dialog-msg-btn-no": "Nein" + }, resourcesPath: mw.config.get('wgScriptPath') + '/extensions/Teahouse/resources' }); \ No newline at end of file diff --git a/resources/mediawiki.teahouse.js b/resources/mediawiki.teahouse.js index 3e2cda8..22d8097 100644 --- a/resources/mediawiki.teahouse.js +++ b/resources/mediawiki.teahouse.js @@ -5,12 +5,28 @@ * single wikipedias */ var _config = { - basePage: 'Project:Teahouse', + basePage: 'Wikipedia:Teahouse', resourcesPath: mw.config.get('wgScript') + "?title=MediaWiki:Gadget-teahouse", - linkLabel: 'Ask your question', //We make this a setting because involving - //the I18N system for just one entry that is almost always needed is - //a waste of resources - linkDescription: 'Click here to submit a question about Wikipedia to the community' + templates: { + pendingQuestion: 'Pending_question', + answeredQuestion: 'Answered_question', + questionWrapper: 'Wikipedia/Teahouse/Question' + }, + i18n: { + "th-button-text": "Ask your question", + "th-dialog-title": "Ask your question", + "th-dialog-description-top": "Ask your question to the Wikipedia Community! You can see the questions of other users on $1", + "th-dialog-label-summary": "Your question", + "th-dialog-label-text": "Further description (You may use wikitext)", + "th-dialog-btn-ok": "Publish", + "th-dialog-btn-cancel": "Cancel", + "th-dialog-disclaimer": "Published under Wikipedia's Terms of Use", + "th-dialog-anon-ip-hint": "Your IP address will be published with the question", + "th-dialog-msg-title-save": "Question published", + "th-dialog-msg-text-save": "Your question has been published on $1. Do you wand to see the complete list of questions?", + "th-dialog-msg-btn-yes": "Yes", + "th-dialog-msg-btn-no": "No" + } }; /** @@ -21,12 +37,12 @@ function _init( config ){ //Register event handler for click on ... - $(d).on( 'click', '#p-teahouse', mw.teahouse.openDialog ); //... menu link - $(d).on( 'click', '.th-ask', mw.teahouse.openDialog ); //... custom element + $(d).on( 'click', '#p-teahouse', mw.teahouse.openQuestionDialog ); //... menu link + $(d).on( 'click', '.th-ask', mw.teahouse.openQuestionDialog ); //... custom element //Set cookie when anon clicks edit link $(d).on( 'click', '#ca-ve-edit, #ca-edit', function(){ - $.cookie('mediaWiki.teahouse.anonEdit', '1'); + mw.cookie.set('mediaWiki.teahouse.anonEdit', '1'); }); _checkUserIsEligible(); @@ -38,7 +54,7 @@ */ function _checkUserIsEligible() { //If not logged in we just check if the user has already made an edit - if( mw.user.isAnon() === true && $.cookie('mediaWiki.teahouse.anonEdit') === '1' ) { + if( mw.user.isAnon() === true && mw.cookie.get('mediaWiki.teahouse.anonEdit') === '1' ) { _showLink(); } //In case of a registered user we need to check for "autoconfirmed" group. @@ -55,8 +71,8 @@ function _showLink() { var linkMarkup = '<li id="p-teahouse">' - + '<a title="' + _config.linkDescription + '" href="#">' - + _config.linkLabel + + '<a title="' + mw.message('th-button-title').plain() + '" href="#">' + + mw.message('th-button-text').plain() + '</a>' + '</li>'; @@ -65,7 +81,10 @@ mw.teahouse = { init: function( config ) { + //called before merge because $.extend is not recursive + mw.messages.set( _config.i18n ); _config = $.extend( _config, config ); + mw.messages.set( _config.i18n ); mw.loader.using( 'mediawiki.user', _init ); }, diff --git a/resources/ui/dialogs/th.ui.QuestionDialog.js b/resources/ui/dialogs/th.ui.QuestionDialog.js index 0e235f1..e1c355c 100644 --- a/resources/ui/dialogs/th.ui.QuestionDialog.js +++ b/resources/ui/dialogs/th.ui.QuestionDialog.js @@ -23,10 +23,11 @@ { action: 'save', label: mw.message('th-dialog-btn-ok').plain(), - flags: 'primary' + flags: 'primary', + disabled: true }, { - action: 'cancel', + //action: 'cancel', label: mw.message('th-dialog-btn-cancel').plain(), flags: 'safe' } @@ -35,46 +36,200 @@ th.ui.QuestionDialog.prototype.initialize = function () { th.ui.QuestionDialog.super.prototype.initialize.apply( this, arguments ); + var config = mw.teahouse.getConfig(); + this.content = new OO.ui.PanelLayout( { $: this.$, padded: true, + scrollable: true, expanded: false } ); - //this.inputWidget = new OO.ui.SearchWidget(); - this.inputWidget = new OO.ui.TextInputWidget({ - //icon: 'search' + //this.tiQuestion = new OO.ui.SearchWidget(); + this.tiQuestion = new OO.ui.TextInputWidget({ + classes: [ 'th-inputWidget', 'th-tiQuestion' ] + }); + this.tiQuestion.on( 'change', this.onTiQuestionChange, [], this ); + var flQuestion = new OO.ui.FieldLayout( + this.tiQuestion, + { + label: mw.message('th-dialog-label-summary').plain(), + align: 'top' + } + ); + + this.tiDesc = new OO.ui.TextInputWidget( { + classes: [ 'th-inputWidget', 'th-tiDesc' ], + multiline: true }); - this.inputLongDesc = new OO.ui.TextInputWidget( { - multiline: true, - autosize: true - }); - - var fl = new OO.ui.FieldLayout( - this.inputLongDesc, + var flDesc = new OO.ui.FieldLayout( + this.tiDesc, { label: mw.message('th-dialog-label-text').plain(), align: 'top' } ); - this.content.$element.append( - mw.message('th-dialog-description-top').plain() - ); - this.content.$element.append( this.inputWidget.$element ); - this.content.$element.append( fl.$element ); + this.btnDisclaimer = new OO.ui.ButtonWidget( { + icon: 'info', + framed: false, + label: mw.message('th-dialog-disclaimer').plain(), + href: 'https://wikimediafoundation.org/wiki/Terms_of_Use', + target: '_blank' + }); + this.btnAnonIPhint = new OO.ui.ButtonWidget( { + classes: [ 'th-pseudoButton' ], + icon: 'info', + framed: false, + label: mw.message('th-dialog-anon-ip-hint').plain() + }); + + this.pnlSimilarQuestions = $('<div>'); + + var anchor = mw.html.element( 'a', { + href: mw.util.getUrl( config.basePage ), + title: config.basePage, + target: '_blank' + }, config.basePage ); + + this.content.$element.append( + $('<p>').append( mw.message('th-dialog-description-top', anchor).text() ) + ); + + this.content.$element.append( flQuestion.$element ); + this.content.$element.append( this.pnlSimilarQuestions ); + this.content.$element.append( flDesc.$element ); + this.content.$element.append( this.btnDisclaimer.$element.wrap('<p>') ); + this.content.$element.append( this.btnAnonIPhint.$element ); + + this.$body.addClass('th-question-dialog-body'); this.$body.append( this.content.$element ); }; -th.ui.QuestionDialog.prototype.getActionProcess = function ( action ) { - var dialog = this; - if ( action ) { - return new OO.ui.Process( function () { - dialog.close( { action: action } ); - } ); +th.ui.QuestionDialog.prototype.onTiQuestionChange = function( value ) { + var me = this; + var config = mw.teahouse.getConfig(); + var actions = this.getActions(); + this.pnlSimilarQuestions.empty(); + //actions.list[0] is the save/publish action + //If there is no question entered or it is way too short to be a question + //we disable the "save" action + if(value !== '' && value.length > 3) { + var api = new mw.Api(); + api.get({ + action: 'query', + list: 'search', + srsearch: value, + srlimit: 50, + srnamespace: 4 //NS_PROJECT --> todo: make configurable + }) + .done(function( response, jqXHR ){ + var list = $('<ul>').addClass('th-similar-questions-list'); + var count = 0; + for( var i = 0; i < response.query.search.length && count < 5; i++ ) { + var title = response.query.search[i].title; + if( title.indexOf( config.basePage ) !== 0 ) { + continue; + } + + var displayTitle = title.replace( config.basePage, '' ); + var anchor = mw.html.element( 'a', { + href: mw.util.getUrl( title ), + title: title, + target: '_blank' + }, title ); + list.append( '<li>'+anchor+'</li>' ); + count++; + } + me.pnlSimilarQuestions.append( list ); + me.getManager().updateWindowSize( me ); + }); + + actions.list[0].setDisabled(false); + return; } + this.getManager().updateWindowSize( this ); + actions.list[0].setDisabled(true); +}; + +th.ui.QuestionDialog.prototype.getSetupProcess = function ( openingData ) { + this._data = openingData; + + //Hide the IP saving hint if user is anon. + if( mw.user.isAnon() === false ) { + this.btnAnonIPhint.$element.hide(); + } + return th.ui.QuestionDialog.super.prototype.getSetupProcess.call( this, openingData ); +}; + +th.ui.QuestionDialog.prototype.getTeardownProcess = function ( closingData ) { + this.tiQuestion.setValue( '' ); + this.tiDesc.setValue( '' ); + + return th.ui.QuestionDialog.super.prototype.getTeardownProcess.call( this, closingData ); +}; + +th.ui.QuestionDialog.prototype.getActionProcess = function ( action ) { + var me = this; + var config = mw.teahouse.getConfig(); + + var text = this.tiDesc.getValue() + ''; //Implicit conversion to string. + //Don't know why it is necessary but otherwise adding a "\n" will break + //the string + + //We append a signature WikiText fragment by default + if( text.indexOf( '--~~~~' ) === false ) { + text += "\n--~~~~"; + } + + var question = { + title: this.tiQuestion.getValue(), + text: text + }; + + if ( action === 'save' ) { + return new OO.ui.Process( function () { + //TODO: Move out of dialog implementation and into "The Board" + var api = new mw.Api(); + return api.postWithToken( 'edit', { + action: 'edit', + title: config.basePage + "/" + question.title, + summary: "Added by Teahouse gadget", + text: question.text + }) + .fail(function( response, jqXHR ){ + console.log(arguments); + }) + .done(function( response, jqXHR ){ + //TODO: add a parameter whether to reset fields or not + //This parameter will be passed to 'getTeardownProcess' + me.close( { action: action } ); + }) + .then(function( response, jqXHR ){ + var msg = mw.message('th-dialog-msg-text-save', response.edit.title ).text(); + + mw.teahouse.openMessageDialog({ + title: mw.message('th-dialog-msg-title-save').plain(), + message: msg, + actions: [ + { label: mw.message('th-dialog-msg-btn-yes').plain(), action: 'yes' }, + { label: mw.message('th-dialog-msg-btn-no').plain(), action: 'no' } + ] + }).then( function ( opening ) { + opening.then( function ( opened ) { + opened.then( function ( data ) { + if( data.action === 'yes' ) { + window.location.href = mw.util.getUrl( config.basePage ); + } + }); + }); + }); + }); + }); + } + return th.ui.QuestionDialog.super.prototype.getActionProcess.call( this, action ); }; -- To view, visit https://gerrit.wikimedia.org/r/166577 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ia3c4dc5aeed4c30a02e48c9fce79aecef29f2462 Gerrit-PatchSet: 5 Gerrit-Project: mediawiki/extensions/Teahouse Gerrit-Branch: master Gerrit-Owner: Robert Vogel <vo...@hallowelt.biz> Gerrit-Reviewer: Robert Vogel <vo...@hallowelt.biz> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits