NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name CPQ Sanity Helper Tweaks // @namespace https://cpqav.bigmachines.com/admin/filemanager/list_files.jsp // @version 0.1 // @description CPQ Sanity Helper Tweaks // @author Obada Kadri // @match *://*.bigmachines.com/* // @grant GM_addStyle // ==/UserScript== console.info('Sanity Helper V0.1'); // Initializations var checkedAssetStringAttributes = []; var cartParts = []; var excludedAttributes = ['bm_cm_model_id', 'quoteName_AP', 'quoteNumber_AP', 'contractStartDate_AP', 'contractDuration_AP', 'operationType_AP', 'operatingUnit_AP', 'contractEndDate_AP', 'contractCurrency_AP', 'dataCenterRegion_AP']; var cartTable = document.getElementById('mandatory-parts'); var activeAttributes = document.querySelectorAll("input[type='text'],input[type='checkbox'],select"); // Grab the assetString (might have different names depending on model) var configAssetString = document.querySelector("[name='configAssetString_ERP']"); var minimumQuantityString = document.querySelector("[name='minimumQuantityString_PF']"); var assetString = (configAssetString ? configAssetString.value : "") + (minimumQuantityString ? minimumQuantityString.value : ""); //////////////// // Prototypes // //////////////// var SanityEl = function(type, attrs) { var self = this; self.el = document.createElement(type); document.body.appendChild(self.el); if (attrs instanceof Object) { Object.keys(attrs).forEach(function(key) { self.el.setAttribute(key, attrs[key]); }); } self.setText = function(text) { var textEl = document.createTextNode(text); self.el.appendChild(textEl); }; }; // UI Elements var sanityToolbar = new SanityEl('ul', { class: 'sanity-toolbar'}); // Construct the cartParts array if a cart is available if (cartTable) { var cartRows = cartTable.querySelectorAll('tbody tr.adv-grid-row'); cartParts = Array.from(cartRows).map(function (row) { return { part_td: row.querySelector('td.part_number'), part_number: row.querySelector('td.part_number').textContent, quantity: row.querySelector('td.Quantity').textContent, description: row.querySelector('td.description').textContent }; }); var cartHeading = document.getElementById('mandatory-parts-wrapper').querySelector('.grouping-heading'); var btnCopyCart = new SanityEl('button', { class: 'btn-copy-cart'}); btnCopyCart.setText('Copy Cart to Clipboard'); btnCopyCart.el.addEventListener("click", function (e) { e.stopPropagation(); e.preventDefault(); copyTextToClipboard( cartParts.map(function(part) { return [part.part_number, part.description, part.quantity].join('\t'); }).join('\n') ); }); cartHeading.appendChild(btnCopyCart.el); } if (assetString) { // Loop over assetString parts to check against cartParts var assetStringArr = assetString.split("@@") .filter(function (p) { return p.length; }) .map(function (p) { return p.split('##'); }); assetStringArr.forEach(function (p) { var node = document.querySelector(".attribute-field-container [name='" + p[1] + "']"); var isChecked = checkedAssetStringAttributes.indexOf(p[0]) >= 0; if (node && !isChecked) { var parent = node.parentNode; var readOnlyHasValue = (node.type == "hidden" && node.value && node.value != "0"); var textboxHasValue = (node.type == "text" && node.value && node.value != "0"); var checkboxIsChecked = (node.type == "checkbox" && node.checked); var singleSelectIsSelected = (node.type === "select-one" && node.value !== "" && node.value !== "No"); if (readOnlyHasValue || textboxHasValue || checkboxIsChecked || singleSelectIsSelected) { var partInCart = cartParts.some(function (part) { return p[0] == part.part_number; }); var inputMeta = new SanityEl('span', { class: partInCart ? 'green' : 'red' }); inputMeta.setText(" " + p[0] + " (" + p[2] + ")"); parent.appendChild(inputMeta.el); checkedAssetStringAttributes.push(p[0]); } } }); // Loop over cartParts to check against checkedAssetStringAttributes parts cartParts.forEach(function (p) { if (checkedAssetStringAttributes.indexOf(p.part_number) >= 0) { p.part_td.classList.add("green"); } else { p.part_td.classList.add("red"); console.warn(p.part_number + " is in cart but the attribute has no value"); } }); // Loop over activeAttributes to check against assetString parts Array.from(activeAttributes).map( function (a) { var existsInAssetString = checkedAssetStringAttributes.some(function (p) { return p[1] == a.name; }); var isExcluded = excludedAttributes.indexOf(a.name) >= 0; if (!(existsInAssetString || isExcluded)) { // console.log("%c Note: " + a.name + " is not in assetString", "color: #AA9900"); } }); } function copyTextToClipboard(text) { var textArea = document.createElement("textarea"); // // *** This styling is an extra step which is likely not required. *** // // Why is it here? To ensure: // 1. the element is able to have focus and selection. // 2. if element was to flash render it has minimal visual impact. // 3. less flakyness with selection and copying which **might** occur if // the textarea element is not visible. // // The likelihood is the element won't even render, not even a flash, // so some of these are just precautions. However in IE the element // is visible whilst the popup box asking the user for permission for // the web page to copy to the clipboard. // // Place in top-left corner of screen regardless of scroll position. textArea.style.position = 'fixed'; textArea.style.top = 0; textArea.style.left = 0; // Ensure it has a small width and height. Setting to 1px / 1em // doesn't work as this gives a negative w/h on some browsers. textArea.style.width = '2em'; textArea.style.height = '2em'; // We don't need padding, reducing the size if it does flash render. textArea.style.padding = 0; // Clean up any borders. textArea.style.border = 'none'; textArea.style.outline = 'none'; textArea.style.boxShadow = 'none'; // Avoid flash of white box if rendered for any reason. textArea.style.background = 'transparent'; textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { var successful = document.execCommand('copy'); var msg = successful ? 'successful' : 'unsuccessful'; } catch (err) { console.error('Oops, unable to copy'); } document.body.removeChild(textArea); } // Styling Stuff var bm_css_src = ` .green { color: green; } .red { color: red; font-weight: bold; } .btn-copy-cart { float: right; font-size: 10px; } ul.sanity-toolbar { position: fixed; left: 0; bottom: 20%; list-style: none; margin: 0; z-index: 1; } ul.sanity-toolbar li { display: block; cursor: pointer; background-color: #00bada; opacity: 0.3; color: white; padding: 0 5px; right: 0; max-width: 3px; white-space: nowrap; overflow-x: hidden; border-radius: 0 5px 5px 0; -webkit-transition: all 0.5s; /* Safari */ transition: all 0.5s; margin: 10px 0; } ul.sanity-toolbar li:hover { max-width: 200px; opacity: 1; } ul.sanity-toolbar li.textboxes { background-color: #333333; } ul.sanity-toolbar li.checkboxes { background-color: #653479; } ul.sanity-toolbar li.dropdowns { background-color: #FF4500; } `; GM_addStyle(bm_css_src);