diff --git a/app/helpers/reporting_event_helper.rb b/app/helpers/reporting_event_helper.rb index e08b5691c..f0a419cc8 100644 --- a/app/helpers/reporting_event_helper.rb +++ b/app/helpers/reporting_event_helper.rb @@ -18,12 +18,25 @@ module ReportingEventHelper end def last_non_human_activity(conversation) - # check if a handoff event already exists - handoff_event = ReportingEvent.where(conversation_id: conversation.id, name: 'conversation_bot_handoff').last + # Try to get either a handoff or reopened event first + # These will always take precedence over any other activity + # Also, any of these events can happen at any time in the course of a conversation lifecycle. + # So we pick the latest event + event = ReportingEvent.where( + conversation_id: conversation.id, + name: %w[conversation_bot_handoff conversation_opened] + ).order(event_end_time: :desc).first - # if a handoff exists, last non human activity is when the handoff ended, - # otherwise it's when the conversation was created - handoff_event&.event_end_time || conversation.created_at + return event.event_end_time if event&.event_end_time + + # Fallback to bot resolved event + # Because this will be closest to the most accurate activity instead of conversation.created_at + bot_event = ReportingEvent.where(conversation_id: conversation.id, name: 'conversation_bot_resolved').last + + return bot_event.event_end_time if bot_event&.event_end_time + + # If no events found, return conversation creation time + conversation.created_at end private diff --git a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue index 610d11dab..fa9102d59 100644 --- a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue +++ b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue @@ -2,6 +2,7 @@ import { ref, computed, onMounted, watch } from 'vue'; import { useStore, useMapGetter } from 'dashboard/composables/store'; import { useI18n } from 'vue-i18n'; +import { useWindowSize } from '@vueuse/core'; import { useUISettings } from 'dashboard/composables/useUISettings'; import { vOnClickOutside } from '@vueuse/components'; import { useAlert } from 'dashboard/composables'; @@ -15,6 +16,7 @@ import { processContactableInboxes, mergeInboxDetails, } from 'dashboard/components-next/NewConversation/helpers/composeConversationHelper'; +import wootConstants from 'dashboard/constants/globals'; import ComposeNewConversationForm from 'dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue'; @@ -37,9 +39,16 @@ const emit = defineEmits(['close']); const store = useStore(); const { t } = useI18n(); +const { width: windowWidth } = useWindowSize(); const { fetchSignatureFlagFromUISettings } = useUISettings(); +const isSmallScreen = computed( + () => windowWidth.value < wootConstants.SMALL_SCREEN_BREAKPOINT +); + +const viewInModal = computed(() => props.isModal || isSmallScreen.value); + const contacts = ref([]); const selectedContact = ref(null); const targetInbox = ref(null); @@ -67,7 +76,7 @@ const directUploadsEnabled = computed( const activeContact = computed(() => contactById.value(props.contactId)); const composePopoverClass = computed(() => { - if (props.isModal) return ''; + if (viewInModal.value) return ''; return props.alignPosition === 'right' ? 'absolute ltr:left-0 ltr:right-[unset] rtl:right-0 rtl:left-[unset]' @@ -179,14 +188,18 @@ const toggle = () => { watch( activeContact, - () => { - if (activeContact.value && props.contactId) { - const contactInboxes = activeContact.value?.contactInboxes || []; + (currentContact, previousContact) => { + if (currentContact && props.contactId) { + // Reset on contact change + if (currentContact?.id !== previousContact?.id) clearSelectedContact(); + // First process the contactable inboxes to get the right structure - const processedInboxes = processContactableInboxes(contactInboxes); + const processedInboxes = processContactableInboxes( + currentContact.contactInboxes || [] + ); // Then Merge processedInboxes with the inboxes list selectedContact.value = { - ...activeContact.value, + ...currentContact, contactInboxes: mergeInboxDetails(processedInboxes, inboxesList.value), }; } @@ -202,7 +215,7 @@ const handleClickOutside = () => { }; const onModalBackdropClick = () => { - if (!props.isModal) return; + if (!viewInModal.value) return; handleClickOutside(); }; @@ -231,7 +244,7 @@ useKeyboardEvents(keyboardEvents); ]" class="relative" :class="{ - 'z-40': showComposeNewConversation, + 'z-50': showComposeNewConversation && !viewInModal, }" > {