This is an automated email from the ASF dual-hosted git repository.

ccondit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/yunikorn-web.git


The following commit(s) were added to refs/heads/master by this push:
     new f510bd2  [YUNIKORN-1914] Change display for resource lists (#130)
f510bd2 is described below

commit f510bd24341980b3125215559e80f78ff4585b9b
Author: wusamzong <[email protected]>
AuthorDate: Tue Sep 26 11:48:08 2023 -0500

    [YUNIKORN-1914] Change display for resource lists (#130)
    
    Closes: #130
    
    Signed-off-by: Craig Condit <[email protected]>
---
 json-db.json                                       |  23 ++--
 .../components/apps-view/apps-view.component.html  | 115 ++++++++++++-------
 .../components/apps-view/apps-view.component.scss  | 123 ++++++++++++++++-----
 .../components/apps-view/apps-view.component.ts    |  26 +++++
 .../nodes-view/nodes-view.component.html           |  57 +++++++---
 .../nodes-view/nodes-view.component.scss           |  62 ++++++++++-
 .../components/nodes-view/nodes-view.component.ts  |  29 ++++-
 7 files changed, 337 insertions(+), 98 deletions(-)

diff --git a/json-db.json b/json-db.json
index f713dd4..8f3ed37 100644
--- a/json-db.json
+++ b/json-db.json
@@ -263,7 +263,8 @@
       "usedResource": {
         "memory": 50000000,
         "pods": 1,
-        "vcore": 10
+        "vcore": 10,
+        "nvidia.com/gpu": 5
       },
       "maxUsedResource": {
         "memory": 50000000,
@@ -297,7 +298,8 @@
           "resource": {
             "memory": 50000000,
             "pods": 1,
-            "vcore": 10
+            "vcore": 10,
+            "nvidia.com/gpu": 5
           },
           "priority": "0",
           "nodeId": "lima-rancher-desktop",
@@ -545,17 +547,22 @@
         "hugepages-64Ki": 0,
         "memory": 4110970880,
         "pods": 110,
-        "vcore": 2000
+        "vcore": 2000,
+        "nvidia.com/gpu": 10,
+        "amd.com/gpu": 10,
+        "gpu.intel.com/i915": 10
       },
       "allocated": {
         "memory": 200000000,
         "pods": 4,
-        "vcore": 40
+        "vcore": 40,
+        "nvidia.com/gpu": 5
       },
       "occupied": {
         "memory": 1325400064,
         "pods": 4,
-        "vcore": 500
+        "vcore": 500,
+        "nvidia.com/gpu": 5
       },
       "available": {
         "ephemeral-storage": 99833802265,
@@ -565,7 +572,8 @@
         "hugepages-64Ki": 0,
         "memory": 2585570816,
         "pods": 102,
-        "vcore": 1460
+        "vcore": 1460,
+        "nvidia.com/gpu": 5
       },
       "utilized": {
         "memory": 4,
@@ -645,7 +653,8 @@
           "resource": {
             "memory": 50000000,
             "pods": 1,
-            "vcore": 10
+            "vcore": 10,
+            "nvidia.com/gpu": 5
           },
           "priority": "0",
           "nodeId": "lima-rancher-desktop",
diff --git a/src/app/components/apps-view/apps-view.component.html 
b/src/app/components/apps-view/apps-view.component.html
index 631634e..6635cd9 100644
--- a/src/app/components/apps-view/apps-view.component.html
+++ b/src/app/components/apps-view/apps-view.component.html
@@ -17,48 +17,57 @@
  -->
 
 <div class="top-section">
-  <div class="dropdown-wrapper">
-    <label class="dropdown-label">Partition: </label>
-    <mat-form-field>
-      <mat-select
-        [(value)]="partitionSelected"
-        (selectionChange)="onPartitionSelectionChanged($event)"
-      >
-        <mat-option *ngFor="let part of partitionList" [value]="part.value">
-          {{ part.name }}
-        </mat-option>
-      </mat-select>
-    </mat-form-field>
+  <div class="left-side">
+    <div class="dropdown-wrapper">
+      <label class="dropdown-label">Partition: </label>
+      <mat-form-field>
+        <mat-select
+          [(value)]="partitionSelected"
+          (selectionChange)="onPartitionSelectionChanged($event)"
+        >
+          <mat-option *ngFor="let part of partitionList" [value]="part.value">
+            {{ part.name }}
+          </mat-option>
+        </mat-select>
+      </mat-form-field>
+    </div>
+    <div class="dropdown-wrapper">
+      <label class="dropdown-label">Queue: </label>
+      <mat-form-field>
+        <mat-select [(value)]="leafQueueSelected" 
(selectionChange)="onQueueSelectionChanged($event)">
+          <mat-option *ngFor="let queue of leafQueueList" 
[value]="queue.value">
+            {{ queue.name }}
+          </mat-option>
+        </mat-select>
+      </mat-form-field>
+    </div>
   </div>
-  <div class="dropdown-wrapper">
-    <label class="dropdown-label">Queue: </label>
-    <mat-form-field>
-      <mat-select [(value)]="leafQueueSelected" 
(selectionChange)="onQueueSelectionChanged($event)">
-        <mat-option *ngFor="let queue of leafQueueList" [value]="queue.value">
-          {{ queue.name }}
-        </mat-option>
-      </mat-select>
+  <div class="right-side">
+    <mat-form-field class="search-wrapper white-mat-form-field">
+      <input
+        matInput
+        type="text"
+        [(ngModel)]="searchText"
+        placeholder="Search By Application ID"
+        #searchInput
+      />
+      <button
+        class="clear-btn"
+        *ngIf="searchText"
+        (click)="onClearSearch()"
+        matTooltip="Clear Search"
+        matTooltipShowDelay="500"
+      >
+        <i class="far fa-times-circle"></i>
+      </button>
+      <i *ngIf="!searchText" class="fas fa-search search-icon"></i>
     </mat-form-field>
+    <div class="btn-wrapper">
+      <button class="btn" (click)="toggle()" 
[style.background-color]="detailToggle ? '#313d54' : '#f5f5f5'">
+        <i class="material-icons __icon" [style.color]="detailToggle ? 
'#f5f5f5' : '#313d54' ">more_horiz</i>
+      </button>
+    </div>
   </div>
-  <mat-form-field class="search-wrapper white-mat-form-field">
-    <input
-      matInput
-      type="text"
-      [(ngModel)]="searchText"
-      placeholder="Search By Application ID"
-      #searchInput
-    />
-    <button
-      class="clear-btn"
-      *ngIf="searchText"
-      (click)="onClearSearch()"
-      matTooltip="Clear Search"
-      matTooltipShowDelay="500"
-    >
-      <i class="far fa-times-circle"></i>
-    </button>
-    <i *ngIf="!searchText" class="fas fa-search search-icon"></i>
-  </mat-form-field>
 </div>
 <div class="apps-view">
   <div class="mat-elevation-z8">
@@ -78,7 +87,18 @@
           <ng-container *ngIf="columnDef.colId === 'usedResource'; else 
renderNext_1">
             <mat-cell *matCellDef="let element">
               <ng-container *ngIf="columnDef.colFormatter; else 
showAppRawData">
-                <span 
[innerHTML]="columnDef.colFormatter(element[columnDef.colId])"></span>
+                <ng-container 
*ngIf="columnDef.colFormatter(element[columnDef.colId]) as colValue">
+                  <ul class="mat-res-ul">
+                    <ng-container *ngFor="let resource of 
formatResources(colValue); let i = index">
+                      <li class="mat-res-li" *ngIf="i<2">
+                        {{resource}}
+                      </li>
+                      <li class="mat-res-li" *ngIf="i>=2 && detailToggle">
+                        {{resource}}
+                      </li>
+                    </ng-container>
+                  </ul>
+                </ng-container>
               </ng-container>
               <ng-template #showAppRawData>
                 <span>{{ element[columnDef.colId] }}</span>
@@ -150,8 +170,19 @@
 
           <ng-container *ngIf="columnDef.colId === 'resource'; else 
renderNext_3">
             <mat-cell *matCellDef="let element">
-              <ng-container *ngIf="columnDef.colFormatter; else 
showAllocRowData">
-                <span 
[innerHTML]="columnDef.colFormatter(element[columnDef.colId])"></span>
+              <ng-container *ngIf="columnDef.colFormatter; else 
showAllocRowData;">
+                <ng-container 
*ngIf="columnDef.colFormatter(element[columnDef.colId]) as colValue">
+                    <ul class="mat-res-ul">
+                      <ng-container *ngFor="let resource of 
formatResources(colValue); let i = index">
+                        <li class="mat-res-li" *ngIf="i<2">
+                          {{resource}}
+                        </li>
+                        <li class="mat-res-li" *ngIf="i>=2 && detailToggle">
+                          {{resource}}
+                        </li>
+                      </ng-container>
+                    </ul>
+                </ng-container>
               </ng-container>
               <ng-template #showAllocRowData>
                 <span>{{ element[columnDef.colId] }}</span>
diff --git a/src/app/components/apps-view/apps-view.component.scss 
b/src/app/components/apps-view/apps-view.component.scss
index 040b978..c91e654 100644
--- a/src/app/components/apps-view/apps-view.component.scss
+++ b/src/app/components/apps-view/apps-view.component.scss
@@ -15,47 +15,86 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@import "https://fonts.googleapis.com/icon?family=Material+Icons";;
 
-.top-section {
+ .top-section {
   width: 100%;
   height: 100%;
   display: flex;
-  .search-wrapper {
-    width: 300px;
-    position: absolute;
-    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;
-        }
+  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;
       }
     }
-    .search-icon {
-      margin-left: 4px;
-      font-size: 17px;
-    }
   }
-  .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%;
@@ -66,6 +105,24 @@
   }
   .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;
+      }
+    }
   }
   .mat-mdc-row {
     &:hover {
@@ -76,6 +133,12 @@
       background: #303d54;
       .mat-mdc-cell {
         color: #fff;
+        .mat-toggle-more {
+          color: #b8bbff;
+          &:hover {
+            color: #b871dc;
+          }
+        }
       }
     }
   }
diff --git a/src/app/components/apps-view/apps-view.component.ts 
b/src/app/components/apps-view/apps-view.component.ts
index 7d691d1..fa94c35 100644
--- a/src/app/components/apps-view/apps-view.component.ts
+++ b/src/app/components/apps-view/apps-view.component.ts
@@ -61,6 +61,8 @@ export class AppsViewComponent implements OnInit {
   partitionSelected = '';
   leafQueueList: DropdownItem[] = [];
   leafQueueSelected = '';
+  
+  detailToggle: boolean = false;
 
   constructor(
     private scheduler: SchedulerService,
@@ -301,4 +303,28 @@ export class AppsViewComponent implements OnInit {
       this.removeRowSelection();
     }
   }
+
+  formatResources(colValue:string):string[]{
+    const arr:string[]=colValue.split("<br/>")
+    // 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"));
+    const result = cpuAndMemoryElements.concat(otherElements);
+
+    return result;
+  }
+
+  toggle(){
+    this.detailToggle = !this.detailToggle;
+  }
 }
diff --git a/src/app/components/nodes-view/nodes-view.component.html 
b/src/app/components/nodes-view/nodes-view.component.html
index 177d64f..076e283 100644
--- a/src/app/components/nodes-view/nodes-view.component.html
+++ b/src/app/components/nodes-view/nodes-view.component.html
@@ -17,17 +17,24 @@
  -->
 
 <div class="top-part">
-  <label class="part-label">Partition: </label>
-  <mat-form-field>
-    <mat-select
-      [(value)]="partitionSelected"
-      (selectionChange)="onPartitionSelectionChanged($event)"
-    >
-      <mat-option *ngFor="let part of partitionList" [value]="part.value">
-        {{ part.name }}
-      </mat-option>
-    </mat-select>
-  </mat-form-field>
+  <div class="dropdown-wrapper">
+    <label class="part-label">Partition: </label>
+    <mat-form-field>
+      <mat-select
+        [(value)]="partitionSelected"
+        (selectionChange)="onPartitionSelectionChanged($event)"
+      >
+        <mat-option *ngFor="let part of partitionList" [value]="part.value">
+          {{ part.name }}
+        </mat-option>
+      </mat-select>
+    </mat-form-field>
+  </div>
+  <div class="btn-wrapper">
+    <button class="btn" (click)="toggle()" 
[style.background-color]="detailToggle ? '#313d54' : '#f5f5f5'">
+      <i class="material-icons __icon" [style.color]="detailToggle ? '#f5f5f5' 
: '#313d54' ">more_horiz</i>
+    </button>
+  </div>
 </div>
 <div class="nodes-view">
   <div class="mat-elevation-z8">
@@ -43,7 +50,18 @@
         >
           <mat-cell *matCellDef="let element">
             <ng-container *ngIf="columnDef.colFormatter; else showNodeRawData">
-              <span 
[innerHTML]="columnDef.colFormatter(element[columnDef.colId])"></span>
+              <ng-container 
*ngIf="columnDef.colFormatter(element[columnDef.colId]) as colValue">
+                  <ul class="mat-res-ul">
+                    <ng-container *ngFor="let resource of 
formatResources(colValue); let i = index">
+                      <li class="mat-res-li" *ngIf="i<2">
+                        {{resource}}
+                      </li>
+                      <li class="mat-res-li" *ngIf="i>=2 && detailToggle">
+                        {{resource}}
+                      </li>
+                    </ng-container>
+                  </ul>
+              </ng-container>
             </ng-container>
             <ng-template #showNodeRawData>
               <span>{{ element[columnDef.colId] }}</span>
@@ -107,8 +125,19 @@
           <ng-container *ngIf="columnDef.colId === 'resource'; else 
renderNext_2">
             <mat-cell *matCellDef="let element">
               <ng-container *ngIf="columnDef.colFormatter; else 
showAllocRowData">
-                <span 
[innerHTML]="columnDef.colFormatter(element[columnDef.colId])"></span>
-              </ng-container>
+                <ng-container 
*ngIf="columnDef.colFormatter(element[columnDef.colId]) as colValue">
+                    <ul class="mat-res-ul">
+                      <ng-container *ngFor="let resource of 
formatResources(colValue); let i = index">
+                        <li class="mat-res-li" *ngIf="i<2">
+                          {{resource}}
+                        </li>
+                        <li class="mat-res-li" *ngIf="i>=2 && detailToggle">
+                          {{resource}}
+                        </li>
+                      </ng-container>
+                    </ul>
+                </ng-container>
+            </ng-container>
               <ng-template #showAllocRowData>
                 <span>{{ element[columnDef.colId] }}</span>
               </ng-template>
diff --git a/src/app/components/nodes-view/nodes-view.component.scss 
b/src/app/components/nodes-view/nodes-view.component.scss
index 67eea13..545d27b 100644
--- a/src/app/components/nodes-view/nodes-view.component.scss
+++ b/src/app/components/nodes-view/nodes-view.component.scss
@@ -15,12 +15,42 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@import "https://fonts.googleapis.com/icon?family=Material+Icons";;
 
-.part-label {
-  color: #333;
-  font-size: 1.2em;
-  margin-right: 10px;
+.top-part{
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  .dropdown-wrapper{
+    padding-right: 40px;
+    .part-label {
+      color: #333;
+      font-size: 1.2em;
+      margin-right: 10px;
+    }
+  }
+  .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);
+    }
+  }
 }
+
 .nodes-view {
   width: 100%;
   height: 100%;
@@ -31,6 +61,24 @@
   }
   .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;
+      }
+    }
   }
   .mat-mdc-row {
     &:hover {
@@ -41,6 +89,12 @@
       background: #303d54;
       .mat-mdc-cell {
         color: #fff;
+        .mat-toggle-more {
+          color: #b8bbff;
+          &:hover {
+            color: #b871dc;
+          }
+        }
       }
     }
   }
diff --git a/src/app/components/nodes-view/nodes-view.component.ts 
b/src/app/components/nodes-view/nodes-view.component.ts
index 6bdb19a..e7dffd8 100644
--- a/src/app/components/nodes-view/nodes-view.component.ts
+++ b/src/app/components/nodes-view/nodes-view.component.ts
@@ -22,7 +22,7 @@ import { MatSelectChange } from '@angular/material/select';
 import { MatSort } from '@angular/material/sort';
 import { MatTableDataSource } from '@angular/material/table';
 import { NgxSpinnerService } from 'ngx-spinner';
-import { finalize } from 'rxjs/operators';
+import { finalize, flatMap } from 'rxjs/operators';
 
 import { SchedulerService } from '@app/services/scheduler/scheduler.service';
 import { NodeInfo } from '@app/models/node-info.model';
@@ -53,6 +53,8 @@ export class NodesViewComponent implements OnInit {
   partitionList: PartitionInfo[] = [];
   partitionSelected = '';
 
+  detailToggle: boolean = false;
+
   constructor(private scheduler: SchedulerService, private spinner: 
NgxSpinnerService) {}
 
   ngOnInit() {
@@ -135,6 +137,7 @@ export class NodesViewComponent implements OnInit {
       )
       .subscribe((data) => {
         this.nodeDataSource.data = data;
+        console.log(data);
       });
   }
 
@@ -190,4 +193,28 @@ export class NodesViewComponent implements OnInit {
     this.clearRowSelection();
     this.fetchNodeListForPartition(this.partitionSelected);
   }
+
+  formatResources(colValue:string):string[]{
+    const arr:string[]=colValue.split("<br/>")
+    // 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"));
+    const result = cpuAndMemoryElements.concat(otherElements);
+
+    return result;
+  }
+
+  toggle(){
+    this.detailToggle = !this.detailToggle;
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to