info and protocols

This commit is contained in:
Michele Artini 2023-01-20 11:39:34 +01:00
parent 737a43ff82
commit 93560e881e
19 changed files with 297 additions and 199 deletions

View File

@ -1,9 +1,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { InfoComponent } from './info/info.component'; import { InfoComponent } from './info/info.component';
import { ProtocolsComponent } from './protocols/protocols.component';
const routes: Routes = [ const routes: Routes = [
{path:"info", component:InfoComponent} { path:"info" , component:InfoComponent},
{ path:"adv_resources/protocol" , component:ProtocolsComponent}
]; ];
@NgModule({ @NgModule({

View File

@ -0,0 +1,18 @@
.sidenav-container {
height: 100%;
}
.sidenav {
width: 400px;
}
.sidenav .mat-toolbar {
background: inherit;
}
.mat-toolbar.mat-primary {
position: sticky;
top: 0;
z-index: 1;
}

View File

@ -1,5 +1,27 @@
<app-main-container></app-main-container> <mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<app-main-menu-tree></app-main-menu-tree>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>{{title}}</span>
</mat-toolbar>
<!-- The routed views render in the <router-outlet>-->
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>

View File

@ -1,8 +1,44 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { LayoutModule } from '@angular/cdk/layout';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatToolbarModule } from '@angular/material/toolbar';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [
NoopAnimationsModule,
LayoutModule,
MatButtonModule,
MatIconModule,
MatListModule,
MatSidenavModule,
MatToolbarModule,
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should compile', () => {
expect(component).toBeTruthy();
});
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ imports: [
@ -33,3 +69,6 @@ describe('AppComponent', () => {
expect(compiled.querySelector('.content span')?.textContent).toContain('dnet-is-application app is running!'); expect(compiled.querySelector('.content span')?.textContent).toContain('dnet-is-application app is running!');
}); });
}); });

View File

@ -1,5 +1,8 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { TitleStrategy } from '@angular/router'; import { TitleStrategy } from '@angular/router';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -7,6 +10,14 @@ import { TitleStrategy } from '@angular/router';
styleUrls: ['./app.component.css'] styleUrls: ['./app.component.css']
}) })
export class AppComponent { export class AppComponent {
title = 'dnet-is-application'; title = 'D-NET Information Service Application';
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
constructor(private breakpointObserver: BreakpointObserver) {}
} }

View File

@ -14,24 +14,22 @@ import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav'; import { MatSidenavModule } from '@angular/material/sidenav';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import {FlatTreeControl} from '@angular/cdk/tree'; import { MatTreeModule} from '@angular/material/tree';
import {MatTree, MatTreeFlatDataSource, MatTreeFlattener, MatTreeNode, MatTreeModule} from '@angular/material/tree';
import { MainContainerComponent } from './main-container/main-container.component';
import { MainMenuTreeComponent } from './main-menu-tree/main-menu-tree.component'; import { MainMenuTreeComponent } from './main-menu-tree/main-menu-tree.component';
import { MatBadgeModule } from '@angular/material/badge'; import { MatBadgeModule } from '@angular/material/badge';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import {MatFormFieldModule} from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input' import { MatInputModule } from '@angular/material/input'
import {MatTableModule} from '@angular/material/table'; import { MatTableModule } from '@angular/material/table';
import { ProtocolsComponent } from './protocols/protocols.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
InfoComponent, InfoComponent,
DatafilterPipe, DatafilterPipe,
MainContainerComponent, MainMenuTreeComponent,
MainMenuTreeComponent ProtocolsComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -1,79 +1,80 @@
<div class="infoPage"> <mat-card>
<mat-card-header>
<h1>Container Info </h1> <mat-card-title>Container Info</mat-card-title>
</mat-card-header>
<mat-form-field> <mat-card-content>
<mat-form-field style="margin-top: 3em; width: 100%;">
<mat-label>Filter</mat-label> <mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event)" placeholder="Filter..." #input> <input matInput (keyup)="applyFilter($event)" placeholder="Filter..." #input />
</mat-form-field> </mat-form-field>
<ng-container *ngFor="let section of kvDatasources"> <div *ngFor="let section of kvDatasources">
<mat-card *ngIf="section.datasource.filteredData.length > 0"> <div style="margin-top: 3em;" *ngIf="section.datasource.filteredData.length > 0">
<mat-card-header> <h3>{{section.name}}</h3>
<mat-card-title>{{section.name}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<table mat-table [dataSource]="section.datasource" class="mat-elevation-z8"> <table mat-table [dataSource]="section.datasource" class="mat-elevation-z8">
<ng-container matColumnDef="k"> <ng-container matColumnDef="k">
<th mat-header-cell *matHeaderCellDef> Property </th> <th mat-header-cell *matHeaderCellDef> Property </th>
<td mat-cell *matCellDef="let element"> {{element.k}} </td> <td mat-cell *matCellDef="let element"> {{element.k}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="v"> <ng-container matColumnDef="v">
<th mat-header-cell *matHeaderCellDef> Value </th> <th mat-header-cell *matHeaderCellDef> Value </th>
<td mat-cell *matCellDef="let element"> {{element.v}} </td> <td mat-cell *matCellDef="let element"> {{element.v}} </td>
</ng-container> </ng-container>
<tr mat-row *matRowDef="let row; columns: displayedKVColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedKVColumns;"></tr>
<!-- Row shown when there is no matching data. -->
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="2">No data matching the filter "{{input.value}}"</td>
</tr>
</table>
</div>
</div>
<div style="margin-top: 3em;" *ngIf="moduleDatasource.filteredData.length > 0">
<h3>Modules</h3>
<table mat-table [dataSource]="moduleDatasource" class="mat-elevation-z8">
<ng-container matColumnDef="group">
<th mat-header-cell *matHeaderCellDef> Group </th>
<td mat-cell *matCellDef="let element"> {{element.group}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="versions">
<th mat-header-cell *matHeaderCellDef> Versions </th>
<td mat-cell *matCellDef="let element"> {{element.versions}} </td>
</ng-container>
<ng-container matColumnDef="files">
<th mat-header-cell *matHeaderCellDef> Files </th>
<td mat-cell *matCellDef="let element"> {{element.files}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedModuleColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedModuleColumns;"></tr>
<!-- Row shown when there is no matching data. --> <!-- Row shown when there is no matching data. -->
<tr class="mat-row" *matNoDataRow> <tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td> <td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr> </tr>
</table> </table>
</mat-card-content> </div>
</mat-card>
</ng-container> </mat-card-content>
</mat-card>
<mat-card *ngIf="moduleDatasource.filteredData.length > 0">
<mat-card-header>
<mat-card-title>Modules</mat-card-title>
</mat-card-header>
<mat-card-content>
<table mat-table [dataSource]="moduleDatasource" class="mat-elevation-z8">
<ng-container matColumnDef="group">
<th mat-header-cell *matHeaderCellDef> Group </th>
<td mat-cell *matCellDef="let element"> {{element.group}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="versions">
<th mat-header-cell *matHeaderCellDef> Versions </th>
<td mat-cell *matCellDef="let element"> {{element.versions}} </td>
</ng-container>
<ng-container matColumnDef="files">
<th mat-header-cell *matHeaderCellDef> Files </th>
<td mat-cell *matCellDef="let element"> {{element.files}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedModuleColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedModuleColumns;"></tr>
<!-- Row shown when there is no matching data. -->
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr>
</table>
</mat-card-content>
</mat-card>
</div>
@ -118,6 +119,4 @@
</mat-card> </mat-card>
</ng-container> </ng-container>
--> -->

View File

@ -16,7 +16,7 @@ export interface Module {
export interface KeyValueDatasource { export interface KeyValueDatasource {
name: string; name: string;
datasource: MatTableDataSource<any[]>; datasource: MatTableDataSource<any>;
} }
@ -26,7 +26,6 @@ export interface KeyValueDatasource {
styleUrls: ['./info.component.css'] styleUrls: ['./info.component.css']
}) })
export class InfoComponent { export class InfoComponent {
infoFilter?:string;
kvDatasources:KeyValueDatasource[] = []; kvDatasources:KeyValueDatasource[] = [];
moduleDatasource:MatTableDataSource<Module[]> = new MatTableDataSource<Module[]>([]); moduleDatasource:MatTableDataSource<Module[]> = new MatTableDataSource<Module[]>([]);
@ -58,18 +57,5 @@ export class InfoComponent {
this.kvDatasources.forEach(s => s.datasource.filter = filterValue) this.kvDatasources.forEach(s => s.datasource.filter = filterValue)
this.moduleDatasource.filter = filterValue; this.moduleDatasource.filter = filterValue;
} }
getFilteredInfo(data:any[]) {
if (this.infoFilter) {
return data.filter(obj => {
return Object.keys(obj).reduce((acc, curr) => {
return acc || obj[curr].toString().toLowerCase().includes(this.infoFilter);
}, false);
})
}
else
return data
}
} }

View File

@ -1,7 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { ResourceType } from './model/controller.model'; import { ResourceType,Protocol } from './model/controller.model';
import { Observable, Observer } from 'rxjs'; import { Observable, Observer } from 'rxjs';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -18,5 +19,8 @@ export class ISCommonService {
return this.client.get<any[]>("/ajax/info/"); return this.client.get<any[]>("/ajax/info/");
} }
loadProtocols():Observable<Protocol[]> {
return this.client.get<any[]>("/ajax/protocols/");
}
} }

View File

@ -1,17 +0,0 @@
.sidenav-container {
height: 100%;
}
.sidenav {
width: 400px;
}
.sidenav .mat-toolbar {
background: inherit;
}
.mat-toolbar.mat-primary {
position: sticky;
top: 0;
z-index: 1;
}

View File

@ -1,26 +0,0 @@
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<app-main-menu-tree></app-main-menu-tree>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>dnet-is-application</span>
</mat-toolbar>
<!-- The routed views render in the <router-outlet>-->
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>

View File

@ -1,40 +0,0 @@
import { LayoutModule } from '@angular/cdk/layout';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MainContainerComponent } from './main-container.component';
describe('MainContainerComponent', () => {
let component: MainContainerComponent;
let fixture: ComponentFixture<MainContainerComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [MainContainerComponent],
imports: [
NoopAnimationsModule,
LayoutModule,
MatButtonModule,
MatIconModule,
MatListModule,
MatSidenavModule,
MatToolbarModule,
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MainContainerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should compile', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,21 +0,0 @@
import { Component } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
@Component({
selector: 'app-main-container',
templateUrl: './main-container.component.html',
styleUrls: ['./main-container.component.css']
})
export class MainContainerComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
constructor(private breakpointObserver: BreakpointObserver) {}
}

View File

@ -56,8 +56,10 @@ export class MainMenuTreeComponent {
badge: resType.count.toString() badge: resType.count.toString()
} }
if (resType.simple) { if (resType.simple) {
item.route = '/resources/' + resType.id;
simpleResources.push(item) simpleResources.push(item)
} else { } else {
item.route = '/adv_resources/' + resType.id;
advancedResources.push(item) advancedResources.push(item)
} }
}) })

View File

@ -1,4 +1,4 @@
export interface ResourceType{ export interface ResourceType {
id:string id:string
name:string name:string
contentType:string contentType:string
@ -6,3 +6,15 @@ export interface ResourceType{
simple:boolean simple:boolean
} }
export interface ProtocolParams {
name:string
label:string
type:string
optional:boolean
hasSelFunction:boolean
}
export interface Protocol {
id: string
params: ProtocolParams[]
}

View File

@ -0,0 +1,51 @@
<mat-card>
<mat-card-header>
<mat-card-title>Harvesting Protocols</mat-card-title>
</mat-card-header>
<mat-card-content>
<div style="margin-top: 20px;" *ngFor="let prot of protDatasources">
<h3>{{prot.protocol}}</h3>
<table mat-table [dataSource]="prot.datasource" class="mat-elevation-z8">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef> Label </th>
<td mat-cell *matCellDef="let element"> {{element.label}} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let element"> {{element.type}} </td>
</ng-container>
<ng-container matColumnDef="optional">
<th mat-header-cell *matHeaderCellDef> Required </th>
<td mat-cell *matCellDef="let element">
<mat-icon fontIcon="check" *ngIf="!element.optional"></mat-icon>
</td>
</ng-container>
<ng-container matColumnDef="hasSelFunction">
<th mat-header-cell *matHeaderCellDef> Has Sel Function </th>
<td mat-cell *matCellDef="let element">
<mat-icon fontIcon="check" *ngIf="element.hasSelFunction"></mat-icon>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="colums"></tr> 
<tr mat-row *matRowDef="let row; columns: colums;"></tr>
<!-- Row shown when there is no matching data. -->
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="5">No parameters</td>
</tr>
</table>
</div>
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProtocolsComponent } from './protocols.component';
describe('ProtocolsComponent', () => {
let component: ProtocolsComponent;
let fixture: ComponentFixture<ProtocolsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ProtocolsComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(ProtocolsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,35 @@
import { Component } from '@angular/core';
import { ISCommonService } from '../iscommon.service';
import { MatTableDataSource } from '@angular/material/table';
import { Protocol, ProtocolParams } from '../model/controller.model';
export interface ProtocolDatasource {
protocol: string;
datasource: MatTableDataSource<ProtocolParams>;
}
@Component({
selector: 'app-protocols',
templateUrl: './protocols.component.html',
styleUrls: ['./protocols.component.css']
})
export class ProtocolsComponent {
protDatasources:ProtocolDatasource[] = [];
colums : string[] = ['name', 'label', 'type', 'optional', 'hasSelFunction'];
constructor(public service:ISCommonService) {
this.service.loadProtocols().subscribe({
next:(data:Protocol[]) => {
data.forEach(p => {
this.protDatasources.push({
protocol : p.id,
datasource : new MatTableDataSource(p.params)
});
})
},
error:error => console.log(error),
complete:() => console.log("Completed")
})
}
}