MediaWiki:AFC-submit-wizard.js: Difference between revisions

Content deleted Content added
apply caching in json load
improve code structure, fix bugs, other fixes + usability improvements
Line 17:
$.ready,
mw.loader.using([
'mediawiki.util', 'mediawiki.api', 'mediawiki.Title',
'mediawiki.widgets', 'oojs-ui-core', 'oojs-ui-widgets'
])
).then(function () {
if (mw.config.get('wgPageName') !== 'Wikipedia:Articles_for_creation/Submitting' ||
 
if ( mw.config.get('wgPageNamewgAction') !== 'Wikipedia:Articles_for_creation/Submittingview') {
return;
}
if (mw.util.getParamValue('withJS') !== 'MediaWiki:AFC-submit-wizard.js') {
return;
}
init();
});
 
var afc = {}, ui = {};
window.afc = afc;
 
function init() {
$('#firstHeading').text('Submitting your draft ...');
document.title = 'Submitting your draft ...';
Line 47 ⟶ 49:
// Two different API objects so that aborts on the lookupApi don't stop the final
// evaluate process
var lookupApiafc.api = new mw.Api(apiOptions),;
submitApi afc.lookupApi = new mw.Api(apiOptions);
 
constructUI();
var draftLayout, talkTagsLayout, shortdescLayout, topicsLayout, submitLayout, draftInput, talkTagsInput, shortdescInput, topicsInput, submitButton, mainStatusLayout, mainStatusArea, talkStatusLayout, talkStatusArea, rawClassLayout, rawClass;
}
 
function constructUI() {
// global
var pagetext, talktext, oresTopics;
 
ui.fieldset = new OO.ui.FieldsetLayout({
// Create the UI
var fieldset = new OO.ui.FieldsetLayout({
label: 'Submit your draft for review at Articles for Creation (AfC)',
classes: [ 'container' ],
items: [
ui.draftLayout = new OO.ui.FieldLayout(ui.draftInput = new mw.widgets.TitleInputWidget({
value: (mw.util.getParamValue('draft') || '').replace(/_/g, ' '),
placeholder: 'Enter the draft title, begins with "Draft:" or "User:"'
Line 70 ⟶ 71:
}),
 
ui.rawClassLayout = new OO.ui.FieldLayout(ui.rawClass = new OO.ui.RadioSelectInputWidget(), {
label: 'Choose the most appropriate category',
help: 'For biographies about scholars, choose one of the two biography categories rather than one associated to their field',
align: 'inline',
}),
 
ui.shortdescLayout = new OO.ui.FieldLayout(ui.shortdescInput = new OO.ui.TextInputWidget({
placeholder: 'Briefly describe the subject in 2–5 words (eg. "British astronomer", "Cricket stadium in India")',
maxLength: 100
Line 83 ⟶ 84:
align: 'top',
help: 'Try not to exceed 40 characters',
helpInline: true,
}),
 
ui.talkTagsLayout = new OO.ui.FieldLayout(ui.talkTagsInput = new OO.ui.MenuTagMultiselectWidget({
placeholder: 'Start typing to search for tags ...',
tagLimit: 10,
Line 98 ⟶ 99:
align: 'top',
help: 'Adding the 1–4 most applicable WikiProjects is plenty. For example, if you add the Physics tag, you do not need to also add the Science tag.',
helpInline: true,
}),
 
// This is shown only if the ORES topic lookup fails, or is inconclusive
ui.topicsLayout = new OO.ui.FieldLayout(ui.topicsInput = new OO.ui.MenuTagMultiselectWidget({
placeholder: 'Start typing to search for topics ...',
tagLimit: 10,
autocomplete: false, // XXX: doesn't seem to work
options: [ "biography", "women", "food-and-drink", "internet-culture", "linguistics", "literature", "books", "entertainment", "films", "media", "music", "radio", "software", "television", "video-games", "performing-arts", "philosophy-and-religion", "sports", "architecture", "comics-and-anime", "fashion", "visual-arts", "geographical", "africa", "central-africa", "eastern-africa", "northern-africa", "southern-africa", "western-africa", "central-america", "north-america", "south-america", "asia", "central-asia", "east-asia", "north-asia", "south-asia", "southeast-asia", "west-asia", "eastern-europe", "europe", "northern-europe", "southern-europe", "western-europe", "oceania", "business-and-economics", "education", "history", "military-and-warfare", "politics-and-government", "society", "transportation", "biology", "chemistry", "computing", "earth-and-environment", "engineering", "libraries-and-information", "mathematics", "medicine-and-health", "physics", "stem", "space", "technology" ].map(function (e) {
return {
data: e,
Line 119 ⟶ 120:
}),
 
ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({
label: 'Submit',
flags: [ 'progressive', 'primary' ],
})),
 
ui.infoLayout = new OO.ui.FieldLayout(new OO.ui.LabelWidget({
label: $('<div>')
.append(linkify('<small>If you are not sure about what to enter in a field, you can skip it. If you need further help, ' +
'you can ask at the <b>[[WP:AFCHD|AfC help desk]]</b> or get <b>[[WP:IRCHELP|live help]]</b>. Facing some issues in using this form? [[WT:WPAFC|Report it]].</small>'))
}), {
align: 'top'
}),
]
});
 
afc.topicOptionsLoaded = getJSONPage('Wikipedia:WikiProject Articles for creation/AfC topic map.json').then(function (optionsJson) {
// Load a JSON page from the wiki
function fetchJsonData(page) {
return $.getJSON("/w/api.php?action=query&format=json&formatversion=2" +
"&titles=" + encodeURIComponent(page) + "&prop=revisions&rvprop=content" +
"&uselang=content&maxage=86400&smaxage=86400" // parameters to force caching
).then(function(apiResponse) {
return JSON.parse(apiResponse.query.pages[0].revisions[0].content);
});
}
 
 
var topicOptionsLoaded = $.Deferred();
fetchJsonData('Wikipedia:WikiProject Articles for creation/AfC topic map.json').then(function(optionsJson) {
var options = [];
$.each(optionsJson, function (code, info) {
options.push({
label: info.label,
Line 147 ⟶ 143:
});
});
ui.rawClass.setOptions(options);
ui.rawClass.setValue('o');
 
// putresolve promise with allowed option codes in promise resolution:
topicOptionsLoaded.resolve(return options.map(function (op) {
return op.data;
}));
});
 
ui.topicsLayout.toggle(false);
 
var asUser = mw.util.getParamValue('username');
if (asUser && asUser !== mw.config.get('wgUserName')) {
ui.fieldset.addItems([
new OO.ui.FieldLayout(new OO.ui.MessageWidget({
type: 'notice',
Line 166 ⟶ 162:
label: 'Submitting as User:' + asUser
}))
], /* position */ 65); // just before submit button
}
 
// Attach
$('.mw-ui-button').parent().replaceWith(fieldset.$element);
$('#afc-submit-wizard-container').empty().append(ui.fieldset.$element);
 
// populatePopulate talk page tags for multi-select widget
afc.talkTagOptionsLoaded = getJSONPage('Wikipedia:WikiProject Articles for creation/WikiProject templates.json').then(function (data) {
var talkTagOptionsLoaded = $.Deferred();
ui.talkTagsInput.addOptions(Object.keys(data).map(function (k) {
fetchJsonData('Wikipedia:WikiProject Articles for creation/WikiProject templates.json').then(function (data) {
talkTagsInput.addOptions(Object.keys(data).map(function (k) {
return {
data: data[k],
Line 180 ⟶ 176:
};
}));
talkTagOptionsLoaded.resolve();
});
 
// Get mapping of infoboxes with relevant WikiProjects
afc.ibxmapLoaded = getJSONPage('Wikipedia:WikiProject Articles for creation/Infobox WikiProject map.json');
var ibxmapLoaded = $.Deferred();
fetchJsonData('Wikipedia:WikiProject Articles for creation/Infobox WikiProject map.json').then(function (data) {
ibxmapLoaded.resolve(data);
});
 
submitButtonui.$elementsubmitButton.on('click', evaluate);
ui.draftInput.on('change', mw.util.debounce(500, onDraftInputChange));
 
if (mw.util.getParamValue('draft')) {
Line 198 ⟶ 190:
// The default font size in monobook and modern are too small at 10px
mw.util.addCSS('.skin-modern .projectTagOverlay, .skin-monobook .projectTagOverlay { font-size: 130%; }');
}
 
function onDraftInputChange() {
afc.lookupApi.abort(); // abort older API requests
 
var drafttitle = ui.draftInput.getValue().trim();
if (!drafttitle) { // empty
return;
}
debug('draft input changed: "' + ui.draftInput.getValue() + '"');
 
// re-initialize
console.log('draft input changed: "' + draftInput.getValue() + '"');
ui.draftLayout.setErrors([]);
ui.draftLayout.setWarnings([]);
afc.oresTopics = null;
afc.talktext = null;
afc.pagetext = null;
 
afc.talkTagOptionsLoaded.then(function () {
// re-initialize
// Clear selection
draftLayout.setErrors([]);
ui.talkTagsInput.setValue([]);
draftLayout.setWarnings([]);
});
oresTopics = null;
talktext = null;
pagetext = null;
 
afc.lookupApi.get({
talkTagOptionsLoaded.then(function () {
"action": "query",
talkTagsInput.setValue([]);
"prop": "revisions|description|info",
});
"titles": drafttitle,
"rvprop": "content",
"rvslots": "main"
}).then(setPrefillsFromPageData);
 
var titleObj = mw.Title.newFromText(drafttitle);
lookupApi.get({
if (!titleObj || titleObj.isTalkPage()) {
"action": "query",
return;
"prop": "revisions|description|info",
}
"titles": drafttitle,
var talkpagename = titleObj.getTalkPage().toText();
"rvprop": "content",
afc.lookupApi.get({
"rvslots": "main"
"action": "query",
}).then(function (json) {
"prop": "revisions",
console.log(json);
"titles": talkpagename,
var page = json.query.pages[0];
"rvprop": "content",
var preNormalizedTitle = json.query.normalized && json.query.normalized[0] &&
"rvslots": "main",
json.query.normalized[0].from;
}).then(setPrefillsFromTalkPageData);
console.log('page.title: "' + page.title + '"');
if (draftInput.getValue() !== (preNormalizedTitle || page.title)) {
return; // user must have changed the title already
}
if (!page || page.invalid) {
draftLayout.setErrors(['Please check draft title. This title is invalid.']);
return;
}
if (page.missing) {
draftLayout.setErrors(['Please check draft title. No such draft exists.']);
return;
}
pagetext = page.revisions[0].slots.main.content;
 
}
// Show no refs warning
if (!/<ref>/.test(pagetext) && !/\{\{[Ss]fn\}\}/.test(pagetext)) {
draftLayout.setWarnings([
new OO.ui.HtmlSnippet('This draft doesn\'t appear to contain any references. Please add references, without this it will almost certainly be declined. See <a href="/wiki/Help:Introduction_to_referencing_with_Wiki_Markup/2" target="_blank">help on adding references</a>.')
]);
}
// set main category
var topicMatch = pagetext.match(/\{\{AFC topic\|(.*?)\}\}/);
if (topicMatch) {
topicOptionsLoaded.then(function(allowedCodes) {
var topic = topicMatch[1];
console.log(topic);
console.log(allowedCodes);
// if the code found in the template is an invalid one, keep the default to "other",
// rather than the first item in the list
if (allowedCodes.indexOf(topic) !== -1) {
rawClass.setValue(topic);
} else {
rawClass.setValue('o');
}
});
} else {
rawClass.setValue('o');
}
 
function setPrefillsFromPageData(json) {
// set shortdesc in form
debug('page fetch query', json);
shortdescInput.setValue(page.description || '');
var page = json.query.pages[0];
var preNormalizedTitle = json.query.normalized && json.query.normalized[0] &&
json.query.normalized[0].from;
debug('page.title: "' + page.title + '"');
if (ui.draftInput.getValue() !== (preNormalizedTitle || page.title)) {
return; // user must have changed the title already
}
if (!page || page.invalid) {
ui.draftLayout.setErrors(['Please check draft title. This title is invalid.']);
return;
}
if (page.missing) {
ui.draftLayout.setErrors(['Please check draft title. No such draft exists.']);
return;
}
afc.pagetext = page.revisions[0].slots.main.content;
 
// Show no refs warning
// guess wikiproject tags from infoboxes on the page
if (!/<ref/i.test(afc.pagetext) && !/\{\{([Ss]fn|[Hh]arv)/.test(afc.pagetext)) {
$.when(ibxmapLoaded, talkTagOptionsLoaded).then(function (ibxmap) {
ui.draftLayout.setWarnings([
var infoboxRgx = /\{\{([Ii]nfobox [^|}]*)/g,
new OO.ui.HtmlSnippet(linkify("This draft doesn't appear to contain any references. Please add references, without which it might be declined. See [[Help:Introduction_to_referencing_with_Wiki_Markup/2|help on adding references]]."))
wikiprojects = [],
match]);
}
while (match = infoboxRgx.exec(pagetext)) { // jshint ignore:line
var ibx = match[1].trim();
if (ibxmap[ibx]) {
wikiprojects = wikiprojects.concat(ibxmap[ibx]);
}
}
console.log('wikiprojects from infobox: ', wikiprojects);
console.log('setValue1:', talkTagsInput.getValue().concat(wikiprojects));
talkTagsInput.setValue(talkTagsInput.getValue().concat(wikiprojects));
});
 
// fill ORES topics
getOresTopics(page.lastrevid).then(function (topics) {
console.log('ORES topics: ', topics);
if (!topics || !topics.length) { // unexpected API response or API returns unsorted
topicsLayout.toggle(true);
} else {
topicsLayout.toggle(false);
oresTopics = topics;
}
}, function () {
topicsLayout.toggle(true);
});
 
// Set AfC topic category
var topicMatch = afc.pagetext.match(/\{\{AfC topic\|(.*?)\}\}/);
if (topicMatch) {
afc.topicOptionsLoaded.then(function(allowedCodes) {
var topic = topicMatch[1];
debug("Allowed topic codes fetched:", allowedCodes);
debug("AfC topic found:", topic);
// if the code found in the template is an invalid one, keep the default to "other",
// rather than the first item in the list
if (allowedCodes.indexOf(topic) !== -1) {
ui.rawClass.setValue(topic);
} else {
ui.rawClass.setValue('o');
}
});
} else {
ui.rawClass.setValue('o');
}
 
// Set short description in form
ui.shortdescInput.setValue(page.description || '');
 
// Guess WikiProject tags from infoboxes on the page
var titleObj = mw.Title.newFromText(drafttitle);
$.when(afc.ibxmapLoaded, afc.talkTagOptionsLoaded).then(function (ibxmap) {
if (!titleObj || titleObj.isTalkPage()) {
var infoboxRgx = /\{\{([Ii]nfobox [^|}]*)/g,
return;
wikiprojects = [],
}
match;
var talkpagename = titleObj.getTalkPage().toText();
while (match = infoboxRgx.exec(afc.pagetext)) {
console.log(talkpagename);
var ibx = match[1].trim();
lookupApi.get({
if (ibxmap[ibx]) {
"action": "query",
wikiprojects = wikiprojects.concat(ibxmap[ibx]);
"prop": "revisions",
"titles": talkpagename,
"rvprop": "content",
"rvslots": "main",
}).then(function (json) {
var talkpage = json.query.pages[0];
if (!talkpage || talkpage.missing) {
return;
}
}
talktext = talkpage.revisions[0].slots.main.content;
debug('wikiprojects from infobox: ', wikiprojects);
console.log(talktext);
ui.talkTagsInput.setValue(ui.talkTagsInput.getValue().concat(wikiprojects));
});
 
// Fill ORES topics
var existingWikiProjects = extractWikiProjectTagsFromText(talktext);
var existingTags = existingWikiProjects getOresTopics(page.lastrevid).mapthen(function (etopics) {
debug('ORES topics: ', topics);
return e.name;
if (!topics || !topics.length) { // unexpected API response or API returns unsorted
});
ui.topicsLayout.toggle(true);
talkTagOptionsLoaded.then(function () {
} else {
console.log('setValue2:', talkTagsInput.getValue().concat(existingTags));
ui.topicsLayout.toggle(false);
talkTagsInput.setValue(talkTagsInput.getValue().concat(existingTags));
afc.oresTopics = topics;
});
}
}, function () {
ui.topicsLayout.toggle(true);
});
}
 
function setPrefillsFromTalkPageData (json) {
console.log(existingTags);
var talkpage = json.query.pages[0];
if (!talkpage || talkpage.missing) {
return;
}
afc.talktext = talkpage.revisions[0].slots.main.content;
debug(afc.talktext);
 
var existingWikiProjects = extractWikiProjectTagsFromText(afc.talktext);
});
var existingTags = existingWikiProjects.map(function (e) {
return e.name;
});
afc.talkTagOptionsLoaded.then(function () {
ui.talkTagsInput.setValue(ui.talkTagsInput.getValue().concat(existingTags));
});
 
debug(existingTags);
}
}
 
function getOresTopics(revid) {
return $.get('https://ores.wikimedia.org/v3/scores/enwiki/?models=drafttopic&revids=' + revid).then(function (json) {
 
// null is returned if at any point something in the API output is unexpected
// ES2020 has optional chaining, but of course on MediaWiki we're still stuck with ES5
return json &&
json.enwiki &&
json.enwiki.scores &&
json.enwiki.scores[revid] &&
json.enwiki.scores[revid].drafttopic &&
json.enwiki.scores[revid].drafttopic.score &&
(json.enwiki.scores[revid].drafttopic.score.prediction instanceof Array) &&
json.enwiki.scores[revid].drafttopic.score.prediction.map(function (topic, idx, topics) {
// Remove Asia.Asia* if Asia.South-Asia is present (example)
if (topic.slice(-1) === '*') {
var metatopic = topic.split('.').slice(0, -1).join('.');
for (var i = 0; i < topics.length; i++) {
if (topics[i] !== topic && topics[i].startsWith(metatopic)) {
return;
}
}
return metatopic.split('.').pop();
}
return topicmetatopic.split('.').pop();
})
return topic.split('.').pop();
})
.filter(function (e) {
return e; // filter out undefined from above
Line 378 ⟶ 369:
.replace(/&/g, 'and');
});
});
}
 
function extractWikiProjectTagsFromText(text) {
if (!text) {
return [];
}
 
// this is best-effort, no guaranteed accuracy
function extractWikiProjectTagsFromText(text) {
var existingTags = [];
if (!text) {
var rgx = /\{\{(WikiProject [^|}]*).*?\}\}/g;
return [];
var match;
while (match = rgx.exec(text)) { // jshint ignore:line
var tag = match[1].trim();
if (tag === 'WikiProject banner shell') {
continue;
}
existingTags.push({
wikitext: match[0],
name: tag
});
}
return existingTags;
}
 
function evaluate() {
// this is best-effort, no guaranteed accuracy
 
var existingTags = [];
if (!ui.mainStatusLayout || !ui.mainStatusLayout.isElementAttached()) {
var rgx = /\{\{(WikiProject [^|}]*).*?\}\}/g;
ui.fieldset.addItems([
var match;
ui.mainStatusLayout = new OO.ui.FieldLayout(ui.mainStatusArea = new OO.ui.MessageWidget({
while (match = rgx.exec(text)) { // jshint ignore:line
type: 'notice',
var tag = match[1].trim();
label: 'Processing ...'
if (tag === 'WikiProject banner shell') {
continue;}))
}]);
existingTags.push({
wikitext: match[0],
name: tag
});
}
return existingTags;
}
 
ui.submitButton.setDisabled(true);
function evaluate() {
 
var draft = ui.draftInput.getValue();
if (!mainStatusLayout || !mainStatusLayout.isElementAttached()) {
debug(draft);
fieldset.addItems([
 
mainStatusLayout = new OO.ui.FieldLayout(mainStatusArea = new OO.ui.MessageWidget({
afc.api.get({
type: 'notice',
"action": "query",
label: 'Processing ...'
"prop": "revisions|description",
}))
"titles": draft,
]);
"rvprop": "content",
"rvslots": "main"
}).then(function (json) {
var page = json.query.pages[0];
if (!page || page.invalid || page.missing) {
ui.draftLayout.setErrors(['Please check draft title. No such draft exists.']);
ui.fieldset.removeItems([ui.mainStatusLayout]);
ui.submitButton.setDisabled(false);
return;
}
var text = page.revisions[0].slots.main.content;
 
var draftheader = draftInput.getValue()'';
console.log(draft);
 
submitApi.get({
"action": "query",
"prop": "revisions",
"titles": draft,
"rvprop": "content",
"rvslots": "main"
}).then(function (json) {
var page = json.query.pages[0];
if (!page || page.invalid || page.missing) {
draftLayout.setErrors(['Please check draft title. No such draft exists.']);
fieldset.removeItems([mainStatusLayout]);
return;
}
var text = page.revisions[0].slots.main.content;
 
// Handle short description
var header = '';
var shortDescTemplateExists = /\{\{[Ss]hort ?desc(ription)?\s*\|/.test(text);
var shortDescExists = !!page.description;
var existingShortDesc = page.description;
 
if (ui.shortdescInput.getValue()) {
// add shortdesc
// 1. No shortdesc - insert the one provided by user
if (shortdescInput.getValue()) {
if (!shortDescExists) {
text = text.replace(/\{\{[Ss]hort description\|.*?\}\}\n*/g, '');
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n';
}
 
// 2. Shortdesc exists from {{short description}} template - replace it
// draft topics
} else if (shortDescExists && shortDescTemplateExists) {
console.log(topicsInput);
text = text.replace(/\{\{[Ss]hort ?desc(ription)?\s*\|.*?\}\}\n*/g, '');
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n';
 
// 3.Shortdesc exists, but not generated by {{short description}}, if the user
if (topicsLayout.isVisible()) {
// has changed the value, save the new value
oresTopics = topicsInput.getValue();
} else if (shortDescExists && existingShortDesc !== ui.shortdescInput.getValue()) {
}
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n';
if (oresTopics.length) {
 
text = text.replace(/\{\{[Dd]raft topics\|.*?\}\}\n*/g, '');
// 4. Shortdesc exists, but not generated by {{short description}}, and user hasn't changed the value
header += '{{Draft topics|' + oresTopics.join('|') + '}}\n';
} else {
// Do nothing
}
} else {
// User emptied the shortdesc field (or didn't exist from before): remove any existing shortdesc.
// This doesn't remove any that are generated by other templates
// Race condition (FIXME): if someone else added a shortdesc to the draft after this user opened the wizard,
// that shortdesc gets removed
text = text.replace(/\{\{[Ss]hort ?desc(ription)?\s*\|.*?\}\}\n*/g, '');
}
 
text = text.replace(/\{\{AFC topic\|(.*?)\}\}/g, '');
header += '{{AFC topic|' + rawClass.getValue() + '}}\n';
 
// Draft topics
// put AFC submission template
debug(ui.topicsInput);
header += '{{subst:submit|' + (mw.util.getParamValue('username') || mw.config.get('wgUserName')) + '}}\n';
if (ui.topicsLayout.isVisible()) {
afc.oresTopics = ui.topicsInput.getValue();
}
if (afc.oresTopics.length) {
text = text.replace(/\{\{[Dd]raft topics\|.*?\}\}\n*/g, '');
header += '{{Draft topics|' + afc.oresTopics.join('|') + '}}\n';
}
 
// insertAdd everythingAfC to the toptopic
text = headertext.replace(/\{\{AfC +topic\|(.*?)\}\}/g, text'');
header += '{{AfC topic|' + ui.rawClass.getValue() + '}}\n';
 
// put AfC submission template
console.log(text);
header += '{{subst:submit|' + (mw.util.getParamValue('username') || mw.config.get('wgUserName')) + '}}\n';
 
// insert everything to the top
mainStatusArea.setType('notice');
text = header + text;
mainStatusArea.setLabel('Saving draft page ...');
debug(text);
 
ui.mainStatusArea.setType('notice');
// saving draft page
ui.mainStatusArea.setLabel('Saving draft page ...');
submitApi.postWithEditToken({
"action": "edit",
"title": draft,
"text": text,
"summary": 'Submitting using [[MediaWiki:AFC-submit-wizard.js|AFC-submit-wizard]])'
}).then(function (data) {
if (data.edit && data.edit.result === 'Success') {
mainStatusArea.setType('success');
mainStatusArea.setLabel('Submission succeeded. Redirecting you to the draft page ...');
 
// saving draft page
setTimeout(function () {
afc.api.postWithEditToken({
___location.href = mw.util.getUrl(draft);
"action": "edit",
}, 1000);
}"title": else {draft,
"text": text,
return $.Deferred().reject('unexpected-result');
"summary": 'Submitting using [[WP:AFCSW|AfC-submit-wizard]])'
}
}).catchthen(function (errdata) {
if (data.edit && data.edit.result === 'Success') {
mainStatusArea.setType('error');
ui.mainStatusArea.setLabelsetType('An error occurred (' + err + '). Please try again or refer to the help desk.success');
ui.mainStatusArea.setLabel('Submission succeeded. Redirecting you to the draft page ...');
});
 
setTimeout(function () {
fieldset.addItems([
___location.href = mw.util.getUrl(draft);
talkStatusLayout = new OO.ui.FieldLayout(talkStatusArea = new OO.ui.MessageWidget({
}, 1000);
type: 'notice',
} else {
label: 'Saving draft talk page ...'
return $.Deferred().reject('unexpected-result');
}))
]);}
}).catch(function (err) {
ui.mainStatusArea.setType('error');
ui.mainStatusArea.setLabel('An error occurred (' + err + '). Please try again or refer to the help desk.');
ui.submitButton.setDisabled(false);
});
 
ui.fieldset.addItems([
// Process text of the talk page
ui.talkStatusLayout = new OO.ui.FieldLayout(ui.talkStatusArea = new OO.ui.MessageWidget({
var alreadyExistingWikiProjects = extractWikiProjectTagsFromText(talktext);
type: 'notice',
var alreadyExistingTags = alreadyExistingWikiProjects.map(function (e) {
label: 'Saving draft talk page ...'
return e.name;
});)
]);
var tagsToAdd = talkTagsInput.getValue().filter(function (tag) {
return alreadyExistingTags.indexOf(tag) === -1;
});
var tagsToRemove = alreadyExistingTags.filter(function (tag) {
return talkTagsInput.getValue().indexOf(tag) === -1;
});
 
tagsToRemove.forEach(function (tag) {
talktext = talktext.replace(new RegExp('\\{\\{\\s*' + tag + '\\s*(\\|.*?)?\\}\\}\\n?'), '');
});
 
// Process text of the talk page
var tagsToAddText = tagsToAdd.map(function (tag) {
var alreadyExistingWikiProjects = extractWikiProjectTagsFromText(afc.talktext);
return '{{' + tag + '}}';
var alreadyExistingTags = alreadyExistingWikiProjects.map(function (e) {
}).join('\n') + (tagsToAdd.length ? '\n' : '');
return e.name;
});
var tagsToAdd = ui.talkTagsInput.getValue().filter(function (tag) {
return alreadyExistingTags.indexOf(tag) === -1;
});
var tagsToRemove = alreadyExistingTags.filter(function (tag) {
return ui.talkTagsInput.getValue().indexOf(tag) === -1;
});
 
tagsToRemove.forEach(function (tag) {
talktext = tagsToAddText + (talktext || '');
afc.talktext = afc.talktext.replace(new RegExp('\\{\\{\\s*' + tag + '\\s*(\\|.*?)?\\}\\}\\n?'), '');
});
 
var tagsToAddText = tagsToAdd.map(function (tag) {
submitApi.postWithEditToken({
return '{{' + tag + '}}';
"action": "edit",
}).join('\n') + (tagsToAdd.length ? '\n' : '');
"title": new mw.Title(draft).getTalkPage().toText(),
"text": talktext,
"summary": 'Adding WikiProject tags using [[MediaWiki:AFC-submit-wizard.js|AFC-submit-wizard]])'
}).then(function (data) {
if (data.edit && data.edit.result === 'Success') {
talkStatusArea.setType('success');
talkStatusArea.setLabel('Successfully added WikiProject tags to talk page');
} else {
return $.Deferred().reject('unexpected-result');
}
}).catch(function (err) {
talkStatusArea.setType('error');
talkStatusArea.setLabel('An error occurred in editing the talk page (' + err + ').');
});
 
afc.talktext = tagsToAddText + (afc.talktext || '');
 
afc.api.postWithEditToken({
"action": "edit",
"title": new mw.Title(draft).getTalkPage().toText(),
"text": afc.talktext,
"summary": 'Adding WikiProject tags using [[WP:AFCSW|AfC-submit-wizard]])'
}).then(function (data) {
if (data.edit && data.edit.result === 'Success') {
ui.talkStatusArea.setType('success');
ui.talkStatusArea.setLabel('Successfully added WikiProject tags to talk page');
} else {
return $.Deferred().reject('unexpected-result');
}
}).catch(function (err) {
mainStatusAreaui.talkStatusArea.setType('error');
mainStatusAreaui.talkStatusArea.setLabel('An error occurred in editing the talk page (' + err + '). Please try again or refer to the help desk.');
});
 
}).catch(function (err) {
}
ui.mainStatusArea.setType('error');
ui.mainStatusArea.setLabel('An error occurred (' + err + '). Please try again or refer to the help desk.');
ui.submitButton.setDisabled(false);
});
 
});
 
// Load a JSON page from the wiki
// Use API (instead of $.getJSON with action=raw) to take advantage of caching
function getJSONPage (page) {
return afc.api.get({
action: 'query',
titles: page,
prop: 'revisions',
rvprop: 'content',
rvlimit: 1,
rvslots: 'main',
uselang: 'content',
maxage: '3600', // 1 hour
smaxage: '3600',
formatversion: 2
}).then(function (json) {
var content = json.query.pages[0].revisions[0].slots.main.content;
return JSON.parse(content);
}).catch(function (err) {
console.error(err);
});
}
 
function linkify(input) {
return input.replace(
/\[\[:?(?:([^|\]]+?)\|)?([^\]|]+?)\]\]/g,
function(_, target, text) {
if (!target) {
target = text;
}
return '<a target="_blank" href="' + mw.util.getUrl(target) +
'" title="' + target.replace(/"/g, '&#34;') + '">' + text + '</a>';
}
);
}
 
function debug() {
Array.prototype.slice.call(arguments).forEach(function (arg) {
console.log(arg);
});
}
 
/* </nowiki> */