Commit 2ce5f255 authored by Lukas Burgey's avatar Lukas Burgey

Change display of live updates

parent b717a992
<p> <p class="mat-body-1">
You can delete your account. All deployments will be withdrawn if you choose to do so. You can delete your account. All deployments will be withdrawn if you choose to do so.
</p> </p>
<p class="mat-body-2">
<mat-checkbox [(ngModel)]="sure" style="margin-right: 8px" [checked]="sure">
</mat-checkbox>
I'm sure I want to delete all my data on the server.
<p> <p>
<mat-checkbox [(ngModel)]="sure" <button mat-raised-button mat-dialog-close color="primary" (click)="delete()" [disabled]="!sure">
style="margin-right: 8px" Delete
[checked]="sure"> </button>
I'm sure I want to delete all my data on the server.
</mat-checkbox>
<button mat-raised-button mat-dialog-close color="primary" (click)="delete()" [disabled]="!sure">Delete</button>
</p> </p>
<mat-toolbar color="primary"> <mat-toolbar color="primary" class="mat-typography">
<span>Federated User Credential Deployment Portal</span> <mat-toolbar-row>
<span class="toolbar-spacer"></span> <h1>
<app-login></app-login> Federated User Credential Deployment Portal
</h1>
</mat-toolbar-row>
<mat-toolbar-row>
<app-login></app-login>
</mat-toolbar-row>
</mat-toolbar> </mat-toolbar>
<div class="outer"> <div class="outer">
<div class="inner"> <div class="inner">
......
...@@ -2,7 +2,6 @@ import {BrowserModule} from '@angular/platform-browser'; ...@@ -2,7 +2,6 @@ import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {JsonPipe} from '@angular/common'; import {JsonPipe} from '@angular/common';
import {HttpModule} from '@angular/http'; import {HttpModule} from '@angular/http';
import {HttpClientModule, HttpClientXsrfModule} from '@angular/common/http'; import {HttpClientModule, HttpClientXsrfModule} from '@angular/common/http';
...@@ -19,6 +18,8 @@ import {MatSelectModule} from '@angular/material/select'; ...@@ -19,6 +18,8 @@ import {MatSelectModule} from '@angular/material/select';
import {MatInputModule} from '@angular/material/input'; import {MatInputModule} from '@angular/material/input';
import {MatCheckboxModule} from '@angular/material/checkbox'; import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatTooltipModule} from '@angular/material/tooltip'; import {MatTooltipModule} from '@angular/material/tooltip';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
// Other libs // Other libs
import {StompRService} from '@stomp/ng2-stompjs'; import {StompRService} from '@stomp/ng2-stompjs';
...@@ -58,11 +59,6 @@ import {AccountComponent} from './account/account.component'; ...@@ -58,11 +59,6 @@ import {AccountComponent} from './account/account.component';
cookieName: 'csrftoken', cookieName: 'csrftoken',
headerName: 'HTTP_X_CSRFTOKEN', headerName: 'HTTP_X_CSRFTOKEN',
}), }),
/*
RouterModule.forRoot(
routes,
),
*/
MatButtonModule, MatButtonModule,
MatToolbarModule, MatToolbarModule,
MatTableModule, MatTableModule,
...@@ -75,6 +71,8 @@ import {AccountComponent} from './account/account.component'; ...@@ -75,6 +71,8 @@ import {AccountComponent} from './account/account.component';
MatInputModule, MatInputModule,
MatCheckboxModule, MatCheckboxModule,
MatTooltipModule, MatTooltipModule,
MatProgressBarModule,
MatProgressSpinnerModule,
], ],
providers: [ providers: [
CookieService, CookieService,
......
<span *ngIf="userService.loggedIn ? false : true"> <span class=".row-fill-remaining-space"></span>
<form *ngIf="idps" <span>
<span *ngIf="userService.loggedIn ? false : true">
<form *ngIf="idps"
(ngSubmit)="userService.login(selectedIdP)" #loginForm="ngForm"> (ngSubmit)="userService.login(selectedIdP)" #loginForm="ngForm">
<mat-form-field> <mat-form-field>
<mat-select name="idp" required [(ngModel)]="selectedIdP"> <mat-select name="idp" required [(ngModel)]="selectedIdP">
<mat-option *ngFor="let idp of idps" [value]="idp"> <mat-option *ngFor="let idp of idps" [value]="idp">
{{ idp.name }} {{ idp.name }}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<button mat-raised-button [disabled]="!loginForm.form.valid" color="accent" type="submit">Login</button> <button mat-raised-button [disabled]="!loginForm.form.valid" color="accent" type="submit">Login</button>
</form> </form>
</span> </span>
<span *ngIf="userService.loggedIn"> <span *ngIf="userService.loggedIn">
<button mat-button mat-icon-button (click)="dialog.openAccount()"> <button mat-button mat-icon-button (click)="dialog.openAccount()">
<mat-icon>settings</mat-icon> <mat-icon>settings</mat-icon>
</button> </button>
<button mat-button mat-icon-button (click)="dialog.openSshKeys()"> <button mat-button mat-icon-button (click)="dialog.openSshKeys()">
<mat-icon>vpn_key</mat-icon> <mat-icon>vpn_key</mat-icon>
</button> </button>
<button mat-button (click)="dialog.openProfile()"> <button mat-button (click)="dialog.openProfile()">
{{ userService.user?.email }} {{ userService.user?.email }}
</button> </button>
<button mat-raised-button color="accent" (click)="userService.logout()">Logout</button> <button mat-raised-button color="accent" (click)="userService.logout()">Logout</button>
</span>
</span> </span>
<div *ngIf="userService.loggedIn"> <div *ngIf="userService.loggedIn">
<div> <div class="mat-typography">
<h4>Services</h4> <h2>Services</h2>
<div *ngIf="userService.services.length > 0"> <div *ngIf="userService.services.length > 0">
<mat-accordion> <mat-accordion>
<app-service *ngFor="let service of userService.services" <app-service *ngFor="let service of userService.services"
...@@ -16,7 +16,15 @@ ...@@ -16,7 +16,15 @@
<h4>Uncompleted tasks</h4> <h4>Uncompleted tasks</h4>
<div> <div>
<p *ngFor="let task of userService.user.deployment_tasks"> <p *ngFor="let task of userService.user.deployment_tasks">
{{ task.action }}: {{ task.key }} {{ task | json }}
</p>
</div>
</div>
<div *ngIf="userService.messages.length > 0">
<h4>Messages</h4>
<div>
<p *ngFor="let message of userService.messages">
{{ message }}
</p> </p>
</div> </div>
</div> </div>
......
<mat-expansion-panel> <mat-expansion-panel *ngIf="serviceData">
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title>{{ serviceData.name }}</mat-panel-title> <mat-panel-title>{{ serviceData.name }}</mat-panel-title>
<mat-panel-description>{{ serviceData.description }}</mat-panel-description> <mat-panel-description>{{ serviceData.description }}</mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div style="padding-bottom: 10px;"> <table width="60%">
<span style="padding-right: 35px;" <tr style="margin-bottom: 15px;">
*ngFor="let site of serviceData.site" <td *ngFor="let site of serviceData.site">
matTooltip="Provided at site {{ site.name }}"> <span matTooltip="Provided at site {{ site.name }}">
<mat-icon style="vertical-align: middle; padding-right: 5px;">storage</mat-icon> <mat-icon style="vertical-align: middle; padding-right: 5px;">storage</mat-icon>
{{ site.name }} {{ site.name }}
</span> </span>
</div> <span *ngIf="userService.taskInProgress(site, serviceData); then progress else done"></span>
<div> <ng-template #progress matTooltip="A task is in progress">
<span style="padding-right: 35px;" <span style="display: inline-block; vertical-align: middle">
*ngFor="let group of serviceData.groups" <mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
matTooltip="Can be used with membership of group {{ group.name }}"> </span>
<mat-icon style="vertical-align: middle; padding-right: 5px;">lock outline</mat-icon> </ng-template>
{{ group.name }} <ng-template #done>
</span> <span matTooltip="All tasks are done">
</div> <mat-icon style="vertical-align: middle">done</mat-icon>
</span>
</ng-template>
</td>
</tr>
<tr>
<td style="padding-right: 35px;"
*ngFor="let group of serviceData.groups"
matTooltip="Can be used with membership of group {{ group.name }}">
<mat-icon style="vertical-align: middle; padding-right: 5px;">lock outline</mat-icon>
{{ group.name }}
</td>
</tr>
</table>
<mat-action-row> <mat-action-row>
<div *ngIf="userService.user.ssh_keys.length > 0"> <div *ngIf="userService.user.ssh_keys.length > 0; then boxes else upload"></div>
<ng-template #boxes>
<span style="margin-right: 15px;"> <span style="margin-right: 15px;">
Deployed keys: SSH Keys:
</span><br/> </span>
<mat-checkbox *ngFor="let key of userService.user.ssh_keys" <mat-checkbox *ngFor="let key of userService.user.ssh_keys"
style="margin-right: 8px" style="margin-right: 8px"
[checked]="isDeployed(key)" [checked]="isDeployed(key)"
(change)="deploymentChange(key)"> (change)="deploymentChange(key)">
{{ key.name }} {{ key.name }}
</mat-checkbox> </mat-checkbox>
</div> </ng-template>
<div *ngIf="userService.user.ssh_keys.length === 0"> <ng-template #upload>
<span style="margin-right: 15px;">
Please upload an SSH Key to use this service:
</span>
<button mat-icon-button (click)="dialog.openSshKeys()"><mat-icon>vpn_key</mat-icon></button> <button mat-icon-button (click)="dialog.openSshKeys()"><mat-icon>vpn_key</mat-icon></button>
</div> </ng-template>
</mat-action-row> </mat-action-row>
</mat-expansion-panel> </mat-expansion-panel>
...@@ -13,6 +13,7 @@ export class SnackBarService { ...@@ -13,6 +13,7 @@ export class SnackBarService {
} }
public open(message: string) { public open(message: string) {
console.log(message); console.log(message);
return this.snackBar.open(message, '', this.config); return this.snackBar.open(message, '', this.config);
} }
......
<div style="margin-bottom: 25px;"> <div style="margin-bottom: 25px;">
<mat-table *ngIf="userService.user.ssh_keys" [dataSource]="userService.sshKeyData"> <div *ngIf="userService.user.ssh_keys.length > 0; then key_list else upload_note"></div>
</div>
<div *ngIf="upload; then uploading else not_uploading"></div>
<ng-template #key_list>
<mat-table [dataSource]="userService.sshKeyData">
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell> <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.name}}</mat-cell> <mat-cell *matCellDef="let element">{{ element.name}}</mat-cell>
...@@ -11,20 +15,24 @@ ...@@ -11,20 +15,24 @@
<ng-container matColumnDef="action"> <ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef>Action</mat-header-cell> <mat-header-cell *matHeaderCellDef>Action</mat-header-cell>
<mat-cell *matCellDef="let element"> <mat-cell *matCellDef="let element">
<button mat-icon-button (click)="deleteKey(element)"><mat-icon>delete_forever</mat-icon></button> <button mat-icon-button (click)="deleteKey(element)">
<mat-icon>delete_forever</mat-icon>
</button>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<mat-header-row *matHeaderRowDef="columns"></mat-header-row> <mat-header-row *matHeaderRowDef="columns"></mat-header-row>
<mat-row *matRowDef="let row; columns: columns;"></mat-row> <mat-row *matRowDef="let row; columns: columns;"></mat-row>
</mat-table> </mat-table>
<p *ngIf="!userService.user.ssh_keys"> </ng-template>
<ng-template #upload_note>
<p>
You have no uploaded keys. You have no uploaded keys.
</p> </p>
</div> </ng-template>
<div *ngIf="!upload"> <ng-template #uploading>
<button mat-icon-button (click)="upload = true"><mat-icon>add</mat-icon></button> <button mat-icon-button (click)="upload = true"><mat-icon>add</mat-icon></button>
</div> </ng-template>
<div *ngIf="upload" class="form-container"> <ng-template #not_uploading>
<form (ngSubmit)="uploadKey()" #sshKeyForm="ngForm"> <form (ngSubmit)="uploadKey()" #sshKeyForm="ngForm">
<mat-form-field> <mat-form-field>
<input matInput placeholder="Name" required [(ngModel)]="newKeyName" name="name"> <input matInput placeholder="Name" required [(ngModel)]="newKeyName" name="name">
...@@ -34,4 +42,4 @@ ...@@ -34,4 +42,4 @@
</mat-form-field> </mat-form-field>
<button mat-raised-button color="primary" type="submit" [disabled]="!sshKeyForm.form.valid">Submit</button> <button mat-raised-button color="primary" type="submit" [disabled]="!sshKeyForm.form.valid">Submit</button>
</form> </form>
</div> </ng-template>
...@@ -47,6 +47,8 @@ export interface User { ...@@ -47,6 +47,8 @@ export interface User {
userinfo: any; userinfo: any;
ssh_keys: SSHKey[]; ssh_keys: SSHKey[];
deployments: Deployment[]; deployments: Deployment[];
deployment_tasks: any[];
deployment_task_items: any[];
id: number; id: number;
} }
......
import {Injectable } from '@angular/core';
import {HttpClient, HttpErrorResponse } from '@angular/common/http';
import {Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import {CookieService } from 'ngx-cookie-service'; import {of as observableOf, Observable} from 'rxjs';
import {MatTableDataSource } from '@angular/material';
import {SnackBarService } from './snackbar.service'; import {catchError, map} from 'rxjs/operators';
import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import {CookieService} from 'ngx-cookie-service';
import {MatTableDataSource} from '@angular/material';
import {SnackBarService} from './snackbar.service';
import {StompConfig, StompRService} from '@stomp/ng2-stompjs'; import {StompConfig, StompRService} from '@stomp/ng2-stompjs';
import {Message} from '@stomp/stompjs'; import {Message} from '@stomp/stompjs';
import {environment } from '../environments/environment'; import {environment} from '../environments/environment';
import {IdP, User, Service, AuthInfo, AllAuthInfo, UserState, SSHKey, NewSSHKey } from './types/types.module'; import {IdP, User, Service, AuthInfo, AllAuthInfo, UserState, SSHKey, NewSSHKey} from './types/types.module';
@Injectable() @Injectable()
...@@ -23,6 +26,7 @@ export class UserService { ...@@ -23,6 +26,7 @@ export class UserService {
public sshKeyData: MatTableDataSource<any>; public sshKeyData: MatTableDataSource<any>;
public userInfoData: MatTableDataSource<any>; public userInfoData: MatTableDataSource<any>;
public services: Service[]; public services: Service[];
public messages: string[];
constructor( constructor(
...@@ -32,6 +36,7 @@ export class UserService { ...@@ -32,6 +36,7 @@ export class UserService {
private _stompService: StompRService, private _stompService: StompRService,
) { ) {
this.update(); this.update();
this.messages = [];
} }
public setIdPPreference(idp: IdP) { public setIdPPreference(idp: IdP) {
...@@ -47,7 +52,7 @@ export class UserService { ...@@ -47,7 +52,7 @@ export class UserService {
public getIdPPreference(): Observable<AllAuthInfo> { public getIdPPreference(): Observable<AllAuthInfo> {
let idpID = Number(this.cookieService.get(environment.idpCookieName)); let idpID = Number(this.cookieService.get(environment.idpCookieName));
return this.http.get('/backend/auth/v1/info/').map( return this.http.get('/backend/auth/v1/info/').pipe(map(
(authInfo: AuthInfo) => { (authInfo: AuthInfo) => {
let selected = authInfo.idps[1]; let selected = authInfo.idps[1];
...@@ -64,15 +69,12 @@ export class UserService { ...@@ -64,15 +69,12 @@ export class UserService {
selected: selected, selected: selected,
}; };
} }
).catch( ),catchError(
(error: any) => { (error: any) => {
this.errorHandler(error); this.errorHandler(error);
return Observable.of(null); return observableOf(null);
} }
); ),);
}
private _handleValueChange(newData: any) {
} }
private _updateUserValues(newUser: any) { private _updateUserValues(newUser: any) {
...@@ -150,6 +152,58 @@ export class UserService { ...@@ -150,6 +152,58 @@ export class UserService {
this.updateState(); this.updateState();
} }
private initStomp() {
// handle with care
let login = this.user.id
let passcode = this.cookieService.get('sessionid');
const stompConfig: StompConfig = {
// Which server?
url: 'wss://hdf-portal.data.kit.edu/ws',
// Headers
// Typical keys: login, passcode, host
headers: {
login: 'webpage-client:' + login,
passcode: passcode,
},
// How often to heartbeat?
// Interval in milliseconds, set to 0 to disable
heartbeat_in: 0, // Typical value 0 - disabled
heartbeat_out: 20000, // Typical value 20000 - every 20 seconds
// Wait in milliseconds before attempting auto reconnect
// Set to 0 to disable
// Typical value 5000 (5 seconds)
reconnect_delay: 5000,
// Will log diagnostics on console
debug: false,
};
this._stompService.config = stompConfig;
this._stompService.initAndConnect();
}
private connectLiveUpdates() {
this.initStomp();
let subscription = this._stompService.subscribe(
'/exchange/update/' + this.user.id.toString()
);
subscription.pipe(map((message: Message) => {
return message.body;
})).subscribe((body: any) => {
let json = JSON.parse(body);
if (json.message && json.message != '') {
this.snackBar.open(json.message);
this.messages.push(json.message);
}
if (json.user_state) {
this._updateUserValues(json.user_state);
}
});
}
public login(idp: IdP) { public login(idp: IdP) {
this.setIdPPreference(idp); this.setIdPPreference(idp);
window.location.href = 'https://hdf-portal.data.kit.edu/backend/auth/v1/request/'; window.location.href = 'https://hdf-portal.data.kit.edu/backend/auth/v1/request/';
...@@ -250,54 +304,15 @@ export class UserService { ...@@ -250,54 +304,15 @@ export class UserService {
); );
} }
public initStomp() { public taskInProgress(site, service): boolean {
// handle with care if (site && service) {
let login = this.user.id
let passcode = this.cookieService.get('sessionid');
const stompConfig: StompConfig = {
// Which server?
url: 'wss://hdf-portal.data.kit.edu:15671/ws',
// Headers
// Typical keys: login, passcode, host
headers: {
login: 'webpage-client:' + login,
passcode: passcode,
},
// How often to heartbeat?
// Interval in milliseconds, set to 0 to disable
heartbeat_in: 0, // Typical value 0 - disabled
heartbeat_out: 20000, // Typical value 20000 - every 20 seconds
// Wait in milliseconds before attempting auto reconnect
// Set to 0 to disable
// Typical value 5000 (5 seconds)
reconnect_delay: 5000,
// Will log diagnostics on console
debug: false,
};
this._stompService.config = stompConfig;
this._stompService.initAndConnect();
}
public connectLiveUpdates() {
this.initStomp();
let subscription = this._stompService.subscribe(
'/exchange/update/' + this.user.id.toString()
);
subscription.map((message: Message) => { for (const item of this.user.deployment_task_items){
return message.body; if (item.site.id == site.id && item.service.id == service.id) {
}).subscribe((body: any) => { return true;
let json = JSON.parse(body); }
if (json.message && json.message != '') {
this.snackBar.open( json.message);
}
if (json.user_state) {
this._updateUserValues(json.user_state);
} }
}); }
return false;
} }
} }
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