Skip to content

Instantly share code, notes, and snippets.

@Brayyy
Last active September 7, 2023 21:47
Show Gist options
  • Save Brayyy/f58a7656642674a6c7f8e836aec5f759 to your computer and use it in GitHub Desktop.
Save Brayyy/f58a7656642674a6c7f8e836aec5f759 to your computer and use it in GitHub Desktop.
UserScript - ExtremeReach fix poorly designed Kendo tables
// ==UserScript==
// @name ER ticket search cleanup
// @namespace https://github.com/Brayyy
// @version 1.2.1
// @description Fix all screwy things about the ticket search page, including column widths and search box layout, and more to come! (hopefully)
// @author balmini@extremereach.com
// @match https://app.extremereach.com/cs/tickets/search
// @icon https://www.google.com/s2/favicons?sz=64&domain=extremereach.com
// @updateURL https://gist.github.com/Brayyy/f58a7656642674a6c7f8e836aec5f759/raw/ER%2520ticket-search-cleanup.user.js
// @downloadURL https://gist.github.com/Brayyy/f58a7656642674a6c7f8e836aec5f759/raw/ER%2520ticket-search-cleanup.user.js
// @grant none
// ==/UserScript==
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
// https://www.freecodecamp.org/news/javascript-debounce-example/
(function() {
'use strict';
function fixSearchBox() {
console.log("fixSearchBox()");
// Reduce columns from 5->4
const cols = document.querySelector('.search-form');
// if (!cols) return console.error("Couldn't find .search-form");
for (let i = 0; i < cols.children.length; i++) {
cols.children[i].style = "grid-template-columns: repeat(4, 1fr)";
}
// Unfuck the cssoverrides
document.querySelectorAll(".search-fields > :nth-child(3)")[0].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(3)")[1].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(2)")[2].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(3)")[2].style = "grid-column: 4";
// advanced may not be enabled
if (document.querySelectorAll(".search-fields > :nth-child(3)").length > 3) {
document.querySelectorAll(".search-fields > :nth-child(3)")[3].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(3)")[4].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(3)")[5].style = "grid-column: 3";
document.querySelectorAll(".search-fields > :nth-child(3)")[6].style = "grid-column: 3";
}
}
function fixSearchResults() {
console.log("fixSearchResultsHeader()");
// Resize dynamic columns
let colStyles = {
// "ID": "width: 75px; background-color: gray;",
"ID": "width: 85px;",
"Subject": "width: 40%;",
"Updated": "width: 160px;",
"Owner": "width: 15%;",
"Milestone": "width: 80px;",
};
const tableHeaders = document.querySelector(`.k-grid-header tr`).children;
let titleToIndex = {};
for (let i = 0; i < tableHeaders.length; i++) {
const columnTitle = tableHeaders[i].querySelector(".k-column-title").innerText;
if (columnTitle) {
titleToIndex[columnTitle] = i;
}
}
// Resize permanent columns lacking a title
document.querySelector(`[kendogridcolgroup] col:nth-child(1)`).style = "width: 30px"; // checkbox
// totally hide worthless, non-removable columns
document.querySelector(`[kendogridcolgroup] col:nth-child(2)`).style = "width: 0px"; // tags
document.querySelector(`[kendogridcolgroup] col:nth-child(4)`).style = "width: 0px"; // linked?
const actionCol = tableHeaders.length; // last column
document.querySelector(`[kendogridcolgroup] col:nth-child(${actionCol})`).style = "width: 0px"; // actions
for (const title in titleToIndex) {
if (colStyles[title] !== undefined) {
const index = titleToIndex[title];
const nthChild = index + 1;
const colStyle = colStyles[title];
console.log(`setting ${index} nth-child(${nthChild}) ${title} style: to width: ${colStyle}`);
document.querySelector(`[kendogridcolgroup] col:nth-child(${nthChild})`).style = colStyle;
}
};
// de-bloat the table, reducing padding
// I'm not sure why this needs to be delayed
setTimeout(() => {
$(".k-grid td").css("padding", "2px");
}, 1000);
}
function addBasicNewTicket () {
const div = document.createElement("div");
const a = document.createElement("a");
a.innerText = "New Ticket, no bullshit ->";
a.href = "https://app.extremereach.com/cs/tickets/details/create/details";
a.target = "_blank";
div.appendChild(a);
document.querySelector(".k-button-solid").parentElement.parentElement.appendChild(div)
}
function debounce_leading(func, timeout = 300){
// console.log("debounce_leading()");
let timer;
return (...args) => {
// console.log("debounce_leading() inner");
if (!timer) {
func.apply(this, args);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = undefined;
}, timeout);
};
}
const fixSearchBox_debounceLeading = debounce_leading(fixSearchBox);
const observer1 = new MutationObserver(() => {
const element = document.querySelector('.search-fields');
if (!element) return
fixSearchBox_debounceLeading();
// Must leave Observer active in case "advanced options" is toggled
// observer1.disconnect();
});
observer1.observe(document.body, { childList: true, subtree: true });
const observer2 = new MutationObserver(() => {
const element = document.querySelector('.k-grid-aria-root table tbody');
if (!element) return
fixSearchResults();
addBasicNewTicket();
observer2.disconnect();
});
observer2.observe(document.body, { childList: true, subtree: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment