Simplify PolicyInstanceComponent
Change-Id: I56357272cf4a1f206184b090b6cbcfbe262d7f41
Issue-ID: NONRTRIC-472
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.html b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.html
index 8c9f5c5..e6d483f 100644
--- a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.html
+++ b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.html
@@ -27,7 +27,7 @@
</button>
</div>
-<table #table mat-table class="instances-table mat-elevation-z8" [ngClass]="{'table-dark': darkMode}" matSort
+<table #table mat-table class="instances-table mat-elevation-z8" [ngClass]="{'table-dark': darkMode}" matSort (matSortChange)="getSortedData($event)"
multiTemplateDataRows [dataSource]="instanceDataSource">
<ng-container matColumnDef="instanceId">
@@ -110,12 +110,7 @@
<mat-footer-cell *matFooterCellDef>No records found.</mat-footer-cell>
</ng-container>
- <mat-header-row *matHeaderRowDef="['instanceId', 'ric', 'service', 'lastModified', 'action']"
- [ngClass]="{'display-none': !this.hasInstances()}">
+ <mat-header-row *matHeaderRowDef="['instanceId', 'ric', 'service', 'lastModified', 'action']">
</mat-header-row>
<mat-row *matRowDef="let instance; columns: ['instanceId', 'ric', 'service', 'lastModified', 'action'];"></mat-row>
-
- <mat-footer-row *matFooterRowDef="['noRecordsFound']" [ngClass]="{'display-none': this.hasInstances()}">
- </mat-footer-row>
-
</table>
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts
new file mode 100644
index 0000000..2546b6d
--- /dev/null
+++ b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts
@@ -0,0 +1,55 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 Nordix Foundation
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================LICENSE_END===================================
+ */
+
+import { async, ComponentFixture } from "@angular/core/testing";
+import { PolicyService } from "@app/services/policy/policy.service";
+import { PolicyInstanceComponent } from "./policy-instance.component";
+
+describe("PolicyInstanceComponent", () => {
+ let component: PolicyInstanceComponent;
+ let fixture: ComponentFixture<PolicyInstanceComponent>;
+
+ // beforeEach(async(() => {
+ // policyDataSourceSpy = jasmine.createSpyObj("PolicyInstanceDataSource", ["getPolicyType"]);
+ // const policyTypeSchema = JSON.parse(
+ // '{"title": "1", "description": "Type 1 policy type"}'
+ // );
+ // const policyType = { policy_schema: policyTypeSchema } as PolicyType;
+ // policyDataSourceSpy.getPolicyType.and.returnValue(of(policyType));
+
+ // TestBed.configureTestingModule({
+ // declarations: [
+ // PolicyTypeComponent,
+ // MockComponent(PolicyInstanceComponent),
+ // ],
+ // providers: [{ provide: PolicyService, useValue: policyDataSourceSpy }],
+ // }).compileComponents();
+ // }));
+
+ // beforeEach(() => {
+ // fixture = TestBed.createComponent(PolicyTypeComponent);
+ // component = fixture.componentInstance;
+ // fixture.detectChanges();
+ // });
+
+ // it("should create", () => {
+ // expect(component).toBeTruthy();
+ // });
+})
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
index 700e929..8442c23 100644
--- a/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
+++ b/webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
@@ -18,192 +18,243 @@
* ========================LICENSE_END===================================
*/
-import { MatSort, Sort } from '@angular/material/sort';
-import { Component, OnInit, ViewChild, Input, AfterViewInit } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
-import { PolicyTypeSchema } from '@interfaces/policy.types';
-import { PolicyInstanceDataSource } from './policy-instance.datasource';
-import { ErrorDialogService } from '@services/ui/error-dialog.service';
-import { NotificationService } from '@services/ui/notification.service';
-import { PolicyService } from '@services/policy/policy.service';
-import { ConfirmDialogService } from '@services/ui/confirm-dialog.service';
-import { PolicyInstance } from '@interfaces/policy.types';
-import { PolicyInstanceDialogComponent } from '../policy-instance-dialog/policy-instance-dialog.component';
-import { getPolicyDialogProperties } from '../policy-instance-dialog/policy-instance-dialog.component';
-import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
-import { BehaviorSubject, Observable } from 'rxjs';
-import { UiService } from '@services/ui/ui.service';
-import { FormControl, FormGroup } from '@angular/forms';
-import { MatTableDataSource } from '@angular/material/table';
+import { Sort } from "@angular/material/sort";
+import { Component, OnInit, Input } from "@angular/core";
+import { MatDialog } from "@angular/material/dialog";
+import { PolicyTypeSchema } from "@interfaces/policy.types";
+import { ErrorDialogService } from "@services/ui/error-dialog.service";
+import { NotificationService } from "@services/ui/notification.service";
+import { PolicyService } from "@services/policy/policy.service";
+import { ConfirmDialogService } from "@services/ui/confirm-dialog.service";
+import { PolicyInstance } from "@interfaces/policy.types";
+import { PolicyInstanceDialogComponent } from "../policy-instance-dialog/policy-instance-dialog.component";
+import { getPolicyDialogProperties } from "../policy-instance-dialog/policy-instance-dialog.component";
+import { HttpErrorResponse, HttpResponse } from "@angular/common/http";
+import { BehaviorSubject, Observable } from "rxjs";
+import { UiService } from "@services/ui/ui.service";
+import { FormControl, FormGroup } from "@angular/forms";
+import { MatTableDataSource } from "@angular/material/table";
class PolicyTypeInfo {
- constructor(public type: PolicyTypeSchema) { }
+ constructor(public type: PolicyTypeSchema) {}
isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
}
@Component({
- selector: 'nrcp-policy-instance',
- templateUrl: './policy-instance.component.html',
- styleUrls: ['./policy-instance.component.scss']
+ selector: "nrcp-policy-instance",
+ templateUrl: "./policy-instance.component.html",
+ styleUrls: ["./policy-instance.component.scss"],
})
+export class PolicyInstanceComponent implements OnInit {
+ @Input() policyTypeSchema: PolicyTypeSchema;
+ @Input() expanded: Observable<boolean>;
+ policyInstances: PolicyInstance[] = [];
+ private policyInstanceSubject = new BehaviorSubject<PolicyInstance[]>([]);
+ policyTypeInfo = new Map<string, PolicyTypeInfo>();
+ instanceDataSource: MatTableDataSource<PolicyInstance> = new MatTableDataSource<PolicyInstance>();
+ policyInstanceForm: FormGroup;
+ darkMode: boolean;
+ constructor(
+ private policySvc: PolicyService,
+ private dialog: MatDialog,
+ private errorDialogService: ErrorDialogService,
+ private notificationService: NotificationService,
+ private confirmDialogService: ConfirmDialogService,
+ private ui: UiService
+ ) {
+ this.policyInstanceForm = new FormGroup({
+ id: new FormControl(""),
+ target: new FormControl(""),
+ owner: new FormControl(""),
+ lastModified: new FormControl(""),
+ });
+ }
-export class PolicyInstanceComponent implements OnInit, AfterViewInit {
- policyInstanceDataSource: PolicyInstanceDataSource;
- @Input() policyTypeSchema: PolicyTypeSchema;
- @Input() expanded: Observable<boolean>;
- @ViewChild(MatSort, { static: true }) sort: MatSort;
- policyTypeInfo = new Map<string, PolicyTypeInfo>();
- instanceDataSource: MatTableDataSource<PolicyInstance> = new MatTableDataSource<PolicyInstance>();
- policyInstanceForm: FormGroup;
- darkMode: boolean;
+ ngOnInit() {
+ this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded));
- constructor(
- private policySvc: PolicyService,
- private dialog: MatDialog,
- private errorDialogService: ErrorDialogService,
- private notificationService: NotificationService,
- private confirmDialogService: ConfirmDialogService,
- private ui: UiService) {
- this.policyInstanceForm = new FormGroup({
- id: new FormControl(''),
- target: new FormControl(''),
- owner: new FormControl(''),
- lastModified: new FormControl('')
- })
- }
+ this.getPolicyInstances();
+ this.policyInstanceSubject.subscribe((data) => {
+ this.instanceDataSource.data = data;
+ });
- ngOnInit() {
- this.policyInstanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService, this.policyTypeSchema.id);
- this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded));
+ this.policyInstanceForm.valueChanges.subscribe((value) => {
+ const filter = { ...value, id: value.id.trim().toLowerCase() } as string;
+ this.instanceDataSource.filter = filter;
+ });
- this.policyInstanceDataSource.connect().subscribe((data) => {
- this.instanceDataSource.data = data;
- })
+ this.instanceDataSource.filterPredicate = ((
+ data: PolicyInstance,
+ filter
+ ) => {
+ return (
+ this.isDataIncluding(data.policy_id, filter.id) &&
+ this.isDataIncluding(data.ric_id, filter.target) &&
+ this.isDataIncluding(data.service_id, filter.owner) &&
+ this.isDataIncluding(data.lastModified, filter.lastModified)
+ );
+ }) as (data: PolicyInstance, filter: any) => boolean;
- this.policyInstanceForm.valueChanges.subscribe(value => {
- const filter = {...value, id: value.id.trim().toLowerCase()} as string;
- this.instanceDataSource.filter = filter;
- });
+ this.ui.darkModeState.subscribe((isDark) => {
+ this.darkMode = isDark;
+ });
+ }
- this.instanceDataSource.filterPredicate = ((data: PolicyInstance, filter) => {
- return this.isDataIncluding(data.policy_id, filter.id)
- && this.isDataIncluding(data.ric_id, filter.target)
- && this.isDataIncluding(data.service_id, filter.owner)
- && this.isDataIncluding(data.lastModified, filter.lastModified);
- }) as (data: PolicyInstance, filter: any) => boolean;
-
- this.ui.darkModeState.subscribe((isDark) => {
- this.darkMode = isDark;
- });
- }
-
- compare(a: any, b: any, isAsc: boolean) {
- return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
- }
-
- stopSort(event: any){
- event.stopPropagation();
- }
-
- isDataIncluding(data: string, filter: string) : boolean {
- return !filter || data.toLowerCase().includes(filter);
- }
-
- ngAfterViewInit() {
- this.policyInstanceDataSource.sort = this.sort;
- }
-
- private onExpand(isExpanded: boolean) {
- if (isExpanded) {
- this.policyInstanceDataSource.getPolicyInstances();
+ getPolicyInstances() {
+ this.policyInstances = [] as PolicyInstance[];
+ this.policySvc
+ .getPolicyInstancesByType(this.policyTypeSchema.id)
+ .subscribe((policies) => {
+ if (policies.policy_ids.length != 0) {
+ policies.policy_ids.forEach((policyId) => {
+ this.policySvc
+ .getPolicyInstance(policyId)
+ .subscribe((policyInstance) => {
+ this.policySvc
+ .getPolicyStatus(policyId)
+ .subscribe((policyStatus) => {
+ policyInstance.lastModified = policyStatus.last_modified;
+ });
+ this.policyInstances.push(policyInstance);
+ });
+ this.policyInstanceSubject.next(this.policyInstances);
+ });
}
- }
+ });
+ }
- private isSchemaEmpty(): boolean {
- return this.policyTypeSchema.schemaObject === '{}';
- }
+ getSortedData(sort: Sort) {
+ const data = this.instanceDataSource.data;
+ data.sort((a, b) => {
+ const isAsc = sort.direction === "asc";
+ switch (sort.active) {
+ case "instanceId":
+ return compare(a.policy_id, b.policy_id, isAsc);
+ case "ric":
+ return compare(a.ric_id, b.ric_id, isAsc);
+ case "service":
+ return compare(a.service_id, b.service_id, isAsc);
+ case "lastModified":
+ return compare(a.lastModified, b.lastModified, isAsc);
+ default:
+ return 0;
+ }
+ });
+ this.instanceDataSource.data = data;
+ }
- modifyInstance(instance: PolicyInstance): void {
- this.policySvc.getPolicyInstance(instance.policy_id).subscribe(
- (refreshedJson: any) => {
- instance = refreshedJson;
- this.dialog.open(
- PolicyInstanceDialogComponent,
- getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
- (_: any) => {
- this.policyInstanceDataSource.getPolicyInstances();
- }
- );
+ stopSort(event: any) {
+ event.stopPropagation();
+ }
+
+ isDataIncluding(data: string, filter: string): boolean {
+ return !filter || data.toLowerCase().includes(filter);
+ }
+
+ private onExpand(isExpanded: boolean) {
+ if (isExpanded) {
+ this.getPolicyInstances();
+ }
+ }
+
+ private isSchemaEmpty(): boolean {
+ return this.policyTypeSchema.schemaObject === "{}";
+ }
+
+ modifyInstance(instance: PolicyInstance): void {
+ this.policySvc.getPolicyInstance(instance.policy_id).subscribe(
+ (refreshedJson: any) => {
+ instance = refreshedJson;
+ this.dialog
+ .open(
+ PolicyInstanceDialogComponent,
+ getPolicyDialogProperties(
+ this.policyTypeSchema,
+ instance,
+ this.darkMode
+ )
+ )
+ .afterClosed()
+ .subscribe((_: any) => {
+ this.getPolicyInstances();
+ });
+ },
+ (httpError: HttpErrorResponse) => {
+ this.notificationService.error(
+ "Could not refresh instance. Please try again." + httpError.message
+ );
+ }
+ );
+ }
+
+ nbInstances(): number {
+ return this.policyInstances.length;
+ }
+
+ toLocalTime(utcTime: string): string {
+ const date = new Date(utcTime);
+ const toutc = date.toUTCString();
+ return new Date(toutc + " UTC").toLocaleString();
+ }
+
+ createPolicyInstance(policyTypeSchema: PolicyTypeSchema): void {
+ let dialogRef = this.dialog.open(
+ PolicyInstanceDialogComponent,
+ getPolicyDialogProperties(policyTypeSchema, null, this.darkMode)
+ );
+ const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyTypeSchema);
+ dialogRef.afterClosed().subscribe((_) => {
+ info.isExpanded.next(info.isExpanded.getValue());
+ });
+ }
+
+ deleteInstance(instance: PolicyInstance): void {
+ this.confirmDialogService
+ .openConfirmDialog(
+ "Are you sure you want to delete this policy instance?"
+ )
+ .afterClosed()
+ .subscribe((res: any) => {
+ if (res) {
+ this.policySvc.deletePolicy(instance.policy_id).subscribe(
+ (response: HttpResponse<Object>) => {
+ switch (response.status) {
+ case 204:
+ this.notificationService.success("Delete succeeded!");
+ this.getPolicyInstances();
+ break;
+ default:
+ this.notificationService.warn(
+ "Delete failed " + response.status + " " + response.body
+ );
+ }
},
- (httpError: HttpErrorResponse) => {
- this.notificationService.error('Could not refresh instance. Please try again.' + httpError.message);
+ (error: HttpErrorResponse) => {
+ this.errorDialogService.displayError(
+ error.statusText + ", " + error.error
+ );
}
- );
- }
-
- hasInstances(): boolean {
- return this.policyInstanceDataSource.rowCount > 0;
- }
-
- nbInstances(): number {
- return this.policyInstanceDataSource.policyInstances.length;
- }
-
- toLocalTime(utcTime: string): string {
- const date = new Date(utcTime);
- const toutc = date.toUTCString();
- return new Date(toutc + ' UTC').toLocaleString();
-
- }
-
- createPolicyInstance(policyTypeSchema: PolicyTypeSchema): void {
- let dialogRef = this.dialog.open(PolicyInstanceDialogComponent,
- getPolicyDialogProperties(policyTypeSchema, null, this.darkMode));
- const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyTypeSchema);
- dialogRef.afterClosed().subscribe(
- (_) => {
- info.isExpanded.next(info.isExpanded.getValue());
- }
- );
- }
-
- deleteInstance(instance: PolicyInstance): void {
- this.confirmDialogService
- .openConfirmDialog('Are you sure you want to delete this policy instance?')
- .afterClosed().subscribe(
- (res: any) => {
- if (res) {
- this.policySvc.deletePolicy(instance.policy_id)
- .subscribe(
- (response: HttpResponse<Object>) => {
- switch (response.status) {
- case 204:
- this.notificationService.success('Delete succeeded!');
- this.policyInstanceDataSource.getPolicyInstances();
- break;
- default:
- this.notificationService.warn('Delete failed ' + response.status + ' ' + response.body);
- }
- },
- (error: HttpErrorResponse) => {
- this.errorDialogService.displayError(error.statusText + ', ' + error.error);
- });
- }
- });
- }
-
- getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
- let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
- if (!info) {
- info = new PolicyTypeInfo(policyTypeSchema);
- this.policyTypeInfo.set(policyTypeSchema.name, info);
+ );
}
- return info;
- }
+ });
+ }
- refreshTable() {
- this.policyInstanceDataSource.getPolicyInstances();
+ getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
+ let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
+ if (!info) {
+ info = new PolicyTypeInfo(policyTypeSchema);
+ this.policyTypeInfo.set(policyTypeSchema.name, info);
}
+ return info;
+ }
+
+ refreshTable() {
+ this.getPolicyInstances();
+ }
+}
+
+function compare(a: string, b: string, isAsc: boolean) {
+ return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
diff --git a/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts b/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts
deleted file mode 100644
index 225aabb..0000000
--- a/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-import { DataSource } from '@angular/cdk/collections';
-import { MatSort } from '@angular/material/sort';
-import { Observable } from 'rxjs/Observable';
-import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { merge } from 'rxjs';
-import { map } from 'rxjs/operators';
-import { PolicyInstance } from '@interfaces/policy.types';
-import { PolicyService } from '@services/policy/policy.service';
-import { NotificationService } from '@services/ui/notification.service';
-
-export class PolicyInstanceDataSource extends DataSource<PolicyInstance> {
-
- policyInstances: PolicyInstance[] = [];
-
- private policyInstanceSubject = new BehaviorSubject<PolicyInstance[]>([]);
-
- private loadingSubject = new BehaviorSubject<boolean>(false);
-
- public loading$ = this.loadingSubject.asObservable();
-
- public rowCount = 1; // hide footer during intial load
-
- constructor(
- private policySvc: PolicyService,
- public sort: MatSort,
- private notificationService: NotificationService,
- private policyTypeSchemaId: string) {
- super();
- }
-
- public getPolicyInstances() {
- this.policyInstances = [] as PolicyInstance[];
- this.policySvc.getPolicyInstancesByType(this.policyTypeSchemaId).subscribe(policies => {
- if (policies.policy_ids.length != 0) {
- policies.policy_ids.forEach(policyId => {
- this.policySvc.getPolicyInstance(policyId).subscribe(policyInstance => {
- this.policySvc.getPolicyStatus(policyId).subscribe(policyStatus => {
- policyInstance.lastModified = policyStatus.last_modified;
- })
- this.policyInstances.push(policyInstance);
- })
- this.policyInstanceSubject.next(this.policyInstances);
- })
- }
- })
- }
-
- connect(): Observable<PolicyInstance[]> {
- const dataMutations = [
- this.policyInstanceSubject.asObservable(),
- this.sort.sortChange
- ];
- return merge(...dataMutations).pipe(map(() => {
- return this.getSortedData([...this.policyInstanceSubject.getValue()]);
- }));
- }
-
- disconnect(): void {
- this.policyInstanceSubject.complete();
- this.loadingSubject.complete();
- }
-
- private getSortedData(data: PolicyInstance[]) {
- if (!this.sort || !this.sort.active || this.sort.direction === '') {
- return data;
- }
-
- return data.sort((a, b) => {
- const isAsc = this.sort.direction === 'asc';
- switch (this.sort.active) {
- case 'instanceId': return compare(a.policy_id, b.policy_id, isAsc);
- case 'ric': return compare(a.ric_id, b.ric_id, isAsc);
- case 'service': return compare(a.service_id, b.service_id, isAsc);
- case 'lastModified': return compare(a.lastModified, b.lastModified, isAsc);
- default: return 0;
- }
- });
- }
-}
-
-function compare(a: string, b: string, isAsc: boolean) {
- return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
-}