From 66b7a69dcff1cc134f7a3540c2b7130d89938083 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Wed, 25 Feb 2026 17:51:09 -0300 Subject: [PATCH 01/11] chore: lift submit form to redux thunk, trigger validation before submission --- .../src/components/PreEngagementFormPhase.tsx | 28 ++--------- aselo-webchat-react-app/src/notifications.ts | 9 ++++ .../src/store/actions/genericActions.ts | 50 +++++++++++++++++++ .../src/store/actions/initActions.ts | 2 - 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx b/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx index 1082f7ca7d..38ddc6ef40 100644 --- a/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx +++ b/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx @@ -20,12 +20,9 @@ import { Button } from '@twilio-paste/core/button'; import { useDispatch, useSelector } from 'react-redux'; import { Text } from '@twilio-paste/core/text'; -import { sessionDataHandler } from '../sessionDataHandler'; -import { addNotification, changeEngagementPhase, updatePreEngagementDataField } from '../store/actions/genericActions'; -import { initSession } from '../store/actions/initActions'; -import { AppState, EngagementPhase } from '../store/definitions'; +import { submitAndInitChatThunk, updatePreEngagementDataField } from '../store/actions/genericActions'; +import { AppState } from '../store/definitions'; import { Header } from './Header'; -import { notifications } from '../notifications'; import { NotificationBar } from './NotificationBar'; import { fieldStyles, titleStyles, formStyles } from './styles/PreEngagementFormPhase.styles'; import LocalizedTemplate from '../localization/LocalizedTemplate'; @@ -36,8 +33,6 @@ export const PreEngagementFormPhase = () => { const { preEngagementFormDefinition } = useSelector((state: AppState) => state.config); const dispatch = useDispatch(); - const { friendlyName } = preEngagementData; - const getItem = (inputName: string) => preEngagementData[inputName] ?? {}; const setItemValue = (payload: { name: string; value: string | boolean }) => { dispatch(updatePreEngagementDataField(payload)); @@ -46,24 +41,7 @@ export const PreEngagementFormPhase = () => { const handleSubmit = async (e: FormEvent) => { e.preventDefault(); - dispatch(changeEngagementPhase({ phase: EngagementPhase.Loading })); - try { - const data = await sessionDataHandler.fetchAndStoreNewSession({ - formData: { - ...preEngagementData, - friendlyName, - }, - }); - dispatch( - initSession({ - token: data.token, - conversationSid: data.conversationSid, - }), - ); - } catch (err) { - dispatch(addNotification(notifications.failedToInitSessionNotification((err as Error).message))); - dispatch(changeEngagementPhase({ phase: EngagementPhase.PreEngagementForm })); - } + await dispatch(submitAndInitChatThunk() as any); }; if (!preEngagementFormDefinition) { diff --git a/aselo-webchat-react-app/src/notifications.ts b/aselo-webchat-react-app/src/notifications.ts index 0db063e3d7..035bf78a57 100644 --- a/aselo-webchat-react-app/src/notifications.ts +++ b/aselo-webchat-react-app/src/notifications.ts @@ -98,6 +98,14 @@ const failedToInitSessionNotification = (error: string): Notification => ({ type: 'error', }); +const formValidationErrorNotification = (): Notification => ({ + id: `FailedToInitSessionNotification`, + dismissible: true, + message: 'Some fields contain errors', + type: 'error', + timeout: 5000, +}); + export const notifications = { fileAttachmentAlreadyAttachedNotification, fileAttachmentInvalidSizeNotification, @@ -106,4 +114,5 @@ export const notifications = { fileDownloadInvalidTypeNotification, noConnectionNotification, failedToInitSessionNotification, + formValidationErrorNotification, }; diff --git a/aselo-webchat-react-app/src/store/actions/genericActions.ts b/aselo-webchat-react-app/src/store/actions/genericActions.ts index 9df48c990c..b7148c806b 100644 --- a/aselo-webchat-react-app/src/store/actions/genericActions.ts +++ b/aselo-webchat-react-app/src/store/actions/genericActions.ts @@ -32,6 +32,10 @@ import { } from './actionTypes'; import { MESSAGES_LOAD_COUNT } from '../../constants'; import { validateInput } from '../../components/forms/formInputs/validation'; +import { sessionDataHandler } from '../../sessionDataHandler'; +import { getDefaultValue } from '../../components/forms/formInputs'; +import { initSession } from './initActions'; +import { notifications } from '../../notifications'; export function changeEngagementPhase({ phase }: { phase: EngagementPhase }) { return { @@ -136,3 +140,49 @@ export const updatePreEngagementDataField = ({ }); }; }; + +const getInitialItem = (definition: PreEngagementFormItem): PreEngagementDataItem => ({ + error: null, + dirty: false, + value: getDefaultValue(definition), +}); + +export const submitAndInitChatThunk = (): ThunkAction => { + return async (dispatch, getState) => { + const state = getState(); + const definition = state.config.preEngagementFormDefinition?.fields || []; + const data = definition.reduce((accum, def) => { + const item = state.session.preEngagementData[def.name]; + const error = validateInput({ definition: def, value: item?.value }); + return { ...accum, [def.name]: { ...(item || getInitialItem(def)), error } }; + }, {}); + + dispatch(updatePreEngagementData(data)); + + const hasError = Object.values(data).some(i => Boolean(i.error)); + if (hasError) { + dispatch(addNotification(notifications.formValidationErrorNotification())); + return; + } + + dispatch(changeEngagementPhase({ phase: EngagementPhase.Loading })); + try { + const preEngagementDataValues = Object.entries(data).reduce( + (accum, [name, { value }]) => ({ ...accum, [name]: value }), + {}, + ); + const sessionData = await sessionDataHandler.fetchAndStoreNewSession({ + formData: preEngagementDataValues, + }); + dispatch( + initSession({ + token: sessionData.token, + conversationSid: sessionData.conversationSid, + }), + ); + } catch (err) { + dispatch(addNotification(notifications.failedToInitSessionNotification((err as Error).message))); + dispatch(changeEngagementPhase({ phase: EngagementPhase.PreEngagementForm })); + } + }; +}; diff --git a/aselo-webchat-react-app/src/store/actions/initActions.ts b/aselo-webchat-react-app/src/store/actions/initActions.ts index 9c4f17d375..ae6ddd2fdb 100644 --- a/aselo-webchat-react-app/src/store/actions/initActions.ts +++ b/aselo-webchat-react-app/src/store/actions/initActions.ts @@ -29,7 +29,6 @@ import { ACTION_LOAD_CONFIG_REQUEST, ACTION_LOAD_CONFIG_SUCCESS, ACTION_LOAD_CONFIG_FAILURE, - ACTION_UPDATE_PRE_ENGAGEMENT_DATA, } from './actionTypes'; import { addNotification, changeEngagementPhase } from './genericActions'; import { MESSAGES_LOAD_COUNT } from '../../constants'; @@ -38,7 +37,6 @@ import { sessionDataHandler } from '../../sessionDataHandler'; import { createParticipantNameMap } from '../../utils/participantNameMap'; import { getDefinitionVersion } from '../../services/configService'; import type { AppState } from '../store'; -import { getDefaultValue } from '../../components/forms/formInputs'; export const initConfigThunk = ( config: Omit, From 44e6d195537e87fce1561ef726197e6a94432bbe Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 12:12:03 -0300 Subject: [PATCH 02/11] chore: save form data in expected conversation attribute --- lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index e72a033cab..7793bd182d 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -34,7 +34,7 @@ const contactWebchatOrchestrator = async ( params.append('ChatFriendlyName', 'Webchat widget'); params.append('CustomerFriendlyName', customerFriendlyName); params.append( - 'PreEngagementData', + 'preEngagementData', JSON.stringify({ ...formData, friendlyName: customerFriendlyName, From bc87b993241e5769483cde4d1be45de8e17e32c4 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 14:19:40 -0300 Subject: [PATCH 03/11] fix: dont assert email regex if empty input is not required --- .../src/components/forms/formInputs/validation.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts b/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts index 94b9f28747..5008398103 100644 --- a/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts +++ b/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts @@ -50,7 +50,11 @@ const validateEmailPattern = ({ return null; } - const matches = (value as string).match(EMAIL_PATTERN); + if (!Boolean(definition.required) && !value) { + return null; + } + + const matches = (value as string)?.match(EMAIL_PATTERN); if (Boolean(matches?.length)) { return null; From 85fd25ece4fbe3973346b10d138cf2f102dc56db Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 14:19:48 -0300 Subject: [PATCH 04/11] chore: fix tests --- .../components/__tests__/PreEngagementFormPhase.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aselo-webchat-react-app/src/components/__tests__/PreEngagementFormPhase.test.tsx b/aselo-webchat-react-app/src/components/__tests__/PreEngagementFormPhase.test.tsx index d8895432ad..6b12dde41d 100644 --- a/aselo-webchat-react-app/src/components/__tests__/PreEngagementFormPhase.test.tsx +++ b/aselo-webchat-react-app/src/components/__tests__/PreEngagementFormPhase.test.tsx @@ -184,9 +184,9 @@ describe('Pre Engagement Form Phase', () => { expect(fetchAndStoreNewSessionSpy).toHaveBeenCalledWith({ formData: { - friendlyName: { value: name, error: null, dirty: true }, - query: { value: query, error: null, dirty: true }, - email: { value: email, error: null, dirty: true }, + friendlyName: name, + query, + email, }, }); }); From de36e29e937ac309da3c30d2e474e5d076a1ea03 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 17:26:51 -0300 Subject: [PATCH 05/11] refactor: replace fetch calls with twilio client --- .../src/webchatAuthentication/initWebchat.ts | 58 ++++++------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index 7793bd182d..7f27d9aede 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -14,7 +14,7 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import { getAccountAuthToken, getTwilioClient } from '@tech-matters/twilio-configuration'; +import { getTwilioClient } from '@tech-matters/twilio-configuration'; import type { AccountScopedHandler, HttpError } from '../httpTypes'; import type { AccountSID, ConversationSID } from '@tech-matters/twilio-types'; import { isErr, newErr, newOk, Result } from '../Result'; @@ -28,36 +28,26 @@ const contactWebchatOrchestrator = async ( customerFriendlyName: string, ): Promise> => { console.info('Calling Webchat Orchestrator'); + try { + const client = await getTwilioClient(accountSid); + const orchestratorResponse = await client.flexApi.v2.webChannels.create({ + customerFriendlyName, + addressSid, + preEngagementData: JSON.stringify(formData), + uiVersion: process.env.WEBCHAT_VERSION || '1.0.0', + chatFriendlyName: 'Webchat widget', + }); + console.info('Webchat Orchestrator successfully called', orchestratorResponse); - const params = new URLSearchParams(); - params.append('AddressSid', addressSid); - params.append('ChatFriendlyName', 'Webchat widget'); - params.append('CustomerFriendlyName', customerFriendlyName); - params.append( - 'preEngagementData', - JSON.stringify({ - ...formData, - friendlyName: customerFriendlyName, - }), - ); - const authToken = await getAccountAuthToken(accountSid); + const { conversationSid, identity } = orchestratorResponse; - const res = await fetch(`https://flex-api.twilio.com/v2/WebChats`, { - method: 'POST', - headers: { - Authorization: - 'Basic ' + Buffer.from(accountSid + ':' + authToken).toString('base64'), - 'ui-version': process.env.WEBCHAT_VERSION || '1.0.0', - }, - body: params, - }); - if (!res.ok) { - const bodyError = await res.text(); - console.error( - 'Error calling https://flex-api.twilio.com/v2/WebChats', - accountSid, - bodyError, - ); + return newOk({ + conversationSid: conversationSid as ConversationSID, + identity, + }); + } catch (err) { + const bodyError = err instanceof Error ? err.message : String(err); + console.error('Error creating web channel', accountSid, bodyError); return newErr({ message: bodyError, error: { @@ -66,16 +56,6 @@ const contactWebchatOrchestrator = async ( }, }); } - const orchestratorResponse = (await res.json()) as any; - - console.info('Webchat Orchestrator successfully called', orchestratorResponse); - - const { conversation_sid: conversationSid, identity } = orchestratorResponse; - - return newOk({ - conversationSid, - identity, - }); }; const sendUserMessage = async ( From ec3937cbb2e0497a97e8ac105a4e8e914cbeb540 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 17:54:08 -0300 Subject: [PATCH 06/11] chore: debug --- .../src/webchatAuthentication/initWebchat.ts | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index 7f27d9aede..173e80d871 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -21,13 +21,32 @@ import { isErr, newErr, newOk, Result } from '../Result'; import { createToken, TOKEN_TTL_IN_SECONDS } from './createToken'; -const contactWebchatOrchestrator = async ( - accountSid: AccountSID, - addressSid: string, - formData: any, - customerFriendlyName: string, -): Promise> => { +const contactWebchatOrchestrator = async ({ + addressSid, + accountSid, + formData, + customerFriendlyName, +}: { + accountSid: AccountSID; + addressSid: string; + formData: any; + customerFriendlyName: string; +}): Promise< + Result +> => { console.info('Calling Webchat Orchestrator'); + console.info( + JSON.stringify( + { + addressSid, + accountSid, + formData, + customerFriendlyName, + }, + null, + 2, + ), + ); try { const client = await getTwilioClient(accountSid); const orchestratorResponse = await client.flexApi.v2.webChannels.create({ @@ -102,12 +121,12 @@ export const initWebchatHandler: AccountScopedHandler = async (request, accountS let identity; // Hit Webchat Orchestration endpoint to generate conversation and get customer participant sid - const result = await contactWebchatOrchestrator( + const result = await contactWebchatOrchestrator({ accountSid, - 'IG1ba46f2d6828b42ddd363f5045138044', // Obvs needs to be SSM parameter - request.body?.formData, + addressSid: 'IG1ba46f2d6828b42ddd363f5045138044', // Obvs needs to be SSM parameter + formData: request.body?.formData, customerFriendlyName, - ); + }); if (isErr(result)) { return result; } From 26544a9117d210aac4996af1efcbe38015922b34 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 18:08:44 -0300 Subject: [PATCH 07/11] chore: debug --- .../src/webchatAuthentication/initWebchat.ts | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index 173e80d871..4b6224deb3 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -77,21 +77,21 @@ const contactWebchatOrchestrator = async ({ } }; -const sendUserMessage = async ( - accountSid: AccountSID, - conversationSid: ConversationSID, - identity: string, - messageBody: string, -) => { - console.debug('Sending user message'); - const client = await getTwilioClient(accountSid); - await client.conversations.v1.conversations(conversationSid).messages.create({ - body: messageBody, - author: identity, - xTwilioWebhookEnabled: 'true', // trigger webhook - }); - console.info('(async) User message sent'); -}; +// const sendUserMessage = async ( +// accountSid: AccountSID, +// conversationSid: ConversationSID, +// identity: string, +// messageBody: string, +// ) => { +// console.debug('Sending user message'); +// const client = await getTwilioClient(accountSid); +// await client.conversations.v1.conversations(conversationSid).messages.create({ +// body: messageBody, +// author: identity, +// xTwilioWebhookEnabled: 'true', // trigger webhook +// }); +// console.info('(async) User message sent'); +// }; const sendWelcomeMessage = async ( accountSid: AccountSID, @@ -114,8 +114,10 @@ const sendWelcomeMessage = async ( export const initWebchatHandler: AccountScopedHandler = async (request, accountSid) => { console.info('Initiating webchat', accountSid); + console.log('>>>>>>> formData: request.body', request.body); - const customerFriendlyName = request.body?.formData?.friendlyName || 'Customer'; + const formData = request.body?.PreEngagementData; + const customerFriendlyName = formData?.friendlyName || 'Customer'; let conversationSid: ConversationSID; let identity; @@ -124,7 +126,7 @@ export const initWebchatHandler: AccountScopedHandler = async (request, accountS const result = await contactWebchatOrchestrator({ accountSid, addressSid: 'IG1ba46f2d6828b42ddd363f5045138044', // Obvs needs to be SSM parameter - formData: request.body?.formData, + formData, customerFriendlyName, }); if (isErr(result)) { @@ -136,18 +138,20 @@ export const initWebchatHandler: AccountScopedHandler = async (request, accountS const token = await createToken(accountSid, identity); // OPTIONAL — if user query is defined - if (request.body?.formData?.query) { - // use it to send a message in behalf of the user with the query as body - sendUserMessage( - accountSid, - conversationSid, - identity, - request.body.formData.query, - ).then(() => - // and then send another message from Concierge, letting the user know that an agent will help them soon - sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), - ); - } + // if (request.body?.formData?.query) { + // // use it to send a message in behalf of the user with the query as body + // sendUserMessage( + // accountSid, + // conversationSid, + // identity, + // request.body.formData.query, + // ).then(() => + // // and then send another message from Concierge, letting the user know that an agent will help them soon + // sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), + // ); + // sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), + // } + await sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName); console.info('Webchat successfully initiated', accountSid); return newOk({ From 39219becf51f2e0b535413cd3fcb8eb87835ad03 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Thu, 26 Feb 2026 18:18:35 -0300 Subject: [PATCH 08/11] fix: parse body --- .../src/webchatAuthentication/initWebchat.ts | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index 4b6224deb3..d6d1e32522 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -29,24 +29,13 @@ const contactWebchatOrchestrator = async ({ }: { accountSid: AccountSID; addressSid: string; - formData: any; + formData: Record; customerFriendlyName: string; }): Promise< Result > => { console.info('Calling Webchat Orchestrator'); - console.info( - JSON.stringify( - { - addressSid, - accountSid, - formData, - customerFriendlyName, - }, - null, - 2, - ), - ); + try { const client = await getTwilioClient(accountSid); const orchestratorResponse = await client.flexApi.v2.webChannels.create({ @@ -116,8 +105,9 @@ export const initWebchatHandler: AccountScopedHandler = async (request, accountS console.info('Initiating webchat', accountSid); console.log('>>>>>>> formData: request.body', request.body); - const formData = request.body?.PreEngagementData; - const customerFriendlyName = formData?.friendlyName || 'Customer'; + const formData = JSON.parse(request.body?.PreEngagementData); + const customerFriendlyName = + formData?.friendlyName || request.body?.CustomerFriendlyName || 'Customer'; let conversationSid: ConversationSID; let identity; From 480decb0a3d7b2e369bfe63442dc0d3afab147c2 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Fri, 27 Feb 2026 17:13:29 -0300 Subject: [PATCH 09/11] chore: debug --- .../src/components/MessagingCanvasPhase.tsx | 11 ---------- .../components/forms/formInputs/validation.ts | 2 +- .../src/webchatAuthentication/initWebchat.ts | 22 +++++-------------- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx index ca3b016ccb..132a43c7e1 100644 --- a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx +++ b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx @@ -29,16 +29,6 @@ import { notifications } from '../notifications'; import { AttachFileDropArea } from './AttachFileDropArea'; import CloseChatButtons from './endChat/CloseChatButtons'; -const sendInitialUserQuery = async (conv?: Conversation, query?: string): Promise => { - if (!query || !conv) return; - - const totalMessagesCount = await conv.getMessagesCount(); - - if (!totalMessagesCount) { - conv.prepareMessage().setBody(query).build().send(); - } -}; - export const MessagingCanvasPhase = () => { const dispatch = useDispatch(); @@ -50,7 +40,6 @@ export const MessagingCanvasPhase = () => { useEffect(() => { dispatch(removeNotification(notifications.failedToInitSessionNotification('ds').id)); - sendInitialUserQuery(conversation as Conversation, 'TODO: trigger message'); }, [dispatch, conversation, preEngagmentData]); const Wrapper = conversationState === 'active' ? AttachFileDropArea : Fragment; diff --git a/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts b/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts index 5008398103..c7c1a2003a 100644 --- a/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts +++ b/aselo-webchat-react-app/src/components/forms/formInputs/validation.ts @@ -50,7 +50,7 @@ const validateEmailPattern = ({ return null; } - if (!Boolean(definition.required) && !value) { + if (!value) { return null; } diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index d6d1e32522..465a498711 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -36,6 +36,12 @@ const contactWebchatOrchestrator = async ({ > => { console.info('Calling Webchat Orchestrator'); + console.log('>>>>>>>>>>>> ', { + addressSid, + accountSid, + formData, + customerFriendlyName, + }); try { const client = await getTwilioClient(accountSid); const orchestratorResponse = await client.flexApi.v2.webChannels.create({ @@ -66,22 +72,6 @@ const contactWebchatOrchestrator = async ({ } }; -// const sendUserMessage = async ( -// accountSid: AccountSID, -// conversationSid: ConversationSID, -// identity: string, -// messageBody: string, -// ) => { -// console.debug('Sending user message'); -// const client = await getTwilioClient(accountSid); -// await client.conversations.v1.conversations(conversationSid).messages.create({ -// body: messageBody, -// author: identity, -// xTwilioWebhookEnabled: 'true', // trigger webhook -// }); -// console.info('(async) User message sent'); -// }; - const sendWelcomeMessage = async ( accountSid: AccountSID, conversationSid: ConversationSID, From 0e50dde5d56af6aa701b1c80cd03eec7fad2a367 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Fri, 27 Feb 2026 17:32:35 -0300 Subject: [PATCH 10/11] revert: src/components/MessagingCanvasPhase.tsx --- .../src/components/MessagingCanvasPhase.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx index 132a43c7e1..ca3b016ccb 100644 --- a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx +++ b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx @@ -29,6 +29,16 @@ import { notifications } from '../notifications'; import { AttachFileDropArea } from './AttachFileDropArea'; import CloseChatButtons from './endChat/CloseChatButtons'; +const sendInitialUserQuery = async (conv?: Conversation, query?: string): Promise => { + if (!query || !conv) return; + + const totalMessagesCount = await conv.getMessagesCount(); + + if (!totalMessagesCount) { + conv.prepareMessage().setBody(query).build().send(); + } +}; + export const MessagingCanvasPhase = () => { const dispatch = useDispatch(); @@ -40,6 +50,7 @@ export const MessagingCanvasPhase = () => { useEffect(() => { dispatch(removeNotification(notifications.failedToInitSessionNotification('ds').id)); + sendInitialUserQuery(conversation as Conversation, 'TODO: trigger message'); }, [dispatch, conversation, preEngagmentData]); const Wrapper = conversationState === 'active' ? AttachFileDropArea : Fragment; From 9b45b0be9165044964fffa55d49474e33ebef3e4 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Fri, 27 Feb 2026 17:42:30 -0300 Subject: [PATCH 11/11] revert: removal of send user message (trigger) --- .../src/webchatAuthentication/initWebchat.ts | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index 465a498711..a347595535 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -36,12 +36,6 @@ const contactWebchatOrchestrator = async ({ > => { console.info('Calling Webchat Orchestrator'); - console.log('>>>>>>>>>>>> ', { - addressSid, - accountSid, - formData, - customerFriendlyName, - }); try { const client = await getTwilioClient(accountSid); const orchestratorResponse = await client.flexApi.v2.webChannels.create({ @@ -72,6 +66,22 @@ const contactWebchatOrchestrator = async ({ } }; +const sendUserMessage = async ( + accountSid: AccountSID, + conversationSid: ConversationSID, + identity: string, + messageBody: string, +) => { + console.debug('Sending user message'); + const client = await getTwilioClient(accountSid); + await client.conversations.v1.conversations(conversationSid).messages.create({ + body: messageBody, + author: identity, + xTwilioWebhookEnabled: 'true', // trigger webhook + }); + console.info('(async) User message sent'); +}; + const sendWelcomeMessage = async ( accountSid: AccountSID, conversationSid: ConversationSID, @@ -93,7 +103,6 @@ const sendWelcomeMessage = async ( export const initWebchatHandler: AccountScopedHandler = async (request, accountSid) => { console.info('Initiating webchat', accountSid); - console.log('>>>>>>> formData: request.body', request.body); const formData = JSON.parse(request.body?.PreEngagementData); const customerFriendlyName = @@ -118,20 +127,18 @@ export const initWebchatHandler: AccountScopedHandler = async (request, accountS const token = await createToken(accountSid, identity); // OPTIONAL — if user query is defined - // if (request.body?.formData?.query) { - // // use it to send a message in behalf of the user with the query as body - // sendUserMessage( - // accountSid, - // conversationSid, - // identity, - // request.body.formData.query, - // ).then(() => - // // and then send another message from Concierge, letting the user know that an agent will help them soon - // sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), - // ); - // sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), - // } - await sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName); + if (request.body?.formData?.query) { + // use it to send a message in behalf of the user with the query as body + sendUserMessage( + accountSid, + conversationSid, + identity, + request.body.formData.query, + ).then(() => + // and then send another message from Concierge, letting the user know that an agent will help them soon + sendWelcomeMessage(accountSid, conversationSid, customerFriendlyName), + ); + } console.info('Webchat successfully initiated', accountSid); return newOk({