From 4303007786d527755bece2a2795729041c00fc27 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 11 Jun 2025 01:10:02 +0530 Subject: [PATCH] feat: Enhance Linear integration UX with multi-issue support and improved placement (#11668) Fixes https://linear.app/chatwoot/issue/CW-4150/support-for-multiple-issues-linking-in-linear This PR significantly improves the Linear integration user experience by relocating the Linear integration from the conversation header to the contact panel and adding support for multiple issue linking per conversation. ### Key Changes - **Relocated Linear integration**: Moved from conversation header to contact panel for better organization and accessibility - **Multi-issue support**: Added ability to link/create multiple Linear issues for a single conversation - **Integration CTA**: Added a dedicated call-to-action section for users who haven't connected their Linear account yet - **UI/UX improvements**: Enhanced design consistency and user flow
Screenshots #### Multiple Issues Support ![link-multiple-issues](https://github.com/user-attachments/assets/b56cfa7d-6f98-42db-b4bb-361ae59d0eae) #### Integration CTA ![link-multiple-issues](https://github.com/user-attachments/assets/a895fcbe-780a-47f8-9fa4-3a2af8b243e1) --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin Co-authored-by: Pranav Co-authored-by: Pranav --- .../conversation/ConversationHeader.vue | 24 -- .../widgets/conversation/linear/Issue.vue | 123 ------- .../conversation/linear/IssueHeader.vue | 44 ++- .../conversation/linear/IssuesList.vue | 132 ++++++++ .../conversation/linear/LinearIssueItem.vue | 111 +++++++ .../conversation/linear/LinearSetupCTA.vue | 54 ++++ .../widgets/conversation/linear/index.vue | 161 ---------- .../dashboard/composables/useUISettings.js | 1 + .../i18n/locale/en/conversation.json | 1 + .../i18n/locale/en/integrations.json | 7 + .../dashboard/conversation/ContactPanel.vue | 301 ++++++++++-------- 11 files changed, 494 insertions(+), 465 deletions(-) delete mode 100644 app/javascript/dashboard/components/widgets/conversation/linear/Issue.vue create mode 100644 app/javascript/dashboard/components/widgets/conversation/linear/IssuesList.vue create mode 100644 app/javascript/dashboard/components/widgets/conversation/linear/LinearIssueItem.vue create mode 100644 app/javascript/dashboard/components/widgets/conversation/linear/LinearSetupCTA.vue delete mode 100644 app/javascript/dashboard/components/widgets/conversation/linear/index.vue diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue index ec05b0eb4..7a3489265 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue @@ -11,8 +11,6 @@ import SLACardLabel from './components/SLACardLabel.vue'; import wootConstants from 'dashboard/constants/globals'; import { conversationListPageURL } from 'dashboard/helper/URLHelper'; import { snoozedReopenTime } from 'dashboard/helper/snoozeHelpers'; -import { FEATURE_FLAGS } from 'dashboard/featureFlags'; -import Linear from './linear/index.vue'; import { useInbox } from 'dashboard/composables/useInbox'; import { useI18n } from 'vue-i18n'; @@ -36,12 +34,6 @@ const { isAWebWidgetInbox } = useInbox(); const currentChat = computed(() => store.getters.getSelectedChat); const accountId = computed(() => store.getters.getCurrentAccountId); -const isFeatureEnabledonAccount = computed( - () => store.getters['accounts/isFeatureEnabledonAccount'] -); -const appIntegrations = computed( - () => store.getters['integrations/getAppIntegrations'] -); const chatMetadata = computed(() => props.chat.meta); @@ -92,16 +84,6 @@ const hasMultipleInboxes = computed( ); const hasSlaPolicyId = computed(() => props.chat?.sla_policy_id); - -const isLinearIntegrationEnabled = computed(() => - appIntegrations.value.find( - integration => integration.id === 'linear' && !!integration.hooks.length - ) -); - -const isLinearFeatureEnabled = computed(() => - isFeatureEnabledonAccount.value(accountId.value, FEATURE_FLAGS.LINEAR) -);