Skip to content

Commit

Permalink
feat(ui): Add Template/Cron workflow filter to workflow page. Closes a…
Browse files Browse the repository at this point in the history
…rgoproj#4532 (argoproj#4543)

Signed-off-by: Tianchu Zhao <evantczhao@gmail.com>
Signed-off-by: Paul Brabban <paul.brabban@gmail.com>
  • Loading branch information
tczhao authored and brabster committed Nov 24, 2020
1 parent 8dc491b commit b48996a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 22 deletions.
1 change: 1 addition & 0 deletions USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,4 @@ Currently, the following organizations are **officially** using Argo Workflows:
1. [UFirstGroup](https://www.ufirstgroup.com)
1. [Wavefront](https://www.wavefront.com/)
1. [Wellcome Trust](https://wellcome.ac.uk/)
1. [Woolworths Group](https://www.woolworthsgroup.com.au/)
35 changes: 15 additions & 20 deletions ui/src/app/reports/components/reports.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Checkbox, DataLoader, Page, Select} from 'argo-ui/src/index';
import {Checkbox, Page} from 'argo-ui/src/index';
import {ChartOptions} from 'chart.js';
import 'chartjs-plugin-annotation';
import * as React from 'react';
Expand All @@ -7,8 +7,9 @@ import {RouteComponentProps} from 'react-router-dom';
import {getColorForNodePhase, NODE_PHASE, Workflow} from '../../../models';
import {uiUrl} from '../../shared/base';
import {BasePage} from '../../shared/components/base-page';
import {DataLoaderDropdown} from '../../shared/components/data-loader-dropdown';
import {ErrorNotice} from '../../shared/components/error-notice';
import {InputFilter} from '../../shared/components/input-filter';
import {NamespaceFilter} from '../../shared/components/namespace-filter';
import {TagsInput} from '../../shared/components/tags-input/tags-input';
import {ZeroState} from '../../shared/components/zero-state';
import {Consumer, ContextApis} from '../../shared/context';
Expand Down Expand Up @@ -43,18 +44,10 @@ export class Reports extends BasePage<RouteComponentProps<any>, State> {
this.setLabel(labelKeyPhase, value);
}

private get workflowTemplate() {
return this.getLabel(labelKeyWorkflowTemplate);
}

private set workflowTemplate(value: string) {
this.setLabel(labelKeyWorkflowTemplate, value);
}

private get cronWorkflow() {
return this.getLabel(labelKeyCronWorkflow);
}

private set cronWorkflow(value: string) {
this.setLabel(labelKeyCronWorkflow, value);
}
Expand Down Expand Up @@ -257,11 +250,11 @@ export class Reports extends BasePage<RouteComponentProps<any>, State> {
</div>
<div className='columns small-4 xlarge-12'>
<p className='wf-filters-container__title'>Namespace</p>
<InputFilter
name='namespace'
<NamespaceFilter
value={this.state.namespace}
placeholder='Namespace'
onChange={namespace => this.fetchReport(namespace, this.state.labels, this.state.archivedWorkflows)}
onChange={namespace => {
this.fetchReport(namespace, this.state.labels, this.state.archivedWorkflows);
}}
/>
</div>
<div className='columns small-4 xlarge-12'>
Expand All @@ -274,15 +267,17 @@ export class Reports extends BasePage<RouteComponentProps<any>, State> {
</div>
<div className='columns small-4 xlarge-12'>
<p className='wf-filters-container__title'>Workflow Template</p>
<DataLoader load={() => services.workflowTemplate.list(this.state.namespace).then(list => list.map(x => x.metadata.name))}>
{list => <Select options={list} value={this.workflowTemplate} onChange={x => (this.workflowTemplate = x.value)} />}
</DataLoader>
<DataLoaderDropdown
load={services.workflowTemplate.list(this.state.namespace).then(list => list.map(x => x.metadata.name))}
onChange={value => (this.workflowTemplate = value)}
/>
</div>
<div className='columns small-4 xlarge-12'>
<p className='wf-filters-container__title'>Cron Workflow</p>
<DataLoader load={() => services.cronWorkflows.list(this.state.namespace).then(list => list.map(x => x.metadata.name))}>
{list => <Select options={list} value={this.cronWorkflow} onChange={x => (this.cronWorkflow = x.value)} />}
</DataLoader>
<DataLoaderDropdown
load={services.cronWorkflows.list(this.state.namespace).then(list => list.map(x => x.metadata.name))}
onChange={value => (this.cronWorkflow = value)}
/>
</div>
<div className='columns small-43 xlarge-12'>
<p className='wf-filters-container__title'>Phase</p>
Expand Down
21 changes: 21 additions & 0 deletions ui/src/app/shared/components/data-loader-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {DataLoader, Select, SelectOption} from 'argo-ui';
import * as React from 'react';

export const DataLoaderDropdown = (props: {load: Promise<(string | SelectOption)[]>; onChange: (value: string) => void}) => {
const [selected, setSelected] = React.useState('');

return (
<DataLoader load={() => props.load}>
{list => (
<Select
options={list}
value={selected}
onChange={x => {
setSelected(x.value);
props.onChange(x.value);
}}
/>
)}
</DataLoader>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as React from 'react';
import * as models from '../../../../models';
import {CheckboxFilter} from '../../../shared/components/checkbox-filter/checkbox-filter';
import {DataLoaderDropdown} from '../../../shared/components/data-loader-dropdown';
import {NamespaceFilter} from '../../../shared/components/namespace-filter';
import {TagsInput} from '../../../shared/components/tags-input/tags-input';
import {services} from '../../../shared/services';

require('./workflow-filters.scss');

Expand All @@ -16,6 +18,18 @@ interface WorkflowFilterProps {
}

export class WorkflowFilters extends React.Component<WorkflowFilterProps, {}> {
private set workflowTemplate(value: string) {
this.setLabel(models.labels.workflowTemplate, value);
}

private set cronWorkflow(value: string) {
this.setLabel(models.labels.cronWorkflow, value);
}

private get labelSuggestion() {
return this.getLabelSuggestions(this.props.workflows);
}

public render() {
return (
<div className='wf-filters-container'>
Expand All @@ -33,13 +47,27 @@ export class WorkflowFilters extends React.Component<WorkflowFilterProps, {}> {
<p className='wf-filters-container__title'>Labels</p>
<TagsInput
placeholder=''
autocomplete={this.getLabelSuggestions(this.props.workflows)}
autocomplete={this.labelSuggestion}
tags={this.props.selectedLabels}
onChange={tags => {
this.props.onChange(this.props.namespace, this.props.selectedPhases, tags);
}}
/>
</div>
<div className='columns small-3 xlarge-12'>
<p className='wf-filters-container__title'>Workflow Template</p>
<DataLoaderDropdown
load={services.workflowTemplate.list(this.props.namespace).then(list => list.map(x => x.metadata.name))}
onChange={value => (this.workflowTemplate = value)}
/>
</div>
<div className='columns small-3 xlarge-12'>
<p className='wf-filters-container__title'>Cron Workflow</p>
<DataLoaderDropdown
load={services.cronWorkflows.list(this.props.namespace).then(list => list.map(x => x.metadata.name))}
onChange={value => (this.cronWorkflow = value)}
/>
</div>
<div className='columns small-6 xlarge-12'>
<p className='wf-filters-container__title'>Phases</p>
<CheckboxFilter
Expand All @@ -56,6 +84,10 @@ export class WorkflowFilters extends React.Component<WorkflowFilterProps, {}> {
);
}

private setLabel(name: string, value: string) {
this.props.onChange(this.props.namespace, this.props.selectedPhases, [name.concat('=' + value)]);
}

private getPhaseItems(workflows: models.Workflow[]) {
const phasesMap = new Map<string, number>();
this.props.phaseItems.forEach(value => phasesMap.set(value, 0));
Expand All @@ -67,6 +99,20 @@ export class WorkflowFilters extends React.Component<WorkflowFilterProps, {}> {
return results;
}

private addCommonLabel(suggestions: string[]) {
const commonLabel = new Array<string>();
const commonLabelPool = [models.labels.cronWorkflow, models.labels.workflowTemplate, models.labels.clusterWorkflowTemplate];
commonLabelPool.forEach(labelPrefix => {
for (const label of suggestions) {
if (label.startsWith(labelPrefix)) {
commonLabel.push(`${labelPrefix}`);
break;
}
}
});
return commonLabel.concat(suggestions);
}

private getLabelSuggestions(workflows: models.Workflow[]) {
const suggestions = new Array<string>();
workflows
Expand All @@ -80,6 +126,6 @@ export class WorkflowFilters extends React.Component<WorkflowFilterProps, {}> {
}
});
});
return suggestions.sort((a, b) => a.localeCompare(b));
return this.addCommonLabel(suggestions.sort((a, b) => a.localeCompare(b)));
}
}

0 comments on commit b48996a

Please sign in to comment.