diff --git a/angular.json b/angular.json index fdd4dcfb0e99f8e2ed7c7dee22a2606d2500e6ab..236fe57d7bcc5f3953197e2f5e4fe9d7bdb47648 100644 --- a/angular.json +++ b/angular.json @@ -21,7 +21,8 @@ "src/favicon.ico" ], "styles": [ - "src/styles.css" + "src/styles.scss", + "src/health-warn.scss" ], "scripts": [] }, diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index d6b0cd53c3316c4c95b59119e28885eb5411f9ba..eddb7fb7b008eb9eb078456aabecf6ff9dab59c0 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -4,6 +4,7 @@ import { LauncherComponent } from './launcher/launcher.component'; import { KeygenComponent } from './keygen/keygen.component'; import { TransferComponent } from './transfer/transfer.component'; import { ShareconnectComponent } from './shareconnect/shareconnect.component'; +import { JoblistComponent } from './joblist/joblist.component'; // import { TokenextractorComponent } from './tokenextractor/tokenextractor.component'; @@ -11,12 +12,12 @@ import { ShareconnectComponent } from './shareconnect/shareconnect.component'; const routes: Routes = [ { path: '', redirectTo: 'launch', pathMatch: 'full'}, - { path: 'launch', component: LauncherComponent}, - { path: 'finishlaunch', component: LauncherComponent}, - { path: 'cancellaunch', component: LauncherComponent}, + { path: 'launch', component: JoblistComponent}, + // { path: 'finishlaunch', component: LauncherComponent}, + //{ path: 'cancellaunch', component: LauncherComponent}, { path: 'sshauthz_callback', component: KeygenComponent}, - { path: 'transfer', component: TransferComponent }, - { path: 'shareconnect', component: ShareconnectComponent } + // { path: 'transfer', component: TransferComponent }, + //{ path: 'shareconnect', component: ShareconnectComponent } // { path: 'sshauthz_callback', component: LauncherComponent} diff --git a/src/app/app.component.html b/src/app/app.component.html index a54e5745b792b6b6682fb916e3a672f946ee2331..8a5de05b2ec20b5ffef9d96dc6fd63391e6b4d32 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,2 +1,10 @@ <!-- <router-outlet class="fill-remaining-space"></router-outlet> --> +<!--<div *ngIf="(tesService.theme | async) == 'strudel-dark-theme'" class="strudel-dark-theme" style="width: 100vw; height: 100vh"> <router-outlet></router-outlet> +</div> +<div *ngIf="(tesService.theme | async) == 'strudel-light-theme'" class="strudel-light-theme" style="width: 100vw; height: 100vh"> +<router-outlet></router-outlet> +</div> --> + +<app-launcher></app-launcher> +<!--<router-outlet></router-outlet>--> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e08e960bbed7ffe809a1a93eee30237fbeea3d87..f938199ec7a6b5e4958cb1b0beb564467bf11ce8 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,6 +4,8 @@ import { AuthorisationService} from './authorisation.service'; import { ComputesitesService} from './computesites.service'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import { MatSnackBar } from '@angular/material'; +import {OverlayContainer} from '@angular/cdk/overlay'; + @Component({ @@ -24,7 +26,7 @@ export class AppComponent { constructor(private tesService: TesService, private authService: AuthorisationService, private computesitesService: ComputesitesService, - public snackBar: MatSnackBar,) { + public snackBar: MatSnackBar) { }; @@ -36,6 +38,7 @@ export class AppComponent { this.computesitesService.setStatusMsg(this.statusMsg); this.authService.setStatusMsg(this.statusMsg); this.statusMsg.subscribe(msg => this.displayMessage(msg)); + } @@ -48,6 +51,9 @@ export class AppComponent { this.snackBarRef = this.snackBar.open(msg,'Dismiss'); } } + + + // login() { // console.log("login"); // this.authService.login() diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 66fc38e19eb4cbbea987eab02778dc4a55fc7123..2db06c72b4afdd5565b14b7f1101eb779b1ed03d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -47,6 +47,8 @@ import { Sv2SideNavComponent } from './sv2-side-nav/sv2-side-nav.component'; import { ShareconnectComponent } from './shareconnect/shareconnect.component'; import { LaunchDialogComponent } from './launch-dialog/launch-dialog.component'; import { ModaldialogComponent } from './modaldialog/modaldialog.component' +import {OverlayModule} from '@angular/cdk/overlay'; + // import { FileExplorerModule } from './file-explorer/file-explorer.module'; @@ -68,7 +70,7 @@ import { ModaldialogComponent } from './modaldialog/modaldialog.component' Sv2SideNavComponent, ShareconnectComponent, LaunchDialogComponent, - ModaldialogComponent + ModaldialogComponent, ], imports: [ BrowserModule, @@ -94,6 +96,7 @@ import { ModaldialogComponent } from './modaldialog/modaldialog.component' FileExplorerModule, FlexLayoutModule, MatProgressBarModule, + OverlayModule, ], diff --git a/src/app/joblist/joblist.component.html b/src/app/joblist/joblist.component.html index 4b6183b4a5b09473bcc540b8477fa91a30ac23ee..1229da1784522f06e86761885b3fba27780d1f7f 100644 --- a/src/app/joblist/joblist.component.html +++ b/src/app/joblist/joblist.component.html @@ -1,35 +1,33 @@ -<!-- <div *ngIf="identities.length == 0"> - <mat-card> - Click identity and login to a service to start an application. - </mat-card> -</div> -<div *ngFor="let id of identities"> --> <mat-card style="width: 100%" style="box-sizing: border-box;"> - <div *ngIf="identity === undefined || identity == null" > + <div *ngIf="(tesService.identitySubject | async) === null" > Click login and select a provider or select one you've already logged in to. </div> - <div *ngIf="(identity !== undefined) && (identity !== null)"> + <div *ngIf="(tesService.identitySubject | async) !== null" > <div *ngFor="let h of tesService.cachetincidents | async"> - <div *ngIf="h.stat == 'error'" style="color: warn"> - <mat-card color='warn' style='width: 100%'> + <div *ngIf="h.stat == 'error'"> + <mat-card style='width: 100%'> + <div class='health-warn'> {{ h.msg }} + </div> </mat-card> </div> </div> <div *ngFor="let h of tesService.userhealth | async"> - <div *ngIf="h.stat == 'error'" style="color: warn"> - <mat-card color='warn' style='width: 100%'> + <div *ngIf="h.stat == 'error'"> + <mat-card style='width: 100%'> + <div class='health-warn'> {{ h.msg }} + </div> </mat-card> </div> </div> - Jobs running as {{ identity.displayName() }} + Jobs running as {{ (tesService.identitySubject | async).displayName() }} <div *ngFor="let job of tesService.joblist | async"> <app-job [jobdata]=job></app-job> </div> <button mat-button (click)="refreshJobs()" style="width: 100%; text-align: right">Refresh Job list</button> - </div> + </div> </mat-card> <!-- <iframe src="http://localhost:5200" frameborder="0" style="width: 100%"></iframe> --> diff --git a/src/app/joblist/joblist.component.ts b/src/app/joblist/joblist.component.ts index 70e696a077302a96ed0c6d4e8529a7024ee0138d..d77c229350b27e3b37f7d67ccb4b6410f96fee86 100644 --- a/src/app/joblist/joblist.component.ts +++ b/src/app/joblist/joblist.component.ts @@ -31,7 +31,7 @@ export class JoblistComponent implements OnInit { } public refreshJobs(): void { - this.tesService.getJobs(this.identity); + this.tesService.getJobs(this.tesService.identitySubject.value); } } diff --git a/src/app/keygen/keygen.component.html b/src/app/keygen/keygen.component.html index c5a8e0b3d39a78357b678ac65202da95eabaca2d..872fc6343930c1a70058ba865d6cbe10a54e47c5 100644 --- a/src/app/keygen/keygen.component.html +++ b/src/app/keygen/keygen.component.html @@ -1,11 +1,3 @@ -<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> +<mat-card> +Generating cryptographic tokens ... this should only take a few seconds +</mat-card> diff --git a/src/app/launcher/launcher.component.html b/src/app/launcher/launcher.component.html index 12f607f125c2963e424fc0f568449b9baffa172d..a7400ba8202e2befef30faf86de9bda3ad34bba8 100644 --- a/src/app/launcher/launcher.component.html +++ b/src/app/launcher/launcher.component.html @@ -61,11 +61,22 @@ <button type="button" mat-button (click)="fileInput.click()">Load Config</button> <input hidden (change)="loadConfig($event)" accept=".json" #fileInput type="file" id="file"> <button mat-button (click)=resetConfig()>Reset Config</button> + <div style="width: 100%"> + Select a theme + <mat-form-field > + <mat-select [(value)] ="theme" (selectionChange)="selectTheme($event.value)"> + <mat-option *ngFor="let opttheme of themes" [value]="opttheme"> + {{ opttheme.name }} + </mat-option> + </mat-select> + </mat-form-field> + </div> </mat-expansion-panel> </mat-accordion> </mat-sidenav> - <app-joblist [identity]="(identitySubject | async)"></app-joblist> +<!--<app-joblist [identity]="(identitySubject | async)"></app-joblist>--> + <router-outlet></router-outlet> <div fxFlex></div> </mat-sidenav-container> diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts index 3875a4ffda25ffc7035e72961f435d22617f61f3..cd36080a22595ead3b7f6711bb38f830a9f5186a 100644 --- a/src/app/launcher/launcher.component.ts +++ b/src/app/launcher/launcher.component.ts @@ -21,6 +21,10 @@ import { ComputesitesService } from '../computesites.service'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import {OverlayContainer} from '@angular/cdk/overlay'; + + + @@ -32,11 +36,12 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject'; export class LauncherComponent implements OnInit { public strudelapps: Strudelapp[]; @Input() menuopen: boolean; + public themeSubject: BehaviorSubject<string>; public app: Strudelapp; public authorised: boolean; public identity: Identity; - public identitySubject: BehaviorSubject<Identity>; + // public identitySubject: BehaviorSubject<Identity>; public identities: Identity[]; public sshauthzservers: SshAuthzServer[]; @@ -45,21 +50,26 @@ export class LauncherComponent implements OnInit { public selectedApiServer: any; private file: any; private config: any; + public theme: any; + public themes: any[] = [ {'name':'Light','value':'strudel-light-theme'}, + {'name': 'Dark','value':'strudel-dark-theme'}] constructor( public dialog: MatDialog, public tesService: TesService, public backendSelectionService: BackendSelectionService, public authService: AuthorisationService, public computeSitesService: ComputesitesService, + public overlayContainer: OverlayContainer, ) { this.authService.sshAuthzServers.subscribe(o => {this.updateSshAuthZServers(o)}); - this.identitySubject = new BehaviorSubject(undefined); this.computeSitesService.appidentities.subscribe(o => this.verifyIdValid(o)); - this.backendSelectionService.apiserver.subscribe((s) => this.selectedApiServer = s); + this.backendSelectionService.apiserver.subscribe((s) => this.selectedApiServer = s); + this.themeSubject = new BehaviorSubject<string>('strudel-dark-theme'); + this.themeSubject.subscribe(v => this.setTheme(v)); } verifyIdValid(o) { - let currentId = this.identitySubject.value + let currentId = this.tesService.identitySubject.value if (currentId === undefined || currentId == null) { return; } @@ -68,7 +78,7 @@ export class LauncherComponent implements OnInit { return; } } - this.identitySubject.next(null); + this.tesService.identitySubject.next(null); //if (!(this.identitySubject.value in this.computeSitesService.appidentities.value)) { // this.identitySubject.next(null); //} @@ -80,20 +90,28 @@ export class LauncherComponent implements OnInit { ngOnInit() { this.strudelapps = []; - // setTimeout( () => this.authService.updateAgentContents() ) - } - - - //updateIdentities(identities) { - // this.identities = identities; - // console.log(this.identities); - // if (this.identities.length > 0) { - // this.identity = this.identities[0]; + var lstheme: string; + try { + console.log('retrieve theme from localStorage'); + lstheme=localStorage.getItem('strudel-theme'); + console.log(lstheme) + } catch { + } + if (lstheme == null) { + console.log('no theme set, using light'); + lstheme = 'strudel-light-theme'; + } + //Set the value of this.theme so that the selection shows a value rather than a blank + console.log('trying to find the initial value for theme'); + for (let t of this.themes) { + if (t.value == lstheme) { + console.log('found the initial value',t); + this.theme = t; + } + } + this.setTheme(lstheme); - // } else { - // this.strudelapps = []; - // } - //} + } logout() { @@ -114,7 +132,7 @@ export class LauncherComponent implements OnInit { selectId(id: Identity) { this.identity=id; - this.identitySubject.next(id); + this.tesService.identitySubject.next(id); this.tesService.clearJobs(); this.tesService.getJobs(id); this.tesService.cancelHealthRequests(); @@ -152,4 +170,27 @@ export class LauncherComponent implements OnInit { this.authService.removeLocalAuthZ() } + setTheme(v) { + console.log('Theme selected'); + console.log(v); + let theme = v; + console.log(this.overlayContainer.getContainerElement().classList); + let classList = document.querySelector('app-root').classList + console.log('this theme'); + console.log(this.theme); + if (theme == 'strudel-light-theme') { + classList.remove('strudel-dark-theme'); + classList.add('strudel-light-theme'); + } + if (theme == 'strudel-dark-theme') { + classList.remove('strudel-light-theme'); + classList.add('strudel-dark-theme'); + } + console.log('setting localStorage theme',v); +} + + selectTheme(event) { + this.themeSubject.next(event.value); + localStorage.setItem('strudel-theme',event.value); + } } diff --git a/src/app/tes.service.ts b/src/app/tes.service.ts index 6f0c9377cff104fc5cd93164cde7321efbe8a145..cde58cbe9aa4ed51018a410b1fd86b0f68ea5efd 100644 --- a/src/app/tes.service.ts +++ b/src/app/tes.service.ts @@ -52,6 +52,9 @@ private updateUserHealthSub: Subscription; private cachetincidents: BehaviorSubject<Health[]>; private nextUpdate: Subscription; private cancelRequests: Subject<string>; +public theme: BehaviorSubject<string>; +public identitySubject: BehaviorSubject<Identity>; + // public batchinterface: {[id: string] : BatchInterface}; constructor(private http: HttpClient, @@ -70,10 +73,12 @@ private cancelRequests: Subject<string>; this.apiserver = new BehaviorSubject<APIServer>(null); this.apiservers = new BehaviorSubject<APIServer[]>([]); this.cancelRequests = new Subject<string>(); + this.identitySubject = new BehaviorSubject<Identity>(null); this.timerSubscription = null; this.appwindowWatcher = null; this.backendSelectionService.apiserver.subscribe( (value) => { if (value != null) {this.twsproxy = value.tws ; this.Base = value.tes }}); + this.theme = new BehaviorSubject('strudel-light-theme'); // this.batchinterface = {}; // this.computesitesService.identities.subscribe(identities => this.startPolling(identities)); } @@ -82,6 +87,9 @@ public setStatusMsg(statusMsg: BehaviorSubject<any>) { this.statusMsg = statusMsg; } + public setTheme(theme: string) { + this.theme.next(theme); + } private buildParams(app: Strudelapp, identity: Identity, batchinterface: BatchInterface, appinst?: any): string { let params = new URLSearchParams(); @@ -167,6 +175,7 @@ public setStatusMsg(statusMsg: BehaviorSubject<any>) { private getCachetIncidentsError(error: any) { return this.getJobsError(error) } + public cancelHealthRequests() { this.cancelRequests.next('cancel') diff --git a/src/health-warn.scss b/src/health-warn.scss new file mode 100644 index 0000000000000000000000000000000000000000..170b6ca40dca128d7df01a35a7afee1aa9c08f2a --- /dev/null +++ b/src/health-warn.scss @@ -0,0 +1,10 @@ +@mixin health-warning-theme($theme) { + $primary: map-get($theme, primary); + $warn: map-get($theme, warn); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); + + .health-warn { + color: mat-color($warn); + } +} diff --git a/src/styles.css b/src/styles.css deleted file mode 100644 index f81c956193d096ce740bbff4ecaee6307770d88a..0000000000000000000000000000000000000000 --- a/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ -@import url( 'https://fonts.googleapis.com/css?family=Roboto:400,700|Material+Icons'); -@import "~@angular/material/prebuilt-themes/indigo-pink.css"; diff --git a/src/styles.scss b/src/styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..bd99ec6c6936b0132496bb0860abb9f7cd5ce632 --- /dev/null +++ b/src/styles.scss @@ -0,0 +1,39 @@ +@import "~@angular/material/theming"; +@import "~@angular/material/prebuilt-themes/deeppurple-amber.css"; +@import 'health-warn.scss'; +@import url('https://fonts.googleapis.com/css?family=Roboto:400,700|Material+Icons'); +// Plus imports for other components in your app. + +// Include the common styles for Angular Material. We include this here so that you only +// have to load a single css file for Angular Material in your app. +// **Be sure that you only ever include this mixin once!** +@include mat-core(); + +// Define the default theme (same as the example above). +$strudel-app-primary: mat-palette($mat-indigo); +$strudel-app-accent: mat-palette($mat-pink, A200, A100, A400); +$strudel-app-theme: mat-light-theme($strudel-app-primary, $strudel-app-accent); +$health-warn: $mat-pink; + +// Include the default theme styles. +@include angular-material-theme($strudel-app-theme); +@include health-warning-theme($strudel-app-theme); + + +// Define an alternate dark theme. +$dark-primary: mat-palette($mat-blue-grey); +$dark-accent: mat-palette($mat-amber, A200, A100, A400); +$dark-warn: mat-palette($mat-deep-orange); +$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn); + +// Include the alternative theme styles inside of a block with a CSS class. You can make this +// CSS class whatever you want. In this example, any component inside of an element with +// `.strudel-dark-theme` will be affected by this alternate dark theme instead of the default theme. +.strudel-light-theme { + @include angular-material-theme($strudel-app-theme); + @include health-warning-theme($strudel-app-theme); +} +.strudel-dark-theme { + @include angular-material-theme($dark-theme); + @include health-warning-theme($dark-theme); +}