Merge "Fix bug in PolicyInstanceDialogComponent"
diff --git a/webapp-frontend/src/app/mock/policies.json b/webapp-frontend/src/app/mock/policies.json
index c392b76..286bf49 100644
--- a/webapp-frontend/src/app/mock/policies.json
+++ b/webapp-frontend/src/app/mock/policies.json
@@ -1,5 +1,6 @@
 {
   "policy_ids": [
-    "2100"
+    "2100",
+    "2000"
   ]
 }
\ No newline at end of file
diff --git a/webapp-frontend/src/app/mock/policies_notype.json b/webapp-frontend/src/app/mock/policies_notype.json
new file mode 100644
index 0000000..1420ec7
--- /dev/null
+++ b/webapp-frontend/src/app/mock/policies_notype.json
@@ -0,0 +1,5 @@
+{
+    "policy_ids": [
+      "2001"
+    ]
+  }
\ No newline at end of file
diff --git a/webapp-frontend/src/app/mock/policy-instance-notype-status.json b/webapp-frontend/src/app/mock/policy-instance-notype-status.json
new file mode 100644
index 0000000..e213694
--- /dev/null
+++ b/webapp-frontend/src/app/mock/policy-instance-notype-status.json
@@ -0,0 +1,6 @@
+{
+  "last_modified": "2021-01-26T13:15:11.895297Z",
+  "status": {
+    "enforceStatus": "UNDEFINED"
+  }
+}
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-control.component.html b/webapp-frontend/src/app/policy/policy-control.component.html
index 9aa8341..63f2dab 100644
--- a/webapp-frontend/src/app/policy/policy-control.component.html
+++ b/webapp-frontend/src/app/policy/policy-control.component.html
@@ -27,57 +27,4 @@
     </div>
 </div>
 
-<table mat-table [dataSource]="policyTypesDataSource" matSort multiTemplateDataRows
-    class="policy-type-table mat-elevation-z8">
-
-    <ng-container matColumnDef="name">
-        <mat-header-cell *matHeaderCellDef>Policy Type</mat-header-cell>
-        <mat-cell *matCellDef="let policyTypeSchema">
-            <mat-icon matTooltip="Properties">{{isInstancesShown(policyTypeSchema)  ? 'expand_less' : 'expand_more'}}
-            </mat-icon>
-            {{this.getDisplayName(policyTypeSchema)}}
-        </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="description">
-        <mat-header-cell *matHeaderCellDef> Description </mat-header-cell>
-        <mat-cell *matCellDef="let policyTypeSchema"> {{policyTypeSchema.schemaObject.description}}
-        </mat-cell>
-    </ng-container>
-
-    <ng-container matColumnDef="action">
-        <mat-header-cell class="action-cell" *matHeaderCellDef>Action </mat-header-cell>
-        <mat-cell class="action-cell" *matCellDef="let policyTypeSchema" (click)="$event.stopPropagation()">
-            <button mat-icon-button (click)="createPolicyInstance(policyTypeSchema)">
-                <mat-icon matTooltip="Create instance">add_box</mat-icon>
-            </button>
-        </mat-cell>
-    </ng-container>
-
-    <!-- =================== Policy instances for one type ======================== -->
-    <ng-container matColumnDef="instanceTableContainer">
-        <mat-cell *matCellDef="let policyTypeSchema">
-            <nrcp-policy-instance [policyTypeSchema]=policyTypeSchema [expanded]=this.getExpandedObserver(policyTypeSchema)>
-            </nrcp-policy-instance>
-        </mat-cell>
-    </ng-container>
-    <!-- ======= -->
-
-    <ng-container matColumnDef="noRecordsFound">
-        <mat-footer-cell *matFooterCellDef>No records found.</mat-footer-cell>
-    </ng-container>
-
-    <mat-header-row *matHeaderRowDef="['name', 'description', 'action']"></mat-header-row>
-    <mat-row *matRowDef="let policyTypeSchema; columns: ['name', 'description', 'action']"
-        (click)="toggleListInstances(policyTypeSchema)">
-    </mat-row>
-
-    <mat-row *matRowDef="let policyTypeSchema; columns: ['instanceTableContainer'];"
-        [@detailExpand]="isInstancesShown(policyTypeSchema) ? 'expanded' : 'collapsed'" style="overflow: hidden">
-    </mat-row>
-
-    <mat-footer-row *matFooterRowDef="['noRecordsFound']"
-        [ngClass]="{'display-none': policyTypesDataSource.rowCount > 0}">
-    </mat-footer-row>
-
-</table>
+<nrcp-policy-type *ngFor="let policyTypeId of this.policyTypeIds" [policyTypeId]="policyTypeId"></nrcp-policy-type>
diff --git a/webapp-frontend/src/app/policy/policy-control.component.spec.ts b/webapp-frontend/src/app/policy/policy-control.component.spec.ts
index 3cd2601..198305d 100644
--- a/webapp-frontend/src/app/policy/policy-control.component.spec.ts
+++ b/webapp-frontend/src/app/policy/policy-control.component.spec.ts
@@ -30,6 +30,7 @@
 import { PolicyTypeDataSource } from "@policy/policy-type/policy-type.datasource";
 import { UiService } from "@services/ui/ui.service";
 import { PolicyTypeSchema } from "@interfaces/policy.types";
+import { PolicyService } from '../services/policy/policy.service';
 
 describe("PolicyControlComponent", () => {
   let component: PolicyControlComponent;
@@ -40,11 +41,13 @@
       "PolicyTypeDataSource",
       ["connect", "getPolicyTypes", "disconnect"]
     );
+    const policyServiceSpy = jasmine.createSpyObj('PolicyService', ['getPolicyTypes']);
     var policyTypeSchema = {} as PolicyTypeSchema;
     policyTypeSchema.name = "";
     policyTypeSchema.schemaObject = "";
     policyTypeDataSourceSpy.connect.and.returnValue(of([policyTypeSchema]));
     policyTypeDataSourceSpy.disconnect();
+    policyServiceSpy.getPolicyTypes.and.returnValue(of(["type1"]));
 
     let matDialogStub: Partial<MatDialog>;
     let notificationServiceStub: Partial<NotificationService>;
@@ -54,6 +57,7 @@
       schemas: [CUSTOM_ELEMENTS_SCHEMA],
       declarations: [PolicyControlComponent],
       providers: [
+        { provide : PolicyService, useValue: policyServiceSpy},
         { provide: PolicyTypeDataSource, useValue: policyTypeDataSourceSpy },
         { provide: MatDialog, useValue: matDialogStub },
         { provide: NotificationService, useValue: notificationServiceStub },
diff --git a/webapp-frontend/src/app/policy/policy-control.component.ts b/webapp-frontend/src/app/policy/policy-control.component.ts
index 1c5b7d8..de3f578 100644
--- a/webapp-frontend/src/app/policy/policy-control.component.ts
+++ b/webapp-frontend/src/app/policy/policy-control.component.ts
@@ -23,11 +23,13 @@
 
 import { BehaviorSubject, Observable } from 'rxjs';
 
-import { PolicyTypeSchema } from '@interfaces/policy.types';
+import { PolicyTypes, PolicyTypeSchema } from '@interfaces/policy.types';
 import { PolicyTypeDataSource } from './policy-type/policy-type.datasource';
 import { getPolicyDialogProperties } from './policy-instance-dialog/policy-instance-dialog.component';
 import { PolicyInstanceDialogComponent } from './policy-instance-dialog/policy-instance-dialog.component';
 import { UiService } from '@services/ui/ui.service';
+import { PolicyService } from '@services/policy/policy.service';
+import { PolicyTypeComponent } from './policy-type/policy-type.component';
 
 class PolicyTypeInfo {
     constructor(public type: PolicyTypeSchema) { }
@@ -51,11 +53,14 @@
 export class PolicyControlComponent implements OnInit {
 
     policyTypeInfo = new Map<string, PolicyTypeInfo>();
+    policyTypeIds: Array<string>;
+    policyTypeComponent = new PolicyTypeComponent(this.policyTypesDataSource);
     darkMode: boolean;
 
     constructor(
         public policyTypesDataSource: PolicyTypeDataSource,
         private dialog: MatDialog,
+        private policyService: PolicyService,
         private ui: UiService) { }
 
     ngOnInit() {
@@ -63,15 +68,8 @@
         this.ui.darkModeState.subscribe((isDark) => {
             this.darkMode = isDark;
         });
-    }
-
-    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());
+        this.policyService.getPolicyTypes().subscribe((policyType: PolicyTypes) => {
+            this.policyTypeIds = policyType.policytype_ids;
             }
         );
     }
@@ -97,15 +95,12 @@
         return '< No type >';
     }
 
-    isInstancesShown(policyTypeSchema: PolicyTypeSchema): boolean {
-        return this.getPolicyTypeInfo(policyTypeSchema).isExpanded.getValue();
-    }
-
     getExpandedObserver(policyTypeSchema: PolicyTypeSchema): Observable<boolean> {
         return this.getPolicyTypeInfo(policyTypeSchema).isExpanded.asObservable();
     }
 
     refreshTables() {
         this.policyTypesDataSource.getPolicyTypes();
+        this.policyTypeComponent.setIsVisible(false);
     }
 }
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 9c7032c..8c9f5c5 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
@@ -17,12 +17,29 @@
   limitations under the License.
   ========================LICENSE_END===================================
   -->
+<div>
+    Number of instances: {{this.nbInstances()}}
+    <button mat-icon-button (click)="createPolicyInstance(policyTypeSchema)">
+        <mat-icon matTooltip="Create instance">add_box</mat-icon>
+    </button>
+    <button mat-icon-button color="primary" (click)="refreshTable()">
+        <mat-icon>refresh</mat-icon>
+    </button>
+</div>
+
 <table #table mat-table class="instances-table mat-elevation-z8" [ngClass]="{'table-dark': darkMode}" matSort
     multiTemplateDataRows [dataSource]="instanceDataSource">
 
     <ng-container matColumnDef="instanceId">
         <mat-header-cell mat-sort-header *matHeaderCellDef matTooltip="The ID of the policy instance">
-            Instance
+            <div (click)="stopSort($event)">
+                <form style="display: flex" [formGroup]="policyInstanceForm">
+                    <mat-form-field>
+                        <input id="policyInstanceIdFilter" matInput formControlName="id">
+                        <mat-placeholder>Instance</mat-placeholder>
+                    </mat-form-field>
+                </form>
+            </div>
         </mat-header-cell>
         <mat-cell *matCellDef="let element" (click)="modifyInstance(element)">{{element.policy_id}}
         </mat-cell>
@@ -31,7 +48,14 @@
     <ng-container matColumnDef="ric">
         <mat-header-cell mat-sort-header *matHeaderCellDef
             matTooltip="Element where the policy instance resides, e.g. a gNodeB or Near-RT RIC">
-            Target
+            <div (click)="stopSort($event)">
+                <form style="display: flex" [formGroup]="policyInstanceForm">
+                    <mat-form-field>
+                        <input id="policyInstanceTargetFilter" matInput formControlName="target">
+                        <mat-placeholder>Target</mat-placeholder>
+                    </mat-form-field>
+                </form>
+            </div>
         </mat-header-cell>
         <mat-cell *matCellDef="let element" (click)="modifyInstance(element)">{{element.ric_id}}
         </mat-cell>
@@ -40,7 +64,14 @@
     <ng-container matColumnDef="service">
         <mat-header-cell mat-sort-header *matHeaderCellDef
             matTooltip="The service that created the policy instance, and is responsible for its lifecycle">
-            Owner
+            <div (click)="stopSort($event)">
+                <form style="display: flex" [formGroup]="policyInstanceForm">
+                    <mat-form-field>
+                        <input id="policyInstanceOwnerFilter" matInput formControlName="owner">
+                        <mat-placeholder>Owner</mat-placeholder>
+                    </mat-form-field>
+                </form>
+            </div>
         </mat-header-cell>
         <mat-cell *matCellDef="let element" (click)="modifyInstance(element)">{{element.service_id}}
         </mat-cell>
@@ -49,7 +80,14 @@
     <ng-container matColumnDef="lastModified">
         <mat-header-cell mat-sort-header *matHeaderCellDef
             matTooltip="The time of the last modification of the policy instance">
-            Last modified
+            <div (click)="stopSort($event)">
+                <form style="display: flex" [formGroup]="policyInstanceForm">
+                    <mat-form-field>
+                        <input id="policyInstanceLastModifiedFilter" matInput formControlName="lastModified">
+                        <mat-placeholder>Last modified</mat-placeholder>
+                    </mat-form-field>
+                </form>
+            </div>
         </mat-header-cell>
         <mat-cell *matCellDef="let element" (click)="modifyInstance(element)">{{toLocalTime(element.lastModified)}}
         </mat-cell>
@@ -80,4 +118,4 @@
     <mat-footer-row *matFooterRowDef="['noRecordsFound']" [ngClass]="{'display-none': this.hasInstances()}">
     </mat-footer-row>
 
-</table>
+</table>
\ 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 eb9747d..24a7cc7 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,7 +18,7 @@
  * ========================LICENSE_END===================================
  */
 
-import { MatSort } from '@angular/material/sort';
+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';
@@ -31,8 +31,16 @@
 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 { Observable } from 'rxjs';
+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) { }
+
+  isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+}
 
 @Component({
     selector: 'nrcp-policy-instance',
@@ -42,10 +50,13 @@
 
 
 export class PolicyInstanceComponent implements OnInit, AfterViewInit {
-    instanceDataSource: PolicyInstanceDataSource;
+    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(
@@ -55,23 +66,62 @@
         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.instanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.policyTypeSchema);
+        let schemaId = this.policyTypeSchema.id;
+        if(schemaId.includes('<No Type>')){
+            schemaId = '';
+        }
+        this.policyInstanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService, schemaId);
         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;
         });
     }
 
+    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.instanceDataSource.sort = this.sort;
+        this.policyInstanceDataSource.sort = this.sort;
     }
 
     private onExpand(isExpanded: boolean) {
         if (isExpanded) {
-            this.instanceDataSource.getPolicyInstances();
+            this.policyInstanceDataSource.getPolicyInstances();
         }
     }
 
@@ -87,7 +137,7 @@
                     PolicyInstanceDialogComponent,
                     getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
                         (_: any) => {
-                            this.instanceDataSource.getPolicyInstances();
+                            this.policyInstanceDataSource.getPolicyInstances();
                         }
                     );
             },
@@ -98,7 +148,11 @@
     }
 
     hasInstances(): boolean {
-        return this.instanceDataSource.rowCount > 0;
+        return this.policyInstanceDataSource.rowCount > 0;
+    }
+
+    nbInstances(): number {
+        return this.policyInstanceDataSource.policyInstances.length;
     }
 
     toLocalTime(utcTime: string): string {
@@ -108,6 +162,17 @@
 
     }
 
+    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?')
@@ -120,7 +185,7 @@
                                     switch (response.status) {
                                         case 204:
                                             this.notificationService.success('Delete succeeded!');
-                                            this.instanceDataSource.getPolicyInstances();
+                                            this.policyInstanceDataSource.getPolicyInstances();
                                             break;
                                         default:
                                             this.notificationService.warn('Delete failed ' + response.status + ' ' + response.body);
@@ -132,4 +197,17 @@
                     }
                 });
     }
+
+    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();
+    }
 }
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
index 031c0eb..225aabb 100644
--- a/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts
+++ b/webapp-frontend/src/app/policy/policy-instance/policy-instance.datasource.ts
@@ -24,8 +24,9 @@
 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
 import { merge } from 'rxjs';
 import { map } from 'rxjs/operators';
-import { PolicyInstance, PolicyTypeSchema } from '@interfaces/policy.types';
+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> {
 
@@ -42,16 +43,16 @@
     constructor(
         private policySvc: PolicyService,
         public sort: MatSort,
-        private policyTypeSchema: PolicyTypeSchema) {
+        private notificationService: NotificationService,
+        private policyTypeSchemaId: string) {
         super();
     }
 
     public getPolicyInstances() {
         this.policyInstances = [] as PolicyInstance[];
-        this.policySvc.getPolicyInstancesByType(this.policyTypeSchema.id).subscribe(policies => {
+        this.policySvc.getPolicyInstancesByType(this.policyTypeSchemaId).subscribe(policies => {
             if (policies.policy_ids.length != 0) {
                 policies.policy_ids.forEach(policyId => {
-                    var policyInstance = {} as PolicyInstance
                     this.policySvc.getPolicyInstance(policyId).subscribe(policyInstance => {
                         this.policySvc.getPolicyStatus(policyId).subscribe(policyStatus => {
                             policyInstance.lastModified = policyStatus.last_modified;
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.component.html b/webapp-frontend/src/app/policy/policy-type/policy-type.component.html
new file mode 100644
index 0000000..6bc273d
--- /dev/null
+++ b/webapp-frontend/src/app/policy/policy-type/policy-type.component.html
@@ -0,0 +1,34 @@
+<!--
+  ========================LICENSE_START=================================
+  O-RAN-SC
+  %%
+  Copyright (C) 2021 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===================================
+  -->
+
+<div fxLayout="row" fxLayoutGap="10px">
+  <div class="default-cursor" (click)="toggleVisible()">
+    <mat-icon matTooltip="Properties">{{isVisible.value? 'expand_less' : 'expand_more'}}</mat-icon>
+  </div>
+  <div>
+    <b><u>Policy type:</u></b> {{policyTypeInfo.type.id}}
+  </div>
+  <div>
+    <b><u>Description:</u></b>{{policyTypeInfo.type.schemaObject.description}}
+  </div>
+</div>
+
+<nrcp-policy-instance *ngIf="isVisible.value" [policyTypeSchema]=policyTypeInfo.type [expanded]=isVisible.asObservable()>
+</nrcp-policy-instance>
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.component.scss b/webapp-frontend/src/app/policy/policy-type/policy-type.component.scss
new file mode 100644
index 0000000..26245c9
--- /dev/null
+++ b/webapp-frontend/src/app/policy/policy-type/policy-type.component.scss
@@ -0,0 +1,19 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2021 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===================================
+ */
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.component.spec.ts b/webapp-frontend/src/app/policy/policy-type/policy-type.component.spec.ts
new file mode 100644
index 0000000..4276ad3
--- /dev/null
+++ b/webapp-frontend/src/app/policy/policy-type/policy-type.component.spec.ts
@@ -0,0 +1,54 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2021 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, TestBed } from '@angular/core/testing';
+
+import { PolicyTypeComponent } from './policy-type.component';
+import { PolicyTypeDataSource } from './policy-type.datasource';
+import { PolicyTypeSchema } from '../../interfaces/policy.types';
+
+describe('PolicyTypeComponent', () => {
+  let component: PolicyTypeComponent;
+  let fixture: ComponentFixture<PolicyTypeComponent>;
+
+  beforeEach(async(() => {
+    const policyTypeDataSourceSpy = jasmine.createSpyObj('PolicyTypeDataSource', ['getPolicyType']);
+    const policyTypeSchema = {"schemaObject": {"description": "Type 1 policy type"}} as PolicyTypeSchema;
+    policyTypeDataSourceSpy.getPolicyType.and.returnValue(policyTypeSchema);
+
+    TestBed.configureTestingModule({
+      declarations: [ PolicyTypeComponent ],
+      providers: [
+        { provide: PolicyTypeDataSource, useValue: policyTypeDataSourceSpy }
+       ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PolicyTypeComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.component.ts b/webapp-frontend/src/app/policy/policy-type/policy-type.component.ts
new file mode 100644
index 0000000..be5b305
--- /dev/null
+++ b/webapp-frontend/src/app/policy/policy-type/policy-type.component.ts
@@ -0,0 +1,63 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2021 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 { Component, Input, OnInit } from '@angular/core';
+import { BehaviorSubject } from 'rxjs';
+import { PolicyTypeSchema } from '@interfaces/policy.types';
+import { PolicyService } from '@services/policy/policy.service';
+import { PolicyTypeDataSource } from './policy-type.datasource';
+
+class PolicyTypeInfo {
+  constructor(public type: PolicyTypeSchema) { }
+
+  isExpanded: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+}
+
+@Component({
+  selector: 'nrcp-policy-type',
+  templateUrl: './policy-type.component.html',
+  styleUrls: ['./policy-type.component.scss']
+})
+export class PolicyTypeComponent implements OnInit {
+
+  @Input() policyTypeId: string;
+
+  isVisible: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+
+  policyTypeInfo: PolicyTypeInfo;
+
+  constructor(private policyTypeDataSource: PolicyTypeDataSource) {
+  }
+
+  ngOnInit(): void {
+    const policyTypeSchema = this.policyTypeDataSource.getPolicyType(this.policyTypeId);
+    this.policyTypeInfo = new PolicyTypeInfo(policyTypeSchema);
+    console.log("this.policyType: ", this.policyTypeInfo);
+    this.isVisible.next(false);
+  }
+
+  public setIsVisible(status: boolean){
+    this.isVisible.next(status);
+  }
+
+  public toggleVisible() {
+    this.isVisible.next(!this.isVisible.value);
+  }
+}
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts b/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts
index 8766084..fe926ee 100644
--- a/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts
+++ b/webapp-frontend/src/app/policy/policy-type/policy-type.datasource.ts
@@ -72,6 +72,20 @@
             })
     }
 
+    public getPolicyType(policyTypeId: string): PolicyTypeSchema {
+        var policyTypeSchema = {} as PolicyTypeSchema;
+        this.policySvc.getPolicyType(policyTypeId)
+            .subscribe((policyType: PolicyType) => {
+                policyTypeSchema.id = policyTypeId;
+                policyTypeSchema.schemaObject = policyType.policy_schema;
+                policyTypeSchema.name = policyType.policy_schema.title;
+            })
+            if (policyTypeId === "") {
+                policyTypeSchema.id = '<No Type>';
+            }
+        return policyTypeSchema;
+    }
+
     connect(collectionViewer: CollectionViewer): Observable<PolicyTypeSchema[]> {
         return of(this.policyTypeSubject.getValue());
     }
diff --git a/webapp-frontend/src/app/policy/policy.module.ts b/webapp-frontend/src/app/policy/policy.module.ts
index 8334259..90d3df0 100644
--- a/webapp-frontend/src/app/policy/policy.module.ts
+++ b/webapp-frontend/src/app/policy/policy.module.ts
@@ -24,6 +24,7 @@
 import { MatTableModule } from '@angular/material/table';
 import { PolicyCardComponent } from './policy-card/policy-card.component';
 import { PolicyControlComponent } from './policy-control.component';
+import { PolicyTypeComponent } from './policy-type/policy-type.component';
 import { PolicyInstanceDialogComponent } from './policy-instance-dialog/policy-instance-dialog.component';
 import { PolicyInstanceComponent } from './policy-instance/policy-instance.component';
 import { ReactiveFormsModule } from '@angular/forms';
@@ -52,6 +53,7 @@
     PolicyControlComponent,
     PolicyInstanceComponent,
     PolicyInstanceDialogComponent,
+    PolicyTypeComponent,
     RicSelectorComponent,
     NoTypePolicyEditorComponent,
     TypedPolicyEditorComponent,
@@ -75,7 +77,8 @@
   ],
   exports: [
     PolicyCardComponent,
-    PolicyControlComponent
-  ]
+    PolicyControlComponent,
+    PolicyTypeComponent
+  ],
 })
 export class PolicyModule { }