From c21e5327a1cb41be7787a87c71f6c234784b6593 Mon Sep 17 00:00:00 2001 From: bozzelliandrea Date: Thu, 21 Jul 2022 23:05:19 +0200 Subject: [PATCH] [Plate] Event Implementation: * First implementation of plate items actions * Added notify system --- api/lib/io.js | 6 +- src/app/modules/plates/item/item.component.ts | 27 ++++++-- src/app/modules/plates/plate-mode.ts | 10 --- src/app/modules/plates/plate.interface.ts | 25 ++++++++ .../modules/plates/plate/plate.component.html | 4 +- .../modules/plates/plate/plate.component.ts | 10 +-- src/app/modules/plates/plate/plate.model.ts | 4 +- .../modules/plates/plates/plates.component.ts | 6 +- .../services/plate-queue-manager.service.ts | 64 +++++++++++++++++-- .../modules/shared/class/reactive-queue.ts | 25 +++++--- .../navbar-button/navbar-button.component.ts | 17 +++-- .../components/navbar/navbar.component.html | 2 + .../components/navbar/navbar.component.ts | 4 +- src/app/modules/shared/shared.module.ts | 4 +- .../services/file-system-connector.service.ts | 4 +- src/environments/environment.ts | 2 +- 16 files changed, 153 insertions(+), 61 deletions(-) delete mode 100644 src/app/modules/plates/plate-mode.ts create mode 100644 src/app/modules/plates/plate.interface.ts diff --git a/api/lib/io.js b/api/lib/io.js index 7d4c13a..6380798 100644 --- a/api/lib/io.js +++ b/api/lib/io.js @@ -19,9 +19,7 @@ async function addPlate(_, config) { // file written successfully }); - // display notification - filesAdded(); - return Promise.resolve("Saved!"); + return Promise.resolve("Saved!"); } async function readPlates(_) { @@ -158,8 +156,6 @@ async function addOrder(_, order) { // file written successfully }); - // display notification - filesAdded(); return Promise.resolve("Saved!"); } diff --git a/src/app/modules/plates/item/item.component.ts b/src/app/modules/plates/item/item.component.ts index d2f2ec1..90f01a0 100644 --- a/src/app/modules/plates/item/item.component.ts +++ b/src/app/modules/plates/item/item.component.ts @@ -1,16 +1,35 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {ItemEvent} from "../plate.interface"; +import {MenuItem, Status} from "../../orders/order"; @Component({ selector: 'item', templateUrl: './item.component.html', styleUrls: ['./item.component.scss'] }) -export class ItemComponent implements OnInit { +export class ItemComponent { - constructor() { + @Input() public config!: MenuItem; + + @Output() public onDoneEvent: EventEmitter = new EventEmitter(false); + @Output() public onCancelEvent: EventEmitter = new EventEmitter(false); + + public onDone(): void { + this.onDoneEvent.emit({ + action: Status.Done, + item: this.config + } as ItemEvent); } - ngOnInit(): void { + public onCancel(): void { + const event: ItemEvent = { + action: Status.Cancelled, + item: this.config + }; + + //TODO: Handle moved or re-queued reasons + + this.onCancelEvent.emit(event); } } diff --git a/src/app/modules/plates/plate-mode.ts b/src/app/modules/plates/plate-mode.ts deleted file mode 100644 index 3dadaa1..0000000 --- a/src/app/modules/plates/plate-mode.ts +++ /dev/null @@ -1,10 +0,0 @@ -export enum PlateMode { - Skeleton = "skeleton", - On = "on", - Off = "off", - Form = "form" -} - -export function mode(): typeof PlateMode { - return PlateMode; -} diff --git a/src/app/modules/plates/plate.interface.ts b/src/app/modules/plates/plate.interface.ts new file mode 100644 index 0000000..b8cb822 --- /dev/null +++ b/src/app/modules/plates/plate.interface.ts @@ -0,0 +1,25 @@ +import {MenuItem, Status} from "../orders/order"; + +export enum PlateInterface { + Skeleton = "skeleton", + On = "on", + Off = "off", + Form = "form" +} + +export function mode(): typeof PlateInterface { + return PlateInterface; +} + +export enum PlateItemStatus { + Moved = "MOVED", + ReQueued = "RE_QUEUED" +} + +export type PlateItemAction = PlateItemStatus | Status; + +export interface ItemEvent { + action: PlateItemAction; + item: MenuItem; + nextId?: string; +} diff --git a/src/app/modules/plates/plate/plate.component.html b/src/app/modules/plates/plate/plate.component.html index 6a78f3b..fa2e0b6 100644 --- a/src/app/modules/plates/plate/plate.component.html +++ b/src/app/modules/plates/plate/plate.component.html @@ -19,11 +19,11 @@

{{config.name}}

[value]="config._status!" styleClass="mr-2"> - +

{{i18n.PLATE.EMPTY}}

-
+
diff --git a/src/app/modules/plates/plate/plate.component.ts b/src/app/modules/plates/plate/plate.component.ts index c0ad620..031e364 100644 --- a/src/app/modules/plates/plate/plate.component.ts +++ b/src/app/modules/plates/plate/plate.component.ts @@ -1,5 +1,5 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {mode, PlateMode} from "../plate-mode"; +import {mode, PlateInterface} from "../plate.interface"; import {I18nService} from "../../../services/i18n.service"; import {Plate} from "./plate.model"; import {FormControl, FormGroup, Validators} from "@angular/forms"; @@ -18,7 +18,7 @@ export class PlateComponent implements OnInit { public readonly i18n: any; public icon: string = "pi-plus"; - public plateMode: typeof PlateMode = mode(); + public plateMode: typeof PlateInterface = mode(); public form?: FormGroup | undefined; public showExpand: boolean = true; @@ -53,7 +53,7 @@ export class PlateComponent implements OnInit { name: this.form?.get("name")?.value, color: this.form?.get("color")?.value, slot: [0, this.form?.get("number")?.value], - mode: PlateMode.On + mode: PlateInterface.On } as Plate); } @@ -63,11 +63,11 @@ export class PlateComponent implements OnInit { color: new FormControl("", Validators.required), number: new FormControl(0, [Validators.required, Validators.pattern("^[0-9]*$")]) }); - this.config.mode = PlateMode.Form; + this.config.mode = PlateInterface.Form; } public discardForm() { - this.config.mode = PlateMode.Skeleton; + this.config.mode = PlateInterface.Skeleton; } public expandTab() { diff --git a/src/app/modules/plates/plate/plate.model.ts b/src/app/modules/plates/plate/plate.model.ts index 4d8ff00..09c2a25 100644 --- a/src/app/modules/plates/plate/plate.model.ts +++ b/src/app/modules/plates/plate/plate.model.ts @@ -1,8 +1,8 @@ -import {PlateMode} from "../plate-mode"; +import {PlateInterface} from "../plate.interface"; export interface Plate { _id?: string; - mode?: PlateMode; + mode?: PlateInterface; color?: string; name?: string; description?: string; diff --git a/src/app/modules/plates/plates/plates.component.ts b/src/app/modules/plates/plates/plates.component.ts index 1b8a1b8..169721c 100644 --- a/src/app/modules/plates/plates/plates.component.ts +++ b/src/app/modules/plates/plates/plates.component.ts @@ -1,5 +1,5 @@ import {AfterViewInit, Component, ElementRef, Inject, OnInit} from '@angular/core'; -import {mode, PlateMode} from "../plate-mode"; +import {mode, PlateInterface} from "../plate.interface"; import {I18nService} from "../../../services/i18n.service"; import {Plate} from "../plate/plate.model"; import {ApiConnector} from "../../../services/api-connector"; @@ -15,7 +15,7 @@ export class PlatesComponent implements OnInit, AfterViewInit { public readonly i18n: any; public readonly DISPLAY_CHUNK = 3; - public plateMode: typeof PlateMode = mode(); + public plateMode: typeof PlateInterface = mode(); public hidePrevious: boolean = true; public hideNext: boolean = true; public plateList!: Plate[]; @@ -113,7 +113,7 @@ export class PlatesComponent implements OnInit, AfterViewInit { this.plateList = [ ...plates, { - mode: PlateMode.Skeleton + mode: PlateInterface.Skeleton } ]; this._total = this.plateList.length; diff --git a/src/app/modules/plates/services/plate-queue-manager.service.ts b/src/app/modules/plates/services/plate-queue-manager.service.ts index 81d6e3a..7a1419d 100644 --- a/src/app/modules/plates/services/plate-queue-manager.service.ts +++ b/src/app/modules/plates/services/plate-queue-manager.service.ts @@ -1,7 +1,9 @@ import {Injectable} from '@angular/core'; import {ReactiveQueue} from "../../shared/class/reactive-queue"; import {Plate} from "../plate/plate.model"; -import {MenuItem} from "../../orders/order"; +import {MenuItem, Status} from "../../orders/order"; +import {PlateItemAction, PlateItemStatus} from "../plate.interface"; +import {BehaviorSubject} from "rxjs"; @Injectable({ providedIn: 'root' @@ -9,6 +11,7 @@ import {MenuItem} from "../../orders/order"; export class PlateQueueManagerService { private _plates: Map> = new Map>(); + private _changes$: BehaviorSubject = new BehaviorSubject(0); constructor() { } @@ -25,19 +28,68 @@ export class PlateQueueManagerService { this._plates.set(plate._id!, new ReactiveQueue()); } + get notify(): BehaviorSubject { + return this._changes$; + } + + get haveNotify(): boolean { + return this._changes$.value > 0; + } + public sendToQueue(id: string, item: MenuItem): void { + this._validateItem(item); + this._getQueue(id).enqueue(item); + this._changes$.next(this._changes$.value + 1); + } + + public removeFromQueue(id: string, item: MenuItem): void { + this._validateItem(item); + const queue: ReactiveQueue = this._getQueue(id); + queue.values = queue.values.filter((i: MenuItem) => { + return i._id != item._id; + }); + this._changes$.next(this._changes$.value - 1); + } + + public onItemAction(id: string, item: MenuItem, action: PlateItemAction, nextId?: string): void { + this._validateItem(item); + + switch (action) { + case PlateItemStatus.Moved: + if (!nextId) throw new Error("No queue selected to move the item"); + this.sendToQueue(nextId, item); + this.onItemAction(nextId, item, Status.Cancelled); + break; + case PlateItemStatus.ReQueued: + this.sendToQueue(id, item); + break; + case Status.Cancelled || Status.Done: + this.removeFromQueue(id, item); + //TODO: Invoke order service + break; + default: + console.warn("[QueueManager] Action not found"); + break; + } + } + + private _validateItem(item: MenuItem): void { + if (!item || !item._id || !item.name) { + throw new Error("Selected item is invalid!"); + } + } + + private _getQueue(id: string): ReactiveQueue { if (!id) { - console.error("Plate Id is undefined!"); - return; + throw new Error("Plate Id is undefined!"); } const queue: ReactiveQueue = this.getQueue(id); if (!queue) { - console.error("No queue found!"); - return; + throw new Error("No queue found!"); } - queue.enqueue(item); + return queue; } } diff --git a/src/app/modules/shared/class/reactive-queue.ts b/src/app/modules/shared/class/reactive-queue.ts index f810aaa..481803c 100644 --- a/src/app/modules/shared/class/reactive-queue.ts +++ b/src/app/modules/shared/class/reactive-queue.ts @@ -1,30 +1,35 @@ -import {BehaviorSubject, Observable, of} from "rxjs"; +import {Observable, of} from "rxjs"; export class ReactiveQueue { - private items$: BehaviorSubject; + private readonly items: T[]; constructor(items?: T[]) { - this.items$ = new BehaviorSubject(items ?? []); + this.items = items ?? []; } get dequeue(): T | undefined { - return this.items$.getValue().shift(); + return this.items.shift(); } - get count(): Observable { - return of(this.items$.getValue().length) + get count$(): Observable { + return of(this.items.length) } get values(): T[] { - return this.items$.getValue(); + return this.items; + } + + set values(items: T[]) { + this.items.length = 0; + this.items.push(...items); } get values$(): Observable { - return of(this.items$.getValue()); + return of(this.items); } - get isEmpty(): Observable { - return of(this.items$.getValue() == null || this.items$.getValue().length == 0); + get isEmpty$(): Observable { + return of(this.items == null || this.items.length == 0); } public enqueue(value: T): void { diff --git a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts index e003753..25bc5ff 100644 --- a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts +++ b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts @@ -3,22 +3,21 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; @Component({ selector: 'navbar-button', template: ` - `, styleUrls: ['navbar-button.component.scss'] }) export class NavbarButtonComponent { - @Input() icon!: string; - @Output() onClick: EventEmitter = new EventEmitter(true); - - public _active: boolean = false; + @Input() public icon!: string; + @Input() public active: boolean = false; + @Input() public badged?: boolean = false; + @Input() public badgeCounter?: number | null; - @Input() set active(value: boolean) { - this._active = value; - } + @Output() onClick: EventEmitter = new EventEmitter(true); public click() { this.onClick.emit(true); diff --git a/src/app/modules/shared/components/navbar/navbar.component.html b/src/app/modules/shared/components/navbar/navbar.component.html index f44b715..1198499 100644 --- a/src/app/modules/shared/components/navbar/navbar.component.html +++ b/src/app/modules/shared/components/navbar/navbar.component.html @@ -5,6 +5,8 @@