Page MenuHomeMiraheze
Paste P444

Miraheze phab auto responses (temp)
ActivePublic

Authored by Reception123 on Sep 9 2021, 09:20.
Tags
None
Referenced Files
F1713497: Miraheze phab auto responses (temp)
Feb 5 2022, 17:15
F1493961: Miraheze phab auto responses (temp)
Sep 9 2021, 09:20
Subscribers
None
// ==UserScript==
// @name Wikimedia Maniphest Triage helper
// @namespace http://tampermonkey.net/
// @description Adds links above the comment field for stock answer, plus some other things.
// @author Andre Klapper <ak-47@gmx.net>
// @version 2021-09-01
// @match https://phabricator.miraheze.org/T*
// @match https://phabricator.miraheze.org/maniphest/task/edit/*
// @match https://phabricator.miraheze.org/maniphest/report/project/*
// @match https://phabricator.miraheze.org/file/query/*
// @match https://phabricator.miraheze.org/p/*
// @grant none
// @copyright Copyright Control by the authors, 2014 and later.
// @license The contents of this file are dual-licensed under the Mozilla Public License 2.0 (MPL-2.0)
// and the GNU General Public License (GPL-2.0) Version 2 or later.
// ==/UserScript==
/* THIS SCRIPT MIGHT NOT WORK AT ALL IN VIOLENTMONKEY ETC.:
https://github.com/violentmonkey/violentmonkey/issues/408
https://github.com/violentmonkey/violentmonkey/issues/173
https://bugzilla.mozilla.org/show_bug.cgi?id=1267027#c41 */
document.getElementsByClassName('phui-crumbs-view')[0].setAttribute('style', "display: none;");
/***********************************************************************/
/* SETTINGS SECTION START - values must be 0 (disabled) or 1 (enabled) */
/***********************************************************************/
// Color projects for extensions which are deployed in green, and extensions being worked on in yellow
var setColorForExtensions = 1;
// use one-click stock answers (canned responses) above field to add new comment.
// If you want to add individual stock answers yourself, you have to do two things:
// a) add an EventHandler function (like "FooClick") in the STOCK ANSWER DEFINITIONS SECTION
// to define your changes when clicking the stock answer (add comment text, set bug resolution, etc)
// b) a createItemInContainer() call in the ADDING THE STOCK ANSWERS section at the very end of this script
// that adds the stock answer link and calls the EventHandler function that you defined under a)
var useStockAnswers = 1;
// Set number of values proposed in dropdowns:
// JX.TypeaheadSource.prototype.setMaximumResultCount(20);
/**********************************************************************************/
/* Additions to user homepages at https://phabricator.miraheze.org/p/username/ : */
/**********************************************************************************/
if ((window.location.pathname.split( '/' )[1] == "p") && ((window.location.pathname.split( '/' )[2]).length > 0)) {
// Provide link to 'People Log Query' on user homepage, to quickly check for other Phab users with the same or similar IPs:
addLinkSection("https://phabricator.miraheze.org/people/logs/?users=" + (window.location.pathname.split( '/' )[2]), " [Query Phab User Logins] ", "User Activity", document.getElementsByClassName("phui-header-header")[0], "");
}
/*********************************************************/
/* get some basic data from the bug report to use later: */
/*********************************************************/
// Find out whether we are in task View or in task Edit mode, they are pretty different:
var task_edit_mode = 0;
if (window.location.pathname.split( '/' )[3] == "edit") {
task_edit_mode = 1;
}
var assignee = null;
var comment_textfield = null;
if ((task_edit_mode == 0) && ((document.getElementsByClassName('fa-square-o').length > 0) || (document.getElementsByClassName('fa-check-square-o').length > 0))) { // we are in task view
/* Priority; only existing if task not resolved: */
if (document.getElementsByClassName('fa-square-o').length > 0) {
var priority = ((document.getElementsByClassName('fa-square-o')[0].parentElement.textContent).substring(document.getElementsByClassName('fa-square-o')[0].parentElement.textContent.indexOf(", ") + 2,document.getElementsByClassName('fa-square-o')[0].parentElement.textContent.length));
}
/* Assignee: */
if ((document.getElementsByClassName('phui-curtain-panel')[0].textContent).substring(document.getElementsByClassName('phui-curtain-panel')[0].textContent.indexOf("Assigned To") + 11,document.getElementsByClassName('phui-curtain-panel')[0].textContent.length) == "None") { // no assignee set
assignee = "None";
}
else {
assignee = (document.getElementsByClassName('phui-curtain-panel')[0].textContent).substring(document.getElementsByClassName('phui-curtain-panel')[0].textContent.indexOf("Assigned To") + 11,document.getElementsByClassName('phui-curtain-panel')[0].textContent.length);
}
/* Reporter: */
var reporter = document.getElementsByClassName('phui-curtain-panel')[1].querySelector('.phui-link-person').textContent;
/* Products: */
var product_array=[]; // collect string names of all the Projects for this task:
for (var n=0; n < (document.getElementsByClassName("phui-curtain-panel")[2].getElementsByClassName("phui-tag-core").length); n++) {
product_array[n] = document.getElementsByClassName("phui-curtain-panel")[2].getElementsByClassName("phui-tag-core")[n].textContent;
}
if (setColorForExtensions == 1) {
var product_array_containers=[]; // collect containers of all the Projects for this task so we can color them:
for (var p=0; p < (document.getElementsByClassName("phui-curtain-panel")[2].getElementsByClassName("phui-tag-core").length); p++) {
product_array_containers[p] = document.getElementsByClassName("phui-curtain-panel")[2].getElementsByClassName("phui-tag-core")[p];
}
}
/* Get the textfield to add comments: */
if (document.getElementsByName("comment").length > 0) {
comment_textfield = document.getElementsByName("comment")[0]; // must point to actual <textarea> id
}
else {
window.alert("Either you are logged out, or the HTML ID of the comment field has changed and your local Phab Stock Answer user script needs updating.");
}
}
else { // we are in task edit mode:
comment_textfield = document.getElementsByName("description")[0];
}
/* Bug number: */
if (document.getElementsByClassName('phui-crumb-name').length > 1) {
var taskId = document.getElementsByClassName('phui-crumb-name')[1].innerHTML;
}
// Check whether task is open or closed. As the top section describing the task
// status is rather hard to gather, check if a class 'status-oh-closed-dark'
// exists - if not, the ticket is open.
var task_status_is_open = 0;
if (document.getElementsByClassName('phui-header-status-dark').length == 0) {
task_status_is_open = 1;
}
/* Get name of user who last changed the task status and who added goodfirsttask tag (for specific stock answers below): */
/* Won't always work due to autocollapsed history. */
var task_activity_array=[];
var last_user_changing_task_status;
var last_user_adding_goodfirsttask_tag;
for(var tc=0; tc<((document.getElementsByClassName('phui-timeline-title')).length); tc++) {
task_activity_array[tc] = document.getElementsByClassName('phui-timeline-title')[tc].textContent;
}
var taal = task_activity_array.length;
while (taal--) {
if (task_activity_array[taal].indexOf("added a project: good first task") > -1) {
last_user_adding_goodfirsttask_tag = (task_activity_array[taal].split(" ")[0]);
}
if ((task_activity_array[taal].indexOf("added projects") > -1) && (task_activity_array[taal].indexOf("good first task") > -1)) {
last_user_adding_goodfirsttask_tag = (task_activity_array[taal].split(" ")[0]);
}
if (task_activity_array[taal].indexOf("changed the task status from") > -1) {
last_user_changing_task_status = (task_activity_array[taal].split(" ")[0]);
}
if (task_activity_array[taal].indexOf("reopened this task as") > -1) {
last_user_changing_task_status = (task_activity_array[taal].split(" ")[0]);
}
// good_first_task already set by reporter?:
if (last_user_adding_goodfirsttask_tag == null) {
last_user_adding_goodfirsttask_tag = reporter;
}
}
/*** helper function to create container elements (e.g. <div>) that we can drop random text or links into
* @param ElementToCreate the element (e.g. a <div>) that we plan to put somewhere,
* MUST have been defined by calling document.createElement("foo") before
* @param place element after which this item is added
* @param ID a random ID parameter
* @param heading optional text header to display at the beginning of the element
* @param style CSS style for this item
* @return void
*/
function createContainer(ElementToCreate, place, ID, heading, style) {
ElementToCreate.setAttribute('id', ID);
ElementToCreate.appendChild(document.createTextNode(heading));
ElementToCreate.setAttribute('style', style);
place.parentNode.insertBefore(ElementToCreate, place);
}
/********************************************************************/
/***helper function that adds an <a> element in a place
* @param url URL of the link
* @param text the text to be displayed
* @param title text to be displayed for mouse over
* @param place element after which this item is added
* @param style CSS style for this item
* @return void
*/
function addLinkSection(url, text, title, place, style) {
var link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('title', title);
link.setAttribute('style', style);
link.appendChild(document.createTextNode(text));
if(place.nextSibling != null) {
place.parentNode.insertBefore(link, place.nextSibling);
}
}
/**********************************************************************/
/* create <div> container for stock answers above comment input field */
/* Only makes sense in non-edit mode as we don't have stockanswers to */
/* edit the initial description */
/**********************************************************************/
if (useStockAnswers == 1 && comment_textfield != null) {
var stockAnswersContainerDiv = document.createElement("div"); // most be defined here globally as we need it later to insert items in it
createContainer(stockAnswersContainerDiv, comment_textfield, "stock_answers_div", '', "border:0px solid #000000; padding:0px; margin: 2px 0px 2px; text-align: left; background-color:#f4f4f4");
}
/**************************************************************************************/
/***helper function that creates new entries in custom <div>s, such as stock answers
* @param element HTML element to create (e.g. <span> or <div>)
* @param cclass class for the element to create
* @param ID some ID for the element to create
* @param text the text to be displayed
* @param clickHandler name of the EventHandler function; makes only sense if this is a stock response (function must have been defined before)
* @param style CSS style for this item
* @param place element after which this item is added
* @return void
*/
function createItemInContainer(element, cclass, ID, text, clickHandler, style, place) {
var SpanContainer = document.createElement(element);
SpanContainer.setAttribute('class', cclass);
SpanContainer.setAttribute('id', ID);
var SpanContainerText = document.createTextNode(text);
SpanContainer.appendChild(SpanContainerText);
place.appendChild(SpanContainer);
if (style == '1') { // green
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#8ae234; color: #000000;");
}
else if (style == '10') { // dark green
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#4aa204; color: #FFFFFF;");
}
else if (style == '2') { // rose
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#f2a0f2; color: #000000;");
}
else if (style == '20') { // aubergine
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#ad7fa8; color: #FFFFFF;");
}
else if (style == '3') { // yellow
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#fce94f; color: #000000;");
}
else if (style == '4') { // orange
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#fcaf3e; color: #000000;");
}
else if (style == '5') { // brown
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#e9b97e; color: #000000;");
}
else if (style == '6') { // red
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#f56969; color: #000000;");
}
else if (style == '60') { // dark red
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#d54040; color: #ffffff;");
}
else if (style == '7') { // light blue
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#82afcf; color: #000000;");
}
else if (style == '70') { // dark blue
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#4475a4; color: #FFFFFF;");
}
else if (style == '99') { // black
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; background-color:#2d2d2d; color: #FFFFFF;");
}
else /* if (style == '0') */ {
SpanContainer.setAttribute('style', "margin: 0px 1px 0px 1px; padding:0px 3px 0px 3px; color: #000000;");
}
SpanContainer.addEventListener("click", clickHandler, true);
}
/**************************************************************************************/
/* helper function that adds reply text to the comment textarea, enables the CC checkbox
* and sets keyboard focus to the "submit" button
* (shamelessly partially adopted from bugzilla.gnome.org code at
* /template/en/default/bug/edit.html.tmpl which is under a Mozilla Public License)
* @param text text to add as a new comment
* @param priority priority to set
* @param status status to set (e.g. "new" or "resolved")
* @param project project to associate (TODO: removing is probably too hard)
* @return void
*/
function addTextToComment(text, priority, status, project) {
var replytext = "";
if (text && text != "") {
text = text.split(/\r|\n/);
replytext = "";
for (var i=0; i < text.length; i++) {
replytext += text[i] + "\n";
}
}
if (replytext && replytext != "") {
var textarea = comment_textfield;
textarea.value += replytext;
}
return false;
}
/*******************************************************************************************************************/
/* STOCK ANSWER DEFINITIONS AND ADDING SECTION */
/* PATTERN: createItemInContainer('span', 'class' 'someID', '[shownText]', ClickHandlerName, colorNumber, place); */
/* The ClickHandlerName must be defined above as the function name! */
/*******************************************************************************************************************/
var textCDNotPointing = "Hi, it seems that you have not pointed your domain correctly to Miraheze's servers. Please make sure to read https://meta.miraheze.org/wiki/Custom_domains and let us know when you have pointed your domain to us. ";
var textManageWiki = "Hi, you don't need to open a Phabricator task for this, you can do this yourself via Special:ManageWiki/extensions. For more information please see https://meta.miraheze.org/wiki/ManageWiki";
var textImportIP = "Hi, your import is currently in progress. Please note that depending on the size it may take a while until it's completed.";
var textImportDone = "Your import has now finished!"
var textRenameDone = "Your wiki rename is now complete. If you experience login issues after this please follow these instructions: Open the private browsing mode of your web browser and login, and go to Special:UserLogout. Next, open the regular browsing mode of your web browser, delete your cookies for *.miraheze.org and try and login again";
var textExtRev = "Hi, we have taken note of your request to install a new extension, however for security reasons Miraheze reviews all new extensions to make sure that they are secure for use, so this will have to be done first."
/* // COLOR SCHEME EXAMPLES FOR BELOW:
createItemInContainer('br', null, null, null, null, null, stockAnswersContainerDiv); // line breaks
createItemInContainer('div', null, '', '1', null, 1, stockAnswersContainerDiv); // first triage
createItemInContainer('div', null, '', '10', null, 10, stockAnswersContainerDiv); // first triage + stalled
createItemInContainer('div', null, '', '2', null, 2, stockAnswersContainerDiv); // clean up
createItemInContainer('div', null, '', '20', null, 20, stockAnswersContainerDiv); // clean up
createItemInContainer('div', null, '', '3', null, 3, stockAnswersContainerDiv); // setting priority for first time
createItemInContainer('div', null, '', '4', null, 4, stockAnswersContainerDiv); // WM-Site-requests; project specific answers
createItemInContainer('div', null, '', '5', null, 5, stockAnswersContainerDiv); // Misc; Phab task answers
createItemInContainer('div', null, '', '6', null, 6, stockAnswersContainerDiv); // revert
createItemInContainer('div', null, '', '60', null, 60, stockAnswersContainerDiv); // revert and potential conflict
createItemInContainer('div', null, '', '7', null, 7, stockAnswersContainerDiv); // nagging
createItemInContainer('div', null, '', '70', null, 70, stockAnswersContainerDiv); // nagging + reset
createItemInContainer('div', null, '', '99', null, 99, stockAnswersContainerDiv); // resolving / closing
*/
if ((useStockAnswers == 1) && (task_edit_mode == 0) && (comment_textfield != null)) {
function CDNotPointing (Event) {
var Text = textCDNotPointing;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'cd_notpointing', '[CD: Not P]', CDNotPointing, '3', stockAnswersContainerDiv);
function ManageWiki (Event) {
var Text = textManageWiki;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'managewiki', '[ManageWiki: available]', ManageWiki, '3', stockAnswersContainerDiv);
function ImportIP (Event) {
var Text = textImportIP;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'importIP', '[Import: InP]', ImportIP, '4', stockAnswersContainerDiv);
function ImportDone (Event) {
var Text = textImportDone;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'importIP', '[Import: D]', ImportDone, '1', stockAnswersContainerDiv);
function RenameDone (Event) {
var Text = textRenameDone;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'renamedone', '[DB: Rename D]', RenameDone, '1', stockAnswersContainerDiv);
function ExtRev (Event) {
var Text = textExtRev;
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'importIP', '[Ext: Rev]', ExtRev, '4', stockAnswersContainerDiv);
if ((product_array != null) && (product_array.indexOf('Tracking-Neverending') > -1)) {
function Tracking2Epic (Event) {
var Text = "#epic task which could be declared resolved at some point in a far away future, hence removing #tracking-neverending tag.";
addTextToComment(Text, '', '', '');
}
createItemInContainer('span', null, 'projectcreated', '[Tracking🡒Epic]', Tracking2Epic, '0', stockAnswersContainerDiv);
}
}
/****************************************************************************/
/* Reports page fun: */
/* - Show percentages per priority instead of total numbers */
/* - Show small arrows symbolizing the priority as columns suck */
/* - Color values if they are higher than a certain threshold */
/* https://phabricator.miraheze.org/maniphest/report/project/?order=total */
/****************************************************************************/
/* Following code is broken and not useful until https://phabricator.miraheze.org/T125357 is fixed */
if ((window.location.pathname.split( '/' )[2] == "report") && (window.location.pathname.split( '/' )[3] == "project")) {
var trs = document.getElementsByTagName("tr");
for (var w = 1; w < trs.length; w++) { // because 0 is <th>
var tds = trs[w].getElementsByTagName("td");
var ttl = (tds[7].innerHTML); // row 7 has total number of open tasks
var regex = new RegExp(',', 'g');
ttl = ttl.replace(regex, '');
ttl = parseInt(ttl, 10);
for (var no = 1; no < 7; no++) { // row 0 is name of project
var foo = parseInt(tds[no].innerHTML);
var prio = null; // append symbol for priority because table columns aren't static
switch (no) {
case 1: prio = "↑"; break;
case 2: prio = "?"; break;
case 3: prio = "↗"; break;
case 4: prio = "→"; break;
case 5: prio = "↘"; break;
case 6: prio = "↓"; break;
}
if (Number.isInteger(foo)) {
var prcnt = (foo / ttl) * 100;
tds[no].innerHTML = prcnt.toFixed(0) + "%" + prio; // cut digits via toFixed; append priority arrow
if (((no == 1) || (n == 3)) && (prcnt > 40)) { // for unbreak/high prio; mark large values red
tds[no].setAttribute('style', "color:#FA1D2F; background-color:#FFDDDD;");
}
else if ((no == 2) && (prcnt > 40)) { // for untriage prio; mark large values violet
tds[no].setAttribute('style', "color:#800080; background-color:#FAD1FA;");
}
else if ((no == 4) && (prcnt > 50)) { // for normal prio; mark large values orange
tds[no].setAttribute('style', "color:#FF7F00; background-color:#FEE5AC;");
}
}
}
}
}
else if (window.location.pathname.split( '/' )[2] == "report") {
var product_array_reports=[]; // collect string names of all the Projects listed in this report:
// "sorted-column" turns into "aphront-table-view-sortable" when sorting, hence using "wide":
for(i=0; i<((document.getElementsByClassName('wide')).length); i++) {
product_array_reports[i] = document.getElementsByClassName('wide')[i].textContent;
}
if (setColorForExtensions == 1) {
var product_array_containers_reports=[]; // collect containers of all the Projects in this report task so we can color them:
for(i=0; i<((document.getElementsByClassName('wide')).length); i++) {
product_array_containers_reports[i] = document.getElementsByClassName('wide')[i];
}
}
}