Skip to content

Commit

Permalink
add yaml switcher in pipeline builder form
Browse files Browse the repository at this point in the history
  • Loading branch information
rottencandy committed Nov 6, 2020
1 parent ec7ace3 commit 9dbdf84
Show file tree
Hide file tree
Showing 20 changed files with 290 additions and 208 deletions.
Expand Up @@ -14,6 +14,7 @@ type EditorContext = {
editor: React.ReactNode;
isDisabled?: boolean;
sanitizeTo?: (preFormData: any) => any;
label?: string;
};

type SyncedEditorFieldProps = {
Expand Down Expand Up @@ -58,7 +59,7 @@ const SyncedEditorField: React.FC<SyncedEditorFieldProps> = ({
const newYAML = safeJSToYAML(formData, yamlData, { skipInvalid: true });
setFieldValue(
yamlContext.name,
yamlContext.sanitizeTo ? formContext.sanitizeTo(newYAML) : newYAML,
yamlContext.sanitizeTo ? yamlContext.sanitizeTo(newYAML) : newYAML,
);
changeEditorType(EditorType.YAML);
};
Expand Down Expand Up @@ -97,12 +98,12 @@ const SyncedEditorField: React.FC<SyncedEditorFieldProps> = ({
name={name}
options={[
{
label: t('console-shared~Form View'),
label: formContext.label || t('console-shared~Form View'),
value: EditorType.Form,
isDisabled: formContext.isDisabled,
},
{
label: t('console-shared~YAML View'),
label: yamlContext.label || t('console-shared~YAML View'),
value: EditorType.YAML,
isDisabled: yamlContext.isDisabled,
},
Expand Down
Expand Up @@ -19,7 +19,7 @@ const PipelineVisualization: React.FC<PipelineTopologyVisualizationProps> = ({
}) => {
const { nodes, edges } = getTopologyNodesEdges(pipeline, pipelineRun);
let content: React.ReactElement;
if (hasInlineTaskSpec(pipeline)) {
if (hasInlineTaskSpec(pipeline.spec.tasks)) {
// TODO: Inline taskSpec is not yet supported feature
content = (
<Alert
Expand Down
@@ -1,11 +1,9 @@
.odc-pipeline-builder-form {
overflow: auto;

&__grid {
grid-template-columns: minmax(0, 1fr);
}

&__content {
overflow: auto;
padding: 30px 30px 0 30px;
padding: 0 30px;
}

&__short-section {
Expand Down
@@ -1,29 +1,35 @@
import * as React from 'react';
import * as _ from 'lodash';
import { FormikProps, FormikValues } from 'formik';
import { Form, Stack, StackItem, TextInputTypes } from '@patternfly/react-core';
import { InputField, FormFooter } from '@console/shared';
import { Pipeline } from '../../../utils/pipeline-augment';
import { PipelineParameters, PipelineResources } from '../detail-page-tabs';
import { UpdateOperationType } from './const';
import { FormikProps } from 'formik';
import { Stack, StackItem } from '@patternfly/react-core';
import { FormFooter, SyncedEditorField, YAMLEditorField, FlexForm } from '@console/shared';
import { EditorType } from '@console/shared/src/components/synced-editor/editor-toggle';
import { safeJSToYAML } from '@console/shared/src/utils/yaml';
import { Pipeline, PipelineResourceTask } from '../../../utils/pipeline-augment';
import { PipelineVisualizationTaskItem } from '../../../utils/pipeline-utils';
import { PipelineModel } from '../../../models';
import { useResourceValidation } from './hooks';
import { removeTaskModal } from './modals';
import PipelineBuilderHeader from './PipelineBuilderHeader';
import PipelineBuilderVisualization from './PipelineBuilderVisualization';
import Sidebar from './task-sidebar/Sidebar';
import TaskSidebar from './task-sidebar/TaskSidebar';
import {
CleanupResults,
PipelineBuilderTaskGroup,
SelectedBuilderTask,
UpdateErrors,
UpdateOperationType,
UpdateOperationUpdateTaskData,
PipelineBuilderFormikValues,
} from './types';
import { applyChange } from './update-utils';
import { convertBuilderFormToPipeline } from './utils';
import { initialPipelineFormData } from './const';
import PipelineBuilderFormEditor from './PipelineBuilderFormEditor';

import './PipelineBuilderForm.scss';

type PipelineBuilderFormProps = FormikProps<FormikValues> & {
type PipelineBuilderFormProps = FormikProps<PipelineBuilderFormikValues> & {
existingPipeline: Pipeline;
namespace: string;
};
Expand Down Expand Up @@ -61,22 +67,29 @@ const PipelineBuilderForm: React.FC<PipelineBuilderFormProps> = (props) => {
[setStatus],
);

useResourceValidation(values.tasks, values.resources, updateErrors);
const onTaskSelection = (task: PipelineVisualizationTaskItem, resource: PipelineResourceTask) => {
setSelectedTask({
taskIndex: values.formData.tasks.findIndex(({ name }) => name === task.name),
resource,
});
};

useResourceValidation(values.formData.tasks, values.formData.resources, updateErrors);

const updateTasks = (changes: CleanupResults): void => {
const { tasks, listTasks, errors: taskErrors } = changes;

setFieldValue('tasks', tasks);
setFieldValue('listTasks', listTasks);
setFieldValue('formData.tasks', tasks);
setFieldValue('formData.listTasks', listTasks);
updateErrors(taskErrors);
};

const selectedId = values.tasks[selectedTask?.taskIndex]?.name;
const selectedId = values.formData.tasks[selectedTask?.taskIndex]?.name;
const selectedIds = selectedId ? [selectedId] : [];

const taskGroup: PipelineBuilderTaskGroup = {
tasks: values.tasks,
listTasks: values.listTasks,
tasks: values.formData.tasks,
listTasks: values.formData.listTasks,
highlightedIds: selectedIds,
};

Expand All @@ -86,67 +99,70 @@ const PipelineBuilderForm: React.FC<PipelineBuilderFormProps> = (props) => {
handleReset();
}, [handleReset]);

const formEditor = (
<PipelineBuilderFormEditor
namespace={namespace}
hasExistingPipeline={!!existingPipeline}
taskGroup={taskGroup}
onTaskSelection={onTaskSelection}
onUpdateTasks={(updatedTaskGroup, op) => {
updateTasks(applyChange(updatedTaskGroup, op));
}}
/>
);

const yamlEditor = (
<YAMLEditorField name="yamlData" onSave={handleSubmit} schemaModel={PipelineModel} />
);

const sanitizeToForm = (newFormData: Pipeline) => {
const formData = {
...newFormData.spec,
name: newFormData.metadata?.name,
listTasks: values.formData.listTasks,
};
return _.merge({}, initialPipelineFormData, formData);
};

const sanitizeToYaml = () =>
safeJSToYAML(convertBuilderFormToPipeline(values.formData, namespace), 'yamlData', {
skipInvalid: true,
});

return (
<>
<Stack className="odc-pipeline-builder-form">
<StackItem>
<PipelineBuilderHeader existingPipeline={existingPipeline} namespace={namespace} />
</StackItem>
<StackItem isFilled className="odc-pipeline-builder-form__content">
<Form className="odc-pipeline-builder-form__grid" onSubmit={handleSubmit}>
<div className="odc-pipeline-builder-form__short-section">
<InputField
label="Name"
name="name"
type={TextInputTypes.text}
isDisabled={!!existingPipeline}
required
/>
</div>

<div>
<h2>Tasks</h2>
<PipelineBuilderVisualization
namespace={namespace}
tasksInError={status?.tasks || {}}
onTaskSelection={(task, resource) => {
setSelectedTask({
taskIndex: values.tasks.findIndex(({ name }) => name === task.name),
resource,
});
}}
onUpdateTasks={(updatedTaskGroup, op) =>
updateTasks(applyChange(updatedTaskGroup, op))
}
taskGroup={taskGroup}
/>
</div>

<div>
<h2>Parameters</h2>
<PipelineParameters addLabel="Add Parameters" fieldName="params" />
</div>

<div>
<h2>Resources</h2>
<PipelineResources addLabel="Add Resources" fieldName="resources" />
</div>
<FormFooter
handleReset={closeSidebarAndHandleReset}
errorMessage={status?.submitError}
isSubmitting={isSubmitting}
submitLabel={existingPipeline ? 'Save' : 'Create'}
disableSubmit={
!dirty ||
!_.isEmpty(errors) ||
!_.isEmpty(status?.tasks) ||
values.tasks.length === 0
}
resetLabel="Cancel"
sticky
/>
</Form>
<PipelineBuilderHeader />
</StackItem>
<FlexForm className="odc-pipeline-builder-form__grid" onSubmit={handleSubmit}>
<SyncedEditorField
name="editorType"
formContext={{
name: 'formData',
editor: formEditor,
label: 'Pipeline Builder',
sanitizeTo: sanitizeToForm,
}}
yamlContext={{ name: 'yamlData', editor: yamlEditor, sanitizeTo: sanitizeToYaml }}
/>
<FormFooter
handleReset={closeSidebarAndHandleReset}
errorMessage={status?.submitError}
isSubmitting={isSubmitting}
submitLabel={existingPipeline ? 'Save' : 'Create'}
disableSubmit={
values.editorType === EditorType.YAML
? !dirty
: !dirty ||
!_.isEmpty(errors) ||
!_.isEmpty(status?.tasks) ||
values.formData.tasks.length === 0
}
resetLabel="Cancel"
sticky
/>
</FlexForm>
</Stack>
<Sidebar
open={!!selectedTask}
Expand All @@ -161,7 +177,7 @@ const PipelineBuilderForm: React.FC<PipelineBuilderFormProps> = (props) => {
<TaskSidebar
// Intentional remount when selection changes
key={selectedTask.taskIndex}
resourceList={values.resources || []}
resourceList={values.formData.resources || []}
errorMap={status?.tasks || {}}
onUpdateTask={(data: UpdateOperationUpdateTaskData) => {
updateTasks(
Expand Down
@@ -0,0 +1,64 @@
import * as React from 'react';
import { useFormikContext } from 'formik';
import { TextInputTypes } from '@patternfly/react-core';
import { InputField } from '@console/shared';
import { PipelineParameters, PipelineResources } from '../detail-page-tabs';
import PipelineBuilderVisualization from './PipelineBuilderVisualization';
import {
PipelineBuilderFormikValues,
PipelineBuilderTaskGroup,
SelectTaskCallback,
UpdateTasksCallback,
} from './types';

import './PipelineBuilderForm.scss';

type PipelineBuilderFormEditorProps = {
namespace: string;
hasExistingPipeline: boolean;
taskGroup: PipelineBuilderTaskGroup;
onTaskSelection: SelectTaskCallback;
onUpdateTasks: UpdateTasksCallback;
};

const PipelineBuilderFormEditor: React.FC<PipelineBuilderFormEditorProps> = (props) => {
const { namespace, hasExistingPipeline, taskGroup, onTaskSelection, onUpdateTasks } = props;
const { status } = useFormikContext<PipelineBuilderFormikValues>();

return (
<>
<div className="odc-pipeline-builder-form__short-section">
<InputField
label="Name"
name="formData.name"
type={TextInputTypes.text}
isDisabled={hasExistingPipeline}
required
/>
</div>

<div>
<h2>Tasks</h2>
<PipelineBuilderVisualization
namespace={namespace}
tasksInError={status?.tasks || {}}
onTaskSelection={onTaskSelection}
onUpdateTasks={onUpdateTasks}
taskGroup={taskGroup}
/>
</div>

<div>
<h2>Parameters</h2>
<PipelineParameters addLabel="Add Parameters" fieldName="formData.params" />
</div>

<div>
<h2>Resources</h2>
<PipelineResources addLabel="Add Resources" fieldName="formData.resources" />
</div>
</>
);
};

export default PipelineBuilderFormEditor;
Expand Up @@ -6,8 +6,4 @@
&__title {
margin: var(--pf-global--spacer--xs) 0 0 0;
}

hr {
margin: 0;
}
}

0 comments on commit 9dbdf84

Please sign in to comment.