Skip to content

Commit

Permalink
feat(ui): Add links to wft, cwf, or cwft to workflow list and details.
Browse files Browse the repository at this point in the history
…Closes #3621 (#3662)
  • Loading branch information
alexec authored Aug 5, 2020
1 parent 1c95a98 commit 32d6f75
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import {uiUrl} from '../../shared/base';
import {LinkButton} from '../../shared/components/link-button';

export const ClusterWorkflowTemplateLink = (props: {name: string}) => (
<LinkButton to={uiUrl('cluster-workflow-templates/' + props.name)}>
<i className='fa fa-window-restore' /> {props.name}
</LinkButton>
);
9 changes: 9 additions & 0 deletions ui/src/app/cron-workflows/components/cron-workflow-link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import {uiUrl} from '../../shared/base';
import {LinkButton} from '../../shared/components/link-button';

export const CronWorkflowLink = (props: {namespace: string; name: string}) => (
<LinkButton to={uiUrl('cron-workflows/' + props.namespace + '/' + props.name)}>
<i className='fa fa-clock' /> {props.name}
</LinkButton>
);
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import * as React from 'react';

import * as kubernetes from 'argo-ui/src/models/kubernetes';
import {Link} from 'react-router-dom';
import {CronWorkflow} from '../../../models';
import {uiUrl} from '../../shared/base';
import {ResourceEditor} from '../../shared/components/resource-editor/resource-editor';
import {Timestamp} from '../../shared/components/timestamp';
import {ConditionsPanel} from '../../shared/conditions-panel';
import {services} from '../../shared/services';
import {WorkflowLink} from '../../workflows/components/workflow-link';

const jsonMergePatch = require('json-merge-patch');

Expand Down Expand Up @@ -86,16 +85,6 @@ export const CronWorkflowSummaryPanel = (props: Props) => {
);
};

function getCronWorkflowActiveWorkflowList(active: kubernetes.ObjectReference[]): JSX.Element {
return (
<div>
{active.reverse().map(activeWf => (
<div>
<Link to={uiUrl(`workflows/${activeWf.namespace}/${activeWf.name}`)}>
{activeWf.namespace}/{activeWf.name}
</Link>
</div>
))}
</div>
);
function getCronWorkflowActiveWorkflowList(active: kubernetes.ObjectReference[]) {
return active.reverse().map(activeWf => <WorkflowLink key={activeWf.uid} namespace={activeWf.namespace} name={activeWf.name} />);
}
8 changes: 8 additions & 0 deletions ui/src/app/shared/components/link-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as React from 'react';
import {ReactNode} from 'react';

export const LinkButton = (props: {to: string; children?: ReactNode}) => (
<button className='argo-button argo-button--base-o' onClick={() => (document.location.href = props.to)}>
{props.children}
</button>
);
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ const LOCAL_STORAGE_KEY = 'ResourceEditorLang';

export class ResourceEditor<T> extends React.Component<Props<T>, State> {
private set lang(lang: string) {
this.setState({lang, value: stringify(parse(this.state.value), lang)});
try {
this.setState({lang, error: null, value: stringify(parse(this.state.value), lang)});
} catch (error) {
this.setState({error});
}
}

private static saveLang(newLang: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import {uiUrl} from '../../shared/base';
import {LinkButton} from '../../shared/components/link-button';

export const WorkflowTemplateLink = (props: {namespace: string; name: string}) => (
<LinkButton to={uiUrl('workflow-templates/' + props.namespace + '/' + props.name)}>
<i className='fa fa-window-maximize' /> {props.name}
</LinkButton>
);
5 changes: 4 additions & 1 deletion ui/src/app/workflows/components/submit-workflow-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ export class SubmitWorkflowPanel extends React.Component<Props, State> {
))}
</>
) : (
<label>No parameters</label>
<>
<br />
<label>No parameters</label>
</>
)}
</div>
<div key='labels' style={{marginBottom: 25}}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Loading} from '../../../shared/components/loading';
import {ConditionsPanel} from '../../../shared/conditions-panel';
import {formatDuration} from '../../../shared/duration';
import {services} from '../../../shared/services';
import {WorkflowFrom} from '../workflow-from';
import {WorkflowLabels} from '../workflow-labels/workflow-labels';

require('./workflow-drawer.scss');
Expand Down Expand Up @@ -74,6 +75,11 @@ export class WorkflowDrawer extends React.Component<WorkflowDrawerProps, Workflo
</div>
</div>
)}
<div className='workflow-drawer__section'>
<div className='workflow-drawer__workflowFrom'>
<WorkflowFrom namespace={wf.metadata.namespace} labels={wf.metadata.labels} />
</div>
</div>
<div className='workflow-drawer__section workflow-drawer__labels'>
<div className='workflow-drawer__title'>LABELS</div>
<div className='workflow-drawer__labels--list'>
Expand Down
19 changes: 19 additions & 0 deletions ui/src/app/workflows/components/workflow-from.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import {labels} from '../../../models';
import {ClusterWorkflowTemplateLink} from '../../cluster-workflow-templates/components/cluster-workflow-template-link';
import {CronWorkflowLink} from '../../cron-workflows/components/cron-workflow-link';
import {WorkflowTemplateLink} from '../../workflow-templates/components/workflow-template-link';

export const WorkflowFrom = (props: {namespace: string; labels: {[name: string]: string}}) => {
const workflowTemplate = props.labels[labels.workflowTemplate];
const clusterWorkflowTemplate = props.labels[labels.clusterWorkflowTemplate];
const cronWorkflow = props.labels[labels.cronWorkflow];
return (
<>
{workflowTemplate && <WorkflowTemplateLink namespace={props.namespace} name={workflowTemplate} />}
{clusterWorkflowTemplate && <ClusterWorkflowTemplateLink name={clusterWorkflowTemplate} />}
{cronWorkflow && <CronWorkflowLink namespace={props.namespace} name={cronWorkflow} />}
{!workflowTemplate && !clusterWorkflowTemplate && !cronWorkflow && '-'}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
align-items: center;
height: 100%;
$gutter: 0.5em;
background-color: $argo-color-gray-1;
margin-top: -8px;
border-radius: 0 0 3px 3px;

.tag {
Expand All @@ -19,6 +17,7 @@
margin-right: 10px;
display: flex;
overflow: hidden;
cursor: pointer;

&:hover {
.key {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require('./workflow-labels.scss');

interface WorkflowLabelsProps {
workflow: models.Workflow;
onChange: (key: string) => void;
onChange: (key: string, value: string) => void;
}

export class WorkflowLabels extends React.Component<WorkflowLabelsProps, {}> {
Expand All @@ -18,16 +18,17 @@ export class WorkflowLabels extends React.Component<WorkflowLabelsProps, {}> {
const w = this.props.workflow;
if (w.metadata.labels) {
labels.push(
Object.keys(w.metadata.labels).map(key => (
Object.entries(w.metadata.labels).map(([key, value]) => (
<div
title={`List workflows labelled with ${key}=${value}`}
className='tag'
key={`${w.metadata.uid}-${key}`}
onClick={async e => {
e.preventDefault();
this.props.onChange(key);
this.props.onChange(key, value);
}}>
<div className='key'>{key}</div>
<div className='value'>{w.metadata.labels[key]}</div>
<div className='value'>{value}</div>
</div>
))
);
Expand Down
9 changes: 9 additions & 0 deletions ui/src/app/workflows/components/workflow-link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import {uiUrl} from '../../shared/base';
import {LinkButton} from '../../shared/components/link-button';

export const WorkflowLink = (props: {namespace: string; name: string}) => (
<LinkButton to={uiUrl('workflows/' + props.namespace + '/' + props.name)}>
<i className='fa fa-stream' /> {props.name}
</LinkButton>
);
22 changes: 20 additions & 2 deletions ui/src/app/workflows/components/workflow-summary-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import {Ticker} from 'argo-ui';
import * as React from 'react';

import {NODE_PHASE, Workflow} from '../../../models';
import {labels, NODE_PHASE, Workflow} from '../../../models';
import {uiUrl} from '../../shared/base';
import {Phase} from '../../shared/components/phase';
import {Timestamp} from '../../shared/components/timestamp';
import {ConditionsPanel} from '../../shared/conditions-panel';
import {Consumer} from '../../shared/context';
import {formatDuration, wfDuration} from '../../shared/duration';
import {ResourcesDuration} from '../../shared/resources-duration';
import {WorkflowFrom} from './workflow-from';
import {WorkflowLabels} from './workflow-labels/workflow-labels';

export const WorkflowSummaryPanel = (props: {workflow: Workflow}) => (
<Ticker disabled={props.workflow && props.workflow.status.phase !== NODE_PHASE.RUNNING}>
Expand All @@ -16,11 +20,25 @@ export const WorkflowSummaryPanel = (props: {workflow: Workflow}) => (
{title: 'Message', value: props.workflow.status.message},
{title: 'Name', value: props.workflow.metadata.name},
{title: 'Namespace', value: props.workflow.metadata.namespace},
{title: 'From', value: <WorkflowFrom namespace={props.workflow.metadata.namespace} labels={props.workflow.metadata.labels} />},
{
title: 'Labels',
value: (
<Consumer>
{ctx => (
<WorkflowLabels
workflow={props.workflow}
onChange={(key, value) => ctx.navigation.goto(uiUrl(`workflows/${props.workflow.metadata.namespace}?label=${key}=${value}`))}
/>
)}
</Consumer>
)
},
{title: 'Started', value: <Timestamp date={props.workflow.status.startedAt} />},
{title: 'Finished ', value: <Timestamp date={props.workflow.status.finishedAt} />},
{title: 'Duration', value: formatDuration(wfDuration(props.workflow.status))}
];
const creator = props.workflow.metadata.labels['workflows.argoproj.io/creator'];
const creator = props.workflow.metadata.labels[labels.creator];
if (creator) {
attributes.push({title: 'Creator', value: creator});
}
Expand Down
6 changes: 5 additions & 1 deletion ui/src/models/workflows.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as kubernetes from 'argo-ui/src/models/kubernetes';

export const labels = {
completed: 'workflows.argoproj.io/completed'
clusterWorkflowTemplate: 'workflows.argoproj.io/cluster-workflow-template',
completed: 'workflows.argoproj.io/completed',
creator: 'workflows.argoproj.io/creator',
cronWorkflow: 'workflows.argoproj.io/cron-workflow',
workflowTemplate: 'workflows.argoproj.io/workflow-template'
};

/**
Expand Down

0 comments on commit 32d6f75

Please sign in to comment.