User:DR/test.js: Difference between revisions
< User:DR
Content deleted Content added
Created page with "// <nowiki> (function() { 'use strict'; const config = window.clearDeleteReasonConfig || { applyOnlyOnMobile: true }; if (window.location.search.includes('action=delete') && (!config.applyOnlyOnMobile || /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent))) { // window.addEventListener('load', function() { // const reasonInput = document.querySelector('input[name="wpReason"]'); // if (reasonInput) { // r..." Tags: Mobile edit Mobile web edit |
No edit summary |
||
| (26 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
// |
//<nowiki> |
||
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () { |
|||
(function() { |
|||
'use strict'; |
|||
const page = 'User:DR/Global rename blacklist'; |
|||
const config = window.clearDeleteReasonConfig || { applyOnlyOnMobile: true }; |
|||
const api = new mw.Api(); |
|||
let token = null; |
|||
async function getToken() { |
|||
if (token) return token; |
|||
const res = await api.get({ |
|||
action: 'query', |
|||
meta: 'tokens', |
|||
type: 'csrf' |
|||
}); |
|||
token = res.query.tokens.csrftoken; |
|||
return token; |
|||
} |
|||
function BlacklistUserInputWidget() { |
|||
OO.ui.Widget.call(this); |
|||
this.textInput = new OO.ui.TextInputWidget({ |
|||
placeholder: 'Username to blacklist', |
|||
required: true, |
|||
rows: 1 |
|||
}); |
|||
this.regexInput = new OO.ui.TextInputWidget({ |
|||
placeholder: 'Regex (auto-generated, editable)', |
|||
required: true |
|||
}); |
|||
this.textInput.on('change', () => { |
|||
const val = this.textInput.getValue(); |
|||
if (val) { |
|||
this.regexInput.setValue('^' + val.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + '$'); |
|||
} else { |
|||
this.regexInput.setValue(''); |
|||
} |
|||
}); |
|||
this.textInput.$element.css('width', '48%'); |
|||
this.regexInput.$element.css('width', '48%').css('margin-left', '2%'); |
|||
this.layout = new OO.ui.HorizontalLayout({ |
|||
items: [ this.textInput, this.regexInput ] |
|||
}); |
|||
this.$element.addClass('blacklistUserInputWidget').css('margin-bottom', '5px'); |
|||
this.$element.append(this.layout.$element); |
|||
} |
|||
OO.inheritClass(BlacklistUserInputWidget, OO.ui.Widget); |
|||
function createUserField() { |
|||
if (window.location.search.includes('action=delete') && (!config.applyOnlyOnMobile || /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent))) { |
|||
return new BlacklistUserInputWidget(); |
|||
// window.addEventListener('load', function() { |
|||
} |
|||
// const reasonInput = document.querySelector('input[name="wpReason"]'); |
|||
// if (reasonInput) { |
|||
// reasonInput.value = ''; |
|||
// } |
|||
// }); |
|||
const observer = new MutationObserver(function(mutations) { |
|||
mutations.forEach(function(mutation) { |
|||
if (mutation.addedNodes.length) { |
|||
const reasonInput = document.querySelector('input[name="wpReason"]'); |
|||
if (reasonInput) { |
|||
reasonInput.value = ''; |
|||
observer.disconnect(); |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
function BlacklistDialog(config) { |
|||
observer.observe(document.body, { childList: true, subtree: true }); |
|||
BlacklistDialog.super.call(this, config); |
|||
} |
|||
} |
|||
})(); |
|||
OO.inheritClass(BlacklistDialog, OO.ui.ProcessDialog); |
|||
// </nowiki> |
|||
BlacklistDialog.static.name = 'BlacklistDialog'; |
|||
BlacklistDialog.static.title = 'Global rename blacklist'; |
|||
BlacklistDialog.static.actions = [ |
|||
{ action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] }, |
|||
{ action: 'cancel', label: 'Cancel', flags: 'safe' } |
|||
]; |
|||
BlacklistDialog.prototype.initialize = function () { |
|||
BlacklistDialog.super.prototype.initialize.apply(this, arguments); |
|||
const loggedInUser = mw.config.get('wgUserName'); |
|||
this.userFieldset = new OO.ui.FieldsetLayout({ label: 'User(s) to blacklist' }); |
|||
this.userFieldset.addItems([ createUserField() ]); |
|||
const addButton = new OO.ui.ButtonWidget({ |
|||
label: '+', |
|||
flags: ['progressive'] |
|||
}); |
|||
addButton.on('click', () => { |
|||
this.userFieldset.addItems([ createUserField() ]); |
|||
this.updateSize(); |
|||
}); |
|||
this.commentInput = new OO.ui.MultilineTextInputWidget({ |
|||
placeholder: 'Reason for blacklisting', |
|||
required: true, |
|||
rows: 2 |
|||
}); |
|||
this.expiryDropdown = new OO.ui.DropdownInputWidget({ |
|||
options: [ |
|||
{ data: '1m', label: '1 month' }, |
|||
{ data: '3m', label: '3 months' }, |
|||
{ data: '6m', label: '6 months' }, |
|||
{ data: '1y', label: '1 year' }, |
|||
{ data: '2y', label: '2 years' }, |
|||
{ data: 'infinite', label: 'No expiry' }, |
|||
{ data: 'custom', label: 'Custom…' } |
|||
], |
|||
value: '1m' |
|||
}); |
|||
this.customExpiryInput = new OO.ui.TextInputWidget({ |
|||
placeholder: 'Custom expiry (e.g., 2027-12-31, 18 months)', |
|||
disabled: true |
|||
}); |
|||
this.expiryDropdown.on('change', () => { |
|||
if (this.expiryDropdown.getValue() === 'custom') { |
|||
this.customExpiryInput.setDisabled(false); |
|||
} else { |
|||
this.customExpiryInput.setValue(''); |
|||
this.customExpiryInput.setDisabled(true); |
|||
} |
|||
}); |
|||
this.userBox = new OO.ui.TextInputWidget({value: loggedInUser, readOnly: true}); |
|||
this.content = new OO.ui.PanelLayout({ padded: true, expanded: false }); |
|||
this.content.$element.append( |
|||
new OO.ui.FieldsetLayout({ |
|||
items: [ |
|||
new OO.ui.FieldLayout(this.userBox, {label: 'Global renamer/Steward:', align: 'top'}), |
|||
this.userFieldset, |
|||
new OO.ui.FieldLayout(addButton), |
|||
new OO.ui.FieldLayout(this.commentInput, { label: 'Comment:', align: 'top' }), |
|||
new OO.ui.FieldLayout(this.expiryDropdown, { label: 'Expiry:', align: 'top' }), |
|||
new OO.ui.FieldLayout(this.customExpiryInput, { label: '', align: 'top' }) |
|||
] |
|||
}).$element |
|||
); |
|||
this.$body.append(this.content.$element); |
|||
}; |
|||
BlacklistDialog.prototype.getBodyHeight = function () { |
|||
return this.content.$element.outerHeight(true) + 20; |
|||
}; |
|||
BlacklistDialog.prototype.getActionProcess = function (action) { |
|||
if (action === 'accept') { |
|||
return new OO.ui.Process(async () => { |
|||
const widgets = this.userFieldset.items.filter(x => x instanceof BlacklistUserInputWidget); |
|||
const blacklistInputs = widgets.map(widget => ({ |
|||
username: widget.textInput.getValue().trim(), |
|||
regex: widget.regexInput.getValue().trim() |
|||
})); |
|||
const blacklistUsers = blacklistInputs.filter(u => u.username && u.regex); |
|||
const comment = this.commentInput.getValue().trim(); |
|||
if (!blacklistUsers.length) { |
|||
alert('Please enter at least one username and regex'); |
|||
return; |
|||
} |
|||
if (!comment) { |
|||
alert('Please enter a comment.'); |
|||
return; |
|||
} |
|||
const expiryMap = { |
|||
'1m': 1, '3m': 3, '6m': 6, '1y': 12, '2y': 24, 'infinite': 0 |
|||
}; |
|||
const expiryCode = this.expiryDropdown.getValue(); |
|||
let expiryTxt = ''; |
|||
if (expiryCode === 'custom') { |
|||
const val = this.customExpiryInput.getValue().trim(); |
|||
if (val) expiryTxt = ` - expires ${val}`; |
|||
} else if (expiryCode !== 'infinite') { |
|||
const now = new Date(); |
|||
now.setMonth(now.getMonth() + expiryMap[expiryCode]); |
|||
expiryTxt = ` - expires until ${now.toISOString().slice(0,10)}`; |
|||
} |
|||
const loggedInUser = mw.config.get('wgUserName'); |
|||
const today = new Date().toISOString().slice(0,10); |
|||
let entry = `\n# Added on ${today} by ${loggedInUser}${expiryTxt} - ${comment}\n`; |
|||
blacklistUsers.forEach(obj => { |
|||
entry += obj.regex + '\n'; |
|||
}); |
|||
if (!token) await getToken(); |
|||
const res = await api.get({ |
|||
action: 'query', |
|||
prop: 'revisions', |
|||
titles: page, |
|||
rvprop: 'content', |
|||
format: 'json' |
|||
}); |
|||
const pages = res.query.pages; |
|||
const data = pages[Object.keys(pages)[0]]; |
|||
let content = data.revisions[0]['*'] || data.revisions[0].content || ''; |
|||
const marker = '#\n #</pre> <!-- leave this line exactly as it is -->'; |
|||
const idx = content.indexOf(marker); |
|||
if (idx === -1) { |
|||
alert('Could not find insertion point in blacklist.'); |
|||
return; |
|||
} |
|||
const newContent = content.slice(0, idx) + entry + marker + content.slice(idx + marker.length); |
|||
await api.postWithToken('csrf', { |
|||
action: 'edit', |
|||
title: page, |
|||
text: newContent, |
|||
summary: '', |
|||
format: 'json' |
|||
}); |
|||
alert('Blacklist updated!'); |
|||
location.reload(); |
|||
this.close({ action: 'accept' }); |
|||
}); |
|||
} else if (action === 'cancel') { |
|||
return new OO.ui.Process(() => { |
|||
this.close({ action: 'cancel' }); |
|||
}); |
|||
} |
|||
}; |
|||
function init() { |
|||
if (mw.config.get('wgPageName') === 'User:DR/Global_rename_blacklist') { |
|||
mw.util.addPortletLink( |
|||
'p-tb', |
|||
'#', |
|||
'Global rename blacklist', |
|||
'gru-blacklist-dialog-portlet', |
|||
'Global rename blacklist' |
|||
); |
|||
$('#gru-blacklist-dialog-portlet').on('click', function (e) { |
|||
e.preventDefault(); |
|||
const windowManager = new OO.ui.WindowManager(); |
|||
$(document.body).append(windowManager.$element); |
|||
const dialog = new BlacklistDialog({ size: 'medium' }); |
|||
windowManager.addWindows([dialog]); |
|||
windowManager.openWindow(dialog); |
|||
}); |
|||
} |
|||
} |
|||
init(); |
|||
}); |
|||
//</nowiki> |
|||
Latest revision as of 06:46, 31 May 2025
//<nowiki>
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
'use strict';
const page = 'User:DR/Global rename blacklist';
const api = new mw.Api();
let token = null;
async function getToken() {
if (token) return token;
const res = await api.get({
action: 'query',
meta: 'tokens',
type: 'csrf'
});
token = res.query.tokens.csrftoken;
return token;
}
function BlacklistUserInputWidget() {
OO.ui.Widget.call(this);
this.textInput = new OO.ui.TextInputWidget({
placeholder: 'Username to blacklist',
required: true,
rows: 1
});
this.regexInput = new OO.ui.TextInputWidget({
placeholder: 'Regex (auto-generated, editable)',
required: true
});
this.textInput.on('change', () => {
const val = this.textInput.getValue();
if (val) {
this.regexInput.setValue('^' + val.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + '$');
} else {
this.regexInput.setValue('');
}
});
this.textInput.$element.css('width', '48%');
this.regexInput.$element.css('width', '48%').css('margin-left', '2%');
this.layout = new OO.ui.HorizontalLayout({
items: [ this.textInput, this.regexInput ]
});
this.$element.addClass('blacklistUserInputWidget').css('margin-bottom', '5px');
this.$element.append(this.layout.$element);
}
OO.inheritClass(BlacklistUserInputWidget, OO.ui.Widget);
function createUserField() {
return new BlacklistUserInputWidget();
}
function BlacklistDialog(config) {
BlacklistDialog.super.call(this, config);
}
OO.inheritClass(BlacklistDialog, OO.ui.ProcessDialog);
BlacklistDialog.static.name = 'BlacklistDialog';
BlacklistDialog.static.title = 'Global rename blacklist';
BlacklistDialog.static.actions = [
{ action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] },
{ action: 'cancel', label: 'Cancel', flags: 'safe' }
];
BlacklistDialog.prototype.initialize = function () {
BlacklistDialog.super.prototype.initialize.apply(this, arguments);
const loggedInUser = mw.config.get('wgUserName');
this.userFieldset = new OO.ui.FieldsetLayout({ label: 'User(s) to blacklist' });
this.userFieldset.addItems([ createUserField() ]);
const addButton = new OO.ui.ButtonWidget({
label: '+',
flags: ['progressive']
});
addButton.on('click', () => {
this.userFieldset.addItems([ createUserField() ]);
this.updateSize();
});
this.commentInput = new OO.ui.MultilineTextInputWidget({
placeholder: 'Reason for blacklisting',
required: true,
rows: 2
});
this.expiryDropdown = new OO.ui.DropdownInputWidget({
options: [
{ data: '1m', label: '1 month' },
{ data: '3m', label: '3 months' },
{ data: '6m', label: '6 months' },
{ data: '1y', label: '1 year' },
{ data: '2y', label: '2 years' },
{ data: 'infinite', label: 'No expiry' },
{ data: 'custom', label: 'Custom…' }
],
value: '1m'
});
this.customExpiryInput = new OO.ui.TextInputWidget({
placeholder: 'Custom expiry (e.g., 2027-12-31, 18 months)',
disabled: true
});
this.expiryDropdown.on('change', () => {
if (this.expiryDropdown.getValue() === 'custom') {
this.customExpiryInput.setDisabled(false);
} else {
this.customExpiryInput.setValue('');
this.customExpiryInput.setDisabled(true);
}
});
this.userBox = new OO.ui.TextInputWidget({value: loggedInUser, readOnly: true});
this.content = new OO.ui.PanelLayout({ padded: true, expanded: false });
this.content.$element.append(
new OO.ui.FieldsetLayout({
items: [
new OO.ui.FieldLayout(this.userBox, {label: 'Global renamer/Steward:', align: 'top'}),
this.userFieldset,
new OO.ui.FieldLayout(addButton),
new OO.ui.FieldLayout(this.commentInput, { label: 'Comment:', align: 'top' }),
new OO.ui.FieldLayout(this.expiryDropdown, { label: 'Expiry:', align: 'top' }),
new OO.ui.FieldLayout(this.customExpiryInput, { label: '', align: 'top' })
]
}).$element
);
this.$body.append(this.content.$element);
};
BlacklistDialog.prototype.getBodyHeight = function () {
return this.content.$element.outerHeight(true) + 20;
};
BlacklistDialog.prototype.getActionProcess = function (action) {
if (action === 'accept') {
return new OO.ui.Process(async () => {
const widgets = this.userFieldset.items.filter(x => x instanceof BlacklistUserInputWidget);
const blacklistInputs = widgets.map(widget => ({
username: widget.textInput.getValue().trim(),
regex: widget.regexInput.getValue().trim()
}));
const blacklistUsers = blacklistInputs.filter(u => u.username && u.regex);
const comment = this.commentInput.getValue().trim();
if (!blacklistUsers.length) {
alert('Please enter at least one username and regex');
return;
}
if (!comment) {
alert('Please enter a comment.');
return;
}
const expiryMap = {
'1m': 1, '3m': 3, '6m': 6, '1y': 12, '2y': 24, 'infinite': 0
};
const expiryCode = this.expiryDropdown.getValue();
let expiryTxt = '';
if (expiryCode === 'custom') {
const val = this.customExpiryInput.getValue().trim();
if (val) expiryTxt = ` - expires ${val}`;
} else if (expiryCode !== 'infinite') {
const now = new Date();
now.setMonth(now.getMonth() + expiryMap[expiryCode]);
expiryTxt = ` - expires until ${now.toISOString().slice(0,10)}`;
}
const loggedInUser = mw.config.get('wgUserName');
const today = new Date().toISOString().slice(0,10);
let entry = `\n# Added on ${today} by ${loggedInUser}${expiryTxt} - ${comment}\n`;
blacklistUsers.forEach(obj => {
entry += obj.regex + '\n';
});
if (!token) await getToken();
const res = await api.get({
action: 'query',
prop: 'revisions',
titles: page,
rvprop: 'content',
format: 'json'
});
const pages = res.query.pages;
const data = pages[Object.keys(pages)[0]];
let content = data.revisions[0]['*'] || data.revisions[0].content || '';
const marker = '#\n #</pre> <!-- leave this line exactly as it is -->';
const idx = content.indexOf(marker);
if (idx === -1) {
alert('Could not find insertion point in blacklist.');
return;
}
const newContent = content.slice(0, idx) + entry + marker + content.slice(idx + marker.length);
await api.postWithToken('csrf', {
action: 'edit',
title: page,
text: newContent,
summary: '',
format: 'json'
});
alert('Blacklist updated!');
location.reload();
this.close({ action: 'accept' });
});
} else if (action === 'cancel') {
return new OO.ui.Process(() => {
this.close({ action: 'cancel' });
});
}
};
function init() {
if (mw.config.get('wgPageName') === 'User:DR/Global_rename_blacklist') {
mw.util.addPortletLink(
'p-tb',
'#',
'Global rename blacklist',
'gru-blacklist-dialog-portlet',
'Global rename blacklist'
);
$('#gru-blacklist-dialog-portlet').on('click', function (e) {
e.preventDefault();
const windowManager = new OO.ui.WindowManager();
$(document.body).append(windowManager.$element);
const dialog = new BlacklistDialog({ size: 'medium' });
windowManager.addWindows([dialog]);
windowManager.openWindow(dialog);
});
}
}
init();
});
//</nowiki>