Skip to content

Commit 169d06c

Browse files
[Ingest Pipelines] Load from json (#70297) (#70751)
* WiP load from json modal ready, need to refactor more stuff * First iteration of load from JSON functionality - refactored the pipeline processsors editor components for portability - added CIT for load from json component * added comment * update deserialize with tests and make it more fault tolerant * use flyout footer * remove console.error and make the json editor a lot shorter * address PR feedback - Update form schema and form schema types - simplify the save handler - refactor processors_title to processors_header * remove unused translations Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 829d378 commit 169d06c

37 files changed

+931
-594
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import React, { FunctionComponent } from 'react';
88
import { i18n } from '@kbn/i18n';
99
import { FormattedMessage } from '@kbn/i18n/react';
1010

11-
import { usePipelineProcessorsContext } from '../context';
11+
import { usePipelineProcessorsContext } from '../pipeline_processors_editor/context';
1212

1313
export const OnFailureProcessorsTitle: FunctionComponent = () => {
1414
const { links } = usePipelineProcessorsContext();

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@ import { FormattedMessage } from '@kbn/i18n/react';
99
import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
1010

1111
import { useForm, Form, FormConfig } from '../../../shared_imports';
12-
import { Pipeline } from '../../../../common/types';
12+
import { Pipeline, Processor } from '../../../../common/types';
1313

14-
import {
15-
OnUpdateHandlerArg,
16-
OnUpdateHandler,
17-
SerializeResult,
18-
} from '../pipeline_processors_editor';
14+
import './pipeline_form.scss';
15+
16+
import { OnUpdateHandlerArg, OnUpdateHandler } from '../pipeline_processors_editor';
1917

2018
import { PipelineRequestFlyout } from './pipeline_request_flyout';
2119
import { PipelineTestFlyout } from './pipeline_test_flyout';
2220
import { PipelineFormFields } from './pipeline_form_fields';
2321
import { PipelineFormError } from './pipeline_form_error';
2422
import { pipelineFormSchema } from './schema';
23+
import { PipelineForm as IPipelineForm } from './types';
2524

2625
export interface PipelineFormProps {
2726
onSave: (pipeline: Pipeline) => void;
@@ -32,14 +31,15 @@ export interface PipelineFormProps {
3231
isEditing?: boolean;
3332
}
3433

34+
const defaultFormValue: Pipeline = Object.freeze({
35+
name: '',
36+
description: '',
37+
processors: [],
38+
on_failure: [],
39+
});
40+
3541
export const PipelineForm: React.FunctionComponent<PipelineFormProps> = ({
36-
defaultValue = {
37-
name: '',
38-
description: '',
39-
processors: [],
40-
on_failure: [],
41-
version: '',
42-
},
42+
defaultValue = defaultFormValue,
4343
onSave,
4444
isSaving,
4545
saveError,
@@ -50,34 +50,42 @@ export const PipelineForm: React.FunctionComponent<PipelineFormProps> = ({
5050

5151
const [isTestingPipeline, setIsTestingPipeline] = useState<boolean>(false);
5252

53-
const processorStateRef = useRef<OnUpdateHandlerArg>();
53+
const {
54+
processors: initialProcessors,
55+
on_failure: initialOnFailureProcessors,
56+
...defaultFormValues
57+
} = defaultValue;
58+
59+
const [processorsState, setProcessorsState] = useState<{
60+
processors: Processor[];
61+
onFailure?: Processor[];
62+
}>({
63+
processors: initialProcessors,
64+
onFailure: initialOnFailureProcessors,
65+
});
5466

55-
const handleSave: FormConfig['onSubmit'] = async (formData, isValid) => {
56-
let override: SerializeResult | undefined;
67+
const processorStateRef = useRef<OnUpdateHandlerArg>();
5768

69+
const handleSave: FormConfig<IPipelineForm>['onSubmit'] = async (formData, isValid) => {
5870
if (!isValid) {
5971
return;
6072
}
6173

6274
if (processorStateRef.current) {
63-
const processorsState = processorStateRef.current;
64-
if (await processorsState.validate()) {
65-
override = processorsState.getData();
66-
} else {
67-
return;
75+
const state = processorStateRef.current;
76+
if (await state.validate()) {
77+
onSave({ ...formData, ...state.getData() });
6878
}
6979
}
70-
71-
onSave({ ...formData, ...(override || {}) } as Pipeline);
7280
};
7381

7482
const handleTestPipelineClick = () => {
7583
setIsTestingPipeline(true);
7684
};
7785

78-
const { form } = useForm({
86+
const { form } = useForm<IPipelineForm>({
7987
schema: pipelineFormSchema,
80-
defaultValue,
88+
defaultValue: defaultFormValues,
8189
onSubmit: handleSave,
8290
});
8391

@@ -121,9 +129,12 @@ export const PipelineForm: React.FunctionComponent<PipelineFormProps> = ({
121129

122130
{/* All form fields */}
123131
<PipelineFormFields
132+
onLoadJson={({ processors, on_failure: onFailure }) => {
133+
setProcessorsState({ processors, onFailure });
134+
}}
124135
onEditorFlyoutOpen={onEditorFlyoutOpen}
125-
initialProcessors={defaultValue.processors}
126-
initialOnFailureProcessors={defaultValue.on_failure}
136+
processors={processorsState.processors}
137+
onFailure={processorsState.onFailure}
127138
onProcessorsUpdate={onProcessorsChangeHandler}
128139
hasVersion={Boolean(defaultValue.version)}
129140
isTestButtonDisabled={isTestingPipeline || form.isValid === false}

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,27 @@
66

77
import React, { useState } from 'react';
88
import { FormattedMessage } from '@kbn/i18n/react';
9-
import { EuiSpacer, EuiSwitch } from '@elastic/eui';
9+
import { EuiSpacer, EuiSwitch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
1010

1111
import { Processor } from '../../../../common/types';
12-
import { FormDataProvider } from '../../../shared_imports';
13-
import { PipelineProcessorsEditor, OnUpdateHandler } from '../pipeline_processors_editor';
1412

1513
import { getUseField, getFormRow, Field, useKibana } from '../../../shared_imports';
1614

15+
import {
16+
PipelineProcessorsContextProvider,
17+
GlobalOnFailureProcessorsEditor,
18+
ProcessorsEditor,
19+
OnUpdateHandler,
20+
OnDoneLoadJsonHandler,
21+
} from '../pipeline_processors_editor';
22+
23+
import { ProcessorsHeader } from './processors_header';
24+
import { OnFailureProcessorsTitle } from './on_failure_processors_title';
25+
1726
interface Props {
18-
initialProcessors: Processor[];
19-
initialOnFailureProcessors?: Processor[];
27+
processors: Processor[];
28+
onFailure?: Processor[];
29+
onLoadJson: OnDoneLoadJsonHandler;
2030
onProcessorsUpdate: OnUpdateHandler;
2131
hasVersion: boolean;
2232
isTestButtonDisabled: boolean;
@@ -29,8 +39,9 @@ const UseField = getUseField({ component: Field });
2939
const FormRow = getFormRow({ titleTag: 'h3' });
3040

3141
export const PipelineFormFields: React.FunctionComponent<Props> = ({
32-
initialProcessors,
33-
initialOnFailureProcessors,
42+
processors,
43+
onFailure,
44+
onLoadJson,
3445
onProcessorsUpdate,
3546
isEditing,
3647
hasVersion,
@@ -113,30 +124,37 @@ export const PipelineFormFields: React.FunctionComponent<Props> = ({
113124
</FormRow>
114125

115126
{/* Pipeline Processors Editor */}
116-
<FormDataProvider pathsToWatch={['processors', 'on_failure']}>
117-
{({ processors, on_failure: onFailure }) => {
118-
const processorProp =
119-
typeof processors === 'string' && processors
120-
? JSON.parse(processors)
121-
: initialProcessors ?? [];
122-
123-
const onFailureProp =
124-
typeof onFailure === 'string' && onFailure
125-
? JSON.parse(onFailure)
126-
: initialOnFailureProcessors ?? [];
127127

128-
return (
129-
<PipelineProcessorsEditor
130-
onFlyoutOpen={onEditorFlyoutOpen}
131-
esDocsBasePath={services.documentation.getEsDocsBasePath()}
132-
isTestButtonDisabled={isTestButtonDisabled}
133-
onTestPipelineClick={onTestPipelineClick}
134-
onUpdate={onProcessorsUpdate}
135-
value={{ processors: processorProp, onFailure: onFailureProp }}
136-
/>
137-
);
138-
}}
139-
</FormDataProvider>
128+
<PipelineProcessorsContextProvider
129+
onFlyoutOpen={onEditorFlyoutOpen}
130+
links={{ esDocsBasePath: services.documentation.getEsDocsBasePath() }}
131+
onUpdate={onProcessorsUpdate}
132+
value={{ processors, onFailure }}
133+
>
134+
<div className="pipelineProcessorsEditor">
135+
<EuiFlexGroup gutterSize="m" responsive={false} direction="column">
136+
<EuiFlexItem grow={false}>
137+
<ProcessorsHeader
138+
onLoadJson={onLoadJson}
139+
onTestPipelineClick={onTestPipelineClick}
140+
isTestButtonDisabled={isTestButtonDisabled}
141+
/>
142+
</EuiFlexItem>
143+
<EuiFlexItem grow={false}>
144+
<ProcessorsEditor />
145+
</EuiFlexItem>
146+
<EuiFlexItem>
147+
<EuiSpacer size="s" />
148+
</EuiFlexItem>
149+
<EuiFlexItem grow={false}>
150+
<OnFailureProcessorsTitle />
151+
</EuiFlexItem>
152+
<EuiFlexItem grow={false}>
153+
<GlobalOnFailureProcessorsEditor />
154+
</EuiFlexItem>
155+
</EuiFlexGroup>
156+
</div>
157+
</PipelineProcessorsContextProvider>
140158
</>
141159
);
142160
};
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from
99
import { i18n } from '@kbn/i18n';
1010
import { FormattedMessage } from '@kbn/i18n/react';
1111

12-
import { usePipelineProcessorsContext } from '../context';
12+
import { usePipelineProcessorsContext } from '../pipeline_processors_editor/context';
13+
14+
import { LoadFromJsonButton, OnDoneLoadJsonHandler } from '../pipeline_processors_editor';
1315

1416
export interface Props {
1517
onTestPipelineClick: () => void;
1618
isTestButtonDisabled: boolean;
19+
onLoadJson: OnDoneLoadJsonHandler;
1720
}
1821

19-
export const ProcessorsTitleAndTestButton: FunctionComponent<Props> = ({
22+
export const ProcessorsHeader: FunctionComponent<Props> = ({
2023
onTestPipelineClick,
2124
isTestButtonDisabled,
25+
onLoadJson,
2226
}) => {
2327
const { links } = usePipelineProcessorsContext();
2428
return (
2529
<EuiFlexGroup
2630
alignItems="center"
27-
gutterSize="none"
31+
gutterSize="s"
2832
justifyContent="spaceBetween"
2933
responsive={false}
3034
>
@@ -55,6 +59,9 @@ export const ProcessorsTitleAndTestButton: FunctionComponent<Props> = ({
5559
/>
5660
</EuiText>
5761
</EuiFlexItem>
62+
<EuiFlexItem grow={false}>
63+
<LoadFromJsonButton onDone={onLoadJson} />
64+
</EuiFlexItem>
5865
<EuiFlexItem grow={false}>
5966
<EuiButton
6067
data-test-subj="testPipelineButton"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { i18n } from '@kbn/i18n';
8+
import { FormSchema, FIELD_TYPES, fieldValidators, fieldFormatters } from '../../../shared_imports';
9+
10+
import { PipelineForm } from './types';
11+
12+
const { emptyField } = fieldValidators;
13+
const { toInt } = fieldFormatters;
14+
15+
export const pipelineFormSchema: FormSchema<PipelineForm> = {
16+
name: {
17+
type: FIELD_TYPES.TEXT,
18+
label: i18n.translate('xpack.ingestPipelines.form.nameFieldLabel', {
19+
defaultMessage: 'Name',
20+
}),
21+
validations: [
22+
{
23+
validator: emptyField(
24+
i18n.translate('xpack.ingestPipelines.form.pipelineNameRequiredError', {
25+
defaultMessage: 'Name is required.',
26+
})
27+
),
28+
},
29+
],
30+
},
31+
description: {
32+
type: FIELD_TYPES.TEXTAREA,
33+
label: i18n.translate('xpack.ingestPipelines.form.descriptionFieldLabel', {
34+
defaultMessage: 'Description (optional)',
35+
}),
36+
},
37+
version: {
38+
type: FIELD_TYPES.NUMBER,
39+
label: i18n.translate('xpack.ingestPipelines.form.versionFieldLabel', {
40+
defaultMessage: 'Version (optional)',
41+
}),
42+
formatters: [toInt],
43+
},
44+
};

0 commit comments

Comments
 (0)