fix(whatsapp): refresh inboxes when opening new conversation composer (#15337)
When an agent starts a new conversation, the WhatsApp template picker in the composer only shows templates that were already loaded into the frontend store — it doesn't refresh when the composer opens. If a template sync completed after the store was last populated, the newly synced template shows up on the inbox's Settings > Templates page (which always refetches on load) but not in the New Conversation composer, since that view relied solely on the account-cache-invalidated websocket event, which doesn't always reach an already-open session in time. ## What changed - `ComposeConversation.vue` now dispatches a cache-aware `inboxes/get` refetch every time the composer popover opens, so the WhatsApp template list is current before an agent picks a template to message a customer. The refetch checks the account's cache key first and only re-pulls the full inbox list when it's actually stale, so it stays cheap in the common case. ## How to reproduce 1. Sync/update WhatsApp templates for an inbox (e.g. via Settings > Inboxes > [WhatsApp inbox] > Sync Templates). 2. Without reloading the page, open the New Conversation composer for that inbox and check the WhatsApp template picker — a newly synced template may be missing until this fix. --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
committed by
GitHub
parent
78069b01f6
commit
430c5cfef0
@@ -201,6 +201,9 @@ const onPopoverShow = () => {
|
||||
// Flag to prevent triggering drag n drop,
|
||||
// When compose modal is active
|
||||
emitter.emit(BUS_EVENTS.NEW_CONVERSATION_MODAL, true);
|
||||
// Cache-aware refetch, so newly synced WhatsApp templates show up here
|
||||
// even if the account-cache-invalidated websocket event was missed.
|
||||
store.dispatch('inboxes/get');
|
||||
};
|
||||
|
||||
const onPopoverHide = () => {
|
||||
|
||||
@@ -21,10 +21,15 @@ const { t } = useI18n();
|
||||
const getFilteredWhatsAppTemplates = useMapGetter(
|
||||
'inboxes/getFilteredWhatsAppTemplates'
|
||||
);
|
||||
const inboxesUiFlags = useMapGetter('inboxes/getUIFlags');
|
||||
|
||||
const searchQuery = ref('');
|
||||
const selectedTemplate = ref(null);
|
||||
|
||||
// Gates the trigger while ComposeConversation's on-open refetch is in flight,
|
||||
// so an agent can't open the picker before a stale template list is refreshed.
|
||||
const isRefreshingTemplates = computed(() => inboxesUiFlags.value.isFetching);
|
||||
|
||||
const whatsAppTemplateMessages = computed(() => {
|
||||
return getFilteredWhatsAppTemplates.value(props.inboxId);
|
||||
});
|
||||
@@ -74,7 +79,7 @@ const handleSendMessage = (template, hide) => {
|
||||
:label="t('COMPOSE_NEW_CONVERSATION.FORM.WHATSAPP_OPTIONS.LABEL')"
|
||||
color="slate"
|
||||
size="sm"
|
||||
:disabled="selectedTemplate"
|
||||
:disabled="selectedTemplate || isRefreshingTemplates"
|
||||
class="!text-xs font-medium"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
|
||||
@@ -35,9 +35,12 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi
|
||||
def sync_templates
|
||||
# ensuring that channels with wrong provider config wouldn't keep trying to sync templates
|
||||
whatsapp_channel.mark_message_templates_updated
|
||||
templates = fetch_whatsapp_templates
|
||||
return if (templates = fetch_whatsapp_templates).blank?
|
||||
|
||||
# update_columns skips touch, so bump the cache key ourselves; only if templates changed
|
||||
whatsapp_channel.account.update_cache_key('inbox') if templates != whatsapp_channel.message_templates
|
||||
# rubocop:disable Rails/SkipsModelValidations
|
||||
whatsapp_channel.update_columns(message_templates: templates, message_templates_last_updated: Time.current) if templates.present?
|
||||
whatsapp_channel.update_columns(message_templates: templates, message_templates_last_updated: Time.current)
|
||||
# rubocop:enable Rails/SkipsModelValidations
|
||||
end
|
||||
|
||||
|
||||
@@ -383,13 +383,23 @@ describe Whatsapp::Providers::WhatsappCloudService do
|
||||
)
|
||||
|
||||
timstamp = whatsapp_channel.reload.message_templates_last_updated
|
||||
expect(subject.sync_templates).to be(true)
|
||||
expect(whatsapp_channel.account).to receive(:update_cache_key).with('inbox').and_call_original
|
||||
subject.sync_templates
|
||||
expect(whatsapp_channel.reload.message_templates.first).to eq({ id: '123456789', name: 'test_template' }.stringify_keys)
|
||||
expect(whatsapp_channel.reload.message_templates.second).to eq({ id: '123456789', name: 'next_template' }.stringify_keys)
|
||||
expect(whatsapp_channel.reload.message_templates.last).to eq({ id: '123456789', name: 'last_template' }.stringify_keys)
|
||||
expect(whatsapp_channel.reload.message_templates_last_updated).not_to eq(timstamp)
|
||||
end
|
||||
|
||||
it 'does not bump the inbox cache key when no templates are returned' do
|
||||
stub_request(:get, 'https://graph.facebook.com/v14.0/123456789/message_templates')
|
||||
.with(headers: { 'Authorization' => 'Bearer test_key' })
|
||||
.to_return(status: 200, headers: response_headers, body: { data: [] }.to_json)
|
||||
|
||||
expect(whatsapp_channel.account).not_to receive(:update_cache_key)
|
||||
subject.sync_templates
|
||||
end
|
||||
|
||||
it 'updates message_templates_last_updated even when template request fails' do
|
||||
stub_request(:get, 'https://graph.facebook.com/v14.0/123456789/message_templates')
|
||||
.with(headers: { 'Authorization' => 'Bearer test_key' })
|
||||
|
||||
Reference in New Issue
Block a user