Updated TTS Filters page to use resolvers, services and better UX.
This commit is contained in:
parent
45d6eaeb73
commit
59bed7c28b
@ -12,6 +12,7 @@ import { RedemptionsComponent } from './redemptions/redemptions/redemptions.comp
|
|||||||
import RedemptionResolver from './shared/resolvers/redemption-resolver';
|
import RedemptionResolver from './shared/resolvers/redemption-resolver';
|
||||||
import TwitchRedemptionResolver from './shared/resolvers/twitch-redemption-resolver';
|
import TwitchRedemptionResolver from './shared/resolvers/twitch-redemption-resolver';
|
||||||
import RedeemableActionResolver from './shared/resolvers/redeemable-action-resolver';
|
import RedeemableActionResolver from './shared/resolvers/redeemable-action-resolver';
|
||||||
|
import TtsFilterResolver from './shared/resolvers/tts-filter-resolver';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -23,6 +24,9 @@ export const routes: Routes = [
|
|||||||
path: 'filters',
|
path: 'filters',
|
||||||
component: FiltersComponent,
|
component: FiltersComponent,
|
||||||
canActivate: [AuthUserGuard],
|
canActivate: [AuthUserGuard],
|
||||||
|
resolve: {
|
||||||
|
filters: TtsFilterResolver,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'actions',
|
path: 'actions',
|
||||||
|
@ -127,14 +127,15 @@ export class HermesClientService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public createTTSFilter(search: string, replace: string) {
|
public createTTSFilter(search: string, replace: string, flag: number) {
|
||||||
if (!this.logged_in)
|
if (!this.logged_in)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.send(3, {
|
this.send(3, {
|
||||||
request_id: null,
|
request_id: null,
|
||||||
type: "create_tts_filter",
|
type: "create_tts_filter",
|
||||||
data: { search, replace },
|
data: { search, replace, flag },
|
||||||
|
nounce: this.session_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,14 +302,14 @@ export class HermesClientService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateTTSFilter(id: string, search: string, replace: string) {
|
public updateTTSFilter(id: string, search: string, replace: string, flag: number) {
|
||||||
if (!this.logged_in)
|
if (!this.logged_in)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.send(3, {
|
this.send(3, {
|
||||||
request_id: null,
|
request_id: null,
|
||||||
type: "update_tts_filter",
|
type: "update_tts_filter",
|
||||||
data: { id, search, replace },
|
data: { id, search, replace, flag },
|
||||||
nounce: this.session_id,
|
nounce: this.session_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,5 +12,4 @@ export interface Filter {
|
|||||||
replace: string;
|
replace: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
flag: FilterFlag;
|
flag: FilterFlag;
|
||||||
is_regex: boolean;
|
|
||||||
}
|
}
|
14
src/app/shared/resolvers/tts-filter-resolver.ts
Normal file
14
src/app/shared/resolvers/tts-filter-resolver.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Filter } from '../models/filter';
|
||||||
|
import { TtsFilterService } from '../services/tts-filter.service';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export default class TtsFilterResolver implements Resolve<Filter[]> {
|
||||||
|
constructor(private service: TtsFilterService) { }
|
||||||
|
|
||||||
|
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Filter[]> {
|
||||||
|
return this.service.fetch();
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/tts-filter.service.spec.ts
Normal file
16
src/app/shared/services/tts-filter.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TtsFilterService } from './tts-filter.service';
|
||||||
|
|
||||||
|
describe('TtsFilterService', () => {
|
||||||
|
let service: TtsFilterService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(TtsFilterService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
55
src/app/shared/services/tts-filter.service.ts
Normal file
55
src/app/shared/services/tts-filter.service.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
|
import { map, Observable, of } from 'rxjs';
|
||||||
|
import EventService from './EventService';
|
||||||
|
import { Filter } from '../models/filter';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class TtsFilterService {
|
||||||
|
private readonly client = inject(HermesClientService);
|
||||||
|
private readonly events = inject(EventService);
|
||||||
|
private data: Filter[] = []
|
||||||
|
private loaded = false;
|
||||||
|
create$: Observable<any> | undefined;
|
||||||
|
update$: Observable<any> | undefined;
|
||||||
|
delete$: Observable<any> | undefined;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.create$ = this.client.filterByRequestType('create_tts_filter');
|
||||||
|
this.update$ = this.client.filterByRequestType('update_tts_filter');
|
||||||
|
this.delete$ = this.client.filterByRequestType('delete_tts_filter');
|
||||||
|
|
||||||
|
this.create$?.subscribe(d => this.data.push(d.data));
|
||||||
|
this.update$?.subscribe(d => {
|
||||||
|
const filter = this.data.find(r => r.id == d.data.id);
|
||||||
|
if (filter) {
|
||||||
|
filter.search = d.data.action_name;
|
||||||
|
filter.replace = d.data.redemption_id;
|
||||||
|
filter.flag = d.data.order;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.delete$?.subscribe(d => this.data = this.data.filter(r => r.id != d.request.data.id));
|
||||||
|
|
||||||
|
this.events.listen('tts_logoff', () => {
|
||||||
|
this.data = [];
|
||||||
|
this.loaded = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
if (this.loaded) {
|
||||||
|
return of(this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const $ = this.client.first(d => d.d.request.type == 'get_tts_word_filters')!.pipe(map(d => d.d.data));
|
||||||
|
$.subscribe(d => {
|
||||||
|
this.data = d;
|
||||||
|
this.loaded = true;
|
||||||
|
});
|
||||||
|
this.client.fetchFilters();
|
||||||
|
return $;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,55 @@
|
|||||||
<h2 mat-dialog-title>TTS Filter</h2>
|
<mat-card>
|
||||||
<mat-dialog-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="forms">
|
<h2 mat-dialog-title>TTS Filter</h2>
|
||||||
<div>
|
<mat-dialog-content>
|
||||||
<mat-form-field>
|
<form [formGroup]="forms">
|
||||||
<mat-label>Search</mat-label>
|
<div>
|
||||||
<input matInput cdkFocusInitial type="text" formControlName="search" />
|
<mat-form-field>
|
||||||
@if (forms.get('search')?.invalid && (forms.get('search')?.dirty || forms.get('search')?.touched)) {
|
<mat-label>Search</mat-label>
|
||||||
<div class="validation-error">Search is required.</div>
|
<input matInput cdkFocusInitial type="text" formControlName="search" />
|
||||||
|
@if (forms.get('search')?.invalid && (forms.get('search')?.dirty || forms.get('search')?.touched)) {
|
||||||
|
<small class="error">Search is required.</small>
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Replace</mat-label>
|
||||||
|
<input matInput formControlName="replace" />
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Regex Options</mat-label>
|
||||||
|
<mat-select multiple [formControl]="flagControl" [compareWith]="compare"
|
||||||
|
(selectionChange)="onSelectionChange($event)">
|
||||||
|
<mat-select-trigger>
|
||||||
|
{{optionsSelected[0] || ''}}
|
||||||
|
@if ((flagControl.value?.length || 0) > 1) {
|
||||||
|
<small class="additional-selection">
|
||||||
|
(+{{flagControl.value!.length - 1}})
|
||||||
|
</small>
|
||||||
|
}
|
||||||
|
</mat-select-trigger>
|
||||||
|
@for (option of regexOptions; track option) {
|
||||||
|
<mat-option [value]="option">{{option.name}}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
@if (errorMessage) {
|
||||||
|
<small class="error">{{errorMessage}}</small>
|
||||||
}
|
}
|
||||||
</mat-form-field>
|
</form>
|
||||||
</div>
|
</mat-dialog-content>
|
||||||
<div>
|
<mat-dialog-actions>
|
||||||
<mat-form-field>
|
<button
|
||||||
<mat-label>Replace</mat-label>
|
mat-button
|
||||||
<input matInput formControlName="replace" />
|
(click)="onCancelClick()">Cancel</button>
|
||||||
</mat-form-field>
|
<button
|
||||||
</div>
|
mat-button
|
||||||
</form>
|
(click)="onSaveClick()"
|
||||||
</mat-dialog-content>
|
[disabled]="!forms.dirty || forms.invalid || waitForResponse">Save</button>
|
||||||
<mat-dialog-actions>
|
</mat-dialog-actions>
|
||||||
<button mat-button (click)="onCancelClick()">Cancel</button>
|
</mat-card-content>
|
||||||
<button mat-button
|
</mat-card>
|
||||||
[mat-dialog-close]="onSaveClick()"
|
|
||||||
[disabled]="!forms.dirty || forms.invalid">Save</button>
|
|
||||||
</mat-dialog-actions>
|
|
@ -1,3 +1,3 @@
|
|||||||
.validation-error {
|
.error {
|
||||||
color: red($color: #000000);
|
color: #ba1a1a;
|
||||||
}
|
}
|
@ -1,10 +1,13 @@
|
|||||||
import { Component, inject, model } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogActions, MatDialogTitle, MatDialogContent } from '@angular/material/dialog';
|
||||||
import { Filter } from '../../shared/models/filter';
|
import { Filter } from '../../shared/models/filter';
|
||||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatSelectChange, MatSelectModule } from '@angular/material/select';
|
||||||
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tts-filter-item-edit',
|
selector: 'tts-filter-item-edit',
|
||||||
@ -12,39 +15,110 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
|
MatCardModule,
|
||||||
MatDialogActions,
|
MatDialogActions,
|
||||||
MatDialogClose,
|
|
||||||
MatDialogContent,
|
MatDialogContent,
|
||||||
MatDialogTitle,
|
MatDialogTitle,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
|
MatSelectModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
],
|
],
|
||||||
templateUrl: './filter-item-edit.component.html',
|
templateUrl: './filter-item-edit.component.html',
|
||||||
styleUrl: './filter-item-edit.component.scss'
|
styleUrl: './filter-item-edit.component.scss'
|
||||||
})
|
})
|
||||||
export class FilterItemEditComponent {
|
export class FilterItemEditComponent {
|
||||||
readonly dialogRef = inject(MatDialogRef<FilterItemEditComponent>);
|
private readonly client = inject(HermesClientService);
|
||||||
|
|
||||||
|
private readonly dialogRef = inject(MatDialogRef<FilterItemEditComponent>);
|
||||||
readonly data = inject<Filter>(MAT_DIALOG_DATA);
|
readonly data = inject<Filter>(MAT_DIALOG_DATA);
|
||||||
|
|
||||||
|
readonly regexOptions = [
|
||||||
|
{
|
||||||
|
name: 'Ignore Case',
|
||||||
|
flag: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Explicit Capture',
|
||||||
|
flag: 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ignore Pattern Whitespace',
|
||||||
|
flag: 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'No Backtracking',
|
||||||
|
flag: 1024
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
readonly searchControl = new FormControl(this.data.search, [Validators.required]);
|
||||||
|
readonly replaceControl = new FormControl(this.data.replace);
|
||||||
|
readonly flagControl = new FormControl<string[]>(this.optionsSelected);
|
||||||
readonly forms = new FormGroup({
|
readonly forms = new FormGroup({
|
||||||
search: new FormControl(this.data.search, [Validators.required]),
|
search: this.searchControl,
|
||||||
replace: new FormControl(this.data.replace),
|
replace: this.replaceControl,
|
||||||
flag: new FormControl(this.data.flag),
|
flag: this.flagControl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
waitForResponse: boolean = false;
|
||||||
|
errorMessage: string | undefined;
|
||||||
|
|
||||||
onSaveClick(): Filter|undefined {
|
|
||||||
if (this.forms.invalid) {
|
get optionsSelected() {
|
||||||
return undefined;
|
const flag = this.data.flag;
|
||||||
|
return this.regexOptions.filter(o => (flag & o.flag) > 0).map(o => o.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveClick(): void {
|
||||||
|
if (this.forms.invalid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.waitForResponse = true;
|
||||||
|
this.errorMessage = undefined;
|
||||||
|
|
||||||
|
const search = this.searchControl.value!;
|
||||||
|
const replace = this.replaceControl.value!;
|
||||||
|
const flag = this.data.flag;
|
||||||
|
|
||||||
|
if (!this.data.id) {
|
||||||
|
this.client.first(d => d.op == 4 && d.d.request.type == 'create_tts_filter' && d.d.data.search == search && d.d.data.replace == replace && d.d.data.flag == flag)
|
||||||
|
?.subscribe({
|
||||||
|
next: d => {
|
||||||
|
if (d.error)
|
||||||
|
this.errorMessage = d.error;
|
||||||
|
else
|
||||||
|
this.dialogRef.close(d.d.data);
|
||||||
|
},
|
||||||
|
error: () => this.waitForResponse = false,
|
||||||
|
complete: () => this.waitForResponse = false,
|
||||||
|
});
|
||||||
|
this.client.createTTSFilter(search, replace, flag);
|
||||||
|
} else {
|
||||||
|
this.client.first(d => d.op == 4 && d.d.request.type == 'update_tts_filter' && d.d.data.id == this.data.id && d.d.data.search == search && d.d.data.replace == replace && d.d.data.flag == flag)
|
||||||
|
?.subscribe({
|
||||||
|
next: d => {
|
||||||
|
if (d.error)
|
||||||
|
this.errorMessage = d.error;
|
||||||
|
else
|
||||||
|
this.dialogRef.close(d.d.data);
|
||||||
|
},
|
||||||
|
error: () => this.waitForResponse = false,
|
||||||
|
complete: () => this.waitForResponse = false,
|
||||||
|
});
|
||||||
|
this.client.updateTTSFilter(this.data.id, search, replace, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.search = this.forms.value.search ?? '';
|
|
||||||
this.data.replace = this.forms.value.replace ?? '';
|
|
||||||
this.data.flag = this.forms.value.flag ?? 0;
|
|
||||||
return this.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancelClick(): void {
|
onCancelClick(): void {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSelectionChange(event: MatSelectChange) {
|
||||||
|
this.data.flag = event.value.reduce((acc: number, option: any) => acc | option.flag, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(o: any, s: any) {
|
||||||
|
return o.flag == s || o.name == s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, EventEmitter, inject, Input, OnInit, Output, signal } from '@angular/core';
|
import { Component, EventEmitter, inject, Input, OnInit, Output } from '@angular/core';
|
||||||
import { Filter, FilterFlag } from '../../shared/models/filter';
|
import { Filter, FilterFlag } from '../../shared/models/filter';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
@ -9,14 +9,14 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tts-filter-item',
|
selector: 'tts-filter-item',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MatButtonModule, MatCardModule, MatMenuModule, MatIconModule],
|
imports: [MatButtonModule, MatCardModule, MatMenuModule, MatIconModule],
|
||||||
templateUrl: './filter-item.component.html',
|
templateUrl: './filter-item.component.html',
|
||||||
styleUrl: './filter-item.component.scss'
|
styleUrl: './filter-item.component.scss'
|
||||||
})
|
})
|
||||||
export class FilterItemComponent implements OnInit {
|
export class FilterItemComponent implements OnInit {
|
||||||
@Input() item: Filter = { id: "", user_id: "", search: "", replace: "", flag: FilterFlag.None, is_regex: false };
|
@Input() item: Filter = { id: "", user_id: "", search: "", replace: "", flag: FilterFlag.None };
|
||||||
@Output() onDelete = new EventEmitter<Filter>();
|
@Output() onDelete = new EventEmitter<Filter>();
|
||||||
readonly client = inject(HermesClientService);
|
readonly client = inject(HermesClientService);
|
||||||
readonly dialog = inject(MatDialog);
|
readonly dialog = inject(MatDialog);
|
||||||
@ -32,17 +32,14 @@ export class FilterItemComponent implements OnInit {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(FilterItemEditComponent, {
|
const dialogRef = this.dialog.open(FilterItemEditComponent, {
|
||||||
data: { id: this.item.id, search: this.item.search, replace: this.item.replace },
|
data: { id: this.item.id, search: this.item.search, replace: this.item.replace, flag: this.item.flag },
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result: Filter) => {
|
dialogRef.afterClosed().subscribe((result: Filter) => {
|
||||||
if (result !== undefined) {
|
if (result) {
|
||||||
this.client.first((d: any) => d.op == 4 && d.d.request.type == 'update_tts_filter' && d.d.data.id == this.item.id)
|
this.item.search = result.search;
|
||||||
?.subscribe(_ => {
|
this.item.replace = result.replace;
|
||||||
this.item.search = result.search;
|
this.item.flag = result.flag;
|
||||||
this.item.replace = result.replace;
|
|
||||||
});
|
|
||||||
this.client.updateTTSFilter(this.item.id, result.search, result.replace);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ div {
|
|||||||
ul.data {
|
ul.data {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -4,18 +4,17 @@ import { Filter } from '../../shared/models/filter';
|
|||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tts-filter-list',
|
selector: 'tts-filter-list',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [FilterItemComponent],
|
imports: [FilterItemComponent],
|
||||||
templateUrl: './filter-list.component.html',
|
templateUrl: './filter-list.component.html',
|
||||||
styleUrl: './filter-list.component.scss'
|
styleUrl: './filter-list.component.scss'
|
||||||
})
|
})
|
||||||
export class FilterListComponent {
|
export class FilterListComponent {
|
||||||
@Input() filters: Filter[] = [];
|
@Input() filters: Filter[] = [];
|
||||||
client = inject(HermesClientService);
|
client = inject(HermesClientService);
|
||||||
|
|
||||||
deleteFilter(e: any): void {
|
deleteFilter(e: any): void {
|
||||||
this.client.deleteTTSFilter(e.id);
|
this.client.deleteTTSFilter(e.id);
|
||||||
this.filters = this.filters.filter(f => f.id != e.id);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,22 +1,27 @@
|
|||||||
import { Component, inject, Inject, Input, OnDestroy, OnInit, PLATFORM_ID, signal } from '@angular/core';
|
import { Component, inject, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
|
||||||
import { FilterListComponent } from "../filter-list/filter-list.component";
|
import { FilterListComponent } from "../filter-list/filter-list.component";
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import { Filter } from '../../shared/models/filter';
|
import { Filter, FilterFlag } from '../../shared/models/filter';
|
||||||
import { isPlatformBrowser } from '@angular/common';
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
import { Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { FilterItemEditComponent } from '../filter-item-edit/filter-item-edit.component';
|
import { FilterItemEditComponent } from '../filter-item-edit/filter-item-edit.component';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { TtsFilterService } from '../../shared/services/tts-filter.service';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'filters',
|
selector: 'filters',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [FilterListComponent, MatButtonModule, MatIconModule],
|
imports: [FilterListComponent, MatButtonModule, MatIconModule],
|
||||||
templateUrl: './filters.component.html',
|
templateUrl: './filters.component.html',
|
||||||
styleUrl: './filters.component.scss'
|
styleUrl: './filters.component.scss'
|
||||||
})
|
})
|
||||||
export class FiltersComponent implements OnInit, OnDestroy {
|
export class FiltersComponent implements OnInit, OnDestroy {
|
||||||
|
private readonly filterService = inject(TtsFilterService);
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
private readonly subscriptions: Subscription[] = [];
|
||||||
private isBrowser: boolean;
|
private isBrowser: boolean;
|
||||||
readonly dialog = inject(MatDialog);
|
readonly dialog = inject(MatDialog);
|
||||||
items: Filter[];
|
items: Filter[];
|
||||||
@ -24,33 +29,45 @@ export class FiltersComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(private client: HermesClientService, private router: Router, @Inject(PLATFORM_ID) private platformId: Object) {
|
constructor(private client: HermesClientService, private router: Router, @Inject(PLATFORM_ID) private platformId: Object) {
|
||||||
this.isBrowser = isPlatformBrowser(this.platformId);
|
this.isBrowser = isPlatformBrowser(this.platformId);
|
||||||
|
this.items = [];
|
||||||
|
|
||||||
this.items = []
|
this.route.data.subscribe(data => {
|
||||||
this.client.subscribe(4, d => {
|
if (!data['filters'])
|
||||||
const type = d.request.type;
|
|
||||||
|
|
||||||
if (type == 'get_tts_word_filters') {
|
|
||||||
this.items = d.data;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (d.request.nounce == client.session_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (type == 'create_tts_filter') {
|
|
||||||
this.items = [d.data, ...this.items];
|
|
||||||
} else if (type == 'delete_tts_filter') {
|
|
||||||
this.items = this.items.filter(i => i.id != d.data.id);
|
|
||||||
} else if (type == 'update_tts_filter') {
|
|
||||||
const filter = this.items.find(f => f.id == d.data.id);
|
|
||||||
if (filter == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
this.items = [...data['filters']];
|
||||||
|
});
|
||||||
|
let subscription = this.filterService.create$?.subscribe(d => {
|
||||||
|
if (d.error || d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.items.push(d.data);
|
||||||
|
});
|
||||||
|
if (subscription)
|
||||||
|
this.subscriptions.push(subscription);
|
||||||
|
|
||||||
|
subscription = this.filterService.update$?.subscribe(d => {
|
||||||
|
if (d.error || d.request.nounce != null && d.request.nounce.startsWith(this.client.session_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const filter = this.items.find(f => f.id == d.data.id);
|
||||||
|
if (filter) {
|
||||||
filter.search = d.data.search;
|
filter.search = d.data.search;
|
||||||
filter.replace = d.data.replace;
|
filter.replace = d.data.replace;
|
||||||
filter.flag = d.data.flag || 0;
|
filter.flag = d.data.flag || 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.client.fetchFilters();
|
if (subscription)
|
||||||
|
this.subscriptions.push(subscription);
|
||||||
|
|
||||||
|
subscription = this.filterService.delete$?.subscribe(d => {
|
||||||
|
if (d.error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.items = this.items.filter(a => a.id != d.request.data.id);
|
||||||
|
});
|
||||||
|
if (subscription)
|
||||||
|
this.subscriptions.push(subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -64,21 +81,17 @@ export class FiltersComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
this.subscriptions.forEach(s => s.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog(): void {
|
openDialog(): void {
|
||||||
const dialogRef = this.dialog.open(FilterItemEditComponent, {
|
const dialogRef = this.dialog.open(FilterItemEditComponent, {
|
||||||
data: { search: '', replace: '' },
|
data: { id: '', user_id: '', search: '', replace: '', flag: FilterFlag.None },
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result: any) => {
|
dialogRef.afterClosed().subscribe((result: Filter) => {
|
||||||
if (result !== undefined) {
|
if (result)
|
||||||
this.client.first(d => d.op == 4 && d.d.request.type == 'create_tts_filter' && d.d.data.search == result.search && d.d.data.replace == result.replace)
|
this.items.push(result);
|
||||||
?.subscribe(d => {
|
|
||||||
this.items = [d.d.data, ...this.items];
|
|
||||||
});
|
|
||||||
this.client.createTTSFilter(result.search, result.replace);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user