From eb2cceb256effb93d055389d42e9b1ee60803762 Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Fri, 6 Sep 2024 15:48:54 +0200 Subject: [PATCH 1/6] wip allocation drawer design --- web/mock-server/server.json | 2 +- .../allocations-drawer.component.html | 130 ++++++++++-------- .../allocations-drawer.component.scss | 15 +- .../allocations-drawer.component.ts | 65 ++++++--- .../allocations-drawer.module.ts | 3 +- .../services/envconfig/envconfig.service.ts | 2 +- 6 files changed, 141 insertions(+), 76 deletions(-) diff --git a/web/mock-server/server.json b/web/mock-server/server.json index 2829c2f6..50ec965c 100644 --- a/web/mock-server/server.json +++ b/web/mock-server/server.json @@ -1,4 +1,4 @@ { - "port": 3000, + "port": 9889, "routes": "mock-server/routes.json" } diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.html b/web/src/app/allocations-drawer/allocations-drawer.component.html index a58eb50a..80d8e49c 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.html +++ b/web/src/app/allocations-drawer/allocations-drawer.component.html @@ -1,82 +1,102 @@ - +
- {{ selectedRow?.applicationId }} ({{ selectedRow?.allocations?.length }} allocations) - + {{ selectedRow?.applicationId }} ({{ allocDataSource?.data?.length }} instances) + +
- - {{ - columnDef.colName }} - - - {{ - element['priority'] }} - + + {{ columnDef.colName }} + - - Logs - - - - - - -
    - -
  • - {{ resource }} -
  • -
  • - {{ resource }} -
  • + + + + + + + +
      + +
    • {{ resource }}
    • +
      +
    -
-
+
+ + {{ element[columnDef.colId] }} + +
- - {{ element[columnDef.colId] }} - - -
- - - {{ element[columnDef.colId] || 'n/a' - }} - + + + + {{ element[columnDef.colId] || 'n/a' }} + + + + +
No records found
+ + + +
+ + + +
+
+ - - - - + +
+ + {{ selectedAllocation?.displayName }} +
+ + + + + {{element.key}} + + + + + + + {{element.value}} + + + {{element.value}} + + + + + + + + +
+ +
-
\ No newline at end of file + diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.scss b/web/src/app/allocations-drawer/allocations-drawer.component.scss index 25d3cf10..55b7adfd 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.scss +++ b/web/src/app/allocations-drawer/allocations-drawer.component.scss @@ -1,3 +1,4 @@ +@import 'https://fonts.googleapis.com/icon?family=Material+Icons'; .mat-drawer-container { min-width: 430px; width: 55%; @@ -83,6 +84,11 @@ color: #f44336; } } + + .arrow-btn { + font-size: 1.2em; + padding-right: 10px; + } .copy-btn { font-size: 1em; cursor: pointer; @@ -135,6 +141,13 @@ } .row { - min-height: unset; + min-height: 30px; + } + .mat-mdc-row:nth-child(even){ + background-color: #f0f0f0; } + + .label-column { + font-weight: bold; + } } \ No newline at end of file diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.ts b/web/src/app/allocations-drawer/allocations-drawer.component.ts index 644fc100..d03b9443 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.component.ts @@ -27,10 +27,18 @@ export class AllocationsDrawerComponent implements OnInit { @Output() removeRowSelection = new EventEmitter(); + selectedAllocation: any; + showDetails: boolean = false; allocColumnDef: ColumnDef[] = []; allocColumnIds: string[] = []; selectedAllocationsRow: number = -1; + displayedColumns: string[] = ['key', 'value']; + + dataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); + + + ngOnChanges(): void { if (this.allocDataSource) { this.allocDataSource.paginator = this.allocPaginator; @@ -42,26 +50,17 @@ export class AllocationsDrawerComponent implements OnInit { ngOnInit(): void { this.allocColumnDef = [ { colId: "displayName", colName: "Display Name", colWidth: 1 }, - { colId: "allocationKey", colName: "Allocation Key", colWidth: 1 }, + { colId: "resource", colName: "Resource", colWidth: 1, colFormatter: CommonUtil.resourceColumnFormatter }, { colId: "nodeId", colName: "Node ID", colWidth: 1 }, - { - colId: "log", - colName: "Log Link", - colWidth: 1, - }, - { - colId: "resource", - colName: "Resource", - colFormatter: CommonUtil.resourceColumnFormatter, - colWidth: 1, - }, - { colId: "priority", colName: "Priority", colWidth: 0.5 }, + { colId: "state", colName: "State", colWidth: 1 }, ]; this.allocColumnIds = this.allocColumnDef.map((col) => col.colId); this.externalLogsBaseUrl = this.envConfig.getExternalLogsBaseUrl(); } + formatResources(colValue: string): string[] { + console.log(colValue); const arr: string[] = colValue.split("
"); // Check if there are "cpu" or "Memory" elements in the array const hasCpu = arr.some((item) => item.toLowerCase().includes("cpu")); @@ -72,10 +71,10 @@ export class AllocationsDrawerComponent implements OnInit { if (!hasMemory) { arr.unshift("Memory: n/a"); } - + // Concatenate the two arrays, with "cpu" and "Memory" elements first - const cpuAndMemoryElements = arr.filter((item) => item.toLowerCase().includes("CPU") || item.toLowerCase().includes("Memory")); - const otherElements = arr.filter((item) => !item.toLowerCase().includes("CPU") && !item.toLowerCase().includes("Memory")); + const cpuAndMemoryElements = arr.filter((item) => item.toLowerCase().includes("cpu") || item.toLowerCase().includes("memory")); + const otherElements = arr.filter((item) => !item.toLowerCase().includes("cpu") && !item.toLowerCase().includes("memory")); const result = cpuAndMemoryElements.concat(otherElements); return result; @@ -85,7 +84,35 @@ export class AllocationsDrawerComponent implements OnInit { return this.allocDataSource?.data && this.allocDataSource.data.length === 0; } - allocationsDetailToggle(row: number) { + allocationsDetailToggle(row: any) { + this.showDetails = true; + this.selectedAllocation = row; + console.log("data", row); + const newData = [ + { key: 'User', value: row.user }, + { key: 'Name', value: row.name }, + { key: 'Application Type', value: row.applicationType }, + { key: 'Application Tags', value: row.applicationTags }, + { key: 'Application Priority', value: row.applicationPriority }, + { key: 'YarnApplication State', value: row.yarnApplicationState }, + { key: 'Queue', value: row.queue }, + { key: 'FinalStatus Reported by AM', value: row.finalStatusReportedByAM }, + { key: 'Started', value: row.started }, + { key: 'Launched', value: row.launched }, + { key: 'Finished', value: row.finished }, + { key: 'Elapsed', value: row.elapsed }, + { key: 'Tracking URL', value: 'History', link: row.trackingUrl }, + { key: 'Log Aggregation Status', value: row.logAggregationStatus }, + { key: 'Application Timeout (Remaining Time)', value: row.applicationTimeout }, + { key: 'Unmanaged Application', value: row.unmanagedApplication }, + { key: 'Application Node Label Expression', value: row.applicationNodeLabelExpression }, + { key: 'AM Container Node Label Expression', value: row.amContainerNodeLabelExpression } + ]; + + + console.log('new data', newData); + this.dataSource.data = newData; + console.log(this.selectedAllocation); if (this.selectedAllocationsRow !== -1) { if (this.selectedAllocationsRow !== row) { this.allocDataSource.data[this.selectedAllocationsRow].expanded = false; @@ -101,6 +128,10 @@ export class AllocationsDrawerComponent implements OnInit { } } + goBackToTable(){ + this.showDetails = false; + } + closeDrawer() { this.selectedAllocationsRow = -1; this.matDrawer.close(); diff --git a/web/src/app/allocations-drawer/allocations-drawer.module.ts b/web/src/app/allocations-drawer/allocations-drawer.module.ts index 6933c0a4..57414b93 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.module.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; import { MatPaginatorModule } from "@angular/material/paginator"; import { MatSidenavModule } from "@angular/material/sidenav"; +import { MatIconModule } from '@angular/material/icon'; import { MatSortModule } from "@angular/material/sort"; import { MatTableModule } from "@angular/material/table"; import { MatTooltipModule } from "@angular/material/tooltip"; @@ -10,7 +11,7 @@ import { AllocationsDrawerComponent } from "./allocations-drawer.component"; @NgModule({ declarations: [AllocationsDrawerComponent], - imports: [CommonModule, MatSortModule, MatSidenavModule, MatPaginatorModule, MatTableModule, MatTooltipModule, BrowserModule], + imports: [CommonModule, MatSortModule, MatSidenavModule, MatPaginatorModule, MatTableModule, MatTooltipModule, MatIconModule, BrowserModule], exports: [AllocationsDrawerComponent], }) export class AllocationsDrawerModule {} diff --git a/web/src/app/services/envconfig/envconfig.service.ts b/web/src/app/services/envconfig/envconfig.service.ts index 579e14de..81c376d6 100644 --- a/web/src/app/services/envconfig/envconfig.service.ts +++ b/web/src/app/services/envconfig/envconfig.service.ts @@ -42,7 +42,7 @@ export class EnvConfigService { this.uiHostname = window.location.hostname; this.uiPort = window.location.port; this.envConfig = { - localYhsComponentsWebAddress: "http://localhost:3000", + localYhsComponentsWebAddress: "http://localhost:8989", }; } From c52a106f0067359d55e58e6ab274c46be5401f30 Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Tue, 10 Sep 2024 15:38:28 +0200 Subject: [PATCH 2/6] adding filters for mat table --- web/package-lock.json | 336 ++++++++++++++++++ .../allocations-drawer.component.html | 23 +- .../allocations-drawer.component.spec.ts | 7 +- .../allocations-drawer.component.ts | 65 ++-- .../allocations-drawer.module.ts | 4 +- web/src/app/app.component.ts | 2 +- .../services/envconfig/envconfig.service.ts | 2 +- web/yarn.lock | 204 ++++++----- 8 files changed, 531 insertions(+), 112 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 62f70484..4b3a7475 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -31,6 +31,7 @@ "@angular/compiler-cli": "^16.2.0", "@types/jasmine": "~4.3.0", "jasmine-core": "~4.6.0", + "json-server": "^0.17.4", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", @@ -5312,6 +5313,24 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5942,6 +5961,15 @@ "node": ">=0.8" } }, + "node_modules/connect-pause": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.1.tgz", + "integrity": "sha512-a1gSWQBQD73krFXdUEYJom2RTFrWUL3YvXDCRkyv//GVXc79cdW9MngtRuN9ih4FDKBtfJAJId+BbDuX+1rh2w==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/connect/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6782,6 +6810,19 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -7079,6 +7120,31 @@ "node": ">= 0.10.0" } }, + "node_modules/express-urlrewrite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/express-urlrewrite/-/express-urlrewrite-1.4.0.tgz", + "integrity": "sha512-PI5h8JuzoweS26vFizwQl6UTF25CAHSggNv0J25Dn/IKZscJHWZzPrI5z2Y2jgOzIaw2qh8l6+/jUcig23Z2SA==", + "dev": true, + "dependencies": { + "debug": "*", + "path-to-regexp": "^1.0.3" + } + }, + "node_modules/express-urlrewrite/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/express-urlrewrite/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, "node_modules/express/node_modules/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", @@ -8411,6 +8477,12 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -8662,6 +8734,12 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8751,12 +8829,124 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==", + "dev": true, + "dependencies": { + "jju": "^1.1.0" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/json-server": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-0.17.4.tgz", + "integrity": "sha512-bGBb0WtFuAKbgI7JV3A864irWnMZSvBYRJbohaOuatHwKSRFUfqtQlrYMrB6WbalXy/cJabyjlb7JkHli6dYjQ==", + "dev": true, + "dependencies": { + "body-parser": "^1.19.0", + "chalk": "^4.1.2", + "compression": "^1.7.4", + "connect-pause": "^0.1.1", + "cors": "^2.8.5", + "errorhandler": "^1.5.1", + "express": "^4.17.1", + "express-urlrewrite": "^1.4.0", + "json-parse-helpfulerror": "^1.0.3", + "lodash": "^4.17.21", + "lodash-id": "^0.14.1", + "lowdb": "^1.0.0", + "method-override": "^3.0.0", + "morgan": "^1.10.0", + "nanoid": "^3.1.23", + "please-upgrade-node": "^3.2.0", + "pluralize": "^8.0.0", + "server-destroy": "^1.0.1", + "yargs": "^17.0.1" + }, + "bin": { + "json-server": "lib/cli/bin.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/json-server/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/json-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/json-server/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/json-server/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/json-server/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/json-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9128,6 +9318,15 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash-id": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.1.tgz", + "integrity": "sha512-ikQPBTiq/d5m6dfKQlFdIXFzvThPi2Be9/AHxktOnDSfSxE1j9ICbBT5Elk1ke7HSTgM38LHTpmJovo9/klnLg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -9236,6 +9435,31 @@ "node": ">=8.0" } }, + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lowdb/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -9534,6 +9758,36 @@ "node": ">= 8" } }, + "node_modules/method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "dev": true, + "dependencies": { + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/method-override/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/method-override/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -9887,6 +10141,49 @@ "node": "*" } }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -11028,6 +11325,24 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -11890,6 +12205,12 @@ "node": ">=10" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -12065,6 +12386,12 @@ "node": ">= 0.8.0" } }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "dev": true + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -12554,6 +12881,15 @@ "node": ">= 0.6" } }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, "node_modules/streamroller": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.html b/web/src/app/allocations-drawer/allocations-drawer.component.html index 80d8e49c..6c42ca8c 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.html +++ b/web/src/app/allocations-drawer/allocations-drawer.component.html @@ -8,7 +8,28 @@
- +
+ + + {{ state }} + + + + + + {{ node }} + + + + + + Show all instances + {{ instance }} + + +
+ + {{ columnDef.colName }} diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.spec.ts b/web/src/app/allocations-drawer/allocations-drawer.component.spec.ts index ba0786f1..64ffbbce 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.spec.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.component.spec.ts @@ -18,6 +18,8 @@ import { MockSchedulerService, } from '@app/testing/mocks'; import {EnvConfigService} from '@app/services/envconfig/envconfig.service'; +import { MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldModule } from "@angular/material/form-field"; +import { MatDialogModule } from "@angular/material/dialog"; describe("AllocationsDrawerComponent", () => { let component: AllocationsDrawerComponent; @@ -35,10 +37,13 @@ describe("AllocationsDrawerComponent", () => { MatInputModule, MatTableModule, MatSelectModule, + MatFormFieldModule, + MatDialogModule, ], providers: [ { provide: EnvConfigService, useValue: MockEnvconfigService }, - { provide: NgxSpinnerService, useValue: MockNgxSpinnerService } + { provide: NgxSpinnerService, useValue: MockNgxSpinnerService }, + { provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: {appearance: 'outline'}} ], }); fixture = TestBed.createComponent(AllocationsDrawerComponent); diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.ts b/web/src/app/allocations-drawer/allocations-drawer.component.ts index d03b9443..4660119f 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.component.ts @@ -37,7 +37,17 @@ export class AllocationsDrawerComponent implements OnInit { dataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); + filteredDataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); + // Variabili per il filtro + selectedState: string = ''; + selectedNode: string = ''; + selectedInstance: string = ''; + + // Stati, nodi, e istanze per il dropdown + states = ['Running', 'Unknown', 'Failed', 'Succeeded']; + nodes = ['lima-rancher-desktop', 'Custom name 1', 'Custom name 2', 'Custom name 3']; + instances = ['default/sleep-dp-7b89667644-ff75z', 'default/sleep-dp-7b89667644-ff75m']; ngOnChanges(): void { if (this.allocDataSource) { @@ -56,6 +66,21 @@ export class AllocationsDrawerComponent implements OnInit { ]; this.allocColumnIds = this.allocColumnDef.map((col) => col.colId); this.externalLogsBaseUrl = this.envConfig.getExternalLogsBaseUrl(); + this.filteredDataSource.data = this.dataSource.data; + } + + applyFilter(): void { + + this.filteredDataSource.data = this.dataSource.data.filter(item => { + /* + const matchesState = this.selectedState ? item.state === this.selectedState : true; + const matchesNode = this.selectedNode ? item.node === this.selectedNode : true; + const matchesInstance = this.selectedInstance ? item.instance === this.selectedInstance : true; + return matchesState && matchesNode && matchesInstance; + + */ + return true; + }); } @@ -87,30 +112,28 @@ export class AllocationsDrawerComponent implements OnInit { allocationsDetailToggle(row: any) { this.showDetails = true; this.selectedAllocation = row; - console.log("data", row); + console.log("data", this.selectedRow); const newData = [ - { key: 'User', value: row.user }, - { key: 'Name', value: row.name }, - { key: 'Application Type', value: row.applicationType }, - { key: 'Application Tags', value: row.applicationTags }, - { key: 'Application Priority', value: row.applicationPriority }, - { key: 'YarnApplication State', value: row.yarnApplicationState }, - { key: 'Queue', value: row.queue }, - { key: 'FinalStatus Reported by AM', value: row.finalStatusReportedByAM }, - { key: 'Started', value: row.started }, - { key: 'Launched', value: row.launched }, - { key: 'Finished', value: row.finished }, - { key: 'Elapsed', value: row.elapsed }, - { key: 'Tracking URL', value: 'History', link: row.trackingUrl }, - { key: 'Log Aggregation Status', value: row.logAggregationStatus }, - { key: 'Application Timeout (Remaining Time)', value: row.applicationTimeout }, - { key: 'Unmanaged Application', value: row.unmanagedApplication }, - { key: 'Application Node Label Expression', value: row.applicationNodeLabelExpression }, - { key: 'AM Container Node Label Expression', value: row.amContainerNodeLabelExpression } + { key: 'User', value: null }, + { key: 'Name', value: null }, + { key: 'Application Type', value: null }, + { key: 'Application Tags', value: null }, + { key: 'Application Priority', value: null }, + { key: 'YarnApplication State', value: this.selectedRow?.applicationState }, + { key: 'Queue', value: row.queueName }, + { key: 'FinalStatus Reported by AM', value: null }, + { key: 'Started', value: null }, + { key: 'Launched', value: null }, + { key: 'Finished', value: null }, + { key: 'Elapsed', value: null }, + { key: 'Tracking URL', value: 'History', link: undefined }, + { key: 'Log Aggregation Status', value: null }, + { key: 'Application Timeout (Remaining Time)', value: null }, + { key: 'Unmanaged Application', value: null }, + { key: 'Application Node Label Expression', value: null }, + { key: 'AM Container Node Label Expression', value: null } ]; - - console.log('new data', newData); this.dataSource.data = newData; console.log(this.selectedAllocation); if (this.selectedAllocationsRow !== -1) { diff --git a/web/src/app/allocations-drawer/allocations-drawer.module.ts b/web/src/app/allocations-drawer/allocations-drawer.module.ts index 57414b93..fadda19c 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.module.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.module.ts @@ -8,10 +8,12 @@ import { MatTableModule } from "@angular/material/table"; import { MatTooltipModule } from "@angular/material/tooltip"; import { BrowserModule } from "@angular/platform-browser"; import { AllocationsDrawerComponent } from "./allocations-drawer.component"; +import { MatSelectModule } from "@angular/material/select"; +import { MatFormFieldModule } from "@angular/material/form-field"; @NgModule({ declarations: [AllocationsDrawerComponent], - imports: [CommonModule, MatSortModule, MatSidenavModule, MatPaginatorModule, MatTableModule, MatTooltipModule, MatIconModule, BrowserModule], + imports: [CommonModule, MatSortModule, MatSidenavModule, MatPaginatorModule, MatTableModule, MatTooltipModule, MatIconModule, BrowserModule, MatFormFieldModule, MatSelectModule], exports: [AllocationsDrawerComponent], }) export class AllocationsDrawerModule {} diff --git a/web/src/app/app.component.ts b/web/src/app/app.component.ts index 55b89253..7abfc9b0 100644 --- a/web/src/app/app.component.ts +++ b/web/src/app/app.component.ts @@ -7,4 +7,4 @@ import { Component } from '@angular/core'; }) export class AppComponent { title = 'yhs-components'; -} +} \ No newline at end of file diff --git a/web/src/app/services/envconfig/envconfig.service.ts b/web/src/app/services/envconfig/envconfig.service.ts index 81c376d6..d8626705 100644 --- a/web/src/app/services/envconfig/envconfig.service.ts +++ b/web/src/app/services/envconfig/envconfig.service.ts @@ -42,7 +42,7 @@ export class EnvConfigService { this.uiHostname = window.location.hostname; this.uiPort = window.location.port; this.envConfig = { - localYhsComponentsWebAddress: "http://localhost:8989", + localYhsComponentsWebAddress: "http://localhost:30001", }; } diff --git a/web/yarn.lock b/web/yarn.lock index f0ef7c4c..4d413d00 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -2930,7 +2930,7 @@ base64id@~2.0.0, base64id@2.0.0: basic-auth@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== dependencies: safe-buffer "5.1.2" @@ -3132,7 +3132,23 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.1.1: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3307,7 +3323,7 @@ connect-history-api-fallback@^2.0.0: connect-pause@^0.1.1: version "0.1.1" - resolved "https://registry.yarnpkg.com/connect-pause/-/connect-pause-0.1.1.tgz#b269b2bb82ddb1ac3db5099c0fb582aba99fb37a" + resolved "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.1.tgz" integrity sha512-a1gSWQBQD73krFXdUEYJom2RTFrWUL3YvXDCRkyv//GVXc79cdW9MngtRuN9ih4FDKBtfJAJId+BbDuX+1rh2w== connect@^3.7.0: @@ -3504,10 +3520,10 @@ date-format@^4.0.14: resolved "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -debug@*: - version "4.3.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" - integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== +debug@*, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4, debug@4: + version "4.3.5" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" @@ -3520,18 +3536,11 @@ debug@2.6.9: debug@3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - decimal.js@^10.2.1: version "10.4.3" resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" @@ -3575,17 +3584,12 @@ delegates@^1.0.0: resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -depd@2.0.0, depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -depd@2.0.0: +depd@~2.0.0, depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -3775,7 +3779,7 @@ error-ex@^1.3.1: errorhandler@^1.5.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" + resolved "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz" integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== dependencies: accepts "~1.3.7" @@ -3934,7 +3938,7 @@ exponential-backoff@^3.1.1: express-urlrewrite@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/express-urlrewrite/-/express-urlrewrite-1.4.0.tgz#985ee022773bac7ed32126f1cf9ec8ee48e1290a" + resolved "https://registry.npmjs.org/express-urlrewrite/-/express-urlrewrite-1.4.0.tgz" integrity sha512-PI5h8JuzoweS26vFizwQl6UTF25CAHSggNv0J25Dn/IKZscJHWZzPrI5z2Y2jgOzIaw2qh8l6+/jUcig23Z2SA== dependencies: debug "*" @@ -4725,7 +4729,7 @@ is-potential-custom-element-name@^1.0.1: is-promise@^2.1.0: version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== is-stream@^2.0.0: @@ -4750,16 +4754,16 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + isbinaryfile@^4.0.8: version "4.0.10" resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz" @@ -4847,7 +4851,7 @@ jiti@^1.18.2: jju@^1.1.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + resolved "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz" integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== js-tokens@^4.0.0: @@ -4930,7 +4934,7 @@ json-parse-even-better-errors@^3.0.0: json-parse-helpfulerror@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc" + resolved "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz" integrity sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg== dependencies: jju "^1.1.0" @@ -4947,7 +4951,7 @@ json-schema-traverse@^1.0.0: json-server@^0.17.4: version "0.17.4" - resolved "https://registry.yarnpkg.com/json-server/-/json-server-0.17.4.tgz#d4ef25a516e26d9ba86fd6db2f9d81a5f405421e" + resolved "https://registry.npmjs.org/json-server/-/json-server-0.17.4.tgz" integrity sha512-bGBb0WtFuAKbgI7JV3A864irWnMZSvBYRJbohaOuatHwKSRFUfqtQlrYMrB6WbalXy/cJabyjlb7JkHli6dYjQ== dependencies: body-parser "^1.19.0" @@ -5149,7 +5153,7 @@ locate-path@^7.1.0: lodash-id@^0.14.1: version "0.14.1" - resolved "https://registry.yarnpkg.com/lodash-id/-/lodash-id-0.14.1.tgz#dffa1f1f8b90d1803bb0d70b7d7547e10751e80b" + resolved "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.1.tgz" integrity sha512-ikQPBTiq/d5m6dfKQlFdIXFzvThPi2Be9/AHxktOnDSfSxE1j9ICbBT5Elk1ke7HSTgM38LHTpmJovo9/klnLg== lodash.debounce@^4.0.8: @@ -5157,7 +5161,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash@4, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.21, lodash@^4.7.0, lodash@4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5183,7 +5187,7 @@ log4js@^6.4.1: lowdb@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/lowdb/-/lowdb-1.0.0.tgz#5243be6b22786ccce30e50c9a33eac36b20c8064" + resolved "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz" integrity sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ== dependencies: graceful-fs "^4.1.3" @@ -5362,7 +5366,7 @@ merge2@^1.3.0, merge2@^1.4.1: method-override@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/method-override/-/method-override-3.0.0.tgz#6ab0d5d574e3208f15b0c9cf45ab52000468d7a2" + resolved "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz" integrity sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA== dependencies: debug "3.1.0" @@ -5567,7 +5571,7 @@ moment@^2.29.4: morgan@^1.10.0: version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== dependencies: basic-auth "~2.0.1" @@ -5609,7 +5613,7 @@ mute-stream@0.0.8: resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@^3.1.23, nanoid@^3.3.6, nanoid@^3.3.7: +nanoid@^3.1.23, nanoid@^3.3.6: version "3.3.7" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== @@ -5648,6 +5652,19 @@ ngx-spinner@^16.0.2: dependencies: tslib "^2.3.0" +nice-napi@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz" + integrity sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA== + dependencies: + node-addon-api "^3.0.0" + node-gyp-build "^4.2.2" + +node-addon-api@^3.0.0: + version "3.2.1" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + node-fetch@^2.6.7: version "2.7.0" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" @@ -5660,6 +5677,11 @@ node-forge@^1: resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== +node-gyp-build@^4.2.2: + version "4.8.1" + resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz" + integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== + node-gyp@^9.0.0: version "9.4.1" resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz" @@ -6056,18 +6078,18 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - path-to-regexp@^1.0.3: version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== dependencies: isarray "0.0.1" +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -6085,7 +6107,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1, picomatch@2.3.1: pify@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pify@^4.0.1: @@ -6113,14 +6135,14 @@ pkg-dir@^7.0.0: please-upgrade-node@^3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz" integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== dependencies: semver-compare "^1.0.0" pluralize@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + resolved "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== postcss-loader@7.3.3: @@ -6589,16 +6611,9 @@ selfsigned@^2.1.1: semver-compare@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz" integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== -semver@7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - semver@^5.6.0: version "5.7.2" resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" @@ -6672,7 +6687,7 @@ serve-static@1.15.0: server-destroy@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" + resolved "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz" integrity sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ== set-blocking@^2.0.0: @@ -6952,9 +6967,14 @@ ssri@^9.0.0: resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + steno@^0.4.1: version "0.4.4" - resolved "https://registry.yarnpkg.com/steno/-/steno-0.4.4.tgz#071105bdfc286e6615c0403c27e9d7b5dcb855cb" + resolved "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz" integrity sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w== dependencies: graceful-fs "^4.1.3" @@ -6968,7 +6988,30 @@ streamroller@^3.1.5: debug "^4.3.4" fs-extra "^8.1.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6986,21 +7029,14 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - safe-buffer "~5.1.0" + ansi-regex "^5.0.1" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7620,7 +7656,16 @@ word-wrap@^1.2.3: resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -7693,19 +7738,6 @@ yargs-parser@^21.1.1: resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@17.7.2, yargs@^17.0.1, yargs@^17.2.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yargs@^16.1.1: version "16.2.0" resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" @@ -7719,7 +7751,7 @@ yargs@^16.1.1: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.2.1, yargs@17.7.2: +yargs@^17.0.1, yargs@^17.2.1, yargs@17.7.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 62dae9a817f1cf0c2cbf823856b44b6bd2f536ff Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Tue, 10 Sep 2024 16:09:03 +0200 Subject: [PATCH 3/6] removing comments --- web/src/app/allocations-drawer/allocations-drawer.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.ts b/web/src/app/allocations-drawer/allocations-drawer.component.ts index 4660119f..b247be35 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.component.ts @@ -39,12 +39,10 @@ export class AllocationsDrawerComponent implements OnInit { filteredDataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); - // Variabili per il filtro selectedState: string = ''; selectedNode: string = ''; selectedInstance: string = ''; - // Stati, nodi, e istanze per il dropdown states = ['Running', 'Unknown', 'Failed', 'Succeeded']; nodes = ['lima-rancher-desktop', 'Custom name 1', 'Custom name 2', 'Custom name 3']; instances = ['default/sleep-dp-7b89667644-ff75z', 'default/sleep-dp-7b89667644-ff75m']; From 7a95785caa9472b8c70f0d75b9f6903cd660ab65 Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Thu, 12 Sep 2024 15:52:10 +0200 Subject: [PATCH 4/6] filters --- .../allocations-drawer.component.html | 18 +++---- .../allocations-drawer.component.scss | 14 +++++ .../allocations-drawer.component.ts | 52 +++++++++---------- web/src/app/app.module.ts | 5 +- web/webpack.config.js | 3 ++ 5 files changed, 54 insertions(+), 38 deletions(-) diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.html b/web/src/app/allocations-drawer/allocations-drawer.component.html index 6c42ca8c..734cf3a0 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.html +++ b/web/src/app/allocations-drawer/allocations-drawer.component.html @@ -9,24 +9,24 @@
- + + + Show all instances + {{ instance }} + + + + {{ state }} - + {{ node }} - - - - Show all instances - {{ instance }} - -
diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.scss b/web/src/app/allocations-drawer/allocations-drawer.component.scss index 55b7adfd..1aec4633 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.scss +++ b/web/src/app/allocations-drawer/allocations-drawer.component.scss @@ -1,4 +1,5 @@ @import 'https://fonts.googleapis.com/icon?family=Material+Icons'; +@import "@angular/material/prebuilt-themes/deeppurple-amber.css"; .mat-drawer-container { min-width: 430px; width: 55%; @@ -150,4 +151,17 @@ .label-column { font-weight: bold; } + + .filters { + display: flex; + align-items: center; + } + + .first-field { + margin-right: auto; + } + + .right-align { + margin-left: 16px; + } } \ No newline at end of file diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.ts b/web/src/app/allocations-drawer/allocations-drawer.component.ts index b247be35..35e594cd 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.ts +++ b/web/src/app/allocations-drawer/allocations-drawer.component.ts @@ -1,4 +1,5 @@ import { Component, EventEmitter, Injectable, Input, OnInit, Output, ViewChild } from "@angular/core"; +import { FormControl } from "@angular/forms"; import { MatPaginator } from "@angular/material/paginator"; import { MatDrawer } from "@angular/material/sidenav"; import { MatSort } from "@angular/material/sort"; @@ -27,6 +28,8 @@ export class AllocationsDrawerComponent implements OnInit { @Output() removeRowSelection = new EventEmitter(); + + disableSelect = new FormControl(false); selectedAllocation: any; showDetails: boolean = false; allocColumnDef: ColumnDef[] = []; @@ -35,9 +38,9 @@ export class AllocationsDrawerComponent implements OnInit { displayedColumns: string[] = ['key', 'value']; - dataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); + dataSource = new MatTableDataSource<{ key: string, value: string|undefined }>([]); - filteredDataSource = new MatTableDataSource<{ key: string, value: string, link?: string }>([]); + filteredDataSource = new MatTableDataSource([]); selectedState: string = ''; selectedNode: string = ''; @@ -45,12 +48,14 @@ export class AllocationsDrawerComponent implements OnInit { states = ['Running', 'Unknown', 'Failed', 'Succeeded']; nodes = ['lima-rancher-desktop', 'Custom name 1', 'Custom name 2', 'Custom name 3']; - instances = ['default/sleep-dp-7b89667644-ff75z', 'default/sleep-dp-7b89667644-ff75m']; + instances: string[] = []; ngOnChanges(): void { if (this.allocDataSource) { + this.updateInstances(); this.allocDataSource.paginator = this.allocPaginator; this.allocDataSource.sort = this.allocSort; + this.applyFilter(); } } constructor(private envConfig: EnvConfigService) {} @@ -64,12 +69,10 @@ export class AllocationsDrawerComponent implements OnInit { ]; this.allocColumnIds = this.allocColumnDef.map((col) => col.colId); this.externalLogsBaseUrl = this.envConfig.getExternalLogsBaseUrl(); - this.filteredDataSource.data = this.dataSource.data; } applyFilter(): void { - - this.filteredDataSource.data = this.dataSource.data.filter(item => { + this.filteredDataSource.data = this.allocDataSource.data.filter(item => { /* const matchesState = this.selectedState ? item.state === this.selectedState : true; const matchesNode = this.selectedNode ? item.node === this.selectedNode : true; @@ -77,13 +80,18 @@ export class AllocationsDrawerComponent implements OnInit { return matchesState && matchesNode && matchesInstance; */ - return true; + const matchesInstance = this.selectedInstance ? item.displayName === this.selectedInstance : true; + return matchesInstance; }); } + updateInstances(): void { + if (this.allocDataSource && this.allocDataSource.data) { + this.instances = [...new Set(this.allocDataSource.data.map(item => item.displayName))]; + } + } formatResources(colValue: string): string[] { - console.log(colValue); const arr: string[] = colValue.split("
"); // Check if there are "cpu" or "Memory" elements in the array const hasCpu = arr.some((item) => item.toLowerCase().includes("cpu")); @@ -110,30 +118,20 @@ export class AllocationsDrawerComponent implements OnInit { allocationsDetailToggle(row: any) { this.showDetails = true; this.selectedAllocation = row; - console.log("data", this.selectedRow); const newData = [ - { key: 'User', value: null }, - { key: 'Name', value: null }, - { key: 'Application Type', value: null }, - { key: 'Application Tags', value: null }, - { key: 'Application Priority', value: null }, + { key: 'User', value: undefined }, + { key: 'Name', value: undefined }, + { key: 'Application Type', value: "spark" }, + { key: 'Application Tags', value: undefined }, { key: 'YarnApplication State', value: this.selectedRow?.applicationState }, - { key: 'Queue', value: row.queueName }, - { key: 'FinalStatus Reported by AM', value: null }, - { key: 'Started', value: null }, - { key: 'Launched', value: null }, - { key: 'Finished', value: null }, - { key: 'Elapsed', value: null }, - { key: 'Tracking URL', value: 'History', link: undefined }, - { key: 'Log Aggregation Status', value: null }, - { key: 'Application Timeout (Remaining Time)', value: null }, - { key: 'Unmanaged Application', value: null }, - { key: 'Application Node Label Expression', value: null }, - { key: 'AM Container Node Label Expression', value: null } + { key: 'FinalStatus Reported by AM', value: undefined }, + { key: 'Started', value: undefined }, + { key: 'Launched', value: undefined }, + { key: 'Finished', value: undefined }, + { key: 'Elapsed', value: undefined }, ]; this.dataSource.data = newData; - console.log(this.selectedAllocation); if (this.selectedAllocationsRow !== -1) { if (this.selectedAllocationsRow !== row) { this.allocDataSource.data[this.selectedAllocationsRow].expanded = false; diff --git a/web/src/app/app.module.ts b/web/src/app/app.module.ts index 74da8f7a..80b54730 100644 --- a/web/src/app/app.module.ts +++ b/web/src/app/app.module.ts @@ -3,16 +3,17 @@ import { BrowserModule } from "@angular/platform-browser"; import { envConfigFactory, EnvConfigService } from "@app/services/envconfig/envconfig.service"; import { AllocationsDrawerModule } from "./allocations-drawer/allocations-drawer.module"; import { AppComponent } from "./app.component"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; @NgModule({ declarations: [AppComponent], - imports: [BrowserModule, AllocationsDrawerModule], + imports: [BrowserModule, AllocationsDrawerModule, BrowserAnimationsModule], providers: [ { useFactory: envConfigFactory, provide: EnvConfigService, deps: [EnvConfigService], - } + }, ], bootstrap: [AppComponent], }) diff --git a/web/webpack.config.js b/web/webpack.config.js index d6d33a44..f1db93f2 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -48,6 +48,9 @@ module.exports = { "@angular/material/table": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, "@angular/material/tooltip": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, "@angular/platform-browser": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, + "@angular/material/select": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, + "@angular/material/form-field": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, + "@angular/material/core": {singleton:true, strictVersion: true, requiredVersion: 'auto'}, ...sharedMappings.getDescriptors(), }) From 09714b68adcfc83347c4287f54aa2d066fff81e9 Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Thu, 12 Sep 2024 16:49:44 +0200 Subject: [PATCH 5/6] =?UTF-8?q?add=20padding=20to=20filters=C2=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/app/allocations-drawer/allocations-drawer.component.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/app/allocations-drawer/allocations-drawer.component.scss b/web/src/app/allocations-drawer/allocations-drawer.component.scss index 1aec4633..4c051a39 100644 --- a/web/src/app/allocations-drawer/allocations-drawer.component.scss +++ b/web/src/app/allocations-drawer/allocations-drawer.component.scss @@ -155,6 +155,7 @@ .filters { display: flex; align-items: center; + padding-top: 10px; } .first-field { From c8b905cf29f6ef937f4fb30ecd3c3015ebd0cc24 Mon Sep 17 00:00:00 2001 From: fabiovincenzi Date: Tue, 17 Sep 2024 16:19:32 +0200 Subject: [PATCH 6/6] removing log --- .../app/apps-view/apps-view.component.html | 146 ++++++ .../app/apps-view/apps-view.component.scss | 272 ++++++++++++ .../app/apps-view/apps-view.component.spec.ts | 143 ++++++ web/src/app/apps-view/apps-view.component.ts | 418 ++++++++++++++++++ web/src/app/apps-view/apps-view.module.ts | 10 + web/src/app/models/dropdown-item.model.ts | 28 ++ .../scheduler/scheduler-loader.service.ts | 28 ++ 7 files changed, 1045 insertions(+) create mode 100644 web/src/app/apps-view/apps-view.component.html create mode 100644 web/src/app/apps-view/apps-view.component.scss create mode 100644 web/src/app/apps-view/apps-view.component.spec.ts create mode 100644 web/src/app/apps-view/apps-view.component.ts create mode 100644 web/src/app/apps-view/apps-view.module.ts create mode 100644 web/src/app/models/dropdown-item.model.ts create mode 100644 web/src/app/services/scheduler/scheduler-loader.service.ts diff --git a/web/src/app/apps-view/apps-view.component.html b/web/src/app/apps-view/apps-view.component.html new file mode 100644 index 00000000..53cea73f --- /dev/null +++ b/web/src/app/apps-view/apps-view.component.html @@ -0,0 +1,146 @@ + + +
+
+ + +
+
+ + + + + +
+ +
+
+
+
+
+ + + {{ columnDef.colName + }} + + + {{ + element['formattedSubmissionTime'] }} + + + + {{ + element['formattedlastStateChangeTime'] }} + + + + + + + + + + + {{ resource }} + + + {{ resource }} + + + + + + + {{ element[columnDef.colId] }} + + + + + + + + + + + + + + + {{ element[columnDef.colId] || 'n/a' }} + + + + + + + + + + + + + + + +
No records found
+
+
+ + + + + + +
+ + +
+ + + + +
\ No newline at end of file diff --git a/web/src/app/apps-view/apps-view.component.scss b/web/src/app/apps-view/apps-view.component.scss new file mode 100644 index 00000000..5b1d5fdf --- /dev/null +++ b/web/src/app/apps-view/apps-view.component.scss @@ -0,0 +1,272 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + @import '~material-design-icons/iconfont/material-icons.css'; + + .top-section { + width: 100%; + height: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + .left-side{ + display: flex; + flex-direction: row; + align-items: center; + .dropdown-wrapper { + padding-right: 40px; + .dropdown-label { + color: #333; + font-size: 1.2em; + margin-right: 10px; + } + } + } + .right-side{ + display: flex; + flex-direction: row; + align-items: center; + .btn-wrapper { + filter: drop-shadow(0px 2px 1px rgba(90, 90, 90, 0.5)); + &:hover{ + filter: drop-shadow(0px 3px 3px rgba(90, 90, 90, 0.5)); + } + :hover{ + cursor: pointer; + } + .btn{ + display: block; + border: none; + padding: 13px 24px; + border-radius: 5px; + font-size: 24px; + transform: translateY(-13px); + } + .material-icons{ + transform: translateY(2px); + } + } + .search-wrapper { + width: 300px; + right: 20px; + padding-right: 20px; + input { + width: calc(100% - 22px); + color: #333; + } + .clear-btn { + outline: none; + border: none; + padding: 0 0 0 4px; + cursor: pointer; + background: transparent; + i { + font-size: 18px; + &:hover { + color: #f44336; + } + } + } + .search-icon { + margin-left: 4px; + font-size: 17px; + } + } + } +} + +.mdc-button .mdc-button__label{ + display: flex; + align-items: center; +} + +.apps-view { + width: 100%; + height: 100%; + + mat-chip { + height: 20px; + line-height: 14px; + font-size: 12px; + margin: 1px; + // border-radius: 5px; + // background-color: #313D54; + background-color: transparent; + + span { + font-size: 12px; + } + } + + .mat-mdc-standard-chip { + --mdc-chip-label-text-color: #333; + --mdc-chip-label-text-size: 12px; + --mdc-chip-label-text-weight: 400; + } + + .mat-mdc-header-cell { + font-size: 15px; + font-weight: bold; + color: #666; + } + .mat-mdc-cell { + color: #333; + display: flex; + flex-direction: column; + align-items: flex-start; + .mat-res-ul{ + padding: 0; + margin: 0; + .mat-res-li{ + list-style-type: none; + } + } + .mat-toggle-more { + display: block; + color: #a1a3b7; + padding: 5px 45px 0 0; + &:hover { + color: #8d00d4; + } + } + } + .even-row { + background: #eee; + } + .mat-mdc-row { + min-height: unset; + font-size: 12px; + &:hover { + background: #cccccc; + cursor: pointer; + } + &.selected-row { + background: #303d54; + .mat-mdc-cell { + color: #fff; + .mat-toggle-more { + color: #b8bbff; + &:hover { + color: #b871dc; + } + } + } + } + } + .mat-mdc-header-cell.indicator-icon, + .mat-mdc-cell.indicator-icon { + max-width: 40px; + font-size: 18px; + margin-left: 10px; + } + .app-allocations { + margin-top: 40px; + .mat-mdc-table { + margin-top: 20px; + } + } + .no-record { + font-size: 14px; + font-weight: bold; + color: #666; + width: 100%; + text-align: center; + } +} + + +.mat-drawer-container { + min-width: 430px; + width: 55%; + height: calc(100vh - 60px); + background: transparent; + pointer-events: none; + position: absolute; + right: 0; + bottom: 0; + .mat-drawer { + pointer-events: auto; + width: 100%; + .content { + padding: 0 10px; + } + } + .close-btn { + float: right; + font-size: 1.2em; + cursor: pointer; + padding-right: 5px; + &:hover { + color: #f44336; + } + } + .copy-btn { + font-size: 1em; + cursor: pointer; + padding-left: 5px; + } + .header { + margin: 20px; + font-weight: 100; + font-size: 1em; + } + .content { + border-top: 1px solid #e1e1e1; + } + .item-wrapper { + .left-item { + text-align: right; + } + .left-item, + .right-item { + width: 50%; + padding: 6px; + padding-right: 0; + color: #666; + } + .right-item { + font-weight: 600; + } + } + .app-link { + text-decoration: none; + color: #666; + &:hover { + text-decoration: underline; + } + } + + .row { + font-size: 0.9em; + } + + .even-row { + background: #eee; + } + + .ellipsis { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + } + + .row { + min-height: unset; + } +} \ No newline at end of file diff --git a/web/src/app/apps-view/apps-view.component.spec.ts b/web/src/app/apps-view/apps-view.component.spec.ts new file mode 100644 index 00000000..b9e667f8 --- /dev/null +++ b/web/src/app/apps-view/apps-view.component.spec.ts @@ -0,0 +1,143 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DebugElement } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatSortModule } from '@angular/material/sort'; +import { MatTableModule } from '@angular/material/table'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { By, HAMMER_LOADER } from '@angular/platform-browser'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppInfo } from '@app/models/app-info.model'; +import { EnvConfigService } from '@app/services/envconfig/envconfig.service'; +import { SchedulerService } from '@app/services/scheduler/scheduler.service'; +import { MatChipsModule } from '@angular/material/chips'; + +import { + MockEnvconfigService, + MockNgxSpinnerService, + MockSchedulerService, +} from '@app/testing/mocks'; +import { NgxSpinnerService } from 'ngx-spinner'; +import { of } from 'rxjs'; + +import { AppsViewComponent } from './apps-view.component'; + +describe('AppsViewComponent', () => { + let component: AppsViewComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [AppsViewComponent], + imports: [ + NoopAnimationsModule, + RouterTestingModule, + FormsModule, + MatTableModule, + MatPaginatorModule, + MatDividerModule, + MatSortModule, + MatInputModule, + MatTooltipModule, + MatSelectModule, + MatSidenavModule, + MatChipsModule, + ], + providers: [ + { provide: SchedulerService, useValue: MockSchedulerService }, + { provide: NgxSpinnerService, useValue: MockNgxSpinnerService }, + { provide: HAMMER_LOADER, useValue: () => new Promise(() => {}) }, + { provide: EnvConfigService, useValue: MockEnvconfigService }, + ], + }).compileComponents(); + fixture = TestBed.createComponent(AppsViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should have usedResource and pendingResource column with detailToggle OFF', () => { + let service: SchedulerService; + service = TestBed.inject(SchedulerService); + let appInfo = new AppInfo( + 'app1', + 'Memory: 500.0 KB, CPU: 10, pods: 1', + 'Memory: 0.0 bytes, CPU: 0, pods: n/a', + '', + 1, + 2, + [], + 2, + 'RUNNING', + [] + ); + spyOn(service, 'fetchAppList').and.returnValue(of([appInfo])); + component.fetchAppListForPartitionAndQueue('default', 'root'); + fixture.detectChanges(); + const debugEl: DebugElement = fixture.debugElement; + expect( + debugEl.query(By.css('[data-test="Memory: 500.0 KB,CPU: 10,pods: 1"]')).nativeElement + .innerText + ).toContain('Memory: 500.0 KB\nCPU: 10'); + expect( + debugEl.query(By.css('[data-test="Memory: 0.0 bytes,CPU: 0,pods: n/a"]')).nativeElement + .innerText + ).toContain('Memory: 0.0 bytes\nCPU: 0'); + }); + + it('should have usedResource and pendingResource column with detailToggle ON', () => { + let service: SchedulerService; + service = TestBed.inject(SchedulerService); + let appInfo = new AppInfo( + 'app1', + 'Memory: 500.0 KB, CPU: 10, pods: 1', + 'Memory: 0.0 bytes, CPU: 0, pods: n/a', + '', + 1, + 2, + [], + 2, + 'RUNNING', + [] + ); + spyOn(service, 'fetchAppList').and.returnValue(of([appInfo])); + component.fetchAppListForPartitionAndQueue('default', 'root'); + component.detailToggle = true; + fixture.detectChanges(); + const debugEl: DebugElement = fixture.debugElement; + expect( + debugEl.query(By.css('[data-test="Memory: 500.0 KB,CPU: 10,pods: 1"]')).nativeElement + .innerText + ).toContain('Memory: 500.0 KB\nCPU: 10\npods: 1'); + expect( + debugEl.query(By.css('[data-test="Memory: 0.0 bytes,CPU: 0,pods: n/a"]')).nativeElement + .innerText + ).toContain('Memory: 0.0 bytes\nCPU: 0\npods: n/a'); + }); +}); diff --git a/web/src/app/apps-view/apps-view.component.ts b/web/src/app/apps-view/apps-view.component.ts new file mode 100644 index 00000000..f70ed9ae --- /dev/null +++ b/web/src/app/apps-view/apps-view.component.ts @@ -0,0 +1,418 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Component, + ComponentRef, + ElementRef, + OnInit, + ViewChild, + ViewContainerRef, + } from '@angular/core'; + import { MatPaginator } from '@angular/material/paginator'; + import { MatSelect, MatSelectChange } from '@angular/material/select'; + import { MatSort } from '@angular/material/sort'; + import { MatTableDataSource } from '@angular/material/table'; + import { ActivatedRoute, Router } from '@angular/router'; + import { AllocationsDrawerComponent } from '@app/allocations-drawer/allocations-drawer.component'; + import { AllocationInfo } from '@app/models/alloc-info.model'; + import { AppInfo } from '@app/models/app-info.model'; + import { ColumnDef } from '@app/models/column-def.model'; + import { DropdownItem } from '@app/models/dropdown-item.model'; + import { PartitionInfo } from '@app/models/partition-info.model'; + import { QueueInfo } from '@app/models/queue-info.model'; + import { EnvConfigService } from '@app/services/envconfig/envconfig.service'; + import { SchedulerService } from '@app/services/scheduler/scheduler.service'; + import { CommonUtil } from '@app/utils/common.util'; + import { NgxSpinnerService } from 'ngx-spinner'; + import { fromEvent } from 'rxjs'; + import { debounceTime, distinctUntilChanged, finalize } from 'rxjs/operators'; + import { + loadRemoteModule, + LoadRemoteModuleEsmOptions, + } from '@angular-architects/module-federation'; + import { SchedulerServiceLoader } from '@app/services/scheduler/scheduler-loader.service'; + + @Component({ + selector: 'app-applications-view', + templateUrl: './apps-view.component.html', + styleUrls: ['./apps-view.component.scss'], + }) + export class AppsViewComponent implements OnInit { + @ViewChild('appsViewMatPaginator', { static: true }) appPaginator!: MatPaginator; + @ViewChild('allocationMatPaginator', { static: true }) allocPaginator!: MatPaginator; + @ViewChild('appSort', { static: true }) appSort!: MatSort; + @ViewChild('allocSort', { static: true }) allocSort!: MatSort; + @ViewChild('searchInput', { static: true }) searchInput!: ElementRef; + @ViewChild('queueSelect', { static: false }) queueSelect!: MatSelect; + + @ViewChild('drawerContainer', { read: ViewContainerRef, static: true }) + drawerContainer!: ViewContainerRef; + + @ViewChild('mfeContainer', { read: ViewContainerRef, static: true }) + mfeContainer!: ViewContainerRef; + + appDataSource = new MatTableDataSource([]); + appColumnDef: ColumnDef[] = []; + appColumnIds: string[] = []; + + allocDataSource = new MatTableDataSource([]); + allocColumnDef: ColumnDef[] = []; + allocColumnIds: string[] = []; + + selectedRow: AppInfo | null = null; + initialAppData: AppInfo[] = []; + searchText = ''; + partitionList: PartitionInfo[] = []; + partitionSelected = ''; + leafQueueList: DropdownItem[] = []; + leafQueueSelected = ''; + + detailToggle: boolean = false; + allocationsDrawerComponent: ComponentRef | undefined = undefined; + + constructor( + private scheduler: SchedulerService, + private spinner: NgxSpinnerService, + private activatedRoute: ActivatedRoute, + private router: Router, + private envConfig: EnvConfigService + ) {} + + ngOnInit() { + this.appDataSource.paginator = this.appPaginator; + this.allocDataSource.paginator = this.allocPaginator; + this.appDataSource.sort = this.appSort; + this.allocDataSource.sort = this.allocSort; + this.appSort.sort({ id: 'submissionTime', start: 'desc', disableClear: false }); + + this.appColumnDef = [ + { colId: 'applicationId', colName: 'Application ID', colWidth: 1 }, + { colId: 'applicationState', colName: 'Application State', colWidth: 1 }, + { + colId: 'lastStateChangeTime', + colName: 'Last State Change Time', + colFormatter: CommonUtil.timeColumnFormatter, + colWidth: 1, + }, + { + colId: 'usedResource', + colName: 'Used Resource', + colFormatter: CommonUtil.resourceColumnFormatter, + colWidth: 2, + }, + { + colId: 'pendingResource', + colName: 'Pending Resource', + colFormatter: CommonUtil.resourceColumnFormatter, + colWidth: 2, + }, + { + colId: 'submissionTime', + colName: 'Submission Time', + colFormatter: CommonUtil.timeColumnFormatter, + colWidth: 1, + }, + ]; + + this.appColumnIds = this.appColumnDef.map((col) => col.colId); + + this.allocColumnDef = [ + { colId: 'displayName', colName: 'Display Name', colWidth: 1 }, + { colId: 'allocationKey', colName: 'Allocation Key', colWidth: 1 }, + { colId: 'nodeId', colName: 'Node ID', colWidth: 1 }, + { + colId: 'resource', + colName: 'Resource', + colFormatter: CommonUtil.resourceColumnFormatter, + colWidth: 1, + }, + { colId: 'priority', colName: 'Priority', colWidth: 0.5 }, + ]; + + this.allocColumnIds = this.allocColumnDef.map((col) => col.colId); + + fromEvent(this.searchInput.nativeElement, 'keyup') + .pipe(debounceTime(500), distinctUntilChanged()) + .subscribe(() => { + this.onSearchAppData(); + }); + + this.scheduler + .fetchPartitionList() + .pipe( + finalize(() => { + this.spinner.hide(); + }) + ) + .subscribe((list) => { + if (list && list.length > 0) { + list.forEach((part) => { + this.partitionList.push(new PartitionInfo(part.name, part.name)); + }); + this.partitionSelected = CommonUtil.getStoredPartition(list[0].name); + this.fetchQueuesForPartition(this.partitionSelected); + } else { + this.partitionList = [new PartitionInfo('-- Select --', '')]; + this.partitionSelected = ''; + this.leafQueueList = [new DropdownItem('-- Select --', '')]; + this.leafQueueSelected = ''; + this.appDataSource.data = []; + this.clearQueueSelection(); + } + }); + + } + + fetchQueuesForPartition(partitionName: string) { + this.spinner.show(); + + this.scheduler + .fetchSchedulerQueues(partitionName) + .pipe( + finalize(() => { + this.spinner.hide(); + }) + ) + .subscribe((data) => { + if (data && data.rootQueue) { + const leafQueueList = this.generateLeafQueueList(data.rootQueue); + this.leafQueueList = [new DropdownItem('-- Select --', ''), ...leafQueueList]; + if (!this.fetchApplicationsUsingQueryParams()) this.setDefaultQueue(leafQueueList); + } else { + this.leafQueueList = [new DropdownItem('-- Select --', '')]; + } + }); + } + + setDefaultQueue(queueList: DropdownItem[]): void { + const storedPartitionAndQueue = localStorage.getItem('selectedPartitionAndQueue'); + + if (!storedPartitionAndQueue || storedPartitionAndQueue.indexOf(':') < 0) { + setTimeout(() => this.openQueueSelection(), 0); + return; + } + + const [storedPartition, storedQueue] = storedPartitionAndQueue.split(':'); + if (this.partitionSelected !== storedPartition) return; + + const storedQueueDropdownItem = queueList.find((queue) => queue.value === storedQueue); + if (storedQueueDropdownItem) { + this.leafQueueSelected = storedQueueDropdownItem.value; + this.fetchAppListForPartitionAndQueue(this.partitionSelected, this.leafQueueSelected); + return; + } else { + this.leafQueueSelected = ''; + this.appDataSource.data = []; + setTimeout(() => this.openQueueSelection(), 0); // Allows render to finish and then opens the queue select dropdown + } + } + + generateLeafQueueList(rootQueue: QueueInfo, list: DropdownItem[] = []): DropdownItem[] { + if (rootQueue && rootQueue.isLeaf) { + list.push(new DropdownItem(rootQueue.queueName, rootQueue.queueName)); + } + + if (rootQueue && rootQueue.children) { + rootQueue.children.forEach((child) => this.generateLeafQueueList(child, list)); + } + + return list; + } + + fetchAppListForPartitionAndQueue( + partitionName: string, + queueName: string, + applicationId?: string + ) { + this.spinner.show(); + + this.scheduler + .fetchAppList(partitionName, queueName) + .pipe( + finalize(() => { + this.spinner.hide(); + }) + ) + .subscribe((data) => { + this.initialAppData = data; + this.appDataSource.data = data; + + const row = this.initialAppData.find((app) => app.applicationId === applicationId); + if (row) { + this.toggleRowSelection(row); + } + }); + } + + fetchApplicationsUsingQueryParams(): boolean { + const partitionName = this.activatedRoute.snapshot.queryParams['partition']; + const queueName = this.activatedRoute.snapshot.queryParams['queue']; + const applicationId = this.activatedRoute.snapshot.queryParams['applicationId']; + + if (partitionName && queueName) { + this.partitionSelected = partitionName; + this.leafQueueSelected = queueName; + this.fetchAppListForPartitionAndQueue(partitionName, queueName, applicationId); + CommonUtil.setStoredQueueAndPartition(partitionName, queueName); + + this.router.navigate([], { + queryParams: { + partition: null, + queue: null, + applicationId: null, + }, + queryParamsHandling: 'merge', + }); + + return true; + } + return false; + } + + unselectAllRowsButOne(row: AppInfo) { + this.appDataSource.data.map((app) => { + if (app !== row) { + app.isSelected = false; + } + }); + } + + toggleRowSelection(row: AppInfo) { + this.unselectAllRowsButOne(row); + if (row.isSelected) { + this.removeRowSelection(); + } else { + this.selectedRow = row; + row.isSelected = true; + if (row.allocations) { + this.allocDataSource.data = row.allocations; + } + this.allocationsDrawerComponent?.setInput('selectedRow', this.selectedRow); + this.allocationsDrawerComponent?.setInput('allocDataSource', this.allocDataSource); + this.allocationsDrawerComponent?.instance.openDrawer(); + } + } + + removeRowSelection() { + if (this.selectedRow) { + this.selectedRow.isSelected = false; + this.selectedRow = null; + this.allocDataSource.data = []; + } + } + + onPaginatorChanged() { + this.removeRowSelection(); + } + + isAppDataSourceEmpty() { + return this.appDataSource.data && this.appDataSource.data.length === 0; + } + + onClearSearch() { + this.searchText = ''; + this.removeRowSelection(); + this.appDataSource.data = this.initialAppData; + } + + onSearchAppData() { + const searchTerm = this.searchText.trim().toLowerCase(); + + if (searchTerm) { + this.removeRowSelection(); + this.appDataSource.data = this.initialAppData.filter((data) => + data.applicationId.toLowerCase().includes(searchTerm) + ); + } else { + this.onClearSearch(); + } + } + + onPartitionSelectionChanged(selected: MatSelectChange) { + if (selected.value !== '') { + this.searchText = ''; + this.partitionSelected = selected.value; + this.appDataSource.data = []; + this.removeRowSelection(); + this.clearQueueSelection(); + this.fetchQueuesForPartition(this.partitionSelected); + } else { + this.searchText = ''; + this.partitionSelected = ''; + this.leafQueueSelected = ''; + this.appDataSource.data = []; + this.removeRowSelection(); + this.clearQueueSelection(); + } + } + + onQueueSelectionChanged(selected: MatSelectChange) { + if (selected.value !== '') { + this.searchText = ''; + this.leafQueueSelected = selected.value; + this.appDataSource.data = []; + this.removeRowSelection(); + this.fetchAppListForPartitionAndQueue(this.partitionSelected, this.leafQueueSelected); + CommonUtil.setStoredQueueAndPartition(this.partitionSelected, this.leafQueueSelected); + } else { + this.searchText = ''; + this.leafQueueSelected = ''; + this.appDataSource.data = []; + this.removeRowSelection(); + this.clearQueueSelection(); + } + } + + formatResources(colValue: string): string[] { + const arr: string[] = colValue.split('
'); + // Check if there are "cpu" or "Memory" elements in the array + const hasCpu = arr.some((item) => item.toLowerCase().includes('cpu')); + const hasMemory = arr.some((item) => item.toLowerCase().includes('memory')); + if (!hasCpu) { + arr.unshift('CPU: n/a'); + } + if (!hasMemory) { + arr.unshift('Memory: n/a'); + } + + // Concatenate the two arrays, with "cpu" and "Memory" elements first + const cpuAndMemoryElements = arr.filter( + (item) => item.toLowerCase().includes('CPU') || item.toLowerCase().includes('Memory') + ); + const otherElements = arr.filter( + (item) => !item.toLowerCase().includes('CPU') && !item.toLowerCase().includes('Memory') + ); + return cpuAndMemoryElements.concat(otherElements); + } + + clearQueueSelection() { + CommonUtil.setStoredQueueAndPartition(''); + this.leafQueueSelected = ''; + this.openQueueSelection(); + } + + openQueueSelection() { + this.queueSelect.open(); + } + + toggle() { + this.detailToggle = !this.detailToggle; + } + } + \ No newline at end of file diff --git a/web/src/app/apps-view/apps-view.module.ts b/web/src/app/apps-view/apps-view.module.ts new file mode 100644 index 00000000..2d7cf361 --- /dev/null +++ b/web/src/app/apps-view/apps-view.module.ts @@ -0,0 +1,10 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { AppsViewComponent } from "./apps-view.component"; + +@NgModule({ + declarations: [AppsViewComponent], + imports: [CommonModule], + exports: [AppsViewComponent], +}) +export class AppsViewModule {} diff --git a/web/src/app/models/dropdown-item.model.ts b/web/src/app/models/dropdown-item.model.ts new file mode 100644 index 00000000..83300504 --- /dev/null +++ b/web/src/app/models/dropdown-item.model.ts @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class DropdownItem { + name: string; + value: string; + + constructor(name: string, value: string) { + this.name = name; + this.value = value; + } + } + \ No newline at end of file diff --git a/web/src/app/services/scheduler/scheduler-loader.service.ts b/web/src/app/services/scheduler/scheduler-loader.service.ts new file mode 100644 index 00000000..0e078dbc --- /dev/null +++ b/web/src/app/services/scheduler/scheduler-loader.service.ts @@ -0,0 +1,28 @@ +import { Injectable, Injector } from '@angular/core'; +import { loadRemoteModule, LoadRemoteModuleEsmOptions } from '@angular-architects/module-federation'; +import { SchedulerService } from './scheduler.service'; + +@Injectable({ + providedIn: 'root', +}) +export class SchedulerServiceLoader { + constructor(private injector: Injector) {} + + async initializeSchedulerService(remoteComponentConfig: LoadRemoteModuleEsmOptions | null): Promise { + if (remoteComponentConfig !== null) { + try { + const remoteModule = await loadRemoteModule(remoteComponentConfig); + if (remoteModule && remoteModule.SchedulerService) { + return this.injector.get(remoteModule.SchedulerService); + } else { + console.error('SchedulerService not found.'); + return null; + } + } catch (error) { + console.error('Error loading the remote module:', error); + return null; + } + } + return null; + } +} \ No newline at end of file