Skip to content

Commit

Permalink
[Integration AutoImport] Multi-valuated input type (elastic#188565)
Browse files Browse the repository at this point in the history
## Summary

This PR changes the "input type" field to a combo box to make it
multi-valuated. The state logic, tests, and telemetry have been adapted.


![multi_input-type](https://github.com/user-attachments/assets/1b5ef55c-1776-409a-af51-a639a831ff8f)
  • Loading branch information
semd authored Jul 18, 2024
1 parent e049eca commit 7a844fa
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ export const mockState: State = {
dataStreamTitle: 'Mocked Data Stream Title',
dataStreamName: 'mocked_datastream_name',
dataStreamDescription: 'Mocked Data Stream Description',
inputType: 'filestream',
inputTypes: ['filestream'],
logsSampleParsed: rawSamples,
},
isGenerating: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ import { DataStreamStep } from './data_stream_step';
import { ActionsProvider } from '../../state';
import { mockActions, mockState } from '../../mocks/state';

jest.mock('@elastic/eui', () => {
return {
...jest.requireActual('@elastic/eui'),
// Mocking EuiComboBox, as it utilizes "react-virtualized" for rendering search suggestions,
// which does not produce a valid component wrapper
EuiComboBox: (props: { onChange: (options: unknown) => void; 'data-test-subj': string }) => (
<input
data-test-subj={props['data-test-subj']}
onChange={(syntheticEvent) => {
props.onChange([{ value: syntheticEvent.target.value }]);
}}
/>
),
};
});

jest.mock('./generation_modal', () => ({
GenerationModal: jest.fn(() => <div data-test-subj="generationModal" />),
}));
Expand Down Expand Up @@ -204,7 +220,7 @@ describe('DataStreamStep', () => {

it('should call setIntegrationSettings', () => {
expect(mockActions.setIntegrationSettings).toHaveBeenCalledWith({
inputType: dataCollectionMethod,
inputTypes: [dataCollectionMethod],
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
*/

import React, { useCallback, useEffect, useMemo, useState } from 'react';
import type { EuiComboBoxOptionOption } from '@elastic/eui';
import {
EuiComboBox,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiFormRow,
EuiPanel,
EuiSelect,
} from '@elastic/eui';
import type { InputType } from '../../../../../../common';
import { useActions, type State } from '../../state';
Expand All @@ -25,21 +26,21 @@ import { GenerationModal } from './generation_modal';
import { useLoadPackageNames } from './use_load_package_names';
import * as i18n from './translations';

export const InputTypeOptions: Array<{ value: InputType; text: string }> = [
{ value: 'aws_cloudwatch', text: 'AWS Cloudwatch' },
{ value: 'aws_s3', text: 'AWS S3' },
{ value: 'azure_blob_storage', text: 'Azure Blob Storage' },
{ value: 'azure_eventhub', text: 'Azure Event Hub' },
{ value: 'cel', text: 'Common Expression Language (CEL)' },
{ value: 'cloudfoundry', text: 'Cloud Foundry' },
{ value: 'filestream', text: 'File Stream' },
{ value: 'gcp_pubsub', text: 'GCP Pub/Sub' },
{ value: 'gcs', text: 'Google Cloud Storage' },
{ value: 'http_endpoint', text: 'HTTP Endpoint' },
{ value: 'journald', text: 'Journald' },
{ value: 'kafka', text: 'Kafka' },
{ value: 'tcp', text: 'TCP' },
{ value: 'udp', text: 'UDP' },
export const InputTypeOptions: Array<EuiComboBoxOptionOption<InputType>> = [
{ value: 'aws_cloudwatch', label: 'AWS Cloudwatch' },
{ value: 'aws_s3', label: 'AWS S3' },
{ value: 'azure_blob_storage', label: 'Azure Blob Storage' },
{ value: 'azure_eventhub', label: 'Azure Event Hub' },
{ value: 'cel', label: 'Common Expression Language (CEL)' },
{ value: 'cloudfoundry', label: 'Cloud Foundry' },
{ value: 'filestream', label: 'File Stream' },
{ value: 'gcp_pubsub', label: 'GCP Pub/Sub' },
{ value: 'gcs', label: 'Google Cloud Storage' },
{ value: 'http_endpoint', label: 'HTTP Endpoint' },
{ value: 'journald', label: 'Journald' },
{ value: 'kafka', label: 'Kafka' },
{ value: 'tcp', label: 'TCP' },
{ value: 'udp', label: 'UDP' },
];

const isValidName = (name: string) => /^[a-z0-9_]+$/.test(name);
Expand Down Expand Up @@ -96,8 +97,8 @@ export const DataStreamStep = React.memo<DataStreamStepProps>(
setIntegrationValues({ dataStreamTitle: e.target.value }),
dataStreamDescription: (e: React.ChangeEvent<HTMLInputElement>) =>
setIntegrationValues({ dataStreamDescription: e.target.value }),
inputType: (e: React.ChangeEvent<HTMLSelectElement>) => {
setIntegrationValues({ inputType: e.target.value as InputType });
inputTypes: (options: EuiComboBoxOptionOption[]) => {
setIntegrationValues({ inputTypes: options.map((option) => option.value as InputType) });
},
};
}, [setIntegrationValues, setInvalidFields, packageNames]);
Expand Down Expand Up @@ -135,6 +136,14 @@ export const DataStreamStep = React.memo<DataStreamStepProps>(
}
}, [packageNames, name]);

const selectedInputTypeOptions = useMemo<Array<EuiComboBoxOptionOption<InputType>>>(
() =>
InputTypeOptions.filter((inputType) =>
integrationSettings?.inputTypes?.includes(inputType.value as InputType)
),
[integrationSettings?.inputTypes]
);

return (
<EuiFlexGroup direction="column" gutterSize="l" data-test-subj="dataStreamStep">
<EuiFlexItem>
Expand Down Expand Up @@ -205,12 +214,12 @@ export const DataStreamStep = React.memo<DataStreamStepProps>(
/>
</EuiFormRow>
<EuiFormRow label={i18n.DATA_COLLECTION_METHOD_LABEL}>
<EuiSelect
name="dataCollectionMethod"
<EuiComboBox
data-test-subj="dataCollectionMethodInput"
options={InputTypeOptions}
value={integrationSettings?.inputType ?? ''}
onChange={onChange.inputType}
selectedOptions={selectedInputTypeOptions}
onChange={onChange.inputTypes}
fullWidth
/>
</EuiFormRow>
<SampleLogsInput integrationSettings={integrationSettings} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const parameters: BuildIntegrationRequestBody = {
title: integrationSettings.dataStreamTitle!,
description: integrationSettings.dataStreamDescription!,
name: integrationSettings.dataStreamName!,
inputTypes: [integrationSettings.inputType!],
inputTypes: integrationSettings.inputTypes!,
rawSamples: integrationSettings.logsSampleParsed!,
docs: results.docs!,
pipeline: results.pipeline,
Expand Down Expand Up @@ -105,7 +105,7 @@ describe('DeployStep', () => {
integrationName,
integrationDescription: integrationSettings.description,
dataStreamName: integrationSettings.dataStreamName,
inputType: integrationSettings.inputType,
inputTypes: integrationSettings.inputTypes,
model: expect.any(String),
actionTypeId: connector.actionTypeId,
provider: connector.apiProvider ?? 'unknown',
Expand Down Expand Up @@ -172,7 +172,7 @@ describe('DeployStep', () => {
integrationName: integrationSettings.name,
integrationDescription: integrationSettings.description,
dataStreamName: integrationSettings.dataStreamName,
inputType: integrationSettings.inputType,
inputTypes: integrationSettings.inputTypes,
model: expect.any(String),
actionTypeId: connector.actionTypeId,
provider: connector.apiProvider ?? 'unknown',
Expand Down Expand Up @@ -224,7 +224,7 @@ describe('DeployStep', () => {
integrationName: integrationSettings.name,
integrationDescription: integrationSettings.description,
dataStreamName: integrationSettings.dataStreamName,
inputType: integrationSettings.inputType,
inputTypes: integrationSettings.inputTypes,
model: expect.any(String),
actionTypeId: connector.actionTypeId,
provider: connector.apiProvider ?? 'unknown',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const useDeployIntegration = ({
title: integrationSettings.dataStreamTitle ?? '',
description: integrationSettings.dataStreamDescription ?? '',
name: integrationSettings.dataStreamName ?? '',
inputTypes: integrationSettings.inputType ? [integrationSettings.inputType] : [],
inputTypes: integrationSettings.inputTypes ?? [],
rawSamples: integrationSettings.logsSampleParsed ?? [],
docs: result.docs ?? [],
pipeline: result.pipeline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ export interface IntegrationSettings {
dataStreamTitle?: string;
dataStreamDescription?: string;
dataStreamName?: string;
inputType?: InputType;
inputTypes?: InputType[];
logsSampleParsed?: string[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const TelemetryContextProvider = React.memo<PropsWithChildren<{}>>(({ chi
integrationName,
integrationDescription: integrationSettings?.description ?? 'unknown',
dataStreamName: integrationSettings?.dataStreamName ?? 'unknown',
inputType: integrationSettings?.inputType ?? 'unknown',
inputTypes: integrationSettings?.inputTypes ?? ['unknown'],
actionTypeId: connector.actionTypeId,
model: getConnectorModel(connector),
provider: connector.apiProvider ?? 'unknown',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,14 @@ export const telemetryEventsSchemas: TelemetryEventsSchemas = {
optional: false,
},
},
inputType: {
type: 'keyword',
_meta: {
description: 'The input type used for the integration',
optional: false,
inputTypes: {
type: 'array',
items: {
type: 'keyword',
_meta: {
description: 'The input type used for the integration',
optional: false,
},
},
},
actionTypeId: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface IntegrationAssistantCompleteData {
integrationName: string;
integrationDescription: string;
dataStreamName: string;
inputType: string;
inputTypes: string[];
actionTypeId: string;
model: string;
provider: string;
Expand Down

0 comments on commit 7a844fa

Please sign in to comment.