diff --git a/extension.json b/extension.json
index 4a46dd0ba..1d42c83ec 100644
--- a/extension.json
+++ b/extension.json
@@ -125,6 +125,7 @@
"discussiontools-ledesection-title",
"discussiontools-newtopic-placeholder-title",
"discussiontools-newtopic-missing-title",
+ "discussiontools-newtopic-missing-title-prompt",
"discussiontools-newtopicssubscription-button-subscribe-label",
"discussiontools-newtopicssubscription-button-subscribe-tooltip",
"discussiontools-newtopicssubscription-button-unsubscribe-label",
diff --git a/i18n/en.json b/i18n/en.json
index ed55a6d66..8c382b5d3 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -57,7 +57,8 @@
"discussiontools-limitreport-errorreqid": "DiscussionTools error request ID",
"discussiontools-limitreport-timeusage": "DiscussionTools time usage",
"discussiontools-limitreport-timeusage-value": "$1 {{PLURAL:$1|second|seconds}}",
- "discussiontools-newtopic-missing-title": "Please provide a title for {{GENDER:|your}} discussion topic. If you click \"{{int:discussiontools-replywidget-newtopic}}\", your topic will be added without a title.",
+ "discussiontools-newtopic-missing-title": "Please provide a title for {{GENDER:|your}} discussion topic.",
+ "discussiontools-newtopic-missing-title-prompt": "{{GENDER:|You}} have not provided a title for {{GENDER:|your}} discussion topic. Are {{GENDER:|you}} sure you want to add this topic without a title?",
"discussiontools-newtopic-placeholder-title": "Subject",
"discussiontools-newtopicssubscription-button-subscribe-label": "Subscribe",
"discussiontools-newtopicssubscription-button-subscribe-tooltip": "Subscribe to receive notifications when new topics are started on this page.",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 2a68222af..27539b54f 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -71,7 +71,8 @@
"discussiontools-limitreport-errorreqid": "Label for the ID of the web request in which a DiscussionTools error has occurred.",
"discussiontools-limitreport-timeusage": "Label for the time usage (duration) of DiscussionTools in the parser limit report. Followed by {{msg-mw|discussiontools-limitreport-timeusage-value}}.\n\nSimilar to:\n* {{msg-mw|limitreport-cputime}}\n* {{msg-mw|limitreport-walltime}}\n* {{msg-mw|scribunto-limitreport-timeusage}}",
"discussiontools-limitreport-timeusage-value": "Follows {{msg-mw|discussiontools-limitreport-timeusage}}.\n\nParameters:\n* $1 - the usage in seconds\n{{Identical|Second}}",
- "discussiontools-newtopic-missing-title": "Warning message shown when leaving the title field empty while adding a new topic to the page.\n\nCopy {{int:discussiontools-replywidget-newtopic}} into your translation. It will be shown as {{msg-mw|discussiontools-replywidget-newtopic}}",
+ "discussiontools-newtopic-missing-title": "Warning message shown when leaving the title field empty while adding a new topic to the page.",
+ "discussiontools-newtopic-missing-title-prompt": "Confirmation prompt shown when trying to submit a new topic with the title field empty.",
"discussiontools-newtopic-placeholder-title": "Placeholder describing the heading field of a new topic\n{{identical|Subject}}",
"discussiontools-newtopicssubscription-button-subscribe-label": "Label for the button to subscribe to notifications about new topics on this page.",
"discussiontools-newtopicssubscription-button-subscribe-tooltip": "Tooltip for the button to subscribe to notifications about new topics on this page.",
diff --git a/modules/CommentController.js b/modules/CommentController.js
index ef64ca6f1..ee635d57f 100644
--- a/modules/CommentController.js
+++ b/modules/CommentController.js
@@ -408,9 +408,10 @@ CommentController.prototype.onReplyWidgetTeardown = function ( mode ) {
*
* @param {string} pageName Title of the page to post on
* @param {Object} checkboxes Value of the promise returned by controller#getCheckboxesPromise
+ * @param {Object} extraParams Extra params to pass to the API
* @return {Object.} API query data
*/
-CommentController.prototype.getApiQuery = function ( pageName, checkboxes ) {
+CommentController.prototype.getApiQuery = function ( pageName, checkboxes, extraParams ) {
const threadItem = this.getThreadItem();
const replyWidget = this.replyWidget;
const sameNameComments = this.threadItemSet.findCommentsByName( threadItem.name );
@@ -426,7 +427,7 @@ CommentController.prototype.getApiQuery = function ( pageName, checkboxes ) {
tags.push( 'discussiontools-source-enhanced' );
}
- const data = {
+ const data = Object.assign( {
action: 'discussiontoolsedit',
paction: 'addcomment',
page: pageName,
@@ -441,7 +442,7 @@ CommentController.prototype.getApiQuery = function ( pageName, checkboxes ) {
// Pass through dtenable query string param from original request
dtenable: new URLSearchParams( location.search ).get( 'dtenable' ) ? '1' : undefined,
dttags: tags.join( ',' )
- };
+ }, extraParams );
if ( replyWidget.getMode() === 'source' ) {
data.wikitext = replyWidget.getValue();
@@ -466,8 +467,10 @@ CommentController.prototype.getApiQuery = function ( pageName, checkboxes ) {
/**
* Handle the reply widget being submitted
+ *
+ * @param {Object} extraParams Extra params to pass to the API
*/
-CommentController.prototype.onReplySubmit = function () {
+CommentController.prototype.onReplySubmit = function ( extraParams ) {
if ( !this.replyWidget ) {
return;
}
@@ -481,7 +484,7 @@ CommentController.prototype.onReplySubmit = function () {
mw.track( 'editAttemptStep', { action: 'saveAttempt' } );
// TODO: When editing a transcluded page, VE API returning the page HTML is a waste, since we won't use it
- this.save( this.replyWidget.pageName )
+ this.save( this.replyWidget.pageName, extraParams )
.then( null, this.saveFail.bind( this ) )
.always( () => {
this.replyWidget.setPending( false );
@@ -543,14 +546,15 @@ CommentController.prototype.saveFail = function ( code, data ) {
* Save the comment in the comment controller
*
* @param {string} pageName Page title
+ * @param {Object} extraParams Extra params to pass to the API
* @return {jQuery.Promise} Promise which resolves when the save is complete
*/
-CommentController.prototype.save = function ( pageName ) {
+CommentController.prototype.save = function ( pageName, extraParams ) {
const replyWidget = this.replyWidget,
threadItem = this.getThreadItem();
return this.replyWidget.checkboxesPromise.then( ( checkboxes ) => {
- const data = this.getApiQuery( pageName, checkboxes );
+ const data = this.getApiQuery( pageName, checkboxes, extraParams );
if (
// We're saving the first comment on a page that previously didn't exist.
diff --git a/modules/NewTopicController.js b/modules/NewTopicController.js
index d465e5ec6..9380ea899 100644
--- a/modules/NewTopicController.js
+++ b/modules/NewTopicController.js
@@ -243,8 +243,8 @@ NewTopicController.prototype.getUnsupportedNodeSelectors = function () {
/**
* @inheritdoc
*/
-NewTopicController.prototype.getApiQuery = function ( pageName, checkboxes ) {
- let data = NewTopicController.super.prototype.getApiQuery.call( this, pageName, checkboxes );
+NewTopicController.prototype.getApiQuery = function ( pageName, checkboxes, extraParams ) {
+ let data = NewTopicController.super.prototype.getApiQuery.call( this, pageName, checkboxes, extraParams );
// Rebuild the tags array and remove the reply tag
const tags = ( data.dttags || '' ).split( ',' );
@@ -258,9 +258,6 @@ NewTopicController.prototype.getApiQuery = function ( pageName, checkboxes ) {
data = Object.assign( {}, data, {
paction: 'addtopic',
sectiontitle: this.sectionTitle.getValue(),
- // TODO: Make the user somehow confirm that they really want to post a topic with no subject
- // before sending this parameter (T334163)
- allownosectiontitle: true,
dttags: tags.join( ',' )
} );
@@ -274,6 +271,24 @@ NewTopicController.prototype.getApiQuery = function ( pageName, checkboxes ) {
return data;
};
+/**
+ * @inheritdoc
+ */
+NewTopicController.prototype.saveFail = function ( code ) {
+ if ( code === 'discussiontools-newtopic-missing-title' ) {
+ OO.ui.confirm( mw.msg( 'discussiontools-newtopic-missing-title-prompt' ) ).then( ( confirmed ) => {
+ if ( confirmed ) {
+ this.onReplySubmit( { allownosectiontitle: true } );
+ } else {
+ this.sectionTitle.focus();
+ }
+ } );
+ return;
+ }
+
+ NewTopicController.super.prototype.saveFail.apply( this, arguments );
+};
+
/**
* Generate a default edit summary based on the section title.
*