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 bdebc0329..bb70fa4db 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js
@@ -43,7 +43,7 @@ export default {
},
},
{
- path: 'dashboard-apps',
+ path: 'dashboard_apps',
component: DashboardApps,
name: 'settings_integrations_dashboard_apps',
meta: {
diff --git a/app/models/integrations/app.rb b/app/models/integrations/app.rb
index b746bd92b..b55687b2a 100644
--- a/app/models/integrations/app.rb
+++ b/app/models/integrations/app.rb
@@ -38,6 +38,8 @@ class Integrations::App
case params[:id]
when 'slack'
ENV['SLACK_CLIENT_SECRET'].present?
+ when 'linear'
+ Current.account.feature_enabled?('linear_integration')
else
true
end
@@ -45,10 +47,10 @@ class Integrations::App
def enabled?(account)
case params[:id]
- when 'slack'
- account.hooks.exists?(app_id: id)
+ when 'webhook'
+ account.webhooks.exists?
else
- true
+ account.hooks.exists?(app_id: id)
end
end
diff --git a/config/integration/apps.yml b/config/integration/apps.yml
index 538f7ee81..74a570ab5 100644
--- a/config/integration/apps.yml
+++ b/config/integration/apps.yml
@@ -9,125 +9,13 @@
# settings_form_schema: the formulate schema used in frontend to render settings form (https://vueformulate.com/)
########################################################
-slack:
- id: slack
- logo: slack.png
- i18n_key: slack
- action: https://slack.com/oauth/v2/authorize?scope=commands,chat:write,channels:read,channels:manage,channels:join,groups:read,groups:write,im:write,mpim:write,users:read,users:read.email,chat:write.customize,channels:history,groups:history,mpim:history,im:history,files:read,files:write
- hook_type: account
- allow_multiple_hooks: false
webhooks:
id: webhook
- logo: cable.svg
+ logo: webhooks.png
i18n_key: webhooks
action: /webhook
hook_type: account
allow_multiple_hooks: true
-dialogflow:
- id: dialogflow
- logo: dialogflow.svg
- i18n_key: dialogflow
- action: /dialogflow
- hook_type: inbox
- allow_multiple_hooks: true
- settings_json_schema: {
- "type": "object",
- "properties": {
- "project_id": { "type": "string" },
- "credentials": { "type": "object" }
- },
- "required": ["project_id", "credentials"],
- "additionalProperties": false
- }
- settings_form_schema: [
- {
- "label": "Dialogflow Project ID",
- "type": "text",
- "name": "project_id",
- "validation": "required",
- "validationName": 'Project Id',
- },
- {
- "label": "Dialogflow Project Key File",
- "type": "textarea",
- "name": "credentials",
- "validation": "required|JSON",
- "validationName": 'Credentials',
- "validation-messages": {
- "JSON": "Invalid JSON",
- "required": "Credentials is required"
- }
- }
- ]
- visible_properties: ['project_id']
-dyte:
- id: dyte
- logo: dyte.png
- i18n_key: dyte
- action: /dyte
- hook_type: account
- allow_multiple_hooks: false
- settings_json_schema: {
- "type": "object",
- "properties": {
- "api_key": { "type": "string" },
- "organization_id": { "type": "string" },
- },
- "required": ["api_key", "organization_id"],
- "additionalProperties": false,
- }
- settings_form_schema: [
- {
- "label": "Organization ID",
- "type": "text",
- "name": "organization_id",
- "validation": "required",
- },
- {
- "label": "API Key",
- "type": "text",
- "name": "api_key",
- "validation": "required",
- },
- ]
- visible_properties: ["organization_id"]
-google_translate:
- id: google_translate
- logo: googletranslate.png
- i18n_key: google_translate
- action: /google_translate
- hook_type: account
- allow_multiple_hooks: false
- settings_json_schema: {
- "type": "object",
- "properties": {
- "project_id": { "type": "string" },
- "credentials": { "type": "object" },
- },
- "required": ["project_id", "credentials"],
- "additionalProperties": false,
- }
- settings_form_schema: [
- {
- "label": "Google Cloud Project ID",
- "type": "text",
- "name": "project_id",
- "validation": "required",
- "validationName": "Project Id",
- },
- {
- "label": "Google Cloud Project Key File",
- "type": "textarea",
- "name": "credentials",
- "validation": "required|JSON",
- "validationName": "Credentials",
- "validation-messages": {
- "JSON": "Invalid JSON",
- "required": "Credentials is required"
- },
- },
- ]
- visible_properties: ['project_id']
openai:
id: openai
logo: openai.png
@@ -183,3 +71,115 @@ linear:
},
]
visible_properties: []
+slack:
+ id: slack
+ logo: slack.png
+ i18n_key: slack
+ action: https://slack.com/oauth/v2/authorize?scope=commands,chat:write,channels:read,channels:manage,channels:join,groups:read,groups:write,im:write,mpim:write,users:read,users:read.email,chat:write.customize,channels:history,groups:history,mpim:history,im:history,files:read,files:write
+ hook_type: account
+ allow_multiple_hooks: false
+dialogflow:
+ id: dialogflow
+ logo: dialogflow.png
+ i18n_key: dialogflow
+ action: /dialogflow
+ hook_type: inbox
+ allow_multiple_hooks: true
+ settings_json_schema: {
+ "type": "object",
+ "properties": {
+ "project_id": { "type": "string" },
+ "credentials": { "type": "object" }
+ },
+ "required": ["project_id", "credentials"],
+ "additionalProperties": false
+ }
+ settings_form_schema: [
+ {
+ "label": "Dialogflow Project ID",
+ "type": "text",
+ "name": "project_id",
+ "validation": "required",
+ "validationName": 'Project Id',
+ },
+ {
+ "label": "Dialogflow Project Key File",
+ "type": "textarea",
+ "name": "credentials",
+ "validation": "required|JSON",
+ "validationName": 'Credentials',
+ "validation-messages": {
+ "JSON": "Invalid JSON",
+ "required": "Credentials is required"
+ }
+ }
+ ]
+ visible_properties: ['project_id']
+google_translate:
+ id: google_translate
+ logo: google-translate.png
+ i18n_key: google_translate
+ action: /google_translate
+ hook_type: account
+ allow_multiple_hooks: false
+ settings_json_schema: {
+ "type": "object",
+ "properties": {
+ "project_id": { "type": "string" },
+ "credentials": { "type": "object" },
+ },
+ "required": ["project_id", "credentials"],
+ "additionalProperties": false,
+ }
+ settings_form_schema: [
+ {
+ "label": "Google Cloud Project ID",
+ "type": "text",
+ "name": "project_id",
+ "validation": "required",
+ "validationName": "Project Id",
+ },
+ {
+ "label": "Google Cloud Project Key File",
+ "type": "textarea",
+ "name": "credentials",
+ "validation": "required|JSON",
+ "validationName": "Credentials",
+ "validation-messages": {
+ "JSON": "Invalid JSON",
+ "required": "Credentials is required"
+ },
+ },
+ ]
+ visible_properties: ['project_id']
+dyte:
+ id: dyte
+ logo: dyte.png
+ i18n_key: dyte
+ action: /dyte
+ hook_type: account
+ allow_multiple_hooks: false
+ settings_json_schema: {
+ "type": "object",
+ "properties": {
+ "api_key": { "type": "string" },
+ "organization_id": { "type": "string" },
+ },
+ "required": ["api_key", "organization_id"],
+ "additionalProperties": false,
+ }
+ settings_form_schema: [
+ {
+ "label": "Organization ID",
+ "type": "text",
+ "name": "organization_id",
+ "validation": "required",
+ },
+ {
+ "label": "API Key",
+ "type": "text",
+ "name": "api_key",
+ "validation": "required",
+ },
+ ]
+ visible_properties: ["organization_id"]
diff --git a/public/dashboard/images/integrations/cable.svg b/public/dashboard/images/integrations/cable.svg
deleted file mode 100644
index b39742a29..000000000
--- a/public/dashboard/images/integrations/cable.svg
+++ /dev/null
@@ -1,39 +0,0 @@
-
diff --git a/public/dashboard/images/integrations/dashboard-apps.svg b/public/dashboard/images/integrations/dashboard-apps.svg
deleted file mode 100644
index 76e165588..000000000
--- a/public/dashboard/images/integrations/dashboard-apps.svg
+++ /dev/null
@@ -1,75 +0,0 @@
-
diff --git a/public/dashboard/images/integrations/dashboard_apps-dark.png b/public/dashboard/images/integrations/dashboard_apps-dark.png
new file mode 100644
index 000000000..a5b9a4b17
Binary files /dev/null and b/public/dashboard/images/integrations/dashboard_apps-dark.png differ
diff --git a/public/dashboard/images/integrations/dashboard_apps.png b/public/dashboard/images/integrations/dashboard_apps.png
new file mode 100644
index 000000000..a5b9a4b17
Binary files /dev/null and b/public/dashboard/images/integrations/dashboard_apps.png differ
diff --git a/public/dashboard/images/integrations/dialogflow-dark.png b/public/dashboard/images/integrations/dialogflow-dark.png
new file mode 100644
index 000000000..a21fa0a19
Binary files /dev/null and b/public/dashboard/images/integrations/dialogflow-dark.png differ
diff --git a/public/dashboard/images/integrations/dialogflow.png b/public/dashboard/images/integrations/dialogflow.png
new file mode 100644
index 000000000..a21fa0a19
Binary files /dev/null and b/public/dashboard/images/integrations/dialogflow.png differ
diff --git a/public/dashboard/images/integrations/dialogflow.svg b/public/dashboard/images/integrations/dialogflow.svg
deleted file mode 100644
index 32c657f3b..000000000
--- a/public/dashboard/images/integrations/dialogflow.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
\ No newline at end of file
diff --git a/public/dashboard/images/integrations/dyte-dark.png b/public/dashboard/images/integrations/dyte-dark.png
new file mode 100644
index 000000000..42162b58a
Binary files /dev/null and b/public/dashboard/images/integrations/dyte-dark.png differ
diff --git a/public/dashboard/images/integrations/dyte.png b/public/dashboard/images/integrations/dyte.png
index 8a4efab2b..42162b58a 100644
Binary files a/public/dashboard/images/integrations/dyte.png and b/public/dashboard/images/integrations/dyte.png differ
diff --git a/public/dashboard/images/integrations/fullcontact.png b/public/dashboard/images/integrations/fullcontact.png
deleted file mode 100644
index 1e5d9b7f9..000000000
Binary files a/public/dashboard/images/integrations/fullcontact.png and /dev/null differ
diff --git a/public/dashboard/images/integrations/google_translate-dark.png b/public/dashboard/images/integrations/google_translate-dark.png
new file mode 100644
index 000000000..1b99e803e
Binary files /dev/null and b/public/dashboard/images/integrations/google_translate-dark.png differ
diff --git a/public/dashboard/images/integrations/google_translate.png b/public/dashboard/images/integrations/google_translate.png
new file mode 100644
index 000000000..1b99e803e
Binary files /dev/null and b/public/dashboard/images/integrations/google_translate.png differ
diff --git a/public/dashboard/images/integrations/googletranslate.png b/public/dashboard/images/integrations/googletranslate.png
deleted file mode 100644
index d502ea051..000000000
Binary files a/public/dashboard/images/integrations/googletranslate.png and /dev/null differ
diff --git a/public/dashboard/images/integrations/linear-dark.png b/public/dashboard/images/integrations/linear-dark.png
new file mode 100644
index 000000000..38c87ee46
Binary files /dev/null and b/public/dashboard/images/integrations/linear-dark.png differ
diff --git a/public/dashboard/images/integrations/linear.png b/public/dashboard/images/integrations/linear.png
index 1921f4c3f..f2f5555d2 100644
Binary files a/public/dashboard/images/integrations/linear.png and b/public/dashboard/images/integrations/linear.png differ
diff --git a/public/dashboard/images/integrations/openai-dark.png b/public/dashboard/images/integrations/openai-dark.png
new file mode 100644
index 000000000..3af9768a1
Binary files /dev/null and b/public/dashboard/images/integrations/openai-dark.png differ
diff --git a/public/dashboard/images/integrations/openai.png b/public/dashboard/images/integrations/openai.png
index 847b476b0..0a0200d33 100644
Binary files a/public/dashboard/images/integrations/openai.png and b/public/dashboard/images/integrations/openai.png differ
diff --git a/public/dashboard/images/integrations/slack-dark.png b/public/dashboard/images/integrations/slack-dark.png
new file mode 100644
index 000000000..00085044f
Binary files /dev/null and b/public/dashboard/images/integrations/slack-dark.png differ
diff --git a/public/dashboard/images/integrations/slack.png b/public/dashboard/images/integrations/slack.png
index 41fc5e45c..00085044f 100644
Binary files a/public/dashboard/images/integrations/slack.png and b/public/dashboard/images/integrations/slack.png differ
diff --git a/public/dashboard/images/integrations/webhook-dark.png b/public/dashboard/images/integrations/webhook-dark.png
new file mode 100644
index 000000000..3a7e67c93
Binary files /dev/null and b/public/dashboard/images/integrations/webhook-dark.png differ
diff --git a/public/dashboard/images/integrations/webhook.png b/public/dashboard/images/integrations/webhook.png
new file mode 100644
index 000000000..ebd449221
Binary files /dev/null and b/public/dashboard/images/integrations/webhook.png differ
diff --git a/spec/models/integrations/app_spec.rb b/spec/models/integrations/app_spec.rb
new file mode 100644
index 000000000..703069349
--- /dev/null
+++ b/spec/models/integrations/app_spec.rb
@@ -0,0 +1,105 @@
+require 'rails_helper'
+
+RSpec.describe Integrations::App do
+ let(:apps) { described_class }
+ let(:app) { apps.find(id: app_name) }
+ let(:account) { create(:account) }
+
+ before do
+ allow(Current).to receive(:account).and_return(account)
+ end
+
+ describe '#name' do
+ let(:app_name) { 'slack' }
+
+ it 'returns the name' do
+ expect(app.name).to eq('Slack')
+ end
+ end
+
+ describe '#logo' do
+ let(:app_name) { 'slack' }
+
+ it 'returns the logo' do
+ expect(app.logo).to eq('slack.png')
+ end
+ end
+
+ describe '#action' do
+ let(:app_name) { 'slack' }
+
+ context 'when the app is slack' do
+ it 'returns the action URL with client_id and redirect_uri' do
+ with_modified_env SLACK_CLIENT_ID: 'dummy_client_id' do
+ expect(app.action).to include('client_id=dummy_client_id')
+ expect(app.action).to include(
+ "/app/accounts/#{account.id}/settings/integrations/slack"
+ )
+ end
+ end
+ end
+ end
+
+ describe '#active?' do
+ let(:app_name) { 'slack' }
+
+ context 'when the app is slack' do
+ it 'returns true if SLACK_CLIENT_SECRET is present' do
+ with_modified_env SLACK_CLIENT_SECRET: 'random_secret' do
+ expect(app.active?).to be true
+ end
+ end
+ end
+
+ context 'when the app is linear' do
+ let(:app_name) { 'linear' }
+
+ it 'returns true if the linear integration feature is disabled' do
+ expect(app.active?).to be false
+ end
+
+ it 'returns false if the linear integration feature is enabled' do
+ account.enable_features('linear_integration')
+ account.save!
+
+ expect(app.active?).to be true
+ end
+ end
+
+ context 'when other apps are queried' do
+ let(:app_name) { 'webhook' }
+
+ it 'returns true' do
+ expect(app.active?).to be true
+ end
+ end
+ end
+
+ describe '#enabled?' do
+ context 'when the app is webhook' do
+ let(:app_name) { 'webhook' }
+
+ it 'returns false if the account does not have any webhooks' do
+ expect(app.enabled?(account)).to be false
+ end
+
+ it 'returns true if the account has webhooks' do
+ create(:webhook, account: account)
+ expect(app.enabled?(account)).to be true
+ end
+ end
+
+ context 'when the app is anything other than webhook' do
+ let(:app_name) { 'openai' }
+
+ it 'returns false if the account does not have any hooks for the app' do
+ expect(app.enabled?(account)).to be false
+ end
+
+ it 'returns true if the account has hooks for the app' do
+ create(:integrations_hook, :openai, account: account)
+ expect(app.enabled?(account)).to be true
+ end
+ end
+ end
+end