User:TheAstorPastor/common.js: Difference between revisions
From Test Wiki
Content deleted Content added
No edit summary Tag: Reverted |
No edit summary |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
//importScript('User:Joepayne/grantBureaucrat.js'); // Backlink: [[User:Joepayne/grantBureaucrat.js]] |
//importScript('User:Joepayne/grantBureaucrat.js'); // Backlink: [[User:Joepayne/grantBureaucrat.js]] |
||
importScript('User:Joepayne/stripRights.js'); // Backlink: [[User:Joepayne/stripRights.js]] |
//importScript('User:Joepayne/stripRights.js'); // Backlink: [[User:Joepayne/stripRights.js]] |
||
//importScript('User:MacFan4000/grantAdmin.js'); // Backlink: [[User:MacFan4000/grantAdmin.js]] |
//importScript('User:MacFan4000/grantAdmin.js'); // Backlink: [[User:MacFan4000/grantAdmin.js]] |
||
//importScript('User:Kiteretsu/js/all-in-one.js'); // Backlink: [[User:Kiteretsu/js/all-in-one.js]] |
//importScript('User:Kiteretsu/js/all-in-one.js'); // Backlink: [[User:Kiteretsu/js/all-in-one.js]] |
||
| Line 10: | Line 10: | ||
importScript('User:Harvici/Twinkle-preferences-toolbar.js'); // Backlink: [[User:Harvici/Twinkle-preferences-toolbar.js]] |
importScript('User:Harvici/Twinkle-preferences-toolbar.js'); // Backlink: [[User:Harvici/Twinkle-preferences-toolbar.js]] |
||
importScript('User:Kiteretsu/rollbackSum.js'); // Backlink: [[User:Kiteretsu/rollbackSum.js]] |
importScript('User:Kiteretsu/rollbackSum.js'); // Backlink: [[User:Kiteretsu/rollbackSum.js]] |
||
//importScript('User:Kiteretsu/EasyResolve.js'); // Backlink: [[User:Kiteretsu/EasyResolve.js]] |
|||
importScript('User:Kiteretsu/DiscussionCloser.js'); // Backlink: [[User:Kiteretsu/DiscussionCloser.js]] |
importScript('User:Kiteretsu/DiscussionCloser.js'); // Backlink: [[User:Kiteretsu/DiscussionCloser.js]] |
||
mw.loader.load('https://testwiki.wiki/index.php?title=User:TheAstorPastor/script.js&action=raw&ctype=text/javascript'); |
|||
importScript('User:TheAstorPastor/VisualEditorEverywhere.js'); // Backlink: [[User:TheAstorPastor/VisualEditorEverywhere.js]] |
|||
mw.loader.load('https://testwiki.wiki/index.php?title=User:TheAstorPastor/script.css&action=raw&ctype=text/css', 'text/css'); |
|||
// User Rights Manager for Test Wiki's Request for Permissions page |
|||
// Script allows sysops to easily assign user rights |
|||
// Licensed under CC-BY-SA 4.0 |
|||
(function() { |
|||
// Only run on the Request for Permissions page or test pages |
|||
if (mw.config.get('wgPageName') !== 'Test_Wiki:Request_for_permissions' && !mw.config.get('wgPageName').includes('URMTW-TESTPAGE-RFP')) { |
|||
return; |
|||
} |
|||
// Check if user has appropriate permissions |
|||
if (!mw.config.get('wgUserGroups').includes('sysop') && !mw.config.get('wgUserGroups').includes('bureaucrat')) { |
|||
console.log('User Rights Manager: You need to be a sysop to use this tool.'); |
|||
return; |
|||
} |
|||
// Define rights mapping and their corresponding display names |
|||
var rightsNames = { |
|||
'sysop': 'Administrator', |
|||
'bureaucrat': 'Bureaucrat', |
|||
'interface-admin': 'Interface administrator', |
|||
'non-stewardsuppress': 'Suppressor', |
|||
'abusefilter-admin': 'Abuse filter administrator' |
|||
}; |
|||
// Define canned responses for each right |
|||
var cannedResponses = { |
|||
'sysop': '{{administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:48, 11 April 2025 (UTC)', |
|||
'bureaucrat': '{{bureaucrat granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:48, 11 April 2025 (UTC)', |
|||
'interface-admin': '{{interface administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:48, 11 April 2025 (UTC)', |
|||
'non-stewardsuppress': '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:48, 11 April 2025 (UTC)', |
|||
'abusefilter-admin': '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:48, 11 April 2025 (UTC)' |
|||
}; |
|||
// Variables for API and UI management |
|||
var api, |
|||
permission, |
|||
selectedRights = [], |
|||
revisionId = mw.config.get('wgRevisionId'), |
|||
permaLink, |
|||
userName, |
|||
sectionId, |
|||
dialog; |
|||
// Add "Assign Rights" button to each request section |
|||
function addAssignButtons() { |
|||
$('.mw-headline').each(function() { |
|||
if ($(this).attr('id') && $(this).text().includes('=')) { |
|||
// Get the username from the headline |
|||
var requestedUser = $(this).text().trim().split('==')[1].trim(); |
|||
// Find the section with requested rights |
|||
var requestSection = $(this).parent().next(); |
|||
// Check if there's already a response (to avoid duplicating buttons) |
|||
if (requestSection.text().includes('{{') || requestSection.text().includes('granted') || requestSection.find('.assign-rights-button').length) { |
|||
return; |
|||
} |
|||
// Create "Assign Rights" button |
|||
var assignButton = $('<button>') |
|||
.addClass('assign-rights-button oo-ui-widget oo-ui-widget-enabled oo-ui-buttonElement oo-ui-buttonElement-framed oo-ui-labelElement') |
|||
.css({ |
|||
'margin': '5px', |
|||
'padding': '5px 10px', |
|||
'background-color': '#36c', |
|||
'color': '#fff', |
|||
'border': 'none', |
|||
'border-radius': '2px', |
|||
'cursor': 'pointer' |
|||
}) |
|||
.text('Assign Rights') |
|||
.on('click', function(e) { |
|||
e.preventDefault(); |
|||
// Find the requested right in the section text |
|||
var sectionText = requestSection.text().toLowerCase(); |
|||
var requestedRight = ''; |
|||
if (sectionText.includes('administrator')) { |
|||
requestedRight = 'sysop'; |
|||
} else if (sectionText.includes('bureaucrat')) { |
|||
requestedRight = 'bureaucrat'; |
|||
} else if (sectionText.includes('interface administrator')) { |
|||
requestedRight = 'interface-admin'; |
|||
} else if (sectionText.includes('suppressor')) { |
|||
requestedRight = 'non-stewardsuppress'; |
|||
} else if (sectionText.includes('abuse filter')) { |
|||
requestedRight = 'abusefilter-admin'; |
|||
} |
|||
// Set global variables |
|||
permission = requestedRight; |
|||
userName = requestedUser; |
|||
sectionId = $(this).closest('h2').find('.mw-editsection a:not(".mw-editsection-visualeditor")').prop('href').match(/section=(\d+)/)[1]; |
|||
// Show the dialog |
|||
showDialog(); |
|||
}); |
|||
// Insert button after the headline |
|||
$(this).append(assignButton); |
|||
} |
|||
}); |
|||
} |
|||
// Load required modules and set up the API |
|||
mw.loader.using(['oojs-ui', 'mediawiki.api'], function() { |
|||
api = new mw.Api(); |
|||
// Add buttons after the page has loaded |
|||
$(document).ready(function() { |
|||
addAssignButtons(); |
|||
}); |
|||
}); |
|||
// Create and show the dialog |
|||
function showDialog() { |
|||
Dialog = function(config) { |
|||
Dialog.super.call(this, config); |
|||
}; |
|||
OO.inheritClass(Dialog, OO.ui.ProcessDialog); |
|||
Dialog.static.name = 'user-rights-manager'; |
|||
Dialog.static.title = 'User Rights Manager'; |
|||
Dialog.static.actions = [ |
|||
{ action: 'submit', label: 'Grant Rights', flags: ['primary', 'progressive'] }, |
|||
{ label: 'Cancel', flags: 'safe' } |
|||
]; |
|||
Dialog.prototype.getApiManager = function() { |
|||
return this.apiManager; |
|||
}; |
|||
Dialog.prototype.getBodyHeight = function() { |
|||
return 400; |
|||
}; |
|||
Dialog.prototype.initialize = function() { |
|||
Dialog.super.prototype.initialize.call(this); |
|||
// Create main panels and fieldsets |
|||
this.editPanel = new OO.ui.PanelLayout({ |
|||
expanded: false, |
|||
padded: true |
|||
}); |
|||
this.editFieldset = new OO.ui.FieldsetLayout({ |
|||
classes: ['container'] |
|||
}); |
|||
this.editPanel.$element.append(this.editFieldset.$element); |
|||
// Create checkbox inputs for each right |
|||
this.rightInputs = {}; |
|||
var detectedRight = permission || 'sysop'; |
|||
for (var right in rightsNames) { |
|||
this.rightInputs[right] = new OO.ui.CheckboxInputWidget({ |
|||
selected: right === detectedRight, |
|||
disabled: (right === 'interface-admin' || right === 'non-stewardsuppress' || right === 'abusefilter-admin') && |
|||
!mw.config.get('wgUserGroups').includes('steward') |
|||
}); |
|||
} |
|||
// Username input |
|||
this.userNameInput = new OO.ui.TextInputWidget({ |
|||
value: userName ? userName.replace(/_/g, ' ') : '' |
|||
}); |
|||
// Closing remarks input |
|||
this.closingRemarksInput = new OO.ui.MultilineTextInputWidget({ |
|||
value: cannedResponses[detectedRight] || '', |
|||
rows: 5 |
|||
}); |
|||
// Create checkbox group for rights |
|||
var rightsFieldset = new OO.ui.FieldsetLayout({ |
|||
label: 'Select rights to grant' |
|||
}); |
|||
for (var right in this.rightInputs) { |
|||
rightsFieldset.addItems([ |
|||
new OO.ui.FieldLayout(this.rightInputs[right], { |
|||
label: rightsNames[right], |
|||
align: 'inline' |
|||
}) |
|||
]); |
|||
} |
|||
// Add all form elements |
|||
this.editFieldset.addItems([ |
|||
new OO.ui.FieldLayout(rightsFieldset, { |
|||
label: 'Rights', |
|||
align: 'top' |
|||
}), |
|||
new OO.ui.FieldLayout(this.userNameInput, { |
|||
label: 'Target user', |
|||
align: 'top' |
|||
}), |
|||
new OO.ui.FieldLayout(this.closingRemarksInput, { |
|||
label: 'Closing remarks', |
|||
align: 'top' |
|||
}) |
|||
]); |
|||
// Create submit panel for progress display |
|||
this.submitPanel = new OO.ui.PanelLayout({ |
|||
expanded: false, |
|||
padded: true |
|||
}); |
|||
this.submitFieldset = new OO.ui.FieldsetLayout({ |
|||
classes: ['container'] |
|||
}); |
|||
this.submitPanel.$element.append(this.submitFieldset.$element); |
|||
// Create progress labels |
|||
this.changeRightsProgressLabel = new OO.ui.LabelWidget(); |
|||
this.changeRightsProgressField = new OO.ui.FieldLayout(this.changeRightsProgressLabel); |
|||
this.markAsDoneProgressLabel = new OO.ui.LabelWidget(); |
|||
this.markAsDoneProgressField = new OO.ui.FieldLayout(this.markAsDoneProgressLabel); |
|||
// Create stack layout to switch between panels |
|||
this.stackLayout = new OO.ui.StackLayout({ |
|||
items: [this.editPanel, this.submitPanel], |
|||
padded: true |
|||
}); |
|||
this.$body.append(this.stackLayout.$element); |
|||
// Listen for right checkbox changes to update the closing remarks |
|||
for (var right in this.rightInputs) { |
|||
this.rightInputs[right].on('change', this.updateClosingRemarks.bind(this)); |
|||
} |
|||
}; |
|||
// Update closing remarks based on selected rights |
|||
Dialog.prototype.updateClosingRemarks = function() { |
|||
var selectedRight = ''; |
|||
// Find the first selected right to use for canned response |
|||
for (var right in this.rightInputs) { |
|||
if (this.rightInputs[right].isSelected()) { |
|||
selectedRight = right; |
|||
break; |
|||
} |
|||
} |
|||
if (selectedRight && cannedResponses[selectedRight]) { |
|||
this.closingRemarksInput.setValue(cannedResponses[selectedRight]); |
|||
} |
|||
}; |
|||
// Handle dialog submission |
|||
Dialog.prototype.onSubmit = function() { |
|||
// Get username and selected rights |
|||
userName = this.userNameInput.getValue(); |
|||
selectedRights = []; |
|||
for (var right in this.rightInputs) { |
|||
if (this.rightInputs[right].isSelected()) { |
|||
selectedRights.push(right); |
|||
} |
|||
} |
|||
if (selectedRights.length === 0) { |
|||
alert('Please select at least one right to grant.'); |
|||
return; |
|||
} |
|||
var self = this, |
|||
promiseCount = 2; |
|||
// Disable submit button |
|||
self.actions.setAbilities({ submit: false }); |
|||
// Helper function to handle promises |
|||
function addPromise(field, promise) { |
|||
self.pushPending(); |
|||
promise.done(function() { |
|||
field.$field.append($('<span>') |
|||
.text('Complete!') |
|||
.prop('style', 'position:relative; top:0.5em; color: #009000; font-weight: bold') |
|||
); |
|||
}).fail(function(obj) { |
|||
if (obj && obj.error && obj.error.info) { |
|||
field.$field.append($('<span>') |
|||
.text('Error: ' + obj.error.info) |
|||
.prop('style', 'position:relative; top:0.5em; color: #cc0000; font-weight: bold') |
|||
); |
|||
} else { |
|||
field.$field.append($('<span>') |
|||
.text('An unknown error occurred.') |
|||
.prop('style', 'position:relative; top:0.5em; color: #cc0000; font-weight: bold') |
|||
); |
|||
} |
|||
}).always(function() { |
|||
promiseCount--; |
|||
self.popPending(); |
|||
if (promiseCount === 0) { |
|||
setTimeout(function() { |
|||
location.reload(true); |
|||
}, 1000); |
|||
} |
|||
}); |
|||
return promise; |
|||
} |
|||
// Add progress fields to the submit panel |
|||
self.markAsDoneProgressField.setLabel('Marking request as done...'); |
|||
self.submitFieldset.addItems([self.markAsDoneProgressField]); |
|||
self.changeRightsProgressField.setLabel('Assigning rights...'); |
|||
self.submitFieldset.addItems([self.changeRightsProgressField]); |
|||
// Process the request |
|||
addPromise( |
|||
self.markAsDoneProgressField, |
|||
markAsDone('\n:' + this.closingRemarksInput.getValue()) |
|||
).then(function(data) { |
|||
addPromise( |
|||
self.changeRightsProgressField, |
|||
assignPermission(data.edit.newrevid) |
|||
); |
|||
}.bind(this)); |
|||
// Switch to the submit panel |
|||
self.stackLayout.setItem(self.submitPanel); |
|||
}; |
|||
// Process dialog actions |
|||
Dialog.prototype.getActionProcess = function(action) { |
|||
return Dialog.super.prototype.getActionProcess.call(this, action).next(function() { |
|||
if (action === 'submit') { |
|||
return this.onSubmit(); |
|||
} else { |
|||
return Dialog.super.prototype.getActionProcess.call(this, action); |
|||
} |
|||
}, this); |
|||
}; |
|||
// Create and open the dialog |
|||
dialog = new Dialog({ |
|||
size: 'medium' |
|||
}); |
|||
var windowManager = new OO.ui.WindowManager(); |
|||
$('body').append(windowManager.$element); |
|||
windowManager.addWindows([dialog]); |
|||
windowManager.openWindow(dialog); |
|||
} |
|||
// Function to assign the selected permissions |
|||
function assignPermission(revId) { |
|||
permaLink = '[[Special:Diff/' + revId + '|Requested]]'; |
|||
return api.postWithToken('userrights', { |
|||
action: 'userrights', |
|||
format: 'json', |
|||
user: userName.replace(/ /g, '_'), |
|||
add: selectedRights.join('|'), |
|||
reason: '+' + selectedRights.join(', +') + '; ' + permaLink + ' at [[TW:RfP]]', |
|||
expiry: 'infinity', |
|||
tags: 'userRightsManager' |
|||
}); |
|||
} |
|||
// Function to mark the request as done |
|||
function markAsDone(closingRemarks) { |
|||
return api.get({ |
|||
'action': 'query', |
|||
'pageids': mw.config.get('wgArticleId'), |
|||
'prop': 'revisions', |
|||
'rvslots': '*', |
|||
'rvlimit': 1, |
|||
'rvprop': 'content', |
|||
'rvsection': sectionId |
|||
}).then(function(data) { |
|||
var newContent = data['query']['pages'][mw.config.get('wgArticleId')]['revisions'][0]['slots']['main']['*'] + closingRemarks; |
|||
return api.postWithToken('edit', { |
|||
'action': 'edit', |
|||
'pageid': mw.config.get('wgArticleId'), |
|||
'section': sectionId, |
|||
'text': newContent, |
|||
'tags': 'userRightsManager', |
|||
'summary': '/* User:' + userName + ' */ done' |
|||
}); |
|||
}); |
|||
} |
|||
})(); |
|||