diff --git a/src/modules/core.js b/src/modules/core.js index 69837ef5..75388685 100644 --- a/src/modules/core.js +++ b/src/modules/core.js @@ -996,7 +996,7 @@ /** * Represents an element in the status container * - * @param {string} initialText Initial text of the element + * @param {string} initialText Initial text of the element * @param {Object} substitutions key-value pairs of strings that should be replaced by something * else. For example, { '$2': mw.user.getUser() }. If not redefined, $1 * will be equal to the current page name. @@ -1005,7 +1005,7 @@ /** * Replace the status element with new html content * - * @param {jQuery|string} html Content of the element + * @param {jQuery|string} html Content of the element * Can use $1 to represent the page name */ this.update = function ( html ) { @@ -1510,16 +1510,23 @@ * @param {string} pagename - The title of the page. * @param {string} displayTitle - What gets shown by the link. * @param {boolean} [newTab=true] - Whether to open page in a new tab. + * @param {boolean} dontFollowRedirects - whether to add &redirect=no to URLs, to prevent auto redirecting when clicked * @return {jQuery} element */ - makeLinkElementToPage: function ( pagename, displayTitle, newTab ) { + makeLinkElementToPage: function ( pagename, displayTitle, newTab, dontFollowRedirects ) { var actualTitle = pagename.replace( /_/g, ' ' ); // newTab is an optional parameter. newTab = ( typeof newTab === 'undefined' ) ? true : newTab; + var options = {}; + if ( dontFollowRedirects ) { + options = { redirect: 'no' }; + } + var url = mw.util.getUrl( actualTitle, options ); + return $( '' ) - .attr( 'href', mw.util.getUrl( actualTitle ) ) + .attr( 'href', url ) .attr( 'id', 'afch-cat-link-' + pagename.toLowerCase().replace( / /g, '-' ).replace( /\//g, '-' ) ) .attr( 'title', actualTitle ) .text( displayTitle || actualTitle ) diff --git a/src/modules/submissions.js b/src/modules/submissions.js index 6837b3b1..568d0bc0 100644 --- a/src/modules/submissions.js +++ b/src/modules/submissions.js @@ -1301,7 +1301,6 @@ // Handler will run after the main AJAX requests complete setupAjaxStopHandler(); - } /** @@ -1755,6 +1754,7 @@ $status.text( '' ); $submitButton .removeClass( 'disabled' ) + .css( 'pointer-events', 'auto' ) .text( 'Accept & publish' ); // If there is no value, die now, because otherwise mw.Title @@ -1787,22 +1787,31 @@ inprop: 'protection', titles: page.rawTitle } ) - ).then( function ( rawBlacklistResult, rawData ) { + ).then( function ( rawBlacklist, rawInfo ) { var errorHtml, buttonText; // Get just the result, not the Promise object - var blacklistResult = rawBlacklistResult[ 0 ], - data = rawData[ 0 ]; + var blacklistResult = rawBlacklist[ 0 ], + infoResult = rawInfo[ 0 ]; - // If the page already exists, display an error - if ( !data.query.pages.hasOwnProperty( '-1' ) ) { + var pageAlreadyExists = !infoResult.query.pages.hasOwnProperty( '-1' ); + + var pages = infoResult && infoResult.query && infoResult.query.pages && infoResult.query.pages; + var firstPageInObject = Object.values( pages )[ 0 ]; + var pageIsRedirect = firstPageInObject && ( 'redirect' in firstPageInObject ); + + if ( pageAlreadyExists && pageIsRedirect ) { + var linkToRedirect = AFCH.jQueryToHtml( AFCH.makeLinkElementToPage( page.rawTitle, null, null, true ) ); + errorHtml = '
Whoops, the page "' + linkToRedirect + '" already exists and is a redirect. Do you want to tag it for speedy deletion so you can accept this draft later?
Yes / No'; + buttonText = 'The proposed title already exists'; + } else if ( pageAlreadyExists ) { errorHtml = 'Whoops, the page "' + linkToPage + '" already exists.'; buttonText = 'The proposed title already exists'; } else { // If the page doesn't exist but IS create-protected and the // current reviewer is not an admin, also display an error // FIXME: offer one-click request unprotection? - $.each( data.query.pages[ '-1' ].protection, function ( _, entry ) { + $.each( infoResult.query.pages[ '-1' ].protection, function ( _, entry ) { if ( entry.type === 'create' && entry.level === 'sysop' && $.inArray( 'sysop', mw.config.get( 'wgUserGroups' ) ) === -1 ) { errorHtml = 'Darn it, "' + linkToPage + '" is create-protected. You will need to request unprotection before accepting.'; buttonText = 'The proposed title is create-protected'; @@ -1828,9 +1837,20 @@ // Show the error message $status.html( errorHtml ); + // Add listener for the "Do you want to tag it for speedy deletion so you can accept this draft later?" "yes" link. + $( '#afch-redirect-tag-speedy' ).on( 'click', function () { + handleAcceptOverRedirect( page.rawTitle ); + } ); + + // Add listener for the "Do you want to tag it for speedy deletion so you can accept this draft later?" "no" link. + $( '#afch-redirect-abort' ).on( 'click', function () { + $( '#afch-redirect-notification' ).hide(); + } ); + // Disable the submit button and show an error in its place $submitButton .addClass( 'disabled' ) + .css( 'pointer-events', 'none' ) .text( buttonText ); } ); } ); @@ -1846,7 +1866,6 @@ existingWPBioTemplateName: existingWPBioTemplateName, existingShortDescription: shortDescription } ); - } ); } @@ -1937,11 +1956,13 @@ $( this ).removeClass( 'bad-input' ); submitButton .removeClass( 'disabled' ) + .css( 'pointer-events', 'auto' ) .text( 'Decline submission' ); } else { $( this ).addClass( 'bad-input' ); submitButton .addClass( 'disabled' ) + .css( 'pointer-events', 'none' ) .text( 'Please enter between one and three URLs!' ); } } ); @@ -2151,6 +2172,7 @@ $afch.find( '#submitterNameStatus' ).text( '' ); $afch.find( '#afchSubmitForm' ) .removeClass( 'disabled' ) + .css( 'pointer-events', 'auto' ) .text( 'Submit' ); } @@ -2188,6 +2210,7 @@ status.text( 'Remove "User:" from the beginning.' ); submitButton .addClass( 'disabled' ) + .css( 'pointer-events', 'none' ) .text( 'Invalid user name' ); return; } @@ -2203,6 +2226,7 @@ status.text( 'No user named "' + submitter + '".' ); submitButton .addClass( 'disabled' ) + .css( 'pointer-events', 'none' ) .text( 'No such user' ); } } ); @@ -2218,8 +2242,37 @@ addFormSubmitHandler( handlePostponeG13 ); } - // These functions actually perform a given action using data passed - // in the `data` parameter. + // These functions perform a given action using data passed in the `data` parameter. + + function handleAcceptOverRedirect( destinationPageTitle ) { + // get rid of the accept form. replace it with the status div. + prepareForProcessing(); + + // Add {{Db-afc-move}} speedy deletion tag to redirect, and add to watchlist + ( new AFCH.Page( destinationPageTitle ) ).edit( { + contents: '{{Db-afc-move|' + afchPage.rawTitle + '}}\n\n', + mode: 'prependtext', + summary: 'Requesting speedy deletion ([[Wikipedia:CSD#G6|CSD G6]]).', + statusText: 'Tagging', + watchlist: 'watch' + } ); + + // Mark the draft as under review. + afchPage.getText( false ).then( function ( rawText ) { + var text = new AFCH.Text( rawText ); + afchSubmission.setStatus( 'r', { + reviewer: AFCH.consts.user, + reviewts: '{{subst:REVISIONTIMESTAMP}}' + } ); + text.updateAfcTemplates( afchSubmission.makeWikicode() ); + text.cleanUp(); + afchPage.edit( { + contents: text.get(), + summary: 'Marking submission as under review', + statusText: 'Marking as under review' + } ); + } ); + } function handleAccept( data ) { var newText = data.afchText;