+
{
searchTerm.value = value;
+ emits('on-search', value);
};
const filteredListItems = computed(() => {
@@ -55,7 +58,7 @@ const isFilterActive = id => {
>
+
@@ -89,6 +93,8 @@ 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';
export default {
components: {
@@ -97,6 +103,7 @@ export default {
MoreActions,
Thumbnail,
SLACardLabel,
+ Linear,
},
mixins: [inboxMixin, agentMixin, keyboardEventListenerMixins],
props: {
@@ -121,6 +128,9 @@ export default {
...mapGetters({
uiFlags: 'inboxAssignableAgents/getUIFlags',
currentChat: 'getSelectedChat',
+ accountId: 'getCurrentAccountId',
+ isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
+ appIntegrations: 'integrations/getAppIntegrations',
}),
chatMetadata() {
return this.chat.meta;
@@ -178,6 +188,17 @@ export default {
hasSlaPolicyId() {
return this.chat?.sla_policy_id;
},
+ isLinearIntegrationEnabled() {
+ return this.appIntegrations.find(
+ integration => integration.id === 'linear' && !!integration.hooks.length
+ );
+ },
+ isLinearFeatureEnabled() {
+ return this.isFeatureEnabledonAccount(
+ this.accountId,
+ FEATURE_FLAGS.LINEAR
+ );
+ },
},
methods: {
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
new file mode 100644
index 000000000..cd3976ec4
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL') }}
+
+
+ {{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE') }}
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue
new file mode 100644
index 000000000..f15b40409
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/Issue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/Issue.vue
new file mode 100644
index 000000000..05cd3ab88
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/Issue.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+ {{ issue.title }}
+
+
+ {{ issue.description }}
+
+
+
+
+
+
+
+
+ {{ issue.state.name }}
+
+
+
+
+
+
{{ priorityLabel }}
+
+
+
+
+
+
+
+ {{
+ $t('INTEGRATION_SETTINGS.LINEAR.ISSUE.CREATED_AT', {
+ createdAt: formattedDate,
+ })
+ }}
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/IssueHeader.vue b/app/javascript/dashboard/components/widgets/conversation/linear/IssueHeader.vue
new file mode 100644
index 000000000..bf907dc69
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/IssueHeader.vue
@@ -0,0 +1,56 @@
+
+
+
+
+ {{ identifier }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/LinkIssue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/LinkIssue.vue
new file mode 100644
index 000000000..404837fc7
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/LinkIssue.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+ {{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL') }}
+
+
+ {{ $t('INTEGRATION_SETTINGS.LINEAR.LINK.TITLE') }}
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/index.vue b/app/javascript/dashboard/components/widgets/conversation/linear/index.vue
new file mode 100644
index 000000000..ffb98db9e
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/index.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
+ {{ linkedIssue.issue.identifier }}
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/validations.js b/app/javascript/dashboard/components/widgets/conversation/linear/validations.js
new file mode 100644
index 000000000..d30b790a7
--- /dev/null
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/validations.js
@@ -0,0 +1,10 @@
+import { required } from '@vuelidate/validators';
+
+export default {
+ title: {
+ required,
+ },
+ teamId: {
+ required,
+ },
+};
diff --git a/app/javascript/dashboard/featureFlags.js b/app/javascript/dashboard/featureFlags.js
index a0453b7d3..11d6c43de 100644
--- a/app/javascript/dashboard/featureFlags.js
+++ b/app/javascript/dashboard/featureFlags.js
@@ -30,4 +30,5 @@ export const FEATURE_FLAGS = {
EMAIL_CONTINUITY_ON_API_CHANNEL: 'email_continuity_on_api_channel',
INBOUND_EMAILS: 'inbound_emails',
IP_LOOKUP: 'ip_lookup',
+ LINEAR: 'linear_integration',
};
diff --git a/app/javascript/dashboard/i18n/locale/en/integrations.json b/app/javascript/dashboard/i18n/locale/en/integrations.json
index 231892079..84390d5b1 100644
--- a/app/javascript/dashboard/i18n/locale/en/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/en/integrations.json
@@ -203,6 +203,74 @@
"API_SUCCESS": "Dashboard app deleted successfully",
"API_ERROR": "We couldn't delete the app. Please try again later"
}
+ },
+ "LINEAR": {
+ "ADD_OR_LINK_BUTTON": "Create/Link Linear Issue",
+ "LOADING": "Fetching linear issues...",
+ "LOADING_ERROR": "There was an error fetching the linear issues, please try again",
+ "CREATE": "Create",
+ "LINK": {
+ "SEARCH": "Search issues",
+ "SELECT": "Select issue",
+ "TITLE": "Link",
+ "EMPTY_LIST": "No linear issues found",
+ "LOADING": "Loading",
+ "ERROR": "There was an error fetching the linear issues, please try again",
+ "LINK_SUCCESS": "Issue linked successfully",
+ "LINK_ERROR": "There was an error linking the issue, please try again"
+ },
+ "ADD_OR_LINK": {
+ "TITLE": "Create/link linear issue",
+ "DESCRIPTION": "Create Linear issues from conversations, or link existing ones for seamless tracking.",
+ "FORM": {
+ "TITLE": {
+ "LABEL": "Title",
+ "PLACEHOLDER": "Enter title",
+ "REQUIRED_ERROR": "Title is required"
+ },
+ "DESCRIPTION": {
+ "LABEL": "Description",
+ "PLACEHOLDER": "Enter description"
+ },
+ "TEAM": {
+ "LABEL": "Team",
+ "REQUIRED_ERROR": "Team is required"
+ },
+ "ASSIGNEE": {
+ "LABEL": "Assignee"
+ },
+ "PRIORITY": {
+ "LABEL": "Priority"
+ },
+ "LABEL": {
+ "LABEL": "Label"
+ },
+ "STATUS": {
+ "LABEL": "Status"
+ },
+ "PROJECT": {
+ "LABEL": "Project"
+ }
+ },
+ "CREATE": "Create",
+ "CANCEL": "Cancel",
+ "CREATE_SUCCESS": "Issue created successfully",
+ "CREATE_ERROR": "There was an error creating the issue, please try again",
+ "LOADING_TEAM_ERROR": "There was an error fetching the teams, please try again",
+ "LOADING_TEAM_ENTITIES_ERROR": "There was an error fetching the team entities, please try again"
+ },
+ "ISSUE": {
+ "STATUS": "Status",
+ "PRIORITY": "Priority",
+ "ASSIGNEE": "Assignee",
+ "LABELS": "Labels",
+ "CREATED_AT": "Created at %{createdAt}"
+ },
+ "UNLINK": {
+ "TITLE": "Unlink",
+ "SUCCESS": "Issue unlinked successfully",
+ "ERROR": "There was an error unlinking the issue, please try again"
+ }
}
}
}
diff --git a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
index aa5f5cc12..731ac26e4 100644
--- a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
+++ b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
@@ -145,7 +145,6 @@ import CustomAttributes from './customAttributes/CustomAttributes.vue';
import draggable from 'vuedraggable';
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import MacrosList from './Macros/List.vue';
-
export default {
components: {
AccordionItem,
diff --git a/app/javascript/shared/components/FluentIcon/dashboard-icons.json b/app/javascript/shared/components/FluentIcon/dashboard-icons.json
index 60c691b7d..f58c2a7dd 100644
--- a/app/javascript/shared/components/FluentIcon/dashboard-icons.json
+++ b/app/javascript/shared/components/FluentIcon/dashboard-icons.json
@@ -275,5 +275,8 @@
"chevrons-right-outline": ["m6 17 5-5-5-5", "m13 17 5-5-5-5"],
"chevron-right-single-outline": "m9 18 6-6-6-6",
"avatar-upload-outline": "M19.754 11a.75.75 0 0 1 .743.648l.007.102v7a3.25 3.25 0 0 1-3.065 3.246l-.185.005h-11a3.25 3.25 0 0 1-3.244-3.066l-.006-.184V11.75a.75.75 0 0 1 1.494-.102l.006.102v7a1.75 1.75 0 0 0 1.607 1.745l.143.006h11A1.75 1.75 0 0 0 19 18.894l.005-.143V11.75a.75.75 0 0 1 .75-.75ZM6.22 7.216l4.996-4.996a.75.75 0 0 1 .976-.073l.084.072l5.005 4.997a.75.75 0 0 1-.976 1.134l-.084-.073l-3.723-3.716l.001 11.694a.75.75 0 0 1-.648.743l-.102.007a.75.75 0 0 1-.743-.648L11 16.255V4.558L7.28 8.277a.75.75 0 0 1-.976.073l-.084-.073a.75.75 0 0 1-.073-.977l.073-.084l4.996-4.996L6.22 7.216Z",
- "text-copy-outline": "M5.503 4.627L5.5 6.75v10.504a3.25 3.25 0 0 0 3.25 3.25h8.616a2.25 2.25 0 0 1-2.122 1.5H8.75A4.75 4.75 0 0 1 4 17.254V6.75c0-.98.627-1.815 1.503-2.123M17.75 2A2.25 2.25 0 0 1 20 4.25v13a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-13A2.25 2.25 0 0 1 8.75 2zm0 1.5h-9a.75.75 0 0 0-.75.75v13c0 .414.336.75.75.75h9a.75.75 0 0 0 .75-.75v-13a.75.75 0 0 0-.75-.75"
+ "text-copy-outline": "M5.503 4.627L5.5 6.75v10.504a3.25 3.25 0 0 0 3.25 3.25h8.616a2.25 2.25 0 0 1-2.122 1.5H8.75A4.75 4.75 0 0 1 4 17.254V6.75c0-.98.627-1.815 1.503-2.123M17.75 2A2.25 2.25 0 0 1 20 4.25v13a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-13A2.25 2.25 0 0 1 8.75 2zm0 1.5h-9a.75.75 0 0 0-.75.75v13c0 .414.336.75.75.75h9a.75.75 0 0 0 .75-.75v-13a.75.75 0 0 0-.75-.75",
+ "linear-outline": "M1.17156 10.4618C1.14041 10.329 1.2986 10.2454 1.39505 10.3418L6.50679 15.4536C6.60323 15.55 6.5196 15.7082 6.38681 15.6771C3.80721 15.0719 1.77669 13.0414 1.17156 10.4618ZM1.00026 8.4131C0.997795 8.45277 1.01271 8.49149 1.0408 8.51959L8.32904 15.8078C8.35714 15.8359 8.39586 15.8509 8.43553 15.8484C8.76721 15.8277 9.09266 15.784 9.41026 15.7187C9.51729 15.6968 9.55447 15.5653 9.47721 15.488L1.36063 7.37142C1.28337 7.29416 1.15187 7.33134 1.12989 7.43837C1.06466 7.75597 1.02092 8.08142 1.00026 8.4131ZM1.58953 6.00739C1.56622 6.05972 1.57809 6.12087 1.6186 6.16139L10.6872 15.23C10.7278 15.2705 10.7889 15.2824 10.8412 15.2591C11.0913 15.1477 11.3336 15.0221 11.5672 14.8833C11.6445 14.8374 11.6564 14.7312 11.5929 14.6676L2.18099 5.25577C2.11742 5.1922 2.01121 5.20412 1.96529 5.28142C1.8265 5.51499 1.70091 5.75733 1.58953 6.00739ZM2.77222 4.37899C2.7204 4.32718 2.7172 4.24407 2.76602 4.18942C4.04913 2.75294 5.9156 1.84863 7.99327 1.84863C11.863 1.84863 15 4.98565 15 8.85536C15 10.933 14.0957 12.7995 12.6592 14.0826C12.6046 14.1314 12.5215 14.1282 12.4696 14.0764L2.77222 4.37899Z",
+ "status-outline": "m8.462 6.81l3.284 13.616c.178.737 1.211.775 1.443.054l3.257-10.122l.586 2.095a.75.75 0 0 0 .722.548h3.494a.75.75 0 0 0 0-1.5h-2.925l-1.105-3.95c-.2-.717-1.208-.736-1.436-.028l-3.203 9.957L9.224 3.574c-.182-.757-1.255-.769-1.454-.016l-2.1 7.943H2.75a.75.75 0 0 0 0 1.5h3.496a.75.75 0 0 0 .725-.558z",
+ "unlink-outline": "m18.84 12.25l1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07a5.006 5.006 0 0 0-6.95 0l-1.72 1.71m-6.58 6.57l-1.71 1.71a5.004 5.004 0 0 0 .12 7.07a5.006 5.006 0 0 0 6.95 0l1.71-1.71M8 2v3M2 8h3m11 11v3m3-6h3"
}
diff --git a/lib/linear.rb b/lib/linear.rb
index 63489b060..2e801c673 100644
--- a/lib/linear.rb
+++ b/lib/linear.rb
@@ -56,7 +56,8 @@ class Linear
description: params[:description],
assigneeId: params[:assignee_id],
priority: params[:priority],
- labelIds: params[:label_ids]
+ labelIds: params[:label_ids],
+ projectId: params[:project_id]
}.compact
mutation = Linear::Mutations.issue_create(variables)
response = post({ query: mutation })
From 9f625715ab9ab99837f38faaa2294b5eac8fef4e Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Thu, 23 May 2024 12:08:04 +0530
Subject: [PATCH 15/56] fix: Cannot read properties of undefined (reading
'toLowerCase') (#9511)
Tried to replicate the issue, but Sentry didn't have enough information.
`toggleMessageSignature` is a user triggered action in
`ReplyBottomPanel.vue`, the value for `channelType` is provided from
`inboxMixin`. The error will occur if either `inbox` is an empty object
`{}` or `channel_type` in `inbox` object is undefined.
I couldn't find any instance where this could be the case. The PR has a
stop gap solution that ensures that no action is triggered
---
app/javascript/dashboard/mixins/uiSettings.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/javascript/dashboard/mixins/uiSettings.js b/app/javascript/dashboard/mixins/uiSettings.js
index 2c60db3cb..f3743c402 100644
--- a/app/javascript/dashboard/mixins/uiSettings.js
+++ b/app/javascript/dashboard/mixins/uiSettings.js
@@ -15,7 +15,7 @@ export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = [
];
const slugifyChannel = name =>
- name.toLowerCase().replace(' ', '_').replace('-', '_').replace('::', '_');
+ name?.toLowerCase().replace(' ', '_').replace('-', '_').replace('::', '_');
export const isEditorHotKeyEnabled = (uiSettings, key) => {
const {
@@ -70,6 +70,8 @@ export default {
this.updateUISettings({ [key]: !this.isContactSidebarItemOpen(key) });
},
setSignatureFlagForInbox(channelType, value) {
+ if (!channelType) return;
+
channelType = slugifyChannel(channelType);
this.updateUISettings({
[`${channelType}_signature_enabled`]: value,
From 0c4c561313cf3cdd73b5c29856606d1d9790da4f Mon Sep 17 00:00:00 2001
From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Date: Thu, 23 May 2024 12:34:42 +0530
Subject: [PATCH 16/56] feat: Adds the ability to add line breaks in helpcenter
articles (#9519)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 78fb2fed1..9ce31d9cf 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
],
"dependencies": {
"@braid/vue-formulate": "^2.5.2",
- "@chatwoot/prosemirror-schema": "1.0.5",
+ "@chatwoot/prosemirror-schema": "1.0.9",
"@chatwoot/utils": "^0.0.25",
"@hcaptcha/vue-hcaptcha": "^0.3.2",
"@june-so/analytics-next": "^2.0.0",
diff --git a/yarn.lock b/yarn.lock
index daecee4b6..83c0ee403 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3165,10 +3165,10 @@
hotkeys-js "3.8.7"
lit "2.2.6"
-"@chatwoot/prosemirror-schema@1.0.5":
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/@chatwoot/prosemirror-schema/-/prosemirror-schema-1.0.5.tgz#d6053692beae59d466ac0b04128fa157f59eb176"
- integrity sha512-dOzkZ2K53PPbE9AQB0RHlVs+GIEyHHdXeeW44dNSEuULwH99PmTpzA2r45QX3uaVa2j7Mip76AQbJZGKbM2fxg==
+"@chatwoot/prosemirror-schema@1.0.9":
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/@chatwoot/prosemirror-schema/-/prosemirror-schema-1.0.9.tgz#447408fc219a312c5bb851c043ac6ea2e069906f"
+ integrity sha512-jR+EgBWXhbKeU5krQRNkX0uuButu5K55notuJgxQUeWvgg3EJkz8LhDizmBoq/5NgV4FoDzqOD2eN6rUsXFa1w==
dependencies:
markdown-it-sup "^1.0.0"
prosemirror-commands "^1.1.4"
From f83af33b87e8e06cc4497063a1929ddba2b5ff25 Mon Sep 17 00:00:00 2001
From: Muhsin Keloth
Date: Thu, 23 May 2024 13:32:41 +0530
Subject: [PATCH 17/56] feat: Add title while linking the linear issue (#9529)
---
.../dashboard/api/integrations/linear.js | 3 ++-
.../conversation/linear/CreateIssue.vue | 6 ++++-
.../conversation/linear/CreateOrLinkIssue.vue | 25 ++++++++++++++-----
.../widgets/conversation/linear/LinkIssue.vue | 6 ++++-
.../widgets/conversation/linear/index.vue | 8 ++++--
.../i18n/locale/en/integrations.json | 3 ++-
6 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/app/javascript/dashboard/api/integrations/linear.js b/app/javascript/dashboard/api/integrations/linear.js
index 600f169d6..2ac0940aa 100644
--- a/app/javascript/dashboard/api/integrations/linear.js
+++ b/app/javascript/dashboard/api/integrations/linear.js
@@ -19,10 +19,11 @@ class LinearAPI extends ApiClient {
return axios.post(`${this.url}/create_issue`, data);
}
- link_issue(conversationId, issueId) {
+ link_issue(conversationId, issueId, title) {
return axios.post(`${this.url}/link_issue`, {
issue_id: issueId,
conversation_id: conversationId,
+ title: title,
});
}
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
index cd3976ec4..5c3575c44 100644
--- a/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
@@ -117,6 +117,10 @@ const props = defineProps({
type: [Number, String],
required: true,
},
+ title: {
+ type: String,
+ default: null,
+ },
});
const emit = defineEmits(['close']);
@@ -218,7 +222,7 @@ const createIssue = async () => {
isCreating.value = true;
const response = await LinearAPI.createIssue(payload);
const { id: issueId } = response.data;
- await LinearAPI.link_issue(props.conversationId, issueId);
+ await LinearAPI.link_issue(props.conversationId, issueId, props.title);
useAlert(t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE_SUCCESS'));
onClose();
} catch (error) {
diff --git a/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue b/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue
index f15b40409..589178853 100644
--- a/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/linear/CreateOrLinkIssue.vue
@@ -25,30 +25,35 @@
-
+