Skip to content

Commit 986e13a

Browse files
committed
kwa(front): Support all namespaces
Add support for all-namespaces in KWA. Signed-off-by: Elena Zioga <[email protected]>
1 parent 1429d61 commit 986e13a

File tree

6 files changed

+84
-94
lines changed

6 files changed

+84
-94
lines changed

pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/experiment-details.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
numberToExponential,
1818
transformStringResponses,
1919
} from '../../shared/utils';
20-
import { getDeleteDialogConfig } from '../experiments/delete-modal-config';
20+
import { generateDeleteConfig } from '../experiments/delete-modal-config';
2121
import { ExperimentK8s } from '../../models/experiment.k8s.model';
2222

2323
@Component({
@@ -134,7 +134,7 @@ export class ExperimentDetailsComponent implements OnInit, OnDestroy {
134134
}
135135

136136
private deleteExperiment(name: string, namespace: string) {
137-
const deleteDialogConfig = getDeleteDialogConfig(name, namespace);
137+
const deleteDialogConfig = generateDeleteConfig(name);
138138
const ref = this.confirmDialog.open(name, deleteDialogConfig);
139139

140140
const delSub = ref.componentInstance.applying$.subscribe(applying => {

pkg/new-ui/v1beta1/frontend/src/app/pages/experiments/config.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import {
55
ActionIconValue,
66
TableConfig,
77
DateTimeValue,
8-
TemplateValue,
9-
ChipsListValue,
108
ComponentValue,
119
LinkValue,
1210
LinkType,
@@ -16,11 +14,11 @@ import {
1614
parseSucceededTrials,
1715
parseRunningTrials,
1816
parseFailedTrials,
19-
parseTotalTrials,
2017
} from './utils';
2118
import { ExperimentOptimalTrialComponent } from './optimal-trial/experiment-optimal-trial.component';
2219

2320
export const experimentsTableConfig: TableConfig = {
21+
dynamicNamespaceColumn: true,
2422
columns: [
2523
{
2624
matHeaderCellDef: 'Status',
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import { DialogConfig } from 'kubeflow';
22

33
// --- Configs for the Confirm Dialogs ---
4-
export function getDeleteDialogConfig(
5-
name: string,
6-
namespace: string,
7-
): DialogConfig {
4+
export function generateDeleteConfig(name: string): DialogConfig {
85
return {
9-
title: `Delete experiment`,
10-
message: `Are you sure you want to delete ${name} experiment from namespace ${namespace}?`,
11-
accept: 'DELETE',
6+
title: $localize`Delete experiment ${name}?`,
7+
message: $localize`You cannot undo this action. Are you sure you want to delete this experiment?`,
8+
accept: $localize`DELETE`,
129
confirmColor: 'warn',
13-
cancel: 'CANCEL',
10+
cancel: $localize`CANCEL`,
1411
error: '',
15-
applying: 'DELETING',
12+
applying: $localize`DELETING`,
1613
width: '600px',
1714
};
1815
}

pkg/new-ui/v1beta1/frontend/src/app/pages/experiments/experiments.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ConfirmDialogService,
1010
NamespaceService,
1111
KubeflowModule,
12+
PollerService,
1213
} from 'kubeflow';
1314
import { KWABackendService } from 'src/app/services/backend.service';
1415
import { RouterTestingModule } from '@angular/router/testing';
@@ -46,6 +47,7 @@ describe('ExperimentsComponent', () => {
4647
{ provide: KWABackendService, useValue: KWABackendServiceStub },
4748
{ provide: ConfirmDialogService, useValue: {} },
4849
{ provide: NamespaceService, useValue: NamespaceServiceStub },
50+
{ provide: PollerService, useValue: {} },
4951
],
5052
}).compileComponents();
5153
}),
Lines changed: 57 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { Component, OnDestroy, OnInit } from '@angular/core';
22
import { environment } from '@app/environment';
33
import { Subscription } from 'rxjs';
4-
import isEqual from 'lodash-es/isEqual';
54
import {
65
ConfirmDialogService,
76
DIALOG_RESP,
8-
ExponentialBackoff,
97
NamespaceService,
108
ActionEvent,
119
DashboardState,
1210
ToolbarButton,
11+
PollerService,
1312
} from 'kubeflow';
1413

1514
import { KWABackendService } from 'src/app/services/backend.service';
@@ -18,7 +17,7 @@ import {
1817
ExperimentsProcessed,
1918
} from '../../models/experiment.model';
2019
import { experimentsTableConfig } from './config';
21-
import { getDeleteDialogConfig } from './delete-modal-config';
20+
import { generateDeleteConfig } from './delete-modal-config';
2221
import { Router } from '@angular/router';
2322

2423
@Component({
@@ -27,50 +26,67 @@ import { Router } from '@angular/router';
2726
styleUrls: ['./experiments.component.scss'],
2827
})
2928
export class ExperimentsComponent implements OnInit, OnDestroy {
30-
experiments: ExperimentsProcessed = [];
31-
currNamespace: string;
32-
config = experimentsTableConfig;
3329
env = environment;
34-
dashboardDisconnectedState = DashboardState.Disconnected;
3530

36-
private subs = new Subscription();
37-
private poller: ExponentialBackoff;
31+
nsSub = new Subscription();
32+
pollSub = new Subscription();
3833

39-
private rawData: Experiment[] = [];
34+
currNamespace: string | string[];
35+
config = experimentsTableConfig;
36+
experiments: ExperimentsProcessed = [];
4037

41-
buttons: ToolbarButton[] = [
42-
new ToolbarButton({
43-
text: `New Experiment`,
44-
icon: 'add',
45-
stroked: true,
46-
fn: () => {
47-
this.router.navigate(['/new']);
48-
},
49-
}),
50-
];
38+
dashboardDisconnectedState = DashboardState.Disconnected;
39+
40+
private newExperimentButton = new ToolbarButton({
41+
text: $localize`New Experiment`,
42+
icon: 'add',
43+
stroked: true,
44+
fn: () => {
45+
this.router.navigate(['/new']);
46+
},
47+
});
48+
49+
buttons: ToolbarButton[] = [this.newExperimentButton];
5150

5251
constructor(
5352
private backend: KWABackendService,
5453
private confirmDialog: ConfirmDialogService,
5554
private router: Router,
5655
public ns: NamespaceService,
56+
public poller: PollerService,
5757
) {}
5858

59-
ngOnInit() {
60-
this.startExperimentsPolling();
61-
59+
ngOnInit(): void {
6260
// Reset the poller whenever the selected namespace changes
63-
this.subs.add(
64-
this.ns.getSelectedNamespace().subscribe(nameSpace => {
65-
this.currNamespace = nameSpace;
66-
this.poller.reset();
67-
}),
68-
);
61+
this.nsSub = this.ns.getSelectedNamespace2().subscribe(ns => {
62+
this.currNamespace = ns;
63+
this.poll(ns);
64+
this.newExperimentButton.namespaceChanged(ns, $localize`Experiment`);
65+
});
66+
}
67+
68+
ngOnDestroy() {
69+
this.nsSub.unsubscribe();
70+
this.pollSub.unsubscribe();
6971
}
7072

71-
ngOnDestroy(): void {
72-
this.subs.unsubscribe();
73-
this.poller.stop();
73+
public poll(ns: string | string[]) {
74+
this.pollSub.unsubscribe();
75+
this.experiments = [];
76+
77+
const request = this.backend.getExperiments(ns);
78+
79+
this.pollSub = this.poller.exponential(request).subscribe(experiments => {
80+
this.experiments = experiments.map(row => {
81+
return {
82+
...row,
83+
link: {
84+
text: row.name,
85+
url: `/experiment/${row.name}`,
86+
},
87+
};
88+
});
89+
});
7490
}
7591

7692
trackByFn(index: number, experiment: Experiment) {
@@ -81,76 +97,38 @@ export class ExperimentsComponent implements OnInit, OnDestroy {
8197
const exp = a.data as Experiment;
8298
switch (a.action) {
8399
case 'delete':
84-
this.onDeleteExperiment(exp.name);
100+
this.deleteClicked(exp);
85101
break;
86102
}
87103
}
88104

89-
onDeleteExperiment(name: string) {
90-
const deleteDialogConfig = getDeleteDialogConfig(name, this.currNamespace);
91-
const ref = this.confirmDialog.open(name, deleteDialogConfig);
105+
deleteClicked(exp: Experiment) {
106+
const deleteDialogConfig = generateDeleteConfig(exp.name);
107+
const ref = this.confirmDialog.open(exp.name, deleteDialogConfig);
92108

93109
const delSub = ref.componentInstance.applying$.subscribe(applying => {
94110
if (!applying) {
95111
return;
96112
}
97113

98114
// Close the open dialog only if the DELETE request succeeded
99-
this.backend.deleteExperiment(name, this.currNamespace).subscribe({
100-
next: _ => {
101-
this.poller.reset();
115+
this.backend.deleteExperiment(exp.name, exp.namespace).subscribe(
116+
res => {
102117
ref.close(DIALOG_RESP.ACCEPT);
103118
},
104-
error: err => {
105-
const errorMsg = err;
106-
deleteDialogConfig.error = errorMsg;
119+
err => {
120+
deleteDialogConfig.error = err;
107121
ref.componentInstance.applying$.next(false);
108122
},
109-
});
123+
);
110124

111125
// DELETE request has succeeded
112126
ref.afterClosed().subscribe(res => {
113127
delSub.unsubscribe();
114128
if (res !== DIALOG_RESP.ACCEPT) {
115129
return;
116130
}
117-
118-
this.poller.reset();
119131
});
120132
});
121133
}
122-
123-
private startExperimentsPolling() {
124-
this.poller = new ExponentialBackoff({ interval: 1000, retries: 3 });
125-
126-
// Poll for new data and reset the poller if different data is found
127-
this.subs.add(
128-
this.poller.start().subscribe(() => {
129-
if (!this.currNamespace) {
130-
return;
131-
}
132-
133-
this.backend
134-
.getExperiments(this.currNamespace)
135-
.subscribe(experiments => {
136-
if (isEqual(this.rawData, experiments)) {
137-
return;
138-
}
139-
140-
this.experiments = experiments.map(row => {
141-
return {
142-
...row,
143-
link: {
144-
text: row.name,
145-
url: `/experiment/${row.namespace}/${row.name}`,
146-
},
147-
};
148-
});
149-
150-
this.rawData = experiments;
151-
this.poller.reset();
152-
});
153-
}),
154-
);
155-
}
156134
}

pkg/new-ui/v1beta1/frontend/src/app/services/backend.service.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class KWABackendService extends BackendService {
3838
return throwError(msg);
3939
}
4040

41-
getExperiments(namespace: string): Observable<Experiments> {
41+
getExperimentsSingleNamespace(namespace: string): Observable<Experiments> {
4242
// If the route doesn't end in a "/"" then the backend will return a 301 to
4343
// the url ending with "/".
4444
const url = `/katib/fetch_experiments/?namespace=${namespace}`;
@@ -51,6 +51,21 @@ export class KWABackendService extends BackendService {
5151
);
5252
}
5353

54+
getExperimentsAllNamespaces(namespaces: string[]): Observable<Experiments> {
55+
return this.getObjectsAllNamespaces(
56+
this.getExperimentsSingleNamespace.bind(this),
57+
namespaces,
58+
);
59+
}
60+
61+
getExperiments(ns: string | string[]): Observable<Experiments> {
62+
if (Array.isArray(ns)) {
63+
return this.getExperimentsAllNamespaces(ns);
64+
}
65+
66+
return this.getExperimentsSingleNamespace(ns);
67+
}
68+
5469
getExperimentTrialsInfo(name: string, namespace: string): Observable<any> {
5570
const url = `/katib/fetch_hp_job_info/?experimentName=${name}&namespace=${namespace}`;
5671

0 commit comments

Comments
 (0)