Skip to content

Commit 88e6787

Browse files
authored
frontend: Make trials table support pagination/sorting/filtering (#2040)
* build: Update the COMMIT file * Update the COMMIT file. Signed-off-by: Elena Zioga <[email protected]> * frontend: Support paging/sorting/filtering in trials table (#1441) * Make trials table support paging, sorting and filtering. Signed-off-by: Elena Zioga <[email protected]> * frontend: Create unit tests for trials table (#1441) * Create unit tests for trials-table component. Signed-off-by: Elena Zioga <[email protected]> Signed-off-by: Elena Zioga <[email protected]>
1 parent 6b54eb2 commit 88e6787

File tree

7 files changed

+274
-147
lines changed

7 files changed

+274
-147
lines changed

pkg/new-ui/v1beta1/frontend/COMMIT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1cca7b81
1+
2b4cc42e

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { ExperimentOverviewModule } from './overview/experiment-overview.module'
1616
import { ExperimentDetailsTabModule } from './details/experiment-details-tab.module';
1717
import { ExperimentYamlModule } from './yaml/experiment-yaml.module';
1818
import { TrialsGraphEchartsModule } from './trials-graph-echarts/trials-graph-echarts.module';
19+
import { KubeflowModule } from 'kubeflow';
1920

2021
@NgModule({
2122
declarations: [ExperimentDetailsComponent],
@@ -33,6 +34,7 @@ import { TrialsGraphEchartsModule } from './trials-graph-echarts/trials-graph-ec
3334
ExperimentYamlModule,
3435
TitleActionsToolbarModule,
3536
TrialsGraphEchartsModule,
37+
KubeflowModule,
3638
],
3739
exports: [ExperimentDetailsComponent],
3840
})
Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,10 @@
1-
<table [dataSource]="data" class="wide" mat-table>
2-
<!--- Note that these columns can be defined in any order.
3-
The actual rendered columns are set as a property on the row definition" -->
4-
5-
<!-- Position Column -->
6-
<ng-container
7-
*ngFor="let column of displayedColumns; let i = index"
8-
[matColumnDef]="column"
9-
>
10-
<th mat-header-cell *matHeaderCellDef>
11-
{{ column === 'Kfp run' ? '' : column }}
12-
</th>
13-
<td
14-
*matCellDef="let element"
15-
[ngClass]="{ cell: column === 'Trial name' }"
16-
mat-cell
17-
>
18-
<span
19-
*ngIf="
20-
column !== 'Trial name' && column !== 'Status' && column !== 'Kfp run'
21-
"
22-
>{{ element[i] }}
23-
</span>
24-
25-
<span
26-
(click)="openTrialDetails(element[i])"
27-
*ngIf="column === 'Trial name'"
28-
class="name"
29-
>{{ element[i] }}
30-
</span>
31-
32-
<div *ngIf="column === 'Kfp run'" class="svg-color">
33-
<mat-icon
34-
(click)="goToKfpRun(element[i])"
35-
[matTooltipDisabled]="!!element[i]"
36-
[ngClass]="{ 'icon-disable': !element[i] }"
37-
class="icon"
38-
matTooltip="No KFP run"
39-
svgIcon="pipeline-centered"
40-
></mat-icon>
41-
</div>
42-
43-
<span
44-
*ngIf="column === 'Status'"
45-
[ngClass]="{
46-
green: element[i] === 'Succeeded',
47-
red: element[i] === 'Failed'
48-
}"
49-
>{{ element[i] }}</span
50-
>
51-
</td>
52-
</ng-container>
53-
54-
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
55-
<tr
56-
(mouseleave)="handleMouseLeave()"
57-
(mouseover)="handleMouseOver(row)"
58-
*matRowDef="let row; let i = index; columns: displayedColumns"
59-
[ngClass]="{ 'best-trail-row': bestTrialIndex === i }"
60-
mat-row
61-
>
62-
>
63-
</tr>
64-
</table>
1+
<div class="lib-content-wrapper">
2+
<div class="page-padding lib-flex-grow lib-overflow-auto">
3+
<lib-table
4+
[config]="config"
5+
[data]="processedData"
6+
[highlightedRow]="bestTrialRow"
7+
(actionsEmitter)="reactToAction($event)"
8+
></lib-table>
9+
</div>
10+
</div>

pkg/new-ui/v1beta1/frontend/src/app/pages/experiment-details/trials-table/trials-table.component.scss

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,3 @@
22
display: block;
33
min-height: 550px;
44
}
5-
6-
.cell {
7-
width: 300px;
8-
}
9-
10-
.name {
11-
cursor: pointer;
12-
13-
&:hover {
14-
color: #1e88e5;
15-
text-decoration: underline;
16-
}
17-
}
18-
19-
.green {
20-
color: green;
21-
}
22-
23-
.red {
24-
color: red;
25-
}
26-
27-
.icon {
28-
cursor: pointer;
29-
30-
&-disable {
31-
cursor: default;
32-
opacity: 0.5;
33-
}
34-
}
35-
36-
td.mat-cell:not(:first-of-type) {
37-
padding: 2px 28px 2px 0;
38-
}
39-
40-
td.mat-cell:first-of-type {
41-
padding: 2px 28px 2px 24px;
42-
}
43-
44-
.mat-row:hover {
45-
background-color: #f3f3f3;
46-
}
47-
48-
.svg-color {
49-
color: #1e88e5;
50-
display: flex;
51-
justify-content: flex-end;
52-
margin-right: 16px;
53-
}
54-
55-
::ng-deep :host svg {
56-
fill: currentColor;
57-
}
58-
59-
.best-trail-row {
60-
background-color: #ffffcd;
61-
62-
&:hover {
63-
background-color: #ffff98;
64-
}
65-
}

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

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ import { MatButtonModule } from '@angular/material/button';
1111
import { TrialsTableComponent } from './trials-table.component';
1212
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
1313

14+
import { SimpleChange } from '@angular/core';
15+
import { PropertyValue, StatusValue, ComponentValue } from 'kubeflow';
16+
import { parseStatus } from '../../experiments/utils';
17+
import lowerCase from 'lodash-es/lowerCase';
18+
import { KfpRunComponent } from './kfp-run/kfp-run.component';
19+
1420
describe('TrialsTableComponent', () => {
1521
let component: TrialsTableComponent;
1622
let fixture: ComponentFixture<TrialsTableComponent>;
@@ -38,10 +44,157 @@ describe('TrialsTableComponent', () => {
3844
beforeEach(() => {
3945
fixture = TestBed.createComponent(TrialsTableComponent);
4046
component = fixture.componentInstance;
47+
component.displayedColumns = [
48+
'Status',
49+
'Trial name',
50+
'Validation loss',
51+
'Lr',
52+
'Batch size',
53+
'Embed dim',
54+
'Dropout',
55+
'Sp dropout',
56+
'Kfp run',
57+
];
58+
component.data = [
59+
[
60+
'Succeeded',
61+
'open-vaccine-0f37u-6cd03cbf',
62+
'0.70573',
63+
'0.0001',
64+
'32',
65+
'20',
66+
'0.2',
67+
'0.2',
68+
'9af7c534-689a-48aa-996b-537d13989729',
69+
'0',
70+
],
71+
[
72+
'Succeeded',
73+
'open-vaccine-0f37u-8ec17b8f',
74+
'0.76401',
75+
'0.0001',
76+
'96',
77+
'20',
78+
'0.2',
79+
'0.2',
80+
'19aed8e0-143c-49d8-8bd3-7ebb464181d8',
81+
'1',
82+
],
83+
];
84+
component.ngOnChanges({
85+
displayedColumns: new SimpleChange(
86+
null,
87+
component.displayedColumns,
88+
false,
89+
),
90+
});
91+
4192
fixture.detectChanges();
4293
});
4394

44-
it('should create', () => {
45-
expect(component).toBeTruthy();
95+
it('should create processedData', () => {
96+
expect(component.processedData).toEqual([
97+
{
98+
'trial name': 'open-vaccine-0f37u-6cd03cbf',
99+
status: 'Succeeded',
100+
'validation loss': '0.70573',
101+
lr: '0.0001',
102+
'batch size': '32',
103+
'embed dim': '20',
104+
dropout: '0.2',
105+
'sp dropout': '0.2',
106+
'kfp run': '9af7c534-689a-48aa-996b-537d13989729',
107+
},
108+
{
109+
'trial name': 'open-vaccine-0f37u-8ec17b8f',
110+
status: 'Succeeded',
111+
'validation loss': '0.76401',
112+
lr: '0.0001',
113+
'batch size': '96',
114+
'embed dim': '20',
115+
dropout: '0.2',
116+
'sp dropout': '0.2',
117+
'kfp run': '19aed8e0-143c-49d8-8bd3-7ebb464181d8',
118+
},
119+
]);
120+
});
121+
122+
it('should create config', () => {
123+
expect(component.config).toEqual({
124+
columns: [
125+
{
126+
matColumnDef: 'Status',
127+
matHeaderCellDef: 'Status',
128+
value: new StatusValue({
129+
valueFn: parseStatus,
130+
}),
131+
sort: true,
132+
},
133+
{
134+
matColumnDef: 'name',
135+
matHeaderCellDef: 'Trial name',
136+
value: new PropertyValue({
137+
field: lowerCase(component.displayedColumns[1]),
138+
isLink: true,
139+
}),
140+
sort: true,
141+
},
142+
{
143+
matColumnDef: 'Validation loss',
144+
matHeaderCellDef: 'Validation loss',
145+
value: new PropertyValue({
146+
field: lowerCase(component.displayedColumns[2]),
147+
}),
148+
sort: true,
149+
},
150+
{
151+
matColumnDef: 'Lr',
152+
matHeaderCellDef: 'Lr',
153+
value: new PropertyValue({
154+
field: lowerCase(component.displayedColumns[3]),
155+
}),
156+
sort: true,
157+
},
158+
{
159+
matColumnDef: 'Batch size',
160+
matHeaderCellDef: 'Batch size',
161+
value: new PropertyValue({
162+
field: lowerCase(component.displayedColumns[4]),
163+
}),
164+
sort: true,
165+
},
166+
{
167+
matColumnDef: 'Embed dim',
168+
matHeaderCellDef: 'Embed dim',
169+
value: new PropertyValue({
170+
field: lowerCase(component.displayedColumns[5]),
171+
}),
172+
sort: true,
173+
},
174+
{
175+
matColumnDef: 'Dropout',
176+
matHeaderCellDef: 'Dropout',
177+
value: new PropertyValue({
178+
field: lowerCase(component.displayedColumns[6]),
179+
}),
180+
sort: true,
181+
},
182+
{
183+
matColumnDef: 'Sp dropout',
184+
matHeaderCellDef: 'Sp dropout',
185+
value: new PropertyValue({
186+
field: lowerCase(component.displayedColumns[7]),
187+
}),
188+
sort: true,
189+
},
190+
{
191+
matHeaderCellDef: '',
192+
matColumnDef: 'actions',
193+
value: new ComponentValue({
194+
component: KfpRunComponent,
195+
}),
196+
},
197+
],
198+
});
46199
});
47200
});

0 commit comments

Comments
 (0)