Introducing filters

This commit is contained in:
Piotr Pekala 2019-08-26 05:17:50 -07:00
parent fee26eff87
commit 801b3ebfac
7 changed files with 120 additions and 44 deletions

View File

@ -1,13 +1,29 @@
<div class="consoleWrapper"> <div class="consoleWrapper">
<div class="consoleHeader"> <div class="consoleHeader">
<span>Console</span> <div>
Console
<mat-form-field>
<mat-label>Select filter</mat-label>
<mat-select [(ngModel)]="selectedFilter" name="filter" (selectionChange)="applyFilter()">
<mat-option *ngFor="let filter of filters" [value]="filter">
{{filter}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="consoleMenu"> <div class="consoleMenu">
<mat-icon (click)="close()" class="closeButton">close</mat-icon> <mat-icon (click)="close()" class="closeButton">close</mat-icon>
</div> </div>
</div> </div>
<div #console class="console">
<span *ngFor="let event of filteredEvents">
{{event.message}} <br/>
</span>
</div>
<div class="divider"></div> <div class="divider"></div>
<div #console class="console"></div>
<div class="divider"></div>
<div class="consoleInput"> <div class="consoleInput">
<mat-icon>keyboard_arrow_right</mat-icon> <mat-icon>keyboard_arrow_right</mat-icon>
<input <input
@ -17,4 +33,5 @@
type="text" type="text"
[(ngModel)]="command"/> [(ngModel)]="command"/>
</div> </div>
<div class="divider"></div>
</div> </div>

View File

@ -3,7 +3,7 @@
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 20px; left: 20px;
height: 120px; height: 180px;
width: 600px; width: 600px;
background: #263238; background: #263238;
color: white; color: white;
@ -13,18 +13,18 @@
.consoleHeader { .consoleHeader {
width: 100%; width: 100%;
height: 24px; height: 50px;
font-size: 12px; font-size: 12px;
overflow: hidden; overflow: hidden;
margin-right: 5px; margin-right: 5px;
display: flex; display: flex;
padding: 2px; padding: 5px;
justify-content: space-between; justify-content: space-between;
} }
.console { .console {
width: 596px; width: 596px;
height: 64px; height: 100px;
overflow-y: scroll; overflow-y: scroll;
margin: 2px; margin: 2px;
color: #dbd5d5; color: #dbd5d5;
@ -34,7 +34,7 @@
.consoleInput { .consoleInput {
width: 100%; width: 100%;
height: 24px; height: 30px;
padding: 2px; padding: 2px;
display: flex; display: flex;
} }
@ -53,11 +53,17 @@
} }
mat-icon { mat-icon {
font-size: 18px; margin-top: 4px;
font-size: 20px;
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
mat-checkbox {
margin-right: 5px;
margin-left: 5px;
}
input:focus{ input:focus{
outline: none; outline: none;
} }

View File

@ -11,6 +11,7 @@ import { Node } from '../../../cartography/models/node';
import { Port } from '../../../models/port'; import { Port } from '../../../models/port';
import { LogEventsDataSource } from './log-events-datasource'; import { LogEventsDataSource } from './log-events-datasource';
import { HttpServer } from '../../../services/http-server.service'; import { HttpServer } from '../../../services/http-server.service';
import { LogEvent } from '../../../models/logEvent';
@Component({ @Component({
@ -29,6 +30,10 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
private serverRequestsSubscription: Subscription; private serverRequestsSubscription: Subscription;
command: string = ''; command: string = '';
filters: string[] = ['all', 'errors', 'warnings', 'map updates', 'server requests'];
selectedFilter: string = 'all';
filteredEvents: LogEvent[] = [];
private regexStart: RegExp = /^start (.*?)$/; private regexStart: RegExp = /^start (.*?)$/;
private regexStop: RegExp = /^stop (.*?)$/; private regexStop: RegExp = /^stop (.*?)$/;
private regexSuspend: RegExp = /^suspend (.*?)$/; private regexSuspend: RegExp = /^suspend (.*?)$/;
@ -47,25 +52,36 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
this.nodeSubscription = this.projectWebServiceHandler.nodeNotificationEmitter.subscribe((event) => { this.nodeSubscription = this.projectWebServiceHandler.nodeNotificationEmitter.subscribe((event) => {
let node: Node = event.event as Node; let node: Node = event.event as Node;
let message = `Event received: ${event.action} - ${this.printNode(node)}.` let message = `Event received: ${event.action} - ${this.printNode(node)}.`
this.showMessage(message); this.showMessage({
type: 'map update',
message: message
});
}); });
this.linkSubscription = this.projectWebServiceHandler.linkNotificationEmitter.subscribe((event) => { this.linkSubscription = this.projectWebServiceHandler.linkNotificationEmitter.subscribe((event) => {
let link: Link = event.event as Link; let link: Link = event.event as Link;
let message = `Event received: ${event.action} - ${this.printLink(link)}.` let message = `Event received: ${event.action} - ${this.printLink(link)}.`
this.showMessage(message); this.showMessage({
type: 'map update',
message: message
});
}); });
this.drawingSubscription = this.projectWebServiceHandler.drawingNotificationEmitter.subscribe((event) => { this.drawingSubscription = this.projectWebServiceHandler.drawingNotificationEmitter.subscribe((event) => {
let drawing: Drawing = event.event as Drawing; let drawing: Drawing = event.event as Drawing;
let message = `Event received: ${event.action} - ${this.printDrawing(drawing)}.` let message = `Event received: ${event.action} - ${this.printDrawing(drawing)}.`
this.showMessage(message); this.showMessage({
type: 'map update',
message: message
});
});
this.serverRequestsSubscription = this.httpService.requestsNotificationEmitter.subscribe((message) => {
this.showMessage({
type: 'server request',
message: message
}); });
this.serverRequestsSubscription = this.httpService.requestsNotificationEmitter.subscribe((event) => {
this.showMessage(event);
}); });
} }
ngAfterViewInit() { ngAfterViewInit() {
this.console.nativeElement.innerHTML = this.logEventsDataSource.getItems()[0] ? this.logEventsDataSource.getItems()[0] : '';
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight; this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
} }
@ -73,6 +89,11 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
this.nodeSubscription.unsubscribe(); this.nodeSubscription.unsubscribe();
this.linkSubscription.unsubscribe(); this.linkSubscription.unsubscribe();
this.drawingSubscription.unsubscribe(); this.drawingSubscription.unsubscribe();
this.serverRequestsSubscription.unsubscribe();
}
applyFilter() {
this.filteredEvents = this.getFilteredEvents();
} }
onKeyDown(event) { onKeyDown(event) {
@ -83,28 +104,28 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
handleCommand() { handleCommand() {
if (this.command === 'help') { if (this.command === 'help') {
this.showMessage("Available commands: help, version, start all, start {node name}, stop all, stop {node name}, suspend all, suspend {node name}, reload all, reload {node name}, show {node name}.") this.showCommand("Available commands: help, version, start all, start {node name}, stop all, stop {node name}, suspend all, suspend {node name}, reload all, reload {node name}, show {node name}.")
} else if (this.command === 'version') { } else if (this.command === 'version') {
this.showMessage("Current version: 2019.2.0"); this.showCommand("Current version: 2019.2.0");
} else if (this.command === 'start all') { } else if (this.command === 'start all') {
this.showMessage("Starting all nodes..."); this.showCommand("Starting all nodes...");
this.nodeService.startAll(this.server, this.project).subscribe(() => { this.nodeService.startAll(this.server, this.project).subscribe(() => {
this.showMessage("All nodes started.") this.showCommand("All nodes started.")
}); });
} else if (this.command === 'stop all') { } else if (this.command === 'stop all') {
this.showMessage("Stopping all nodes..."); this.showCommand("Stopping all nodes...");
this.nodeService.stopAll(this.server, this.project).subscribe(() => { this.nodeService.stopAll(this.server, this.project).subscribe(() => {
this.showMessage("All nodes stopped.") this.showCommand("All nodes stopped.")
}); });
} else if (this.command === 'suspend all') { } else if (this.command === 'suspend all') {
this.showMessage("Suspending all nodes..."); this.showCommand("Suspending all nodes...");
this.nodeService.suspendAll(this.server, this.project).subscribe(() => { this.nodeService.suspendAll(this.server, this.project).subscribe(() => {
this.showMessage("All nodes suspended.") this.showCommand("All nodes suspended.")
}); });
} else if (this.command === 'reload all') { } else if (this.command === 'reload all') {
this.showMessage("Reloading all nodes..."); this.showCommand("Reloading all nodes...");
this.nodeService.reloadAll(this.server, this.project).subscribe(() => { this.nodeService.reloadAll(this.server, this.project).subscribe(() => {
this.showMessage("All nodes reloaded.") this.showCommand("All nodes reloaded.")
}); });
} else if ( } else if (
this.regexStart.test(this.command) || this.regexStop.test(this.command) || this.regexSuspend.test(this.command) || this.regexReload.test(this.command) || this.regexShow.test(this.command)) { this.regexStart.test(this.command) || this.regexStop.test(this.command) || this.regexSuspend.test(this.command) || this.regexReload.test(this.command) || this.regexShow.test(this.command)) {
@ -112,47 +133,66 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
let node = this.nodesDataSource.getItems().find(n => n.name.valueOf() === splittedCommand[1].valueOf()); let node = this.nodesDataSource.getItems().find(n => n.name.valueOf() === splittedCommand[1].valueOf());
if (node) { if (node) {
if (this.regexStart.test(this.command)) { if (this.regexStart.test(this.command)) {
this.showMessage(`Starting node ${splittedCommand[1]}...`); this.showCommand(`Starting node ${splittedCommand[1]}...`);
this.nodeService.start(this.server, node).subscribe(() => this.showMessage(`Node ${node.name} started.`)); this.nodeService.start(this.server, node).subscribe(() => this.showCommand(`Node ${node.name} started.`));
} }
else if (this.regexStop.test(this.command)) { else if (this.regexStop.test(this.command)) {
this.showMessage(`Stopping node ${splittedCommand[1]}...`); this.showCommand(`Stopping node ${splittedCommand[1]}...`);
this.nodeService.stop(this.server, node).subscribe(() => this.showMessage(`Node ${node.name} stopped.`)); this.nodeService.stop(this.server, node).subscribe(() => this.showCommand(`Node ${node.name} stopped.`));
} }
else if (this.regexSuspend.test(this.command)) { else if (this.regexSuspend.test(this.command)) {
this.showMessage(`Suspending node ${splittedCommand[1]}...`); this.showCommand(`Suspending node ${splittedCommand[1]}...`);
this.nodeService.suspend(this.server, node).subscribe(() => this.showMessage(`Node ${node.name} suspended.`)); this.nodeService.suspend(this.server, node).subscribe(() => this.showCommand(`Node ${node.name} suspended.`));
} }
else if (this.regexReload.test(this.command)) { else if (this.regexReload.test(this.command)) {
this.showMessage(`Reloading node ${splittedCommand[1]}...`); this.showCommand(`Reloading node ${splittedCommand[1]}...`);
this.nodeService.reload(this.server, node).subscribe(() => this.showMessage(`Node ${node.name} reloaded.`)); this.nodeService.reload(this.server, node).subscribe(() => this.showCommand(`Node ${node.name} reloaded.`));
} }
else if (this.regexShow.test(this.command)) { else if (this.regexShow.test(this.command)) {
this.showMessage(`Information about node ${node.name}:`); this.showCommand(`Information about node ${node.name}:`);
this.showMessage(this.printNode(node)); this.showCommand(this.printNode(node));
} }
} else { } else {
this.showMessage(`Node with ${splittedCommand[1]} name was not found.`); this.showCommand(`Node with ${splittedCommand[1]} name was not found.`);
} }
} else { } else {
this.showMessage(`Unknown syntax: ${this.command}`); this.showCommand(`Unknown syntax: ${this.command}`);
} }
this.command = ''; this.command = '';
} }
clearConsole() { clearConsole() {
this.console.nativeElement.innerHTML = ''; this.filteredEvents = [];
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight; this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
} }
showMessage(message: string) { showCommand(message: string) {
this.logEventsDataSource.clear(); this.showMessage({
this.logEventsDataSource.add(this.console.nativeElement.innerHTML + message + " <br />"); type: 'command',
message: message
});
}
this.console.nativeElement.innerHTML += message += " <br />"; showMessage(event: LogEvent) {
this.logEventsDataSource.add(event);
this.filteredEvents = this.getFilteredEvents();
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight; this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
} }
getFilteredEvents(): LogEvent[] {
if (this.selectedFilter === 'server requests') {
return this.logEventsDataSource.getItems().filter(n => n.type === 'server request' || n.type === 'command');
} else if (this.selectedFilter === 'errors') {
return this.logEventsDataSource.getItems().filter(n => n.type === 'error' || n.type === 'command');
} else if (this.selectedFilter === 'warnings') {
return this.logEventsDataSource.getItems().filter(n => n.type === 'warning' || n.type === 'command');
} else if (this.selectedFilter === 'map updates') {
return this.logEventsDataSource.getItems().filter(n => n.type === 'map update' || n.type === 'command');
} else {
return this.logEventsDataSource.getItems();
}
}
printNode(node: Node): string { printNode(node: Node): string {
return `command_line: ${node.command_line}, return `command_line: ${node.command_line},
compute_id: ${node.compute_id}, compute_id: ${node.compute_id},

View File

@ -1,9 +1,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { DataSource } from '../../../cartography/datasources/datasource'; import { DataSource } from '../../../cartography/datasources/datasource';
import { LogEvent } from '../../../models/logEvent';
@Injectable() @Injectable()
export class LogEventsDataSource extends DataSource<string> { export class LogEventsDataSource extends DataSource<LogEvent> {
protected getItemKey(log: string) { protected getItemKey(log: LogEvent) {
return log; return log;
} }
} }

View File

@ -136,6 +136,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.settings = this.settingsService.getAll(); this.settings = this.settingsService.getAll();
this.isTopologySummaryVisible = this.mapSettingsService.isTopologySummaryVisible; this.isTopologySummaryVisible = this.mapSettingsService.isTopologySummaryVisible;
this.isConsoleVisible = this.mapSettingsService.isLogConsoleVisible;
this.progressService.activate(); this.progressService.activate();
const routeSub = this.route.paramMap.subscribe((paramMap: ParamMap) => { const routeSub = this.route.paramMap.subscribe((paramMap: ParamMap) => {
@ -275,6 +276,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.ws = new WebSocket(this.projectService.notificationsPath(this.server, project.project_id)); this.ws = new WebSocket(this.projectService.notificationsPath(this.server, project.project_id));
this.ws.onmessage = (event: MessageEvent) => { this.ws.onmessage = (event: MessageEvent) => {
// console.log(event);
this.projectWebServiceHandler.handleMessage(JSON.parse(event.data)); this.projectWebServiceHandler.handleMessage(JSON.parse(event.data));
}; };
@ -406,6 +408,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
public toggleShowConsole(visible: boolean) { public toggleShowConsole(visible: boolean) {
this.isConsoleVisible = visible; this.isConsoleVisible = visible;
this.mapSettingsService.toggleLogConsole(this.isConsoleVisible);
} }
public toggleShowTopologySummary(visible: boolean) { public toggleShowTopologySummary(visible: boolean) {

View File

@ -0,0 +1,4 @@
export class LogEvent {
type: string;
message: string;
}

View File

@ -5,6 +5,7 @@ import { Subject } from 'rxjs';
export class MapSettingsService { export class MapSettingsService {
public isMapLocked = new Subject<boolean>(); public isMapLocked = new Subject<boolean>();
public isTopologySummaryVisible: boolean = false; public isTopologySummaryVisible: boolean = false;
public isLogConsoleVisible: boolean = false;
constructor() {} constructor() {}
@ -15,4 +16,8 @@ export class MapSettingsService {
toggleTopologySummary(value: boolean) { toggleTopologySummary(value: boolean) {
this.isTopologySummaryVisible = value; this.isTopologySummaryVisible = value;
} }
toggleLogConsole(value: boolean) {
this.isLogConsoleVisible = value;
}
} }