diff --git a/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.test.ts b/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.test.ts index 56758da0415b0..714ef278c0029 100644 --- a/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.test.ts +++ b/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.test.ts @@ -211,6 +211,22 @@ describe('convertUIStepsToDSL', () => { expect(dsl.steps).toHaveLength(0); }); + it('strips undefined fields from action steps', () => { + const uiSteps: StreamlangStepWithUIAttributes[] = [ + { + customIdentifier: '1', + action: 'set', + to: 'foo', + value: 'bar', + description: undefined, + parentId: null, + }, + ]; + const dsl = convertUIStepsToDSL(uiSteps); + expect(dsl.steps[0]).not.toHaveProperty('description'); + expect(dsl.steps[0]).toMatchObject({ action: 'set', to: 'foo', value: 'bar' }); + }); + it('nests else-branch steps under condition.else using branch attribute', () => { const uiSteps: StreamlangStepWithUIAttributes[] = [ { diff --git a/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.ts b/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.ts index c4458accc1fc0..6802343536ac1 100644 --- a/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.ts +++ b/x-pack/platform/packages/shared/kbn-streamlang/src/transpilers/shared/convert_for_ui.ts @@ -76,6 +76,9 @@ export const convertStepToUIDefinition = (obj: T): T => + Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as T; + type StreamlangStepWithUIProps = StreamlangStep & { parentId: string | null; branch?: StreamlangUIBranch; @@ -157,7 +160,10 @@ export const convertUIStepsToDSL = ( : { ...whereRest, customIdentifier, condition }; } else { const { parentId, branch, customIdentifier, ...actionRest } = step; - return removeCustomIdentifiers ? actionRest : { ...actionRest, customIdentifier }; + const actionRestSanitised = stripUndefinedValues(actionRest); + return removeCustomIdentifiers + ? actionRestSanitised + : { ...actionRestSanitised, customIdentifier }; } } diff --git a/x-pack/platform/plugins/private/translations/translations/de-DE.json b/x-pack/platform/plugins/private/translations/translations/de-DE.json index a2083e465872c..fadcbdc45c9a2 100644 --- a/x-pack/platform/plugins/private/translations/translations/de-DE.json +++ b/x-pack/platform/plugins/private/translations/translations/de-DE.json @@ -50877,9 +50877,6 @@ "xpack.streams.enrichment.processor.discardChanges.confirmButtonText": "Verwerfen", "xpack.streams.enrichment.processor.discardChanges.message": "Möchten Sie Ihre Änderungen wirklich verwerfen?", "xpack.streams.enrichment.processor.discardChanges.title": "Änderungen verwerfen?", - "xpack.streams.enrichment.processor.editDescription.cancelButtonLabel": "Abbrechen", - "xpack.streams.enrichment.processor.editDescription.fieldAriaLabel": "Beschreibung des Prozessors", - "xpack.streams.enrichment.processor.editDescription.helpText": "Erklären Sie diesen Schritt, da er die Metadaten überschreiben würde. Wenn Sie die Beschreibung entfernen, werden die Metadaten wieder angezeigt.", "xpack.streams.enrichment.simulation.dateSuggestionsError": "Beim Abrufen der Vorschläge für Datumsformate ist ein Fehler aufgetreten.", "xpack.streams.enrichment.simulation.simulationRunError": "Beim Ausführen der Simulation ist ein Problem aufgetreten.", "xpack.streams.enrichment.yamlMode.runSimulationButton.ariaLabel": "Simulation ausführen", @@ -51648,7 +51645,6 @@ "xpack.streams.streamDetailView.managementTab.bottomBar.onlySimulate": "Sie haben nicht die erforderlichen Berechtigungen, um Änderungen zu speichern.", "xpack.streams.streamDetailView.managementTab.bottomBar.viewCode": "API-Anfrage anzeigen", "xpack.streams.streamDetailView.managementTab.enrichment.addButtonText": "Erstellen", - "xpack.streams.streamDetailView.managementTab.enrichment.addDescriptionButtonText": "Beschreibung hinzufügen", "xpack.streams.streamDetailView.managementTab.enrichment.appendProcessorDescription": "Hängt {value} an „{field}“ an", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionPlural": "Verkettet die Werte {fromLength}.", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionSingular": "Verkettet den Wert {fromLength}.", @@ -51712,7 +51708,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.dissectProcessorFlyout.tryAgain": "Wiederholen", "xpack.streams.streamDetailView.managementTab.enrichment.dropProcessorDescription": "Legt Dokumente ab", "xpack.streams.streamDetailView.managementTab.enrichment.duplicateItemButtonText": "Duplikat", - "xpack.streams.streamDetailView.managementTab.enrichment.editDescriptionButtonText": "Beschreibung bearbeiten", "xpack.streams.streamDetailView.managementTab.enrichment.editItemButtonText": "Bearbeiten", "xpack.streams.streamDetailView.managementTab.enrichment.enrichProcessorDescription": "Daten mit der Richtlinie „{policy_name}“ anreichern", "xpack.streams.streamDetailView.managementTab.enrichment.errorPanel.title": "{count, plural, one {# Validation error or issue} other {# Validation errors or issues}}", @@ -51974,7 +51969,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.refreshSuggestions": "Muster generieren", "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.tryAgain": "Wiederholen", "xpack.streams.streamDetailView.managementTab.enrichment.removeByPrefixProcessorDescription": "Entfernt {field} und alle verschachtelten Felder", - "xpack.streams.streamDetailView.managementTab.enrichment.removeDescriptionButtonText": "Beschreibung entfernen", "xpack.streams.streamDetailView.managementTab.enrichment.removeProcessorDescription": "Entfernt {field}", "xpack.streams.streamDetailView.managementTab.enrichment.renameProcessorDescription": "Benennt „{field}“ in „{newField}“ um.", "xpack.streams.streamDetailView.managementTab.enrichment.saveChangesError": "Beim Speichern der Änderungen der Prozessoren ist ein Problem aufgetreten.", diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 32dcb5b83bf01..7960f526f7196 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -50707,9 +50707,6 @@ "xpack.streams.enrichment.processor.discardChanges.confirmButtonText": "Abandonner", "xpack.streams.enrichment.processor.discardChanges.message": "Voulez-vous vraiment abandonner vos modifications ?", "xpack.streams.enrichment.processor.discardChanges.title": "Abandonner les modifications ?", - "xpack.streams.enrichment.processor.editDescription.cancelButtonLabel": "Annuler", - "xpack.streams.enrichment.processor.editDescription.fieldAriaLabel": "Description du processeur", - "xpack.streams.enrichment.processor.editDescription.helpText": "Expliquez cette étape, cela écrasera les métadonnées. Si vous décidez de supprimer la description, les métadonnées réapparaîtront.", "xpack.streams.enrichment.simulation.dateSuggestionsError": "Une erreur s'est produite lors de la récupération des suggestions de formats de date.", "xpack.streams.enrichment.simulation.simulationRunError": "Un problème s'est produit lors de l'exécution de la simulation.", "xpack.streams.enrichment.yamlMode.runSimulationButton.ariaLabel": "Exécuter la simulation", @@ -51472,7 +51469,6 @@ "xpack.streams.streamDetailView.managementTab.bottomBar.onlySimulate": "Vous n'avez pas les privilèges suffisants pour enregistrer les modifications.", "xpack.streams.streamDetailView.managementTab.bottomBar.viewCode": "Afficher la requête API", "xpack.streams.streamDetailView.managementTab.enrichment.addButtonText": "Créer", - "xpack.streams.streamDetailView.managementTab.enrichment.addDescriptionButtonText": "Ajouter une description", "xpack.streams.streamDetailView.managementTab.enrichment.appendProcessorDescription": "Ajoute {value} à \"{field}\"", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionPlural": "Concatène les valeurs {fromLength}.", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionSingular": "Concatène la valeur {fromLength}.", @@ -51536,7 +51532,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.dissectProcessorFlyout.tryAgain": "Réessayer", "xpack.streams.streamDetailView.managementTab.enrichment.dropProcessorDescription": "Abandonne des documents", "xpack.streams.streamDetailView.managementTab.enrichment.duplicateItemButtonText": "Dupliquer", - "xpack.streams.streamDetailView.managementTab.enrichment.editDescriptionButtonText": "Modifier la description", "xpack.streams.streamDetailView.managementTab.enrichment.editItemButtonText": "Modifier", "xpack.streams.streamDetailView.managementTab.enrichment.enrichProcessorDescription": "Enrichir les données avec la politique \"{policy_name}\"", "xpack.streams.streamDetailView.managementTab.enrichment.errorPanel.title": "{count, plural, one {# Validation error or issue} other {# Erreurs ou problèmes de validation}}", @@ -51801,7 +51796,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.refreshSuggestions": "Générer un modèle", "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.tryAgain": "Réessayer", "xpack.streams.streamDetailView.managementTab.enrichment.removeByPrefixProcessorDescription": "Supprime {field} et tous les champs imbriqués", - "xpack.streams.streamDetailView.managementTab.enrichment.removeDescriptionButtonText": "Supprimer la description", "xpack.streams.streamDetailView.managementTab.enrichment.removeProcessorDescription": "Supprime {field}", "xpack.streams.streamDetailView.managementTab.enrichment.renameProcessorDescription": "Renomme « {field} » en « {newField} »", "xpack.streams.streamDetailView.managementTab.enrichment.saveChangesError": "Un problème a eu lieu lors de l'enregistrement des modifications des processeurs.", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 566e0adf5d809..c174bbcc1dab9 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -51065,9 +51065,6 @@ "xpack.streams.enrichment.processor.discardChanges.confirmButtonText": "破棄", "xpack.streams.enrichment.processor.discardChanges.message": "変更を破棄しますか?", "xpack.streams.enrichment.processor.discardChanges.title": "変更を破棄しますか?", - "xpack.streams.enrichment.processor.editDescription.cancelButtonLabel": "キャンセル", - "xpack.streams.enrichment.processor.editDescription.fieldAriaLabel": "プロセッサーの説明", - "xpack.streams.enrichment.processor.editDescription.helpText": "このステップについて説明します。これによりメタデータが上書きされます。説明を削除すると、メタデータが再び表示されます。", "xpack.streams.enrichment.simulation.dateSuggestionsError": "日付形式の提案を取得中にエラーが発生しました。", "xpack.streams.enrichment.simulation.simulationRunError": "シミュレーションの実行中に問題が発生しました。", "xpack.streams.enrichment.yamlMode.runSimulationButton.ariaLabel": "シミュレーションを実行", @@ -51836,7 +51833,6 @@ "xpack.streams.streamDetailView.managementTab.bottomBar.onlySimulate": "変更を保存するのに十分な権限がありません。", "xpack.streams.streamDetailView.managementTab.bottomBar.viewCode": "APIリクエストを表示", "xpack.streams.streamDetailView.managementTab.enrichment.addButtonText": "作成", - "xpack.streams.streamDetailView.managementTab.enrichment.addDescriptionButtonText": "説明を追加", "xpack.streams.streamDetailView.managementTab.enrichment.appendProcessorDescription": "「{field}」の末尾に{value}を追加します", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionPlural": "{fromLength}の値を連結します。", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionSingular": "{fromLength}値を連結します。", @@ -51900,7 +51896,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.dissectProcessorFlyout.tryAgain": "再試行", "xpack.streams.streamDetailView.managementTab.enrichment.dropProcessorDescription": "ドキュメントをドロップします", "xpack.streams.streamDetailView.managementTab.enrichment.duplicateItemButtonText": "複製", - "xpack.streams.streamDetailView.managementTab.enrichment.editDescriptionButtonText": "説明を編集", "xpack.streams.streamDetailView.managementTab.enrichment.editItemButtonText": "編集", "xpack.streams.streamDetailView.managementTab.enrichment.enrichProcessorDescription": "ポリシー「{policy_name}」でデータをエンリッチ", "xpack.streams.streamDetailView.managementTab.enrichment.errorPanel.title": "{count, plural, one {# Validation error or issue} other {#件の検証エラーまたは問題}}", @@ -52161,7 +52156,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.refreshSuggestions": "パターンを生成", "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.tryAgain": "再試行", "xpack.streams.streamDetailView.managementTab.enrichment.removeByPrefixProcessorDescription": "{field}とネストされたすべてのフィールドを削除します", - "xpack.streams.streamDetailView.managementTab.enrichment.removeDescriptionButtonText": "説明を削除", "xpack.streams.streamDetailView.managementTab.enrichment.removeProcessorDescription": "{field} を削除します", "xpack.streams.streamDetailView.managementTab.enrichment.renameProcessorDescription": "「{field}」の名前を「{newField}」に変更します", "xpack.streams.streamDetailView.managementTab.enrichment.saveChangesError": "プロセッサーの変更の保存中に問題が発生しました。", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index 4f1b3c8bd9f4c..45129d6d80b7b 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -51056,9 +51056,6 @@ "xpack.streams.enrichment.processor.discardChanges.confirmButtonText": "丢弃", "xpack.streams.enrichment.processor.discardChanges.message": "是否确定要舍弃您的更改?", "xpack.streams.enrichment.processor.discardChanges.title": "放弃更改?", - "xpack.streams.enrichment.processor.editDescription.cancelButtonLabel": "取消", - "xpack.streams.enrichment.processor.editDescription.fieldAriaLabel": "处理器说明", - "xpack.streams.enrichment.processor.editDescription.helpText": "解释这一步,这将覆盖元数据。如果您决定删除描述,元数据会重新显示出来。", "xpack.streams.enrichment.simulation.dateSuggestionsError": "在获取日期格式建议时发生错误。", "xpack.streams.enrichment.simulation.simulationRunError": "运行模拟时出现问题。", "xpack.streams.enrichment.yamlMode.runSimulationButton.ariaLabel": "运行模拟", @@ -51827,7 +51824,6 @@ "xpack.streams.streamDetailView.managementTab.bottomBar.onlySimulate": "您没有足够的权限来保存更改。", "xpack.streams.streamDetailView.managementTab.bottomBar.viewCode": "查看 API 请求", "xpack.streams.streamDetailView.managementTab.enrichment.addButtonText": "创建", - "xpack.streams.streamDetailView.managementTab.enrichment.addDescriptionButtonText": "添加描述", "xpack.streams.streamDetailView.managementTab.enrichment.appendProcessorDescription": "将 {value} 追加到“{field}”字段", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionPlural": "串联 {fromLength} 个值。", "xpack.streams.streamDetailView.managementTab.enrichment.concatProcessorDescriptionSingular": "串联 {fromLength} 个值。", @@ -51891,7 +51887,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.dissectProcessorFlyout.tryAgain": "重试", "xpack.streams.streamDetailView.managementTab.enrichment.dropProcessorDescription": "Drops文档", "xpack.streams.streamDetailView.managementTab.enrichment.duplicateItemButtonText": "复制", - "xpack.streams.streamDetailView.managementTab.enrichment.editDescriptionButtonText": "编辑描述", "xpack.streams.streamDetailView.managementTab.enrichment.editItemButtonText": "编辑", "xpack.streams.streamDetailView.managementTab.enrichment.enrichProcessorDescription": "使用策略“{policy_name}”扩充数据", "xpack.streams.streamDetailView.managementTab.enrichment.errorPanel.title": "{count, plural, one {# Validation error or issue} other {# 个验证错误或问题}}", @@ -52154,7 +52149,6 @@ "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.refreshSuggestions": "生成模式", "xpack.streams.streamDetailView.managementTab.enrichment.processorFlyout.tryAgain": "重试", "xpack.streams.streamDetailView.managementTab.enrichment.removeByPrefixProcessorDescription": "移除 {field} 和所有嵌套字段", - "xpack.streams.streamDetailView.managementTab.enrichment.removeDescriptionButtonText": "删除说明", "xpack.streams.streamDetailView.managementTab.enrichment.removeProcessorDescription": "移除 {field}", "xpack.streams.streamDetailView.managementTab.enrichment.renameProcessorDescription": "将“{field}”重命名为“{newField}”", "xpack.streams.streamDetailView.managementTab.enrichment.saveChangesError": "保存处理器的更改时出现问题。", diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/interactive_mode_machine/interactive_mode_machine.ts b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/interactive_mode_machine/interactive_mode_machine.ts index 8b7be8081746b..cf76aa9d39216 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/interactive_mode_machine/interactive_mode_machine.ts +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/interactive_mode_machine/interactive_mode_machine.ts @@ -578,6 +578,7 @@ export const interactiveModeMachine = setup({ 'step.change': { actions: [ { type: 'reassignSteps' }, + { type: 'syncToDSL' }, { type: 'sendStepsToSimulator', params: ({ event }) => event }, ], }, diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/steps_state_machine.ts b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/steps_state_machine.ts index 48afe4391b52e..e6259267ea6fd 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/steps_state_machine.ts +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/steps_state_machine.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { isEqual, isUndefined, omitBy } from 'lodash'; import type { ActorRefFrom, SnapshotFrom } from 'xstate'; import { and, assign, forwardTo, sendTo, setup } from 'xstate'; import type { @@ -18,6 +19,15 @@ import type { StepContext, StepEvent, StepInput } from './types'; export type StepActorRef = ActorRefFrom; export type StepActorSnapshot = SnapshotFrom; +// Strips customIdentifier and undefined values from a step +const sanitiseStep = ({ customIdentifier, ...restOfStep }: StreamlangStepWithUIAttributes) => + omitBy(restOfStep, isUndefined); + +const isStepUpdated = ( + step: StreamlangStepWithUIAttributes, + originalStep: StreamlangStepWithUIAttributes +): boolean => !isEqual(sanitiseStep(step), sanitiseStep(originalStep)); + export const stepMachine = setup({ types: { input: {} as StepInput, @@ -73,7 +83,7 @@ export const stepMachine = setup({ return { step: updatedStep, previousStep: updatedStep, - isUpdated: true, + isUpdated: isStepUpdated(updatedStep, context.originalStep), }; }), changeParent: assign( @@ -90,7 +100,7 @@ export const stepMachine = setup({ return { step: updatedStep, previousStep: updatedStep, - isUpdated: true, + isUpdated: isStepUpdated(updatedStep, context.originalStep), }; } ), @@ -99,7 +109,7 @@ export const stepMachine = setup({ })), markAsUpdated: assign(({ context }) => ({ previousStep: context.step, - isUpdated: true, + isUpdated: isStepUpdated(context.step, context.originalStep), })), forwardEventToParent: forwardTo(({ context }) => context.parentRef), notifyStepSave: sendTo( @@ -172,6 +182,7 @@ export const stepMachine = setup({ id: 'processor', context: ({ input }) => ({ parentRef: input.parentRef, + originalStep: input.step, previousStep: input.step, step: input.step, isNew: input.isNew ?? false, diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/types.ts b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/types.ts index 459b9a31b2053..e9965575d9074 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/types.ts +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/steps_state_machine/types.ts @@ -36,6 +36,7 @@ export type StepParentActor = Omit & { export interface StepContext { parentRef: StepParentActor; + originalStep: StreamlangStepWithUIAttributes; previousStep: StreamlangStepWithUIAttributes; step: StreamlangStepWithUIAttributes; isNew: boolean; diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/stream_enrichment_state_machine/stream_enrichment_state_machine.ts b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/stream_enrichment_state_machine/stream_enrichment_state_machine.ts index f49f88b4226bc..f472456836699 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/stream_enrichment_state_machine/stream_enrichment_state_machine.ts +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/state_management/stream_enrichment_state_machine/stream_enrichment_state_machine.ts @@ -28,6 +28,7 @@ import { streamlangDSLSchemaStrict, type StreamlangDSL, } from '@kbn/streamlang/types/streamlang'; +import { isEqual } from 'lodash'; import type { EnrichmentDataSource, EnrichmentUrlState, @@ -728,9 +729,9 @@ const hasChanges = (nextStreamlangDSL: StreamlangDSL, previousStreamlangDSL: Str if (!isValidSchema) { return true; } else { - return ( - JSON.stringify(sanitiseForEditing(nextStreamlangDSL)) !== - JSON.stringify(sanitiseForEditing(previousStreamlangDSL)) + return !isEqual( + sanitiseForEditing(nextStreamlangDSL), + sanitiseForEditing(previousStreamlangDSL) ); } }; diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/edit_step_description_modal.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/edit_step_description_modal.tsx deleted file mode 100644 index 7c854526b5e58..0000000000000 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/edit_step_description_modal.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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, { useMemo, useState } from 'react'; -import { - EuiButton, - EuiButtonEmpty, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, - EuiSpacer, - EuiText, - EuiFieldText, - useEuiTheme, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import { i18n } from '@kbn/i18n'; -import type { StreamlangProcessorDefinitionWithUIAttributes } from '@kbn/streamlang'; -import { getStepDescription } from './utils'; -import { - ADD_DESCRIPTION_MENU_LABEL, - DESCRIPTION_FIELD_ARIA_LABEL, - DESCRIPTION_HELP_TEXT, - EDIT_DESCRIPTION_MENU_LABEL, -} from './translations'; - -export interface EditStepDescriptionModalProps { - step: StreamlangProcessorDefinitionWithUIAttributes; - onSave: (description: string) => void; - onCancel: () => void; -} - -export const EditStepDescriptionModal: React.FC = ({ - step, - onSave, - onCancel, -}) => { - const { euiTheme } = useEuiTheme(); - const modalHeaderCss = css` - padding-block-end: ${euiTheme.size.xs}; - `; - - const initialValue = useMemo(() => { - if (step.description && step.description.trim().length > 0) { - return step.description; - } - - return getStepDescription({ - ...step, - description: undefined, - }); - }, [step]); - - const [value, setValue] = useState(initialValue); - - const handleSave = () => { - onSave(value); - }; - - const isEditMode = Boolean(step.description?.trim()); - const title = isEditMode ? EDIT_DESCRIPTION_MENU_LABEL : ADD_DESCRIPTION_MENU_LABEL; - const helpText = DESCRIPTION_HELP_TEXT; - - return ( - - - {title} - - - - {helpText} - - - setValue(e.target.value)} - aria-label={DESCRIPTION_FIELD_ARIA_LABEL} - /> - - - - {i18n.translate('xpack.streams.enrichment.processor.editDescription.cancelButtonLabel', { - defaultMessage: 'Cancel', - })} - - - {title} - - - - ); -}; diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/list_item.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/list_item.tsx index c769a1170166f..8858fd058a5cf 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/list_item.tsx +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/list_item.tsx @@ -8,6 +8,7 @@ import { EuiBadge, EuiButtonEmpty, + EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiPanel, @@ -21,9 +22,13 @@ import { i18n } from '@kbn/i18n'; import type { Condition } from '@kbn/streamlang'; import { isActionBlock } from '@kbn/streamlang'; import { useSelector } from '@xstate/react'; -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; +import useToggle from 'react-use/lib/useToggle'; import type { ActionBlockProps } from '.'; -import { useStreamEnrichmentSelector } from '../../../state_management/stream_enrichment_state_machine'; +import { + useInteractiveModeSelector, + useStreamEnrichmentSelector, +} from '../../../state_management/stream_enrichment_state_machine'; import { selectValidationErrors } from '../../../state_management/stream_enrichment_state_machine/selectors'; import { ConditionDisplay } from '../../../../shared'; import { getStepPanelColour } from '../../../utils'; @@ -54,6 +59,19 @@ export const ActionBlockListItem = (props: ActionBlockProps) => { // For the inner description we once again invert the colours const descriptionPanelColour = getStepPanelColour(level + 1); + const [isEditingDescription, toggleEditingDescription] = useToggle(false); + const [editValue, setEditValue] = useState(''); + const inputRef = useRef(null); + const canEdit = useInteractiveModeSelector((snapshot) => snapshot.can({ type: 'step.edit' })); + const isEditable = !readOnly && canEdit; + + useEffect(() => { + if (isEditingDescription && inputRef.current) { + inputRef.current.focus(); + inputRef.current.select(); + } + }, [isEditingDescription]); + if (!isActionBlock(step)) return null; const stepDescription = getStepDescription(step); @@ -63,6 +81,32 @@ export const ActionBlockListItem = (props: ActionBlockProps) => { stepRef.send({ type: 'step.edit' }); }; + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + saveDescription(); + toggleEditingDescription(false); + } else if (e.key === 'Escape') { + e.preventDefault(); + toggleEditingDescription(false); + } + }; + + const handleDescriptionClick = () => { + if (isEditable) { + setEditValue(stepDescription); + toggleEditingDescription(true); + } + }; + + const saveDescription = () => { + const trimmedEditValue = editValue.trim(); + if (stepDescription !== trimmedEditValue) { + stepRef.send({ type: 'step.changeDescription', description: trimmedEditValue }); + } + toggleEditingDescription(false); + }; + return ( <> {/* The step under edit is part of the same root level hierarchy, @@ -232,20 +276,55 @@ export const ActionBlockListItem = (props: ActionBlockProps) => { } )} /> + ) : isEditingDescription ? ( + setEditValue(e.target.value)} + css={css` + font-family: ${euiTheme.font.familyCode}; + font-size: ${euiTheme.size.m}; + `} + /> ) : ( - - + - {stepDescription} - + + {stepDescription} + + )} diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/translations.ts b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/translations.ts deleted file mode 100644 index 1d12d428c46e6..0000000000000 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/translations.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; - -export const ADD_DESCRIPTION_MENU_LABEL = i18n.translate( - 'xpack.streams.streamDetailView.managementTab.enrichment.addDescriptionButtonText', - { - defaultMessage: 'Add description', - } -); - -export const EDIT_DESCRIPTION_MENU_LABEL = i18n.translate( - 'xpack.streams.streamDetailView.managementTab.enrichment.editDescriptionButtonText', - { - defaultMessage: 'Edit description', - } -); - -export const REMOVE_DESCRIPTION_MENU_LABEL = i18n.translate( - 'xpack.streams.streamDetailView.managementTab.enrichment.removeDescriptionButtonText', - { - defaultMessage: 'Remove description', - } -); - -export const DESCRIPTION_HELP_TEXT = i18n.translate( - 'xpack.streams.enrichment.processor.editDescription.helpText', - { - defaultMessage: - 'Explain this step, this would override the metadata. If you decide to remove the description, the metadata would appear back.', - } -); - -export const DESCRIPTION_FIELD_ARIA_LABEL = i18n.translate( - 'xpack.streams.enrichment.processor.editDescription.fieldAriaLabel', - { defaultMessage: 'Processor description' } -); diff --git a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/context_menu.tsx b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/context_menu.tsx index 2197594a838bd..f7ea076ee38bc 100644 --- a/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/context_menu.tsx +++ b/x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/context_menu.tsx @@ -14,7 +14,7 @@ import { useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { isActionBlock, isConditionBlock } from '@kbn/streamlang'; +import { isConditionBlock } from '@kbn/streamlang'; import { useSelector } from '@xstate/react'; import React from 'react'; import useToggle from 'react-use/lib/useToggle'; @@ -28,13 +28,7 @@ import { import { selectStreamType } from '../../state_management/stream_enrichment_state_machine/selectors'; import { collectDescendantStepIds } from '../../state_management/utils'; import type { StepConfigurationProps } from '../steps_list'; -import { EditStepDescriptionModal } from './action/edit_step_description_modal'; import { deleteProcessorPromptOptions } from './action/prompt_options'; -import { - ADD_DESCRIPTION_MENU_LABEL, - EDIT_DESCRIPTION_MENU_LABEL, - REMOVE_DESCRIPTION_MENU_LABEL, -} from './action/translations'; import { deleteConditionPromptOptions } from './where/prompt_options'; const moveUpItemText = i18n.translate( @@ -79,6 +73,13 @@ const deleteItemText = i18n.translate( } ); +const tooltipContent = i18n.translate( + 'xpack.streams.streamDetailView.managementTab.enrichment.stepContextMenuButtonAriaLabel', + { + defaultMessage: 'Step context menu', + } +); + type StepContextMenuProps = Pick< StepConfigurationProps, 'stepRef' | 'stepUnderEdit' | 'isFirstStepInLevel' | 'isLastStepInLevel' @@ -119,13 +120,8 @@ export const StepContextMenu: React.FC = ({ const streamType = useStreamEnrichmentSelector((snapshot) => selectStreamType(snapshot.context)); const isWhere = isConditionBlock(step); - const hasCustomDescription = - isActionBlock(step) && - typeof step.description === 'string' && - step.description.trim().length > 0; const [isPopoverOpen, togglePopover] = useToggle(false); - const [isEditDescriptionModalOpen, toggleEditDescriptionModal] = useToggle(false); const menuPopoverId = useGeneratedHtmlId({ prefix: 'stepContextMenuPopover', @@ -205,49 +201,6 @@ export const StepContextMenu: React.FC = ({ > {moveDownItemText} , - ...(!isWhere - ? hasCustomDescription - ? [ - { - togglePopover(false); - toggleEditDescriptionModal(true); - }} - > - {EDIT_DESCRIPTION_MENU_LABEL} - , - { - togglePopover(false); - stepRef.send({ type: 'step.changeDescription', description: '' }); - }} - > - {REMOVE_DESCRIPTION_MENU_LABEL} - , - ] - : [ - { - togglePopover(false); - toggleEditDescriptionModal(true); - }} - > - {ADD_DESCRIPTION_MENU_LABEL} - , - ] - : []), = ({ ]; const button = ( - + = ({ ); return ( - <> - togglePopover(false)} - panelPaddingSize="none" - > - - - {isEditDescriptionModalOpen && !isWhere && isActionBlock(step) && ( - toggleEditDescriptionModal(false)} - onSave={(description) => { - toggleEditDescriptionModal(false); - stepRef.send({ type: 'step.changeDescription', description }); - }} - /> - )} - + togglePopover(false)} + panelPaddingSize="none" + > + + ); };