From c62b9aaaadee8843e5607c767a3d885b7671fc11 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 15 Jan 2025 00:58:55 +0000 Subject: [PATCH] Actions now use resolver. Dialog handles websocket messaging. Added support for text values on actions. --- .../action-item-edit.component.html | 24 ++++++++++++-- .../action-item-edit.component.ts | 25 ++++++++++++--- .../action-list/action-list.component.scss | 30 ++++++++++------- .../action-list/action-list.component.ts | 27 ++++++---------- src/app/actions/actions.module.ts | 4 +-- .../actions/actions/actions.component.html | 2 +- src/app/actions/actions/actions.component.ts | 30 ++++++++++------- .../services/redeemable-action.service.ts | 32 +++++++++++++++++-- 8 files changed, 121 insertions(+), 53 deletions(-) diff --git a/src/app/actions/action-item-edit/action-item-edit.component.html b/src/app/actions/action-item-edit/action-item-edit.component.html index fda87e9..5b527e7 100644 --- a/src/app/actions/action-item-edit/action-item-edit.component.html +++ b/src/app/actions/action-item-edit/action-item-edit.component.html @@ -76,6 +76,21 @@ } } + @else if (field.type == 'text-values') { + + {{field.label}} + + @for (value of field.values; track $index) { + {{value}} + } + + @if (field.control.invalid && (field.control.dirty || field.control.touched)) { + @if (field.control.hasError('required')) { + This field is required. + } + } + + } } @@ -87,8 +102,13 @@ @if (!isNew) { } - - + + \ No newline at end of file diff --git a/src/app/actions/action-item-edit/action-item-edit.component.ts b/src/app/actions/action-item-edit/action-item-edit.component.ts index 5ba0feb..538c868 100644 --- a/src/app/actions/action-item-edit/action-item-edit.component.ts +++ b/src/app/actions/action-item-edit/action-item-edit.component.ts @@ -25,9 +25,9 @@ import { HermesClientService } from '../../hermes-client.service'; styleUrl: './action-item-edit.component.scss' }) export class ActionItemEditComponent implements OnInit { - readonly client = inject(HermesClientService); + private readonly client = inject(HermesClientService); readonly dialogRef = inject(MatDialogRef); - readonly data = inject<{ action: RedeemableAction, actions:RedeemableAction[] }>(MAT_DIALOG_DATA); + private readonly data = inject<{ action: RedeemableAction, actions: RedeemableAction[] }>(MAT_DIALOG_DATA); action = this.data.action; actions = this.data.actions; readonly actionEntries: ({ [key: string]: any[] }) = { @@ -203,6 +203,7 @@ export class ActionItemEditComponent implements OnInit { isNew: boolean = true; previousName: string = this.action.name; + waitForResponse: boolean = false; readonly formGroup = new FormGroup({ name: new FormControl(this.action.name, [Validators.required]), @@ -237,8 +238,13 @@ export class ActionItemEditComponent implements OnInit { if (this.isNew) return; + this.client.first((d: any) => d.op == 4 && d.d.request.type == 'delete_redeemable_action' && d.d.request.data.name == this.action.name) + .subscribe({ + next: () => this.dialogRef.close(), + error: () => this.waitForResponse = false, + complete: () => this.waitForResponse = false, + }); this.client.deleteRedeemableAction(action.name); - this.dialogRef.close(); } save(): void { @@ -262,6 +268,17 @@ export class ActionItemEditComponent implements OnInit { return; } - this.dialogRef.close(this.action); + const isNewAction = !this.action.user_id; + const requestType = isNewAction ? 'create_redeemable_action' : 'update_redeemable_action'; + this.client.first((d: any) => d.op == 4 && d.d.request.type == requestType && d.d.data.name == this.action.name) + .subscribe({ + next: () => this.dialogRef.close(this.action), + error: () => this.waitForResponse = false, + complete: () => this.waitForResponse = false, + }); + if (isNewAction) + this.client.createRedeemableAction(this.action.name, this.action.type, this.action.data); + else + this.client.updateRedeemableAction(this.action.name, this.action.type, this.action.data); } } diff --git a/src/app/actions/action-list/action-list.component.scss b/src/app/actions/action-list/action-list.component.scss index fe1d043..aa75f44 100644 --- a/src/app/actions/action-list/action-list.component.scss +++ b/src/app/actions/action-list/action-list.component.scss @@ -2,18 +2,6 @@ main { display: grid; grid-template-columns: repeat(1, 1fr); - @media (min-width:1200px) { - grid-template-columns: repeat(2, 1fr); - } - - @media (min-width:1650px) { - grid-template-columns: repeat(3, 1fr); - } - - @media (min-width:2200px) { - grid-template-columns: repeat(4, 1fr); - } - grid-auto-flow: row dense; grid-gap: 1rem; justify-content: center; @@ -53,4 +41,22 @@ main { & article:first-child { flex: 1; } +} + +@media (min-width:1200px) { + main { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width:1650px) { + main { + grid-template-columns: repeat(3, 1fr); + } +} + +@media (min-width:2200px) { + main { + grid-template-columns: repeat(4, 1fr); + } } \ No newline at end of file diff --git a/src/app/actions/action-list/action-list.component.ts b/src/app/actions/action-list/action-list.component.ts index e81c425..c85345d 100644 --- a/src/app/actions/action-list/action-list.component.ts +++ b/src/app/actions/action-list/action-list.component.ts @@ -37,30 +37,21 @@ export class ActionListComponent { this.opened = true; const dialogRef = this.dialog.open(ActionItemEditComponent, { - data: { action: {user_id: action.user_id, name: action.name, type: action.type, data: action.data }, actions: this.actions }, + data: { action: { user_id: action.user_id, name: action.name, type: action.type, data: action.data }, actions: this.actions }, }); - const isNewAction = action.name.length <= 0; - const requestType = isNewAction ? 'create_redeemable_action' : 'update_redeemable_action'; - dialogRef.afterClosed().subscribe((result: RedeemableAction) => { + const isNewAction = action.name.length <= 0; + dialogRef.afterClosed().subscribe((result: RedeemableAction | undefined) => { this.opened = false; if (!result) return; - this.client.first((d: any) => d.op == 4 && d.d.request.type == requestType && d.d.data.name == result.name) - ?.subscribe(_ => { - if (isNewAction) { - this.actionsChange.emit(result); - } else { - action.type = result.type; - action.data = result.data; - } - }); - - if (isNewAction) - this.client.createRedeemableAction(result.name, result.type, result.data); - else - this.client.updateRedeemableAction(result.name, result.type, result.data); + if (isNewAction) { + this.actionsChange.emit(result); + } else { + action.type = result.type; + action.data = result.data; + } }); } } diff --git a/src/app/actions/actions.module.ts b/src/app/actions/actions.module.ts index 3acfc2f..562f7a0 100644 --- a/src/app/actions/actions.module.ts +++ b/src/app/actions/actions.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ActionsComponent } from './actions/actions.component'; import { ActionListComponent } from './action-list/action-list.component'; -import { ActionItemComponent } from './action-item/action-item.component'; +import { ActionItemEditComponent } from './action-item-edit/action-item-edit.component'; @@ -11,7 +11,7 @@ import { ActionItemComponent } from './action-item/action-item.component'; imports: [ ActionsComponent, ActionListComponent, - ActionItemComponent, + ActionItemEditComponent, ] }) export class ActionsModule { } diff --git a/src/app/actions/actions/actions.component.html b/src/app/actions/actions/actions.component.html index 8d42f57..3752838 100644 --- a/src/app/actions/actions/actions.component.html +++ b/src/app/actions/actions/actions.component.html @@ -4,7 +4,7 @@
- Filter + Filter by type filter_list {{filter.name}} diff --git a/src/app/actions/actions/actions.component.ts b/src/app/actions/actions/actions.component.ts index a69f9d9..865b27d 100644 --- a/src/app/actions/actions/actions.component.ts +++ b/src/app/actions/actions/actions.component.ts @@ -7,6 +7,8 @@ import { MatIconModule } from '@angular/material/icon'; import { HermesClientService } from '../../hermes-client.service'; import RedeemableAction from '../../shared/models/redeemable_action'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { RedeemableActionService } from '../../shared/services/redeemable-action.service'; interface IActionFilter { name: string @@ -38,27 +40,30 @@ export class ActionsComponent implements OnInit { { name: 'Veadotube', filter: data => data.type.includes('VEADOTUBE') }, ]; - client = inject(HermesClientService); + private readonly client = inject(HermesClientService); + private readonly redeemableActionService = inject(RedeemableActionService); + private readonly route = inject(ActivatedRoute); filter = this.filters[0]; searchControl = new FormControl(''); search = ''; items: RedeemableAction[] = []; ngOnInit(): void { - this.client.subscribeToRequests('get_redeemable_actions', d => { - this.items = d.data; - }); - this.client.subscribeToRequests('create_redeemable_action', d => { - if (d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) { + this.route.data.subscribe(data => { + if (!data['redeemableActions']) + return; + + this.actions = [...data['redeemableActions']]; + }); + this.redeemableActionService.create$?.subscribe(d => { + if (d.error || d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) return; - } this.actions.push(d.data); }); - this.client.subscribeToRequests('update_redeemable_action', d => { - if (d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) { + this.redeemableActionService.update$?.subscribe(d => { + if (d.error || d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) return; - } const action = this.actions.find(a => a.name == d.data.name); if (action) { @@ -66,7 +71,10 @@ export class ActionsComponent implements OnInit { action.data = d.data.data; } }); - this.client.subscribeToRequests('delete_redeemable_action', d => { + this.redeemableActionService.delete$?.subscribe(d => { + if (d.error) + return; + this.items = this.actions.filter(a => a.name != d.request.data.name); }); diff --git a/src/app/shared/services/redeemable-action.service.ts b/src/app/shared/services/redeemable-action.service.ts index ce21f56..be9f712 100644 --- a/src/app/shared/services/redeemable-action.service.ts +++ b/src/app/shared/services/redeemable-action.service.ts @@ -1,17 +1,43 @@ import { inject, Injectable } from '@angular/core'; import { HermesClientService } from '../../hermes-client.service'; -import { map, of } from 'rxjs'; +import { map, Observable, of } from 'rxjs'; import RedeemableAction from '../models/redeemable_action'; +import EventService from './EventService'; @Injectable({ providedIn: 'root' }) export class RedeemableActionService { - private client = inject(HermesClientService); + private readonly client = inject(HermesClientService); + private readonly events = inject(EventService); private data: RedeemableAction[] = [] - loaded = false; + private loaded = false; + create$: Observable | undefined; + update$: Observable | undefined; + delete$: Observable | undefined; + constructor() { + this.create$ = this.client.filterByRequestType('create_redeemable_action'); + this.update$ = this.client.filterByRequestType('update_redeemable_action'); + this.delete$ = this.client.filterByRequestType('delete_redeemable_action'); + + this.create$?.subscribe(d => this.data.push(d.data)); + this.update$?.subscribe(d => { + const action = this.data.find(r => r.name == d.data.name); + if (action) { + action.type = d.data.type; + action.data = d.data.data; + } + }); + this.delete$?.subscribe(d => this.data = this.data.filter(r => r.name != d.request.data.name)); + + this.events.listen('tts_logoff', () => { + this.data = []; + this.loaded = false; + }); + } + fetch() { if (this.loaded) { return of(this.data);