Jump to content

User:Terasail/Edit Request Tool.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Terasail (talk | contribs) at 11:09, 10 March 2022 (Fix to quick reply options & reorder and fixes to replyoption list). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
var rOS = 9; //Reply options start
var replyERT = {	
semi: ["Semi", "semi", "1/1b/", "ESp|"],
extended: ["Extended", "extended", "8/8c/", "EEp|"],
template: ["Template", "template", "5/53/", "ETp|"],
full: ["Full", "fully", "4/44/", "EP|"],
"interface": ["Interface", "interface", "2/28/", "EIp|"],
"Close": ["", "Close", "Closed edit request"],
"Change": ["", "Close", "Changed level of protected edit request"],
"ChangeTarget": ["", "Close", "Changed target of protected edit request"], 
"Remove": ["", "Remove", "Removed edit request"],
"Comment (No template)": ["", "speechBubbleAdd", "Comment"],
"Done": ["d", "checkAll", "Done"],
"Partly done:": ["pd", "check", "Partly done"],
"Already Done": ["a", "clock", "Already Done"],
"In progress: An editor is implementing the requested edit.": ["prog", "clock", "In progress"],
"Note:": ["note", "ellipsis", "Note"],
"Question:": ["q", "helpNotice", "Question"],
"Not done:": ["n", "notice", "Not done"],
"Not done for now:": ["nfn", "notice", "Not done for now"],
"Not done: it's not clear what changes you want to be made. Please mention the specific changes in a 'change X to Y' format and provide a reliable source if appropriate.": ["xy", "helpNotice", "Not done - Unclear request"],
"Not done: please provide reliable sources that support the change you want to be made.": ["rs", "link", "Not done - Needs reliable sources"],
"Not done for now: please establish a consensus for this alteration before using the edit protected template.": ["c", "userGroup", "Not done - Needs consensus"],
"Not done: please make your requested changes to the template's sandbox first; see WP:TESTCASES.": ["sb", "linkExternal", "Not done - Use sandbox first"],
"Not done: this is the talk page for the page. Please make your request at the talk page for the article concerned.": ["mis", "ongoingConversation", "Not done - Misplaced"],
"Not done: this is the talk page for discussing improvements to the page. If possible, please make your request at the talk page for the article concerned.": ["tp", "ongoingConversation", "Not done - Misplaced"],
"Not done: According to the page's protection level you should be able to edit the page yourself. If you seem to be unable to, please reopen the request with further details.": ["hr", "unLock", "Not done - User can edit page"],
"Not done: The page's protection level has changed since this request was placed. You should now be able to edit the page yourself...": ["nlp", "unLock", "Not done - Page protection has changed"],
"Not done: {{Edit protected}} is usually not required for edits to the documentation or categories of templates using a documentation subpage.": ["doc", "code", "Not done"],
"Not done: requests for increases to the page protection level should be made at Wikipedia:Requests for page protection.": ["r", "editLock", "Not done - Use [[WP:RPP]]"],
"Not done: requests for decreases to the page protection level should be directed to the protecting admin or to Wikipedia:Requests for page protection.": ["ru", "editLock", "Not done - Use [[WP:RPP]]"],
"Not done: requests for recreating deleted pages protected against creation should be made at Wikipedia:Deletion review.": ["drv", "articleAdd", "Not done - Use [[WP:DRV]]"],
"Not done: page move requests should be made at Wikipedia:Requested moves.": ["m", "tableMoveColumnAfter", "Not done - Use [[WP:RM]]"],
"Not done: Please make your request for a new image to be uploaded to Files For Upload. Once the file has been properly uploaded, feel free to reactivate this request.": ["ffu", "imageLayoutFrameless", "Not done - Use [[WP:FFU]]"],
"Not done: this is the talk page for discussing improvements to the page. If possible, please make your request at the talk page for the article concerned.": ["tp", "ongoingConversation", "Not done - Misplaced"],
"Not done: this is not the right page to request additional user rights. You may reopen this request with the specific changes to be made and someone will add them for you.": ["p", "userAdd", "Not done - Use [[WP:RFPERM]]"],
"Partially undone: This request has been partially undone.": ["pud","undo", "Partly undone"], 
"Undone: This request has been undone.": ["ud", "undo", "Undone"]
};

function postEdit(wikitext, editSummary, pageName, secIdx) {
	var api = new mw.Api();
	api.postWithEditToken({
		action: 'edit',
		title: pageName,
		text: wikitext,
		section: secIdx,
		summary: editSummary
	}).done(function(result) {
		window.location = "/w/index.php?title=" + pageName + "&type=revision&diff=cur&oldid=prev";
	});
}

function execute(currentBox, replyOption, inputText, answered, boxType, targets) {
	OO.ui.confirm("Confirm in order to reply to this edit request.").done(function(confirmed) {
		if (confirmed) {
			//Change buttons to label box + loading bar
			var leftOOUI = currentBox.getElementsByClassName('mbox-image')[0].getElementsByClassName('oo-ui-widget');
			if (leftOOUI.length > 1) {
				leftOOUI[0].remove();
			}
			leftOOUI[0].remove();
			currentBox.children[2].remove();
			var infoBox = new OO.ui.MessageWidget( {
				icon: 'pageSettings',
				type: 'notice',
				label: 'Processing request — Edit request starting, getting section data to edit.'
			});
			var firstRow = currentBox.getElementsByTagName('tr')[1].children[0];
			firstRow.style = "padding-bottom:10px";
			firstRow.innerHTML = "";
			var progressBar = new OO.ui.ProgressBarWidget( {
				progress: false
			});
			$(firstRow).append(progressBar.$element);
			$(firstRow).append(infoBox.$element);
			progressBar.$element[0].style = "margin:auto";
			infoBox.$element[0].style = "margin:10px auto 0px; max-width:50em";
			//Find header
			var header = "";
			var curElement = currentBox.parentNode;
			do {
				curElement = curElement.previousElementSibling;
				if (curElement.getElementsByClassName("mw-headline").length == 1) {
					header = curElement.getElementsByClassName("mw-headline")[0].id;
				}
			}
			while (header == "");
			var pageName = mw.config.values.wgPageName;
			var api = new mw.Api();
			api.get( {
				action: "parse",
				page: pageName,
				prop: "sections|wikitext|revid"
			}).done(function(data) {
				infoBox.setLabel("Processing request — Making changes to the edit request");
				boxType = replyERT[boxType];
				var editTemplate = "{{Edit " + boxType[1] + "-protected";
				if (answered) { answered = "yes"; } else { answered = "no"; }
				for (var c3 = 0; c3 < targets.length; c3++) {
					editTemplate += "|" + targets[c3];
				}
				editTemplate += "|answered=" + answered;
				var sections = data.parse.sections;
				var wikitext = data.parse.wikitext["*"];
				var newRev = data.parse.revid;
				var secIndx = -1, endIndx = -1;
				for (var j = 0; j < sections.length; j++) {
					var tempSec = sections[j];
					if (tempSec.anchor == header && !isNaN(Number(tempSec.index))) {
						secIndx = tempSec;
						if (sections[j+1]) { endIndx = j; }
					} else if (tempSec.number.indexOf(secIndx.number + ".") == 0) {
						if (sections[j+1]) { endIndx = j; } else { endIndx = -1; }
					}
				}
				if (endIndx == -1) {
					endIndx = wikitext.length;
				} else {
					endIndx = wikitext.lastIndexOf("==", sections[endIndx + 1].byteoffset + 5);
				}
				wikitext = wikitext.slice(wikitext.indexOf("==", secIndx.byteoffset - 5), endIndx);
				secIndx = secIndx.index;
				wikitext = wikitext.replace(/{{ *([SETFI]PER|Edit[ -]?[A-Z]+[ -]?Protected)\s*[^}}]*/i, editTemplate);
				var editSummary = "/* " + header.replaceAll("_", " ") + " */ " + replyOption[2] +  " ([[User:Terasail/Edit_Request_Tool|Edit Request Tool]])";
				if (replyOption[1] != "Close") {
					var lastMsg = wikitext.lastIndexOf("\n", wikitext.lastIndexOf("(UTC)")) + 1;
					wikitext = wikitext.trim() + "\n:";
					while(lastMsg == wikitext.indexOf(":", lastMsg)) {
						lastMsg++;
						wikitext += ":";
					}
					if (replyOption[0] != "") { wikitext += "{{subst:" + boxType[3] + replyOption[0] + "}} "; }
					if (inputText != "") { wikitext += inputText.replaceAll(/\s*~~~~\s*/g, "") + " "; }
					wikitext += "~~~~";
					if (replyOption[1] == "Remove") {
						wikitext = "";
						editSummary = editSummary.replace(/[^]+\*\/ /, "");
					}
				}
				infoBox.setType("success");
				infoBox.setLabel("Processing '" + replyOption[2] + "' request — Saving changes to the talk page.");
				if (newRev == mw.config.values.wgRevisionId) {
					postEdit(wikitext, editSummary, pageName, secIndx);
				} else {
					OO.ui.confirm("There has been a new revision to the page, do you wish to continue?").done(function(revCon) {
						if (revCon) { postEdit(wikitext, editSummary, pageName, secIndx); }
					});
				}
			});
		}
	});
}

function addButtons(currentBox) {
	var boxType = currentBox.parentElement.dataset.origlevel;
	var replyList = Object.entries(replyERT);
	var mainResponse = [[replyList[rOS + 9][1], "Unclear: X-Y", "Unclear request"], [replyList[rOS + 10][1], "WP:Reliable", "Needs reliable sources"], [replyList[rOS + 11][1], "WP:Consensus", "Change needs consensus"]];
	$(currentBox).append('<tr><td colspan="2"><div style="display: flex; justify-content: center;"></div></td></tr><tr style="display:none;"><td colspan=2 style="padding-bottom:10px; text-align:center"><div style="display: flex; justify-content: center;"></div></td></tr>');
	var firstRow = currentBox.children[1].children[0].children[0];
	//Create type change dropdown
	var typeChange = new OO.ui.DropdownInputWidget( {
		value: boxType,
		options: [
			{data:"semi", label:"Semi protected edit request"},
			{data:"extended", label:"Extended confirmed protected edit request"},
			{data:"template", label:"Template protected edit request"},
			{data:"full", label:"Fully protected edit request"},
			{data:"interface", label:"Interface protected edit request"}
		]
	});
	typeChange.$element[0].style = "text-align:left; margin:auto";
	$(currentBox.children[2].children[0]).append(typeChange.$element);
	//Create target page list
	var boxLinks = currentBox.getElementsByClassName("mbox-text")[0].getElementsByClassName("external text");
	var pageLinks = [];
	if (boxLinks.length > 0) {//Open request
		for(var c1 = 0; c1 < boxLinks.length; c1++) {
			if (boxLinks[c1].parentElement.tagName == "LI" || boxLinks[c1].parentElement.tagName == "B") {
				pageLinks[pageLinks.length] = boxLinks[c1].innerHTML;
			}
		}
	} else {//Closed request
		boxLinks = currentBox.getElementsByClassName("mbox-text")[0].getElementsByTagName("A");
		for(var c2 = 1; c2 < boxLinks.length; c2++) {
			pageLinks[pageLinks.length] = boxLinks[c2].title;
		}
		if (pageLinks.length == 0) {
			pageLinks = mw.config.values.wgPageName.replace(/(_talk|Talk:)/, "").replaceAll("_", " ");
		}
	}
	var targetPages = new OO.ui.TagMultiselectWidget( {
		placeholder: 'Target Pages',
		allowArbitrary: true,
		selected: pageLinks
	});
	targetPages.$element[0].style = "text-align:left; margin:5px auto 5px auto";
	$(currentBox.children[2].children[0]).append(targetPages.$element);
	//Create dropdown menu
	var dropMenu = new OO.ui.DropdownWidget( {
		label: "Select reply option -  Add additional text below",
		menu: {items: []}
	});
	for (var count = 9; count < replyList.length; count++) {
		var newOption = new OO.ui.MenuOptionWidget({
			label: replyList[count][0],
			icon: replyList[count][1][1]
		});
		dropMenu.menu.addItems([newOption]);
	}
	dropMenu.$element[0].style = "text-align:left; margin:0px";
	$(currentBox.children[2].children[0]).append(dropMenu.$element);
	//Create input box
	var inputText = new OO.ui.MultilineTextInputWidget({autosize: true, label: "Automatically signed"});
	inputText.$element[0].style = "margin:auto";
	$(currentBox.children[2].children[0]).append(inputText.$element);
	//Create top horizontal layout
	var hzLayoutT = new OO.ui.HorizontalLayout();
	//Done
	var doneB = new OO.ui.ButtonWidget( {
		icon: "checkAll",
		label: "Done",
		flags: ["primary", "progressive"],
		title: "Mark as done"
	});
	doneB.on("click", function() {
		if (doneB.getLabel() == "Submit") {
			if (typeof(replyERT[dropMenu.getLabel()]) != "undefined") {
				execute(currentBox, replyERT[dropMenu.getLabel()], inputText.value, toggleAns.selected, typeChange.value, targetPages.getValue());
			} else if (typeChange.value != typeChange.defaultValue) {
				execute(currentBox, replyERT.Change, "", false, typeChange.value, targetPages.getValue());
			}
			var newTargets = false;
			var targets = targetPages.items;
			if (targets.length == pageLinks.length) {
				for(var item = 0; item < targets.length; item++) {
					if (targets[item].data != pageLinks[item]) { newTargets = true; }
				}
			} else {
				newTargets = true;
			}
			if (newTargets) {
				execute(currentBox, replyERT.ChangeTarget, "", false, typeChange.value, targetPages.getValue());
			}
		} else {
			execute(currentBox, replyERT.Done, "", toggleAns.selected, typeChange.defaultValue, targetPages.getValue());
		}
	});
	hzLayoutT.addItems([doneB]);
	mainResponse.forEach(function(item) {
		item[3] = new OO.ui.ButtonWidget({
			label: item[1],
			title: item[2]
		});
		item[3].on("click", function() {
			execute(currentBox, item[0], "", toggleAns.selected, typeChange.defaultValue, targetPages.getValue());
		});
		hzLayoutT.addItems([item[3]]);
	});
	//Respond
	var respondB = new OO.ui.ButtonWidget( {
		icon: "add",
		label: "More",
		title: "Extra response options"
	});
	respondB.on("click", function() {
		if (respondB.getIcon() == "add") {
			currentBox.children[2].style = "";
			doneB.setLabel("Submit");
			doneB.setTitle("Submit response");
			respondB.setIcon("subtract");
			respondB.setLabel("Less");
		} else {
			currentBox.children[2].style = "display:none";
			inputText = "";
			doneB.setLabel("Done");
			doneB.setTitle("Mark as done");
			respondB.setIcon("add");
			respondB.setLabel("More");
		}
	});
	hzLayoutT.addItems([respondB]);
	//Toggle answer button
	var toggleAns = new OO.ui.CheckboxInputWidget({selected: true});
	hzLayoutT.addItems([toggleAns, new OO.ui.LabelWidget({label: "Answered"})]);
	//Create firstrow fieldset
	var fieldsetT = new OO.ui.FieldsetLayout();
	// Add an horizontal field layout
	fieldsetT.addItems( [ 
		new OO.ui.FieldLayout(
			new OO.ui.Widget( {
				content: [hzLayoutT]
			} )
		)
	] );
	$(firstRow).append(fieldsetT.$element);
	//Close request
	var closeB = new OO.ui.ButtonWidget( { 
		icon: "unFlag",
		invisibleLabel: true,
		title: "Mark as closed"
	});
	closeB.$element[0].style = "margin:10px 10px 0px";
	closeB.on("click", function() {
		execute(currentBox, replyERT.Close, "", true, typeChange.defaultValue, targetPages.getValue());
	});
	if (currentBox.parentElement.attributes[2].localName != "data-origlevel") {
		$(currentBox.children[0].children[0]).append(closeB.$element);
	}
	//Remove request
	var remove = new OO.ui.ButtonWidget( { 
		icon: "trash",
		flags: ["primary", "destructive"],
		invisibleLabel: true,
		title: "Delete entire section!"
	});
	remove.$element[0].style = "margin:10px";
	remove.on("click", function() {
		execute(currentBox, replyERT.Remove, "", null, typeChange.defaultValue, targetPages.getValue());
	});
	$(currentBox.children[0].children[0]).append(remove.$element);
}

function addRButton(currentBox) {
	var boxType = replyERT[currentBox.parentElement.dataset.origlevel];
	var openB = new OO.ui.ButtonWidget( { 
		icon: "edit",
		flags: "progressive", 
		invisibleLabel: true,
		title: "Add response / reopen"
	});
	openB.$element[0].style = "margin-top:2px";
	openB.on("click", function() {
		openB.$element.remove();
		currentBox.parentElement.className = "plainlinks tmbox tmbox-notice editrequest";
		var imgSrc = boxType[0] + "-protection-shackle.svg";
		var origImg = currentBox.getElementsByTagName("img")[0];
		var img = origImg.outerHTML.slice(0, origImg.outerHTML.match(/\d\//).index);
		img += boxType[2] + imgSrc + "/60px-" + imgSrc + '.png" height="60" width="60" style="margin-top:5px">';
		origImg.outerHTML = img;
		var mboxText = currentBox.children[0].children[1];
		mboxText.style = "font-size:120%; text-align:center;";
		mboxText.innerHTML = mboxText.innerHTML.replace(/ Set.*\/b>/i, '<br/>Uncheck the "answered" checkbox and use a reply option');
		addButtons(currentBox);
	});
	$(currentBox.children[0].children[0]).append(openB.$element);
}

var editRequestBoxes = document.getElementsByClassName("plainlinks tmbox tmbox-notice editrequest");
if (editRequestBoxes.length != 0) {
	mw.loader.using(["oojs-ui-core", "oojs-ui-widgets", "oojs-ui-windows"]).done(function() {
		mw.loader.load(["oojs-ui.styles.icons-alerts", "oojs-ui.styles.icons-interactions", "oojs-ui.styles.icons-moderation", "oojs-ui.styles.icons-user", "oojs-ui.styles.icons-content", "oojs-ui.styles.icons-editing-core", "oojs-ui.styles.icons-editing-advanced"]);
		for (var i = 0; i < editRequestBoxes.length; i++) {
			var currentBox = editRequestBoxes[i].children[0]; //The tbody tag for the box
			if (editRequestBoxes[i].id != "") {
				addButtons(currentBox);
			} else if (currentBox.getElementsByTagName("code").length == 2) { //Check that it is a closed protected edit request
				addRButton(currentBox);
			}
		}
	});
}
//</nowiki>[[Category:Wikipedia scripts]]