Simplify PolicyInstanceComponent 45/5845/1
authorelinuxhenrik <henrik.b.andersson@est.tech>
Wed, 31 Mar 2021 15:26:54 +0000 (17:26 +0200)
committerelinuxhenrik <henrik.b.andersson@est.tech>
Wed, 31 Mar 2021 15:27:00 +0000 (17:27 +0200)
Change-Id: I56357272cf4a1f206184b090b6cbcfbe262d7f41
Issue-ID: NONRTRIC-472
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.html
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.spec.ts [new file with mode: 0644]
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts [deleted file]

index 8c9f5c5..e6d483f 100644 (file)
@@ -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">
         <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 (file)
index 0000000..2546b6d
--- /dev/null
@@ -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
index 700e929..8442c23 100644 (file)
  * ========================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;
-
-    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('')
-            })
-    }
+  ngOnInit() {
+    this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded));
 
-    ngOnInit() {
-        this.policyInstanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService, this.policyTypeSchema.id);
-        this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded));
-
-        this.policyInstanceDataSource.connect().subscribe((data) => {
-            this.instanceDataSource.data = data;
-        })
-
-        this.policyInstanceForm.valueChanges.subscribe(value => {
-            const filter = {...value, id: value.id.trim().toLowerCase()} as string;
-            this.instanceDataSource.filter = filter;
-        });
-
-        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;
-        });
-    }
+    this.getPolicyInstances();
+    this.policyInstanceSubject.subscribe((data) => {
+      this.instanceDataSource.data = data;
+    });
 
-    compare(a: any, b: any, isAsc: boolean) {
-      return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
-    }
+    this.policyInstanceForm.valueChanges.subscribe((value) => {
+      const filter = { ...value, id: value.id.trim().toLowerCase() } as string;
+      this.instanceDataSource.filter = filter;
+    });
 
-    stopSort(event: any){
-        event.stopPropagation();
-    }
+    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;
 
-    isDataIncluding(data: string, filter: string) : boolean {
-        return !filter || data.toLowerCase().includes(filter);
-    }
-
-    ngAfterViewInit() {
-        this.policyInstanceDataSource.sort = this.sort;
-    }
+    this.ui.darkModeState.subscribe((isDark) => {
+      this.darkMode = isDark;
+    });
+  }
 
-    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();
-                        }
-                    );
-            },
-            (httpError: HttpErrorResponse) => {
-                this.notificationService.error('Could not refresh instance. Please try again.' + httpError.message);
-            }
-        );
-    }
+  stopSort(event: any) {
+    event.stopPropagation();
+  }
 
-    hasInstances(): boolean {
-        return this.policyInstanceDataSource.rowCount > 0;
-    }
+  isDataIncluding(data: string, filter: string): boolean {
+    return !filter || data.toLowerCase().includes(filter);
+  }
 
-    nbInstances(): number {
-        return this.policyInstanceDataSource.policyInstances.length;
+  private onExpand(isExpanded: boolean) {
+    if (isExpanded) {
+      this.getPolicyInstances();
     }
+  }
 
-    toLocalTime(utcTime: string): string {
-        const date = new Date(utcTime);
-        const toutc = date.toUTCString();
-        return new Date(toutc + ' UTC').toLocaleString();
+  private isSchemaEmpty(): boolean {
+    return this.policyTypeSchema.schemaObject === "{}";
+  }
 
-    }
-
-    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());
-            }
+  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
         );
-    }
+      }
+    );
+  }
 
-    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);
-                                });
-                    }
-                });
-    }
+  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());
+    });
+  }
 
-    getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
-        let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
-        if (!info) {
-            info = new PolicyTypeInfo(policyTypeSchema);
-            this.policyTypeInfo.set(policyTypeSchema.name, info);
+  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
+                  );
+              }
+            },
+            (error: HttpErrorResponse) => {
+              this.errorDialogService.displayError(
+                error.statusText + ", " + error.error
+              );
+            }
+          );
         }
-        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 (file)
index 225aabb..0000000
+++ /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);
-}