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. *