Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.

Commit 3a19aaa

Browse files
author
Matt Jeanes
committed
Improve filter and add paginator
Paginator doesn't actually work yet, not sure why Also fix css class conflict with snackbar
1 parent 119780f commit 3a19aaa

File tree

5 files changed

+104
-146
lines changed

5 files changed

+104
-146
lines changed

SystemChecker.Web/ClientApp/app/app.module.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ import {
4343
MatIconModule,
4444
MatInputModule,
4545
MatNativeDateModule,
46+
MatPaginatorModule,
4647
MatSelectModule,
47-
MatTabsModule,
48-
MatTooltipModule,
4948
MatSnackBarModule,
50-
MatTableModule,
51-
MAT_SNACK_BAR_DEFAULT_OPTIONS,
5249
MatSortModule,
50+
MatTableModule,
51+
MatTabsModule,
52+
MatTooltipModule,
5353
} from "@angular/material";
5454

5555
import {
@@ -125,6 +125,7 @@ routes.forEach(x => {
125125
MatSnackBarModule,
126126
MatTableModule,
127127
MatSortModule,
128+
MatPaginatorModule,
128129
],
129130
declarations: [
130131
AppComponent,
@@ -153,7 +154,6 @@ routes.forEach(x => {
153154
{ provide: LOCALE_ID, useValue: "en-GB" },
154155
{ provide: MAT_DATE_LOCALE, useValue: "en-GB" },
155156
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
156-
{ provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 5000 } },
157157
],
158158
entryComponents: [
159159
RunCheckComponent,

SystemChecker.Web/ClientApp/app/dashboard/dashboard.component.ts

+31-16
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
22
import { Router } from "@angular/router";
33
import { HttpTransportType, HubConnectionBuilder } from "@aspnet/signalr";
44

5+
import { MatPaginator, MatSort, MatTableDataSource } from "@angular/material";
56
import { CheckResultStatus } from "../app.enums";
67
import { ICheck, ICheckGroup, ICheckType, IEnvironment, ISettings } from "../app.interfaces";
78
import { RunCheckComponent } from "../components";
89
import { AppService, MessageService } from "../services";
9-
import { MatTableDataSource, MatSort } from "@angular/material";
1010

1111
interface IChart {
1212
name: string;
@@ -39,7 +39,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
3939
public checks: ICheck[] = [];
4040
public dataSource: MatTableDataSource<ICheck>;
4141
public displayedColumns = ["name", "active", "group", "environment", "type", "lastResultStatus", "options"];
42-
@ViewChild("sort") public sort: MatSort;
42+
@ViewChild(MatSort) public sort: MatSort;
43+
@ViewChild(MatPaginator) public paginator: MatPaginator;
4344

4445
public filter: string;
4546
public activeOnly: boolean = true;
@@ -107,15 +108,29 @@ export class DashboardComponent implements OnInit, OnDestroy {
107108
this.checks = await this.appService.getAll(true);
108109
this.dataSource = new MatTableDataSource(this.checks);
109110
this.dataSource.sort = this.sort;
111+
this.dataSource.paginator = this.paginator;
110112
console.log(this.sort);
111-
this.dataSource.filterPredicate = (check, value) => {
112-
return `${check.Name}
113-
${check.Active ? "Yes" : "No"}
114-
${check.GroupID ? this.checkGroupLookup[check.GroupID].Name : "None"}
115-
${this.environmentLookup[check.EnvironmentID!].Name}
116-
${this.typeLookup[check.TypeID!].Name}
117-
${CheckResultStatus[check.LastResultStatus!]}
118-
`.toLowerCase().includes(value);
113+
this.dataSource.filterPredicate = (check, valueRaw) => {
114+
if (!valueRaw) { return true; }
115+
const fields = [
116+
`name: ${check.Name}`,
117+
`active: ${check.Active ? "Yes" : "No"}`,
118+
`group: ${check.GroupID ? this.checkGroupLookup[check.GroupID].Name : "None"}`,
119+
`env: ${this.environmentLookup[check.EnvironmentID!].Name}`,
120+
`type: ${this.typeLookup[check.TypeID!].Name}`,
121+
`status: ${CheckResultStatus[check.LastResultStatus!]}`,
122+
].map(x => x.replace(/ /g, "").toLowerCase());
123+
const values = valueRaw.split(",").filter(x => x);
124+
for (const value of values) {
125+
let match = false;
126+
for (const field of fields) {
127+
if (field.includes(value)) {
128+
match = true;
129+
}
130+
}
131+
if (!match) { return false; }
132+
}
133+
return true;
119134
};
120135
this.dataSource.sortingDataAccessor = (check, header) => {
121136
console.log(header);
@@ -127,11 +142,11 @@ ${CheckResultStatus[check.LastResultStatus!]}
127142
case "group":
128143
return check.GroupID ? this.checkGroupLookup[check.GroupID].Name : "None";
129144
case "environment":
130-
return this.environmentLookup[check.EnvironmentID!].Name
145+
return this.environmentLookup[check.EnvironmentID!].Name;
131146
case "type":
132-
return this.typeLookup[check.TypeID!].Name
147+
return this.typeLookup[check.TypeID!].Name;
133148
case "lastResultStatus":
134-
return CheckResultStatus[check.LastResultStatus!]
149+
return CheckResultStatus[check.LastResultStatus!];
135150
default:
136151
return check[header];
137152
}
@@ -154,7 +169,7 @@ ${CheckResultStatus[check.LastResultStatus!]}
154169
}
155170
}
156171
public applyFilter() {
157-
this.dataSource.filter = this.filter.replace(/ /g, "").toLowerCase();
172+
this.dataSource.filter = this.filter ? this.filter.replace(/ /g, "").toLowerCase() : "";
158173
}
159174
public async run(check: ICheck) {
160175
await this.appService.run(RunCheckComponent, check);
@@ -214,15 +229,15 @@ ${CheckResultStatus[check.LastResultStatus!]}
214229
public onChartSelect(results: IChart, event: { name: string, value: number }) {
215230
const selected = results.results.find(x => x.name === event.name);
216231
if (selected) {
217-
this.filter = `${this.environmentLookup[results.environmentID].Name} ${CheckResultStatus[selected.type!]}`;
232+
this.filter = `env:${this.environmentLookup[results.environmentID].Name}, status:${CheckResultStatus[selected.type!]}`;
218233
this.applyFilter();
219234
}
220235
}
221236
public onCheckSelected(event: { data: ICheck }) {
222237
this.router.navigate(["/details", event.data.ID]);
223238
}
224239
public setEnvironment(id: number) {
225-
this.filter = this.environmentLookup[id].Name;
240+
this.filter = `env:${this.environmentLookup[id].Name}`;
226241
this.applyFilter();
227242
}
228243
public trackChart(index: number, chart: IChart) {

SystemChecker.Web/ClientApp/app/dashboard/dashboard.template.html

+64-122
Original file line numberDiff line numberDiff line change
@@ -4,132 +4,74 @@
44
<button mat-raised-button color="primary" routerLink="/edit/0">Add new</button>
55
<button mat-raised-button color="primary" routerLink="/settings">Settings</button>
66
</div>
7-
<div *ngFor="let results of chart; trackBy: trackChart" class="ui-g ui-g-12 ui-lg-6 chart">
8-
<span class="environment" (click)="setEnvironment(results.environmentID)">{{results.name}}</span>
9-
<ngx-charts-advanced-pie-chart [scheme]="chartColors"
10-
[results]="results.results"
11-
(select)="onChartSelect(results, $event)">
12-
</ngx-charts-advanced-pie-chart>
13-
</div>
14-
<div class="ui-g-12" *ngIf="dataSource">
15-
<mat-checkbox [(ngModel)]="activeOnly">Active Only</mat-checkbox>
16-
<mat-form-field class="full">
17-
<input matInput [(ngModel)]="filter" (keyup)="applyFilter()" placeholder="Search">
18-
</mat-form-field>
19-
<table mat-table [dataSource]="dataSource" class="full mat-elevation-z2" matSort #sort="matSort">
20-
<ng-container matColumnDef="name">
21-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
22-
<td mat-cell *matCellDef="let check"> {{check.Name}} </td>
23-
</ng-container>
7+
</mat-card-content>
8+
</mat-card>
9+
<div *ngFor="let results of chart; trackBy: trackChart" class="ui-g ui-g-12 ui-lg-6 chart">
10+
<span class="environment" (click)="setEnvironment(results.environmentID)">{{results.name}}</span>
11+
<ngx-charts-advanced-pie-chart [scheme]="chartColors"
12+
[results]="results.results"
13+
(select)="onChartSelect(results, $event)">
14+
</ngx-charts-advanced-pie-chart>
15+
</div>
16+
<div class="ui-g-12" *ngIf="dataSource">
17+
<mat-checkbox [(ngModel)]="activeOnly" matTooltip="Shows only active checks in above charts" matTooltipPosition="above">Active Only</mat-checkbox>
18+
<br />
19+
<br />
20+
<mat-form-field class="full">
21+
<input matInput [(ngModel)]="filter" (keyup)="applyFilter()" placeholder="Search">
22+
</mat-form-field>
23+
<div class="mat-elevation-z2">
24+
<table mat-table [dataSource]="dataSource" class="full" matSort #sort="matSort">
25+
<ng-container matColumnDef="name">
26+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
27+
<td mat-cell *matCellDef="let check"> {{check.Name}} </td>
28+
</ng-container>
2429

25-
<ng-container matColumnDef="active">
26-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Active</th>
27-
<td mat-cell *matCellDef="let check">{{check.Active ? "Yes" : "No"}} </td>
28-
</ng-container>
30+
<ng-container matColumnDef="active">
31+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Active</th>
32+
<td mat-cell *matCellDef="let check">{{check.Active ? "Yes" : "No"}} </td>
33+
</ng-container>
2934

30-
<ng-container matColumnDef="group">
31-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Group</th>
32-
<td mat-cell *matCellDef="let check">{{check.GroupID ? checkGroupLookup[check.GroupID].Name : "None"}}</td>
33-
</ng-container>
35+
<ng-container matColumnDef="group">
36+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Group</th>
37+
<td mat-cell *matCellDef="let check">{{check.GroupID ? checkGroupLookup[check.GroupID].Name : "None"}}</td>
38+
</ng-container>
3439

35-
<ng-container matColumnDef="environment">
36-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Environment</th>
37-
<td mat-cell *matCellDef="let check">{{environmentLookup[check.EnvironmentID].Name}}</td>
38-
</ng-container>
40+
<ng-container matColumnDef="environment">
41+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Environment</th>
42+
<td mat-cell *matCellDef="let check">{{environmentLookup[check.EnvironmentID].Name}}</td>
43+
</ng-container>
3944

40-
<ng-container matColumnDef="type">
41-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
42-
<td mat-cell *matCellDef="let check">{{typeLookup[check.TypeID].Name}}</td>
43-
</ng-container>
45+
<ng-container matColumnDef="type">
46+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
47+
<td mat-cell *matCellDef="let check">{{typeLookup[check.TypeID].Name}}</td>
48+
</ng-container>
4449

45-
<ng-container matColumnDef="lastResultStatus">
46-
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last Result Status</th>
47-
<td mat-cell *matCellDef="let check">{{CheckResultStatus[check.LastResultStatus]}}</td>
48-
</ng-container>
50+
<ng-container matColumnDef="lastResultStatus">
51+
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last Result Status</th>
52+
<td mat-cell *matCellDef="let check">{{CheckResultStatus[check.LastResultStatus]}}</td>
53+
</ng-container>
4954

50-
<ng-container matColumnDef="options">
51-
<th mat-header-cell *matHeaderCellDef>Options</th>
52-
<td mat-cell *matCellDef="let check">
53-
<div class="rowbuttons">
54-
<button matTooltip="Edit" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}">
55-
<mat-icon class="md-24">edit</mat-icon>
56-
</button>
57-
<button matTooltip="Copy" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}/copy">
58-
<mat-icon class="md-24">content_copy</mat-icon>
59-
</button>
60-
<button matTooltip="Run" matTooltipPosition="above" mat-icon-button color="primary" (click)="run(check)">
61-
<mat-icon class="md-24">play_arrow</mat-icon>
62-
</button>
63-
</div>
64-
</td>
65-
</ng-container>
55+
<ng-container matColumnDef="options">
56+
<th mat-header-cell *matHeaderCellDef>Options</th>
57+
<td mat-cell *matCellDef="let check">
58+
<div class="rowbuttons">
59+
<button matTooltip="Edit" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}">
60+
<mat-icon class="md-24">edit</mat-icon>
61+
</button>
62+
<button matTooltip="Copy" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}/copy">
63+
<mat-icon class="md-24">content_copy</mat-icon>
64+
</button>
65+
<button matTooltip="Run" matTooltipPosition="above" mat-icon-button color="primary" (click)="run(check)">
66+
<mat-icon class="md-24">play_arrow</mat-icon>
67+
</button>
68+
</div>
69+
</td>
70+
</ng-container>
6671

67-
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
68-
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
69-
</table>
70-
<!--<p-dataTable #dt [value]="checks" [paginator]="true" [rowsPerPageOptions]="[10,25,50,100]" [rows]="25" [responsive]="true" selectionMode="single" (onRowSelect)="onCheckSelected($event)">
71-
<p-column header="Name" field="Name" sortable="true" [filter]="true"></p-column>
72-
<p-column header="Active" field="Active" sortable="true" [filter]="true" filterMatchMode="equals" [style]="{'overflow':'visible'}">
73-
<ng-template pTemplate="filter" let-col>
74-
<p-dropdown [options]="activeOptions" [(ngModel)]="activeOption" [style]="{'width':'100%'}" (onChange)="updateActiveFilter()"
75-
styleClass="ui-column-filter"></p-dropdown>
76-
</ng-template>
77-
<ng-template let-check="rowData" pTemplate="body">
78-
{{check.Active ? "Yes" : "No"}}
79-
</ng-template>
80-
</p-column>
81-
<p-column header="Group" field="GroupID" sortable="true" [filter]="true" filterMatchMode="equals" [style]="{'overflow':'visible'}">
82-
<ng-template pTemplate="filter" let-col>
83-
<p-dropdown [options]="checkGroupOptions" [(ngModel)]="checkGroupOption" [style]="{'width':'100%'}" (onChange)="updateCheckGroupFilter()"
84-
styleClass="ui-column-filter"></p-dropdown>
85-
</ng-template>
86-
<ng-template let-check="rowData" pTemplate="body">
87-
{{check.GroupID ? checkGroupLookup[check.GroupID].Name : "None"}}
88-
</ng-template>
89-
</p-column>
90-
<p-column header="Environment" field="EnvironmentID" sortable="true" [filter]="true" filterMatchMode="equals" [style]="{'overflow':'visible'}">
91-
<ng-template pTemplate="filter" let-col>
92-
<p-dropdown [options]="environmentOptions" [(ngModel)]="environmentOption" [style]="{'width':'100%'}" (onChange)="updateEnvironmentFilter()"
93-
styleClass="ui-column-filter"></p-dropdown>
94-
</ng-template>
95-
<ng-template let-check="rowData" pTemplate="body">
96-
{{environmentLookup[check.EnvironmentID].Name}}
97-
</ng-template>
98-
</p-column>
99-
<p-column header="Type" field="TypeID" sortable="true" [filter]="true" filterMatchMode="equals" [style]="{'overflow':'visible'}">
100-
<ng-template pTemplate="filter" let-col>
101-
<p-dropdown [options]="typeOptions" [(ngModel)]="typeOption" [style]="{'width':'100%'}" (onChange)="updateTypeFilter()"
102-
styleClass="ui-column-filter"></p-dropdown>
103-
</ng-template>
104-
<ng-template let-check="rowData" pTemplate="body">
105-
{{typeLookup[check.TypeID].Name}}
106-
</ng-template>
107-
</p-column>
108-
<p-column header="Last Result Status" field="LastResultStatus" sortable="true" [filter]="true" filterMatchMode="equals" [style]="{'overflow':'visible'}">
109-
<ng-template pTemplate="filter" let-col>
110-
<p-dropdown [options]="resultOptions" [(ngModel)]="resultOption" [style]="{'width':'100%'}" (onChange)="updateResultFilter()"
111-
styleClass="ui-column-filter"></p-dropdown>
112-
</ng-template>
113-
<ng-template let-check="rowData" pTemplate="body">
114-
{{CheckResultStatus[check.LastResultStatus]}}
115-
</ng-template>
116-
</p-column>
117-
<p-column header="Options">
118-
<ng-template let-check="rowData" pTemplate="body">
119-
<div class="rowbuttons">
120-
<button matTooltip="Edit" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}">
121-
<mat-icon class="md-24">edit</mat-icon>
122-
</button>
123-
<button matTooltip="Copy" matTooltipPosition="above" mat-icon-button color="primary" routerLink="/edit/{{check.ID}}/copy">
124-
<mat-icon class="md-24">content_copy</mat-icon>
125-
</button>
126-
<button matTooltip="Run" matTooltipPosition="above" mat-icon-button color="primary" (click)="run(check)">
127-
<mat-icon class="md-24">play_arrow</mat-icon>
128-
</button>
129-
</div>
130-
</ng-template>
131-
</p-column>
132-
</p-dataTable>-->
133-
</div>
134-
</mat-card-content>
135-
</mat-card>
72+
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
73+
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
74+
</table>
75+
<mat-paginator [pageSize]="25" [pageSizeOptions]="[10,25,50,100]"></mat-paginator>
76+
</div>
77+
</div>

SystemChecker.Web/ClientApp/app/services/message.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export class MessageService {
1313
constructor(private snackbar: MatSnackBar, private dialogService: TdDialogService) { }
1414
public addMessage(message: IMessage) {
1515
this.snackbar.open(message.summary, (message.detail ? "Details" : "Okay").toUpperCase(), {
16-
panelClass: message.severity,
16+
panelClass: `snackbar-${message.severity}`,
17+
duration: message.severity == "error" ? 5000 : 2000,
1718
}).onAction().subscribe(() => {
1819
if (message.detail) {
1920
this.dialogService.openAlert({

SystemChecker.Web/ClientApp/styles/main.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ h3, h4 {
2828
max-width: 100% !important;
2929
}
3030

31-
.error {
31+
.snackbar-error {
3232
color: #ffffff;
3333
background-color: #ef5350;
3434

@@ -38,7 +38,7 @@ h3, h4 {
3838
}
3939
}
4040

41-
.success {
41+
.snackbar-success {
4242
color: #ffffff;
4343
background-color: #43a047;
4444

0 commit comments

Comments
 (0)