Skip to content
Snippets Groups Projects
Commit 5edb03d0 authored by Chris Hines's avatar Chris Hines
Browse files

ui overhaul

parent 49ed5c68
No related branches found
No related tags found
2 merge requests!21New css dev,!18Dev
Pipeline #7795 passed
Showing
with 581 additions and 196 deletions
<div fxLayout=column fxLayoutAlign="space-between" style="width: 100%; height: 100%">
<div *ngIf="(identity.systemalerts | async) == null || (identity.accountalerts | async) == null; then loading else displayAlerts"></div>
<ng-template #loading><h2> Loading ...</h2></ng-template>
<ng-template #displayAlerts>
<!-- This is all the system level alerts-->
<!--<div style="padding-left: 5%; padding-right: 5%; padding-top: 5%">-->
<div >
<mat-list>
<div *ngFor="let h of (identity.systemalerts | async)">
<mat-list-item>
<div *ngIf="h.stat == 'error'">
<div class='health-warn'>
{{ h.msg }}
</div>
</div>
</mat-list-item>
</div>
</mat-list>
<mat-list>
<div *ngFor="let h of (identity.accountalerts | async)">
<div *ngIf="h.type === undefined || h.type != 'quota'">
<mat-list-item>
<div [ngClass]="h.stat == 'error' || h.stat == 'warn' ? 'health-warn': 'health-ok'">
{{ h.msg }}
</div>
</mat-list-item>
</div>
<div *ngIf="h.type == 'table'">
<h3>{{ h.title }}</h3>
<table mat-table [dataSource]="h.data.rows" style="width: 100%">
<ng-container *ngFor="let c of h.data.cols" matColumnDef="{{c.key}}">
<th mat-header-cell *matHeaderCellDef style="text-align: right">{{ c.header }} </th>
<td mat-cell *matCellDef="let row;" style="text-align: right"> {{row[c.key]}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="calculateCols(h.data.cols); sticky: true" ></tr>
<tr mat-row *matRowDef="let row; columns: calculateCols(h.data.cols)" [ngClass]="rowClass(row)" ></tr>
</table>
</div>
</div>
</mat-list>
</div>
</ng-template>
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AccountinfoComponent } from './accountinfo.component';
describe('AccountinfoComponent', () => {
let component: AccountinfoComponent;
let fixture: ComponentFixture<AccountinfoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AccountinfoComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AccountinfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input } from '@angular/core';
import { Identity } from '../identity';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { TesService } from '../tes.service';
@Component({
selector: 'app-accountinfo',
templateUrl: './accountinfo.component.html',
styleUrls: ['./accountinfo.component.css']
})
export class AccountinfoComponent implements OnInit {
@Input() identity: Identity;
constructor(
private router: Router,
public tesService: TesService,
) { }
ngOnInit() {
}
calculateCols(data) {
return data.map(function(r) { return r.key });
}
humanKBytes(n: number) {
if (n > 1024*1024*1024) {
let v = n/1024/1024/1024;
return v.toFixed(0)+'TB';
}
if (n > 1024*1024) {
let v = n/1024/1024;
return v.toFixed(0)+'GB';
}
if (n > 1024) {
let v = n/1024;
return v.toFixed(0)+'MB';
}
return '0 MB';
}
rowClass(row) {
if (row.stat == 'error' || row.stat == 'warn') {
return 'health-warn';
} else {
return 'health-ok';
}
}
navLogin(o) {
if (o == null) {
return
}
if (o.length == 0) {
this.router.navigate(['/login']);
} else {
}
}
getHealth(o) {
if (o == null) {
return
}
for (let id of o) {
this.tesService.getHealthAlerts(id);
}
}
}
......@@ -18,13 +18,15 @@ const routes: Routes = [
{ path: '', redirectTo: 'launch', pathMatch: 'full'},
//{ path: 'launch', component: JoblistComponent},
{ path: 'launch', component: LauncherComponent},
{ path: 'launch/:site', component: LauncherComponent},
{ path: 'launch/:site/:app', component: LauncherComponent},
{ path: 'login', component: LoginComponent},
{ path: 'logout', component: LogoutComponent},
{ path: 'settings', component: SettingsComponent },
// { path: 'finishlaunch', component: LauncherComponent},
//{ path: 'cancellaunch', component: LauncherComponent},
{ path: 'sshauthz_callback', component: KeygenComponent},
// { path: 'transfer', component: TransferComponent },
{ path: 'transfer', component: TransferComponent },
//{ path: 'shareconnect', component: ShareconnectComponent }
......
......@@ -7,9 +7,37 @@
</div> -->
<!--<app-launcher></app-launcher>-->
<mat-sidenav-container style="height: 100%; width: 100%">
<mat-sidenav></mat-sidenav>
<mat-sidenav-container style="height: 100vh; width: 100%">
<!--<mat-sidenav-container>-->
<mat-sidenav closed>
1st sidenav
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
<div fxLayout="column" fxLayoutAlign="space-between stretch" style="height: 100%; width: 100%">
<mat-toolbar color="primary">
<div fxLayout="row" style="width: 100%">
<mat-toolbar-row style="width: 100%">
<img src="assets/MASSIVElogoTransparent128x128.png" style="width: auto; height: 90%">
<span>Strudel2</span>
<span fxFlex></span>
<span class="fill-horizontal-space"></span>
<button mat-icon-button [matMenuTriggerFor]="actionmenu">
<mat-icon>person</mat-icon>
</button>
<mat-menu #actionmenu="matMenu">
<div *ngFor="let az of (authService.loggedInAuthZ | async)">
<button mat-menu-item routerLink="/logout"><mat-icon>logout</mat-icon>Log out of {{ az.name }}</button>
</div>
<button mat-menu-item routerLink="/settings"><mat-icon>settings</mat-icon>Settings</button>
<button *ngIf="(authService.loggedOutAuthZ | async).length > 0" mat-menu-item routerLink="/login"><mat-icon>exit_to_app</mat-icon>More services</button>
</mat-menu>
</mat-toolbar-row>
</div>
</mat-toolbar>
<div style="height: 100%">
<router-outlet></router-outlet>
</div>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
......@@ -5,6 +5,7 @@ import { ComputesitesService} from './computesites.service';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import { MatSnackBar } from '@angular/material';
import {OverlayContainer} from '@angular/cdk/overlay';
import { Computesite, Health } from './computesite';
......@@ -69,6 +70,31 @@ export class AppComponent {
classList.add(theme);
}
countErrors(a: Health[], b: Health[]) {
var count: number = 0
var h: Health;
if (a != null) {
for (h of a) {
if (h.stat == 'error' || h.stat == 'warn') {
count++;
}
if(!isNaN(parseInt(h.stat))) {
count = count + parseInt(h.stat);
}
}
}
if (b != null) {
for (h of b) {
if (h.stat == 'error' || h.stat == 'warn') {
count++;
}
if(!isNaN(parseInt(h.stat))) {
count = count + parseInt(h.stat);
}
}
}
return count;
}
// login() {
......
......@@ -6,13 +6,14 @@ import { AppComponent } from './app.component';
import { LauncherComponent } from './launcher/launcher.component';
import { JoblistComponent } from './joblist/joblist.component';
import { MatButtonModule } from '@angular/material';
import { MatButtonToggleModule} from '@angular/material';
import { MatFormFieldModule } from '@angular/material';
import { MatOptionModule } from '@angular/material';
import { MatInputModule } from '@angular/material';
import { MatSelectModule } from '@angular/material';
import { MatListModule} from '@angular/material';
import { MatTableModule } from '@angular/material/table';
import { MatCardModule } from '@angular/material';
import { MatCardModule, MatTabsModule } from '@angular/material';
import { MatToolbarModule } from '@angular/material';
import { MatDialogModule, MatDialog } from '@angular/material';
import { MatSnackBarModule } from "@angular/material";
......@@ -53,6 +54,7 @@ import {OverlayModule} from '@angular/cdk/overlay';
import { LoginComponent } from './login/login.component';
import { SettingsComponent } from './settings/settings.component';
import { LogoutComponent } from './logout/logout.component';
import { AccountinfoComponent } from './accountinfo/accountinfo.component';
// import { FileExplorerModule } from './file-explorer/file-explorer.module';
......@@ -79,10 +81,12 @@ import { LogoutComponent } from './logout/logout.component';
LoginComponent,
SettingsComponent,
LogoutComponent,
AccountinfoComponent,
],
imports: [
BrowserModule,
MatButtonModule,
MatButtonToggleModule,
MatFormFieldModule,
MatOptionModule,
MatInputModule,
......@@ -90,6 +94,7 @@ import { LogoutComponent } from './logout/logout.component';
MatListModule,
MatTableModule,
MatCardModule,
MatTabsModule,
MatToolbarModule,
MatDialogModule,
MatProgressSpinnerModule,
......
......@@ -226,15 +226,12 @@ public getKeys(id?: Identity) {
let path=sessionStorage.getItem('path');
//skip1 because loggedInAuthZ is a behaviour subject and we don't want the current value but the value
this.loggedInAuthZ.pipe(skip(1),take(1)).subscribe( () => {this.readyToNavigate.next([true,path])});
console.log('cert generated, adding keycert to agent');
this.sshAdd(keyCert);
// only navigate once the agent contents has been refreshed
}
public querySshAgentError(error: any) {
this.agentContents.next([]);
console.log('querySshAgentError');
console.log(error);
if (error.status == 0) {
this.statusMsg.next("A network error occured. Are you connected to the internet?")
}
......@@ -253,7 +250,7 @@ public getKeys(id?: Identity) {
var anyvar: any;
this.http.get<any>(this.backendURI+'/sshagent',options)
.pipe(catchError(this.handleError(anyvar)))
.subscribe(resp => { this.agentContents.next(resp); console.log('agent response'); console.log(resp); this.statusMsg.next("") },
.subscribe(resp => { this.agentContents.next(resp); this.statusMsg.next("") },
error => this.querySshAgentError(error));
// .subscribe(resp => this.computeSitesService.updateIdentities(resp),
// error => this.httperror(error))
......
......@@ -156,9 +156,6 @@ export class ComputesitesService {
var appidentities: Identity[] = [];
var ftidentities: Identity[] = [];
// If the agent contents is set to null we are probably still updating it
console.log('updating app identities');
console.log(resp);
console.log(this.authorisationService.agentContents.value)
if (resp == null) {
return
......
:host {
/*:host {
height: 100%;
display: flex;
flex-direction: column;
......@@ -8,9 +8,9 @@
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
}*/
.file-or-folder {
/*.file-or-folder {
padding: 8px;
overflow: hidden;
}
......@@ -29,11 +29,9 @@
flex: 1 1 auto;
}
.file-table {
/* flex: 1 1 auto; */
height: 400px;
/* width: 100%; */
}
.basic-container {
height: 400px;
}
}*/
......@@ -95,6 +95,22 @@
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="navigate(row)"></tr>
<mat-menu #contextMenu="matMenu" [overlapTrigger]="false">
<ng-template matMenuContent let-element="element">
<!-- <button mat-menu-item [matMenuTriggerFor]="moveToMenu" [matMenuTriggerData]="{self: element}">
<mat-icon>open_with</mat-icon>
<span>Move To</span>
</button> -->
<button mat-menu-item (click)="emitSendFile(element)">
<mat-icon>send</mat-icon>
<span>Send file</span>
</button>
<button mat-menu-item (click)="openNewFolderDialog()">
<mat-icon>send</mat-icon>
<span>New directory</span>
</button>
</ng-template>
</mat-menu>
</table>
......@@ -121,19 +137,3 @@
<!-- </div> -->
<!-- </div> -->
<mat-menu #contextMenu="matMenu" [overlapTrigger]="false">
<ng-template matMenuContent let-element="element">
<!-- <button mat-menu-item [matMenuTriggerFor]="moveToMenu" [matMenuTriggerData]="{self: element}">
<mat-icon>open_with</mat-icon>
<span>Move To</span>
</button> -->
<button mat-menu-item (click)="emitSendFile(element)">
<mat-icon>send</mat-icon>
<span>Send file</span>
</button>
<button mat-menu-item (click)="openNewFolderDialog()">
<mat-icon>send</mat-icon>
<span>New directory</span>
</button>
</ng-template>
</mat-menu>
......@@ -10,7 +10,7 @@
<div> {{ timeremaining }} </div>
</div>
<div fxFlex></div>
<div fxFlex="15%" fxLayout="row">
<div fxFlex fxLayout="row">
<div fxFlex *ngIf="!nocancel"> <button mat-button (click)="onCancel()" > Cancel </button> </div>
<div *ngFor="let action of jobdata.app.actions">
<div fxFlex *ngIf="action.states === undefined || action.states === null || action.states.indexOf(jobdata.state) != -1">
......
......@@ -71,9 +71,7 @@ export class JobComponent implements OnInit, OnDestroy {
let end = this.parseDate(this.jobdata.endtime);
let remaining = end.valueOf() - Date.now().valueOf();
this.timeremaining = "Time remaining: "+this.secondsToHms(remaining/1000);
} else {
console.log('jobdata endtime is undefined');
}
}
}
secondsToHms(d: number) {
......
<mat-toolbar color="primary">
<mat-toolbar-row>
<button mat-icon-button ><mat-icon>menu</mat-icon></button>
<span>Strudel v2.0</span>
<span class="fill-horizontal-space"></span>
</mat-toolbar-row>
</mat-toolbar>
<mat-card>
Generating cryptographic tokens ... this should only take a few seconds
</mat-card>
......@@ -5,10 +5,14 @@
<iframe *ngIf="appconfigurl != null" [src]="batchcmdsafeurl" style="height: 1px; min-height: 0px; border: none" #batchbuilderiframe></iframe>-->
<div *ngIf="(appSubject | async ) !== null" style="width: 100%">
<iframe [src]="batchcmdsafeurl" style="border: none; border-style: none; border-width: 0px; width: 100%" [style.height]="height+'px'" #batchbuilderiframe></iframe>
<iframe [src]="batchcmdsafeurl" style="border: none; border-style: none; border-width: 0px; width: 100%; overflow: auto" [style.height]="height+'px'" #batchbuilderiframe></iframe>
<!--<div *ngIf="appconfigsafeurl !== null && configtoggle">
<iframe [src]="appconfigsafeurl" style="border: none; border-style: none; border-width: 0px; width: 100%" [style.height]="appconfigheight+'px'" #batchbuilderiframe></iframe>
</div>-->
<div fxLayout="row" fxLayoutAlign="space-around">
<button mat-flat-button (click)="launch()" color="primary" #launchbtn>Launch</button>
<button *ngIf="appconfigsafeurl !== null" mat-flat-button (click)="configdialog()" color="primary">Configure</button>
<button mat-flat-button (click)="launch()" color="primary" #launchbtn [disabled]="!readyToLaunch">Launch</button>
</div>
</div>
</div>
......@@ -3,11 +3,13 @@ import { DomSanitizer} from '@angular/platform-browser';
import { Renderer2 } from '@angular/core';
//import { MatDialogRef,MAT_DIALOG_DATA } from '@angular/material';
import { TesService } from '../tes.service';
import { timer, Subscription} from 'rxjs';
import { Observable, merge, pipe, timer, Subscription} from 'rxjs';
import { BehaviorSubject } from 'rxjs';
import { take } from 'rxjs/operators';
import { Identity } from '../identity';
import { Strudelapp } from '../strudelapp';
import { BatchInterface} from '../batchinterface';
import { fromEvent } from 'rxjs';
@Component({
......@@ -18,6 +20,7 @@ import { BatchInterface} from '../batchinterface';
export class LaunchDialogComponent implements OnInit {
@Input() identity: Identity;
@Input() appSubject: BehaviorSubject<Strudelapp>;
//@Input() app: Strudelapp;
app: Strudelapp;
batchcmdurl: string;
appconfigurl: string;
......@@ -30,9 +33,13 @@ export class LaunchDialogComponent implements OnInit {
subscriptions: Subscription[];
launchNext: Boolean;
width: number;
appconfigwidth: number;
height: number;
public appData: any;
public submitcmd: string;
public appData: BehaviorSubject<any>;
public submitcmd: BehaviorSubject<string>;
configtoggle: boolean;
configwindow: any;
public readyToLaunch: boolean;
//constructor( public dialogRef: MatDialogRef<LaunchDialogComponent>,
constructor(
......@@ -40,10 +47,13 @@ export class LaunchDialogComponent implements OnInit {
private renderer: Renderer2,
private tesService: TesService,
) {
this.submitcmd = null;
this.appData = null
this.submitcmd = new BehaviorSubject<string>(null);
this.appData = new BehaviorSubject<any>(null);
this.subscriptions = [];
this.launchNext = false;
this.height=0;
this.submitcmd.subscribe(() => this.canILaunch());
this.appData.subscribe(() => this.canILaunch());
}
......@@ -51,11 +61,23 @@ export class LaunchDialogComponent implements OnInit {
console.log('creating launch-dialog');
this.rmListen = this.renderer.listen('window','message',(event) => this.receiveMessage(event));
this.setFocus = false;
this.subscriptions.push(this.appSubject.subscribe(() => { this.setReady(false); this.app = this.appSubject.value; this.updateURLs()}));
this.updateURLs();
this.clearInfo();
this.subscriptions.push(this.appSubject.subscribe(() => { this.app = this.appSubject.value; this.updateURLs() ; this.clearInfo()}));
}
configdialog(){
console.log('open app config');
console.log(this.app.url);
this.configwindow = window.open(this.app.url);
this.configwindow.onunload = function () { console.log('config closed')};
this.subscriptions.push(fromEvent(this.configwindow,'message').subscribe((event) => this.receiveAppconfig(event)));
}
updateURLs() {
if (this.app == null) {
return;
}
let theme = "";
theme=localStorage.getItem('strudel-theme');
if (theme == null) {
......@@ -65,11 +87,16 @@ export class LaunchDialogComponent implements OnInit {
this.batchcmdurl = this.identity.site.url+"/"+this.app.name+"?theme="+theme;
}
this.batchcmdsafeurl = this.domSanitizer.bypassSecurityTrustResourceUrl(this.batchcmdurl);
if (this.app !== null) {
if (this.app.url !== null) {
this.appconfigurl = this.app.url+"?theme="+theme;
} else {
this.appconfigurl = null;
}
if (!(this.appconfigurl == null)) {
this.appconfigsafeurl = this.domSanitizer.bypassSecurityTrustResourceUrl(this.appconfigurl);
} else {
this.appconfigsafeurl = null;
}
console.log('updatedURLs');
}
......@@ -83,38 +110,33 @@ export class LaunchDialogComponent implements OnInit {
setReady(ready) {
console.log('call setReady',ready);
this.readyToLaunch = ready;
if (this.launchbtn === undefined) {
console.log('launchbtn is not defined, cant set ready');
return
}
if (ready && !(this.setFocus)) {
this.launchbtn.nativeElement._disabled = false;
this.launchbtn.nativeElement.focus();
this.setFocus = true;
} else {
this.launchbtn.nativeElement._disabled = true;
console.log('launch is still disabled');
}
}
receiveAppconfig(event) {
if (event.data['appData'] !== undefined) {
this.appData.next(event.data['appData']);
console.log('received appData');
}
}
receiveMessage(event) {
console.log(event);
if (event.data['batchcmd'] !== undefined) {
this.submitcmd = event.data['batchcmd'];
console.log('recieved a submit cmd');
console.log('recieveMessage'+this.submitcmd);
if (this.launchNext) {
this.launchThisCmd(this.submitcmd);
this.launchNext = false;
}
}
if (event.data['appData'] !== undefined) {
this.appData = event.data['appData'];
this.submitcmd.next(event.data['batchcmd']);
}
if (event.data['resize'] !== undefined) {
console.log('setting iframe size');
this.height = event.data['resize']['height'];
this.width = event.data['resize']['width'];
console.log(this.height);
}
}
......@@ -122,14 +144,15 @@ export class LaunchDialogComponent implements OnInit {
// tell the batchbuilder iframe that lanch was selected
// This is the queue to save the values as defaults for next launch
this.batchbuilderiframe.nativeElement.contentWindow.postMessage('launch selected',"*");
this.submitcmd.pipe(take(1)).subscribe( (submitcmd) => this.reallyLaunch(submitcmd))
this.launchNext=true;
}
launchThisCmd(cmd) {
reallyLaunch(submitcmd) {
let bi = new BatchInterface();
bi.submitcmd = cmd;
if (this.appData != null){
let appparams = this.appData;
bi.submitcmd = submitcmd;
if (this.appData.value != null){
let appparams = this.appData.value;
this.tesService.submit(this.app,this.identity,bi,appparams);
} else {
this.tesService.submit(this.app,this.identity,bi);
......@@ -137,13 +160,18 @@ export class LaunchDialogComponent implements OnInit {
}
clearInfo() {
this.appData = null;
this.submitcmd = null;
this.appData.next(null);
this.submitcmd.next(null);
}
canILaunch() {
if (this.submitcmd != null) {
if (this.app.url == null || this.appData != null ) {
if (this.app == null) {
this.setReady(false);
return
}
if (this.submitcmd.value != null) {
console.log(this.app.url);
if (this.app.url === null || this.appData.value != null ) {
this.setReady(true);
return;
}
......
<div fxFlex style="flex: 1 1 0%; box-sizing: border-box">
<div fxLayout="column" fxLayoutAlign="space-around stretch" style="height: 100%; width: 100%" >
<mat-toolbar color="primary">
<mat-toolbar-row>
<button mat-icon-button (click)=idSideNav.toggle()><mat-icon>menu</mat-icon></button>
<span>Strudel v2.0</span>
<span class="fill-horizontal-space"></span>
</mat-toolbar-row>
</mat-toolbar>
<mat-sidenav-container style="height: 100%; width: 100%" autosize>
<!--<div fxFlex style="flex: 1 1 0%; box-sizing: border-box">-->
<mat-sidenav-container style="height: 100%" autosize>
<mat-sidenav #idSideNav mode="side" opened>
<div fxLayout="column" style="height: 100%">
<div>
<div *ngIf="usemenu">
<div fxLayout="column" fxLayout="stretch" style="height: 100%">
<nav>
<mat-accordion style="width: 100%" [displayMode]="flat">
<div *ngFor="let id of (computeSitesService.appidentities | async)">
<mat-expansion-panel (afterExpand)="selectId(id)" (closed)="selectId(id)" style="width: 100%">
<mat-expansion-panel-header>
<mat-panel-title>
<span fxFlex matBadge="{{ countErrors((id.systemalerts | async), (id.accountalerts | async)) }}"
[matBadgeHidden]= "countErrors((id.systemalerts | async), (id.accountalerts | async)) == 0"
matBadgePosition="above before"
matBadgeColor="warn"
matBadgeOverlap="false" matBadgeSize="small"
style="text-align: left; margin-left: 20px; margin-top: 10px" >
{{ id.displayName() }}
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<app-strudelapplist [applist]=id.site.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist>
</mat-expansion-panel>
</div>
<div *ngFor="let id of (computeSitesService.appidentities | async)">
<!--<mat-expansion-panel (afterExpand)="selectId(id)" (closed)="selectId(id)" style="width: 100%">-->
<mat-expansion-panel style="width: 100%">
<mat-expansion-panel-header>
<mat-panel-title>
<span fxFlex matBadge="{{ countErrors((id.systemalerts | async), (id.accountalerts | async)) }}"
[matBadgeHidden]= "countErrors((id.systemalerts | async), (id.accountalerts | async)) == 0"
matBadgePosition="above before"
matBadgeColor="warn"
matBadgeOverlap="false" matBadgeSize="small"
style="text-align: left; margin-left: 20px; margin-top: 10px" >
{{ id.displayName() }}
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list style="width: 100%">
<mat-list-item>
<button mat-button style="width: 100%; text-align: left"
[routerLink]="['/launch',id.site.name,'accountinfo']"
routerLinkActive #rla="routerLinkActive">
Account Info
</button>
</mat-list-item>
<app-strudelapplist [applist]=id.site.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist>
</mat-list>
</mat-expansion-panel>
</div>
</mat-accordion>
</nav>
</div>
<div fxFlex></div>
<mat-menu #actionmenu="matMenu">
<div *ngFor="let az of (authService.loggedInAuthZ | async)">
<button mat-menu-item routerLink="/logout"><mat-icon>logout</mat-icon>Log out of {{ az.name }}</button>
</div>
<button mat-menu-item routerLink="/settings"><mat-icon>settings</mat-icon>Settings</button>
<button *ngIf="(authService.loggedOutAuthZ | async).length > 0" mat-menu-item routerLink="/login"><mat-icon>exit_to_app</mat-icon>More services</button>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="actionmenu">
<mat-icon>person</mat-icon>
</button>
</div>
</mat-sidenav>
<mat-sidenav-content>
<div fxLayout="column" style="height: 100%">
<div *ngIf="identitySubject | async as id">
<!-- the list of warning either on the computer system or the users account -->
<div *ngIf="id !== null && (appSubject | async) === null" >
<div *ngIf="(id.systemalerts | async) == null || (id.accountalerts | async) == null; then loading else displayAlerts"></div>
<ng-template #loading><h2> Loading ...</h2></ng-template>
<ng-template #displayAlerts>
<!-- This is all the system level alerts-->
<mat-list>
<div *ngFor="let h of (id.systemalerts | async)">
<mat-list-item>
<div *ngIf="h.stat == 'error'">
<div class='health-warn'>
{{ h.msg }}
</div>
</div>
</mat-list-item>
</div>
</mat-list>
<mat-list>
<div *ngFor="let h of ((identitySubject | async).accountalerts | async)">
<div *ngIf="h.type === undefined || h.type != 'quota'">
<mat-list-item>
<div [ngClass]="h.stat == 'error' || h.stat == 'warn' ? 'health-warn': 'health-ok'">
{{ h.msg }}
</div>
</mat-list-item>
</div>
<div *ngIf="h.type == 'table'">
<h3>{{ h.title }}</h3>
<table mat-table [dataSource]="h.data.rows" style="width: 100%">
<ng-container *ngFor="let c of h.data.cols" matColumnDef="{{c.key}}">
<th mat-header-cell *matHeaderCellDef>{{ c.header }} </th>
<td mat-cell *matCellDef="let row;"> {{row[c.key]}}</td>
</ng-container>
<mat-sidenav-content style="height: 100%">
<!--<div *ngIf="usetabs" class=darker-theme>
<nav mat-tab-nav-bar color="accent" backgroundColor="primary">
<a mat-tab-link
*ngFor="let id of (computeSitesService.appidentities | async)"
[routerLink]="['/launch',id.site.name]"
routerLinkActive #rla="routerLinkActive"
[routerLinkActiveOptions]="{'exact': false}"
[active]="rla.isActive">
<span fxFlex matBadge="{{ countErrors((id.systemalerts | async), (id.accountalerts | async)) }}"
[matBadgeHidden]= "countErrors((id.systemalerts | async), (id.accountalerts | async)) == 0"
matBadgePosition="above before"
matBadgeColor="warn"
matBadgeOverlap="false" matBadgeSize="small"
style="text-align: left; margin-left: 20px; margin-top: 10px" >
{{ id.displayName() }}
</span>
</a>
</nav>
<div *ngIf="(identitySubject | async) !== null" style="width: 100%" class=darker-theme>
<nav mat-tab-nav-bar color=accent backgroundColor=primary>
<a mat-tab-link
[routerLink]="['/launch',identitySubject.value.site.name,'accountinfo']"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
Account Info
</a>
<a mat-tab-link
*ngFor="let app of (identitySubject.value.site.appCatalog | async)"
[routerLink]="['/launch',identitySubject.value.site.name,app.name]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{ app.name }}
</a>
</nav>
</div>
</div>-->
<div fxLayout="column" fxLayoutAlign="space-between stretch" style="width: 100%; height: 100%" >
<tr mat-header-row *matHeaderRowDef="calculateCols(h.data.cols); sticky: true" ></tr>
<tr mat-row *matRowDef="let row; columns: calculateCols(h.data.cols)" [ngClass]="rowClass(row)" ></tr>
</table>
</div>
</div>
</mat-list>
</ng-template>
</div>
<div *ngIf="(appSubject | async) !== null && (identitySubject | async) !== null" >
<app-launch-dialog [identity]="identitySubject | async" [appSubject]="appSubject"></app-launch-dialog>
<app-joblist [identitySubject]="identitySubject" [appSubject]="appSubject"></app-joblist>
</div>
</div>
</div>
</mat-sidenav-content>
<div *ngIf="identitySubject | async as identity">
<div *ngIf="identity !== undefined && identity !== null && (appSubject | async) === null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%;">
<app-accountinfo [identity]="identity"></app-accountinfo>
</div>
<div *ngIf="identity !== undefined && identity !== null && (appSubject | async) !== undefined && (appSubject | async) !== null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%;">
<app-launch-dialog [identity]="identitySubject | async" [appSubject]="appSubject"></app-launch-dialog>
<app-joblist [identitySubject]="identitySubject" [appSubject]="appSubject"></app-joblist>
</div>
</div>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
<!-- <app-joblist></app-joblist> -->
<div fxFlex style="flex: 1 1 0%; box-sizing: border-box">
<div fxLayout="column" fxLayoutAlign="space-around stretch" style="height: 100%; width: 100%" >
<!-- <mat-sidenav-container style="height: 100%; width: 100%" autosize>
<mat-sidenav #idSideNav mode="side" opened>
<div fxLayout="column" style="height: 100%">
<div>
<mat-accordion style="width: 100%" [displayMode]="flat">
<div *ngFor="let id of (computeSitesService.appidentities | async)">
<mat-expansion-panel (afterExpand)="selectId(id)" (closed)="selectId(id)" style="width: 100%">
<mat-expansion-panel-header>
<mat-panel-title>
<span fxFlex matBadge="{{ countErrors((id.systemalerts | async), (id.accountalerts | async)) }}"
[matBadgeHidden]= "countErrors((id.systemalerts | async), (id.accountalerts | async)) == 0"
matBadgePosition="above before"
matBadgeColor="warn"
matBadgeOverlap="false" matBadgeSize="small"
style="text-align: left; margin-left: 20px; margin-top: 10px" >
{{ id.displayName() }}
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<app-strudelapplist [applist]=id.site.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist>
</mat-expansion-panel>
</div>
</mat-accordion>
</div>
<div fxFlex></div>
<mat-menu #actionmenu="matMenu">
<div *ngFor="let az of (authService.loggedInAuthZ | async)">
<button mat-menu-item routerLink="/logout"><mat-icon>logout</mat-icon>Log out of {{ az.name }}</button>
</div>
<button mat-menu-item routerLink="/settings"><mat-icon>settings</mat-icon>Settings</button>
<button *ngIf="(authService.loggedOutAuthZ | async).length > 0" mat-menu-item routerLink="/login"><mat-icon>exit_to_app</mat-icon>More services</button>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="actionmenu">
<mat-icon>person</mat-icon>
</button>
</div>
</mat-sidenav>
<mat-sidenav-content>-->
<div *ngIf="identity !== null">
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let app of (identity.appcatalog | async)"
[routerLink]="['/launch',identity.site.name,app.name]">
{{ app.name }}
</a>
</nav>
</div>
<!-- <div fxLayout="column" style="height: 100%">
<div *ngIf="identitySubject | async as id">
<!-- the list of warning either on the computer system or the users account -->
<div *ngIf="id !== null && (appSubject | async) === null" >
<div *ngIf="(id.systemalerts | async) == null || (id.accountalerts | async) == null; then loading else displayAlerts"></div>
<ng-template #loading><h2> Loading ...</h2></ng-template>
<ng-template #displayAlerts>
<!-- This is all the system level alerts-->
<mat-list>
<div *ngFor="let h of (id.systemalerts | async)">
<mat-list-item>
<div *ngIf="h.stat == 'error'">
<div class='health-warn'>
{{ h.msg }}
</div>
</div>
</mat-list-item>
</div>
</mat-list>
<mat-list>
<div *ngFor="let h of ((identitySubject | async).accountalerts | async)">
<div *ngIf="h.type === undefined || h.type != 'quota'">
<mat-list-item>
<div [ngClass]="h.stat == 'error' || h.stat == 'warn' ? 'health-warn': 'health-ok'">
{{ h.msg }}
</div>
</mat-list-item>
</div>
<div *ngIf="h.type == 'table'">
<h3>{{ h.title }}</h3>
<table mat-table [dataSource]="h.data.rows" style="width: 100%">
<ng-container *ngFor="let c of h.data.cols" matColumnDef="{{c.key}}">
<th mat-header-cell *matHeaderCellDef>{{ c.header }} </th>
<td mat-cell *matCellDef="let row;"> {{row[c.key]}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="calculateCols(h.data.cols); sticky: true" ></tr>
<tr mat-row *matRowDef="let row; columns: calculateCols(h.data.cols)" [ngClass]="rowClass(row)" ></tr>
</table>
</div>
</div>
</mat-list>
</ng-template>
</div>
<div *ngIf="(appSubject | async) !== null && (identitySubject | async) !== null" >
<app-launch-dialog [identity]="identitySubject | async" [appSubject]="appSubject"></app-launch-dialog>
<app-joblist [identitySubject]="identitySubject" [appSubject]="appSubject"></app-joblist>
</div>
</div>
</div>-->
<!-- </mat-sidenav-content>
</mat-sidenav-container>-->
<!-- <app-joblist></app-joblist> -->
......@@ -4,11 +4,11 @@ import { MatTableDataSource, MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialog
import { Location } from '@angular/common';
// import { HttpClientModule, HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import { Subscription } from 'rxjs';
import { Subscription, of } from 'rxjs';
import { fromEvent } from 'rxjs';
import { timer } from 'rxjs/observable/timer';
import { repeat, takeUntil, skip } from 'rxjs/operators';
import { Router, NavigationStart } from '@angular/router';
import { repeat, takeUntil, skip, switchMap, take, filter } from 'rxjs/operators';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import {Strudelapp} from '../strudelapp';
import { StrudelappsService } from '../strudelapps.service';
......@@ -42,11 +42,10 @@ export interface Quota {
})
export class LauncherComponent implements OnInit {
public strudelapps: Strudelapp[];
@Input() menuopen: boolean;
public appSubject: BehaviorSubject<Strudelapp>;
public authorised: boolean;
//public identity: Identity;
public identity: Identity;
public identitySubject: BehaviorSubject<Identity>;
public identities: Identity[];
......@@ -56,6 +55,11 @@ export class LauncherComponent implements OnInit {
private subscriptions: Subscription[];
//public quotas: BehaviorSubject<any[]>;
displayedColumns: string[] = [];
private identity$: Observable<Identity>;
private app$: Observable<Strudelapp>;
private app: Strudelapp;
private usetabs: boolean;
private usemenu: boolean;
constructor( public dialog: MatDialog,
......@@ -64,6 +68,8 @@ export class LauncherComponent implements OnInit {
public authService: AuthorisationService,
public computeSitesService: ComputesitesService,
private router: Router,
private route: ActivatedRoute,
private strudelappsService: StrudelappsService,
) {
this.subscriptions = [];
this.subscriptions.push(this.authService.sshAuthzServers.subscribe(o => {this.updateSshAuthZServers(o)}));
......@@ -71,6 +77,7 @@ export class LauncherComponent implements OnInit {
this.subscriptions.push(this.computeSitesService.appidentities.subscribe(o => this.getHealth(o)));
this.appSubject = new BehaviorSubject<Strudelapp>(null);
this.identitySubject = new BehaviorSubject<Identity>(null);
this.identity = null;
//this.quotas = new BehaviorSubject<any[]>([]);
}
......@@ -129,16 +136,12 @@ export class LauncherComponent implements OnInit {
}
navLogin(o) {
console.log('in navLogin');
if (o == null) {
console.log('not redireting null');
return
}
if (o.length == 0) {
console.log('redireting length == 0');
this.router.navigate(['/login']);
} else {
console.log('not redirecting, ids detected');
}
}
......@@ -157,8 +160,83 @@ export class LauncherComponent implements OnInit {
ngOnInit() {
this.strudelapps = [];
/*this.identity$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) => this.getId(params.get('site')))
);*/
this.route.paramMap.subscribe((params: ParamMap) => this.updateIdApp(params));
/*this.app$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) => this.getApp(params.get('app')))
);
this.identity$.subscribe((v) => {console.log('id changed'); console.log(v)});
this.identity$.subscribe((v) => this.identity = v);
this.app$.subscribe((v) => { console.log('app changed'); console.log(v)});*/
//this.site$.subscribe ( (v) => { this.getId(v) });
//this.app$.subscribe( (v) => { this.getApp(v) });
this.usetabs = false;
this.usemenu = true;
}
updateIdApp(params: ParamMap) {
var ids: string = params.get('site');
var apps: string = params.get('app');
if (ids === null) {
this.identitySubject.next(null);
return;
}
var id: Identity = this.getId(ids);
if (id === null) {
console.log('id is null, callback updateIdApp');
this.computeSitesService.appidentities.pipe(skip(1),filter((v) => v !== null && v.length > 0),take(1)).subscribe(() => this.updateIdApp(params));
return
}
if (id !== this.identitySubject.value) {
this.identitySubject.next(id);
}
if (apps === null) {
apps = 'acocuntinfo';
//this.appSubject.next(null);
//return;
}
if (id.site.appCatalog.value === undefined || id.site.appCatalog.value === null || (id.site.appCatalog.value).length == 0) {
id.site.appCatalog.pipe(filter((v) => v !== null && v.length > 0)).subscribe(() => this.updateIdApp(params));
return
}
var app: Strudelapp = this.getApp(id,apps);
if (app !== this.appSubject.value) {
this.appSubject.next(app);
}}
getApp(id,v: any): Strudelapp {
if (id == 'accountinfo') {
return null;
}
return this.strudelappsService.getApp(v,id.site.appCatalog.value);
}
getId(v: any) {
if (v === null) {
console.error('getId called with null value');
return null;
}
if (this.computeSitesService.appidentities.value === null || this.computeSitesService.appidentities.value == []) {
console.error('no appidentities yet? call back latter');
this.computeSitesService.appidentities.pipe(filter((v) => v !== null)).subscribe(() => this.getId(v));
return null
}
for ( let id of this.computeSitesService.appidentities.value) {
if (v == id.site.name) {
return id
}
}
console.error('didnt find a matching id');
console.log(v);
console.log(this.computeSitesService.appidentities.value);
return null;
}
ngOnDestroy() {
for (let s of this.subscriptions) {
s.unsubscribe();
......@@ -167,6 +245,7 @@ export class LauncherComponent implements OnInit {
selectId(id: Identity) {
this.identitySubject.next(id);
this.identity = id;
this.appSubject.next(null);
//if (id != null) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment