Commit b8dd6232 authored by Qianwen's avatar Qianwen
Browse files

restructure

parent 6c33f0cd
Pipeline #563615 passed with stages
in 3 minutes and 30 seconds
......@@ -3,18 +3,14 @@ import { Routes, RouterModule } from '@angular/router';
import { OverviewComponent} from './pages/overview/overview.component';
import { AMSComponent} from './pages/ams/ams.component';
import { DFComponent} from './pages/df/df.component';
import { LoggerComponent} from './pages/logger/logger.component';
const routes: Routes = [
{ path: '', redirectTo: '/overview', pathMatch: 'full'},
{ path: 'overview', component: OverviewComponent },
{ path: 'ams', component: AMSComponent},
{ path: 'ams/:masid', component: AMSComponent},
{ path: 'df', component: DFComponent},
{ path: 'df/:masid', component: DFComponent},
{ path: 'logger', component: LoggerComponent},
{ path: 'logger/:masid', component: LoggerComponent}
];
@NgModule({
......
<app-top-bar></app-top-bar>
<router-outlet></router-outlet>
<div class="w-100">
<app-sidebar></app-sidebar>
<div class="content-container">
<router-outlet></router-outlet>
</div>
</div>
.content-container {
padding-left: 14rem;
}
......@@ -7,9 +7,9 @@ import { AppComponent } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { OverviewComponent } from './pages/overview/overview.component';
import { AMSComponent } from './pages/ams/ams.component';
import { LoggerComponent } from './pages/logger/logger.component';
import { DFComponent } from './pages/df/df.component';
import { TopBarComponent } from './pages/top-bar/top-bar.component';
import { LoggerModule } from './pages/logger/logger.module';
import { SharedModule } from './pages/shared/shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgxMatTimepickerModule } from 'ngx-mat-timepicker';
......@@ -23,6 +23,8 @@ import { MatSelectModule } from '@angular/material/select';
import { MatIconModule } from '@angular/material/icon';
const materialModules = [
MatDatepickerModule,
MatNativeDateModule,
......@@ -37,9 +39,7 @@ const materialModules = [
AppComponent,
OverviewComponent,
AMSComponent,
LoggerComponent,
DFComponent,
TopBarComponent
],
imports: [
BrowserModule,
......@@ -52,7 +52,9 @@ const materialModules = [
...materialModules,
NgxMatTimepickerModule,
NgxChartsModule,
NgxPaginationModule
NgxPaginationModule,
LoggerModule,
SharedModule,
],
providers: [],
bootstrap: [AppComponent]
......
<div class="sidebar">
<div class="nav">
<div class="nav-item" *ngFor="let id of MASID, index as i" routerLinkActive="is-active" [ngClass]="id === selectedMASID ? 'active' : ''">
<a class="list-text" [routerLink]="['/ams', id]" >
<p > MAS {{ id }}</p>
</a>
</div>
</div>
</div>
<div class="pl-5">
<div class="title my-4">Config</div>
<table class="table table-striped mb-5 default-fontsize" style="width: 40rem;">
<tbody>
<tr>
<th>Id</th>
<td>{{selectedMAS.id}}</td>
</tr>
<tr>
<th>Name</th>
<td>{{ selectedMAS.config.name }}</td>
</tr>
<tr>
<th>Agents per agency</th>
<td>{{ selectedMAS.config.agentsperagency}}</td>
</tr>
<tr>
<th>DF</th>
<td>{{selectedMAS.config.df.active}}</td>
</tr>
<tr>
<th>Logging</th>
<td>{{selectedMAS.config.logger.active}}</td>
</tr>
<tr>
<th>MQTT</th>
<td>{{ selectedMAS.config.mqtt.active}}</td>
</tr>
</tbody>
</table>
<div *ngIf="selectedMAS === null" class="content-container d-flex justify-content-center align-items-center">
<h1>No MAS selected, select one...</h1>
</div>
<div *ngIf="selectedMAS !== null" class="content-container justify-content-center align-items-center" style="width: 80%;">
<div class="title my-4">Config</div>
<table class="table table-striped mb-5 default-fontsize" style="width: 40rem;">
<tbody>
<tr>
<th>Id</th>
<td>{{selectedMAS.id}}</td>
</tr>
<tr>
<th>Name</th>
<td>{{ selectedMAS.config.name }}</td>
</tr>
<tr>
<th>Agents per agency</th>
<td>{{ selectedMAS.config.agentsperagency}}</td>
</tr>
<tr>
<th>DF</th>
<td>{{selectedMAS.config.df.active}}</td>
</tr>
<tr>
<th>Logging</th>
<td>{{selectedMAS.config.logger.active}}</td>
</tr>
<tr>
<th>MQTT</th>
<td>{{ selectedMAS.config.mqtt.active}}</td>
</tr>
</tbody>
</table>
<div class="title mb-4">Containers</div>
<table class="table mb-5 default-fontsize">
<thead>
<th>#</th>
<th>Image</th>
<th>Agencies</th>
</thead>
<tbody>
<tr *ngFor="let image of selectedMAS.imagegroups.instances, index as i" >
<th>{{image.id}}</th>
<td>{{image.config.image}}</td>
<td>{{image.agencies.counter}}</td>
</tr>
</tbody>
</table>
<div class="title mb-4">Agents</div>
<div>
<table class="table mb-5 default-fontsize">
<thead>
<th>#</th>
<th>Name</th>
<th>Type</th>
<th>Agency</th>
</thead>
<tbody>
<tr *ngFor="let agent of selectedMAS.agents.instances | paginate: { itemsPerPage: 12, currentPage: q } index as i;">
<th> {{agent.id}}</th>
<td>{{agent.spec.name}}</td>
<td>{{agent.spec.type}}</td>
<td>{{agent.address.agency}}</td>
</tr>
</tbody>
</table>
<div class="title mb-4">Containers</div>
<table class="table mb-5 default-fontsize">
<thead>
<th>#</th>
<th>Image</th>
<th>Agencies</th>
</thead>
<tbody>
<tr *ngFor="let image of selectedMAS.imagegroups.instances, index as i" >
<th>{{image.id}}</th>
<td>{{image.config.image}}</td>
<td>{{image.agencies.counter}}</td>
</tr>
</tbody>
</table>
<div class="d-flex justify-content-end pr-5">
<pagination-controls class="pagination" (pageChange)="q = $event"></pagination-controls>
</div>
</div>
</div>
<div class="title mb-4">Agents</div>
<table class="table mb-5 default-fontsize">
<thead>
<th>#</th>
<th>Name</th>
<th>Type</th>
<th>Agency</th>
</thead>
<tbody>
<tr *ngFor="let agent of selectedMAS.agents.instances | paginate: { itemsPerPage: 12, currentPage: q };">
<th> {{agent.id}}</th>
<td>{{agent.spec.name}}</td>
<td>{{agent.spec.type}}</td>
<td>{{agent.address.agency}}</td>
</tr>
</tbody>
</table>
<div class="d-flex justify-content-end align-items-center">
<pagination-controls class="pagination" (pageChange)="q = $event"></pagination-controls>
</div>
</div>
......
@import 'src/styles.scss' ;
/* .table-striped > tbody > tr:nth-child(2n+1) > td, .table-striped > tbody > tr:nth-child(2n+1) > th {
background-color: $background-primary-color;
......@@ -25,9 +26,7 @@ td, th {
background: var(--secondary);
}
.content-container {
padding-left: 4rem;
}
......
......@@ -12,6 +12,7 @@ export class AMSComponent implements OnInit {
MASID: number[] = [];
selectedMASID: number = -1;
selectedMAS: any = null;
q: number = 1;
constructor(
private masService: MasService,
......@@ -20,18 +21,6 @@ export class AMSComponent implements OnInit {
ngOnInit() {
// get the information for the sidebar
this.masService.getMAS().subscribe((MASs: any) => {
this.MASID = []
if (MASs !== null) {
for (let MAS of MASs) {
if (MAS.status.code != 5) {
this.MASID.push(MAS.id)
}
}
}
});
// get the concrete content of the selected MAS
this.route.params.subscribe(
(params: Params) => {
......
<!--sidebar-->
<div class="sidebar" *ngIf="MASID.length !== 0">
<div class="nav">
<div class="nav-item" *ngFor="let id of MASID, index as i" routerLinkActive="is-active" [ngClass]="id === selectedMASID ? 'active' : ''">
<a class="list-text" [routerLink]="['/df', id]" >
<p > MAS {{ id }}</p>
</a>
</div>
</div>
</div>
<ul class="nav nav-tabs justify-content-end">
<li class="nav-item" >
<a class="nav-link" [class.active]="curr_state==='list'" (click)="onClickList()" >list</a>
</li>
<li class="nav-item" style="padding-right:10rem;">
<a class="nav-link" [class.active]="curr_state==='graph'" (click)="onClickGraph()">graph</a>
</li>
</ul>
<div class="content-container">
<div class="notalive" *ngIf="!alive" >
<h1 text-primary>DF is not alive......</h1>
<div class="d-flex-column align-items-center justify-content-center" *ngIf="curr_state === 'list'">
<div class="inputs d-flex justify-content-center align-items-center">
<input #desc type="text" class="input" id="searchDesc" placeholder="Enter the description"/>
<input #nodeid type="text" class="input" id="searchNode" placeholder="Enter the node ID"/>
<input #dist type="text" class="input" id="searchDist" placeholder="Enter the distance"/>
<button class="btn btn-secondary" type="submit" (click)="onSearchSvcs(desc.value, nodeid.value, dist.value)">
<i class="fas fa-search fa-2x"></i>
</button>
</div>
<div class="alive" *ngIf="alive">
<ul class="nav nav-tabs justify-content-end">
<li class="nav-item" >
<a class="nav-link" [class.active]="curr_state==='list'" (click)="onClickList()" >list</a>
</li>
<li class="nav-item" style="padding-right:10rem;">
<a class="nav-link" [class.active]="curr_state==='graph'" (click)="onClickGraph()">graph</a>
</li>
</ul>
<div class="d-flex-column align-items-center justify-content-center" *ngIf="curr_state === 'list'">
<div class="inputs d-flex justify-content-center align-items-center">
<input #desc type="text" class="input" id="searchDesc" placeholder="Enter the description"/>
<input #nodeid type="text" class="input" id="searchNode" placeholder="Enter the node ID"/>
<input #dist type="text" class="input" id="searchDist" placeholder="Enter the distance"/>
<button class="btn btn-secondary" type="submit" (click)="onSearchSvcs(desc.value, nodeid.value, dist.value)">
<i class="fas fa-search fa-2x"></i>
</button>
</div>
<div class="empty-service" *ngIf="searched_results === null">
<h1>No services found</h1>
</div>
<div class="services" *ngIf="searched_results !== null && searched_results.length !== 0">
<table class="table table-striped default-fontsize">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">MAS ID</th>
<th scope="col">Agent ID</th>
<th scope="col">Node ID</th>
<th scope="col">Description</th>
<th scope="col">Create Date</th>
<th scope="col">Change Date</th>
<th scope="col">Dist</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let res of searched_results | paginate: { itemsPerPage: 20, currentPage: q }; index as i ">
<th>{{i+1}}</th>
<td>{{res.masid}}</td>
<td>{{res.agentid}}</td>
<td>{{res.nodeid}}</td>
<td>{{res.desc}}</td>
<td>{{res.createdat}}</td>
<td>{{res.changedat}}</td>
<td>{{res.dist}}</td>
</tbody>
</table>
<div class="pagination mt-4 d-flex justify-content-center align-items-center">
<pagination-controls (pageChange)="q = $event"></pagination-controls>
</div>
</div>
</div>
<div class="content" [hidden]="curr_state === 'list'">
<div id="graph">
</div>
</div>
<div class="empty-service" *ngIf="searched_results === null">
<h1>No services found</h1>
</div>
<div class="services" *ngIf="searched_results !== null && searched_results.length !== 0">
<table class="table table-striped default-fontsize">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">MAS ID</th>
<th scope="col">Agent ID</th>
<th scope="col">Node ID</th>
<th scope="col">Description</th>
<th scope="col">Create Date</th>
<th scope="col">Change Date</th>
<th scope="col">Dist</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let res of searched_results | paginate: { itemsPerPage: 20, currentPage: q }; index as i ">
<th>{{i+1}}</th>
<td>{{res.masid}}</td>
<td>{{res.agentid}}</td>
<td>{{res.nodeid}}</td>
<td>{{res.desc}}</td>
<td>{{res.createdat}}</td>
<td>{{res.changedat}}</td>
<td>{{res.dist}}</td>
</tbody>
</table>
<div class="pagination mt-4 d-flex justify-content-center align-items-center">
<pagination-controls (pageChange)="q = $event"></pagination-controls>
</div>
</div>
</div>
<div class="content" [hidden]="curr_state === 'list'">
<div id="graph">
</div>
</div>
......@@ -16,9 +16,6 @@ cytoscape.use( popper);
})
export class DFComponent implements OnInit {
selectedMASID:number = -1;
MASID: any = [];
alive: boolean = true;
fileToUpload: File = null;
display: string = "";
filename: string = "Choose a file...";
searched_results: Service[] = [];
......@@ -31,25 +28,6 @@ export class DFComponent implements OnInit {
) { }
ngOnInit() {
this.dfService.getAlive().subscribe( (res: any) => {
this.alive = res.df;
}, error => {
console.log(error);
});
// update the sidebar
this.masService.getMAS().subscribe((MASs: any) => {
if (MASs !== null) {
for (let MAS of MASs) {
if (MAS.status.code != 5) {
this.MASID.push(MAS.id)
}
}
}
}, err => {
console.log(err)
});
this.route.params.subscribe((params: Params) => {
if (params.masid) {
this.selectedMASID = params.masid;
......
<app-tabs></app-tabs>
<!--selection board -->
<div class="my-5 d-flex justify-content-center">
<app-period-selector #periodSelector></app-period-selector>
<mat-form-field appearance="fill" class="mr-4" style="width: 20rem;">
<mat-label>Automatic partition?</mat-label>
<mat-select (selectionChange)="updatePartition($event.value)">
<mat-option value="Yes">Yes</mat-option>
<mat-option value="No">No</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill" class="mr-4" [hidden]="autoPartition" style="width: 10rem;">
<mat-label>Partitions</mat-label>
<input matInput (change)="getPartitionNum($event.target.value)" placeholder="5">
</mat-form-field>
<i class="fas fa-search fa-2x mt-3 mr-5" (click)="onClickSearchButton(
periodSelector.selectedStartDate,
periodSelector.selectedEndDate,
periodSelector.selectedStartTime,
periodSelector.selectedEndTime
)"></i>
</div>
<ng-template #popContent >
<div class="default-fontsize" *ngFor="let content of popoverContent">
{{content}}
</div>
</ng-template>
<div class="d-flex justify-content-center">
<svg class="heatmap" width="1000" height="800" >
<rect class="grid" *ngFor="let grid of grids, index as i"
[attr.fill]="grid.color"
[attr.x]="grid.x * gridWidth"
[attr.y]="grid.y * gridWidth"
[attr.width]="gridWidth"
[attr.height]="gridWidth"
(mouseenter)="onEnterGrid(i)"
(mouseleave)="onLeaveGrid(i)"
triggers="mouseenter:mouseleave"
[ngbPopover]="popFrequency"
placement="top"
container="body"
></rect>
<rect *ngFor="let legend of colorPartitionEle, index as i"
[attr.x] = "700"
[attr.y]= "(legendWidth + 10) * i + 50"
[attr.width]="legendWidth"
[attr.height]="legendWidth"
[attr.fill]="legend"
></rect>
<text *ngFor="let text of colorLegendTexts, index as i"
[attr.x] = "750"
[attr.y]= "(legendWidth + 10) * i + 70"
[attr.fill]="gray"
> {{text}}</text>
<!-- <text class="xlabel" x="350" y="730"> agent ID of sender</text>
<text class="ylabel" x="-10" y="350"> agent ID of receiver</text> -->
</svg>
</div>
<ng-template #popFrequency class="heatmap-popover" >
<div class="default-fontsize"> Agent Send: {{ popoverFrequency.x }} </div>
<div class="default-fontsize"> Agent Receive : {{ popoverFrequency.y }} </div>
<div class="default-fontsize"> Msg Count :{{ popoverFrequency.value }} </div>
</ng-template>
\ No newline at end of file
/* heatmap */
.heatmap-legend{
background-color: red;
}
.xlabel {
font-size: 2rem;
fill: gray;
}
.ylabel {
font-size: 2rem;
fill: gray;
/* transform: rotate(90deg); */
transform-box: fill-box;
transform-origin: center;
transform: rotate(-90deg);
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeatmapComponent } from './heatmap.component';
describe('HeatmapComponent', () => {
let component: HeatmapComponent;
let fixture: ComponentFixture<HeatmapComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HeatmapComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeatmapComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { LoggerService} from 'src/app/services/logger.service';
import { Router, Event, NavigationEnd } from '@angular/router';
@Component({
selector: 'app-heatmap',
templateUrl: './heatmap.component.html',
styleUrls: ['./heatmap.component.scss']
})
export class HeatmapComponent implements OnInit {
selectedMASID: number = -1;
gridColors: string[] = [];
grids: any[] = [];
gridWidth: number = 4;
popoverFrequency: any = {};
autoPartition: boolean = false;
partitionNum: number = 5;
colorPartitionEle: string[] = [];
colorLegendTexts: string[] = [];
legendWidth = 30;
constructor(
private loggerService: LoggerService,