+
{
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 0000000000000..cd3976ec467e1
--- /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 0000000000000..f15b40409dfbf
--- /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 0000000000000..05cd3ab8810fc
--- /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 0000000000000..bf907dc69f2a7
--- /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 0000000000000..404837fc7b289
--- /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 0000000000000..ffb98db9eda21
--- /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 0000000000000..d30b790a7e1c0
--- /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 a0453b7d30874..11d6c43deca47 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 231892079339c..84390d5b1e73c 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 aa5f5cc12f5cb..731ac26e4d951 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 60c691b7d37ab..f58c2a7dde4d8 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 63489b0606a50..2e801c6735092 100644
--- a/lib/linear.rb
+++ b/lib/linear.rb
@@ -56,7 +56,8 @@ def create_issue(params)
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 015/352] 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 2c60db3cb4913..f3743c4021cff 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 016/352] 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 78fb2fed106ce..9ce31d9cffd21 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 daecee4b66fb0..83c0ee403c587 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 017/352] 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 600f169d6ee2b..2ac0940aa8db6 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 cd3976ec467e1..5c3575c44427e 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 f15b40409dfbf..5891788531bd9 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 @@
-
+