Skip to content

Commit

Permalink
Distinct page for each Trial in the UI (#1783)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-gol committed Jun 29, 2022
1 parent cfa2d84 commit 2d35224
Show file tree
Hide file tree
Showing 22 changed files with 679 additions and 89 deletions.
1 change: 1 addition & 0 deletions cmd/new-ui/v1beta1/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func main() {
http.HandleFunc("/katib/delete_experiment/", kuh.DeleteExperiment)

http.HandleFunc("/katib/fetch_experiment/", kuh.FetchExperiment)
http.HandleFunc("/katib/fetch_trial/", kuh.FetchTrial)
http.HandleFunc("/katib/fetch_suggestion/", kuh.FetchSuggestion)

http.HandleFunc("/katib/fetch_hp_job_info/", kuh.FetchHPJobInfo)
Expand Down
24 changes: 24 additions & 0 deletions pkg/new-ui/v1beta1/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,27 @@ func (k *KatibUIHandler) FetchSuggestion(w http.ResponseWriter, r *http.Request)
return
}
}

// FetchTrial gets trial in specific namespace.
func (k *KatibUIHandler) FetchTrial(w http.ResponseWriter, r *http.Request) {
trialName := r.URL.Query()["trialName"][0]
namespace := r.URL.Query()["namespace"][0]

trial, err := k.katibClient.GetTrial(trialName, namespace)
if err != nil {
log.Printf("GetTrial failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
response, err := json.Marshal(trial)
if err != nil {
log.Printf("Marshal Trial failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if _, err = w.Write(response); err != nil {
log.Printf("Write trial failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
5 changes: 5 additions & 0 deletions pkg/new-ui/v1beta1/frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { Routes, RouterModule } from '@angular/router';
import { ExperimentsComponent } from './pages/experiments/experiments.component';
import { ExperimentDetailsComponent } from './pages/experiment-details/experiment-details.component';
import { ExperimentCreationComponent } from './pages/experiment-creation/experiment-creation.component';
import { TrialModalComponent } from './pages/experiment-details/trials-table/trial-modal/trial-modal.component';

const routes: Routes = [
{ path: '', component: ExperimentsComponent },
{ path: 'experiment/:experimentName', component: ExperimentDetailsComponent },
{ path: 'new', component: ExperimentCreationComponent },
{
path: 'experiment/:experimentName/trial/:trialName',
component: TrialModalComponent,
},
];

@NgModule({
Expand Down
2 changes: 2 additions & 0 deletions pkg/new-ui/v1beta1/frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AppComponent } from './app.component';
import { ExperimentsModule } from './pages/experiments/experiments.module';
import { ExperimentDetailsModule } from './pages/experiment-details/experiment-details.module';
import { ExperimentCreationModule } from './pages/experiment-creation/experiment-creation.module';
import { TrialModalModule } from './pages/experiment-details/trials-table/trial-modal/trial-modal.module';

@NgModule({
declarations: [AppComponent],
Expand All @@ -19,6 +20,7 @@ import { ExperimentCreationModule } from './pages/experiment-creation/experiment
ExperimentDetailsModule,
ReactiveFormsModule,
ExperimentCreationModule,
TrialModalModule,
],
providers: [],
bootstrap: [AppComponent],
Expand Down
84 changes: 84 additions & 0 deletions pkg/new-ui/v1beta1/frontend/src/app/models/trial.k8s.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { K8sObject } from 'kubeflow';
import { V1Container } from '@kubernetes/client-node';

/*
* K8s object definitions
*/
export const TRIAL_KIND = 'Trial';
export const TRIAL_APIVERSION = 'kubeflow.org/v1beta1';

export interface TrialK8s extends K8sObject {
spec?: TrialSpec;
status?: TrialStatus;
}

export interface TrialSpec {
metricsCollector: MetricsCollector;
objective: Objective;
parameterAssignments: { name: string; value: number }[];
primaryContainerName: string;
successCondition: string;
failureCondition: string;
runSpec: K8sObject;
}

export interface MetricsCollector {
collector?: CollectorSpec;
}

export interface CollectorSpec {
kind: CollectorKind;
customCollector: V1Container;
}

export type CollectorKind =
| 'StdOut'
| 'File'
| 'TensorFlowEvent'
| 'PrometheusMetric'
| 'Custom'
| 'None';

export interface Objective {
type: ObjectiveType;
goal: number;
objectiveMetricName: string;
additionalMetricNames: string[];
metricStrategies: MetricStrategy[];
}

export type ObjectiveType = 'maximize' | 'minimize';

export interface MetricStrategy {
name: string;
value: string;
}

export interface RunSpec {}

/*
* status
*/

interface TrialStatus {
startTime: string;
completionTime: string;
conditions: TrialStatusCondition[];
observation: {
metrics: {
name: string;
latest: string;
min: string;
max: string;
}[];
};
}

interface TrialStatusCondition {
type: string;
status: boolean;
reason: string;
message: string;
lastUpdateTime: string;
lastTransitionTime: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@
</ng-template>

<div class="tab-height-fix">
<mat-tab-group dynamicHeight animationDuration="0ms">
<mat-tab-group
dynamicHeight
animationDuration="0ms"
[(selectedIndex)]="selectedTab"
(selectedTabChange)="tabChanged($event)"
>
<mat-tab label="OVERVIEW">
<app-experiment-overview
[experimentName]="name"
Expand All @@ -45,6 +50,7 @@
(leaveMouseFromTrial)="mouseLeftTrial()"
(mouseOnTrial)="mouseOverTrial($event)"
[data]="details"
[experimentName]="name"
[displayedColumns]="columns"
[namespace]="namespace"
[bestTrialName]="bestTrialName"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MatTabChangeEvent } from '@angular/material/tabs';
import {
ConfirmDialogService,
DIALOG_RESP,
Expand Down Expand Up @@ -35,6 +36,13 @@ export class ExperimentDetailsComponent implements OnInit, OnDestroy {
showGraph: boolean;
bestTrialName: string;
pageLoading = true;
selectedTab = 0;
tabs = new Map<string, number>([
['overview', 0],
['trials', 1],
['details', 2],
['yaml', 3],
]);

constructor(
private activatedRoute: ActivatedRoute,
Expand Down Expand Up @@ -62,6 +70,12 @@ export class ExperimentDetailsComponent implements OnInit, OnDestroy {
ngOnInit() {
this.name = this.activatedRoute.snapshot.params.experimentName;

if (this.activatedRoute.snapshot.queryParams['tab']) {
this.selectedTab = this.tabs.get(
this.activatedRoute.snapshot.queryParams['tab'],
);
}

this.subs.add(
this.namespaceService.getSelectedNamespace().subscribe(namespace => {
this.namespace = namespace;
Expand All @@ -70,6 +84,10 @@ export class ExperimentDetailsComponent implements OnInit, OnDestroy {
);
}

tabChanged(event: MatTabChangeEvent) {
this.selectedTab = event.index;
}

ngOnDestroy(): void {
this.subs.unsubscribe();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<lib-details-list-item key="Latest">
{{ latest }}
</lib-details-list-item>

<lib-details-list-item key="Minimum">
{{ min }}
</lib-details-list-item>

<lib-details-list-item key="Maximum">
{{ max }}
</lib-details-list-item>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { ConditionsTableModule, DetailsListModule } from 'kubeflow';
import { TrialModalMetricsComponent } from './metrics.component';

@NgModule({
declarations: [TrialModalMetricsComponent],
imports: [ConditionsTableModule, DetailsListModule],
exports: [TrialModalMetricsComponent],
})
export class TrialModalMetricsModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { TrialModalMetricsComponent } from './metrics.component';

describe('TrialModalMetricsComponent', () => {
let component: TrialModalMetricsComponent;
let fixture: ComponentFixture<TrialModalMetricsComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TrialModalMetricsComponent],
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(TrialModalMetricsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'app-metrics-overview',
templateUrl: './metrics.component.html',
})
export class TrialModalMetricsComponent {
@Input() name: string;
@Input() latest: string;
@Input() max: string;
@Input() min: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div>
<lib-details-list-item key="Trial Name">
{{ trialName }}
</lib-details-list-item>

<lib-details-list-item key="Experiment Name">
{{ experimentName }}
</lib-details-list-item>

<lib-details-list-item key="Status" [icon]="statusIcon">
{{ status }}
</lib-details-list-item>

<lib-details-list-item key="Completion Time">
{{ completionTime }}
</lib-details-list-item>

<lib-details-list-item [chipsList]="performance" key="Performance">
</lib-details-list-item>

<ng-container *ngIf="trial.status.observation?.metrics">
<div
*ngFor="let metric of trial.status.observation?.metrics"
[style.margin-top]="'16px'"
>
<lib-heading-row heading="Metric:" subHeading="{{ metric.name }}">
</lib-heading-row>
<app-metrics-overview
[name]="metric.name"
[min]="metric.min"
[max]="metric.max"
[latest]="metric.latest"
></app-metrics-overview>
</div>
</ng-container>

<lib-conditions-table
*ngIf="trial"
[conditions]="trial.status.conditions"
title="Trial Conditions"
></lib-conditions-table>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { TrialModalOverviewComponent } from './trial-modal-overview.component';

describe('TrialModalOverviewComponent', () => {
let component: TrialModalOverviewComponent;
let fixture: ComponentFixture<TrialModalOverviewComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TrialModalOverviewComponent],
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(TrialModalOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 2d35224

Please sign in to comment.