[Ingest Pipelines] Fix description field bug (#79445)
* rendering optimisation of text fields * fix description disappearing bug * refactor fix to get value from form serializer
This commit is contained in:
parent
c7caac61a2
commit
e98e2796d5
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import classNames from 'classnames';
|
||||
import React, { FunctionComponent, useState, useEffect, useCallback } from 'react';
|
||||
import React, { useState, useEffect, useCallback, memo } from 'react';
|
||||
import { EuiFieldText, EuiText, keys } from '@elastic/eui';
|
||||
|
||||
export interface Props {
|
||||
|
@ -23,15 +23,15 @@ export interface Props {
|
|||
text?: string;
|
||||
}
|
||||
|
||||
export const InlineTextInput: FunctionComponent<Props> = ({
|
||||
function _InlineTextInput({
|
||||
placeholder,
|
||||
text,
|
||||
ariaLabel,
|
||||
disabled = false,
|
||||
onChange,
|
||||
}) => {
|
||||
}: Props): React.ReactElement<any, any> | null {
|
||||
const [isShowingTextInput, setIsShowingTextInput] = useState<boolean>(false);
|
||||
const [textValue, setTextValue] = useState<string>(text ?? '');
|
||||
const [textValue, setTextValue] = useState<string>(() => text ?? '');
|
||||
|
||||
const containerClasses = classNames('pipelineProcessorsEditor__item__textContainer', {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
|
@ -47,6 +47,10 @@ export const InlineTextInput: FunctionComponent<Props> = ({
|
|||
});
|
||||
}, [setIsShowingTextInput, onChange, textValue]);
|
||||
|
||||
useEffect(() => {
|
||||
setTextValue(text ?? '');
|
||||
}, [text]);
|
||||
|
||||
useEffect(() => {
|
||||
const keyboardListener = (event: KeyboardEvent) => {
|
||||
if (event.key === keys.ESCAPE || event.code === 'Escape') {
|
||||
|
@ -91,4 +95,6 @@ export const InlineTextInput: FunctionComponent<Props> = ({
|
|||
</EuiText>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const InlineTextInput = memo(_InlineTextInput);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, { FunctionComponent, memo } from 'react';
|
||||
import React, { FunctionComponent, memo, useCallback } from 'react';
|
||||
import {
|
||||
EuiButtonToggle,
|
||||
EuiFlexGroup,
|
||||
|
@ -89,6 +89,32 @@ export const PipelineProcessorsEditorItem: FunctionComponent<Props> = memo(
|
|||
'pipelineProcessorsEditor__item--displayNone': isInMoveMode && !processor.options.description,
|
||||
});
|
||||
|
||||
const onDescriptionChange = useCallback(
|
||||
(nextDescription) => {
|
||||
let nextOptions: Record<string, any>;
|
||||
if (!nextDescription) {
|
||||
const { description: _description, ...restOptions } = processor.options;
|
||||
nextOptions = restOptions;
|
||||
} else {
|
||||
nextOptions = {
|
||||
...processor.options,
|
||||
description: nextDescription,
|
||||
};
|
||||
}
|
||||
processorsDispatch({
|
||||
type: 'updateProcessor',
|
||||
payload: {
|
||||
processor: {
|
||||
...processor,
|
||||
options: nextOptions,
|
||||
},
|
||||
selector,
|
||||
},
|
||||
});
|
||||
},
|
||||
[processor, processorsDispatch, selector]
|
||||
);
|
||||
|
||||
const renderMoveButton = () => {
|
||||
const label = !isMovingThisProcessor
|
||||
? i18nTexts.moveButtonLabel
|
||||
|
@ -176,28 +202,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent<Props> = memo(
|
|||
<EuiFlexItem className={inlineTextInputContainerClasses} grow={false}>
|
||||
<InlineTextInput
|
||||
disabled={isEditorNotInIdleMode}
|
||||
onChange={(nextDescription) => {
|
||||
let nextOptions: Record<string, any>;
|
||||
if (!nextDescription) {
|
||||
const { description: _description, ...restOptions } = processor.options;
|
||||
nextOptions = restOptions;
|
||||
} else {
|
||||
nextOptions = {
|
||||
...processor.options,
|
||||
description: nextDescription,
|
||||
};
|
||||
}
|
||||
processorsDispatch({
|
||||
type: 'updateProcessor',
|
||||
payload: {
|
||||
processor: {
|
||||
...processor,
|
||||
options: nextOptions,
|
||||
},
|
||||
selector,
|
||||
},
|
||||
});
|
||||
}}
|
||||
onChange={onDescriptionChange}
|
||||
ariaLabel={i18nTexts.processorTypeLabel({ type: processor.type })}
|
||||
text={description}
|
||||
placeholder={i18nTexts.descriptionPlaceholder}
|
||||
|
|
|
@ -24,10 +24,8 @@ import { getProcessorDescriptor } from '../shared';
|
|||
|
||||
import { DocumentationButton } from './documentation_button';
|
||||
import { ProcessorSettingsFields } from './processor_settings_fields';
|
||||
import { Fields } from './processor_form.container';
|
||||
|
||||
interface Fields {
|
||||
fields: { [key: string]: any };
|
||||
}
|
||||
export interface Props {
|
||||
isOnFailure: boolean;
|
||||
form: FormHook<Fields>;
|
||||
|
|
|
@ -19,6 +19,7 @@ export type OnSubmitHandler = (processor: ProcessorFormOnSubmitArg) => void;
|
|||
export type OnFormUpdateHandler = (form: OnFormUpdateArg<any>) => void;
|
||||
|
||||
export interface Fields {
|
||||
type: string;
|
||||
fields: { [key: string]: any };
|
||||
}
|
||||
|
||||
|
@ -57,8 +58,28 @@ export const ProcessorFormContainer: FunctionComponent<Props> = ({
|
|||
return { ...processor, options } as ProcessorInternal;
|
||||
}, [processor, unsavedFormState]);
|
||||
|
||||
const formSerializer = useCallback(
|
||||
(formState) => {
|
||||
return {
|
||||
type: formState.type,
|
||||
fields: formState.customOptions
|
||||
? {
|
||||
...formState.customOptions,
|
||||
}
|
||||
: {
|
||||
...formState.fields,
|
||||
// The description field is not editable in processor forms currently. We re-add it here or it will be
|
||||
// stripped.
|
||||
description: processor ? processor.options.description : undefined,
|
||||
},
|
||||
};
|
||||
},
|
||||
[processor]
|
||||
);
|
||||
|
||||
const { form } = useForm({
|
||||
defaultValue: { fields: getProcessor().options },
|
||||
serializer: formSerializer,
|
||||
});
|
||||
const { subscribe } = form;
|
||||
|
||||
|
@ -67,8 +88,7 @@ export const ProcessorFormContainer: FunctionComponent<Props> = ({
|
|||
const { isValid, data } = await form.submit();
|
||||
|
||||
if (isValid) {
|
||||
const { type, customOptions, fields } = data as FormData;
|
||||
const options = customOptions ? customOptions : fields;
|
||||
const { type, fields: options } = data as FormData;
|
||||
|
||||
unsavedFormState.current = options;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent, MutableRefObject, useEffect } from 'react';
|
||||
import React, { FunctionComponent, MutableRefObject, useEffect, useMemo } from 'react';
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import { AutoSizer, List, WindowScroller } from 'react-virtualized';
|
||||
|
||||
|
@ -65,6 +65,10 @@ export const PrivateTree: FunctionComponent<PrivateProps> = ({
|
|||
windowScrollerRef,
|
||||
listRef,
|
||||
}) => {
|
||||
const selectors: string[][] = useMemo(() => {
|
||||
return processors.map((_, idx) => selector.concat(String(idx)));
|
||||
}, [processors, selector]);
|
||||
|
||||
const renderRow = ({
|
||||
idx,
|
||||
info,
|
||||
|
@ -163,7 +167,7 @@ export const PrivateTree: FunctionComponent<PrivateProps> = ({
|
|||
const below = processors[idx + 1];
|
||||
const info: ProcessorInfo = {
|
||||
id: processor.id,
|
||||
selector: selector.concat(String(idx)),
|
||||
selector: selectors[idx],
|
||||
aboveId: above?.id,
|
||||
belowId: below?.id,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue