From 642f97af6950738cbc2b4d3a2a7649bc6ba892cb Mon Sep 17 00:00:00 2001 From: Abhinav Raut Date: Wed, 19 Feb 2025 02:08:45 +0530 Subject: [PATCH] fix: fixes to sidebar for smaller devices. - fix: avatarless contact message bubble. - fix: set viewport width to device width. - revert[backend]: remove demo env check for starting backend services. i changed my mind. --- cmd/main.go | 20 +- frontend/index.html | 2 +- frontend/src/App.vue | 88 +- frontend/src/assets/styles/main.scss | 6 +- frontend/src/components/sidebar/Sidebar.vue | 864 ++++++------------ frontend/src/constants/navigation.js | 128 +++ .../conversation/list/ConversationList.vue | 4 +- .../message/ContactMessageBubble.vue | 2 +- frontend/src/stores/conversation.js | 4 +- frontend/src/stores/user.js | 20 +- frontend/src/utils/nav-permissions.js | 17 + .../conversation/ConversationDetailView.vue | 2 +- frontend/src/views/inbox/InboxView.vue | 2 +- frontend/tailwind.config.js | 1 + 14 files changed, 547 insertions(+), 613 deletions(-) create mode 100644 frontend/src/constants/navigation.js create mode 100644 frontend/src/utils/nav-permissions.js diff --git a/cmd/main.go b/cmd/main.go index b9d56153..10e5c6af 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -48,7 +48,6 @@ var ( ctx = context.Background() appName = "libredesk" frontendDir = "frontend/dist" - envDemo = "demo" // Injected at build time. buildString = "" @@ -171,16 +170,14 @@ func main() { ) automation.SetConversationStore(conversation) - if ko.MustString("app.env") != envDemo { - startInboxes(ctx, inbox, conversation) - go automation.Run(ctx, automationWorkers) - go autoassigner.Run(ctx, autoAssignInterval) - go conversation.Run(ctx, messageIncomingQWorkers, messageOutgoingQWorkers, messageOutgoingScanInterval) - go conversation.RunUnsnoozer(ctx, unsnoozeInterval) - go notifier.Run(ctx) - go sla.Run(ctx, slaEvaluationInterval) - go media.DeleteUnlinkedMedia(ctx) - } + startInboxes(ctx, inbox, conversation) + go automation.Run(ctx, automationWorkers) + go autoassigner.Run(ctx, autoAssignInterval) + go conversation.Run(ctx, messageIncomingQWorkers, messageOutgoingQWorkers, messageOutgoingScanInterval) + go conversation.RunUnsnoozer(ctx, unsnoozeInterval) + go notifier.Run(ctx) + go sla.Run(ctx, slaEvaluationInterval) + go media.DeleteUnlinkedMedia(ctx) var app = &App{ lo: lo, @@ -227,7 +224,6 @@ func main() { } go func() { - colorlog.Green("Starting HTTP server in %s mode", ko.String("app.env")) colorlog.Green("Server started at %s", ko.String("app.server.address")) if ko.String("server.socket") != "" { colorlog.Green("Unix socket created at %s", ko.String("server.socket")) diff --git a/frontend/index.html b/frontend/index.html index 3c1437c8..038b5f39 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,7 @@ - + -
- - -
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ -
- - + + +
+ diff --git a/frontend/src/constants/navigation.js b/frontend/src/constants/navigation.js new file mode 100644 index 00000000..5a653133 --- /dev/null +++ b/frontend/src/constants/navigation.js @@ -0,0 +1,128 @@ +export const reportsNavItems = [ + { + title: 'Overview', + href: '/reports/overview', + permission: 'reports:manage' + } +] + +export const adminNavItems = [ + { + title: 'Workspace', + children: [ + { + title: 'General', + href: '/admin/general', + permission: 'general_settings:manage' + }, + { + title: 'Business Hours', + href: '/admin/business-hours', + permission: 'business_hours:manage' + }, + { + title: 'SLA', + href: '/admin/sla', + permission: 'sla:manage' + } + ] + }, + { + title: 'Conversations', + children: [ + { + title: 'Tags', + href: '/admin/conversations/tags', + permission: 'tags:manage' + }, + { + title: 'Macros', + href: '/admin/conversations/macros', + permission: 'macros:manage' + }, + { + title: 'Statuses', + href: '/admin/conversations/statuses', + permission: 'status:manage' + } + ] + }, + { + title: 'Inboxes', + children: [ + { + title: 'Inboxes', + href: '/admin/inboxes', + permission: 'inboxes:manage' + } + ] + }, + { + title: 'Teammates', + children: [ + { + title: 'Users', + href: '/admin/teams/users', + permission: 'users:manage' + }, + { + title: 'Teams', + href: '/admin/teams/teams', + permission: 'teams:manage' + }, + { + title: 'Roles', + href: '/admin/teams/roles', + permission: 'roles:manage' + } + ] + }, + { + title: 'Automations', + children: [ + { + title: 'Automations', + href: '/admin/automations', + permission: 'automations:manage' + } + ] + }, + { + title: 'Notifications', + children: [ + { + title: 'Email', + href: '/admin/notification', + permission: 'notification_settings:manage' + } + ] + }, + { + title: 'Templates', + children: [ + { + title: 'Templates', + href: '/admin/templates', + permission: 'templates:manage' + } + ] + }, + { + title: 'Security', + children: [ + { + title: 'SSO', + href: '/admin/oidc', + permission: 'oidc:manage' + } + ] + } +] + +export const accountNavItems = [ + { + title: 'Profile', + href: '/account/profile', + description: 'Update your profile' + } +] diff --git a/frontend/src/features/conversation/list/ConversationList.vue b/frontend/src/features/conversation/list/ConversationList.vue index 0d00fd21..c9b32622 100644 --- a/frontend/src/features/conversation/list/ConversationList.vue +++ b/frontend/src/features/conversation/list/ConversationList.vue @@ -38,8 +38,8 @@ - Oldest - Newest + Oldest activity + Newest activity Started first diff --git a/frontend/src/features/conversation/message/ContactMessageBubble.vue b/frontend/src/features/conversation/message/ContactMessageBubble.vue index 1c356b40..933832df 100644 --- a/frontend/src/features/conversation/message/ContactMessageBubble.vue +++ b/frontend/src/features/conversation/message/ContactMessageBubble.vue @@ -82,7 +82,7 @@ const convStore = useConversationStore() const showQuotedText = ref(false) const getAvatar = computed(() => { - return convStore.current?.avatar_url || '' + return convStore.current?.contact.avatar_url || '' }) const sanitizedMessageContent = computed(() => { diff --git a/frontend/src/stores/conversation.js b/frontend/src/stores/conversation.js index 4723fd1e..fb9054d0 100644 --- a/frontend/src/stores/conversation.js +++ b/frontend/src/stores/conversation.js @@ -58,8 +58,8 @@ export const useConversationStore = defineStore('conversation', () => { } const sortFieldLabels = { - oldest: 'Oldest', - newest: 'Newest', + oldest: 'Oldest activity', + newest: 'Newest activity', started_first: 'Started first', started_last: 'Started last', waiting_longest: 'Waiting longest', diff --git a/frontend/src/stores/user.js b/frontend/src/stores/user.js index 97ede280..e03eacdc 100644 --- a/frontend/src/stores/user.js +++ b/frontend/src/stores/user.js @@ -3,6 +3,8 @@ 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', () => { @@ -37,6 +39,18 @@ export const useUserStore = defineStore('user', () => { 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() @@ -69,10 +83,6 @@ export const useUserStore = defineStore('user', () => { user.value.avatar_url = '' } - const can = (permission) => { - return user.value.permissions.includes(permission) - } - return { user, userID, @@ -84,6 +94,8 @@ export const useUserStore = defineStore('user', () => { permissions, getFullName, getInitials, + hasAdminTabPermissions, + hasReportTabPermissions, getCurrentUser, clearAvatar, setAvatar, diff --git a/frontend/src/utils/nav-permissions.js b/frontend/src/utils/nav-permissions.js new file mode 100644 index 00000000..83295490 --- /dev/null +++ b/frontend/src/utils/nav-permissions.js @@ -0,0 +1,17 @@ +export const filterNavItems = (navItems, can) => { + return navItems + .map(item => { + // Process children first + const filteredChildren = item.children + ? filterNavItems(item.children, can) + : undefined + // Check item's permission + const hasAccess = item.permission ? can(item.permission) : true + // Only keep the item if: + // 1. Has required permission (or none required) + // 2. Has valid children (if parent item) + const keep = hasAccess && (!item.children || filteredChildren.length > 0) + return keep ? { ...item, children: filteredChildren } : null + }) + .filter(Boolean) // Remove null entries +} \ No newline at end of file diff --git a/frontend/src/views/conversation/ConversationDetailView.vue b/frontend/src/views/conversation/ConversationDetailView.vue index 7014669b..c7c1f5d3 100644 --- a/frontend/src/views/conversation/ConversationDetailView.vue +++ b/frontend/src/views/conversation/ConversationDetailView.vue @@ -1,6 +1,6 @@