update
Took 5 hours 14 minutes
This commit is contained in:
parent
a4ac8d083b
commit
a722caf2d4
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
/dist/
|
||||
/.idea/
|
||||
/node_modules
|
||||
/node_modules
|
||||
|
9
public/stylesheets/containers.css
Normal file
9
public/stylesheets/containers.css
Normal file
@ -0,0 +1,9 @@
|
||||
#containers_volume {
|
||||
min-width: 10%;
|
||||
max-width: 10%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#containers_volumeSlider {
|
||||
width: 45%;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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%;
|
||||
}
|
@ -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*/
|
||||
|
5
src/RequestType.ts
Normal file
5
src/RequestType.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum RequestType {
|
||||
CONTAINERS = "CONTAINERS",
|
||||
INGREDIENTS = "INGREDIENTS",
|
||||
STATS = "STATS",
|
||||
}
|
@ -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"
|
||||
}
|
@ -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);
|
||||
})
|
||||
}
|
||||
|
@ -125,9 +125,9 @@ export class iTender {
|
||||
|
||||
}
|
||||
log("Drinks refreshed!");
|
||||
|
||||
await WebSocketHandler.sendDrinks();
|
||||
resolve();
|
||||
this.setStatus(iTenderStatus.READY);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
142
src/web/Containers.ts
Normal file
142
src/web/Containers.ts
Normal file
@ -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<any, number> = {};
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@ -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<void> {
|
||||
return new Promise(async (resolve) => {
|
||||
/* if (this._leftCentered) {
|
||||
this._content = "<div style='text-align: left; padding-left: 2%;'>" + this._content;
|
||||
}*/ //todo
|
||||
|
||||
/* if (this._loader)
|
||||
this._content += "<br><div class=\"lds-ellipsis\">\n" +
|
||||
" <div></div><div></div><div></div><div></div>\n" +
|
||||
"</div>";*/ // todo
|
||||
if (this._loader) {
|
||||
let div = document.createElement("div");
|
||||
div.innerHTML = "<br><div class=\"lds-ellipsis\">\n" +
|
||||
" <div></div><div></div><div></div><div></div>\n" +
|
||||
"</div>";
|
||||
this._elements.push(div);
|
||||
}
|
||||
|
||||
/*if (this._leftCentered) {
|
||||
this._content += "</div>";
|
||||
@ -121,7 +124,7 @@ export class Modal {
|
||||
|
||||
}
|
||||
|
||||
public close() : void {
|
||||
public close(): void {
|
||||
Modal.close(this._id);
|
||||
}
|
||||
|
||||
|
@ -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<br><br>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.<br><br>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.<br><br>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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<WebSocketPayload>
|
||||
* @param type
|
||||
*/
|
||||
public static request(type: RequestType): Promise<WebSocketPayload> {
|
||||
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<void> {
|
||||
console.log("[WS] Sending " + payload.event + " Event", payload);
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
@ -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<void> {
|
||||
return new Promise(resolve => {
|
||||
wsHandler = new WebWebSocketHandler(resolve);
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user