Skip to content

Commit e425791

Browse files
authored
Merge pull request #125 from delphi-hub/feature/informationCenter
Feature/information center
2 parents 9174864 + be812ac commit e425791

16 files changed

+884
-645
lines changed

client/package-lock.json

Lines changed: 631 additions & 533 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"bootstrap": "^4.3.1",
2828
"core-js": "^2.6.5",
2929
"cytoscape": "^3.5.0",
30-
"cytoscape-edgehandles": "^3.5.0",
30+
"cytoscape-edgehandles": "^3.5.1",
3131
"font-awesome": "^4.7.0",
3232
"hammerjs": "^2.0.8",
3333
"jquery": "^3.3.1",
@@ -39,13 +39,14 @@
3939
"devDependencies": {
4040
"@angular-devkit/build-angular": "^0.12.4",
4141
"@angular/cli": "^7.3.5",
42-
"@angular/compiler-cli": "^7.2.8",
42+
"@angular/compiler-cli": "^7.2.9",
4343
"@angular/language-service": "^7.2.8",
4444
"@types/cytoscape": "^3.3.0",
4545
"@types/jasmine": "^3.3.9",
4646
"@types/jasminewd2": "^2.0.6",
4747
"@types/node": "^10.12.30",
4848
"codelyzer": "^4.5.0",
49+
"jasmine": "^2.99.0",
4950
"jasmine-core": "^3.3.0",
5051
"jasmine-spec-reporter": "^4.2.1",
5152
"karma": "^3.1.4",

client/src/app/api/api/socket.service.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818

1919
import {Injectable} from '@angular/core';
20-
import {Observable, Observer, Subject} from 'rxjs';
20+
import {Observable, Subject} from 'rxjs';
2121
import {
2222
DockerOperationError,
2323
EventType,
@@ -88,7 +88,6 @@ export class SocketService {
8888
* @param eventName
8989
*/
9090
public subscribeForEvent<T extends ReturnType>(eventName: EventType): Observable<T> {
91-
return new Observable<T>((observer: Observer<T>) => {
9291

9392
/**
9493
* First step to subscribe for an event is to append the new observer to the set
@@ -113,19 +112,8 @@ export class SocketService {
113112

114113
this.send({event: publishEventName});
115114
}
116-
this.observers[eventName].subscribe(observer);
117115

118-
this.socket.addEventListener('message', (e: MessageEvent) => this.socketOnMessage(e));
119-
120-
/**
121-
* If an observable stream ends the observer is removed from the
122-
* observer list and the list is deleted if it is empty.
123-
*/
124-
return () => {
125-
// TODO: see console log
126-
console.log('observer completed, implement unsubscribe logic !');
127-
};
128-
});
116+
return (this.observers[eventName].asObservable() as Observable<T>);
129117
}
130118

131119
/**
@@ -244,7 +232,10 @@ export class SocketService {
244232
*/
245233
public initSocket(): Promise<void> {
246234
if (this.socket === null) {
235+
247236
this.socket = new WebSocket(this.wsUri);
237+
this.socket.addEventListener('message', (e: MessageEvent) => this.socketOnMessage(e));
238+
248239
setInterval(() => {
249240
this.send({event: EventTypeEnum.Heartbeat});
250241
}, 5000);

client/src/app/dashboard/dashboard-overview/dashboard-overview.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ <h2 class="alignHeading">System Overview</h2>
4040
<div class="col-md-4 col-sm-4">
4141
<div class="row">
4242
<div class=" col-md-12 col-sm-2">
43-
<app-infor-center></app-infor-center>
43+
<app-info-center></app-info-center>
4444
</div>
4545
<div class=" col-md-8 col-sm-2 topSpace">
4646
<app-statuscard></app-statuscard>
4747
</div>
4848
</div>
4949
</div>
5050
</div>
51-
</div>
51+
</div>

client/src/app/dashboard/dashboard-overview/dashboard-overview.component.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,20 @@ import { StatusCardComponent } from '../status-card/status-card.component';
2323
import { DashboardCardComponent } from '../dashboard-card/dashboard-card.component';
2424
import { RouterModule } from '@angular/router';
2525
import { MaterialModule } from '../../material-module/material.module';
26-
import { InforCenterComponent } from '../infor-center/infor-center.component';
26+
import { InfoCenterComponent} from '../info-center/info-center.component';
2727
import { GraphViewModule} from '../graph-view/graph-view.module';
2828
import { DashboardOverviewComponent } from './dashboard-overview.component';
29+
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
30+
2931

3032
describe('DashboardOverviewComponent', () => {
3133
let component: DashboardOverviewComponent;
3234
let fixture: ComponentFixture<DashboardOverviewComponent>;
3335

3436
beforeEach(async(() => {
3537
TestBed.configureTestingModule({
36-
declarations: [ DashboardOverviewComponent, DashboardCardComponent, StatusCardComponent, InforCenterComponent],
37-
imports: [RouterModule, HttpClientModule, RouterTestingModule, MaterialModule, GraphViewModule]
38+
declarations: [ DashboardOverviewComponent, DashboardCardComponent, StatusCardComponent, InfoCenterComponent],
39+
imports: [RouterModule, HttpClientModule, RouterTestingModule, MaterialModule, GraphViewModule, NoopAnimationsModule]
3840
})
3941
.compileComponents();
4042
}));
@@ -48,9 +50,8 @@ describe('DashboardOverviewComponent', () => {
4850
fixture.destroy();
4951
});
5052

51-
52-
5353
it('should create', () => {
5454
expect(component).toBeTruthy();
5555
});
56+
5657
});

client/src/app/dashboard/dashboard.component.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { RouterTestingModule } from '@angular/router/testing';
2323
import { HeaderComponent } from './header/header.component';
2424
import { DashboardComponent } from './dashboard.component';
2525

26-
2726
describe('component: DashboardComponent', () => {
2827

2928
let location: Location, router: Router;
@@ -38,7 +37,6 @@ describe('component: DashboardComponent', () => {
3837
])
3938
],
4039
declarations: [ DashboardComponent, HeaderComponent],
41-
4240
});
4341
});
4442

client/src/app/dashboard/dashboard.module.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ import {ApiModule} from '../api/api.module';
3939
import {ModelModule} from '../model/model.module';
4040
import { MaterialModule } from '../material-module/material.module';
4141
import { GraphViewModule } from './graph-view/graph-view.module';
42-
import { InforCenterComponent } from './infor-center/infor-center.component';
4342
import { InstanceDetailsComponent } from './instance-details/instance-details.component';
4443
import { TableOverviewComponent } from './table-overview/table-overview.component';
44+
import { InfoCenterComponent } from './info-center/info-center.component';
45+
import {MatTableModule, MatPaginatorModule, MatSortModule, MatIconModule} from '@angular/material';
4546
import { LabelDialogComponent } from './label-dialog/label-dialog.component';
4647

47-
4848
@NgModule({
4949
imports: [
5050
BrowserModule,
@@ -57,7 +57,11 @@ import { LabelDialogComponent } from './label-dialog/label-dialog.component';
5757
DashboardRoutingModule,
5858
ApiModule,
5959
ModelModule,
60-
GraphViewModule
60+
GraphViewModule,
61+
MatTableModule,
62+
MatPaginatorModule,
63+
MatSortModule,
64+
MatIconModule
6165
],
6266
declarations: [
6367
DashboardCardComponent,
@@ -73,9 +77,9 @@ import { LabelDialogComponent } from './label-dialog/label-dialog.component';
7377
UserManagementComponent,
7478
DeleteDialogComponent,
7579
AddDialogComponent,
76-
InforCenterComponent,
7780
InstanceDetailsComponent,
7881
TableOverviewComponent,
82+
InfoCenterComponent,
7983
LabelDialogComponent
8084
],
8185
entryComponents: [
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { DataSource } from '@angular/cdk/collections';
2+
import { MatPaginator, MatSort } from '@angular/material';
3+
import { map } from 'rxjs/operators';
4+
import { Observable, of as observableOf, merge } from 'rxjs';
5+
6+
export interface InfoCenterItem {
7+
instanceId: number;
8+
type: string;
9+
notifName: string;
10+
dateTime: string;
11+
details: string;
12+
}
13+
14+
const DATA: InfoCenterItem[] = [];
15+
16+
/**
17+
* Data source for the InfoCenter view. This class should
18+
* encapsulate all logic for fetching and manipulating the displayed data
19+
* (including sorting, pagination, and filtering).
20+
*/
21+
export class InfoCenterDataSource extends DataSource<InfoCenterItem> {
22+
data: InfoCenterItem[] = DATA;
23+
24+
constructor(private paginator: MatPaginator, private sort: MatSort) {
25+
super();
26+
}
27+
28+
/**
29+
* Connect this data source to the table. The table will only update when
30+
* the returned stream emits new items.
31+
* @returns A stream of the items to be rendered.
32+
*/
33+
connect(): Observable<InfoCenterItem[]> {
34+
// Combine everything that affects the rendered data into one update
35+
// stream for the data-table to consume.
36+
const dataMutations = [
37+
observableOf(this.data),
38+
this.paginator.page,
39+
];
40+
41+
// Set the paginator's length
42+
this.paginator.length = this.data.length;
43+
44+
return merge(...dataMutations).pipe(map(() => {
45+
return this.getPagedData(this.getSortedData([...this.data]));
46+
}));
47+
}
48+
49+
/**
50+
* Called when the table is being destroyed. Use this function, to clean up
51+
* any open connections or free any held resources that were set up during connect.
52+
*/
53+
disconnect() {}
54+
55+
/**
56+
* Paginate the data (client-side). If you're using server-side pagination,
57+
* this would be replaced by requesting the appropriate data from the server.
58+
*/
59+
private getPagedData(data: InfoCenterItem[]) {
60+
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
61+
return data.splice(startIndex, this.paginator.pageSize);
62+
}
63+
64+
/**
65+
* Sort the data (client-side). If you're using server-side sorting,
66+
* this would be replaced by requesting the appropriate data from the server.
67+
*/
68+
private getSortedData(data: InfoCenterItem[]) {
69+
if (!this.sort.active || this.sort.direction === '') {
70+
return data;
71+
}
72+
73+
return data.sort((a, b) => {
74+
const isAsc = this.sort.direction === 'asc';
75+
switch (this.sort.active) {
76+
case 'name': return compare(a.notifName, b.notifName, isAsc);
77+
case 'id': return compare(+a.dateTime, +b.dateTime, isAsc);
78+
default: return 0;
79+
}
80+
});
81+
}
82+
public add(element: InfoCenterItem) {
83+
this.data.push(element);
84+
}
85+
}
86+
87+
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
88+
function compare(a: string | number, b: string | number, isAsc: boolean) {
89+
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
90+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.full-width-table {
2+
width: 100%;
3+
}
4+
5+
.infoCenter{
6+
border: 1px solid black;
7+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<h4>Information Center</h4>
2+
<div class="mat-elevation-z8" [ngClass]="'infoCenter'">
3+
<mat-table #table class="full-width-table" [dataSource]="dataSource" matSort aria-label="Elements">
4+
<!-- type Column -->
5+
<ng-container matColumnDef="type">
6+
<mat-header-cell *matHeaderCellDef mat-sort-header>Type</mat-header-cell>
7+
<mat-cell *matCellDef="let row"><mat-icon>{{row.type}}</mat-icon></mat-cell>
8+
</ng-container>
9+
10+
<!-- Name notif Column -->
11+
<ng-container matColumnDef="notifName">
12+
<mat-header-cell *matHeaderCellDef mat-sort-header>Notification</mat-header-cell>
13+
<mat-cell *matCellDef="let row">{{row.notifName}}</mat-cell>
14+
</ng-container>
15+
16+
<!-- Date name Column -->
17+
<ng-container matColumnDef="dateTime">
18+
<mat-header-cell *matHeaderCellDef mat-sort-header>Date and Time</mat-header-cell>
19+
<mat-cell *matCellDef="let row">{{row.dateTime}}</mat-cell>
20+
</ng-container>
21+
22+
23+
<!-- Details Column -->
24+
<ng-container matColumnDef="details">
25+
<mat-header-cell *matHeaderCellDef mat-sort-header>Details</mat-header-cell>
26+
<mat-cell *matCellDef="let row">{{row.details}}</mat-cell>
27+
</ng-container>
28+
29+
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
30+
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
31+
</mat-table>
32+
33+
<mat-paginator #paginator
34+
[length]="dataSource.data.length"
35+
[pageIndex]="0"
36+
[pageSize]="5"
37+
[pageSizeOptions]="[5, 10, 25, 100]">
38+
</mat-paginator>
39+
</div>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
3+
import { MatPaginatorModule, MatSortModule, MatTableModule, MatIconModule } from '@angular/material';
4+
5+
import { InfoCenterComponent } from './info-center.component';
6+
import {SocketService} from '../../api/api/socket.service';
7+
8+
describe('InfoCenterComponent', () => {
9+
let component: InfoCenterComponent;
10+
let fixture: ComponentFixture<InfoCenterComponent>;
11+
12+
beforeEach(async(() => {
13+
TestBed.configureTestingModule({
14+
declarations: [ InfoCenterComponent],
15+
imports: [
16+
NoopAnimationsModule,
17+
MatPaginatorModule,
18+
MatSortModule,
19+
MatTableModule,
20+
MatIconModule,
21+
]
22+
23+
}).compileComponents();
24+
}));
25+
26+
beforeEach(() => {
27+
fixture = TestBed.createComponent(InfoCenterComponent);
28+
component = fixture.componentInstance;
29+
});
30+
31+
it('should compile', () => {
32+
expect(component).toBeTruthy();
33+
});
34+
});

0 commit comments

Comments
 (0)