User:Justarandomamerican/globalUserLock.js: Difference between revisions
From WikiOasis Meta
More actions
maybe? |
No edit summary |
||
| Line 19: | Line 19: | ||
// ── Load Dependencies First ──────────────────────────────────────────────── | // ── Load Dependencies First ──────────────────────────────────────────────── | ||
$.when( | $.when( | ||
mw.loader.using( [ 'mediawiki.util', 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ), | mw.loader.using( [ 'mediawiki.util', 'mediawiki.api', 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] ), | ||
$.ready | $.ready | ||
).then( function () { | ).then( function () { | ||
// Initialize the MediaWiki API helper | |||
const api = new mw.Api(); | |||
// ── OOUI Dialog Definition ───────────────────────────────────────────── | // ── OOUI Dialog Definition ───────────────────────────────────────────── | ||
| Line 298: | Line 301: | ||
// ── API helpers ──────────────────────────────────────────────────────── | // ── API helpers ──────────────────────────────────────────────────────── | ||
function fetchMatchingUsers( query, fromUser ) { | function fetchMatchingUsers( query, fromUser ) { | ||
const deferred = $.Deferred(); | const deferred = $.Deferred(); | ||
| Line 332: | Line 326: | ||
if ( continueFrom ) { params.agufrom = continueFrom; } | if ( continueFrom ) { params.agufrom = continueFrom; } | ||
api.get( params ) | |||
.done( function ( data ) { | .done( function ( data ) { | ||
const users = ( data.query || {} ).globalallusers || []; | const users = ( data.query || {} ).globalallusers || []; | ||
| Line 356: | Line 350: | ||
} | } | ||
} ) | } ) | ||
.fail( function ( | .fail( function ( code ) { | ||
deferred.reject( 'API request failed: ' + | deferred.reject( 'API request failed: ' + code ); | ||
} ); | } ); | ||
} | } | ||
| Line 365: | Line 359: | ||
} | } | ||
function lockAccount( username | function lockAccount( username, reason, hide, suppress ) { | ||
const payload = { | const payload = { | ||
action: 'setglobalaccountstatus', | action: 'setglobalaccountstatus', | ||
| Line 371: | Line 365: | ||
locked: 'lock', | locked: 'lock', | ||
reason: reason, | reason: reason, | ||
format: 'json' | format: 'json' | ||
}; | }; | ||
| Line 381: | Line 374: | ||
} | } | ||
return | return api.postWithToken( 'csrf', payload ); | ||
} | } | ||
| Line 458: | Line 451: | ||
const skipLocked = $( '#gul-skip-locked' ).prop( 'checked' ); | const skipLocked = $( '#gul-skip-locked' ).prop( 'checked' ); | ||
if ( !reason ) { setStatus( 'A lock reason is required.', 'error' ); return; } | if ( !reason ) { | ||
setStatus( '🛑 A lock reason is required before locking.', 'error' ); | |||
$( '#gul-reason' ).trigger( 'focus' ); | |||
return; | |||
} | |||
const selected = []; | const selected = []; | ||
| Line 464: | Line 461: | ||
if ( selected.length === 0 ) { setStatus( 'No accounts selected.', 'warning' ); return; } | if ( selected.length === 0 ) { setStatus( 'No accounts selected.', 'warning' ); return; } | ||
const confirmMessage = 'You are about to globally lock ' + selected.length + ' account(s).\n\n' + | |||
'Reason: ' + reason + '\n' + | |||
( hide ? 'Hide username: YES\n' : '' ) + | |||
( suppress ? 'Suppress username: YES\n' : '' ) + | |||
'\nThis action will be logged. Proceed?'; | |||
OO.ui.confirm( confirmMessage ).done( function ( confirmed ) { | |||
if ( !confirmed ) { return; } | |||
$( '#gul-btn-lock, #gul-btn-search' ).prop( 'disabled', true ); | |||
. | $( '#gul-progress' ).addClass( 'visible' ); | ||
setProgress( 0, selected.length ); | |||
setStatus( 'Locking ' + selected.length + ' account(s)…', 'info' ); | |||
let done = 0, locked = 0, skipped = 0, failed = 0; | |||
function processNext( i ) { | |||
if ( i >= selected.length ) { | |||
setProgress( done, selected.length ); | |||
setStatus( 'Done. <strong>' + locked + '</strong> locked, <strong>' + skipped + '</strong> skipped, <strong>' + failed + '</strong> failed.', failed > 0 ? 'warning' : 'success' ); | |||
$( '#gul-btn-search' ).prop( 'disabled', false ); | |||
$( '#gul-lock-summary' ).remove(); | |||
$( '#gul-results-wrap' ).append( $( '<div id="gul-lock-summary">' ).addClass( 'gul-summary' ).html( '<strong>Summary:</strong> ' + locked + ' locked · ' + skipped + ' skipped · ' + failed + ' failed' ) ); | |||
return; | |||
} | |||
const username = selected[ i ]; | |||
const wasLocked = $( 'tr[data-user="' + $.escapeSelector( username ) + '"] td:nth-child(3)' ).text().trim() === 'Locked'; | |||
if ( skipLocked && wasLocked ) { | |||
skipped++; done++; | |||
setBadge( username, 'skipped', 'Skipped' ); | |||
setProgress( done, selected.length ); | |||
processNext( i + 1 ); | |||
return; | |||
} | |||
setBadge( username, 'pending', 'Locking…' ); | |||
lockAccount( username, reason, hide, suppress ) | |||
.done( function ( data ) { | |||
if ( data.error ) { | |||
failed++; | |||
setBadge( username, 'failed', 'Error: ' + mw.html.escape( data.error.info || data.error.code ) ); | |||
} else { | |||
locked++; | |||
setBadge( username, 'locked', 'Locked ✓' ); | |||
} | |||
} ) | |||
.fail( function ( code, result ) { | |||
failed++; | |||
const errMsg = (result && result.error && result.error.info) ? result.error.info : code; | |||
setBadge( username, 'failed', 'Error: ' + mw.html.escape( errMsg ) ); | |||
} ) | |||
.always( function () { | |||
done++; | |||
setProgress( done, selected.length ); | |||
setStatus( 'Processing ' + done + ' / ' + selected.length + '…', 'info' ); | |||
setTimeout( function () { processNext( i + 1 ); }, 300 ); | |||
} ); | |||
} | |||
processNext( 0 ); | |||
} ); | |||
} | } | ||