Added groups - missing user management. Fixed several issues.
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { PolicyComponent } from './policy/policy.component';
|
||||
import { PolicyTableComponent } from './policy-table/policy-table.component';
|
||||
import { PolicyAddFormComponent } from './policy-add-form/policy-add-form.component';
|
||||
import { PolicyItemEditComponent } from './policy-item-edit/policy-item-edit.component';
|
||||
import { PolicyAddButtonComponent } from './policy-add-button/policy-add-button.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
PolicyComponent, PolicyTableComponent, PolicyAddFormComponent
|
||||
PolicyComponent,
|
||||
PolicyTableComponent,
|
||||
PolicyAddButtonComponent,
|
||||
PolicyItemEditComponent,
|
||||
]
|
||||
})
|
||||
export class PoliciesModule { }
|
||||
@@ -0,0 +1,4 @@
|
||||
<button mat-button (click)="openDialog()">
|
||||
<mat-icon>add</mat-icon>
|
||||
Add a policy
|
||||
</button>
|
||||
@@ -0,0 +1,3 @@
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PolicyAddButtonComponent } from './policy-add-button.component';
|
||||
|
||||
describe('PolicyAddButtonComponent', () => {
|
||||
let component: PolicyAddButtonComponent;
|
||||
let fixture: ComponentFixture<PolicyAddButtonComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PolicyAddButtonComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PolicyAddButtonComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
|
||||
import { Policy } from '../../shared/models/policy';
|
||||
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { Group } from '../../shared/models/group';
|
||||
|
||||
@Component({
|
||||
selector: 'policy-add-button',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
],
|
||||
templateUrl: './policy-add-button.component.html',
|
||||
styleUrl: './policy-add-button.component.scss'
|
||||
})
|
||||
export class PolicyAddButtonComponent {
|
||||
private readonly dialog = inject(MatDialog);
|
||||
@Input({ required: true }) policies: Policy[] = [];
|
||||
@Input({ required: true }) groups: Group[] = [];
|
||||
@Input() group: string|undefined = undefined;
|
||||
@Output() policy = new EventEmitter<Policy>();
|
||||
|
||||
|
||||
openDialog(): void {
|
||||
const dialogRef = this.dialog.open(PolicyItemEditComponent, {
|
||||
data: {
|
||||
policies: this.policies,
|
||||
groups: this.groups,
|
||||
group_id: this.group,
|
||||
groupDisabled: !!this.group,
|
||||
isNew: true,
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result: Policy) => {
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
this.policy.emit(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{isNew ? 'Add' : 'Edit'}} Policy</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<group-dropdown
|
||||
ngDefaultControl
|
||||
[formControl]="groupControl"
|
||||
[groups]="data.groups"
|
||||
[group]="data.group_id"
|
||||
[groupDisabled]="data.groupDisabled"
|
||||
[errorMessages]="groupErrorMessages" />
|
||||
<mat-form-field>
|
||||
<mat-label>Path</mat-label>
|
||||
<input matInput placeholder="Path" [formControl]="pathControl" />
|
||||
@if (pathControl.invalid && (pathControl.dirty || pathControl.touched)) {
|
||||
@if (pathControl.hasError('required')) {
|
||||
<small class="error">This field is required.</small>
|
||||
}
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Usage</mat-label>
|
||||
<input matInput type="number" [formControl]="usageControl" />
|
||||
@if (usageControl.invalid && (usageControl.dirty || usageControl.touched)) {
|
||||
@if (usageControl.hasError('required')) {
|
||||
<small class="error">This field is required.</small>
|
||||
}
|
||||
@if (usageControl.hasError('min')) {
|
||||
<small class="error">The value needs to be positive.</small>
|
||||
}
|
||||
@if (usageControl.hasError('max')) {
|
||||
<small class="error">The value needs to be lower than 100.</small>
|
||||
}
|
||||
@if (usageControl.hasError('integer')) {
|
||||
<small class="error">The value needs to be an integer.</small>
|
||||
}
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Span</mat-label>
|
||||
<input matInput type="number" [formControl]="spanControl" />
|
||||
@if (spanControl.invalid && (spanControl.dirty || spanControl.touched)) {
|
||||
@if (spanControl.hasError('required')) {
|
||||
<small class="error">This field is required.</small>
|
||||
}
|
||||
@if (spanControl.hasError('min')) {
|
||||
<small class="error">The value needs to be at least 1000.</small>
|
||||
}
|
||||
@if (spanControl.hasError('max')) {
|
||||
<small class="error">The value needs to be lower than 86401.</small>
|
||||
}
|
||||
@if (spanControl.hasError('integer')) {
|
||||
<small class="error">The value needs to be an integer.</small>
|
||||
}
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
@if (isNew) {
|
||||
<button mat-button (click)="save()">
|
||||
<mat-icon>add</mat-icon>Add
|
||||
</button>
|
||||
} @else {
|
||||
<button mat-button (click)="save()">
|
||||
<mat-icon>save</mat-icon>Save
|
||||
</button>
|
||||
}
|
||||
<button mat-button (click)="dialogRef.close()">
|
||||
<mat-icon>cancel</mat-icon>Cancel
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,10 @@
|
||||
.mat-mdc-card-content {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-auto-flow: row dense;
|
||||
grid-gap: 0 1em;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ba1a1a;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PolicyItemEditComponent } from './policy-item-edit.component';
|
||||
|
||||
describe('PolicyItemEditComponent', () => {
|
||||
let component: PolicyItemEditComponent;
|
||||
let fixture: ComponentFixture<PolicyItemEditComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PolicyItemEditComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PolicyItemEditComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { GroupDropdownComponent } from '../../groups/group-dropdown/group-dropdown.component';
|
||||
import { Group } from '../../shared/models/group';
|
||||
import { Policy } from '../../shared/models/policy';
|
||||
|
||||
@Component({
|
||||
selector: 'policy-item-edit',
|
||||
imports: [
|
||||
GroupDropdownComponent,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
templateUrl: './policy-item-edit.component.html',
|
||||
styleUrl: './policy-item-edit.component.scss'
|
||||
})
|
||||
export class PolicyItemEditComponent implements OnInit {
|
||||
private readonly client = inject(HermesClientService);
|
||||
readonly data = inject(MAT_DIALOG_DATA);
|
||||
readonly dialogRef = inject(MatDialogRef<PolicyItemEditComponent>);
|
||||
|
||||
readonly groupControl = new FormControl<Group | string | undefined>(undefined, [Validators.required]);
|
||||
readonly pathControl = new FormControl('', [Validators.required]);
|
||||
readonly usageControl = new FormControl(1, [Validators.required, Validators.min(1), Validators.max(99)]);
|
||||
readonly spanControl = new FormControl(5000, [Validators.required, Validators.min(1000), Validators.max(86400)]);
|
||||
|
||||
readonly groupErrorMessages = {
|
||||
'required': 'This field is required.'
|
||||
};
|
||||
|
||||
readonly formGroup = new FormGroup({
|
||||
group: this.groupControl,
|
||||
path: this.pathControl,
|
||||
usage: this.usageControl,
|
||||
span: this.spanControl,
|
||||
});
|
||||
|
||||
isNew: boolean = false;
|
||||
waitForResponse: boolean = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.isNew = this.data.isNew;
|
||||
|
||||
if (!this.data.policy_id)
|
||||
return;
|
||||
|
||||
const policy = this.data.policies.find((p: Policy) => p.id == this.data.policy_id);
|
||||
if (!policy)
|
||||
return;
|
||||
|
||||
this.groupControl.setValue(policy.group_id);
|
||||
this.pathControl.setValue(policy.path);
|
||||
this.usageControl.setValue(policy.usage);
|
||||
this.spanControl.setValue(policy.span);
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.formGroup.invalid || this.waitForResponse)
|
||||
return;
|
||||
|
||||
this.waitForResponse = true;
|
||||
const group_id = (this.groupControl.value as Group)!.id;
|
||||
const path = this.pathControl.value!;
|
||||
const usage = this.usageControl.value!;
|
||||
const span = this.spanControl.value!;
|
||||
|
||||
if (this.isNew) {
|
||||
this.client.first((d: any) => d.op == 4 && d.d.request.type == 'create_policy' && d.d.data.group_id == group_id && d.d.data.path == path && d.d.data.usage == usage && d.d.data.span == span)
|
||||
.subscribe({
|
||||
next: (d) => this.dialogRef.close(d.d.data),
|
||||
error: () => this.waitForResponse = false,
|
||||
complete: () => this.waitForResponse = false,
|
||||
});
|
||||
this.client.createPolicy(group_id, path, usage, span);
|
||||
} else {
|
||||
this.client.first((d: any) => d.op == 4 && d.d.request.type == 'update_policy' && d.d.data.id == this.data.policy_id && d.d.data.group_id == group_id && d.d.data.path == path && d.d.data.usage == usage && d.d.data.span == span)
|
||||
.subscribe({
|
||||
next: (d) => this.dialogRef.close(d.d.data),
|
||||
error: () => this.waitForResponse = false,
|
||||
complete: () => this.waitForResponse = false,
|
||||
});
|
||||
this.client.updatePolicy(this.data.policy_id, group_id, path, usage, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +1,40 @@
|
||||
<table mat-table [dataSource]="policies" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="path">
|
||||
<th mat-header-cell *matHeaderCellDef>Path</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
{{policy.path}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="path">
|
||||
<th mat-header-cell *matHeaderCellDef>Path</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
{{policy.path}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="group">
|
||||
<th mat-header-cell *matHeaderCellDef>Group</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
@if (policy.editing) {
|
||||
<input type="text" [(ngModel)]="policy.temp_group_name" />
|
||||
}
|
||||
@if (!policy.editing && groups[policy.group_id]) {
|
||||
{{groups[policy.group_id].name}}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="group">
|
||||
<th mat-header-cell *matHeaderCellDef>Group</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
{{getGroupById(policy.group_id)?.name || '\<unknown group\>'}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="usage">
|
||||
<th mat-header-cell *matHeaderCellDef>Usage Rate</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
@if (policy.editing) {
|
||||
<input type="number" [(ngModel)]="policy.usage" (keypress)="($event.charCode >= 48 && $event.charCode < 58)" />
|
||||
}
|
||||
@if (!policy.editing) {
|
||||
{{policy.usage}}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="usage">
|
||||
<th mat-header-cell *matHeaderCellDef>Usage Rate</th>
|
||||
<td mat-cell class="center" *matCellDef="let policy">
|
||||
{{policy.usage}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="span">
|
||||
<th mat-header-cell *matHeaderCellDef>Span (ms)</th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
@if (policy.editing) {
|
||||
<input type="number" [(ngModel)]="policy.span" (keypress)="($event.charCode >= 48 && $event.charCode < 58)" />
|
||||
}
|
||||
@if (!policy.editing) {
|
||||
{{policy.span}}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="span">
|
||||
<th mat-header-cell *matHeaderCellDef>Span (ms)</th>
|
||||
<td mat-cell class="center" *matCellDef="let policy">
|
||||
{{policy.span}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
@if (!policy.editing) {
|
||||
<button mat-mini-fab (click)="edit(policy)"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-mini-fab (click)="delete(policy)"><mat-icon>delete</mat-icon></button>
|
||||
}
|
||||
@if (policy.editing) {
|
||||
<button mat-mini-fab (click)="save(policy)"><mat-icon>save</mat-icon></button>
|
||||
<button mat-mini-fab (click)="cancel(policy)"><mat-icon>cancel</mat-icon></button>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let policy">
|
||||
<button mat-button (click)="edit(policy)"><mat-icon>edit</mat-icon>Edit</button>
|
||||
<button mat-button class="delete" (click)="delete(policy)"><mat-icon>delete</mat-icon>Delete</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,12 @@
|
||||
table {
|
||||
border-radius: 15px;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.delete {
|
||||
color: red;
|
||||
}
|
||||
|
||||
button ~ button {
|
||||
margin-left: 1em;
|
||||
}
|
||||
@@ -1,119 +1,83 @@
|
||||
import { Component, ElementRef, Input, isDevMode, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { AfterViewInit, Component, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { MatTable, MatTableModule } from '@angular/material/table';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import EventService from '../../shared/services/EventService';
|
||||
import { Policy } from '../../shared/models/policy';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { PolicyItemEditComponent } from '../policy-item-edit/policy-item-edit.component';
|
||||
import { Group } from '../../shared/models/group';
|
||||
|
||||
@Component({
|
||||
selector: 'policy-table',
|
||||
imports: [FormsModule, MatTableModule, MatIconModule],
|
||||
imports: [FormsModule, MatButtonModule, MatTableModule, MatIconModule],
|
||||
templateUrl: './policy-table.component.html',
|
||||
styleUrl: './policy-table.component.scss'
|
||||
})
|
||||
export class PolicyTableComponent implements OnInit, OnDestroy {
|
||||
@Input() policies: Policy[] = []
|
||||
displayedColumns = ['path', 'group', 'usage', 'span', 'actions']
|
||||
groups: { [id: string]: { id: string, name: string, priority: number } }
|
||||
private readonly _subscriptions: Subscription[] = [];
|
||||
export class PolicyTableComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly hermes = inject(HermesClientService);
|
||||
private readonly events = inject(EventService);
|
||||
private readonly dialog = inject(MatDialog);
|
||||
|
||||
@Input() policies: Policy[] = [];
|
||||
@ViewChild(MatTable) table: MatTable<Policy>;
|
||||
private subscription: Subscription | undefined;
|
||||
|
||||
constructor(private events: EventService, private hermes: HermesClientService) {
|
||||
readonly displayedColumns = ['path', 'group', 'usage', 'span', 'actions'];
|
||||
private readonly _subscriptions: any[] = [];
|
||||
|
||||
groups: Group[] = [];
|
||||
|
||||
|
||||
constructor() {
|
||||
this.table = {} as MatTable<Policy>;
|
||||
this.groups = {};
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._subscriptions.push(this.events.listen('addPolicy', (payload) => {
|
||||
if (!payload)
|
||||
return;
|
||||
if (this.policies.map(p => p.path).includes(payload)) {
|
||||
return;
|
||||
}
|
||||
this.route.data.subscribe(r => {
|
||||
this.groups = [...r['groups']];
|
||||
});
|
||||
|
||||
this.policies.push(new Policy("", "", payload, 1, 5000, "", true, true));
|
||||
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();
|
||||
}));
|
||||
|
||||
const subscription = this.hermes.subscribe(4, (response: any) => {
|
||||
if (response.request.type == "get_policies") {
|
||||
for (let policy of response.data) {
|
||||
this.policies.push(new Policy(policy.id, policy.group_id, policy.path, policy.usage, policy.span, "", false, false));
|
||||
}
|
||||
this.table.renderRows();
|
||||
} else if (response.request.type == "create_policy") {
|
||||
const policy = this.policies.find(p => this.groups[response.data.group_id].name == p.temp_group_name && p.path == response.data.path);
|
||||
if (policy == null) {
|
||||
this.policies.push(new Policy(response.data.id, response.data.group_id, response.data.path, response.data.usage, response.data.span));
|
||||
} else {
|
||||
policy.id = response.data.id;
|
||||
policy.group_id = response.data.group_id;
|
||||
policy.editing = false;
|
||||
policy.isNew = false;
|
||||
}
|
||||
this.table.renderRows();
|
||||
} else if (response.request.type == "update_policy") {
|
||||
const policy = this.policies.find(p => p.id == response.data.id);
|
||||
if (policy == null) {
|
||||
this.policies.push(new Policy(response.data.id, response.data.group_id, response.data.path, response.data.usage, response.data.span));
|
||||
} else {
|
||||
policy.id = response.data.id;
|
||||
policy.group_id = response.data.group_id;
|
||||
policy.editing = false;
|
||||
policy.isNew = false;
|
||||
}
|
||||
this.table.renderRows();
|
||||
} else if (response.request.type == "delete_policy") {
|
||||
const policy = this.policies.find(p => p.id == response.request.data.id);
|
||||
if (!policy) {
|
||||
return;
|
||||
}
|
||||
const index = this.policies.indexOf(policy);
|
||||
if (index >= 0) {
|
||||
this.policies.splice(index, 1);
|
||||
this.table.renderRows();
|
||||
}
|
||||
} else if (response.request.type == "get_permissions") {
|
||||
this.groups = Object.assign({}, ...response.data.groups.map((g: any) => ({ [g.id]: g })));
|
||||
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();
|
||||
}));
|
||||
|
||||
if (subscription) {
|
||||
this._subscriptions.push(subscription);
|
||||
}
|
||||
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.hermes.fetchPolicies();
|
||||
this.hermes.fetchPermissionsAndGroups();
|
||||
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 {
|
||||
if (this._subscriptions.length > 0)
|
||||
this._subscriptions.forEach(s => s.unsubscribe());
|
||||
}
|
||||
|
||||
cancel(policy: Policy) {
|
||||
if (!policy.editing)
|
||||
return;
|
||||
|
||||
if (policy.isNew) {
|
||||
const index = this.policies.indexOf(policy);
|
||||
if (index >= 0) {
|
||||
this.policies.splice(index, 1);
|
||||
this.table.renderRows();
|
||||
}
|
||||
} else {
|
||||
policy.path = policy.old_path ?? '';
|
||||
policy.usage = policy.old_usage ?? 1;
|
||||
policy.span = policy.old_span ?? 5000;
|
||||
policy.old_path = undefined;
|
||||
policy.old_span = undefined;
|
||||
policy.old_usage = undefined;
|
||||
policy.editing = false;
|
||||
}
|
||||
this._subscriptions.filter(s => !!s).forEach(s => s.unsubscribe());
|
||||
}
|
||||
|
||||
delete(policy: Policy) {
|
||||
@@ -121,62 +85,29 @@ export class PolicyTableComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
edit(policy: Policy) {
|
||||
policy.old_path = policy.path;
|
||||
policy.old_span = policy.span;
|
||||
policy.old_usage = policy.usage;
|
||||
policy.temp_group_name = this.groups[policy.group_id].name
|
||||
policy.editing = true;
|
||||
}
|
||||
|
||||
save(policy: Policy) {
|
||||
if (!policy.temp_group_name) {
|
||||
console.log('group must be valid.');
|
||||
return;
|
||||
}
|
||||
const group = Object.values(this.groups).find(g => g.name == policy.temp_group_name);
|
||||
if (group == null) {
|
||||
console.log('group does not exist.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (policy.isNew) {
|
||||
const match = this.policies.find(p => p.group_id == group.id && p.path == policy.path);
|
||||
if (match) {
|
||||
console.log('policy already exists');
|
||||
return;
|
||||
const dialogRef = this.dialog.open(PolicyItemEditComponent, {
|
||||
data: {
|
||||
policies: this.policies,
|
||||
groups: this.groups,
|
||||
policy_id: policy.id,
|
||||
group_id: policy.group_id,
|
||||
groupDisabled: true,
|
||||
isNew: false,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isNaN(policy.usage)) {
|
||||
console.log('usage must be a whole number.');
|
||||
return;
|
||||
}
|
||||
if (policy.usage < 1 || policy.usage > 99) {
|
||||
console.error('usage must be between 1 and 99.');
|
||||
return;
|
||||
}
|
||||
if (policy.usage % 1.0 != 0) {
|
||||
console.error('usage must be a whole number.');
|
||||
return;
|
||||
}
|
||||
dialogRef.afterClosed().subscribe((result: Policy) => {
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
if (isNaN(policy.span)) {
|
||||
console.log('span must be a whole number.');
|
||||
return;
|
||||
}
|
||||
if (policy.span < 1000 || policy.span > 1800000) {
|
||||
console.error('span must be between 1 and 1800000.');
|
||||
return;
|
||||
}
|
||||
if (policy.span % 1.0 != 0) {
|
||||
console.error('span must be a whole number.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (policy.isNew) {
|
||||
this.hermes.createPolicy(group.id, policy.path, policy.usage, policy.span);
|
||||
} else {
|
||||
this.hermes.updatePolicy(policy.id, group.id, policy.path, policy.usage, policy.span);
|
||||
}
|
||||
policy.group_id = result.group_id;
|
||||
policy.path = result.path;
|
||||
policy.usage = result.usage;
|
||||
policy.span = result.span;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getGroupById(group_id: string) {
|
||||
return this.groups.find((g: Group) => g.id == group_id);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<h4>Policies</h4>
|
||||
<div>
|
||||
<policy-add-form />
|
||||
<div class="add">
|
||||
<policy-add-button [policies]="policies" [groups]="groups" (policy)="addPolicy($event)" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<policy-table [policies]="policies" />
|
||||
<policy-table [policies]="policies" />
|
||||
</div>
|
||||
@@ -1,3 +1,9 @@
|
||||
h4 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 2em;
|
||||
margin: 1em 2em 2em;
|
||||
}
|
||||
@@ -1,42 +1,51 @@
|
||||
import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
|
||||
import { PolicyAddFormComponent } from "../policy-add-form/policy-add-form.component";
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { PolicyTableComponent } from "../policy-table/policy-table.component";
|
||||
import { Policy, PolicyScope } from '../../shared/models/policy';
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { Policy } from '../../shared/models/policy';
|
||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { PolicyAddButtonComponent } from "../policy-add-button/policy-add-button.component";
|
||||
import { Group } from '../../shared/models/group';
|
||||
|
||||
@Component({
|
||||
selector: 'policy',
|
||||
imports: [RouterModule, PolicyAddFormComponent, PolicyTableComponent],
|
||||
templateUrl: './policy.component.html',
|
||||
styleUrl: './policy.component.scss'
|
||||
selector: 'policy',
|
||||
imports: [MatButtonModule, MatIconModule, PolicyTableComponent, RouterModule, PolicyAddButtonComponent],
|
||||
templateUrl: './policy.component.html',
|
||||
styleUrl: './policy.component.scss'
|
||||
})
|
||||
export class PolicyComponent implements OnInit, OnDestroy {
|
||||
private isBrowser: boolean;
|
||||
items: Policy[];
|
||||
export class PolicyComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private _policies: Policy[] = [];
|
||||
groups: Group[] = [];
|
||||
|
||||
|
||||
constructor(private client: HermesClientService, private router: Router, @Inject(PLATFORM_ID) private platformId: Object) {
|
||||
this.isBrowser = isPlatformBrowser(this.platformId)
|
||||
constructor() {
|
||||
this.route.data.subscribe((data) => {
|
||||
const policies = [...data['policies']];
|
||||
policies.sort(this.compare);
|
||||
this._policies = policies;
|
||||
|
||||
this.items = []
|
||||
this.groups = [...data['groups']];
|
||||
});
|
||||
}
|
||||
|
||||
get policies() {
|
||||
return this._policies;
|
||||
}
|
||||
|
||||
addPolicy(policy: Policy) {
|
||||
let index = -1;
|
||||
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);
|
||||
}
|
||||
|
||||
get policies() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.isBrowser)
|
||||
return;
|
||||
|
||||
if (!this.client.logged_in) {
|
||||
this.router.navigate(["tts-login"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
}
|
||||
compare(a: Policy, b: Policy) {
|
||||
return a.path.localeCompare(b.path);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user