Skip to content

Commit

Permalink
Allows uploading pipeline at run creation time
Browse files Browse the repository at this point in the history
  • Loading branch information
rileyjbauer committed Sep 6, 2019
1 parent 5360f3f commit 2332747
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 4 deletions.
42 changes: 41 additions & 1 deletion frontend/src/pages/NewRun.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import * as React from 'react';
import BusyButton from '../atoms/BusyButton';
import Button from '@material-ui/core/Button';
import Buttons from '../lib/Buttons';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
Expand All @@ -43,6 +44,7 @@ import { Workflow } from '../../../frontend/third_party/argo-ui/argo_template';
import { classes, stylesheet } from 'typestyle';
import { commonCss, padding, color } from '../Css';
import { logger, errorToMessage } from '../lib/Utils';
import UploadPipelineDialog, { ImportMethod } from '../components/UploadPipelineDialog';

interface NewRunState {
description: string;
Expand Down Expand Up @@ -71,6 +73,7 @@ interface NewRunState {
unconfirmedSelectedExperiment?: ApiExperiment;
unconfirmedSelectedPipeline?: ApiPipeline;
useWorkflowFromRun: boolean;
uploadDialogOpen: boolean;
usePipelineFromRunLabel: string;
}

Expand Down Expand Up @@ -113,6 +116,7 @@ class NewRun extends Page<{}, NewRunState> {
pipelineName: '',
pipelineSelectorOpen: false,
runName: '',
uploadDialogOpen: false,
usePipelineFromRunLabel: 'Using pipeline from cloned run',
useWorkflowFromRun: false,
};
Expand Down Expand Up @@ -153,6 +157,8 @@ class NewRun extends Page<{}, NewRunState> {
urlParser.build({ [QUERY_PARAMS.fromRunId]: originalRunId })
: '';

const buttons = new Buttons(this.props, this.refresh.bind(this));

return (
<div className={classes(commonCss.page, padding(20, 'lr'))}>
<div className={commonCss.scrollContainer}>
Expand Down Expand Up @@ -202,7 +208,9 @@ class NewRun extends Page<{}, NewRunState> {
emptyMessage='No pipelines found. Upload a pipeline and then try again.'
initialSortColumn={PipelineSortKeys.CREATED_AT}
selectionChanged={(selectedPipeline: ApiPipeline) =>
this.setStateSafe({ unconfirmedSelectedPipeline: selectedPipeline })} />
this.setStateSafe({ unconfirmedSelectedPipeline: selectedPipeline })}
toolbarActionMap={buttons.upload(() =>
this.setStateSafe({ pipelineSelectorOpen: false, uploadDialogOpen: true })).getToolbarActionMap()} />
</DialogContent>
<DialogActions>
<Button id='cancelPipelineSelectionBtn' onClick={() => this._pipelineSelectorClosed(false)} color='secondary'>
Expand All @@ -215,6 +223,9 @@ class NewRun extends Page<{}, NewRunState> {
</DialogActions>
</Dialog>

<UploadPipelineDialog open={this.state.uploadDialogOpen}
onClose={this._uploadDialogClosed.bind(this)} />

{/* Experiment selector dialog */}
<Dialog open={experimentSelectorOpen}
classes={{ paper: css.selectorDialog }}
Expand Down Expand Up @@ -483,6 +494,35 @@ class NewRun extends Page<{}, NewRunState> {
this.setStateSafe({ parameters });
}

private async _uploadDialogClosed(confirmed: boolean, name: string, file: File | null, url: string,
method: ImportMethod, description?: string): Promise<boolean> {

if (!confirmed
|| (method === ImportMethod.LOCAL && !file)
|| (method === ImportMethod.URL && !url)) {
this.setStateSafe({ pipelineSelectorOpen: true, uploadDialogOpen: false });
return false;
}

try {
const uploadedPipeline =
method === ImportMethod.LOCAL
? await Apis.uploadPipeline(name, file!)
: await Apis.pipelineServiceApi.createPipeline({ name, url: { pipeline_url: url } });
this.setStateSafe({
pipeline: uploadedPipeline,
pipelineName: (uploadedPipeline && uploadedPipeline.name) || '',
pipelineSelectorOpen: false,
uploadDialogOpen: false,
}, () => this._validate());
return true;
} catch (err) {
const errorMessage = await errorToMessage(err);
this.showErrorDialog('Failed to upload pipeline', errorMessage);
return false;
}
}

private async _prepareFormFromEmbeddedPipeline(embeddedPipelineRunId: string): Promise<void> {
let embeddedPipelineSpec: string | null;
let runWithEmbeddedPipeline: ApiRunDetail;
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/ResourceSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface ResourceSelectorProps extends RouteComponentProps {
initialSortColumn: any;
selectionChanged: (resource: BaseResource) => void;
title: string;
toolbarActionMap?: ToolbarActionMap;
updateDialog: (dialogProps: DialogProps) => void;
}

Expand All @@ -63,17 +64,17 @@ class ResourceSelector extends React.Component<ResourceSelectorProps, ResourceSe
resources: [],
rows: [],
selectedIds: [],
toolbarActionMap: {},
toolbarActionMap: (props && props.toolbarActionMap) || {},
};
}

public render(): JSX.Element {
const { rows, selectedIds, toolbarActionMap: toolbarActions } = this.state;
const { rows, selectedIds, toolbarActionMap } = this.state;
const { columns, title, filterLabel, emptyMessage, initialSortColumn } = this.props;

return (
<React.Fragment>
<Toolbar actions={toolbarActions} breadcrumbs={[]} pageTitle={title} />
<Toolbar actions={toolbarActionMap} breadcrumbs={[]} pageTitle={title} />
<CustomTable columns={columns} rows={rows} selectedIds={selectedIds} useRadioButtons={true}
updateSelection={this._selectionChanged.bind(this)} filterLabel={filterLabel}
initialSortColumn={initialSortColumn} reload={this._load.bind(this)}
Expand Down
Loading

0 comments on commit 2332747

Please sign in to comment.