Cleaned up code for redeemable actions.

This commit is contained in:
Tom
2025-04-08 12:57:08 +00:00
parent 01c62bc143
commit 931046cbb3
12 changed files with 72 additions and 121 deletions

View File

@ -28,10 +28,12 @@ import { MatIconModule } from '@angular/material/icon';
})
export class ActionItemEditComponent implements OnInit {
private readonly client = inject(HermesClientService);
readonly dialogRef = inject(MatDialogRef<ActionItemEditComponent>);
private readonly data = inject<{ action: RedeemableAction, actions: RedeemableAction[] }>(MAT_DIALOG_DATA);
readonly dialogRef = inject(MatDialogRef<ActionItemEditComponent>);
action = this.data.action;
actions = this.data.actions;
readonly actionEntries: ({ [key: string]: any[] }) = {
'SLEEP': [
{
@ -272,18 +274,18 @@ export class ActionItemEditComponent implements OnInit {
return;
}
this.action.name = this.formGroup.get('name')!.value!;
this.action.type = this.formGroup.get('type')!.value!;
this.action.data = {}
for (const entry of this.actionEntries[this.action.type]) {
this.action.data[entry.key] = entry.control.value!.toString();
}
if (!(this.action.type in this.actionEntries)) {
this.waitForResponse = false;
return;
}
this.action.name = this.formGroup.get('name')!.value!;
this.action.type = this.formGroup.get('type')!.value!;
this.action.data = {};
for (const entry of this.actionEntries[this.action.type]) {
this.action.data[entry.key] = entry.control.value!.toString();
}
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)
@ -299,8 +301,8 @@ export class ActionItemEditComponent implements OnInit {
complete: () => this.waitForResponse = false,
});
if (isNewAction)
this.client.createRedeemableAction(this.action.name, this.action.type, this.action.data);
this.client.createRedeemableAction(this.action.name, this.action.type, false, this.action.data);
else
this.client.updateRedeemableAction(this.action.name, this.action.type, this.action.data);
this.client.updateRedeemableAction(this.action.name, this.action.type, false, this.action.data);
}
}

View File

@ -1,5 +1,5 @@
<main>
@for (action of actions; track action.name) {
@for (action of actions(); track action.name) {
<button type="button"
class="container"
(click)="modify(action)">

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
import { Component, inject, input } from '@angular/core';
import { MatListModule } from '@angular/material/list';
import RedeemableAction from '../../shared/models/redeemable-action';
import { MatButtonModule } from '@angular/material/button';
@ -23,16 +23,14 @@ import { MatSelectModule } from '@angular/material/select';
styleUrl: './action-list.component.scss'
})
export class ActionListComponent {
@Input() actions: RedeemableAction[] = []
@Output() actionsChange = new EventEmitter<RedeemableAction>();
actions = input.required<RedeemableAction[]>({ alias: 'actions' });
readonly dialog = inject(MatDialog);
readonly client = inject(HermesClientService);
opened = false;
create(): void {
this.openDialog({ user_id: '', name: '', type: '', data: {} });
this.openDialog({ user_id: '', name: '', type: '', has_message: false, data: {} });
}
modify(action: RedeemableAction): void {
@ -40,27 +38,8 @@ export class ActionListComponent {
}
private openDialog(action: RedeemableAction): void {
if (this.opened)
return;
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 },
});
const isNewAction = action.name.length <= 0;
dialogRef.afterClosed().subscribe((result: RedeemableAction | undefined) => {
this.opened = false;
if (!result)
return;
if (isNewAction) {
this.actionsChange.emit(result);
} else {
action.type = result.type;
action.data = result.data;
}
this.dialog.open(ActionItemEditComponent, {
data: { action: { user_id: action.user_id, name: action.name, type: action.type, data: action.data }, actions: this.actions() },
});
}
}

View File

@ -6,7 +6,7 @@
<mat-form-field subscriptSizing="dynamic">
<mat-label>Filter by type</mat-label>
<mat-select value="0"
(selectionChange)="onFilterChange($event.value)">
(selectionChange)="filter = filters[$event.value]">
<mat-select-trigger>
<mat-icon matPrefix>filter_list</mat-icon>&nbsp;{{filter.name}}
</mat-select-trigger>
@ -22,13 +22,11 @@
<input matInput
type="text"
placeholder="Name of action"
[formControl]="searchControl"
[(ngModel)]="search">
[formControl]="searchControl" />
<mat-icon matPrefix>search</mat-icon>
</mat-form-field>
</article>
</section>
<action-list class="list center"
[actions]="actions"
(actionsChange)="items.push($event)" />
[actions]="actions" />
</content>

View File

@ -1,4 +1,4 @@
import { Component, Inject, inject, OnInit } from '@angular/core';
import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { ActionListComponent } from "../action-list/action-list.component";
import { MatSelectModule } from '@angular/material/select';
import { MatFormFieldModule } from '@angular/material/form-field';
@ -10,7 +10,8 @@ import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import RedeemableActionService from '../../shared/services/redeemable-action.service';
import { MatButtonModule } from '@angular/material/button';
import { DOCUMENT } from '@angular/common';
import { containsLettersInOrder } from '../../shared/utils/string-compare';
import { Subscription } from 'rxjs';
interface IActionFilter {
name: string
@ -32,7 +33,7 @@ interface IActionFilter {
templateUrl: './actions.component.html',
styleUrl: './actions.component.scss'
})
export class ActionsComponent implements OnInit {
export class ActionsComponent implements OnInit, OnDestroy {
filters: IActionFilter[] = [
{ name: 'All', filter: _ => true },
{ name: 'Local File', filter: data => data.type.includes('_FILE') },
@ -47,58 +48,28 @@ export class ActionsComponent implements OnInit {
private readonly redeemableActionService = inject(RedeemableActionService);
private readonly route = inject(ActivatedRoute);
filter = this.filters[0];
searchControl = new FormControl('');
search = '';
items: RedeemableAction[] = [];
private readonly subscriptions: (Subscription | undefined)[] = [];
constructor(@Inject(DOCUMENT) private document: Document) { }
filter = this.filters[0];
searchControl = new FormControl<string>('');
_actions: RedeemableAction[] = [];
ngOnInit(): void {
this.route.data.subscribe(data => {
if (!data['redeemableActions'])
return;
this.route.data.subscribe(data => this._actions = data['redeemableActions'] || []);
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.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) {
action.type = d.data.type;
action.data = d.data.data;
}
});
this.redeemableActionService.delete$?.subscribe(d => {
if (d.error)
return;
this.items = this.actions.filter(a => a.name != d.request.data.name);
});
this.subscriptions.push(this.redeemableActionService.delete$?.subscribe(_ => this.redeemableActionService.fetch().subscribe(a => this._actions = a)));
this.client.fetchRedeemableActions();
}
ngOnDestroy(): void {
this.subscriptions.filter(s => s).forEach(s => s?.unsubscribe());
}
get actions(): RedeemableAction[] {
const searchLower = this.search.toLowerCase();
return this.items.filter(this.filter.filter)
.filter((action) => action.name.toLowerCase().includes(searchLower));
}
set actions(value) {
this.items = value;
}
onFilterChange(event: any): void {
this.filter = this.filters[event];
const searchLower = this.searchControl.value!.toLowerCase();
return this._actions.filter(this.filter.filter)
.filter((action) => containsLettersInOrder(action.name.toLowerCase(), searchLower));
}
}

View File

@ -1,6 +1,13 @@
@use '@angular/material' as mat;
ul {
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
@include mat.all-component-densities(-5);
@include mat.form-field-overrides((
@ -8,13 +15,6 @@ ul {
outlined-focus-label-text-color: rgb(155, 57, 194),
outlined-focus-outline-color: rgb(155, 57, 194),
));
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
}
ul li {

View File

@ -156,14 +156,14 @@ export class HermesClientService {
});
}
public createRedeemableAction(name: string, type: string, d: { [key: string]: any }) {
public createRedeemableAction(name: string, type: string, has_message: boolean, d: { [key: string]: any }) {
if (!this.logged_in)
return;
this.send(3, {
request_id: null,
type: "create_redeemable_action",
data: { name, type, data: d },
data: { name, type, has_message, data: d },
nounce: this.session_id,
});
}
@ -439,14 +439,14 @@ export class HermesClientService {
});
}
public updateRedeemableAction(name: string, type: string, d: { [key: string]: any }) {
public updateRedeemableAction(name: string, type: string, has_message: boolean, d: { [key: string]: any }) {
if (!this.logged_in)
return;
this.send(3, {
request_id: null,
type: "update_redeemable_action",
data: { name, type, data: d },
data: { name, type, has_message, data: d },
nounce: this.session_id,
});
}

View File

@ -1,6 +1,13 @@
@use '@angular/material' as mat;
ul {
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 600px;
overflow: hidden;
@include mat.all-component-densities(-5);
@include mat.form-field-overrides((
@ -8,13 +15,6 @@ ul {
outlined-focus-label-text-color: rgb(155, 57, 194),
outlined-focus-outline-color: rgb(155, 57, 194),
));
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 600px;
overflow: hidden;
}
ul li {

View File

@ -1,6 +1,13 @@
@use '@angular/material' as mat;
ul {
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
@include mat.all-component-densities(-5);
@include mat.form-field-overrides((
@ -8,13 +15,6 @@ ul {
outlined-focus-label-text-color: rgb(155, 57, 194),
outlined-focus-outline-color: rgb(155, 57, 194),
));
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
}
ul li {

View File

@ -2,5 +2,6 @@ export default interface RedeemableAction {
user_id: string;
name: string;
type: string;
has_message: boolean;
data: any;
}

View File

@ -22,7 +22,7 @@ export default class RedeemableActionService {
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.create$?.subscribe(d => {this.data.push(d.data); console.log('action service add:', d.data) });
this.update$?.subscribe(d => {
const action = this.data.find(r => r.name == d.data.name);
if (action) {

View File

@ -1,6 +1,13 @@
@use '@angular/material' as mat;
ul {
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
@include mat.all-component-densities(-5);
@include mat.form-field-overrides((
@ -8,13 +15,6 @@ ul {
outlined-focus-label-text-color: rgb(155, 57, 194),
outlined-focus-outline-color: rgb(155, 57, 194),
));
background-color: rgb(202, 68, 255);
border-radius: 15px;
margin: 0 0;
padding: 0;
max-width: 500px;
overflow: hidden;
}
ul li {