diff --git a/app/controllers/api/v1/accounts/data_imports_controller.rb b/app/controllers/api/v1/accounts/data_imports_controller.rb index 70432bc33..790cac87d 100644 --- a/app/controllers/api/v1/accounts/data_imports_controller.rb +++ b/app/controllers/api/v1/accounts/data_imports_controller.rb @@ -19,14 +19,12 @@ class Api::V1::Accounts::DataImportsController < Api::V1::Accounts::BaseControll end def validate_source - totals = validate_intercom_source + totals = source_class.credentials_validator(source_params: permitted_params.to_h, import_types: import_types).perform render json: { valid: true, totals: totals } - rescue DataImports::Intercom::Client::AuthenticationError - render_source_validation_error('We could not validate this Intercom access key. Check the key and its permissions.') - rescue DataImports::Intercom::Client::Error - render_source_validation_error('Intercom could not be reached. Please try again.') rescue ArgumentError => e render_source_validation_error(e.message) + rescue StandardError => e + render_source_client_error(e) end def create @@ -36,44 +34,42 @@ class Api::V1::Accounts::DataImportsController < Api::V1::Accounts::BaseControll return end - DataImports::Intercom::ImportJob.perform_later(@data_import, @data_import.active_intercom_import_run_id) + enqueue_import(@data_import) render_show - rescue DataImports::Intercom::Client::AuthenticationError - render_source_validation_error('We could not validate this Intercom access key. Check the key and its permissions.') - rescue DataImports::Intercom::Client::Error - render_source_validation_error('Intercom could not be reached. Please try again.') rescue ArgumentError => e render_source_validation_error(e.message) + rescue StandardError => e + render_source_client_error(e) end def start - restart_service = DataImports::Intercom::RestartService.new(account: Current.account, data_import: @data_import) + restart_service = DataImports::RestartService.new(account: Current.account, data_import: @data_import) restart_result = restart_service.perform @data_import = restart_service.data_import if restart_result == :access_token_missing - render json: { message: 'The Intercom access key for this import is unavailable.' }, status: :unprocessable_entity + render json: { message: "The #{source_name} #{credential_name} for this import is unavailable." }, status: :unprocessable_entity return end - DataImports::Intercom::ImportJob.perform_later(@data_import, @data_import.active_intercom_import_run_id) if restart_result == :enqueue + enqueue_import(@data_import) if restart_result == :enqueue render_show end def retry_import - retry_service = DataImports::Intercom::RetryService.new(account: Current.account, data_import: @data_import) + retry_service = DataImports::RetryService.new(account: Current.account, data_import: @data_import) retry_result = retry_service.perform @data_import = retry_service.data_import case retry_result when :enqueue - DataImports::Intercom::ImportJob.perform_later(@data_import, @data_import.active_intercom_import_run_id) + enqueue_import(@data_import) render_show when :not_stalled - render json: { message: 'This Intercom import is no longer stalled.' }, status: :unprocessable_entity + render json: { message: "This #{source_name} import is no longer stalled." }, status: :unprocessable_entity when :active_import_exists - render json: { message: 'Another Intercom import is already in progress.' }, status: :unprocessable_entity + render json: { message: "Another #{source_name} import is already in progress." }, status: :unprocessable_entity when :access_token_missing - render json: { message: 'The Intercom access key for this import is unavailable.' }, status: :unprocessable_entity + render json: { message: "The #{source_name} #{credential_name} for this import is unavailable." }, status: :unprocessable_entity end end @@ -113,11 +109,11 @@ class Api::V1::Accounts::DataImportsController < Api::V1::Accounts::BaseControll end def permitted_params - params.permit(:name, :source_provider, :access_token, import_types: []) + params.permit(:name, :source_provider, :access_token, :domain, import_types: []) end def creation_service - DataImports::Intercom::CreationService.new( + DataImports::CreationService.new( account: Current.account, initiated_by: Current.user, source_params: permitted_params.to_h @@ -125,24 +121,50 @@ class Api::V1::Accounts::DataImportsController < Api::V1::Accounts::BaseControll end def import_types - return DataImports::Intercom::Importer::DEFAULT_IMPORT_TYPES unless permitted_params.key?(:import_types) + return DataImports::Importer::DEFAULT_IMPORT_TYPES unless permitted_params.key?(:import_types) Array(permitted_params[:import_types]).compact_blank end - def validate_intercom_source - raise ArgumentError, 'Unsupported import source.' unless permitted_params[:source_provider] == 'intercom' + def source_class + provider = @data_import&.source_provider || permitted_params[:source_provider] + DataImports::Source.source_class(provider) + end - DataImports::Intercom::CredentialsValidator.new( - access_token: permitted_params[:access_token], - import_types: import_types - ).perform + def source_name + return 'Integration' unless DataImports::Source.supported?(@data_import&.source_provider || permitted_params[:source_provider]) + + source_class::DISPLAY_NAME + end + + def credential_name + return 'credential' unless DataImports::Source.supported?(@data_import&.source_provider || permitted_params[:source_provider]) + + source_class.credential_name + end + + def enqueue_import(data_import) + DataImports::Source.source_class(data_import.source_provider).import_job_class.perform_later( + data_import, + data_import.active_import_run_id + ) end def render_source_validation_error(message) render json: { valid: false, message: message }, status: :unprocessable_entity end + def render_source_client_error(error) + raise error unless source_class.client_error?(error) + + message = if source_class.authentication_error?(error) + "We could not validate this #{source_name} #{credential_name}. Check the key and its permissions." + else + "#{source_name} could not be reached. Please try again." + end + render_source_validation_error(message) + end + def render_show @import_errors_finder = DataImportErrorFinder.new(@data_import) @skip_logs_finder = DataImportSkipLogFinder.new(@data_import, params) diff --git a/app/javascript/dashboard/i18n/locale/en/settings.json b/app/javascript/dashboard/i18n/locale/en/settings.json index e36732e48..8d1516f3f 100644 --- a/app/javascript/dashboard/i18n/locale/en/settings.json +++ b/app/javascript/dashboard/i18n/locale/en/settings.json @@ -421,6 +421,10 @@ "DESCRIPTION": "Bring your existing contacts and past conversations into this account from another support tool. Each import runs in the background, so you can keep working while it finishes, track its progress, and review anything that was skipped along the way.", "LOADING": "Fetching imports", "DEFAULT_IMPORT_NAME": "Intercom import", + "DEFAULT_IMPORT_NAMES": { + "INTERCOM": "Intercom import", + "FRESHDESK": "Freshdesk import" + }, "TABS": { "IMPORT": "Import", "EXPORT": "Export" @@ -434,9 +438,15 @@ "TITLE": "New import", "SOURCE": "Source", "NAME": "Import name", - "NAME_PLACEHOLDER": "July Intercom migration", + "NAME_PLACEHOLDER": "July support migration", "ACCESS_KEY": "Intercom access key", "ACCESS_KEY_PLACEHOLDER": "Paste your Intercom access key", + "INTERCOM_ACCESS_KEY": "Intercom access key", + "INTERCOM_ACCESS_KEY_PLACEHOLDER": "Paste your Intercom access key", + "FRESHDESK_API_KEY": "Freshdesk API key", + "FRESHDESK_API_KEY_PLACEHOLDER": "Paste your Freshdesk API key", + "FRESHDESK_DOMAIN": "Freshdesk domain", + "FRESHDESK_DOMAIN_PLACEHOLDER": "acme.freshdesk.com", "DATA_TYPES": "Data to import", "VALIDATING": "Validating access key...", "VALID_KEY": "Access key validated.", @@ -510,11 +520,11 @@ } }, "ALERTS": { - "IMPORT_STARTED": "Intercom import has started.", - "IMPORT_RETRIED": "Intercom import has been queued to resume.", - "IMPORT_RETRY_FAILED": "Could not retry the Intercom import.", - "IMPORT_ABANDONED": "Intercom import has been abandoned.", - "IMPORT_FAILED": "Could not start the Intercom import." + "IMPORT_STARTED": "Import has started.", + "IMPORT_RETRIED": "Import has been queued to resume.", + "IMPORT_RETRY_FAILED": "Could not retry the import.", + "IMPORT_ABANDONED": "Import has been abandoned.", + "IMPORT_FAILED": "Could not start the import." } }, "CAPTAIN_SETTINGS": { diff --git a/app/javascript/dashboard/routes/dashboard/settings/data/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/data/Index.vue index 1a11c543a..c34c0a8f6 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/data/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/data/Index.vue @@ -24,7 +24,7 @@ import { formatStatus, importedCount, isActiveImport, - isActiveIntercomImport, + isActiveIntegrationImport, statusDotClass, } from './importStatus'; @@ -53,8 +53,8 @@ const activeTabIndex = computed(() => ); const hasActiveImport = computed(() => dataImports.value.some(isActiveImport)); -const hasActiveIntercomImport = computed(() => - dataImports.value.some(isActiveIntercomImport) +const hasActiveIntegrationImport = computed(() => + dataImports.value.some(isActiveIntegrationImport) ); const dataImportRoute = dataImport => ({ @@ -137,7 +137,7 @@ const openImport = dataImport => { }; const openImportDrawer = () => { - if (!hasActiveIntercomImport.value) showImportDrawer.value = true; + if (!hasActiveIntegrationImport.value) showImportDrawer.value = true; }; const onImportCreated = dataImportId => { @@ -227,9 +227,9 @@ onBeforeUnmount(() => {