From 61ae8927faa1686ae80d2a939921cc11ed750d51 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 25 Jun 2020 17:47:07 -0700 Subject: [PATCH 1/6] Fixed adding an extra space character on selecting alert variable in action text fields. --- .../components/builtin_action_types/email/email_params.tsx | 2 +- .../builtin_action_types/es_index/es_index_params.tsx | 2 +- .../builtin_action_types/pagerduty/pagerduty_params.tsx | 2 +- .../builtin_action_types/server_log/server_log_params.tsx | 2 +- .../components/builtin_action_types/slack/slack_params.tsx | 2 +- .../components/builtin_action_types/webhook/webhook_params.tsx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx index 58a9685fc73d9..f76b44e415f9b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx @@ -36,7 +36,7 @@ export const EmailParamsFields = ({ const onSelectMessageVariable = (paramsProperty: string, variable: string) => { editAction( paramsProperty, - ((actionParams as any)[paramsProperty] ?? '').concat(` {{${variable}}}`), + !(actionParams as any)[paramsProperty] ? `{{${variable}}}` : ` {{${variable}}}`, index ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx index 0b095cdc26984..66400f3e4786d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx @@ -22,7 +22,7 @@ export const IndexParamsFields = ({ documents && documents.length > 0 ? documents[0] : null ); const onSelectMessageVariable = (variable: string) => { - const value = (xJson ?? '').concat(` {{${variable}}}`); + const value = !xJson ? `{{${variable}}}` : ` {{${variable}}}`; setXJson(value); // Keep the documents in sync with the editor content onDocumentsChange(convertToJson(value)); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx index f0b131deb1490..94e82db81477e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx @@ -98,7 +98,7 @@ const PagerDutyParamsFields: React.FunctionComponent { editAction( paramsProperty, - ((actionParams as any)[paramsProperty] ?? '').concat(` {{${variable}}}`), + !(actionParams as any)[paramsProperty] ? `{{${variable}}}` : ` {{${variable}}}`, index ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx index c19aec2a993db..c737d57c19a8a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx @@ -32,7 +32,7 @@ export const ServerLogParamsFields: React.FunctionComponent { - editAction(paramsProperty, (message ?? '').concat(` {{${variable}}}`), index); + editAction(paramsProperty, !message ? `{{${variable}}}` : ` {{${variable}}}`, index); }; return ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx index 5789d37a6bcf6..bcbe4a733b9eb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx @@ -27,7 +27,7 @@ const SlackParamsFields: React.FunctionComponent { - editAction(paramsProperty, (message ?? '').concat(` {{${variable}}}`), index); + editAction(paramsProperty, !message ? `{{${variable}}}` : ` {{${variable}}}`, index); }; return ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx index 9e802b96e16be..487d94bc1790b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx @@ -19,7 +19,7 @@ const WebhookParamsFields: React.FunctionComponent { const { body } = actionParams; const onSelectMessageVariable = (paramsProperty: string, variable: string) => { - editAction(paramsProperty, (body ?? '').concat(` {{${variable}}}`), index); + editAction(paramsProperty, !body ? `{{${variable}}}` : ` {{${variable}}}`, index); }; return ( From 3652434307236305908fb5dc2e8ee6c50f8977dd Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 30 Jun 2020 21:32:36 -0700 Subject: [PATCH 2/6] Made components for variables to be able to insert the variable by the cursor position --- .../email/email_params.tsx | 85 ++----- .../pagerduty/pagerduty_params.tsx | 207 ++++-------------- .../slack/slack_params.tsx | 50 +---- .../webhook/webhook_params.tsx | 5 +- .../text_area_with_message_variables.tsx | 92 ++++++++ .../text_field_with_message_variables.tsx | 77 +++++++ 6 files changed, 247 insertions(+), 269 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx index f76b44e415f9b..e377892c8fa12 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx @@ -5,11 +5,18 @@ */ import React, { Fragment, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiFieldText, EuiComboBox, EuiTextArea, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; +import { EuiComboBox, EuiTextArea, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { EmailActionParams } from '../types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { + AddMessageVariables, + onSelectMessageVariable, + onChangeWithMessageVariable, + onClickWithMessageVariable, +} from '../../add_message_variables'; +import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables'; +import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; export const EmailParamsFields = ({ actionParams, @@ -33,14 +40,6 @@ export const EmailParamsFields = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const onSelectMessageVariable = (paramsProperty: string, variable: string) => { - editAction( - paramsProperty, - !(actionParams as any)[paramsProperty] ? `{{${variable}}}` : ` {{${variable}}}`, - index - ); - }; - return ( - onSelectMessageVariable('subject', variable) - } - paramsProperty="subject" - /> - } > - 0 && subject !== undefined} - name="subject" - data-test-subj="emailSubjectInput" - value={subject || ''} - onChange={(e) => { - editAction('subject', e.target.value, index); - }} - onBlur={() => { - if (!subject) { - editAction('subject', '', index); - } - }} + - 0 && message !== undefined} + - onSelectMessageVariable('message', variable) - } - paramsProperty="message" - /> - } - > - 0 && message !== undefined} - value={message || ''} - name="message" - data-test-subj="emailMessageInput" - onChange={(e) => { - editAction('message', e.target.value, index); - }} - onBlur={() => { - if (!message) { - editAction('message', '', index); - } - }} - /> - + /> ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx index 94e82db81477e..94ba92a599ce0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { Fragment } from 'react'; -import { EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { PagerDutyActionParams } from '.././types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables'; const PagerDutyParamsFields: React.FunctionComponent> = ({ actionParams, @@ -94,15 +94,6 @@ const PagerDutyParamsFields: React.FunctionComponent { - editAction( - paramsProperty, - !(actionParams as any)[paramsProperty] ? `{{${variable}}}` : ` {{${variable}}}`, - index - ); - }; - return ( @@ -159,29 +150,13 @@ const PagerDutyParamsFields: React.FunctionComponent - onSelectMessageVariable('dedupKey', variable) - } - paramsProperty="dedupKey" - /> - } > - ) => { - editAction('dedupKey', e.target.value, index); - }} - onBlur={() => { - if (!dedupKey) { - editAction('dedupKey', '', index); - } - }} + @@ -196,32 +171,13 @@ const PagerDutyParamsFields: React.FunctionComponent - onSelectMessageVariable('timestamp', variable) - } - paramsProperty="timestamp" - /> - } > - 0 && timestamp !== undefined} - onChange={(e: React.ChangeEvent) => { - editAction('timestamp', e.target.value, index); - }} - onBlur={() => { - if (timestamp?.trim()) { - editAction('timestamp', timestamp.trim(), index); - } else { - editAction('timestamp', '', index); - } - }} + @@ -234,29 +190,13 @@ const PagerDutyParamsFields: React.FunctionComponent - onSelectMessageVariable('component', variable) - } - paramsProperty="component" - /> - } > - ) => { - editAction('component', e.target.value, index); - }} - onBlur={() => { - if (!component) { - editAction('component', '', index); - } - }} + onSelectMessageVariable('group', variable)} - paramsProperty="group" - /> - } > - ) => { - editAction('group', e.target.value, index); - }} - onBlur={() => { - if (!group) { - editAction('group', '', index); - } - }} + onSelectMessageVariable('source', variable)} - paramsProperty="source" - /> - } > - ) => { - editAction('source', e.target.value, index); - }} - onBlur={() => { - if (!source) { - editAction('source', '', index); - } - }} + - onSelectMessageVariable('summary', variable) - } - paramsProperty="summary" - /> - } > - 0 && summary !== undefined} - name="summary" - value={summary || ''} - data-test-subj="pagerdutySummaryInput" - onChange={(e: React.ChangeEvent) => { - editAction('summary', e.target.value, index); - }} - onBlur={() => { - if (!summary) { - editAction('summary', '', index); - } - }} + onSelectMessageVariable('class', variable)} - paramsProperty="class" - /> - } > - ) => { - editAction('class', e.target.value, index); - }} - onBlur={() => { - if (!actionParams.class) { - editAction('class', '', index); - } - }} + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx index bcbe4a733b9eb..7cb786e2f0516 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx @@ -3,12 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { EuiTextArea, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { SlackActionParams } from '../types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; const SlackParamsFields: React.FunctionComponent> = ({ actionParams, @@ -26,50 +26,22 @@ const SlackParamsFields: React.FunctionComponent { - editAction(paramsProperty, !message ? `{{${variable}}}` : ` {{${variable}}}`, index); - }; - return ( - - 0 && message !== undefined} + <> + - onSelectMessageVariable('message', variable) - } - paramsProperty="message" - /> - } - > - 0 && message !== undefined} - name="message" - value={message || ''} - data-test-subj="slackMessageTextArea" - onChange={(e) => { - editAction('message', e.target.value, index); - }} - onBlur={() => { - if (!message) { - editAction('message', '', index); - } - }} - /> - - + /> + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx index 487d94bc1790b..5773a22604944 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx @@ -8,7 +8,7 @@ import { EuiFormRow, EuiCodeEditor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { WebhookActionParams } from '../types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { AddMessageVariables, onSelectMessageVariable } from '../../add_message_variables'; const WebhookParamsFields: React.FunctionComponent> = ({ actionParams, @@ -18,9 +18,6 @@ const WebhookParamsFields: React.FunctionComponent { const { body } = actionParams; - const onSelectMessageVariable = (paramsProperty: string, variable: string) => { - editAction(paramsProperty, !body ? `{{${variable}}}` : ` {{${variable}}}`, index); - }; return ( void; + label: string; +} + +export const TextAreaWithMessageVariables: React.FunctionComponent = ({ + messageVariables, + paramsProperty, + index, + inputTargetValue, + editAction, + label, +}) => { + const [cursorPositionStart, setCursorPositionStart] = useState(0); + const [cursorPositionEnd, setCursorPositionEnd] = useState(0); + + const onSelectMessageVariable = (variable: string) => { + let newValue = inputTargetValue ?? ''; + const templatedVar = `{{${variable}}}`; + const startPosition = cursorPositionStart; + const endPosition = cursorPositionEnd; + newValue = + newValue.substring(0, startPosition) + + templatedVar + + newValue.substring(endPosition, newValue.length); + setCursorPositionStart(startPosition + templatedVar.length); + setCursorPositionEnd(startPosition + templatedVar.length); + editAction(paramsProperty, newValue, index); + }; + + const onChangeWithMessageVariable = (e: React.ChangeEvent) => { + editAction(paramsProperty, e.target.value, index); + setCursorPositionStart(e.target.selectionStart ?? 0); + setCursorPositionEnd(e.target.selectionEnd ?? 0); + }; + + const onClickWithMessageVariable = (e: React.MouseEvent) => { + setCursorPositionStart(e.currentTarget.selectionStart ?? 0); + setCursorPositionEnd(e.currentTarget.selectionEnd ?? 0); + }; + + return ( + 0 && message !== undefined} + label={label} + labelAppend={ + + onSelectMessageVariable(paramsProperty, variable, index) + } + paramsProperty={paramsProperty} + /> + } + > + 0 && inputTargetValue !== undefined} + name={paramsProperty} + value={inputTargetValue} + data-test-subj={`{${paramsProperty}TextArea`} + onChange={(e: React.ChangeEvent) => + onChangeWithMessageVariable(e, paramsProperty, index) + } + onClick={(e: React.MouseEvent) => + onClickWithMessageVariable(e) + } + onBlur={() => { + if (!inputTargetValue) { + editAction(paramsProperty, '', index); + } + }} + /> + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx new file mode 100644 index 0000000000000..1e2cfc13c970b --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { useState } from 'react'; +import { EuiFieldText } from '@elastic/eui'; +import './add_message_variables.scss'; +import { AddMessageVariables } from './add_message_variables'; + +interface Props { + messageVariables: string[] | undefined; + paramsProperty: string; + index: number; + inputTargetValue?: string; + editAction: (property: string, value: any, index: number) => void; +} + +export const TextFieldWithMessageVariables: React.FunctionComponent = ({ + messageVariables, + paramsProperty, + index, + inputTargetValue, + editAction, +}) => { + const [cursorPositionStart, setCursorPositionStart] = useState(0); + const [cursorPositionEnd, setCursorPositionEnd] = useState(0); + + const onSelectMessageVariable = (variable: string) => { + let newValue = inputTargetValue ?? ''; + const templatedVar = `{{${variable}}}`; + const startPosition = cursorPositionStart; + const endPosition = cursorPositionEnd; + newValue = + newValue.substring(0, startPosition) + + templatedVar + + newValue.substring(endPosition, newValue.length); + setCursorPositionStart(startPosition + templatedVar.length); + setCursorPositionEnd(startPosition + templatedVar.length); + editAction(paramsProperty, newValue, index); + }; + + const onChangeWithMessageVariable = (e: React.ChangeEvent) => { + editAction(paramsProperty, e.target.value, index); + setCursorPositionStart(e.target.selectionStart ?? 0); + setCursorPositionEnd(e.target.selectionEnd ?? 0); + }; + + const onClickWithMessageVariable = (e: React.MouseEvent) => { + setCursorPositionStart(e.currentTarget.selectionStart ?? 0); + setCursorPositionEnd(e.currentTarget.selectionEnd ?? 0); + }; + + return ( + ) => onChangeWithMessageVariable(e)} + onClick={(e: React.MouseEvent) => onClickWithMessageVariable(e)} + onBlur={() => { + if (!inputTargetValue) { + editAction(paramsProperty, '', index); + } + setCursorPositionStart((inputTargetValue ?? '').length); + }} + append={ + onSelectMessageVariable(variable)} + paramsProperty={paramsProperty} + /> + } + /> + ); +}; From 46946c014cb2307af5e7ec0d3439635d14ca19e4 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 30 Jun 2020 21:33:59 -0700 Subject: [PATCH 3/6] cleanup --- .../builtin_action_types/email/email_params.tsx | 8 +------- .../builtin_action_types/webhook/webhook_params.tsx | 8 -------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx index e377892c8fa12..e3ae68bd4b5ba 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx @@ -5,16 +5,10 @@ */ import React, { Fragment, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiComboBox, EuiTextArea, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; +import { EuiComboBox, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { EmailActionParams } from '../types'; -import { - AddMessageVariables, - onSelectMessageVariable, - onChangeWithMessageVariable, - onClickWithMessageVariable, -} from '../../add_message_variables'; import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables'; import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx index 5773a22604944..40ac09fbf78c0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx @@ -8,7 +8,6 @@ import { EuiFormRow, EuiCodeEditor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { WebhookActionParams } from '../types'; -import { AddMessageVariables, onSelectMessageVariable } from '../../add_message_variables'; const WebhookParamsFields: React.FunctionComponent> = ({ actionParams, @@ -31,13 +30,6 @@ const WebhookParamsFields: React.FunctionComponent 0 && body !== undefined} fullWidth error={errors.body} - labelAppend={ - onSelectMessageVariable('body', variable)} - paramsProperty="body" - /> - } > Date: Wed, 1 Jul 2020 19:10:29 -0700 Subject: [PATCH 4/6] Added variables support for all components --- .../components/add_message_variables.tsx | 1 + .../email/email_params.test.tsx | 4 +- .../email/email_params.tsx | 6 +- .../es_index/es_index_params.test.tsx | 2 +- .../es_index/es_index_params.tsx | 76 ++++++---------- .../pagerduty/pagerduty_params.test.tsx | 2 +- .../pagerduty/pagerduty_params.tsx | 16 ++-- .../server_log/server_log_params.test.tsx | 4 +- .../server_log/server_log_params.tsx | 47 +++------- .../slack/slack_params.test.tsx | 8 +- .../slack/slack_params.tsx | 30 +++---- .../webhook/webhook_params.test.tsx | 8 +- .../webhook/webhook_params.tsx | 57 +++++------- .../json_editor_with_message_variables.tsx | 86 +++++++++++++++++++ .../text_area_with_message_variables.tsx | 30 +++---- .../text_field_with_message_variables.tsx | 23 +++-- 16 files changed, 215 insertions(+), 185 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx index 957c79a5c5123..655f64995d147 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx @@ -47,6 +47,7 @@ export const AddMessageVariables: React.FunctionComponent = ({ setIsVariablesPopoverOpen(true)} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.test.tsx index 053541d84c431..08616b2895a80 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.test.tsx @@ -28,7 +28,7 @@ describe('EmailParamsFields renders', () => { expect( wrapper.find('[data-test-subj="toEmailAddressInput"]').first().prop('selectedOptions') ).toStrictEqual([{ label: 'test@test.com' }]); - expect(wrapper.find('[data-test-subj="emailSubjectInput"]').length > 0).toBeTruthy(); - expect(wrapper.find('[data-test-subj="emailMessageInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="subjectInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="messageTextArea"]').length > 0).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx index e3ae68bd4b5ba..39c59a10fbc81 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_params.tsx @@ -196,7 +196,8 @@ export const EmailParamsFields = ({ editAction={editAction} messageVariables={messageVariables} paramsProperty={'subject'} - inputTargetValue={subject || ''} + inputTargetValue={subject} + errors={errors.subject as string[]} /> ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx index 1f8bfde2cd22b..4a6c13bf7f1a6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx @@ -20,7 +20,7 @@ describe('IndexParamsFields renders', () => { index={0} /> ); - expect(wrapper.find('[data-test-subj="actionIndexDoc"]').first().prop('value')).toBe(`{ + expect(wrapper.find('[data-test-subj="documentsJsonEditor"]').first().prop('value')).toBe(`{ "test": 123 }`); expect(wrapper.find('[data-test-subj="documentsAddVariableButton"]').length > 0).toBeTruthy(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx index 66400f3e4786d..fd6a3d64bd4be 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.tsx @@ -3,13 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; -import { EuiFormRow, EuiCodeEditor } from '@elastic/eui'; +import React from 'react'; import { i18n } from '@kbn/i18n'; -import { useXJsonMode } from '../../../../../../../../src/plugins/es_ui_shared/static/ace_x_json/hooks'; import { ActionParamsProps } from '../../../../types'; import { IndexActionParams } from '.././types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { JsonEditorWithMessageVariables } from '../../json_editor_with_message_variables'; export const IndexParamsFields = ({ actionParams, @@ -18,62 +16,36 @@ export const IndexParamsFields = ({ messageVariables, }: ActionParamsProps) => { const { documents } = actionParams; - const { xJsonMode, convertToJson, setXJson, xJson } = useXJsonMode( - documents && documents.length > 0 ? documents[0] : null - ); - const onSelectMessageVariable = (variable: string) => { - const value = !xJson ? `{{${variable}}}` : ` {{${variable}}}`; - setXJson(value); - // Keep the documents in sync with the editor content - onDocumentsChange(convertToJson(value)); - }; - function onDocumentsChange(updatedDocuments: string) { + const onDocumentsChange = (updatedDocuments: string) => { try { const documentsJSON = JSON.parse(updatedDocuments); editAction('documents', [documentsJSON], index); // eslint-disable-next-line no-empty } catch (e) {} - } + }; + return ( - - onSelectMessageVariable(variable)} - paramsProperty="documents" - /> + 0 ? ((documents[0] as unknown) as string) : '' + } + label={i18n.translate( + 'xpack.triggersActionsUI.components.builtinActionTypes.indexAction.documentsFieldLabel', + { + defaultMessage: 'Document to index', + } + )} + aria-label={i18n.translate( + 'xpack.triggersActionsUI.components.builtinActionTypes.indexAction.jsonDocAriaLabel', + { + defaultMessage: 'Code editor', } - > - { - setXJson(xjson); - // Keep the documents in sync with the editor content - onDocumentsChange(convertToJson(xjson)); - }} - /> - - + )} + onDocumentsChange={onDocumentsChange} + /> ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx index 94bea3c51760d..1b26b1157add9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx @@ -39,7 +39,7 @@ describe('PagerDutyParamsFields renders', () => { expect(wrapper.find('[data-test-subj="componentInput"]').length > 0).toBeTruthy(); expect(wrapper.find('[data-test-subj="groupInput"]').length > 0).toBeTruthy(); expect(wrapper.find('[data-test-subj="sourceInput"]').length > 0).toBeTruthy(); - expect(wrapper.find('[data-test-subj="pagerdutySummaryInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="summaryInput"]').length > 0).toBeTruthy(); expect(wrapper.find('[data-test-subj="dedupKeyAddVariableButton"]').length > 0).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx index 94ba92a599ce0..c8ad5f5b7080e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.tsx @@ -156,7 +156,7 @@ const PagerDutyParamsFields: React.FunctionComponent @@ -177,7 +177,8 @@ const PagerDutyParamsFields: React.FunctionComponent @@ -196,7 +197,7 @@ const PagerDutyParamsFields: React.FunctionComponent diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.test.tsx index cb905023cae44..1849a7ec9817a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.test.tsx @@ -27,7 +27,7 @@ describe('ServerLogParamsFields renders', () => { expect( wrapper.find('[data-test-subj="loggingLevelSelect"]').first().prop('value') ).toStrictEqual('trace'); - expect(wrapper.find('[data-test-subj="loggingMessageInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="messageTextArea"]').length > 0).toBeTruthy(); }); test('level param field is rendered with default value if not selected', () => { @@ -47,6 +47,6 @@ describe('ServerLogParamsFields renders', () => { expect( wrapper.find('[data-test-subj="loggingLevelSelect"]').first().prop('value') ).toStrictEqual('info'); - expect(wrapper.find('[data-test-subj="loggingMessageInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="messageTextArea"]').length > 0).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx index c737d57c19a8a..b79fa0ea94050 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log/server_log_params.tsx @@ -5,10 +5,10 @@ */ import React, { Fragment, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiSelect, EuiTextArea, EuiFormRow } from '@elastic/eui'; +import { EuiSelect, EuiFormRow } from '@elastic/eui'; import { ActionParamsProps } from '../../../../types'; import { ServerLogActionParams } from '.././types'; -import { AddMessageVariables } from '../../add_message_variables'; +import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; export const ServerLogParamsFields: React.FunctionComponent { - editAction(paramsProperty, !message ? `{{${variable}}}` : ` {{${variable}}}`, index); - }; - return ( - 0 && message !== undefined} + - onSelectMessageVariable('message', variable) - } - paramsProperty="message" - /> - } - > - 0 && message !== undefined} - value={message || ''} - name="message" - data-test-subj="loggingMessageInput" - onChange={(e) => { - editAction('message', e.target.value, index); - }} - onBlur={() => { - if (!message) { - editAction('message', '', index); - } - }} - /> - + errors={errors.message as string[]} + /> ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.test.tsx index 6efa8d64dafbe..8777c8f48e0f5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.test.tsx @@ -20,9 +20,9 @@ describe('SlackParamsFields renders', () => { index={0} /> ); - expect(wrapper.find('[data-test-subj="slackMessageTextArea"]').length > 0).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="slackMessageTextArea"]').first().prop('value') - ).toStrictEqual('test message'); + expect(wrapper.find('[data-test-subj="messageTextArea"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="messageTextArea"]').first().prop('value')).toStrictEqual( + 'test message' + ); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx index 7cb786e2f0516..80a2f9d7709cc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack_params.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { useEffect } from 'react'; -import { EuiTextArea, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { SlackActionParams } from '../types'; @@ -27,21 +26,20 @@ const SlackParamsFields: React.FunctionComponent - - + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx index 665114bd86e9b..9e57d7ae608cc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx @@ -20,10 +20,10 @@ describe('WebhookParamsFields renders', () => { index={0} /> ); - expect(wrapper.find('[data-test-subj="webhookBodyEditor"]').length > 0).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="webhookBodyEditor"]').first().prop('value') - ).toStrictEqual('test message'); + expect(wrapper.find('[data-test-subj="bodyJsonEditor"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="bodyJsonEditor"]').first().prop('value')).toStrictEqual( + 'test message' + ); expect(wrapper.find('[data-test-subj="bodyAddVariableButton"]').length > 0).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx index 40ac09fbf78c0..1dfd9e3edc2c5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.tsx @@ -3,11 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; -import { EuiFormRow, EuiCodeEditor } from '@elastic/eui'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { ActionParamsProps } from '../../../../types'; import { WebhookActionParams } from '../types'; +import { JsonEditorWithMessageVariables } from '../../json_editor_with_message_variables'; const WebhookParamsFields: React.FunctionComponent> = ({ actionParams, @@ -18,38 +18,27 @@ const WebhookParamsFields: React.FunctionComponent { const { body } = actionParams; return ( - - 0 && body !== undefined} - fullWidth - error={errors.body} - > - { - editAction('body', json, index); - }} - /> - - + { + editAction('body', json, index); + }} + /> ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx new file mode 100644 index 0000000000000..79b2c144a29e0 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { useState } from 'react'; +import { EuiCodeEditor, EuiFormRow } from '@elastic/eui'; +import './add_message_variables.scss'; +import { useXJsonMode } from '../../../../../../src/plugins/es_ui_shared/static/ace_x_json/hooks'; + +import { AddMessageVariables } from './add_message_variables'; + +interface Props { + messageVariables: string[] | undefined; + paramsProperty: string; + inputTargetValue: string; + label: string; + errors?: string[]; + areaLabel?: string; + onDocumentsChange: (data: string) => void; +} + +export const JsonEditorWithMessageVariables: React.FunctionComponent = ({ + messageVariables, + paramsProperty, + inputTargetValue, + label, + errors, + areaLabel, + onDocumentsChange, +}) => { + const [cursorPosition, setCursorPosition] = useState(null); + + const { xJsonMode, convertToJson, setXJson, xJson } = useXJsonMode(inputTargetValue ?? null); + + const onSelectMessageVariable = (variable: string) => { + const templatedVar = `{{${variable}}}`; + let newValue = ''; + if (cursorPosition) { + const cursor = cursorPosition.getCursor(); + cursorPosition.session.insert(cursor, templatedVar); + newValue = cursorPosition.session.getValue(); + } else { + newValue = templatedVar; + } + setXJson(newValue); + // Keep the documents in sync with the editor content + onDocumentsChange(convertToJson(newValue)); + }; + + const onClickWithMessageVariable = (_value: any, e: any) => { + setCursorPosition(_value); + }; + + return ( + 0 && inputTargetValue !== undefined} + label={label} + labelAppend={ + onSelectMessageVariable(variable)} + paramsProperty={paramsProperty} + /> + } + > + { + setXJson(xjson); + // Keep the documents in sync with the editor content + onDocumentsChange(convertToJson(xjson)); + }} + onCursorChange={(_value: any, e: any) => onClickWithMessageVariable(_value, e)} + /> + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx index eb5657f56da10..161edd4253208 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx @@ -15,6 +15,7 @@ interface Props { inputTargetValue?: string; editAction: (property: string, value: any, index: number) => void; label: string; + errors?: string[]; } export const TextAreaWithMessageVariables: React.FunctionComponent = ({ @@ -24,31 +25,32 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({ inputTargetValue, editAction, label, + errors, }) => { const [cursorPositionStart, setCursorPositionStart] = useState(0); const [cursorPositionEnd, setCursorPositionEnd] = useState(0); const onSelectMessageVariable = (variable: string) => { - let newValue = inputTargetValue ?? ''; + let newValue = inputTargetValue || ''; const templatedVar = `{{${variable}}}`; const startPosition = cursorPositionStart; const endPosition = cursorPositionEnd; newValue = - newValue.substring(0, startPosition) + + (inputTargetValue || '').substring(0, startPosition) + templatedVar + - newValue.substring(endPosition, newValue.length); + (inputTargetValue || '').substring(endPosition, (inputTargetValue || '').length); setCursorPositionStart(startPosition + templatedVar.length); setCursorPositionEnd(startPosition + templatedVar.length); editAction(paramsProperty, newValue, index); }; - const onChangeWithMessageVariable = (e: React.ChangeEvent) => { + const onChangeWithMessageVariable = (e: React.ChangeEvent) => { editAction(paramsProperty, e.target.value, index); setCursorPositionStart(e.target.selectionStart ?? 0); setCursorPositionEnd(e.target.selectionEnd ?? 0); }; - const onClickWithMessageVariable = (e: React.MouseEvent) => { + const onClickWithMessageVariable = (e: React.MouseEvent) => { setCursorPositionStart(e.currentTarget.selectionStart ?? 0); setCursorPositionEnd(e.currentTarget.selectionEnd ?? 0); }; @@ -56,29 +58,25 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({ return ( 0 && message !== undefined} + error={errors} + isInvalid={errors && errors.length > 0 && inputTargetValue !== undefined} label={label} labelAppend={ - onSelectMessageVariable(paramsProperty, variable, index) - } + onSelectEventHandler={(variable: string) => onSelectMessageVariable(variable)} paramsProperty={paramsProperty} /> } > 0 && inputTargetValue !== undefined} + isInvalid={errors && errors.length > 0 && inputTargetValue !== undefined} name={paramsProperty} value={inputTargetValue} - data-test-subj={`{${paramsProperty}TextArea`} - onChange={(e: React.ChangeEvent) => - onChangeWithMessageVariable(e, paramsProperty, index) - } - onClick={(e: React.MouseEvent) => + data-test-subj={`${paramsProperty}TextArea`} + onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)} + onClick={(e: React.MouseEvent) => onClickWithMessageVariable(e) } onBlur={() => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx index 1e2cfc13c970b..a764de784a3b4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx @@ -14,6 +14,7 @@ interface Props { index: number; inputTargetValue?: string; editAction: (property: string, value: any, index: number) => void; + errors?: string[]; } export const TextFieldWithMessageVariables: React.FunctionComponent = ({ @@ -22,19 +23,20 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ index, inputTargetValue, editAction, + errors, }) => { const [cursorPositionStart, setCursorPositionStart] = useState(0); const [cursorPositionEnd, setCursorPositionEnd] = useState(0); const onSelectMessageVariable = (variable: string) => { - let newValue = inputTargetValue ?? ''; + let newValue = inputTargetValue || ''; const templatedVar = `{{${variable}}}`; const startPosition = cursorPositionStart; const endPosition = cursorPositionEnd; newValue = - newValue.substring(0, startPosition) + + (inputTargetValue || '').substring(0, startPosition) + templatedVar + - newValue.substring(endPosition, newValue.length); + (inputTargetValue || '').substring(endPosition, (inputTargetValue || '').length); setCursorPositionStart(startPosition + templatedVar.length); setCursorPositionEnd(startPosition + templatedVar.length); editAction(paramsProperty, newValue, index); @@ -55,15 +57,22 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ 0 && inputTargetValue !== undefined} + data-test-subj={`${paramsProperty}Input`} + value={inputTargetValue} onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)} onClick={(e: React.MouseEvent) => onClickWithMessageVariable(e)} - onBlur={() => { + onBlur={(e: React.FocusEvent) => { if (!inputTargetValue) { editAction(paramsProperty, '', index); } - setCursorPositionStart((inputTargetValue ?? '').length); + }} + onMouseLeave={(e: React.MouseEvent) => { + if (e.currentTarget.id !== `${paramsProperty}Id`) { + setCursorPositionStart((inputTargetValue || '').length); + setCursorPositionEnd((inputTargetValue || '').length); + } }} append={ Date: Thu, 2 Jul 2020 14:35:28 -0700 Subject: [PATCH 5/6] update on handle selections for text --- .../text_area_with_message_variables.tsx | 32 +++++------------- .../text_field_with_message_variables.tsx | 33 ++++--------------- 2 files changed, 16 insertions(+), 49 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx index 98d4a234a2fc1..0b8a9349ad5fb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx @@ -27,32 +27,21 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({ label, errors, }) => { - const [cursorPositionStart, setCursorPositionStart] = useState(0); - const [cursorPositionEnd, setCursorPositionEnd] = useState(0); + const [currentTextElement, setCurrentTextElement] = useState(null); const onSelectMessageVariable = (variable: string) => { - let newValue = inputTargetValue || ''; const templatedVar = `{{${variable}}}`; - const startPosition = cursorPositionStart; - const endPosition = cursorPositionEnd; - newValue = - (inputTargetValue || '').substring(0, startPosition) + + const startPosition = currentTextElement?.selectionStart ?? 0; + const endPosition = currentTextElement?.selectionEnd ?? 0; + const newValue = + (inputTargetValue ?? '').substring(0, startPosition) + templatedVar + - (inputTargetValue || '').substring(endPosition, (inputTargetValue || '').length); - setCursorPositionStart(startPosition + templatedVar.length); - setCursorPositionEnd(endPosition + templatedVar.length); + (inputTargetValue ?? '').substring(endPosition, (inputTargetValue ?? '').length); editAction(paramsProperty, newValue, index); }; const onChangeWithMessageVariable = (e: React.ChangeEvent) => { editAction(paramsProperty, e.target.value, index); - setCursorPositionStart(e.target.selectionStart ?? 0); - setCursorPositionEnd(e.target.selectionEnd ?? 0); - }; - - const onClickWithMessageVariable = (target: HTMLInputElement) => { - setCursorPositionStart(target.selectionStart ?? 0); - setCursorPositionEnd(target.selectionEnd ?? 0); }; return ( @@ -76,12 +65,9 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({ value={inputTargetValue} data-test-subj={`${paramsProperty}TextArea`} onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)} - onClick={(e: React.MouseEvent) => - onClickWithMessageVariable(e.currentTarget) - } - onKeyDown={(e: React.KeyboardEvent) => - onClickWithMessageVariable(e.currentTarget) - } + onFocus={(e: React.FocusEvent) => { + setCurrentTextElement(e.target); + }} onBlur={() => { if (!inputTargetValue) { editAction(paramsProperty, '', index); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx index 60a497d341f49..e280fd3f34e99 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_field_with_message_variables.tsx @@ -25,31 +25,21 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ editAction, errors, }) => { - const [cursorPositionStart, setCursorPositionStart] = useState(0); - const [cursorPositionEnd, setCursorPositionEnd] = useState(0); + const [currentTextElement, setCurrentTextElement] = useState(null); const onSelectMessageVariable = (variable: string) => { const templatedVar = `{{${variable}}}`; - const startPosition = cursorPositionStart; - const endPosition = cursorPositionEnd; + const startPosition = currentTextElement?.selectionStart ?? 0; + const endPosition = currentTextElement?.selectionEnd ?? 0; const newValue = (inputTargetValue ?? '').substring(0, startPosition) + templatedVar + - (inputTargetValue ?? '').substring(endPosition, (inputTargetValue || '').length); - setCursorPositionStart(startPosition + templatedVar.length); - setCursorPositionEnd(endPosition + templatedVar.length); + (inputTargetValue ?? '').substring(endPosition, (inputTargetValue ?? '').length); editAction(paramsProperty, newValue, index); }; const onChangeWithMessageVariable = (e: React.ChangeEvent) => { editAction(paramsProperty, e.target.value, index); - setCursorPositionStart(e.target.selectionStart ?? 0); - setCursorPositionEnd(e.target.selectionEnd ?? 0); - }; - - const onClickWithMessageVariable = (target: HTMLInputElement) => { - setCursorPositionStart(target.selectionStart ?? 0); - setCursorPositionEnd(target.selectionEnd ?? 0); }; return ( @@ -61,23 +51,14 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ data-test-subj={`${paramsProperty}Input`} value={inputTargetValue} onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)} - onClick={(e: React.MouseEvent) => - onClickWithMessageVariable(e.currentTarget) - } - onKeyDown={(e: React.KeyboardEvent) => - onClickWithMessageVariable(e.currentTarget) - } + onFocus={(e: React.FocusEvent) => { + setCurrentTextElement(e.target); + }} onBlur={(e: React.FocusEvent) => { if (!inputTargetValue) { editAction(paramsProperty, '', index); } }} - onMouseLeave={(e: React.MouseEvent) => { - if (e.currentTarget.id !== `${paramsProperty}Id`) { - setCursorPositionStart((inputTargetValue || '').length); - setCursorPositionEnd((inputTargetValue || '').length); - } - }} append={ Date: Thu, 2 Jul 2020 16:06:02 -0700 Subject: [PATCH 6/6] Fixed functional tests --- .../apps/triggers_actions_ui/alerts.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts index 63a53fcb552e4..2225316bba80f 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts @@ -80,15 +80,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('variableMenuButton-0'); const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}'); - await messageTextArea.focus(); - await testSubjects.focus('messageAddVariableButton'); + await messageTextArea.type(' some additional text '); await testSubjects.click('messageAddVariableButton'); await testSubjects.click('variableMenuButton-1'); - const messageTextArea1 = await find.byCssSelector('[data-test-subj="messageTextArea"]'); - expect(await messageTextArea1.getAttribute('value')).to.eql( - 'test message {{alertId}}{{alertName}}' + expect(await messageTextArea.getAttribute('value')).to.eql( + 'test message {{alertId}} some additional text {{alertName}}' ); await testSubjects.click('saveAlertButton');