Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/app/dag/dag.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
}

/deep/ g.root {
rect {
rect,
circle {
stroke: $primary-lighter !important;
fill: $primary-light !important;
}
Expand Down Expand Up @@ -134,28 +135,32 @@
}

/deep/ .node.succeeded {
rect {
rect,
circle {
stroke: $success;
fill: $success-light;
}
}

/deep/ .node.running {
rect {
rect,
circle {
stroke: $primary;
fill: $primary-light;
}
}

/deep/ .node.failed {
rect {
rect,
circle {
stroke: $danger;
fill: $danger-light;
}
}

/deep/ .node.error {
rect {
rect,
circle {
stroke: $danger;
fill: $danger-light;
}
Expand All @@ -171,7 +176,8 @@
}

/deep/ .node.selected {
rect {
rect,
circle {
stroke: #F6881F !important;
stroke-width: 2px;
}
Expand Down
8 changes: 4 additions & 4 deletions src/app/node-info/metrics/metrics.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">METRICS</div>
<div *ngFor="let item of metrics" class="font-roboto mt-2">
<div class="key font-weight-bold">{{item.name}}</div>
<div *ngIf="item.value" class="value">{{item.value}}</div>
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-5">METRICS</div>
<div *ngFor="let item of metrics" class="font-roboto d-block mt-2 ml-1">
<span class="key font-weight-bold">{{item.name}}: </span>
<span *ngIf="item.value" class="value">{{item.value}}</span>
</div>
2 changes: 1 addition & 1 deletion src/app/node-info/metrics/metrics.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { Metric, MetricsService } from "./metrics.service";
import { Metric } from "./metrics.service";

@Component({
selector: 'app-metrics',
Expand Down
155 changes: 90 additions & 65 deletions src/app/node-info/node-info.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,53 +62,36 @@
<mat-expansion-panel class="op-expansion-panel parameters" hideToggle="true" (expandedChange)="onParametersExpandChange($event)">
<mat-expansion-panel-header [expandedHeight]="'48px'">
<mat-panel-title class="font-size-larger font-primary justify-content-between align-items-center">
Parameters
Inputs
<div class="expansion-icon" *ngIf="!parametersExpanded">&#43;</div>
<div class="expansion-icon" *ngIf="parametersExpanded">&#8722;</div>
</mat-panel-title>
</mat-expansion-panel-header>

<div *ngIf="inputArtifacts?.length || inputParameters?.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">INPUTS</div>

<div *ngIf="inputArtifacts?.length">
<div class="font-roboto-bold font-size-small font-medium-gray font-weight-bold mt-5 ml-2">ARTIFACTS</div>
<app-artifact-parameter
*ngFor="let parameter of inputArtifacts"
[parameter]="parameter"
class="d-block mt-2 ml-4">
</app-artifact-parameter>
</div>

<div *ngIf="inputParameters?.length">
<div class="font-roboto-bold font-size-small font-medium-gray font-weight-bold mt-5 ml-2">PARAMETERS</div>
<app-parameter
*ngFor="let parameter of inputParameters"
[parameter]="parameter"
class="ml-4">
</app-parameter>
</div>
<div *ngIf="inputParameters?.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-2">PARAMETERS</div>
<app-parameter
*ngFor="let parameter of inputParameters"
[parameter]="parameter"
class="d-block mt-2 ml-1">
</app-parameter>
</div>

<div *ngIf="outputArtifacts?.length || outputParameters?.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-5" *ngIf="node.type === 'Pod'">OUTPUTS</div>

<div *ngIf="outputArtifacts?.length">
<div class="font-roboto-bold font-size-small font-medium-gray font-weight-bold mt-5 ml-2">ARTIFACTS</div>
<app-artifact-parameter *ngFor="let parameter of outputArtifacts" [parameter]="parameter" class="d-block mt-2 ml-4">
</app-artifact-parameter>
</div>
<div *ngIf="inputArtifacts?.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-5">ARTIFACTS</div>
<app-artifact-parameter
*ngFor="let parameter of inputArtifacts"
[parameter]="parameter"
class="d-block mt-2 ml-1">
</app-artifact-parameter>
</div>

<div *ngIf="outputParameters?.length">
<div class="font-roboto-bold font-size-small font-medium-gray font-weight-bold mt-5 ml-2">PARAMETERS</div>
<app-parameter
*ngFor="let parameter of outputParameters"
[parameter]="parameter"
class="ml-4">
</app-parameter>
</div>
<div *ngIf="!inputParameters?.length && !inputArtifacts?.length" class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">
No inputs
</div>

</mat-expansion-panel>

<mat-expansion-panel class="op-expansion-panel" hideToggle="true" *ngIf="node.type === 'Pod'" (expandedChange)="onContainersExpandChange($event)">
<mat-expansion-panel-header [expandedHeight]="'48px'">
<mat-panel-title class="font-size-larger font-primary justify-content-between align-items-center">
Expand All @@ -120,51 +103,93 @@

<div *ngIf="template">
<div>
<div class="font-weight-bold">Name</div>
<div>{{template.name}}</div>
<span class="font-weight-bold">Name: </span>
<span>{{template.name}}</span>
</div>
<div class="mt-2" *ngIf="template.container?.image || template.script?.image">
<span class="font-weight-bold w-50">Image: </span>
<span>{{template.container?.image}}{{template.script?.image}}</span>
</div>
<div class="mt-2" *ngIf="template.container?.command || template.script?.command">
<div class="font-weight-bold w-50">Command:</div>
<pre class="source-code">{{template.container?.command?.join(" ")}}{{template.script?.command?.join(" ")}}</pre>
</div>
<div class="mt-2" *ngIf="template.container?.args || template.script?.args">
<div class="font-weight-bold w-50">Args:</div>
<pre class="source-code">{{template.container?.args?.join(" ")}}{{template.script?.args?.join(" ")}}</pre>
</div>
<div class="mt-2">
<div class="font-weight-bold w-50">Image</div>
<div>{{template.container?.image}}</div>
<div class="mt-2" *ngIf="template.script?.source">
<div class="font-weight-bold w-50">Source:</div>
<pre class="source-code">{{template.script?.source}}</pre>
</div>
<div class="mt-2">
<div class="font-weight-bold w-50">Command</div>
<div>{{template.container?.command?.join(" ")}}</div>
<div class="mt-2" *ngIf="template.resource?.action">
<span class="font-weight-bold w-50">Action: </span>
<span class="source-code">{{template.resource?.action}}</span>
</div>
<div class="mt-2">
<div class="font-weight-bold w-50">Args</div>
<div>{{template.container?.args?.join(" ")}}</div>
<div class="mt-2" *ngIf="template.resource?.successCondition">
<span class="font-weight-bold w-50">Success condition: </span>
<span class="source-code">{{template.resource?.successCondition}}</span>
</div>
<div class="mt-2" *ngIf="template.resource?.failureCondition">
<span class="font-weight-bold w-50">Failure condition: </span>
<span class="source-code">{{template.resource?.failureCondition}}</span>
</div>
<div class="mt-2" *ngIf="template.resource?.manifest">
<div class="font-weight-bold w-50">Manifest:</div>
<pre class="source-code">{{template.resource?.manifest}}</pre>
</div>
</div>
</mat-expansion-panel>

<mat-expansion-panel class="op-expansion-panel" hideToggle="true" *ngIf="node.type === 'Pod'" (expandedChange)="onArtifactsExpandChange($event)">
<mat-expansion-panel-header [expandedHeight]="'48px'">
<mat-panel-title class="font-size-larger font-primary justify-content-between align-items-center">
Artifacts
Outputs
<div class="expansion-icon" *ngIf="!artifactsExpanded">&#43;</div>
<div class="expansion-icon" *ngIf="artifactsExpanded">&#8722;</div>
</mat-panel-title>
</mat-expansion-panel-header>

<div>
<app-metrics *ngIf="metrics.length" [metrics]="metrics">
</app-metrics>

<div *ngIf="hasFiles" class="mt-4">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">FILES</div>
<app-file-browser *ngFor="let fileNavigator of fileNavigators"
class="d-block mt-3"
[displayedColumns]="['icon', 'name', 'size', 'actions']"
[rootName]="fileNavigator.displayRootPath"
[fileNavigator]="fileNavigator"
[namespace]="this.namespace"
[name]="fileNavigator.name">
</app-file-browser>
<div *ngIf="sidecars.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-2">SIDECARS</div>
<div class="d-inline-flex w-100 mt-5">
<button *ngFor="let sidecar of sidecars" mat-stroked-button color="primary"
[disabled]="node.phase !== 'Running'"
class="op-rounded op-button op-button-disableable ml-1"
(click)="this.openSidecar(sidecar.url)">
<span class="ml-1">OPEN {{sidecar.name}}</span>
</button>
</div>
</div>
<div *ngIf="!metrics.length && !hasFiles" class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">
No Artifacts

<app-metrics *ngIf="metrics.length" [metrics]="metrics">
</app-metrics>

<div *ngIf="outputParameters?.length">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold mt-5">PARAMETERS</div>
<app-parameter
*ngFor="let parameter of outputParameters"
[parameter]="parameter"
class="d-block mt-2 ml-1">
</app-parameter>
</div>

<div *ngIf="hasFiles" class="mt-4">
<div class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">ARTIFACTS</div>
<app-file-browser *ngFor="let fileNavigator of fileNavigators"
class="d-block mt-3"
[displayedColumns]="['icon', 'name', 'size', 'actions']"
[rootName]="fileNavigator.displayRootPath"
[fileNavigator]="fileNavigator"
[namespace]="this.namespace"
[name]="fileNavigator.name">
</app-file-browser>
</div>

<div *ngIf="!outputParameters?.length && !metrics.length && !sidecars.length && !hasFiles" class="font-roboto-bold font-size-regular font-medium-gray font-weight-bold">
No outputs
</div>

</mat-expansion-panel>
</div>
</div>
15 changes: 15 additions & 0 deletions src/app/node-info/node-info.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,19 @@
.finished-at {
margin-bottom: 35px;
}

pre.source-code {
background: #f4f4f4;
border: 1px solid #ddd;
color: #666;
page-break-inside: avoid;
font-family: monospace;
font-size: 14px;
line-height: 1.6;
max-width: 100%;
overflow: auto;
padding: 0.5em 0.75em;
display: block;
word-wrap: break-word;
}
}
53 changes: 50 additions & 3 deletions src/app/node-info/node-info.component.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { NodeStatus } from '../node/node.service';
import { NodeParameter, NodeStatus } from '../node/node.service';
import { SimpleWorkflowDetail, WorkflowPhase, WorkflowService, } from '../workflow/workflow.service';
import * as yaml from 'js-yaml';
import { TemplateDefinition } from '../workflow-template/workflow-template.service';
import { FileNavigator } from '../files/fileNavigator';
import { WorkflowServiceService } from '../../api';
import { Metric, MetricsService } from './metrics/metrics.service';

interface SideCar {
name: string;
url: string;
}

@Component({
selector: 'app-node-info',
templateUrl: './node-info.component.html',
styleUrls: ['./node-info.component.scss'],
providers: [WorkflowService, MetricsService]
})
export class NodeInfoComponent implements OnInit, OnDestroy {

@Input() namespace: string;
@Input() name: string;

Expand Down Expand Up @@ -48,6 +52,7 @@ export class NodeInfoComponent implements OnInit, OnDestroy {

fileNavigators = [];
fileLoaderSubscriptions = {};
sidecars = new Array<SideCar>();

constructor(private workflowService: WorkflowService,
private workflowServiceService: WorkflowServiceService,
Expand Down Expand Up @@ -114,6 +119,21 @@ export class NodeInfoComponent implements OnInit, OnDestroy {
return directories;
}

private static sysSideCarUrlPrefixLength = 17;

private static paramToSideCar(parameter: NodeParameter): SideCar {
let name = parameter.name.substring(NodeInfoComponent.sysSideCarUrlPrefixLength);
// some of the names have dashes like 'tensor-first'.
// change it to be 'tensor first' instead to look nicer for the button
name = name.replace(/-/g, ' ');
let url = `//${parameter.value}`;

return {
name,
url
};
}

ngOnInit() {
}

Expand Down Expand Up @@ -192,7 +212,10 @@ export class NodeInfoComponent implements OnInit, OnDestroy {
}

if (node.type !== 'DAG' && node.type !== 'Steps' && node.outputs) {
this.outputParameters = node.outputs.parameters;
if(node.outputs.parameters) {
this.updateOutputParameters(node.outputs.parameters);
}

this.outputArtifacts = node.outputs.artifacts;
}

Expand Down Expand Up @@ -264,6 +287,10 @@ export class NodeInfoComponent implements OnInit, OnDestroy {
return;
}

// Clear out the metrics. On success, it'll load new data.
// On failure, we will not have any metrics.
this.metrics = [];

this.metricsService.getWorkflowMetrics(this.namespace, this.workflow.name, this.node.id)
.subscribe(res => {
this.metrics = res.metrics;
Expand All @@ -285,4 +312,24 @@ export class NodeInfoComponent implements OnInit, OnDestroy {
private transitionedToFinishedNode(): boolean {
return this.previousNodeStatus && this.previousNodeStatus.finishedAt === null && this.node.finishedAt !== null;
}

updateOutputParameters(parameters: NodeParameter[]) {
let sidecars = [];
let outputParameters = [];

for(const param of parameters) {
if(param.name.startsWith('sys-sidecar-url')) {
sidecars.push(NodeInfoComponent.paramToSideCar(param));
} else {
outputParameters.push(param);
}
}

this.sidecars = sidecars;
this.outputParameters = outputParameters;
}

openSidecar(url: string) {
window.open(url);
}
}
Loading