From 4378506a359dc657702453466970e130c6462afe Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 15 Jul 2025 08:56:03 +0530 Subject: [PATCH 1/9] feat: add response guidelines and guardrails field (#11911) Co-authored-by: Muhsin Keloth --- ...es_and_guardrails_to_captain_assistants.rb | 6 +++ db/schema.rb | 4 +- .../accounts/captain/assistants_controller.rb | 18 +++++--- enterprise/app/models/captain/assistant.rb | 16 +++---- .../models/captain/_assistant.json.jbuilder | 2 + .../captain/assistants_controller_spec.rb | 42 ++++++++++++++++++- 6 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb diff --git a/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb b/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb new file mode 100644 index 000000000..3c048b8f7 --- /dev/null +++ b/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb @@ -0,0 +1,6 @@ +class AddResponseGuidelinesAndGuardrailsToCaptainAssistants < ActiveRecord::Migration[7.1] + def change + add_column :captain_assistants, :response_guidelines, :jsonb, default: [] + add_column :captain_assistants, :guardrails, :jsonb, default: [] + end +end diff --git a/db/schema.rb b/db/schema.rb index 837eb58bd..1806ab23f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_07_10_145708) do +ActiveRecord::Schema[7.1].define(version: 2025_07_14_104358) do # These extensions should be enabled to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -277,6 +277,8 @@ ActiveRecord::Schema[7.1].define(version: 2025_07_10_145708) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.jsonb "config", default: {}, null: false + t.jsonb "response_guidelines", default: [] + t.jsonb "guardrails", default: [] t.index ["account_id"], name: "index_captain_assistants_on_account_id" end diff --git a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb index ec8e8e653..37890fade 100644 --- a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb +++ b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb @@ -43,12 +43,18 @@ class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::Base end def assistant_params - params.require(:assistant).permit(:name, :description, - config: [ - :product_name, :feature_faq, :feature_memory, - :welcome_message, :handoff_message, :resolution_message, - :instructions, :temperature - ]) + permitted = params.require(:assistant).permit(:name, :description, + config: [ + :product_name, :feature_faq, :feature_memory, + :welcome_message, :handoff_message, :resolution_message, + :instructions, :temperature + ]) + + # Handle array parameters separately to allow partial updates + permitted[:response_guidelines] = params[:assistant][:response_guidelines] if params[:assistant][:response_guidelines].present? + permitted[:guardrails] = params[:assistant][:guardrails] if params[:assistant][:guardrails].present? + + permitted end def playground_params diff --git a/enterprise/app/models/captain/assistant.rb b/enterprise/app/models/captain/assistant.rb index 8f1227231..4ce4c4afd 100644 --- a/enterprise/app/models/captain/assistant.rb +++ b/enterprise/app/models/captain/assistant.rb @@ -2,13 +2,15 @@ # # Table name: captain_assistants # -# id :bigint not null, primary key -# config :jsonb not null -# description :string -# name :string not null -# created_at :datetime not null -# updated_at :datetime not null -# account_id :bigint not null +# id :bigint not null, primary key +# config :jsonb not null +# description :string +# guardrails :jsonb +# name :string not null +# response_guidelines :jsonb +# created_at :datetime not null +# updated_at :datetime not null +# account_id :bigint not null # # Indexes # diff --git a/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder b/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder index 80008423c..d597ed220 100644 --- a/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder +++ b/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder @@ -2,6 +2,8 @@ json.account_id resource.account_id json.config resource.config json.created_at resource.created_at.to_i json.description resource.description +json.guardrails resource.guardrails json.id resource.id json.name resource.name +json.response_guidelines resource.response_guidelines json.updated_at resource.updated_at.to_i diff --git a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb index 80be6f30f..b6418c8ec 100644 --- a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb +++ b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb @@ -62,7 +62,9 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do { assistant: { name: 'New Assistant', - description: 'Assistant Description' + description: 'Assistant Description', + response_guidelines: ['Be helpful', 'Be concise'], + guardrails: ['No harmful content', 'Stay on topic'] } } end @@ -96,6 +98,8 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do end.to change(Captain::Assistant, :count).by(1) expect(json_response[:name]).to eq('New Assistant') + expect(json_response[:response_guidelines]).to eq(['Be helpful', 'Be concise']) + expect(json_response[:guardrails]).to eq(['No harmful content', 'Stay on topic']) expect(response).to have_http_status(:success) end end @@ -106,7 +110,9 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do let(:update_attributes) do { assistant: { - name: 'Updated Assistant' + name: 'Updated Assistant', + response_guidelines: ['Updated guideline'], + guardrails: ['Updated guardrail'] } } end @@ -139,6 +145,38 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do expect(response).to have_http_status(:success) expect(json_response[:name]).to eq('Updated Assistant') + expect(json_response[:response_guidelines]).to eq(['Updated guideline']) + expect(json_response[:guardrails]).to eq(['Updated guardrail']) + end + + it 'updates only response_guidelines when only that is provided' do + assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail']) + original_name = assistant.name + + patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}", + params: { assistant: { response_guidelines: ['New guideline only'] } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(json_response[:name]).to eq(original_name) + expect(json_response[:response_guidelines]).to eq(['New guideline only']) + expect(json_response[:guardrails]).to eq(['Original guardrail']) + end + + it 'updates only guardrails when only that is provided' do + assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail']) + original_name = assistant.name + + patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}", + params: { assistant: { guardrails: ['New guardrail only'] } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(json_response[:name]).to eq(original_name) + expect(json_response[:response_guidelines]).to eq(['Original guideline']) + expect(json_response[:guardrails]).to eq(['New guardrail only']) end end end From 61d10044a04f84252e038c1f5a1cce287063435e Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Tue, 15 Jul 2025 11:37:06 +0700 Subject: [PATCH 2/9] feat: Whatsapp embedded signup (#11612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR introduces WhatsApp Embedded Signup functionality, enabling users to connect their WhatsApp Business accounts through Meta's streamlined OAuth flow without manual webhook configuration. This significantly improves the user experience by automating the entire setup process. **Key Features:** - Embedded signup flow using Facebook SDK and Meta's OAuth 2.0 - Automatic webhook registration and phone number configuration - Enhanced provider selection UI with card-based design - Real-time progress tracking during signup process - Comprehensive error handling and user feedback ## Required Configuration The following environment variables must be configured by administrators before this feature can be used: Super Admin Configuration (via super_admin/app_config?config=whatsapp_embedded) - `WHATSAPP_APP_ID`: The Facebook App ID for WhatsApp Business API integration - `WHATSAPP_CONFIGURATION_ID`: The Configuration ID for WhatsApp Embedded Signup flow (obtained from Meta Developer Portal) - `WHATSAPP_APP_SECRET`: The App Secret for WhatsApp Embedded Signup flow (required for token exchange) ![Screenshot 2025-06-09 at 11 21 08 AM](https://github.com/user-attachments/assets/1615fb0d-27fc-4d9e-b193-9be7894ea93a) ## How Has This Been Tested? #### Backend Tests (RSpec): - Authentication validation for embedded signup endpoints - Authorization code validation and error handling - Missing business parameter validation - Proper response format for configuration endpoint - Unauthorized access prevention #### Manual Test Cases: - Complete embedded signup flow (happy path) - Provider selection UI navigation - Facebook authentication popup handling - Error scenarios (cancelled auth, invalid business data, API failures) - Configuration presence/absence behavior ## Related Screenshots: ![Screenshot 2025-06-09 at 7 48 18 PM](https://github.com/user-attachments/assets/34001425-df11-4d78-9424-334461e3178f) ![Screenshot 2025-06-09 at 7 48 22 PM](https://github.com/user-attachments/assets/c09f4964-3aba-4c39-9285-d1e8e37d0e33) ![Screenshot 2025-06-09 at 7 48 32 PM](https://github.com/user-attachments/assets/a34d5382-7a91-4e1c-906e-dc2d570c864a) ![Screenshot 2025-06-09 at 10 43 05 AM](https://github.com/user-attachments/assets/a15840d8-8223-4513-82e4-b08f23c95927) ![Screenshot 2025-06-09 at 10 42 56 AM](https://github.com/user-attachments/assets/8c345022-38b5-44c4-aba2-0cda81389c69) Fixes https://linear.app/chatwoot/issue/CW-2131/spec-for-whatsapp-cloud-channels-sign-in-with-facebook --------- Co-authored-by: Muhsin Keloth Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: iamsivin Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Sojan Jose --- .rubocop.yml | 2 +- .../integrations/notion_controller.rb | 2 +- .../notion/authorizations_controller.rb | 2 +- .../whatsapp/authorizations_controller.rb | 64 ++++ app/controllers/dashboard_controller.rb | 2 + .../notion/callbacks_controller.rb | 2 +- .../super_admin/app_configs_controller.rb | 5 +- .../dashboard/api/channel/whatsappChannel.js | 14 + app/javascript/dashboard/featureFlags.js | 1 + .../dashboard/i18n/locale/en/inboxMgmt.json | 29 ++ .../dashboard/settings/inbox/FinishSetup.vue | 16 +- .../dashboard/settings/inbox/Settings.vue | 14 +- .../settings/inbox/channels/Whatsapp.vue | 172 +++++++-- .../inbox/channels/WhatsappEmbeddedSignup.vue | 327 ++++++++++++++++++ .../dashboard/store/modules/inboxes.js | 14 + app/models/channel/whatsapp.rb | 38 ++ app/presenters/message_content_presenter.rb | 2 +- .../whatsapp/channel_creation_service.rb | 75 ++++ .../whatsapp/embedded_signup_service.rb | 44 +++ app/services/whatsapp/facebook_api_client.rb | 86 +++++ app/services/whatsapp/phone_info_service.rb | 57 +++ .../whatsapp/token_exchange_service.rb | 26 ++ .../whatsapp/token_validation_service.rb | 42 +++ .../whatsapp/webhook_setup_service.rb | 67 ++++ .../v1/accounts/search/articles.json.jbuilder | 2 +- .../callbacks/embedded_signup.json.jbuilder | 1 + app/views/layouts/vueapp.html.erb | 3 + config/features.yml | 3 + config/installation_config.yml | 20 ++ config/routes.rb | 4 + .../20250620120000_create_channel_voice.rb | 2 +- .../accounts/captain/scenarios_controller.rb | 2 +- .../app/helpers/super_admin/features.yml | 6 + enterprise/app/models/channel/voice.rb | 1 - .../app/policies/captain/scenario_policy.rb | 2 +- .../open_ai_message_builder_service.rb | 2 +- .../captain/scenarios/create.json.jbuilder | 2 +- .../captain/scenarios/index.json.jbuilder | 2 +- .../captain/scenarios/show.json.jbuilder | 2 +- .../captain/scenarios/update.json.jbuilder | 2 +- .../v1/models/captain/_scenario.json.jbuilder | 2 +- .../images/dashboard/channels/whatsapp.png | Bin 46629 -> 13525 bytes .../notion/authorization_controller_spec.rb | 2 +- .../authorizations_controller_spec.rb | 303 ++++++++++++++++ .../captain/scenarios_controller_spec.rb | 2 +- .../models/captain/scenario_spec.rb | 2 +- spec/models/channel/whatsapp_spec.rb | 61 ++++ spec/models/concerns/featurable_spec.rb | 57 +++ .../message_content_presenter_spec.rb | 2 +- spec/services/csat_survey_service_spec.rb | 2 +- .../linear/activity_message_service_spec.rb | 2 +- .../whatsapp/channel_creation_service_spec.rb | 119 +++++++ .../whatsapp/embedded_signup_service_spec.rb | 127 +++++++ .../whatsapp/facebook_api_client_spec.rb | 197 +++++++++++ .../whatsapp/phone_info_service_spec.rb | 147 ++++++++ .../whatsapp/token_exchange_service_spec.rb | 45 +++ .../whatsapp/token_validation_service_spec.rb | 99 ++++++ .../whatsapp/webhook_setup_service_spec.rb | 119 +++++++ 58 files changed, 2384 insertions(+), 63 deletions(-) create mode 100644 app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb create mode 100644 app/javascript/dashboard/api/channel/whatsappChannel.js create mode 100644 app/javascript/dashboard/routes/dashboard/settings/inbox/channels/WhatsappEmbeddedSignup.vue create mode 100644 app/services/whatsapp/channel_creation_service.rb create mode 100644 app/services/whatsapp/embedded_signup_service.rb create mode 100644 app/services/whatsapp/facebook_api_client.rb create mode 100644 app/services/whatsapp/phone_info_service.rb create mode 100644 app/services/whatsapp/token_exchange_service.rb create mode 100644 app/services/whatsapp/token_validation_service.rb create mode 100644 app/services/whatsapp/webhook_setup_service.rb create mode 100644 app/views/api/v1/accounts/whatsapp/callbacks/embedded_signup.json.jbuilder create mode 100644 spec/controllers/api/v1/accounts/whatsapp/authorizations_controller_spec.rb create mode 100644 spec/models/concerns/featurable_spec.rb create mode 100644 spec/services/whatsapp/channel_creation_service_spec.rb create mode 100644 spec/services/whatsapp/embedded_signup_service_spec.rb create mode 100644 spec/services/whatsapp/facebook_api_client_spec.rb create mode 100644 spec/services/whatsapp/phone_info_service_spec.rb create mode 100644 spec/services/whatsapp/token_exchange_service_spec.rb create mode 100644 spec/services/whatsapp/token_validation_service_spec.rb create mode 100644 spec/services/whatsapp/webhook_setup_service_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index 12e756af6..e30a71ee9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -283,7 +283,7 @@ Rails/RedundantActiveRecordAllMethod: Enabled: false Layout/TrailingEmptyLines: - Enabled: false + Enabled: true Style/SafeNavigationChainLength: Enabled: false diff --git a/app/controllers/api/v1/accounts/integrations/notion_controller.rb b/app/controllers/api/v1/accounts/integrations/notion_controller.rb index dff6ccece..ecf6bae6e 100644 --- a/app/controllers/api/v1/accounts/integrations/notion_controller.rb +++ b/app/controllers/api/v1/accounts/integrations/notion_controller.rb @@ -11,4 +11,4 @@ class Api::V1::Accounts::Integrations::NotionController < Api::V1::Accounts::Bas def fetch_hook @hook = Integrations::Hook.where(account: Current.account).find_by(app_id: 'notion') end -end \ No newline at end of file +end diff --git a/app/controllers/api/v1/accounts/notion/authorizations_controller.rb b/app/controllers/api/v1/accounts/notion/authorizations_controller.rb index bb9b2f858..3e0f6586a 100644 --- a/app/controllers/api/v1/accounts/notion/authorizations_controller.rb +++ b/app/controllers/api/v1/accounts/notion/authorizations_controller.rb @@ -18,4 +18,4 @@ class Api::V1::Accounts::Notion::AuthorizationsController < Api::V1::Accounts::O render json: { success: false }, status: :unprocessable_entity end end -end \ No newline at end of file +end diff --git a/app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb b/app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb new file mode 100644 index 000000000..e7a1f3fa6 --- /dev/null +++ b/app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb @@ -0,0 +1,64 @@ +class Api::V1::Accounts::Whatsapp::AuthorizationsController < Api::V1::Accounts::BaseController + before_action :validate_feature_enabled! + + # POST /api/v1/accounts/:account_id/whatsapp/authorization + # Handles the embedded signup callback data from the Facebook SDK + def create + validate_embedded_signup_params! + channel = process_embedded_signup + render_success_response(channel.inbox) + rescue StandardError => e + render_error_response(e) + end + + private + + def process_embedded_signup + service = Whatsapp::EmbeddedSignupService.new( + account: Current.account, + code: params[:code], + business_id: params[:business_id], + waba_id: params[:waba_id], + phone_number_id: params[:phone_number_id] + ) + service.perform + end + + def render_success_response(inbox) + render json: { + success: true, + id: inbox.id, + name: inbox.name, + channel_type: 'whatsapp' + } + end + + def render_error_response(error) + Rails.logger.error "[WHATSAPP AUTHORIZATION] Embedded signup error: #{error.message}" + Rails.logger.error error.backtrace.join("\n") + render json: { + success: false, + error: error.message + }, status: :unprocessable_entity + end + + def validate_feature_enabled! + return if Current.account.feature_whatsapp_embedded_signup? + + render json: { + success: false, + error: 'WhatsApp embedded signup is not enabled for this account' + }, status: :forbidden + end + + def validate_embedded_signup_params! + missing_params = [] + missing_params << 'code' if params[:code].blank? + missing_params << 'business_id' if params[:business_id].blank? + missing_params << 'waba_id' if params[:waba_id].blank? + + return if missing_params.empty? + + raise ArgumentError, "Required parameters are missing: #{missing_params.join(', ')}" + end +end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 6a4ce2461..4a2df5ee5 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -67,6 +67,8 @@ class DashboardController < ActionController::Base FB_APP_ID: GlobalConfigService.load('FB_APP_ID', ''), INSTAGRAM_APP_ID: GlobalConfigService.load('INSTAGRAM_APP_ID', ''), FACEBOOK_API_VERSION: GlobalConfigService.load('FACEBOOK_API_VERSION', 'v17.0'), + WHATSAPP_APP_ID: GlobalConfigService.load('WHATSAPP_APP_ID', ''), + WHATSAPP_CONFIGURATION_ID: GlobalConfigService.load('WHATSAPP_CONFIGURATION_ID', ''), IS_ENTERPRISE: ChatwootApp.enterprise?, AZURE_APP_ID: GlobalConfigService.load('AZURE_APP_ID', ''), GIT_SHA: GIT_HASH diff --git a/app/controllers/notion/callbacks_controller.rb b/app/controllers/notion/callbacks_controller.rb index 94030fc8e..22dcf6d30 100644 --- a/app/controllers/notion/callbacks_controller.rb +++ b/app/controllers/notion/callbacks_controller.rb @@ -33,4 +33,4 @@ class Notion::CallbacksController < OauthCallbackController def notion_redirect_uri "#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/integrations/notion" end -end \ No newline at end of file +end diff --git a/app/controllers/super_admin/app_configs_controller.rb b/app/controllers/super_admin/app_configs_controller.rb index 771f9f28c..3972d5a28 100644 --- a/app/controllers/super_admin/app_configs_controller.rb +++ b/app/controllers/super_admin/app_configs_controller.rb @@ -39,8 +39,9 @@ class SuperAdmin::AppConfigsController < SuperAdmin::ApplicationController 'email' => ['MAILER_INBOUND_EMAIL_DOMAIN'], 'linear' => %w[LINEAR_CLIENT_ID LINEAR_CLIENT_SECRET], 'slack' => %w[SLACK_CLIENT_ID SLACK_CLIENT_SECRET], - 'notion' => %w[NOTION_CLIENT_ID NOTION_CLIENT_SECRET], - 'instagram' => %w[INSTAGRAM_APP_ID INSTAGRAM_APP_SECRET INSTAGRAM_VERIFY_TOKEN INSTAGRAM_API_VERSION ENABLE_INSTAGRAM_CHANNEL_HUMAN_AGENT] + 'instagram' => %w[INSTAGRAM_APP_ID INSTAGRAM_APP_SECRET INSTAGRAM_VERIFY_TOKEN INSTAGRAM_API_VERSION ENABLE_INSTAGRAM_CHANNEL_HUMAN_AGENT], + 'whatsapp_embedded' => %w[WHATSAPP_APP_ID WHATSAPP_APP_SECRET WHATSAPP_CONFIGURATION_ID WHATSAPP_API_VERSION], + 'notion' => %w[NOTION_CLIENT_ID NOTION_CLIENT_SECRET] } @allowed_configs = mapping.fetch(@config, %w[ENABLE_ACCOUNT_SIGNUP FIREBASE_PROJECT_ID FIREBASE_CREDENTIALS]) diff --git a/app/javascript/dashboard/api/channel/whatsappChannel.js b/app/javascript/dashboard/api/channel/whatsappChannel.js new file mode 100644 index 000000000..e1003b123 --- /dev/null +++ b/app/javascript/dashboard/api/channel/whatsappChannel.js @@ -0,0 +1,14 @@ +/* global axios */ +import ApiClient from '../ApiClient'; + +class WhatsappChannel extends ApiClient { + constructor() { + super('whatsapp', { accountScoped: true }); + } + + createEmbeddedSignup(params) { + return axios.post(`${this.baseUrl()}/whatsapp/authorization`, params); + } +} + +export default new WhatsappChannel(); diff --git a/app/javascript/dashboard/featureFlags.js b/app/javascript/dashboard/featureFlags.js index 98234539b..78109e82c 100644 --- a/app/javascript/dashboard/featureFlags.js +++ b/app/javascript/dashboard/featureFlags.js @@ -36,6 +36,7 @@ export const FEATURE_FLAGS = { REPORT_V4: 'report_v4', CHANNEL_INSTAGRAM: 'channel_instagram', CONTACT_CHATWOOT_SUPPORT_TEAM: 'contact_chatwoot_support_team', + WHATSAPP_EMBEDDED_SIGNUP: 'whatsapp_embedded_signup', CAPTAIN_V2: 'captain_integration_v2', }; diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index be7a6f2f9..eb999a0e5 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -222,10 +222,17 @@ "DESC": "Start supporting your customers via WhatsApp.", "PROVIDERS": { "LABEL": "API Provider", + "WHATSAPP_EMBEDDED": "WhatsApp Business", "TWILIO": "Twilio", "WHATSAPP_CLOUD": "WhatsApp Cloud", + "WHATSAPP_CLOUD_DESC": "Quick setup through Meta", + "TWILIO_DESC": "Connect via Twilio credentials", "360_DIALOG": "360Dialog" }, + "SELECT_PROVIDER": { + "TITLE": "Select your API provider", + "DESCRIPTION": "Choose your WhatsApp provider. You can connect directly through Meta which requires no setup, or connect through Twilio using your account credentials." + }, "INBOX_NAME": { "LABEL": "Inbox Name", "PLACEHOLDER": "Please enter an inbox name", @@ -264,6 +271,28 @@ "WEBHOOK_VERIFICATION_TOKEN": "Webhook Verification Token" }, "SUBMIT_BUTTON": "Create WhatsApp Channel", + "EMBEDDED_SIGNUP": { + "TITLE": "Quick Setup with Meta", + "DESC": "You will be redirected to Meta to log into your WhatsApp Business account. Having admin access will help make the setup smooth and easy.", + "BENEFITS": { + "TITLE": "Benefits of Embedded Signup:", + "EASY_SETUP": "No manual configuration required", + "SECURE_AUTH": "Secure OAuth based authentication", + "AUTO_CONFIG": "Automatic webhook and phone number configuration" + }, + "SUBMIT_BUTTON": "Connect with WhatsApp Business", + "AUTH_PROCESSING": "Authenticating with Meta", + "WAITING_FOR_BUSINESS_INFO": "Please complete business setup in the Meta window...", + "PROCESSING": "Setting up your WhatsApp Business Account", + "LOADING_SDK": "Loading Facebook SDK...", + "CANCELLED": "WhatsApp Signup was cancelled", + "SUCCESS_TITLE": "WhatsApp Business Account Connected!", + "WAITING_FOR_AUTH": "Waiting for authentication...", + "INVALID_BUSINESS_DATA": "Invalid business data received from Facebook. Please try again.", + "SIGNUP_ERROR": "Signup error occurred", + "AUTH_NOT_COMPLETED": "Authentication not completed. Please restart the process.", + "SUCCESS_FALLBACK": "WhatsApp Business Account has been successfully configured" + }, "API": { "ERROR_MESSAGE": "We were not able to save the WhatsApp channel" } diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/FinishSetup.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/FinishSetup.vue index f6d0707af..ac09448f6 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/FinishSetup.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/FinishSetup.vue @@ -47,6 +47,13 @@ export default { this.currentInbox.provider === 'whatsapp_cloud' ); }, + // If the inbox is a whatsapp cloud inbox and the source is not embedded signup, then show the webhook details + shouldShowWhatsAppWebhookDetails() { + return ( + this.isWhatsAppCloudInbox && + this.currentInbox.provider_config?.source !== 'embedded_signup' + ); + }, message() { if (this.isATwilioInbox) { return `${this.$t('INBOX_MGMT.FINISH.MESSAGE')}. ${this.$t( @@ -66,7 +73,7 @@ export default { )}`; } - if (this.isWhatsAppCloudInbox) { + if (this.isWhatsAppCloudInbox && this.shouldShowWhatsAppWebhookDetails) { return `${this.$t('INBOX_MGMT.FINISH.MESSAGE')}. ${this.$t( 'INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.SUBTITLE' )}`; @@ -113,8 +120,11 @@ export default { :script="currentInbox.callback_webhook_url" /> -
-

+

+

{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.WEBHOOK_URL') }}

diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue index a3f60c6d5..420d7b7b9 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue @@ -86,6 +86,12 @@ export default { selectedTabKey() { return this.tabs[this.selectedTabIndex]?.key; }, + shouldShowWhatsAppConfiguration() { + return !!( + this.isAWhatsAppCloudChannel && + this.inbox.provider_config?.source !== 'embedded_signup' + ); + }, whatsAppAPIProviderName() { if (this.isAWhatsAppCloudChannel) { return this.$t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD'); @@ -137,7 +143,7 @@ export default { this.isALineChannel || this.isAPIInbox || (this.isAnEmailChannel && !this.inbox.provider) || - this.isAWhatsAppChannel || + this.shouldShowWhatsAppConfiguration || this.isAWebWidgetInbox ) { visibleToAllChannelTabs = [ @@ -383,7 +389,7 @@ export default {