mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-23 02:53:32 +00:00
more fixes
This commit is contained in:
@@ -26,22 +26,21 @@ const userStore = useUserStore()
|
||||
// Initialize unread count tracking and sending to parent window.
|
||||
useUnreadCount()
|
||||
|
||||
const widgetConfig = getCurrentInstance().appContext.config.globalProperties.$widgetConfig
|
||||
if (widgetConfig) {
|
||||
widgetStore.updateConfig(widgetConfig)
|
||||
applyCSSColor('--primary', widgetConfig.colors?.primary)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Use pre-fetched widget config from main.js
|
||||
const widgetConfig = getCurrentInstance().appContext.config.globalProperties.$widgetConfig
|
||||
if (widgetConfig) {
|
||||
widgetStore.updateConfig(widgetConfig)
|
||||
// Apply custom primary color from config
|
||||
applyCSSColor('--primary', widgetConfig.colors?.primary)
|
||||
}
|
||||
|
||||
initializeWebSocket()
|
||||
|
||||
widgetStore.setOpen(true)
|
||||
|
||||
setupParentMessageListeners()
|
||||
|
||||
await chatStore.fetchConversations()
|
||||
// Only fetch conversations if not directly navigating to a conversation
|
||||
if (!widgetStore.config?.direct_to_conversation) {
|
||||
await chatStore.fetchConversations()
|
||||
}
|
||||
|
||||
// Notify parent window that Vue app is ready
|
||||
window.parent.postMessage(
|
||||
|
||||
@@ -245,8 +245,10 @@ const scrollToBottom = () => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Update last seen timestamp when conversation is opened
|
||||
chatStore.updateCurrentConversationLastSeen()
|
||||
// Update last seen timestamp only when widget is actually visible.
|
||||
if (widgetStore.isOpen) {
|
||||
chatStore.updateCurrentConversationLastSeen()
|
||||
}
|
||||
|
||||
// Check initial scroll position
|
||||
checkIfAtBottom()
|
||||
@@ -309,4 +311,18 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Watch for widget becoming visible - scroll to bottom and update last seen
|
||||
// This handles the direct_to_conversation case where messages load while widget is hidden
|
||||
watch(
|
||||
() => widgetStore.isOpen,
|
||||
(isOpen) => {
|
||||
if (isOpen && chatStore.currentConversation?.uuid) {
|
||||
chatStore.updateCurrentConversationLastSeen()
|
||||
setTimeout(() => {
|
||||
scrollToBottom()
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -46,10 +46,12 @@ import { computed } from 'vue'
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@shared-ui/components/ui/avatar'
|
||||
import { getRelativeTime } from '@shared-ui/utils/datetime.js'
|
||||
import { useBusinessHours } from '@widget/composables/useBusinessHours.js'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const chatStore = useChatStore()
|
||||
const widgetStore = useWidgetStore()
|
||||
const { resolveBusinessHours, getBusinessHoursStatus } = useBusinessHours()
|
||||
const { t } = useI18n()
|
||||
|
||||
const businessHoursStatus = computed(() => {
|
||||
const config = widgetStore.config
|
||||
@@ -84,6 +86,17 @@ const businessHoursStatus = computed(() => {
|
||||
})
|
||||
|
||||
const chatTitle = computed(() => {
|
||||
// Show loading state while conversation is being fetched
|
||||
if (chatStore.isLoadingConversation) {
|
||||
return {
|
||||
name: t('globals.terms.loading'),
|
||||
avatarUrl: '',
|
||||
avatarFallback: '',
|
||||
availability_status: null,
|
||||
hasAssignee: false
|
||||
}
|
||||
}
|
||||
|
||||
const config = widgetStore.config
|
||||
const assignee = chatStore.currentConversation?.assignee
|
||||
if (assignee?.id && assignee?.id > 0) {
|
||||
|
||||
@@ -60,9 +60,7 @@ const authorDisplayName = computed(() => {
|
||||
})
|
||||
|
||||
const continueConversation = async () => {
|
||||
// Load the conversation details and messages
|
||||
await chatStore.loadConversation(props.conversation.uuid)
|
||||
// Navigate to chat view
|
||||
widgetStore.navigateToChat()
|
||||
await chatStore.loadConversation(props.conversation.uuid)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,12 +7,6 @@ import { useI18n } from 'vue-i18n'
|
||||
export function useBusinessHours() {
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
* Get the business hours by ID from a list
|
||||
* @param {number} businessHoursId - Business hours ID
|
||||
* @param {Array} businessHoursList - List of business hours objects
|
||||
* @returns {Object|null} Business hours object or null
|
||||
*/
|
||||
function getBusinessHoursById(businessHoursId, businessHoursList) {
|
||||
if (!businessHoursId || !businessHoursList) {
|
||||
return null
|
||||
@@ -21,16 +15,6 @@ export function useBusinessHours() {
|
||||
return businessHoursList.find(bh => bh.id === businessHoursId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which business hours to use based on configuration
|
||||
* @param {Object} options - Configuration options
|
||||
* @param {boolean} options.showOfficeHours - Whether to show office hours
|
||||
* @param {boolean} options.showAfterAssignment - Whether to show team hours after assignment
|
||||
* @param {number|null} options.assignedBusinessHoursId - Business hours ID from assignment
|
||||
* @param {number|null} options.defaultBusinessHoursId - Default business hours ID
|
||||
* @param {Array} options.businessHoursList - List of available business hours
|
||||
* @returns {Object|null} Business hours object or null
|
||||
*/
|
||||
function resolveBusinessHours(options) {
|
||||
const {
|
||||
showOfficeHours,
|
||||
@@ -57,13 +41,6 @@ export function useBusinessHours() {
|
||||
return getBusinessHoursById(businessHoursId, businessHoursList)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given time is within business hours
|
||||
* @param {Object} businessHours - Business hours object
|
||||
* @param {Date} date - Date to check
|
||||
* @param {number} utcOffset - UTC offset in minutes
|
||||
* @returns {boolean} True if within business hours
|
||||
*/
|
||||
function isWithinBusinessHours(businessHours, date, utcOffset = 0) {
|
||||
if (!businessHours || businessHours.is_always_open) {
|
||||
return true
|
||||
@@ -93,12 +70,6 @@ export function useBusinessHours() {
|
||||
return currentTime >= schedule.open && currentTime <= schedule.close
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a date is a holiday
|
||||
* @param {Object} businessHours - Business hours object
|
||||
* @param {Date} date - Date to check
|
||||
* @returns {boolean} True if it's a holiday
|
||||
*/
|
||||
function isHoliday(businessHours, date) {
|
||||
if (!businessHours.holidays || businessHours.holidays.length === 0) {
|
||||
return false
|
||||
@@ -107,13 +78,6 @@ export function useBusinessHours() {
|
||||
return businessHours.holidays.some(holiday => holiday.date === dateStr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next working time
|
||||
* @param {Object} businessHours - Business hours object
|
||||
* @param {Date} fromDate - Date to start from
|
||||
* @param {number} utcOffset - UTC offset in minutes
|
||||
* @returns {Date|null} Next working time or null
|
||||
*/
|
||||
function getNextWorkingTime(businessHours, fromDate, utcOffset = 0) {
|
||||
if (!businessHours || businessHours.is_always_open) {
|
||||
return fromDate
|
||||
@@ -140,14 +104,18 @@ export function useBusinessHours() {
|
||||
const [openHour, openMinute] = schedule.open.split(':').map(Number)
|
||||
let nextWorking = setMinutes(setHours(localDate, openHour), openMinute)
|
||||
|
||||
// If it's the same day and current time is before opening time
|
||||
// Handle same-day logic
|
||||
if (i === 0) {
|
||||
const currentTime = format(localDate, 'HH:mm')
|
||||
// Currently within business hours
|
||||
if (currentTime >= schedule.open && currentTime < schedule.close) {
|
||||
return new Date(localDate.getTime() - (utcOffset * 60000))
|
||||
}
|
||||
// Before opening time today
|
||||
if (currentTime < schedule.open) {
|
||||
// Convert back from business timezone to user timezone
|
||||
return new Date(nextWorking.getTime() - (utcOffset * 60000))
|
||||
}
|
||||
// If it's the same day but past opening time, continue to next day
|
||||
// Past closing time, check next day
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -159,29 +127,11 @@ export function useBusinessHours() {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get day name from day number
|
||||
* @param {number} dayNum - Day number (0 = Sunday, 1 = Monday, etc.)
|
||||
* @returns {string} Day name
|
||||
*/
|
||||
// Returns English day name to match backend hours keys
|
||||
function getDayName(dayNum) {
|
||||
const days = [
|
||||
t('globals.days.sunday'),
|
||||
t('globals.days.monday'),
|
||||
t('globals.days.tuesday'),
|
||||
t('globals.days.wednesday'),
|
||||
t('globals.days.thursday'),
|
||||
t('globals.days.friday'),
|
||||
t('globals.days.saturday')
|
||||
]
|
||||
return days[dayNum]
|
||||
return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][dayNum]
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the next working time for display
|
||||
* @param {Date} nextWorkingTime - Next working time
|
||||
* @returns {string} Formatted string
|
||||
*/
|
||||
function formatNextWorkingTime(nextWorkingTime) {
|
||||
if (!nextWorkingTime) {
|
||||
return ''
|
||||
@@ -198,13 +148,6 @@ export function useBusinessHours() {
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get business hours status message and whether it's within business hours
|
||||
* @param {Object} businessHours - Business hours object
|
||||
* @param {number} utcOffset - UTC offset in minutes
|
||||
* @param {string} withinHoursMessage - Message to show when within hours
|
||||
* @returns {Object|null} { status: string|null, isWithin: boolean } or null
|
||||
*/
|
||||
function getBusinessHoursStatus(businessHours, utcOffset = 0, withinHoursMessage = '') {
|
||||
if (!businessHours) {
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user