Commit c7091df6 authored by Lukas Burgey's avatar Lukas Burgey

Fix the service list

parent a07a5a1e
......@@ -11,7 +11,7 @@ import { SSHKey, NewSSHKey } from '../../types/types.module';
})
export class SshKeysComponent implements OnInit {
columns = ['name', 'key', 'action'];
// does the user want to update a key?
// does the user want to upload a key?
upload: boolean;
newKeyName: string;
newKeyKey: string;
......@@ -31,7 +31,7 @@ export class SshKeysComponent implements OnInit {
name: this.newKeyName,
key: this.newKeyKey,
};
this.userService.addSshKey(newKey);
this.userService.uploadSshKey(newKey);
this.ngOnInit();
}
......
<div *ngIf="userService.loggedIn()">
<div style="padding-bottom: 30px;">
<h2>Services</h2>
<div *ngIf="userService.services.length > 0">
<mat-accordion>
<app-service *ngFor="let service of userService.services"
[service]="service"></app-service>
</mat-accordion>
</div>
<p *ngIf="userService.services?.length == 0">
<mat-accordion *ngIf="userService.deploymentIDs.length > 0">
<app-service *ngFor="let dID of userService.deploymentIDs" [deployment]="userService.getDeployment(dID)"></app-service>
</mat-accordion>
<p *ngIf="userService.deploymentIDs.length === 0">
You have no available services.<br/>
This is due services requiring users to be member of a certain group.
</p>
</div>
<!--
<div *ngIf="userService.user.deployment_tasks.length > 0">
<h3>Uncompleted tasks</h3>
<div>
<pre *ngFor="let task of userService.user.deployment_tasks">
{{ task | json }}
</pre>
</div>
</div>
<div *ngIf="userService.messages.length > 0">
<h3>Messages</h3>
<div>
<p *ngFor="let message of userService.messages">
{{ message }}
</p>
</div>
</div>
-->
</div>
<mat-expansion-panel *ngIf="service">
<mat-expansion-panel *ngIf="deployment">
<mat-expansion-panel-header>
<mat-panel-title>{{ service.name }}</mat-panel-title>
<mat-panel-title>{{ service.name }}</mat-panel-title>
<mat-panel-description>{{ service.description }}</mat-panel-description>
</mat-expansion-panel-header>
<table width="60%">
<tr style="margin-bottom: 15px;">
<td *ngFor="let site of service.site">
<span matTooltip="Provided at site {{ site.name }}" style="margin-right: 10px;">
<mat-icon style="vertical-align: middle; padding-right: 5px;">storage</mat-icon>
{{ site.name }}
</span>
<span *ngIf="userService.user.ssh_keys.length > 0">
<span *ngFor="let key of userService.user.ssh_keys"
[ngSwitch]="userService.taskState(site, service, key)" class="childs-inline" style="margin-right: 5px;">
<!-- states with actions -->
<button *ngSwitchCase="'deployed'" mat-button mat-icon-button
matTooltip="The key {{key.name}} is deployed to the site. Click to see details.">
<mat-icon style="vertical-align: middle">call_made</mat-icon>
</button>
<button *ngSwitchCase="'questionnaire'" mat-button mat-icon-button
(click)="dialog.openQuestionnaire(userService.taskItem(site, service))"
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'" 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 *ngSwitchCase="'removal_pending'" matTooltip="Waiting for the removal of the key {{ key.name }} from the site">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span>
<span *ngSwitchCase="'not_deployed'" matTooltip="The key {{ key.name }} is not deployed to this site.">
<mat-icon style="vertical-align: middle">call_received</mat-icon>
</span>
<span *ngSwitchCase="'failed'" matTooltip="This site failed to deploy the credentials. The deployment will be retried.">
<mat-icon style="vertical-align: middle">error</mat-icon>
</span>
<span *ngSwitchCase="'rejected'" matTooltip="This site rejected the deployment of the key {{ key.name }}.">
<mat-icon style="vertical-align: middle">error</mat-icon>
</span>
<span *ngSwitchDefault matTooltip="Unrecognized state">
<mat-icon style="vertical-align: middle">error</mat-icon>
<table>
<tr style="margin-bottom: 25px;">
<td>
<span *ngFor="let site of service.site" style="margin-right: 15px;">
<span matTooltip="Provided at site {{ site.name }}" style="margin-right: 10px;">
<mat-icon style="vertical-align: middle; padding-right: 5px;">storage</mat-icon>
{{ site.name }}
</span>
<span *ngIf="userService.user.ssh_keys.length > 0" style="margin-right: 10px;">
<span *ngFor="let key of userService.user.ssh_keys"
[ngSwitch]="taskState(site, key)" class="childs-inline">
<!-- states with actions -->
<button *ngSwitchCase="'deployed'" mat-button mat-icon-button
matTooltip="The key {{key.name}} is deployed to the site. Click to see details.">
<mat-icon style="vertical-align: middle">call_made</mat-icon>
</button>
<button *ngSwitchCase="'questionnaire'" mat-button mat-icon-button
(click)="dialog.openQuestionnaire(userService.taskItem(site, service))"
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 *ngSwitchCase="'removal_pending'" mat-icon-button matTooltip="Waiting for the removal of the key {{ key.name }} from the site">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span>
<span *ngSwitchCase="'not_deployed'" mat-icon-button matTooltip="The key {{ key.name }} is not deployed to this site.">
<mat-icon style="vertical-align: middle">call_received</mat-icon>
</span>
<span *ngSwitchCase="'failed'" mat-icon-button matTooltip="This site failed to deploy the credentials. The deployment will be retried.">
<mat-icon style="vertical-align: middle">error</mat-icon>
</span>
<span *ngSwitchCase="'rejected'" mat-icon-button matTooltip="This site rejected the deployment of the key {{ key.name }}.">
<mat-icon style="vertical-align: middle">error</mat-icon>
</span>
<!-- hacky solution -->
<span *ngSwitchDefault mat-icon-button matTooltip="Receiving update from backend">
<mat-progress-spinner diameter="24" mode="indeterminate"></mat-progress-spinner>
</span>
</span>
</span>
</span>
......@@ -48,8 +51,8 @@
</tr>
<tr>
<td style="padding-right: 35px;"
*ngFor="let group of service.groups"
matTooltip="Can be used with membership of group {{ group.name }}">
*ngFor="let group of service.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>
......@@ -62,9 +65,9 @@
SSH Keys:
</span>
<mat-checkbox *ngFor="let key of userService.user.ssh_keys"
style="margin-right: 8px"
[checked]="isDeployed(key)"
(change)="deploymentChange(key)">
style="margin-right: 8px"
[checked]="isDeployed(key)"
(change)="deploymentChange(key)">
{{ key.name }}
</mat-checkbox>
</ng-template>
......
import { Component, OnInit, Input } from '@angular/core';
import { MatCheckboxChange } from '@angular/material/checkbox';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import { UserService } from '../user.service';
import { DialogService } from '../dialogues/dialog.service';
......@@ -12,23 +14,18 @@ import * as t from '../types/types.module';
styleUrls: ['./service.component.css']
})
export class ServiceComponent implements OnInit {
@Input() service: t.Service;
public sshKeys: t.SSHKeyRef[];
public deployment: t.Deployment;
@Input() deployment: t.Deployment;
public service: t.Service;
constructor(
public userService: UserService,
public dialog: DialogService,
public http: HttpClient,
) {
}
ngOnInit() {
this.sshKeys = this.userService.user.ssh_keys;
this.deployment = this.userService.userState.deployments.find(
d => {
return d.service.id === this.service.id;
}
);
this.service = this.deployment.service;
}
public isDeployed(key: t.SSHKeyRef): boolean {
......@@ -40,11 +37,55 @@ export class ServiceComponent implements OnInit {
return false;
}
public deploymentChange(key) {
public taskItem(site: t.Site, key: t.SSHKeyRef): t.DeploymentStateItem {
if (this.deployment) {
const deploymentState = this.deployment.states.find(
state => {
return state.key.id === key.id
}
);
if (deploymentState) {
return deploymentState.state_items.find(
item => {
return item.site.id === site.id
}
);
}
}
}
public taskState(site: t.Site, key: t.SSHKeyRef): string {
let item = this.taskItem(site, key);
if (item) {
return item.state;
}
return "";
}
public changeDeployment(key: t.SSHKeyRef, action: string) {
const body = {
'type': action,
'key': key.id,
'service': this.service.id,
};
return this.http.post('/backend/api/deployments', body).subscribe(
(newDep: t.Deployment) => {
// update the deployment
this.deployment = newDep;
},
(err) => {
console.log(err);
this.userService.update();
}
);
}
public deploymentChange(key: t.SSHKeyRef) {
if (!this.isDeployed(key)) {
this.userService.addDeployment(this.service, key);
this.changeDeployment(key, 'add');
} else {
this.userService.removeDeployment(this.service, key);
this.changeDeployment(key, 'remove');
}
}
}
......@@ -63,9 +63,11 @@ export interface DeploymentStateItem {
export interface DeploymentState {
id: number;
service: Service;
key: SSHKeyRef;
state_items: DeploymentStateItem[];
}
export interface Deployment {
id: number;
service: Service;
ssh_keys: SSHKeyRef[];
ssh_keys_to_withdraw: SSHKeyRef[];
......
......@@ -22,8 +22,10 @@ export class UserService {
public user: t.User;
public userState: t.UserState;
public messages: string[] = [];
public services: t.Service[];
// local copy of deployments
public deploymentIDs: number[] = [];
constructor(
......@@ -92,6 +94,14 @@ export class UserService {
this.user = newUser;
}
private updateDeployments(newDeployments: t.Deployment[]){
if (this.deploymentIDs.length !== newDeployments.length) {
for (let dep of newDeployments) {
this.deploymentIDs.push(dep.id);
}
}
}
private updateUserState(newState: t.UserState) {
// did a login occur?
let login = (!this._loggedIn && newState);
......@@ -110,13 +120,14 @@ export class UserService {
this._stompService.disconnect();
}
this.updateDeployments(newState.deployments);
this.userState = newState;
}
private stateAPIUpdate(update: t.StateAPIResult) {
this.updateUser(update.user)
this.updateUserState(update.user_state);
this.services = update.services;
// report an occured error
if (update.error) {
......@@ -129,6 +140,13 @@ export class UserService {
}
// PUBLIC API
public getDeployment(id: number): t.Deployment {
return this.userState.deployments.find(
dep => {
return dep.id == id
}
);
}
public userInfo(): MatTableDataSource<any> {
const userInfoList = [];
for (const key in this.user.userinfo) {
......@@ -211,7 +229,7 @@ export class UserService {
);
}
public addSshKey(key: t.NewSSHKey) {
public uploadSshKey(key: t.NewSSHKey) {
const body = {
'type': 'add',
'key': key,
......@@ -236,6 +254,9 @@ export class UserService {
return this.http.post('/backend/api/sshkey', body).subscribe(
(data: t.UserState) => {
this.updateUserState(data);
this.user.ssh_keys = this.user.ssh_keys.filter(
k => key.id == k.id
);
},
(err) => {
this.snackBar.open('Error deleting key');
......@@ -245,45 +266,6 @@ export class UserService {
);
}
public addDeployment(service: t.Service, key: t.SSHKey) {
const body = {
'type': 'add',
'key': key.id,
'service': service.id,
};
return this.http.post('/backend/api/deployments', body).subscribe(
(data: t.UserState) => {
//this.snackBar.open('Deployed key ' + key.name);
this.updateUserState(data);
},
(err) => {
this.snackBar.open('Error deploying key ' + key.name);
console.log(err);
this.update();
}
);
}
public removeDeployment(service: t.Service, key: t.SSHKey) {
const body = {
'type': 'remove',
'key': key.id,
'service': service.id,
};
return this.http.post('/backend/api/deployments', body).subscribe(
(data: t.UserState) => {
//this.snackBar.open('Withdrew key ' + key.name);
this.updateUserState(data);
},
(err) => {
this.snackBar.open('Error withdrawing key ' + key.name);
console.log(err);
this.update();
}
);
}
public sentQuestionnaire(taskItemID: number, answers: any) {
return this.http.post('/backend/api/questionnaire?id='+String(taskItemID), answers).subscribe(
(data: t.UserState) => {
......@@ -312,25 +294,4 @@ export class UserService {
}
);
}
public taskItem(site: t.Site, service: t.Service, key: t.SSHKeyRef): t.DeploymentStateItem {
if (this.userState.deployment_state_items && site && service && key) {
for (const item of this.userState.deployment_state_items){
if (item.site.id == site.id
&& item.key.id == key.id
&& item.service.id == service.id) {
return item;
}
}
}
return null;
}
public taskState(site: t.Site, service: t.Service, key: t.SSHKeyRef): string {
let item = this.taskItem(site, service, key);
if (item !== null) {
return item.state;
}
return "";
}
}
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