Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ingest pipelines] Test pipeline enhancements #74964

Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const getFormActions = (testBed: TestBed) => {
find('submitButton').simulate('click');
};

const clickTestPipelineButton = () => {
find('testPipelineButton').simulate('click');
const clickAddDocumentsButton = () => {
find('addDocumentsButton').simulate('click');
};

const clickShowRequestLink = () => {
Expand All @@ -34,11 +34,12 @@ export const getFormActions = (testBed: TestBed) => {
clickShowRequestLink,
toggleVersionSwitch,
toggleOnFailureSwitch,
clickTestPipelineButton,
clickAddDocumentsButton,
};
};

export type PipelineFormTestSubjects =
| 'addDocumentsButton'
| 'submitButton'
| 'pageTitle'
| 'savePipelineError'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ describe('<PipelinesCreate />', () => {
const { actions, exists, find, waitFor } = testBed;

await act(async () => {
actions.clickTestPipelineButton();
actions.clickAddDocumentsButton();
await waitFor('testPipelineFlyout');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from '@elastic/eui';
import { EuiLink, EuiText, EuiTitle } from '@elastic/eui';
import React, { FunctionComponent } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
Expand All @@ -12,47 +12,41 @@ import { useKibana } from '../../../shared_imports';

export const OnFailureProcessorsTitle: FunctionComponent = () => {
const { services } = useKibana();

return (
<EuiFlexGroup
alignItems="center"
gutterSize="none"
justifyContent="spaceBetween"
responsive={false}
>
<EuiFlexItem>
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.ingestPipelines.pipelineEditor.onFailureTreeTitle"
defaultMessage="Failure processors"
/>
</h3>
</EuiTitle>
<EuiText size="s" color="subdued">
<div className="pipelineProcessorsEditor__onFailureTitle">
<EuiTitle size="xs">
<h4>
<FormattedMessage
id="xpack.ingestPipelines.pipelineEditor.onFailureTreeDescription"
defaultMessage="The processors used to handle exceptions in this pipeline. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={
services.documentation.getEsDocsBasePath() +
'/handling-failure-in-pipelines.html'
}
target="_blank"
>
{i18n.translate(
'xpack.ingestPipelines.pipelineEditor.onFailureProcessorsDocumentationLink',
{
defaultMessage: 'Learn more.',
}
)}
</EuiLink>
),
}}
id="xpack.ingestPipelines.pipelineEditor.onFailureTreeTitle"
defaultMessage="Failure processors"
/>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</h4>
</EuiTitle>
<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.ingestPipelines.pipelineEditor.onFailureTreeDescription"
defaultMessage="The processors used to handle exceptions in this pipeline. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={
services.documentation.getEsDocsBasePath() + '/handling-failure-in-pipelines.html'
}
target="_blank"
external
>
{i18n.translate(
'xpack.ingestPipelines.pipelineEditor.onFailureProcessorsDocumentationLink',
{
defaultMessage: 'Learn more.',
}
)}
</EuiLink>
),
}}
/>
</EuiText>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
.pipelineProcessorsEditor {
margin-bottom: $euiSizeXL;

&__container {
background-color: $euiColorLightestShade;
}

&__onFailureTitle {
padding-left: $euiSizeS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,13 @@ export const PipelineFormFields: React.FunctionComponent<Props> = ({
<EuiFlexItem grow={false}>
<ProcessorsHeader onLoadJson={onLoadJson} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexItem grow={false} className="pipelineProcessorsEditor__container">
<ProcessorsEditor />
</EuiFlexItem>
<EuiFlexItem>

<EuiSpacer size="s" />
</EuiFlexItem>
<EuiFlexItem grow={false}>

<OnFailureProcessorsTitle />
</EuiFlexItem>
<EuiFlexItem grow={false}>

<GlobalOnFailureProcessorsEditor />
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,146 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FunctionComponent } from 'react';
import React, { FunctionComponent, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';

import { useKibana } from '../../../shared_imports';

import {
usePipelineProcessorsContext,
useTestPipelineContext,
} from '../pipeline_processors_editor/context';

import {
LoadFromJsonButton,
OnDoneLoadJsonHandler,
TestPipelineButton,
TestOutputButton,
DocumentsDropdown,
AddDocumentsButton,
TestPipelineFlyout,
TestPipelineFlyoutTab,
} from '../pipeline_processors_editor';

export interface Props {
onLoadJson: OnDoneLoadJsonHandler;
}

export const ProcessorsHeader: FunctionComponent<Props> = ({ onLoadJson }) => {
const {
state: { processors },
} = usePipelineProcessorsContext();
const { testPipelineData, setCurrentTestPipelineData } = useTestPipelineContext();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the TestPipelineContext is available to processors_header.tsx but I think it might provide a slightly better decoupling between processors_header and pipeline_processors_editor:

  1. Update the pipeline_processors_editor to just export <ManageDocumentsButton /> component (I made this up but it would wrap DocumentsDropdown and AddDocumentsButton ) which contains the logic for showing/hiding the flyout
  2. Only call useTestPipelineContext from within new 👆🏻 button component
  3. Drive the state updates to test pipeline context from within pipeline_processors_editor (call to setCurrentTestPipelineData).
  4. Remove DocumentsDropdown, AddDocumentsButton, TestPipelineFlyout and TestPipelineFlyoutTab from pipeline processors exports.

Not major, but I believe this would be cleaner. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point. I agree; I think this would be cleaner. I think I may have started in this direction, but can't remember now why I pivoted 🤔 . I'll look into refactoring this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up creating a component called TestPipelineActions that renders the add documents button/documents dropdown and the output button. The pipeline processor editor exports this as well as the DocumentsDropdown, since the dropdown is also reused in the output tab of each processor. Let me know what you think!

const { services } = useKibana();

const {
testOutputPerProcessor,
config: { documents, selectedDocumentIndex },
} = testPipelineData;

const [openTestPipelineFlyout, setOpenTestPipelineFlyout] = useState(false);
const [activeFlyoutTab, setActiveFlyoutTab] = useState<TestPipelineFlyoutTab>('documents');

const updateSelectedDocument = (index: number) => {
setCurrentTestPipelineData({
type: 'updateActiveDocument',
payload: {
config: {
selectedDocumentIndex: index,
},
},
});
};

return (
<EuiFlexGroup
alignItems="center"
gutterSize="s"
justifyContent="spaceBetween"
responsive={false}
>
<EuiFlexItem>
<EuiTitle size="s">
<h3>
{i18n.translate('xpack.ingestPipelines.pipelineEditor.processorsTreeTitle', {
defaultMessage: 'Processors',
})}
</h3>
</EuiTitle>
<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.ingestPipelines.pipelineEditor.processorsTreeDescription"
defaultMessage="The processors used to pre-process documents before indexing. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={services.documentation.getEsDocsBasePath() + '/ingest-processors.html'}
target="_blank"
>
{i18n.translate(
'xpack.ingestPipelines.pipelineEditor.processorsDocumentationLink',
{
defaultMessage: 'Learn more.',
}
)}
</EuiLink>
),
}}
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<LoadFromJsonButton onDone={onLoadJson} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<TestPipelineButton />
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiFlexGroup
alignItems="center"
gutterSize="s"
justifyContent="spaceBetween"
responsive={false}
>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<h3>
{i18n.translate('xpack.ingestPipelines.pipelineEditor.processorsTreeTitle', {
defaultMessage: 'Processors',
})}
</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<LoadFromJsonButton onDone={onLoadJson} />
</EuiFlexItem>
</EuiFlexGroup>

<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.ingestPipelines.pipelineEditor.processorsTreeDescription"
defaultMessage="The processors used to pre-process documents before indexing. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={services.documentation.getEsDocsBasePath() + '/ingest-processors.html'}
target="_blank"
external
>
{i18n.translate(
'xpack.ingestPipelines.pipelineEditor.processorsDocumentationLink',
{
defaultMessage: 'Learn more.',
}
)}
</EuiLink>
),
}}
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
{documents ? (
<DocumentsDropdown
documents={documents}
selectedDocumentIndex={selectedDocumentIndex}
updateSelectedDocument={updateSelectedDocument}
/>
) : (
<AddDocumentsButton
openTestPipelineFlyout={() => {
setOpenTestPipelineFlyout(true);
setActiveFlyoutTab('documents');
}}
/>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<TestOutputButton
isDisabled={Boolean(testOutputPerProcessor) === false}
openTestPipelineFlyout={() => {
setOpenTestPipelineFlyout(true);
setActiveFlyoutTab('output');
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>

{openTestPipelineFlyout && (
<TestPipelineFlyout
activeTab={activeFlyoutTab}
processors={{
processors: processors.state.processors,
onFailure: processors.state.onFailure,
}}
onClose={() => setOpenTestPipelineFlyout(false)}
/>
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,27 @@
*/
import { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiButton } from '@elastic/eui';

import { FlyoutProvider } from './flyout_provider';
import { EuiButtonEmpty } from '@elastic/eui';

const i18nTexts = {
buttonLabel: i18n.translate('xpack.ingestPipelines.pipelineEditor.testPipeline.buttonLabel', {
defaultMessage: 'Test pipeline',
defaultMessage: 'Add documents',
}),
};

export const TestPipelineButton: FunctionComponent = () => {
interface Props {
openTestPipelineFlyout: () => void;
}

export const AddDocumentsButton: FunctionComponent<Props> = ({ openTestPipelineFlyout }) => {
return (
<FlyoutProvider>
{(openFlyout) => {
return (
<EuiButton size="s" onClick={openFlyout} data-test-subj="testPipelineButton">
{i18nTexts.buttonLabel}
</EuiButton>
);
}}
</FlyoutProvider>
<EuiButtonEmpty
size="s"
onClick={openTestPipelineFlyout}
data-test-subj="addDocumentsButton"
iconType="plusInCircleFilled"
>
{i18nTexts.buttonLabel}
</EuiButtonEmpty>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.documentsDropdown__selectContainer {
max-width: 200px;
}
Loading