├── .DS_Store ├── .gitignore ├── CRMS Extension ├── .DS_Store ├── control.html ├── images │ ├── icon-128.png │ ├── icon-16.png │ ├── icon-32.png │ └── icon-48.png ├── manifest.json ├── popup.js ├── scrapestyle.css ├── scripts │ ├── additem.js │ ├── addtab.js │ ├── autocheckin.js │ ├── availabilityscrape.js │ ├── containercheckin.js │ ├── content.js │ ├── cost-injected.js │ ├── costsview.js │ ├── detail-header-injected.js │ ├── globalassetshortcut.js │ ├── globalsearchoppscrape.js │ ├── injected.js │ ├── order-header-injected.js │ ├── productpage.js │ ├── purchaseorderspage.js │ ├── removeasset.js │ ├── servicespage.js │ └── test-injected.js ├── service-worker.js ├── sounds │ ├── alert.wav │ ├── container_scan_sound.mp3 │ ├── correct.mp3 │ ├── error_sound.wav │ ├── scan_sound.mp3 │ └── short_alert.mp3 └── style.css ├── Container Scan Barcode Example.png ├── Features.md ├── Free Scan Toggle Barcode Example.png ├── README.md ├── Revert Scan Barcode Example.png └── custom_field_alert /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | CRMS Extension/.DS_Store 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /CRMS Extension/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/CRMS Extension/.DS_Store -------------------------------------------------------------------------------- /CRMS Extension/control.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 30 | 31 |
32 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /CRMS Extension/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/CRMS Extension/images/icon-128.png -------------------------------------------------------------------------------- /CRMS Extension/images/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/CRMS Extension/images/icon-16.png -------------------------------------------------------------------------------- /CRMS Extension/images/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/CRMS Extension/images/icon-32.png -------------------------------------------------------------------------------- /CRMS Extension/images/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompositeLight/currentRMS-helper/845f8b4a214f9660e807a13d2bcaaab33ad1ac67/CRMS Extension/images/icon-48.png -------------------------------------------------------------------------------- /CRMS Extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "CurrentRMS Helper", 4 | "version": "2.0.8", 5 | "description": "Adding functionality to Current RMS, one reduced click at a time.", 6 | "icons": { 7 | "16": "images/icon-16.png", 8 | "32": "images/icon-32.png", 9 | "48": "images/icon-48.png", 10 | "128": "images/icon-128.png" 11 | }, 12 | "action": { 13 | "default_popup": "control.html" 14 | }, 15 | 16 | 17 | "permissions": ["activeTab", "tabs", "scripting", "ttsEngine", "storage", "unlimitedStorage"], 18 | 19 | "host_permissions": [ 20 | "https://api.current-rms.com/*" 21 | ], 22 | 23 | 24 | "content_scripts": [ 25 | { 26 | "matches": ["https://*.current-rms.com/*"], 27 | "exclude_matches": [ 28 | "https://*.current-rms.com/availability/opportunity/*", 29 | "https://*.current-rms.com/opportunity_items/*", 30 | "https://*.current-rms.com/products/*", 31 | "https://*.current-rms.com/opportunities/*view=c", 32 | "https://*.current-rms.com/opportunities?*", 33 | "https://*.current-rms.com/opportunities", 34 | "https://*.current-rms.com/products?*", 35 | "https://*.current-rms.com/purchase_orders*", 36 | "https://*.current-rms.com/services*", 37 | "https://*.current-rms.com/global_check_in?autocheckin&*" 38 | ], 39 | "js": ["scripts/content.js", "scripts/addtab.js"], 40 | "css": ["style.css"], 41 | "run_at": "document_end" 42 | }, 43 | { 44 | "matches": ["https://*.current-rms.com/availability/opportunity/*"], 45 | "js": ["scripts/availabilityscrape.js", "scripts/addtab.js"], 46 | "css": ["scrapestyle.css"] 47 | }, 48 | { 49 | "matches": ["https://*.current-rms.com/opportunity_items/*/edit?rp=*"], 50 | "js": ["scripts/removeasset.js", "scripts/addtab.js"], 51 | "css": ["scrapestyle.css"] 52 | }, 53 | { 54 | "matches": ["https://*.current-rms.com/opportunities/*view=c"], 55 | "js": ["scripts/costsview.js", "scripts/addtab.js"], 56 | "css": ["style.css"] 57 | }, 58 | { 59 | "matches": ["https://*.current-rms.com/products/*", "https://*.current-rms.com/products?*"], 60 | "js": ["scripts/productpage.js", "scripts/addtab.js"], 61 | "css": ["style.css"] 62 | }, 63 | { 64 | "matches": ["https://*.current-rms.com/opportunities?*", "https://*.current-rms.com/opportunities"], 65 | "js": ["scripts/globalsearchoppscrape.js", "scripts/addtab.js"], 66 | "css": ["scrapestyle.css"] 67 | }, 68 | { 69 | "matches": ["https://*.current-rms.com/opportunity_items/new?*"], 70 | "js": ["scripts/additem.js", "scripts/addtab.js"], 71 | "css": ["style.css"] 72 | }, 73 | { 74 | "matches": ["https://*.current-rms.com/purchase_orders*"], 75 | "js": ["scripts/purchaseorderspage.js", "scripts/addtab.js"], 76 | "css": ["style.css"] 77 | }, 78 | { 79 | "matches": ["https://*.current-rms.com/services*"], 80 | "js": ["scripts/servicespage.js", "scripts/addtab.js"], 81 | "css": ["style.css"] 82 | }, 83 | { 84 | "matches": ["https://*.current-rms.com/global_search?*"], 85 | "js": ["scripts/globalassetshortcut.js"] 86 | }, 87 | { 88 | "matches": ["https://*.current-rms.com/serialised_containers/*"], 89 | "js": ["scripts/containercheckin.js"], 90 | "css": ["style.css"] 91 | }, 92 | { 93 | "matches": ["https://*.current-rms.com/global_check_in?autocheckin&*"], 94 | "js": ["scripts/autocheckin.js"] 95 | } 96 | 97 | ], 98 | "background": { 99 | "service_worker": "/service-worker.js", 100 | "type": "module" 101 | }, 102 | "web_accessible_resources": [ 103 | { 104 | "resources": [ 105 | "sounds/error_sound.wav", 106 | "sounds/scan_sound.mp3", 107 | "sounds/correct.mp3", 108 | "sounds/alert.wav", 109 | "sounds/short_alert.mp3", 110 | "sounds/container_scan_sound.mp3", 111 | "scripts/injected.js", 112 | "scripts/cost-injected.js", 113 | "scripts/test-injected.js", 114 | "scripts/detail-header-injected.js", 115 | "scripts/order-header-injected.js", 116 | "style.css" 117 | ], 118 | "matches": [ 119 | "*://*/*" 120 | ] 121 | } 122 | ] 123 | } 124 | -------------------------------------------------------------------------------- /CRMS Extension/popup.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var manifestData = chrome.runtime.getManifest(); 4 | document.getElementById("maifest-version").innerHTML = manifestData.version; 5 | getApiTime(); 6 | getQuarantineTime(); 7 | 8 | // Code for the Mark As Prepared setting: 9 | chrome.storage.local.get(["setPrepared"]).then((result) => { 10 | if (result.setPrepared == "false"){ 11 | document.querySelector(`input[name="markprepared"][value="false"]`).checked = true; 12 | } 13 | }); 14 | 15 | document.querySelectorAll('input[name="markprepared"]').forEach(function(radio) { 16 | radio.addEventListener('change', function() { 17 | console.log(this.value); 18 | //await chrome.storage.session.set({ prepareSet: this.value }); 19 | chrome.storage.local.set({ "setPrepared": this.value }).then(() => { 20 | console.log("Mark as prepared set"); 21 | }); 22 | }); 23 | }); 24 | 25 | // Event listener for Force Refresh button 26 | var refreshButton = document.getElementById("force-refresh-button"); 27 | refreshButton.addEventListener('click', function() { 28 | refreshButton.disabled = true; 29 | refreshButton.value = "Refreshing..."; 30 | console.log("Refresh clicked."); 31 | // Tell service worker to refresh the list 32 | chrome.runtime.sendMessage("refreshProducts"); 33 | }); 34 | 35 | 36 | // message listener to reset the button 37 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 38 | // Assuming the message contains some data 39 | console.log(message); 40 | if (message.messageType == "alert"){ 41 | alert(message.messageText); 42 | if (message.messageText.includes("API")){ 43 | refreshButton.disabled = false; 44 | refreshButton.value = "Force Refresh"; 45 | } 46 | } else if (message == "apidatawasrefreshed"){ 47 | refreshButton.disabled = false; 48 | refreshButton.value = "Force Refresh"; 49 | getApiTime(); 50 | } else if (message == "awaitingstock"){ 51 | refreshButton.disabled = true; 52 | refreshButton.value = "Refreshing stock records..."; 53 | } else if (message == "awaitingproducts"){ 54 | refreshButton.disabled = true; 55 | refreshButton.value = "Refreshing product records..."; 56 | } else if (message.messageType == "progress"){ 57 | var progressBar = document.getElementById("api-progress-bar"); 58 | progressBar.innerHTML = message.messageProgress+"%"; 59 | progressBar.style.width = message.messageProgress+"%"; 60 | progressBar.classList.add("w3-green"); 61 | } else if (message == "quarantinedatarefreshed"){ 62 | quarantinesRefreshButton.disabled = false; 63 | quarantinesRefreshButton.value = "Refresh Quarantines"; 64 | getQuarantineTime(); 65 | } 66 | 67 | 68 | }); 69 | 70 | // Event listener for Refresh Quarantines button 71 | var quarantinesRefreshButton = document.getElementById("quarantines-refresh-button"); 72 | quarantinesRefreshButton.addEventListener('click', function() { 73 | quarantinesRefreshButton.disabled = true; 74 | quarantinesRefreshButton.value = "Refreshing..."; 75 | console.log("Refresh Quarantines clicked."); 76 | // Tell service worker to refresh the list 77 | chrome.runtime.sendMessage("refreshQuarantines"); 78 | }); 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | // Get time of last API update stored in local storage 88 | function getApiTime(){ 89 | chrome.storage.local.get(["apiUpdateTime"]).then((result) => { 90 | if (result.apiUpdateTime){ 91 | var progressBar = document.getElementById("api-progress-bar"); 92 | progressBar.innerHTML = "Updated: "+result.apiUpdateTime; 93 | progressBar.style.width = "100%"; 94 | progressBar.classList.remove("w3-green"); 95 | progressBar.classList.remove("w3-white"); 96 | } 97 | }); 98 | } 99 | 100 | 101 | function getQuarantineTime(){ 102 | chrome.storage.local.get(["quarantineUpdateTime"]).then((result) => { 103 | if (result.quarantineUpdateTime){ 104 | var progressBar = document.getElementById("quarantine-progress-bar"); 105 | 106 | var updateTime = convertMillisToDateTimeString(result.quarantineUpdateTime); 107 | 108 | 109 | progressBar.innerHTML = "Updated: "+updateTime; 110 | progressBar.style.width = "100%"; 111 | progressBar.classList.remove("w3-green"); 112 | progressBar.classList.remove("w3-white"); 113 | } 114 | }); 115 | } 116 | 117 | // Code for getting the Allocate by Default radio button to match the stored value 118 | chrome.storage.local.get(["soundsOn"]).then((result) => { 119 | if (result.soundsOn == "false"){ 120 | document.querySelector(`input[name="soundson"][value="false"]`).checked = true; 121 | } 122 | }); 123 | 124 | // Code for watching the Extension sounds radio buttons for changes and updating local storage 125 | document.querySelectorAll('input[name="soundson"]').forEach(function(radio) { 126 | radio.addEventListener('change', function() { 127 | console.log(this.value); 128 | chrome.storage.local.set({ "soundsOn": this.value }).then(() => { 129 | console.log("Extension sounds setting was changed"); 130 | chrome.runtime.sendMessage("soundchanged"); 131 | }); 132 | 133 | }); 134 | }); 135 | 136 | 137 | 138 | 139 | // Code for getting the Allocate by Default radio button to match the stored value 140 | chrome.storage.local.get(["allocateDefault"]).then((result) => { 141 | if (result.allocateDefault == "false"){ 142 | document.querySelector(`input[name="allocatedefault"][value="false"]`).checked = true; 143 | } 144 | }); 145 | 146 | // Code for watching the Allocate by Default radio buttons for changes and updating local storage 147 | document.querySelectorAll('input[name="allocatedefault"]').forEach(function(radio) { 148 | radio.addEventListener('change', function() { 149 | console.log(this.value); 150 | //await chrome.storage.session.set({ prepareSet: this.value }); 151 | chrome.storage.local.set({ "allocateDefault": this.value }).then(() => { 152 | console.log("Allocate View by Default setting was changed"); 153 | }); 154 | 155 | }); 156 | }); 157 | 158 | 159 | 160 | // Code for getting the Prepared radio button to match the stored value 161 | chrome.storage.local.get(["setPrepared"]).then((result) => { 162 | if (result.setPrepared == "false"){ 163 | document.querySelector(`input[name="markprepared"][value="false"]`).checked = true; 164 | } 165 | }); 166 | 167 | 168 | 169 | // Code for the Announce Inspections setting: 170 | chrome.storage.local.get(["inspectionAlert"]).then((result) => { 171 | if (result.inspectionAlert){ 172 | var selectedOption = "input[name='inspectionalert'][value='" + result.inspectionAlert + "']"; 173 | document.querySelector(selectedOption).checked = true; 174 | } 175 | }); 176 | 177 | document.querySelectorAll('input[name="inspectionalert"]').forEach(function(radio) { 178 | radio.addEventListener('change', function() { 179 | console.log(this.value); 180 | //await chrome.storage.session.set({ prepareSet: this.value }); 181 | chrome.storage.local.set({ "inspectionAlert": this.value }).then(() => { 182 | console.log("Inspection alert set"); 183 | chrome.runtime.sendMessage({ inspectionAlerts: this.value }); 184 | }); 185 | 186 | }); 187 | }); 188 | 189 | // Code for the Global Check-in setting: 190 | chrome.storage.local.get(["multiGlobal"]).then((result) => { 191 | if (result.multiGlobal){ 192 | var selectedOption = "input[name='multiglobal'][value='" + result.multiGlobal + "']"; 193 | document.querySelector(selectedOption).checked = true; 194 | } 195 | }); 196 | 197 | document.querySelectorAll('input[name="multiglobal"]').forEach(function(radio) { 198 | radio.addEventListener('change', function() { 199 | console.log(this.value); 200 | //await chrome.storage.session.set({ prepareSet: this.value }); 201 | chrome.storage.local.set({ "multiGlobal": this.value }).then(() => { 202 | console.log("Global check-in overide set"); 203 | chrome.runtime.sendMessage({ multiGlobal: this.value }); 204 | }); 205 | 206 | }); 207 | }); 208 | 209 | 210 | 211 | 212 | 213 | // Code for the auto book out nested containers setting: 214 | chrome.storage.local.get(["bookOutContainers"]).then((result) => { 215 | console.log(result.bookOutContainers); 216 | if (result.bookOutContainers){ 217 | var selectedOption = "input[name='bookoutcontainers'][value='" + result.bookOutContainers + "']"; 218 | document.querySelector(selectedOption).checked = true; 219 | } 220 | }); 221 | 222 | document.querySelectorAll('input[name="bookoutcontainers"]').forEach(function(radio) { 223 | radio.addEventListener('change', function() { 224 | console.log(this.value); 225 | //await chrome.storage.session.set({ prepareSet: this.value }); 226 | chrome.storage.local.set({ "bookOutContainers": this.value }).then(() => { 227 | console.log("Auto Book Out nested containers changed"); 228 | console.log(this.value); 229 | chrome.runtime.sendMessage("bookOutContainers"); 230 | }); 231 | 232 | }); 233 | }); 234 | 235 | 236 | 237 | // Code for the disable detail view delete function setting: 238 | chrome.storage.local.get(["detailDelete"]).then((result) => { 239 | console.log(result.detailDelete); 240 | if (result.detailDelete){ 241 | var selectedOption = "input[name='detaildelete'][value='" + result.detailDelete + "']"; 242 | document.querySelector(selectedOption).checked = true; 243 | } 244 | }); 245 | 246 | document.querySelectorAll('input[name="detaildelete"]').forEach(function(radio) { 247 | radio.addEventListener('change', function() { 248 | console.log(this.value); 249 | //await chrome.storage.session.set({ prepareSet: this.value }); 250 | chrome.storage.local.set({ "detailDelete": this.value }).then(() => { 251 | console.log("Disable Detail View Delete setting changed"); 252 | console.log(this.value); 253 | chrome.runtime.sendMessage("detailDelete"); 254 | }); 255 | 256 | }); 257 | }); 258 | 259 | 260 | 261 | 262 | 263 | 264 | // Code for the block scan of quartantines setting: 265 | chrome.storage.local.get(["blockQuarantines"]).then((result) => { 266 | if ("blockQuarantines" in result){ 267 | console.log(result); 268 | var selectedOption = "input[name='blockquarantines'][value='" + result.blockQuarantines + "']"; 269 | document.querySelector(selectedOption).checked = true; 270 | } 271 | 272 | }); 273 | 274 | document.querySelectorAll('input[name="blockquarantines"]').forEach(function(radio) { 275 | radio.addEventListener('change', function() { 276 | console.log(this.value); 277 | //await chrome.storage.session.set({ prepareSet: this.value }); 278 | chrome.storage.local.set({ "blockQuarantines": this.value }).then(() => { 279 | console.log("Block Quarantines option set"); 280 | chrome.runtime.sendMessage({ blockQuarantines: this.value }); 281 | }); 282 | 283 | }); 284 | }); 285 | 286 | 287 | 288 | 289 | // Code for the error timeout setting 290 | 291 | var timeOutBox = document.getElementById('error-message-timeout'); 292 | 293 | chrome.storage.local.get(["errorTimeout"]).then((result) => { 294 | if ("errorTimeout" in result){ 295 | console.log(result); 296 | console.log("errorTimeout:" + result.errorTimeout); 297 | timeOutBox.value = result.errorTimeout; 298 | } 299 | }); 300 | 301 | 302 | timeOutBox.addEventListener('change', function() { 303 | console.log(this.value); 304 | chrome.storage.local.set({ "errorTimeout": this.value }).then(() => { 305 | console.log("errorTimeout value set"); 306 | chrome.runtime.sendMessage("errortimeoutchanged"); 307 | }); 308 | 309 | }); 310 | 311 | 312 | 313 | // Code for the Show Collapsed Item Totals setting: 314 | chrome.storage.local.get(["nestedTotals"]).then((result) => { 315 | console.log(result.nestedTotals); 316 | if (result.nestedTotals){ 317 | var selectedOption = "input[name='nestedtotals'][value='" + result.nestedTotals + "']"; 318 | document.querySelector(selectedOption).checked = true; 319 | } 320 | }); 321 | 322 | document.querySelectorAll('input[name="nestedtotals"]').forEach(function(radio) { 323 | radio.addEventListener('change', function() { 324 | console.log(this.value); 325 | 326 | chrome.storage.local.set({ "nestedTotals": this.value }).then(() => { 327 | console.log("Show Collapsed Item Totals setting changed"); 328 | console.log(this.value); 329 | chrome.runtime.sendMessage("nestedTotals"); 330 | }); 331 | 332 | }); 333 | }); 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | // API Settings section 348 | // Get the current API details if stored. 349 | chrome.storage.local.get(["api-details"]).then((result) => { 350 | console.log(result); 351 | if (result["api-details"].apiKey){ 352 | document.getElementById("api-key-input").value = result["api-details"].apiKey; 353 | } else { 354 | console.log("No API key saved in local storage."); 355 | } 356 | if (result["api-details"].apiSubdomain){ 357 | document.getElementById("api-subdomain-input").value = result["api-details"].apiSubdomain; 358 | } else { 359 | console.log("No API Subdomain saved in local storage."); 360 | } 361 | }); 362 | 363 | // no add event listener to save api details button 364 | var setAPIButton = document.getElementById("api-save"); 365 | setAPIButton.addEventListener('click', function() { 366 | 367 | var theApiKey = document.getElementById("api-key-input").value; 368 | var theApiSubdomain = document.getElementById("api-subdomain-input").value; 369 | var apiDetails = {apiKey: theApiKey, apiSubdomain: theApiSubdomain}; 370 | 371 | setAPIButton.disabled = true; 372 | setAPIButton.value = "Saving..."; 373 | chrome.storage.local.set({ "api-details": apiDetails }).then(() => { 374 | console.log("API details were saved into local storage."); 375 | setAPIButton.disabled = false; 376 | setAPIButton.value = "Save API Details"; 377 | }); 378 | 379 | 380 | }); 381 | 382 | 383 | 384 | function convertMillisToDateTimeString(milliseconds) { 385 | const date = new Date(milliseconds); 386 | 387 | // Padding function to ensure single-digit numbers are preceded by a 0 388 | const pad = (num) => num.toString().padStart(2, '0'); 389 | 390 | // Extracting date and time parts 391 | const hours = pad(date.getHours()); 392 | const minutes = pad(date.getMinutes()); 393 | const seconds = pad(date.getSeconds()); 394 | const day = pad(date.getDate()); 395 | const month = pad(date.getMonth() + 1); // Months are zero-indexed 396 | const year = date.getFullYear().toString().substr(-2); // Getting last two digits of the year 397 | 398 | // Formatting to "hh:mm:ss dd:mm:yy" 399 | return `${hours}:${minutes}:${seconds} ${day}/${month}/${year}`; 400 | } 401 | 402 | 403 | 404 | 405 | if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { 406 | // It's dark mode 407 | document.body.classList.add('dark-mode'); 408 | } else { 409 | console.log("Light mode"); 410 | // It's light mode 411 | document.body.classList.add('light-mode'); 412 | } 413 | -------------------------------------------------------------------------------- /CRMS Extension/scrapestyle.css: -------------------------------------------------------------------------------- 1 | .block-out { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | background-color: rgba(0, 0, 0, 0.8); 8 | z-index: 1500; 9 | pointer-events: auto; /* Prevent clicks on content underneath */ 10 | 11 | /* Flexbox to center the content */ 12 | display: flex; 13 | align-items: center; /* Vertical centering */ 14 | justify-content: center; /* Horizontal centering */ 15 | color: white; /* White text color */ 16 | font-size: 4em; /* Larger text size */ 17 | text-align: center; /* Center text alignment */ 18 | padding: 20px; /* Padding for text */ 19 | } 20 | 21 | td.row-avatar{ 22 | cursor: zoom-in !important; 23 | } 24 | -------------------------------------------------------------------------------- /CRMS Extension/scripts/additem.js: -------------------------------------------------------------------------------- 1 | console.log("CurrentRMS Helper Activated - additem.js"); 2 | 3 | const textButton = document.getElementById("opportunity_item_item_type_textitem"); 4 | const productButton = document.getElementById("opportunity_item_item_type_item"); 5 | 6 | const productInput = document.getElementById("opportunity_item_item_name"); 7 | const textInput = document.getElementById("opportunity_item_name"); 8 | 9 | textButton.addEventListener('click', function(event) { 10 | textInput.value = productInput.value; 11 | }); 12 | -------------------------------------------------------------------------------- /CRMS Extension/scripts/addtab.js: -------------------------------------------------------------------------------- 1 | 2 | let recentOppsList = []; 3 | 4 | if (!orderView){ 5 | var orderView = false; 6 | } 7 | if (!detailView){ 8 | var detailView = false; 9 | } 10 | 11 | getSetRecents(); 12 | 13 | function getSetRecents(){ 14 | // get the multi global check in setting from local storage 15 | chrome.storage.local.get(["recentsOpps"]).then((result) => { 16 | 17 | if (result.recentsOpps != undefined){ 18 | recentOppsList = result.recentsOpps; 19 | } 20 | // populate the tab on this page 21 | // Call the function to add the menu item 22 | addMenuItemToNavbar(); 23 | 24 | // now check if we need to add a new entry to the list 25 | if (orderView || detailView){ 26 | 27 | //var title = document.querySelector("h1.subject-title").innerText; 28 | var titleElement = document.querySelector("h1.subject-title"); 29 | var title = Array.from(titleElement.childNodes) 30 | .filter(node => node.nodeType === Node.TEXT_NODE) 31 | .map(node => node.textContent.trim()) 32 | .join(" "); 33 | 34 | 35 | // scrape the opportunity ID from the page URL if there is one 36 | let opportunityID = (function() { 37 | const currentUrl = window.location.href; 38 | // Use a regular expression to match the opportunity ID in the URL 39 | const match = currentUrl.match(/\/opportunities\/(\d+)/); 40 | // Check if there is a match and return the opportunity ID (group 1 in the regex) 41 | return match ? match[1] : null; 42 | })(); 43 | 44 | // Check if opportunityID already exists in the recentOppsList array of objects 45 | const found = recentOppsList.some(item => item[opportunityID] !== undefined); 46 | 47 | if (found){ 48 | const filteredOppsList = recentOppsList.filter(obj => !obj.hasOwnProperty(opportunityID)); 49 | filteredOppsList.unshift({[opportunityID]: title}); 50 | recentOppsList = filteredOppsList; 51 | } else { 52 | recentOppsList.unshift({[opportunityID]: title}); 53 | }; 54 | 55 | while (recentOppsList.length > 10) { 56 | recentOppsList.splice(-1, 1); // Remove the last element 57 | } 58 | 59 | chrome.storage.local.set({'recentsOpps': recentOppsList}).then(() => { 60 | //console.log("Recent opps list was updated"); 61 | //console.log("Recent Opps:"); 62 | //console.log(recentOppsList); 63 | }); 64 | 65 | 66 | }; 67 | 68 | }); 69 | } 70 | 71 | function clearRecentOpportunitiesList() { 72 | chrome.storage.local.set({'recentsOpps': []}).then(() => { 73 | console.log("Recent opps list was cleared"); 74 | recentOppsList = []; 75 | getSetRecents(); 76 | }); 77 | } 78 | 79 | 80 | 81 | function addMenuItemToNavbar() { 82 | // Find the first