diff --git a/app/javascript/dashboard/components-next/message/chips/File.vue b/app/javascript/dashboard/components-next/message/chips/File.vue index df9961c46..8638fd15d 100644 --- a/app/javascript/dashboard/components-next/message/chips/File.vue +++ b/app/javascript/dashboard/components-next/message/chips/File.vue @@ -16,20 +16,41 @@ const { t } = useI18n(); const fileName = computed(() => { const url = attachment.dataUrl; - if (url) { - const filename = url.substring(url.lastIndexOf('/') + 1); - return filename || t('CONVERSATION.UNKNOWN_FILE_TYPE'); + if (!url) return t('CONVERSATION.UNKNOWN_FILE_TYPE'); + + try { + const encodedFilename = url.substring(url.lastIndexOf('/') + 1); + return decodeURIComponent(encodedFilename); + } catch { + return t('CONVERSATION.UNKNOWN_FILE_TYPE'); } - return t('CONVERSATION.UNKNOWN_FILE_TYPE'); }); -const fileType = computed(() => { - return fileName.value.split('.').pop(); -}); +const fileType = computed(() => fileName.value.split('.').pop()?.toLowerCase()); const fileNameWithoutExt = computed(() => { const parts = fileName.value.split('.'); - return parts.slice(0, -1).join('.') || fileName.value; + + // If there's no extension (no dots in filename) + if (parts.length === 1) { + return fileName.value.trim(); + } + + // Take all parts except the last one (extension) + const nameWithoutExt = parts.slice(0, -1).join('.'); + return nameWithoutExt.trim(); +}); + +const displayFileName = computed(() => { + const name = fileNameWithoutExt.value; + const truncatedName = (str, maxLength, hasExt) => + str.length > maxLength + ? `${str.substring(0, maxLength).trimEnd()}${hasExt ? '..' : '...'}` + : str; + + return fileType.value + ? `${truncatedName(name, 14, true)}.${fileType.value}` + : truncatedName(name, 16, false); }); const textColorClass = computed(() => { @@ -62,17 +83,15 @@ const textColorClass = computed(() => { > - - {{ fileNameWithoutExt }} - - .{{ fileType }} + {{ displayFileName }} { icon: 'i-lucide-inbox', to: accountScopedRoute('inbox_view'), activeOn: ['inbox_view', 'inbox_view_conversation'], + getterKeys: { + badge: 'notifications/getHasUnreadNotifications', + }, }, { name: 'Conversation', diff --git a/app/javascript/dashboard/components-next/sidebar/SidebarGroup.vue b/app/javascript/dashboard/components-next/sidebar/SidebarGroup.vue index 305171d10..64345c7de 100644 --- a/app/javascript/dashboard/components-next/sidebar/SidebarGroup.vue +++ b/app/javascript/dashboard/components-next/sidebar/SidebarGroup.vue @@ -15,6 +15,7 @@ const props = defineProps({ to: { type: Object, default: null }, activeOn: { type: Array, default: () => [] }, children: { type: Array, default: undefined }, + getterKeys: { type: Object, default: () => ({}) }, }); const { @@ -143,6 +144,7 @@ onMounted(async () => { :name :label :to + :getter-keys="getterKeys" :is-active="isActive" :has-active-child="hasActiveChild" :expandable="hasChildren" diff --git a/app/javascript/dashboard/components-next/sidebar/SidebarGroupHeader.vue b/app/javascript/dashboard/components-next/sidebar/SidebarGroupHeader.vue index 160483a6a..1fd1786a0 100644 --- a/app/javascript/dashboard/components-next/sidebar/SidebarGroupHeader.vue +++ b/app/javascript/dashboard/components-next/sidebar/SidebarGroupHeader.vue @@ -1,7 +1,8 @@