Merge "Add functionality to truncate amount of instances"
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 3203c0d..db676a6 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
@@ -25,6 +25,13 @@
<button id="refreshButton" mat-icon-button color="primary" (click)="refreshTable()">
<mat-icon id="refreshIcon">refresh</mat-icon>
</button>
+ <div class="spinner-container" style="display: flex; justify-content: center; align-items: center;"
+ *ngIf="loading$ | async">
+ <mat-spinner></mat-spinner>
+ </div>
+ <div id="truncated" *ngIf="truncated" class="alert">
+ Too many instances! Only {{slice}} results will be shown.
+ </div>
</div>
<mat-table class="instances-table mat-elevation-z8" id="policiesTable" [dataSource]="instanceDataSource" matSort
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
index baaa80a..4a50046 100644
--- 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
@@ -186,27 +186,24 @@
});
it("should contain number of instances heading and value, create and refresh buttons, and policies table", async () => {
- const instancesHeading = hostFixture.debugElement.nativeElement.querySelector(
- "div"
- );
+ const instancesHeading =
+ hostFixture.debugElement.nativeElement.querySelector("div");
expect(instancesHeading.innerText).toContain("Number of instances: 2");
const createButton: MatButtonHarness = await loader.getHarness(
MatButtonHarness.with({ selector: "#createButton" })
);
expect(createButton).toBeTruthy();
- const createIcon = hostFixture.debugElement.nativeElement.querySelector(
- "#createIcon"
- );
+ const createIcon =
+ hostFixture.debugElement.nativeElement.querySelector("#createIcon");
expect(createIcon.innerText).toContain("add_box");
const refreshButton: MatButtonHarness = await loader.getHarness(
MatButtonHarness.with({ selector: "#refreshButton" })
);
expect(refreshButton).toBeTruthy();
- const refreshIcon = hostFixture.debugElement.nativeElement.querySelector(
- "#refreshIcon"
- );
+ const refreshIcon =
+ hostFixture.debugElement.nativeElement.querySelector("#refreshIcon");
expect(refreshIcon.innerText).toContain("refresh");
const policiesTable = await loader.getHarness(
@@ -309,7 +306,7 @@
const lastModifiedCell = (await firstRow.getCells())[3];
(await lastModifiedCell.host()).click();
- // Totally unnecessary call just to make the bloody framework count the number of calls to the spy correctly!
+ // Totally unnecessary call just to make the framework count the number of calls to the spy correctly!
await policiesTable.getRows();
expect(componentUnderTest.modifyInstance).toHaveBeenCalledTimes(4);
@@ -494,24 +491,22 @@
it("should not sort when click in filter inputs", async () => {
spyOn(componentUnderTest, "stopSort").and.callThrough();
- const idFilterInputDiv = hostFixture.debugElement.nativeElement.querySelector(
- "#idSortStop"
- );
+ const idFilterInputDiv =
+ hostFixture.debugElement.nativeElement.querySelector("#idSortStop");
idFilterInputDiv.click();
- const targetFilterInputDiv = hostFixture.debugElement.nativeElement.querySelector(
- "#targetSortStop"
- );
+ const targetFilterInputDiv =
+ hostFixture.debugElement.nativeElement.querySelector("#targetSortStop");
targetFilterInputDiv.click();
- const ownerFilterInputDiv = hostFixture.debugElement.nativeElement.querySelector(
- "#ownerSortStop"
- );
+ const ownerFilterInputDiv =
+ hostFixture.debugElement.nativeElement.querySelector("#ownerSortStop");
ownerFilterInputDiv.click();
- const lastModifiedFilterInputDiv = hostFixture.debugElement.nativeElement.querySelector(
- "#lastModifiedSortStop"
- );
+ const lastModifiedFilterInputDiv =
+ hostFixture.debugElement.nativeElement.querySelector(
+ "#lastModifiedSortStop"
+ );
lastModifiedFilterInputDiv.click();
expect(componentUnderTest.stopSort).toHaveBeenCalledTimes(4);
@@ -521,6 +516,38 @@
expect(eventSpy.stopPropagation).toHaveBeenCalled();
});
+ describe("#truncate data", () => {
+ fit("should verify that data is correctly truncated when needed", async () => {
+ policyServiceSpy.getPolicyInstancesByType.and.returnValue(
+ of(policyInstances)
+ );
+ policyServiceSpy.getPolicyInstance.and.callFake(function (
+ policyId: string
+ ) {
+ return of(policyIdToInstanceMap[policyId]);
+ });
+ policyServiceSpy.getPolicyStatus.and.callFake(function (
+ policyId: string
+ ) {
+ return of(policyIdToStatusMap[policyId]);
+ });
+ compileAndGetComponents();
+ componentUnderTest.slice = 1;
+ componentUnderTest.ngOnInit();
+
+ const policiesTable = await loader.getHarness(
+ MatTableHarness.with({ selector: "#policiesTable" })
+ );
+ const policyRows = await policiesTable.getRows();
+ expect(policyRows.length).toEqual(1);
+ policyRows[0].getCellTextByColumnName().then((values) => {
+ expect(expectedPolicy1Row).toEqual(jasmine.objectContaining(values));
+ });
+
+ expect(componentUnderTest.truncated).toBeTruthy();
+ });
+ });
+
describe("#sorting", () => {
it("should verify sort functionality on the table", async () => {
const sort = await loader.getHarness(MatSortHarness);
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 1649d39..5e29f3a 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
@@ -33,7 +33,7 @@
import { UiService } from "@services/ui/ui.service";
import { FormControl, FormGroup } from "@angular/forms";
import { MatTableDataSource } from "@angular/material/table";
-import { mergeMap } from "rxjs/operators";
+import { finalize, mergeMap, map } from "rxjs/operators";
@Component({
selector: "nrcp-policy-instance",
@@ -41,12 +41,16 @@
styleUrls: ["./policy-instance.component.scss"],
})
export class PolicyInstanceComponent implements OnInit {
+ public slice: number = 1000;
@Input() policyTypeSchema: PolicyTypeSchema;
darkMode: boolean;
instanceDataSource: MatTableDataSource<PolicyInstance>;
policyInstanceForm: FormGroup;
private policyInstanceSubject = new BehaviorSubject<PolicyInstance[]>([]);
policyInstances: PolicyInstance[] = [];
+ private loadingSubject$ = new BehaviorSubject<boolean>(false);
+ public loading$ = this.loadingSubject$.asObservable();
+ public truncated = false;
constructor(
private policySvc: PolicyService,
@@ -96,9 +100,17 @@
getPolicyInstances() {
this.policyInstances = [] as PolicyInstance[];
+ this.loadingSubject$.next(true);
this.policySvc
.getPolicyInstancesByType(this.policyTypeSchema.id)
.pipe(
+ map((data) => {
+ if (data.policy_ids.length > this.slice) {
+ this.truncated = true;
+ data.policy_ids = data.policy_ids.slice(0, this.slice);
+ }
+ return data;
+ }),
mergeMap((policyIds) =>
forkJoin(
policyIds.policy_ids.map((id) => {
@@ -108,7 +120,8 @@
]);
})
)
- )
+ ),
+ finalize(() => this.loadingSubject$.next(false))
)
.subscribe((res) => {
this.policyInstances = res.map((policy) => {
@@ -178,7 +191,7 @@
hasInstances(): boolean {
return this.instanceCount() > 0;
-}
+ }
instanceCount(): number {
return this.policyInstances.length;
@@ -212,6 +225,7 @@
}
refreshTable() {
+ this.truncated = false;
this.getPolicyInstances();
}
}
diff --git a/webapp-frontend/src/app/policy/policy.module.ts b/webapp-frontend/src/app/policy/policy.module.ts
index a6a187c..38b9755 100644
--- a/webapp-frontend/src/app/policy/policy.module.ts
+++ b/webapp-frontend/src/app/policy/policy.module.ts
@@ -43,6 +43,7 @@
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatCardModule } from '@angular/material/card';
import { MatTooltipModule } from '@angular/material/tooltip';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
const routes:Routes = [
{path: 'policy', component: PolicyControlComponent}
@@ -69,6 +70,7 @@
MatFormFieldModule,
MatIconModule,
MatInputModule,
+ MatProgressSpinnerModule,
MatSelectModule,
MatSortModule,
MaterialDesignFrameworkModule,