[Ingest Node Pipelines] Sentence-case processor names (#74645)
* wip on fixing processor names * added comment * fix Jest test element selector Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
ce6011e4d5
commit
92289b63ef
|
@ -89,7 +89,7 @@ const createActions = (testBed: TestBed<TestSubject>) => {
|
|||
async addProcessor(processorsSelector: string, type: string, options: Record<string, any>) {
|
||||
find(`${processorsSelector}.addProcessorButton`).simulate('click');
|
||||
await act(async () => {
|
||||
find('processorTypeSelector').simulate('change', [{ value: type, label: type }]);
|
||||
find('processorTypeSelector.input').simulate('change', [{ value: type, label: type }]);
|
||||
});
|
||||
component.update();
|
||||
await act(async () => {
|
||||
|
@ -129,7 +129,7 @@ const createActions = (testBed: TestBed<TestSubject>) => {
|
|||
find(`${processorSelector}.moreMenu.button`).simulate('click');
|
||||
find(`${processorSelector}.moreMenu.addOnFailureButton`).simulate('click');
|
||||
await act(async () => {
|
||||
find('processorTypeSelector').simulate('change', [{ value: type, label: type }]);
|
||||
find('processorTypeSelector.input').simulate('change', [{ value: type, label: type }]);
|
||||
});
|
||||
component.update();
|
||||
await act(async () => {
|
||||
|
|
|
@ -22,6 +22,8 @@ import { ProcessorsDispatch } from '../../processors_reducer';
|
|||
|
||||
import { ProcessorInfo } from '../processors_tree';
|
||||
|
||||
import { getProcessorDescriptor } from '../shared';
|
||||
|
||||
import './pipeline_processors_editor_item.scss';
|
||||
|
||||
import { InlineTextInput } from './inline_text_input';
|
||||
|
@ -139,7 +141,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent<Props> = memo(
|
|||
className="pipelineProcessorsEditor__item__processorTypeLabel"
|
||||
color={isDimmed ? 'subdued' : undefined}
|
||||
>
|
||||
<b>{processor.type}</b>
|
||||
<b>{getProcessorDescriptor(processor.type)?.label ?? processor.type}</b>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className={inlineTextInputContainerClasses} grow={false}>
|
||||
|
|
|
@ -23,8 +23,9 @@ import {
|
|||
import { Form, FormDataProvider, FormHook } from '../../../../../shared_imports';
|
||||
import { ProcessorInternal } from '../../types';
|
||||
|
||||
import { getProcessorDescriptor } from '../shared';
|
||||
|
||||
import { DocumentationButton } from './documentation_button';
|
||||
import { getProcessorFormDescriptor } from './map_processor_type_to_form';
|
||||
import { CommonProcessorFields, ProcessorTypeField } from './processors/common_fields';
|
||||
import { Custom } from './processors/custom';
|
||||
|
||||
|
@ -88,7 +89,7 @@ export const ProcessorSettingsForm: FunctionComponent<Props> = memo(
|
|||
<EuiFlexItem grow={false}>
|
||||
<FormDataProvider pathsToWatch="type">
|
||||
{({ type }) => {
|
||||
const formDescriptor = getProcessorFormDescriptor(type as any);
|
||||
const formDescriptor = getProcessorDescriptor(type as any);
|
||||
|
||||
if (formDescriptor) {
|
||||
return (
|
||||
|
@ -114,7 +115,7 @@ export const ProcessorSettingsForm: FunctionComponent<Props> = memo(
|
|||
const { type } = arg;
|
||||
|
||||
if (type?.length) {
|
||||
const formDescriptor = getProcessorFormDescriptor(type as any);
|
||||
const formDescriptor = getProcessorDescriptor(type as any);
|
||||
|
||||
if (formDescriptor?.FieldsComponent) {
|
||||
return (
|
||||
|
|
|
@ -3,16 +3,42 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { flow } from 'fp-ts/lib/function';
|
||||
import { map } from 'fp-ts/lib/Array';
|
||||
|
||||
import {
|
||||
FIELD_TYPES,
|
||||
FieldConfig,
|
||||
UseField,
|
||||
fieldValidators,
|
||||
ComboBoxField,
|
||||
} from '../../../../../../../shared_imports';
|
||||
import { types } from '../../map_processor_type_to_form';
|
||||
|
||||
import { getProcessorDescriptor, mapProcessorTypeToDescriptor } from '../../../shared';
|
||||
import {
|
||||
FieldValidateResponse,
|
||||
VALIDATION_TYPES,
|
||||
} from '../../../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
|
||||
|
||||
const extractProcessorTypesAndLabels = flow(
|
||||
Object.entries,
|
||||
map(([type, { label }]) => ({
|
||||
label,
|
||||
value: type,
|
||||
})),
|
||||
(arr) => arr.sort((a, b) => a.label.localeCompare(b.label))
|
||||
);
|
||||
|
||||
interface ProcessorTypeAndLabel {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const processorTypesAndLabels: ProcessorTypeAndLabel[] = extractProcessorTypesAndLabels(
|
||||
mapProcessorTypeToDescriptor
|
||||
);
|
||||
|
||||
interface Props {
|
||||
initialType?: string;
|
||||
|
@ -47,22 +73,76 @@ const typeConfig: FieldConfig = {
|
|||
|
||||
export const ProcessorTypeField: FunctionComponent<Props> = ({ initialType }) => {
|
||||
return (
|
||||
<UseField
|
||||
config={typeConfig}
|
||||
defaultValue={initialType}
|
||||
path="type"
|
||||
component={ComboBoxField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'processorTypeSelector',
|
||||
fullWidth: true,
|
||||
options: types.map((type) => ({ label: type, value: type })),
|
||||
noSuggestions: false,
|
||||
singleSelection: {
|
||||
asPlainText: true,
|
||||
},
|
||||
},
|
||||
<UseField config={typeConfig} defaultValue={initialType} path="type">
|
||||
{(typeField) => {
|
||||
let selectedOptions: ProcessorTypeAndLabel[];
|
||||
if ((typeField.value as string[]).length) {
|
||||
const [type] = typeField.value as string[];
|
||||
const descriptor = getProcessorDescriptor(type);
|
||||
selectedOptions = descriptor
|
||||
? [{ label: descriptor.label, value: type }]
|
||||
: // If there is no label for this processor type, just use the type as the label
|
||||
[{ label: type, value: type }];
|
||||
} else {
|
||||
selectedOptions = [];
|
||||
}
|
||||
|
||||
const error = typeField.getErrorsMessages();
|
||||
const isInvalid = error ? Boolean(error.length) : false;
|
||||
|
||||
const onCreateComboOption = (value: string) => {
|
||||
// Note: for now, all validations for a comboBox array item have to be synchronous
|
||||
// If there is a need to support asynchronous validation, we'll work on it (and will need to update the <EuiComboBox /> logic).
|
||||
const { isValid } = typeField.validate({
|
||||
value,
|
||||
validationType: VALIDATION_TYPES.ARRAY_ITEM,
|
||||
}) as FieldValidateResponse;
|
||||
|
||||
if (!isValid) {
|
||||
// Return false to explicitly reject the user's input.
|
||||
return false;
|
||||
}
|
||||
|
||||
const newValue = [...(typeField.value as string[]), value];
|
||||
|
||||
typeField.setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={typeField.label}
|
||||
labelAppend={typeField.labelAppend}
|
||||
helpText={
|
||||
typeof typeField.helpText === 'function' ? typeField.helpText() : typeField.helpText
|
||||
}
|
||||
error={error}
|
||||
isInvalid={isInvalid}
|
||||
fullWidth
|
||||
data-test-subj="processorTypeSelector"
|
||||
>
|
||||
<EuiComboBox
|
||||
fullWidth
|
||||
placeholder={i18n.translate(
|
||||
'xpack.ingestPipelines.pipelineEditor.typeField.typeFieldComboboxPlaceholder',
|
||||
{
|
||||
defaultMessage: 'Type and then hit "ENTER"',
|
||||
}
|
||||
)}
|
||||
options={processorTypesAndLabels}
|
||||
selectedOptions={selectedOptions}
|
||||
onCreateOption={onCreateComboOption}
|
||||
onChange={(options: EuiComboBoxOptionOption[]) => {
|
||||
typeField.setValue(options.map(({ value }) => value));
|
||||
}}
|
||||
noSuggestions={false}
|
||||
singleSelection={{
|
||||
asPlainText: true,
|
||||
}}
|
||||
data-test-subj="input"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</UseField>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
getProcessorDescriptor,
|
||||
mapProcessorTypeToDescriptor,
|
||||
ProcessorType,
|
||||
} from './map_processor_type_to_form';
|
|
@ -10,7 +10,7 @@ import { FunctionComponent } from 'react';
|
|||
// import { SetProcessor } from './processors/set';
|
||||
// import { Gsub } from './processors/gsub';
|
||||
|
||||
interface FieldsFormDescriptor {
|
||||
interface FieldDescriptor {
|
||||
FieldsComponent?: FunctionComponent;
|
||||
docLinkPath: string;
|
||||
/**
|
||||
|
@ -19,7 +19,9 @@ interface FieldsFormDescriptor {
|
|||
label: string;
|
||||
}
|
||||
|
||||
const mapProcessorTypeToFormDescriptor: Record<string, FieldsFormDescriptor> = {
|
||||
type MapProcessorTypeToDescriptor = Record<string, FieldDescriptor>;
|
||||
|
||||
export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = {
|
||||
append: {
|
||||
FieldsComponent: undefined, // TODO: Implement
|
||||
docLinkPath: '/append-processor.html',
|
||||
|
@ -262,12 +264,10 @@ const mapProcessorTypeToFormDescriptor: Record<string, FieldsFormDescriptor> = {
|
|||
},
|
||||
};
|
||||
|
||||
export const types = Object.keys(mapProcessorTypeToFormDescriptor).sort();
|
||||
export type ProcessorType = keyof typeof mapProcessorTypeToDescriptor;
|
||||
|
||||
export type ProcessorType = keyof typeof mapProcessorTypeToFormDescriptor;
|
||||
|
||||
export const getProcessorFormDescriptor = (
|
||||
export const getProcessorDescriptor = (
|
||||
type: ProcessorType | string
|
||||
): FieldsFormDescriptor | undefined => {
|
||||
return mapProcessorTypeToFormDescriptor[type as ProcessorType];
|
||||
): FieldDescriptor | undefined => {
|
||||
return mapProcessorTypeToDescriptor[type as ProcessorType];
|
||||
};
|
Loading…
Reference in a new issue