Commit 1dbee646 authored by Chris Hines's avatar Chris Hines
Browse files

new layout plus working on cloudcmd as an app

parent b5d82c9b
Pipeline #7902 passed with stages
in 4 minutes and 37 seconds
......@@ -12,11 +12,11 @@
<mat-sidenav closed>
</mat-sidenav>
<mat-sidenav-content>
<div fxLayout="column" fxLayoutAlign="space-between stretch" style="height: 100%; width: 100%">
<div fxLayout="column" fxLayoutAlign="none" style="height: 100%; width: 100%">
<mat-toolbar color="primary">
<div fxLayout="row" style="width: 100%">
<mat-toolbar-row style="width: 100%">
<button mat-icon-button aria-label="toggle menu" (click)=toggleMenu()><mat-icon>menu</mat-icon></button>
<button mat-icon-button *ngIf="settingsService.useMenu$ | async" aria-label="toggle menu" (click)=toggleMenu()><mat-icon>menu</mat-icon></button>
<img src="assets/MASSIVElogoTransparent128x128.png" style="width: auto; height: 90%">
<span>Strudel2</span>
<span fxFlex></span>
......@@ -31,11 +31,35 @@
</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>
<div *ngFor="let id of (computeSitesService.appidentities | async)">
<button mat-button fxFlex
[routerLink]="['/launch',id.displayName()]"
routerLinkActive #rla="routerLinkActive"
[disabled]="rla.isActive"
[routerLinkActiveOptions]="{'exact': false}"
style="text-align: left"
>
<mat-icon></mat-icon>
<span
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: 15px; margin-top: 10px">
<!--<span>-->
{{ id.displayName() }}
</span>
</button>
</div>
</mat-menu>
</mat-toolbar-row>
</div>
</mat-toolbar>
<div style="height: 100%">
<div>
<router-outlet></router-outlet>
</div>
</div>
......
......@@ -27,7 +27,7 @@ export class AppComponent {
constructor(private tesService: TesService,
private authService: AuthorisationService,
private computesitesService: ComputesitesService,
private computeSitesService: ComputesitesService,
private settingsService: SettingsService,
public snackBar: MatSnackBar) {
......@@ -38,7 +38,7 @@ export class AppComponent {
// this.testingAuth = false;
this.statusMsg = new BehaviorSubject<any>('');
this.tesService.setStatusMsg(this.statusMsg);
this.computesitesService.setStatusMsg(this.statusMsg);
this.computeSitesService.setStatusMsg(this.statusMsg);
this.authService.setStatusMsg(this.statusMsg);
this.statusMsg.subscribe(msg => this.displayMessage(msg));
this.settingsService.theme$.subscribe((v) => this.setTheme(v))
......
......@@ -14,6 +14,6 @@ export class Job {
public batch_host: string;
public identity: Identity;
public app: Strudelapp;
public appinst: string;
public appinst: any;
public connectionState: number;
}
<!--<div fxFlex style="flex: 1 1 0%; box-sizing: border-box">-->
<mat-sidenav-container style="height: 100%" autosize>
<mat-sidenav #idSideNav mode="side" [opened]="(settingsService.menuToggle$ | async) && (settingsService.useMenu$ | async)">
<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 style="width: 100%" [expanded]="(identity$ | async) === id">
<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.displayName(),'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 fxLayout="column" fxLayoutAlign="none" style="height: 100%">
<div *ngIf="!(settingsService.useMenu$ | async)">
<mat-divider></mat-divider>
<div *ngIf="(identity$ | async) !== null" style="width: 100%">
<nav mat-tab-nav-bar color=accent backgroundColor=primary>
<a mat-tab-link
[routerLink]="['/launch',identity$.value.displayName(),'accountinfo']"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
Account Info
</a>
<a mat-tab-link
*ngFor="let app of (identity$.value.site.appCatalog | async)"
[routerLink]="['/launch',identity$.value.displayName(),app.name]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{ app.name }}
</a>
</nav>
</div>
</div>
<div fxFlex></div>
</mat-sidenav>
<mat-sidenav-content style="height: 100%">
<div *ngIf="!(settingsService.useMenu$ | async)" 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.displayName()]"
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="(identity$ | async) !== null" style="width: 100%" class=darker-theme>
<nav mat-tab-nav-bar color=accent backgroundColor=primary>
<a mat-tab-link
[routerLink]="['/launch',identity$.value.displayName(),'accountinfo']"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
Account Info
</a>
<a mat-tab-link
*ngFor="let app of (identity$.value.site.appCatalog | async)"
[routerLink]="['/launch',identity$.value.displayName(),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%" >
<!--<div *ngIf="identitySubject.value !== undefined && identitySubject.value !== null && appSubject.value === null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%;">-->
<div *ngIf="(app$ | async) == null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%;">
<div *ngIf="(app$ | async) == null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%; overflow-y: scroll">
<app-accountinfo [identity$]="identity$" [app$]="app$"></app-accountinfo>
</div>
<div *ngIf="identity$.value !== undefined && identity$.value !== null && app$.value !== undefined && app$.value !== null" style="padding-left: 5%; padding-right: 5%; padding-top: 5%;">
<app-launch-dialog [identity]="identity$ | async" [appSubject]="app$"></app-launch-dialog>
<app-joblist [identitySubject]="identity$" [appSubject]="app$"></app-joblist>
<div style="height: 5%"></div>
<mat-divider ></mat-divider>
<div style="overflow-y: scroll">
<app-joblist [identitySubject]="identity$" [appSubject]="app$"></app-joblist>
</div>
</div>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
......@@ -168,7 +168,7 @@ export class LauncherComponent implements OnInit {
refreshId() {
var ids: string;
var id: Identity;
if (this.identity$ !== null) {
if (this.identity$.value !== null) {
ids = this.identity$.value.site.name;
} else {
return
......@@ -195,7 +195,7 @@ export class LauncherComponent implements OnInit {
}
if (apps === null) {
apps = 'acocuntinfo';
apps = 'accountinfo';
}
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));
......@@ -220,13 +220,23 @@ export class LauncherComponent implements OnInit {
}
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));
//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.displayName()) {
return id
} else {
console.log(v,'is not the same as ',id.displayName());
}
}
for ( let id of this.computeSitesService.appidentities.value) {
if (v == id.site.name) {
return id
} else {
console.log(v,'is not the same as ',id.displayName());
}
}
......@@ -242,6 +252,8 @@ export class LauncherComponent implements OnInit {
for ( let id of this.computeSitesService.appidentities.value) {
if (sitename == id.site.name) {
return id
} else {
console.log('sitename',sitename,'is not the same as ',id.site.name);
}
}
......
......@@ -12,7 +12,7 @@ export class SettingsService {
constructor() {
this.menuToggle$ = new BehaviorSubject<boolean>(true);
this.theme$ = new BehaviorSubject<string>('strudel-theme-light');
this.useMenu$ = new BehaviorSubject<boolean>(true);
this.useMenu$ = new BehaviorSubject<boolean>(false);
this.getTheme();
}
......
export class AppAction {
name: string;
paramscmd: string;
client: {cmd: string[], redir: string};
client: {cmd: string[], redir: string, usebasicauth: boolean};
states: string[]; // list of stats such as 'RUNNING' in which the action is valid. null||undefined if its always valid
}
export class Strudelapp {
......
......@@ -440,7 +440,7 @@ addUserHealth(identity,resp) {
//params.set('cmd',JSON.stringify(action.paramscmd));
let paramstr = params.toString();
this.http.post<string>(this.Base+'/createtunnel/'+username+'/'+loginhost+'/'+batchhost+'?'+paramstr, job.appinst, options)
.subscribe(() => { this.getAppUrl(job, action) } )
.subscribe(() => { this.getAppUrl(job, action) }, error => {this.handleTunnelError(job,error)} )
}
public getAppUrl(job: Job, action: AppAction) {
......@@ -454,7 +454,7 @@ addUserHealth(identity,resp) {
job.connectionState = 3;
this.http.get<string>(this.Base+'/appurl?'+paramstr,options)
.pipe(catchError(this.handleError))
.subscribe(resp => { job.connectionState = 0; this.openAppWindow(resp,job)});
.subscribe(resp => { job.connectionState = 0; this.openAppWindow(resp,job,action)});
}
......@@ -463,10 +463,23 @@ addUserHealth(identity,resp) {
this.getAppInstance(job, action);
}
public openAppWindow(url: any, job: Job) {
public openAppWindow(url: any, job: Job, action: AppAction) {
var re = /^https:\/\/([a-z0-9\.-]+)\/?/;
let twshost = this.twsproxy.replace(re,"$1");
console.log('in openappwindow url is ',url);
let windowloc = url.replace(/\{twsproxy\}/g,this.twsproxy).replace(/twshost/g,twshost);
console.log('window loc is',windowloc);
let user='chines';
let pass='pass';
var authwindow = null;
if (action.client.usebasicauth) {
let authwindowloc = windowloc.replace(/^https:\/\//,'https://'+job.appinst.username+':'+job.appinst.password+'@');
console.log('authwindowloc is',authwindowloc);
console.log(job.appinst);
authwindow = window.open(authwindowloc);
//windowloc = authwindowloc;
}
let appwindow = window.open(windowloc);
if (appwindow == null) {
......@@ -477,6 +490,9 @@ addUserHealth(identity,resp) {
return
}
this.openapps.push({'window':appwindow,'job':job})
if (authwindow !== null) {
authwindow.close();
}
}
......@@ -549,6 +565,16 @@ private httperror(errorstr: string) {
// }
private handleTunnelError(job: Job, error: any) {
job.connectionState=0;
if (error.stats == 500) {
this.statusMsg.next(error.error.message);
return;
}
this.statusMsg.next('Failed to create a tunnel. Please try again');
return;
}
private handleAppInstanceError(job: Job, error: any) {
console.log(error);
job.connectionState=0;
......
......@@ -147,5 +147,37 @@
"client": {"cmd": null, "redir": null },
"localbind": true,
"applist": null
},
{ "url": null,
"name": "File Explorer",
"startscript": "#!/bin/bash\n/usr/local/sv2/cloudcmd/start.sh\n ",
"actions": [
{
"name": "Connect",
"paramscmd": "/usr/local/sv2/dev/cloudcmd/params.py {jobid}",
"client": {"cmd": null, "redir": "", "usebasicauth": true },
"states": ["RUNNING"]
},
{
"name": "View log",
"paramscmd": "/usr/local/sv2/dev/desktop/logparams.py {jobid}",
"client": {"cmd": null, "redir": "index.html?token={token}" },
"states": ["RUNNING","Finished"]
},
{
"name": "View Usage",
"paramscmd": "/usr/local/sv2/dev/desktop/usageparams.py {jobid}",
"client": {"cmd": null, "redir": "index.html?token={token}" },
"states": ["Finished"]
},
{
"name": "Remove log",
"paramscmd": "/usr/local/sv2/dev/rmlog.py {jobid}",
"client": null,
"states": ["Finished"]
}
],
"localbind": true,
"applist": null
}
]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment