-
Notifications
You must be signed in to change notification settings - Fork 13k
feat: Outbound Message UI #36207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Outbound Message UI #36207
Conversation
|
Looks like this PR is ready to merge! 🎉 |
🦋 Changeset detectedLatest commit: b6fcc40 The changes in this PR will be included in the next version bump. This PR includes changesets to release 44 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #36207 +/- ##
===========================================
+ Coverage 66.58% 70.23% +3.65%
===========================================
Files 3346 3090 -256
Lines 114666 106231 -8435
Branches 21099 18845 -2254
===========================================
- Hits 76352 74615 -1737
+ Misses 35619 29643 -5976
+ Partials 2695 1973 -722
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
d6f396a to
d0d0b53
Compare
|
e1f94ba to
672300d
Compare
39df003 to
ac91c2b
Compare
52a9cc6 to
49f27be
Compare
d1f2ebf to
b7b0542
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (5)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/RecipientField.tsx (1)
31-31: Fix confirmed: phone-only validation now gated by type.This resolves the earlier bug where email flows were blocked. Good change.
packages/i18n/src/locales/en.i18n.json (1)
3907-3913: Consolidate 'Outbound_Message' vs 'Outbound_message' across repoPast review flagged mixed casing. Keep a single canonical key (suggest: "Outbound_message") and drop the other variant; update callers accordingly.
Run to verify keys and usages:
#!/bin/bash # Find duplicate i18n keys and call sites rg -nP '"Outbound_Message"\s*:' packages/i18n/src/locales/en.i18n.json rg -nP '"Outbound_message"\s*:' packages/i18n/src/locales/en.i18n.json # Find UI call sites (ts/tsx/js) rg -n --type-add 'tsx:*.{ts,tsx,js,jsx}' -e "t\\(['\"]Outbound_Message['\"]\\)" -e "t\\(['\"]Outbound_message['\"]\\)" -C2apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (3)
180-180: Nice: switched tomutateAsyncsoisSubmittingreflects network work.This resolves the prior UX concern.
179-185: Fix invalidation targets after edit: don’t invalidatecontact()without id; widencontactsinvalidation prefix.
invalidateQueries({ queryKey: omnichannelQueryKeys.contact() })won’t match detail queries keyed with a contact id.contactSearch()with a 3-segment key includingundefinedwon’t match list/search variants that pass params.Use the specific contact id for detail and a 2‑segment prefix for lists/search.
Apply this diff:
- await editContact.mutateAsync({ contactId: contactData?._id, ...payload }); - await Promise.all([ - queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contact() }), - queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contactSearch() }), - ]); + await editContact.mutateAsync({ contactId: contactData._id, ...payload }); + await Promise.all([ + // Detail: precise key for the edited contact + queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contact(contactData._id) }), + // Lists/search: invalidate all variants (any filter/limit) + queryClient.invalidateQueries({ queryKey: [...omnichannelQueryKeys.all, 'contacts'], exact: false }), + ]);
188-192: Create flow: capture created id (if returned) and invalidate correct prefixes.
- Dropping
contact()without id avoids a no-op.- Invalidate all contacts lists; if API returns the new
_id, also invalidate its detail.Apply this diff:
- await createContact.mutateAsync(payload); - await Promise.all([ - queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contact() }), - queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contactSearch() }), - ]); + const created = await createContact.mutateAsync(payload); + // Lists/search + await queryClient.invalidateQueries({ queryKey: [...omnichannelQueryKeys.all, 'contacts'], exact: false }); + // Detail (best-effort) + if (created?._id) { + await queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contact(created._id) }); + }
🧹 Nitpick comments (41)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/RecipientField.tsx (6)
50-50: Pass a boolean to error prop.Use a boolean instead of the string literal to match common prop typing and avoid accidental truthy strings.
- error={recipientFieldError && 'error'} + error={Boolean(recipientFieldError)}
43-55: Preserve RHF semantics: pass onBlur.Include onBlur so touched state and onBlur validation work as expected.
onChange={recipientField.onChange} + onBlur={recipientField.onBlur}
29-35: Optional: add symmetric email validation + message.Mirror the phone validation for email to give users clearer guidance when contacts lack emails.
rules: { validate: { noPhoneNumber: () => (type === 'phone' && contact ? !!contact.phones?.length : true), + noEmail: () => (type === 'email' && contact ? !!contact.emails?.length : true), required: (value) => (!value ? t('Required_field', { field: t('To') }) : true), }, },{recipientFieldError?.type === 'noPhoneNumber' && ( <FieldError aria-live='assertive' id={`${recipientFieldId}-error`}> <Trans i18nKey='No_phone_number_yet_edit_contact'> No phone number yet <a href={`/omnichannel-directory/contacts/edit/${contact?._id}`}>Edit contact</a> </Trans> </FieldError> )} + {recipientFieldError?.type === 'noEmail' && ( + <FieldError aria-live='assertive' id={`${recipientFieldId}-error`}> + <Trans i18nKey='No_email_yet_edit_contact'> + No email yet <a href={`/omnichannel-directory/contacts/edit/${contact?._id}`}>Edit contact</a> + </Trans> + </FieldError> + )}Also applies to: 62-68
16-19: Minor typing nit: make isLoading optional.You already default it to false; mark it optional for ergonomics.
- isLoading: boolean; + isLoading?: boolean;
39-39: Tiny cleanup: avoid redundant template literal.- <FieldLabel is='span' required id={`${recipientFieldId}`}> + <FieldLabel is='span' required id={recipientFieldId}>
64-66: Optional: keep markup out of translations and avoid hardcoded routes.Prefer Trans components mapping and a route helper to build the URL; this reduces translator risk and centralizes paths.
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannelsItem.tsx (3)
34-34: Hook usage OK; consider narrowing deps by destructuring.Optionally do
const { open } = useOutboundMessageModal();and depend onopeninstead of the whole object in the memo below.
46-51: Make “Block/Unblock” styling reflect action severity.Showing “Unblock” as danger is a bit off. Use danger only when the action is “Block”.
Apply:
- variant: 'danger', + variant: blocked ? 'default' : 'danger',
10-10: Re‑export verified — consider lazy‑loading the modal.
- Verified: apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/index.ts re-exports the hook (export * from './useOutboundMessageModal') and the hook file exports useOutboundMessageModal — the import path is valid.
- Optional: lazy‑load the modal component inside useOutboundMessageModal (apps/meteor/.../OutboundMessageModal/useOutboundMessageModal.tsx) to avoid pulling modal code into this view’s chunk.
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx (3)
12-15: Narrow prop type: enforce value as string.Ensures parseOutboundPhoneNumber receives the expected type; avoids accidental ReactNode passing.
-type ContactInfoPhoneEntryProps = Omit<ComponentProps<typeof ContactInfoDetailsEntry>, 'icon' | 'actions'> & { - contactId?: string; -}; +type ContactInfoPhoneEntryProps = Omit<ComponentProps<typeof ContactInfoDetailsEntry>, 'icon' | 'actions' | 'value'> & { + value: string; + contactId?: string; +};
16-20: Compute once; copy the displayed value for consistency.Avoids double parsing and makes the clipboard match the UI value.
-const ContactInfoPhoneEntry = ({ contactId, value, ...props }: ContactInfoPhoneEntryProps) => { +const ContactInfoPhoneEntry = ({ contactId, value, ...props }: ContactInfoPhoneEntryProps) => { const { t } = useTranslation(); const isCallReady = useIsCallReady(); - const { copy } = useClipboardWithToast(value); + const formattedValue = parseOutboundPhoneNumber(value); + const { copy } = useClipboardWithToast(formattedValue); @@ - value={parseOutboundPhoneNumber(value)} + value={formattedValue}Also applies to: 25-25
21-31: Memoize actions to avoid unnecessary re-renders (optional).Minor perf tidy-up; keeps props stable when nothing changes.
+import { useMemo } from 'react'; @@ - return ( - <ContactInfoDetailsEntry + const actions = useMemo( + () => [ + <IconButton key='copy' onClick={copy} tiny icon='copy' title={t('Copy')} aria-label={t('Copy')} />, + isCallReady ? <ContactInfoCallButton key='call' phoneNumber={value} /> : null, + <ContactInfoOutboundMessageButton key='outbound-message' defaultValues={{ contactId, recipient: value }} />, + ].filter(Boolean), + [copy, isCallReady, value, contactId, t], + ); + + return ( + <ContactInfoDetailsEntry {...props} icon='phone' - value={formattedValue} - actions={[ - <IconButton key='copy' onClick={copy} tiny icon='copy' title={t('Copy')} aria-label={t('Copy')} />, - isCallReady ? <ContactInfoCallButton key='call' phoneNumber={value} /> : null, - <ContactInfoOutboundMessageButton key='outbound-message' defaultValues={{ contactId, recipient: value }} />, - ].filter(Boolean)} + value={formattedValue} + actions={actions} /> );packages/i18n/src/locales/pt-BR.i18n.json (5)
671-671: Term consistency: “mensagem ativa” vs “proativa/saída”.PR introduz “Outbound message” como “mensagem ativa”. Em PT‑BR, “mensagem proativa” ou “mensagem de saída” são mais claros. Sugiro alinhar todas as novas chaves “Outbound_message*” para um único termo. Exemplo de ajuste nesta linha:
- "Are_you_sure_you_want_to_discard_this_outbound_message": "Tem certeza de que deseja descartar esta mensagem ativa?", + "Are_you_sure_you_want_to_discard_this_outbound_message": "Tem certeza de que deseja descartar esta mensagem proativa?",
3371-3371: Melhorar naturalidade da frase.“ O envio da mensagem não pode ser desfeito” soa artificial. Sugestão:
- "Messages_cannot_be_unsent": "O envio da mensagem não pode ser desfeito", + "Messages_cannot_be_unsent": "Não é possível desfazer o envio da mensagem",
4581-4592: LGTM – comandos de seleção consistentes.Opcional: manter o artigo ausente (“Selecionar canal/agente/...”) como feito aqui para consistência.
5006-5009: Ajuste de estilo e naturalidade para “Template”.
- “Template_message” fica mais natural como “Modelo de mensagem”.
- Remover espaço desnecessário após o valor de “template”.
- "Template": "Modelo", - "template": "modelo", - "Template_message": "Mensagem modelo", + "Template": "Modelo", + "template": "modelo", + "Template_message": "Modelo de mensagem",
3835-3845: Padronizar “Outbound” → “mensagem proativa” e substituir “admin” → “administrador”Verificado em packages/i18n/src/locales/en.i18n.json — chaves correspondentes encontradas. Aplique a alteração sugerida:
- "Outbound_message": "Mensagem ativa", - "Outbound_message_agent_hint": "Deixe em branco para que qualquer agente do departamento designado possa gerenciar as respostas.", - "Outbound_message_agent_hint_no_permission": "Você não tem permissão para atribuir um agente. A resposta será atribuída ao departamento.", - "Outbound_message_department_hint": "Atribuir respostas a um departamento.", - "Outbound_message_not_sent": "Mensagem ativa não enviada.", - "Outbound_message_sent_to__name__": "Mensagem ativa enviada para: {{name}}", - "Outbound_message_upsell_alt": "Ilustração de um smartphone recebendo uma nova notificação de mensagem.", - "Outbound_message_upsell_annotation": "Entre em contato com o admin do seu workspace para habilitar a mensagem ativa", - "Outbound_message_upsell_description": "Envie mensagens ativas personalizadas no WhatsApp e em outros canais - ideal para lembretes, alertas e acompanhamentos.", - "Outbound_message_upsell_title": "Dê o primeiro passo na conversa" + "Outbound_message": "Mensagem proativa", + "Outbound_message_agent_hint": "Deixe em branco para que qualquer agente do departamento designado possa gerenciar as respostas.", + "Outbound_message_agent_hint_no_permission": "Você não tem permissão para atribuir um agente. A resposta será atribuída ao departamento.", + "Outbound_message_department_hint": "Atribua respostas a um departamento.", + "Outbound_message_not_sent": "A mensagem proativa não foi enviada.", + "Outbound_message_sent_to__name__": "Mensagem proativa enviada para: {{name}}", + "Outbound_message_upsell_alt": "Ilustração de um smartphone recebendo uma nova notificação de mensagem.", + "Outbound_message_upsell_annotation": "Entre em contato com o administrador do seu workspace para habilitar mensagens proativas.", + "Outbound_message_upsell_description": "Envie mensagens proativas personalizadas no WhatsApp e em outros canais — ideal para lembretes, alertas e acompanhamentos.", + "Outbound_message_upsell_title": "Dê o primeiro passo na conversa"apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/PreviewItem.tsx (1)
3-11: Minor a11y/type polish: mark icon decorative, group the labelled content, and use PropsWithChildren.
- Silence SRs for the decorative icon.
- Give the content container an explicit group role tied to the label.
- Prefer PropsWithChildren over a manual children prop.
Apply:
-import type { ReactNode } from 'react'; +import type { PropsWithChildren } from 'react'; @@ -type PreviewItemProps = { - label: string; - icon: Keys; - children: ReactNode; -}; +type PreviewItemProps = PropsWithChildren<{ + label: string; + icon: Keys; +}>; @@ - <Icon size={18} name={icon} /> + <Icon size={18} name={icon} aria-hidden='true' /> @@ - <div aria-labelledby={id}> + <div role='group' aria-labelledby={id}>Please confirm the i18n key t('None') exists in the bundles used here so the fallback always renders as translated.
Also applies to: 19-19, 24-24
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePreview.tsx (1)
41-44: Improve preview region semantics and avoid rendering empty blocks.
- Mark the callout as a region for AT navigation.
- Render body/footer only when present.
- <Callout type='info' icon='balloon-text' title={content.header || ''} aria-labelledby={previewId}> - <MarkdownText parseEmoji content={content.body || ''} /> - <MarkdownText parseEmoji color='annotation' content={content.footer || ''} /> + <Callout type='info' icon='balloon-text' title={content.header || ''} aria-labelledby={previewId} role='region'> + {content.body ? <MarkdownText parseEmoji content={content.body} /> : null} + {content.footer ? <MarkdownText parseEmoji color='annotation' content={content.footer} /> : null} </Callout>apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.spec.tsx (2)
26-30: Fix lint error: do not export from test files.Biome flags this export. Keep the fixture local.
-export const template2 = createFakeOutboundTemplate({ +const template2 = createFakeOutboundTemplate({ id: 'template-2', name: 'Template Two', components: [component.header, component.body], });
16-18: Align header component shape with production types (add format: 'text').Without format, header may be treated as non‑text (e.g., shown as “[Media]” in previews). Add explicit format to match real data.
- header: { type: 'header', text: 'New {{1}} appointment' }, + header: { type: 'header', format: 'text', text: 'New {{1}} appointment' },packages/i18n/src/locales/en.i18n.json (6)
2923-2925: Punctuate time labels to match existing styleAlign with “Last_message__date__”: add colons.
- "Last_contact__time__": "Last contact {{time}}", - "Last_message_received__time__": "Last message received {{time}}", + "Last_contact__time__": "Last contact: {{time}}", + "Last_message_received__time__": "Last message received: {{time}}",
1158-1158: Pluralize “detail” labelsMore natural English in UI.
- "Contact_detail": "Contact detail", + "Contact_detail": "Contact details", - "Workspace_detail": "Workspace detail", + "Workspace_detail": "Workspace details",Also applies to: 5777-5777
399-399: Confirm intent of new lowercase nouns duplicating existing capitalized labelsYou’ve added “agent/contact/Custom_fields/department” alongside existing “Agent/Contact/Custom_Fields/Department”. If both are needed (e.g., sentence‑case vs title‑case), consider namespacing to avoid accidental misuse (e.g., Outbound_message_agent_label).
Also applies to: 1154-1154, 1514-1514, 1626-1626
5094-5097: Avoid duplicate concept keys: 'Template', 'template', 'Template_message'These may confuse callers. Prefer one canonical label (e.g., 'Template'); reserve others only if semantics differ (e.g., 'Template_message' as content type).
If only the label is needed, remove the extra entry and update callers accordingly.
3365-3365: Tidy sentence and newline in error textConsistent punctuation and avoid unnecessary newline in short toasts.
- "Message_not_sent_try_again": "Message not sent. \nPlease try again", + "Message_not_sent_try_again": "Message not sent. Please try again.",
4012-4012: Overly generic key name“Placeholder” is too generic and easy to misuse. Consider a scoped key (e.g., “Outbound_message_placeholder”) for maintainability.
apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx (2)
12-21: Add missing i18n key to make the test deterministic.The title assertion relies on "Outbound message", but the mock app root doesn't provide the
Outbound_messagekey. Add it to avoid depending on external/default locales.const appRoot = mockAppRoot() .withTranslations('en', 'core', { Close: 'Close', Discard: 'Discard', Discard_message: 'Discard message', This_action_cannot_be_undone: 'This action cannot be undone', Keep_editing: 'Keep editing', Are_you_sure_you_want_to_discard_this_outbound_message: 'Are you sure you want to discard this outbound message?', + Outbound_message: 'Outbound message', }) .build();
33-35: Make a11y description assertion resilient to copy changes.Use a substring/regex match so minor text tweaks don’t break the test.
- expect(screen.getByRole('dialog', { name: 'Discard message' })).toHaveAccessibleDescription( - 'Are you sure you want to discard this outbound message?', - ); + expect(screen.getByRole('dialog', { name: 'Discard message' })).toHaveAccessibleDescription( + expect.stringContaining('Are you sure you want to discard this outbound message?'), + );(Apply in both places.)
Also applies to: 49-51
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.spec.tsx (2)
35-43: Provide 'Back' translation to avoid locale bleed-through.The spec queries the Back button by its label but doesn’t stub the translation. Add it to prevent false negatives in environments without default en resources.
const appRoot = mockAppRoot() .withJohnDoe() .withTranslations('en', 'core', { Send: 'Send', + Back: 'Back', })
81-87: Optional: add an assertion for Back disabled while sending (if we disable it).If we gate Back during send (see component suggestion), add a quick check here.
render(<ReviewStep {...defaultProps} />, { wrapper: appRoot }); const sendButton = screen.getByRole('button', { name: 'Send' }); await userEvent.click(sendButton); - await waitFor(() => expect(sendButton).toBeDisabled()); + await waitFor(() => expect(sendButton).toBeDisabled()); + const backButton = screen.getByRole('button', { name: 'Back' }); + expect(backButton).toBeDisabled();Also applies to: 99-117
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.tsx (2)
16-17: Add a mutation key for easier debugging and DevTools grouping.Not required, but helpful for observability and testability.
- const sendMutation = useMutation({ mutationFn: onSend }); + const sendMutation = useMutation({ mutationKey: ['outbound-message', 'send'], mutationFn: onSend });
24-29: Disable Back while sending to prevent mid-send navigation.Prevents accidental state changes while the mutation is in-flight.
- <WizardBackButton /> + <WizardBackButton disabled={sendMutation.isPending} />apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx (3)
34-35: Default to an empty array when templates for the sender are missing.Avoid passing
undefinedto MessageStep when the selected sender has no templates.- const templates = sender ? provider?.templates[sender] : []; + const templates = sender ? provider?.templates[sender] ?? [] : [];
18-18: Fix naming typo for the skeleton component.Improves readability and avoids confusion in future greps.
-import OutboubdMessageWizardSkeleton from './components/OutboundMessageWizardSkeleton'; +import OutboundMessageWizardSkeleton from './components/OutboundMessageWizardSkeleton'; ... - return <OutboubdMessageWizardSkeleton />; + return <OutboundMessageWizardSkeleton />;Also applies to: 141-142
66-70: Optional: consider upsell when Omnichannel module is missing.You compute
hasOmnichannelModulebut don’t gate on it. If outbound messaging requires livechat-enterprise, include it in the upsell condition.apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx (4)
9-11: Header mock likely missing required “format” fieldThe header component in our mocks usually requires a format (e.g., 'text'). Add it to avoid TS/type issues when overriding components.
- header: { type: 'header', text: 'New {{1}} appointment' }, + header: { type: 'header', format: 'text', text: 'New {{1}} appointment' },
49-59: Apply userEvent.setup() here as wellMirror the pattern in this test to keep behavior consistent.
it('should display the template language as the option description', async () => { render(<TemplateSelect templates={mockTemplates} placeholder='Select template' value='' onChange={jest.fn()} />, { wrapper: appRoot }); - await userEvent.click(screen.getByPlaceholderText('Select template')); + const user = userEvent.setup(); + await user.click(screen.getByPlaceholderText('Select template'));
31-60: Optional: add an interaction assertionConsider a test that selects an option and asserts onChange is called with the expected value. This guards the wiring, not just rendering.
37-44: Use userEvent.setup() for reliabilityyarn.lock resolves @testing-library/user-event to 14.5.2 — userEvent.setup() is supported. Replace the direct userEvent call in the test:
it('should display the correct template options with language descriptions', async () => { render(<TemplateSelect templates={mockTemplates} placeholder='Select template' value='' onChange={jest.fn()} />, { wrapper: appRoot }); - await userEvent.click(screen.getByPlaceholderText('Select template')); + const user = userEvent.setup(); + await user.click(screen.getByPlaceholderText('Select template'));apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (1)
190-191: Optional: use a single predicate invalidation for all contact keys.If you prefer one call, predicate keeps intent explicit and avoids key-shape pitfalls.
Apply this alternative snippet instead of multiple calls:
- await Promise.all([ - queryClient.invalidateQueries({ queryKey: omnichannelQueryKeys.contact(contactData._id) }), - queryClient.invalidateQueries({ queryKey: [...omnichannelQueryKeys.all, 'contacts'], exact: false }), - ]); + await queryClient.invalidateQueries({ + predicate: (q) => + Array.isArray(q.queryKey) && + q.queryKey[0] === 'omnichannel' && + (q.queryKey[1] === 'contact' || q.queryKey[1] === 'contacts'), + });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/__snapshots__/MessageStep.spec.tsx.snapis excluded by!**/*.snapapps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/__snapshots__/RecipientStep.spec.tsx.snapis excluded by!**/*.snapapps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/__snapshots__/RepliesStep.spec.tsx.snapis excluded by!**/*.snapapps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/__snapshots__/ReviewStep.spec.tsx.snapis excluded by!**/*.snapapps/meteor/public/images/outbound-message-upsell.svgis excluded by!**/*.svg
📒 Files selected for processing (107)
.changeset/rich-rules-sleep.md(1 hunks)apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useCreateNewItems.tsx(3 hunks)apps/meteor/client/components/AutoCompleteContact/AutoCompleteContact.tsx(1 hunks)apps/meteor/client/components/AutoCompleteContact/index.ts(1 hunks)apps/meteor/client/components/AutoCompleteContact/useContactsList.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteDepartmentAgent.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteDepartmentAgent.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteOutboundProvider.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/OutboundMessagePreview.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/PreviewItem.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/OutboundMessageWizardErrorState.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/OutboundMessageWizardSkeleton.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/RetryButton.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/components/TemplatePlaceholderField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/components/TemplatePreviewField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/RecipientForm.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/ChannelField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/ContactField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/RecipientField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/SenderField.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RepliesForm.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RepliesForm.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/hooks/useFormKeyboardSubmit.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/utils/cx.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/utils/errors.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/RecipientSelect.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/SenderSelect.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderButton.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderInput.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderInput.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderSelector.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useAgentSection.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useContactSection.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useCustomFieldsSection.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePreview.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/definitions/template.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/hooks/useOutboundProvidersList.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageCloseConfirmationModal.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/useOutboundMessageModal.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.stories.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/index.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/findLastChatFromChannel.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/outbound-message.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/template.spec.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/template.ts(1 hunks)apps/meteor/client/lib/formatPhoneNumber.spec.ts(1 hunks)apps/meteor/client/lib/formatPhoneNumber.ts(1 hunks)apps/meteor/client/lib/queryKeys.ts(2 hunks)apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx(3 hunks)apps/meteor/client/views/omnichannel/components/Info.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfo.tsx(2 hunks)apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx(4 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx(3 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannelsItem.tsx(2 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetails.tsx(2 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetailsEntry.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetailsGroup.tsx(0 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoOutboundMessageButton.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx(1 hunks)apps/meteor/ee/app/livechat-enterprise/server/outboundcomms/rest.ts(1 hunks)apps/meteor/package.json(1 hunks)apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts(1 hunks)apps/meteor/tests/mocks/data.ts(2 hunks)apps/meteor/tests/mocks/data/outbound-message.ts(1 hunks)apps/uikit-playground/package.json(1 hunks)ee/packages/license/src/v2/convertToV3.ts(1 hunks)ee/packages/ui-theming/package.json(1 hunks)packages/apps-engine/src/definition/outboundComunication/IOutboundMessage.ts(1 hunks)packages/core-typings/src/omnichannel/outbound.ts(1 hunks)packages/fuselage-ui-kit/package.json(1 hunks)packages/gazzodown/package.json(1 hunks)packages/i18n/src/locales/en.i18n.json(23 hunks)packages/i18n/src/locales/pt-BR.i18n.json(15 hunks)
⛔ Files not processed due to max files limit (7)
- packages/storybook-config/package.json
- packages/ui-avatar/package.json
- packages/ui-client/package.json
- packages/ui-composer/package.json
- packages/ui-video-conf/package.json
- packages/ui-voip/package.json
- packages/web-ui-registration/package.json
🔥 Files not summarized due to errors (1)
- packages/i18n/src/locales/pt-BR.i18n.json: Error: Server error: no LLM provider could handle the message
💤 Files with no reviewable changes (1)
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetailsGroup.tsx
🚧 Files skipped from review as they are similar to previous changes (91)
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/SenderSelect.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderSelector.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/components/TemplatePreviewField.tsx
- apps/uikit-playground/package.json
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderInput.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RepliesForm.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.stories.tsx
- .changeset/rich-rules-sleep.md
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/hooks/useFormKeyboardSubmit.tsx
- apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts
- apps/meteor/tests/mocks/data/outbound-message.ts
- apps/meteor/package.json
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/OutboundMessageWizardSkeleton.tsx
- ee/packages/license/src/v2/convertToV3.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageCloseConfirmationModal.tsx
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoOutboundMessageButton.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx
- apps/meteor/client/components/AutoCompleteContact/AutoCompleteContact.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.spec.tsx
- apps/meteor/tests/mocks/data.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/RecipientSelect.tsx
- apps/meteor/client/lib/queryKeys.ts
- apps/meteor/client/components/AutoCompleteContact/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/utils/outbound-message.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.stories.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/OutboundMessageWizardErrorState.tsx
- packages/gazzodown/package.json
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/SenderField.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/useOutboundMessageModal.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteOutboundProvider.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useContactSection.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RepliesForm.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/utils/errors.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/components/RetryButton.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderButton.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/utils/template.spec.ts
- apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteDepartmentAgent.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/AutoCompleteDepartmentAgent.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/hooks/useOutboundProvidersList.ts
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx
- apps/meteor/ee/app/livechat-enterprise/server/outboundcomms/rest.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RecipientStep.stories.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useCustomFieldsSection.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx
- apps/meteor/client/lib/formatPhoneNumber.spec.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessagePreview/OutboundMessagePreview.tsx
- packages/core-typings/src/omnichannel/outbound.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.stories.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/components/TemplatePlaceholderField.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/utils/cx.ts
- apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useCreateNewItems.tsx
- apps/meteor/client/components/AutoCompleteContact/useContactsList.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.stories.tsx
- apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfo.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/RepliesStep.spec.tsx
- packages/apps-engine/src/definition/outboundComunication/IOutboundMessage.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/ContactField.tsx
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetails.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/ChannelField.tsx
- apps/meteor/client/views/omnichannel/components/Info.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/RecipientForm.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/definitions/template.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/MessageStep.stories.tsx
- packages/fuselage-ui-kit/package.json
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoDetailsEntry.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/hooks/useAgentSection.tsx
- apps/meteor/client/lib/formatPhoneNumber.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.tsx
- ee/packages/ui-theming/package.json
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/index.ts
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePlaceholderSelector/TemplatePlaceholderInput.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/utils/template.ts
🧰 Additional context used
🧬 Code graph analysis (9)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.spec.tsx (2)
packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)packages/ui-client/src/components/Wizard/WizardContext.tsx (1)
WizardContext(17-17)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/components/RecipientField.tsx (1)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/RecipientForm/RecipientForm.tsx (1)
RecipientFormData(20-25)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePreview.tsx (2)
apps/meteor/client/components/Omnichannel/OutboundMessage/definitions/template.ts (2)
TemplateParameters(10-10)ComponentType(3-3)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/template.ts (1)
processTemplatePreviewText(65-86)
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (1)
apps/meteor/client/lib/queryKeys.ts (1)
omnichannelQueryKeys(30-81)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.spec.tsx (3)
apps/meteor/tests/mocks/data/outbound-message.ts (1)
createFakeOutboundTemplate(25-64)apps/meteor/tests/mocks/data.ts (1)
createFakeContactWithManagerData(352-366)packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)
apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx (1)
packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx (6)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/index.ts (1)
SubmitPayload(5-5)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx (1)
useOutboundMessageUpsellModal(9-21)apps/meteor/client/hooks/useEndpointMutation.ts (1)
useEndpointMutation(23-43)packages/ui-client/src/components/Wizard/useWizard.tsx (1)
useWizard(20-101)apps/meteor/client/components/Omnichannel/OutboundMessage/utils/outbound-message.ts (4)
isRecipientStepValid(14-16)isMessageStepValid(18-20)isRepliesStepValid(22-24)formatOutboundMessagePayload(48-79)apps/meteor/client/lib/formatPhoneNumber.ts (1)
formatPhoneNumber(24-36)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannelsItem.tsx (1)
apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/useOutboundMessageModal.tsx (1)
useOutboundMessageModal(8-18)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx (2)
apps/meteor/tests/mocks/data/outbound-message.ts (1)
createFakeOutboundTemplate(25-64)packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)
🪛 Biome (2.1.2)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.spec.tsx
[error] 25-30: Do not export from a test file.
(lint/suspicious/noExportsInTest)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx
[error] 19-25: Do not export from a test file.
(lint/suspicious/noExportsInTest)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx
[error] 28-28: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: 🔎 Code Check / TypeScript
- GitHub Check: 🔨 Test Unit / Unit Tests
- GitHub Check: 🔎 Code Check / Code Lint
- GitHub Check: 🔨 Test Storybook / Test Storybook
- GitHub Check: 📦 Meteor Build - coverage
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (24)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannelsItem.tsx (4)
6-6: Imports look good.
useMemois appropriately added and used;useStateis already in use.
15-18: Prop additions are sensible; clarify invariants.
contactId?andcanSendOutboundMessage?make sense. Invariants assumed later: opening the modal requires bothcontactIdanddetails.id. We gate this below, but ensure callers setcanSendOutboundMessageonly when both exist.
20-27: Component signature changes LGTM.Destructuring the new props is consistent with the type update.
58-59: i18n key exists — no action required.
Outbound_message is defined in packages/i18n/src/locales/en.i18n.json and packages/i18n/src/locales/pt-BR.i18n.json.apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx (1)
27-30: Confirm which phone format to pass to call/outbound buttonsUI renders a formatted value but this snippet passes the raw value — verify which form the downstream components expect (display-formatted vs dialable/E.164) and align accordingly.
File: apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx (around lines 27-30)
<IconButton key={`${value}-copy`} onClick={() => copy()} tiny icon='copy' title={t('Copy')} />, isCallReady ? <ContactInfoCallButton phoneNumber={value} /> : null, <ContactInfoOutboundMessageButton key={`${value}-outbound-message`} defaultValues={{ contactId, recipient: value }} />,
- Check ContactInfoCallButton: inspect the phoneNumber prop/type and its downstream dialer integration — if it requires dialable/E.164, normalize before passing.
- Check ContactInfoOutboundMessageButton: inspect defaultValues.recipient expectation — normalize if it requires E.164, otherwise pass formattedValue.
- If a phone-normalization util exists (toE164/normalizePhoneNumber/etc.), use it here; add one if missing.
packages/i18n/src/locales/pt-BR.i18n.json (8)
1703-1703: LGTM – tradução correta e direta.
1778-1778: LGTM – placeholders corretos e mensagem clara.
2656-2656: LGTM – frase natural no contexto de edição.
2877-2877: LGTM – placeholder e ordem natural (“Última mensagem recebida {{time}}”).
4138-4138: LGTM – “Destinatário” adequado ao contexto.
5718-5718: LGTM – mensagem padrão de permissão consistente com o restante do arquivo.
6346-6346: LGTM – termo comum em toda a UI.
5683-5683: Verificar chave "Workspace_detail" — confirmadaEncontrada em en‑US (linha indicada na saída: 5777) e em pt‑BR (packages/i18n/src/locales/pt-BR.i18n.json:5683). Chave é singular em ambos — sem divergência.
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplatePreview.tsx (1)
42-43: Confirm Markdown sanitization to prevent XSS in previews.Templates may contain user‑entered text. Please confirm MarkdownText sanitizes HTML/URLs and that dangerous markdown is stripped in preview mode. If not, enable sanitization or pass the appropriate props.
apps/meteor/client/components/Omnichannel/OutboundMessage/utils/findLastChatFromChannel.ts (1)
3-5: Add explicit return type and confirm channel discriminator (name vs providerId)
- Make the function's return type explicit to aid callers/TS. Suggested change:
-export const findLastChatFromChannel = (channels: Serialized<ILivechatContactChannel>[] = [], providerId: string) => { +export const findLastChatFromChannel = ( + channels: Serialized<ILivechatContactChannel>[] = [], + providerId: string, +): Date | string | undefined => { const channel = channels.find((channel) => channel.name === providerId); return channel?.lastChat?.ts; };
- Verify that ILivechatContactChannel actually uses
nameas the provider identifier (it may beproviderIdor a nested field); ILivechatContactChannel typings were not found in this checkout — confirm the correct discriminator and the exact type oflastChat.ts, then update the return type accordingly.apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx (2)
7-10: Confirm mocked import path matches the component’s import.If
OutboundMessageModal.tsximports the wizard via a different relative path (index vs. file path), this mock won’t intercept it. Please verify path parity.
23-40: Close-confirmation flow test reads well.Good coverage of open → confirm → invoke
onClose. No changes needed.apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.spec.tsx (1)
81-87: Tests are comprehensive and exercise async states.Good use of
waitFor, pending/reject flows, and wizard navigation.Also applies to: 89-97, 99-117, 119-137
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/steps/ReviewStep.tsx (1)
27-29: Verify react-query version: isPending vs isLoading.If the repo is on @tanstack/react-query v4,
isPendingdoesn’t exist (useisLoading). Confirm version alignment to avoid runtime/typing errors.apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx (1)
81-128: Success/error flows look solid.Step validation, payload formatting, toast messages, and debug logging are consistent.
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx (1)
32-35: Baseline render test: looks goodPlaceholder assertion is a simple, effective smoke test for initial render.
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (3)
5-5: Import looks good.Adding
useQueryClientis appropriate for post-mutation cache management.
27-27: Right source of truth for keys.Importing
omnichannelQueryKeysis correct and keeps invalidations consistent.
81-81: LGTM: singlequeryClientinstance.Correct place and usage within the component.
apps/meteor/client/components/Omnichannel/OutboundMessage/components/TemplateSelect.spec.tsx
Show resolved
Hide resolved
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx
Outdated
Show resolved
Hide resolved
...or/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannelsItem.tsx
Show resolved
Hide resolved
...eteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
.changeset/rich-rules-sleep.md (1)
20-20: Polish release note and surface gating details.Add punctuation and briefly mention the permission gate to aid consumers scanning the changelog.
-Introduces the Outbound Message feature to Omnichannel, allowing organizations to initiate proactive communication with contacts through their preferred messaging channel directly from Rocket.Chat +Introduces the Omnichannel Outbound Message feature, enabling proactive communication with contacts via their preferred messaging channel directly from Rocket.Chat. +Requires permission: `outbound.send-messages`.apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (1)
180-180: Drop unnecessary optional chaining on guarded id.Inside
if (contactData),contactDatais truthy; usecontactData._idto avoid an accidentalundefined.- await editContact.mutateAsync({ contactId: contactData?._id, ...payload }); + await editContact.mutateAsync({ contactId: contactData._id, ...payload });apps/meteor/client/lib/queryKeys.ts (2)
76-78: Ensure const‑tuple typing for both branches.The
contactsbuilder lacksas conston the no‑arg branch, weakening type safety.- contacts: (query?: { filter: string; limit?: number }) => - !query ? [...omnichannelQueryKeys.all, 'contacts'] : ([...omnichannelQueryKeys.all, 'contacts', query] as const), + contacts: (query?: { filter: string; limit?: number }) => + !query ? ([...omnichannelQueryKeys.all, 'contacts'] as const) : ([...omnichannelQueryKeys.all, 'contacts', query] as const),
78-78: Avoid emittingundefinedin query keys.
contact(contactId?: string)can appendundefinedto the key. Prefer requiring an id (or branch like other builders).- contact: (contactId?: string) => [...omnichannelQueryKeys.contacts(), contactId] as const, + // Option A (preferred): require id + contact: (contactId: string) => [...omnichannelQueryKeys.contacts(), contactId] as const, + // Option B: branch by presence + // contact: (contactId?: string) => + // contactId ? ([...omnichannelQueryKeys.contacts(), contactId] as const) : ([...omnichannelQueryKeys.contacts()] as const),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.changeset/rich-rules-sleep.md(1 hunks)apps/meteor/client/lib/queryKeys.ts(2 hunks)apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx(4 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactInfoPhoneEntry.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (1)
apps/meteor/client/lib/queryKeys.ts (1)
omnichannelQueryKeys(30-82)
apps/meteor/client/lib/queryKeys.ts (1)
packages/core-typings/src/omnichannel/outbound.ts (1)
IOutboundProvider(134-139)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: 🔨 Test Unit / Unit Tests
- GitHub Check: 🔨 Test Storybook / Test Storybook
- GitHub Check: 🔎 Code Check / Code Lint
- GitHub Check: 🔎 Code Check / TypeScript
- GitHub Check: 📦 Meteor Build - coverage
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (5)
.changeset/rich-rules-sleep.md (2)
1-18: Changeset front‑matter structure looks valid.YAML block and second
---separator are correctly formed for a multi‑package changeset. Please just confirm SemVer intent for each bump, especially for@rocket.chat/core-typingsand@rocket.chat/apps-enginewhere non‑backward‑compatible type changes would require a major bump.
2-17: Verify package coverage and bump levels align with actual changes — rerun diagnosticThe prior diagnostic failed (awk / conditional errors). Run the corrected script below and paste its output; then ensure every changed workspace is listed in the changeset and that UI-only/internal copy changes are "patch" while public API/typings changes are "minor".
#!/usr/bin/env bash set -euo pipefail CS_FILE=".changeset/rich-rules-sleep.md" [[ -f "$CS_FILE" ]] || { echo "ERROR: $CS_FILE not found"; exit 0; } # parse changeset (name|bump) grep -E "^'[^']+':" "$CS_FILE" | sed -E "s/^'([^']+)':[[:space:]]*([a-zA-Z]+)/\1|\2/" > /tmp/changeset_pkgs.txt || true echo "Packages listed in this changeset:" cat /tmp/changeset_pkgs.txt || true BASE_REF=$(git merge-base origin/develop HEAD 2>/dev/null || true) if [[ -n "$BASE_REF" ]]; then RANGE="$BASE_REF...HEAD"; else RANGE="HEAD"; fi git diff --name-only "$RANGE" | grep -E '^(apps|packages)/[^/]+' | sed -E 's|^((apps|packages)/[^/]+)/.*|\1|' | sort -u > /tmp/changed_ws.txt || true echo echo "Workspaces with files changed in this PR:" cat /tmp/changed_ws.txt || true > /tmp/changed_pkg_names.txt while IFS= read -r ws; do [[ -z "$ws" ]] && continue pkg_json=$(find "$ws" -maxdepth 3 -name package.json -print -quit 2>/dev/null || true) if [[ -f "$pkg_json" ]]; then name=$(jq -r '.name // empty' "$pkg_json" 2>/dev/null || true) echo "$ws -> $name" [[ -n "$name" ]] && echo "$name" >> /tmp/changed_pkg_names.txt else echo "$ws -> (no package.json found)" fi done < /tmp/changed_ws.txt || true echo echo "Changed package names (from package.json):" sort -u /tmp/changed_pkg_names.txt || true echo echo "Changed-but-not-in-changeset:" comm -23 <(sort -u /tmp/changed_pkg_names.txt) <(sort -u /tmp/changeset_pkgs.txt) || true echo echo "In-changeset-but-not-changed:" comm -13 <(sort -u /tmp/changed_pkg_names.txt) <(sort -u /tmp/changeset_pkgs.txt) || trueIf the script shows any entries under "Changed-but-not-in-changeset", add them to the .changeset; if any appear under "In-changeset-but-not-changed", remove them or adjust bump level.
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (2)
180-186: Good fix: mutateAsync + prefix-key invalidation.Using mutateAsync keeps
isSubmittingaccurate, and invalidatingomnichannelQueryKeys.contacts()will refresh both lists and per-contact queries that share the prefix. This addresses the earlier UX/cache concerns.
5-5: LGTM: react-query integration.Importing
useQueryClient, centralizing keys viaomnichannelQueryKeys, and instantiatingqueryClientlocally is clean and consistent.Also applies to: 27-27, 81-81
apps/meteor/client/lib/queryKeys.ts (1)
79-81: Outbound provider keys: LGTM.Key shapes look consistent and specific enough for targeted invalidation/refetch.
f79c74f to
2c0f847
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/meteor/client/components/Omnichannel/OutboundMessage/constants.ts (3)
1-2: Avoid scattering hard-coded external URLs; prefer a single source of truth.
Consider grouping these under one exported map to ease future changes and reduce import churn:export const OUTBOUND_LINKS = { docs: OUTBOUND_DOCS_LINK, contactSales: CONTACT_SALES_LINK, } as const;I can help extract or consolidate other existing RC external links into this module if desired.
1-2: Ensure consumers open external links safely.
Where these constants are used with target="_blank", also set rel="noopener noreferrer" (or use a shared ExternalLink component) to prevent tabnabbing.
1-2: *Prefer _URL suffix — rename these constants for consistency.
Repo search shows 17 *_URL vs 10 *_LINK; rename OUTBOUND_DOCS_LINK → OUTBOUND_DOCS_URL and CONTACT_SALES_LINK → CONTACT_SALES_URL in apps/meteor/client/components/Omnichannel/OutboundMessage/constants.ts (lines 1–2).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/constants.ts(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx(1 hunks)apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageModal/OutboundMessageModal.spec.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx
- apps/meteor/client/components/Omnichannel/OutboundMessage/components/OutboundMessageWizard/forms/MessageForm/MessageForm.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: 📦 Build Packages
- GitHub Check: Builds matrix rust bindings against alpine
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (2)
apps/meteor/client/components/Omnichannel/OutboundMessage/constants.ts (2)
1-2: LGTM: extracting external links into constants improves reuse.
1-2: Links validated — both URLs resolve successfully (HTTP 200).
docs.rocket.chat returns 200 at https://docs.rocket.chat/docs/p2p-outbound-messaging; go.rocket.chat redirects to https://www.rocket.chat/sales-contact (final) and returns 200. No 404s or redirect loops found.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/i18n/src/locales/pt-BR.i18n.json (1)
1144-1149: Duplicate “contact” key resolved — thank you.A duplicidade sinalizada anteriormente foi removida; permanece apenas “contact”: “contato”. Nada mais a fazer.
🧹 Nitpick comments (3)
packages/i18n/src/locales/pt-BR.i18n.json (3)
2877-2877: Add missing colon after label.Fica mais natural e consistente com “Última mensagem: {{date}}”.
Apply this diff:
-"Last_message_received__time__": "Última mensagem recebida {{time}}", +"Last_message_received__time__": "Última mensagem recebida: {{time}}",
3835-3845: Outbound message strings read well; one terminology tweak.Padronizar “admin” → “administrador” para seguir o restante do arquivo.
Apply this diff:
-"Outbound_message_upsell_annotation": "Entre em contato com o admin do seu workspace para habilitar a mensagem ativa", +"Outbound_message_upsell_annotation": "Entre em contato com o administrador do seu workspace para habilitar a mensagem ativa",
5006-5009: Naturalness nit: “Template_message”.“Mensagem do modelo” soa mais natural em pt‑BR.
Apply this diff:
-"Template_message": "Mensagem modelo", +"Template_message": "Mensagem do modelo",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
packages/i18n/src/locales/en.i18n.json(23 hunks)packages/i18n/src/locales/pt-BR.i18n.json(15 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/i18n/src/locales/en.i18n.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: 📦 Build Packages
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (8)
packages/i18n/src/locales/pt-BR.i18n.json (8)
671-671: Wording OK for discard confirmation.Tradução consistente com “Mensagem ativa”. Nada a ajustar aqui.
1703-1703: LGTM: “Discard_message”.Texto curto e claro.
1978-1978: LGTM: placeholder preservado.“{{name}}” mantido corretamente.
3656-3656: LGTM: “Keep_editing”.Boa escolha verbal (“Continuar editando”).
4138-4138: LGTM: selection/recipient keys.Terminologia consistente (Destinatário/Selecionar ...).
Also applies to: 4581-4592
4646-4646: LGTM: “Message_preview”.Termo adequado para UI.
5684-5684: LGTM: “Workspace_detail”.Coerente com demais entradas.
5718-5718: LGTM: authorization message.Clara e direta.
Proposed changes (including videos or screenshots)
This PR introduces the Outbound Message feature to Omnichannel, allowing organizations to initiate proactive communication with contacts through their preferred messaging channel directly from Rocket.Chat.
Screen.Recording.2025-09-16.at.11.21.01.mov
Issue(s)
CTZ-186
Steps to test or reproduce
Further comments
Summary by CodeRabbit
New Features
Improvements
Chores