From 92ee815150812d11a47f43d80be316497702d62e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 06:17:40 +0000 Subject: [PATCH 01/19] feat(Dependencies): Update dependency ng2-charts to v6 | datasource | package | from | to | | ---------- | ---------- | ----- | ----- | | npm | ng2-charts | 5.0.4 | 6.0.1 | --- package-lock.json | 21 +++++++++++---------- package.json | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00910e4bb5..3e89f0fd8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.873.0", + "version": "4.874.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.873.0", + "version": "4.874.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", "@angular/animations": "18.2.2", @@ -50,7 +50,7 @@ "keypairs": "1.2.14", "mime": "4.0.4", "moment": "2.30.1", - "ng2-charts": "5.0.4", + "ng2-charts": "6.0.1", "ng2-cookies": "1.0.12", "ngx-bootstrap": "18.0.2", "ngx-clipboard": "16.0.0", @@ -13220,18 +13220,19 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node_modules/ng2-charts": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-5.0.4.tgz", - "integrity": "sha512-AnOZ2KSRw7QjiMMNtXz9tdnO+XrIKP/2MX1TfqEEo2fwFU5c8LFJIYqmkMPkIzAEm/U9y/1psA5TDNmxxjEdgA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-6.0.1.tgz", + "integrity": "sha512-pO7evbvHqjiKB7zqE12tCKWQI9gmQ8DVOEaWBBLlxJabc4fLGk7o9t4jC4+Q9pJiQrTtQkugm0dIPQ4PFHUaWA==", + "license": "MIT", "dependencies": { "lodash-es": "^4.17.15", "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": ">=16.0.0", - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0", - "@angular/platform-browser": ">=16.0.0", + "@angular/cdk": ">=17.0.0", + "@angular/common": ">=17.0.0", + "@angular/core": ">=17.0.0", + "@angular/platform-browser": ">=17.0.0", "chart.js": "^3.4.0 || ^4.0.0", "rxjs": "^6.5.3 || ^7.4.0" } diff --git a/package.json b/package.json index 2a0069a5e5..42c7e20d17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.873.0", + "version": "4.874.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -60,7 +60,7 @@ "keypairs": "1.2.14", "mime": "4.0.4", "moment": "2.30.1", - "ng2-charts": "5.0.4", + "ng2-charts": "6.0.1", "ng2-cookies": "1.0.12", "ngx-bootstrap": "18.0.2", "ngx-clipboard": "16.0.0", From 67c2573dbf2fc4dadaa62add98af40d10fe7c973 Mon Sep 17 00:00:00 2001 From: dweinholz Date: Wed, 4 Sep 2024 13:20:45 +0200 Subject: [PATCH 02/19] updated --- src/app/app.module.ts | 4 ++-- src/app/projectmanagement/projectmanagement.module.ts | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 961ab08b13..5857bb2bbc 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,7 +4,7 @@ import { BrowserModule, Title } from '@angular/platform-browser' import { BsDropdownModule } from 'ngx-bootstrap/dropdown' import { TabsModule } from 'ngx-bootstrap/tabs' import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' -import { NgChartsModule } from 'ng2-charts' +import { provideCharts, withDefaultRegisterables } from 'ng2-charts' import { ModalModule } from 'ngx-bootstrap/modal' import { PaginationModule } from 'ngx-bootstrap/pagination' import { ClipboardModule } from 'ngx-clipboard' @@ -73,7 +73,6 @@ import { TitleService } from './title.service' CommonModule, BsDropdownModule.forRoot(), TabsModule.forRoot(), - NgChartsModule, ModalModule.forRoot(), PaginationModule.forRoot(), SharedModuleModule, @@ -110,6 +109,7 @@ import { TitleService } from './title.service' provide: ErrorHandler, useClass: UncaughtExceptionHandler }, + provideCharts(withDefaultRegisterables()), ApiSettings, UserService, CookieService, diff --git a/src/app/projectmanagement/projectmanagement.module.ts b/src/app/projectmanagement/projectmanagement.module.ts index 7a612831d0..64baca103e 100644 --- a/src/app/projectmanagement/projectmanagement.module.ts +++ b/src/app/projectmanagement/projectmanagement.module.ts @@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common' import { ModalModule } from 'ngx-bootstrap/modal' import { FormsModule } from '@angular/forms' import { AccordionModule } from 'ngx-bootstrap/accordion' -import { NgChartsModule } from 'ng2-charts' import { BsDropdownModule } from 'ngx-bootstrap/dropdown' import { AlertModule } from 'ngx-bootstrap/alert' import { NgSelectModule } from '@ng-select/ng-select' @@ -40,7 +39,6 @@ import { WithdrawModalComponent } from './modals/withdraw/withdraw-modal.compone ModalModule.forRoot(), ApplicationsModule, SharedDirectivesModule, - NgChartsModule, PipeModuleModule, BsDropdownModule, AlertModule, From ceea116beb9ca93c608835b3b4faa5fc489636c8 Mon Sep 17 00:00:00 2001 From: dweinholz Date: Wed, 4 Sep 2024 13:30:21 +0200 Subject: [PATCH 03/19] added spinner to numbers --- .../number-charts.component.html | 162 ++++++++++-------- .../number-charts/number-charts.component.ts | 15 +- 2 files changed, 99 insertions(+), 78 deletions(-) diff --git a/src/app/vo_manager/number-charts/number-charts.component.html b/src/app/vo_manager/number-charts/number-charts.component.html index 9187aa5def..0cdab42671 100644 --- a/src/app/vo_manager/number-charts/number-charts.component.html +++ b/src/app/vo_manager/number-charts/number-charts.component.html @@ -3,89 +3,101 @@
Project Numbers
-
-
-
- - - - -
+ @if (generatingNumbersCharts) { + + } @else { +
+
+
+ + + + +
+ }
Cloud Resources
-
-
-
- - - - -
+ @if (generatingRamsCharts) { + + } @else { +
+
+
+ + + + +
+ }
-
-
+ @if (generatingCoresCharts) { + + } @else { +
+
-
- - - - -
+
+ + + + +
+ }
diff --git a/src/app/vo_manager/number-charts/number-charts.component.ts b/src/app/vo_manager/number-charts/number-charts.component.ts index 3e989a8879..2acc4f0bfc 100644 --- a/src/app/vo_manager/number-charts/number-charts.component.ts +++ b/src/app/vo_manager/number-charts/number-charts.component.ts @@ -21,9 +21,7 @@ export class NumberChartsComponent implements OnInit { is_vo_admin: boolean = true title: string = 'Cloud Numbers' - constructor(private numbersService: NumbersService) { - this.numbersService = numbersService - } + constructor(private numbersService: NumbersService) {} /** * Charts @@ -41,6 +39,9 @@ export class NumberChartsComponent implements OnInit { showRamAreChart: boolean = true showProjectNumbersAreaChart: boolean = true showProjectNumbersBarChart: boolean = false + generatingNumbersCharts: boolean = true + generatingRamsCharts: boolean = true + generatingCoresCharts: boolean = true /** * Lists for numbers of projects per project type and status. @@ -141,6 +142,8 @@ export class NumberChartsComponent implements OnInit { * Draws the cores Chart into the template. */ drawCoresNumbersChart(): void { + this.generatingCoresCharts = true + this.coresAreaChart = bb.generate({ bindto: '#coresAreaChart', size: { @@ -228,6 +231,7 @@ export class NumberChartsComponent implements OnInit { show: false } }) + this.generatingCoresCharts = false } /** @@ -235,6 +239,8 @@ export class NumberChartsComponent implements OnInit { * Draws the ram Chart into the template. */ drawRamNumbersChart(): void { + this.generatingRamsCharts = true + this.ramAreaChart = bb.generate({ bindto: '#ramAreaChart', size: { @@ -322,12 +328,14 @@ export class NumberChartsComponent implements OnInit { show: false } }) + this.generatingRamsCharts = false } /** * Draws the project numbers chart in the template. */ drawProjectNumbersChart(): void { + this.generatingNumbersCharts = true this.projectNumbersAreaChart = bb.generate({ bindto: '#projectNumbersAreaChart', size: { @@ -431,6 +439,7 @@ export class NumberChartsComponent implements OnInit { show: false } }) + this.generatingNumbersCharts = false } toggleGraph(chart: string): void { From 002e25be4e976f36fe1ac589635b3898849689cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 22:22:23 +0000 Subject: [PATCH 04/19] feat(Dependencies): Update all non-major dependencies | datasource | package | from | to | | ---------- | --------------------------------- | ------- | ------- | | npm | @angular-devkit/build-angular | 18.2.2 | 18.2.3 | | npm | @angular/animations | 18.2.2 | 18.2.3 | | npm | @angular/cdk | 18.2.2 | 18.2.3 | | npm | @angular/cli | 18.2.2 | 18.2.3 | | npm | @angular/common | 18.2.2 | 18.2.3 | | npm | @angular/compiler | 18.2.2 | 18.2.3 | | npm | @angular/compiler-cli | 18.2.2 | 18.2.3 | | npm | @angular/core | 18.2.2 | 18.2.3 | | npm | @angular/forms | 18.2.2 | 18.2.3 | | npm | @angular/localize | 18.2.2 | 18.2.3 | | npm | @angular/platform-browser | 18.2.2 | 18.2.3 | | npm | @angular/platform-browser-dynamic | 18.2.2 | 18.2.3 | | npm | @angular/router | 18.2.2 | 18.2.3 | | npm | @angular/service-worker | 18.2.2 | 18.2.3 | | npm | @angular/upgrade | 18.2.2 | 18.2.3 | | npm | @types/node | 20.16.4 | 20.16.5 | | npm | cssnano | 7.0.5 | 7.0.6 | --- package-lock.json | 350 +++++++++++++++++++++++----------------------- package.json | 32 ++--- 2 files changed, 191 insertions(+), 191 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e89f0fd8c..a503024c48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,26 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.874.0", + "version": "4.875.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.874.0", + "version": "4.875.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", - "@angular/animations": "18.2.2", - "@angular/cdk": "18.2.2", - "@angular/common": "18.2.2", - "@angular/compiler": "18.2.2", - "@angular/core": "18.2.2", - "@angular/forms": "18.2.2", - "@angular/localize": "18.2.2", - "@angular/platform-browser": "18.2.2", - "@angular/platform-browser-dynamic": "18.2.2", - "@angular/router": "18.2.2", - "@angular/service-worker": "18.2.2", - "@angular/upgrade": "18.2.2", + "@angular/animations": "18.2.3", + "@angular/cdk": "18.2.3", + "@angular/common": "18.2.3", + "@angular/compiler": "18.2.3", + "@angular/core": "18.2.3", + "@angular/forms": "18.2.3", + "@angular/localize": "18.2.3", + "@angular/platform-browser": "18.2.3", + "@angular/platform-browser-dynamic": "18.2.3", + "@angular/router": "18.2.3", + "@angular/service-worker": "18.2.3", + "@angular/upgrade": "18.2.3", "@coreui/angular": "5.2.17", "@coreui/coreui": "5.1.2", "@coreui/icons-angular": "5.2.17", @@ -38,7 +38,7 @@ "cli-color": "2.0.4", "core-js": "3.38.1", "css-loader": "7.1.2", - "cssnano": "7.0.5", + "cssnano": "7.0.6", "d3": "7.9.0", "export-to-csv": "1.4.0", "file-saver": "2.0.5", @@ -75,12 +75,12 @@ "@angular-eslint/schematics": "18.3.0", "@angular-eslint/template-parser": "18.3.0", "@angular/cli": "^18.1.4", - "@angular/compiler-cli": "18.2.2", + "@angular/compiler-cli": "18.2.3", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.9.0", "@playwright/test": "1.46.1", "@types/jasmine": "5.1.4", - "@types/node": "20.16.4", + "@types/node": "20.16.5", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", "async": "3.2.6", @@ -134,13 +134,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1802.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.2.tgz", - "integrity": "sha512-LPRl9jhcf0NgshaL6RoUy1uL/cAyNt7oxctoZ9EHUu8eh5E9W/jZGhVowjOLpirwqYhmEzKJJIeS49Ssqs3RQg==", + "version": "0.1802.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.3.tgz", + "integrity": "sha512-WQ2AmkUKy1bqrDlNfozW8+VT2Tv/Fdmu4GIXps3ytZANyAKiIvTzmmql2cRCXXraa9FNMjLWNvz+qolDxWVdYQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.2", + "@angular-devkit/core": "18.2.3", "rxjs": "7.8.1" }, "engines": { @@ -150,17 +150,17 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.2.tgz", - "integrity": "sha512-7HEnTN2T1jnjuItXKcApOsoYGgfou4+POju3ZbwIQukDZ3B2COskvQkVTxqPNrQ0ZjT2mxZYoVlmGW9M+7N25g==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.3.tgz", + "integrity": "sha512-uUQba0SIskKORHcPayt7LpqPRKD//48EW92SgGHEArn2KklM+FSYBOA9OtrJeZ/UAcoJpdLDtvyY4+S7oFzomg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.2", - "@angular-devkit/build-webpack": "0.1802.2", - "@angular-devkit/core": "18.2.2", - "@angular/build": "18.2.2", + "@angular-devkit/architect": "0.1802.3", + "@angular-devkit/build-webpack": "0.1802.3", + "@angular-devkit/core": "18.2.3", + "@angular/build": "18.2.3", "@babel/core": "7.25.2", "@babel/generator": "7.25.0", "@babel/helper-annotate-as-pure": "7.24.7", @@ -171,7 +171,7 @@ "@babel/preset-env": "7.25.3", "@babel/runtime": "7.25.0", "@discoveryjs/json-ext": "0.6.1", - "@ngtools/webpack": "18.2.2", + "@ngtools/webpack": "18.2.3", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", @@ -214,7 +214,7 @@ "vite": "5.4.0", "watchpack": "2.4.1", "webpack": "5.94.0", - "webpack-dev-middleware": "7.3.0", + "webpack-dev-middleware": "7.4.2", "webpack-dev-server": "5.0.4", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" @@ -802,13 +802,13 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1802.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.2.tgz", - "integrity": "sha512-Pj+YmKh0nJOKl6QAsqYh3SqfuVJrFqjyp5WrG9BgfsMD9GCMD+5teMHNYJlp+vG/C8e7VdZp4rqOon8K9Xn4Mw==", + "version": "0.1802.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.3.tgz", + "integrity": "sha512-/Nixv9uAg6v/OPoZa0PB0zi+iezzBkgLrnrJnestny5B536l9WRtsw97RjeQDu+x2BClQsxNe8NL2A7EvjVD6w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.2", + "@angular-devkit/architect": "0.1802.3", "rxjs": "7.8.1" }, "engines": { @@ -822,9 +822,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.2.tgz", - "integrity": "sha512-Zz0tGptI/QQnUBDdp+1G5wGwQWMjpfe2oO+UohkrDVgFS71yVj4VDnOy51kMTxBvzw+36evTgthPpmzqPIfxBw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.3.tgz", + "integrity": "sha512-vbFs+ofNK9OWeMIcFarFjegXVklhtSdLTEFKZ9trDVr8alTJdjI9AiYa6OOUTDAyq0hqYxV26xlCisWAPe7s5w==", "dev": true, "license": "MIT", "dependencies": { @@ -850,13 +850,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.2.tgz", - "integrity": "sha512-PU6+3nX+gQ3gofR7BGwXuvNUNeeV2raURaZjlPfGpBqjyTBxukMV71QsTTWptAZT4WibCWkTFp6X1gvsOGbjMg==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.3.tgz", + "integrity": "sha512-N3tRAzBW2yWQhebvc1Ha18XTMSXOQTfr8HNjx7Fasx0Fg1tNyGR612MJNZw6je/PqyItKeUHOhztvFMfCQjRyg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.2", + "@angular-devkit/core": "18.2.3", "jsonc-parser": "3.3.1", "magic-string": "0.30.11", "ora": "5.4.1", @@ -959,9 +959,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.2.tgz", - "integrity": "sha512-jh/dGrY77HGm54HdTiQsxmvoRfFeJgHeWAK2+nWCPoc4b7OHcWxy/04cYffs0/27ThmABmppP7ERAyZ0f60uow==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.3.tgz", + "integrity": "sha512-rIATopHr83lYR0X05buHeHssq9CGw0I0YPIQcpUTGnlqIpJcQVCf7jCFn4KGZrE9V55hFY3MD4S28njlwCToQQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -970,18 +970,18 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.2" + "@angular/core": "18.2.3" } }, "node_modules/@angular/build": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.2.tgz", - "integrity": "sha512-okaDdTMXnDhvnnnih6rPQnexL6htfEAPr19bB1Ci9d31gEjVuKZCjlcw2sPZ6BUyilwC9nZlCI5vbH1Ljf6mzA==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.3.tgz", + "integrity": "sha512-USrD2Zvcb1te2dnqhH7JZ5XeJDg/t7fjUHR4f93vvMrnrncwCjLoHbHpz01HCHfcIVRgsYUdAmAi1iG7vpak7w==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.2", + "@angular-devkit/architect": "0.1802.3", "@babel/core": "7.25.2", "@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-split-export-declaration": "7.24.7", @@ -1492,9 +1492,9 @@ } }, "node_modules/@angular/cdk": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.2.tgz", - "integrity": "sha512-+u7ZcMA24WO03vDzlBJJWq+okZLFDeW9JrtHzrdiT09FDt4sdUp+7PddXaZcRHIXjJL+CaCLQ6slaqPNEufqgg==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.3.tgz", + "integrity": "sha512-lUcpYTxPZuntJ1FK7V2ugapCGMIhT6TUDjIGgXfS9AxGSSKgwr8HNs6Ze9pcjYC44UhP40sYAZuiaFwmE60A2A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1509,18 +1509,18 @@ } }, "node_modules/@angular/cli": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.2.tgz", - "integrity": "sha512-HVVaMxnbID0q+V3KE+JqzGbPHcBUFo1RKhBZ/jxY7USZNzgtyYbRc0IYqPWNdr99UT5QefTJrjVazJo1nqQZvQ==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.3.tgz", + "integrity": "sha512-40258vuliH6+p8QSByZe5EcIXSj0iR3PNF6yuusClR/ByToHOnmuPw7WC+AYr0ooozmqlim/EjQe4/037OUB3w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.2", - "@angular-devkit/core": "18.2.2", - "@angular-devkit/schematics": "18.2.2", + "@angular-devkit/architect": "0.1802.3", + "@angular-devkit/core": "18.2.3", + "@angular-devkit/schematics": "18.2.3", "@inquirer/prompts": "5.3.8", "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.2", + "@schematics/angular": "18.2.3", "@yarnpkg/lockfile": "1.1.0", "ini": "4.1.3", "jsonc-parser": "3.3.1", @@ -1543,9 +1543,9 @@ } }, "node_modules/@angular/common": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.2.tgz", - "integrity": "sha512-AQe4xnnNNch/sXRnV82C8FmhijxPATKfPGojC2qbAG2o6VkWKgt5Lbj0O8WxvSIOS5Syedv+O2kLY/JMGWHNtw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.3.tgz", + "integrity": "sha512-NFL4yXXImSCH7i1xnHykUjHa9vl9827fGiwSV2mnf7LjSUsyDzFD8/54dNuYN9OY8AUD+PnK0YdNro6cczVyIA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1554,14 +1554,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.2", + "@angular/core": "18.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.2.tgz", - "integrity": "sha512-gmVNCXZiv/CIk2eKRLnH19N9VsPuE2s3Oxm0MNi003zk1cLy7D4YEm4fSrjKXtPY8MMpRXiu5f63W94hLwWEVw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.3.tgz", + "integrity": "sha512-Il3ljs0j1GaYoqYFdShjUP1ryck5xTOaA8uQuRgqwU0FOwEDfugSAM3Qf7nJx/sgxTM0Lm/Nrdv2u6i1gZWeuQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1570,7 +1570,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.2" + "@angular/core": "18.2.3" }, "peerDependenciesMeta": { "@angular/core": { @@ -1579,9 +1579,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.2.tgz", - "integrity": "sha512-fF7lDrTA12YGqVjF4LyMi4hm58cv9G6CWmzSlvun0nMYCwrbRNnakZsj19dOfiIqqu4MwHaF4w3PTmUSxkMuiw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.3.tgz", + "integrity": "sha512-BcmqYKnkcJTkGjuPztClZNQve7tdI290J5F3iZBx6c7/vaw8EU8EGZtpWYZpgiVn5S6jhcKyc1dLF9ggO9vftg==", "license": "MIT", "dependencies": { "@babel/core": "7.25.2", @@ -1602,14 +1602,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.2", + "@angular/compiler": "18.2.3", "typescript": ">=5.4 <5.6" } }, "node_modules/@angular/core": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.2.tgz", - "integrity": "sha512-Rx6XajL0Ydj9hXUSPDvL2Q/kMzWtbiE3VxZFJnkE+fLQiWvr0GncB+NTb/nQ6QlPQ0ly60DvuI3KLcGDuFtGVA==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.3.tgz", + "integrity": "sha512-VGhMJxj7d0rYpqVfQrcGRB7EE/BCziotft/I/YPl6bOMPSAvMukG7DXQuJdYpNrr62ks78mlzHlZX/cdmB9Prw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1623,9 +1623,9 @@ } }, "node_modules/@angular/forms": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.2.tgz", - "integrity": "sha512-K8cv0w6o7+ocQfUrdSA3XaKrYfa1+2TlmtyxPHjEd2mCu2R+Yqo5RqJ3P8keFewJ1+bSLhz6xnn6mumwl0RnUQ==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.3.tgz", + "integrity": "sha512-+OBaAH0e8hue9eyLnbgpxg1/X9fps6bwXECfJ0nL5BDPU5itZ428YJbEnj5bTx0hEbqfTRiV4LgexdI+D9eOpw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1634,16 +1634,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.2", - "@angular/core": "18.2.2", - "@angular/platform-browser": "18.2.2", + "@angular/common": "18.2.3", + "@angular/core": "18.2.3", + "@angular/platform-browser": "18.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/localize": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.2.tgz", - "integrity": "sha512-grWQ3CVbizOWCthGpyIlNNnZCpF/xpWYa6tIsPzKOXLCyqFQ7vOEtSludNN1nsUmMlZQt76+wA17Fx0qcNx0EA==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.3.tgz", + "integrity": "sha512-ZTliuRfH/hGwQTmFb1FwKOyMUks2ATuFVFzKnxbsxoo+XgTg+e12FcUfPEfdtPAteZ9gSuc/9hP8sM0RzW0LPg==", "license": "MIT", "dependencies": { "@babel/core": "7.25.2", @@ -1660,14 +1660,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.2", - "@angular/compiler-cli": "18.2.2" + "@angular/compiler": "18.2.3", + "@angular/compiler-cli": "18.2.3" } }, "node_modules/@angular/platform-browser": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.2.tgz", - "integrity": "sha512-Bfvl8elCFxyJ9vlwamr4X5sVMcp/tSwBal2coyl0WR+/PH2PAAtf+/WMYxIN90yZmPiJx6RZWUSJRlHOFiFp3A==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.3.tgz", + "integrity": "sha512-M2ob4zN7tAcL2mx7U6KnZNqNFPFl9MlPBE0FrjQjIzAjU0wSYPIJXmaPu9aMUp9niyo+He5iX98I+URi2Yc99g==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1676,9 +1676,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.2", - "@angular/common": "18.2.2", - "@angular/core": "18.2.2" + "@angular/animations": "18.2.3", + "@angular/common": "18.2.3", + "@angular/core": "18.2.3" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1687,9 +1687,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.2.tgz", - "integrity": "sha512-UM/+1nY4iIj1v4lxAmV3XRHPAh/4qfNKScCLq8tJGot64rPCbtCl0Rl8rFFGqxAFvTErVDaJycUgWNZSfVl/hw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.3.tgz", + "integrity": "sha512-nWi9ZxN4KpbJkttIckFO1PCoW0+gb/18xFO+JWyLBAtcbsudj/Mv0P/fdOaSfQdLkPhZfORr3ZcfiTkhmuGyEg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1698,16 +1698,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.2", - "@angular/compiler": "18.2.2", - "@angular/core": "18.2.2", - "@angular/platform-browser": "18.2.2" + "@angular/common": "18.2.3", + "@angular/compiler": "18.2.3", + "@angular/core": "18.2.3", + "@angular/platform-browser": "18.2.3" } }, "node_modules/@angular/router": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.2.tgz", - "integrity": "sha512-tBHwuNtZNjzYAoVdveTI1ke/ZnQjKhc7gqDk9HCH2JUpdQhGbTvCKwDM51ktJpPMPcZlA263lQyy7VIyvdtK0A==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.3.tgz", + "integrity": "sha512-fvD9eSDIiIbeYoUokoWkXzu7/ZaxlzKPUHFqX1JuKuH5ciQDeT/d7lp4mj31Bxammhohzi3+z12THJYsCkj/iQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1716,16 +1716,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.2", - "@angular/core": "18.2.2", - "@angular/platform-browser": "18.2.2", + "@angular/common": "18.2.3", + "@angular/core": "18.2.3", + "@angular/platform-browser": "18.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.2.tgz", - "integrity": "sha512-az0v0gNkAjOQ4DThDWfNJv2DkH63B4Vj/WnXd8pbY/C7Be6w3S1mN2y9vJClWAzUH/GSLQHnOrZJfnZtTc8M0w==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.3.tgz", + "integrity": "sha512-KplaBYhhwsM3gPeOImfDGhAknN+BIcZJkHl8YRnhoUEFHsTZ8LTV02C4LWQL3YTu3pK+uj/lPMKi1CA37cXQ8g==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1737,14 +1737,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.2", - "@angular/core": "18.2.2" + "@angular/common": "18.2.3", + "@angular/core": "18.2.3" } }, "node_modules/@angular/upgrade": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-18.2.2.tgz", - "integrity": "sha512-IP4RCK8NaKLpOQnYgkNlRx3oj9L31kS9/sHo17vqh9ilBpGczCpR6+h/a85Lp2YOeeal82z6GvuUXQ7UkAWG7A==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-18.2.3.tgz", + "integrity": "sha512-Fm1qa4hMzFXOG0Lxw+ak9TbgzlWnCVOQED1b6gavcW+OKEuhWPH1/O+SKzaQKDfXEY9Rqxt/hUdLFyi0H0yNpg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1753,10 +1753,10 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.2", - "@angular/core": "18.2.2", - "@angular/platform-browser": "18.2.2", - "@angular/platform-browser-dynamic": "18.2.2" + "@angular/compiler": "18.2.3", + "@angular/core": "18.2.3", + "@angular/platform-browser": "18.2.3", + "@angular/platform-browser-dynamic": "18.2.3" } }, "node_modules/@babel/code-frame": { @@ -4825,9 +4825,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.2.tgz", - "integrity": "sha512-YhADmc+lVjLt3kze07A+yLry2yzcghdclu+7D3EDfa6fG2Pk33HK3MY2I0Z0BO+Ivoq7cV7yxm+naR+Od0Y5ng==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.3.tgz", + "integrity": "sha512-DDuBHcu23qckt43SexBJaPEIeMc/HKaFOidILZM9D4gU4C9VroMActdR218dvQ802QfL0S46t5Ykz8ENprIfjA==", "dev": true, "license": "MIT", "engines": { @@ -5379,14 +5379,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.2.tgz", - "integrity": "sha512-0uPA1kQ38RnbNrzMlveX/QAqQIDu2INl5IYd3EUbJZRfYSp1VVyOSyuIBJ+1iUl5Y5VUa2uylaVZXhFdKWprXw==", + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.3.tgz", + "integrity": "sha512-whSON70z9HYb4WboVXmPFE/RLKJJQLWNzNcUyi8OSDZkQbJnYgPp0///n738m26Y/XeJDv11q1gESy+Zl2AdUw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.2", - "@angular-devkit/schematics": "18.2.2", + "@angular-devkit/core": "18.2.3", + "@angular-devkit/schematics": "18.2.3", "jsonc-parser": "3.3.1" }, "engines": { @@ -5960,9 +5960,9 @@ } }, "node_modules/@types/node": { - "version": "20.16.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.4.tgz", - "integrity": "sha512-ioyQ1zK9aGEomJ45zz8S8IdzElyxhvP1RVWnPrXDf6wFaUb+kk1tEcVVJkF7RPGM0VWI7cp5U57oCPIn5iN1qg==", + "version": "20.16.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", + "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -8196,12 +8196,12 @@ } }, "node_modules/cssnano": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.0.5.tgz", - "integrity": "sha512-Aq0vqBLtpTT5Yxj+hLlLfNPFuRQCDIjx5JQAhhaedQKLNDvDGeVziF24PS+S1f0Z5KCxWvw0QVI3VNHNBITxVQ==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.0.6.tgz", + "integrity": "sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==", "license": "MIT", "dependencies": { - "cssnano-preset-default": "^7.0.5", + "cssnano-preset-default": "^7.0.6", "lilconfig": "^3.1.2" }, "engines": { @@ -8216,27 +8216,27 @@ } }, "node_modules/cssnano-preset-default": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.5.tgz", - "integrity": "sha512-Jbzja0xaKwc5JzxPQoc+fotKpYtWEu4wQLMQe29CM0FjjdRjA4omvbGHl2DTGgARKxSTpPssBsok+ixv8uTBqw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.6.tgz", + "integrity": "sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==", "license": "MIT", "dependencies": { "browserslist": "^4.23.3", "css-declaration-sorter": "^7.2.0", "cssnano-utils": "^5.0.0", - "postcss-calc": "^10.0.1", + "postcss-calc": "^10.0.2", "postcss-colormin": "^7.0.2", - "postcss-convert-values": "^7.0.3", - "postcss-discard-comments": "^7.0.2", + "postcss-convert-values": "^7.0.4", + "postcss-discard-comments": "^7.0.3", "postcss-discard-duplicates": "^7.0.1", "postcss-discard-empty": "^7.0.0", "postcss-discard-overridden": "^7.0.0", - "postcss-merge-longhand": "^7.0.3", - "postcss-merge-rules": "^7.0.3", + "postcss-merge-longhand": "^7.0.4", + "postcss-merge-rules": "^7.0.4", "postcss-minify-font-values": "^7.0.0", "postcss-minify-gradients": "^7.0.0", "postcss-minify-params": "^7.0.2", - "postcss-minify-selectors": "^7.0.3", + "postcss-minify-selectors": "^7.0.4", "postcss-normalize-charset": "^7.0.0", "postcss-normalize-display-values": "^7.0.0", "postcss-normalize-positions": "^7.0.0", @@ -8250,7 +8250,7 @@ "postcss-reduce-initial": "^7.0.2", "postcss-reduce-transforms": "^7.0.0", "postcss-svgo": "^7.0.1", - "postcss-unique-selectors": "^7.0.2" + "postcss-unique-selectors": "^7.0.3" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -14540,12 +14540,12 @@ } }, "node_modules/postcss-calc": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.0.1.tgz", - "integrity": "sha512-pp1Z3FxtxA+xHAoWXcOXgnBN1WPu4ZiJ5LWGjKyf9MMreagAsaTUtnqFK1y1sHhyJddAkYTPu6XSuLgb3oYCjw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.0.2.tgz", + "integrity": "sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg==", "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.1.1", + "postcss-selector-parser": "^6.1.2", "postcss-value-parser": "^4.2.0" }, "engines": { @@ -14574,9 +14574,9 @@ } }, "node_modules/postcss-convert-values": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.3.tgz", - "integrity": "sha512-yJhocjCs2SQer0uZ9lXTMOwDowbxvhwFVrZeS6NPEij/XXthl73ggUmfwVvJM+Vaj5gtCKJV1jiUu4IhAUkX/Q==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.4.tgz", + "integrity": "sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==", "license": "MIT", "dependencies": { "browserslist": "^4.23.3", @@ -14590,12 +14590,12 @@ } }, "node_modules/postcss-discard-comments": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.2.tgz", - "integrity": "sha512-/Hje9Ls1IYcB9duELO/AyDUJI6aQVY3h5Rj1ziXgaLYCTi1iVBLnjg/TS0D6NszR/kDG6I86OwLmAYe+bvJjiQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.3.tgz", + "integrity": "sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==", "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^6.1.2" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -14677,13 +14677,13 @@ "dev": true }, "node_modules/postcss-merge-longhand": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.3.tgz", - "integrity": "sha512-8waYomFxshdv6M9Em3QRM9MettRLDRcH2JQi2l0Z1KlYD/vhal3gbkeSES0NuACXOlZBB0V/B0AseHZaklzWOA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.4.tgz", + "integrity": "sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==", "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0", - "stylehacks": "^7.0.3" + "stylehacks": "^7.0.4" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -14693,15 +14693,15 @@ } }, "node_modules/postcss-merge-rules": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.3.tgz", - "integrity": "sha512-2eSas2p3voPxNfdI5sQrvIkMaeUHpVc3EezgVs18hz/wRTQAC9U99tp9j3W5Jx9/L3qHkEDvizEx/LdnmumIvQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.4.tgz", + "integrity": "sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==", "license": "MIT", "dependencies": { "browserslist": "^4.23.3", "caniuse-api": "^3.0.0", "cssnano-utils": "^5.0.0", - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^6.1.2" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -14760,13 +14760,13 @@ } }, "node_modules/postcss-minify-selectors": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.0.3.tgz", - "integrity": "sha512-SxTgUQSgBk6wEqzQZKEv1xQYIp9UBju6no9q+npohzSdhuSICQdkqmD1UMKkZWItS3olJSJMDDEY9WOJ5oGJew==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.0.4.tgz", + "integrity": "sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^6.1.2" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -15039,12 +15039,12 @@ } }, "node_modules/postcss-unique-selectors": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.2.tgz", - "integrity": "sha512-CjSam+7Vf8cflJQsHrMS0P2hmy9u0+n/P001kb5eAszLmhjMqrt/i5AqQuNFihhViwDvEAezqTmXqaYXL2ugMw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.3.tgz", + "integrity": "sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==", "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^6.1.2" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -16903,13 +16903,13 @@ } }, "node_modules/stylehacks": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.3.tgz", - "integrity": "sha512-4DqtecvI/Nd+2BCvW9YEF6lhBN5UM50IJ1R3rnEAhBwbCKf4VehRf+uqvnVArnBayjYD/WtT3g0G/HSRxWfTRg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.4.tgz", + "integrity": "sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==", "license": "MIT", "dependencies": { "browserslist": "^4.23.3", - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^6.1.2" }, "engines": { "node": "^18.12.0 || ^20.9.0 || >=22.0" @@ -18096,9 +18096,9 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.3.0.tgz", - "integrity": "sha512-xD2qnNew+F6KwOGZR7kWdbIou/ud7cVqLEXeK1q0nHcNsX/u7ul/fSdlOTX4ntSL5FNFy7ZJJXbf0piF591JYw==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 42c7e20d17..1ddb45a251 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.874.0", + "version": "4.875.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -19,18 +19,18 @@ "private": true, "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", - "@angular/animations": "18.2.2", - "@angular/cdk": "18.2.2", - "@angular/common": "18.2.2", - "@angular/compiler": "18.2.2", - "@angular/core": "18.2.2", - "@angular/forms": "18.2.2", - "@angular/localize": "18.2.2", - "@angular/platform-browser": "18.2.2", - "@angular/platform-browser-dynamic": "18.2.2", - "@angular/router": "18.2.2", - "@angular/service-worker": "18.2.2", - "@angular/upgrade": "18.2.2", + "@angular/animations": "18.2.3", + "@angular/cdk": "18.2.3", + "@angular/common": "18.2.3", + "@angular/compiler": "18.2.3", + "@angular/core": "18.2.3", + "@angular/forms": "18.2.3", + "@angular/localize": "18.2.3", + "@angular/platform-browser": "18.2.3", + "@angular/platform-browser-dynamic": "18.2.3", + "@angular/router": "18.2.3", + "@angular/service-worker": "18.2.3", + "@angular/upgrade": "18.2.3", "@coreui/angular": "5.2.17", "@coreui/coreui": "5.1.2", "@coreui/icons-angular": "5.2.17", @@ -48,7 +48,7 @@ "cli-color": "2.0.4", "core-js": "3.38.1", "css-loader": "7.1.2", - "cssnano": "7.0.5", + "cssnano": "7.0.6", "d3": "7.9.0", "export-to-csv": "1.4.0", "file-saver": "2.0.5", @@ -85,12 +85,12 @@ "@angular-eslint/schematics": "18.3.0", "@angular-eslint/template-parser": "18.3.0", "@angular/cli": "^18.1.4", - "@angular/compiler-cli": "18.2.2", + "@angular/compiler-cli": "18.2.3", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.9.0", "@playwright/test": "1.46.1", "@types/jasmine": "5.1.4", - "@types/node": "20.16.4", + "@types/node": "20.16.5", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", "async": "3.2.6", From d3cc917e765771ec5690482f31f130af89e55038 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:04:53 +0000 Subject: [PATCH 05/19] feat(Dependencies): Update peter-evans/create-pull-request action to v7.0.1 | datasource | package | from | to | | ----------- | ------------------------------- | ------ | ------ | | github-tags | peter-evans/create-pull-request | v7.0.0 | v7.0.1 | --- .github/workflows/LintingAutoFix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LintingAutoFix.yml b/.github/workflows/LintingAutoFix.yml index eb064fdabe..7cc64372c8 100644 --- a/.github/workflows/LintingAutoFix.yml +++ b/.github/workflows/LintingAutoFix.yml @@ -46,7 +46,7 @@ jobs: - name: Create Pull Request if: steps.git-check.outputs.modified == 'true' id: cpr - uses: peter-evans/create-pull-request@v7.0.0 + uses: peter-evans/create-pull-request@v7.0.1 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: fix(Linting):blacked code From b68ac9f500f375c91e0eabb2267bf682a3ded396 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:24:27 +0000 Subject: [PATCH 06/19] feat(Dependencies): Update dependency @ng-select/ng-select to v13.7.1 | datasource | package | from | to | | ---------- | -------------------- | ------ | ------ | | npm | @ng-select/ng-select | 13.7.0 | 13.7.1 | --- package-lock.json | 13 +++++++------ package.json | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index a503024c48..2aced3eebb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.875.0", + "version": "4.876.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.875.0", + "version": "4.876.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", "@angular/animations": "18.2.3", @@ -25,7 +25,7 @@ "@coreui/coreui": "5.1.2", "@coreui/icons-angular": "5.2.17", "@ng-bootstrap/ng-bootstrap": "17.0.1", - "@ng-select/ng-select": "13.7.0", + "@ng-select/ng-select": "13.7.1", "@sindresorhus/transliterate": "1.6.0", "@types/d3": "7.4.3", "@types/jquery": "3.5.30", @@ -4808,9 +4808,10 @@ } }, "node_modules/@ng-select/ng-select": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-13.7.0.tgz", - "integrity": "sha512-GMNu3bLYxWAbgy9pXZ4RgnWp/cxRcrWRQdxLLyg8p9gMCLpim1p4TXR8laXJKK25MKG/LEaWgs+90yCVOoWgZA==", + "version": "13.7.1", + "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-13.7.1.tgz", + "integrity": "sha512-v/GwSBpuHd31DyoYFQECh+rCwn7xmCBpwMQTcwWerKaDQSr1egpGPSnCq2SzvfHqiJ5e1ckx7ZNTuk+swBweag==", + "license": "MIT", "dependencies": { "tslib": "^2.3.1" }, diff --git a/package.json b/package.json index 1ddb45a251..fdb922bf87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.875.0", + "version": "4.876.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -35,7 +35,7 @@ "@coreui/coreui": "5.1.2", "@coreui/icons-angular": "5.2.17", "@ng-bootstrap/ng-bootstrap": "17.0.1", - "@ng-select/ng-select": "13.7.0", + "@ng-select/ng-select": "13.7.1", "@sindresorhus/transliterate": "1.6.0", "@types/d3": "7.4.3", "@types/jquery": "3.5.30", From d60710ecc10f9f8ad7c4a0523a6488714ddec4aa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:50:09 +0000 Subject: [PATCH 07/19] feat(Dependencies): Update dependency @playwright/test to v1.47.0 | datasource | package | from | to | | ---------- | ---------------- | ------ | ------ | | npm | @playwright/test | 1.46.1 | 1.47.0 | --- package-lock.json | 28 ++++++++++++++-------------- package.json | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2aced3eebb..f11ea5d152 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.876.0", + "version": "4.877.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.876.0", + "version": "4.877.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", "@angular/animations": "18.2.3", @@ -78,7 +78,7 @@ "@angular/compiler-cli": "18.2.3", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.9.0", - "@playwright/test": "1.46.1", + "@playwright/test": "1.47.0", "@types/jasmine": "5.1.4", "@types/node": "20.16.5", "@typescript-eslint/eslint-plugin": "^8.0.0", @@ -5131,13 +5131,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", - "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.46.1" + "playwright": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -14468,13 +14468,13 @@ } }, "node_modules/playwright": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", - "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.46.1" + "playwright-core": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -14487,9 +14487,9 @@ } }, "node_modules/playwright-core": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", - "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index fdb922bf87..ed97c7a9d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.876.0", + "version": "4.877.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -88,7 +88,7 @@ "@angular/compiler-cli": "18.2.3", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.9.0", - "@playwright/test": "1.46.1", + "@playwright/test": "1.47.0", "@types/jasmine": "5.1.4", "@types/node": "20.16.5", "@typescript-eslint/eslint-plugin": "^8.0.0", From cd54b95ee5f4a50ebf454fd16cb01bcb99149248 Mon Sep 17 00:00:00 2001 From: dweinholz Date: Fri, 6 Sep 2024 12:31:03 +0200 Subject: [PATCH 08/19] refactor(SimpleVM):removed old simplevm parts (#6176) * refactor(SimpleVM):removed old simplevm parts * small fix * check for static folder --------- Co-authored-by: denbicloud <46009071+denbicloud@users.noreply.github.com> Co-authored-by: vktrrdk --- package-lock.json | 24 +- package.json | 3 +- src/app/api-connector/bioconda.service.ts | 86 -- src/app/api-connector/facility.service.ts | 98 -- src/app/api-connector/image.service.ts | 114 +- src/app/api-connector/playbook.service.ts | 23 - .../api-connector/virtualmachine.service.ts | 559 -------- src/app/api-connector/workshop.service.ts | 52 +- src/app/app.routing.ts | 8 - .../applications/type-overview.component.ts | 12 +- .../facility_manager/imagetags.component.ts | 17 +- src/app/layouts/full-layout.component.ts | 26 +- src/app/userinfo/userinfo.component.ts | 19 - src/app/virtualmachines/addvm.component.html | 1042 --------------- src/app/virtualmachines/addvm.component.ts | 855 ------------ .../clustercard/clustercard.component.html | 64 - .../clustercard/clustercard.component.scss | 0 .../clustercard/clustercard.component.ts | 193 --- .../add-cluster/add-cluster.component.html | 572 -------- .../add-cluster/add-cluster.component.scss | 0 .../add-cluster/add-cluster.component.ts | 554 -------- .../cluster-actions.component.html | 173 --- .../cluster-actions.component.scss | 0 .../cluster-actions.component.spec.ts | 21 - .../cluster-actions.component.ts | 263 ---- .../clusters/clusterPage.model.ts | 27 - .../clusterdetail.component.html | 177 --- .../clusterdetail.component.scss | 25 - .../clusterdetail/clusterdetail.component.ts | 261 ---- .../clusterinfo/clusterinfo.component.html | 34 - .../clusterinfo/clusterinfo.component.ts | 13 - .../clusterOverview.component.html | 200 --- .../clusterOverview.component.ts | 307 ----- .../clusters/clusterstatus/clusterstates.ts | 40 - .../clusterstatus.component.html | 83 -- .../clusterstatus/clusterstatus.component.ts | 18 - .../virtualmachines/conda/backend/backend.ts | 19 - .../conda/bioconda.component.html | 95 -- .../conda/bioconda.component.ts | 227 ---- .../conda/conda-package-meta.ts | 9 - .../conda/condaPackage.model.ts | 16 - src/app/virtualmachines/conda/condalog.ts | 97 -- .../conda/res-env.component.html | 235 ---- .../conda/res-env.component.ts | 179 --- .../conda/resenvTemplate.model.ts | 19 - .../virtualmachines/conda/template-names.ts | 62 - .../flavordetail.component.html | 332 ----- .../virtualmachines/flavordetail.component.ts | 138 -- .../imageCarouselSlide.component.html | 126 -- .../imageCarouselSlide.component.ts | 38 - .../imagedetail.component.html | 199 --- .../imagedetail.component.scss | 7 - .../virtualmachines/imagedetail.component.ts | 149 --- .../delete-cluster.component.html | 43 - .../delete-cluster.component.ts | 36 - .../modals/delete-vm/delete-vm.component.html | 70 - .../modals/delete-vm/delete-vm.component.ts | 37 - .../password-cluster.component.html | 34 - .../password-cluster.component.ts | 43 - .../modals/reboot-vm/reboot-vm.component.html | 112 -- .../modals/reboot-vm/reboot-vm.component.ts | 49 - .../recreate-backend-vm.component.html | 28 - .../recreate-backend-vm.component.ts | 29 - .../rename-cluster.component.html | 29 - .../rename-cluster.component.ts | 36 - .../resume-cluster.component.html | 19 - .../resume-cluster.component.ts | 29 - .../modals/resume-vm/resume-vm.component.html | 26 - .../modals/resume-vm/resume-vm.component.ts | 29 - .../scale-cluster.component.html | 455 ------- .../scale-cluster/scale-cluster.component.ts | 257 ---- .../snapshot-vm/snapshot-vm.component.html | 67 - .../snapshot-vm/snapshot-vm.component.ts | 66 - .../stop-cluster/stop-cluster.component.html | 20 - .../stop-cluster/stop-cluster.component.ts | 23 - .../modals/stop-vm/stop-vm.component.html | 31 - .../modals/stop-vm/stop-vm.component.ts | 29 - .../modals/volume-vm/volume-vm.component.html | 81 -- .../modals/volume-vm/volume-vm.component.ts | 64 - .../project-user-list.component.html | 62 - .../project-user-list.component.ts | 50 - .../snapshots/snapshotOverview.component.html | 348 ----- .../snapshots/snapshotOverview.component.ts | 316 ----- .../snapshots/snapshotPage.model.ts | 25 - .../virtualmachinemodels/virtualmachine.ts | 58 +- src/app/virtualmachines/vm.module.ts | 117 -- .../virtualmachines/vmOverview.component.html | 332 ----- .../virtualmachines/vmOverview.component.scss | 71 - .../virtualmachines/vmOverview.component.ts | 459 ------- src/app/virtualmachines/vm_routing.module.ts | 94 -- .../vmcard/vmcard.component.html | 573 -------- .../vmcard/vmcard.component.scss | 0 .../vmcard/vmcard.component.ts | 656 ---------- .../virtualmachineinfo.component.html | 115 -- .../virtualmachineinfo.component.scss | 0 .../virtualmachineinfo.component.ts | 61 - .../vmdetail/vmdetail.component.html | 1166 ----------------- .../vmdetail/vmdetail.component.scss | 47 - .../vmdetail/vmdetail.component.ts | 822 ------------ .../vmdetail/vmstatus/vmstatus.component.html | 163 --- .../vmdetail/vmstatus/vmstatus.component.scss | 0 .../vmdetail/vmstatus/vmstatus.component.ts | 19 - .../volumes/volume-action-states.enum.ts | 17 - .../volumes/volume-request-states.enum.ts | 5 - src/app/virtualmachines/volumes/volume.ts | 31 +- .../volumes/volumeOverview.component.html | 1136 ---------------- .../volumes/volumeOverview.component.ts | 839 ------------ .../volumes/volumePage.model.ts | 25 - .../virtualmachines/volumes/volume_states.ts | 128 -- .../add-workshop/add-workshop.component.html | 544 -------- .../add-workshop/add-workshop.component.scss | 0 .../add-workshop/add-workshop.component.ts | 466 ------- .../workshop-overview.component.html | 782 ----------- .../workshop-overview.component.scss | 0 .../workshop-overview.component.ts | 448 ------- .../number-charts/number-charts.component.ts | 23 - 116 files changed, 47 insertions(+), 19603 deletions(-) delete mode 100644 src/app/api-connector/bioconda.service.ts delete mode 100644 src/app/api-connector/playbook.service.ts delete mode 100644 src/app/api-connector/virtualmachine.service.ts delete mode 100644 src/app/virtualmachines/addvm.component.html delete mode 100644 src/app/virtualmachines/addvm.component.ts delete mode 100644 src/app/virtualmachines/clustercard/clustercard.component.html delete mode 100644 src/app/virtualmachines/clustercard/clustercard.component.scss delete mode 100644 src/app/virtualmachines/clustercard/clustercard.component.ts delete mode 100644 src/app/virtualmachines/clusters/add-cluster/add-cluster.component.html delete mode 100644 src/app/virtualmachines/clusters/add-cluster/add-cluster.component.scss delete mode 100644 src/app/virtualmachines/clusters/add-cluster/add-cluster.component.ts delete mode 100644 src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.html delete mode 100644 src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.scss delete mode 100644 src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.spec.ts delete mode 100644 src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.ts delete mode 100644 src/app/virtualmachines/clusters/clusterPage.model.ts delete mode 100644 src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.html delete mode 100644 src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.scss delete mode 100644 src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.ts delete mode 100644 src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.html delete mode 100644 src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.ts delete mode 100644 src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.html delete mode 100644 src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.ts delete mode 100644 src/app/virtualmachines/clusters/clusterstatus/clusterstates.ts delete mode 100644 src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.html delete mode 100644 src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.ts delete mode 100644 src/app/virtualmachines/conda/backend/backend.ts delete mode 100644 src/app/virtualmachines/conda/bioconda.component.html delete mode 100644 src/app/virtualmachines/conda/bioconda.component.ts delete mode 100644 src/app/virtualmachines/conda/conda-package-meta.ts delete mode 100644 src/app/virtualmachines/conda/condaPackage.model.ts delete mode 100644 src/app/virtualmachines/conda/condalog.ts delete mode 100644 src/app/virtualmachines/conda/res-env.component.html delete mode 100644 src/app/virtualmachines/conda/res-env.component.ts delete mode 100644 src/app/virtualmachines/conda/resenvTemplate.model.ts delete mode 100644 src/app/virtualmachines/conda/template-names.ts delete mode 100644 src/app/virtualmachines/flavordetail.component.html delete mode 100644 src/app/virtualmachines/flavordetail.component.ts delete mode 100644 src/app/virtualmachines/imageCarouselSlide.component.html delete mode 100644 src/app/virtualmachines/imageCarouselSlide.component.ts delete mode 100644 src/app/virtualmachines/imagedetail.component.html delete mode 100644 src/app/virtualmachines/imagedetail.component.scss delete mode 100644 src/app/virtualmachines/imagedetail.component.ts delete mode 100644 src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/delete-vm/delete-vm.component.html delete mode 100644 src/app/virtualmachines/modals/delete-vm/delete-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/password-cluster/password-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/password-cluster/password-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.html delete mode 100644 src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.html delete mode 100644 src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/resume-vm/resume-vm.component.html delete mode 100644 src/app/virtualmachines/modals/resume-vm/resume-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.html delete mode 100644 src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.html delete mode 100644 src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.ts delete mode 100644 src/app/virtualmachines/modals/stop-vm/stop-vm.component.html delete mode 100644 src/app/virtualmachines/modals/stop-vm/stop-vm.component.ts delete mode 100644 src/app/virtualmachines/modals/volume-vm/volume-vm.component.html delete mode 100644 src/app/virtualmachines/modals/volume-vm/volume-vm.component.ts delete mode 100644 src/app/virtualmachines/project-user-list/project-user-list.component.html delete mode 100644 src/app/virtualmachines/project-user-list/project-user-list.component.ts delete mode 100644 src/app/virtualmachines/snapshots/snapshotOverview.component.html delete mode 100644 src/app/virtualmachines/snapshots/snapshotOverview.component.ts delete mode 100644 src/app/virtualmachines/snapshots/snapshotPage.model.ts delete mode 100644 src/app/virtualmachines/vm.module.ts delete mode 100644 src/app/virtualmachines/vmOverview.component.html delete mode 100644 src/app/virtualmachines/vmOverview.component.scss delete mode 100644 src/app/virtualmachines/vmOverview.component.ts delete mode 100644 src/app/virtualmachines/vm_routing.module.ts delete mode 100644 src/app/virtualmachines/vmcard/vmcard.component.html delete mode 100644 src/app/virtualmachines/vmcard/vmcard.component.scss delete mode 100644 src/app/virtualmachines/vmcard/vmcard.component.ts delete mode 100644 src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.html delete mode 100644 src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.scss delete mode 100644 src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.ts delete mode 100644 src/app/virtualmachines/vmdetail/vmdetail.component.html delete mode 100644 src/app/virtualmachines/vmdetail/vmdetail.component.scss delete mode 100644 src/app/virtualmachines/vmdetail/vmdetail.component.ts delete mode 100644 src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.html delete mode 100644 src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.scss delete mode 100644 src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.ts delete mode 100644 src/app/virtualmachines/volumes/volume-action-states.enum.ts delete mode 100644 src/app/virtualmachines/volumes/volume-request-states.enum.ts delete mode 100644 src/app/virtualmachines/volumes/volumeOverview.component.html delete mode 100644 src/app/virtualmachines/volumes/volumeOverview.component.ts delete mode 100644 src/app/virtualmachines/volumes/volumePage.model.ts delete mode 100644 src/app/virtualmachines/volumes/volume_states.ts delete mode 100644 src/app/virtualmachines/workshop/add-workshop/add-workshop.component.html delete mode 100644 src/app/virtualmachines/workshop/add-workshop/add-workshop.component.scss delete mode 100644 src/app/virtualmachines/workshop/add-workshop/add-workshop.component.ts delete mode 100644 src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.html delete mode 100644 src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.scss delete mode 100644 src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.ts diff --git a/package-lock.json b/package-lock.json index f11ea5d152..ef15007abc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,7 +46,6 @@ "html2canvas": "1.4.1", "is-promise": "4.0.0", "jsnlog": "2.30.0", - "jspdf": "2.5.1", "keypairs": "1.2.14", "mime": "4.0.4", "moment": "2.30.1", @@ -5989,7 +5988,8 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", - "optional": true + "optional": true, + "peer": true }, "node_modules/@types/range-parser": { "version": "1.2.7", @@ -6764,6 +6764,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "peer": true, "bin": { "atob": "bin/atob.js" }, @@ -7160,6 +7161,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "peer": true, "bin": { "btoa": "bin/btoa.js" }, @@ -7343,6 +7345,7 @@ "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", "optional": true, + "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", "@types/raf": "^3.4.0", @@ -7361,7 +7364,8 @@ "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "optional": true + "optional": true, + "peer": true }, "node_modules/chalk": { "version": "2.4.2", @@ -9058,7 +9062,8 @@ "version": "2.5.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz", "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==", - "optional": true + "optional": true, + "peer": true }, "node_modules/domutils": { "version": "3.1.0", @@ -10113,7 +10118,8 @@ "node_modules/fflate": { "version": "0.4.8", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "peer": true }, "node_modules/file-entry-cache": { "version": "8.0.0", @@ -11716,6 +11722,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.14.0", "atob": "^2.1.2", @@ -14320,7 +14327,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "optional": true + "optional": true, + "peer": true }, "node_modules/picocolors": { "version": "1.0.1", @@ -15280,6 +15288,7 @@ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "optional": true, + "peer": true, "dependencies": { "performance-now": "^2.1.0" } @@ -15847,6 +15856,7 @@ "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", "optional": true, + "peer": true, "engines": { "node": ">= 0.8.15" } @@ -16711,6 +16721,7 @@ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", "optional": true, + "peer": true, "engines": { "node": ">=0.1.14" } @@ -17007,6 +17018,7 @@ "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", "optional": true, + "peer": true, "engines": { "node": ">=12.0.0" } diff --git a/package.json b/package.json index ed97c7a9d2..d4b1064493 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,7 @@ "html2canvas": "1.4.1", "is-promise": "4.0.0", "jsnlog": "2.30.0", - "jspdf": "2.5.1", - "keypairs": "1.2.14", + "keypairs": "1.2.14", "mime": "4.0.4", "moment": "2.30.1", "ng2-charts": "6.0.1", diff --git a/src/app/api-connector/bioconda.service.ts b/src/app/api-connector/bioconda.service.ts deleted file mode 100644 index ad63d0ba47..0000000000 --- a/src/app/api-connector/bioconda.service.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Injectable } from '@angular/core' -import { HttpClient, HttpParams } from '@angular/common/http' -import { Observable } from 'rxjs' -import { map } from 'rxjs/operators' -import { ApiSettings } from './api-settings.service' -import { ResearchEnvironment } from '../virtualmachines/virtualmachinemodels/res-env' -import { VirtualMachine } from '../virtualmachines/virtualmachinemodels/virtualmachine' -import { Backend } from '../virtualmachines/conda/backend/backend' - -/** - * Bioconda service. - */ -@Injectable() -export class BiocondaService { - constructor(private http: HttpClient) { - this.http = http - } - - getAllTools(page: number, name?: string): Observable { - const params: HttpParams = new HttpParams().set('page', page.toString()).set('name', name) - - return this.http.get(`${ApiSettings.getApiBaseURL()}conda/all/`, { - withCredentials: true, - params - }) - } - - getForcTemplates(clientid: string): Observable { - const params: HttpParams = new HttpParams().set('clientid', clientid) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}forc/templates/`, { - withCredentials: true, - params - }) - .pipe( - map((resenvs: ResearchEnvironment[]): ResearchEnvironment[] => - resenvs.map((resenv: ResearchEnvironment): ResearchEnvironment => new ResearchEnvironment(resenv)) - ) - ) - } - - getSuggestedForcTemplates(facility_id?: string): Observable { - const params: HttpParams = new HttpParams().set('facility_id', facility_id) - - return this.http.get(`${ApiSettings.getApiBaseURL()}forc/templates/allowed/`, { - withCredentials: true, - params - }) - } - - getTemplateNameByVmName(vm: VirtualMachine): Observable { - const params: HttpParams = new HttpParams().set('vm', vm.name) - - return this.http.get(`${ApiSettings.getApiBaseURL()}forc/backends/vm_name/`, { - withCredentials: true, - params - }) - } - - getUsersForBackend(vmId: string): Observable { - const params: HttpParams = new HttpParams().set('vm_id', vmId) - - return this.http.get(`${ApiSettings.getApiBaseURL()}forc/backs/users/`, { - withCredentials: true, - params - }) - } - - addUserToBackend(vmId: string, user_id: string): Observable { - const params: HttpParams = new HttpParams().set('vm_id', vmId).set('user_id', user_id) - - return this.http.post(`${ApiSettings.getApiBaseURL()}forc/backs/users/`, params, { - withCredentials: true - }) - } - - deleteUserFromBackend(vmId: string, user_id: string): Observable { - const params: HttpParams = new HttpParams().set('vm_id', vmId).set('user_id', user_id) - - return this.http.delete(`${ApiSettings.getApiBaseURL()}forc/backs/users/`, { - withCredentials: true, - params - }) - } -} diff --git a/src/app/api-connector/facility.service.ts b/src/app/api-connector/facility.service.ts index d619368c46..817c452240 100644 --- a/src/app/api-connector/facility.service.ts +++ b/src/app/api-connector/facility.service.ts @@ -10,9 +10,6 @@ import { ResourceMachine } from '../facility_manager/resources/resource-machine' import { ProjectMember } from '../projectmanagement/project_member.model' import { GPUSpecification } from '../facility_manager/resources/gpu-specification' import { GeneralStorageFactor } from '../facility_manager/resources/general-storage-factor' -import { ClusterPage } from '../virtualmachines/clusters/clusterPage.model' -import { VolumePage } from '../virtualmachines/volumes/volumePage.model' -import { SnapshotPage } from '../virtualmachines/snapshots/snapshotPage.model' /** * Service which provides methods for the facilities. @@ -80,38 +77,6 @@ export class FacilityService { ) } - getClustersFacility( - facility_id: string, - page: number, - vm_per_site: number, - filter?: string, - filter_status?: string[] - ): Observable { - let params: HttpParams = new HttpParams() - .set('page', page.toString()) - .set('cluster_per_site', vm_per_site.toString()) - - if (filter) { - params = params.set('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}computecenters/${facility_id}/clusters/`, { - withCredentials: true, - params - }) - .pipe(map((cluster_page: ClusterPage): ClusterPage => new ClusterPage(cluster_page))) - } - - getComputeCenterClientLimits(facility_id): Observable { - return this.http.get(`${ApiSettings.getApiBaseURL()}computecenters/${facility_id}/simpleVM/limits/`, { - withCredentials: true - }) - } - getComputeCenterClientLimitsAvailable(facility_id, application_id): Observable { return this.http.get( `${ApiSettings.getApiBaseURL()}computecenters/${facility_id}/simpleVM/${application_id}/limits/`, @@ -284,69 +249,6 @@ export class FacilityService { ) } - /** - * Gets all volumes from a specific facility. - * - * @param facility - * @returns - */ - getFacilityVolumes(facility: number | string, items_per_page: number, current_page: number): Observable { - const params: HttpParams = new HttpParams() - .set('items_per_page', items_per_page.toString()) - .set('page', current_page.toString()) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}computecenters/${facility}/volumes/`, { - withCredentials: true, - params - }) - .pipe(map((volume_page: VolumePage): VolumePage => new VolumePage(volume_page))) - } - - /** - * Gets all volumes from a specific facility. - * - * @param facility - * @param currentPage - * @param snapsPerSite - * @returns - */ - getFacilitySnapshots( - facility: number | string, - currentPage: number, - snapsPerSite: number, - filter?: string - ): Observable { - let params: HttpParams = new HttpParams() - .set('page', currentPage.toString()) - .set('snaps_per_site', snapsPerSite.toString()) - if (filter) { - params = params.set('filter', filter) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}computecenters/${facility}/snapshots/`, { - withCredentials: true, - params - }) - .pipe(map((snapshot_page: SnapshotPage): SnapshotPage => new SnapshotPage(snapshot_page))) - } - - /** - * Gets all facility modification applications which are waiting for conirmation. - * - * @param facility - * @returns - */ - getFacilityModificationApplicationsWaitingForConfirmation(facility: number | string): Observable { - return this.http.get( - `${ApiSettings.getApiBaseURL()}computecenters/${facility}/modification_applications/`, - { - withCredentials: true - } - ) - } - /** * Approves an facility application. * diff --git a/src/app/api-connector/image.service.ts b/src/app/api-connector/image.service.ts index ebc4e8aea3..950802dc76 100644 --- a/src/app/api-connector/image.service.ts +++ b/src/app/api-connector/image.service.ts @@ -1,66 +1,17 @@ import { Injectable } from '@angular/core' import { Observable } from 'rxjs' import { HttpClient, HttpParams } from '@angular/common/http' -import { map } from 'rxjs/operators' -import { Image } from '../virtualmachines/virtualmachinemodels/image' -import { SnapshotModel } from '../virtualmachines/snapshots/snapshot.model' + import { ApiSettings } from './api-settings.service' import { IResponseTemplate } from './response-template' import { BlockedImageTag, BlockedImageTagResenv, ImageLogo, ImageMode, ImageTag } from '../facility_manager/image-tag' -import { SnapshotPage } from '../virtualmachines/snapshots/snapshotPage.model' -import { ImageTypes } from '../virtualmachines/virtualmachinemodels/imageTypes' /** * Service which provides image methods. */ @Injectable() export class ImageService { - BASE_IMAGE_TAG = 'base_image' - BASE_CLUSTER_IMAGE_TAG = 'base_cluster' - - constructor(private http: HttpClient) { - this.http = http - } - - getImages(project_id: number, filter?: string): Observable { - let params: HttpParams = new HttpParams().set('project_id', project_id.toString()) - if (filter) { - params = new HttpParams().set('project_id', project_id.toString()).set('filter', filter) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}images/`, { - withCredentials: true, - params - }) - .pipe(map((images: Image[]): Image[] => images.map((image: Image): Image => new Image(image)))) - } - - getImageByProjectAndName(project_id: number, name: string): Observable { - const params: HttpParams = new HttpParams().set('name', name) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}images/project/${project_id}/`, { - withCredentials: true, - params - }) - .pipe(map((image: Image): Image => new Image(image))) - } - - checkSnapshotNameAvailable(snapshot_name: string, client_id: string): Observable { - return this.http.get(`${ApiSettings.getApiBaseURL()}snapshots/names/`, { - withCredentials: true, - params: { snapshot_name, client_id } - }) - } - - getSnapshot(openstack_id: string): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}snapshots/${openstack_id}/status/`, { - withCredentials: true - }) - .pipe(map((image: Image): Image => new Image(image))) - } + constructor(private http: HttpClient) {} getImageTags(facility: number): Observable { const params: HttpParams = new HttpParams().set('facility', facility.toString()) @@ -194,65 +145,4 @@ export class ImageService { params }) } - - createSnapshot(snaptshot_instance: string, snapshot_name: string, description: string): Observable { - const params: HttpParams = new HttpParams() - .set('snapshot_name', snapshot_name) - .set('snapshot_instance', snaptshot_instance) - .set('description', description) - - return this.http - .post(`${ApiSettings.getApiBaseURL()}snapshots/`, params, { - withCredentials: true - }) - .pipe(map((snapshot: SnapshotModel): SnapshotModel => new SnapshotModel(snapshot))) - } - - deleteSnapshot(snapshot_id: string): Observable { - return this.http.delete(`${ApiSettings.getApiBaseURL()}snapshots/${snapshot_id}/`, { - withCredentials: true - }) - } - - getSnapshotsByUser(currentPage: number, snapsPerSite: number, filter?: string): Observable { - let params: HttpParams = new HttpParams() - .set('page', currentPage.toString()) - .set('snaps_per_site', snapsPerSite.toString()) - - if (filter) { - params = params.set('filter', filter) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}snapshots/`, { - withCredentials: true, - params - }) - .pipe(map((snapshot_page: SnapshotPage): SnapshotPage => new SnapshotPage(snapshot_page))) - } - - sortImages(images: Image[], resenv_names: string[] = []): { [name: string]: Image[] } { - const image_types: { [name: string]: Image[] } = {} - image_types[ImageTypes.IMAGE] = [] - image_types[ImageTypes.SNAPSHOT] = [] - image_types[ImageTypes.CUSTOM] = [] - image_types[ImageTypes.CLUSTER_IMAGE] = [] - image_types[ImageTypes.RESENV] = [] - - for (const image of images) { - if (image.is_snapshot) { - image_types[ImageTypes.SNAPSHOT].push(image) - } else if (image.tags.includes(this.BASE_IMAGE_TAG)) { - image_types[ImageTypes.IMAGE].push(image) - } else if (image.tags.includes(this.BASE_CLUSTER_IMAGE_TAG)) { - image_types[ImageTypes.CLUSTER_IMAGE].push(image) - } else if (image.tags.filter(x => resenv_names.includes(x)).length > 0) { - image_types[ImageTypes.RESENV].push(image) - } else { - image_types[ImageTypes.CUSTOM].push(image) - } - } - - return image_types - } } diff --git a/src/app/api-connector/playbook.service.ts b/src/app/api-connector/playbook.service.ts deleted file mode 100644 index 3e98637a70..0000000000 --- a/src/app/api-connector/playbook.service.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core' -import { Observable } from 'rxjs' -import { HttpClient } from '@angular/common/http' -import { ApiSettings } from './api-settings.service' - -/** - * Service which provides playbooks from database - */ -@Injectable() -export class PlaybookService { - data: string - baseUrl: string = `${ApiSettings.getApiBaseURL()}playbooks/` - - constructor(private http: HttpClient) { - this.http = http - } - - getPlaybookForVM(vm_id: string): Observable { - return this.http.get(`${this.baseUrl}${vm_id}/`, { - withCredentials: true - }) - } -} diff --git a/src/app/api-connector/virtualmachine.service.ts b/src/app/api-connector/virtualmachine.service.ts deleted file mode 100644 index 49b686d2c5..0000000000 --- a/src/app/api-connector/virtualmachine.service.ts +++ /dev/null @@ -1,559 +0,0 @@ -import { Injectable } from '@angular/core' -import { Observable } from 'rxjs' -import { HttpClient, HttpParams } from '@angular/common/http' -import { map } from 'rxjs/operators' -import { ApiSettings } from './api-settings.service' -import { VirtualMachine } from '../virtualmachines/virtualmachinemodels/virtualmachine' -import { Volume } from '../virtualmachines/volumes/volume' -import { IResponseTemplate } from './response-template' -import { Clusterinfo, WorkerBatch } from '../virtualmachines/clusters/clusterinfo' -import { Image } from '../virtualmachines/virtualmachinemodels/image' -import { Condalog } from '../virtualmachines/conda/condalog' -import { VirtualMachinePage } from '../virtualmachines/virtualmachinemodels/virtualMachinePage' -import { VolumePage } from '../virtualmachines/volumes/volumePage.model' -import { ClusterPage } from '../virtualmachines/clusters/clusterPage.model' - -/** - * Service which provides vm methods. - */ -@Injectable({ - providedIn: 'root' -}) -export class VirtualmachineService { - data: string - baseVmUrl: string = `${ApiSettings.getApiBaseURL()}vms/` - - constructor(private http: HttpClient) { - this.http = http - } - - getClusterAllowed(): Observable { - return this.http.get(`${ApiSettings.getApiBaseURL()}clusters/allowed/`, { - withCredentials: true - }) - } - - triggerVolumeUpdate(volumeIds: string[]): Observable { - const params: HttpParams = new HttpParams().set('volume_ids', volumeIds.join()) - - return this.http.get(`${ApiSettings.getApiBaseURL()}volumes/trigger_update/`, { - withCredentials: true, - params, - observe: 'response' - }) - } - - startCluster( - masterFlavor: string, - masterImage: Image, - workerBatches: WorkerBatch[], - project_id: string | number, - name: string, - additional_elixir_ids: string[] - ): Observable { - return this.http.post( - `${ApiSettings.getApiBaseURL()}clusters/`, - { - master_flavor: masterFlavor, - master_image: masterImage, - worker_batches: workerBatches, - project_id, - name, - additional_elixir_ids - }, - { - withCredentials: true - } - ) - } - - getClusterInfo(cluster_id: string): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/`, { - withCredentials: true - }) - .pipe(map((clusterinfo: Clusterinfo): Clusterinfo => new Clusterinfo(clusterinfo))) - } - - renameCluster(cluster_id: string, name: string): Observable { - const params: HttpParams = new HttpParams().set('name', name) - - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/name/`, params, { - withCredentials: true - }) - } - - scaleCluster(cluster_id: string, worker_flavor_name: string, upscale_count: number): Observable { - const params: HttpParams = new HttpParams() - .set('worker_flavor_name', worker_flavor_name) - .set('upscale_count', upscale_count) - - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/scale-up/`, params, { - withCredentials: true - }) - } - - generatePasswordCluster(cluster_id: string) { - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/password/`, { - withCredentials: true - }) - } - - scaleDownCluster(cluster_id: string, downscale_list: any): Observable { - const params: HttpParams = new HttpParams().set( - 'downscale_list', - encodeURIComponent(JSON.stringify(downscale_list)) - ) - - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/scale-down/`, params, { - withCredentials: true - }) - } - - getClusters( - page: number, - cluster_per_site: number, - filter?: string, - filter_status?: string[] - ): Observable { - let params: HttpParams = new HttpParams() - .set('page', page.toString()) - .set('cluster_per_site', cluster_per_site.toString()) - - if (filter) { - params = params.set('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}clusters/`, { - withCredentials: true, - params - }) - .pipe(map((clusters: ClusterPage): ClusterPage => new ClusterPage(clusters))) - } - - deleteCluster(cluster_id: string): Observable { - return this.http.delete(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/`, { - withCredentials: true - }) - } - - resumeCluster(cluster_id: string): Observable { - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/resume/`, { - withCredentials: true - }) - } - - stopCluster(cluster_id: string): Observable { - return this.http.post(`${ApiSettings.getApiBaseURL()}clusters/${cluster_id}/stop/`, { - withCredentials: true - }) - } - - startVM( - flavor: string, - image: Image, - servername: string, - project: string, - projectid: string, - http: boolean, - https: boolean, - udp: boolean, - new_volumes: Volume[], - attach_volumes: Volume[], - playbook_information?: string, - additional_elixir_ids?: string[] - ): Observable { - const params: HttpParams = new HttpParams() - .set('flavor', flavor) - .set('image', JSON.stringify(image)) - .set('servername', servername) - .set('project', project) - .set('projectid', projectid) - .set('new_volumes', JSON.stringify(new_volumes)) - .set('attach_volumes', JSON.stringify(attach_volumes)) - .set('http_allowed', http.toString()) - .set('https_allowed', https.toString()) - .set('udp_allowed', udp.toString()) - .set('playbook_information', playbook_information) - .set('additional_elixir_ids', JSON.stringify(additional_elixir_ids)) - - return this.http.post(this.baseVmUrl, params, { - withCredentials: true - }) - } - - startWorkshopVMs( - flavor: string, - image: Image, - servers: { [key: string]: string }[], - project: string, - projectid: string, - workshopShortname: string - ): Observable { - const params: HttpParams = new HttpParams() - .set('flavor', flavor) - .set('image', JSON.stringify(image)) - .set('servers', JSON.stringify(servers)) - .set('project', project) - .set('projectid', projectid) - .set('workshopShortname', workshopShortname) - - return this.http.post(`${this.baseVmUrl}workshop/`, params, { - withCredentials: true - }) - } - - getAllVM( - page: number, - vm_per_site: number, - filter?: string, - filter_status?: string[], - filter_cluster: boolean = false, - filter_set_for_termination: boolean = false - ): Observable { - let params: HttpParams = new HttpParams().set('page', page.toString()).set('vm_per_site', vm_per_site.toString()) - if (filter) { - params = params.append('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - if (filter_cluster) { - params = params.append('filter_cluster', 'true') - } - if (filter_set_for_termination) { - params = params.append('filter_set_for_termination', 'true') - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}voManager/vms/`, { - withCredentials: true, - params - }) - .pipe(map((vm_page: VirtualMachinePage): VirtualMachinePage => new VirtualMachinePage(vm_page))) - } - - getAllClusters( - page: number, - vm_per_site: number, - filter?: string, - filter_status?: string[] - ): Observable { - let params: HttpParams = new HttpParams() - .set('page', page.toString()) - .set('cluster_per_site', vm_per_site.toString()) - - if (filter) { - params = params.set('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}voManager/vms/clusters/`, { - withCredentials: true, - params - }) - .pipe(map((clusters: ClusterPage): ClusterPage => new ClusterPage(clusters))) - } - - getVmById(openstackId: string): Observable { - return this.http - .get(`${this.baseVmUrl}${openstackId}/details/`, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } - - getVmsFromLoggedInUser( - page?: number, - vm_per_site?: number, - filter?: string, - filter_status?: string[], - filter_cluster: boolean = false, - filter_set_for_termination: boolean = false, - not_paginated: boolean = false - ): Observable { - let params: HttpParams = new HttpParams().set('page', page.toString()).set('vm_per_site', vm_per_site.toString()) - - if (filter) { - params = params.set('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - if (filter_cluster) { - params = params.append('filter_cluster', 'true') - } - if (filter_set_for_termination) { - params = params.append('filter_set_for_termination', 'true') - } - - if (not_paginated) { - params = params.append('not_paginated', JSON.stringify(not_paginated)) - } - - const temp_resp: any = this.http.get(this.baseVmUrl, { - withCredentials: true, - params - }) - - if (not_paginated) { - return temp_resp - } else { - return temp_resp.pipe(map((vm_page: VirtualMachinePage) => new VirtualMachinePage(vm_page))) - } - } - - getCondaLogs(openstack_id: string): Observable { - return this.http - .post(`${this.baseVmUrl}${openstack_id}/logs/`, null, { - withCredentials: true - }) - .pipe(map((condaLog: Condalog): Condalog => new Condalog(condaLog))) - } - - getVmsFromFacilitiesOfLoggedUser( - facility_id: string | number, - page: number, - vm_per_site: number, - filter?: string, - filter_status?: string[], - filter_cluster: boolean = false, - filter_set_for_termination: boolean = false - ): Observable { - let params: HttpParams = new HttpParams().set('page', page.toString()).set('vm_per_site', vm_per_site.toString()) - if (filter) { - params = params.set('filter', filter) - } - if (filter_status) { - params = params.append('filter_status', JSON.stringify(filter_status)) - } - if (filter_cluster) { - params = params.append('filter_cluster', 'true') - } - if (filter_set_for_termination) { - params = params.append('filter_set_for_termination', 'true') - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}computecenters/${facility_id}/vms/`, { - withCredentials: true, - params - }) - .pipe(map((vm_page: VirtualMachinePage): VirtualMachinePage => new VirtualMachinePage(vm_page))) - } - - getActiveVmsByProject(groupid: string): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}projects/${groupid}/vms/`, { - withCredentials: true - }) - .pipe( - map((vms: VirtualMachine[]): VirtualMachine[] => - vms.map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm)) - ) - ) - } - - checkVmStatus(openstack_id: string, name?: string): Observable { - if (openstack_id) { - return this.http - .post(`${this.baseVmUrl}${openstack_id}/status/`, null, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } else if (name) { - return this.http - .post(`${this.baseVmUrl}${name}/status/`, null, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } else { - return null - } - } - - deleteVms(vm_ids: string[]): Observable { - const params: HttpParams = new HttpParams().set('vm_ids', JSON.stringify(vm_ids)) - - return this.http.post(`${this.baseVmUrl}/delete/`, params, { - withCredentials: true - }) - } - - checkVmStatusWhenReboot(openstack_id: string): Observable { - const params: HttpParams = new HttpParams().set('reboot', 'true') - - return this.http.post(`${this.baseVmUrl}${openstack_id}/status/`, params, { - withCredentials: true - }) - } - - deleteVM(openstack_id: string): Observable { - return this.http - .delete(`${this.baseVmUrl}${openstack_id}/`, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } - - setVmNeeded(openstack_id: string): Observable { - return this.http.post(`${this.baseVmUrl}${openstack_id}/need/`, { - withCredentials: true - }) - } - - stopVM(openstack_id: string): Observable { - const params: HttpParams = new HttpParams().set('os_action', 'stop') - - return this.http - .post(`${this.baseVmUrl}${openstack_id}/action/`, params, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } - - rebootVM(openstack_id: string, reboot_type: string): Observable { - const params: HttpParams = new HttpParams().set('os_action', 'reboot').set('reboot_type', reboot_type) - - return this.http.post(`${this.baseVmUrl}${openstack_id}/action/`, params, { - withCredentials: true - }) - } - - recreateVmBackend(openstack_id: string): Observable { - return this.http - .post(`${this.baseVmUrl}${openstack_id}/backend/`, null, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } - - resumeVM(openstack_id: string): Observable { - const params: HttpParams = new HttpParams().set('os_action', 'resume') - - return this.http - .post(`${this.baseVmUrl}${openstack_id}/action/`, params, { - withCredentials: true - }) - .pipe(map((vm: VirtualMachine): VirtualMachine => new VirtualMachine(vm))) - } - - getDetachedVolumesByProject(project_id: string | number): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}volumes/project/${project_id}/`, { - withCredentials: true - }) - .pipe(map((volumes: Volume[]): Volume[] => volumes.map((volume: Volume): Volume => new Volume(volume)))) - } - - getVolumesByUser(items_per_page: number, current_page: number, filter?: string): Observable { - let params: HttpParams = new HttpParams() - .set('items_per_page', items_per_page.toString()) - .set('page', current_page.toString()) - if (filter) { - params = params.set('filter', filter) - } - - return this.http - .get(`${ApiSettings.getApiBaseURL()}volumes/`, { - withCredentials: true, - params - }) - .pipe(map((volume_page: VolumePage): VolumePage => new VolumePage(volume_page))) - } - - getVolumeById(id: string): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}volumes/${id}/`, { - withCredentials: true - }) - .pipe(map((volume: Volume): Volume => new Volume(volume))) - } - - getVolumeByNameAndVmName(volume_name: string, virtualmachine_name: string): Observable { - const params: HttpParams = new HttpParams().set('volume_name', volume_name) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}volumes/vms/${virtualmachine_name}/`, { - withCredentials: true, - params - }) - .pipe(map((volume: Volume): Volume => new Volume(volume))) - } - - createVolume(volume_name: string, volume_storage: string, vm_openstackid: string): Observable { - const params: HttpParams = new HttpParams() - .set('volume_name', volume_name) - .set('volume_storage', volume_storage) - .set('vm_openstackid', vm_openstackid) - - return this.http - .post(`${ApiSettings.getApiBaseURL()}volumes/`, params, { - withCredentials: true - }) - .pipe(map((volume: Volume): Volume => new Volume(volume))) - } - - extendVolume(volume_id: string, new_size: string): Observable { - const params: HttpParams = new HttpParams().set('os_action', 'extend').set('new_size', new_size) - - return this.http.post(`${ApiSettings.getApiBaseURL()}volumes/${volume_id}/action/`, params, { - withCredentials: true - }) - } - - attachVolumetoServer(volume_id: string, instance_id: string): Observable { - const params: HttpParams = new HttpParams().set('instance_id', instance_id).set('os_action', 'attach') - - return this.http.post(`${ApiSettings.getApiBaseURL()}volumes/${volume_id}/action/`, params, { - withCredentials: true - }) - } - - renameVolume(volume_id: string, new_volume_name: string): Observable { - const params: HttpParams = new HttpParams().set('new_volume_name', new_volume_name) - - return this.http - .patch(`${ApiSettings.getApiBaseURL()}volumes/${volume_id}/`, params, { - withCredentials: true - }) - .pipe(map((volume: Volume): Volume => new Volume(volume))) - } - - deleteVolume(volume_id: string): Observable { - return this.http.delete(`${ApiSettings.getApiBaseURL()}volumes/${volume_id}/`, { - withCredentials: true - }) - } - - deleteVolumes(volume_ids: string[]): Observable { - const params: HttpParams = new HttpParams().set('volume_ids', JSON.stringify(volume_ids)) - - return this.http.post(`${ApiSettings.getApiBaseURL()}volumes/delete/`, params, { - withCredentials: true - }) - } - - deleteVolumeAttachment(volume_id: string, instance_id: string): Observable { - const params: HttpParams = new HttpParams().set('instance_id', instance_id).set('os_action', 'detach') - - return this.http.post(`${ApiSettings.getApiBaseURL()}volumes/${volume_id}/action/`, params, { - withCredentials: true - }) - } - - deleteVolumeAttachments(volume_ids: string[]): Observable { - const params: HttpParams = new HttpParams().set('volume_ids', JSON.stringify(volume_ids)) - - return this.http.post(`${ApiSettings.getApiBaseURL()}volumes/attachments/delete/`, params, { - withCredentials: true - }) - } -} diff --git a/src/app/api-connector/workshop.service.ts b/src/app/api-connector/workshop.service.ts index 6d88c7c0e7..a1f5ad83b9 100644 --- a/src/app/api-connector/workshop.service.ts +++ b/src/app/api-connector/workshop.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@angular/core' import { HttpClient, HttpParams } from '@angular/common/http' import { Observable } from 'rxjs' import { map } from 'rxjs/operators' -import { UrlData, WorkshopUrlInfoModel } from '../virtualmachines/workshop/workshop-urlinfo.model' import { ApiSettings } from './api-settings.service' import { Workshop } from '../virtualmachines/workshop/workshop.model' import { WorkshopVM } from '../virtualmachines/workshop/workshop-vm.model' @@ -10,56 +9,7 @@ import { WorkshopTimeFrame } from '../virtualmachines/workshop/workshopTimeFrame @Injectable() export class WorkshopService { - constructor(private http: HttpClient) { - this.http = http - } - - getWorkshopInfoUrl(application_id: string | number): Observable { - const params: HttpParams = new HttpParams().set('application_id', application_id) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}workshops/url_info/all_vms/`, { - withCredentials: true, - params - }) - .pipe( - map((workshops_infos: WorkshopUrlInfoModel[]): WorkshopUrlInfoModel[] => - workshops_infos.map( - (workshop_info: WorkshopUrlInfoModel): WorkshopUrlInfoModel => new WorkshopUrlInfoModel(workshop_info) - ) - ) - ) - } - - getUrlDataForWorkshopVm(workshop_id: number, openstackid: string): Observable { - const params: HttpParams = new HttpParams().set('openstackid', openstackid) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}workshops/${workshop_id}/url_info/one_vm/`, { - withCredentials: true, - params - }) - .pipe(map((urlData: UrlData): UrlData => new UrlData(urlData))) - } - - getResenvUrlForWorkshopVm(workshop_id: number, openstackid: string): Observable { - const params: HttpParams = new HttpParams().set('openstackid', openstackid) - - return this.http - .get(`${ApiSettings.getApiBaseURL()}workshops/${workshop_id}/url_info/one_vm/resenv_only/`, { - withCredentials: true, - params - }) - .pipe(map((urlData: UrlData): UrlData => new UrlData(urlData))) - } - - loadWorkshopWithVms(workshop_id: number): Observable { - return this.http - .get(`${ApiSettings.getApiBaseURL()}workshops/${workshop_id}/vms/`, { - withCredentials: true - }) - .pipe(map((workshop: Workshop): Workshop => new Workshop(workshop))) - } + constructor(private http: HttpClient) {} loadWorkshopCalender(workshop_id: number): Observable { return this.http diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 6ead6f2e35..5b122cb04f 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -47,14 +47,12 @@ export const routes: Routes = [ path: 'userinfo', canActivate: [LoggedInGuard], - loadChildren: () => import('./userinfo/userinfo.module').then(m => m.UserinfoModule), }, { path: 'help', canActivate: [LoggedInGuard], - loadChildren: () => import('./help/help.module').then(m => m.HelpModule), }, { @@ -69,12 +67,6 @@ export const routes: Routes = [ loadChildren: () => import('./applications/applications.module').then(m => m.ApplicationsModule), }, - { - path: 'virtualmachines', - canActivate: [LoggedInGuard], - - loadChildren: () => import('./virtualmachines/vm.module').then(m => m.VmModule), - }, { path: 'vo-manager', loadChildren: () => import('./vo_manager/VoManager.module').then(m => m.VoManagerModule), diff --git a/src/app/applications/type-overview.component.ts b/src/app/applications/type-overview.component.ts index e67b0d1983..8d9275c07a 100644 --- a/src/app/applications/type-overview.component.ts +++ b/src/app/applications/type-overview.component.ts @@ -39,16 +39,16 @@ export class TypeOverviewComponent implements OnInit { ngOnInit(): any { this.simpleVM_logo_link = `${this.static_img_folder}simpleVM_Logo.svg` - this.simpleVM_curve_logo = `${this.static_img_folder}/simplevm-info-page/flatlearning.svg` - this.simpleVM_ease_logo = `${this.static_img_folder}/simplevm-info-page/easytouse.svg` - this.simpleVM_remote_logo = `${this.static_img_folder}/simplevm-info-page/remote.svg` + this.simpleVM_curve_logo = `${this.static_img_folder}simplevm-info-page/flatlearning.svg` + this.simpleVM_ease_logo = `${this.static_img_folder}simplevm-info-page/easytouse.svg` + this.simpleVM_remote_logo = `${this.static_img_folder}simplevm-info-page/remote.svg` this.kubernetes_logo_link = `${this.static_img_folder}kubernetes_logo.svg` this.kubernetes_logo_border = `${this.static_img_folder}kubernetes_logo_border.svg` this.openstack_logo_link = `${this.static_img_folder}openstack_plain_red.svg` - this.openstack_api_logo = `${this.static_img_folder}/openstack-info-page/api.svg` - this.openstack_conf_logo = `${this.static_img_folder}/openstack-info-page/configuration.svg` - this.openstack_scale_logo = `${this.static_img_folder}/openstack-info-page/scale.svg` + this.openstack_api_logo = `${this.static_img_folder}openstack-info-page/api.svg` + this.openstack_conf_logo = `${this.static_img_folder}openstack-info-page/configuration.svg` + this.openstack_scale_logo = `${this.static_img_folder}openstack-info-page/scale.svg` } } diff --git a/src/app/facility_manager/imagetags.component.ts b/src/app/facility_manager/imagetags.component.ts index 9d9470ea1e..6297ded36f 100644 --- a/src/app/facility_manager/imagetags.component.ts +++ b/src/app/facility_manager/imagetags.component.ts @@ -4,7 +4,6 @@ import { forkJoin } from 'rxjs' import { ImageService } from '../api-connector/image.service' import { BlockedImageTag, BlockedImageTagResenv, ImageLogo, ImageMode, ImageTag } from './image-tag' import { FacilityService } from '../api-connector/facility.service' -import { BiocondaService } from '../api-connector/bioconda.service' /** * ImageTag component. @@ -12,7 +11,7 @@ import { BiocondaService } from '../api-connector/bioconda.service' @Component({ selector: 'app-image-tags', templateUrl: 'imageTag.component.html', - providers: [ImageService, FacilityService, BiocondaService] + providers: [ImageService, FacilityService] }) export class ImageTagComponent implements OnInit { title: string = 'Image Tags' @@ -50,8 +49,7 @@ export class ImageTagComponent implements OnInit { constructor( private imageService: ImageService, - private facilityService: FacilityService, - private biocondaService: BiocondaService + private facilityService: FacilityService ) { // constructor for ImageTags } @@ -107,7 +105,6 @@ export class ImageTagComponent implements OnInit { this.facilityService.getManagerFacilities().subscribe((result: any): void => { this.managerFacilities = result this.selectedFacility = this.managerFacilities[0] - this.getTagModeSuggestions() forkJoin( this.imageService.getImageTags(this.selectedFacility['FacilityId']), this.imageService.getImageLogos(), @@ -175,7 +172,6 @@ export class ImageTagComponent implements OnInit { this.newModeDescription = '' this.newModeCopy = '' this.imageModes.push(createdMode) - this.getTagModeSuggestions() }) } @@ -195,7 +191,6 @@ export class ImageTagComponent implements OnInit { update_mode.name = this.updateModeName this.imageService.updateImageMode(update_mode).subscribe((updated_mode: ImageMode): void => { this.imageModes[idx] = updated_mode - this.getTagModeSuggestions() }) } @@ -228,14 +223,6 @@ export class ImageTagComponent implements OnInit { }) } - getTagModeSuggestions(): void { - this.biocondaService - .getSuggestedForcTemplates(this.selectedFacility['FacilityId'].toString()) - .subscribe((response: any[]): void => { - this.suggestedModes = response.map((template: any): any => template) - }) - } - addBlockedTagResenv(tag: string, input: HTMLInputElement): void { if (input.validity.valid) { this.imageService diff --git a/src/app/layouts/full-layout.component.ts b/src/app/layouts/full-layout.component.ts index 5d91e8c056..2808448169 100644 --- a/src/app/layouts/full-layout.component.ts +++ b/src/app/layouts/full-layout.component.ts @@ -1,6 +1,5 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core' import moment from 'moment' -import { Router } from '@angular/router' import { ApiSettings } from '../api-connector/api-settings.service' import { ClientService } from '../api-connector/client.service' import { FacilityService } from '../api-connector/facility.service' @@ -13,7 +12,6 @@ import { ApplicationsService } from '../api-connector/applications.service' import { ProjectEnumeration } from '../projectmanagement/project-enumeration' import { environment } from '../../environments/environment' import { is_vo } from '../shared/globalvar' -import { VirtualmachineService } from '../api-connector/virtualmachine.service' import { Application_States } from '../shared/shared_modules/baseClass/abstract-base-class' import { WIKI, WIKI_FAQ, STATUS_LINK } from '../../links/links' import { MaintenanceTimeFrame } from '../vo_manager/maintenance/maintenanceTimeFrame.model' @@ -26,16 +24,7 @@ import { UserInfoComponent } from '../userinfo/userinfo.component' @Component({ selector: 'app-dashboard', templateUrl: './full-layout.component.html', - providers: [ - ApplicationsService, - VirtualmachineService, - VoService, - GroupService, - UserService, - FacilityService, - ClientService, - ApiSettings - ] + providers: [ApplicationsService, VoService, GroupService, UserService, FacilityService, ClientService, ApiSettings] }) export class FullLayoutComponent extends ApplicationBaseClassComponent implements OnInit { public year: number = new Date().getFullYear() @@ -57,7 +46,6 @@ export class FullLayoutComponent extends ApplicationBaseClassComponent implement openstack_logo: string = 'static/webapp/assets/img/openstack_plain_red.svg' kubernetes_logo: string = 'static/webapp/assets/img/kubernetes_logo.svg' - cluster_allowed: boolean = false has_workshops: boolean = false missing_consents: string[] = [] maintenanceTimeframes: MaintenanceTimeFrame[] = [] @@ -79,15 +67,12 @@ export class FullLayoutComponent extends ApplicationBaseClassComponent implement STATUS_LINK: string = STATUS_LINK constructor( - private voService: VoService, private maintenanceService: MaintenanceService, private groupService: GroupService, userService: UserService, facilityService: FacilityService, applicationsService: ApplicationsService, - private virtualMachineService: VirtualmachineService, - private cd: ChangeDetectorRef, - private router: Router + private cd: ChangeDetectorRef ) { super(userService, applicationsService, facilityService, cd) } @@ -122,12 +107,6 @@ export class FullLayoutComponent extends ApplicationBaseClassComponent implement } } - set_cluster_allowed(): void { - this.virtualMachineService.getClusterAllowed().subscribe((res: any): void => { - this.cluster_allowed = res['allowed'] - }) - } - public get_is_facility_manager(): void { this.facilityService.getManagerFacilities().subscribe((result: any): void => { if (result.length > 0) { @@ -180,7 +159,6 @@ export class FullLayoutComponent extends ApplicationBaseClassComponent implement } ngOnInit(): void { - this.set_cluster_allowed() this.getGroupsEnumeration() this.is_vm_project_member() this.is_workshop_admin() diff --git a/src/app/userinfo/userinfo.component.ts b/src/app/userinfo/userinfo.component.ts index 97f05a8d07..cae401f00a 100644 --- a/src/app/userinfo/userinfo.component.ts +++ b/src/app/userinfo/userinfo.component.ts @@ -16,9 +16,7 @@ import { } from '../../links/links' import { ProjectEnumeration } from '../projectmanagement/project-enumeration' import { ApplicationsService } from '../api-connector/applications.service' -import { VirtualmachineService } from '../api-connector/virtualmachine.service' import { VirtualMachine } from '../virtualmachines/virtualmachinemodels/virtualmachine' -import { VirtualMachineStates } from '../virtualmachines/virtualmachinemodels/virtualmachinestates' import { Application } from '../applications/application.model/application.model' import { ProjectMember } from '../projectmanagement/project_member.model' import { Application_States } from '../shared/shared_modules/baseClass/abstract-base-class' @@ -127,14 +125,12 @@ export class UserInfoComponent implements OnInit { private userService: UserService, private keyService: KeyService, private applicationsService: ApplicationsService, - private vmService: VirtualmachineService, private modalService: BsModalService ) { this.groupService = groupService this.userService = userService this.keyService = keyService this.applicationsService = applicationsService - this.vmService = vmService } emitConfirmation() { @@ -310,21 +306,6 @@ export class UserInfoComponent implements OnInit { }) } }) - const vmFilter: string[] = [ - VirtualMachineStates.ACTIVE, - VirtualMachineStates.SHUTOFF, - VirtualMachineStates.CLIENT_OFFLINE - ] - VirtualMachineStates.IN_PROCESS_STATES.forEach((state: string) => vmFilter.push(state)) - this.vmService.getVmsFromLoggedInUser(0, 25, '', vmFilter, false, false, true).subscribe({ - next: (res: VirtualMachine[]) => { - this.userVirtualMachines = res - this.summaryError = false - }, - error: () => { - this.summaryError = true - } - }) } else { this.userHasNoGroups = true this.summaryError = false diff --git a/src/app/virtualmachines/addvm.component.html b/src/app/virtualmachines/addvm.component.html deleted file mode 100644 index b87f7c7fd0..0000000000 --- a/src/app/virtualmachines/addvm.component.html +++ /dev/null @@ -1,1042 +0,0 @@ -
-
-
-
Public Key
- -
-
- Info: You need to set a valid SSH Key before you can start a machine. Please set a valid key - below or on your personal data page. -
-
- - - - -
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- New Virtual Machine - - - {{ this.selectedProject[0] }} -
- -
-
-
-
- - - -
-
-
-
- -
-
-
- -
- The following limit/limits has/have been reached: -
- Amount of VMs
-
- Amount of cores
-
- Amount of RAM
-
- An admin of your project can request more resources if necessary. -
-
-
-
- -
-
- -
- -
- -
-
-
- Allowed characters are upper and lower case letters (a-z A-Z) and arabic numbers (0-9). -
-
-
- -
-
-
- - -
- Loading flavors ... -
-
-
-
-
-
-
- Information for ephemeral flavors: - Ephemeral storage is not best suited for persistent data. Read more - here. -
-
- -
-
- - -
-
-
- -
- -
-
-
- Volumes
- Volumes offer more space for your data, comparable to an external harddrive. You may - create new volumes or attach existing ones. - -
-
- -
-
-
- You can't create a new volume, because you have reached the maximum number of volumes - available for this project. -
-
-
-
-
-
- You can't create a new volume, because you have reached the maximum amount of storage - (in GB) available for this project. -
-
-
- -
-
-
-
-
- Name -
-
- -
-
-
-
- Mountpath -
-
-
- /vol/ -
- -
-
-
-
- Storage -
-
- -
- - GB (max - {{ - selectedProjectRessources.max_volume_storage - - (this.selectedProjectRessources.used_volume_storage + - this.getStorageInList()) - }} - ) - -
-
-
-
- - -
-
- {{ selected_detached_vol.volume_name }} -
-
-
-
- /vol/ -
- -
-
-
- {{ selected_detached_vol.volume_storage }} - GB -
-
- -
-
-
-
- -
-
- - -
-
- -
-
-
- -
-
- Volumes to mount -
-
-
-
- Name -
-
- Mountpath -
-
- Storage -
-
-
- -
-
- {{ vol.volume_name }} - (New) -
-
/vol/{{ vol.volume_path }}
-
- {{ vol.volume_storage }} - GB -
-
- -
-
-
- -
-
- {{ vol.volume_name }} - (Existing) -
-
/vol/{{ vol.volume_path }}
-
- {{ vol.volume_storage }} - GB -
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
- - - -
- Tools - powered by - Conda® BETA - -
- -
-

- Please be aware that all Bioconda tools and packages are provided by third parties. de.NBI - Cloud is not responsible for the functionality of the packages provided. In case of problems - during installation or use, please contact the developers of the respective packages. -

-
- -
- -
-
- - -
- Browser-based Research Environments - (e.g. RStudio, Apache Guacamole, Theia IDE, VSCode, Jupyterlab) - BETA - -
- - -
- -
- Grant access for specific project members of {{ selectedProject[0] }} - -
- - -
- - -
- Optional parameters - -
- -
- -
- - -
-
- To use MOSH with UDP ports, please select an Image which supports MOSH. Learn more about - MOSH - here. -
-
-
- -
- - - -
-
-
-
-
-
-
- - -
-
- - -
-
- - -
-
-
- -
-
-
-
-
-
-
- You are not allowed to start a machine in this project, as the administrators of the project do not - allow non-administrators to start machines. -

This is the only SimpleVm project you are a member of.

-
-
-
- - -
-
- -
- The corresponding client is currently offline. If you have any questions please contact - {{ CLOUD_PORTAL_SUPPORT_MAIL }}. - Check our - status overview to see if the site - of your project is reachable. -
-
- - -
-
-
-
- - - diff --git a/src/app/virtualmachines/addvm.component.ts b/src/app/virtualmachines/addvm.component.ts deleted file mode 100644 index 03952561bd..0000000000 --- a/src/app/virtualmachines/addvm.component.ts +++ /dev/null @@ -1,855 +0,0 @@ -import { Component, DoCheck, OnDestroy, OnInit, ViewChild } from '@angular/core' -import { forkJoin, Subscription } from 'rxjs' -import { Router } from '@angular/router' -import { - CLOUD_PORTAL_SUPPORT_MAIL, - STATUS_LINK, - WIKI_EPHEMERAL_LINK, - WIKI_MOSH_LINK, - WIKI_PERSISTENT_TERMINAL_LINK, - WIKI_VOLUME_OVERVIEW -} from 'links/links' -import { KeyValue } from '@angular/common' - -import { Image } from './virtualmachinemodels/image' -import { Flavor } from './virtualmachinemodels/flavor' -import { Userinfo } from '../userinfo/userinfo.model' -import { environment } from '../../environments/environment' -import { IResponseTemplate } from '../api-connector/response-template' -import { Client } from '../vo_manager/clients/client.model' -import { VirtualMachine } from './virtualmachinemodels/virtualmachine' -import { BiocondaComponent } from './conda/bioconda.component' -import { ResEnvComponent } from './conda/res-env.component' -import { is_vo } from '../shared/globalvar' -import { RandomNameGenerator } from '../shared/randomNameGenerator' -import { Volume } from './volumes/volume' -import { UserService } from '../api-connector/user.service' -import { GroupService } from '../api-connector/group.service' -import { KeyService } from '../api-connector/key.service' -import { FlavorService } from '../api-connector/flavor.service' -import { BiocondaService } from '../api-connector/bioconda.service' -import { VirtualmachineService } from '../api-connector/virtualmachine.service' -import { ApiSettings } from '../api-connector/api-settings.service' -import { BlockedImageTagResenv } from '../facility_manager/image-tag' -import { ApplicationRessourceUsage } from '../applications/application-ressource-usage/application-ressource-usage' -import { ProjectMember } from '../projectmanagement/project_member.model' -import { ApplicationsService } from '../api-connector/applications.service' -import { ImageService } from '../api-connector/image.service' - -/** - * Start virtualmachine component. - */ -@Component({ - selector: 'app-new-vm', - templateUrl: 'addvm.component.html', - providers: [ - GroupService, - KeyService, - FlavorService, - VirtualmachineService, - ApiSettings, - UserService, - ApplicationsService, - BiocondaService, - ImageService - ] -}) -export class VirtualMachineComponent implements OnInit, DoCheck, OnDestroy { - SIXTY_SIX_PERCENT: number = 66 - - SEVENTY_FIVE: number = 75 - ACTIVE: string = 'ACTIVE' - DELETED: string = 'DELETED' - PORT_CLOSED: string = 'PORT_CLOSED' - PREPARE_PLAYBOOK_BUILD: string = 'PREPARE_PLAYBOOK_BUILD' - CREATING_STATUS: string = 'Creating...' - CHECKING_PORT_STATUS: string = 'Checking Connection..' - PREPARE_PLAYBOOK_STATUS: string = 'Prepare Playbook Build...' - ANIMATED_PROGRESS_BAR: string = 'progress-bar-animated' - redirectProgress: string = '0' - newVm: VirtualMachine = null - members_to_add: ProjectMember[] = [] - progress_bar_status: string = 'Creating..' - progress_bar_animated: string = 'progress-bar-animated' - progress_bar_width: number = 0 - http_allowed: boolean = false - https_allowed: boolean = false - udp_allowed: boolean = false - install_mosh: boolean = false - vm_responsibility: boolean = false - is_vo: boolean = false - hasTools: boolean = false - gaveOkay: boolean = false - client_checked: boolean = false - playbook_run: number = 0 - timeout: number = 0 - has_forc: boolean = false - WIKI_VOLUME_OVERVIEW: string = WIKI_VOLUME_OVERVIEW - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - STATUS_LINK: string = STATUS_LINK - WIKI_EPHEMERAL_LINK: string = WIKI_EPHEMERAL_LINK - WIKI_MOSH_LINK: string = WIKI_MOSH_LINK - WIKI_PERSISTENT_TERMINAL_LINK = WIKI_PERSISTENT_TERMINAL_LINK - blockedImageTagsResenv: BlockedImageTagResenv[] - initial_loaded: boolean = false - - forc_url: string = '' - client_id: string - mosh_mode_available: boolean = false - resenvSelected: boolean = false - resEnvValid: boolean = true - resEnvNeedsName: boolean = false - resEnvNeedsTemplate: boolean = false - resEnvOkayNeeded: boolean = false - volumesToMount: Volume[] = [] - volumesToAttach: Volume[] = [] - - title: string = 'New Instance' - - vm_name: string - - started_machine: boolean = false - - conda_img_path: string = 'static/webapp/assets/img/conda_logo.svg' - - singleProject: boolean = false - - showAddVol: boolean = false - - flavors_loaded: boolean = false - error_starting_machine: boolean = false - - create_error: IResponseTemplate - - selectedProjectIsMigrated: boolean = false - - /** - * All flavors of a project. - */ - flavors: Flavor[] = [] - selected_flavor_types: Flavor[] = [] - selected_flavor_type: string = 'Standard Flavors' - - flavor_types: { [name: string]: Flavor[] } = {} - - /** - * Selected Image. - */ - selectedImage: Image - - /** - * Selected Flavor. - */ - selectedFlavor: Flavor - - /** - * Userinfo from the user. - */ - userinfo: Userinfo - - /** - * Selected Project vms client. - */ - selectedProjectClient: Client - - detached_project_volumes: Volume[] = [] - selected_detached_vol: Volume - undefined_detached_vol: Volume = new Volume() - newCores: number = 0 - newRam: number = 0 - newVms: number = 0 - newGpus: number = 0 - cluster_allowed: boolean = false - current_key_blocked: boolean = false - selectedProjectRessources: ApplicationRessourceUsage - - /** - * The selected project ['name',id]. - */ - selectedProject: [string, number] - - /** - * If the client for a project is viable. - */ - client_available: boolean = false - showAttachVol: boolean = false - credits_allowed: boolean = false - - /** - * Default volume name. - * - * @type {string} - */ - volumeName: string = '' - volumeMountPath: string - - /** - * Default volumeStorage. - * - * @type {number} - */ - volumeStorage: number = 0 - - /** - * Indicates whether the projects of the user are loaded or not. - * @type {boolean} - */ - projects_loaded: boolean - - /** - * Indicates whether the information about the user are loaded or not. - * @type {boolean} - */ - - userinfo_loaded: boolean - - /** - * All projects of the user. - * - * @type {any[]} - */ - projects: [string, number][] = [] - - /** - * All projects in which the user is allowed to start machines. - * - * @type {any[]} - */ - allowedProjects: [string, number][] = [] - - /** - * If all project data is loaded. - * - * @type {boolean} - */ - projectDataLoaded: boolean = false - - /** - * id of the freemium project. - * - * @type {number} - */ - FREEMIUM_ID: number = environment.freemium_project_id - - prod: boolean = environment.production - subscription: Subscription = new Subscription() - - /** - * Time for the check status loop. - * - * @type {number} - */ - private checkStatusTimeout: number = 5000 - - @ViewChild('bioconda') biocondaComponent: BiocondaComponent - @ViewChild('resEnv') resEnvComponent: ResEnvComponent - - constructor( - private groupService: GroupService, - private imageService: ImageService, - private flavorService: FlavorService, - private virtualmachineservice: VirtualmachineService, - private keyservice: KeyService, - private userService: UserService, - private router: Router, - private condaService: BiocondaService, - private applicationsService: ApplicationsService - ) {} - - /** - * Get flavors for the project. - * - * @param project_id - */ - getFlavors(project_id: number): void { - this.subscription.add( - this.flavorService.getFlavors(project_id).subscribe( - (flavors: Flavor[]): void => { - this.flavors = flavors - this.flavor_types = this.flavorService.sortFlavors(this.flavors) - this.flavors_loaded = true - this.initial_loaded = true - }, - (error: any) => { - console.log(error) - this.flavors = [] - this.flavor_types = {} - this.flavors_loaded = true - this.initial_loaded = true - } - ) - ) - } - - setCurrentKeyBlocked(value: boolean): void { - this.current_key_blocked = value - } - - reloadFlavors(): void { - this.flavors_loaded = false - this.selectedFlavor = undefined - this.getFlavors(this.selectedProject[1]) - } - - getDetachedVolumesByProject(): void { - this.subscription.add( - this.virtualmachineservice - .getDetachedVolumesByProject(this.selectedProject[1]) - .subscribe((detached_volumes: Volume[]): void => { - this.detached_project_volumes = detached_volumes - }) - ) - } - - checkIfMountPathIsUsable(path?: string): boolean { - if (path) { - for (const vol of this.volumesToMount) { - if (vol.volume_path === path) { - return false - } - } - - for (const vol of this.volumesToAttach) { - if (vol.volume_path === path) { - return false - } - } - - return true - } - - return false - } - - /** - * Checks if the name which is entered for a new volume is valid. - */ - checkInputVolumeString(text?: string): boolean { - if (text) { - if (!(text.length > 0)) { - return false - } - - return new RegExp('^[\\w]+$', 'i').test(text) - } - - return false - } - - /** - * Checks if the amount of storage that is entered for a new volume is valid. - * Depends on free storage-space in the project and the amount of storage already 'reserved' by the volumes - * in the 'volumesToMount'-list. - */ - checkStorageNumber(): boolean { - if (!(this.volumeStorage > 0)) { - return false - } else { - return ( - this.selectedProjectRessources.used_volume_storage + this.getStorageInList() + this.volumeStorage <= - this.selectedProjectRessources.max_volume_storage - ) - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - unsorted(a: KeyValue, b: KeyValue): number { - return 0 - } - - /** - * Checks if the entered amount of storage and the entered name for a new volume are both okay. - * A new volume can only be added to the list, if this function returns true. - */ - checkVolumeValidity(): boolean { - return ( - this.checkStorageNumber() && - this.checkIfMountPathIsUsable(this.volumeMountPath) && - this.checkInputVolumeString(this.volumeMountPath) && - this.checkInputVolumeString(this.volumeName) - ) - } - - /** - * Adds a new volume to the list of volumes which will be mounted to the machine when it gets started. - */ - addVolumeToList(): void { - const newVol: Volume = new Volume() - newVol.volume_storage = this.volumeStorage - newVol.volume_name = this.volumeName - newVol.volume_path = this.volumeMountPath - newVol.volume_device = 'test' - this.volumesToMount.push(newVol) - this.volumeStorage = 0 - this.volumeName = '' - this.volumeMountPath = '' - } - - addAttachVolume(vol: Volume): void { - this.selected_detached_vol = this.undefined_detached_vol - this.volumesToAttach.push(vol) - this.detached_project_volumes = this.detached_project_volumes.filter((volume: Volume): any => vol !== volume) - if (this.detached_project_volumes.length === 0) { - this.toggleShowAttachVol() - } - } - - removeAttachVolume(vol: Volume): void { - this.selected_detached_vol = null - const idx: number = this.volumesToAttach.indexOf(vol) - vol.volume_path = null - if (idx !== -1) { - this.volumesToAttach.splice(idx, 1) - this.detached_project_volumes.push(vol) - } - } - - removeVolFromList(vol: Volume): void { - const idx: number = this.volumesToMount.indexOf(vol) - vol.volume_path = null - if (idx > -1) { - this.volumesToMount.splice(idx, 1) - } - } - - /** - * Validate the public key of the user. - */ - validatePublicKey(): boolean { - return /ssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3}( [^@]+@[^@]+)?/.test(this.userinfo.PublicKey) - } - - /** - * Toggles the state of the showAddVol Boolean - */ - toggleShowAddVol(): void { - if (!this.showAddVol) { - this.showAddVol = true - this.showAttachVol = false - this.volumeName = '' - this.volumeMountPath = null - this.volumeStorage = 0 - } else { - this.showAddVol = false - this.volumeName = '' - this.volumeMountPath = null - this.volumeStorage = 0 - } - } - - toggleShowAttachVol(): void { - if (!this.showAttachVol) { - this.showAttachVol = true - this.showAddVol = false - this.selected_detached_vol = this.undefined_detached_vol - } else { - this.showAttachVol = false - this.selected_detached_vol = this.undefined_detached_vol - } - } - - /** - * Reset the progress bar. - */ - resetProgressBar(): void { - this.progress_bar_status = this.CREATING_STATUS - this.progress_bar_animated = this.ANIMATED_PROGRESS_BAR - this.progress_bar_width = 0 - } - - /** - * Start a virtual machine with specific params. - * - * @param flavor - * @param servername - * @param project - * @param projectid - */ - startVM(flavor: string, servername: string, project: string, projectid: string | number): void { - this.progress_bar_width = 25 - this.create_error = null - // tslint:disable-next-line:no-complex-conditionals - if (this.selectedImage && flavor && servername && project) { - this.create_error = null - this.started_machine = true - - const re: RegExp = /\+/gi - - const flavor_fixed: string = flavor.replace(re, '%2B') - // Playbook and Research-Environment stuff - let play_information: string = this.getPlaybookInformation() - if (play_information !== '{}') { - this.playbook_run = 1 - } else { - play_information = null - } - - if (!this.mosh_mode_available) { - this.udp_allowed = false - } - this.delay(500) - .then((): any => { - this.progress_bar_width = 50 - }) - .catch((): any => {}) - const additional_elixir_ids: string[] = this.members_to_add.map((mem: ProjectMember): string => mem.elixirId) - this.subscription.add( - this.virtualmachineservice - .startVM( - flavor_fixed, - this.selectedImage, - servername, - project, - projectid.toString(), - this.http_allowed, - this.https_allowed, - this.udp_allowed, - this.volumesToMount, - this.volumesToAttach, - play_information, - additional_elixir_ids - ) - .subscribe( - (newVm: VirtualMachine): void => { - this.error_starting_machine = false - this.newVm = newVm - this.started_machine = false - - if (newVm.status) { - if (newVm['volume_error']) { - this.progress_bar_width = 50 - - this.progress_bar_status = - 'At least 1 volume could not be created due to invalid naming. This will not stop the machine creation process.' - setTimeout((): void => { - void this.router.navigate(['/virtualmachines/vmOverview']).then().catch() - }, 15000) - } else { - this.progress_bar_width = 75 - setTimeout((): void => { - void this.router.navigate(['/virtualmachines/vmOverview']).then().catch() - }, 2000) - } - } else { - this.loadProjectData() - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - this.create_error = (newVm) - } - }, - (error): void => { - console.log(error) - this.error_starting_machine = true - } - ) - ) - } else { - this.progress_bar_status = this.CREATING_STATUS - this.newVm = null - } - } - - async delay(ms: number): Promise { - await new Promise((resolve: any): any => setTimeout(resolve, ms)) - } - - getPlaybookInformation(): string { - const playbook_info: { - [name: string]: { - [variable: string]: string - } - } = {} - this.timeout = 300 - if (this.biocondaComponent.hasChosenTools()) { - playbook_info['conda'] = { - packages: this.biocondaComponent.getChosenTools() - } - this.timeout += this.biocondaComponent.getTimeout() - } - - if ( - this.resEnvComponent && - this.resEnvComponent.selectedTemplate.template_name !== 'undefined' && - this.resEnvComponent.user_key_url.errors === null - ) { - playbook_info[this.resEnvComponent.selectedTemplate.template_name] = { - create_only_backend: `${this.resEnvComponent.getCreateOnlyBackend()}` - } - playbook_info['user_key_url'] = { user_key_url: this.resEnvComponent.getUserKeyUrl() } - } - - if (this.udp_allowed && this.install_mosh) { - playbook_info['optional'] = { mosh: 'install' } - } - - return JSON.stringify(playbook_info) - } - - /** - * Get the client from the selected project. - * If connected get vm,volumes etc. - */ - getSelectedProjectClient(): void { - this.subscription.unsubscribe() - this.subscription = new Subscription() - this.subscription.add( - this.groupService.getCreditsAllowedByPerunId(this.selectedProject[1]).subscribe((res: any): void => { - this.credits_allowed = res['credits_allowed'] - }) - ) - this.newCores = 0 - this.newGpus = 0 - this.newVms = 0 - this.volumesToAttach = [] - this.volumesToMount = [] - this.client_checked = false - this.projectDataLoaded = false - this.subscription.add( - this.groupService.getClient(this.selectedProject[1].toString()).subscribe((client: Client): void => { - this.loadProjectData() - - if (client.status && client.status === 'Connected' && client.activated) { - this.client_available = true - - this.client_checked = true - this.getForc(client.id) - } else { - this.client_available = false - this.client_checked = true - } - this.selectedProjectClient = client - this.subscription.add( - this.imageService - .getBlockedImageTagsResenv(Number(this.selectedProjectClient.id), 'true') - .subscribe((tags: BlockedImageTagResenv[]): void => { - this.blockedImageTagsResenv = tags - }) - ) - }) - ) - this.subscription.add( - this.applicationsService - .getApplicationMigratedByGroupId(this.selectedProject[1].toString()) - .subscribe((migrated: boolean): void => { - this.selectedProjectIsMigrated = migrated - }) - ) - } - - getForc(id: string): void { - this.subscription.add( - this.groupService.getClientForcUrl(this.selectedProject[1].toString()).subscribe((response: JSON): void => { - if (response['forc_url'] !== null) { - this.has_forc = true - this.forc_url = response['forc_url'] - } - }) - ) - this.client_id = id - } - - /** - * Reset the data attribute. - */ - resetData(): void { - if (this.newVm === null) { - return - } - this.newVm = null - } - - /** - * Initializes the data. - * Gets all groups of the user and their key. - */ - initializeData(): void { - this.subscription.add( - forkJoin([ - this.groupService.getSimpleVmAllowedByUser(), - this.groupService.getSimpleVmByUser(), - this.userService.getUserInfo() - ]).subscribe((result: any): void => { - this.userinfo = result[2] - this.userinfo_loaded = true - this.validatePublicKey() - const allowedMemberGroups: any = result[0] - const memberGroups: any = result[1] - for (const project of memberGroups) { - this.projects.push(project) - } - this.projects_loaded = true - for (const project of allowedMemberGroups) { - this.allowedProjects.push(project) - } - if (this.projects.length === 1) { - this.resetChecks() - this.selectedProject = this.projects[0] - this.getSelectedProjectClient() - this.singleProject = true - } - }) - ) - } - - loadProjectData(): void { - this.projectDataLoaded = false - this.flavors = [] - this.flavors_loaded = false - this.selectedImage = undefined - this.selectedFlavor = undefined - this.getDetachedVolumesByProject() - this.subscription.add( - this.groupService - .getGroupResources(this.selectedProject[1].toString()) - .subscribe((res: ApplicationRessourceUsage): void => { - this.selectedProjectRessources = new ApplicationRessourceUsage(res) - this.projectDataLoaded = true - this.generateRandomName() - }) - ) - this.getFlavors(this.selectedProject[1]) - } - - generateRandomName(): void { - const rng: RandomNameGenerator = new RandomNameGenerator() - this.vm_name = rng.randomName() - } - - setSelectedImage(image: Image): void { - this.selectedImage = image - this.isMoshModeAvailable() - this.hasImageResenv() - } - - checkImageAgain(): void { - if (this.selectedImage !== undefined) { - if (this.selectedImage.min_disk > 0) { - if (this.selectedFlavor.rootdisk < this.selectedImage.min_disk) { - this.selectedImage = undefined - } - } - } - } - - isMoshModeAvailable(): void { - for (const mode of this.selectedImage.modes) { - if (mode.name === 'MOSH') { - this.mosh_mode_available = true - - return - } - } - this.mosh_mode_available = false - } - - hasImageResenv(): void { - if (!this.resEnvComponent) { - this.resEnvComponent.unsetOnlyNamespace() - - return - } - for (const mode of this.selectedImage.modes) { - for (const template of this.resEnvComponent.templates) { - if (template.template_name === mode.name) { - this.resenvSelected = true - this.resEnvComponent.setOnlyNamespace(template) - if (!this.resEnvComponent.getUserKeyUrl()) { - this.resEnvComponent.setUserKeyUrl(this.vm_name) - } - - return - } - } - } - this.resenvSelected = false - if (this.resEnvComponent) { - this.resEnvComponent.unsetOnlyNamespace() - if (!this.resEnvComponent.getUserKeyUrl()) { - this.resEnvComponent.setUserKeyUrl(this.vm_name) - } - } - } - - setSelectedFlavor(flavor: Flavor): void { - this.selectedFlavor = flavor - this.newCores = this.selectedFlavor.vcpus - this.newRam = this.selectedFlavor.ram_gib - this.newGpus = this.selectedFlavor.gpu - this.checkImageAgain() - } - - ngOnInit(): void { - this.initializeData() - this.is_vo = is_vo - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } - - ngDoCheck(): void { - if (this.resEnvComponent) { - this.resEnvValid = this.resEnvComponent.isValid() - this.resEnvNeedsName = this.resEnvComponent.needsName() - this.resEnvNeedsTemplate = this.resEnvComponent.needsTemplate() - this.resEnvOkayNeeded = this.resEnvComponent.okayNeeded() - } - } - - hasChosenTools(hasSomeTools: boolean): void { - this.hasTools = hasSomeTools - } - - getTimeoutMinutes(): number { - return Math.ceil(this.timeout / 60) - } - - resetChecks(): void { - this.initial_loaded = false - this.gaveOkay = false - this.hasTools = false - this.newVm = null - this.members_to_add = [] - this.http_allowed = false - this.https_allowed = false - this.udp_allowed = false - this.install_mosh = false - this.vm_responsibility = false - this.client_checked = false - this.playbook_run = 0 - this.has_forc = false - this.forc_url = '' - this.mosh_mode_available = false - this.resenvSelected = false - this.resEnvValid = true - this.resEnvNeedsName = false - this.resEnvNeedsTemplate = false - this.resEnvOkayNeeded = false - this.volumesToMount = [] - this.volumesToAttach = [] - this.started_machine = false - this.showAddVol = false - this.flavors_loaded = false - this.flavors = [] - this.selected_flavor_types = [] - this.flavor_types = {} - this.detached_project_volumes = [] - } - - /** - * Calculates the amount of storage that is used when all volumes which are currently listed will be mounted - * to the machine. - */ - getStorageInList(): number { - if (this.volumesToMount.length === 0) { - return 0 - } else { - let storageInList: number = 0 - - this.volumesToMount.forEach((volume: Volume): void => { - storageInList += volume.volume_storage - }) - - return storageInList - } - } -} diff --git a/src/app/virtualmachines/clustercard/clustercard.component.html b/src/app/virtualmachines/clustercard/clustercard.component.html deleted file mode 100644 index 618a057807..0000000000 --- a/src/app/virtualmachines/clustercard/clustercard.component.html +++ /dev/null @@ -1,64 +0,0 @@ -
-
-
- - -
- {{ cluster?.userlogin }} -
- {{ cluster?.launch_date | date: 'yyyy.MM.dd HH:mm' }} -
-
-
-
-
ID: {{ cluster.cluster_id }}
-
-
-
- Inst: {{ cluster.instances_count }} -
-
-
-
- - Batch {{ batch.index }}: {{ batch.running_worker }}/{{ batch.worker_count }} VMs - active -
-
-
-
- Checking worker count: - -
-
-
-
- Public IP: {{ cluster?.public_ip }} -
-
-
- -
-
diff --git a/src/app/virtualmachines/clustercard/clustercard.component.scss b/src/app/virtualmachines/clustercard/clustercard.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/clustercard/clustercard.component.ts b/src/app/virtualmachines/clustercard/clustercard.component.ts deleted file mode 100644 index 5f68d5d557..0000000000 --- a/src/app/virtualmachines/clustercard/clustercard.component.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' -import { ClipboardService } from 'ngx-clipboard' -import { Subscription } from 'rxjs' -import { BsModalService } from 'ngx-bootstrap/modal' -import { VirtualMachineStates } from '../virtualmachinemodels/virtualmachinestates' -import { VirtualmachineService } from '../../api-connector/virtualmachine.service' -import { ImageService } from '../../api-connector/image.service' -import { Clusterinfo } from '../clusters/clusterinfo' - -import { SharedModal } from '../../shared/shared_modules/baseClass/shared-modal' - -import { CLOUD_PORTAL_SUPPORT_MAIL } from '../../../links/links' - -/** - * Vm card component to be used by vm-overview. Holds information about a virtual machine. - */ -@Component({ - selector: 'app-cluster-card', - templateUrl: 'clustercard.component.html', - styleUrls: ['./clustercard.component.scss'], - providers: [ImageService] -}) -export class ClustercardComponent extends SharedModal implements OnInit, OnDestroy { - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - - /** - * The virtual machine this card is for. - */ - @Input() cluster: Clusterinfo - - /** - * Possible virtual machine states. - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - /** - * Eventemitter when the vm is checked/unchecked. - */ - @Output() check_change_event: EventEmitter = new EventEmitter() - - /** - * Elixir id of the user. - */ - @Input() user_elixir_id: string = '' - - /** - * If the user is a vo admin. - */ - @Input() is_vo_admin: boolean = false - - /** - * If the user is an admin of the group the cluster belongs to. - */ - @Input() is_cluster_admin: boolean = false - - /** - * Subscription objcet to listen to different events. - */ - subscription: Subscription = new Subscription() - - statusSubscription: Subscription = new Subscription() - - /** - * Modal reference to be changed/showed/hidden depending on chosen modal. - */ - // bsModalRef: BsModalRef; - - /** - * Default wait time between status checks if no other value specified. - * @private - */ - private checkStatusTimeout: number = 15000 - - /** - * Default time in ms to show an error message if no other value specified. - */ - ERROR_TIMER: number = 20000 - - /** - * Timeout object to control check status loop (i.e. stopping and starting check status loop). - */ - checkStatusTimer: ReturnType - /** - * Timeout object to control check status loop (i.e. stopping and starting check status loop). - */ - checkWorkerStatusTimer: ReturnType - - all_worker_loaded: boolean = false - - constructor( - private clipboardService: ClipboardService, - modalService: BsModalService, - private virtualmachineservice: VirtualmachineService - ) { - super(modalService) - } - - ngOnInit() { - this.statusSubscription = new Subscription() - - this.check_status_loop() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - this.statusSubscription.unsubscribe() - this.stopAllCheckStatusTimer() - } - - /** - * Stop and clear the check status loop. - */ - stopCheckStatusTimer(): void { - if (this.checkStatusTimer) { - clearTimeout(this.checkStatusTimer) - } - if (this.statusSubscription) { - this.statusSubscription.unsubscribe() - } - } - - /** - * Stop and clear the worker check status loop. - */ - stopCheckWorkerStatusTimer(): void { - if (this.checkWorkerStatusTimer) { - clearTimeout(this.checkWorkerStatusTimer) - } - if (this.statusSubscription) { - this.statusSubscription.unsubscribe() - } - } - - /** - * Stop and clear all check status loop. - */ - stopAllCheckStatusTimer(): void { - this.stopCheckStatusTimer() - this.stopCheckWorkerStatusTimer() - } - - get_all_batches_loaded(): boolean { - let worker_amount: number = 0 - for (const worker_batch of this.cluster.worker_batches) { - worker_amount += worker_batch.worker_count - } - - return this.cluster.worker_instances.length === worker_amount - } - - check_status_loop(): void { - this.all_worker_loaded = this.get_all_batches_loaded() - this.checkStatusTimer = setTimeout((): void => { - this.statusSubscription.add( - this.virtualmachineservice - .getClusterInfo(this.cluster.cluster_id) - .subscribe((updated_cluster: Clusterinfo): void => { - const password: string = this.cluster.password - this.cluster = new Clusterinfo(updated_cluster) - this.cluster.password = password - if ( - this.cluster.status !== VirtualMachineStates.DELETED && - this.cluster.status !== VirtualMachineStates.NOT_FOUND && - this.cluster.status !== VirtualMachineStates.MIGRATED - ) { - this.check_status_loop() - } - }) - ) - }, this.checkStatusTimeout) - } - - /** - * Copy some text to clipboard. - */ - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - /** - * Show message in span that text was copied. - */ - showCopiedMessage(name: string): void { - const span_id: string = `${name}resenvSpan` - const { innerHTML } = document.getElementById(span_id) - document.getElementById(span_id).innerHTML = 'Copied URL!' - setTimeout((): void => { - document.getElementById(span_id).innerHTML = innerHTML - }, 1000) - } -} diff --git a/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.html b/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.html deleted file mode 100644 index cc3c180875..0000000000 --- a/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.html +++ /dev/null @@ -1,572 +0,0 @@ -
-
-
-
Public Key
- -
-
- Info: You need to set a valid SSH Key before you can start a machine. Please set a valid key - below or on your personal data page. -
-
- - - - -
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- New Cluster - - - {{ this.selectedProject[0] }} -
- -
-
-
-
- - -
-
-
-
- - -
-
- - -
- - - -
- The following limit/limits has/have been reached: -
- Amount of VMs
-
- Amount of cores
-
- Amount of RAM
-
- An admin of your project can request more resources if necessary. -
-
-
-
-
- -
-
- Please choose a name
- -
- -
- -
-
-
- -
-
- Please choose your master instance
- This will be the master node of your cluster. Please choose its resources and the image for - all nodes. The master node can not be changed afterwards. -
- -
-
- - -
- Loading flavors ... -
-
-
-
- -
-
- -
- This image will also be used for every worker! -
-
-
-
- - - - - - - -
- Worker Instances [disabled] - - Worker Instances - - - -
- -
- Not enough resources available to start another worker batch with a different flavor! -
- -
- -
- - -
- -
- -
-
-
- - - - -
-
- - -
- Grant access for specific project members of {{ selectedProject[0] }} - -
- - -
-
-
-
-
- - - -
- -
-
-
- - -
-
- You are not allowed to start a machine in this project, as the administrators of the project do not - allow non-administrators to start machines. -

This is the only SimpleVm project you are a member of.

-
-
-
-
- -
- The corresponding client is currently offline. If you have any questions please contact - {{ CLOUD_PORTAL_SUPPORT_MAIL }}. -
-
- - -
-
-
-
- - - diff --git a/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.scss b/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.ts b/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.ts deleted file mode 100644 index 90f09aa8e0..0000000000 --- a/src/app/virtualmachines/clusters/add-cluster/add-cluster.component.ts +++ /dev/null @@ -1,554 +0,0 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core' -import { forkJoin, Subscription } from 'rxjs' -import { Router } from '@angular/router' -import { KeyValue } from '@angular/common' - -import { GroupService } from '../../../api-connector/group.service' -import { ImageService } from '../../../api-connector/image.service' -import { KeyService } from '../../../api-connector/key.service' -import { FlavorService } from '../../../api-connector/flavor.service' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' -import { ApiSettings } from '../../../api-connector/api-settings.service' -import { ClientService } from '../../../api-connector/client.service' -import { UserService } from '../../../api-connector/user.service' -import { VoService } from '../../../api-connector/vo.service' -import { Image } from '../../virtualmachinemodels/image' -import { IResponseTemplate } from '../../../api-connector/response-template' -import { Flavor } from '../../virtualmachinemodels/flavor' -import { Userinfo } from '../../../userinfo/userinfo.model' -import { Client } from '../../../vo_manager/clients/client.model' -import { BiocondaComponent } from '../../conda/bioconda.component' -import { ApplicationRessourceUsage } from '../../../applications/application-ressource-usage/application-ressource-usage' -import { WorkerBatch } from '../clusterinfo' -import { CLOUD_PORTAL_SUPPORT_MAIL, STATUS_LINK } from '../../../../links/links' -import { RandomNameGenerator } from '../../../shared/randomNameGenerator' -import { BiocondaService } from '../../../api-connector/bioconda.service' -import { ApplicationsService } from '../../../api-connector/applications.service' -import { ProjectMember } from '../../../projectmanagement/project_member.model' - -/** - * Cluster Component - */ -@Component({ - selector: 'app-add-cluster', - templateUrl: './add-cluster.component.html', - styleUrls: ['./add-cluster.component.scss'], - providers: [ - GroupService, - ImageService, - KeyService, - FlavorService, - VirtualmachineService, - ApiSettings, - KeyService, - ClientService, - UserService, - VoService, - BiocondaService - ] -}) -export class AddClusterComponent implements OnInit, OnDestroy { - is_vo: boolean = false - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - STATUS_LINK: string = STATUS_LINK - - client_checked: boolean = false - timeout: number = 0 - title: string = 'New Cluster' - - flavors_loaded: boolean = false - - projects_loaded: boolean - - userinfo_loaded: boolean - - create_error: IResponseTemplate - initial_loaded: boolean = false - - /** - * All flavors of a project. - */ - flavors: Flavor[] = [] - - flavors_usable: Flavor[] = [] - selected_flavor_types: Flavor[] = [] - selected_flavor_type: string = 'Standard Flavors' - flavor_types: { [name: string]: Flavor[] } = {} - vm_limit_reached: boolean = false - cores_limit_reached: boolean = false - ram_limit_reached: boolean = false - - cluster_id: string - cluster_error: string - cluster_started: boolean = false - cluster_responsibility: boolean = false - resenv_names: string[] = [] - - /** - * Selected Image. - */ - selectedImage: Image - selectedMasterImage: Image - selectedWorkerBatches: WorkerBatch[] = [new WorkerBatch(1)] - selectedBatch: WorkerBatch = this.selectedWorkerBatches[0] - - maxWorkerInstances: number - - singleProject: boolean = false - cluster_name: string = '' - - /** - * Selected Flavor. - */ - selectedMasterFlavor: Flavor - selectedFlavor: Flavor - selectedWorkerFlavorSet: boolean = false - - workerInstancesCount: number - - /** - * Userinfo from the user. - */ - userinfo: Userinfo - current_key_blocked: boolean = false - - /** - * Selected Project vms client. - */ - selectedProjectClient: Client - - selectedProjectRessources: ApplicationRessourceUsage - - /** - * The selected project ['name',id]. - */ - selectedProject: [string, number] - members_to_add: ProjectMember[] = [] - - /** - * If the client for a project is viable. - */ - client_available: boolean = false - - /** - * If the data for the site is initialized. - * - * @type {boolean} - */ - - /** - * All projects of the user. - * - * @type {any[]} - */ - projects: [string, number][] = [] - - /** - * All projects of the user where the user is allowed to start machines. - * - * @type {any[]} - */ - allowedProjects: [string, number][] = [] - - /** - * If all project data is loaded. - * - * @type {boolean} - */ - projectDataLoaded: boolean = false - - selectedProjectIsMigrated: boolean = false - - newCores: number = 0 - newRam: number = 0 - newVms: number = 2 - newGpus: number = 0 - subscription: Subscription = new Subscription() - - @ViewChild('bioconda', { static: true }) biocondaComponent: BiocondaComponent - - constructor( - private groupService: GroupService, - private imageService: ImageService, - private flavorService: FlavorService, - private virtualmachineservice: VirtualmachineService, - private keyservice: KeyService, - private userService: UserService, - private voService: VoService, - private router: Router, - private applicationsService: ApplicationsService, - private condaService: BiocondaService, - private cdRef: ChangeDetectorRef - ) {} - - calcWorkerInstancesCount(): void { - let count: number = 0 - this.selectedWorkerBatches.forEach((batch: WorkerBatch): void => { - batch.valid_batch = batch.worker_count <= batch.max_worker_count && batch.worker_count > 0 - count += batch.worker_count - }) - this.workerInstancesCount = count - this.newVms = this.workerInstancesCount + 1 - } - - setCurrentKeyBlocked(value: boolean): void { - this.current_key_blocked = value - } - - changeCount(): void { - this.calcWorkerInstancesCount() - this.calculateNewValues() - } - - checkFlavorsUsableForCluster(): void { - const used_flavors: Flavor[] = [] - - // tslint:disable-next-line:no-for-each-push - this.selectedWorkerBatches.forEach((batch: WorkerBatch): void => { - if (batch !== this.selectedBatch) { - used_flavors.push(batch.flavor) - } - }) - const flavors_to_filter: Flavor[] = this.flavors.filter( - (flavor: Flavor): boolean => used_flavors.indexOf(flavor) < 0 - ) - this.flavors_usable = flavors_to_filter.filter((flav: Flavor): boolean => - this.selectedProjectRessources.filterFlavorsTest(flav, this.selectedWorkerBatches) - ) - this.flavor_types = this.flavorService.sortFlavors(this.flavors_usable) - - this.flavors_loaded = true - this.initial_loaded = true - } - - calcMaxWorkerInstancesByFlavor(): void { - if (this.selectedBatch.flavor) { - this.selectedBatch.max_worker_count = this.selectedProjectRessources.calcMaxWorkerInstancesByFlavor( - this.selectedMasterFlavor, - this.selectedBatch, - this.selectedWorkerBatches - ) - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - unsorted(a: KeyValue, b: KeyValue): number { - return 0 - } - - setSelectedFlavorType(key: string): void { - this.selected_flavor_type = key - } - - calculateNewValues(): void { - let tmp_ram: number = 0 - let tmp_cores: number = 0 - let tmp_gpus: number = 0 - if (this.selectedMasterFlavor) { - tmp_ram += this.selectedMasterFlavor.ram_gib - tmp_cores += this.selectedMasterFlavor.vcpus - tmp_gpus += this.selectedMasterFlavor.gpu - } - if (this.selectedWorkerBatches) { - this.selectedWorkerBatches.forEach((batch: WorkerBatch): void => { - if (batch.worker_count && batch.flavor) { - tmp_ram += batch.flavor.ram_gib * batch.worker_count - tmp_cores += batch.flavor.vcpus * batch.worker_count - tmp_gpus += batch.flavor.gpu * batch.worker_count - } - }) - } - - this.newRam = tmp_ram - this.newCores = tmp_cores - this.newGpus = tmp_gpus - } - - generateRandomName(): void { - const rng: RandomNameGenerator = new RandomNameGenerator() - this.cluster_name = `${rng.randomName()}Cluster` - } - - /** - * Get flavors for the project. - * - * @param project_id - */ - getFlavors(project_id: number): void { - this.subscription.add( - this.flavorService.getFlavors(project_id).subscribe( - (flavors: Flavor[]): void => { - this.flavors = flavors - this.checkFlavorsUsableForCluster() - }, - (error: any) => { - console.log(error) - this.flavors = [] - this.flavors_usable = [] - this.flavors_loaded = true - this.initial_loaded = true - } - ) - ) - } - - reloadFlavors(): void { - this.flavors_loaded = false - this.selectedMasterFlavor = undefined - this.selectedFlavor = undefined - this.getFlavors(this.selectedProject[1]) - } - - /** - * Validate the public key of the user. - */ - validatePublicKey(): boolean { - return /ssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3}( [^@]+@[^@]+)?/.test(this.userinfo.PublicKey) - } - - resetBatches(): void { - this.selectedWorkerBatches = [new WorkerBatch(1)] - this.selectedBatch = this.selectedWorkerBatches[0] - this.setBatchUsableFlavors() - } - - setBatchUsableFlavors(): void { - const used_flavors: Flavor[] = [] - - // tslint:disable-next-line:no-for-each-push - this.selectedWorkerBatches.forEach((existingBatch: WorkerBatch): void => { - if (existingBatch !== this.selectedBatch) { - used_flavors.push(existingBatch.flavor) - } - }) - const flavors_to_filter: Flavor[] = this.flavors.filter( - (flavor: Flavor): boolean => used_flavors.indexOf(flavor) < 0 - ) - - this.selectedBatch.usable_flavors = flavors_to_filter.filter((flav: Flavor): boolean => - this.selectedProjectRessources.filterFlavorsTest(flav, this.selectedWorkerBatches, this.selectedMasterFlavor) - ) - } - - setSelectedBatch(batch: WorkerBatch): void { - this.selectedBatch = batch - this.checkFlavorsUsableForCluster() - this.setBatchUsableFlavors() - this.calcWorkerInstancesCount() - this.calculateNewValues() - this.calcMaxWorkerInstancesByFlavor() - this.setBatchUsableFlavors() - } - - addBatch(): void { - this.selectedWorkerFlavorSet = false - this.selectedBatch = null - const newBatch: WorkerBatch = new WorkerBatch( - this.selectedWorkerBatches[this.selectedWorkerBatches.length - 1].index + 1 - ) - this.selectedBatch = newBatch - this.selectedWorkerBatches.push(this.selectedBatch) - this.setBatchUsableFlavors() - this.selectedBatch.image = this.selectedMasterImage - this.maxWorkerInstances = null - } - - removeBatch(batch: WorkerBatch): void { - const idx: number = this.selectedWorkerBatches.indexOf(batch) - if (batch === this.selectedBatch) { - for (let i = idx; i < this.selectedWorkerBatches.length; i++) { - this.selectedWorkerBatches[i].index -= 1 - } - if (idx !== 0) { - this.selectedBatch = this.selectedWorkerBatches[idx - 1] - this.selectedWorkerFlavorSet = true - } else if (idx === 0 && this.selectedWorkerBatches.length > 0) { - this.selectedBatch = this.selectedWorkerBatches[idx + 1] - } - } - - this.selectedWorkerBatches.splice(idx, 1) - - this.checkFlavorsUsableForCluster() - this.setBatchUsableFlavors() - this.calcWorkerInstancesCount() - this.calculateNewValues() - this.calcMaxWorkerInstancesByFlavor() - } - - startCluster(): void { - this.cluster_error = null - this.cluster_id = null - - // not needed anymore when using body directly in POST request - // const masterFlavor: string = this.selectedMasterFlavor.name.replace(re, '%2B'); - const additional_elixir_ids: string[] = this.members_to_add.map((mem: ProjectMember): string => mem.elixirId) - - this.subscription.add( - this.virtualmachineservice - .startCluster( - this.selectedMasterFlavor.name, - this.selectedMasterImage, - this.selectedWorkerBatches, - this.selectedProject[1], - this.cluster_name, - additional_elixir_ids - ) - .subscribe( - (res: any): void => { - if (res['status'] && res['status'] === 'mutex_locked') { - setTimeout((): void => { - this.startCluster() - }, 1000) - } else { - this.cluster_id = res['id'] - this.cluster_started = true - - setTimeout((): void => { - void this.router.navigate(['/virtualmachines/clusterOverview']).then().catch() - }, 4000) - } - }, - (error: any): void => { - console.log(error) - if (error['error']['error']) { - this.cluster_error = error['error']['error'] - } else { - this.cluster_error = error - } - setTimeout((): void => { - void this.router.navigate(['/virtualmachines/clusterOverview']).then().catch() - }, 4000) - } - ) - ) - } - - /** - * Get the client from the selected project. - * If connected geht vm,volumes etc. - */ - getSelectedProjectClient(): void { - this.client_checked = false - this.projectDataLoaded = false - - this.subscription.unsubscribe() - this.subscription = new Subscription() - this.subscription.add( - this.applicationsService - .getApplicationMigratedByGroupId(this.selectedProject[1].toString()) - .subscribe((migrated: boolean): void => { - this.selectedProjectIsMigrated = migrated - }) - ) - this.subscription.add( - this.groupService.getClientBibigrid(this.selectedProject[1].toString()).subscribe((client: Client): void => { - if (client.status && client.status === 'Connected') { - this.client_available = true - - this.loadProjectData() - this.client_checked = true - } else { - this.client_available = false - this.client_checked = true - this.projectDataLoaded = true - } - this.selectedProjectClient = client - }) - ) - } - - /** - * Initializes the data. - * Gets all groups of the user and their key. - */ - initializeData(): void { - this.subscription.add( - forkJoin([ - this.groupService.getSimpleVmAllowedByUserWithClusterAllowed(), - this.groupService.getSimpleVmByUserWithClusterAllowed(), - this.userService.getUserInfo() - ]).subscribe((result: any): void => { - this.userinfo = result[2] - this.userinfo_loaded = true - this.validatePublicKey() - const allowedMemberGroups: any = result[0] - const membergroups: any = result[1] - for (const project of membergroups) { - this.projects.push(project) - } - for (const project of allowedMemberGroups) { - this.allowedProjects.push(project) - } - this.projects_loaded = true - if (this.allowedProjects.length === 1) { - this.selectedProject = this.allowedProjects[0] - this.singleProject = true - this.getSelectedProjectClient() - } - }) - ) - } - - loadProjectData(): void { - this.initial_loaded = false - this.projectDataLoaded = false - this.flavors = [] - this.flavors_loaded = false - this.selectedImage = undefined - this.selectedFlavor = undefined - this.subscription.add( - this.groupService - .getGroupResources(this.selectedProject[1].toString()) - .subscribe((res: ApplicationRessourceUsage): void => { - this.selectedProjectRessources = new ApplicationRessourceUsage(res) - this.getFlavors(this.selectedProject[1]) - this.checkResources() - this.projectDataLoaded = true - }) - ) - } - - checkResources(): void { - this.newCores = 0 - this.newRam = 0 - this.newVms = 2 - this.newGpus = 0 - this.vm_limit_reached = this.selectedProjectRessources.used_vms + 2 > this.selectedProjectRessources.number_vms - this.cores_limit_reached = this.selectedProjectRessources.cores_used >= this.selectedProjectRessources.cores_total - this.ram_limit_reached = this.selectedProjectRessources.ram_used >= this.selectedProjectRessources.ram_total - } - - resizeFix(): void { - window.dispatchEvent(new Event('resize')) - } - - ngOnInit(): void { - this.initializeData() - this.generateRandomName() - this.subscription.add( - this.voService.isVo().subscribe((result: IResponseTemplate): void => { - this.is_vo = result.value as boolean - }) - ) - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } - - setMasterFlavor(flavor: Flavor): void { - this.selectedMasterFlavor = flavor - this.checkImageAgain() - } - - checkImageAgain(): void { - if (this.selectedMasterImage !== undefined) { - if (this.selectedMasterImage.min_disk > 0) { - if (this.selectedMasterFlavor.rootdisk < this.selectedMasterImage.min_disk) { - this.selectedMasterImage = undefined - } - } - } - } -} diff --git a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.html b/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.html deleted file mode 100644 index 6dcda89b3f..0000000000 --- a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.html +++ /dev/null @@ -1,173 +0,0 @@ -
-
- - - - -
- - Stop -
- - - - -
-
-
- You are not able to control this instance via this platform as it is part of a migrated project! You can - access the new platform here: - {{ - NEW_SVM_PORTAL_LINK - }} -
-
-
-
-
- diff --git a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.scss b/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.spec.ts b/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.spec.ts deleted file mode 100644 index 5bb16fd082..0000000000 --- a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing' - -import { ClusterActionsComponent } from './cluster-actions.component' - -describe('ClusterActionsComponent', () => { - let component: ClusterActionsComponent - let fixture: ComponentFixture - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [ClusterActionsComponent] - }) - fixture = TestBed.createComponent(ClusterActionsComponent) - component = fixture.componentInstance - fixture.detectChanges() - }) - - it('should create', () => { - expect(component).toBeTruthy() - }) -}) diff --git a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.ts b/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.ts deleted file mode 100644 index e9fb47ec71..0000000000 --- a/src/app/virtualmachines/clusters/cluster-actions/cluster-actions.component.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core' -import { ClipboardService } from 'ngx-clipboard' -import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal' -import { Subscription } from 'rxjs' -import { CLOUD_PORTAL_SUPPORT_MAIL, NEW_SVM_PORTAL_LINK } from '../../../../links/links' -import { Clusterinfo, WorkerBatch } from '../clusterinfo' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { ResumeClusterComponent } from '../../modals/resume-cluster/resume-cluster.component' -import { StopClusterComponent } from '../../modals/stop-cluster/stop-cluster.component' -import { DeleteClusterComponent } from '../../modals/delete-cluster/delete-cluster.component' -import { RenameClusterComponent } from '../../modals/rename-cluster/rename-cluster.component' -import { PasswordClusterComponent } from '../../modals/password-cluster/password-cluster.component' -import { ScaleClusterComponent } from '../../modals/scale-cluster/scale-cluster.component' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' -import { NotificationModalComponent } from '../../../shared/modal/notification-modal' - -@Component({ - selector: 'app-cluster-actions', - templateUrl: './cluster-actions.component.html', - styleUrls: ['./cluster-actions.component.scss'] -}) -export class ClusterActionsComponent implements OnDestroy { - @Input() cluster: Clusterinfo - bsModalRef: BsModalRef - subscription: Subscription = new Subscription() - SCALE_UP: string = 'scale_up' - SCALE_DOWN: string = 'scale_down' - SCALE_SUCCESS: string = 'scale_success' - show_connection_info: boolean = false - - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - @Output() readonly stopStatusLoop: EventEmitter = new EventEmitter() - @Output() readonly startStatusLoop: EventEmitter = new EventEmitter() - - protected readonly CLOUD_PORTAL_SUPPORT_MAIL = CLOUD_PORTAL_SUPPORT_MAIL - - constructor( - private clipboardService: ClipboardService, - private modalService: BsModalService, - private virtualmachineservice: VirtualmachineService - ) {} - - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - ngOnDestroy() { - this.subscription.unsubscribe() - // this.statusSubscription.unsubscribe(); - // this.stopAllCheckStatusTimer(); - } - - showResumeModal(): void { - const initialState = { cluster: this.cluster } - - this.bsModalRef = this.modalService.show(ResumeClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Show Cluster Stop modal - */ - showStopModal(): void { - const initialState = { cluster: this.cluster } - - this.bsModalRef = this.modalService.show(StopClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - showDeleteModal(): void { - // this.stopAllCheckStatusTimer(); - // const all_loaded: boolean = this.get_all_batches_loaded(); - const initialState = { cluster: this.cluster } - - this.bsModalRef = this.modalService.show(DeleteClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Show rename modal - */ - showRenameModal(): void { - // this.stopAllCheckStatusTimer(); - // const all_loaded: boolean = this.get_all_batches_loaded(); - const initialState = { cluster: this.cluster } - - this.bsModalRef = this.modalService.show(RenameClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - showPasswordModal(): void { - // this.stopCheckStatusTimer(); - const initialState = { cluster: this.cluster } - - this.bsModalRef = this.modalService.show(PasswordClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - showScaleModal(mode: string, msg?: string): void { - this.hideCurrentModal() - // this.stopCheckStatusTimer(); - const initialState = { cluster: this.cluster, mode, msg } - this.bsModalRef = this.modalService.show(ScaleClusterComponent, { initialState }) - this.bsModalRef.setClass('modal-xl') - this.subscribeToBsModalRef() - } - - hideCurrentModal() { - if (this.bsModalRef) { - this.modalService.hide(this.bsModalRef.id) - } - } - - stopCluster(): void { - this.stopStatusLoop.emit() - - this.cluster.status = VirtualMachineStates.POWERING_OFF - this.subscription.add( - this.virtualmachineservice.stopCluster(this.cluster.cluster_id).subscribe((): void => { - this.cluster.status = VirtualMachineStates.POWERING_OFF - this.startStatusLoop.emit() - }) - ) - } - - renameCluster(name: string): void { - this.stopStatusLoop.emit() - - this.subscription.add( - this.virtualmachineservice.renameCluster(this.cluster.cluster_id, name).subscribe((cl: Clusterinfo): void => { - this.cluster.name = cl.name - this.startStatusLoop.emit() - }) - ) - } - - deleteCluster(): void { - this.stopStatusLoop.emit() - - this.cluster.status = VirtualMachineStates.DELETING - this.subscription.add( - this.virtualmachineservice.deleteCluster(this.cluster.cluster_id).subscribe((): void => { - this.cluster.status = VirtualMachineStates.DELETED - this.startStatusLoop.emit() - }) - ) - } - - resumeCluster(): void { - this.stopStatusLoop.emit() - this.cluster.status = VirtualMachineStates.POWERING_ON - this.subscription.add( - this.virtualmachineservice.resumeCluster(this.cluster.cluster_id).subscribe((): void => { - this.startStatusLoop.emit() - }) - ) - } - - showNotificationModal( - notificationModalTitle: string, - notificationModalMessage: string, - notificationModalType: string - ) { - const initialState = { notificationModalTitle, notificationModalType, notificationModalMessage } - if (this.bsModalRef) { - this.bsModalRef.hide() - } - - this.bsModalRef = this.modalService.show(NotificationModalComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - } - - scaleDownCluster(cluster: Clusterinfo): void { - this.stopStatusLoop.emit() - - this.cluster = cluster - let scale_down_count: number = 0 - - const scale_down_batches: any = [] - this.cluster.worker_batches.forEach((batch: WorkerBatch): void => { - if (batch.delete_count > 0) { - scale_down_batches.push({ worker_flavor_name: batch.flavor.name, downscale_count: batch.delete_count }) - scale_down_count += batch.delete_count - } - }) - let msg: string = 'Scaling Down Batches: ' - for (const batch of scale_down_batches) { - msg += ` \n[Batch with Flavor ${batch.worker_flavor_name} by ${batch.downscale_count} instances ]` - } - this.showNotificationModal('Scaling Down', msg, 'info') - - this.subscription.add( - this.virtualmachineservice - .scaleDownCluster(this.cluster.cluster_id, scale_down_batches) - .subscribe((res: any): void => { - this.cluster.password = res['password'] - - this.cluster.setScaleDownBatchesCount() - - this.cluster.instances_count -= scale_down_count - this.startStatusLoop.emit() - this.showScaleModal(this.SCALE_SUCCESS, 'Successfully Scaled Down!') - }) - ) - } - - scaleUpCluster(selectedBatch: WorkerBatch): void { - this.stopStatusLoop.emit() - - const scale_up_count: number = selectedBatch.upscale_count - this.showNotificationModal('Upscaling Cluster', `Starting ${scale_up_count} additional workers..`, 'info') - - this.subscription.add( - this.virtualmachineservice - .scaleCluster( - this.cluster.cluster_id, - encodeURIComponent(selectedBatch.flavor.name), - selectedBatch.upscale_count - ) - .subscribe((res: any): void => { - selectedBatch.setNewScalingUpWorkerCount() - this.cluster.password = res['password'] - this.startStatusLoop.emit() - - this.showScaleModal( - this.SCALE_SUCCESS, - `The start of ${scale_up_count} workers was successfully initiated. Remember to configure your cluster after the machines are active!'` - ) - }) - ) - } - - subscribeToBsModalRef(): void { - this.subscription.add( - this.bsModalRef.content.event.subscribe((result: any) => { - if ('new_name' in result) { - this.renameCluster(result['new_name']) - } else if ('deleteCluster' in result) { - this.deleteCluster() - } else if ('scaleDownCluster' in result) { - this.scaleDownCluster(result['cluster']) - } else if ('scaleUpCluster' in result) { - this.scaleUpCluster(result['selectedBatch']) - } else if ('resumeCluster' in result) { - this.resumeCluster() - } else if ('stopCluster' in result) { - this.stopCluster() - } else { - // this.check_status_loop(); - } - }) - ) - } - - protected readonly NEW_SVM_PORTAL_LINK = NEW_SVM_PORTAL_LINK -} diff --git a/src/app/virtualmachines/clusters/clusterPage.model.ts b/src/app/virtualmachines/clusters/clusterPage.model.ts deleted file mode 100644 index 53d92ad75f..0000000000 --- a/src/app/virtualmachines/clusters/clusterPage.model.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Clusterinfo } from './clusterinfo'; - -export class ClusterPage { - cluster_list: Clusterinfo[]; - total_pages: number = 0; - total_items: number = 0; - items_per_page: number = 7; - num_pages: number = 0; - cluster_status_error: boolean = false; - - constructor(cluster_page?: Partial) { - Object.assign(this, cluster_page); - this.cluster_list = []; - if (cluster_page) { - for (const cluster of cluster_page.cluster_list) { - this.cluster_list.push(new Clusterinfo(cluster)); - } - if (cluster_page.num_pages) { - this.total_pages = cluster_page.num_pages; - } - if (cluster_page.total_pages) { - this.num_pages = cluster_page.total_pages; - } - this.cluster_status_error = cluster_page.cluster_status_error; - } - } -} diff --git a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.html b/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.html deleted file mode 100644 index 96179939f5..0000000000 --- a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.html +++ /dev/null @@ -1,177 +0,0 @@ -
- The Cluster could not be found. -
- -
- -
-
-
- Cluster: {{ cluster?.name }} - [ID: {{ cluster?.cluster_id }} ] -
-
- -
- Connect Information -
-
-
-
-
- via
- {{ mode.name }} -
-
-
-
- with
- -
-
-
-
- Copy Command -
-
-
-
-
-

- Learn more about persistent terminal sessions when using ssh: - Tutorial -

-
-
-
-
- Research Environment: -
-
- {{ - cluster.master_instance?.res_env_url - }} -
- For RStudio credentials please visit: - {{ WIKI_RSTUDIO_LINK }} -
- For Apache Guacamole credentials please visit: - {{ - WIKI_GUACAMOLE_LINK - }} -
-
-
-
-
-
- The detailed cluster information cannot be loaded right now. It is possible that the facility on which your - cluster is running cannot be reached at the moment. Please check our - status overview -
- -
-
Actions
- -
-
- -
-
Master Instance
- -
-
- Instance: {{ cluster?.master_instance.name }} - -
- -
-
-
-
Worker Instances
- -
-
- Instance: {{ worker.name }} - -
- -
- -
-
-
-
-
- - - diff --git a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.scss b/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.scss deleted file mode 100644 index 3c80c5e51c..0000000000 --- a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.scss +++ /dev/null @@ -1,25 +0,0 @@ -.dot { - height: 25px; - width: 25px; - background-color: #bbb; - border-radius: 50%; - display: inline-block; - -} - -.dot-colorless { - height: 10px; - width: 10px; - border-radius: 50%; - display: inline-block; -} - -.pulseAnim { - border-radius: 50%; - cursor: pointer; - background: rgb(77, 189, 116); - box-shadow: 0 0 0 rgba(77, 189, 116, 0.4); - -moz-animation: pulse 2s infinite; - -webkit-animation: pulse 2s infinite; - animation: pulse 2s infinite; -} diff --git a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.ts b/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.ts deleted file mode 100644 index c6e963d280..0000000000 --- a/src/app/virtualmachines/clusters/clusterdetail/clusterdetail.component.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { Component, OnDestroy, OnInit } from '@angular/core' -import { ActivatedRoute } from '@angular/router' -import { Subscription } from 'rxjs' -import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal' -import { ClipboardService } from 'ngx-clipboard' - -import { Clusterinfo } from '../clusterinfo' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { - STATUS_LINK, - WIKI_GUACAMOLE_LINK, - WIKI_RSTUDIO_LINK, - WIKI_VOLUME_OVERVIEW, - WIKI_PERSISTENT_TERMINAL_LINK -} from '../../../../links/links' -import { DeleteVmComponent } from '../../modals/delete-vm/delete-vm.component' -import { TemplateNames } from '../../conda/template-names' - -/** - * Clusterdetail component. - */ -@Component({ - selector: 'app-clusterdetail', - templateUrl: './clusterdetail.component.html', - styleUrls: ['./clusterdetail.component.scss'], - providers: [VirtualmachineService] -}) -export class ClusterdetailComponent implements OnInit, OnDestroy { - WIKI_RSTUDIO_LINK: string = WIKI_RSTUDIO_LINK - WIKI_GUACAMOLE_LINK: string = WIKI_GUACAMOLE_LINK - WIKI_VOLUME_OVERVIEW: string = WIKI_VOLUME_OVERVIEW - - WIKI_PERSISTENT_TERMINAL_LINK: string = WIKI_PERSISTENT_TERMINAL_LINK - virtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - cluster_id: string - cluster: Clusterinfo - isLoaded: boolean = false - notFoundCluster: boolean = false - checkStatusTimeout: number = 5000 - subscription: Subscription = new Subscription() - errorOnLoading = false - STATUS_LINK: string = STATUS_LINK - bsModalRef: BsModalRef - all_worker_loaded: boolean = false - checkStatusTimer: ReturnType - - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - statusSubscription: Subscription = new Subscription() - - constructor( - private activatedRoute: ActivatedRoute, - private virtualmachineService: VirtualmachineService, - private modalService: BsModalService, - private clipboardService: ClipboardService - ) { - this.activatedRoute = activatedRoute - this.virtualmachineService = virtualmachineService - } - - ngOnInit(): void { - this.activatedRoute.params.subscribe((paramsId: any): void => { - this.cluster_id = paramsId.id - this.setClusterById() - }) - } - - resenv_by_play(vm: VirtualMachine): boolean { - for (const mode of vm.modes) { - if (TemplateNames.ALL_TEMPLATE_NAMES.indexOf(mode.name) !== -1) { - return false - } - } - - return true - } - - deleteCluster(): void { - this.virtualmachineService.deleteCluster(this.cluster_id).subscribe((): void => { - this.cluster.status = 'Deleted' - this.cluster.master_instance.status = VirtualMachineStates.DELETED - this.cluster.worker_instances.forEach((vm: VirtualMachine): void => { - vm.status = VirtualMachineStates.DELETED - }) - }) - } - - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - setClusterById(): void { - this.virtualmachineService.getClusterInfo(this.cluster_id).subscribe( - (cluster_info: Clusterinfo): void => { - this.cluster = new Clusterinfo(cluster_info) - this.isLoaded = true - this.check_status_loop() - this.check_status_loop_cluster_vms() - }, - () => { - this.errorOnLoading = true - this.isLoaded = true - } - ) - } - - check_status_loop_vm(vm: VirtualMachine, final_state: string = VirtualMachineStates.ACTIVE): void { - setTimeout( - (): void => { - this.subscription.add( - this.virtualmachineService - .checkVmStatus(vm.openstackid, vm.name) - .subscribe((updated_vm: VirtualMachine): void => { - updated_vm = new VirtualMachine(updated_vm) - // tslint:disable-next-line:triple-equals - if (vm !== undefined) { - this.cluster.worker_instances[this.cluster.worker_instances.indexOf(vm)] = updated_vm - if (VirtualMachineStates.IN_PROCESS_STATES.indexOf(updated_vm.status) !== -1) { - this.check_status_loop_vm(updated_vm, final_state) - } else if (updated_vm.status === VirtualMachineStates.MIGRATED) { - // do nothing - } else if (VirtualMachineStates.NOT_IN_PROCESS_STATES.indexOf(updated_vm.status) !== -1) { - if (final_state && updated_vm.status !== final_state) { - this.check_status_loop_vm(updated_vm, final_state) - } else { - this.check_status_loop_vm(updated_vm, final_state) - } - } - } - }) - ) - }, - - this.checkStatusTimeout - ) - } - - get_all_batches_loaded(): boolean { - let worker_amount: number = 0 - for (const worker_batch of this.cluster.worker_batches) { - worker_amount += worker_batch.worker_count - } - - return this.cluster.worker_instances.length === worker_amount - } - - stopAllCheckStatusTimer(): void { - this.stopCheckStatusTimer() - } - - stopCheckStatusTimer(): void { - if (this.checkStatusTimer) { - clearTimeout(this.checkStatusTimer) - } - if (this.statusSubscription) { - this.statusSubscription.unsubscribe() - } - } - - /** - * Stop and clear the worker check status loop. - */ - - check_status_loop(): void { - this.all_worker_loaded = this.get_all_batches_loaded() - this.stopAllCheckStatusTimer() - this.statusSubscription = new Subscription() - this.checkStatusTimer = setTimeout((): void => { - this.statusSubscription.add( - this.virtualmachineService - .getClusterInfo(this.cluster.cluster_id) - .subscribe((updated_cluster: Clusterinfo): void => { - const password: string = this.cluster.password - this.cluster = new Clusterinfo(updated_cluster) - this.cluster.password = password - if ( - this.cluster.status !== VirtualMachineStates.DELETED || - this.cluster.status !== VirtualMachineStates.MIGRATED - ) { - this.check_status_loop() - this.check_status_loop_cluster_vms() - } - }) - ) - }, this.checkStatusTimeout) - } - - check_status_loop_cluster_vms(): void { - this.cluster.worker_instances.forEach((vm: VirtualMachine): void => { - if ( - vm.status !== VirtualMachineStates.ACTIVE && - VirtualMachineStates.NOT_IN_PROCESS_STATES.indexOf(vm.status) === -1 - ) { - this.check_status_loop_vm(vm) - } - }) - } - - ngOnDestroy(): void { - this.subscription.unsubscribe() - } - - showDeleteModal(worker: VirtualMachine): void { - const initialState = { virtualMachine: worker, clusterWorker: true } - - this.bsModalRef = this.modalService.show(DeleteVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - subscribeToBsModalRef(): void { - this.subscription.add( - this.bsModalRef.content.event.subscribe((result: any) => { - if ('deleteVM' in result) { - this.deleteVM(result['worker']) - } - }) - ) - } - - deleteVM(worker: VirtualMachine): void { - this.setInstanceStatus(worker, VirtualMachineStates.DELETING) - this.subscription.add( - this.virtualmachineService.deleteVM(worker.openstackid).subscribe((updated_vm: VirtualMachine): void => { - if (updated_vm.status !== VirtualMachineStates.DELETED) { - setTimeout((): void => { - this.deleteVM(worker) - }, this.checkStatusTimeout) - } else { - this.removeInstance(worker) - } - }) - ) - } - - removeInstance(worker: VirtualMachine): void { - const worker_instances: VirtualMachine[] = [] - for (const vm of this.cluster.worker_instances) { - if (vm.openstackid === worker.openstackid) { - continue - } - worker_instances.push(vm) - } - this.cluster.worker_instances = worker_instances - } - - setInstanceStatus(worker: VirtualMachine, status: string): void { - const worker_instances: VirtualMachine[] = [] - for (const vm of this.cluster.worker_instances) { - if (vm.openstackid === worker.openstackid) { - vm.status = status - } - worker_instances.push(vm) - } - this.cluster.worker_instances = worker_instances - } -} diff --git a/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.html b/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.html deleted file mode 100644 index 930d251bc7..0000000000 --- a/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.html +++ /dev/null @@ -1,34 +0,0 @@ -
-
- - -
-
-
- Created at (y-m-d)
- {{cluster?.launch_date | date: 'yyyy.MM.dd HH:mm'}} -
-
-
- -
-
-
- Created by
- {{cluster?.userlogin}} -
-
-
-
-
-
- Public IP
- {{cluster?.public_ip}} -
-
-
diff --git a/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.ts b/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.ts deleted file mode 100644 index 09cb19c5c7..0000000000 --- a/src/app/virtualmachines/clusters/clusterinfo/clusterinfo.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Component, Input } from '@angular/core' -import { Clusterinfo } from '../clusterinfo' - -/** - * Clusterinfo component - */ -@Component({ - selector: 'app-clusterinfo', - templateUrl: './clusterinfo.component.html' -}) -export class ClusterinfoComponent { - @Input() cluster: Clusterinfo -} diff --git a/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.html b/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.html deleted file mode 100644 index fc2981e50a..0000000000 --- a/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.html +++ /dev/null @@ -1,200 +0,0 @@ -
-
-
-
-
- - - - -
-
- -
-
-
-
- - -
-
-
- - -
-
- -
- Clusters per page -
-
-
- -
-
-
-
-
-
-
-
- - {{ ClusterStates.staticRUNNING }} -
-
- - {{ ClusterStates.staticCONFIGURING }} -
-
- - {{ VirtualMachineStates.staticSHUTOFF }} -
-
- - {{ ClusterStates.staticCREATING }} -
-
- - {{ VirtualMachineStates.staticDELETED }} -
-
- - - {{ ClusterStates.staticError }} -
-
-
- -
-
- -
-
-
- -
- There are no clusters available! -
-
-
-
-
-
-
Cluster ID
-
Project
-
Created (by/at)
-
-
-
-
-
-
- An error occurred while checking the cluster statuses. It is possible that the facility where one of your - clusters is running is not accessible. Please check our - status overview for this. -
-
-
- - -
-
-
-
-
diff --git a/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.ts b/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.ts deleted file mode 100644 index f755999e3f..0000000000 --- a/src/app/virtualmachines/clusters/clusteroverview/clusterOverview.component.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { Component, OnDestroy, OnInit } from '@angular/core' -import { debounceTime, distinctUntilChanged } from 'rxjs/operators' -import { Subject, Subscription } from 'rxjs' -import { UntypedFormBuilder } from '@angular/forms' -import { ClipboardService } from 'ngx-clipboard' - -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' -import { FullLayoutComponent } from '../../../layouts/full-layout.component' -import { UserService } from '../../../api-connector/user.service' -import { ImageService } from '../../../api-connector/image.service' -import { FacilityService } from '../../../api-connector/facility.service' -import { elixir_id, is_vo } from '../../../shared/globalvar' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { GroupService } from '../../../api-connector/group.service' -import { ClientService } from '../../../api-connector/client.service' -import { Clusterinfo } from '../clusterinfo' -import { CLOUD_PORTAL_SUPPORT_MAIL, SCALE_SCRIPT_LINK, STATUS_LINK } from '../../../../links/links' -import { AbstractBaseClass } from '../../../shared/shared_modules/baseClass/abstract-base-class' -import { Flavor } from '../../virtualmachinemodels/flavor' -import { FlavorService } from '../../../api-connector/flavor.service' -import { ClusterPage } from '../clusterPage.model' -import { Clusterstates } from '../clusterstatus/clusterstates' -import { ApplicationsService } from '../../../api-connector/applications.service' - -export const SCALING_SCRIPT_NAME: string = 'scaling.py' - -/** - * Cluster overview componentn. - */ -@Component({ - selector: 'app-cluster-overview', - templateUrl: './clusterOverview.component.html', - styleUrls: ['../../vmOverview.component.scss'], - providers: [ - FacilityService, - ImageService, - UserService, - VirtualmachineService, - FullLayoutComponent, - GroupService, - ClientService, - GroupService, - FlavorService - ] -}) -export class ClusterOverviewComponent extends AbstractBaseClass implements OnInit, OnDestroy { - title: string = 'Cluster Overview' - - private subscription: Subscription = new Subscription() - - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - ClusterStates: Clusterstates = new Clusterstates() - - cluster_page: ClusterPage = new ClusterPage() - currentPage: number = 1 - DEBOUNCE_TIME: number = 300 - FILTER_DEBOUNCE_TIME: number = 2000 - SCALING_SCRIPT_LINK: string = SCALE_SCRIPT_LINK - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - STATUS_LINK: string = STATUS_LINK - user_elixir_id: string = elixir_id - - isSearching: boolean = true - - /** - * Facilities where the user is manager ['name',id]. - */ - public managerFacilities: [string, number][] - /** - * Chosen facility. - */ - public selectedFacility: [string, number] - - filter: string - cluster_per_site: number = 7 - total_pages: number - total_items: number - clusters: Clusterinfo[] = [] - /** - * If user is vo admin. - */ - - items_per_page: number = 7 - - is_vo_admin: boolean - flavors: Flavor[] = [] - flavors_usable: Flavor[] = [] - flavors_loaded: boolean = false - - /** - * Tab which is shown own|all. - * - * @type {string} - */ - tab: string = 'own' - - is_facility_manager: boolean = false - - clusterPerPageChange: Subject = new Subject() - - filterChanged: Subject = new Subject() - filter_status_list: string[] = [ - Clusterstates.RUNNING, - Clusterstates.CREATING, - Clusterstates.CONFIGURING, - Clusterstates.ERROR, - VirtualMachineStates.SHUTOFF - ] - - migratedProjectIds: string[] = [] - migratedProjectNames: string[] = [] - - constructor( - private facilityService: FacilityService, - private groupService: GroupService, - private imageService: ImageService, - private userService: UserService, - private virtualmachineservice: VirtualmachineService, - private fb: UntypedFormBuilder, - private clipboardService: ClipboardService, - private flavorService: FlavorService, - - private applicationsService: ApplicationsService - ) { - super() - } - - /** - * Apply filter to all vms. - */ - applyFilter(): void { - if (this.filter) { - this.filter = this.filter.trim() - } - this.isSearching = true - if (typeof this.cluster_per_site !== 'number' || this.cluster_per_site <= 0) { - this.cluster_per_site = 7 - } - if (this.tab === 'own') { - this.getClusters() - } else if (this.tab === 'all') { - this.getAllClusters() - } else if (this.tab === 'facility') { - this.getAllCLusterFacilities() - } - } - - /** - * How to track the child cluster cards. - * @param index Track by a number or a string. - * @param vm Track by vm openstackid. - */ - trackByCluster(index: number | string, cluster: Clusterinfo): string { - return cluster.cluster_id - } - - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - get_is_facility_manager(): void { - this.subscription.add( - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - if (result.length > 0) { - this.is_facility_manager = true - } - }) - ) - } - - /** - * Toggle tab own|all. - * - * @param tabString - */ - toggleTab(tabString: string): void { - this.tab = tabString - } - - /** - * Load vms depending on page. - * - * @param event - */ - pageChanged(event: any): void { - this.isSearching = true - - this.currentPage = event.page - if (this.tab === 'own') { - this.getClusters() - } else if (this.tab === 'all') { - this.getAllClusters() - } else if (this.tab === 'facility') { - this.getAllCLusterFacilities() - } - } - - generateMigratedProjectIdList(): void { - this.migratedProjectIds = [] - this.cluster_page.cluster_list.forEach((cluster: Clusterinfo) => { - if (cluster.migrate_project_to_simple_vm || cluster.project_is_migrated_to_simple_vm) { - this.migratedProjectIds.push(cluster.project_id.toString()) - } - const unique = (arr: string[]): string[] => [...new Set(arr)] - this.migratedProjectIds = unique(this.migratedProjectIds) - }) - } - generateMigratedProjectNamesList(): void { - this.migratedProjectNames = [] - this.cluster_page.cluster_list.forEach((cluster: Clusterinfo) => { - if (cluster.migrate_project_to_simple_vm || cluster.project_is_migrated_to_simple_vm) { - this.migratedProjectNames.push(cluster.project) - } - }) - } - - /** - * Get all vms of user. - */ - getClusters(): void { - this.subscription.add( - this.virtualmachineservice - .getClusters(this.currentPage, this.cluster_per_site, this.filter, this.filter_status_list) - .subscribe((cluster_page: ClusterPage): void => { - this.prepareClusters(cluster_page) - }) - ) - } - - getAllCLusterFacilities(): void { - this.subscription.add( - this.facilityService - .getClustersFacility( - this.selectedFacility['FacilityId'], - this.currentPage, - this.cluster_per_site, - this.filter, - this.filter_status_list - ) - .subscribe((cluster_page_infos: ClusterPage): void => { - this.prepareClusters(cluster_page_infos) - }) - ) - } - - prepareClusters(cluster_page_infos: ClusterPage): void { - this.cluster_page = cluster_page_infos - // this.clusters = cluster_page_infos['cluster_list'].map((cluster: Clusterinfo): Clusterinfo => new Clusterinfo(cluster)); - // this.total_items = cluster_page_infos['total_items']; - // this.items_per_page = cluster_page_infos['items_per_page']; - // this.total_pages = cluster_page_infos['num_pages']; - - this.isSearching = false - this.generateMigratedProjectIdList() - this.generateMigratedProjectNamesList() - } - - changeFilterStatus(status: string): void { - this.currentPage = 1 - const indexOf: number = this.filter_status_list.indexOf(status) - if (indexOf === -1) { - this.filter_status_list.push(status) - } else { - this.filter_status_list.splice(indexOf, 1) - } - } - - getAllClusters(): void { - this.subscription.add( - this.virtualmachineservice - .getAllClusters(this.currentPage, this.cluster_per_site, this.filter, this.filter_status_list) - .subscribe((cluster_page_infos: ClusterPage): void => { - this.prepareClusters(cluster_page_infos) - }) - ) - } - - ngOnInit(): void { - this.getClusters() - this.is_vo_admin = is_vo - this.get_is_facility_manager() - this.subscription.add( - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - this.managerFacilities = result - this.selectedFacility = this.managerFacilities[0] - }) - ) - - this.subscription.add( - this.filterChanged.pipe(debounceTime(this.FILTER_DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - this.applyFilter() - }) - ) - - this.subscription.add( - this.clusterPerPageChange.pipe(debounceTime(this.DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - this.applyFilter() - }) - ) - } - - ngOnDestroy(): void { - this.subscription.unsubscribe() - } -} diff --git a/src/app/virtualmachines/clusters/clusterstatus/clusterstates.ts b/src/app/virtualmachines/clusters/clusterstatus/clusterstates.ts deleted file mode 100644 index 44e8af582c..0000000000 --- a/src/app/virtualmachines/clusters/clusterstatus/clusterstates.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { GeneralStatusStates } from '../../../shared/shared_modules/baseClass/statusstates'; - -export class Clusterstates extends GeneralStatusStates { - private static readonly _RUNNING: string = 'Running'; - private static readonly _CREATING_: string = 'Creating'; - private static readonly _CONFIGURING: string = 'Configuring'; - private static readonly _ERROR_: string = 'Error'; - - static get ERROR(): string { - return this._ERROR_; - } - - static get RUNNING(): string { - return this._RUNNING; - } - - static get CREATING(): string { - return this._CREATING_; - } - - static get CONFIGURING(): string { - return this._CONFIGURING; - } - - public get staticRUNNING(): string { - return Clusterstates.RUNNING; - } - - public get staticError(): string { - return Clusterstates.ERROR; - } - - public get staticCREATING(): string { - return Clusterstates.CREATING; - } - - public get staticCONFIGURING(): string { - return Clusterstates.CONFIGURING; - } -} diff --git a/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.html b/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.html deleted file mode 100644 index 81d2426a10..0000000000 --- a/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.html +++ /dev/null @@ -1,83 +0,0 @@ - -
-
- -
-
-
-
-
- -
-
-
-
- Status: {{ cluster?.status }} - -
diff --git a/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.ts b/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.ts deleted file mode 100644 index 905434e52f..0000000000 --- a/src/app/virtualmachines/clusters/clusterstatus/clusterstatus.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component, Input } from '@angular/core' -import { Clusterinfo } from '../clusterinfo' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { Clusterstates } from './clusterstates' - -/** - * Clusterstatus component. - */ -@Component({ - selector: 'app-clusterstatus', - templateUrl: './clusterstatus.component.html' -}) -export class ClusterstatusComponent { - @Input() cluster: Clusterinfo - @Input() show_text_status: boolean = true - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - ClusterStates: Clusterstates = new Clusterstates() -} diff --git a/src/app/virtualmachines/conda/backend/backend.ts b/src/app/virtualmachines/conda/backend/backend.ts deleted file mode 100644 index bfe7026790..0000000000 --- a/src/app/virtualmachines/conda/backend/backend.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Backend class. - */ -export class Backend { - owner: string; - user_key_url: string; - template: string; - template_version: string; - upstream_url: string; - backend_id: number; - location_url: string; - playbook_successful: boolean; - playbook_done: boolean; - no_playbook: boolean; - - constructor(backend?: Partial) { - Object.assign(this, backend); - } -} diff --git a/src/app/virtualmachines/conda/bioconda.component.html b/src/app/virtualmachines/conda/bioconda.component.html deleted file mode 100644 index 0acd7f7aa0..0000000000 --- a/src/app/virtualmachines/conda/bioconda.component.html +++ /dev/null @@ -1,95 +0,0 @@ -
-
-
-
-
Add/Remove
-
Name
-
Version
-
- -
-
- -
-
- -
-
 
-
 
-
- - -
-
- -
-
- {{ tool.name }} - {{ tool.name }} -
-
- -
-
-
-
-
- -
-
-
-
Remove
-
Chosen Package
-
- -
-
- -
-
- Name: {{ tool.name }}
- Version: {{ tool.version }}
-
-
-
-
-
- - -
-
diff --git a/src/app/virtualmachines/conda/bioconda.component.ts b/src/app/virtualmachines/conda/bioconda.component.ts deleted file mode 100644 index 3dc5cbaf31..0000000000 --- a/src/app/virtualmachines/conda/bioconda.component.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { - ChangeDetectorRef, - Component, - ElementRef, - EventEmitter, - HostListener, - OnInit, - Output, - ViewChild -} from '@angular/core' -import { Subject } from 'rxjs' -import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators' -import { PaginationComponent } from 'ngx-bootstrap/pagination' -import { BiocondaService } from '../../api-connector/bioconda.service' -import { CondaPackageMeta } from './conda-package-meta' -import { CondaPackage } from './condaPackage.model' - -/** - * Bioconda component. - */ -@Component({ - selector: 'app-bioconda', - templateUrl: 'bioconda.component.html', - providers: [BiocondaService] -}) -export class BiocondaComponent implements OnInit { - FIRST_PAGE: number = 1 - DEBOUNCE_TIME: number = 700 - - all_tools_meta: CondaPackageMeta[] = [] - - chosen_tools: CondaPackage[] = [] - - toolsPerPage: number = 10 - - currentPage: number = this.FIRST_PAGE - - toolsStart: number = 0 - - toolsEnd: number = this.toolsPerPage - - filterToolName: string = '' - - isSearching: boolean - - max_pages: number = 15 - total_pages: number - window_size: number - MAX_WINDOW_SIZE: number = 1200 - - filternameChanged: Subject = new Subject() - - @Output() readonly hasTools: EventEmitter = new EventEmitter() - @ViewChild('pagination', { static: true }) pagination: PaginationComponent - @ViewChild('chosenTable', { static: true }) chosenTable: ElementRef - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - @HostListener('window:resize', ['$event']) onResize(event: any): void { - this.window_size = window.innerWidth - } - - constructor( - private condaService: BiocondaService, - private cdr: ChangeDetectorRef - ) { - this.condaService = condaService - this.cdr = cdr - } - - pageChanged(event: any): void { - this.getAllTools(event.page) - } - - ngOnInit(): void { - this.window_size = window.innerWidth - - this.getAllTools(this.FIRST_PAGE) - - this.filternameChanged - .pipe( - debounceTime(this.DEBOUNCE_TIME), - distinctUntilChanged(), - switchMap((filterName: string): any => { - this.isSearching = true - - this.filterToolName = filterName.trim() - - return this.condaService.getAllTools(1, this.filterToolName) - }) - ) - .subscribe((res: any): void => { - this.setAllTools(res, 1) - }) - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onChange(event: any): void { - this.cdr.detectChanges() - } - - getAllTools(page: number): void { - this.isSearching = true - this.condaService.getAllTools(page, this.filterToolName).subscribe((metas: any): void => { - this.setAllTools(metas, page) - }) - } - - compareVersions(a: string, b: string): number { - if (a === b) { - return 0 - } - const splitA = a.split('.') - const splitB = b.split('.') - const length = Math.max(splitA.length, splitB.length) - - for (let i = 0; i < length; i++) { - if ( - parseInt(splitA[i], 10) > parseInt(splitB[i], 10) || - (splitA[i] === splitB[i] && Number.isNaN(splitB[i + 1])) - ) { - return 1 - } - if ( - parseInt(splitA[i], 10) < parseInt(splitB[i], 10) || - (splitA[i] === splitB[i] && Number.isNaN(splitA[i + 1])) - ) { - return -1 - } - } - - return 0 - } - - adjustToolVersionSort(metaToSort: CondaPackageMeta[]): CondaPackageMeta[] { - const sortedMeta: CondaPackageMeta[] = [] - metaToSort.forEach((packageMeta: CondaPackageMeta): void => { - packageMeta.versions = packageMeta.versions.sort(this.compareVersions).reverse() - sortedMeta.push(packageMeta) - }) - - return sortedMeta - } - - setAllTools(res: any, page: number): void { - this.isSearching = true - - this.all_tools_meta = res['packages'] - this.all_tools_meta = this.adjustToolVersionSort(this.all_tools_meta) - this.total_pages = res['total_items'] - this.toolsStart = 0 - this.toolsPerPage = res['items_per_page'] - this.toolsEnd = this.toolsPerPage - - this.currentPage = page - this.pagination.selectPage(this.currentPage) - this.cdr.detectChanges() - - this.isSearching = false - } - - changedNameFilter(text: string): void { - this.filternameChanged.next(text) - } - - addTool(name: string, version: string): void { - const tool: CondaPackage = new CondaPackage(null, name, version) - - if (!this.is_tool_name_added(tool.name)) { - this.chosen_tools.push(tool) - } else { - this.chosen_tools.forEach((item: CondaPackage, index: number): void => { - if (tool.name === item.name) { - this.chosen_tools.splice(index, 1) - } - }) - this.chosen_tools.push(tool) - } - this.hasTools.emit(this.hasChosenTools()) - } - - removeTool(tool: CondaPackage): void { - this.chosen_tools.forEach((item: CondaPackage, index: number): void => { - if (tool.name === item.name && tool.version === item.version) { - this.chosen_tools.splice(index, 1) - - } - }) - - this.hasTools.emit(this.hasChosenTools()) - } - - is_tool_name_added(name: string): boolean { - let found: boolean = false - this.chosen_tools.forEach((item: CondaPackage): void => { - if (name === item.name) { - found = true - } - }) - - return found - } - - is_added(name: string, version: string): boolean { - const tool: CondaPackage = new CondaPackage(null, name, version) - - let found: boolean = false - this.chosen_tools.forEach((item: CondaPackage): void => { - if (tool.name === item.name && tool.version === item.version) { - found = true - } - }) - - return found - } - - getChosenTools(): string { - return JSON.stringify(this.chosen_tools) - } - - getTimeout(): number { - return this.chosen_tools.length * 300 + 840 - } - - hasChosenTools(): boolean { - return this.chosen_tools.length > 0 - } -} diff --git a/src/app/virtualmachines/conda/conda-package-meta.ts b/src/app/virtualmachines/conda/conda-package-meta.ts deleted file mode 100644 index 720b3351f6..0000000000 --- a/src/app/virtualmachines/conda/conda-package-meta.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class CondaPackageMeta { - home: string; - name: string; - versions: string[]; - - constructor(condaPackageMeta?: Partial) { - Object.assign(this, condaPackageMeta); - } -} diff --git a/src/app/virtualmachines/conda/condaPackage.model.ts b/src/app/virtualmachines/conda/condaPackage.model.ts deleted file mode 100644 index 90958d5059..0000000000 --- a/src/app/virtualmachines/conda/condaPackage.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Class for packages selected in Conda to represent them in the instance-detail. - */ -export class CondaPackage { - name: string; - version: string; - - constructor(condaPackage?: Partial, name?: string, version?: string) { - if (condaPackage) { - Object.assign(this, condaPackage); - } else { - this.name = name; - this.version = version; - } - } -} diff --git a/src/app/virtualmachines/conda/condalog.ts b/src/app/virtualmachines/conda/condalog.ts deleted file mode 100644 index 9ea81976ef..0000000000 --- a/src/app/virtualmachines/conda/condalog.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { jsPDF } from 'jspdf'; -/** - * Conda Log class - */ -export class Condalog { - private _status: number; - private _stdout: string; - private _stderr: string; - private _log_pdf: jsPDF; - - constructor(log: Condalog) { - this._status = log.status; - this._stdout = log.stdout; - this._stderr = log.stderr; - } - - saveAsPDF(): void { - this.createLogPDF(); - this._log_pdf.save('Playbook-Logs.pdf'); - } - - saveAsTxt(): void { - const element: HTMLElement = document.createElement('a'); - const fileType: string = 'text/plain'; - const status: string = `Statuscode: ${this._status.toString()}\n`; - const stdout: string = `Log: ${this._stdout.toString()}\n`; - const stderr: string = `Errorlog: ${this._stderr.toString()}\n`; - element.setAttribute('href', `data:${fileType};charset=utf-8,${encodeURIComponent(status + stdout + stderr)}`); - element.setAttribute('download', 'Playbook-logs.txt'); - - const event: MouseEvent = new MouseEvent('click'); - element.dispatchEvent(event); - } - - private createLogPDF(): void { - // eslint-disable-next-line new-cap - const doc: jsPDF = new jsPDF('p', 'mm', 'a4'); - const lineWidth: number = doc.internal.pageSize.width; - const margin: number = 10; - const pageHeight: number = doc.internal.pageSize.height; - const maxLineWidth: number = lineWidth - margin * 3; - const statusCode: string = 'Statuscode: '; - const statusCodeString: string = statusCode + this._status.toString(); - doc.text(statusCodeString, margin * 2, margin); - const stdout: string[] = doc.splitTextToSize(this._stdout, maxLineWidth); - stdout.unshift('Log: '); - let currentLine: number = 10; - for (const line of stdout) { - if ((currentLine + margin) > pageHeight) { - doc.addPage(); - currentLine = 10; - } - doc.text(line, margin * 2, currentLine + margin); - currentLine += 10; - } - const stderr: string[] = doc.splitTextToSize(this._stderr, maxLineWidth); - stderr.unshift('Errorlog:'); - for (const line of stderr) { - if ((currentLine + margin) > pageHeight) { - doc.addPage(); - currentLine = 10; - } - doc.text(line, margin * 2, currentLine + margin); - currentLine += 10; - } - this._log_pdf = doc; - } - - get log_pdf(): jsPDF { - return this._log_pdf; - } - - get status(): number { - return this._status; - } - - set status(value: number) { - this._status = value; - } - - get stdout(): string { - return this._stdout; - } - - set stdout(value: string) { - this._stdout = value; - } - - get stderr(): string { - return this._stderr; - } - - set stderr(value: string) { - this._stderr = value; - } - -} diff --git a/src/app/virtualmachines/conda/res-env.component.html b/src/app/virtualmachines/conda/res-env.component.html deleted file mode 100644 index 55b076bc57..0000000000 --- a/src/app/virtualmachines/conda/res-env.component.html +++ /dev/null @@ -1,235 +0,0 @@ -
-
-
-
- We recommend using our prebuilt images, accessible within the "Research Environments" section during the image - selection process. -
-
-
-
- If you are unfamiliar with research environments or want to learn more about them, please feel free to read our - wiki entry. -
-
-
- -
-
- Please select a research environment template you would like to have installed: -
-
- -
-
-
- - {{ selectedTemplate.title }} - {{ selectedTemplate.template_name }} -
-
-
-

- {{ selectedTemplate.title }}® - {{ selectedTemplate.template_name }}® -

-

- {{ selectedTemplate?.description }} -

-

- Click here for more Information. -

- -
  • - {{ info }}:{{ selectedTemplate.information_for_display[info] }} -
  • -
    -
    -
    -
    -
    - - - -
    -
    -
    - - - {{ template.title }} - {{ template.template_name }} -
    -
    -
    -

    - {{ template.title }}® - {{ template.template_name }}® -

    -

    - {{ template?.description }} -

    -

    - Click here for more Information. -

    - -
  • - {{ info }}: {{ template.information_for_display[info] }} -
  • -
    -
    -
    -
    -
    -
    -
    - -
    -
    - This template is known to be incompatible with:
    -
      -
    • - {{ version }} -
    • -
    -
    - If you encounter an error with a version that is not listed, please contact us at - {{ CLOUD_PORTAL_SUPPORT_MAIL }}. -
    -
    -
    -
    -
    - Selected Image has research environment installed: - {{ selectedTemplate.template_name }} -
    - -
    -
    - Please select a research environment name: -
    -
    -
    - -
    -
    - {{ forc_url }} -
    - -
    - _automatically_generated_number/ - -
    -
    -
    -
    - At least three characters are required.
    - - Allowed characters are upper and lower case letters (a-z A-Z). -
    -
    -
    -
    -
    - -
    -
    -
    - - -
    -
    - Activate this option if you are sure that your chosen image/snapshot has your desired research environment - installed.
    - This option will only run the tasks necessary to setup access and will not install the research environment - itself. -
    Guacamole will be accessable about 15 minutes after your virtual machine is ACTIVE, due to the nature - of the research environment.
    -
    -
    -
    -
    diff --git a/src/app/virtualmachines/conda/res-env.component.ts b/src/app/virtualmachines/conda/res-env.component.ts deleted file mode 100644 index 0deeab293c..0000000000 --- a/src/app/virtualmachines/conda/res-env.component.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core' -import { UntypedFormControl, Validators } from '@angular/forms' -import { Subscription } from 'rxjs' -import { BiocondaService } from '../../api-connector/bioconda.service' -import { ResearchEnvironment } from '../virtualmachinemodels/res-env' -import { RandomNameGenerator } from '../../shared/randomNameGenerator' -import { WIKI_RESENV_LINK, CLOUD_PORTAL_SUPPORT_MAIL } from '../../../links/links' -import { BlockedImageTagResenv } from '../../facility_manager/image-tag' - -/** - * ResEnv. - */ -@Component({ - selector: 'app-res-env', - templateUrl: 'res-env.component.html', - providers: [BiocondaService] -}) -export class ResEnvComponent implements OnInit, OnChanges, OnDestroy { - @Input() clientid: string - @Input() forc_url: string - @Input() onlyNamespace: boolean = false - @Input() imageName: string = '' - @Input() selectedImageTags: string[] = [] - @Input() blockedImageTagsResenv: BlockedImageTagResenv[] - @Input() workshopMode: boolean = false - - Object: object = Object - - templates_to_block: string[] = [] - - user_key_url: UntypedFormControl = new UntypedFormControl('', [ - Validators.required, - Validators.pattern('[a-zA-Z]{3,20}') - ]) - - selectedTemplate: ResearchEnvironment | undefined = undefined - - templates: ResearchEnvironment[] = [] - - undefinedTemplate: ResearchEnvironment = new ResearchEnvironment() - - rng: RandomNameGenerator - - WIKI_RESENV_LINK: string = WIKI_RESENV_LINK - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - - create_only_backend: boolean = false - - subscription: Subscription = new Subscription() - - constructor(private condaService: BiocondaService) { - this.condaService = condaService - } - - setUserKeyUrl(url: string): void { - if (this.needsName()) { - this.user_key_url.setValue(url) - } - } - - getUserKeyUrl(): string { - return this.user_key_url.value - } - - getCreateOnlyBackend(): boolean { - return this.create_only_backend - } - - setSelectedTemplate(template: ResearchEnvironment): void { - if (template === null) { - this.selectedTemplate = this.undefinedTemplate - this.user_key_url.setValue('') - this.create_only_backend = false - } else { - this.selectedTemplate = template - if (!this.user_key_url.value) { - this.generateRandomName() - } - } - } - - ngOnInit(): void { - this.undefinedTemplate.template_name = 'undefined' - this.templates_to_block = [] - this.setSelectedTemplate(null) - this.subscription.add( - this.condaService.getForcTemplates(this.clientid).subscribe((templates: ResearchEnvironment[]): void => { - this.templates = templates - }) - ) - this.rng = new RandomNameGenerator() - this.generateRandomName() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } - - ngOnChanges(): void { - this.checkBlocked() - } - - isValid(): boolean { - if (this.onlyNamespace) { - if (this.workshopMode) { - return true - } else { - return this.user_key_url.errors === null - } - } else if (this.selectedTemplate.template_name === 'undefined') { - if (this.workshopMode) { - return false - } else { - return this.user_key_url.value.length === 0 - } - } else if (this.workshopMode) { - return true - } else { - return this.user_key_url.errors === null - } - } - - needsName(): boolean { - if (this.onlyNamespace || this.selectedTemplate.template_name !== 'undefined') { - return this.user_key_url.errors !== null - } - - return false - } - - needsTemplate(): boolean { - if (this.workshopMode && this.selectedTemplate.template_name === 'undefined') { - return true - } else if (this.user_key_url.value.length !== 0 && !this.onlyNamespace) { - return this.selectedTemplate.template_name === 'undefined' - } - - return false - } - - okayNeeded(): boolean { - return this.selectedTemplate.template_name !== 'undefined' - } - - setOnlyNamespace(template): void { - this.onlyNamespace = true - this.create_only_backend = true - this.setSelectedTemplate(template) - } - - unsetOnlyNamespace(): void { - this.onlyNamespace = false - this.user_key_url.setValue('') - this.setSelectedTemplate(null) - } - - generateRandomName(): void { - this.user_key_url.setValue(this.rng.randomName()) - } - - checkBlocked(): void { - if (this.selectedImageTags === null || this.selectedImageTags === undefined) { - return - } - for (const blockedTag of this.blockedImageTagsResenv) { - if (this.selectedImageTags.indexOf(blockedTag.tag) !== -1) { - this.templates_to_block = blockedTag.resenvs - - return - } - } - this.templates_to_block = [] - } - - resetData(): void { - this.setSelectedTemplate(null) - this.create_only_backend = false - } -} diff --git a/src/app/virtualmachines/conda/resenvTemplate.model.ts b/src/app/virtualmachines/conda/resenvTemplate.model.ts deleted file mode 100644 index fdf6354e1a..0000000000 --- a/src/app/virtualmachines/conda/resenvTemplate.model.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Model for Research Environment Templates - */ -export class ResenvTemplate { - - template_name: string; - title: string; - description: string; - info_url: string; - logo_url: string; - - constructor(template_name: string, title: string, description: string, info_url: string, logo_url: string) { - this.template_name = template_name; - this.title = title; - this.description = description; - this.info_url = info_url; - this.logo_url = logo_url; - } -} diff --git a/src/app/virtualmachines/conda/template-names.ts b/src/app/virtualmachines/conda/template-names.ts deleted file mode 100644 index 6e8a108950..0000000000 --- a/src/app/virtualmachines/conda/template-names.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Class containing all FORC Template names - */ -export class TemplateNames { - private static _RSTUDIO: string = 'rstudio' - private static _THEIA: string = 'theiaide' - private static _GUACAMOLE: string = 'guacamole' - private static _JUPYTERLAB: string = 'jupyterlab' - private static _VSCODE: string = 'vscode' - - private static _ALL_TEMPLATES: string[] = [ - TemplateNames._RSTUDIO, - TemplateNames._THEIA, - TemplateNames._GUACAMOLE, - TemplateNames._JUPYTERLAB, - TemplateNames._VSCODE - ] - - static get RSTUDIO(): string { - return this._RSTUDIO - } - - static set RSTUDIO(value: string) { - this._RSTUDIO = value - } - - static get THEIA(): string { - return this._THEIA - } - - static set THEIA(value: string) { - this._THEIA = value - } - - static get GUACAMOLE(): string { - return this._GUACAMOLE - } - - static set GUACAMOLE(value: string) { - this._GUACAMOLE = value - } - - static get JUPYTERLAB(): string { - return this._JUPYTERLAB - } - - static set JUPYTERLAB(value: string) { - this._JUPYTERLAB = value - } - - static get VSCODE(): string { - return this._VSCODE - } - - static set VSCODE(value: string) { - this._VSCODE = value - } - - static get ALL_TEMPLATE_NAMES(): string[] { - return this._ALL_TEMPLATES - } -} diff --git a/src/app/virtualmachines/flavordetail.component.html b/src/app/virtualmachines/flavordetail.component.html deleted file mode 100644 index dc745610de..0000000000 --- a/src/app/virtualmachines/flavordetail.component.html +++ /dev/null @@ -1,332 +0,0 @@ -
    -
    - Flavor*
    - Flavors specify the amount of resources for your machine. -
    -
    - -
    -
    - - -
    -
    -
    - {{ flavor_types[selected_flavor_type][0].type.description }} -
    -
    -
    -
    -
    - Selected: {{ selectedFlavor?.name }} -
    -
    -
    -
    -
    -
    - -
    - {{ selectedFlavor?.ram_gib }} GB Ram -
    -
    -
    -
    -
    - -
    - {{ selectedFlavor?.vcpus }} Cores -
    -
    -
    -
    -
    - -
    - {{ selectedFlavor?.rootdisk }} GB root disk - - + {{ selectedFlavor.ephemeral_disk }} GB ephemeral disk -
    -
    - -
    -
    -
    - -
    - {{ selectedFlavor?.gpu }} GPU GPUs -
    -
    - -
    -
    -
    - -
    - {{ selectedFlavor?.credits_costs_per_hour }} Credits/hour -
    -
    -
    -
    -
    -
    -
    - - - - - -
    -
    -
    -
    - {{ flavor.name }} -
    -
    -
    -
    -
    -
    - -
    - {{ flavor?.ram_gib }} GB Ram -
    -
    -
    -
    -
    - -
    - {{ flavor?.vcpus }} Cores -
    -
    -
    -
    -
    - -
    - {{ flavor?.rootdisk }} GB root disk - + {{ flavor.ephemeral_disk }} GB ephemeral disk -   -
    -
    -
    -
    -
    - -
    - {{ flavor?.gpu }} GPU GPUs -
    -
    - -
    -
    -
    - -
    - {{ flavor?.credits_costs_per_hour }} Credits/hour -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    - {{ flavor.name }} -
    -
    -
    -
    -
    -
    - -
    - {{ flavor?.ram_gib }} GB Ram -
    -
    -
    -
    -
    - -
    - {{ flavor?.vcpus }} Cores -
    -
    -
    -
    -
    - -
    - {{ flavor?.rootdisk }} GB root disk - + {{ flavor.ephemeral_disk }} GB ephemeral disk -   -
    -
    - -
    -
    -
    - -
    - {{ flavor?.gpu }} GPU GPUs -
    -
    - -
    -
    -
    - -
    - {{ flavor?.credits_costs_per_hour }} Credits/hour -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - Please consider
    -

    - If a GPU flavor you want to use is not available at the given time, for example because all resources of this - type are occupied, you have 2 possible courses of action: -

    -
      -
    • - You can wait until the desired resource is free again. Please bear in mind that this form is not updated - automatically. Update the view yourself by using the reload button above or by refreshing of this page. -
    • -
    • You use a different flavor.
    • -
    -

    Please bear in mind that it can take a long time until a certain resource is free again!

    -
    -
    -
    -
    diff --git a/src/app/virtualmachines/flavordetail.component.ts b/src/app/virtualmachines/flavordetail.component.ts deleted file mode 100644 index 4244cc97d7..0000000000 --- a/src/app/virtualmachines/flavordetail.component.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { Component, EventEmitter, HostListener, Input, OnChanges, OnInit, Output } from '@angular/core' -import { OwlOptions } from 'ngx-owl-carousel-o' -import { KeyValue } from '@angular/common' -import { Flavor } from './virtualmachinemodels/flavor' -import { FlavorService } from '../api-connector/flavor.service' -import { Image } from './virtualmachinemodels/image' - -/** - * Flavor detail component. - */ -@Component({ - selector: 'app-flavor-detail', - templateUrl: 'flavordetail.component.html', - providers: [FlavorService] -}) -export class FlavorDetailComponent implements OnInit, OnChanges { - @Input() selectedFlavor: Flavor - @Input() selectedImage: Image - @Input() creditsAllowed: boolean - @Input() flavors: Flavor[] - @Input() allowReload: boolean = false - @Output() readonly selectedFlavorChange: EventEmitter = new EventEmitter() - @Output() readonly reloadFlavors: EventEmitter = new EventEmitter() - - regexp_data_test_id: RegExp = /[ ().]/g - selected_flavor_types: Flavor[] = [] - selected_flavor_type: string = 'Standard Flavors' - flavor_types: { [name: string]: Flavor[] } = {} - flavors_per_row: number = 4 - possible_flavors: Flavor[] = [] - filter: string = '' - filterTimeout = null - filterDebounceTime: number = 300 - - carousel_activated: boolean = true - window_size: number - carousel_window_min_xl_9: number = 1700 - carousel_window_min_xl_8: number = 1380 - carousel_window_min_xl6: number = 1200 - - filterFlavorsWithDebounce() { - clearTimeout(this.filterTimeout) - this.filterTimeout = setTimeout(() => { - this.filterFlavors() - }, this.filterDebounceTime) - } - - filterFlavors(): void { - if (this.filter) { - this.possible_flavors = this.flavors.filter(image => image.name.toLowerCase().includes(this.filter.toLowerCase())) - } else { - this.possible_flavors = this.flavor_types[this.selected_flavor_type] - } - } - - // icons for graphics within flavor cards: - - STATIC_IMG_FOLDER: string = 'static/webapp/assets/img/' - - CPU_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/cpu_icon.svg` - RAM_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/ram_icon.svg` - STORAGE_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/storage_icon.svg` - GPU_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/gpu_icon.svg` - CREDITS_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/credits_icon.svg` - - customOptions: OwlOptions = { - loop: false, - mouseDrag: false, - touchDrag: false, - pullDrag: false, - dots: true, - navSpeed: 700, - navText: ["", ""], - responsive: { - 0: { - items: 1 - }, - 550: { - items: 2 - }, - 800: { - items: 3 - }, - 1200: { - items: 4 - } - }, - nav: true - } - - constructor(private flavorService: FlavorService) { - - } - - ngOnInit(): void { - this.window_size = window.innerWidth - this.flavor_types = this.flavorService.sortFlavors(this.flavors) - this.possible_flavors = this.flavor_types[this.selected_flavor_type] - } - - ngOnChanges() { - this.flavor_types = this.flavorService.sortFlavors(this.flavors) - this.possible_flavors = this.flavor_types[this.selected_flavor_type] - this.filterFlavors() - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - @HostListener('window:resize', ['$event']) onResize(event: any): void { - this.window_size = window.innerWidth - } - - /** - * Sets the selected Flavor. - * If a selectedFlavor exist it will be added to the flavor list and the new selectedFlavor will be removed. - * - * @param flavor Flavor which will become the selected Flavor. - */ - setSelectedFlavor(flavor: Flavor): void { - this.selectedFlavor = flavor - this.selectedFlavorChange.emit(this.selectedFlavor) - } - - emitFlavorReload(): void { - this.selectedFlavor = undefined - this.selected_flavor_type = 'Standard Flavors' - this.reloadFlavors.emit() - } - - setSelectedFlavorType(key: string): void { - this.selected_flavor_type = key - this.possible_flavors = this.flavor_types[key] - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - unsorted(a: KeyValue, b: KeyValue): number { - return 0 - } -} diff --git a/src/app/virtualmachines/imageCarouselSlide.component.html b/src/app/virtualmachines/imageCarouselSlide.component.html deleted file mode 100644 index 4e646d5bfa..0000000000 --- a/src/app/virtualmachines/imageCarouselSlide.component.html +++ /dev/null @@ -1,126 +0,0 @@ -
    -
    -
    - {{ image.name }} -
    -
    -
    -
    - {{ image?.description }} -
    -
    - {{ image?.description }} -
    -
    -
    - -
    -
    -
    -
    - - {{ selectedImage?.name }} -
    -
    -
    -
    - {{ selectedImage?.description }} -
    -
    - Logo -
    -
    -
    - -
    diff --git a/src/app/virtualmachines/imageCarouselSlide.component.ts b/src/app/virtualmachines/imageCarouselSlide.component.ts deleted file mode 100644 index d7d217f755..0000000000 --- a/src/app/virtualmachines/imageCarouselSlide.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' -import { Image } from './virtualmachinemodels/image' -import { Flavor } from './virtualmachinemodels/flavor' - -/** - * Image carousel slide. - */ -@Component({ - selector: 'app-image-slide', - templateUrl: 'imageCarouselSlide.component.html', - styleUrls: ['./imagedetail.component.scss'] -}) -export class ImageCarouselSlideComponent implements OnInit { - @Input() image: Image - @Input() selectedImage: Image - @Input() selectedFlavor: Flavor - @Output() readonly selectedImageChange: EventEmitter = new EventEmitter() - window_size: number - img_height: string = '120px!important' - img_width: string = '210px!important' - object_fit_scale: string = 'scale' - image_visible: boolean = true - regexp_data_test_id: RegExp = /[ ().]/g - STATIC_IMG_FOLDER: string = 'static/webapp/assets/img/' - - RAM_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/ram_icon.svg` - STORAGE_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/storage_icon.svg` - - ngOnInit(): void { - this.window_size = window.innerWidth - } - - public setImageVisible(): void { - if (this.image.logo_url) { - this.image_visible = !this.image_visible - } - } -} diff --git a/src/app/virtualmachines/imagedetail.component.html b/src/app/virtualmachines/imagedetail.component.html deleted file mode 100644 index 4f079e8076..0000000000 --- a/src/app/virtualmachines/imagedetail.component.html +++ /dev/null @@ -1,199 +0,0 @@ -
    - Loading images ... -
    -
    - -
    -
    - Image*
    - Images specify the operating system for your machine. You may choose a clean base image or a previously created - snapshot of a running machine. - -
    -
    -
    - There are no images available for selection at the moment. Please contact the support of the facility where your - project is running. -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    - - {{ - selectedImage?.name - }} -
    -
    -
    -
    - {{ selectedImage?.description }} -
    -
    - {{ selectedImage?.description }} -
    -
    -
    - -
    -
    - -
    - - - - - - - - - -
    -
    - - - - - - - -
    -
    -
    -
    diff --git a/src/app/virtualmachines/imagedetail.component.scss b/src/app/virtualmachines/imagedetail.component.scss deleted file mode 100644 index 6b6c3046e2..0000000000 --- a/src/app/virtualmachines/imagedetail.component.scss +++ /dev/null @@ -1,7 +0,0 @@ -.card-body .scroll-image .ng-star-inserted img, .card-body .ng-star-inserted img -{ - display: block !important; - margin: auto !important; - height: 120px !important; - width:auto !important; -} diff --git a/src/app/virtualmachines/imagedetail.component.ts b/src/app/virtualmachines/imagedetail.component.ts deleted file mode 100644 index fb4028b324..0000000000 --- a/src/app/virtualmachines/imagedetail.component.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Component, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core' -import { OwlOptions } from 'ngx-owl-carousel-o' -import { forkJoin, Subscription } from 'rxjs' -import { Image } from './virtualmachinemodels/image' -import { ImageService } from '../api-connector/image.service' -import { ImageTypes } from './virtualmachinemodels/imageTypes' -import { Flavor } from './virtualmachinemodels/flavor' -import { BiocondaService } from '../api-connector/bioconda.service' -import { Client } from '../vo_manager/clients/client.model' - -/** - * Imagedetail component. - */ -@Component({ - selector: 'app-image-detail[client][project_id]', - templateUrl: 'imagedetail.component.html', - styleUrls: ['./imagedetail.component.scss'], - providers: [ImageService, BiocondaService] -}) -export class ImageDetailComponent implements OnInit, OnDestroy { - @Input() selectedImage: Image - @Input() selectedFlavor: Flavor - @Output() readonly selectedImageChange: EventEmitter = new EventEmitter() - @Input() isCluster: boolean = false - @Input() client: Client - @Input() project_id: number - images_loaded: boolean = false - resenv_names: string[] = [] - images: Image[] = [] - filter: string = '' - - subscription: Subscription = new Subscription() - regexp_data_test_id: RegExp = /[ ().]/g - carousel_activated: boolean = true - images_per_row: number = 4 - window_size: number - carousel_window_min_xl_9: number = 1700 - carousel_window_min_xl_8: number = 1380 - carousel_window_min_xl6: number = 1200 - img_height: string = '120px!important' - img_width: string = '210px!important' - image_visible: boolean = true - selected_image_type: string = ImageTypes.IMAGE - image_types: { [name: string]: Image[] } = {} - imageTypes = ImageTypes - image_selection: Image[] - - filterTimeout = null - filterDebounceTime: number = 300 - - filterImagesWithDebounce() { - clearTimeout(this.filterTimeout) - this.filterTimeout = setTimeout(() => { - this.filterImages() - }, this.filterDebounceTime) - } - - filterImages(): void { - if (this.filter) { - this.image_selection = this.images.filter(image => image.name.toLowerCase().includes(this.filter.toLowerCase())) - } else { - this.image_selection = this.image_types[this.selected_image_type] - } - } - - STATIC_IMG_FOLDER: string = 'static/webapp/assets/img/' - RAM_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/ram_icon.svg` - STORAGE_ICON_PATH: string = `${this.STATIC_IMG_FOLDER}/new_instance/storage_icon.svg` - - customOptions: OwlOptions = { - loop: false, - mouseDrag: false, - touchDrag: false, - pullDrag: false, - dots: true, - navSpeed: 700, - navText: ["", ""], - responsive: { - 0: { - items: 1 - }, - 550: { - items: 2 - }, - 800: { - items: 3 - }, - 1200: { - items: 4 - } - }, - nav: true - } - - constructor( - private imageService: ImageService, - private condaService: BiocondaService - ) { - - } - - ngOnInit(): void { - this.window_size = window.innerWidth - this.prepareImages() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } - - prepareImages(): void { - this.images_loaded = false - this.images = [] - let image_mode = '' - if (this.isCluster) { - image_mode = 'cluster' - } - forkJoin([ - this.condaService.getForcTemplates(this.client.id), - - this.imageService.getImages(this.project_id, image_mode) - ]).subscribe(async (res: any) => { - res[0].forEach(resenv => this.resenv_names.push(resenv.template_name)) - this.images = res[1] - this.image_types = this.imageService.sortImages(this.images, this.resenv_names) - if (this.isCluster) { - this.selected_image_type = ImageTypes.CLUSTER_IMAGE - } else { - this.selected_image_type = ImageTypes.IMAGE - } - this.image_selection = this.image_types[this.selected_image_type] - this.images_loaded = true - }) - } - - setSelectedImageType(key: string): void { - this.selected_image_type = key - this.image_selection = this.image_types[key] - } - - public setImageVisible(): void { - this.image_visible = !this.image_visible - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - @HostListener('window:resize', ['$event']) onResize(event: any): void { - this.window_size = window.innerWidth - } -} diff --git a/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.html b/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.html deleted file mode 100644 index d3f376e4ad..0000000000 --- a/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.html +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.ts b/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.ts deleted file mode 100644 index d17aad5ec3..0000000000 --- a/src/app/virtualmachines/modals/delete-cluster/delete-cluster.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Clusterinfo } from '../../clusters/clusterinfo' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' - -@Component({ - selector: 'app-delete-cluster', - templateUrl: '../delete-cluster/delete-cluster.component.html' -}) -export class DeleteClusterComponent implements OnDestroy { - /** - * Possible virtual machine states. - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - cluster: Clusterinfo - all_loaded: boolean = true - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - deleteCluster(): void { - this.submitted = true - this.event.emit({ deleteCluster: true }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/delete-vm/delete-vm.component.html b/src/app/virtualmachines/modals/delete-vm/delete-vm.component.html deleted file mode 100644 index 6c4fe5acc4..0000000000 --- a/src/app/virtualmachines/modals/delete-vm/delete-vm.component.html +++ /dev/null @@ -1,70 +0,0 @@ - - diff --git a/src/app/virtualmachines/modals/delete-vm/delete-vm.component.ts b/src/app/virtualmachines/modals/delete-vm/delete-vm.component.ts deleted file mode 100644 index 1860c104e2..0000000000 --- a/src/app/virtualmachines/modals/delete-vm/delete-vm.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { elixir_id } from '../../../shared/globalvar' - -@Component({ - selector: 'app-delete-vm', - templateUrl: './delete-vm.component.html' -}) -export class DeleteVmComponent implements OnDestroy { - virtualMachine: VirtualMachine - clusterWorker: boolean = false - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - user_elixir_id: string = elixir_id - - /** - * To check if the user agreed to deleting someone else's VM - */ - delete_foreign_vm_consent: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - deleteVM(): void { - this.submitted = true - this.event.emit({ deleteVM: true, worker: this.virtualMachine }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/password-cluster/password-cluster.component.html b/src/app/virtualmachines/modals/password-cluster/password-cluster.component.html deleted file mode 100644 index a3e2c1370d..0000000000 --- a/src/app/virtualmachines/modals/password-cluster/password-cluster.component.html +++ /dev/null @@ -1,34 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/password-cluster/password-cluster.component.ts b/src/app/virtualmachines/modals/password-cluster/password-cluster.component.ts deleted file mode 100644 index abed285721..0000000000 --- a/src/app/virtualmachines/modals/password-cluster/password-cluster.component.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Component, EventEmitter, OnInit } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { ClipboardService } from 'ngx-clipboard' -import { Clusterinfo } from '../../clusters/clusterinfo' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' - -@Component({ - selector: 'app-password-cluster', - templateUrl: '../password-cluster/password-cluster.component.html', - providers: [VirtualmachineService] -}) -export class PasswordClusterComponent implements OnInit { - cluster: Clusterinfo - password: string = null - public event: EventEmitter = new EventEmitter() - - - constructor( - public bsModalRef: BsModalRef, - private clipboardService: ClipboardService, - private virtualmachineservice: VirtualmachineService - ) {} - - ngOnInit() { - this.generatePassword() - } - - /** - * Copy some text to clipboard. - */ - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - generatePassword(): void { - this.cluster.password = null - this.virtualmachineservice.generatePasswordCluster(this.cluster.cluster_id).subscribe((res: any) => { - this.password = res['password'] - }) - } -} diff --git a/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.html b/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.html deleted file mode 100644 index 341d1847d1..0000000000 --- a/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - diff --git a/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.ts b/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.ts deleted file mode 100644 index fd4df531ab..0000000000 --- a/src/app/virtualmachines/modals/reboot-vm/reboot-vm.component.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { WIKI_MOUNT_VOLUME } from '../../../../links/links' - -@Component({ - selector: 'app-reboot-vm', - templateUrl: './reboot-vm.component.html' -}) -export class RebootVmComponent implements OnDestroy { - virtualMachine: VirtualMachine - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - choosingType: boolean = true - confirm: boolean = false - reboot_type: string = '' - - WIKI_MOUNT_VOLUME: string = WIKI_MOUNT_VOLUME - - constructor(public bsModalRef: BsModalRef) { - - } - - rebootVm(): void { - this.submitted = true - this.event.emit({ reboot_type: this.reboot_type }) - this.bsModalRef.hide() - } - - softRebootShow(): void { - this.choosingType = false - this.confirm = true - this.reboot_type = 'SOFT' - } - - hardRebootShow(): void { - this.choosingType = false - this.confirm = true - this.reboot_type = 'HARD' - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.html b/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.html deleted file mode 100644 index 4a98c20ed9..0000000000 --- a/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.html +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.ts b/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.ts deleted file mode 100644 index 88ca4d2658..0000000000 --- a/src/app/virtualmachines/modals/recreate-backend-vm/recreate-backend-vm.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' - -@Component({ - selector: 'app-recreate-backend-vm', - templateUrl: './recreate-backend-vm.component.html' -}) -export class RecreateBackendVmComponent implements OnDestroy { - virtualMachine: VirtualMachine - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - recreateBackendVM(): void { - this.submitted = true - this.event.emit({ recreateBackendVM: true }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.html b/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.html deleted file mode 100644 index 22b5b3a954..0000000000 --- a/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.html +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.ts b/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.ts deleted file mode 100644 index 3b056490d7..0000000000 --- a/src/app/virtualmachines/modals/rename-cluster/rename-cluster.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Clusterinfo } from '../../clusters/clusterinfo' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' - -@Component({ - selector: 'app-rename-cluster', - templateUrl: '../rename-cluster/rename-cluster.component.html' -}) -export class RenameClusterComponent implements OnDestroy { - /** - * Possible virtual machine states. - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - cluster: Clusterinfo - all_loaded: boolean = true - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - renameCluster(name: string): void { - this.submitted = true - this.event.emit({ new_name: name }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.html b/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.html deleted file mode 100644 index 14b92afa71..0000000000 --- a/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.html +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.ts b/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.ts deleted file mode 100644 index 682d0ee1e1..0000000000 --- a/src/app/virtualmachines/modals/resume-cluster/resume-cluster.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Clusterinfo } from '../../clusters/clusterinfo' - -@Component({ - selector: 'app-resume-cluster', - templateUrl: './resume-cluster.component.html' -}) -export class ResumeClusterComponent implements OnDestroy { - cluster: Clusterinfo - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - resumeCluster(): void { - this.submitted = true - this.event.emit({ resumeCluster: true }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/resume-vm/resume-vm.component.html b/src/app/virtualmachines/modals/resume-vm/resume-vm.component.html deleted file mode 100644 index 703198185c..0000000000 --- a/src/app/virtualmachines/modals/resume-vm/resume-vm.component.html +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/resume-vm/resume-vm.component.ts b/src/app/virtualmachines/modals/resume-vm/resume-vm.component.ts deleted file mode 100644 index 16f3c7bf64..0000000000 --- a/src/app/virtualmachines/modals/resume-vm/resume-vm.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' - -@Component({ - selector: 'app-resume-vm', - templateUrl: './resume-vm.component.html' -}) -export class ResumeVmComponent implements OnDestroy { - virtualMachine: VirtualMachine - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - resumeVM(): void { - this.submitted = true - this.event.emit({ resumeVM: true }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.html b/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.html deleted file mode 100644 index 2266aaa3b6..0000000000 --- a/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.html +++ /dev/null @@ -1,455 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.ts b/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.ts deleted file mode 100644 index 93bca1b967..0000000000 --- a/src/app/virtualmachines/modals/scale-cluster/scale-cluster.component.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { ClipboardService } from 'ngx-clipboard' -import { Subscription } from 'rxjs' -import { Clusterinfo, WorkerBatch } from '../../clusters/clusterinfo' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { SCALE_SCRIPT_LINK } from '../../../../links/links' -import { Flavor } from '../../virtualmachinemodels/flavor' -import { ApplicationRessourceUsage } from '../../../applications/application-ressource-usage/application-ressource-usage' -import { FlavorService } from '../../../api-connector/flavor.service' -import { GroupService } from '../../../api-connector/group.service' - -@Component({ - selector: 'app-scale-cluster', - templateUrl: './scale-cluster.component.html', - providers: [FlavorService, GroupService] -}) -export class ScaleClusterComponent implements OnDestroy, OnInit { - /** - * Possible virtual machine states. - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - private subscription: Subscription = new Subscription() - - scaling_warning_read: boolean = false - SCALING_SCRIPT_LINK: string = SCALE_SCRIPT_LINK - SCALING_SCRIPT_NAME: string = 'scaling.py' - scale_down: boolean = false - scale_up: boolean = false - scale_success: boolean = false - projectDataLoaded: boolean = false - selectedBatch: WorkerBatch - scale_down_count: number = 0 - scale_up_worker_count: number - created_new_batch: boolean = false - flavors: Flavor[] = [] - flavors_usable: Flavor[] = [] - flavors_loaded: boolean = false - selectedProjectRessources: ApplicationRessourceUsage - max_scale_up_count: number = 0 - max_scale_up_count_loaded: boolean = false - mode: string - msg: string - - cluster: Clusterinfo - old_cluster: Clusterinfo - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - - constructor( - public bsModalRef: BsModalRef, - private clipboardService: ClipboardService, - private flavorService: FlavorService, - private groupService: GroupService - ) { - - } - - ngOnInit(): void { - if (this.mode === 'scale_up') { - this.scale_up = true - this.calcRess() - } else if (this.mode === 'scale_down') { - this.scale_down = true - } else if (this.mode === 'scale_success') { - this.scale_success = true - } - } - - /** - * Copy some text to clipboard.projectDataLoaded - */ - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - checkDelCount(batch: WorkerBatch): void { - if (batch.delete_count > batch.worker_count) { - batch.delete_count = batch.worker_count - } - this.scale_down_count = 0 - - this.cluster.worker_batches.forEach((bat: WorkerBatch): void => { - if (bat.delete_count > 0) { - this.scale_down_count += bat.delete_count - } - }) - } - - loadProjectRessource(): void { - this.projectDataLoaded = false - this.flavors_loaded = false - - this.flavors = [] - this.subscription.add( - this.groupService.getGroupResources(this.cluster.project_id).subscribe((res: ApplicationRessourceUsage): void => { - this.selectedProjectRessources = new ApplicationRessourceUsage(res) - this.getFlavors(this.cluster.project_id) - this.projectDataLoaded = true - }) - ) - } - - checkUpCount(batch: WorkerBatch): void { - if (batch.upscale_count > batch.max_scale_up_count) { - batch.upscale_count = batch.max_scale_up_count - } - } - - calcRess(): void { - this.max_scale_up_count_loaded = false - - // tslint:disable-next-line:max-line-length - this.subscription.add( - this.groupService - .getGroupResources(this.cluster.master_instance.projectid.toString()) - .subscribe((res: ApplicationRessourceUsage): void => { - this.selectedProjectRessources = new ApplicationRessourceUsage(res) - for (const workerBatch of this.cluster.worker_batches) { - workerBatch.max_scale_up_count = this.selectedProjectRessources.calcMaxScaleUpWorkerInstancesByFlavor( - workerBatch.flavor - ) - } - this.max_scale_up_count_loaded = true - }) - ) - } - - setSelectedBatch(batch: WorkerBatch): void { - this.selectedBatch = batch - } - resizeFix(): void { - window.dispatchEvent(new Event('resize')) - } - - getFlavors(project_id: number | string): void { - this.subscription.add( - this.flavorService.getFlavors(project_id).subscribe( - (flavors: Flavor[]): void => { - this.flavors = flavors - this.checkFlavorsUsableForCluster() - }, - (error: any) => { - console.log(error) - this.flavors = [] - this.flavors_usable = [] - this.flavors_loaded = true - } - ) - ) - } - - calcMaxWorkerInstancesByFlavor(): void { - this.selectedBatch.setMaxWorkerCount(this.selectedProjectRessources) - } - - removeNewBatchSelectedCluster(): void { - if (this.created_new_batch && this.selectedBatch) { - this.cluster.remove_batch(this.selectedBatch) - this.created_new_batch = false - this.selectedBatch = null - } - } - - createNewBatchSelectedCluster(): void { - this.created_new_batch = true - const idx: number = this.getBatchUpscaleIndexNumber() - this.cluster.create_new_batch(idx) - this.selectedBatch = this.cluster.worker_batches[this.cluster.worker_batches.length - 1] - this.loadProjectRessource() - } - - getBatchUpscaleIndexNumber(): number { - const indexList: number[] = [] - this.cluster.worker_batches.forEach((cwb: WorkerBatch): void => { - indexList.push(cwb.index) - }) - indexList.sort() - let idx: number = 1 - while (indexList.indexOf(idx) !== -1) { - idx += 1 - } - - return idx - } - - checkFlavorsUsableForCluster(): void { - this.flavors_usable = [] - const used_flavors: Flavor[] = [] - let flavors_to_filter: Flavor[] = [] - - // tslint:disable-next-line:no-for-each-push - this.cluster.worker_batches.forEach((batch: WorkerBatch): void => { - if (batch.flavor) { - used_flavors.push(batch.flavor) - } - }) - if (used_flavors.length > 0) { - flavors_to_filter = this.flavors.filter((flavor: Flavor): boolean => { - let not_used: boolean = true - - used_flavors.forEach((used_flavor: Flavor): void => { - if (flavor.name === used_flavor.name) { - not_used = false - } - }) - - return not_used - }) - } else { - flavors_to_filter = this.flavors - } - this.flavors_usable = flavors_to_filter.filter((flav: Flavor): boolean => - this.selectedProjectRessources.filterFlavorsTestUpScaling(flav) - ) - - this.flavors_loaded = true - } - - scaleDownCluster(): void { - this.submitted = true - this.event.emit({ scaleDownCluster: true, cluster: this.cluster }) - - this.bsModalRef.hide() - } - - scaleUpCluster(): void { - this.submitted = true - this.event.emit({ - scaleUpCluster: true, - selectedBatch: this.selectedBatch, - created_new_batch: this.created_new_batch - }) - - this.bsModalRef.hide() - } - - resetScalingBatches(): void { - for (const workerBatch of this.cluster.worker_batches) { - workerBatch.upscale_count = 0 - workerBatch.delete_count = 0 - } - } - - ngOnDestroy() { - this.subscription.unsubscribe() - - if (!this.submitted) { - this.removeNewBatchSelectedCluster() - this.resetScalingBatches() - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.html b/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.html deleted file mode 100644 index 9e6e1470de..0000000000 --- a/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.html +++ /dev/null @@ -1,67 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.ts b/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.ts deleted file mode 100644 index 14eaf29e18..0000000000 --- a/src/app/virtualmachines/modals/snapshot-vm/snapshot-vm.component.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Subject, Subscription } from 'rxjs' -import { debounceTime, distinctUntilChanged } from 'rxjs/operators' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { SnapshotModel } from '../../snapshots/snapshot.model' -import { IResponseTemplate } from '../../../api-connector/response-template' -import { ImageService } from '../../../api-connector/image.service' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' - -@Component({ - selector: 'app-snapshot-vm', - templateUrl: './snapshot-vm.component.html', - providers: [ImageService] -}) -export class SnapshotVmComponent implements OnDestroy, OnInit { - virtualMachine: VirtualMachine - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - SNAPSHOT_MAX_RAM: number = SnapshotModel.MAX_RAM - snapshotSearchTerm: Subject = new Subject() - subscription: Subscription = new Subscription() - DEBOUNCE_TIME: number = 300 - validSnapshotNameBool: boolean - snapshotNameCheckDone: boolean = false - snapshotName: string = '' - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - constructor( - public bsModalRef: BsModalRef, - private imageService: ImageService - ) { - - } - - snapshotVM(description: any): void { - this.submitted = true - this.event.emit({ snapshotVM: true, snapshotName: this.snapshotName, description }) - this.bsModalRef.hide() - } - - validSnapshotName(): any { - this.snapshotNameCheckDone = false - this.imageService - .checkSnapshotNameAvailable(this.snapshotName.trim(), this.virtualMachine.client.id) - .subscribe((res: IResponseTemplate): void => { - this.validSnapshotNameBool = this.snapshotName.length > 0 && (res.value as boolean) - this.snapshotNameCheckDone = true - }) - } - - ngOnInit() { - this.subscription.add( - this.snapshotSearchTerm.pipe(debounceTime(this.DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - this.validSnapshotName() - }) - ) - } - - ngOnDestroy() { - this.subscription.unsubscribe() - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.html b/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.html deleted file mode 100644 index a66dd0c208..0000000000 --- a/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.html +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.ts b/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.ts deleted file mode 100644 index 8cfe183215..0000000000 --- a/src/app/virtualmachines/modals/stop-cluster/stop-cluster.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Component, EventEmitter } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Clusterinfo } from '../../clusters/clusterinfo' - -@Component({ - selector: 'app-cluster-vm', - templateUrl: './stop-cluster.component.html' -}) -export class StopClusterComponent { - cluster: Clusterinfo - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - stopCluster(): void { - this.submitted = true - this.event.emit({ stopCluster: true }) - this.bsModalRef.hide() - } -} diff --git a/src/app/virtualmachines/modals/stop-vm/stop-vm.component.html b/src/app/virtualmachines/modals/stop-vm/stop-vm.component.html deleted file mode 100644 index 2c28d9ebcb..0000000000 --- a/src/app/virtualmachines/modals/stop-vm/stop-vm.component.html +++ /dev/null @@ -1,31 +0,0 @@ - - diff --git a/src/app/virtualmachines/modals/stop-vm/stop-vm.component.ts b/src/app/virtualmachines/modals/stop-vm/stop-vm.component.ts deleted file mode 100644 index 5a94680a90..0000000000 --- a/src/app/virtualmachines/modals/stop-vm/stop-vm.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, EventEmitter, OnDestroy } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' - -@Component({ - selector: 'app-stop-vm', - templateUrl: './stop-vm.component.html' -}) -export class StopVmComponent implements OnDestroy { - virtualMachine: VirtualMachine - public event: EventEmitter = new EventEmitter() - private submitted: boolean = false - - constructor(public bsModalRef: BsModalRef) { - - } - - stopVm(): void { - this.submitted = true - this.event.emit({ stopVM: true }) - this.bsModalRef.hide() - } - - ngOnDestroy() { - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/modals/volume-vm/volume-vm.component.html b/src/app/virtualmachines/modals/volume-vm/volume-vm.component.html deleted file mode 100644 index ec6c8d99b4..0000000000 --- a/src/app/virtualmachines/modals/volume-vm/volume-vm.component.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - diff --git a/src/app/virtualmachines/modals/volume-vm/volume-vm.component.ts b/src/app/virtualmachines/modals/volume-vm/volume-vm.component.ts deleted file mode 100644 index af60c15e43..0000000000 --- a/src/app/virtualmachines/modals/volume-vm/volume-vm.component.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core' -import { BsModalRef } from 'ngx-bootstrap/modal' -import { Subscription } from 'rxjs' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { WIKI_VOLUME_OVERVIEW } from '../../../../links/links' -import { Volume } from '../../volumes/volume' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' - -@Component({ - selector: 'app-volume-vm', - templateUrl: './volume-vm.component.html', - providers: [VirtualmachineService] -}) -export class VolumeVmComponent implements OnInit, OnDestroy { - virtualMachine: VirtualMachine - selectedVolume: Volume - detached_project_volumes: Volume[] = [] - public event: EventEmitter = new EventEmitter() - private subscription: Subscription = new Subscription() - private submitted: boolean = false - WIKI_VOLUME_OVERVIEW: string = WIKI_VOLUME_OVERVIEW - attach: boolean = false - detach: boolean = false - mode: string = '' - - constructor( - public bsModalRef: BsModalRef, - private virtualmachineservice: VirtualmachineService - ) { - - } - - attachVolume(): void { - this.submitted = true - this.event.emit({ attachVolume: true, volume: this.selectedVolume }) - this.bsModalRef.hide() - } - - detachVolume(): void { - this.submitted = true - this.event.emit({ detachVolume: true, volume: this.selectedVolume }) - this.bsModalRef.hide() - } - - ngOnInit(): void { - if (this.mode === 'attach') { - this.subscription.add( - this.virtualmachineservice - .getDetachedVolumesByProject(this.virtualMachine.projectid) - .subscribe((detached_volumes: Volume[]): void => { - this.detached_project_volumes = detached_volumes - }) - ) - this.attach = true - } else if (this.mode === 'detach') this.detach = true - } - - ngOnDestroy() { - this.subscription.unsubscribe() - if (!this.submitted) { - this.event.emit({ resume: true }) - } - } -} diff --git a/src/app/virtualmachines/project-user-list/project-user-list.component.html b/src/app/virtualmachines/project-user-list/project-user-list.component.html deleted file mode 100644 index 40b318126f..0000000000 --- a/src/app/virtualmachines/project-user-list/project-user-list.component.html +++ /dev/null @@ -1,62 +0,0 @@ -
    - If you want to give other members of your project access to the new machine(s), add the user here. Their public key - will then also be added to the new machine(s). -

    The members must already have set their public key for this function!

    - -
    - These users will be able log in on the machine with the same user as you and will therefore have the same - rights/permissions on the machine as you! They will not be able to alter the machine on the 'Instance Overview' or - the 'Detail Page'. -
    -
    - These users will not be able to access the browser-based research environment. -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    Full NamePublic Key SetAction
    {{ member.userName }} -   -   - - - -
    -
    -
    -
    diff --git a/src/app/virtualmachines/project-user-list/project-user-list.component.ts b/src/app/virtualmachines/project-user-list/project-user-list.component.ts deleted file mode 100644 index a42621284c..0000000000 --- a/src/app/virtualmachines/project-user-list/project-user-list.component.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core' -import { Subscription } from 'rxjs' -import { ProjectMember } from '../../projectmanagement/project_member.model' -import { GroupService } from '../../api-connector/group.service' - -/** - * Project member list selection. - */ -@Component({ - selector: 'app-project-user-list', - templateUrl: './project-user-list.component.html', - providers: [GroupService] -}) -export class ProjectUserListComponent implements OnInit, OnDestroy { - @Input() project_id: string | number - @Input() user_member_id: number - project_members: ProjectMember[] = [] - @Input() members_to_add: ProjectMember[] = [] - subscription: Subscription = new Subscription() - - constructor(private groupService: GroupService) { - this.groupService = groupService - } - - getMembersOfTheProject(): void { - this.subscription.add( - this.groupService.getGroupMembers(this.project_id.toString()).subscribe((members: ProjectMember[]): void => { - this.project_members = members.filter( - (mem: ProjectMember): boolean => mem.memberId.toString() !== this.user_member_id.toString() - ) - }) - ) - } - - addMember(member: ProjectMember): void { - this.members_to_add.push(member) - } - - removeMember(member: ProjectMember): void { - this.members_to_add.splice(this.members_to_add.indexOf(member), 1) - } - - ngOnInit(): void { - this.getMembersOfTheProject() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } -} diff --git a/src/app/virtualmachines/snapshots/snapshotOverview.component.html b/src/app/virtualmachines/snapshots/snapshotOverview.component.html deleted file mode 100644 index 9170b51163..0000000000 --- a/src/app/virtualmachines/snapshots/snapshotOverview.component.html +++ /dev/null @@ -1,348 +0,0 @@ -
    -
    -
    - Wiki - - - - -
    -
    -
    Snapshots – Overview
    -
    - - -
    -
    -
    -
    - - -
    -
    - -
    -
    - -
    Snapshots per page
    -
    - -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    Name
    -
    Project
    -
    Actions
    -
    Status
    -
    - Select all -
    - - -
    - -
    -
    {{ snapshot?.snapshot_name }}
    -
    {{ snapshot?.snapshot_project }}
    -
    - -
    -
    -
    This snapshot is part of a migrated project!
    -
    -
    - - {{ snapshot?.snapshot_status | uppercase }} - - - {{ snapshot?.snapshot_status | uppercase }} - -
    - - -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - No snapshots available. Click this link to see how to use - and create a snapshot. -
    -
    -
    - - - - - - - - diff --git a/src/app/virtualmachines/snapshots/snapshotOverview.component.ts b/src/app/virtualmachines/snapshots/snapshotOverview.component.ts deleted file mode 100644 index 834ca2da70..0000000000 --- a/src/app/virtualmachines/snapshots/snapshotOverview.component.ts +++ /dev/null @@ -1,316 +0,0 @@ -import { Component, OnInit } from '@angular/core' -import { forkJoin, Subject } from 'rxjs' -import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators' - -import { ImageService } from '../../api-connector/image.service' -import { SnapshotModel } from './snapshot.model' -import { IResponseTemplate } from '../../api-connector/response-template' -import { FacilityService } from '../../api-connector/facility.service' -import { CLOUD_PORTAL_SUPPORT_MAIL, WIKI_SNAPSHOTS } from '../../../links/links' -import { SnapshotPage } from './snapshotPage.model' -import { ApplicationsService } from '../../api-connector/applications.service' -import { IsMigratedProjectIdPipe } from '../../pipe-module/pipes/migratedList' - -enum Snapshot_Delete_Statuses { - WAITING = 0, - SUCCESS = 1, - ERROR = 2, -} - -/** - * Snapshot overivew. - */ -@Component({ - selector: 'app-snapshot-overview', - templateUrl: 'snapshotOverview.component.html', - providers: [FacilityService, ImageService] -}) -export class SnapshotOverviewComponent implements OnInit { - snapshot_page: SnapshotPage = new SnapshotPage() - WIKI_SNAPSHOTS: string = WIKI_SNAPSHOTS - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - checked_snapshots: SnapshotModel[] = [] - - title: string = 'Snapshot Overview' - - showFacilities: boolean = false - - /** - * Facilitties where the user is manager ['name',id]. - */ - managerFacilities: [string, number][] - /** - * Chosen facility. - */ - selectedFacility: [string, number] - - /** - * Selected snapshot. - */ - selected_snapshot: SnapshotModel - /** - * Actual delete status. - * - * @type {Snapshot_Delete_Statuses} - */ - delete_status: number = Snapshot_Delete_Statuses.WAITING - delete_statuses: typeof Snapshot_Delete_Statuses = Snapshot_Delete_Statuses - /** - * If site was initialized. - * - * @type {boolean} - */ - isLoaded: boolean = false - filterChanged: Subject = new Subject() - filter: string = '' - all_snapshots_checked: boolean = false - - private checkStatusTimeout: number = 5000 - - currentPage: number = 1 - snapshotsPerPageChange: Subject = new Subject() - isSearching: boolean = true - DEBOUNCE_TIME: number = 300 - migratedProjectIds: string[] = [] - migratedProjectNames: string[] = [] - - constructor( - private facilityService: FacilityService, - private imageService: ImageService, - private applicationsService: ApplicationsService, - private isMigratedPipe: IsMigratedProjectIdPipe - ) { - this.facilityService = facilityService - this.imageService = imageService - } - - changedFilter(text: string): void { - this.filterChanged.next(text) - } - - /** - * Set selected Snapshot. - * - * @param snapshot - */ - setSelectedSnapshot(snapshot: SnapshotModel): void { - this.selected_snapshot = snapshot - } - - /** - * Get snapshots by user. - */ - getSnapshots(): void { - this.filter = this.filter.trim() - this.imageService - .getSnapshotsByUser(this.currentPage, this.snapshot_page.items_per_page, this.filter) - .subscribe((snapshot_page: SnapshotPage): void => { - this.snapshot_page = snapshot_page - this.generateMigratedProjectIdList() - this.generateMigratedProjectNamesList() - this.isLoaded = true - this.checkSnapShotsStatus() - this.isSearching = false - }) - } - - generateMigratedProjectIdList(): void { - this.migratedProjectIds = [] - this.snapshot_page.snapshot_list.forEach((snap: SnapshotModel) => { - if (snap.migrate_project_to_simple_vm || snap.project_is_migrated_to_simple_vm) { - this.migratedProjectIds.push(snap.snapshot_projectid.toString()) - } - const unique = (arr: string[]): string[] => [...new Set(arr)] - this.migratedProjectIds = unique(this.migratedProjectIds) - }) - } - generateMigratedProjectNamesList(): void { - this.migratedProjectNames = [] - this.snapshot_page.snapshot_list.forEach((snap: SnapshotModel) => { - if (snap.migrate_project_to_simple_vm || snap.project_is_migrated_to_simple_vm) { - this.migratedProjectNames.push(snap.snapshot_project) - } - }) - } - - changeCheckAllSnapshots(): void { - if (this.all_snapshots_checked) { - this.checked_snapshots = [] - this.all_snapshots_checked = false - - return - } - - this.snapshot_page.snapshot_list.forEach((snap: SnapshotModel): void => { - if ( - !this.isSnapChecked(snap) && - !this.isMigratedPipe.transform(snap.snapshot_projectid, this.migratedProjectIds) - ) { - this.checked_snapshots.push(snap) - } - }) - this.all_snapshots_checked = true - } - - checkSnapShotsStatus(): void { - let all_active_or_migrated: boolean = true - - setTimeout((): void => { - const observables: any = [] - for (const snapshot of this.snapshot_page.snapshot_list) { - if (snapshot.snapshot_status !== 'active' && snapshot.snapshot_status !== 'MIGRATED') { - observables.push(this.imageService.getSnapshot(snapshot.snapshot_openstackid)) - } - } - forkJoin(observables).subscribe((res: any): void => { - for (const snap of res) { - this.snapshot_page.snapshot_list[res.indexOf(snap)].snapshot_status = snap['status'] - if (snap['status'] !== 'active' && snap['status'] !== 'MIGRATED') { - all_active_or_migrated = false - } - } - if (!all_active_or_migrated) { - this.checkSnapShotsStatus() - } - }) - }, this.checkStatusTimeout) - } - - getFacilitySnapshots(): void { - this.facilityService - .getFacilitySnapshots(this.selectedFacility['FacilityId'], this.currentPage, this.snapshot_page.items_per_page) - .subscribe((snapshot_page: SnapshotPage): void => { - this.snapshot_page = snapshot_page - this.isSearching = false - }) - } - - /** - * Delete snapshot. - * - * @param snapshot - */ - deleteSnapshot(snapshot: SnapshotModel): void { - this.imageService.deleteSnapshot(snapshot.snapshot_openstackid).subscribe((result: IResponseTemplate): void => { - this.delete_status = 0 - - if (result.value as boolean) { - this.delete_status = 1 - const idx: number = this.snapshot_page.snapshot_list.indexOf(snapshot) - - this.snapshot_page.snapshot_list.splice(idx, 1) - } else if (result.value) { - this.delete_status = 3 - this.getSnapshots() - } else { - this.delete_status = 2 - this.getSnapshots() - } - }) - } - - ngOnInit(): void { - this.getSnapshots() - - this.filterChanged - .pipe( - debounceTime(this.DEBOUNCE_TIME), - distinctUntilChanged(), - switchMap((filterName: string): any => { - this.isSearching = true - - this.filter = filterName.trim() - if (this.showFacilities) { - return this.facilityService.getFacilitySnapshots( - this.selectedFacility['FacilityId'], - this.currentPage, - this.snapshot_page.items_per_page, - this.filter - ) - } else { - return this.imageService.getSnapshotsByUser( - this.currentPage, - this.snapshot_page.items_per_page, - this.filter - ) - } - }) - ) - .subscribe((snapshot_page: SnapshotPage): void => { - this.snapshot_page = snapshot_page - this.isLoaded = true - this.checkSnapShotsStatus() - this.isSearching = false - }) - - this.snapshotsPerPageChange.pipe(debounceTime(this.DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - if (this.showFacilities) { - this.getFacilitySnapshots() - } else { - this.getSnapshots() - } - }) - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - this.managerFacilities = result - this.selectedFacility = this.managerFacilities[0] - }) - } - - areAllSnapshotsChecked(): void { - let all_checked: boolean = true - this.snapshot_page.snapshot_list.forEach((snap: SnapshotModel): void => { - if (!this.isSnapChecked(snap)) { - all_checked = false - } - }) - - this.all_snapshots_checked = all_checked - } - - changeCheckedSnapshot(snap: SnapshotModel): void { - if (!this.isSnapChecked(snap)) { - this.checked_snapshots.push(snap) - } else { - this.checked_snapshots.splice(this.checked_snapshots.indexOf(snap), 1) - } - this.areAllSnapshotsChecked() - } - - isSnapChecked(snap: SnapshotModel): boolean { - return this.checked_snapshots.indexOf(snap) !== -1 - } - - deleteSelectedSnapshots(): void { - this.checked_snapshots.forEach((snap: SnapshotModel): void => { - this.deleteSnapshot(snap) - }) - this.uncheckAll() - } - - uncheckAll(): void { - this.checked_snapshots = [] - this.all_snapshots_checked = false - } - - /** - * Load vms depending on page. - * - * @param event - */ - pageChanged(event: any): void { - this.isSearching = true - - this.currentPage = event.page - if (this.showFacilities) { - this.getFacilitySnapshots() - } else { - this.getSnapshots() - } - } - - reset(): void { - this.snapshot_page = new SnapshotPage() - this.isSearching = true - this.currentPage = 1 - } -} diff --git a/src/app/virtualmachines/snapshots/snapshotPage.model.ts b/src/app/virtualmachines/snapshots/snapshotPage.model.ts deleted file mode 100644 index 7181b72684..0000000000 --- a/src/app/virtualmachines/snapshots/snapshotPage.model.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { SnapshotModel } from './snapshot.model'; - -export class SnapshotPage { - snapshot_list: SnapshotModel[]; - total_pages: number = 0; - num_pages: number = 0; - total_items: number = 0; - items_per_page: number = 7; - - constructor(snapshot_page?: Partial) { - Object.assign(this, snapshot_page); - this.snapshot_list = []; - if (snapshot_page) { - for (const snapshot of snapshot_page.snapshot_list) { - this.snapshot_list.push(new SnapshotModel(snapshot)); - } - if (snapshot_page.num_pages) { - this.total_pages = snapshot_page.num_pages; - } - if (snapshot_page.total_pages) { - this.num_pages = snapshot_page.total_pages; - } - } - } -} diff --git a/src/app/virtualmachines/virtualmachinemodels/virtualmachine.ts b/src/app/virtualmachines/virtualmachinemodels/virtualmachine.ts index fc8d9979cf..8eedcfb3ed 100644 --- a/src/app/virtualmachines/virtualmachinemodels/virtualmachine.ts +++ b/src/app/virtualmachines/virtualmachinemodels/virtualmachine.ts @@ -3,9 +3,6 @@ import { Client } from '../../vo_manager/clients/client.model' import { ImageMode } from '../../facility_manager/image-tag' import { Clusterinfo } from '../clusters/clusterinfo' import { Volume } from '../volumes/volume' -import { Backend } from '../conda/backend/backend' -import { VirtualMachineStates } from './virtualmachinestates' -import { CondaPackage } from '../conda/condaPackage.model' /** * Virtualmachine class. @@ -20,37 +17,20 @@ export class VirtualMachine { client: Client openstackid: string created_at_date: string - deleted_at_date: string still_used_confirmation_requested_date: Date - still_used_confirmed_user_id: string - stopped_at: string + elixir_id: string - fixed_ip: string - userlogin: string - floating_ip: string - ssh_command: string - udp_command: string + application_id: string cardState: number cluster: Clusterinfo projectid: number - playbook_successful: boolean - playbook_done: boolean - res_env_url: string + modes: ImageMode[] volumes: Volume[] - still_used_confirmation_requested: boolean error_msg: string - info_msg: string msg: string days_running: number - backend: Backend - conda_packages: CondaPackage[] = [] - still_used_confirmed_date: Date - // still used confirmed date missing in webapp! - - migrate_project_to_simple_vm: boolean = false - project_is_migrated_to_simple_vm: boolean = false constructor(vm?: Partial) { Object.assign(this, vm) @@ -71,15 +51,6 @@ export class VirtualMachine { this.volumes.push(new Volume(volume)) } } - if (vm.backend) { - this.backend = new Backend(vm.backend) - } - this.conda_packages = [] - if (vm.conda_packages) { - for (const conda_package of vm.conda_packages) { - this.conda_packages.push(new CondaPackage(conda_package)) - } - } } this.getTerminationStartDateString() if (this.days_running === null) { @@ -108,27 +79,4 @@ export class VirtualMachine { return term_date.toLocaleDateString() } - - setErrorMsgWithTimeout(msg: string, timeout: number = 10000): void { - this.error_msg = msg - setTimeout((): void => { - this.error_msg = null - }, timeout) - } - - setMsgWithTimeout(msg: string, timeout: number = 10000): void { - this.msg = msg - setTimeout((): void => { - this.msg = null - }, timeout) - } - - updateClusterStatus(): void { - if (!this.cluster) { - return - } - if (this.status === VirtualMachineStates.SHUTOFF) { - this.cluster.status = VirtualMachineStates.SHUTOFF - } - } } diff --git a/src/app/virtualmachines/vm.module.ts b/src/app/virtualmachines/vm.module.ts deleted file mode 100644 index 8dcbbc3103..0000000000 --- a/src/app/virtualmachines/vm.module.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { NgModule } from '@angular/core' -import { CarouselModule } from 'ngx-owl-carousel-o' -import { TabsModule } from 'ngx-bootstrap/tabs' -import { CommonModule } from '@angular/common' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { ModalModule } from 'ngx-bootstrap/modal' -import { PaginationModule } from 'ngx-bootstrap/pagination' -import { AccordionModule } from 'ngx-bootstrap/accordion' -import { BsDropdownModule } from 'ngx-bootstrap/dropdown' -import { NgbModule } from '@ng-bootstrap/ng-bootstrap' -import { VmRoutingModule } from './vm_routing.module' -import { ImageDetailComponent } from './imagedetail.component' -import { VirtualMachineComponent } from './addvm.component' -import { FlavorDetailComponent } from './flavordetail.component' -import { VmOverviewComponent } from './vmOverview.component' -import { VolumeOverviewComponent } from './volumes/volumeOverview.component' -import { SnapshotOverviewComponent } from './snapshots/snapshotOverview.component' -import { PublicKeyModule } from '../shared/shared_modules/public-key/public-key.module' -import { BiocondaComponent } from './conda/bioconda.component' -import { SharedDirectivesModule } from '../shared/shared_modules/shared_directives.module' -import { ImageCarouselSlideComponent } from './imageCarouselSlide.component' -import { VmDetailComponent } from './vmdetail/vmdetail.component' -import { AddClusterComponent } from './clusters/add-cluster/add-cluster.component' -import { ResourceOverviewComponent } from './resource-overview/resource-overview.component' -import { ResEnvComponent } from './conda/res-env.component' -import { ClusterdetailComponent } from './clusters/clusterdetail/clusterdetail.component' -import { VirtualmachineinfoComponent } from './vmdetail/virtualmachineinfo/virtualmachineinfo.component' -import { VmstatusComponent } from './vmdetail/vmstatus/vmstatus.component' -import { ClusterOverviewComponent } from './clusters/clusteroverview/clusterOverview.component' -import { ClusterinfoComponent } from './clusters/clusterinfo/clusterinfo.component' -import { ClusterstatusComponent } from './clusters/clusterstatus/clusterstatus.component' -import { VolumStatusComponent } from './volumes/volum-status/volum-status.component' -import { PipeModuleModule } from '../pipe-module/pipe-module.module' -import { ProjectUserListComponent } from './project-user-list/project-user-list.component' -import { StopVmComponent } from './modals/stop-vm/stop-vm.component' -import { VmCardComponent } from './vmcard/vmcard.component' -import { ResumeVmComponent } from './modals/resume-vm/resume-vm.component' -import { ResumeClusterComponent } from './modals/resume-cluster/resume-cluster.component' -import { DeleteVmComponent } from './modals/delete-vm/delete-vm.component' -import { SnapshotVmComponent } from './modals/snapshot-vm/snapshot-vm.component' -import { VolumeVmComponent } from './modals/volume-vm/volume-vm.component' -import { RebootVmComponent } from './modals/reboot-vm/reboot-vm.component' -import { ClustercardComponent } from './clustercard/clustercard.component' -import { ScaleClusterComponent } from './modals/scale-cluster/scale-cluster.component' -import { DeleteClusterComponent } from './modals/delete-cluster/delete-cluster.component' -import { AddWorkshopComponent } from './workshop/add-workshop/add-workshop.component' -import { WorkshopOverviewComponent } from './workshop/workshop-overview/workshop-overview.component' -import { NewsModule } from '../news/news.module' -import { RecreateBackendVmComponent } from './modals/recreate-backend-vm/recreate-backend-vm.component' -import { DatePickerComponent } from '../shared/datepicking/datepicker.component' -import { TimepickerComponent } from '../shared/datepicking/timepicker.component' -import { SharedModuleModule } from '../shared/shared_modules/shared-module.module' -import { ClusterActionsComponent } from './clusters/cluster-actions/cluster-actions.component' - -/** - * VM module. - */ -@NgModule({ - imports: [ - PipeModuleModule, - PublicKeyModule, - VmRoutingModule, - TabsModule, - CommonModule, - FormsModule, - ModalModule.forRoot(), - PaginationModule.forRoot(), - BsDropdownModule.forRoot(), - CarouselModule, - AccordionModule.forRoot(), - SharedDirectivesModule, - NgbModule, - ReactiveFormsModule, - NewsModule, - DatePickerComponent, - TimepickerComponent, - SharedModuleModule - ], - declarations: [ - ImageCarouselSlideComponent, - ClusterActionsComponent, - ImageDetailComponent, - VirtualMachineComponent, - FlavorDetailComponent, - VmOverviewComponent, - VolumeOverviewComponent, - SnapshotOverviewComponent, - ClusterstatusComponent, - BiocondaComponent, - VmDetailComponent, - AddClusterComponent, - ResourceOverviewComponent, - ResEnvComponent, - ClusterinfoComponent, - ClusterdetailComponent, - ClusterOverviewComponent, - VirtualmachineinfoComponent, - VmstatusComponent, - VolumStatusComponent, - ProjectUserListComponent, - VmCardComponent, - StopVmComponent, - RecreateBackendVmComponent, - ResumeClusterComponent, - ResumeVmComponent, - DeleteVmComponent, - SnapshotVmComponent, - VolumeVmComponent, - RebootVmComponent, - ClustercardComponent, - ScaleClusterComponent, - DeleteClusterComponent, - AddWorkshopComponent, - WorkshopOverviewComponent - ] -}) -export class VmModule {} diff --git a/src/app/virtualmachines/vmOverview.component.html b/src/app/virtualmachines/vmOverview.component.html deleted file mode 100644 index 01708801ff..0000000000 --- a/src/app/virtualmachines/vmOverview.component.html +++ /dev/null @@ -1,332 +0,0 @@ -
    -
    -
    -
    -
    - - - - -
    -
    - -
    -
    -
    -
    - - -
    -
    -
    - - -
    -
    - -
    - VMs per page -
    -
    -
    - -
    -
    -
    -
    -
    - - Cluster -
    -
    - - Set for termination -
    -
    - - {{ VirtualMachineStates.staticACTIVE }} -
    -
    - - {{ VirtualMachineStates.staticSHUTOFF }} -
    -
    - - {{ VirtualMachineStates.staticDELETED }} -
    -
    -
    - -
    -
    - -
    -
    - -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    - Instance Name -
    -
    - Project -
    -
    - Created (by/at) -
    -
    - - Select all - -
    -
    -
    -
    -
    -
    - -
    -
    - - -
    -
    -
    - There are no machines to show. -
    -
    -
    -
    - - diff --git a/src/app/virtualmachines/vmOverview.component.scss b/src/app/virtualmachines/vmOverview.component.scss deleted file mode 100644 index 8754c9c718..0000000000 --- a/src/app/virtualmachines/vmOverview.component.scss +++ /dev/null @@ -1,71 +0,0 @@ -.dot { - height: 25px; - width: 25px; - background-color: #bbb; - border-radius: 50%; - display: inline-block; - -} - -.dot-colorless { - height: 10px; - width: 10px; - border-radius: 50%; - display: inline-block; -} - -.pulseAnim { - border-radius: 50%; - cursor: pointer; - background: rgb(77, 189, 116); - box-shadow: 0 0 0 rgba(77, 189, 116, 0.4); - -moz-animation: pulse 2s infinite; - -webkit-animation: pulse 2s infinite; - animation: pulse 2s infinite; -} - -@keyframes bouncing-loader { - to { - opacity: 0.1; - transform: translate3d(0, -16px, 0); - } -} - -.bouncingLoader > div, .bouncingLoader:before, .bouncingLoader:after { - display: inline-block; - width: 13px; - height: 13px; - background: #333; - border-radius: 50%; - animation: bouncing-loader 0.6s infinite alternate; -} - -.bouncingLoader > div, .bouncingLoader:before, .bouncingLoader:after { - content: " "; -} - -.bouncingLoader > div { - margin: 0 5px; -} - -.bouncingLoader > div { - animation-delay: 0.2s; -} - -.bouncingLoader:after { - animation-delay: 0.4s; -} - - -@keyframes pulse { - 0% { - box-shadow: 0 0 0 0 rgba(77, 189, 116, 0.4); - } - 70% { - box-shadow: 0 0 0 10px rgba(77, 189, 116, 0); - } - 100% { - box-shadow: 0 0 0 0 rgba(77, 189, 116, 0); - } -} - diff --git a/src/app/virtualmachines/vmOverview.component.ts b/src/app/virtualmachines/vmOverview.component.ts deleted file mode 100644 index 231d550242..0000000000 --- a/src/app/virtualmachines/vmOverview.component.ts +++ /dev/null @@ -1,459 +0,0 @@ -import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core' -import { debounceTime, distinctUntilChanged } from 'rxjs/operators' -import { Subject, Subscription } from 'rxjs' -import { ClipboardService } from 'ngx-clipboard' - -import { VirtualmachineService } from '../api-connector/virtualmachine.service' -import { VirtualMachine } from './virtualmachinemodels/virtualmachine' -import { VirtualMachinePage } from './virtualmachinemodels/virtualMachinePage' -import { FullLayoutComponent } from '../layouts/full-layout.component' -import { UserService } from '../api-connector/user.service' -import { ImageService } from '../api-connector/image.service' -import { FacilityService } from '../api-connector/facility.service' -import { is_vo, elixir_id } from '../shared/globalvar' -import { VirtualMachineStates } from './virtualmachinemodels/virtualmachinestates' -import { GroupService } from '../api-connector/group.service' -import { ClientService } from '../api-connector/client.service' -import { VmCardComponent } from './vmcard/vmcard.component' -import { ApplicationsService } from '../api-connector/applications.service' - -/** - * Vm overview component. - */ -@Component({ - selector: 'app-vm-overview', - templateUrl: 'vmOverview.component.html', - styleUrls: ['./vmOverview.component.scss'], - providers: [FacilityService, ImageService, UserService, FullLayoutComponent, GroupService, ClientService] -}) -export class VmOverviewComponent implements OnInit, OnDestroy { - /** - * Title of page - */ - title: string = 'Instance Overview' - - /** - * Subscription to events - * @private - */ - private subscription: Subscription = new Subscription() - - /** - * States a virtual machine can have - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - /** - * Current page. - */ - currentPage: number = 1 - - /** - * Pagination object which holds vm objects and pagination information - */ - vm_page: VirtualMachinePage = new VirtualMachinePage() - - /** - * Child vm cards to call their functions and get information. - */ - @ViewChildren(VmCardComponent) children: QueryList - - /** - * Debounce time to apply filter if filter was clicked. - */ - LONG_DEBOUNCE_TIME: number = 1000 - - /** - * If cluster machines should be shown. - */ - filter_cluster: boolean = false - - /** - * If machines set for termination should be shown. - */ - filter_set_for_termination: boolean = false - - /** - * List with statuses to filter vms by. - */ - filter_status_list: string[] = [VirtualMachineStates.ACTIVE, VirtualMachineStates.SHUTOFF] - - /** - * If page is loading/searching backend for vms. - */ - isSearching: boolean = true - - /** - * If 'Select all' is clicked. - */ - all_checked: boolean = false - - /** - * Facilities where the user is manager ['name',id]. - */ - public managerFacilities: [string, number][] - - /** - * Chosen facility. - */ - public selectedFacility: [string, number] - - /** - * Custom string value to filter vms by. - */ - filter: string - - /** - * If user is vo admin. - */ - is_vo_admin: boolean - - /** - * Elixir is of user. - */ - user_elixir_id: string - - /** - * Tab which is shown own|all. - * - * @type {string} - */ - tab: string = 'own' - - /** - * If user is manager of a facility. - */ - is_facility_manager: boolean = false - - /** - * If user is allowed to see cluster related things. - */ - cluster_allowed: boolean = false - - /** - * Subject to listen and react to page changes. - */ - vmPerPageChange: Subject = new Subject() - - /** - * List for all machines which are checked. - */ - selectedMachines: VmCardComponent[] = [] - - /** - * List for all not user-owned machines which are checked. - */ - otherSelectedMachines: VmCardComponent[] = [] - - /** - * To check if the user agreed to deleting someone else's VMs - */ - deleteOtherMachines_confirmation: boolean = false - - /** - * List of groups of which the user is admin. - */ - vms_admin: string[] = [] - - /** - * Perun id of user. - */ - user_perun_id: string - - migratedProjectIds: string[] = [] - migratedProjectNames: string[] = [] - - constructor( - private facilityService: FacilityService, - private clipboardService: ClipboardService, - private imageService: ImageService, - private userService: UserService, - private virtualmachineservice: VirtualmachineService, - private groupService: GroupService, - - private applicationsService: ApplicationsService - ) {} - - ngOnInit(): void { - this.set_cluster_allowed() - this.getVms() - this.is_vo_admin = is_vo - this.user_elixir_id = elixir_id - this.get_is_facility_manager() - this.subscription.add( - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - this.managerFacilities = result - this.selectedFacility = this.managerFacilities[0] - }) - ) - this.subscription.add( - this.vmPerPageChange.pipe(debounceTime(this.LONG_DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - this.applyFilter() - }) - ) - } - - ngOnDestroy(): void { - this.subscription.unsubscribe() - } - - /** - * Apply filter to all vms. - */ - applyFilter(): void { - if (this.filter) { - this.filter = this.filter.trim() - } - this.isSearching = true - if (typeof this.vm_page.items_per_page !== 'number' || this.vm_page.items_per_page <= 0) { - this.vm_page.items_per_page = 7 - } - - if (this.tab === 'own') { - this.getVms() - } else if (this.tab === 'all') { - this.getAllVms() - } else if (this.tab === 'facility') { - this.getAllVmsFacilities() - } - } - - /** - * How to track the child vm cards. - * @param index Track by a number or a string. - * @param vm Track by vm openstackid. - */ - trackByVm(index: number | string, vm: VirtualMachine): string { - return vm.openstackid - } - - /** - * Set value if user has a project with cluster allowed status. - */ - set_cluster_allowed(): void { - this.subscription.add( - this.virtualmachineservice.getClusterAllowed().subscribe((res: any): void => { - this.cluster_allowed = res['allowed'] - }) - ) - } - - /** - * Add/Remove status to filter vms by. - * @param status Which status to add/remove from status filter. - */ - changeFilterStatus(status: string): void { - this.currentPage = 1 - const indexOf: number = this.filter_status_list.indexOf(status) - if (indexOf === -1) { - this.filter_status_list.push(status) - } else { - this.filter_status_list.splice(indexOf, 1) - } - } - - /** - * Check if user is a facility manager. - */ - get_is_facility_manager(): void { - this.subscription.add( - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - if (result.length > 0) { - this.is_facility_manager = true - } - }) - ) - } - - /** - * Toggle tab own|all. - * - * @param tabString - */ - toggleTab(tabString: string): void { - this.tab = tabString - } - - /** - * Load vms depending on page. - * - * @param event - */ - pageChanged(event: any): void { - this.isSearching = true - - this.currentPage = event.page - if (this.tab === 'own') { - this.getVms() - } else if (this.tab === 'all') { - this.getAllVms() - } else if (this.tab === 'facility') { - this.getAllVmsFacilities() - } - } - - /** - * Get all vms of user. - */ - getVms(): void { - this.subscription.add( - this.virtualmachineservice - .getVmsFromLoggedInUser( - this.currentPage, - this.vm_page.items_per_page, - this.filter, - this.filter_status_list, - this.filter_cluster, - this.filter_set_for_termination - ) - .subscribe((vm_page: VirtualMachinePage): void => { - this.vm_page = vm_page - this.generateMigratedProjectIdList() - this.generateMigratedProjectNamesList() - this.prepareVMS() - }) - ) - } - - generateMigratedProjectIdList(): void { - this.migratedProjectIds = [] - this.vm_page.vm_list.forEach((vm: VirtualMachine) => { - if (vm.migrate_project_to_simple_vm || vm.project_is_migrated_to_simple_vm) { - this.migratedProjectIds.push(vm.projectid.toString()) - } - const unique = (arr: string[]): string[] => [...new Set(arr)] - this.migratedProjectIds = unique(this.migratedProjectIds) - }) - } - generateMigratedProjectNamesList(): void { - this.migratedProjectNames = [] - this.vm_page.vm_list.forEach((vm: VirtualMachine) => { - if (vm.migrate_project_to_simple_vm || vm.project_is_migrated_to_simple_vm) { - this.migratedProjectNames.push(vm.project) - } - }) - } - - /** - * Get all vms of a facility. - */ - getAllVmsFacilities(): void { - this.subscription.add( - this.virtualmachineservice - .getVmsFromFacilitiesOfLoggedUser( - this.selectedFacility['FacilityId'], - this.currentPage, - this.vm_page.items_per_page, - this.filter, - this.filter_status_list, - this.filter_cluster, - this.filter_set_for_termination - ) - .subscribe((vm_page: VirtualMachinePage): void => { - this.vm_page = vm_page - this.prepareVMS() - }) - ) - } - - /** - * Checks and lists machines for which the visiting user is a project-administrator - */ - checkVMAdminState(): void { - this.subscription.add( - this.userService.getMemberByUser().subscribe((res: any): void => { - this.user_perun_id = res['userId'] - this.vm_page.vm_list.forEach((vm: VirtualMachine): void => { - this.subscription.add( - this.groupService.isLoggedUserGroupAdmin(vm.projectid).subscribe((result): any => { - if (result['admin']) { - this.vms_admin.push(vm.openstackid) - } - }) - ) - }) - }) - ) - } - - /** - * Prepare to show vms. - */ - prepareVMS(): void { - this.checkVMAdminState() - this.children.forEach((child: VmCardComponent) => { - child.restartAndResumeCheckStatusTimer() - }) - this.isSearching = false - } - - /** - * Get all vms. - */ - getAllVms(): void { - this.subscription.add( - this.virtualmachineservice - .getAllVM( - this.currentPage, - this.vm_page.items_per_page, - this.filter, - this.filter_status_list, - this.filter_cluster, - this.filter_set_for_termination - ) - .subscribe((vm_page: VirtualMachinePage): void => { - this.vm_page = vm_page - this.prepareVMS() - }) - ) - } - - /** - * Called if 'Select all' is toggled. Will call a function of every child vm card with value of 'Select all'. - */ - toggleAllChecked(): void { - this.all_checked = !this.all_checked - this.children.forEach((child: VmCardComponent) => { - child.toggleAllChecked(this.all_checked) - }) - } - - /** - * Function to be called if a vm card child emits a checked event. Does not trust the emitted event and checks all - * vm cards for their checked values. - */ - childChecked(): void { - let total: number = 0 - let total_child_checked: number = 0 - this.children.forEach((child: VmCardComponent) => { - total += child.is_checkable() - total_child_checked += child.vm_is_checked() - }) - this.all_checked = total_child_checked === total - } - - /** - * Delete all vms which are in selectedMachines list. - */ - deleteAllCheckedVms(): void { - this.selectedMachines.forEach((child: VmCardComponent) => { - child.deleteVM() - }) - } - - /** - * Gather all vms which are checked. - */ - gatherAllSelectedVMs(): void { - this.selectedMachines = [] - this.otherSelectedMachines = [] - this.children.forEach((child: VmCardComponent) => { - if (child.is_checked) { - if (this.user_elixir_id !== child.vm.elixir_id) { - this.otherSelectedMachines.push(child) - } - this.selectedMachines.push(child) - } - }) - } -} diff --git a/src/app/virtualmachines/vm_routing.module.ts b/src/app/virtualmachines/vm_routing.module.ts deleted file mode 100644 index 11423d3c6d..0000000000 --- a/src/app/virtualmachines/vm_routing.module.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' -import { VirtualMachineComponent } from './addvm.component' -import { VmOverviewComponent } from './vmOverview.component' -import { VolumeOverviewComponent } from './volumes/volumeOverview.component' -import { SnapshotOverviewComponent } from './snapshots/snapshotOverview.component' -import { VmDetailComponent } from './vmdetail/vmdetail.component' -import { AddClusterComponent } from './clusters/add-cluster/add-cluster.component' -import { ClusterdetailComponent } from './clusters/clusterdetail/clusterdetail.component' -import { ClusterOverviewComponent } from './clusters/clusteroverview/clusterOverview.component' -import { AddWorkshopComponent } from './workshop/add-workshop/add-workshop.component' -import { WorkshopOverviewComponent } from './workshop/workshop-overview/workshop-overview.component' - -const routes: Routes = [ - { - path: 'newVM', - component: VirtualMachineComponent, - data: { - title: 'New Instance' - } - }, - { - path: 'newCluster', - component: AddClusterComponent, - data: { - title: 'New Cluster' - } - }, - { - path: 'newWorkshop', - component: AddWorkshopComponent, - data: { - title: 'New Workshop VMs' - } - }, - { - path: 'vmOverview', - component: VmOverviewComponent, - data: { - title: 'VM Overview' - } - }, - { - path: 'workshopOverview', - component: WorkshopOverviewComponent, - data: { - title: 'Workshop management' - } - }, - { - path: 'clusterOverview', - component: ClusterOverviewComponent, - data: { - title: 'Cluster Overview' - } - }, - { - path: 'cluster/:id', - component: ClusterdetailComponent, - data: { - title: 'Cluster Detail' - } - }, - { - path: 'detail/:id', - component: VmDetailComponent, - data: { - title: 'VM Detail' - } - }, - { - path: 'volumeOverview', - component: VolumeOverviewComponent, - data: { - title: 'Volumes Overview' - } - }, - { - path: 'snapshotOverview', - component: SnapshotOverviewComponent, - data: { - title: 'Snapshots Overview' - } - } -] - -/** - * Vm routing module. - */ -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class VmRoutingModule {} diff --git a/src/app/virtualmachines/vmcard/vmcard.component.html b/src/app/virtualmachines/vmcard/vmcard.component.html deleted file mode 100644 index 34dfb4c69b..0000000000 --- a/src/app/virtualmachines/vmcard/vmcard.component.html +++ /dev/null @@ -1,573 +0,0 @@ -
    -
    -
    -
    - - - {{ vm?.name }} - - - - - - {{ vm?.name }} - - - -
    - - -
    - {{ vm?.userlogin }} -
    - {{ vm?.created_at_date }} -
    -
    -
    - -
    -
    -
    -
    - - -
    -
    -
    - - - {{ vm?.volumes.length }} - - -
    -
    - - - - - - -
    -
    - - - - - -
    -
    - - - {{ vm?.conda_packages?.length.toString() }} - - - - - - - - {{ vm?.conda_packages?.length.toString() }} - - - - - -
    -
    - - - {{ vm?.cluster.instances_count }} - - -
    -
    -
    - -
    -
    -
    - {{ vm?.flavor?.name }}: {{ vm?.flavor?.vcpus + ' VCPUs - ' }}{{ vm?.flavor?.ram_gib + ' GB RAM - ' - }}{{ vm?.flavor?.rootdisk + ' GB root disk' }} -
    -
    -
    -
    Image: {{ vm?.image }}
    -
    -
    - -
    -
    - -
    - -
    -
    - -
    -
    -
    - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    - You are not able to control this instance via this platform as it is part of a migrated project! You can - access the new platform here: - {{ - NEW_SVM_PORTAL_LINK - }} -
    -
    -
    -
    - - -
    diff --git a/src/app/virtualmachines/vmcard/vmcard.component.scss b/src/app/virtualmachines/vmcard/vmcard.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/vmcard/vmcard.component.ts b/src/app/virtualmachines/vmcard/vmcard.component.ts deleted file mode 100644 index a6b5c2e7c1..0000000000 --- a/src/app/virtualmachines/vmcard/vmcard.component.ts +++ /dev/null @@ -1,656 +0,0 @@ -import { Component, Input, Output, EventEmitter, OnDestroy, OnInit } from '@angular/core' -import { ClipboardService } from 'ngx-clipboard' -import { Subscription } from 'rxjs' -import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal' -import { VirtualMachine } from '../virtualmachinemodels/virtualmachine' -import { VirtualMachineStates } from '../virtualmachinemodels/virtualmachinestates' -import { - WIKI_GUACAMOLE_LINK, - WIKI_RSTUDIO_LINK, - WIKI_PERSISTENT_TERMINAL_LINK, - WIKI_JUPYTERLAB_LINK, - NEW_SVM_PORTAL_LINK -} from '../../../links/links' -import { TemplateNames } from '../conda/template-names' -import { StopVmComponent } from '../modals/stop-vm/stop-vm.component' -import { VirtualmachineService } from '../../api-connector/virtualmachine.service' -import { ResumeVmComponent } from '../modals/resume-vm/resume-vm.component' -import { DeleteVmComponent } from '../modals/delete-vm/delete-vm.component' -import { SnapshotModel } from '../snapshots/snapshot.model' -import { ImageService } from '../../api-connector/image.service' -import { SnapshotVmComponent } from '../modals/snapshot-vm/snapshot-vm.component' -import { VolumeVmComponent } from '../modals/volume-vm/volume-vm.component' -import { Volume } from '../volumes/volume' -import { IResponseTemplate } from '../../api-connector/response-template' -import { RebootVmComponent } from '../modals/reboot-vm/reboot-vm.component' -import { RecreateBackendVmComponent } from '../modals/recreate-backend-vm/recreate-backend-vm.component' - -/** - * Vm card component to be used by vm-overview. Holds information about a virtual machine. - */ -@Component({ - selector: 'app-vm-card', - templateUrl: 'vmcard.component.html', - styleUrls: ['./vmcard.component.scss'], - providers: [ImageService] -}) -export class VmCardComponent implements OnInit, OnDestroy { - /** - * The virtual machine this card is for. - */ - @Input() vm: VirtualMachine - - /** - * Possible virtual machine states. - */ - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - - /** - * Is the vm checked. - */ - is_checked: boolean = false - - /** - * Eventemitter when the vm is checked/unchecked. - */ - @Output() check_change_event: EventEmitter = new EventEmitter() - - /** - * Elixir id of the user. - */ - @Input() user_elixir_id: string = '' - - /** - * If the user is a vo admin. - */ - @Input() is_vo_admin: boolean = false - - /** - * If the user is an admin of the group the vm belongs to. - */ - @Input() is_vm_admin: boolean = false - - /** - * Link to rstudio wiki - */ - WIKI_RSTUDIO_LINK: string = WIKI_RSTUDIO_LINK - WIKI_JUPYTERLAB_LINK: string = WIKI_JUPYTERLAB_LINK - - /** - * Link to guacamole wiki. - */ - WIKI_GUACAMOLE_LINK: string = WIKI_GUACAMOLE_LINK - - /** - * Link to persistent terminal sessions tutorial. - */ - WIKI_PERSISTENT_TERMINAL_LINK: string = WIKI_PERSISTENT_TERMINAL_LINK - - /** - * Subscription object to listen to different events. - */ - subscription: Subscription = new Subscription() - - /** - * Modal reference to be changed/showed/hidden depending on chosen modal. - */ - bsModalRef: BsModalRef - - /** - * Default wait time between status checks if no other value specified. - * @private - */ - private checkStatusTimeout: number = 5000 - - /** - * Default time in ms to show an error message if no other value specified. - */ - ERROR_TIMER: number = 10000 - - /** - * Error message to show if 409 status was returned, typically returned if vm is creating a snapshot. - */ - SNAPSHOT_CREATING_ERROR_MSG: string = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - - /** Error message to when reboot failed - * - */ - REBOOT_ERROR_MSG: string = 'Reboot of machine failed. If the error persists, please contact the support.' - - /** - * Timeout object to control check status loop (i.e. stopping and starting check status loop). - */ - checkStatusTimer: ReturnType - - /** - * Constant message for connection issues with client/OpenStack to ensure that the user knows that the information may not be up-to-date. - */ - TIMEOUT_ALERT_MESSAGE: string = - 'The information available here may not be up-to-date. This is due to connection problems with the compute center. If necessary, try again later.' - - /** - * String which can be filled with information in case any problems occur or additional information needs to be placed. - */ - alertMessage: string = '' - - /** - * Bool which indicates whether the alert with additional information is shown or not. - */ - alertVisible: boolean = false - - constructor( - private clipboardService: ClipboardService, - private modalService: BsModalService, - private virtualmachineservice: VirtualmachineService, - private imageService: ImageService - ) { - - } - - ngOnInit() { - this.resumeCheckStatusTimer() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - this.stopCheckStatusTimer() - } - - /** - * Start the check status loop without arguments. - */ - resumeCheckStatusTimer(): void { - this.check_status_loop() - } - - /** - * Stop and clear the check status loop. Then resume it with a value between 1 second and 3 seconds. - */ - restartAndResumeCheckStatusTimer(): void { - this.stopCheckStatusTimer() - // so not all requests are at the same time for the vms - const min: number = 1000 - const max: number = 3000 - this.check_status_loop(null, Math.floor(Math.random() * (max - min)) + min) - } - - /** - * Stop and clear the check status loop. - */ - stopCheckStatusTimer(): void { - if (this.checkStatusTimer) { - clearTimeout(this.checkStatusTimer) - } - } - - /** - * Show stop modal. - */ - showStopModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(StopVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - recreateBackend(): void { - this.subscription.add( - this.virtualmachineservice.recreateVmBackend(this.vm.openstackid).subscribe( - (updated_vm: VirtualMachine) => { - this.vm.backend = updated_vm.backend - this.vm.setMsgWithTimeout('Backend was successfully recreated!') - }, - () => { - this.vm.setErrorMsgWithTimeout('Failed to recreate the backend!', this.ERROR_TIMER) - } - ) - ) - } - - /** - * Run function to stop a vm. - */ - stopVM(): void { - this.subscription.add( - this.virtualmachineservice.stopVM(this.vm.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - updated_vm.cardState = 0 - this.vm = updated_vm - if (this.vm.status === VirtualMachineStates.SHUTOFF) { - this.resumeCheckStatusTimer() - } else { - this.check_status_loop(VirtualMachineStates.SHUTOFF) - } - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - this.resumeCheckStatusTimer() - } - } - ) - ) - } - - /** - * Show attach/detach modal. - */ - showVolumeModal(mode: string): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm, mode } - - this.bsModalRef = this.modalService.show(VolumeVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Show attach/detach modal. - */ - showRecreateBackendModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(RecreateBackendVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Run function to attach a volume to a vm. - */ - attachVolume(volume: Volume): void { - this.vm.status = VirtualMachineStates.GETTING_STATUS - this.subscription.add( - this.virtualmachineservice.attachVolumetoServer(volume.volume_openstackid, this.vm.openstackid).subscribe( - (result: IResponseTemplate): void => { - if (result.value === 'attached') { - this.vm.setMsgWithTimeout('Volume attached') - this.check_status_loop(null, 1000) - } else { - this.vm.setErrorMsgWithTimeout('Volume not attached') - this.resumeCheckStatusTimer() - } - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - this.resumeCheckStatusTimer() - } - } - ) - ) - } - - /** - * Run function to detach a volume from a vm. - */ - detachVolume(volume: Volume): void { - this.vm.status = VirtualMachineStates.GETTING_STATUS - this.subscription.add( - this.virtualmachineservice.deleteVolumeAttachment(volume.volume_openstackid, this.vm.openstackid).subscribe( - (result: any): void => { - if (result.value === 'deleted') { - this.vm.setMsgWithTimeout('Volume detached') - this.check_status_loop(null, 1000) - } else { - this.vm.setErrorMsgWithTimeout('Volume not detached') - this.resumeCheckStatusTimer() - } - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - } - } - ) - ) - } - - /** - * Show resume/restart modal. - */ - showRestartModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(ResumeVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Run function to resume a shutoff vm. - */ - resumeVM(): void { - this.subscription.add( - this.virtualmachineservice.resumeVM(this.vm.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - updated_vm.cardState = 0 - this.vm = updated_vm - if (this.vm.status === VirtualMachineStates.ACTIVE) { - this.resumeCheckStatusTimer() - } else { - this.check_status_loop(VirtualMachineStates.ACTIVE) - } - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - this.resumeCheckStatusTimer() - } - } - ) - ) - } - - /** - * Show hard/soft reboot modal. - */ - showRebootModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(RebootVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Run function to soft/hard reboot a vm. - */ - rebootVM(reboot_type: string): void { - this.vm.status = VirtualMachineStates.GETTING_STATUS - this.subscription.add( - this.virtualmachineservice.rebootVM(this.vm.openstackid, reboot_type).subscribe( - (result: IResponseTemplate): void => { - this.vm.cardState = 0 - if (result.value as boolean) { - this.vm.setMsgWithTimeout('Reboot initiated', 5000) - this.resumeCheckStatusTimer() - } else { - this.check_status_loop(VirtualMachineStates.ACTIVE) - } - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.REBOOT_ERROR_MSG, this.ERROR_TIMER) - } - } - ) - ) - } - - /** - * Show snapshot modal. - */ - showSnapshotModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(SnapshotVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Run function to create a snapshot of a vm. - */ - createSnapshot(snapshot_name: string, description?: string): void { - this.vm.setMsgWithTimeout('Queuing Snapshot...') - const final_state: string = this.vm.status - this.vm.status = VirtualMachineStates.IMAGE_PENDING_UPLOAD - this.subscription.add( - this.imageService.createSnapshot(this.vm.openstackid, snapshot_name.trim(), description).subscribe( - (newSnapshot: SnapshotModel): void => { - if (!newSnapshot.snapshot_openstackid) { - this.vm.setErrorMsgWithTimeout('Error creating Snapshot', this.ERROR_TIMER) - } else { - const text: string = `Successfully queued Snapshot.
    - It might take some minutes till you can use it for starting a new instance at the "New Instance" tab.
    - You can see the current status in the Snapshot Overview.` - this.vm.setMsgWithTimeout(text, 30000) - } - this.check_status_loop(final_state, 15000) - }, - (error1: any): void => { - if (error1['error']['error'] === '409') { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - this.resumeCheckStatusTimer() - } - } - ) - ) - } - - /** - * Show deletion modal - */ - showDeleteModal(): void { - this.stopCheckStatusTimer() - const initialState = { virtualMachine: this.vm } - - this.bsModalRef = this.modalService.show(DeleteVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Run function to delete a vm. - */ - deleteVM(): void { - this.is_checked = false - this.vm.status = VirtualMachineStates.DELETING - this.vm.cardState = 0 - this.subscription.add( - this.virtualmachineservice.deleteVM(this.vm.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - updated_vm.cardState = 0 - - if (updated_vm.status !== VirtualMachineStates.DELETED) { - setTimeout((): void => { - this.deleteVM() - }, this.checkStatusTimeout) - } else { - this.stopCheckStatusTimer() - this.vm = updated_vm - } - }, - (error1: any): void => { - if (error1['status'] === 409) { - this.vm.setErrorMsgWithTimeout(this.SNAPSHOT_CREATING_ERROR_MSG, this.ERROR_TIMER) - } - } - ) - ) - } - - /** - * Function to listen to modal results. - */ - subscribeToBsModalRef(): void { - this.subscription.add( - this.bsModalRef.content.event.subscribe((result: any) => { - if ('recreateBackendVM' in result) { - this.recreateBackend() - } else if ('resume' in result) { - this.resumeCheckStatusTimer() - } else if ('stopVM' in result) { - this.stopVM() - } else if ('resumeVM' in result) { - this.resumeVM() - } else if ('deleteVM' in result) { - this.deleteVM() - } else if ('snapshotVM' in result) { - this.createSnapshot(result['snapshotName'], result['description']) - } else if ('attachVolume' in result) { - this.attachVolume(result['volume']) - } else if ('detachVolume' in result) { - this.detachVolume(result['volume']) - } else if ('reboot_type' in result) { - this.rebootVM(result['reboot_type']) - } - }) - ) - } - - showAlert(message: string): void { - switch (message) { - case 'TIMEOUT': - this.alertMessage = this.TIMEOUT_ALERT_MESSAGE - break - default: - this.alertMessage = '' - } - this.alertVisible = true - } - - /** - * Loop which checks status of a vm depending on its status. Will always stop the timer if it exists first. - */ - check_status_loop(final_state?: string, timeout: number = this.checkStatusTimeout): void { - this.stopCheckStatusTimer() - this.checkStatusTimer = setTimeout((): void => { - this.subscription.add( - this.virtualmachineservice - .checkVmStatus(this.vm.openstackid, this.vm.name) - .subscribe((updated_vm: VirtualMachine): void => { - updated_vm.cardState = this.vm.cardState - if (this.vm.msg) { - updated_vm.setMsgWithTimeout(this.vm.msg) - } - if (this.vm.error_msg) { - updated_vm.setErrorMsgWithTimeout(this.vm.error_msg) - } - this.vm = updated_vm - if (this.vm.status === VirtualMachineStates.ACTIVE) { - if (this.vm.volumes?.length > 0) { - const volumeIds: string[] = [] - for (const vol of this.vm.volumes) { - volumeIds.push(vol.volume_openstackid) - } - this.virtualmachineservice.triggerVolumeUpdate(volumeIds).subscribe( - (): void => { - this.alertVisible = false - }, - (error: Response): void => { - if (error.status === 408) { - // timeout for request - this.showAlert('TIMEOUT') - } - } - ) - } - } - if (final_state) { - if (final_state === this.vm.status) { - this.resumeCheckStatusTimer() - } else { - this.check_status_loop(final_state) - } - } else if (VirtualMachineStates.IN_PROCESS_STATES.indexOf(this.vm.status) !== -1) { - this.check_status_loop() - } else if (this.vm.status === VirtualMachineStates.MIGRATED) { - this.stopCheckStatusTimer() - } else if (this.vm.status !== VirtualMachineStates.DELETED) { - // so not all requests are at the same time for the vms - const min: number = 20000 - const max: number = 40000 - this.check_status_loop(null, Math.floor(Math.random() * (max - min)) + max) - } - }) - ) - }, timeout) - } - - /** - * Function called by parent if 'Select all' was clicked. - */ - toggleAllChecked(all_checked: boolean): void { - if ( - (this.vm.status === VirtualMachineStates.ACTIVE || this.vm.status === VirtualMachineStates.SHUTOFF) && - !(this.vm.project_is_migrated_to_simple_vm || this.vm.migrate_project_to_simple_vm) - ) { - this.is_checked = all_checked - } else { - this.is_checked = false - } - } - - /** - * Toggle checked status and notify parent. - */ - toggleChecked(): void { - this.is_checked = !this.is_checked - if (this.is_checked) { - this.check_change_event.emit(1) - } else { - this.check_change_event.emit(-1) - } - } - - /** - * Function to call by parent. Returns 1 if vm is active or shutoff, -1 otherwise. - */ - is_checkable(): number { - if (this.vm.status === VirtualMachineStates.ACTIVE || this.vm.status === VirtualMachineStates.SHUTOFF) { - return 1 - } else { - return -1 - } - } - - /** - * Function to call by parent. Returns 1 if vm is active or shutoff and checked, -1 otherwise. - */ - vm_is_checked(): number { - if ( - (this.vm.status === VirtualMachineStates.ACTIVE || this.vm.status === VirtualMachineStates.SHUTOFF) && - this.is_checked - ) { - return 1 - } else { - return -1 - } - } - - /** - * Copy some text to clipboard. - */ - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - /** - * Show message in span that text was copied. - */ - showCopiedMessage(name: string): void { - const span_id: string = `${name}resenvSpan` - const { innerHTML } = document.getElementById(span_id) - document.getElementById(span_id).innerHTML = 'Copied URL!' - setTimeout((): void => { - document.getElementById(span_id).innerHTML = innerHTML - }, 1000) - } - - /** - * Return false if resenv was not started by playbook (e.g. by Image instead). - */ - resenv_by_play(vm: VirtualMachine): boolean { - for (const mode of vm.modes) { - if (TemplateNames.ALL_TEMPLATE_NAMES.indexOf(mode.name) !== -1) { - return false - } - } - - return true - } - - protected readonly NEW_SVM_PORTAL_LINK = NEW_SVM_PORTAL_LINK -} diff --git a/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.html b/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.html deleted file mode 100644 index 376c631140..0000000000 --- a/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.html +++ /dev/null @@ -1,115 +0,0 @@ -
    -
    - - -
    - Created at (d-m-y)
    - {{ virtualMachine.created_at_date }} -
    -
    - -
    - Created at (d-m-y)
    - {{ virtualMachine.created_at_date }} -
    -
    - -
    - Created at (d-m-y)
    - {{ virtualMachine.created_at_date }} -
    -
    - -
    - Created at (d-m-y)
    - {{ virtualMachine.created_at_date }} -
    -
    - -
    - Deleted at (d-m-y)
    - {{ virtualMachine.deleted_at_date | date: 'dd-MM-yyyy' }} -
    -
    - -
    - Created at (d-m-y)
    - {{ virtualMachine.created_at_date }} -
    -
    -
    -
    -
    -
    - Created by
    - {{ virtualMachine.userlogin }} -
    -
    -
    -
    - Elixir-ID of {{ virtualMachine.userlogin }}
    - {{ virtualMachine.elixir_id }} -
    -
    -
    -
    -
    -
    - Usage confirmation requested at (d-m-y)
    - {{ - virtualMachine.still_used_confirmation_requested_date | date: 'dd-MM-yyyy' - }} -
    -
    - -
    -
    - Usage confirmed at (d-m-y)
    - {{ virtualMachine.still_used_confirmed_date | date: 'dd-MM-yyyy' }} -
    -
    -
    -
    - Usage confirmed by {{ virtualMachine.still_used_confirmed_user_id }}
    - {{ this.userSurname }}, {{ this.userName }} -
    -
    -
    - -
    -
    - Usage confirmed at (d-m-y)
    - Usage not confirmed yet! -
    -
    -
    -
    - -
    - -
    -
    - Openstack-ID
    - {{ virtualMachine.openstackid }} -
    -
    -
    -
    - Private IP
    - {{ virtualMachine.fixed_ip }} -
    -
    -
    diff --git a/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.scss b/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.ts b/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.ts deleted file mode 100644 index 73243b4c43..0000000000 --- a/src/app/virtualmachines/vmdetail/virtualmachineinfo/virtualmachineinfo.component.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Component, Input, OnChanges, SimpleChanges, OnInit, ChangeDetectorRef } from '@angular/core' -import { UserService } from 'app/api-connector/user.service' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' - -/** - * Virtualmachine info component - */ -@Component({ - selector: 'app-virtualmachineinfo', - templateUrl: './virtualmachineinfo.component.html', - styleUrls: ['./virtualmachineinfo.component.scss'], - - providers: [UserService] -}) -export class VirtualmachineinfoComponent implements OnChanges, OnInit { - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - @Input() virtualMachine: VirtualMachine - @Input() cluster_machine: boolean = false - - userName: string = '' - userSurname: string = '' - - constructor( - private userService: UserService, - private changeDetectorRef: ChangeDetectorRef - ) { - this.userService = userService - this.changeDetectorRef = changeDetectorRef - } - - ngOnInit(): void { - if (this.virtualMachine) { - if (this.virtualMachine.still_used_confirmed_user_id) { - this.userService - .getMemberDetailsByElixirId(this.virtualMachine.still_used_confirmed_user_id) - .subscribe((result: any) => { - this.userName = result['firstName'] - this.userSurname = result['lastName'] - this.changeDetectorRef.detectChanges() - }) - } - } - } - - ngOnChanges(changes: SimpleChanges): void { - const { changedVM } = changes - console.log(changedVM) - if (changedVM) { - if (changedVM['virtualMachine']['currentValue']['still_used_confirmed_user_id']) { - this.userService - .getMemberDetailsByElixirId(this.virtualMachine.still_used_confirmed_user_id) - .subscribe((result: any) => { - this.userName = result['firstName'] - this.userSurname = result['lastName'] - this.changeDetectorRef.detectChanges() - }) - } - } - } -} diff --git a/src/app/virtualmachines/vmdetail/vmdetail.component.html b/src/app/virtualmachines/vmdetail/vmdetail.component.html deleted file mode 100644 index 8bdb2df551..0000000000 --- a/src/app/virtualmachines/vmdetail/vmdetail.component.html +++ /dev/null @@ -1,1166 +0,0 @@ -
    - The Virtual Machine could not be found. -
    - -
    - -
    -
    -
    -
    -
    - {{ virtualMachine?.name }} - -
    -
    -
    - This machine has been consuming resources for {{ virtualMachine?.days_running }} days!
    - Please confirm that you still need this machine.
    - Otherwise, the machine is scheduled for deletion starting from - {{ virtualMachine?.getTerminationStartDateString() }}.
    -
    -

    - If this machine is no longer needed, back up your data if necessary and delete the machine. Stopping the - machine alone does not release the used resources. -
    - Note: - You can save the state of your machine in a snapshot before shutting down and deleting the machine, and - continue working based on that snapshot. Learn more about creating snapshots - here. -
    - If necessary, do not forget to back up important data. Please save the data on a suitable medium. At best, - save the data offline. You can use volumes, but these are subject to the usual risk of cloud services. You - can learn more about the use of volumes - here. -
    - We are not liable for the loss of data due to faulty machines or volumes. -

    - - -
    - Please consider
    - In this case, you confirm as a administrator of the project that the project member who started this - machine still needs it. -
    - - -
    -
    -
    - -
    -
    - -
    -
    -
    - - Connect Information -
    -
    -
    -
    -
    - via
    - {{ mode.name }} -
    -
    -
    -
    - with
    - -
    -
    -
    -
    - Copy Command -
    -
    -
    -
    -
    -

    - Learn more about persistent terminal sessions when using ssh: - Tutorial -

    -
    -
    -
    -
    - Research Environment: -
    -
    - {{ - virtualMachine?.res_env_url - }} -
    - For RStudio credentials please visit: - {{ - WIKI_RSTUDIO_LINK - }} -
    - For Apache Guacamole credentials please visit: - {{ - WIKI_GUACAMOLE_LINK - }} -
    -
    -
    -
    -
    - - Connect Information -
    -
    -
    - There currently is no connect information available, as the machine is in error-state. -
    -
    -
    -
    - -
    -
    - Actions -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    - You are not able to control this machine using the current platform. You can access the new platform - here: - {{ - NEW_SVM_PORTAL_LINK - }} -
    -
    -
    -
    - -
    -
    Flavor Information
    -
    -
    -
    -
    - Name
    - {{ virtualMachine?.flavor?.name }} -
    -
    -
    -
    - Number of VCPUs
    - {{ virtualMachine?.flavor?.vcpus }} -
    -
    -
    -
    - RAM
    - {{ virtualMachine?.flavor?.ram_gib }} GB -
    -
    -
    -
    -
    -
    - Rootdisk
    - {{ virtualMachine?.flavor?.rootdisk }} GB -
    -
    -
    -
    - Ephemeral disk
    - {{ virtualMachine?.flavor?.ephemeral_disk }} GB -
    -
    -
    - -
    -
    -
    - Flavor type
    - {{ virtualMachine?.flavor?.type?.long_name }} -
    -
    -
    -
    - GPU cores
    - {{ virtualMachine?.flavor?.gpu }} -
    -
    -
    -
    - You can check which CUDA drivers are currently supported here:
    - -
    -
    -
    -
    -
    -
    - Comment
    - {{ virtualMachine?.flavor?.comment }} -
    -
    -
    -
    -
    - -
    -
    Image Information
    -
    -
    -
    -
    - -
    -
    -
    -
    - Name
    - {{ image?.name }} -
    -
    -
    -
    - Image-Type
    - Snapshot -
    -
    -
    -
    -
    -
    - Description
    - {{ image?.description }} -
    -
    -
    -
    -
    - -
    - -
    Installed Conda Packages
    -
    -
    -
    -
    -
    -
    - Package name
    - {{ pkg.name }} -
    -
    - Version
    - {{ pkg.version }} -
    -
    -
    -
    -
    -
    -
    - -
    -
    Attached Volumes
    -
    -
    -
    -
    - Name
    - {{ vol?.volume_name }} -
    -
    -
    -
    - Status
    - -
    -
    -
    -
    - Storage
    - {{ vol?.volume_storage }} GB -
    -
    -
    -
    -
    -
    - Volume ID
    - {{ vol?.volume_openstackid }} -
    -
    -
    -
    - Initially attached to
    - /vol/{{ vol?.volume_path }} -
    -
    -
    -
    - Device
    - {{ vol?.volume_device }} -
    -
    -
    -
    -
    -
    - Actions -
    -
    -
    - -
    -
    -
    You are not able to detach this volume using the current platform.
    -
    -
    -
    -
    -
    - -
    -
    Attachable volumes
    -
    -
    -
    -
    - Name
    - {{ vol?.volume_name }} -
    -
    -
    -
    - Status
    - - -
    -
    - -
    -
    - Storage
    - {{ vol?.volume_storage }} GB -
    -
    -
    -
    -
    -
    - Volume ID
    - {{ vol?.volume_openstackid }} -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    Research Environment
    -
    -
    -
    -
    - -
    -
    -
    -
    - Name
    - {{ resenvTemplate.title }} - - {{ - resenvTemplate.title - }} -
    -
    -
    -
    - Description
    - {{ resenvTemplate.description }} -
    -
    - -
    -
    - -
    User management
    -
    -
    - - -
    -
    -
    - - - - - - - - - - - - - - - - - -
    User IDMember IDFull NameActions
    - {{ member['user_id'] }} - {{ member['member_id'] }}{{ member['firstName'] }} {{ member['lastName'] }} - -
    -
    -
    -
    -
    - -
    -
    Ansible/Conda/Research-environment logs
    -
    -
    - - -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    - - - -
    diff --git a/src/app/virtualmachines/vmdetail/vmdetail.component.scss b/src/app/virtualmachines/vmdetail/vmdetail.component.scss deleted file mode 100644 index 3f61861af2..0000000000 --- a/src/app/virtualmachines/vmdetail/vmdetail.component.scss +++ /dev/null @@ -1,47 +0,0 @@ - - -@keyframes bouncing-loader { - to { - opacity: 0.1; - transform: translate3d(0, -16px, 0); - } -} - -.bouncingLoader > div, .bouncingLoader:before, .bouncingLoader:after { - display: inline-block; - width: 13px; - height: 13px; - background: #333; - border-radius: 50%; - animation: bouncing-loader 0.6s infinite alternate; -} - -.bouncingLoader > div, .bouncingLoader:before, .bouncingLoader:after { - content: " "; -} - -.bouncingLoader > div { - margin: 0 5px; -} - -.bouncingLoader > div { - animation-delay: 0.2s; -} - -.bouncingLoader:after { - animation-delay: 0.4s; -} - - -@keyframes pulse { - 0% { - box-shadow: 0 0 0 0 rgba(77, 189, 116, 0.4); - } - 70% { - box-shadow: 0 0 0 10px rgba(77, 189, 116, 0); - } - 100% { - box-shadow: 0 0 0 0 rgba(77, 189, 116, 0); - } -} - diff --git a/src/app/virtualmachines/vmdetail/vmdetail.component.ts b/src/app/virtualmachines/vmdetail/vmdetail.component.ts deleted file mode 100644 index ff679dcf29..0000000000 --- a/src/app/virtualmachines/vmdetail/vmdetail.component.ts +++ /dev/null @@ -1,822 +0,0 @@ -import { Component, OnInit, ChangeDetectorRef } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { Subject, Subscription } from 'rxjs' -import { debounceTime, distinctUntilChanged } from 'rxjs/operators' -import { ClipboardService } from 'ngx-clipboard' -import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal' - -import { FlavorService } from '../../api-connector/flavor.service' -import { ApplicationsService } from '../../api-connector/applications.service' -import { FacilityService } from '../../api-connector/facility.service' -import { VoService } from '../../api-connector/vo.service' -import { UserService } from '../../api-connector/user.service' -import { GroupService } from '../../api-connector/group.service' -import { CreditsService } from '../../api-connector/credits.service' -import { AbstractBaseClass } from '../../shared/shared_modules/baseClass/abstract-base-class' -import { VirtualMachine } from '../virtualmachinemodels/virtualmachine' -import { VirtualmachineService } from '../../api-connector/virtualmachine.service' -import { ImageService } from '../../api-connector/image.service' -import { Image } from '../virtualmachinemodels/image' -import { VirtualMachineStates } from '../virtualmachinemodels/virtualmachinestates' -import { IResponseTemplate } from '../../api-connector/response-template' -import { SnapshotModel } from '../snapshots/snapshot.model' -import { PlaybookService } from '../../api-connector/playbook.service' -import { BiocondaService } from '../../api-connector/bioconda.service' -import { ResenvTemplate } from '../conda/resenvTemplate.model' -import { elixir_id, is_vo } from '../../shared/globalvar' -import { - NEW_SVM_PORTAL_LINK, - WIKI_CREATE_SNAPSHOT_LINK, - WIKI_GUACAMOLE_LINK, - WIKI_PERSISTENT_TERMINAL_LINK, - WIKI_RSTUDIO_LINK, - WIKI_VOLUME_OVERVIEW -} from '../../../links/links' -import { Volume } from '../volumes/volume' -import { VolumeStates } from '../volumes/volume_states' -import { Condalog } from '../conda/condalog' -import { Backend } from '../conda/backend/backend' -import { DeleteVmComponent } from '../modals/delete-vm/delete-vm.component' -import { TemplateNames } from '../conda/template-names' -import { RebootVmComponent } from '../modals/reboot-vm/reboot-vm.component' -import { NotificationModalComponent } from '../../shared/modal/notification-modal' - -/** - * VM Detail page component - */ -@Component({ - selector: 'app-virtual-machine-detail', - templateUrl: 'vmdetail.component.html', - styleUrls: ['./vmdetail.component.scss'], - - providers: [ - FlavorService, - FacilityService, - VoService, - UserService, - GroupService, - VoService, - CreditsService, - VirtualmachineService, - ImageService, - PlaybookService, - BiocondaService - ] -}) -export class VmDetailComponent extends AbstractBaseClass implements OnInit { - vm_id: string - conda_logs: Condalog - title: string = 'Instance Detail' - image: Image - VolumeStates: VolumeStates = new VolumeStates() - virtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - virtualMachine: VirtualMachine - resenvTemplate: ResenvTemplate - snapshotSearchTerm: Subject = new Subject() - errorMessage: boolean = false - error_msg: string = '' - filteredMembers: any = null - backend_users: any = [] - extendDone: boolean = false - VOLUME_END_STATES: string[] = [ - VolumeStates.AVAILABLE, - VolumeStates.NOT_FOUND, - VolumeStates.IN_USE, - VirtualMachineStates.DELETED, - VirtualMachineStates.DELETING_FAILED - ] - - is_vo_admin: boolean = is_vo - WIKI_RSTUDIO_LINK: string = WIKI_RSTUDIO_LINK - WIKI_GUACAMOLE_LINK: string = WIKI_GUACAMOLE_LINK - WIKI_VOLUME_OVERVIEW: string = WIKI_VOLUME_OVERVIEW - WIKI_CREATE_SNAPSHOT_LINK: string = WIKI_CREATE_SNAPSHOT_LINK - WIKI_PERSISTENT_TERMINAL_LINK: string = WIKI_PERSISTENT_TERMINAL_LINK - SNAPSHOT_MAX_RAM: number = SnapshotModel.MAX_RAM - - REBOOT_ERROR_MSG: string = 'Reboot of machine failed. If the error persists, please contact the support.' - - DEBOUNCE_TIME: number = 300 - - volume_to_attach: Volume - detached_project_volumes: Volume[] = [] - user_elixir_id: string = elixir_id - - is_project_admin: boolean = false - - /** - * The changed status. - * - * @type {number} - */ - status_changed: number = 0 - /** - * Timeout for checking vm status. - * - * @type {number} - */ - private checkStatusTimeout: number = 1500 - - checkStatusTimer: ReturnType - /** - * Type of reboot HARD|SOFT. - */ - reboot_type: string - /** - * If an error appeared when checking vm status. - */ - status_check_error: boolean - /** - * IF reboot is done. - */ - reboot_done: boolean - - /** - * If the snapshot name is valid. - */ - validSnapshotNameBool: boolean - /** - * String if the snapshot is done. - * - * @type {string} - */ - snapshotNameCheckDone: boolean = false - snapshotDone: string = 'Waiting' - /** - * name of the snapshot. - */ - snapshotName: string = '' - - isMigrated: boolean = false - - /** - * Modal reference to be changed/showed/hidden depending on chosen modal. - */ - bsModalRef: BsModalRef - - /** - * Default time in ms to show an error message if no other value specified. - */ - ERROR_TIMER: number = 10000 - - /** - * Error message to show if 409 status was returned, typically returned if vm is creating a snapshot. - */ - SNAPSHOT_CREATING_ERROR_MSG: string = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - - constructor( - private activatedRoute: ActivatedRoute, - private virtualmachineService: VirtualmachineService, - private modalService: BsModalService, - // public bsModalRef: BsModalRef, TODO: bsModalRef in constructor? - private router: Router, - private userService: UserService, - private applicationService: ApplicationsService, - private flavorService: FlavorService, - private imageService: ImageService, - private playbookService: PlaybookService, - private biocondaService: BiocondaService, - private clipboardService: ClipboardService, - private groupService: GroupService, - private cdr: ChangeDetectorRef - ) { - super() - } - - getVmCondaLogs(): void { - this.virtualmachineService.getCondaLogs(this.vm_id).subscribe((log: Condalog): void => { - if (log) { - this.conda_logs = new Condalog(log) - } - }) - } - - ngOnInit(): void { - this.activatedRoute.params.subscribe((paramsId: any): void => { - this.vm_id = paramsId.id - this.getVmCondaLogs() - this.getVmById() - this.snapshotSearchTerm - .pipe(debounceTime(this.DEBOUNCE_TIME), distinctUntilChanged()) - .subscribe((event: any): void => { - this.validSnapshotName(event) - }) - }) - } - - /** - * Check if the snapshot name is valid. - * - * @param e - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - validSnapshotName(event: any): any { - this.snapshotNameCheckDone = false - this.imageService - .checkSnapshotNameAvailable(this.snapshotName.trim(), this.virtualMachine.client.id) - .subscribe((res: IResponseTemplate): void => { - this.validSnapshotNameBool = this.snapshotName.length > 0 && (res.value as boolean) - this.snapshotNameCheckDone = true - }) - } - - /** - * Reset the snapshotDone to waiting. - */ - resetSnapshotResult(): void { - this.snapshotDone = 'Waiting' - } - - /** - * Check status of vm. - * - * @param vm instance - */ - checkStatus(): void { - this.virtualmachineService - .checkVmStatus(this.virtualMachine.openstackid) - .subscribe((updated_vm: VirtualMachine): void => { - this.virtualMachine = updated_vm - }) - } - - setVmNeeded(): void { - this.virtualmachineService.setVmNeeded(this.virtualMachine.openstackid).subscribe((res: any): void => { - if (res['still_needed']) { - this.virtualMachine.still_used_confirmation_requested = false - this.virtualMachine.still_used_confirmed_date = new Date() - this.cdr.detectChanges() - } - }) - } - - checkVmVolumesStatus(): void { - this.virtualMachine.volumes.forEach((vol: Volume): void => { - if ( - vol.volume_status !== VolumeStates.AVAILABLE && - vol.volume_status !== VolumeStates.NOT_FOUND && - vol.volume_status !== VolumeStates.IN_USE && - vol.volume_status !== VolumeStates.MIGRATED - ) { - this.check_status_loop_vol(vol) - } - }) - } - - check_status_loop_vol( - volume: Volume, - initial_timeout: number = this.checkStatusTimeout, - final_state?: string, - expected_storage?: number - ): void { - const created: boolean = volume.volume_created_by_user - - setTimeout((): void => { - const idx: number = this.virtualMachine.volumes.indexOf(volume) - if (volume.volume_openstackid) { - this.virtualmachineService.getVolumeById(volume.volume_openstackid).subscribe((vol: Volume): void => { - if (expected_storage && vol.volume_storage !== expected_storage) { - return this.check_status_loop_vol(volume, this.checkStatusTimeout, final_state, expected_storage) - } else if (expected_storage && vol.volume_storage === expected_storage) { - this.extendDone = true - } - if (volume.error_msg !== '' && volume.error_msg !== undefined && volume.error_msg !== null) { - vol.error_msg = volume.error_msg - setTimeout((): void => { - vol.error_msg = null - }, 5000) - } - if (idx > -1) { - vol.volume_created_by_user = created - this.virtualMachine.volumes[idx] = vol - } - // tslint:disable-next-line:max-line-length - if (this.VOLUME_END_STATES.indexOf(vol.volume_status) === -1 && final_state !== vol.volume_status) { - this.check_status_loop_vol(this.virtualMachine.volumes[idx], this.checkStatusTimeout, final_state) - } - }) - } else { - // tslint:disable-next-line:max-line-length - this.virtualmachineService - .getVolumeByNameAndVmName(volume.volume_name, volume.volume_virtualmachine.name) - .subscribe((vol: Volume): void => { - if (volume.error_msg !== '' && volume.error_msg !== undefined && volume.error_msg !== null) { - vol.error_msg = volume.error_msg - setTimeout((): void => { - vol.error_msg = null - }, 5000) - } - if (idx > -1) { - vol.volume_created_by_user = created - this.virtualMachine.volumes[idx] = vol - } - // tslint:disable-next-line:max-line-length - if ( - vol.volume_status !== VolumeStates.AVAILABLE && - vol.volume_status !== VolumeStates.NOT_FOUND && - vol.volume_status !== VolumeStates.IN_USE && - vol.volume_status !== VolumeStates.MIGRATED && - vol.volume_status !== final_state - ) { - this.check_status_loop_vol(this.virtualMachine.volumes[idx], this.checkStatusTimeout, final_state) - } - }) - } - }, initial_timeout) - } - - /** - * Delete VM. - * - * @param vm which will be deleted - */ - deleteVm(): void { - this.virtualMachine.status = VirtualMachineStates.DELETING - this.virtualmachineService.deleteVM(this.virtualMachine.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - updated_vm.cardState = 0 - this.virtualMachine = updated_vm - if (updated_vm.status === VirtualMachineStates.DELETED) { - this.status_changed = 1 - } else { - this.status_changed = 2 - } - }, - (error1: any): void => { - this.status_changed = 2 - if (error1['status'] === 409) { - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - } - this.getVmById() - } - ) - } - - /** - * Subscription object to listen to different events. - */ - subscription: Subscription = new Subscription() - - /** - * Function to listen to modal results. - */ - subscribeToBsModalRef(): void { - this.subscription.add( - this.bsModalRef.content.event.subscribe((result: any) => { - if ('deleteVM' in result) { - this.deleteVm() - /** } else if ('stopVM' in result) { - this.stopVM(); - } else if ('resumeVM' in result) { - this.resumeVM(); - } else if ('resume' in result) { - this.resumeCheckStatusTimer(); - } else if ('snapshotVM' in result) { - this.createSnapshot(result['snapshotName'], result['description']); - } else if ('attachVolume' in result) { - this.attachVolume(result['volume']); - } else if ('detachVolume' in result) { - this.detachVolume(result['volume']); */ - } else if ('reboot_type' in result) { - this.rebootVM(result['reboot_type']) - } - }) - ) - } - - /** - * Show deletion modal - */ - showDeleteModal(): void { - const initialState = { virtualMachine: this.virtualMachine } - - this.bsModalRef = this.modalService.show(DeleteVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - /** - * Show reboot modal - */ - showRebootModal(): void { - const initialState = { virtualMachine: this.virtualMachine } - - this.bsModalRef = this.modalService.show(RebootVmComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - this.subscribeToBsModalRef() - } - - getDetachedVolumesByVSelectedMProject(): void { - this.virtualmachineService - .getDetachedVolumesByProject(this.virtualMachine.projectid) - .subscribe((detached_volumes: Volume[]): void => { - this.detached_project_volumes = detached_volumes - }) - } - - attachVolume(volume: Volume): void { - const volume_status_backup: string = volume.volume_status - volume.volume_status = VolumeStates.ATTACHING - - this.virtualmachineService - .attachVolumetoServer(volume.volume_openstackid, this.virtualMachine.openstackid) - .subscribe( - (result: IResponseTemplate): void => { - if (result.value === 'attached') { - this.getVmById() - } - }, - (error1: any): void => { - this.status_changed = 2 - if (error1['error']['error'] === '409') { - this.volume_to_attach.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - setTimeout((): void => { - this.volume_to_attach.error_msg = null - }, 5000) - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - volume.volume_status = volume_status_backup - } - } - ) - } - - detachVolume(volume: Volume): void { - const volume_status_backup: string = volume.volume_status - volume.volume_status = VolumeStates.DETACHING - - this.virtualmachineService - .deleteVolumeAttachment(volume.volume_openstackid, this.virtualMachine.openstackid) - .subscribe( - (result: any): void => { - if (result.value === 'deleted') { - this.getDetachedVolumesByVSelectedMProject() - this.getVmById() - } - }, - (error1: any): void => { - this.status_changed = 2 - if (error1['error']['error'] === '409') { - volume.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - setTimeout((): void => { - volume.error_msg = null - }, 5000) - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - volume.volume_status = volume_status_backup - } - } - ) - } - - /** - * Reboot a vm. - * - * @param vm which will be rebooted - * @param reboot_type HARD|SOFT - */ - rebootVM(reboot_type: string): void { - this.stopCheckStatusTimer() - this.virtualMachine.status = VirtualMachineStates.GETTING_STATUS - this.subscription.add( - this.virtualmachineService.rebootVM(this.virtualMachine.openstackid, reboot_type).subscribe( - (result: IResponseTemplate): void => { - this.virtualMachine.cardState = 0 - if (result.value as boolean) { - this.virtualMachine.setMsgWithTimeout('Reboot initiated', 5000) - this.check_status_loop_when_reboot() - } else { - this.check_status_loop(VirtualMachineStates.ACTIVE) - } - }, - (error1: any): void => { - this.error_msg = this.REBOOT_ERROR_MSG - - if (error1['error']['error'] === '409') { - this.virtualMachine.setErrorMsgWithTimeout(this.REBOOT_ERROR_MSG, this.ERROR_TIMER) - } - } - ) - ) - } - - /** - * Check Status of vm in loop till final state is reached. - * - * @param vm - * @param final_state - * @param is_selected_vm If the vm should be the selected vm - */ - check_status_loop(final_state: string, is_selected_vm?: boolean, timeout: number = this.checkStatusTimeout): void { - this.checkStatusTimer = setTimeout((): void => { - if (this.virtualMachine.openstackid) { - this.virtualmachineService - .checkVmStatus(this.virtualMachine.openstackid) - .subscribe((updated_vm: VirtualMachine): void => { - this.virtualMachine = updated_vm - this.virtualMachine.cardState = 0 - - if (updated_vm.status === final_state || updated_vm.status === VirtualMachineStates.MIGRATED) { - this.virtualMachine = updated_vm - } else { - if (this.virtualMachine['error']) { - this.status_check_error = true - } - this.check_status_loop(final_state, is_selected_vm) - } - }) - } else { - this.virtualmachineService - .checkVmStatus(this.virtualMachine.name) - .subscribe((updated_vm: VirtualMachine): void => { - this.virtualMachine = updated_vm - this.virtualMachine.cardState = 0 - - if (updated_vm.status === final_state) { - this.virtualMachine = updated_vm - } else { - if (this.virtualMachine['error']) { - this.status_check_error = true - } - this.check_status_loop(final_state, is_selected_vm) - } - }) - } - }, timeout) - } - - /** - * Check Status of vm in loop till active. - * - * @param vm - */ - check_status_loop_when_reboot(): void { - this.checkStatusTimer = setTimeout((): void => { - this.virtualmachineService - .checkVmStatusWhenReboot(this.virtualMachine.openstackid) - .subscribe((updated_vm: VirtualMachine): void => { - if (updated_vm.status === VirtualMachineStates.ACTIVE) { - this.reboot_done = true - this.virtualMachine = updated_vm - this.showNotificationModal('Success', 'The virtual machine was rebooted successfully!', 'success') - } else { - if (this.virtualMachine['error']) { - this.status_check_error = true - this.showNotificationModal('Failed', 'The reboot of the virtual machine failed!', 'danger') - } - this.check_status_loop_when_reboot() - } - }) - }, this.checkStatusTimeout) - } - - showNotificationModal( - notificationModalTitle: string, - notificationModalMessage: string, - notificationModalType: string - ) { - const initialState = { notificationModalTitle, notificationModalType, notificationModalMessage } - if (this.bsModalRef) { - this.bsModalRef.hide() - } - - this.bsModalRef = this.modalService.show(NotificationModalComponent, { initialState }) - this.bsModalRef.setClass('modal-lg') - } - - stopCheckStatusTimer(): void { - if (this.checkStatusTimer) { - clearTimeout(this.checkStatusTimer) - } - } - - /** - * Stop a vm. - * - * @param openstack_id of instance. - */ - stopVm(): void { - this.virtualmachineService.stopVM(this.virtualMachine.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - this.status_changed = 0 - - updated_vm.cardState = 0 - this.virtualMachine = updated_vm - - switch (updated_vm.status) { - case VirtualMachineStates.SHUTOFF: - this.status_changed = 1 - break - case VirtualMachineStates.POWERING_OFF: - this.check_status_loop(VirtualMachineStates.SHUTOFF, true) - break - default: - this.status_changed = 2 - break - } - }, - (error1: any): void => { - this.status_changed = 2 - if (error1['error']['error'] === '409') { - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - } - } - ) - } - - checkVmTillActive(): void { - if ( - this.virtualMachine.status !== VirtualMachineStates.ACTIVE && - this.virtualMachine.status !== VirtualMachineStates.SHUTOFF && - this.virtualMachine.status !== VirtualMachineStates.DELETED - ) { - this.check_status_loop(VirtualMachineStates.ACTIVE) - } - } - - resumeVM(): void { - this.virtualmachineService.resumeVM(this.virtualMachine.openstackid).subscribe( - (updated_vm: VirtualMachine): void => { - this.status_changed = 0 - updated_vm.cardState = 0 - this.virtualMachine = updated_vm - switch (updated_vm.status) { - case VirtualMachineStates.ACTIVE: - this.status_changed = 1 - break - case VirtualMachineStates.POWERING_ON: - this.check_status_loop(VirtualMachineStates.ACTIVE, true) - break - default: - this.status_changed = 2 - break - } - }, - (error1: any): void => { - this.status_changed = 2 - if (error1['error']['error'] === '409') { - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - } - } - ) - } - - /** - * Create snapshot. - * - * @param snapshot_instance which is used for creating the snapshot - * @param snapshot_name name of the snapshot - */ - createSnapshot(snapshot_instance: string, snapshot_name: string, description?: string): void { - this.imageService.createSnapshot(snapshot_instance, snapshot_name.trim(), description).subscribe( - (newSnapshot: SnapshotModel): void => { - if (newSnapshot.snapshot_openstackid) { - this.snapshotDone = 'true' - this.virtualMachine.status = VirtualMachineStates.IMAGE_PENDING_UPLOAD - this.check_status_loop(VirtualMachineStates.ACTIVE, null, 10000) - } else { - this.snapshotDone = 'error' - this.check_status_loop(VirtualMachineStates.ACTIVE) - } - }, - (error1: any): void => { - this.snapshotDone = 'error' - this.status_changed = 2 - if (error1['error']['error'] === '409') { - this.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - } - } - ) - } - - /** - * Copies the content of the field it get's clicked on (e.g. ssh connection information). - * - * @param text the content of the field - */ - copyToClipboard(text: string): void { - if (this.clipboardService.isSupported) { - this.clipboardService.copy(text) - } - } - - /** - * Checks if the user visiting the detail-page is admin of the project - */ - checkVMAdminState(): void { - this.userService.getMemberByUser().subscribe((): void => { - this.groupService.isLoggedUserGroupAdmin(this.virtualMachine.projectid).subscribe((result): any => { - if (result['admin']) { - this.is_project_admin = true - } - }) - }) - } - - getVmById(): void { - this.virtualmachineService.getVmById(this.vm_id).subscribe((vm: VirtualMachine): void => { - vm = new VirtualMachine(vm) - this.checkAndGetForcDetails(vm) - this.title = vm['name'] - this.virtualMachine = vm - this.applicationService - .getApplicationMigratedByGroupId(this.virtualMachine.projectid.toString()) - .subscribe((migrated: boolean): void => { - this.isMigrated = migrated - }) - this.checkVMAdminState() - this.biocondaService.getTemplateNameByVmName(vm).subscribe((backend: Backend): void => { - if (backend !== null) { - const template_name: string = backend.template - this.biocondaService.getForcTemplates(vm.client.id).subscribe((templates: any): void => { - if (templates !== null) { - for (const temp of templates) { - if (temp['template_name'] === template_name) { - this.resenvTemplate = temp - break - } - } - } - }) - } - }) - this.getImageDetails(this.virtualMachine.projectid, this.virtualMachine.image) - this.getDetachedVolumesByVSelectedMProject() - this.checkVmVolumesStatus() - this.isLoaded = true - }) - } - - getImageDetails(project_id: number, name: string): Image { - const newImage: Image = new Image() - this.imageService.getImageByProjectAndName(project_id, name).subscribe( - (image: Image): void => { - this.image = image - }, - (): void => { - this.isLoaded = false - } - ) - - return newImage - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - checkAndGetForcDetails(vm: VirtualMachine): void { - // for (const mode of vm.modes) { - // if (TemplateNames.ALL_TEMPLATE_NAMES.indexOf(mode.name) !== -1) { - // checkForForc = false; - // } - // } - - this.getUsersForBackend() - } - - filterMembers(searchString: string): void { - this.groupService - .getFilteredMembersByProject(searchString, this.virtualMachine.projectid) - .subscribe((result: object): void => { - this.filteredMembers = result - }) - } - - addUserToBackend(userId: any): void { - this.biocondaService.addUserToBackend(this.vm_id, userId).subscribe((): void => { - this.getUsersForBackend() - }) - } - - getUsersForBackend(): void { - this.biocondaService.getUsersForBackend(this.vm_id).subscribe((result: any): void => { - this.backend_users = result - }) - } - - deleteUserFromBackend(userId: any): void { - this.biocondaService.deleteUserFromBackend(this.vm_id, userId.toString()).subscribe((): void => { - this.getUsersForBackend() - }) - } - - /** - * Return false if resenv was not started by playbook (e.g. by Image instead). - */ - resenv_by_play(vm: VirtualMachine): boolean { - for (const mode of vm.modes) { - if (TemplateNames.ALL_TEMPLATE_NAMES.indexOf(mode.name) !== -1) { - return false - } - } - - return true - } - - protected readonly NEW_SVM_PORTAL_LINK = NEW_SVM_PORTAL_LINK -} diff --git a/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.html b/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.html deleted file mode 100644 index c16c151124..0000000000 --- a/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.html +++ /dev/null @@ -1,163 +0,0 @@ -Status: - - -
    - {{ VirtualMachineStates.staticACTIVE }} -
    - -
    - {{ VirtualMachineStates.staticSHUTOFF }} -
    - - -
    - {{ VirtualMachineStates.staticMIGRATED }} -
    - -
    - {{ VirtualMachineStates.staticDISABLED }} -
    - -
    - {{ VirtualMachineStates.staticDELETED }} -
    - -
    - {{ VirtualMachineStates.staticBUILD }} -
    - -
    - {{ VirtualMachineStates.staticSCHEDULING }} -
    - -
    - {{ VirtualMachineStates.staticSPAWNING }} -
    - -
    - {{ VirtualMachineStates.staticBUILD }} -
    - - -
    - {{ VirtualMachineStates.staticPLANNED }}
    -
    - -
    - {{ VirtualMachineStates.staticNOT_FOUND }} - -
    - -
    - {{ VirtualMachineStates.staticERROR }} -
    - -
    - {{ VirtualMachineStates.staticCREATION_FAILED }} -
    - -
    - {{ VirtualMachineStates.staticBUILD_PLAYBOOK }} -
    - -
    - {{ VirtualMachineStates.staticDELETING }} -
    - -
    - {{ VirtualMachineStates.staticDELETING }} -
    - -
    - {{ VirtualMachineStates.staticIMAGE_PENDING_UPLOAD }} -
    - -
    - {{ VirtualMachineStates.staticIMAGE_UPLOADING }} -
    - - -
    - {{ VirtualMachineStates.staticREBOOTING_STARTED }} -
    - -
    - {{ VirtualMachineStates.staticREBOOTING }} -
    - -
    - {{ VirtualMachineStates.staticREBOOTING_HARD }} -
    - -
    - {{ VirtualMachineStates.staticPOWERING_OFF }} -
    - -
    - {{ VirtualMachineStates.staticPOWERING_ON }} -
    - - -
    - {{ VirtualMachineStates.staticCHECKING_CONNECTION }}
    -
    - - -
    - {{ VirtualMachineStates.staticCLIENT_OFFLINE }} -
    - -
    - {{ VirtualMachineStates.staticLOCKED }} -
    - -
    - {{ VirtualMachineStates.staticGETTING_STATUS }} -
    -
    diff --git a/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.scss b/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.ts b/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.ts deleted file mode 100644 index 68c0f48418..0000000000 --- a/src/app/virtualmachines/vmdetail/vmstatus/vmstatus.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Component, Input } from '@angular/core' -import { VirtualMachineStates } from '../../virtualmachinemodels/virtualmachinestates' -import { VirtualMachine } from '../../virtualmachinemodels/virtualmachine' -import { CLOUD_PORTAL_SUPPORT_MAIL } from '../../../../links/links' - -/** - * Vmstatus component. - */ -@Component({ - selector: 'app-vmstatus', - templateUrl: './vmstatus.component.html', - styleUrls: ['./vmstatus.component.scss'] -}) -export class VmstatusComponent { - VirtualMachineStates: VirtualMachineStates = new VirtualMachineStates() - @Input() vm: VirtualMachine - @Input() with_text: boolean = false - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL -} diff --git a/src/app/virtualmachines/volumes/volume-action-states.enum.ts b/src/app/virtualmachines/volumes/volume-action-states.enum.ts deleted file mode 100644 index 5a506f0e58..0000000000 --- a/src/app/virtualmachines/volumes/volume-action-states.enum.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Enum of all possible volume action statuses. - */ -// eslint-disable-next-line no-shadow -export enum VolumeActionStates { - WAITING = 0, - SUCCESS = 1, - ERROR = 2, - DETACHING_VOLUME = 3, - SUCCESSFULLY_DETACHED_VOLUME = 4, - ATTACHING = 5, - ATTACHING_SUCCESSFULL = 6, - WAIT_CREATION = 7, - SUCCESSFULLY_CREATED_ATTACHED = 8, - CHANGING_NAME = 9, - CHANGING_NAME_SUCESSFULL = 10 -} diff --git a/src/app/virtualmachines/volumes/volume-request-states.enum.ts b/src/app/virtualmachines/volumes/volume-request-states.enum.ts deleted file mode 100644 index 7661f95474..0000000000 --- a/src/app/virtualmachines/volumes/volume-request-states.enum.ts +++ /dev/null @@ -1,5 +0,0 @@ -// eslint-disable-next-line no-shadow -export enum VolumeRequestStates { - DELETE = 0, - DETACH = 1 -} diff --git a/src/app/virtualmachines/volumes/volume.ts b/src/app/virtualmachines/volumes/volume.ts index b727e78424..abadbb708a 100644 --- a/src/app/virtualmachines/volumes/volume.ts +++ b/src/app/virtualmachines/volumes/volume.ts @@ -1,33 +1,26 @@ -import { VirtualMachine } from '../virtualmachinemodels/virtualmachine'; -import { Client } from '../../vo_manager/clients/client.model'; +import { VirtualMachine } from '../virtualmachinemodels/virtualmachine' +import { Client } from '../../vo_manager/clients/client.model' /** * Volume class. */ export class Volume { - volume_name: string; - volume_project: string; - volume_projectid: string; - volume_openstackid: string; - volume_storage: number; - volume_path: string; - volume_virtualmachine: VirtualMachine; - volume_client: Client; - volume_created_by_user: boolean; - volume_status: string; - volume_device: string; - error_msg: string; + volume_name: string - migrate_project_to_simple_vm: boolean = false; - project_is_migrated_to_simple_vm: boolean = false; + volume_openstackid: string + volume_storage: number + volume_virtualmachine: VirtualMachine + volume_client: Client + volume_status: string + error_msg: string constructor(volume?: Partial) { - Object.assign(this, volume); + Object.assign(this, volume) if (volume) { - this.volume_client = new Client(volume.volume_client); + this.volume_client = new Client(volume.volume_client) if (volume.volume_virtualmachine) { - this.volume_virtualmachine = new VirtualMachine(volume.volume_virtualmachine); + this.volume_virtualmachine = new VirtualMachine(volume.volume_virtualmachine) } } } diff --git a/src/app/virtualmachines/volumes/volumeOverview.component.html b/src/app/virtualmachines/volumes/volumeOverview.component.html deleted file mode 100644 index 56f8a3dacf..0000000000 --- a/src/app/virtualmachines/volumes/volumeOverview.component.html +++ /dev/null @@ -1,1136 +0,0 @@ -
    -
    - Wiki - - - - -
    - -
    -
    Volumes – Overview
    -
    - -
    -
    - - -
    -
    -
    -
    - - -
    -
    - -
    -
    - -
    Volumes per page
    -
    - -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    Project
    -
    Attached To
    -
    Name
    -
    Status
    -
    Size
    -
    Actions
    -
    - - Select all -
    -
    - -
    -
    {{ volume?.volume_project }}
    -
    - - Initial attached to: /vol/{{ volume?.volume_path }}
    - Device: {{ volume?.volume_device }}
    VM: - {{ volume?.volume_virtualmachine.name }} -
    -
    -
    {{ volume?.volume_name }}
    - - -
    {{ volume?.volume_storage }} GB
    -
    -
    -
    - - - -
    -
    -
    -
    This volume is part of a migrated project!
    -
    -
    -
    - -
    - - -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/app/virtualmachines/volumes/volumeOverview.component.ts b/src/app/virtualmachines/volumes/volumeOverview.component.ts deleted file mode 100644 index 96000e0086..0000000000 --- a/src/app/virtualmachines/volumes/volumeOverview.component.ts +++ /dev/null @@ -1,839 +0,0 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' -import { forkJoin, lastValueFrom, Subject, Subscription } from 'rxjs' -import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators' -import { AbstractControl, UntypedFormControl, ValidatorFn } from '@angular/forms' - -import { Volume } from './volume' -import { VirtualmachineService } from '../../api-connector/virtualmachine.service' -import { VirtualMachine } from '../virtualmachinemodels/virtualmachine' -import { GroupService } from '../../api-connector/group.service' -import { AbstractBaseClass } from '../../shared/shared_modules/baseClass/abstract-base-class' -import { VolumeActionStates } from './volume-action-states.enum' -import { VolumeRequestStates } from './volume-request-states.enum' -import { IResponseTemplate } from '../../api-connector/response-template' -import { FacilityService } from '../../api-connector/facility.service' -import { WIKI_EXTEND_VOLUME, WIKI_VOLUME_OVERVIEW, CLOUD_PORTAL_SUPPORT_MAIL } from '../../../links/links' -import { VolumeStates } from './volume_states' -import { VirtualMachineStates } from '../virtualmachinemodels/virtualmachinestates' -import { VolumePage } from './volumePage.model' -import { ApplicationsService } from '../../api-connector/applications.service' -import { IsMigratedProjectIdPipe } from '../../pipe-module/pipes/migratedList' - -/** - * Volume overview component. - */ -@Component({ - selector: 'app-volume-overview', - templateUrl: 'volumeOverview.component.html', - providers: [FacilityService, GroupService, VirtualmachineService, IsMigratedProjectIdPipe], - styleUrls: ['../vmOverview.component.scss'] -}) -export class VolumeOverviewComponent extends AbstractBaseClass implements OnInit, OnDestroy { - @ViewChild('errorModal') errorModal: any - - volume_page: VolumePage = new VolumePage() - - WIKI_EXTEND_VOLUME: string = WIKI_EXTEND_VOLUME - WIKI_VOLUME_OVERVIEW: string = WIKI_VOLUME_OVERVIEW - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - title: string = 'Volume Overview' - selected_volume_data_loaded: boolean = false - filter: string - checked_volumes: Volume[] = [] - storageSize: UntypedFormControl = null - - /** - * Enum of all volume action states. - */ - volumeActionStates: typeof VolumeActionStates = VolumeActionStates - extendError: boolean = false - extendDone: boolean = false - - showFacilities: boolean = false - - /** - * Enum of all request states. - * - * @type {VolumeRequestStates} - */ - volumeRequestStates: typeof VolumeRequestStates = VolumeRequestStates - - /** - * Facilitties where the user is manager ['name',id]. - */ - managerFacilities: [string, number][] = [] - /** - * Chosen facility. - */ - selectedFacility: [string, number] - - /** - * Array of volumes from the selected Project. - */ - project_vms: VirtualMachine[] - /** - * Selected vm. - */ - selected_vm: VirtualMachine - /** - * If the site is loaded. - * - * @type {boolean} - */ - isLoaded: boolean = false - /** - * Selected volume. - */ - selected_volume: Volume - /** - * Diskspace max from selected Project. - */ - selectedProjectDiskspaceMax: number - /** - * Diskspace used from selected Project. - */ - selectedProjectDiskspaceUsed: number - /** - * Volumes max from selected Project. - */ - selectedProjectVolumesMax: number - /** - * Volumes used from selected Project. - */ - selectedProjectVolumesUsed: number - /** - * Diskspace actual + addition if new volume would be created for selected Project. - */ - selectedProjectDiskSpaceSum: number - /** - * The selected Project [name,id]. - */ - selectedProject: [string, number] - /** - * List of all projects from the user. - * - * @type {any[]} - */ - projects: string[] = [] - /** - * Default volumeStorage. - * - * @type {number} - */ - diskspace: number = 1 - /** - * Default volumename. - * - * @type {string} - */ - volumeName: string = '' - /** - * Action which is performed with a volume. - */ - volume_action_status: number - - extendVolumeStorage: number - - migratedProjectIds: string[] = [] - migratedProjectNames: string[] = [] - - /** - * Type of request. - */ - request_status: number - private checkStatusSubscription: Subscription = new Subscription() - private getVolumesSubscription: Subscription = new Subscription() - private checkStatusTimeout: number = 5000 - VolumeStates: VolumeStates = new VolumeStates() - volumePerPageChange: Subject = new Subject() - filterChanged: Subject = new Subject() - DEBOUNCE_TIME: number = 1000 - currentPage: number = 1 - isSearching: boolean = true - all_volumes_checked: boolean = false - selected_volumes_to_detach: boolean = false - VOLUME_END_STATES: string[] = [ - VolumeStates.AVAILABLE, - VolumeStates.NOT_FOUND, - VolumeStates.IN_USE, - VirtualMachineStates.DELETED, - VirtualMachineStates.DELETING_FAILED, - VolumeStates.ERROR - ] - errorState: number = 0 - - constructor( - private facilityService: FacilityService, - private groupService: GroupService, - private vmService: VirtualmachineService, - private applicationsService: ApplicationsService, - - private isMigratedPipe: IsMigratedProjectIdPipe - ) { - super() - } - - ngOnDestroy(): void { - this.checkStatusSubscription.unsubscribe() - this.getVolumesSubscription.unsubscribe() - } - - changedFilter(text: string): void { - this.filterChanged.next(text) - } - - isVolChecked(vol: Volume): boolean { - return this.checked_volumes.indexOf(vol) !== -1 - } - - changeCheckedVolume(vol: Volume): void { - if (!this.isVolChecked(vol)) { - this.checked_volumes.push(vol) - } else { - this.checked_volumes.splice(this.checked_volumes.indexOf(vol), 1) - } - this.areAllVolumesChecked() - this.areSelectedVolumesDetachable() - } - - areSelectedVolumesDetachable(): void { - this.selected_volumes_to_detach = false - this.checked_volumes.forEach((vol: Volume): void => { - if (vol.volume_virtualmachine) { - this.selected_volumes_to_detach = true - } - }) - } - - uncheckAll(): void { - this.checked_volumes = [] - this.all_volumes_checked = false - this.selected_volumes_to_detach = false - } - - deleteSelectedVolumes(): void { - const delete_vols: Volume[] = this.checked_volumes - const vol_ids: string[] = this.checked_volumes.map((vol: Volume): string => { - vol.volume_status = VolumeStates.DELETING - - return vol.volume_openstackid - }) - this.vmService.deleteVolumes(vol_ids).subscribe((): void => { - delete_vols.forEach((vol: Volume): void => { - vol.volume_status = VolumeStates.DELETED - }) - }) - - this.uncheckAll() - } - - detachSelectedVolumes(): void { - const detach_vols: Volume[] = this.checked_volumes - const vol_ids: string[] = this.checked_volumes.map((vol: Volume): string => { - if (vol.volume_virtualmachine) { - vol.volume_status = VolumeStates.DETACHING - - return vol.volume_openstackid - } else { - return null - } - }) - this.vmService.deleteVolumeAttachments(vol_ids).subscribe((): void => { - detach_vols.forEach((vol: Volume): void => { - this.check_status_loop(vol, 2000, VolumeStates.AVAILABLE) - }) - }) - - this.uncheckAll() - } - - areAllVolumesChecked(): void { - let all_checked: boolean = true - this.volume_page.volume_list.forEach((vol: Volume): void => { - if (!this.isVolChecked(vol)) { - all_checked = false - } - }) - - this.all_volumes_checked = all_checked - } - - changeCheckAllVolumes(): void { - if (this.all_volumes_checked) { - this.checked_volumes = [] - this.all_volumes_checked = false - - return - } - - this.volume_page.volume_list.forEach((vol: Volume): void => { - if (!this.isVolChecked(vol) && !this.isMigratedPipe.transform(vol.volume_projectid, this.migratedProjectIds)) { - this.checked_volumes.push(vol) - } - }) - this.all_volumes_checked = true - this.areSelectedVolumesDetachable() - } - - setSelectedProjectByVolume(volume: Volume): void { - this.selectedProject = [volume.volume_project, parseInt(volume.volume_projectid, 10)] - } - - ngOnInit(): void { - this.getVolumes() - this.getUserApprovedProjects() - this.facilityService.getManagerFacilities().subscribe((result: any): void => { - this.managerFacilities = result - this.selectedFacility = this.managerFacilities[0] - }) - this.filterChanged - .pipe( - debounceTime(this.DEBOUNCE_TIME), - distinctUntilChanged(), - switchMap((filter: string): any => { - this.isSearching = true - - this.filter = filter.trim() - - return this.vmService.getVolumesByUser(this.volume_page.items_per_page, this.currentPage, this.filter) - }) - ) - .subscribe((volume_page: VolumePage): void => { - this.volume_page = volume_page - for (const volume of this.volume_page.volume_list) { - this.setCollapseStatus(volume.volume_openstackid, false) - } - this.isSearching = false - this.volume_page.volume_list.forEach((vol: Volume): void => { - if ( - vol.volume_status !== VolumeStates.AVAILABLE && - vol.volume_status !== VolumeStates.NOT_FOUND && - vol.volume_status !== VolumeStates.IN_USE - ) { - this.check_status_loop(vol) - } - }) - }) - this.volumePerPageChange.pipe(debounceTime(this.DEBOUNCE_TIME), distinctUntilChanged()).subscribe((): void => { - if (this.volume_page.items_per_page && this.volume_page.items_per_page > 0) { - if (this.showFacilities) { - this.getFacilityVolumes() - } else { - this.getVolumes() - } - } - }) - } - - /** - * Attach a volume to an instance. - * - * @param volume volume with openstack_id - * @param instance_id openstack_id of the instance - * @returns - */ - async attachVolume(volume: Volume, instance_id: string): Promise { - await this.updateVolume(volume) - - volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - if (volume.volume_status !== VolumeStates.AVAILABLE) { - volume.error_msg = "Conflict detected. The volume can't be attached, because it is not AVAILABLE" - setTimeout((): void => { - volume.error_msg = null - }, 10000) - - return - } - - volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - - volume.volume_status = VolumeStates.ATTACHING - this.vmService.attachVolumetoServer(volume.volume_openstackid, instance_id).subscribe( - (result: IResponseTemplate): void => { - if (result.value === 'attached') { - this.volume_action_status = this.volumeActionStates.ATTACHING_SUCCESSFULL - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - this.check_status_loop(volume, 5000, VolumeStates.IN_USE) - }, - (error: any): void => { - if (error['error']['error'] === '409') { - volume.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - setTimeout((): void => { - volume.error_msg = null - }, 5000) - } - this.check_status_loop(volume, 0) - } - ) - } - - async extendVolume(volume: Volume, new_storage: number): Promise { - await this.updateVolume(volume) - - volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - if (volume.volume_status !== VolumeStates.AVAILABLE) { - volume.error_msg = "Conflict detected. The volume can't be extended, because it is not AVAILABLE" - setTimeout((): void => { - volume.error_msg = null - }, 10000) - - return - } - - volume.volume_status = VolumeStates.EXTENDING - this.vmService.extendVolume(volume.volume_openstackid, new_storage.toString()).subscribe((res: any): void => { - if (res['status_code'] === 0) { - this.check_status_loop(volume, 0, undefined, new_storage) - } else { - this.extendError = true - this.check_status_loop(volume, 0) - } - }) - } - - /** - * Load volumes depending on page. - * - * @param event - */ - pageChanged(event: any): void { - this.isSearching = true - - this.currentPage = event.page - if (this.showFacilities) { - this.getFacilityVolumes() - } else { - this.getVolumes() - } - } - - getFacilityVolumes(): void { - this.isSearching = true - this.getVolumesSubscription.unsubscribe() - this.getVolumesSubscription = new Subscription() - - this.getVolumesSubscription.add( - this.facilityService - .getFacilityVolumes(this.selectedFacility['FacilityId'], this.volume_page.items_per_page, this.currentPage) - .subscribe((volume_page: VolumePage): void => { - this.volume_page = volume_page - for (const volume of this.volume_page.volume_list) { - this.setCollapseStatus(volume.volume_openstackid, false) - } - - this.isLoaded = true - this.isSearching = false - this.volume_page.volume_list.forEach((vol: Volume): void => { - if (vol.volume_status !== VolumeStates.NOT_FOUND) { - this.check_status_loop(vol) - } - }) - }) - ) - } - - /** - * Create an volume and attach to an instance. - * - * @param volume_name name of the volume - * @param diskspace volumeStorage of the volume - * @param instance_id opentack_id of the instance - * @returns - */ - createAndAttachvolume(volume_name: string, diskspace: number, instance_id: string): void { - this.volume_action_status = 7 - this.vmService.createVolume(volume_name, diskspace.toString(), instance_id).subscribe( - async (newVolume: Volume): Promise => { - newVolume.volume_created_by_user = true - - if (newVolume.volume_openstackid) { - newVolume.volume_status = VolumeStates.CREATING - this.volume_page.volume_list.push(newVolume) - await this.updateVolume(newVolume) - let volume: Volume = this.get_volume_from_list_by_id(newVolume.volume_openstackid) - while (volume.volume_status !== VolumeStates.AVAILABLE) { - await this.updateVolume(newVolume) - - volume = this.get_volume_from_list_by_id(newVolume.volume_openstackid) - } - - this.volume_action_status = this.volumeActionStates.ATTACHING - - this.vmService.attachVolumetoServer(volume.volume_openstackid, instance_id).subscribe( - (res: IResponseTemplate): void => { - if (res.value === 'attached') { - this.volume_action_status = this.volumeActionStates.SUCCESSFULLY_CREATED_ATTACHED - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - this.check_status_loop(volume, 0) - }, - (error: any): void => { - if (error['error']['error'] === '409') { - volume.error_msg = - 'Conflict detected. ' + - 'The virtual machine is currently creating a snapshot and must not be altered.' - setTimeout((): void => { - volume.error_msg = null - }, 5000) - } - this.check_status_loop(volume, 0) - } - ) - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - }, - (): void => { - this.errorState = 0 - this.errorModal.show() - } - ) - } - - /** - * Create an volume. - * - * @param volume_name name of the volume. - * @param diskspace volumeStorage of the new volume - * @param instance_id openstack_id of instance. - * @returns - */ - createVolume(volume_name: string, diskspace: number, instance_id: string): void { - this.volume_action_status = this.volumeActionStates.WAITING - this.vmService.createVolume(volume_name, diskspace.toString(), instance_id).subscribe((newVolume: Volume): void => { - if (newVolume.volume_openstackid) { - this.volume_action_status = this.volumeActionStates.WAIT_CREATION - this.volume_page.volume_list.push(newVolume) - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - }) - } - - deleteVolume(volume: Volume): void { - volume.volume_status = VolumeStates.DELETING - this.vmService.deleteVolume(volume.volume_openstackid).subscribe( - (): void => { - volume.volume_status = VolumeStates.DELETED - }, - (error: any) => { - console.log(error) - this.errorState = 1 - this.errorModal.show() - } - ) - } - - /** - * Detach volume from instance. - * - * @param volume - * @param instance_id openstack_id of the instance - * @returns - */ - async detachVolume(volume: Volume, instance_id: string): Promise { - await this.updateVolume(volume) - - volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - if (volume.volume_status !== VolumeStates.IN_USE) { - volume.error_msg = "Conflict detected. The volume can't be detached, because it is not IN-USE" - setTimeout((): void => { - volume.error_msg = null - }, 10000) - - return - } - - this.volume_action_status = this.volumeActionStates.DETACHING_VOLUME - volume.volume_status = VolumeStates.DETACHING - this.vmService.deleteVolumeAttachment(volume.volume_openstackid, instance_id).subscribe( - (result: any): void => { - if (result.value === 'deleted') { - this.volume_action_status = this.volumeActionStates.SUCCESSFULLY_DETACHED_VOLUME - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - this.check_status_loop(volume, 5000, VolumeStates.AVAILABLE) - }, - (error: any): void => { - if (error['error']['error'] === '409') { - volume.error_msg = - 'Conflict detected. The virtual machine is currently creating a snapshot and must not be altered.' - setTimeout((): void => { - volume.error_msg = null - }, 5000) - } else { - this.errorState = 2 - this.errorModal.show() - } - this.check_status_loop(volume, 0) - } - ) - } - - /** - * Rename a volume ( just in Django DB not in OpenStack). - * - * @param volume_id openstack_id of volume - * @param new_volume_name the new name - * @returns - */ - renameVolume(volume: Volume, new_volume_name: string): void { - this.volume_action_status = this.volumeActionStates.CHANGING_NAME - this.vmService - .renameVolume(volume.volume_openstackid, new_volume_name) - .subscribe((changed_volume: Volume): void => { - if (changed_volume.volume_name === new_volume_name) { - this.volume_action_status = this.volumeActionStates.CHANGING_NAME_SUCESSFULL - } else { - this.volume_action_status = this.volumeActionStates.ERROR - } - this.volume_page.volume_list[this.volume_page.volume_list.indexOf(volume)] = changed_volume - }) - } - - generateMigratedProjectIdList(): void { - this.migratedProjectIds = [] - this.volume_page.volume_list.forEach((vol: Volume) => { - if (vol.migrate_project_to_simple_vm || vol.project_is_migrated_to_simple_vm) { - this.migratedProjectIds.push(vol.volume_projectid.toString()) - } - const unique = (arr: string[]): string[] => [...new Set(arr)] - this.migratedProjectIds = unique(this.migratedProjectIds) - }) - } - generateMigratedProjectNamesList(): void { - this.migratedProjectNames = [] - this.volume_page.volume_list.forEach((vol: Volume) => { - if (vol.migrate_project_to_simple_vm || vol.project_is_migrated_to_simple_vm) { - this.migratedProjectNames.push(vol.volume_project) - } - }) - } - - /** - * Get all volumes from user. - * - * @returns - */ - getVolumes(): void { - this.isSearching = true - this.getVolumesSubscription.unsubscribe() - this.getVolumesSubscription = new Subscription() - this.getVolumesSubscription.add( - this.vmService - .getVolumesByUser(this.volume_page.items_per_page, this.currentPage) - .subscribe((volume_page: VolumePage): void => { - this.volume_page = volume_page - this.generateMigratedProjectIdList() - this.generateMigratedProjectNamesList() - - for (const volume of this.volume_page.volume_list) { - this.setCollapseStatus(volume.volume_openstackid, false) - } - - this.isLoaded = true - this.isSearching = false - this.volume_page.volume_list.forEach((vol: Volume): void => { - if (vol.volume_status !== VolumeStates.NOT_FOUND && vol.volume_status !== VolumeStates.MIGRATED) { - this.check_status_loop(vol) - } - }) - this.storageSize = new UntypedFormControl({ defaultValue: 1 }, this.checkAvailableVolumeSpaceForCreation()) - }) - ) - } - - checkAvailableVolumeSpaceForCreation(): ValidatorFn { - return (control: AbstractControl): { [key: string]: any } | null => - control.value > 0 && this.selectedProjectDiskSpaceSum <= this.selectedProjectDiskspaceMax - ? null - : { wrongNumber: control.value } - } - - async updateVolume(volume: Volume): Promise { - const created: boolean = volume.volume_created_by_user - - const vol: Volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - const updated_volume: Volume = await lastValueFrom(this.vmService.getVolumeById(vol.volume_openstackid)) - const idx: number = this.volume_page.volume_list.indexOf(vol) - updated_volume.volume_created_by_user = created - this.volume_page.volume_list[idx] = updated_volume - } - - get_volume_from_list_by_id(openstack_id: string): Volume { - for (const volume of this.volume_page.volume_list) { - if (volume.volume_openstackid === openstack_id) { - return volume - } - } - - return null - } - - check_status_loop( - volume: Volume, - initial_timeout: number = this.checkStatusTimeout, - final_state?: string, - expected_storage?: number - ): void { - setTimeout( - async (): Promise => { - await this.updateVolume(volume) - const updated_volume: Volume = this.get_volume_from_list_by_id(volume.volume_openstackid) - - if (expected_storage && updated_volume.volume_storage !== expected_storage) { - return this.check_status_loop(volume, this.checkStatusTimeout, final_state, expected_storage) - } else if (expected_storage && updated_volume.volume_storage === expected_storage) { - this.extendDone = true - } - if (volume.error_msg !== '' && volume.error_msg !== undefined && volume.error_msg !== null) { - updated_volume.error_msg = volume.error_msg - setTimeout((): void => { - updated_volume.error_msg = null - }, 5000) - } - - if ( - this.VOLUME_END_STATES.indexOf(updated_volume.volume_status) === -1 && - final_state && - final_state !== updated_volume.volume_status - ) { - this.check_status_loop(volume, this.checkStatusTimeout, final_state) - } - }, - - initial_timeout - ) - } - - /** - * Get all approved projects from the user. - * - * @returns - */ - getUserApprovedProjects(): void { - this.groupService.getSimpleVmByUser().subscribe((membergroups: any): void => { - for (const project of membergroups) { - this.projects.push(project) - } - }) - } - - /** - * Set request status. - * - * @param status - * @returns - */ - setRequestStatus(status: number): void { - this.request_status = status - } - - /** - * Set selected volume. - * - * @param volume - * @returns - */ - setSelectedVolume(volume: Volume): void { - this.selected_volume = volume - } - - /** - * Calc volumeStorage sum of selected project volumeStorage and additional volumeStorage of new volume. - */ - calcDiskSpaceSum(): void { - this.selectedProjectDiskSpaceSum = - parseInt(this.diskspace.toString(), 10) + parseInt(this.selectedProjectDiskspaceUsed.toString(), 10) - } - - getSelectedVolumeStorage(): void { - this.setSelectedProjectByVolume(this.selected_volume) - this.selected_volume_data_loaded = false - forkJoin( - this.groupService.getGroupMaxDiskspace(this.selectedProject[1].toString()), - this.groupService.getGroupUsedDiskspace(this.selectedProject[1].toString()) - ).subscribe((result: any): void => { - if (result[0]['value']) { - this.selectedProjectDiskspaceMax = result[0]['value'] - } else { - this.selectedProjectDiskspaceMax = 0 - } - if (result[1]['value']) { - this.selectedProjectDiskspaceUsed = result[1]['value'] - } else { - this.selectedProjectDiskspaceUsed = 0 - } - this.selected_volume_data_loaded = true - }) - } - - /** - * Get volumeStorage of selected project. - * - * @returns - */ - getSelectedProjectDiskspace(): void { - this.groupService - .getGroupMaxDiskspace(this.selectedProject[1].toString()) - .subscribe((result: IResponseTemplate): void => { - if (result.value) { - this.selectedProjectDiskspaceMax = result.value as number - } else { - this.selectedProjectDiskspaceMax = 0 - } - }) - this.groupService - .getGroupUsedDiskspace(this.selectedProject[1].toString()) - .subscribe((result: IResponseTemplate): void => { - if (result.value) { - this.selectedProjectDiskspaceUsed = result.value as number - } else { - this.selectedProjectDiskspaceUsed = 0 - } - }) - } - - /** - * Get volumes of selected project. - * - * @returns - */ - getSelectedProjectVolumes(): void { - this.groupService - .getVolumeCounter(this.selectedProject[1].toString()) - .subscribe((result: IResponseTemplate): void => { - if (result.value) { - this.selectedProjectVolumesMax = result.value as number - } else { - this.selectedProjectVolumesMax = 0 - } - }) - this.groupService - .getVolumesUsed(this.selectedProject[1].toString()) - .subscribe((result: IResponseTemplate): void => { - if (result.value) { - this.selectedProjectVolumesUsed = result.value as number - } else { - this.selectedProjectVolumesUsed = 0 - } - }) - } - - /** - * Get all active vms from a project. - * - * @param groupid id of the perun group from the project. - * @returns - */ - getActiveVmsByProject(groupid: number | string): void { - this.vmService.getActiveVmsByProject(groupid.toString()).subscribe((result: any): void => { - this.project_vms = result - }) - } -} diff --git a/src/app/virtualmachines/volumes/volumePage.model.ts b/src/app/virtualmachines/volumes/volumePage.model.ts deleted file mode 100644 index 33100d2926..0000000000 --- a/src/app/virtualmachines/volumes/volumePage.model.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Volume } from './volume'; - -export class VolumePage { - volume_list: Volume[]; - total_pages: number = 0; - total_items: number = 0; - items_per_page: number = 7; - num_pages: number = 0; - - constructor(volume_page?: Partial) { - Object.assign(this, volume_page); - this.volume_list = []; - if (volume_page) { - for (const volume of volume_page.volume_list) { - this.volume_list.push(new Volume(volume)); - } - if (volume_page.num_pages) { - this.total_pages = volume_page.num_pages; - } - if (volume_page.total_pages) { - this.num_pages = volume_page.total_pages; - } - } - } -} diff --git a/src/app/virtualmachines/volumes/volume_states.ts b/src/app/virtualmachines/volumes/volume_states.ts deleted file mode 100644 index 25b48f6700..0000000000 --- a/src/app/virtualmachines/volumes/volume_states.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { GeneralStatusStates } from '../../shared/shared_modules/baseClass/statusstates' - -/** - * VolumeStates class. - */ -export class VolumeStates extends GeneralStatusStates { - private static readonly _IN_USE: string = 'IN-USE' - private static readonly _RESERVED: string = 'RESERVED' - private static readonly _AVAILABLE: string = 'AVAILABLE' - private static readonly _RESERVED_PLANNED_STATUS: string = 'RESERVED_PLANNED' - private static readonly _RESERVED_ATTACHED: string = 'RESERVED_ATTACHED' - private static readonly _DETACHING: string = 'DETACHING' - private static readonly _ATTACHING: string = 'ATTACHING' - private static readonly _EXTENDING: string = 'EXTENDING' - - private static readonly _IN_PROCESS_STATES: string[] = [ - VolumeStates._RESERVED, - VolumeStates._DELETING, - VolumeStates._DETACHING, - VolumeStates._EXTENDING - ] - - private static readonly _NOT_IN_PROCESS_STATES: string[] = [ - VolumeStates._IN_USE, - VolumeStates._AVAILABLE, - VolumeStates._NOT_FOUND, - VolumeStates._ERROR, - VolumeStates._DELETED, - VolumeStates._MIGRATED - ] - - private static readonly _NO_ACTIONS: string[] = [ - VolumeStates._DETACHING, - VolumeStates._ATTACHING, - VolumeStates._NOT_FOUND, - VolumeStates._DELETING, - VolumeStates._RESERVED, - VolumeStates._RESERVED_ATTACHED, - VolumeStates._CREATING, - VolumeStates._RESERVED_PLANNED_STATUS, - VolumeStates._EXTENDING, - VolumeStates._DELETED - ] - - static get RESERVED_PLANNED_STATUS(): string { - return this._RESERVED_PLANNED_STATUS - } - - static get RESERVED_ATTACHED(): string { - return this._RESERVED_ATTACHED - } - - static get IN_USE(): string { - return this._IN_USE - } - - static get RESERVED(): string { - return this._RESERVED - } - - static get AVAILABLE(): string { - return this._AVAILABLE - } - - static get IN_PROCESS_STATES(): string[] { - return this._IN_PROCESS_STATES - } - - static get NOT_IN_PROCESS_STATES(): string[] { - return this._NOT_IN_PROCESS_STATES - } - - static get DETACHING(): string { - return this._DETACHING - } - - static get ATTACHING(): string { - return this._ATTACHING - } - - static get NO_ACTIONS(): string[] { - return this._NO_ACTIONS - } - - static get EXTENDING(): string { - return this._EXTENDING - } - - public get staticRESERVED_ATTACHED(): string { - return VolumeStates.RESERVED_ATTACHED - } - - public get staticNO_ACTIONS(): string[] { - return VolumeStates.NO_ACTIONS - } - - public get staticRESERVED(): string { - return VolumeStates.RESERVED - } - - public get staticDETACHING(): string { - return VolumeStates.DETACHING - } - - public get staticATTACHING(): string { - return VolumeStates.ATTACHING - } - - public get staticIN_USE(): string { - return VolumeStates.IN_USE - } - - public get staticAVAILABLE(): string { - return VolumeStates.AVAILABLE - } - - public get staticNOT_IN_PROCESS_STATE(): string[] { - return VolumeStates.NOT_IN_PROCESS_STATES - } - - public get staticRESERVED_PLANNED(): string { - return VolumeStates.RESERVED_PLANNED_STATUS - } - - public get staticEXTENDING(): string { - return VolumeStates.EXTENDING - } -} diff --git a/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.html b/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.html deleted file mode 100644 index e19151cd58..0000000000 --- a/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.html +++ /dev/null @@ -1,544 +0,0 @@ -
    -
    -
    Public Key
    -
    -
    - Info: You need to set a valid SSH Key before you can start machines for your workshop. Please - set a valid key below or on your personal data page. -
    -
    - - - - -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    - Add workshop VMs -
    -
    - - To learn more about workshops, please see our - WIKI. - -
    -
    -
    - - -
    -
    -
    - -
    -
    -
    The client is currently unavailable.
    -
    -
    - -
    -
    -
    - {{ workshop.shortname }} - {{ workshop.longname }} -
    -
    VMs: {{ workshop.vm_list.length }}
    -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    -
    -
    -
    -
    - Information for ephemeral flavors: - Ephemeral storage is not best suited for persistent data. Read more - here . -
    -
    -
    -
    - - -
    -
    -
    - - -
    - Browser-based Research Environments - (e.g. RStudio, Apache Guacamole, Theia IDE) - BETA - -
    - - -
    -
    -
    - - -
    -
    - -
    - Choose project members of {{ selected_project[0] }} you want to start a vm - for - -
    -
    - If no research environment is selected, only vms can be started for members who have set an SSH - key. Otherwise no connection to the VM can be established. -
    -
    - - - - - - - - - - - - - - - - - - -
    Full NameVm started for this user in this workshopSSH Key SetAction
    - {{ member.userName }} -

    (Group admin)

    -
    - - - {{ member.vm_amount }} VMs started in this workshop for this user - - - - - -   -   - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    - -
    - -
    -
    -
    - - -
    -
    - -
    - The corresponding client is currently offline. If you have any questions please contact - {{ CLOUD_PORTAL_SUPPORT_MAIL }}. Check our - status overview to see if the site - of your project is reachable. -
    -
    -
    - -
    -
    -
    -
    - - - -
    diff --git a/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.scss b/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.ts b/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.ts deleted file mode 100644 index 8180c2ca71..0000000000 --- a/src/app/virtualmachines/workshop/add-workshop/add-workshop.component.ts +++ /dev/null @@ -1,466 +0,0 @@ -import { Component, DoCheck, OnDestroy, OnInit, ViewChild } from '@angular/core' -import { Subscription } from 'rxjs' -import { KeyValue } from '@angular/common' -import transliterate from '@sindresorhus/transliterate' -import { Router } from '@angular/router' - -import { Workshop } from '../workshop.model' -import { Userinfo } from '../../../userinfo/userinfo.model' -import { GroupService } from '../../../api-connector/group.service' -import { Client } from '../../../vo_manager/clients/client.model' -import { BlockedImageTagResenv } from '../../../facility_manager/image-tag' -import { ImageService } from '../../../api-connector/image.service' -import { ApplicationRessourceUsage } from '../../../applications/application-ressource-usage/application-ressource-usage' -import { Flavor } from '../../virtualmachinemodels/flavor' -import { Image } from '../../virtualmachinemodels/image' -import { FlavorService } from '../../../api-connector/flavor.service' -import { UserService } from '../../../api-connector/user.service' -import { ResEnvComponent } from '../../conda/res-env.component' -import { ProjectMember } from '../../../projectmanagement/project_member.model' -import { CLOUD_PORTAL_SUPPORT_MAIL, STATUS_LINK, WIKI_WORKSHOPS, WIKI_EPHEMERAL_LINK } from '../../../../links/links' -import { VirtualmachineService } from '../../../api-connector/virtualmachine.service' -import { WorkshopService } from '../../../api-connector/workshop.service' -import { BiocondaService } from '../../../api-connector/bioconda.service' - -@Component({ - selector: 'app-add-workshop', - templateUrl: './add-workshop.component.html', - styleUrls: ['./add-workshop.component.scss'], - providers: [ - GroupService, - ImageService, - FlavorService, - UserService, - VirtualmachineService, - WorkshopService, - BiocondaService - ] -}) -export class AddWorkshopComponent implements OnInit, OnDestroy, DoCheck { - title: string = 'New workshop VMs' - - WIKI_WORKSHOPS: string = WIKI_WORKSHOPS - STATUS_LINK: string = STATUS_LINK - WIKI_EPHEMERAL_LINK: string = WIKI_EPHEMERAL_LINK - - /** - * The selected workshop. - */ - selected_workshop: Workshop - /** - * List of all workshops. - */ - workshops: Workshop[] = [] - /** - * If all needed data is loaded. - */ - is_loaded: boolean = false - /** - * Userinfo of the user who wants to start a workshop. - */ - userinfo: Userinfo - /** - * All simplevm application with workshop set to true where user is admin. - */ - projects: [string, number][] = [] - /** - * Selected Application for workshops. - */ - selected_project: [string, number] - /** - * Subscription object. - */ - subscription: Subscription = new Subscription() - /** - * If the client for a project is viable. - */ - client_available: boolean = false - /** - * If all project data is loaded. - */ - @ViewChild('res_env') res_env_component: ResEnvComponent - resenv_selected: boolean = false - res_env_valid: boolean = true - res_env_needs_template: boolean = false - res_env_okay_needed: boolean = false - gave_okay: boolean = false - project_data_loaded: boolean = false - credits_allowed: boolean = false - new_cores: number = 0 - new_ram: number = 0 - new_gpus: number = 0 - new_vms: number = 0 - client_checked: boolean = false - selected_project_client: Client - blocked_image_tags_resenv: BlockedImageTagResenv[] - has_forc: boolean = false - forc_url: string = '' - flavors: Flavor[] = [] - selected_flavor: Flavor = undefined - flavors_loaded: boolean = false - - selected_image: Image = undefined - data_loaded: boolean = false - selected_project_ressources: ApplicationRessourceUsage - selected_flavor_type: string = 'Standard Flavors' - flavor_types: { [name: string]: Flavor[] } = {} - workshop_data_loaded: boolean = false - members_to_add: ProjectMember[] = [] - project_members: ProjectMember[] = [] - member_data_loaded: boolean = false - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - vm_responsibility: boolean = false - started_machine: boolean = false - progress_bar_animated: string = 'progress-bar-animated' - progress_bar_width: number = 0 - resenv_names: string[] = [] - - constructor( - private group_service: GroupService, - private image_service: ImageService, - private flavor_service: FlavorService, - private user_service: UserService, - private virtual_machine_service: VirtualmachineService, - private workshop_service: WorkshopService, - private router: Router, - private condaService: BiocondaService - ) {} - - ngOnInit(): void { - this.get_applications() - this.get_user_data() - } - - ngOnDestroy() { - this.subscription.unsubscribe() - } - - ngDoCheck(): void { - if (this.res_env_component) { - this.res_env_valid = this.res_env_component.isValid() - this.res_env_needs_template = this.res_env_component.needsTemplate() - this.res_env_okay_needed = this.res_env_component.okayNeeded() - } - } - - get_applications(): void { - this.projects = [] - this.subscription.add( - this.group_service.getSimpleVmByUserWhereWorkshopAndAdmin().subscribe((projects: any) => { - for (const project of projects) { - this.projects.push(project) - } - this.is_loaded = true - }) - ) - } - - get_user_data(): void { - this.subscription.add( - this.user_service.getUserInfo().subscribe((result: Userinfo) => { - this.userinfo = result - }) - ) - } - - get_members_of_the_project(): void { - this.subscription.add( - this.group_service - .getGroupMembers(this.selected_project[1].toString()) - .subscribe((members: ProjectMember[]): void => { - this.project_members = members - this.member_data_loaded = true - this.check_project_data_loaded() - }) - ) - } - - get_selected_project_client(): void { - this.subscription.add( - this.group_service.getCreditsAllowedByPerunId(this.selected_project[1]).subscribe((res: any): void => { - this.credits_allowed = res['credits_allowed'] - }) - ) - - this.subscription.add( - this.group_service.getClient(this.selected_project[1].toString()).subscribe((client: Client): void => { - this.load_project_data() - if (client.status && client.status === 'Connected' && client.activated) { - this.client_available = true - this.client_checked = true - this.get_forc() - } else { - this.client_available = false - this.client_checked = true - } - this.selected_project_client = client - this.subscription.add( - this.image_service - .getBlockedImageTagsResenv(Number(this.selected_project_client.id), 'true') - .subscribe((tags: BlockedImageTagResenv[]): void => { - this.blocked_image_tags_resenv = tags - }) - ) - }) - ) - } - - get_workshops_for_application(): void { - this.workshops = [] - this.subscription.add( - this.workshop_service.getWorkshops(this.selected_project[1]).subscribe((workshops: Workshop[]) => { - for (const workshop of workshops) { - this.subscription.add( - this.workshop_service.loadWorkshopWithVms(workshop.id).subscribe((workshop_with_vms: Workshop) => { - this.workshops.push(workshop_with_vms) - }) - ) - } - }) - ) - } - - load_project_data(): void { - this.subscription.add( - this.group_service - .getGroupResources(this.selected_project[1].toString()) - .subscribe((res: ApplicationRessourceUsage): void => { - this.selected_project_ressources = new ApplicationRessourceUsage(res) - this.data_loaded = true - this.check_project_data_loaded() - }) - ) - this.get_flavors(this.selected_project[1]) - this.get_members_of_the_project() - } - - get_forc(): void { - this.subscription.add( - this.group_service.getClientForcUrl(this.selected_project[1].toString()).subscribe((response: JSON): void => { - if (response['forc_url'] !== null) { - this.has_forc = true - this.forc_url = response['forc_url'] - } - }) - ) - } - - get_flavors(id: number): void { - this.subscription.add( - this.flavor_service.getFlavors(id).subscribe( - (flavors: Flavor[]): void => { - this.flavors = flavors - this.flavor_types = this.flavor_service.sortFlavors(this.flavors) - this.flavors_loaded = true - this.check_project_data_loaded() - }, - (error: any) => { - console.log(error) - this.flavors = [] - this.flavor_types = {} - this.flavors_loaded = true - this.check_project_data_loaded() - } - ) - ) - } - - check_project_data_loaded(): void { - if (this.flavors_loaded && this.data_loaded && this.member_data_loaded) { - this.project_data_loaded = true - this.is_loaded = true - } - } - - set_selected_workshop(workshop: Workshop): void { - this.selected_workshop = workshop - this.workshop_data_loaded = true - - for (const member of this.project_members) { - member.vm_amount = 0 - member.hasVM = false - for (const workshopvm of this.selected_workshop.vm_list) { - if (member.elixirId === workshopvm.elixirid) { - member.hasVM = true - member.vm_amount += 1 - } - } - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - unsorted(a: KeyValue, b: KeyValue): number { - return 0 - } - - set_selected_flavor_type(key: string): void { - this.selected_flavor_type = key - } - - set_selected_flavor(flavor: Flavor): void { - this.selected_flavor = flavor - this.new_cores = this.selected_flavor.vcpus - this.new_ram = this.selected_flavor.ram_gib - this.new_gpus = this.selected_flavor.gpu - } - - set_selected_image(image: Image): void { - this.selected_image = image - this.has_image_resenv() - } - - has_image_resenv(): void { - for (const mode of this.selected_image.modes) { - for (const template of this.res_env_component.templates) { - if (template.template_name === mode.name) { - this.resenv_selected = true - this.res_env_component.setOnlyNamespace(template) - - return - } - } - } - this.resenv_selected = false - this.res_env_component.unsetOnlyNamespace() - } - - get_playbook_information(name: string): string { - const playbook_info: { - [name: string]: { - [variable: string]: string - } - } = {} - - if (this.res_env_component && this.res_env_component.selectedTemplate.template_name !== 'undefined') { - playbook_info[this.res_env_component.selectedTemplate.template_name] = { - create_only_backend: `${this.res_env_component.getCreateOnlyBackend()}` - } - playbook_info['user_key_url'] = { user_key_url: name } - } - - return JSON.stringify(playbook_info) - } - - /** - * Creates a concatenation of workshop shortname and user name. - * Also translates all characters to latin representation, removes all other characters not in [a-zA-Z0-9] and slices - * it to max 64 characters. - * @param user_name Name to append to workshop shortname. - */ - create_name(user_name: string): string { - let name: string = `${this.selected_workshop.shortname}${user_name}` - name = transliterate(name) - name = name.replace(/[^a-zA-Z0-9]/g, '') - name = name.slice(0, 25) - - return name - } - - start_vms(): void { - this.started_machine = true - const servers: { [key: string]: string }[] = [] - const re: RegExp = /\+/gi - const flavor_fixed: string = this.selected_flavor.name.replace(re, '%2B') - for (const member of this.members_to_add) { - const name: string = this.create_name(`${member.lastName}${member.firstName}`) - - // Playbook and Research-Environment stuff - const playbook_information: string = this.get_playbook_information(name) - servers.push({ - name, - playbook_information, - elixirId: member.elixirId, - userName: `${member.lastName}${member.firstName}` - }) - } - this.delay(500) - .then((): any => { - this.progress_bar_width = 50 - }) - .catch((): any => {}) - this.subscription.add( - this.virtual_machine_service - .startWorkshopVMs( - flavor_fixed, - this.selected_image, - servers, - this.selected_project[0], - this.selected_project[1].toString(), - this.selected_workshop.shortname - ) - .subscribe( - () => { - this.progress_bar_width = 75 - setTimeout((): void => { - void this.router.navigate(['/virtualmachines/vmOverview']).then().catch() - }, 2000) - }, - (error: any) => { - console.log(error) - } - ) - ) - } - - async delay(ms: number): Promise { - await new Promise((resolve: any): any => setTimeout(resolve, ms)) - } - - add_member(member: ProjectMember): void { - this.members_to_add.push(member) - } - - remove_member(member: ProjectMember): void { - this.members_to_add.splice(this.members_to_add.indexOf(member), 1) - } - - reset_all_data(): void { - this.selected_project = null - this.selected_workshop = null - this.workshops = [] - this.reset_on_project_change() - this.reset_on_workshop_change() - } - - reset_on_project_change(): void { - this.reset_on_workshop_change() - this.has_forc = false - this.forc_url = '' - this.selected_project_client = null - this.client_checked = false - this.client_available = false - this.project_data_loaded = false - this.flavors = [] - this.data_loaded = false - this.flavors_loaded = false - this.selected_workshop = null - this.credits_allowed = false - this.project_members = [] - this.member_data_loaded = false - this.selected_project_ressources = null - this.flavor_types = {} - } - - reset_on_workshop_change(): void { - this.new_cores = 0 - this.new_gpus = 0 - this.new_ram = 0 - this.new_vms = 0 - this.workshop_data_loaded = false - this.selected_image = undefined - this.selected_flavor = undefined - this.selected_flavor_type = 'Standard Flavors' - this.members_to_add = [] - this.vm_responsibility = false - this.started_machine = false - this.resenv_selected = false - this.res_env_valid = true - this.res_env_needs_template = false - this.res_env_okay_needed = false - this.gave_okay = false - this.progress_bar_width = 0 - if (this.res_env_component) { - this.res_env_component.resetData() - } - } -} diff --git a/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.html b/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.html deleted file mode 100644 index 20649a0e9c..0000000000 --- a/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.html +++ /dev/null @@ -1,782 +0,0 @@ -
    An Error has occurred. {{ errorMessage }}
    - -
    - -
    -
    - - To learn more about workshops, please see our - WIKI. - - - While standard accounts are recommended, we understand that the registration process can be time-consuming for - workshop attendees. That's why LifeScience is offering hostel accounts as an alternative. These accounts feature a - straightforward username and password login, making the registration process simpler for your participants. Please - share the following - registration link with your - attendees and instruct them to select "LifeScience Hostel" for future logins. - - - Often Workshop participants need access to the same data. Unfortunately, it is not yet possible to create volume - snapshots for SimpleVM projects. However, since this is an important feature for the workshops to provide the same - data to the participants and a manual creation of the individual volumes would be very time-consuming for the - workshop organizer, we offer as long as the volume snapshot feature is not yet available, that we create multiple - copies of a volume prepared by you and assign them to your project. Please contact us by mail at - {{ CLOUD_PORTAL_SUPPORT_MAIL }}. - -
    -
    -
    - - -
    -
    - -
    -
    - Getting workshops... -
    - No workshops found. -
    - -
    -
    -
    -
    -
    - -
    -
    -
    - Getting project members... -
    -
    -
    -
    - -
    -
    -
    -
    -
    - - Workshops -
    -
    -
    Please select a workshop:
    -
    - - - -
    -
    - -
    - - - Your workshop longname must contain between 3 and 256 characters and may only contain letters and - numbers. - -
    -
    - -
    - - - Your workshop shortname must contain between 3 and 8 characters, may only contain letters and numbers - and has to be unique among your project. - -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - -
    User Info - Vm Info - -
    -
    - {{ member.projectMember.userName }}
    - {{ member.projectMember.email }}
    - Admin - Participant -
    -
    No workshop selected.No vms for this user. -
    -
    - -
    -
    - - - - {{ vm?.vm?.name }} - -
    - {{ vm.vm.status }}
    - - - {{ vm.urlData.resenv_url }} - -
    - - {{ vm.resenv_name | uppercase }} -
    - - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - Calender -
    - -
    -
    - You can enter time slots for the workshop in which work is actively carried out in the portal or on the - machines. This enables the de.NBI Cloud Team to improve the planning of portal updates, for example, so as - not to hinder or restrict the work of the participants at peak times. Please consider, that the existing - timeframes are displayed using the "Central European Time". The date you enter is - dependent on the timezone of your browser . Please enter the time slots day by day, to be - more precise! -
    -
    Existing timeframes
    - - - - - - - - - - - - - - - - - - - - - -
    #Start timeEnd timeWorkshopDescriptionAction
    {{ i + 1 }}{{ wstimeframe.start_time | date: 'dd/MM/yy HH:mm' : 'de' }}{{ wstimeframe.end_time | date: 'dd/MM/yy HH:mm' : 'de' }}{{ wstimeframe.workshop?.longname }}{{ wstimeframe.description }} - -
    -
    - There are no entered timeframes yet -
    -
    -
    -
    -
    Add new timeframes
    - - - -
    -
    -
    - -
    - -
    - - -
    - -
    - - -
    -
    - -
    -
    - - -
    - You are free to enter a short description of the planned event -
    -
    -
    - -
    -
    - - -
    - You are free to select a specific workshop this timeframe gets connected with. Otherwise it will be - just linked with your project. -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    - Please select a timeframe, where the start time is before the end time and in the future! -
    -
    -
    -
    -
    -
    -
    - An error occurred while loading the timeframes of this calender - please try again later! -
    -
    -
    - -
    -
    -
    - -
    - - - - - - - - - - - - - - - -
    diff --git a/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.scss b/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.ts b/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.ts deleted file mode 100644 index 4b46a074ea..0000000000 --- a/src/app/virtualmachines/workshop/workshop-overview/workshop-overview.component.ts +++ /dev/null @@ -1,448 +0,0 @@ -import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core' -import { Subscription } from 'rxjs' - -import { Workshop } from '../workshop.model' -import { GroupService } from '../../../api-connector/group.service' -import { UrlData } from '../workshop-urlinfo.model' -import { WorkshopService } from '../../../api-connector/workshop.service' -import { ProjectMember } from '../../../projectmanagement/project_member.model' -import { WorkshopVM } from '../workshop-vm.model' -import { WIKI_WORKSHOPS, CLOUD_PORTAL_SUPPORT_MAIL, LIFESCIENCE_HOSTEL_SIGNUP } from '../../../../links/links' -import { WorkshopTimeFrame } from '../workshopTimeFrame.model' - -interface MemberVm { - projectMember: ProjectMember - workshopVmLink: { [key: number]: WorkshopVM[] } -} - -@Component({ - selector: 'app-overview', - templateUrl: './workshop-overview.component.html', - styleUrls: ['./workshop-overview.component.scss'], - providers: [GroupService, WorkshopService] -}) -export class WorkshopOverviewComponent implements OnInit, OnDestroy { - title: string = 'Workshop management' - - @ViewChild('confirmInterferingSlotModal') confirmInterfereModal: any - - WIKI_WORKSHOPS: string = WIKI_WORKSHOPS - LIFESCIENCE_HOSTEL_SIGNUP: string = LIFESCIENCE_HOSTEL_SIGNUP - CLOUD_PORTAL_SUPPORT_MAIL: string = CLOUD_PORTAL_SUPPORT_MAIL - subscription: Subscription = new Subscription() - resend_info: boolean = false - sending_mails = false - sending_done = false - newWorkShopTimeFrame: WorkshopTimeFrame = null - workshops: Workshop[] = [] - selectedWorkshop: Workshop - memberVms: MemberVm[] = [] - workshopTimeFramesLoaded: boolean = false - errorLoadingTimeFrames: boolean = false - workshopTimeFrames: WorkshopTimeFrame[] = [] - loadedVmsForWorkshop: number[] = [] - projects: [string, number][] = [] - selectedProject: [string, number] - errorMessage: string = null - isLoaded: boolean = false - projectWorkshopsLoading: boolean = false - projectWorkshopsLoaded: boolean = false - projectMembersLoading: boolean = false - projectMembersLoaded: boolean = false - informationTitle: string = '' - informationType: string = '' - informationMessage: string = '' - deleting: boolean = false - deleteSuccess: boolean = false - invalidShortname: boolean = true - invalidLongname: boolean = true - newWorkshop: boolean = false - workshopCreationMessage: { message: string; success: boolean } = { message: '', success: false } - listOfOverlaps: WorkshopTimeFrame[] = [] - - @ViewChild('creationStatusModal') creationStatusModal: any - - constructor( - private workshopService: WorkshopService, - private groupService: GroupService - ) {} - - ngOnInit(): void { - this.newWorkShopTimeFrame = new WorkshopTimeFrame({ - id: null, - end_time: new Date(), - start_time: new Date(), - workshop: new Workshop(), - project: null, - description: '' - }) - this.getProjects() - } - - ngOnDestroy(): void { - this.subscription.unsubscribe() - } - - getProjects(): void { - this.projects = [] - this.subscription.add( - this.groupService.getSimpleVmByUserWhereWorkshopAndAdmin().subscribe((projects: any) => { - for (const project of projects) { - this.projects.push(project) - } - this.isLoaded = true - }) - ) - } - - projectChange(): void { - this.resetsOnProjectChange() - this.getWorkshopsForProject() - this.getMembersOfTheProject() - this.loadCalenderForSelectedProject() - } - - dayChanged(date: { year: number; month: number; day: number }): void { - this.newWorkShopTimeFrame.start_time.setDate(date.day) - this.newWorkShopTimeFrame.start_time.setMonth(date.month - 1) - this.newWorkShopTimeFrame.start_time.setFullYear(date.year) - - this.newWorkShopTimeFrame.end_time.setDate(date.day) - this.newWorkShopTimeFrame.end_time.setMonth(date.month - 1) - this.newWorkShopTimeFrame.end_time.setFullYear(date.year) - } - - startTimeChanged(time: { hour: number; minute: number }): void { - this.newWorkShopTimeFrame.start_time.setHours(time.hour) - this.newWorkShopTimeFrame.start_time.setMinutes(time.minute) - } - - endTimeChanged(time: { hour: number; minute: number }): void { - this.newWorkShopTimeFrame.end_time.setHours(time.hour) - this.newWorkShopTimeFrame.end_time.setMinutes(time.minute) - } - - createNewTimeFrame(): void { - if (this.checkTimeFrameOverlap()) { - this.confirmInterfereModal.show() - } else { - this.processAddAfterConfirm() - } - } - - datesOverlap(first_start: number, first_end: number, second_start: number, second_end: number): boolean { - return ( - (first_start >= second_start && first_start <= second_end) || - (first_end >= second_start && first_end <= second_end) || - (second_start >= first_start && second_start <= first_end) || - (second_end >= first_start && second_end <= first_end) - ) - } - - checkTimeFrameOverlap(): boolean { - // eslint-disable-next-line prefer-const - let interferingTimeframes: WorkshopTimeFrame[] = [] - - this.workshopTimeFrames.forEach((wstf: WorkshopTimeFrame) => { - const start_time: number = new Date(wstf.start_time).getTime() - const end_time: number = new Date(wstf.end_time).getTime() - if ( - this.datesOverlap( - start_time, - end_time, - this.newWorkShopTimeFrame.start_time.getTime(), - this.newWorkShopTimeFrame.end_time.getTime() - ) - ) { - interferingTimeframes.push(wstf) - } - }) - this.listOfOverlaps = interferingTimeframes - - return interferingTimeframes.length > 0 - } - - processAddAfterConfirm(): void { - this.workshopService.addWorkshopTimeFrame(this.selectedProject[1], this.newWorkShopTimeFrame).subscribe({ - next: () => { - this.loadCalenderForSelectedProject() - this.informationTitle = 'Success' - this.informationType = 'info' - this.informationMessage = 'The new timeframe got successfully added to the calender!' - }, - error: () => { - this.informationTitle = 'Error' - this.informationType = 'danger' - this.informationMessage = 'An error occured while adding the timeframe to the calender!' - } - }) - } - - deleteWorkshopTimeFrame(timeframe: WorkshopTimeFrame): void { - this.workshopService.removeWorkshopTimeFrame(this.selectedProject[1], timeframe).subscribe({ - next: () => { - this.loadCalenderForSelectedProject() - this.informationTitle = 'Success' - this.informationType = 'info' - this.informationMessage = 'The selected timeframe got successfully removed from the calender!' - }, - error: () => { - this.informationTitle = 'Error' - this.informationType = 'danger' - this.informationMessage = 'An error occured while removing the timeframe from the calender!' - } - }) - } - - getWorkshopsForProject(): void { - this.projectWorkshopsLoading = true - this.subscription.add( - this.workshopService.getWorkshops(this.selectedProject[1]).subscribe((workshops: Workshop[]) => { - this.workshops = workshops - this.selectedWorkshop = new Workshop() - this.projectWorkshopsLoading = false - this.projectWorkshopsLoaded = true - }) - ) - } - - getMembersOfTheProject(): void { - this.projectMembersLoading = true - this.memberVms = [] - this.subscription.add( - this.groupService - .getWorkshopMembers(this.selectedProject[1].toString()) - .subscribe((members: ProjectMember[]): void => { - for (const member of members) { - const workshopVmLink: { [key: number]: WorkshopVM[] } = {} - const membervm: MemberVm = { projectMember: member, workshopVmLink } - this.memberVms.push(membervm) - this.projectMembersLoading = false - this.projectMembersLoaded = true - } - }) - ) - } - - workshopChange(workshop: Workshop): void { - this.selectedWorkshop = workshop - this.newWorkShopTimeFrame = new WorkshopTimeFrame({ workshop: this.selectedWorkshop, start_time: new Date() }) - this.newWorkshop = false - this.invalidShortname = true - this.invalidLongname = true - this.loadVmsForSelectedProject() - } - - loadCalenderForSelectedProject(): void { - this.workshopTimeFramesLoaded = false - this.subscription.add( - this.workshopService.loadWorkshopCalender(this.selectedProject[1]).subscribe({ - next: (wsTimeFrames: WorkshopTimeFrame[]) => { - this.workshopTimeFrames = wsTimeFrames.sort((a, b) => { - if (a.start_time < b.start_time) { - return -1 - } else if (a.start_time > b.start_time) { - return 1 - } else { - return 0 - } - }) - this.workshopTimeFramesLoaded = true - this.errorLoadingTimeFrames = false - }, - error: () => { - this.workshopTimeFramesLoaded = true - this.errorLoadingTimeFrames = true - } - }) - ) - } - - loadVmsForSelectedProject(): void { - if (this.loadedVmsForWorkshop.includes(this.selectedWorkshop.id)) { - return - } - - this.subscription.add( - this.workshopService.loadWorkshopWithVms(this.selectedWorkshop.id).subscribe((workshopIncoming: Workshop) => { - for (let workshop of this.workshops) { - if (workshop.id === workshopIncoming.id) { - workshop = workshopIncoming - this.loadedVmsForWorkshop.push(workshop.id) - this.addVmsToProjectMembers(workshop) - this.getUrlDataForWorkshopVms(workshop) - } - } - }) - ) - } - - addVmsToProjectMembers(workshop: Workshop): void { - for (const member of this.memberVms) { - if (!(workshop.id in member.workshopVmLink)) { - member.workshopVmLink[workshop.id] = [] - } - for (const vm of workshop.vm_list) { - if (member.projectMember.elixirId === vm.elixirid) { - member.workshopVmLink[workshop.id].push(vm) - } - } - } - } - - resetSendingMails(): void { - this.resend_info = false - this.sending_mails = false - this.sending_done = false - } - - sendWorkshopVMsEmailInfo(): void { - this.sending_mails = true - this.sending_done = false - const vms: WorkshopVM[] = [] - for (const memberVm of this.memberVms) { - for (const wvm of memberVm.workshopVmLink[this.selectedWorkshop.id]) { - if (this.resend_info) { - vms.push(wvm) - } else if (!wvm.email_sent) { - vms.push(wvm) - } - } - } - - for (const vm of vms) { - this.sendWorkshopVMEMailInfo(vm) - } - this.sending_done = true - this.sending_mails = false - } - - sendWorkshopVMEMailInfo(workshop_vm: WorkshopVM): void { - this.subscription.add( - this.workshopService.sendWorkshopVmEmail(this.selectedWorkshop.id, workshop_vm?.vm?.openstackid).subscribe( - (upd_workshop_vm: WorkshopVM) => { - for (const memberVm of this.memberVms) { - for (const wvm of memberVm.workshopVmLink[this.selectedWorkshop.id]) { - if (wvm === workshop_vm) { - const idx: number = memberVm.workshopVmLink[this.selectedWorkshop.id].indexOf(wvm) - memberVm.workshopVmLink[this.selectedWorkshop.id][idx].email_sent = upd_workshop_vm.email_sent - } - } - } - }, - (error: any) => { - if ('error' in error) { - console.log(error) - } - } - ) - ) - } - - getUrlDataForWorkshopVms(workshop: Workshop): void { - for (const member of this.memberVms) { - if (!(workshop.id in member.workshopVmLink)) { - continue - } - for (const vm of member.workshopVmLink[workshop.id]) { - if (vm.vm.openstackid && vm.vm.openstackid !== '') { - vm.setLoadingUrlData(true) - this.subscription.add( - this.workshopService - .getResenvUrlForWorkshopVm(workshop.id, vm.vm.openstackid) - .subscribe((urlData: UrlData) => { - vm.setLoadingUrlData(false) - vm.setUrlData(urlData) - }) - ) - } - } - } - } - - cleanupWorkshop(): void { - const selectedId = this.selectedWorkshop.id - this.selectedWorkshop = new Workshop() - this.deleting = true - this.subscription.add( - this.workshopService.deleteWorkshop(selectedId).subscribe((result: boolean) => { - this.deleting = false - if (result) { - this.deleteSuccess = true - for (const workshop of this.workshops) { - if (workshop.id === selectedId) { - this.workshops.splice(this.workshops.indexOf(workshop), 1) - } - } - } else { - this.deleteSuccess = false - } - }) - ) - } - - resetsOnProjectChange(): void { - this.projectWorkshopsLoading = false - this.projectWorkshopsLoaded = false - - this.projectWorkshopsLoading = false - this.projectMembersLoaded = false - - this.workshops = [] - this.memberVms = [] - this.loadedVmsForWorkshop = [] - - this.newWorkshop = false - this.invalidLongname = true - this.invalidShortname = true - } - - checkShortname(shortname: string): void { - this.invalidShortname = shortname.length < 3 || shortname.length > 8 || !/^[a-zA-Z0-9\s]*$/.test(shortname) - } - - checkLongname(longname: string): void { - this.invalidLongname = longname.length < 3 || longname.length > 256 || !this.isASCII(longname) - } - - isASCII(testString: string): boolean { - // eslint-disable-next-line no-control-regex - return /^[\x00-\x7F]*$/.test(testString) - } - - blankWorkshop(): void { - this.newWorkshop = true - this.selectedWorkshop = new Workshop() - } - - createNewWorkshop(): void { - this.selectedWorkshop.shortname = this.selectedWorkshop.shortname.replace(/\s/g, '') - this.subscription.add( - this.workshopService.createWorkshop(this.selectedProject[1], this.selectedWorkshop).subscribe( - (workshop: Workshop) => { - this.workshops.push(workshop) - this.workshopChange(workshop) - this.workshopCreationMessage = { message: 'Workshop created successfully!', success: true } - this.creationStatusModal.show() - }, - (error: any) => { - if ('error' in error) { - this.selectedWorkshop.longname = '' - this.invalidLongname = true - this.selectedWorkshop.shortname = '' - this.invalidShortname = true - if (error['error']['error'] === 'unique_constraint') { - this.workshopCreationMessage = { - message: 'Workshop name already taken! Please select another name.', - success: false - } - } else { - this.workshopCreationMessage = { message: 'An error occured. Please try again!', success: false } - } - this.creationStatusModal.show() - } - } - ) - ) - } -} diff --git a/src/app/vo_manager/number-charts/number-charts.component.ts b/src/app/vo_manager/number-charts/number-charts.component.ts index 2acc4f0bfc..4015e54462 100644 --- a/src/app/vo_manager/number-charts/number-charts.component.ts +++ b/src/app/vo_manager/number-charts/number-charts.component.ts @@ -1,8 +1,6 @@ import { Component, OnInit } from '@angular/core' -import html2canvas from 'html2canvas' import * as saveSVG from 'save-svg-as-png' import bb, { areaSpline, bar, Chart } from 'billboard.js' -import { jsPDF } from 'jspdf' import * as d3 from 'd3' import { NumbersService } from '../../api-connector/numbers.service' @@ -105,27 +103,6 @@ export class NumberChartsComponent implements OnInit { ) } - /** - * Downloads the chart as a PDF-File - currently not in use - */ - downloadAsPDF(elementId: string, filename: string): void { - html2canvas(document.getElementById(elementId)) - .then((canvas: HTMLCanvasElement): void => { - // Few necessary setting options - const imgWidth: number = 208 - const imgHeight: number = (canvas.height * imgWidth) / canvas.width - const contentDataURL: string = canvas.toDataURL('image/png') - - const pdf: jsPDF = new jsPDF('p', 'mm', 'a4') // A4 size page of PDF - const position: number = 0 - pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight) - pdf.save(filename.concat('.pdf')) - }) - .catch((): void => { - console.log('failed to convert to pdf') - }) - } - /** * Downloads the numbers graphic as a png. */ From 328945f0e2072f4fa2fbacc95c213e778fa6fc7f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:31:58 +0000 Subject: [PATCH 09/19] feat(Dependencies): Update dependency follow-redirects to v1.15.9 | datasource | package | from | to | | ---------- | ---------------- | ------ | ------ | | npm | follow-redirects | 1.15.8 | 1.15.9 | --- package-lock.json | 12 ++++++------ package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef15007abc..ec24ed98c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.877.0", + "version": "4.878.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@denbi/cloud-portal-webapp", - "version": "4.877.0", + "version": "4.878.0", "dependencies": { "@angular-eslint/eslint-plugin": "^18.3.0", "@angular/animations": "18.2.3", @@ -42,7 +42,7 @@ "d3": "7.9.0", "export-to-csv": "1.4.0", "file-saver": "2.0.5", - "follow-redirects": "1.15.8", + "follow-redirects": "1.15.9", "html2canvas": "1.4.1", "is-promise": "4.0.0", "jsnlog": "2.30.0", @@ -10334,9 +10334,9 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.8.tgz", - "integrity": "sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", diff --git a/package.json b/package.json index d4b1064493..feedb6f247 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@denbi/cloud-portal-webapp", - "version": "4.877.0", + "version": "4.878.0", "description": "de.NBI Cloud Portal", "scripts": { "ng": "ng serve", @@ -52,7 +52,7 @@ "d3": "7.9.0", "export-to-csv": "1.4.0", "file-saver": "2.0.5", - "follow-redirects": "1.15.8", + "follow-redirects": "1.15.9", "html2canvas": "1.4.1", "is-promise": "4.0.0", "jsnlog": "2.30.0", From 3d2f5dc90dc22ac62eacc64ad262483c4de5faf8 Mon Sep 17 00:00:00 2001 From: vktrrdk Date: Fri, 6 Sep 2024 15:08:45 +0000 Subject: [PATCH 10/19] feat(Matomo): Set default id for staging --- src/environments/environment.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 98c1d2bf81..13461ee74d 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -5,7 +5,7 @@ const VO_NAME: string = window['env']['VO_NAME'] || 'denbi-dev' const NEW_SIMPLE_VM: string = window['env']['NEW_SIMPLE_VM'] || 'https://simplevm.denbi.de' -const MATOMO_SITE_ID = window['env']['MATOMO_SITE_ID'] || 22 +const MATOMO_SITE_ID = window['env']['MATOMO_SITE_ID'] || 26 const MATOMO_TRACKING_URL = window['env']['MATOMO_TRACKING_URL'] || 'https://piwik.cebitec.uni-bielefeld.de/' export const environment: any = { From e17ae3904de13dc2355fe5ead6b96fbca35c2049 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:16:11 +0000 Subject: [PATCH 11/19] feat(Dependencies): Update all non-major dependencies to v9.10.0 | datasource | package | from | to | | ---------- | ---------- | ----- | ------ | | npm | @eslint/js | 9.9.1 | 9.10.0 | | npm | eslint | 9.9.1 | 9.10.0 | --- package-lock.json | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec24ed98c6..558786f915 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4112,9 +4112,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4128,6 +4128,18 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", + "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -9430,16 +9442,17 @@ } }, "node_modules/eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", + "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", + "@eslint/js": "9.10.0", + "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -9462,7 +9475,6 @@ "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", From a07116ee09b37aeee9d4bd21cea189badd884bb8 Mon Sep 17 00:00:00 2001 From: dweinholz Date: Tue, 10 Sep 2024 17:33:50 +0200 Subject: [PATCH 12/19] fix(Application):now able to adjust fileds without changing flavor (#6192) Co-authored-by: denbicloud <46009071+denbicloud@users.noreply.github.com> --- .../modals/adjust-application/adjust-application.component.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/projectmanagement/modals/adjust-application/adjust-application.component.ts b/src/app/projectmanagement/modals/adjust-application/adjust-application.component.ts index 2c5841deb7..4e83a69405 100644 --- a/src/app/projectmanagement/modals/adjust-application/adjust-application.component.ts +++ b/src/app/projectmanagement/modals/adjust-application/adjust-application.component.ts @@ -54,6 +54,8 @@ export class AdjustApplicationComponent implements OnInit { this.adjustedApplication = new Application(this.application) this.getAvailableFlavorTypes() this.getAvailableFlavors() + + this.checkIfMinimumSelected() } getAvailableFlavors() { From 7996a865a01156b8ec2e830fd8619a6fa8f417a3 Mon Sep 17 00:00:00 2001 From: vktrrdk Date: Wed, 11 Sep 2024 15:52:19 +0000 Subject: [PATCH 13/19] wip - no form control instance attached... --- .../newsmanagement/facility-news.ts | 20 +++--- .../news-manager.component.html | 71 +++++++++---------- .../newsmanagement/news-manager.component.ts | 8 +-- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/app/facility_manager/newsmanagement/facility-news.ts b/src/app/facility_manager/newsmanagement/facility-news.ts index ed0f2ea583..cda9b2ec48 100644 --- a/src/app/facility_manager/newsmanagement/facility-news.ts +++ b/src/app/facility_manager/newsmanagement/facility-news.ts @@ -1,15 +1,15 @@ export class FacilityNews { - id; - title: string; - posted_at: string; - text: string; - motd: string; - tags: string[]; - facility: number; - valid_till: Date; - is_current_motd: boolean; + id + title: string + posted_at: string + text: string + motd: string + tags: string[] + facility: number + expire_at: Date + is_current_motd: boolean constructor(news?: Partial) { - Object.assign(this, news); + Object.assign(this, news) } } diff --git a/src/app/facility_manager/newsmanagement/news-manager.component.html b/src/app/facility_manager/newsmanagement/news-manager.component.html index c374597dd3..4b0fd0baab 100644 --- a/src/app/facility_manager/newsmanagement/news-manager.component.html +++ b/src/app/facility_manager/newsmanagement/news-manager.component.html @@ -36,6 +36,9 @@
    Please select the facilities to load news from:

    In case you also want to send the news as a mail to the users of your facility, please use the mail function on the Facility Overview page. +
    + When not setting a specific expiry date for this news, the news will be removed from the facility news + section of the de.NBI Cloud website after one year. @@ -56,7 +59,7 @@
    Please select the facilities to load news from:
    style="cursor: pointer" (click)="setCurrentNews(news)" [ngStyle]="{ - 'border-color': news.id === selectedFacilityNews.id ? '#005aa9' : '#c8ced3' + 'border-color': news.id === selectedFacilityNews.id ? '#005aa9' : '#c8ced3', }" >
    Please select the facilities to load news from:
    - Valid Till: - {{ news.valid_till | date: 'YYYY-MM-dd' }} - not set + Expires at: + {{ news.expire_at | date: 'YYYY-MM-dd' }} + not set

    @@ -162,8 +165,7 @@
    Please select the facilities to load news from:
    id="news_text" formControlName="text" name="news_text" - placeholder="e.g. Dear cloud users, -we are happy to inform..." + placeholder="e.g. Dear cloud users, we are happy to inform..." [class.is-invalid]=" selectedNewsForm.controls['text'].invalid && (selectedNewsForm.controls['text'].dirty || selectedNewsForm.controls['text'].touched) @@ -203,6 +205,33 @@
    Please select the facilities to load news from:
    +
    + + + +
    +
    Please select the facilities to load news from: >
    -
    -
    Set Expiry date for MOTD
    -
    -
    - valid till -
    - - -
    -

    diff --git a/src/app/facility_manager/newsmanagement/news-manager.component.ts b/src/app/facility_manager/newsmanagement/news-manager.component.ts index 2bd3a15991..7937ba0715 100644 --- a/src/app/facility_manager/newsmanagement/news-manager.component.ts +++ b/src/app/facility_manager/newsmanagement/news-manager.component.ts @@ -43,7 +43,7 @@ export class NewsManagerComponent implements OnInit, OnDestroy { title: new UntypedFormControl({ value: this.newFacilityNews.title, disabled: false }, Validators.required), text: new UntypedFormControl({ value: this.newFacilityNews.text, disabled: false }, Validators.required), motd: new UntypedFormControl({ value: this.newFacilityNews.motd, disabled: false }), - valid_till: new UntypedFormControl({ value: this.newFacilityNews.valid_till, disabled: false }), + expire_at: new UntypedFormControl({ value: this.newFacilityNews.expire_at, disabled: false }), entered_tags: new UntypedFormControl({ value: this.newFacilityNews.tags, disabled: false }) }) @@ -112,7 +112,7 @@ export class NewsManagerComponent implements OnInit, OnDestroy { news.title = this.selectedNewsForm.controls['title'].value news.text = this.selectedNewsForm.controls['text'].value news.motd = this.selectedNewsForm.controls['motd'].value - news.valid_till = this.selectedNewsForm.controls['valid_till'].value + news.expire_at = this.selectedNewsForm.controls['expire_at'].value news.facility = this.facilityToPost news.tags = this.selectedFacilityNews.tags if (document.getElementById(`news_select_${this.facilityToPost}_motd`)['checked']) { @@ -164,7 +164,7 @@ export class NewsManagerComponent implements OnInit, OnDestroy { news.title = this.selectedNewsForm.controls['title'].value news.text = this.selectedNewsForm.controls['text'].value news.motd = this.selectedNewsForm.controls['motd'].value - news.valid_till = this.selectedNewsForm.controls['valid_till'].value + news.expire_at = this.selectedNewsForm.controls['expire_at'].value news.facility = this.facilityToPost news.tags = this.selectedFacilityNews.tags if (document.getElementById(`news_select_${this.facilityToPost}_motd`)['checked']) { @@ -337,7 +337,7 @@ export class NewsManagerComponent implements OnInit, OnDestroy { text: new UntypedFormControl({ value: this.selectedFacilityNews.text, disabled: false }, Validators.required), motd: new UntypedFormControl({ value: this.selectedFacilityNews.motd, disabled: false }), tag: new UntypedFormControl({ value: this.selectedFacilityNews.tags, disabled: false }), - valid_till: new UntypedFormControl({ value: this.selectedFacilityNews.valid_till, disabled: false }), + expire_at: new UntypedFormControl({ value: this.selectedFacilityNews.expire_at, disabled: false }), entered_tags: new UntypedFormControl({ value: this.selectedFacilityNews.tags, disabled: false }) }) this.subscription.add( From 2ab483984425875952c6bb2588435c65d9ab963b Mon Sep 17 00:00:00 2001 From: vktrrdk Date: Thu, 12 Sep 2024 08:33:57 +0000 Subject: [PATCH 14/19] refactor(Form): mix of ngModel and Form-Control --- .../news-manager.component.html | 110 +++++++----------- .../newsmanagement/news-manager.component.ts | 48 ++------ src/app/pipe-module/pipe-module.module.ts | 7 +- src/app/pipe-module/pipes/news-valid.pipe.ts | 15 +++ 4 files changed, 70 insertions(+), 110 deletions(-) create mode 100644 src/app/pipe-module/pipes/news-valid.pipe.ts diff --git a/src/app/facility_manager/newsmanagement/news-manager.component.html b/src/app/facility_manager/newsmanagement/news-manager.component.html index 4b0fd0baab..d511e760a2 100644 --- a/src/app/facility_manager/newsmanagement/news-manager.component.html +++ b/src/app/facility_manager/newsmanagement/news-manager.component.html @@ -102,7 +102,7 @@
    Please select the facilities to load news from:
    -
    +
    Expires at: {{ news.expire_at | date: 'YYYY-MM-dd' }} not set @@ -110,7 +110,7 @@
    Please select the facilities to load news from:

    -
    - News needs a title. -
    +
    -
    - News needs some content. -
    +
    @@ -207,29 +174,35 @@
    Please select the facilities to load news from:
    - - +
    +
    + +
    +
    + +
    +
    @@ -244,7 +217,6 @@
    Please select the facilities to load news from:
    [addTagText]="'Set new Tag'" bindLabel="term" maxSelectedItems="10" - formControlName="entered_tags" placeholder="You are free to enter tags" dropdownPosition="bottom" [(ngModel)]="selectedFacilityNews.tags" @@ -322,7 +294,7 @@
    Please select the facilities to load news from:
    class="btn btn-success" style="margin: 5px" (click)="addModal.show()" - [disabled]="selectedNewsForm.invalid || !facilityToPost" + [disabled]="!facilityToPost || !(selectedFacilityNews | newsValid)" *ngIf="selectedFacilityNews.id === null" > Create & Upload News @@ -330,7 +302,7 @@
    Please select the facilities to load news from: