diff --git a/Gemfile b/Gemfile
index a0624fee4..4044c9b66 100644
--- a/Gemfile
+++ b/Gemfile
@@ -96,12 +96,12 @@ gem 'koala'
# slack client
gem 'slack-ruby-client', '~> 2.2.0'
# for dialogflow integrations
-gem 'google-cloud-dialogflow-v2'
+gem 'google-cloud-dialogflow-v2', '>= 0.24.0'
gem 'grpc'
# Translate integrations
# 'google-cloud-translate' gem depends on faraday 2.0 version
# this dependency breaks the slack-ruby-client gem
-gem 'google-cloud-translate-v3'
+gem 'google-cloud-translate-v3', '>= 0.7.0'
##-- apm and error monitoring ---#
# loaded only when environment variables are set.
diff --git a/Gemfile.lock b/Gemfile.lock
index 06f479659..46a766b4c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -257,7 +257,7 @@ GEM
faraday-net_http_persistent (2.1.0)
faraday (~> 2.5)
net-http-persistent (~> 4.0)
- faraday-retry (2.1.0)
+ faraday-retry (2.2.1)
faraday (~> 2.0)
fcm (1.0.8)
faraday (>= 1.0.0, < 3.0)
@@ -271,7 +271,7 @@ GEM
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
- gapic-common (0.18.0)
+ gapic-common (0.20.0)
faraday (>= 1.9, < 3.a)
faraday-retry (>= 1.0, < 3.a)
google-protobuf (~> 3.14)
@@ -301,15 +301,15 @@ GEM
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
- google-cloud-dialogflow-v2 (0.23.0)
- gapic-common (>= 0.18.0, < 2.a)
+ google-cloud-dialogflow-v2 (0.31.0)
+ gapic-common (>= 0.20.0, < 2.a)
google-cloud-errors (~> 1.0)
google-cloud-location (>= 0.4, < 2.a)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.3.1)
- google-cloud-location (0.4.0)
- gapic-common (>= 0.17.1, < 2.a)
+ google-cloud-location (0.6.0)
+ gapic-common (>= 0.20.0, < 2.a)
google-cloud-errors (~> 1.0)
google-cloud-storage (1.44.0)
addressable (~> 2.8)
@@ -319,17 +319,17 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
- google-cloud-translate-v3 (0.6.0)
- gapic-common (>= 0.17.1, < 2.a)
+ google-cloud-translate-v3 (0.10.0)
+ gapic-common (>= 0.20.0, < 2.a)
google-cloud-errors (~> 1.0)
google-protobuf (3.25.3)
google-protobuf (3.25.3-arm64-darwin)
google-protobuf (3.25.3-x86_64-darwin)
google-protobuf (3.25.3-x86_64-linux)
- googleapis-common-protos (1.4.0)
- google-protobuf (~> 3.14)
- googleapis-common-protos-types (~> 1.2)
- grpc (~> 1.27)
+ googleapis-common-protos (1.6.0)
+ google-protobuf (>= 3.18, < 5.a)
+ googleapis-common-protos-types (~> 1.7)
+ grpc (~> 1.41)
googleapis-common-protos-types (1.14.0)
google-protobuf (~> 3.18)
googleauth (1.5.2)
@@ -881,9 +881,9 @@ DEPENDENCIES
foreman
geocoder
gmail_xoauth
- google-cloud-dialogflow-v2
+ google-cloud-dialogflow-v2 (>= 0.24.0)
google-cloud-storage
- google-cloud-translate-v3
+ google-cloud-translate-v3 (>= 0.7.0)
groupdate
grpc
haikunator
diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb
index ff67eefc5..6f7980586 100644
--- a/app/builders/account_builder.rb
+++ b/app/builders/account_builder.rb
@@ -94,8 +94,8 @@ class AccountBuilder
def blocked_domains
domains = GlobalConfigService.load('BLOCKED_EMAIL_DOMAINS', '')
- domains.split("\n").map(&:strip) if domains.present?
+ return [] if domains.blank?
- []
+ domains.split("\n").map(&:strip)
end
end
diff --git a/app/javascript/dashboard/components/CustomAttribute.vue b/app/javascript/dashboard/components/CustomAttribute.vue
index 4bf97320b..ee00c182d 100644
--- a/app/javascript/dashboard/components/CustomAttribute.vue
+++ b/app/javascript/dashboard/components/CustomAttribute.vue
@@ -331,10 +331,12 @@ export default {
::v-deep {
.selector-wrap {
@apply m-0 top-1;
+
.selector-name {
@apply ml-0;
}
}
+
.name {
@apply ml-0;
}
diff --git a/app/javascript/dashboard/components/widgets/ShowMore.vue b/app/javascript/dashboard/components/widgets/ShowMore.vue
index c17c32e2a..37e2f9a68 100644
--- a/app/javascript/dashboard/components/widgets/ShowMore.vue
+++ b/app/javascript/dashboard/components/widgets/ShowMore.vue
@@ -1,38 +1,34 @@
-
@@ -41,16 +37,10 @@ export default {
{{ textToBeDisplayed }}
{{ buttonLabel }}
-
-
diff --git a/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue b/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue
index ab4be9342..754182207 100644
--- a/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue
+++ b/app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue
@@ -120,7 +120,6 @@ export default {
if (fileUrl) {
this.onImageUploadStart(fileUrl);
}
- useAlert(this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.SUCCESS'));
} catch (error) {
useAlert(this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.ERROR'));
}
@@ -173,6 +172,18 @@ export default {
blur: () => {
this.onBlur();
},
+ paste: (view, event) => {
+ const data = event.clipboardData.files;
+ if (data.length > 0) {
+ data.forEach(file => {
+ // Check if the file is an image
+ if (file.type.includes('image')) {
+ this.uploadImageToStorage(file);
+ }
+ });
+ event.preventDefault();
+ }
+ },
},
});
},
diff --git a/app/javascript/dashboard/helper/featureHelper.js b/app/javascript/dashboard/helper/featureHelper.js
index a7fa21616..529c0a44e 100644
--- a/app/javascript/dashboard/helper/featureHelper.js
+++ b/app/javascript/dashboard/helper/featureHelper.js
@@ -9,6 +9,7 @@ const FEATURE_HELP_URLS = {
custom_attributes: 'https://chwt.app/hc/custom-attributes',
dashboard_apps: 'https://chwt.app/hc/dashboard-apps',
help_center: 'https://chwt.app/hc/help-center',
+ inboxes: 'https://chwt.app/hc/inboxes',
integrations: 'https://chwt.app/hc/integrations',
labels: 'https://chwt.app/hc/labels',
macros: 'https://chwt.app/hc/macros',
@@ -16,6 +17,7 @@ const FEATURE_HELP_URLS = {
reports: 'https://chwt.app/hc/reports',
sla: 'https://chwt.app/hc/sla',
team_management: 'https://chwt.app/hc/teams',
+ webhook: 'https://chwt.app/hc/webhooks',
};
export function getHelpUrlForFeature(featureName) {
diff --git a/app/javascript/dashboard/i18n/locale/en/attributesMgmt.json b/app/javascript/dashboard/i18n/locale/en/attributesMgmt.json
index a2f7386dc..a83852fb8 100644
--- a/app/javascript/dashboard/i18n/locale/en/attributesMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/en/attributesMgmt.json
@@ -3,7 +3,8 @@
"HEADER": "Custom Attributes",
"HEADER_BTN_TXT": "Add Custom Attribute",
"LOADING": "Fetching custom attributes",
- "SIDEBAR_TXT": "
Custom Attributes
A custom attribute tracks facts about your contacts/conversation — like the subscription plan, or when they ordered the first item etc. For creating a Custom Attribute, just click on the Add Custom Attribute. You can also edit or delete an existing Custom Attribute by clicking on the Edit or Delete button.
",
+ "DESCRIPTION": "A custom attribute tracks additional details about your contacts or conversations—such as the subscription plan or the date of their first purchase. You can add different types of custom attributes, such as text, lists, or numbers, to capture the specific information you need.",
+ "LEARN_MORE": "Learn more about custom attributes",
"ADD": {
"TITLE": "Add Custom Attribute",
"SUBMIT": "Create",
@@ -91,7 +92,12 @@
"CONTACT": "Contact"
},
"LIST": {
- "TABLE_HEADER": ["Name", "Description", "Type", "Key"],
+ "TABLE_HEADER": [
+ "Name",
+ "Description",
+ "Type",
+ "Key"
+ ],
"BUTTONS": {
"EDIT": "Edit",
"DELETE": "Delete"
diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
index eec8ccde6..5bd1b6989 100644
--- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
@@ -1,7 +1,8 @@
{
"INBOX_MGMT": {
"HEADER": "Inboxes",
- "SIDEBAR_TXT": "Inbox
When you connect a website or a facebook Page to Chatwoot, it is called an Inbox . You can have unlimited inboxes in your Chatwoot account.
Click on Add Inbox to connect a website or a Facebook Page.
In the Dashboard, you can see all the conversations from all your inboxes in a single place and respond to them under the `Conversations` tab.
You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard.
",
+ "DESCRIPTION": "A channel is the mode of communication your customer chooses to interact with you. An inbox is where you manage interactions for a specific channel. It can include communications from various sources such as email, live chat, and social media.",
+ "LEARN_MORE": "Learn more about inboxes",
"RECONNECTION_REQUIRED": "Your inbox is disconnected. You won't receive new messages until you reauthorize it.",
"CLICK_TO_RECONNECT": "Click here to reconnect.",
"LIST": {
@@ -745,6 +746,18 @@
"MICROSOFT": "Microsoft",
"GOOGLE": "Google",
"OTHER_PROVIDERS": "Other Providers"
+ },
+ "CHANNELS": {
+ "MESSENGER": "Messenger",
+ "WEB_WIDGET": "Website",
+ "TWITTER_PROFILE": "Twitter",
+ "TWILIO_SMS": "Twilio SMS",
+ "WHATSAPP": "WhatsApp",
+ "SMS": "SMS",
+ "EMAIL": "Email",
+ "TELEGRAM": "Telegram",
+ "LINE": "Line",
+ "API": "API Channel"
}
}
}
diff --git a/app/javascript/dashboard/i18n/locale/en/integrations.json b/app/javascript/dashboard/i18n/locale/en/integrations.json
index 47349d1b1..f478b71b4 100644
--- a/app/javascript/dashboard/i18n/locale/en/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/en/integrations.json
@@ -12,6 +12,7 @@
},
"WEBHOOK": {
"SUBSCRIBED_EVENTS": "Subscribed Events",
+ "LEARN_MORE": "Learn more about webhooks",
"FORM": {
"CANCEL": "Cancel",
"DESC": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. Please enter a valid URL to configure a callback.",
diff --git a/app/javascript/dashboard/routes/dashboard/settings/SettingsLayout.vue b/app/javascript/dashboard/routes/dashboard/settings/SettingsLayout.vue
index 916f821ad..0e6a42fe8 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/SettingsLayout.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/SettingsLayout.vue
@@ -22,17 +22,21 @@ defineProps({
-
-
-
-
- {{ noRecordsMessage }}
-
-
-
-
+
+
+
+
+
+
+
+ {{ noRecordsMessage }}
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/AddAttribute.vue b/app/javascript/dashboard/routes/dashboard/settings/attributes/AddAttribute.vue
index 1ff257b7e..33f9ab7a5 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/attributes/AddAttribute.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/AddAttribute.vue
@@ -12,6 +12,12 @@ export default {
type: Function,
default: () => {},
},
+ // Passes 0 or 1 based on the selected AttributeModel tab selected in the UI
+ // Needs a better data type, todo: refactor this component later
+ selectedAttributeModelTab: {
+ type: Number,
+ default: 0,
+ },
},
setup() {
return { v$: useVuelidate() };
@@ -20,7 +26,10 @@ export default {
return {
displayName: '',
description: '',
- attributeModel: 0,
+ // Using the prop as default. There is no side effect here as the component
+ // is destroyed completely when the modal is closed. The prop doesn't change
+ // dynamically when the modal is active.
+ attributeModel: this.selectedAttributeModelTab || 0,
attributeType: 0,
attributeKey: '',
regexPattern: null,
@@ -280,13 +289,16 @@ export default {
padding: 0 var(--space-small) var(--space-small) 0;
font-family: monospace;
}
+
.multiselect--wrap {
margin-bottom: var(--space-normal);
+
.error-message {
color: var(--r-400);
font-size: var(--font-size-small);
font-weight: var(--font-weight-normal);
}
+
.invalid {
::v-deep {
.multiselect__tags {
@@ -295,13 +307,16 @@ export default {
}
}
}
+
::v-deep {
.multiselect {
margin-bottom: 0;
}
+
.multiselect__content-wrapper {
display: none;
}
+
.multiselect--active .multiselect__tags {
border-radius: var(--border-radius-normal);
}
diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue b/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
index 5c234ec03..9e55c619d 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/CustomAttribute.vue
@@ -1,195 +1,141 @@
-
-
-
-
-
-
-
-
-
+
+
+
- {{ $t('ATTRIBUTES_MGMT.LIST.EMPTY_RESULT.404') }}
-
-
-
-
-
- {{ tableHeader }}
-
-
-
-
-
- {{ attribute.attribute_display_name }}
-
-
- {{ attribute.attribute_description }}
-
-
- {{ attribute.attribute_display_type }}
-
-
- {{ attribute.attribute_key }}
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {{ tableHeader }}
+
+
+
+
+
+ {{ attribute.attribute_display_name }}
+
+
+ {{ attribute.attribute_description }}
+
+
+ {{ attribute.attribute_display_type }}
+
+
+ {{ attribute.attribute_key }}
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/attributes/Index.vue
index e7670caef..67f461f01 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/attributes/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/Index.vue
@@ -1,40 +1,112 @@
-
-
-
+
+
+
+
+ {{ $t('ATTRIBUTES_MGMT.HEADER_BTN_TXT') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
- {{ $t('ATTRIBUTES_MGMT.HEADER_BTN_TXT') }}
-
-
-
-
+
-
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js b/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js
index 93c4f8eda..3453f1afc 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/settings/attributes/attributes.routes.js
@@ -1,17 +1,12 @@
import { frontendURL } from '../../../../helper/URLHelper';
-const SettingsContent = () => import('../Wrapper.vue');
+const SettingsWrapper = () => import('../SettingsWrapper.vue');
const AttributesHome = () => import('./Index.vue');
export default {
routes: [
{
path: frontendURL('accounts/:accountId/settings/custom-attributes'),
- component: SettingsContent,
- props: {
- headerTitle: 'ATTRIBUTES_MGMT.HEADER',
- icon: 'code',
- showNewButton: false,
- },
+ component: SettingsWrapper,
children: [
{
path: '',
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
index c7c7a2a44..895d11360 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Index.vue
@@ -1,219 +1,177 @@
-
-
-
-
-
- {{ $t('INBOX_MGMT.LIST.404') }}
+
+
+
+
+
{{ $t('SETTINGS.INBOXES.NEW_INBOX') }}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
- {{ item.name }}
-
- {{ 'Facebook' }}
-
-
- {{ 'Website' }}
-
-
- {{ 'Twitter' }}
-
-
- {{ twilioChannelName(item) }}
-
-
- {{ 'Whatsapp' }}
-
-
- {{ 'Sms' }}
-
-
- {{ 'Email' }}
-
-
- {{ 'Telegram' }}
-
-
- {{ 'Line' }}
-
-
- {{ globalConfig.apiChannelName || 'API' }}
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+ {{ inbox.name }}
+
+
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/components/ChannelName.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/components/ChannelName.vue
new file mode 100644
index 000000000..68b8d96a7
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/components/ChannelName.vue
@@ -0,0 +1,55 @@
+
+
+
+
+ {{ readableChannelName }}
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js b/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js
index 3866b96bd..a12202e29 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/inbox.routes.js
@@ -1,8 +1,8 @@
-/* eslint arrow-body-style: 0 */
import { frontendURL } from '../../../../helper/URLHelper';
import channelFactory from './channel-factory';
const SettingsContent = () => import('../Wrapper.vue');
+const SettingWrapper = () => import('../SettingsWrapper.vue');
const InboxHome = () => import('./Index.vue');
const Settings = () => import('./Settings.vue');
const InboxChannel = () => import('./InboxChannels.vue');
@@ -12,6 +12,24 @@ const FinishSetup = () => import('./FinishSetup.vue');
export default {
routes: [
+ {
+ path: frontendURL('accounts/:accountId/settings/inboxes'),
+ component: SettingWrapper,
+ children: [
+ {
+ path: '',
+ redirect: 'list',
+ },
+ {
+ path: 'list',
+ name: 'settings_inbox_list',
+ component: InboxHome,
+ meta: {
+ permissions: ['administrator'],
+ },
+ },
+ ],
+ },
{
path: frontendURL('accounts/:accountId/settings/inboxes'),
component: SettingsContent,
@@ -26,18 +44,6 @@ export default {
};
},
children: [
- {
- path: '',
- redirect: 'list',
- },
- {
- path: 'list',
- name: 'settings_inbox_list',
- component: InboxHome,
- meta: {
- permissions: ['administrator'],
- },
- },
{
path: 'new',
component: InboxChannel,
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue
index e9ec855dc..23d0baa9c 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue
@@ -3,16 +3,18 @@ import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import NewWebhook from './NewWebHook.vue';
import EditWebhook from './EditWebHook.vue';
-import globalConfigMixin from 'shared/mixins/globalConfigMixin';
import WebhookRow from './WebhookRow.vue';
+import BaseSettingsHeader from '../../components/BaseSettingsHeader.vue';
+import SettingsLayout from '../../SettingsLayout.vue';
export default {
components: {
+ SettingsLayout,
+ BaseSettingsHeader,
NewWebhook,
EditWebhook,
WebhookRow,
},
- mixins: [globalConfigMixin],
data() {
return {
loading: {},
@@ -26,8 +28,10 @@ export default {
...mapGetters({
records: 'webhooks/getWebhooks',
uiFlags: 'webhooks/getUIFlags',
- globalConfig: 'globalConfig/get',
}),
+ integration() {
+ return this.$store.getters['integrations/getIntegration']('webhook');
+ },
},
mounted() {
this.$store.dispatch('webhooks/get');
@@ -75,69 +79,59 @@ export default {
-
-
- {{ $t('INTEGRATION_SETTINGS.WEBHOOK.HEADER_BTN_TXT') }}
-
-
-
-
-
+
+
+
+
+ {{ $t('INTEGRATION_SETTINGS.WEBHOOK.HEADER_BTN_TXT') }}
+
+
+
+
+
+
+
+
+ {{ thHeader }}
+
+
+
- {{ $t('INTEGRATION_SETTINGS.WEBHOOK.LIST.404') }}
-
-
-
-
-
-
- {{ thHeader }}
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -163,5 +157,5 @@ export default {
:confirm-text="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.YES')"
:reject-text="$t('INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.NO')"
/>
-
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue
index d399adbdd..f5fbc6a3d 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue
@@ -1,8 +1,8 @@
@@ -105,10 +105,10 @@ export default {
type="checkbox"
:value="event"
name="subscriptions"
- class="checkbox"
+ class="mr-2"
/>
- {{ `${getEventLabel(event)} (${event})` }}
+ {{ `${$t(getEventNamei18n(event))} (${event})` }}
@@ -129,9 +129,3 @@ export default {
-
-
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookRow.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookRow.vue
index 20e6d6c1a..447913ecb 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookRow.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookRow.vue
@@ -1,59 +1,58 @@
-
-
-
+
+
{{ webhook.url }}
-
+
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.SUBSCRIBED_EVENTS') }}:
-
+
-
-
-
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookHelper.spec.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookHelper.spec.js
new file mode 100644
index 000000000..9bde34063
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookHelper.spec.js
@@ -0,0 +1,9 @@
+import { getEventNamei18n } from '../webhookHelper';
+
+describe('#getEventNamei18n', () => {
+ it('returns correct i18n translation text', () => {
+ expect(getEventNamei18n('message_created')).toEqual(
+ `INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.EVENTS.MESSAGE_CREATED`
+ );
+ });
+});
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookMixin.spec.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookMixin.spec.js
deleted file mode 100644
index c617b64b0..000000000
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/specs/webhookMixin.spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { createWrapper } from '@vue/test-utils';
-import webhookMixin from '../webhookMixin';
-import Vue from 'vue';
-
-describe('webhookMixin', () => {
- describe('#getEventLabel', () => {
- it('returns correct i18n translation:', () => {
- const Component = {
- render() {},
- title: 'WebhookComponent',
- mixins: [webhookMixin],
- methods: {
- $t(text) {
- return text;
- },
- },
- };
- const Constructor = Vue.extend(Component);
- const vm = new Constructor().$mount();
- const wrapper = createWrapper(vm);
- expect(wrapper.vm.getEventLabel('message_created')).toEqual(
- `INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.EVENTS.MESSAGE_CREATED`
- );
- });
- });
-});
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookHelper.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookHelper.js
new file mode 100644
index 000000000..699dafdc8
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookHelper.js
@@ -0,0 +1,4 @@
+export const getEventNamei18n = event => {
+ const eventName = event.toUpperCase();
+ return `INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.EVENTS.${eventName}`;
+};
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookMixin.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookMixin.js
deleted file mode 100644
index 38283fe90..000000000
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/webhookMixin.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export default {
- methods: {
- getEventLabel(event) {
- const eventName = event.toUpperCase();
- return this.$t(
- `INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.EVENTS.${eventName}`
- );
- },
- },
-};
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js b/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js
index c4d319173..8a4937dd4 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js
@@ -30,6 +30,14 @@ export default {
permissions: ['administrator'],
},
},
+ {
+ path: 'webhook',
+ component: Webhook,
+ name: 'settings_integrations_webhook',
+ meta: {
+ permissions: ['administrator'],
+ },
+ },
],
},
{
@@ -49,14 +57,6 @@ export default {
};
},
children: [
- {
- path: 'webhook',
- component: Webhook,
- name: 'settings_integrations_webhook',
- meta: {
- permissions: ['administrator'],
- },
- },
{
path: 'slack',
name: 'settings_integrations_slack',