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

Change display of live updates

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