[ML] Fix runtime mapping texts to runtime fields, add transform switch modal (#97008)

This commit is contained in:
Quynh Nguyen 2021-04-19 13:46:18 -05:00 committed by GitHub
parent 64f30a224e
commit 71e8118984
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 280 additions and 121 deletions

View file

@ -77,15 +77,15 @@ describe('ML runtime field utils', () => {
).toBe(false);
});
it('allows object with most basic runtime mapping', () => {
it('allows object with most basic runtime field', () => {
expect(isRuntimeMappings({ fieldName: { type: 'keyword' } })).toBe(true);
});
it('allows object with multiple most basic runtime mappings', () => {
it('allows object with multiple most basic runtime fields', () => {
expect(
isRuntimeMappings({ fieldName1: { type: 'keyword' }, fieldName2: { type: 'keyword' } })
).toBe(true);
});
it('allows object with runtime mappings including scripts', () => {
it('allows object with runtime fields including scripts', () => {
expect(
isRuntimeMappings({
fieldName1: { type: 'keyword' },

View file

@ -364,7 +364,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
}
return !option.key?.includes(runtimeMappingKey);
});
// Runtime mappings have been removed
// Runtime fields have been removed
if (runtimeMappings === undefined && runtimeMappingsUpdated === true) {
setDependentVariableOptions(filteredOptions);
} else if (runtimeMappings) {
@ -374,7 +374,7 @@ export const ConfigurationStepForm: FC<ConfigurationStepProps> = ({
}
}
// Update includes - remove previous runtime mappings then add supported runtime fields to includes
// Update includes - remove previous runtime fields then add supported runtime fields to includes
const updatedIncludes = includes.filter((field) => {
const isRemovedRuntimeField = previousRuntimeMapping && previousRuntimeMapping[field];
return !isRemovedRuntimeField;

View file

@ -20,19 +20,48 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { XJsonMode } from '@kbn/ace';
import { RuntimeField } from '../../../../../../../../../../src/plugins/data/common/index_patterns';
import { useMlContext } from '../../../../../contexts/ml';
import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/use_create_analytics_form';
import { XJson } from '../../../../../../../../../../src/plugins/es_ui_shared/public';
import { getCombinedRuntimeMappings } from '../../../../../components/data_grid/common';
import { isPopulatedObject } from '../../../../../../../common/util/object_utils';
import { RuntimeMappingsEditor } from './runtime_mappings_editor';
import { isRuntimeMappings } from '../../../../../../../common';
import { SwitchModal } from './switch_modal';
const advancedEditorsSidebarWidth = '220px';
const COPY_TO_CLIPBOARD_RUNTIME_MAPPINGS = i18n.translate(
const COPY_RUNTIME_FIELDS_TO_CLIPBOARD_TEXT = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.indexPreview.copyRuntimeMappingsClipboardTooltip',
{
defaultMessage: 'Copy Dev Console statement of the runtime mappings to the clipboard.',
defaultMessage: 'Copy Dev Console statement of the runtime fields to the clipboard.',
}
);
const APPLY_CHANGES_TEXT = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedSourceEditorApplyButtonText',
{
defaultMessage: 'Apply changes',
}
);
const RUNTIME_FIELDS_EDITOR_HELP_TEXT = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedRuntimeFieldsEditorHelpText',
{
defaultMessage: 'The advanced editor allows you to edit the runtime fields of the source.',
}
);
const EDIT_SWITCH_LABEL_TEXT = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedEditorRuntimeFieldsSwitchLabel',
{
defaultMessage: 'Edit runtime fields',
}
);
const RUNTIME_FIELDS_LABEL_TEXT = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.runtimeFieldsLabel',
{
defaultMessage: 'Runtime fields',
}
);
@ -45,12 +74,15 @@ interface Props {
state: CreateAnalyticsFormProps['state'];
}
type RuntimeMappings = Record<string, RuntimeField>;
export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
const [isRuntimeMappingsEditorEnabled, setIsRuntimeMappingsEditorEnabled] = useState<boolean>(
false
);
const [
isRuntimeMappingsEditorSwitchModalVisible,
setRuntimeMappingsEditorSwitchModalVisible,
] = useState<boolean>(false);
const [
isRuntimeMappingsEditorApplyButtonEnabled,
setIsRuntimeMappingsEditorApplyButtonEnabled,
@ -59,7 +91,6 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
advancedEditorRuntimeMappingsLastApplied,
setAdvancedEditorRuntimeMappingsLastApplied,
] = useState<string>();
const [advancedEditorRuntimeMappings, setAdvancedEditorRuntimeMappings] = useState<string>();
const { setFormState } = actions;
const { jobType, previousRuntimeMapping, runtimeMappings } = state.form;
@ -90,22 +121,22 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
runtimeMappingsUpdated: true,
previousRuntimeMapping: previous,
});
setAdvancedEditorRuntimeMappings(prettySourceConfig);
setAdvancedRuntimeMappingsConfig(prettySourceConfig);
setAdvancedEditorRuntimeMappingsLastApplied(prettySourceConfig);
setIsRuntimeMappingsEditorApplyButtonEnabled(false);
};
// If switching to KQL after updating via editor - reset search
const toggleEditorHandler = (reset = false) => {
if (reset === true) {
setFormState({ runtimeMappingsUpdated: false });
}
if (isRuntimeMappingsEditorEnabled === false) {
setAdvancedEditorRuntimeMappingsLastApplied(advancedEditorRuntimeMappings);
setFormState({
runtimeMappingsUpdated: false,
});
setAdvancedRuntimeMappingsConfig(advancedEditorRuntimeMappingsLastApplied ?? '');
}
setIsRuntimeMappingsEditorEnabled(!isRuntimeMappingsEditorEnabled);
setIsRuntimeMappingsEditorApplyButtonEnabled(false);
setIsRuntimeMappingsEditorApplyButtonEnabled(isRuntimeMappings(runtimeMappings));
};
useEffect(function getInitialRuntimeMappings() {
@ -114,8 +145,11 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
runtimeMappings
);
const prettySourceConfig = JSON.stringify(combinedRuntimeMappings, null, 2);
if (combinedRuntimeMappings) {
setAdvancedRuntimeMappingsConfig(JSON.stringify(combinedRuntimeMappings, null, 2));
setAdvancedRuntimeMappingsConfig(prettySourceConfig);
setAdvancedEditorRuntimeMappingsLastApplied(prettySourceConfig);
setFormState({
runtimeMappings: combinedRuntimeMappings,
});
@ -125,12 +159,7 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
return (
<>
<EuiSpacer size="s" />
<EuiFormRow
fullWidth={true}
label={i18n.translate('xpack.ml.dataframe.analytics.createWizard.runtimeMappingsLabel', {
defaultMessage: 'Runtime mappings',
})}
>
<EuiFormRow fullWidth={true} label={RUNTIME_FIELDS_LABEL_TEXT}>
<EuiFlexGroup alignItems="baseline" justifyContent="spaceBetween">
<EuiFlexItem grow={true}>
{isPopulatedObject(runtimeMappings) ? (
@ -139,8 +168,8 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
</EuiText>
) : (
<FormattedMessage
id="xpack.ml.dataframe.analytics.createWizard.noRuntimeMappingsLabel"
defaultMessage="No runtime mapping"
id="xpack.ml.dataframe.analytics.createWizard.noRuntimeFieldLabel"
defaultMessage="No runtime field"
/>
)}
@ -170,27 +199,41 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
<EuiFlexItem grow={false}>
<EuiSwitch
disabled={jobType === undefined}
label={i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedEditorRuntimeMappingsSwitchLabel',
{
defaultMessage: 'Edit runtime mappings',
}
)}
label={EDIT_SWITCH_LABEL_TEXT}
checked={isRuntimeMappingsEditorEnabled}
onChange={() => toggleEditorHandler()}
onChange={() => {
if (
isRuntimeMappingsEditorEnabled &&
advancedRuntimeMappingsConfig !== advancedEditorRuntimeMappingsLastApplied
) {
setRuntimeMappingsEditorSwitchModalVisible(true);
return;
}
toggleEditorHandler();
}}
data-test-subj="mlDataFrameAnalyticsRuntimeMappingsEditorSwitch"
/>
{isRuntimeMappingsEditorSwitchModalVisible && (
<SwitchModal
onCancel={() => setRuntimeMappingsEditorSwitchModalVisible(false)}
onConfirm={() => {
setRuntimeMappingsEditorSwitchModalVisible(false);
toggleEditorHandler(true);
}}
/>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiCopy
beforeMessage={COPY_TO_CLIPBOARD_RUNTIME_MAPPINGS}
beforeMessage={COPY_RUNTIME_FIELDS_TO_CLIPBOARD_TEXT}
textToCopy={advancedRuntimeMappingsConfig ?? ''}
>
{(copy: () => void) => (
<EuiButtonIcon
onClick={copy}
iconType="copyClipboard"
aria-label={COPY_TO_CLIPBOARD_RUNTIME_MAPPINGS}
aria-label={COPY_RUNTIME_FIELDS_TO_CLIPBOARD_TEXT}
/>
)}
</EuiCopy>
@ -201,15 +244,7 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
{isRuntimeMappingsEditorEnabled && (
<EuiFlexItem style={{ width: advancedEditorsSidebarWidth }}>
<EuiSpacer size="s" />
<EuiText size="xs">
{i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedRuntimeMappingsEditorHelpText',
{
defaultMessage:
'The advanced editor allows you to edit the runtime mappings of the source.',
}
)}
</EuiText>
<EuiText size="xs">{RUNTIME_FIELDS_EDITOR_HELP_TEXT}</EuiText>
<EuiSpacer size="s" />
<EuiButton
style={{ width: 'fit-content' }}
@ -219,12 +254,7 @@ export const RuntimeMappings: FC<Props> = ({ actions, state }) => {
disabled={!isRuntimeMappingsEditorApplyButtonEnabled}
data-test-subj="mlDataFrameAnalyticsRuntimeMappingsApplyButton"
>
{i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.advancedSourceEditorApplyButtonText',
{
defaultMessage: 'Apply changes',
}
)}
{APPLY_CHANGES_TEXT}
</EuiButton>
</EuiFlexItem>
)}

View file

@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FC } from 'react';
import { EuiConfirmModal } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
interface Props {
onCancel: () => void;
onConfirm: () => void;
}
const modalTitle = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.runtimeEditorSwitchModalTitle',
{
defaultMessage: 'Edits will be lost',
}
);
const cancelButtonText = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.runtimeEditorSwitchModalCancelButtonText',
{
defaultMessage: 'Cancel',
}
);
const applyChangesText = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.runtimeEditorSwitchModalConfirmButtonText',
{
defaultMessage: 'Close editor',
}
);
const modalMessage = i18n.translate(
'xpack.ml.dataframe.analytics.createWizard.runtimeEditorSwitchModalBodyText',
{
defaultMessage: `The changes in the editor haven't been applied yet. By closing the editor you will lose your edits.`,
}
);
export const SwitchModal: FC<Props> = ({ onCancel, onConfirm }) => (
<EuiConfirmModal
title={modalTitle}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText={cancelButtonText}
confirmButtonText={applyChangesText}
buttonColor="danger"
defaultFocusedButton="confirm"
>
<p>{modalMessage}</p>
</EuiConfirmModal>
);

View file

@ -102,7 +102,7 @@ describe('filter_runtime_mappings', () => {
datafeed = getDatafeed();
});
test('returns no runtime mappings, no mappings in aggs', () => {
test('returns no runtime fields, no mappings in aggs', () => {
const resp = filterRuntimeMappings(job, datafeed);
expect(Object.keys(resp.runtime_mappings).length).toEqual(0);
@ -111,7 +111,7 @@ describe('filter_runtime_mappings', () => {
expect(resp.discarded_mappings.airline_lower).not.toEqual(undefined);
});
test('returns no runtime mappings, no runtime mappings in datafeed', () => {
test('returns no runtime fields, no runtime fields in datafeed', () => {
datafeed.runtime_mappings = undefined;
const resp = filterRuntimeMappings(job, datafeed);
expect(Object.keys(resp.runtime_mappings).length).toEqual(0);
@ -131,7 +131,7 @@ describe('filter_runtime_mappings', () => {
expect(resp.discarded_mappings.airline_lower).not.toEqual(undefined);
});
test('return no runtime mappings, no mappings in aggs', () => {
test('return no runtime fields, no mappings in aggs', () => {
datafeed.aggregations = getAggs();
datafeed.aggregations!.buckets!.aggregations!.responsetime!.avg!.field! = 'responsetime';
@ -154,7 +154,7 @@ describe('filter_runtime_mappings', () => {
expect(resp.discarded_mappings.airline_lower).not.toEqual(undefined);
});
test('return two runtime mappings, no mappings in aggs', () => {
test('return two runtime fields, no mappings in aggs', () => {
// set the detector field to be a runtime mapping
job.analysis_config.detectors[0].field_name = 'responsetime_big';
// set the detector by field to be a runtime mapping
@ -167,7 +167,7 @@ describe('filter_runtime_mappings', () => {
expect(Object.keys(resp.discarded_mappings).length).toEqual(0);
});
test('return two runtime mappings, no mappings in aggs, categorization job', () => {
test('return two runtime fields, no mappings in aggs, categorization job', () => {
job.analysis_config.detectors[0].function = 'count';
// set the detector field to be a runtime mapping
job.analysis_config.detectors[0].field_name = undefined;

View file

@ -970,7 +970,7 @@ export function resultsServiceProvider(mlApiServices) {
},
},
},
// Runtime mappings only needed to support when query includes a runtime field
// Runtime fields only needed to support when query includes a runtime field
// even though the default timeField can be a search time runtime field
// because currently Kibana doesn't support that
...(isPopulatedObject(runtimeMappings) && query

View file

@ -627,7 +627,7 @@ export class DataVisualizer {
// filter aggregation with exists query.
const aggs: Aggs = datafeedAggregations !== undefined ? { ...datafeedAggregations } : {};
// Combine runtime mappings from the index pattern as well as the datafeed
// Combine runtime fields from the index pattern as well as the datafeed
const combinedRuntimeMappings: RuntimeMappings = {
...(isPopulatedObject(runtimeMappings) ? runtimeMappings : {}),
...(isPopulatedObject(datafeedConfig) && isPopulatedObject(datafeedConfig.runtime_mappings)

View file

@ -166,7 +166,7 @@ const validateFactory = (client: IScopedClusterClient, job: CombinedJob): Valida
}
} else {
// only report uniqueFieldName as not aggregatable if it's not part
// of a valid categorization configuration and if it's not a scripted field or runtime mapping.
// of a valid categorization configuration and if it's not a scripted field or runtime field.
if (
!isValidCategorizationConfig(job, uniqueFieldName) &&
!isScriptField(job, uniqueFieldName) &&

View file

@ -20,7 +20,7 @@ export const dataVisualizerFieldHistogramsSchema = schema.object({
fields: schema.arrayOf(schema.any()),
/** Number of documents to be collected in the sample processed on each shard, or -1 for no sampling. */
samplerShardSize: schema.number(),
/** Optional search time runtime mappings */
/** Optional search time runtime fields */
runtimeMappings: runtimeMappingsSchema,
});
@ -40,7 +40,7 @@ export const dataVisualizerFieldStatsSchema = schema.object({
interval: schema.maybe(schema.number()),
/** Maximum number of examples to return for text type fields. */
maxExamples: schema.number(),
/** Optional search time runtime mappings */
/** Optional search time runtime fields */
runtimeMappings: runtimeMappingsSchema,
});
@ -59,6 +59,6 @@ export const dataVisualizerOverallStatsSchema = schema.object({
earliest: schema.maybe(schema.number()),
/** Latest timestamp for search, as epoch ms (optional). */
latest: schema.maybe(schema.number()),
/** Optional search time runtime mappings */
/** Optional search time runtime fields */
runtimeMappings: runtimeMappingsSchema,
});

View file

@ -16,7 +16,7 @@ export const fieldHistogramsRequestSchema = schema.object({
query: schema.any(),
/** The fields to return histogram data. */
fields: schema.arrayOf(schema.any()),
/** Optional runtime mappings */
/** Optional runtime fields */
runtimeMappings: runtimeMappingsSchema,
/** Number of documents to be collected in the sample processed on each shard, or -1 for no sampling. */
samplerShardSize: schema.number(),

View file

@ -266,7 +266,7 @@ describe('Transform: Common', () => {
});
});
test('getCreateTransformRequestBody() with runtime mappings', () => {
test('getCreateTransformRequestBody() with runtime fields', () => {
const runtimeMappings = {
rt_bytes_bigger: {
type: 'double',

View file

@ -26,9 +26,6 @@ export const AdvancedPivotEditorSwitch: FC<StepDefineFormHook> = ({
isAdvancedPivotEditorApplyButtonEnabled,
},
},
pivotConfig: {
actions: { setAggList, setGroupByList },
},
}) => {
return (
<EuiFormRow>

View file

@ -27,6 +27,8 @@ export const AdvancedQueryEditorSwitch: FC<StepDefineFormHook> = ({
isAdvancedSourceEditorEnabled,
isAdvancedSourceEditorSwitchModalVisible,
sourceConfigUpdated,
advancedEditorSourceConfigLastApplied,
advancedEditorSourceConfig,
},
},
searchBar: {
@ -53,7 +55,11 @@ export const AdvancedQueryEditorSwitch: FC<StepDefineFormHook> = ({
)}
checked={isAdvancedSourceEditorEnabled}
onChange={() => {
if (isAdvancedSourceEditorEnabled && sourceConfigUpdated) {
if (
isAdvancedSourceEditorEnabled &&
(sourceConfigUpdated ||
advancedEditorSourceConfig !== advancedEditorSourceConfigLastApplied)
) {
setAdvancedSourceEditorSwitchModalVisible(true);
return;
}

View file

@ -8,35 +8,58 @@
import React, { FC } from 'react';
import { EuiSwitch } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { StepDefineFormHook } from '../step_define';
import { SwitchModal } from './switch_modal';
import { useAdvancedRuntimeMappingsEditor } from '../step_define/hooks/use_advanced_runtime_mappings_editor';
export const AdvancedRuntimeMappingsEditorSwitch: FC<
StepDefineFormHook['runtimeMappingsEditor']
> = (props) => {
type Props = ReturnType<typeof useAdvancedRuntimeMappingsEditor>;
export const AdvancedRuntimeMappingsEditorSwitch: FC<Props> = (props) => {
const {
actions: { setRuntimeMappingsUpdated, toggleRuntimeMappingsEditor },
state: { isRuntimeMappingsEditorEnabled },
actions: { toggleRuntimeMappingsEditor, setRuntimeMappingsEditorSwitchModalVisible },
state: {
isRuntimeMappingsEditorEnabled,
isRuntimeMappingsEditorSwitchModalVisible,
advancedEditorRuntimeMappingsLastApplied,
advancedRuntimeMappingsConfig,
},
} = props;
// If switching to KQL after updating via editor - reset search
const toggleEditorHandler = (reset = false) => {
if (reset === true) {
setRuntimeMappingsUpdated(false);
}
toggleRuntimeMappingsEditor(reset);
};
return (
<EuiSwitch
label={i18n.translate(
'xpack.transform.stepDefineForm.advancedEditorRuntimeMappingsSwitchLabel',
{
defaultMessage: 'Edit runtime mappings',
}
<>
<EuiSwitch
label={i18n.translate(
'xpack.transform.stepDefineForm.advancedEditorRuntimeFieldsSwitchLabel',
{
defaultMessage: 'Edit runtime fields',
}
)}
checked={isRuntimeMappingsEditorEnabled}
onChange={() => {
if (
isRuntimeMappingsEditorEnabled &&
advancedRuntimeMappingsConfig !== advancedEditorRuntimeMappingsLastApplied
) {
setRuntimeMappingsEditorSwitchModalVisible(true);
return;
}
toggleEditorHandler();
}}
data-test-subj="transformAdvancedRuntimeMappingsEditorSwitch"
/>
{isRuntimeMappingsEditorSwitchModalVisible && (
<SwitchModal
onCancel={() => setRuntimeMappingsEditorSwitchModalVisible(false)}
onConfirm={() => {
setRuntimeMappingsEditorSwitchModalVisible(false);
toggleEditorHandler(true);
}}
/>
)}
checked={isRuntimeMappingsEditorEnabled}
onChange={() => toggleEditorHandler()}
data-test-subj="transformAdvancedRuntimeMappingsEditorSwitch"
/>
</>
);
};

View file

@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FC } from 'react';
import { EuiConfirmModal } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
interface Props {
onCancel: () => void;
onConfirm: () => void;
}
const modalTitle = i18n.translate('xpack.transform.stepDefineForm.runtimeEditorSwitchModalTitle', {
defaultMessage: 'Edits will be lost',
});
const cancelButtonText = i18n.translate(
'xpack.transform.stepDefineForm.runtimeEditorSwitchModalCancelButtonText',
{
defaultMessage: 'Cancel',
}
);
const applyChangesText = i18n.translate(
'xpack.transform.stepDefineForm.runtimeEditorSwitchModalConfirmButtonText',
{
defaultMessage: 'Close editor',
}
);
const modalMessage = i18n.translate(
'xpack.transform.stepDefineForm.runtimeEditorSwitchModalBodyText',
{
defaultMessage: `The changes in the advanced editor haven't been applied yet. By closing the editor you will lose your edits.`,
}
);
export const SwitchModal: FC<Props> = ({ onCancel, onConfirm }) => (
<EuiConfirmModal
title={modalTitle}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText={cancelButtonText}
confirmButtonText={applyChangesText}
buttonColor="danger"
defaultFocusedButton="confirm"
>
<p>{modalMessage}</p>
</EuiConfirmModal>
);

View file

@ -29,9 +29,9 @@ import { isPivotAggConfigWithUiSupport } from '../../../../common/pivot_group_by
const advancedEditorsSidebarWidth = '220px';
const COPY_TO_CLIPBOARD_RUNTIME_MAPPINGS = i18n.translate(
'xpack.transform.indexPreview.copyRuntimeMappingsClipboardTooltip',
'xpack.transform.indexPreview.copyRuntimeFieldsClipboardTooltip',
{
defaultMessage: 'Copy Dev Console statement of the runtime mappings to the clipboard.',
defaultMessage: 'Copy Dev Console statement of the runtime fields to the clipboard.',
}
);
@ -87,15 +87,15 @@ export const AdvancedRuntimeMappingsSettings: FC<StepDefineFormHook> = (props) =
<EuiFormRow
fullWidth={true}
label={i18n.translate('xpack.transform.stepDefineForm.runtimeMappingsLabel', {
defaultMessage: 'Runtime mappings',
label={i18n.translate('xpack.transform.stepDefineForm.runtimeFieldsLabel', {
defaultMessage: 'Runtime fields',
})}
>
<EuiFlexGroup alignItems="baseline" justifyContent="spaceBetween">
<EuiFlexItem grow={true}>
{runtimeMappings !== undefined && Object.keys(runtimeMappings).length > 0 ? (
<FormattedMessage
id="xpack.transform.stepDefineForm.runtimeMappingsListLabel"
id="xpack.transform.stepDefineForm.runtimeFieldsListLabel"
defaultMessage="{runtimeFields}"
values={{
runtimeFields: Object.keys(runtimeMappings).join(','),
@ -104,7 +104,7 @@ export const AdvancedRuntimeMappingsSettings: FC<StepDefineFormHook> = (props) =
) : (
<FormattedMessage
id="xpack.transform.stepDefineForm.noRuntimeMappingsLabel"
defaultMessage="No runtime mapping"
defaultMessage="No runtime field"
/>
)}
@ -145,10 +145,10 @@ export const AdvancedRuntimeMappingsSettings: FC<StepDefineFormHook> = (props) =
<EuiSpacer size="s" />
<EuiText size="xs">
{i18n.translate(
'xpack.transform.stepDefineForm.advancedRuntimeMappingsEditorHelpText',
'xpack.transform.stepDefineForm.advancedRuntimeFieldsEditorHelpText',
{
defaultMessage:
'The advanced editor allows you to edit the runtime mappings of the transform configuration.',
'The advanced editor allows you to edit the runtime fields of the transform configuration.',
}
)}
</EuiText>

View file

@ -37,7 +37,7 @@ export function applyTransformConfigToDefineState(
transformConfig?: TransformBaseConfig,
indexPattern?: StepDefineFormProps['searchItems']['indexPattern']
): StepDefineExposedState {
// apply runtime mappings from both the index pattern and inline configurations
// apply runtime fields from both the index pattern and inline configurations
state.runtimeMappings = getCombinedRuntimeMappings(
indexPattern,
transformConfig?.source?.runtime_mappings

View file

@ -39,7 +39,7 @@ export function getSupportedFilterAggs(
];
}
throw new Error(`The field ${fieldName} does not exist in the index or runtime mappings`);
throw new Error(`The field ${fieldName} does not exist in the index or runtime fields`);
}
/**

View file

@ -62,11 +62,8 @@ export const useAdvancedRuntimeMappingsEditor = (defaults: StepDefineExposedStat
const toggleRuntimeMappingsEditor = (reset = false) => {
if (reset === true) {
setRuntimeMappingsUpdated(false);
setAdvancedRuntimeMappingsConfig(advancedEditorRuntimeMappingsLastApplied);
}
if (isRuntimeMappingsEditorEnabled === false) {
setAdvancedEditorRuntimeMappingsLastApplied(advancedRuntimeMappingsConfig);
}
setRuntimeMappingsEditorEnabled(!isRuntimeMappingsEditorEnabled);
setRuntimeMappingsEditorApplyButtonEnabled(false);
};

View file

@ -51,7 +51,7 @@ export const useStepDefineForm = ({ overrides, onChange, searchItems }: StepDefi
// source config hook
const advancedSourceEditor = useAdvancedSourceEditor(defaults, previewRequest);
// runtime mappings config hook
// runtime fields config hook
const runtimeMappingsEditor = useAdvancedRuntimeMappingsEditor(defaults);
useEffect(() => {

View file

@ -21758,7 +21758,6 @@
"xpack.transform.groupByLabelForm.editIntervalAriaLabel": "間隔を編集",
"xpack.transform.home.breadcrumbTitle": "変換",
"xpack.transform.indexPreview.copyClipboardTooltip": "インデックスプレビューの開発コンソールステートメントをクリップボードにコピーします。",
"xpack.transform.indexPreview.copyRuntimeMappingsClipboardTooltip": "ランタイムマッピングの開発コンソールステートメントをクリップボードにコピーします。",
"xpack.transform.latestPreview.latestPreviewIncompleteConfigCalloutBody": "1 つ以上の一意キーと並べ替えフィールドを選択してください。",
"xpack.transform.licenseCheckErrorMessage": "ライセンス確認失敗",
"xpack.transform.list.emptyPromptButtonText": "初めての変換を作成してみましょう。",
@ -21818,14 +21817,12 @@
"xpack.transform.stepDefineForm.advancedEditorHelpText": "詳細エディターでは、変換のピボット構成を編集できます。",
"xpack.transform.stepDefineForm.advancedEditorHelpTextLink": "使用可能なオプションの詳細を確認してください。",
"xpack.transform.stepDefineForm.advancedEditorLabel": "ピボット構成オブジェクト",
"xpack.transform.stepDefineForm.advancedEditorRuntimeMappingsSwitchLabel": "ランタイムマッピングの編集",
"xpack.transform.stepDefineForm.advancedEditorSourceConfigSwitchLabel": "JSONクエリを編集",
"xpack.transform.stepDefineForm.advancedEditorSwitchLabel": "JSON構成を編集",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalBodyText": "詳細エディターの変更は適用されませんでした。詳細エディターを無効にすると、編集内容が失われます。",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalCancelButtonText": "キャンセル",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalConfirmButtonText": "詳細エディターを無効にする",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalTitle": "適用されていない変更",
"xpack.transform.stepDefineForm.advancedRuntimeMappingsEditorHelpText": "高度なエディターでは、変換構成のランタイムマッピングを編集できます。",
"xpack.transform.stepDefineForm.advancedSourceEditorApplyButtonText": "変更を適用",
"xpack.transform.stepDefineForm.advancedSourceEditorAriaLabel": "クエリの詳細エディター",
"xpack.transform.stepDefineForm.advancedSourceEditorHelpText": "高度なエディターでは、変換構成のソースクエリ句を編集できます。",
@ -21851,8 +21848,6 @@
"xpack.transform.stepDefineForm.pivotLabel": "ピボット",
"xpack.transform.stepDefineForm.queryPlaceholderKql": "例:{example}",
"xpack.transform.stepDefineForm.queryPlaceholderLucene": "例:{example}",
"xpack.transform.stepDefineForm.runtimeMappingsLabel": "ランタイムマッピング",
"xpack.transform.stepDefineForm.runtimeMappingsListLabel": "{runtimeFields}",
"xpack.transform.stepDefineForm.savedSearchLabel": "保存検索",
"xpack.transform.stepDefineForm.sortFieldOptionsEmptyError": "並べ替えの条件にする日付フィールドがありません。別のフィールド型を使用するには、構成をクリップボードにコピーして、コンソールで変換を作成し続けます。",
"xpack.transform.stepDefineForm.sortHelpText": "最新のドキュメントを特定するために使用する日付フィールドを選択してます。",

View file

@ -22106,7 +22106,6 @@
"xpack.transform.groupByLabelForm.editIntervalAriaLabel": "编辑时间间隔",
"xpack.transform.home.breadcrumbTitle": "转换",
"xpack.transform.indexPreview.copyClipboardTooltip": "将索引预览的开发控制台语句复制到剪贴板。",
"xpack.transform.indexPreview.copyRuntimeMappingsClipboardTooltip": "将运行时映射的开发控制台语句复制到剪贴板。",
"xpack.transform.latestPreview.latestPreviewIncompleteConfigCalloutBody": "请选择至少一个唯一键和排序字段。",
"xpack.transform.licenseCheckErrorMessage": "许可证检查失败",
"xpack.transform.list.emptyPromptButtonText": "创建您的首个转换",
@ -22167,14 +22166,12 @@
"xpack.transform.stepDefineForm.advancedEditorHelpText": "高级编辑器允许您编辑数据帧转换的数据透视表配置。",
"xpack.transform.stepDefineForm.advancedEditorHelpTextLink": "详细了解可用选项。",
"xpack.transform.stepDefineForm.advancedEditorLabel": "数据透视表配置对象",
"xpack.transform.stepDefineForm.advancedEditorRuntimeMappingsSwitchLabel": "编辑运行时映射",
"xpack.transform.stepDefineForm.advancedEditorSourceConfigSwitchLabel": "编辑 JSON 查询",
"xpack.transform.stepDefineForm.advancedEditorSwitchLabel": "编辑 JSON 配置",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalBodyText": "高级编辑器中的更改尚未应用。禁用高级编辑器将会使您的编辑丢失。",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalCancelButtonText": "取消",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalConfirmButtonText": "禁用高级编辑器",
"xpack.transform.stepDefineForm.advancedEditorSwitchModalTitle": "未应用的更改",
"xpack.transform.stepDefineForm.advancedRuntimeMappingsEditorHelpText": "高级编辑器允许您编辑转换配置的运行时映射。",
"xpack.transform.stepDefineForm.advancedSourceEditorApplyButtonText": "应用更改",
"xpack.transform.stepDefineForm.advancedSourceEditorAriaLabel": "高级查询编辑器",
"xpack.transform.stepDefineForm.advancedSourceEditorHelpText": "高级编辑器允许您编辑转换配置的源查询子句。",
@ -22200,8 +22197,6 @@
"xpack.transform.stepDefineForm.pivotLabel": "数据透视表",
"xpack.transform.stepDefineForm.queryPlaceholderKql": "例如,{example}",
"xpack.transform.stepDefineForm.queryPlaceholderLucene": "例如,{example}",
"xpack.transform.stepDefineForm.runtimeMappingsLabel": "运行时映射",
"xpack.transform.stepDefineForm.runtimeMappingsListLabel": "{runtimeFields}",
"xpack.transform.stepDefineForm.savedSearchLabel": "已保存搜索",
"xpack.transform.stepDefineForm.sortFieldOptionsEmptyError": "没有日期字段可用于排序。要使用其他字段类型,请将配置复制到剪贴板,然后继续在控制台中创建转换。",
"xpack.transform.stepDefineForm.sortHelpText": "选择要用于标识最新文档的日期字段。",

View file

@ -62,6 +62,7 @@ export default function ({ getService }: FtrProviderContext) {
{ color: '#D3DAE6', percentage: 8 },
{ color: '#F5F7FA', percentage: 15 },
],
runtimeFieldsEditorContent: ['{', ' "uppercase_y": {', ' "type": "keyword",'],
row: {
type: 'classification',
status: 'stopped',
@ -113,9 +114,9 @@ export default function ({ getService }: FtrProviderContext) {
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"uppercase_y":{"type":"keyword","script":"emit(params._source.y.toUpperCase())"}}',
]);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(
testData.expected.runtimeFieldsEditorContent
);
await ml.testExecution.logTestStep('inputs the dependent variable');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputExists();

View file

@ -72,6 +72,11 @@ export default function ({ getService }: FtrProviderContext) {
// anti-aliasing
{ color: '#F5F7FA', percentage: 30 },
],
runtimeFieldsEditorContent: [
'{',
' "lowercase_central_air": {',
' "type": "keyword",',
],
row: {
type: 'outlier_detection',
status: 'stopped',
@ -124,9 +129,9 @@ export default function ({ getService }: FtrProviderContext) {
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"lowercase_central_air":{"type":"keyword","script":"emit(params._source.CentralAir.toLowerCase())"}}',
]);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(
testData.expected.runtimeFieldsEditorContent
);
await ml.testExecution.logTestStep('does not display the dependent variable input');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputMissing();

View file

@ -55,6 +55,7 @@ export default function ({ getService }: FtrProviderContext) {
{ color: '#F5F7FA', percentage: 10 },
{ color: '#D3DAE6', percentage: 3 },
],
runtimeFieldsEditorContent: ['{', ' "uppercase_stab": {', ' "type": "keyword",'],
row: {
type: 'regression',
status: 'stopped',
@ -107,9 +108,9 @@ export default function ({ getService }: FtrProviderContext) {
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"uppercase_stab":{"type":"keyword","script":"emit(params._source.stabf.toUpperCase())"}}',
]);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(
testData.expected.runtimeFieldsEditorContent
);
await ml.testExecution.logTestStep('inputs the dependent variable');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputExists();