Commit 0cd7b267 authored by Lukas Burgey's avatar Lukas Burgey

Refactor the depiction of VO services

parent 62b54714
<div class="body"> <div class="body">
<div *ngIf="userService.loggedIn()" class="mat-typography"> <div *ngIf="userService.loggedIn()" class="mat-typography">
<div style="padding-bottom: 30px;">
<h2>Your Virtual Organisations</h2>
<mat-accordion *ngIf="userService.user.groups.length > 0">
<app-vo *ngFor="let group of userService.getGroups()" [group]="group" [deployment]="userService.getDeploymentByGroup(group)"></app-vo>
</mat-accordion>
</div>
<div style="padding-bottom: 30px;"> <div style="padding-bottom: 30px;">
<h2>Services</h2> <h2>Services</h2>
<mat-accordion *ngIf="userService.services.length > 0"> <mat-accordion *ngIf="userService.services.length > 0">
...@@ -10,11 +16,5 @@ ...@@ -10,11 +16,5 @@
This is due services requiring users to be member of a certain group. This is due services requiring users to be member of a certain group.
</p> </p>
</div> </div>
<div *ngIf="userService.user" style="padding-bottom: 30px;">
<h2>Your Virtual Organisations</h2>
<mat-accordion *ngIf="userService.user.groups.length > 0">
<app-vo *ngFor="let group of userService.getGroups()" [group]="group"></app-vo>
</mat-accordion>
</div>
</div> </div>
</div> </div>
<div class="mat-typography"> <div class="mat-typography">
<h2>Credentials</h2> <h2>Credentials</h2>
<p> <p>
You can access the service {{ stateItem.service.name }} at {{ stateItem.site.name }} using the SSH Key {{ stateItem.key.name }}. You can access the service {{ service.name }} at {{ service.site[0].name }} using your SSH Key {{ stateItem.key.name }}.
</p> </p>
<div *ngIf="credentialCount > 0"> <div *ngIf="credentialCount > 0">
<p> <p>
......
...@@ -13,6 +13,7 @@ import * as t from '../../types/types.module'; ...@@ -13,6 +13,7 @@ import * as t from '../../types/types.module';
export class CredentialsComponent implements OnInit { export class CredentialsComponent implements OnInit {
public columns = ["name", "value"]; public columns = ["name", "value"];
public stateItem: t.DeploymentStateItem; public stateItem: t.DeploymentStateItem;
public service: t.Service;
public credentialCount: number = 0; public credentialCount: number = 0;
public table: MatTableDataSource<any>; public table: MatTableDataSource<any>;
...@@ -21,6 +22,7 @@ export class CredentialsComponent implements OnInit { ...@@ -21,6 +22,7 @@ export class CredentialsComponent implements OnInit {
@Inject(MAT_DIALOG_DATA) public data: any, @Inject(MAT_DIALOG_DATA) public data: any,
) { ) {
this.stateItem = data.stateItem; this.stateItem = data.stateItem;
this.service = data.service;
} }
ngOnInit() { ngOnInit() {
......
...@@ -57,12 +57,13 @@ export class DialogService { ...@@ -57,12 +57,13 @@ export class DialogService {
); );
} }
public openCredentials(stateItem: t.DeploymentStateItem) { public openCredentials(service: t.Service, stateItem: t.DeploymentStateItem) {
this.credentialsDialog = this.dialog.open( this.credentialsDialog = this.dialog.open(
CredentialsComponent, CredentialsComponent,
{ {
data: { data: {
stateItem: stateItem, stateItem: stateItem,
service: service,
} }
} }
); );
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<span [ngSwitch]="taskState(site, key)" class="childs-inline"> <span [ngSwitch]="taskState(site, key)" class="childs-inline">
<!-- states with actions --> <!-- states with actions -->
<button *ngSwitchCase="'deployed'" mat-button mat-icon-button <button *ngSwitchCase="'deployed'" mat-button mat-icon-button
(click)="dialog.openCredentials(taskItem(site, key))" (click)="dialog.openCredentials(service, taskItem(site, key))"
matTooltip="The key {{key.name}} is deployed to the site. Click to see details."> matTooltip="The key {{key.name}} is deployed to the site. Click to see details.">
<mat-icon style="vertical-align: middle">call_made</mat-icon> <mat-icon style="vertical-align: middle">call_made</mat-icon>
</button> </button>
......
...@@ -48,7 +48,8 @@ export interface SSHKeyRef { ...@@ -48,7 +48,8 @@ export interface SSHKeyRef {
export interface Service { export interface Service {
id: number; id: number;
name: string; name: string;
sites: Site[]; site: Site[];
description: string;
groups: Group[]; groups: Group[];
} }
...@@ -64,10 +65,14 @@ export interface DeploymentStateItem { ...@@ -64,10 +65,14 @@ export interface DeploymentStateItem {
credentials: JSONObject; credentials: JSONObject;
key: SSHKeyRef; key: SSHKeyRef;
service: Service; service: Service;
services: Service[];
group: Group;
} }
export interface DeploymentState { export interface DeploymentState {
id: number; id: number;
service: Service; service: Service;
services: Service[];
group: Group;
key: SSHKeyRef; key: SSHKeyRef;
state_items: DeploymentStateItem[]; state_items: DeploymentStateItem[];
} }
...@@ -78,6 +83,7 @@ export interface Deployment { ...@@ -78,6 +83,7 @@ export interface Deployment {
group: number; // the group id group: number; // the group id
ssh_keys: SSHKeyRef[]; ssh_keys: SSHKeyRef[];
states: DeploymentState[]; states: DeploymentState[];
sites: Site[];
} }
export interface User { export interface User {
......
...@@ -75,7 +75,7 @@ export class UserService { ...@@ -75,7 +75,7 @@ export class UserService {
private connectLiveUpdates() { private connectLiveUpdates() {
this.initStomp(); this.initStomp();
let subscription = this._stompService.subscribe( let subscription = this._stompService.subscribe(
'/exchange/update/' + this.user.id.toString() '/exchange/users/' + this.user.id.toString()
); );
subscription.subscribe( subscription.subscribe(
...@@ -178,6 +178,12 @@ export class UserService { ...@@ -178,6 +178,12 @@ export class UserService {
} }
// PUBLIC API // PUBLIC API
public serviceDescription(service: t.Service): string {
if (service.description != "") {
return service.description;
}
return "No description";
}
public getDeployment(service: t.Service): t.Deployment { public getDeployment(service: t.Service): t.Deployment {
return this.userState.deployments.find( return this.userState.deployments.find(
dep => { dep => {
...@@ -193,6 +199,15 @@ export class UserService { ...@@ -193,6 +199,15 @@ export class UserService {
return this.groupMap.get(group.name); return this.groupMap.get(group.name);
} }
private getDeploymentByGroup(group: t.Group): t.Deployment | undefined {
let dep = this.userState.deployments.find(
(d: t.Deployment) => {
return d.group === group.id;
}
);
return dep
}
public getGroups(): t.Group[] { public getGroups(): t.Group[] {
if (this.user.groups) { if (this.user.groups) {
return this.user.groups.sort( return this.user.groups.sort(
......
<mat-expansion-panel> <mat-expansion-panel>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title style="min-width: 100px;">{{ group.name }}</mat-panel-title> <mat-panel-title style="min-width: 100px;">{{ group.name }}</mat-panel-title>
<mat-panel-description>VO "{{ group.name }}" (Group ID: {{ group.id }})</mat-panel-description> <!--
<mat-panel-description>VO "{{ group.name }}" (Group ID: {{ group.id }})</mat-panel-description>
-->
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div *ngIf="userService.getServices(group).length > 0; then serviceList else noServiceList"></div> <div *ngIf="userService.getServices(group).length > 0; then serviceList else noServiceList"></div>
<ng-template #serviceList> <ng-template #serviceList>
<p> <p>
You have access to these services, because you are a member of the VO "{{ group.name }}": These services are provided for members of this VO:
</p> </p>
<table style="margin-bottom: 30px;"> <table style="margin-bottom: 30px; margin: auto;">
<thead> <thead>
<tr> <tr>
<td></td> <td></td>
...@@ -16,69 +18,76 @@ ...@@ -16,69 +18,76 @@
<td>SSH Keys</td> <td>SSH Keys</td>
</tr> </tr>
<tr> <tr>
<td style="min-width: 150px;">Service</td>
<td style="min-width: 150px;">Site</td> <td style="min-width: 150px;">Site</td>
<td style="min-width: 150px;">Service</td>
<td *ngFor="let key of userService.user.ssh_keys" style="min-width: 100px;"> <td *ngFor="let key of userService.user.ssh_keys" style="min-width: 100px;">
{{key.name}} {{key.name}}
</td> </td>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let service of services()" style="height: 42px;"> <ng-container *ngFor="let site of sites()">
<td> <tr *ngFor="let service of servicesBySite(site);" style="height: 42px;">
<span style="margin-right: 10px;"> <td>
<mat-icon>web</mat-icon> <span style="margin-right: 10px;" matTooltip="Site {{ site.name }} provides the service {{ service.name }} for members of
{{ service.name }} {{ group.name }}">
</span> <mat-icon>account_balance</mat-icon>
</td> {{ site.name }}
<td>
<span *ngFor="let site of service.site" matTooltip="Provided at site {{ site.name }}" style="margin-right: 10px;">
<mat-icon>account_balance</mat-icon>
{{ site.name }}
</span>
</td>
<td *ngFor="let key of userService.user.ssh_keys">
<span *ngFor="let site of service.site" [ngSwitch]="taskState(site, key)" class="childs-inline">
<!-- states with actions -->
<button *ngSwitchCase="'deployed'" mat-button mat-icon-button
(click)="dialog.openCredentials(taskItem(site, key))"
matTooltip="The key {{key.name}} is deployed to the site. Click to see details.">
<mat-icon>call_made</mat-icon>
</button>
<button *ngSwitchCase="'questionnaire'" mat-button mat-icon-button
(click)="dialog.openQuestionnaire(taskItem(site, y))"
matTooltip="This site needs more data to deploy the keys. Please click to submit the data.">
<mat-icon>warning</mat-icon>
</button>
<!-- states without actions -->
<span *ngSwitchCase="'deployment_pending'" mat-icon-button matTooltip="Waiting for the deployment of the key {{ key.name }} by the site">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span> </span>
<span *ngSwitchCase="'removal_pending'" mat-icon-button matTooltip="Waiting for the removal of the key {{ key.name }} from the site"> </td>
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner> <td>
<span style="margin-right: 10px;" matTooltip="{{ userService.serviceDescription(service) }}">
<mat-icon>web</mat-icon>
{{ service.name }}
</span> </span>
<button *ngSwitchCase="'not_deployed'" mat-icon-button matTooltip="The key {{ key.name }} is not deployed to this site."> </td>
<mat-icon>call_received</mat-icon> <td *ngFor="let key of userService.user.ssh_keys">
</button> <span [ngSwitch]="taskState(site, key)" class="childs-inline">
<button *ngSwitchCase="'failed'" mat-icon-button matTooltip="This site failed to deploy the credentials. The deployment will be retried."> <!-- states with actions -->
<mat-icon>error</mat-icon> <button *ngSwitchCase="'deployed'" mat-button mat-icon-button
</button> (click)="dialog.openCredentials(service, taskItem(site, key))"
<button *ngSwitchCase="'rejected'" mat-icon-button matTooltip="This site rejected the deployment of the key {{ key.name }}."> matTooltip="The key {{ key.name }} is deployed for the service {{ service.name }}. Click to see details.">
<mat-icon>error</mat-icon> <mat-icon>call_made</mat-icon>
</button> </button>
<!-- if we have no deployment -> assume state == not_deployed --> <button *ngSwitchCase="'questionnaire'" mat-button mat-icon-button
<span *ngSwitchDefault mat-icon-button matTooltip="The key {{ key.name }} is not deployed to this site."> (click)="dialog.openQuestionnaire(taskItem(site, key))"
<mat-icon>call_received</mat-icon> matTooltip="This site needs more data to deploy the keys. Please click to submit the data.">
<mat-icon>warning</mat-icon>
</button>
<!-- states without actions -->
<span *ngSwitchCase="'deployment_pending'" mat-icon-button matTooltip="Waiting for the deployment of the key {{
key.name }} to the site {{ site.name }}">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span>
<span *ngSwitchCase="'removal_pending'" mat-icon-button matTooltip="Waiting for the removal of the key {{ key.name }}
from the site {{ site.name }}">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span>
<button *ngSwitchCase="'not_deployed'" mat-icon-button
matTooltip="The key {{ key.name }} is not deployed for the service {{ service.name }}.">
<mat-icon>call_received</mat-icon>
</button>
<button *ngSwitchCase="'failed'" mat-icon-button matTooltip="Site {{ site.name }} failed to deploy the credentials. The deployment will be retried.">
<mat-icon>error</mat-icon>
</button>
<button *ngSwitchCase="'rejected'" mat-icon-button matTooltip="Site {{ site.name }} rejected the deployment of the key {{ key.name }}.">
<mat-icon>error</mat-icon>
</button>
<!-- if we have no deployment -> assume state == not_deployed -->
<span *ngSwitchDefault mat-icon-button matTooltip="The key {{ key.name }} is not deployed to the site {{ site.name }}.">
<mat-icon>call_received</mat-icon>
</span>
</span> </span>
</span> </td>
</td> </tr>
</tr> </ng-container>
</tbody> </tbody>
</table> </table>
</ng-template> </ng-template>
<ng-template #noServiceList> <ng-template #noServiceList>
<p> <p>
No services need membership of the VO "{{ group.name }}". Currently, no services need membership of this VO. You can select keys for this VO anyway. We will deploy them to new services, that need
membership of this VO.
</p> </p>
</ng-template> </ng-template>
<mat-action-row> <mat-action-row>
......
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { DialogService } from '../dialogues/dialog.service';
import { UserService } from '../user.service'; import { UserService } from '../user.service';
import * as t from '../types/types.module'; import * as t from '../types/types.module';
...@@ -12,24 +13,46 @@ import * as t from '../types/types.module'; ...@@ -12,24 +13,46 @@ import * as t from '../types/types.module';
export class VoComponent implements OnInit { export class VoComponent implements OnInit {
@Input() group: t.Group; @Input() group: t.Group;
public deployment: t.Deployment; @Input() deployment: t.Deployment;
constructor( constructor(
public userService: UserService, public userService: UserService,
public http: HttpClient, public http: HttpClient,
public dialog: DialogService,
) { } ) { }
ngOnInit() { ngOnInit() {
this.deployment = this._deployment();
} }
private _deployment(): t.Deployment | undefined { public sites(): t.Site[] {
let dep = this.userService.userState.deployments.find( if (this.deployment) {
(d: t.Deployment) => { return this.deployment.sites;
return d.group === this.group.id; }
return this.userService.getServices(this.group).map(
(s: t.Service) => {
if (s.site.length == 1) {
return s.site[0];
} else {
console.log("Group service is provided by more than one site!")
return undefined
}
} }
); );
return dep }
public servicesBySite(site: t.Site): t.Service[] {
if (this.deployment) {
return this.deployment.services.filter(
(s: t.Service) => {
return s.site.some(
(ss: t.Site) => {
return ss.id === site.id;
}
);
}
);
}
return this.userService.getServices(this.group);
} }
public services(): t.Service[] { public services(): t.Service[] {
...@@ -39,7 +62,7 @@ export class VoComponent implements OnInit { ...@@ -39,7 +62,7 @@ export class VoComponent implements OnInit {
return this.userService.getServices(this.group); return this.userService.getServices(this.group);
} }
public taskItem(site: t.Site, key: t.SSHKeyRef): t.DeploymentStateItem | undefined { public taskItem(site: t.Site, key: t.SSHKeyRef): t.DeploymentStateItem {
if (this.deployment == undefined) { if (this.deployment == undefined) {
return undefined; return undefined;
} }
......
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