User:PieWriter/vfd.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// <nowiki>
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
function getOrdinal(n) {
var s = ["th", "st", "nd", "rd"];
var v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
}
function getVfdSubpageTitle(api, pageName) {
var baseTitle = "Wikiquote:Votes for deletion/" + pageName;
return api.get({
action: 'query',
titles: baseTitle,
formatversion: 2
}).then(function (data) {
var page = data.query.pages[0];
if (page.missing) {
return baseTitle;
}
function checkNext(n) {
var candidate =
baseTitle + " (" + getOrdinal(n) + " nomination)";
return api.get({
action: 'query',
titles: candidate,
formatversion: 2
}).then(function (res) {
var p = res.query.pages[0];
if (p.missing) {
return candidate;
}
return checkNext(n + 1);
});
}
return checkNext(2);
});
}
function openDialog() {
var windowManager = new OO.ui.WindowManager();
$(document.body).append(windowManager.$element);
var dialog = new OO.ui.MessageDialog();
windowManager.addWindows([dialog]);
var radioSelect = new OO.ui.RadioSelectWidget({
items: [
new OO.ui.RadioOptionWidget({
data: 'spam',
label: 'Spam'
}),
new OO.ui.RadioOptionWidget({
data: 'vandalism',
label: 'Vandalism'
}),
new OO.ui.RadioOptionWidget({
data: 'empty',
label: 'Empty page'
}),
new OO.ui.RadioOptionWidget({
data: 'notable',
label: 'Not notable'
}),
new OO.ui.RadioOptionWidget({
data: 'oop',
label: 'Out of project scope'
}),
new OO.ui.RadioOptionWidget({
data: 'custom',
label: 'Custom reason'
})
]
});
var customInput = new OO.ui.MultilineTextInputWidget({
placeholder: 'Enter custom reason...',
autosize: true
});
var container = new OO.ui.PanelLayout({
padded: true,
expanded: false
});
container.$element.append(
new OO.ui.LabelWidget({
label: 'Select a reason:'
}).$element,
radioSelect.$element,
customInput.$element
);
windowManager.openWindow(dialog, {
title: 'Votes for Deletion',
message: container.$element,
actions: [
{
action: 'submit',
label: 'Nominate',
flags: ['primary', 'progressive']
},
{
action: 'cancel',
label: 'Cancel',
flags: 'safe'
}
]
}).closed.then(function (data) {
if (!data || data.action !== 'submit') {
return;
}
var selected = radioSelect.findSelectedItem();
if (!selected) {
mw.notify('Select a reason', {
type: 'error'
});
return;
}
var reasonMap = {
spam: 'Spam page',
vandalism: 'Vandalism',
empty: 'Empty page',
notable: 'Not notable',
oop: 'Out of project scope'
};
var reason = selected.getData() === 'custom'
? customInput.getValue()
: reasonMap[selected.getData()];
if (!reason) {
mw.notify('Provide a reason', {
type: 'error'
});
return;
}
var titleObj = new mw.Title(
mw.config.get('wgPageName')
);
var pageName = titleObj.getPrefixedText();
var api = new mw.Api();
var vfdSubpage = '';
getVfdSubpageTitle(api, pageName)
.then(function (targetSubpage) {
vfdSubpage = targetSubpage;
return api.get({
action: 'query',
prop: 'revisions',
titles: pageName,
rvprop: 'content',
formatversion: 2
});
})
.then(function (data) {
var page = data.query.pages[0];
var content =
(page.revisions && page.revisions[0])
? page.revisions[0].content
: "";
if (content.includes('{{vfd-new')) {
throw new Error("Already nominated");
}
return api.postWithToken('csrf', {
action: 'edit',
title: pageName,
text: "{{vfd-new}}\n" +
content.replace(/^\s+/, ''),
summary:
'Adding VFD with [[User:PieWriter/vfd|tool]]',
watchlist: 'watch'
});
})
.then(function () {
return api.postWithToken('csrf', {
action: 'edit',
title: vfdSubpage,
text:
"{{subst:vfd-new2|pg=" +
pageName +
"|text=" +
reason +
" — ~~~~}}",
summary: "VfD: " + pageName,
watchlist: 'watch'
});
})
/*
* Add the nominator vote.
*
* The old code attempted to insert the vote before
* the "Vote closes" line. This caused the vote to
* appear above the closure date.
*
* The vote is now added after the generated VFD
* content, leaving the closure date untouched.
*/
.then(function () {
return api.get({
action: 'query',
prop: 'revisions',
titles: vfdSubpage,
rvprop: 'content',
formatversion: 2
}).then(function (data) {
var page = data.query.pages[0];
if (
!page.revisions ||
!page.revisions[0]
) {
throw new Error(
"Could not retrieve VFD page"
);
}
var text =
page.revisions[0].content;
var voteText =
": '''Delete''' as nominator ~~~~";
/*
* Remove trailing whitespace and append
* the nominator vote.
*/
var newText =
text.replace(/\s+$/, '') +
"\n" +
voteText;
return api.postWithToken('csrf', {
action: 'edit',
title: vfdSubpage,
text: newText,
summary: "Adding nominator vote",
watchlist: 'watch'
});
});
})
.then(function () {
return api.get({
action: 'query',
prop: 'revisions',
titles: "Wikiquote:Votes for deletion",
rvprop: 'content',
formatversion: 2
}).then(function (data) {
var page = data.query.pages[0];
if (
!page.revisions ||
!page.revisions[0]
) {
throw new Error(
"Could not retrieve main VFD page"
);
}
var text =
page.revisions[0].content;
var cleanText =
text.replace(/\s+$/, '');
return api.postWithToken('csrf', {
action: 'edit',
title: "Wikiquote:Votes for deletion",
text:
cleanText +
"\n{{" +
vfdSubpage +
"}}",
summary:
"Adding " +
pageName +
" VfD entry",
watchlist: 'watch'
});
});
})
.then(function () {
mw.notify(
'VfD nomination complete',
{
type: 'success'
}
);
})
.catch(function (err) {
mw.notify(
err.message ||
'Error during VFD',
{
type: 'error'
}
);
});
});
}
function addLink() {
if (mw.config.get('wgNamespaceNumber') < 0) {
return;
}
var link = mw.util.addPortletLink(
'p-cactions',
'#',
'VFD',
'ca-vfd',
'Nominate for deletion'
);
if (!link) {
return;
}
$(link).on('click', function (e) {
e.preventDefault();
openDialog();
});
}
$(addLink);
});
// </nowiki>