NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name My CPQ Tweaks // @version 0.736 // @description My CPQ Tweaks // @author Obada Kadri // @match *://*.bigmachines.com/* // @grant GM_addStyle // @license MIT // @require https://code.jquery.com/jquery-3.4.1.min.js // @require https://momentjs.com/downloads/moment.js // ==/UserScript== // Extend jQuery contains to have case insensitive option (conaintsi) $.extend($.expr[':'], { 'containsi': function(elem, i, match, array) { return (elem.textContent || elem.innerText || '').toLowerCase() .indexOf((match[3] || "").toLowerCase()) >= 0; } }); var iframe; var bodyHasNoText = (document.body.innerText.length === 0); // Auto refresh // Only for deployment center var dCenters = ["schedule_deployment.jsp", "schedule_events.jsp"]; if (dCenters.indexOf(document.URL.split("/").pop().split("?").shift()) >= 0) { var refreshBtn = document.querySelector("[name='refresh']"); var timer = 10; // in seconds var autoRefresh = true; var note, btn, refreshInterval, timeout; var toggleAutoRefresh = function () { autoRefresh = !autoRefresh; if (autoRefresh) { startAutoRefresh(); } else { btn.innerHTML = "Auto Refresh Off"; timer = 30; clearInterval(refreshInterval); clearTimeout(timeout); } }; var startAutoRefresh = function () { btn.innerHTML = "Auto refreshing in " + timer + "..."; refreshInterval = setInterval(function () { var text; if (--timer > 0) { text = "Auto refreshing in " + timer + "..."; } else { text = "Auto refreshing now..."; } btn.innerHTML = text; }, 1000); timeout = setTimeout(function () { refreshBtn.click(); }, 1000 * timer); }; if (refreshBtn) { note = document.createTextNode("Auto refreshing in " + timer + "..."); btn = document.createElement("button"); btn.className += " auto-refresh"; btn.addEventListener("click", toggleAutoRefresh); btn.appendChild(note); document.body.appendChild(btn); if (autoRefresh) { startAutoRefresh(); } } // Delete a history entry in deployment center if more than 5 entries var KEEP_ENTRIES = 5; var historyEntries = document.querySelectorAll("tr[class^='bgcolor-list-']"); Array.from(historyEntries).forEach(function (el, i) { if (i < historyEntries.length - KEEP_ENTRIES) { el.querySelector("input[type=\"checkbox\"]").click(); } }); if (historyEntries.length > KEEP_ENTRIES) { document.getElementById("delete").click(); } } // Append SSO link if (document.querySelector("#login-form .login-links")) { var sspSpan = document.createElement("span"); var ssoLink = document.createElement("a"); var ssoText = document.createTextNode("SSO Login"); sspSpan.classList.add("login-link"); ssoLink.classList.add("commerce-sidebar-item"); ssoLink.setAttribute("href", "/sso/saml_request.jsp"); ssoLink.appendChild(ssoText); sspSpan.appendChild(ssoLink); document.querySelector("#login-form .login-links").appendChild(sspSpan); } // Konami Kickass if (window.addEventListener) { var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65"; window.addEventListener("keydown", function (e) { kkeys.push(e.keyCode); if (kkeys.toString().indexOf(konami) >= 0) { var s = document.createElement("script"); s.type = "text/javascript"; document.body.appendChild(s); s.src = "//hi.kickassapp.com/kickass.js"; kkeys = []; } }, true); } // Prevent Timeout (auto clicks on 'Continue Working' button) setInterval(function () { var timeOutPopup = document.getElementById("session-timeout-popup"); var timeOutBtn = document.getElementById("reset-session"); if (timeOutPopup && timeOutPopup.style.display != "none") { timeOutBtn.click(); } }, 30000); // Hightlight Config util functions in migration tool // Set listeners everytime the DOM has something added or removed const migrationTree = document.body; //document.getElementById("nav-tree"); if (migrationTree) { let mutationObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === "childList" && $("#nav-tree_HLD-0-0 .x-tree3-node") // The utils folder is visible && $("#nav-tree_HLD-0-0 .x-item-expanded").length > 0 // The utils folder is expanded && !$("#nav-tree_HLD-0-0 .x-item-expanded").hasClass("x-item-checkbox-gone") // The utils folder has a checkbox (Usually no checkbox if no mode) ) { // Other util functions $("#nav-tree_HLD-0-0 .x-tree3-node .x-tree3-node-text") .filter((i, el) => $(el).text().indexOf("HWSW") < 0 && $(el).text().indexOf("C:") < 0) .closest(".x-tree3-node").addClass("other-util"); // In-sync utils $("#nav-tree_HLD-0-0 .x-tree3-node .x-tree3-node-text") .filter((i, el) => $(el).siblings(".x-tree3-node-icon").attr("style").indexOf("tick.png") >= 0) .closest(".x-tree3-node").addClass("in-sync-util"); // HWSW $("#nav-tree_HLD-0-0 .x-tree3-node .x-tree3-node-text") .filter((i, el) => $(el).text().indexOf("HWSW") >= 0) .closest(".x-tree3-node").addClass("hwsw-util"); // CC: $("#nav-tree_HLD-0-0 .x-tree3-node .x-tree3-node-text") .filter((i, el) => $(el).text().indexOf("CC:") >= 0) .closest(".x-tree3-node").addClass("cc-util"); // C: $("#nav-tree_HLD-0-0 .x-tree3-node .x-tree3-node-text") .filter((i, el) => $(el).text().indexOf("C:") >= 0 && !$(el).closest(".x-tree3-node").hasClass("cc-util")) .closest(".x-tree3-node").addClass("c-util"); } }); }); mutationObserver.observe(migrationTree, { attributes: true, characterData: true, childList: true, subtree: true, attributeOldValue: true, characterDataOldValue: true }); } // Show Hidden Grid const hiddenGridInterval = setInterval(() => { const hiddenGrid = document.querySelector('.hidden-grid'); if (hiddenGrid) { clearInterval(hiddenGridInterval); const showHiddenGrid = () => { hiddenGrid.style.display = "block"; } let hdnGridBtn = document.createElement("button"); hdnGridBtn.classList.add("btn-show-hidden-grid"); let hdnGridTxt = document.createTextNode("Show Hidden Grid"); hdnGridBtn.appendChild(hdnGridTxt); document.body.appendChild(hdnGridBtn); hdnGridBtn.addEventListener("click", (e) => { showHiddenGrid(); e.target.style.display = "none"; }); } }, 500); // Attributes Serializations + JSON pretty print // Only for pipeline viewer var pipelineViewerUrls = ["pipeline_viewer_config.jsp"]; if (pipelineViewerUrls.indexOf(document.URL.split("/").pop().split("?").shift()) >= 0) { const serializeState = (el, label) => { if (el.length) { const stateTxt = el.closest("tr").children().eq(1).text(); if (stateTxt.indexOf("$$$") >= 0) { let allParts = {}; stateTxt.split("$$$") .forEach(apt => { const apa = apt.split(":::"); let apVal = apa[1] || ''; if (apVal.indexOf("@@") >= 0) { apVal = apVal.split("@@").map(val => { if (val.indexOf("+++") >= 0) { const objVal = {}; val.split("+++").forEach(tva => { const subValArr = tva.split("==="); objVal[subValArr[0]] = subValArr[1]; }); return objVal; } return val; }); } else if (apVal.indexOf("+++") >= 0) { const objVal = {}; apVal.split("+++").forEach(tva => { const subValArr = tva.split("==="); objVal[subValArr[0]] = subValArr[1]; }); apVal = objVal; } if (apa[0].trim()) allParts[apa[0].trim()] = apVal; }); console.log(label, allParts); } } }; const stateLabels = ['All Parts State', 'Cache Date State', 'Quote State', 'Selected Parts State', 'Filters State', 'Search State', 'Messages State']; stateLabels.forEach(stateLabel => serializeState($(`tr td.form-label:first-child:contains("${stateLabel}")`), stateLabel)); // pretty print Array.from(document.querySelectorAll(`#tab_attributes tr`)).forEach(c => { const attrLabelEl = c.querySelector("td.form-label"); const attrValEl = c.querySelector("td.form-input"); const attrVal = attrValEl?.innerText; if (attrVal?.startsWith("{")) { try { attrValEl.innerHTML = "<textarea rows='4' cols='50'>" + JSON.stringify(JSON.parse(attrVal), undefined, 2) + "</textarea>"; } catch (e) { console.info("skipped invalid JSON", attrLabelEl.innerText); } } if (attrVal?.length > 5) { const copyBtn = document.createElement("button"); copyBtn.innerText = "Copy to clipboard"; copyBtn.classList.add("copy-btn"); copyBtn.addEventListener('click', e => { e.preventDefault(); navigator.clipboard.writeText(attrVal); }); attrLabelEl?.append(copyBtn); } }); const headerTitles = ["Attribute Name", "Attribute Value", "Input to Rules"]; headerTitles.forEach((headerTitle, i) => { const attrNameHead = $(`#tab_attributes td.view-header:contains("${headerTitle}")`); const searchAttrEl = $(`<input type='text' class='pipeline-search' placeholder='${headerTitle}' ${i==0 ? 'autofocus' : ''} />`); searchAttrEl.keyup(se => { const currentEl = $(se.target); $(".pipeline-search").not(currentEl).val(''); $(`#tab_attributes tr.bgcolor-form`).addClass('hidden-row'); if (i == 0) { // Search labels colum $(`tr td.form-label:containsi("${searchAttrEl.val()}")`).each((i, e) => $(e).closest('tr').removeClass("hidden-row")); } else { // Search other columns $(`tr td.form-input:nth-child(${i+1}):containsi("${searchAttrEl.val()}")`).each((i, e) => $(e).closest('tr').removeClass("hidden-row")); } }); attrNameHead.html(searchAttrEl); }); } // Styling Stuff var bm_css_src = ` /* Stupid Field: fix to text box that is completely covered by scroll bar in firefox */ .x-form-field-wrap.x-component, .x-small-editor, .x-grid-editor { overflow: hidden !important; } /* Force enable all homepage tabs */ #mainnav li { display: inline !important; } button.auto-refresh { position: fixed; bottom: 0; left: 5em; color: #fff; background-color: #d9534f; border-color: #d43f3a; display: inline-block; padding: 3px 6px; margin-bottom: 0; font-size: 11px; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-image: none; border: 1px solid transparent; border-radius: 5px 5px 0 0; } ul.features-menu { position: fixed; left: -71%; bottom: 0; width: 70%; transition: left .3s ease-in-out; margin: 0 0 10px 25px; } ul.features-menu.expanded { left: 100px; } ul.features-menu li { display: inline-block; border: 2px solid red; border-radius: 3px; cursor: pointer; padding: 3px; margin: 3px; color: #777; background-color: #fff; box-shadow: 0 0 3px 1px #888; } ul.features-menu li.enabled { border: 2px solid green; color: #000; } ul.features-menu li.btn-expand { float: right; position: absolute; bottom: 0; right: -35px; width: 16px; height: 16px; font-size: 3em; line-height: .3; } .btn-show-hidden-grid { position: fixed; bottom: 0; right: 10%; translate: 50%; background: rgba(90, 90, 90, 0.3); border: 1px solid #ccc; font-size: 12px; padding: 5px 10px; cursor: pointer; z-index: 999; } iframe.ext-shim, tr.hidden-row { display: none !important; } .hwsw-util .x-tree3-node-text, .cc-util .x-tree3-node-text, .c-util .x-tree3-node-text { font-weight: bold; } .hwsw-util { background-color: rgba(50, 50, 250, 0.5); } .cc-util { background-color: rgba(250, 50, 50, 0.5) } .c-util { background-color: rgba(50, 250, 50, 0.5); } .other-util, .in-sync-util { opacity: 0.5; } td.view-header { text-align: center; } td.form-input { max-width: 700px; overflow-wrap: break-word; } button.copy-btn { margin: 1em 0 1em 1em; background: none; border: 1px solid #ccc; cursor: pointer; } `; // eslint-disable-next-line no-undef GM_addStyle(bm_css_src);