diff --git a/.gitignore b/.gitignore index d36bc0a..88f704a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /dist/ /.idea/ -/node_modules \ No newline at end of file +/node_modules diff --git a/public/stylesheets/containers.css b/public/stylesheets/containers.css new file mode 100644 index 0000000..2376dea --- /dev/null +++ b/public/stylesheets/containers.css @@ -0,0 +1,9 @@ +#containers_volume { + min-width: 10%; + max-width: 10%; + display: inline-block; +} + +#containers_volumeSlider { + width: 45%; +} \ No newline at end of file diff --git a/public/stylesheets/inputs.css b/public/stylesheets/inputs.css index 2153304..69e86f0 100644 --- a/public/stylesheets/inputs.css +++ b/public/stylesheets/inputs.css @@ -102,9 +102,9 @@ label { .input { padding: 6px; font-size: 1.1em; - margin-left: 1%; margin-right: 1%; + margin-bottom: 2%; border: 0; border-radius: 3px; } diff --git a/public/stylesheets/menu.css b/public/stylesheets/menu.css index 02a95d9..3cffcbf 100644 --- a/public/stylesheets/menu.css +++ b/public/stylesheets/menu.css @@ -1,10 +1,18 @@ #menu { padding-left: 5%; padding-right: 5%; - padding-top: 1%; + padding-top: 10%; display: grid; - grid-template-columns: repeat(2, calc(90% / 2)); - grid-template-rows: repeat(2, calc(90% / 2)); + grid-template-columns: repeat(2, calc(100% / 2)); + grid-template-rows: repeat(2, calc(95% / 2)); grid-gap: 2% 2%; color: white; +} + + +#menu > button { + grid-row: span 1; + grid-column: span 1; + font-size: 1.8em; + height: 50%; } \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 5e7cb06..1c08446 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -2,13 +2,19 @@ @import url("/stylesheets/fonts.css"); @import url("/stylesheets/inputs.css"); @import url("/stylesheets/modal.css"); +@import url("/stylesheets/menu.css"); @import url("/stylesheets/main.css"); @import url("/stylesheets/setup.css"); +@import url("/stylesheets/containers.css"); + :root { /*cursor: none !important;*/ } +ul { + list-style: circle; +} html * { /*cursor: none !important*/ diff --git a/src/RequestType.ts b/src/RequestType.ts new file mode 100644 index 0000000..fe959a6 --- /dev/null +++ b/src/RequestType.ts @@ -0,0 +1,5 @@ +export enum RequestType { + CONTAINERS = "CONTAINERS", + INGREDIENTS = "INGREDIENTS", + STATS = "STATS", +} \ No newline at end of file diff --git a/src/WebSocketEvent.ts b/src/WebSocketEvent.ts index c5a082e..03bbe46 100644 --- a/src/WebSocketEvent.ts +++ b/src/WebSocketEvent.ts @@ -2,8 +2,10 @@ export enum WebSocketEvent { STATUS= "STATUS", DRINKS = "DRINKS", CONTAINERS = "CONTAINERS", + CONTAINER_UPDATE = "CONTAINER_UPDATE", CONFIG = "CONFIG", TARE = "TARE", SETUP = "SETUP", - REQUEST = "REQUEST" + REQUEST = "REQUEST", + RESPONSE = "RESPONSE" } \ No newline at end of file diff --git a/src/WebSocketHandler.ts b/src/WebSocketHandler.ts index 60cb555..1382ea6 100644 --- a/src/WebSocketHandler.ts +++ b/src/WebSocketHandler.ts @@ -3,6 +3,11 @@ import {WebSocketEvent} from "./WebSocketEvent"; import {iTender} from "./iTender"; import {Settings} from "./Settings"; import Container from "./database/Container"; +import Job from "./database/Job"; +import Drink from "./database/Drink"; +import {IDrink} from "./database/IDrink"; +import Ingredient from "./database/Ingredient"; +import {RequestType} from "./RequestType"; export class WebSocketHandler { private static _ws: WebSocket; @@ -28,6 +33,11 @@ export class WebSocketHandler { }); } + public static answerRequest(type: RequestType, content: any) { + WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.RESPONSE, false, {type: type, content: content})); + + } + public static sendStatus() { return new Promise(resolve => { let payload = new WebSocketPayload(WebSocketEvent.STATUS, false, {status: iTender.status}); @@ -39,12 +49,52 @@ export class WebSocketHandler { return new Promise(resolve => { let payload = new WebSocketPayload(WebSocketEvent.CONFIG, false, Settings.json); WebSocketHandler.send(payload).then(resolve); - }) + }); + } + + static sendStats() { + return new Promise(async resolve => { + let counts: IDrink[] = []; + for (let drink of (await Drink.find())) { + // @ts-ignore + drink.count = (await Job.countDocuments({drink: drink})); + counts.push(drink) + } + counts.sort((a: IDrink, b: IDrink) => { + // @ts-ignore + if (a.count < b.count) + return -1; + // @ts-ignore + else if (a.count > b.count) + return 1; + else + return 0; + }); + + let stats = { + "drinks_finished": (await Job.countDocuments({successful: true})), + "drink_most": counts[0].name, + "count_ingredients": (await Ingredient.countDocuments()), + "count_cocktails": (await Drink.countDocuments()) + }; + let payload = new WebSocketPayload(WebSocketEvent.RESPONSE, false, { + type: RequestType.STATS, + content: stats + }); + WebSocketHandler.send(payload).then(resolve); + }); } static sendContainers() { return new Promise(async resolve => { - let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, false, ( await Container.find() )); + let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, false, (await Container.find())); + WebSocketHandler.send(payload).then(resolve); + }) + } + + static sendDrinks() { + return new Promise(async resolve => { + let payload = new WebSocketPayload(WebSocketEvent.DRINKS, false, iTender.drinks); WebSocketHandler.send(payload).then(resolve); }) } diff --git a/src/iTender.ts b/src/iTender.ts index 6714ffe..ef34c8a 100644 --- a/src/iTender.ts +++ b/src/iTender.ts @@ -125,9 +125,9 @@ export class iTender { } log("Drinks refreshed!"); - + await WebSocketHandler.sendDrinks(); resolve(); - this.setStatus(iTenderStatus.READY); + }); } diff --git a/src/main.ts b/src/main.ts index 5b490fc..d43e428 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,6 @@ import Ingredient from "./database/Ingredient"; import {iTender} from "./iTender"; import {iTenderStatus} from "./iTenderStatus"; import {Utils} from "./Utils"; -import Container from "./database/Container"; import {Settings} from "./Settings"; const log = debug("itender:server"); @@ -43,7 +42,7 @@ const wsApp = new WebsocketApp(); await init(); - setInterval(refresh, 1000 * 60 * 10); + setInterval(refresh, 1000 * 60); iTender.setStatus(iTenderStatus.READY); }, 1000); } diff --git a/src/routes/ws/websocketRoute.ts b/src/routes/ws/websocketRoute.ts index 70b49fc..8b88620 100644 --- a/src/routes/ws/websocketRoute.ts +++ b/src/routes/ws/websocketRoute.ts @@ -7,6 +7,8 @@ import {WebSocketEvent} from "../../WebSocketEvent"; import Container from "../../database/Container"; import {SensorType} from "../../SensorType"; import {Settings} from "../../Settings"; +import Ingredient from "../../database/Ingredient"; +import {RequestType} from "../../RequestType"; const express = require('express'); const router = express.Router(); @@ -26,6 +28,8 @@ router.ws('/', async (ws, req, next) => { await WebSocketHandler.sendRunningConfig(); await WebSocketHandler.sendContainers(); await WebSocketHandler.sendStatus(); + await WebSocketHandler.sendDrinks(); + ws.on('message', async (raw, bool) => { @@ -36,6 +40,8 @@ router.ws('/', async (ws, req, next) => { return; } + log(msg); + switch (msg.event) { case WebSocketEvent.TARE: { if (msg.data["state"] == true) { @@ -66,6 +72,26 @@ router.ws('/', async (ws, req, next) => { break; } + case WebSocketEvent.CONTAINER_UPDATE: { + let container = await Container.findById(msg.data["container"]); + if (!container) break; + + let ingredient; + if (msg.data["ingredient"] != null) { + ingredient = await Ingredient.findById(msg.data["ingredient"]); + if (!ingredient) + ingredient = undefined; + } + + container.volume = parseInt(msg.data["volume"]); + container.content = ingredient; + + await container.save(); + + await iTender.refreshDrinks(); + break; + } + case WebSocketEvent.CONFIG: { // ToDo console.log("New Settings:", msg.data); @@ -85,10 +111,34 @@ router.ws('/', async (ws, req, next) => { if (Settings.setupDone) { iTender.setStatus(iTenderStatus.READY); await WebSocketHandler.sendRunningConfig(); - } } await WebSocketHandler.sendContainers(); + break; + } + + case WebSocketEvent.REQUEST: { + + switch (msg.data["type"] as RequestType) { + case RequestType.STATS: { + await WebSocketHandler.sendStats(); + break; + } + case RequestType.CONTAINERS: { + WebSocketHandler.answerRequest(msg.data["type"] as RequestType, (await Container.find().sort({"slot": 1}))); + break; + } + case RequestType.INGREDIENTS: { + WebSocketHandler.answerRequest(msg.data["type"] as RequestType, (await Ingredient.find().sort({"name": 1}))); + break; + } + + } + break; + } + + default: { + log("WebSocketHandler does not know how to handle " + msg.event + " Event"); } } }); diff --git a/src/web/Containers.ts b/src/web/Containers.ts new file mode 100644 index 0000000..d4362bb --- /dev/null +++ b/src/web/Containers.ts @@ -0,0 +1,142 @@ +import {Modal} from "./Modal"; +import {WebWebSocketHandler} from "./WebWebSocketHandler"; +import {IContainer} from "../database/IContainer"; +import {IIngredient} from "../database/IIngredient"; +import {ButtonType} from "./ButtonType"; +import {RequestType} from "../RequestType"; +import {WebSocketPayload} from "../WebSocketPayload"; +import {WebSocketEvent} from "../WebSocketEvent"; + +export class Containers { + static openMenu() { + let modal = new Modal("containers", "Behälter aktualisieren"); + let txt = document.createElement("p"); + txt.innerText = "Zu aktualisierenden Behälter wählen"; + modal.addContent(txt); + modal.addContent(document.createElement("br")); + + let form = document.createElement("div"); + modal.addContent(form); + + let btnSave = document.createElement("button"); + btnSave.innerText = "Speichern"; + btnSave.classList.add("btn", "btn-primary") + btnSave.disabled = true; + + let containerVolumes: Record = {}; + + let volume = document.createElement("span"); + volume.innerText = ""; + volume.id = "containers_volume"; + + let volumeSlider = document.createElement("input"); + volumeSlider.type = "range"; + volumeSlider.step = "10"; + volumeSlider.style.visibility = "hidden"; + volumeSlider.id = "containers_volumeSlider" + + function onChange() { + volume.innerText = volumeSlider.value + " ml "; + txt.innerText = "Speichern zum abschließen" + } + + volumeSlider.oninput = onChange; + volumeSlider.onchange = onChange; + + let nonSelect = document.createElement("option"); + nonSelect.value = "-1"; + nonSelect.innerText = "Bitte wählen"; + nonSelect.disabled = true; + + + let selectIngredient = document.createElement("select"); + selectIngredient.style.visibility = "hidden"; + selectIngredient.classList.add("input"); + selectIngredient.onchange = () => { + if (selectIngredient.value == "null") { + volumeSlider.value = "0"; + volumeSlider.disabled = true; + } else { + volumeSlider.disabled = false; + } + + volumeSlider.style.visibility = "visible"; + volume.innerText = volumeSlider.value + " ml "; + + if (selectContainer.value && selectIngredient.value) + btnSave.disabled = false; + + + txt.innerText = "Menge des Inhalts mittels Slider einstellen"; + } + selectIngredient.append(nonSelect.cloneNode(true)); + selectIngredient.selectedIndex = 0; + let noIngredient = document.createElement("option"); + noIngredient.value = "null"; + noIngredient.innerText = "Kein Inhalt"; + selectIngredient.append(noIngredient); + + let selectContainer = document.createElement("select"); + selectContainer.classList.add("input"); + selectContainer.onchange = () => { + selectIngredient.style.visibility = "visible"; + volumeSlider.max = String(containerVolumes[selectContainer.value]); + volumeSlider.min = String(0); + volumeSlider.value = String(containerVolumes[selectContainer.value] / 2); + txt.innerText = "Ingredient des Behälters auswählen"; + } + + + selectContainer.append(nonSelect.cloneNode(true)); + selectContainer.selectedIndex = 0; + + WebWebSocketHandler.request(RequestType.CONTAINERS).then((payload) => { + for (let container of (payload.data["content"] as IContainer[])) { + containerVolumes[container._id] = container.volume; + let option = document.createElement("option"); + option.value = container._id; + option.innerText = "Behälter Slot " + container.slot + "[" + (container.content && container.content.name ? container.content.name : "Kein Inhalt") + "]"; + selectContainer.append(option); + + } + }); + WebWebSocketHandler.request(RequestType.INGREDIENTS).then((payload) => { + for (let ingredient of (payload.data["content"] as IIngredient[])) { + let option = document.createElement("option"); + option.value = ingredient._id; + option.innerText = ingredient.name; + selectIngredient.append(option); + } + }); + + form.append(selectContainer, document.createElement("br"), selectIngredient, document.createElement("br"), volume, volumeSlider); + + + modal.addContent(document.createElement("br")); + modal.addButton(ButtonType.PRIMARY, "Abbrechen", () => modal.close()); + + + modal.addContent(btnSave); + + btnSave.onclick = () => { + + // Validation + if (selectIngredient.value == "-1" || selectContainer.value == "-1") { + return; + } + + // If no ingredient, move slider to 0 + if (selectIngredient.value == "null") + volumeSlider.value = "0"; + + let payload = new WebSocketPayload(WebSocketEvent.CONTAINER_UPDATE, false, { + container: selectContainer.value, + ingredient: (selectIngredient.value == "null") ? null : selectIngredient.value, + volume: volumeSlider.value + }); + WebWebSocketHandler.send(payload).then(() => modal.close()); + }; + + modal.open(); + } +} \ No newline at end of file diff --git a/src/web/Modal.ts b/src/web/Modal.ts index fa040f2..fc0f398 100644 --- a/src/web/Modal.ts +++ b/src/web/Modal.ts @@ -44,7 +44,8 @@ export class Modal { this._loader = value; } - public addButton(type: ButtonType, content: string, onclick: Function = () => {}): HTMLButtonElement { + public addButton(type: ButtonType, content: string, onclick: Function = () => { + }): HTMLButtonElement { let btn = document.createElement("button"); btn.classList.add("btn", "btn-" + type); btn.onclick = () => onclick(btn); @@ -56,17 +57,19 @@ export class Modal { } - public open(): Promise { return new Promise(async (resolve) => { /* if (this._leftCentered) { this._content = "
" + this._content; }*/ //todo - /* if (this._loader) - this._content += "
\n" + - "
\n" + - "
";*/ // todo + if (this._loader) { + let div = document.createElement("div"); + div.innerHTML = "
\n" + + "
\n" + + "
"; + this._elements.push(div); + } /*if (this._leftCentered) { this._content += "
"; @@ -121,7 +124,7 @@ export class Modal { } - public close() : void { + public close(): void { Modal.close(this._id); } diff --git a/src/web/Setup.ts b/src/web/Setup.ts index bd21fe4..a034e61 100644 --- a/src/web/Setup.ts +++ b/src/web/Setup.ts @@ -7,6 +7,7 @@ import {WebSocketEvent} from "../WebSocketEvent"; import {WebWebSocketHandler} from "./WebWebSocketHandler"; import {IContainer} from "../database/IContainer"; import {SensorType} from "../SensorType"; +import {RequestType} from "../RequestType"; export class Setup { @@ -200,7 +201,6 @@ Während der Einmessung müssen die Behälter einmal geleert und gefüllt werden let ul; tareModal.addButton(ButtonType.PRIMARY, "Starten", async () => { tareModal.close(); - let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {state: true}); let modal = new Modal("tare", "Einmessung"); @@ -213,6 +213,8 @@ Die Gewichtssensoren werden beim Bestätigen austariert

Zum fortfahren Ta ul = document.createElement("ul"); modal.addContent(ul); + let tareInterval: NodeJS.Timer; + let btn = document.createElement("button"); btn.classList.add("btn", "btn-primary"); btn.innerText = "Tarieren"; @@ -227,30 +229,35 @@ Die Gewichtssensoren werden beim Bestätigen austariert.

Zum fortfahren T btn.onclick = () => { let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 1}); WebWebSocketHandler.send(payload); - btn.onclick = () => modal.close(); + + btn.onclick = () => { + modal.close(); + clearInterval(tareInterval); + }; }; }; modal.addContent(btn); await modal.open(); - await WebWebSocketHandler.send(payload); + + tareInterval = setInterval(() => WebWebSocketHandler.request(RequestType.CONTAINERS).then((payload) => { + if (!ul) return; + + ul.innerHTML = ""; + let containers = payload.data as IContainer[]; + for (let c of containers) { + if (c.sensorType == SensorType.NONE) continue; + + let li = document.createElement("li"); + li.innerText = `Behälter ${c.slot}: ${c.rawData.toFixed(3)} [${c.sensorType}]`; + ul.append(li); + } + }), 250); + }); tareModal.open(); - WebWebSocketHandler.registerForEvent(WebSocketEvent.CONTAINERS, (payload: WebSocketPayload) => { - if (!ul) return; - - ul.innerHTML = ""; - let containers = payload.data as IContainer[]; - for (let c of containers) { - if (c.sensorType == SensorType.NONE) continue; - - let li = document.createElement("li"); - li.innerText = `Behälter ${c.slot}: ${c.rawData.toFixed(3)} [${c.sensorType}]`; - ul.append(li); - } - }); } public static addSetupContainer() { @@ -406,6 +413,41 @@ Die Gewichtssensoren werden beim Bestätigen austariert.

Zum fortfahren T } + public static onContainerUpdate(payload: WebSocketPayload) { + let containerDiv = document.getElementById("setupContainers") as HTMLDivElement; + containerDiv.innerHTML = ""; + + let containers = payload.data["content"] as IContainer[]; + for (let c of containers) { + Setup.addSetupContainer(); + } + + let i = 0; + let list = containerDiv.getElementsByTagName("div"); + for (let c of containers) { + let current = list[i] as HTMLDivElement; + let selects = current.getElementsByTagName("select"); + + (selects[0] as HTMLSelectElement).value = c.pumpPin.toString(); + let type; + if (c.sensorType == SensorType.NONE) + type = "-1"; + else if (c.sensorType == SensorType.ULTRASOUND) + type = "0"; + else + type = "1"; + (selects[1] as HTMLSelectElement).value = type; + (selects[2] as HTMLSelectElement).value = c.sensorPin1.toString(); + (selects[3] as HTMLSelectElement).value = c.sensorPin2.toString(); + (selects[4] as HTMLSelectElement).value = c.volume.toString(); + let event = new Event('change', {bubbles: true}); + selects[1].dispatchEvent(event); + + i++; + } + + } + public static checkContainers(): boolean { console.log("Checking containers...") let returner = true; diff --git a/src/web/WebHandler.ts b/src/web/WebHandler.ts index 256cec0..692efd0 100644 --- a/src/web/WebHandler.ts +++ b/src/web/WebHandler.ts @@ -1,15 +1,12 @@ import {WebSocketPayload} from "../WebSocketPayload"; import {IDrink} from "../database/IDrink"; import {Pane} from "./Pane"; -import {IContainer} from "../database/IContainer"; import {Setup} from "./Setup"; -import {SensorType} from "../SensorType"; export class WebHandler { static get currentPane(): Pane { return this._currentPane; } - private static containers = []; public static onDrinkUpdate(payload: WebSocketPayload) { if (!payload.data) return; @@ -18,6 +15,8 @@ export class WebHandler { const main = document.getElementById("main"); if (!main) return; + console.log(drinks) + main.style.gridTemplateRows = `repeat(${Math.round(drinks.length / 3)}, calc(90%/2))`; main.innerHTML = ""; @@ -55,43 +54,7 @@ ${ingredients}`*/ //todo // modal.open(); //}; - //main.append(drinkEle); - } - - } - - - public static onContainerUpdate(payload: WebSocketPayload) { - let containerDiv = document.getElementById("setupContainers") as HTMLDivElement; - containerDiv.innerHTML = ""; - - let containers = payload.data as IContainer[]; - for (let c of containers) { - Setup.addSetupContainer(); - } - - let i = 0; - let list = containerDiv.getElementsByTagName("div"); - for (let c of containers) { - let current = list[i] as HTMLDivElement; - let selects = current.getElementsByTagName("select"); - - (selects[0] as HTMLSelectElement).value = c.pumpPin.toString(); - let type; - if (c.sensorType == SensorType.NONE) - type = "-1"; - else if (c.sensorType == SensorType.ULTRASOUND) - type = "0"; - else - type = "1"; - (selects[1] as HTMLSelectElement).value = type; - (selects[2] as HTMLSelectElement).value = c.sensorPin1.toString(); - (selects[3] as HTMLSelectElement).value = c.sensorPin2.toString(); - (selects[4] as HTMLSelectElement).value = c.volume.toString(); - let event = new Event('change', {bubbles: true}); - selects[1].dispatchEvent(event); - - i++; + main.append(drinkEle); } } @@ -99,6 +62,7 @@ ${ingredients}`*/ //todo private static _currentPane: Pane; public static openPane(pane: Pane): void { + const menuBtn = document.getElementById("menuBtn") as HTMLButtonElement; let mainPanel = document.getElementById("main") as HTMLDivElement; let setupPanel = document.getElementById("setup") as HTMLDivElement; let menuPanel = document.getElementById("menu") as HTMLDivElement; @@ -112,6 +76,7 @@ ${ingredients}`*/ //todo settingsPanel.classList.add("hiddenPane"); } + switch (this._currentPane) { case Pane.MAIN: { mainPanel.classList.add("hiddenPane"); @@ -129,29 +94,36 @@ ${ingredients}`*/ //todo settingsPanel.classList.add("hiddenPane"); break; } + case Pane.CONTAINERS: { + + } } - + menuBtn.innerText = "Menü"; let title = document.getElementById("title") as HTMLTitleElement; switch (pane) { case Pane.MAIN: { mainPanel.classList.remove("hiddenPane"); + mainPanel.scrollTo({top: 0, behavior: "smooth"}); title.innerText = "iTender"; break; } case Pane.MENU: { menuPanel.classList.remove("hiddenPane"); title.innerText = "Menü"; + menuBtn.innerText = "Start"; break; } case Pane.SETUP: { setupPanel.classList.remove("hiddenPane"); title.innerText = "Setup"; + setupPanel.scrollTo({top: 0, behavior: "smooth"}); break; } case Pane.SETTINGS: { settingsPanel.classList.remove("hiddenPane"); title.innerText = "Einstellungen"; + settingsPanel.scrollTo({top: 0, behavior: "smooth"}) break; } } diff --git a/src/web/WebWebSocketHandler.ts b/src/web/WebWebSocketHandler.ts index bc33496..c1c32b8 100644 --- a/src/web/WebWebSocketHandler.ts +++ b/src/web/WebWebSocketHandler.ts @@ -6,6 +6,7 @@ import {iTenderStatus} from "../iTenderStatus"; import {WebHandler} from "./WebHandler"; import {Setup} from "./Setup"; import {Pane} from "./Pane"; +import {RequestType} from "../RequestType"; export class WebWebSocketHandler { private static socket: WebSocket; @@ -14,12 +15,16 @@ export class WebWebSocketHandler { private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload) => void }[] = []; - constructor() { + constructor(resolver: (() => void)) { WebWebSocketHandler.socket = new WebSocket(WebWebSocketHandler.url); - WebWebSocketHandler.socket.onopen = this.onOpen; + WebWebSocketHandler.socket.onopen = (x) => { + resolver(); + this.onOpen(x); + }; WebWebSocketHandler.socket.onclose = this.onClose; WebWebSocketHandler.socket.onerror = this.onError; WebWebSocketHandler.socket.onmessage = this.onMessage; + } public static registerForEvent(event: WebSocketEvent, fn: (payload: WebSocketPayload) => void) { @@ -95,6 +100,7 @@ export class WebWebSocketHandler { } } + private onOpen(event) { console.log("[WS] Connected", event); @@ -171,6 +177,22 @@ export class WebWebSocketHandler { //window.location.reload(); } + /** + * @return Promise + * @param type + */ + public static request(type: RequestType): Promise { + console.log("Request to " + type) + return new Promise(resolve => { + WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => { + if ((payload.data["type"] as RequestType) == type) { + resolve(payload); + } + }); + WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, false, {type: type})); + }); + } + public static send(payload: WebSocketPayload): Promise { console.log("[WS] Sending " + payload.event + " Event", payload); return new Promise(async (resolve, reject) => { diff --git a/src/web/main.ts b/src/web/main.ts index 28a9703..e6fb0c5 100644 --- a/src/web/main.ts +++ b/src/web/main.ts @@ -5,13 +5,15 @@ import {Pane} from "./Pane"; import {WebSocketPayload} from "../WebSocketPayload"; import {WebSocketEvent} from "../WebSocketEvent"; import {ButtonType} from "./ButtonType"; +import {Containers} from "./Containers"; +import {Setup} from "./Setup"; +import {RequestType} from "../RequestType"; const main = document.getElementById("main"); const time = document.getElementById("right"); -document.addEventListener("DOMContentLoaded", () => { +document.addEventListener("DOMContentLoaded", async () => { console.log("DOM Loaded"); - setupOnClickEvents(); WebHandler.openPane(Pane.NONE); let modal = new Modal("start", "iTender"); @@ -20,7 +22,9 @@ document.addEventListener("DOMContentLoaded", () => { modal.addContent(txt); modal.loader = true; //modal.open(); - connect(); + await connect(); + + setupOnClickEvents(); setTimeout(load, 100); }); @@ -33,10 +37,8 @@ function setupOnClickEvents() { function doMenu() { if (WebHandler.currentPane != Pane.MENU) { WebHandler.openPane(Pane.MENU); - menuBtn.innerText = "Start"; } else { WebHandler.openPane(Pane.MAIN); - menuBtn.innerText = "Menü"; } } @@ -46,7 +48,9 @@ function setupOnClickEvents() { const menuContainersBtn = document.getElementById("menu_containers") as HTMLButtonElement; const menuStatsBtn = document.getElementById("menu_stats") as HTMLButtonElement; - menuContainersBtn.onclick = () => WebHandler.openPane(Pane.CONTAINERS); + menuContainersBtn.onclick = Containers.openMenu; + + menuStatsBtn.onclick = async () => { let statsModal = new Modal("stats", "Statistiken"); @@ -65,29 +69,25 @@ function setupOnClickEvents() { statsModal.addContent(document.createElement("br")); statsModal.addButton(ButtonType.PRIMARY, "Schließen", () => statsModal.close()); - WebWebSocketHandler.registerForEvent(WebSocketEvent.REQUEST, (payload) => { - if (payload.data["event"] == "stats") { - let li = document.createElement("li"); - li.innerText = "Cocktails ausgegeben: " + payload.data["content"]["drinks_finished"]; - list.append(li); + WebWebSocketHandler.request(RequestType.STATS).then((payload) => { + let li = document.createElement("li"); + li.innerText = "Cocktails ausgegeben: " + payload.data["content"]["drinks_finished"]; + list.append(li); - li = document.createElement("li"); - li.innerText = "Häufigster Cocktail: " + payload.data["content"]["drink_most"]; - list.append(li); + li = document.createElement("li"); + li.innerText = "Häufigster Cocktail: " + payload.data["content"]["drink_most"]; + list.append(li); - li = document.createElement("li"); - li.innerText = "Anzahl Ingredients: " + payload.data["content"]["count_ingredients"]; - list.append(li); + li = document.createElement("li"); + li.innerText = "Anzahl Ingredients: " + payload.data["content"]["count_ingredients"]; + list.append(li); + + li = document.createElement("li"); + li.innerText = "Anzahl Cocktails: " + payload.data["content"]["count_cocktails"]; + list.append(li); - li = document.createElement("li"); - li.innerText = "Anzahl Cocktails: " + payload.data["content"]["count_cocktails"]; - list.append(li); - } }); - let payload = new WebSocketPayload(WebSocketEvent.REQUEST, false, {type: "stats"}); - await WebWebSocketHandler.send(payload); - await statsModal.open(); }; @@ -96,10 +96,12 @@ function setupOnClickEvents() { menuSettingsBtn.onclick = () => WebHandler.openPane(Pane.SETTINGS); menuSetupBtn.onclick = () => { - let payload = new WebSocketPayload(WebSocketEvent.SETUP, false, true ); + let payload = new WebSocketPayload(WebSocketEvent.SETUP, false, true); WebWebSocketHandler.send(payload); } + WebWebSocketHandler.request(RequestType.CONTAINERS).then(Setup.onContainerUpdate); + } function load() { @@ -114,6 +116,9 @@ function load() { let wsHandler; -function connect() { - wsHandler = new WebWebSocketHandler(); +function connect(): Promise { + return new Promise(resolve => { + wsHandler = new WebWebSocketHandler(resolve); + }); + }