mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-10-23 05:11:57 +00:00
New columns in users table to store user availability status. Websocket pings sets the last active at timestamp, once user stops sending pings (on disconnect) after 5 minutes the user availalbility status changes to offline. Detects auto away by checking for mouse, keyboard events and sets user status to away. User can also set their status to away manually from the sidebar. Migrations for v0.3.0 Minor visual fixes. Bump version in package.json
121 lines
3.3 KiB
JavaScript
121 lines
3.3 KiB
JavaScript
import { ref, computed } from 'vue'
|
|
import { defineStore } from 'pinia'
|
|
import { handleHTTPError } from '@/utils/http'
|
|
import { useEmitter } from '@/composables/useEmitter'
|
|
import { EMITTER_EVENTS } from '@/constants/emitterEvents'
|
|
import { adminNavItems, reportsNavItems } from '@/constants/navigation'
|
|
import { filterNavItems } from '@/utils/nav-permissions'
|
|
import api from '@/api'
|
|
|
|
export const useUserStore = defineStore('user', () => {
|
|
const user = ref({
|
|
id: null,
|
|
first_name: '',
|
|
last_name: '',
|
|
avatar_url: '',
|
|
email: '',
|
|
teams: [],
|
|
permissions: [],
|
|
availability_status: 'offline'
|
|
})
|
|
const emitter = useEmitter()
|
|
|
|
const userID = computed(() => user.value.id)
|
|
const firstName = computed(() => user.value.first_name || '')
|
|
const lastName = computed(() => user.value.last_name || '')
|
|
const avatar = computed(() => user.value.avatar_url || '')
|
|
const permissions = computed(() => user.value.permissions || [])
|
|
const email = computed(() => user.value.email)
|
|
const teams = computed(() => user.value.teams || [])
|
|
|
|
const getFullName = computed(() => {
|
|
const first = user.value.first_name ?? ''
|
|
const last = user.value.last_name ?? ''
|
|
return `${first} ${last}`.trim()
|
|
})
|
|
|
|
const getInitials = computed(() => {
|
|
const firstInitial = user.value.first_name?.charAt(0)?.toUpperCase() || ''
|
|
const lastInitial = user.value.last_name?.charAt(0)?.toUpperCase() || ''
|
|
return `${firstInitial}${lastInitial}`
|
|
})
|
|
|
|
const can = (permission) => {
|
|
return user.value.permissions.includes(permission)
|
|
}
|
|
|
|
const hasAdminTabPermissions = computed(() => {
|
|
return filterNavItems(adminNavItems, can).length > 0
|
|
})
|
|
|
|
const hasReportTabPermissions = computed(() => {
|
|
return filterNavItems(reportsNavItems, can).length > 0
|
|
})
|
|
|
|
const getCurrentUser = async () => {
|
|
try {
|
|
const response = await api.getCurrentUser()
|
|
const userData = response?.data?.data
|
|
if (userData) {
|
|
user.value = userData
|
|
} else {
|
|
throw new Error('No user data found')
|
|
}
|
|
} catch (error) {
|
|
if (error.response?.status !== 401) {
|
|
emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
|
|
title: 'Could not fetch current user',
|
|
variant: 'destructive',
|
|
description: handleHTTPError(error).message
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
const setCurrentUser = (userData) => {
|
|
user.value = userData
|
|
}
|
|
|
|
const setAvatar = (avatarURL) => {
|
|
if (typeof avatarURL !== 'string') {
|
|
console.warn('Avatar URL must be a string')
|
|
return
|
|
}
|
|
user.value.avatar_url = avatarURL
|
|
}
|
|
|
|
const clearAvatar = () => {
|
|
user.value.avatar_url = ''
|
|
}
|
|
|
|
const updateUserAvailability = async (status, isManual = true) => {
|
|
try {
|
|
const apiStatus = status === 'away' && isManual ? 'away_manual' : status
|
|
await api.updateCurrentUserAvailability({ status: apiStatus })
|
|
user.value.availability_status = apiStatus
|
|
} catch (error) {
|
|
if (error?.response?.status === 401) window.location.href = '/'
|
|
}
|
|
}
|
|
|
|
return {
|
|
user,
|
|
userID,
|
|
firstName,
|
|
lastName,
|
|
avatar,
|
|
email,
|
|
teams,
|
|
permissions,
|
|
getFullName,
|
|
getInitials,
|
|
hasAdminTabPermissions,
|
|
hasReportTabPermissions,
|
|
setCurrentUser,
|
|
getCurrentUser,
|
|
clearAvatar,
|
|
setAvatar,
|
|
updateUserAvailability,
|
|
can
|
|
}
|
|
}) |