Skip to content

Commit 2805d92

Browse files
committed
initial commit
0 parents  commit 2805d92

12 files changed

+358
-0
lines changed

background/background.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
2+
if (changeInfo.status == "complete") {
3+
chrome.tabs.sendMessage(tabId, {
4+
message: "TAB LOADED",
5+
status: changeInfo.status
6+
});
7+
}
8+
});

manifest.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "Brewman v7 Tools",
4+
"version": "1.0",
5+
"description": "QoL changes to the Brewman v7 website",
6+
"permissions": [
7+
"storage",
8+
"tabs"
9+
],
10+
"content_scripts": [
11+
{
12+
"js": [
13+
"scripts/jquery-3.7.1.min.js",
14+
"scripts/waitForKeyElements.js",
15+
"scripts/waitForBrewmanLoad.js",
16+
"scripts/minimize.js",
17+
"scripts/searchFilter.js",
18+
"scripts/existingOrderWarning.js"
19+
],
20+
"matches": ["https://brewman.premiersystems.com/*"]
21+
}
22+
],
23+
"background": {
24+
"service_worker": "background/background.js"
25+
},
26+
"action": {
27+
"default_popup": "popup/popup.html"
28+
},
29+
"options_page": "options/options.html"
30+
}

options/options.html

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<body>
4+
<h1>User Details</h1>
5+
<label for="api-key">API Key:</label>
6+
<input type="text" id="api-key" size="40"><br>
7+
<h1>Minimize tabs</h1>
8+
<h2>Outlet CRM Page</h2>
9+
<input type="checkbox" id="minimize-crm-log-communication">
10+
<label for="log-communication">Log Communication</label><br>
11+
<input type="checkbox" id="minimize-crm-activity-log">
12+
<label for="activity-log">Activity Log</label><br>
13+
<input type="checkbox" id="minimize-crm-outlet-summary">
14+
<label for="outlet-summary">Outlet Summary</label><br>
15+
<input type="checkbox" id="minimize-crm-contacts">
16+
<label for="contacts">Contacts</label><br>
17+
<input type="checkbox" id="minimize-crm-upcoming-tasks-and-sales-visits">
18+
<label for="upcoming-tasks-and-sales-visits">Upcoming Tasks and Sales Visits</label><br>
19+
<input type="checkbox" id="minimize-crm-recently-ordered-products">
20+
<label for="recently-ordered-products">Recently Ordered Products</label><br>
21+
<input type="checkbox" id="minimize-crm-recent-orders">
22+
<label for="recent-orders">Recent Orders</label><br>
23+
<input type="checkbox" id="minimize-crm-recent-credit-notes">
24+
<label for="recent-credit-notes">Recent Credit Notes</label><br>
25+
<input type="checkbox" id="minimize-crm-containers-at-outlet">
26+
<label for="containers-at-outlet">Containers at Outlet</label><br>
27+
<br>
28+
<h2>Delivery Planning</h2>
29+
<h2>Distribution Processing</h2>
30+
<button id="save">Save</button>
31+
<p id="status" style="color:red;"></p>
32+
</body>
33+
<script src="options.js"></script>
34+
</html>

options/options.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function restoreOptions () {
2+
chrome.storage.local.get(null, (data) => {
3+
document.getElementById("api-key").value = data["apiKey"];
4+
document.getElementById("minimize-crm-log-communication").checked = data["minimize_crm"]["log_communication"];
5+
document.getElementById("minimize-crm-activity-log").checked = data["minimize_crm"]["activity_log"];
6+
document.getElementById("minimize-crm-outlet-summary").checked = data["minimize_crm"]["outlet_summary"];
7+
document.getElementById("minimize-crm-contacts").checked = data["minimize_crm"]["contacts"];
8+
document.getElementById("minimize-crm-upcoming-tasks-and-sales-visits").checked = data["minimize_crm"]["upcoming_tasks_and_sales_visits"];
9+
document.getElementById("minimize-crm-recently-ordered-products").checked = data["minimize_crm"]["recently_ordered_products"];
10+
document.getElementById("minimize-crm-recent-orders").checked = data["minimize_crm"]["recent_orders"];
11+
document.getElementById("minimize-crm-recent-credit-notes").checked = data["minimize_crm"]["recent_credit_notes"];
12+
document.getElementById("minimize-crm-containers-at-outlet").checked = data["minimize_crm"]["containers_at_outlet"];
13+
});
14+
};
15+
16+
function saveOptions () {
17+
chrome.storage.local.set({
18+
apiKey: document.getElementById("api-key").value,
19+
minimize_crm: {
20+
log_communication: document.getElementById("minimize-crm-log-communication").checked,
21+
activity_log: document.getElementById("minimize-crm-activity-log").checked,
22+
outlet_summary: document.getElementById("minimize-crm-outlet-summary").checked,
23+
contacts: document.getElementById("minimize-crm-contacts").checked,
24+
upcoming_tasks_and_sales_visits: document.getElementById("minimize-crm-upcoming-tasks-and-sales-visits").checked,
25+
recently_ordered_products: document.getElementById("minimize-crm-recently-ordered-products").checked,
26+
recent_orders: document.getElementById("minimize-crm-recent-orders").checked,
27+
recent_credit_notes: document.getElementById("minimize-crm-recent-credit-notes").checked,
28+
containers_at_outlet: document.getElementById("minimize-crm-containers-at-outlet").checked
29+
}
30+
}, () => {});
31+
document.getElementById("status").innerText = "Saved!";
32+
};
33+
34+
document.addEventListener("DOMContentLoaded", restoreOptions);
35+
document.getElementById("save").addEventListener("click", saveOptions);

popup/popup.html

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<button id="options-button">Options</button>
4+
<script src="popup.js"></script>
5+
</html>

popup/popup.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
document.querySelector("#options-button").addEventListener("click", function () {
2+
console.log("clicked");
3+
if (chrome.runtime.openOptionsPage) {
4+
chrome.runtime.openOptionsPage();
5+
} else {
6+
window.open(chrome.runtime.getURL("options.html"));
7+
}
8+
});

scripts/existingOrderWarning.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
2+
// Remove any existing warnings
3+
let previousWarning = $("#existing-order-warning")
4+
if (previousWarning.length > 0) {
5+
previousWarning.remove();
6+
}
7+
waitForBrewmanLoad(showWarning);
8+
});
9+
10+
function showWarning () {
11+
jNode = $("div[value='[object Object]']");
12+
url = window.location.pathname.split("/");
13+
14+
// If page is outlet CRM screen
15+
if (url[1] == "outlet" && url[3] == "crm") {
16+
chrome.storage.local.get("apiKey", (storage) => {
17+
18+
// Get tenant from user API
19+
fetch("https://brewman.premiersystems.com/webapi/user/v1/getCurrentUserContext", {
20+
method: "POST",
21+
headers: {
22+
"Api-Token": storage["apiKey"],
23+
"Accept": "*/*",
24+
"content-type": "application/json"
25+
},
26+
body: JSON.stringify({})
27+
})
28+
.then((response) => response.json())
29+
.then((data) => {
30+
let tenantId = data["userContext"]["user"]["readOnly"]["selectedTenant"];
31+
let outletId = url[2];
32+
let d = new Date();
33+
d.setMonth(d.getMonth() - 3);
34+
let dateFilter = d.getFullYear() + "-" + d.getMonth() + "-" + d.getDate();
35+
return fetch("https://brewman.premiersystems.com/webapi/order/v1/getOrdersByFilter", {
36+
method: "POST",
37+
headers: {
38+
"Api-Token": storage["apiKey"],
39+
"Accept": "*/*",
40+
"content-type": "application/json"
41+
},
42+
body: JSON.stringify({
43+
tenantId: tenantId,
44+
filter: {
45+
fromDespatchDate: dateFilter,
46+
maximumResults: 100,
47+
singleOutletId: outletId,
48+
limitStatuses: ["Open"]
49+
}
50+
})
51+
})
52+
})
53+
.then((response) => response.json())
54+
.then((data) => {
55+
if (data["results"]["matchingCount"] > 0) {
56+
// TODO: Write function for creating alerts
57+
58+
let orderWarning = document.createElement("div");
59+
orderWarning.setAttribute("class", "v-alert bm-headline warning");
60+
orderWarning.setAttribute("id", "existing-order-warning")
61+
62+
let orderWarningWrapper = document.createElement("div");
63+
orderWarningWrapper.setAttribute("class", "v-alert__content");
64+
orderWarningWrapper.innerText = " There is currently already an open order for this outlet: ";
65+
66+
orderWarning.prepend(orderWarningWrapper);
67+
68+
data["results"]["orders"].forEach((value, index, array) => {
69+
console.log(value);
70+
let orderLink = document.createElement("a");
71+
orderLink.setAttribute("href", "https://brewman.premiersystems.com/orders/" + value["header"]["readOnly"]["id"] + "/view");
72+
orderLink.innerText = value["header"]["readOnly"]["orderNumber"];
73+
orderWarningWrapper.append(orderLink);
74+
if (index + 1 != array.length) {
75+
orderWarningWrapper.append(", ");
76+
}
77+
});
78+
79+
jNode.prepend(orderWarning);
80+
}
81+
})
82+
});
83+
};
84+
}

scripts/jquery-3.7.1.min.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/minimize.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
waitForKeyElements(".bm-card-title", minimize)
2+
3+
function minimize (jNode) {
4+
url = window.location.pathname.split("/");
5+
if (url[1] == "outlet" && url[3] == "crm") {
6+
chrome.storage.local.get("minimize_crm", (data) => {
7+
switch (jNode.parent().attr("label")) {
8+
case "Log Communication":
9+
if (data["minimize_crm"]["log_communication"]) {jNode.click();};
10+
break;
11+
case "Activity Log":
12+
if (data["minimize_crm"]["activity_log"]) {jNode.click();};
13+
break;
14+
case "Outlet Summary":
15+
if (data["minimize_crm"]["outlet_summary"]) {jNode.click();};
16+
break;
17+
case "Contacts":
18+
if (data["minimize_crm"]["contacts"]) {jNode.click();};
19+
break;
20+
case "Upcoming Tasks and Sales Visits":
21+
if (data["minimize_crm"]["upcoming_tasks_and_sales_visits"]) {jNode.click();};
22+
break;
23+
case "Recently Ordered Products":
24+
if (data["minimize_crm"]["recently_ordered_products"]) {jNode.click();};
25+
break;
26+
case "Recent Orders":
27+
if (data["minimize_crm"]["recent_orders"]) {jNode.click();};
28+
break;
29+
case "Recent Credit Notes":
30+
if (data["minimize_crm"]["recent_credit_notes"]) {jNode.click();};
31+
break;
32+
case "Containers At Outlet":
33+
if (data["minimize_crm"]["containers_at_outlet"]) {jNode.click();};
34+
break;
35+
};
36+
});
37+
};
38+
};

scripts/searchFilter.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
waitForKeyElements(".bm-search", addSearchFilter);
2+
3+
function addSearchFilter (jNode) {
4+
};

scripts/waitForBrewmanLoad.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function waitForBrewmanLoad (actionFunction, delay) {
2+
// Default delay of 1 second
3+
if (!delay) {delay = 1000}
4+
5+
// Check for loading dialog after delay
6+
// Initial delay allows time for loading dialog to first appear
7+
// Subsequent delays wait for dialog to disappear
8+
9+
// (Function assumes that loading dialog will appear within initial delay
10+
//If dialog appears after, it will assume the page has loaded before the dialog appears)
11+
let intervalId = setInterval(function () {
12+
let loadingDialog = $("div.loading_dialog");
13+
if (loadingDialog.is(":hidden")) {
14+
clearInterval(intervalId)
15+
actionFunction();
16+
}
17+
}, delay);
18+
}

scripts/waitForKeyElements.js

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
2+
that detects and handles AJAXed content.
3+
4+
Usage example:
5+
6+
waitForKeyElements (
7+
"div.comments"
8+
, commentCallbackFunction
9+
);
10+
11+
//--- Page-specific function to do what we want when the node is found.
12+
function commentCallbackFunction (jNode) {
13+
jNode.text ("This comment changed by waitForKeyElements().");
14+
}
15+
16+
IMPORTANT: This function requires your script to have loaded jQuery.
17+
*/
18+
function waitForKeyElements (
19+
selectorTxt, /* Required: The jQuery selector string that
20+
specifies the desired element(s).
21+
*/
22+
actionFunction, /* Required: The code to run when elements are
23+
found. It is passed a jNode to the matched
24+
element.
25+
*/
26+
bWaitOnce, /* Optional: If false, will continue to scan for
27+
new elements even after the first match is
28+
found.
29+
*/
30+
iframeSelector /* Optional: If set, identifies the iframe to
31+
search.
32+
*/
33+
) {
34+
var targetNodes, btargetsFound;
35+
36+
if (typeof iframeSelector == "undefined")
37+
targetNodes = $(selectorTxt);
38+
else
39+
targetNodes = $(iframeSelector).contents ()
40+
.find (selectorTxt);
41+
42+
if (targetNodes && targetNodes.length > 0) {
43+
btargetsFound = true;
44+
/*--- Found target node(s). Go through each and act if they
45+
are new.
46+
*/
47+
targetNodes.each ( function () {
48+
var jThis = $(this);
49+
var alreadyFound = jThis.data ('alreadyFound') || false;
50+
51+
if (!alreadyFound) {
52+
//--- Call the payload function.
53+
var cancelFound = actionFunction (jThis);
54+
if (cancelFound)
55+
btargetsFound = false;
56+
else
57+
jThis.data ('alreadyFound', true);
58+
}
59+
} );
60+
}
61+
else {
62+
btargetsFound = false;
63+
}
64+
65+
//--- Get the timer-control variable for this selector.
66+
var controlObj = waitForKeyElements.controlObj || {};
67+
var controlKey = selectorTxt.replace (/[^\w]/g, "_");
68+
var timeControl = controlObj [controlKey];
69+
70+
//--- Now set or clear the timer as appropriate.
71+
if (btargetsFound && bWaitOnce && timeControl) {
72+
//--- The only condition where we need to clear the timer.
73+
clearInterval (timeControl);
74+
delete controlObj [controlKey]
75+
}
76+
else {
77+
//--- Set a timer, if needed.
78+
if ( ! timeControl) {
79+
timeControl = setInterval ( function () {
80+
waitForKeyElements ( selectorTxt,
81+
actionFunction,
82+
bWaitOnce,
83+
iframeSelector
84+
);
85+
},
86+
300
87+
);
88+
controlObj [controlKey] = timeControl;
89+
}
90+
}
91+
waitForKeyElements.controlObj = controlObj;
92+
}

0 commit comments

Comments
 (0)