Skip to content

Commit fdb507f

Browse files
committed
feat: Add icons to main tables + refactor
* Add icons to headers of the two tables under the main-table component * Refactor code for cleaner use of promises * Show user size of volumes in table * Show user what notebooks volumes are mounted to
1 parent 2095188 commit fdb507f

File tree

7 files changed

+72
-88
lines changed

7 files changed

+72
-88
lines changed

frontend/src/app/main-table/main-table.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ table {
2828
height: 64px;
2929
}
3030

31+
.header mat-icon {
32+
margin: 3px 10px 0 0;
33+
}
34+
3135
.header p {
3236
font-weight: 400;
3337
font-size: 20px;
Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { Component, OnInit } from "@angular/core";
2-
import { NamespaceService } from "../services/namespace.service";
3-
import { KubernetesService } from "src/app/services/kubernetes.service";
1+
import {Component, OnInit} from "@angular/core";
2+
import {NamespaceService} from "../services/namespace.service";
3+
import {KubernetesService} from "src/app/services/kubernetes.service";
44

5-
import { Subscription } from "rxjs";
6-
import { isEqual } from "lodash";
7-
import { first } from "rxjs/operators";
8-
9-
import { ExponentialBackoff } from "src/app/utils/polling";
10-
import { MatDialog } from "@angular/material/dialog";
11-
import { ConfirmDialogComponent } from "./confirm-dialog/confirm-dialog.component";
12-
import { Pvc, Volume, Resource } from "../utils/types";
5+
import {Subscription} from "rxjs";
6+
import {isEqual} from "lodash";
7+
import {first} from "rxjs/operators";
138

9+
import {ExponentialBackoff} from "src/app/utils/polling";
10+
import {MatDialog} from "@angular/material/dialog";
11+
import {ConfirmDialogComponent} from "./confirm-dialog/confirm-dialog.component";
12+
import {Pvc, Volume, Resource} from "../utils/types";
1413

1514
@Component({
1615
selector: "app-main-table",
@@ -35,47 +34,36 @@ export class MainTableComponent implements OnInit {
3534
) {}
3635

3736
ngOnInit() {
38-
this.poller = new ExponentialBackoff({ interval: 2000, retries: 3 });
37+
this.poller = new ExponentialBackoff({interval: 2000, retries: 3});
3938
const resourcesSub = this.poller.start().subscribe(() => {
4039
if (!this.currNamespace) {
4140
return;
42-
}
41+
}
4342

44-
let getVolumes = this.k8s.getVolumes(this.currNamespace).toPromise().then(
45-
pvcs => {
46-
if(isEqual(this.pvcs, pvcs)){
47-
return;
48-
}
49-
this.pvcs = pvcs;
50-
}
51-
);
52-
53-
let getResource = this.k8s.getResource(this.currNamespace).toPromise().then(
54-
resources => {
55-
if (isEqual(this.resources, resources)){
56-
return;
43+
Promise.all([
44+
this.k8s.getResource(this.currNamespace).toPromise(),
45+
this.k8s.getVolumes(this.currNamespace).toPromise()
46+
]).then(([notebooks, volumes]) => {
47+
if (!isEqual(notebooks, this.resources) || !isEqual(volumes, this.pvcs)) {
48+
this.poller.reset();
5749
}
58-
this.resources = resources;
59-
this.usedPVCs.clear();
60-
this.resources.forEach(res => {this.usedPVCs.add(res.volumes.forEach(element => {this.usedPVCs.add(element);}))})
61-
});
62-
63-
Promise.all([getVolumes, getResource])
64-
.then(val => {
65-
this.customPvcs = [];
66-
this.pvcs.forEach(vol => {
67-
this.customPvcs.push({pvc:vol, ismounted:this.usedPVCs.has(vol.name)});
68-
});
50+
this.resources = notebooks;
51+
this.pvcs = volumes;
52+
let mounts = Object.fromEntries(
53+
notebooks.flatMap(nb => nb.volumes.map(v => [v, nb]))
54+
);
55+
this.customPvcs = volumes.map(v => ({
56+
pvc: v,
57+
mountedBy: mounts[v.name]?.name
58+
}));
6959
});
7060
});
7161

7262
// Keep track of the selected namespace
73-
const namespaceSub = this.ns
74-
.getSelectedNamespace()
75-
.subscribe(namespace => {
76-
this.currNamespace = namespace;
77-
this.poller.reset();
78-
});
63+
const namespaceSub = this.ns.getSelectedNamespace().subscribe(namespace => {
64+
this.currNamespace = namespace;
65+
this.poller.reset();
66+
});
7967

8068
this.subscriptions.add(resourcesSub);
8169
this.subscriptions.add(namespaceSub);
@@ -115,29 +103,29 @@ export class MainTableComponent implements OnInit {
115103
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
116104
width: "fit-content",
117105
data: {
118-
title: "You are about to delete the PVC: " + p.pvc.name,
106+
title: "You are about to delete the volume: " + p.pvc.name,
119107
message:
120-
"Are you sure you want to delete this Persistent Volume Claim? ",
108+
"Are you sure you want to delete this volume? " +
109+
"This action can't be undone.",
121110
yes: "delete",
122111
no: "cancel"
123112
}
124113
});
125114

126115
dialogRef
127-
.afterClosed()
128-
.pipe(first())
129-
.subscribe(result => {
130-
if (result !== "delete") {
131-
return;
132-
}
116+
.afterClosed()
117+
.pipe(first())
118+
.subscribe(result => {
119+
if (result !== "delete") {
120+
return;
121+
}
133122

134-
this.k8s
135-
.deletePersistentStorageClaim(p.pvc.namespace, p.pvc.name)
136-
.pipe(first())
137-
.subscribe(r => {
138-
this.poller.reset();
139-
});
140-
});
123+
this.k8s
124+
.deletePersistentStorageClaim(p.pvc.namespace, p.pvc.name)
125+
.pipe(first())
126+
.subscribe(_ => {
127+
this.poller.reset();
128+
});
129+
});
141130
}
142-
143131
}

frontend/src/app/main-table/resource-table/resource-table.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<div class="card mat-elevation-z2">
22
<div class="header">
3+
<mat-icon>computer</mat-icon>
34
<p>Notebook Servers</p>
45

56
<div class="spacer"></div>

frontend/src/app/main-table/volumes-table/volume-table.component.html

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<div class="card mat-elevation-z2">
22
<div class="header">
3+
<mat-icon>storage</mat-icon>
34
<p>Notebook Volumes</p>
45
</div>
56
<table mat-table [dataSource]="custompvcs" matSort>
@@ -9,15 +10,17 @@
910
<td mat-cell *matCellDef="let elem">{{ elem.pvc.name }}</td>
1011
</ng-container>
1112

12-
<ng-container matColumnDef="namespace">
13-
<th mat-header-cell *matHeaderCellDef>Namespace</th>
14-
<td mat-cell *matCellDef="let elem">{{ elem.pvc.namespace }}</td>
13+
<ng-container matColumnDef="size">
14+
<th mat-header-cell *matHeaderCellDef>Size</th>
15+
<td mat-cell *matCellDef="let elem">
16+
{{ elem.pvc.size }}
17+
</td>
1518
</ng-container>
1619

17-
<ng-container matColumnDef="isMounted">
18-
<th mat-header-cell *matHeaderCellDef>Is Mounted?</th>
20+
<ng-container matColumnDef="mountedBy">
21+
<th mat-header-cell *matHeaderCellDef>Used By</th>
1922
<td mat-cell *matCellDef="let elem">
20-
{{ elem.ismounted ? 'Yes' : 'No' }}
23+
{{ elem.mountedBy || '(None)' }}
2124
</td>
2225
</ng-container>
2326

@@ -27,7 +30,7 @@
2730
<td mat-cell *matCellDef="let elem">
2831
<button
2932
mat-icon-button
30-
[disabled]="elem.ismounted === true"
33+
[disabled]="elem.mountedBy"
3134
(click)="deletePvc(elem)"
3235
>
3336
<mat-icon>delete</mat-icon>
Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,21 @@
1-
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
2-
import { MatTableDataSource } from "@angular/material/table";
3-
import { Pvc } from "../../utils/types";
1+
import {Component, Input, Output, EventEmitter} from "@angular/core";
2+
import {MatTableDataSource} from "@angular/material/table";
3+
import {Pvc} from "../../utils/types";
44

55
@Component({
66
selector: "app-volume-table",
77
templateUrl: "./volume-table.component.html",
8-
styleUrls: ["./volume-table.component.scss","../main-table.component.scss"]
8+
styleUrls: ["./volume-table.component.scss", "../main-table.component.scss"]
99
})
10-
11-
export class VolumeTableComponent implements OnInit {
10+
export class VolumeTableComponent {
1211
@Input() custompvcs: Pvc[];
1312
@Output() deletePvcEvent = new EventEmitter<Pvc>();
1413

1514
// Table data
16-
displayedColumns: string[] = [
17-
"name",
18-
"namespace",
19-
"isMounted",
20-
"actions"
21-
];
15+
displayedColumns: string[] = ["name", "size", "mountedBy", "actions"];
2216
dataSource = new MatTableDataSource();
2317

24-
constructor() { }
25-
26-
ngOnInit() { }
27-
28-
ngOnDestroy() { }
29-
30-
deletePvc(pvc: Pvc){
18+
deletePvc(pvc: Pvc) {
3119
this.deletePvcEvent.emit(pvc);
3220
}
3321
}

frontend/src/app/utils/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export enum SnackType {
139139
Info
140140
}
141141

142-
export interface Pvc {
142+
export type Pvc = {
143143
pvc: Volume;
144-
ismounted: boolean
144+
mountedBy: string | null;
145145
}

frontend/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"node_modules/@types"
1616
],
1717
"lib": [
18-
"es2018",
18+
"es2020",
1919
"dom"
2020
]
2121
}

0 commit comments

Comments
 (0)