Skip to content

Commit

Permalink
Merge branch 'feature/pipeline-editor' into pipeline-editor/custom-pr…
Browse files Browse the repository at this point in the history
…ocessor
  • Loading branch information
elasticmachine authored May 13, 2020
2 parents 5314442 + 0f477f3 commit f2a746d
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 205 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { registerTestBed } from '../../../../../../../test_utils';
import { PipelineProcessorsEditor, Props } from '../pipeline_processors_editor';
import { PipelineProcessorsEditor, Props } from '../pipeline_processors_editor.container';

const testBedSetup = registerTestBed<TestSubject>(PipelineProcessorsEditor, {
doMountAsync: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,17 @@ export const DragAndDropTreeUI: FunctionComponent<Props> = ({
_processors.forEach((processor, idx) => {
const index = flatTreeIndex++;
const nodeSelector = _selector.concat(String(idx));
const id = [treeId].concat(nodeSelector).join('.');
_items.push([
nodeSelector,
<TreeNode
key={index}
index={index}
level={level}
processor={processor}
selector={nodeSelector}
id={id}
selector={baseSelector.concat(nodeSelector)}
component={renderItem}
treeId={treeId}
/>,
]);

Expand All @@ -88,7 +89,7 @@ export const DragAndDropTreeUI: FunctionComponent<Props> = ({

addRenderedItems(processors, [], 0);
return _items;
}, [processors, renderItem, currentDragSelector]);
}, [processors, renderItem, currentDragSelector, baseSelector]);

const treeId = `${readTreeId()}_PIPELINE_PROCESSORS_EDITOR`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { DragAndDropTreeProvider } from './drag_and_drop_tree_provider';
export { DragAndDropTreeProvider, OnDragEndArgs } from './drag_and_drop_tree_provider';
export { DragAndDropTree, RenderTreeItemFunction } from './drag_and_drop_tree';
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@ export interface TreeNodeComponentArgs {

interface Props {
component: (args: TreeNodeComponentArgs) => React.ReactNode;
id: string;
selector: ProcessorSelector;
processor: ProcessorInternal;
treeId: string;
index: number;
level: number;
}

export const TreeNode: FunctionComponent<Props> = ({
processor,
id,
selector,
index,
component,
level,
treeId,
}) => {
const id = [treeId].concat(selector).join('.');
return (
<EuiDraggable spacing="l" draggableId={id} key={id} index={index} customDragHandle>
{provided => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export {
DragAndDropTree,
DragAndDropTreeProvider,
RenderTreeItemFunction,
OnDragEndArgs,
} from './drag_and_drop_tree';

export { PipelineProcessorEditorItem } from './pipeline_processor_editor_item';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export {
PipelineProcessorsEditor,
OnUpdateHandlerArg,
OnUpdateHandler,
} from './pipeline_processors_editor';
} from './pipeline_processors_editor.container';
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, {
FunctionComponent,
useCallback,
useEffect,
useMemo,
useState,
Dispatch,
} from 'react';

import { Processor } from '../../../../common/types';
import { OnFormUpdateArg } from '../../../shared_imports';

import { deserialize } from './serialize';
import { ProcessorInternal, ProcessorSelector } from './types';
import { useProcessorsState } from './processors_reducer';
import { serialize, SerializeResult } from './deserialize';
import { ProcessorRemoveModal, SettingsFormFlyout } from './components';
import { getValue } from './utils';

import { PipelineProcessorsEditor as PipelineProcessorsEditorUI } from './pipeline_processors_editor';

export interface Props {
value: {
processors: Processor[];
onFailure?: Processor[];
};
onUpdate: (arg: OnUpdateHandlerArg) => void;
isTestButtonDisabled: boolean;
onTestPipelineClick: () => void;
learnMoreAboutProcessorsUrl: string;
learnMoreAboutOnFailureProcessorsUrl: string;
}

/**
* The settings form can be in different modes. This enables us to hold
* a reference to data dispatch to * the reducer (like the {@link ProcessorSelector}
* which will be used to update the in-memory processors data structure.
*/
type SettingsFormMode =
| { id: 'creatingTopLevelProcessor'; arg: ProcessorSelector }
| { id: 'creatingOnFailureProcessor'; arg: ProcessorSelector }
| { id: 'editingProcessor'; arg: { processor: ProcessorInternal; selector: ProcessorSelector } }
| { id: 'closed' };

export type SetSettingsFormMode = Dispatch<SettingsFormMode>;

interface FormValidityState {
validate: OnFormUpdateArg<any>['validate'];
}

export interface OnUpdateHandlerArg extends FormValidityState {
getData: () => SerializeResult;
}

export type OnUpdateHandler = (arg: OnUpdateHandlerArg) => void;

export const PipelineProcessorsEditor: FunctionComponent<Props> = ({
value: { processors: originalProcessors, onFailure: originalOnFailureProcessors },
onUpdate,
isTestButtonDisabled,
learnMoreAboutOnFailureProcessorsUrl,
learnMoreAboutProcessorsUrl,
onTestPipelineClick,
}) => {
const deserializedResult = useMemo(
() => deserialize({ processors: originalProcessors, onFailure: originalOnFailureProcessors }),
[originalProcessors, originalOnFailureProcessors]
);

const [processorToDeleteSelector, setProcessorToDeleteSelector] = useState<
ProcessorSelector | undefined
>();

const [settingsFormMode, setSettingsFormMode] = useState<SettingsFormMode>({ id: 'closed' });
const [processorsState, processorsDispatch] = useProcessorsState(deserializedResult);
const { processors, onFailure } = processorsState;

const [formState, setFormState] = useState<FormValidityState>({
validate: () => Promise.resolve(true),
});

const onFormUpdate = useCallback(
arg => {
setFormState({ validate: arg.validate });
},
[setFormState]
);

useEffect(() => {
onUpdate({
validate: async () => {
const formValid = await formState.validate();
return formValid && settingsFormMode.id === 'closed';
},
getData: () => serialize(processorsState),
});
}, [processorsState, onUpdate, formState, settingsFormMode]);

const onSubmit = useCallback(
processorTypeAndOptions => {
switch (settingsFormMode.id) {
case 'creatingTopLevelProcessor':
processorsDispatch({
type: 'addTopLevelProcessor',
payload: { processor: processorTypeAndOptions, selector: settingsFormMode.arg },
});
break;
case 'creatingOnFailureProcessor':
processorsDispatch({
type: 'addOnFailureProcessor',
payload: {
onFailureProcessor: processorTypeAndOptions,
targetSelector: settingsFormMode.arg,
},
});
break;
case 'editingProcessor':
processorsDispatch({
type: 'updateProcessor',
payload: {
processor: {
...settingsFormMode.arg.processor,
...processorTypeAndOptions,
},
selector: settingsFormMode.arg.selector,
},
});
break;
default:
}
dismissFlyout();
},
[processorsDispatch, settingsFormMode]
);

const onDragEnd = useCallback(
args => {
processorsDispatch({
type: 'moveProcessor',
payload: args,
});
},
[processorsDispatch]
);

const dismissFlyout = () => {
setSettingsFormMode({ id: 'closed' });
};

return (
<>
<PipelineProcessorsEditorUI
processors={processors}
onFailureProcessors={onFailure}
processorsDispatch={processorsDispatch}
setSettingsFormMode={setSettingsFormMode}
setProcessorToDeleteSelector={setProcessorToDeleteSelector}
isTestButtonDisabled={isTestButtonDisabled}
onTestPipelineClick={onTestPipelineClick}
learnMoreAboutProcessorsUrl={learnMoreAboutProcessorsUrl}
learnMoreAboutOnFailureProcessorsUrl={learnMoreAboutOnFailureProcessorsUrl}
onDragEnd={onDragEnd}
/>
{settingsFormMode.id !== 'closed' ? (
<SettingsFormFlyout
onFormUpdate={onFormUpdate}
onSubmit={onSubmit}
processor={
settingsFormMode.id === 'editingProcessor' ? settingsFormMode.arg.processor : undefined
}
onClose={() => {
dismissFlyout();
setFormState({ validate: () => Promise.resolve(true) });
}}
/>
) : (
undefined
)}
{processorToDeleteSelector && (
<ProcessorRemoveModal
processor={getValue(processorToDeleteSelector, processors)}
onResult={confirmed => {
if (confirmed) {
processorsDispatch({
type: 'removeProcessor',
payload: { selector: processorToDeleteSelector },
});
}
setProcessorToDeleteSelector(undefined);
}}
/>
)}
</>
);
};
Loading

0 comments on commit f2a746d

Please sign in to comment.