Added zendesk import browser tests.
This commit is contained in:
parent
d45f634e05
commit
64d722d14c
7 changed files with 565 additions and 50 deletions
|
@ -404,3 +404,13 @@ job_integration_autowizard_chrome:
|
||||||
- ruby -I test/ test/integration/auto_wizard_test.rb || script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1
|
- ruby -I test/ test/integration/auto_wizard_test.rb || script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1
|
||||||
- script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT
|
- script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT
|
||||||
|
|
||||||
|
job_integration_zendesk_chrome:
|
||||||
|
- export BROWSER_PORT=4071
|
||||||
|
- export WS_PORT=4072
|
||||||
|
- export BROWSER_URL=http://$IP:$BROWSER_PORT
|
||||||
|
- RAILS_ENV=test rake db:create
|
||||||
|
- script/bootstrap.sh
|
||||||
|
- rake assets:precompile
|
||||||
|
- script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT
|
||||||
|
- ruby -I test/ test/integration/zendesk_import_browser_test.rb || script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1
|
||||||
|
- script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
class Index extends App.ControllerContent
|
class Index extends App.ControllerContent
|
||||||
className: 'getstarted fit'
|
className: 'getstarted fit'
|
||||||
elements:
|
elements:
|
||||||
'.input-feedback': 'urlStatus'
|
'.input-feedback': 'urlStatus'
|
||||||
'[data-target=otrs-start-migration]': 'nextStartMigration'
|
'[data-target=zendesk-credentials]': 'nextEnterCredentials'
|
||||||
'.otrs-link-error': 'linkErrorMessage'
|
'[data-target=zendesk-start-migration]': 'nextStartMigration'
|
||||||
|
'#zendesk-url': 'zendeskUrl'
|
||||||
|
'.js-zendeskUrlApiToken': 'zendeskUrlApiToken'
|
||||||
|
'.zendesk-url-error': 'linkErrorMessage'
|
||||||
|
'.zendesk-api-token-error': 'apiTokenErrorMessage'
|
||||||
|
'#zendesk-email': 'zendeskEmail'
|
||||||
|
'#zendesk-api-token': 'zendeskApiToken'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click .js-otrs-link': 'showLink'
|
'click .js-zendesk-credentials': 'showCredentials'
|
||||||
'click .js-download': 'startDownload'
|
'click .js-migration-start': 'startMigration'
|
||||||
'click .js-migration-start': 'startMigration'
|
'keyup #zendesk-url': 'updateUrl'
|
||||||
'keyup #otrs-link': 'updateUrl'
|
'keyup #zendesk-api-token': 'updateApiToken'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
@ -34,7 +41,7 @@ class Index extends App.ControllerContent
|
||||||
return
|
return
|
||||||
|
|
||||||
# check if import is active
|
# check if import is active
|
||||||
if data.import_mode == true && data.import_backend != 'otrs'
|
if data.import_mode == true && data.import_backend != 'zendesk'
|
||||||
@navigate '#import/' + data.import_backend
|
@navigate '#import/' + data.import_backend
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -47,34 +54,19 @@ class Index extends App.ControllerContent
|
||||||
)
|
)
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
@html App.view('import/otrs')()
|
@html App.view('import/zendesk')()
|
||||||
|
|
||||||
startDownload: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@$('.js-otrs-link').removeClass('hide')
|
|
||||||
|
|
||||||
showLink: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@$('[data-slide=otrs-plugin]').toggleClass('hide')
|
|
||||||
@$('[data-slide=otrs-link]').toggleClass('hide')
|
|
||||||
|
|
||||||
showImportState: =>
|
|
||||||
@$('[data-slide=otrs-plugin]').addClass('hide')
|
|
||||||
@$('[data-slide=otrs-link]').addClass('hide')
|
|
||||||
@$('[data-slide=otrs-import]').removeClass('hide')
|
|
||||||
|
|
||||||
updateUrl: (e) =>
|
updateUrl: (e) =>
|
||||||
url = $(e.target).val()
|
|
||||||
@urlStatus.attr('data-state', 'loading')
|
@urlStatus.attr('data-state', 'loading')
|
||||||
@linkErrorMessage.text('')
|
@linkErrorMessage.text('')
|
||||||
|
|
||||||
# get data
|
# get data
|
||||||
callback = =>
|
callback = =>
|
||||||
@ajax(
|
@ajax(
|
||||||
id: 'import_otrs_url',
|
id: 'import_zendesk_url',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: @apiPath + '/import/otrs/url_check',
|
url: @apiPath + '/import/zendesk/url_check',
|
||||||
data: JSON.stringify(url: url)
|
data: JSON.stringify(url: @zendeskUrl.val())
|
||||||
processData: true,
|
processData: true,
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
@ -83,14 +75,55 @@ class Index extends App.ControllerContent
|
||||||
if data.result is 'ok'
|
if data.result is 'ok'
|
||||||
@urlStatus.attr('data-state', 'success')
|
@urlStatus.attr('data-state', 'success')
|
||||||
@linkErrorMessage.text('')
|
@linkErrorMessage.text('')
|
||||||
@nextStartMigration.removeClass('hide')
|
@nextEnterCredentials.removeClass('hide')
|
||||||
else
|
else
|
||||||
@urlStatus.attr('data-state', 'error')
|
@urlStatus.attr('data-state', 'error')
|
||||||
@linkErrorMessage.text( data.message_human || data.message )
|
@linkErrorMessage.text( data.message_human || data.message )
|
||||||
|
@nextEnterCredentials.addClass('hide')
|
||||||
|
|
||||||
|
)
|
||||||
|
@delay( callback, 700, 'import_zendesk_url' )
|
||||||
|
|
||||||
|
updateApiToken: (e) =>
|
||||||
|
@urlStatus.attr('data-state', 'loading')
|
||||||
|
@apiTokenErrorMessage.text('')
|
||||||
|
|
||||||
|
# get data
|
||||||
|
callback = =>
|
||||||
|
@ajax(
|
||||||
|
id: 'import_zendesk_api_token',
|
||||||
|
type: 'POST',
|
||||||
|
url: @apiPath + '/import/zendesk/credentials_check',
|
||||||
|
data: JSON.stringify(username: @zendeskEmail.val(), token: @zendeskApiToken.val())
|
||||||
|
processData: true,
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# validate form
|
||||||
|
console.log(data)
|
||||||
|
if data.result is 'ok'
|
||||||
|
@urlStatus.attr('data-state', 'success')
|
||||||
|
@apiTokenErrorMessage.text('')
|
||||||
|
@nextStartMigration.removeClass('hide')
|
||||||
|
else
|
||||||
|
@urlStatus.attr('data-state', 'error')
|
||||||
|
@apiTokenErrorMessage.text( data.message_human || data.message )
|
||||||
@nextStartMigration.addClass('hide')
|
@nextStartMigration.addClass('hide')
|
||||||
|
|
||||||
)
|
)
|
||||||
@delay( callback, 700, 'import_otrs_url' )
|
@delay( callback, 700, 'import_zendesk_api_token' )
|
||||||
|
|
||||||
|
showCredentials: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@urlStatus.attr('data-state', '')
|
||||||
|
@zendeskUrlApiToken.attr('href', @zendeskUrl.val() + "agent/admin/api")
|
||||||
|
@zendeskUrlApiToken.val('HERE')
|
||||||
|
@$('[data-slide=zendesk-url]').toggleClass('hide')
|
||||||
|
@$('[data-slide=zendesk-credentials]').toggleClass('hide')
|
||||||
|
|
||||||
|
showImportState: =>
|
||||||
|
@$('[data-slide=zendesk-url]').addClass('hide')
|
||||||
|
@$('[data-slide=zendesk-credentials]').addClass('hide')
|
||||||
|
@$('[data-slide=zendesk-import]').removeClass('hide')
|
||||||
|
|
||||||
startMigration: (e) =>
|
startMigration: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -98,7 +131,7 @@ class Index extends App.ControllerContent
|
||||||
@ajax(
|
@ajax(
|
||||||
id: 'import_start',
|
id: 'import_start',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: @apiPath + '/import/otrs/import_start',
|
url: @apiPath + '/import/zendesk/import_start',
|
||||||
processData: true,
|
processData: true,
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
@ -108,19 +141,17 @@ class Index extends App.ControllerContent
|
||||||
@delay( @updateMigration, 3000 )
|
@delay( @updateMigration, 3000 )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
updateMigration: =>
|
updateMigration: =>
|
||||||
@showImportState()
|
@showImportState()
|
||||||
@ajax(
|
@ajax(
|
||||||
id: 'import_status',
|
id: 'import_status',
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: @apiPath + '/import/otrs/import_status',
|
url: @apiPath + '/import/zendesk/import_status',
|
||||||
processData: true,
|
processData: true,
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
if data.setup_done
|
if data.result is 'import_done'
|
||||||
@Config.set('system_init_done', true)
|
window.location.reload()
|
||||||
@navigate '#'
|
|
||||||
return
|
return
|
||||||
|
|
||||||
for key, item of data.data
|
for key, item of data.data
|
||||||
|
|
108
app/assets/javascripts/app/views/import/zendesk.jst.eco
Normal file
108
app/assets/javascripts/app/views/import/zendesk.jst.eco
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
<div class="main flex vertical centered darkBackground">
|
||||||
|
<%- @Icon('full-logo', 'wizard-logo') %>
|
||||||
|
<div class="import wizard">
|
||||||
|
<div class="wizard-slide vertical" data-slide="zendesk-url">
|
||||||
|
<h2><%- @T('Zendesk URL') %></h2>
|
||||||
|
<div class="wizard-body flex vertical justified">
|
||||||
|
<p>
|
||||||
|
<%- @T('Enter the URL of your Zendesk system') %>:
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="zendesk-url">Zendesk URL</label>
|
||||||
|
<div class="u-positionOrigin">
|
||||||
|
<input type="url" id="zendesk-url" class="form-control" placeholder="https://example.zendesk.com/" name="zendesk-url">
|
||||||
|
<div class="input-feedback centered">
|
||||||
|
<div class="small loading icon"></div>
|
||||||
|
<%- @Icon('diagonal-cross', 'icon-error') %>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="error zendesk-url-error"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wizard-controls horizontal center">
|
||||||
|
<a class="btn btn--text btn--secondary" href="#import"><%- @T('Go Back') %></a>
|
||||||
|
<div class="btn btn--primary align-right hide js-zendesk-credentials" data-target="zendesk-credentials"><%- @T('Enter credentials') %></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wizard-slide vertical hide" data-slide="zendesk-credentials">
|
||||||
|
<h2><%- @T('Zendesk credentials') %></h2>
|
||||||
|
<div class="wizard-body flex vertical justified">
|
||||||
|
<p>
|
||||||
|
<%- @T('Enter your Email address and the Zendesk API token gained from your') %> <a class="js-zendeskUrlApiToken" target="_blank"><%- @T('admin interface') %></a>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="zendesk-email">Email address</label>
|
||||||
|
<div class="u-positionOrigin">
|
||||||
|
<input type="email" id="zendesk-email" class="form-control" placeholder="admin@example.com" name="zendesk-email">
|
||||||
|
</div>
|
||||||
|
<label for="zendesk-api-token">API token</label>
|
||||||
|
<div class="u-positionOrigin">
|
||||||
|
<input type="email" id="zendesk-api-token" class="form-control" placeholder="XYZ3133723421111" name="zendesk-api-token">
|
||||||
|
<div class="input-feedback centered">
|
||||||
|
<div class="small loading icon"></div>
|
||||||
|
<%- @Icon('diagonal-cross', 'icon-error') %>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="error zendesk-api-token-error"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wizard-controls horizontal center">
|
||||||
|
<a class="btn btn--text btn--secondary" href="#import"><%- @T('Go Back') %></a>
|
||||||
|
<div class="btn btn--primary align-right hide js-migration-start" data-target="zendesk-start-migration"><%- @T('Migrate Zendesk Data') %></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wizard-slide vertical hide" data-slide="zendesk-import">
|
||||||
|
<h2><%- @T('Zendesk Migration') %></h2>
|
||||||
|
<div class="alert alert--danger hide js-error" role="alert"></div>
|
||||||
|
<div class="wizard-body flex vertical justified">
|
||||||
|
<table class="progressTable">
|
||||||
|
<tr class="js-group">
|
||||||
|
<td><span class="js-done">-</span>/<span class="js-total">-</span>
|
||||||
|
<td><span><%- @T('Groups') %></span>
|
||||||
|
<td class="progressTable-progressCell">
|
||||||
|
<div class="horizontal center">
|
||||||
|
<div class="flex"><progress max="42" value="42"></progress></div>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
<tr class="js-organization">
|
||||||
|
<td><span class="js-done">-</span>/<span class="js-total">-</span>
|
||||||
|
<td><span><%- @T('Organizations') %></span>
|
||||||
|
<td class="progressTable-progressCell">
|
||||||
|
<div class="horizontal center">
|
||||||
|
<div class="flex"><progress max="42" value="42"></progress></div>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
<tr class="js-user">
|
||||||
|
<td><span class="js-done">-</span>/<span class="js-total">-</span>
|
||||||
|
<td><span><%- @T('Users') %></span>
|
||||||
|
<td class="progressTable-progressCell">
|
||||||
|
<div class="horizontal center">
|
||||||
|
<div class="flex"><progress max="42" value="42"></progress></div>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
<tr class="js-ticket">
|
||||||
|
<td><span class="js-done">-</span>/<span class="js-total">-</span>
|
||||||
|
<td><span><%- @T('Tickets') %></span>
|
||||||
|
<td class="progressTable-progressCell">
|
||||||
|
<div class="horizontal center">
|
||||||
|
<div class="flex"><progress max="42" value="42"></progress></div>
|
||||||
|
<%- @Icon('checkmark') %>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="wizard-controls horizontal center">
|
||||||
|
<a href="#" class="btn btn--primary align-right hide js-finished"><%- @T('Done') %></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
124
app/controllers/import_zendesk_controller.rb
Normal file
124
app/controllers/import_zendesk_controller.rb
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
require 'zendesk_api'
|
||||||
|
|
||||||
|
class ImportZendeskController < ApplicationController
|
||||||
|
|
||||||
|
def url_check
|
||||||
|
return if setup_done_response
|
||||||
|
|
||||||
|
# validate
|
||||||
|
if !params[:url] || params[:url] !~ %r{^(http|https)://.+?$}
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Invalid URL!',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# connection test
|
||||||
|
translation_map = {
|
||||||
|
'No such file' => 'Hostname not found!',
|
||||||
|
'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
|
||||||
|
'No route to host' => 'No route to host!',
|
||||||
|
'Connection refused' => 'Connection refused!',
|
||||||
|
}
|
||||||
|
|
||||||
|
response = UserAgent.request( params[:url] )
|
||||||
|
|
||||||
|
if !response.success?
|
||||||
|
message_human = ''
|
||||||
|
translation_map.each {|key, message|
|
||||||
|
if response.error.to_s =~ /#{Regexp.escape(key)}/i
|
||||||
|
message_human = message
|
||||||
|
end
|
||||||
|
}
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message_human: message_human,
|
||||||
|
message: response.error.to_s,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
Setting.set('import_zendesk_endpoint', "#{params[:url]}api/v2")
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'ok',
|
||||||
|
url: params[:url],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def credentials_check
|
||||||
|
return if setup_done_response
|
||||||
|
|
||||||
|
if !params[:username] || !params[:token]
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message_human: 'Incomplete credentials',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
Setting.set('import_zendesk_endpoint_username', params[:username])
|
||||||
|
Setting.set('import_zendesk_endpoint_key', params[:token])
|
||||||
|
|
||||||
|
if !Import::Zendesk.connection_test
|
||||||
|
|
||||||
|
Setting.set('import_zendesk_endpoint_username', nil)
|
||||||
|
Setting.set('import_zendesk_endpoint_key', nil)
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message_human: 'Invalid credentials!',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'ok',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def import_start
|
||||||
|
return if setup_done_response
|
||||||
|
Setting.set('import_mode', true)
|
||||||
|
|
||||||
|
# start migration
|
||||||
|
Import::Zendesk.delay.start_bg
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'ok',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def import_status
|
||||||
|
result = Import::Zendesk.status_bg
|
||||||
|
if result[:result] == 'import_done'
|
||||||
|
Setting.reload
|
||||||
|
end
|
||||||
|
render json: result
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def setup_done
|
||||||
|
count = User.all.count()
|
||||||
|
done = true
|
||||||
|
if count <= 2
|
||||||
|
done = false
|
||||||
|
end
|
||||||
|
done
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_done_response
|
||||||
|
if !setup_done
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
render json: {
|
||||||
|
setup_done: true,
|
||||||
|
}
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
10
config/routes/import_zendesk.rb
Normal file
10
config/routes/import_zendesk.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Zammad::Application.routes.draw do
|
||||||
|
api_path = Rails.configuration.api_path
|
||||||
|
|
||||||
|
# import zendesk
|
||||||
|
match api_path + '/import/zendesk/url_check', to: 'import_zendesk#url_check', via: :post
|
||||||
|
match api_path + '/import/zendesk/credentials_check', to: 'import_zendesk#credentials_check', via: :post
|
||||||
|
match api_path + '/import/zendesk/import_start', to: 'import_zendesk#import_start', via: :post
|
||||||
|
match api_path + '/import/zendesk/import_status', to: 'import_zendesk#import_status', via: :get
|
||||||
|
|
||||||
|
end
|
|
@ -48,6 +48,95 @@ module Import::Zendesk
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
start import in background
|
||||||
|
|
||||||
|
Import::Zendesk.start_bg
|
||||||
|
=end
|
||||||
|
|
||||||
|
def start_bg
|
||||||
|
Setting.reload
|
||||||
|
|
||||||
|
Import::Zendesk.connection_test
|
||||||
|
|
||||||
|
# start thread to observe current state
|
||||||
|
status_update_thread = Thread.new {
|
||||||
|
loop do
|
||||||
|
result = {
|
||||||
|
data: current_state,
|
||||||
|
result: 'in_progress',
|
||||||
|
}
|
||||||
|
Cache.write('import:state', result, expires_in: 10.minutes)
|
||||||
|
sleep 8
|
||||||
|
end
|
||||||
|
}
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# start thread to import data
|
||||||
|
begin
|
||||||
|
import_thread = Thread.new {
|
||||||
|
Import::Zendesk.start
|
||||||
|
}
|
||||||
|
rescue => e
|
||||||
|
status_update_thread.exit
|
||||||
|
status_update_thread.join
|
||||||
|
Rails.logger.error e.message
|
||||||
|
Rails.logger.error e.backtrace.inspect
|
||||||
|
result = {
|
||||||
|
message: e.message,
|
||||||
|
result: 'error',
|
||||||
|
}
|
||||||
|
Cache.write('import:state', result, expires_in: 10.hours)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
import_thread.join
|
||||||
|
status_update_thread.exit
|
||||||
|
status_update_thread.join
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'import_done',
|
||||||
|
}
|
||||||
|
Cache.write('import:state', result, expires_in: 10.hours)
|
||||||
|
|
||||||
|
Setting.set('system_init_done', true)
|
||||||
|
Setting.set('import_mode', false)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get import state from background process
|
||||||
|
|
||||||
|
result = Import::Zendesk.status_bg
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def status_bg
|
||||||
|
state = Cache.get('import:state')
|
||||||
|
return state if state
|
||||||
|
{
|
||||||
|
message: 'not running',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
start get request to backend to check connection
|
||||||
|
|
||||||
|
result = connection_test
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
true | false
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def connection_test
|
||||||
|
initialize_client
|
||||||
|
|
||||||
|
return true if @client.users.first
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def statistic
|
def statistic
|
||||||
|
|
||||||
# check cache
|
# check cache
|
||||||
|
@ -89,9 +178,61 @@ module Import::Zendesk
|
||||||
statistic
|
statistic
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_client
|
=begin
|
||||||
return nil if @client
|
|
||||||
|
|
||||||
|
return current import state
|
||||||
|
|
||||||
|
result = current_state
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
{
|
||||||
|
:Group => {
|
||||||
|
:total => 1234,
|
||||||
|
:done => 13,
|
||||||
|
},
|
||||||
|
:Organization => {
|
||||||
|
:total => 1234,
|
||||||
|
:done => 13,
|
||||||
|
},
|
||||||
|
:User => {
|
||||||
|
:total => 1234,
|
||||||
|
:done => 13,
|
||||||
|
},
|
||||||
|
:Ticket => {
|
||||||
|
:total => 1234,
|
||||||
|
:done => 13,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def current_state
|
||||||
|
|
||||||
|
data = statistic
|
||||||
|
|
||||||
|
# TODO: Ticket, User, Organization fields
|
||||||
|
{
|
||||||
|
Group: {
|
||||||
|
done: Group.count,
|
||||||
|
total: data['Groups'] || 0,
|
||||||
|
},
|
||||||
|
Organization: {
|
||||||
|
done: Organization.count,
|
||||||
|
total: data['Organizations'] || 0,
|
||||||
|
},
|
||||||
|
User: {
|
||||||
|
done: User.count,
|
||||||
|
total: data['Users'] || 0,
|
||||||
|
},
|
||||||
|
Ticket: {
|
||||||
|
done: Ticket.count,
|
||||||
|
total: data['Tickets'] || 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_client
|
||||||
@client = ZendeskAPI::Client.new do |config|
|
@client = ZendeskAPI::Client.new do |config|
|
||||||
config.url = Setting.get('import_zendesk_endpoint')
|
config.url = Setting.get('import_zendesk_endpoint')
|
||||||
|
|
||||||
|
@ -350,11 +491,13 @@ module Import::Zendesk
|
||||||
@client.organizations.each { |zendesk_organization|
|
@client.organizations.each { |zendesk_organization|
|
||||||
|
|
||||||
local_organization_fields = {
|
local_organization_fields = {
|
||||||
name: zendesk_organization.name,
|
name: zendesk_organization.name,
|
||||||
note: zendesk_organization.note,
|
note: zendesk_organization.note,
|
||||||
shared: zendesk_organization.shared_tickets,
|
shared: zendesk_organization.shared_tickets,
|
||||||
# shared: zendesk_organization.shared_comments, # TODO, not yet implemented
|
# shared: zendesk_organization.shared_comments, # TODO, not yet implemented
|
||||||
# }.merge(zendesk_organization.organization_fields) # TODO
|
# }.merge(zendesk_organization.organization_fields) # TODO
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
local_organization = Organization.create_if_not_exists( local_organization_fields )
|
local_organization = Organization.create_if_not_exists( local_organization_fields )
|
||||||
|
@ -391,6 +534,8 @@ module Import::Zendesk
|
||||||
verified: zendesk_user.verified,
|
verified: zendesk_user.verified,
|
||||||
organization_id: @zendesk_organization_mapping[ zendesk_user.organization_id ],
|
organization_id: @zendesk_organization_mapping[ zendesk_user.organization_id ],
|
||||||
last_login: zendesk_user.last_login_at,
|
last_login: zendesk_user.last_login_at,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if @zendesk_user_group_mapping[ zendesk_user.id ]
|
if @zendesk_user_group_mapping[ zendesk_user.id ]
|
||||||
|
@ -498,19 +643,18 @@ module Import::Zendesk
|
||||||
title: zendesk_ticket.subject,
|
title: zendesk_ticket.subject,
|
||||||
note: zendesk_ticket.description,
|
note: zendesk_ticket.description,
|
||||||
group_id: @zendesk_group_mapping[ zendesk_ticket.group_id ] || 1,
|
group_id: @zendesk_group_mapping[ zendesk_ticket.group_id ] || 1,
|
||||||
customer_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ],
|
customer_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1,
|
||||||
organization_id: @zendesk_organization_mapping[ zendesk_ticket.organization_id ],
|
organization_id: @zendesk_organization_mapping[ zendesk_ticket.organization_id ],
|
||||||
state: Ticket::State.lookup( name: mapping_state( zendesk_ticket.status ) ),
|
state: Ticket::State.lookup( name: mapping_state( zendesk_ticket.status ) ),
|
||||||
priority: Ticket::Priority.lookup( name: mapping_priority( zendesk_ticket.priority ) ),
|
priority: Ticket::Priority.lookup( name: mapping_priority( zendesk_ticket.priority ) ),
|
||||||
pending_time: zendesk_ticket.due_at,
|
pending_time: zendesk_ticket.due_at,
|
||||||
updated_at: zendesk_ticket.updated_at,
|
updated_at: zendesk_ticket.updated_at,
|
||||||
created_at: zendesk_ticket.created_at,
|
created_at: zendesk_ticket.created_at,
|
||||||
updated_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ],
|
updated_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1,
|
||||||
created_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ],
|
created_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1,
|
||||||
# }.merge(zendesk_ticket_fields) TODO
|
# }.merge(zendesk_ticket_fields) TODO
|
||||||
}
|
}
|
||||||
|
ticket_author = User.find( @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1 )
|
||||||
ticket_author = User.find( @zendesk_user_mapping[ zendesk_ticket.requester_id ] )
|
|
||||||
|
|
||||||
local_ticket_fields[:create_article_sender_id] = if ticket_author.role?('Customer')
|
local_ticket_fields[:create_article_sender_id] = if ticket_author.role?('Customer')
|
||||||
article_sender_customer.id
|
article_sender_customer.id
|
||||||
|
@ -553,7 +697,7 @@ module Import::Zendesk
|
||||||
object: 'Ticket',
|
object: 'Ticket',
|
||||||
o_id: local_ticket.id,
|
o_id: local_ticket.id,
|
||||||
item: tag.id,
|
item: tag.id,
|
||||||
created_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ],
|
created_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,11 +725,11 @@ module Import::Zendesk
|
||||||
ticket_id: local_ticket.id,
|
ticket_id: local_ticket.id,
|
||||||
body: zendesk_article.html_body,
|
body: zendesk_article.html_body,
|
||||||
internal: !zendesk_article.public,
|
internal: !zendesk_article.public,
|
||||||
updated_by_id: @zendesk_user_mapping[ zendesk_article.author_id ],
|
updated_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1,
|
||||||
created_by_id: @zendesk_user_mapping[ zendesk_article.author_id ],
|
created_by_id: @zendesk_user_mapping[ zendesk_article.author_id ] || 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
article_author = User.find( @zendesk_user_mapping[ zendesk_article.author_id ] )
|
article_author = User.find( @zendesk_user_mapping[ zendesk_article.author_id ] || 1 )
|
||||||
|
|
||||||
local_article_fields[:sender_id] = if article_author.role?('Customer')
|
local_article_fields[:sender_id] = if article_author.role?('Customer')
|
||||||
article_sender_customer.id
|
article_sender_customer.id
|
||||||
|
@ -662,7 +806,8 @@ module Import::Zendesk
|
||||||
filename: zendesk_attachment.file_name,
|
filename: zendesk_attachment.file_name,
|
||||||
preferences: {
|
preferences: {
|
||||||
'Content-Type' => zendesk_attachment.content_type
|
'Content-Type' => zendesk_attachment.content_type
|
||||||
}
|
},
|
||||||
|
created_by_id: 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
87
test/integration/zendesk_import_browser_test.rb
Normal file
87
test/integration/zendesk_import_browser_test.rb
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class ZendeskImportBrowserTest < TestCase
|
||||||
|
def test_import
|
||||||
|
|
||||||
|
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT']
|
||||||
|
fail "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT - hint IMPORT_BT_ZENDESK_ENDPOINT='https://example.zendesk.com/' (including trailing slash!)"
|
||||||
|
end
|
||||||
|
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT_USERNAME']
|
||||||
|
fail "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT_USERNAME - hint IMPORT_BT_ZENDESK_ENDPOINT_USERNAME='your@email.com'"
|
||||||
|
end
|
||||||
|
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT_KEY']
|
||||||
|
fail "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT_KEY - hint IMPORT_BT_ZENDESK_ENDPOINT_KEY='XYZ3133723421111'"
|
||||||
|
end
|
||||||
|
|
||||||
|
@browser = browser_instance
|
||||||
|
location(url: browser_url)
|
||||||
|
|
||||||
|
click(css: 'a[href="#import"]')
|
||||||
|
|
||||||
|
click(css: 'a[href="#import/zendesk"]')
|
||||||
|
|
||||||
|
set(
|
||||||
|
css: '#zendesk-url',
|
||||||
|
value: 'https://reallybadexample.zendesk.com/'
|
||||||
|
)
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
watch_for(
|
||||||
|
css: '.zendesk-url-error',
|
||||||
|
value: 'Hostname not found!',
|
||||||
|
)
|
||||||
|
|
||||||
|
set(
|
||||||
|
css: '#zendesk-url',
|
||||||
|
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT']
|
||||||
|
)
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
watch_for_disappear(
|
||||||
|
css: '.zendesk-url-error',
|
||||||
|
value: 'Hostname not found!',
|
||||||
|
)
|
||||||
|
|
||||||
|
click(css: '.js-zendesk-credentials')
|
||||||
|
|
||||||
|
set(
|
||||||
|
css: '#zendesk-email',
|
||||||
|
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT_USERNAME']
|
||||||
|
)
|
||||||
|
|
||||||
|
set(
|
||||||
|
css: '#zendesk-api-token',
|
||||||
|
value: '1nv4l1dT0K3N'
|
||||||
|
)
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
watch_for(
|
||||||
|
css: '.zendesk-api-token-error',
|
||||||
|
value: 'Invalid credentials!',
|
||||||
|
)
|
||||||
|
|
||||||
|
set(
|
||||||
|
css: '#zendesk-api-token',
|
||||||
|
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT_KEY']
|
||||||
|
)
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
watch_for_disappear(
|
||||||
|
css: '.zendesk-url-error',
|
||||||
|
value: 'Invalid credentials!',
|
||||||
|
)
|
||||||
|
|
||||||
|
click(css: '.js-migration-start')
|
||||||
|
|
||||||
|
watch_for(
|
||||||
|
css: 'body',
|
||||||
|
value: 'login',
|
||||||
|
timeout: 300,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue