Improved the code for handling policies.
This commit is contained in:
parent
f2c5178e82
commit
f4511157a5
@ -37,7 +37,8 @@
|
|||||||
[groups]="groups"
|
[groups]="groups"
|
||||||
[policies]="policies"
|
[policies]="policies"
|
||||||
[group]="group?.id" />
|
[group]="group?.id" />
|
||||||
<policy-table [policies]="policies" />
|
<policy-table [policies]="policies"
|
||||||
|
[groups]="groups"/>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
<mat-expansion-panel>
|
<mat-expansion-panel>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
|
import { Component, inject, input } from '@angular/core';
|
||||||
import { Policy } from '../../shared/models/policy';
|
import { Policy } from '../../shared/models/policy';
|
||||||
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
@ -17,28 +17,21 @@ import { Group } from '../../shared/models/group';
|
|||||||
})
|
})
|
||||||
export class PolicyAddButtonComponent {
|
export class PolicyAddButtonComponent {
|
||||||
private readonly dialog = inject(MatDialog);
|
private readonly dialog = inject(MatDialog);
|
||||||
@Input({ required: true }) policies: Policy[] = [];
|
|
||||||
@Input({ required: true }) groups: Group[] = [];
|
policies = input.required<Policy[]>();
|
||||||
@Input() group: string | undefined = undefined;
|
groups = input.required<Group[]>();
|
||||||
@Output() policy = new EventEmitter<Policy>();
|
group = input<string | undefined>();
|
||||||
|
|
||||||
|
|
||||||
openDialog(): void {
|
openDialog(): void {
|
||||||
const dialogRef = this.dialog.open(PolicyItemEditComponent, {
|
this.dialog.open(PolicyItemEditComponent, {
|
||||||
data: {
|
data: {
|
||||||
policies: this.policies,
|
policies: this.policies(),
|
||||||
groups: this.groups,
|
groups: this.groups(),
|
||||||
group_id: this.group,
|
group_id: this.group(),
|
||||||
groupDisabled: !!this.group,
|
groupDisabled: !!this.group(),
|
||||||
isNew: true,
|
isNew: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result: Policy) => {
|
|
||||||
if (!result)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.policy.emit(result);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,8 +7,11 @@
|
|||||||
[formControl]="policyControl"
|
[formControl]="policyControl"
|
||||||
[matAutocomplete]="auto" />
|
[matAutocomplete]="auto" />
|
||||||
<mat-autocomplete #auto="matAutocomplete">
|
<mat-autocomplete #auto="matAutocomplete">
|
||||||
@for (option of filteredPolicies | async; track option) {
|
@for (option of filteredPolicies | async; track option.path) {
|
||||||
<mat-option [value]="option">{{option}}</mat-option>
|
<mat-option [value]="option.path">
|
||||||
|
<p class="path">{{option.path}}</p>
|
||||||
|
<p class="description muted">{{option.description}}</p>
|
||||||
|
</mat-option>
|
||||||
}
|
}
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
@if (policyControl.invalid && (policyControl.dirty || policyControl.touched)) {
|
@if (policyControl.invalid && (policyControl.dirty || policyControl.touched)) {
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
.muted {
|
||||||
|
color: #999999
|
||||||
|
}
|
@ -4,9 +4,14 @@ import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angu
|
|||||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { map, Observable, startWith } from 'rxjs';
|
import { EMPTY, map, Observable, startWith } from 'rxjs';
|
||||||
|
|
||||||
const Policies = [
|
interface PolicyData {
|
||||||
|
path: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Policies: PolicyData[] = [
|
||||||
{ path: "tts", description: "Anything to do with TTS" },
|
{ path: "tts", description: "Anything to do with TTS" },
|
||||||
{ path: "tts.chat", description: "Anything to do with chat" },
|
{ path: "tts.chat", description: "Anything to do with chat" },
|
||||||
{ path: "tts.chat.bits.read", description: "To read chat messages with bits via TTS" },
|
{ path: "tts.chat.bits.read", description: "To read chat messages with bits via TTS" },
|
||||||
@ -43,14 +48,7 @@ const Policies = [
|
|||||||
export class PolicyDropdownComponent {
|
export class PolicyDropdownComponent {
|
||||||
@Input() policy: string | null = '';
|
@Input() policy: string | null = '';
|
||||||
@Input({ alias: 'control' }) policyControl = new FormControl('', [Validators.required]);
|
@Input({ alias: 'control' }) policyControl = new FormControl('', [Validators.required]);
|
||||||
filteredPolicies: Observable<string[]>;
|
filteredPolicies: Observable<PolicyData[]> = EMPTY;
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.filteredPolicies = this.policyControl.valueChanges.pipe(
|
|
||||||
startWith(''),
|
|
||||||
map(value => this._filter(value || '')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.policyControl.setValue(this.policy);
|
this.policyControl.setValue(this.policy);
|
||||||
@ -60,13 +58,12 @@ export class PolicyDropdownComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filter(value: string): string[] {
|
private _filter(value: string): PolicyData[] {
|
||||||
const filterValue = value.toLowerCase();
|
const filterValue = value.toLowerCase();
|
||||||
const names = Policies.map(p => p.path);
|
if (Policies.map(p => p.path).includes(filterValue)) {
|
||||||
if (names.includes(filterValue)) {
|
return Policies;
|
||||||
return names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return names.filter(option => option.toLowerCase().includes(filterValue));
|
return Policies.filter(option => option.path.toLowerCase().includes(filterValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<table mat-table
|
<table mat-table
|
||||||
[dataSource]="policies"
|
[dataSource]="policies()"
|
||||||
class="mat-elevation-z8">
|
class="mat-elevation-z8">
|
||||||
<ng-container matColumnDef="path">
|
<ng-container matColumnDef="path">
|
||||||
<th mat-header-cell
|
<th mat-header-cell
|
||||||
|
@ -1,79 +1,48 @@
|
|||||||
import { AfterViewInit, Component, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from '@angular/core';
|
import { Component, inject, input, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
import { MatTable, MatTableModule } from '@angular/material/table';
|
import { MatTable, MatTableModule } from '@angular/material/table';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import EventService from '../../shared/services/EventService';
|
|
||||||
import { Policy } from '../../shared/models/policy';
|
import { Policy } from '../../shared/models/policy';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
||||||
import { Group } from '../../shared/models/group';
|
import { Group } from '../../shared/models/group';
|
||||||
|
import PolicyService from '../../shared/services/policy.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'policy-table',
|
selector: 'policy-table',
|
||||||
imports: [FormsModule, MatButtonModule, MatTableModule, MatIconModule],
|
imports: [
|
||||||
|
FormsModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatIconModule,
|
||||||
|
],
|
||||||
templateUrl: './policy-table.component.html',
|
templateUrl: './policy-table.component.html',
|
||||||
styleUrl: './policy-table.component.scss'
|
styleUrl: './policy-table.component.scss'
|
||||||
})
|
})
|
||||||
export class PolicyTableComponent implements OnInit, OnDestroy, AfterViewInit {
|
export class PolicyTableComponent implements OnInit, OnDestroy {
|
||||||
private readonly route = inject(ActivatedRoute);
|
private readonly client = inject(HermesClientService);
|
||||||
private readonly hermes = inject(HermesClientService);
|
private readonly policyService = inject(PolicyService);
|
||||||
private readonly events = inject(EventService);
|
|
||||||
private readonly dialog = inject(MatDialog);
|
private readonly dialog = inject(MatDialog);
|
||||||
|
|
||||||
@Input() policies: Policy[] = [];
|
policies = input.required<Policy[]>();
|
||||||
|
groups = input.required<Group[]>();
|
||||||
|
|
||||||
@ViewChild(MatTable) table: MatTable<Policy>;
|
@ViewChild(MatTable) table: MatTable<Policy>;
|
||||||
|
|
||||||
readonly displayedColumns = ['path', 'group', 'usage', 'span', 'actions'];
|
readonly displayedColumns = ['path', 'group', 'usage', 'span', 'actions'];
|
||||||
private readonly _subscriptions: any[] = [];
|
private readonly _subscriptions: any[] = [];
|
||||||
|
|
||||||
groups: Group[] = [];
|
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = {} as MatTable<Policy>;
|
this.table = {} as MatTable<Policy>;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.route.data.subscribe(r => {
|
this._subscriptions.push(this.policyService.create$?.subscribe(_ => this.table.renderRows()));
|
||||||
this.groups = [...r['groups']];
|
this._subscriptions.push(this.policyService.update$?.subscribe(_ => this.table.renderRows()));
|
||||||
});
|
this._subscriptions.push(this.policyService.delete$?.subscribe(_ => this.table.renderRows()));
|
||||||
|
|
||||||
this._subscriptions.push(this.events.listen('addPolicy', (payload) => {
|
|
||||||
if (!payload || this.policies.map(p => p.path).includes(payload))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.policies.push(payload);
|
|
||||||
this.table.renderRows();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._subscriptions.push(this.hermes.subscribeToRequests('create_policy', response => {
|
|
||||||
const policy = this.policies.find(p => p.path == response.data.path);
|
|
||||||
if (policy == null) {
|
|
||||||
this.policies.push(response.data);
|
|
||||||
}
|
|
||||||
this.table.renderRows();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._subscriptions.push(this.hermes.subscribeToRequests('update_policy', response => {
|
|
||||||
const policy = this.policies.find(p => p.id == response.data.id);
|
|
||||||
if (policy != null) {
|
|
||||||
policy.id = response.data.id;
|
|
||||||
policy.group_id = response.data.group_id;
|
|
||||||
}
|
|
||||||
this.table.renderRows();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._subscriptions.push(this.hermes.subscribeToRequests('delete_policy', response => {
|
|
||||||
this.policies = this.policies.filter(p => p.id != response.request.data.id);
|
|
||||||
this.table.renderRows();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
|
||||||
this.table.renderRows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -81,33 +50,23 @@ export class PolicyTableComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete(policy: Policy) {
|
delete(policy: Policy) {
|
||||||
this.hermes.deletePolicy(policy.id);
|
this.client.deletePolicy(policy.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
edit(policy: Policy) {
|
edit(policy: Policy) {
|
||||||
const dialogRef = this.dialog.open(PolicyItemEditComponent, {
|
this.dialog.open(PolicyItemEditComponent, {
|
||||||
data: {
|
data: {
|
||||||
policies: this.policies,
|
policies: this.policies(),
|
||||||
groups: this.groups,
|
groups: this.groups(),
|
||||||
policy_id: policy.id,
|
policy_id: policy.id,
|
||||||
group_id: policy.group_id,
|
group_id: policy.group_id,
|
||||||
groupDisabled: true,
|
groupDisabled: true,
|
||||||
isNew: false,
|
isNew: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((result: Policy) => {
|
|
||||||
if (!result)
|
|
||||||
return;
|
|
||||||
|
|
||||||
policy.group_id = result.group_id;
|
|
||||||
policy.path = result.path;
|
|
||||||
policy.usage = result.usage;
|
|
||||||
policy.span = result.span;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getGroupById(group_id: string) {
|
getGroupById(group_id: string) {
|
||||||
return this.groups.find((g: Group) => g.id == group_id);
|
return this.groups().find((g: Group) => g.id == group_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
<h4>Policies</h4>
|
<h4>Policies</h4>
|
||||||
<div class="add">
|
<div class="add">
|
||||||
<policy-add-button [policies]="policies"
|
<policy-add-button [policies]="policies"
|
||||||
[groups]="groups"
|
[groups]="groups" />
|
||||||
(policy)="addPolicy($event)" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<policy-table [policies]="policies" />
|
<policy-table [policies]="policies"
|
||||||
|
[groups]="groups" />
|
||||||
</div>
|
</div>
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject, OnDestroy } from '@angular/core';
|
||||||
import { PolicyTableComponent } from "../policy-table/policy-table.component";
|
import { PolicyTableComponent } from "../policy-table/policy-table.component";
|
||||||
import { Policy } from '../../shared/models/policy';
|
import { Policy } from '../../shared/models/policy';
|
||||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||||
@ -6,43 +6,55 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { PolicyAddButtonComponent } from "../policy-add-button/policy-add-button.component";
|
import { PolicyAddButtonComponent } from "../policy-add-button/policy-add-button.component";
|
||||||
import { Group } from '../../shared/models/group';
|
import { Group } from '../../shared/models/group';
|
||||||
|
import PolicyService from '../../shared/services/policy.service';
|
||||||
|
import GroupService from '../../shared/services/group.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'policy',
|
selector: 'policy',
|
||||||
imports: [MatButtonModule, MatIconModule, PolicyTableComponent, RouterModule, PolicyAddButtonComponent],
|
imports: [
|
||||||
|
MatButtonModule,
|
||||||
|
MatIconModule,
|
||||||
|
PolicyTableComponent,
|
||||||
|
RouterModule,
|
||||||
|
PolicyAddButtonComponent,
|
||||||
|
],
|
||||||
templateUrl: './policy.component.html',
|
templateUrl: './policy.component.html',
|
||||||
styleUrl: './policy.component.scss'
|
styleUrl: './policy.component.scss'
|
||||||
})
|
})
|
||||||
export class PolicyComponent {
|
export class PolicyComponent implements OnDestroy {
|
||||||
private readonly route = inject(ActivatedRoute);
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
|
||||||
|
private readonly policyService = inject(PolicyService);
|
||||||
|
private readonly groupService = inject(GroupService);
|
||||||
|
|
||||||
|
private readonly _subscriptions: any[] = [];
|
||||||
private _policies: Policy[] = [];
|
private _policies: Policy[] = [];
|
||||||
groups: Group[] = [];
|
private _groups: Group[] = [];
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.route.data.subscribe((data) => {
|
this.route.data.subscribe((data) => {
|
||||||
const policies = [...data['policies']];
|
this._policies = data['policies'];
|
||||||
policies.sort(this.compare);
|
this._groups = data['groups'];
|
||||||
this._policies = policies;
|
|
||||||
|
|
||||||
this.groups = [...data['groups']];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._subscriptions.push(this.policyService.delete$?.subscribe(_ =>
|
||||||
|
this.policyService.fetch().subscribe(p => this._policies = p)));
|
||||||
|
|
||||||
|
this._subscriptions.push(this.groupService.deleteGroup$?.subscribe(_ =>
|
||||||
|
this.groupService.fetch().subscribe(g => this._groups = g.groups)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this._subscriptions.filter(s => !!s).forEach(s => s.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
get policies() {
|
get policies() {
|
||||||
return this._policies;
|
return this._policies;
|
||||||
}
|
}
|
||||||
|
|
||||||
addPolicy(policy: Policy) {
|
get groups() {
|
||||||
let index = -1;
|
return this._groups;
|
||||||
for (let i = 0; i < this._policies.length; i++) {
|
|
||||||
const comp = this.compare(policy, this._policies[i]);
|
|
||||||
if (comp < 0) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._policies.splice(index >= 0 ? index : this._policies.length, 0, policy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compare(a: Policy, b: Policy) {
|
compare(a: Policy, b: Policy) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user