User:TheAstorPastor/common.js: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
Undo revision 60262 by TheAstorPastor (talk) Tags: Replaced Undo Reverted |
No edit summary Tag: Reverted |
||
| Line 1: | Line 1: | ||
// 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() { |
|||
//importScript('User:Joepayne/grantBureaucrat.js'); // Backlink: [[User:Joepayne/grantBureaucrat.js]] |
|||
// Only run on the Request for Permissions page or test pages |
|||
importScript('User:Joepayne/stripRights.js'); // Backlink: [[User:Joepayne/stripRights.js]] |
|||
if (mw.config.get('wgPageName') !== 'Test_Wiki:Request_for_permissions' && !mw.config.get('wgPageName').includes('URMTW-TESTPAGE-RFP')) { |
|||
//importScript('User:MacFan4000/grantAdmin.js'); // Backlink: [[User:MacFan4000/grantAdmin.js]] |
|||
return; |
|||
//importScript('User:Kiteretsu/js/all-in-one.js'); // Backlink: [[User:Kiteretsu/js/all-in-one.js]] |
|||
} |
|||
//importScript('User:DodoMan/chatbot.js'); // Backlink: [[User:DodoMan/chatbot.js]] |
|||
importScript('User:JJBullet/findInactiveSysops.js'); // Backlink: [[User:JJBullet/findInactiveSysops.js]] |
|||
// Check if user has appropriate permissions |
|||
importScript('User:Harvici/find-archived-section.js'); // Backlink: [[User:Harvici/find-archived-section.js]] |
|||
if (!mw.config.get('wgUserGroups').includes('sysop') && !mw.config.get('wgUserGroups').includes('bureaucrat')) { |
|||
importScript('User:Harvici/UTCLiveClock.js'); // Backlink: [[User:Harvici/UTCLiveClock.js]] |
|||
console.log('User Rights Manager: You need to be a sysop to use this tool.'); |
|||
importScript('User:Harvici/Twinkle-preferences-toolbar.js'); // Backlink: [[User:Harvici/Twinkle-preferences-toolbar.js]] |
|||
return; |
|||
importScript('User:Kiteretsu/rollbackSum.js'); // Backlink: [[User:Kiteretsu/rollbackSum.js]] |
|||
} |
|||
importScript('User:Kiteretsu/DiscussionCloser.js'); // Backlink: [[User:Kiteretsu/DiscussionCloser.js]] |
|||
importScript('User:TheAstorPastor/VisualEditorEverywhere.js'); // Backlink: [[User:TheAstorPastor/VisualEditorEverywhere.js]] |
|||
// 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:53, 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:53, 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:53, 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:53, 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:53, 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' |
|||
}); |
|||
}); |
|||
} |
|||
})(); |
|||
Revision as of 13:53, 11 April 2025
// 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:53, 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:53, 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:53, 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:53, 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:53, 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'
});
});
}
})();