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 <[email protected]>
Gerrit-Reviewer: Robert Vogel <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits