[8.x] [Streams 🌊] Schema editor bug fixes (#218225) (#218269)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Streams 🌊] Schema editor bug fixes
(#218225)](https://github.com/elastic/kibana/pull/218225)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Marco Antonio
Ghiani","email":"marcoantonio.ghiani01@gmail.com"},"sourceCommit":{"committedDate":"2025-04-15T13:36:09Z","message":"[Streams
🌊] Schema editor bug fixes (#218225)\n\n## 📓 Summary\n\nThese changes
address various minor issues reported on the Schema\nEditor.\n\nCloses
#217888 \nCloses #217889\nCloses #217891\nCloses #217892\nCloses #217893
\n\n### [Streams 🌊] \"System managed\" appears in the list of field
types in\nthe schema editor\n\n<img width=\"659\" alt=\"Screenshot
2025-04-15 at 10 50
37\"\nsrc=\"https://github.com/user-attachments/assets/5f9e832a-e7ea-4e19-9507-2bd3669c7043\"\n/>\n\n###
[Streams 🌊] Clicking the link in the schema editor to edit a
field\nmapping in the parent stream loads a new
page\n\n\nhttps://github.com/user-attachments/assets/de1a1b09-5eca-4143-a822-2de6814333b6\n\n###
[Streams 🌊] Saving changes in the schema editor for an inherited\nfield
results in
error\n\n\nhttps://github.com/user-attachments/assets/603c8a89-6df3-474a-91bc-ee7bbee0f250\n\n###
[Streams 🌊] Disable submit button when there is invalid input
for\nmapping in the schema
editor\n\n\nhttps://github.com/user-attachments/assets/22dfb91a-fa37-4b68-a8c5-c5f3a89a98e5\n\n###
Advanced fields mapping simulation and client-side
validation\n\n\nhttps://github.com/user-attachments/assets/faf99f86-5074-4587-9cc6-65f39f3595e9\n\n###
[Streams 🌊] Increase width in the type filter popup in schema
editor\n\n\nhttps://github.com/user-attachments/assets/b6eab484-308b-42dd-887b-560fb91986da","sha":"d36b269e60308a6b0a5db19b2eac047d2fd51f9d","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:obs-ux-logs","backport:version","Feature:Streams","v9.1.0","v8.19.0"],"title":"[Streams
🌊] Schema editor bug
fixes","number":218225,"url":"https://github.com/elastic/kibana/pull/218225","mergeCommit":{"message":"[Streams
🌊] Schema editor bug fixes (#218225)\n\n## 📓 Summary\n\nThese changes
address various minor issues reported on the Schema\nEditor.\n\nCloses
#217888 \nCloses #217889\nCloses #217891\nCloses #217892\nCloses #217893
\n\n### [Streams 🌊] \"System managed\" appears in the list of field
types in\nthe schema editor\n\n<img width=\"659\" alt=\"Screenshot
2025-04-15 at 10 50
37\"\nsrc=\"https://github.com/user-attachments/assets/5f9e832a-e7ea-4e19-9507-2bd3669c7043\"\n/>\n\n###
[Streams 🌊] Clicking the link in the schema editor to edit a
field\nmapping in the parent stream loads a new
page\n\n\nhttps://github.com/user-attachments/assets/de1a1b09-5eca-4143-a822-2de6814333b6\n\n###
[Streams 🌊] Saving changes in the schema editor for an inherited\nfield
results in
error\n\n\nhttps://github.com/user-attachments/assets/603c8a89-6df3-474a-91bc-ee7bbee0f250\n\n###
[Streams 🌊] Disable submit button when there is invalid input
for\nmapping in the schema
editor\n\n\nhttps://github.com/user-attachments/assets/22dfb91a-fa37-4b68-a8c5-c5f3a89a98e5\n\n###
Advanced fields mapping simulation and client-side
validation\n\n\nhttps://github.com/user-attachments/assets/faf99f86-5074-4587-9cc6-65f39f3595e9\n\n###
[Streams 🌊] Increase width in the type filter popup in schema
editor\n\n\nhttps://github.com/user-attachments/assets/b6eab484-308b-42dd-887b-560fb91986da","sha":"d36b269e60308a6b0a5db19b2eac047d2fd51f9d"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/218225","number":218225,"mergeCommit":{"message":"[Streams
🌊] Schema editor bug fixes (#218225)\n\n## 📓 Summary\n\nThese changes
address various minor issues reported on the Schema\nEditor.\n\nCloses
#217888 \nCloses #217889\nCloses #217891\nCloses #217892\nCloses #217893
\n\n### [Streams 🌊] \"System managed\" appears in the list of field
types in\nthe schema editor\n\n<img width=\"659\" alt=\"Screenshot
2025-04-15 at 10 50
37\"\nsrc=\"https://github.com/user-attachments/assets/5f9e832a-e7ea-4e19-9507-2bd3669c7043\"\n/>\n\n###
[Streams 🌊] Clicking the link in the schema editor to edit a
field\nmapping in the parent stream loads a new
page\n\n\nhttps://github.com/user-attachments/assets/de1a1b09-5eca-4143-a822-2de6814333b6\n\n###
[Streams 🌊] Saving changes in the schema editor for an inherited\nfield
results in
error\n\n\nhttps://github.com/user-attachments/assets/603c8a89-6df3-474a-91bc-ee7bbee0f250\n\n###
[Streams 🌊] Disable submit button when there is invalid input
for\nmapping in the schema
editor\n\n\nhttps://github.com/user-attachments/assets/22dfb91a-fa37-4b68-a8c5-c5f3a89a98e5\n\n###
Advanced fields mapping simulation and client-side
validation\n\n\nhttps://github.com/user-attachments/assets/faf99f86-5074-4587-9cc6-65f39f3595e9\n\n###
[Streams 🌊] Increase width in the type filter popup in schema
editor\n\n\nhttps://github.com/user-attachments/assets/b6eab484-308b-42dd-887b-560fb91986da","sha":"d36b269e60308a6b0a5db19b2eac047d2fd51f9d"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani01@gmail.com>
This commit is contained in:
Kibana Machine 2025-04-15 18:27:12 +02:00 committed by GitHub
parent cdd4855188
commit 0e10b2ea53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 226 additions and 108 deletions

View file

@ -171,13 +171,7 @@ export const schemaFieldsSimulationRoute = createServerRoute({
}
const propertiesForSimulation = Object.fromEntries(
userFieldDefinitions.map((field) => [
field.name,
{
type: field.type,
...(field.format ? { format: field.format } : {}),
},
])
userFieldDefinitions.map(({ name, ...field }) => [name, field])
);
const fieldDefinitionKeys = Object.keys(propertiesForSimulation);

View file

@ -14,41 +14,49 @@ export const FIELD_TYPE_MAP = {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableBooleanType', {
defaultMessage: 'Boolean',
}),
readonly: false,
},
date: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableDateType', {
defaultMessage: 'Date',
}),
readonly: false,
},
keyword: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableKeywordType', {
defaultMessage: 'Keyword',
}),
readonly: false,
},
match_only_text: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableTextType', {
defaultMessage: 'Text (match_only_text)',
}),
readonly: false,
},
long: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableNumberType', {
defaultMessage: 'Number (long)',
}),
readonly: false,
},
double: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableNumberType', {
defaultMessage: 'Number (double)',
}),
readonly: false,
},
ip: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableIpType', {
defaultMessage: 'IP',
}),
readonly: false,
},
system: {
label: i18n.translate('xpack.streams.streamDetailSchemaEditorFieldsTableSystemType', {
defaultMessage: 'System managed',
}),
readonly: true,
},
} as const;

View file

@ -15,6 +15,7 @@ import {
} from '@elastic/eui';
import { useBoolean } from '@kbn/react-hooks';
import React from 'react';
import { css } from '@emotion/react';
export const FilterGroup = ({
filterGroupButtonLabel,
@ -57,9 +58,9 @@ export const FilterGroup = ({
<EuiSelectable aria-label={filterGroupButtonLabel} options={items} onChange={onChange}>
{(list) => (
<div
css={{
minWidth: '200px',
}}
css={css`
min-width: 220px;
`}
>
{list}
</div>

View file

@ -5,14 +5,15 @@
* 2.0.
*/
import { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { EuiSelectableOption, EuiSelectableProps } from '@elastic/eui';
import { FilterGroup } from './filter_group';
import { FIELD_STATUS_MAP } from '../constants';
import { TControlsChangeHandler } from '../hooks/use_controls';
import { SchemaFieldStatus } from '../types';
import { useSchemaEditorContext } from '../schema_editor_context';
const BUTTON_LABEL = i18n.translate(
'xpack.streams.streamDetailSchemaEditor.fieldStatusFilterGroupButtonLabel',
@ -20,14 +21,28 @@ const BUTTON_LABEL = i18n.translate(
);
export const FieldStatusFilterGroup = ({ onChange }: { onChange: TControlsChangeHandler }) => {
const [items, setItems] = useState<EuiSelectableOption[]>(() =>
Object.entries(FIELD_STATUS_MAP).map(([key, value]) => {
return {
label: value.label,
key,
};
})
);
const { fields } = useSchemaEditorContext();
const fieldStatus = useMemo(() => uniq(fields.map((field) => field.status)), [fields]);
const [items, setItems] = useState<EuiSelectableOption[]>(() => getStatusOptions(fieldStatus));
// This side effect is due to the fact that the available field status can be updated once the unmapped fields are fetched.
useEffect(() => {
setItems((prevItems) => {
const prevSelection = new Map(prevItems.map((item) => [item.key, item.checked]));
const nextItems = getStatusOptions(fieldStatus);
nextItems.forEach((item) => {
if (prevSelection.has(item.key)) {
item.checked = prevSelection.get(item.key);
}
});
return nextItems;
});
}, [fieldStatus]);
const onChangeItems = useCallback<Required<EuiSelectableProps>['onChange']>(
(nextItems) => {
@ -45,3 +60,10 @@ export const FieldStatusFilterGroup = ({ onChange }: { onChange: TControlsChange
<FilterGroup items={items} filterGroupButtonLabel={BUTTON_LABEL} onChange={onChangeItems} />
);
};
const getStatusOptions = (fieldStatus: SchemaFieldStatus[]): EuiSelectableOption[] => {
return fieldStatus.map((key) => ({
label: FIELD_STATUS_MAP[key].label,
key,
}));
};

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { EuiSelectableOption, EuiSelectableProps } from '@elastic/eui';
import { FilterGroup } from './filter_group';
import { FIELD_TYPE_MAP } from '../constants';
import { FIELD_TYPE_MAP, FieldTypeOption } from '../constants';
import { TControlsChangeHandler } from '../hooks/use_controls';
import { SchemaFieldType } from '../types';
import { useSchemaEditorContext } from '../schema_editor_context';
const BUTTON_LABEL = i18n.translate(
'xpack.streams.streamDetailSchemaEditor.fieldTypeFilterGroupButtonLabel',
@ -20,22 +20,44 @@ const BUTTON_LABEL = i18n.translate(
);
export const FieldTypeFilterGroup = ({ onChange }: { onChange: TControlsChangeHandler }) => {
const [items, setItems] = useState<EuiSelectableOption[]>(() =>
Object.entries(FIELD_TYPE_MAP).map(([key, value]) => {
return {
label: value.label,
key,
};
})
const { fields } = useSchemaEditorContext();
const fieldTypes = useMemo(
() =>
uniq(
fields
.map((field) => field.type)
.filter((type): type is FieldTypeOption => type !== undefined)
),
[fields]
);
const [items, setItems] = useState<EuiSelectableOption[]>(() => getTypeOptions(fieldTypes));
// This side effect is due to the fact that the available field status can be updated once the unmapped fields are fetched.
useEffect(() => {
setItems((prevItems) => {
const prevSelection = new Map(prevItems.map((item) => [item.key, item.checked]));
const nextItems = getTypeOptions(fieldTypes);
nextItems.forEach((item) => {
if (prevSelection.has(item.key)) {
item.checked = prevSelection.get(item.key);
}
});
return nextItems;
});
}, [fieldTypes]);
const onChangeItems = useCallback<Required<EuiSelectableProps>['onChange']>(
(nextItems) => {
setItems(nextItems);
onChange({
type: nextItems
.filter((nextItem) => nextItem.checked === 'on')
.map((item) => item.key as SchemaFieldType),
.map((item) => item.key as FieldTypeOption),
});
},
[onChange]
@ -45,3 +67,10 @@ export const FieldTypeFilterGroup = ({ onChange }: { onChange: TControlsChangeHa
<FilterGroup items={items} filterGroupButtonLabel={BUTTON_LABEL} onChange={onChangeItems} />
);
};
const getTypeOptions = (fieldStatus: FieldTypeOption[]): EuiSelectableOption[] => {
return fieldStatus.map((key) => ({
label: FIELD_TYPE_MAP[key].label,
key,
}));
};

View file

@ -7,17 +7,21 @@
import {
EuiAccordion,
EuiCodeBlock,
EuiFormRow,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
useGeneratedHtmlId,
} from '@elastic/eui';
import { CodeEditor } from '@kbn/code-editor';
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { getAdvancedParameters } from '@kbn/streams-schema';
import {
FieldDefinitionConfigAdvancedParameters,
isSchema,
recursiveRecord,
} from '@kbn/streams-schema';
import { useBoolean } from '@kbn/react-hooks';
import { SchemaField } from '../types';
import { useKibana } from '../../../../hooks/use_kibana';
@ -28,16 +32,23 @@ const label = i18n.translate('xpack.streams.advancedFieldMappingOptions.label',
export const AdvancedFieldMappingOptions = ({
field,
onChange,
onValidate,
isEditing,
}: {
field: SchemaField;
onChange: (field: Partial<SchemaField>) => void;
onValidate?: (isValid: boolean) => void;
isEditing: boolean;
}) => {
const { core } = useKibana();
const accordionId = useGeneratedHtmlId({ prefix: 'accordionID' });
const [hasParsingError, { on: markAsParsingError, off: resetParsingErrorFlag }] =
useBoolean(false);
const isInvalid = hasParsingError || !getValidFlag(field.additionalParameters);
const jsonOptions = useMemo(
() => (field.additionalParameters ? JSON.stringify(field.additionalParameters, null, 2) : ''),
[field.additionalParameters]
@ -46,50 +57,73 @@ export const AdvancedFieldMappingOptions = ({
return (
<EuiAccordion id={accordionId} buttonContent={label}>
<EuiPanel color="subdued">
<EuiText size="xs">
<FormattedMessage
id="xpack.streams.advancedFieldMappingOptions.docs.label"
defaultMessage="Parameters can be defined with JSON. {link}"
values={{
link: (
<EuiLink
data-test-subj="streamsAppAdvancedFieldMappingOptionsViewDocumentationLink"
href={core.docLinks.links.elasticsearch.docsBase.concat('mapping-params.html')}
target="_blank"
external
>
<FormattedMessage
id="xpack.streams.indexPattern.randomSampling.learnMore"
defaultMessage="View documentation."
/>
</EuiLink>
),
}}
/>
</EuiText>
<EuiSpacer size="s" />
{isEditing ? (
<CodeEditor
height={120}
languageId="json"
value={jsonOptions}
onChange={(value) => {
try {
onChange({
additionalParameters:
value === '' ? undefined : getAdvancedParameters(field.name, JSON.parse(value)),
});
} catch (error: unknown) {
// do nothing
}
}}
/>
) : (
<EuiCodeBlock language="json" isCopyable>
{jsonOptions ?? ''}
</EuiCodeBlock>
)}
<EuiFormRow
isInvalid={isInvalid}
error={
isInvalid
? i18n.translate('xpack.streams.advancedFieldMappingOptions.error', {
defaultMessage:
'Invalid advanced field mapping parameters. It should be defined as a JSON object.',
})
: undefined
}
label={
<FormattedMessage
id="xpack.streams.advancedFieldMappingOptions.docs.label"
defaultMessage="Parameters can be defined with JSON. {link}"
values={{
link: (
<EuiLink
data-test-subj="streamsAppAdvancedFieldMappingOptionsViewDocumentationLink"
href={core.docLinks.links.elasticsearch.docsBase.concat('mapping-params.html')}
target="_blank"
external
>
<FormattedMessage
id="xpack.streams.indexPattern.randomSampling.learnMore"
defaultMessage="View documentation."
/>
</EuiLink>
),
}}
/>
}
>
{isEditing ? (
<CodeEditor
height={120}
languageId="json"
value={jsonOptions}
onChange={(value) => {
try {
const additionalParameters =
value === ''
? undefined
: (JSON.parse(value) as FieldDefinitionConfigAdvancedParameters);
onChange({ additionalParameters });
if (onValidate) onValidate(getValidFlag(additionalParameters));
resetParsingErrorFlag();
} catch (error: unknown) {
markAsParsingError();
if (onValidate) onValidate(false);
}
}}
/>
) : (
<EuiCodeBlock language="json" isCopyable>
{jsonOptions}
</EuiCodeBlock>
)}
</EuiFormRow>
</EuiPanel>
</EuiAccordion>
);
};
const getValidFlag = (additionalParameters?: FieldDefinitionConfigAdvancedParameters) => {
return Boolean(
!additionalParameters ||
additionalParameters === '' ||
isSchema(recursiveRecord, additionalParameters)
);
};

View file

@ -67,6 +67,13 @@ interface FieldTypeSelectorProps {
value?: FieldTypeOption;
}
const typeSelectorOptions = Object.entries(FIELD_TYPE_MAP)
.filter(([_, { readonly }]) => !readonly)
.map(([optionKey, { label }]) => ({
text: label,
value: optionKey,
}));
const FieldTypeSelector = ({ value, onChange, isLoading = false }: FieldTypeSelectorProps) => {
return (
<EuiSelect
@ -77,10 +84,7 @@ const FieldTypeSelector = ({ value, onChange, isLoading = false }: FieldTypeSele
onChange(event.target.value as FieldTypeOption);
}}
value={value}
options={Object.entries(FIELD_TYPE_MAP).map(([optionKey, optionConfig]) => ({
text: optionConfig.label,
value: optionKey,
}))}
options={typeSelectorOptions}
/>
);
};

View file

@ -108,6 +108,7 @@ export const FieldSummary = (props: FieldSummaryProps) => {
tab: 'schemaEditor',
},
})}
target="_blank"
>
{i18n.translate('xpack.streams.fieldSummary.editInParentButtonLabel', {
defaultMessage: 'Edit in parent stream',

View file

@ -15,7 +15,7 @@ import {
EuiTitle,
EuiButton,
} from '@elastic/eui';
import React, { useReducer } from 'react';
import React, { useReducer, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { IngestStreamDefinition } from '@kbn/streams-schema';
import useAsyncFn from 'react-use/lib/useAsyncFn';
@ -43,6 +43,8 @@ export const SchemaEditorFlyout = ({
withFieldSimulation = false,
}: SchemaEditorFlyoutProps) => {
const [isEditing, toggleEditMode] = useToggle(isEditingByDefault);
const [isValidAdvancedFieldMappings, setValidAdvancedFieldMappings] = useState(true);
const [isValidSimulation, setValidSimulation] = useState(true);
const [nextField, setNextField] = useReducer(
(prev: SchemaField, updated: Partial<SchemaField>) =>
@ -53,6 +55,8 @@ export const SchemaEditorFlyout = ({
field
);
const hasValidFieldType = nextField.type !== undefined;
const [{ loading: isSaving }, saveChanges] = useAsyncFn(async () => {
await onSave(nextField);
if (onClose) onClose();
@ -78,39 +82,52 @@ export const SchemaEditorFlyout = ({
<AdvancedFieldMappingOptions
field={nextField}
onChange={setNextField}
onValidate={setValidAdvancedFieldMappings}
isEditing={isEditing}
/>
{withFieldSimulation && (
<EuiFlexItem grow={false}>
<SamplePreviewTable stream={stream} nextField={nextField} />
<SamplePreviewTable
stream={stream}
nextField={nextField}
onValidate={setValidSimulation}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiButtonEmpty
data-test-subj="streamsAppSchemaEditorFlyoutCloseButton"
iconType="cross"
onClick={onClose}
flush="left"
>
{i18n.translate('xpack.streams.schemaEditorFlyout.closeButtonLabel', {
defaultMessage: 'Cancel',
})}
</EuiButtonEmpty>
<EuiButton
data-test-subj="streamsAppSchemaEditorFieldSaveButton"
isLoading={isSaving}
onClick={saveChanges}
>
{i18n.translate('xpack.streams.fieldForm.saveButtonLabel', {
defaultMessage: 'Save changes',
})}
</EuiButton>
</EuiFlexGroup>
</EuiFlyoutFooter>
{isEditing && (
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiButtonEmpty
data-test-subj="streamsAppSchemaEditorFlyoutCloseButton"
iconType="cross"
onClick={onClose}
flush="left"
>
{i18n.translate('xpack.streams.schemaEditorFlyout.closeButtonLabel', {
defaultMessage: 'Cancel',
})}
</EuiButtonEmpty>
<EuiButton
data-test-subj="streamsAppSchemaEditorFieldSaveButton"
disabled={
isSaving ||
!hasValidFieldType ||
!isValidAdvancedFieldMappings ||
!isValidSimulation
}
isLoading={isSaving}
onClick={saveChanges}
>
{i18n.translate('xpack.streams.fieldForm.saveButtonLabel', {
defaultMessage: 'Save changes',
})}
</EuiButton>
</EuiFlexGroup>
</EuiFlyoutFooter>
)}
</>
);
};

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { EuiCallOut } from '@elastic/eui';
@ -21,6 +21,7 @@ import { convertToFieldDefinitionConfig } from '../utils';
interface SamplePreviewTableProps {
stream: IngestStreamDefinition;
nextField: SchemaField;
onValidate?: (isValid: boolean) => void;
}
export const SamplePreviewTable = (props: SamplePreviewTableProps) => {
@ -37,6 +38,7 @@ const SAMPLE_DOCUMENTS_TO_SHOW = 20;
const SamplePreviewTableContent = ({
stream,
nextField,
onValidate,
}: SamplePreviewTableProps & { nextField: MappedSchemaField }) => {
const { streamsRepositoryClient } = useKibana().dependencies.start.streams;
@ -63,6 +65,12 @@ const SamplePreviewTableContent = ({
{ disableToastOnError: true }
);
useEffect(() => {
if (onValidate) {
onValidate(value?.status === 'failure' || error ? false : true);
}
}, [value, error, onValidate]);
const columns = useMemo(() => {
return [nextField.name];
}, [nextField.name]);