diff --git a/Gemfile.lock b/Gemfile.lock index 32f54c64d..42a4bbd85 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -971,4 +971,4 @@ RUBY VERSION ruby 3.3.3p89 BUNDLED WITH - 2.5.14 + 2.5.16 diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/IntegrationItem.vue b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/IntegrationItem.vue index 151afd049..d8306735d 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/IntegrationItem.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/IntegrationItem.vue @@ -2,7 +2,7 @@
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/SingleIntegrationHooks.vue b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/SingleIntegrationHooks.vue index 3f8dfccea..b26cfd229 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrationapps/SingleIntegrationHooks.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrationapps/SingleIntegrationHooks.vue @@ -7,7 +7,7 @@
diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Index.vue index 5ab8cd74b..c7b20e8a5 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Index.vue @@ -21,8 +21,7 @@ class="bg-white dark:bg-slate-800 border border-solid border-slate-75 dark:border-slate-700/50 rounded-sm mb-4 p-4" >
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