Actions now use resolver. Dialog handles websocket messaging. Added support for text values on actions.
This commit is contained in:
parent
9cda9a5738
commit
c62b9aaaad
@ -76,6 +76,21 @@
|
|||||||
}
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
}
|
}
|
||||||
|
@else if (field.type == 'text-values') {
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>{{field.label}}</mat-label>
|
||||||
|
<mat-select [formControl]="field.control">
|
||||||
|
@for (value of field.values; track $index) {
|
||||||
|
<mat-option [value]="value">{{value}}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
@if (field.control.invalid && (field.control.dirty || field.control.touched)) {
|
||||||
|
@if (field.control.hasError('required')) {
|
||||||
|
<small class="error">This field is required.</small>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -87,8 +102,13 @@
|
|||||||
@if (!isNew) {
|
@if (!isNew) {
|
||||||
<button mat-raised-button class="delete" (click)="deleteAction(action)">Delete</button>
|
<button mat-raised-button class="delete" (click)="deleteAction(action)">Delete</button>
|
||||||
}
|
}
|
||||||
<button mat-raised-button (click)="dialogRef.close()">Cancel</button>
|
<button
|
||||||
<button mat-raised-button disabled="{{!formsDirty || !formsValidity}}" (click)="save()">Save</button>
|
mat-raised-button
|
||||||
|
(click)="dialogRef.close()">Cancel</button>
|
||||||
|
<button
|
||||||
|
mat-raised-button
|
||||||
|
disabled="{{!formsDirty || !formsValidity || waitForResponse}}"
|
||||||
|
(click)="save()">Save</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</body>
|
</body>
|
@ -25,9 +25,9 @@ import { HermesClientService } from '../../hermes-client.service';
|
|||||||
styleUrl: './action-item-edit.component.scss'
|
styleUrl: './action-item-edit.component.scss'
|
||||||
})
|
})
|
||||||
export class ActionItemEditComponent implements OnInit {
|
export class ActionItemEditComponent implements OnInit {
|
||||||
readonly client = inject(HermesClientService);
|
private readonly client = inject(HermesClientService);
|
||||||
readonly dialogRef = inject(MatDialogRef<ActionItemEditComponent>);
|
readonly dialogRef = inject(MatDialogRef<ActionItemEditComponent>);
|
||||||
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;
|
action = this.data.action;
|
||||||
actions = this.data.actions;
|
actions = this.data.actions;
|
||||||
readonly actionEntries: ({ [key: string]: any[] }) = {
|
readonly actionEntries: ({ [key: string]: any[] }) = {
|
||||||
@ -203,6 +203,7 @@ export class ActionItemEditComponent implements OnInit {
|
|||||||
|
|
||||||
isNew: boolean = true;
|
isNew: boolean = true;
|
||||||
previousName: string = this.action.name;
|
previousName: string = this.action.name;
|
||||||
|
waitForResponse: boolean = false;
|
||||||
|
|
||||||
readonly formGroup = new FormGroup({
|
readonly formGroup = new FormGroup({
|
||||||
name: new FormControl(this.action.name, [Validators.required]),
|
name: new FormControl(this.action.name, [Validators.required]),
|
||||||
@ -237,8 +238,13 @@ export class ActionItemEditComponent implements OnInit {
|
|||||||
if (this.isNew)
|
if (this.isNew)
|
||||||
return;
|
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.client.deleteRedeemableAction(action.name);
|
||||||
this.dialogRef.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
save(): void {
|
save(): void {
|
||||||
@ -262,6 +268,17 @@ export class ActionItemEditComponent implements OnInit {
|
|||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,6 @@ main {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(1, 1fr);
|
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-auto-flow: row dense;
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -53,4 +41,22 @@ main {
|
|||||||
& article:first-child {
|
& article:first-child {
|
||||||
flex: 1;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
@ -37,30 +37,21 @@ export class ActionListComponent {
|
|||||||
this.opened = true;
|
this.opened = true;
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(ActionItemEditComponent, {
|
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;
|
this.opened = false;
|
||||||
if (!result)
|
if (!result)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.client.first((d: any) => d.op == 4 && d.d.request.type == requestType && d.d.data.name == result.name)
|
if (isNewAction) {
|
||||||
?.subscribe(_ => {
|
this.actionsChange.emit(result);
|
||||||
if (isNewAction) {
|
} else {
|
||||||
this.actionsChange.emit(result);
|
action.type = result.type;
|
||||||
} else {
|
action.data = result.data;
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { ActionsComponent } from './actions/actions.component';
|
import { ActionsComponent } from './actions/actions.component';
|
||||||
import { ActionListComponent } from './action-list/action-list.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: [
|
imports: [
|
||||||
ActionsComponent,
|
ActionsComponent,
|
||||||
ActionListComponent,
|
ActionListComponent,
|
||||||
ActionItemComponent,
|
ActionItemEditComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ActionsModule { }
|
export class ActionsModule { }
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<section>
|
<section>
|
||||||
<article>
|
<article>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Filter</mat-label>
|
<mat-label>Filter by type</mat-label>
|
||||||
<mat-select (selectionChange)="onFilterChange($event.value)" value="0">
|
<mat-select (selectionChange)="onFilterChange($event.value)" value="0">
|
||||||
<mat-select-trigger>
|
<mat-select-trigger>
|
||||||
<mat-icon matPrefix>filter_list</mat-icon> {{filter.name}}
|
<mat-icon matPrefix>filter_list</mat-icon> {{filter.name}}
|
||||||
|
@ -7,6 +7,8 @@ import { MatIconModule } from '@angular/material/icon';
|
|||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import RedeemableAction from '../../shared/models/redeemable_action';
|
import RedeemableAction from '../../shared/models/redeemable_action';
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { RedeemableActionService } from '../../shared/services/redeemable-action.service';
|
||||||
|
|
||||||
interface IActionFilter {
|
interface IActionFilter {
|
||||||
name: string
|
name: string
|
||||||
@ -38,27 +40,30 @@ export class ActionsComponent implements OnInit {
|
|||||||
{ name: 'Veadotube', filter: data => data.type.includes('VEADOTUBE') },
|
{ 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];
|
filter = this.filters[0];
|
||||||
searchControl = new FormControl('');
|
searchControl = new FormControl('');
|
||||||
search = '';
|
search = '';
|
||||||
items: RedeemableAction[] = [];
|
items: RedeemableAction[] = [];
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.client.subscribeToRequests('get_redeemable_actions', d => {
|
this.route.data.subscribe(data => {
|
||||||
this.items = d.data;
|
if (!data['redeemableActions'])
|
||||||
});
|
return;
|
||||||
this.client.subscribeToRequests('create_redeemable_action', d => {
|
|
||||||
if (d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) {
|
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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
this.actions.push(d.data);
|
this.actions.push(d.data);
|
||||||
});
|
});
|
||||||
this.client.subscribeToRequests('update_redeemable_action', d => {
|
this.redeemableActionService.update$?.subscribe(d => {
|
||||||
if (d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id)) {
|
if (d.error || d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const action = this.actions.find(a => a.name == d.data.name);
|
const action = this.actions.find(a => a.name == d.data.name);
|
||||||
if (action) {
|
if (action) {
|
||||||
@ -66,7 +71,10 @@ export class ActionsComponent implements OnInit {
|
|||||||
action.data = d.data.data;
|
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);
|
this.items = this.actions.filter(a => a.name != d.request.data.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,17 +1,43 @@
|
|||||||
import { inject, Injectable } from '@angular/core';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import { map, of } from 'rxjs';
|
import { map, Observable, of } from 'rxjs';
|
||||||
import RedeemableAction from '../models/redeemable_action';
|
import RedeemableAction from '../models/redeemable_action';
|
||||||
|
import EventService from './EventService';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class RedeemableActionService {
|
export class RedeemableActionService {
|
||||||
private client = inject(HermesClientService);
|
private readonly client = inject(HermesClientService);
|
||||||
|
private readonly events = inject(EventService);
|
||||||
private data: RedeemableAction[] = []
|
private data: RedeemableAction[] = []
|
||||||
loaded = false;
|
private loaded = false;
|
||||||
|
create$: Observable<any> | undefined;
|
||||||
|
update$: Observable<any> | undefined;
|
||||||
|
delete$: Observable<any> | 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() {
|
fetch() {
|
||||||
if (this.loaded) {
|
if (this.loaded) {
|
||||||
return of(this.data);
|
return of(this.data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user