From ea10d24c386707505e506f81162af3084f51de04 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 13 Jan 2016 16:59:26 +0100 Subject: [PATCH 1/7] Current state of browser test. --- test/integration/otrs_import_browser_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/integration/otrs_import_browser_test.rb b/test/integration/otrs_import_browser_test.rb index 816f56d47..d7e386a1f 100644 --- a/test/integration/otrs_import_browser_test.rb +++ b/test/integration/otrs_import_browser_test.rb @@ -20,11 +20,21 @@ class OtrsImportBrowserTest < TestCase click(css: 'a[href="#import/otrs"]') + click(css: 'a.js-download') + + click(css: 'a.js-otrs-link') + set( css: '#otrs-link', value: import_url ) + exists( + css: 'svg.icon-checkmark' + ) + + click(css: 'a.js-migration-start') + watch_for( css: 'body', value: 'xxxx', From 437023ac79bebcf74501fe466015ab9e29dbe3a0 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 13 Jan 2016 17:14:28 +0100 Subject: [PATCH 2/7] Fixed bug: Invalid API keys are validated as correct. --- app/controllers/import_otrs_controller.rb | 31 +++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/app/controllers/import_otrs_controller.rb b/app/controllers/import_otrs_controller.rb index 7b84208a2..24a174659 100644 --- a/app/controllers/import_otrs_controller.rb +++ b/app/controllers/import_otrs_controller.rb @@ -22,9 +22,7 @@ class ImportOtrsController < ApplicationController 'Connection refused' => 'Connection refused!', } - url_parts = params[:url].split(';') - - response = UserAgent.request( url_parts[0] ) + response = UserAgent.request( params[:url] ) if !response.success? && response.code.to_s !~ /^40.$/ message_human = '' @@ -44,16 +42,27 @@ class ImportOtrsController < ApplicationController result = {} if response.body =~ /zammad migrator/ - key_parts = url_parts[1].split('=') + migrator_response = JSON.parse(response.body) - Setting.set('import_backend', 'otrs') - Setting.set('import_otrs_endpoint', url_parts[0]) - Setting.set('import_otrs_endpoint_key', key_parts[1]) + if migrator_response['Success'] == 1 - result = { - result: 'ok', - url: params[:url], - } + url_parts = params[:url].split(';') + key_parts = url_parts[1].split('=') + + Setting.set('import_backend', 'otrs') + Setting.set('import_otrs_endpoint', url_parts[0]) + Setting.set('import_otrs_endpoint_key', key_parts[1]) + + result = { + result: 'ok', + url: params[:url], + } + else + result = { + result: 'invalid', + message_human: migrator_response['Error'] + } + end elsif response.body =~ /(otrs\sag|otrs\.com|otrs\.org)/i result = { result: 'invalid', From e779f459b413205b9b3745da27e67961e5c91bca Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 13 Jan 2016 17:33:08 +0100 Subject: [PATCH 3/7] Improved finish of import. --- .../app/controllers/import_otrs.coffee | 8 ++++++-- lib/import/otrs.rb | 5 +++++ test/integration/otrs_import_browser_test.rb | 20 +++++-------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/app/controllers/import_otrs.coffee b/app/assets/javascripts/app/controllers/import_otrs.coffee index 2d04674a5..887737c97 100644 --- a/app/assets/javascripts/app/controllers/import_otrs.coffee +++ b/app/assets/javascripts/app/controllers/import_otrs.coffee @@ -18,6 +18,12 @@ class Index extends App.ControllerContent @fetch() + @bind('import:finished', => + console.log('import:finished') + @Config.set('system_init_done', true) + @navigate '#' + ) + fetch: -> # get data @@ -79,7 +85,6 @@ class Index extends App.ControllerContent success: (data, status, xhr) => # validate form - console.log(data) if data.result is 'ok' @urlStatus.attr('data-state', 'success') @linkErrorMessage.text('') @@ -103,7 +108,6 @@ class Index extends App.ControllerContent success: (data, status, xhr) => # validate form - console.log(data) if data.result is 'ok' @delay( @updateMigration, 3000 ) ) diff --git a/lib/import/otrs.rb b/lib/import/otrs.rb index 98c9cd80b..0ec12c2ba 100644 --- a/lib/import/otrs.rb +++ b/lib/import/otrs.rb @@ -412,6 +412,11 @@ module Import::OTRS Setting.set('system_init_done', true) Setting.set('import_mode', false) + # broadcast import finish + Sessions.broadcast( + event: 'import:finished', + ) + true end diff --git a/test/integration/otrs_import_browser_test.rb b/test/integration/otrs_import_browser_test.rb index d7e386a1f..3bbcf81e6 100644 --- a/test/integration/otrs_import_browser_test.rb +++ b/test/integration/otrs_import_browser_test.rb @@ -20,9 +20,9 @@ class OtrsImportBrowserTest < TestCase click(css: 'a[href="#import/otrs"]') - click(css: 'a.js-download') + click(css: '.js-download') - click(css: 'a.js-otrs-link') + click(css: '.js-otrs-link') set( css: '#otrs-link', @@ -33,24 +33,14 @@ class OtrsImportBrowserTest < TestCase css: 'svg.icon-checkmark' ) - click(css: 'a.js-migration-start') + click(css: '.js-migration-start') watch_for( css: 'body', - value: 'xxxx', - timeout: 10, + value: 'login', + timeout: 300, ) - # click import - - # click otrs - - # enter otrs url + key - - # watch for import start - - # watch for import end - end end From 896f33b4ce7990d7d6f0311ecb39c124950569f2 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 13 Jan 2016 18:00:43 +0100 Subject: [PATCH 4/7] Added browser test for invalid API key. --- test/integration/otrs_import_browser_test.rb | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/test/integration/otrs_import_browser_test.rb b/test/integration/otrs_import_browser_test.rb index 3bbcf81e6..4f59578aa 100644 --- a/test/integration/otrs_import_browser_test.rb +++ b/test/integration/otrs_import_browser_test.rb @@ -11,8 +11,6 @@ class OtrsImportBrowserTest < TestCase fail "ERROR: Need IMPORT_BT_OTRS_ENDPOINT_KEY - hint IMPORT_BT_OTRS_ENDPOINT_KEY='01234567899876543210'" end - import_url = "#{ENV['IMPORT_BT_OTRS_ENDPOINT']};Key=#{ENV['IMPORT_BT_OTRS_ENDPOINT_KEY']}" - @browser = browser_instance location(url: browser_url) @@ -24,13 +22,31 @@ class OtrsImportBrowserTest < TestCase click(css: '.js-otrs-link') + invalid_key_url = "#{ENV['IMPORT_BT_OTRS_ENDPOINT']};Key=31337" + + set( + css: '#otrs-link', + value: invalid_key_url + ) + + sleep 5 + + watch_for( + css: '.otrs-link-error', + value: 'Invalid API key.', + ) + + import_url = "#{ENV['IMPORT_BT_OTRS_ENDPOINT']};Key=#{ENV['IMPORT_BT_OTRS_ENDPOINT_KEY']}" set( css: '#otrs-link', value: import_url ) - exists( - css: 'svg.icon-checkmark' + sleep 5 + + watch_for_disappear( + css: '.otrs-link-error', + value: 'Invalid API key.', ) click(css: '.js-migration-start') From 159aa3f41f437fa36d96c848b7bae1ccf29a1b39 Mon Sep 17 00:00:00 2001 From: Felix Niklas Date: Wed, 13 Jan 2016 18:38:31 +0100 Subject: [PATCH 5/7] customer chat: add create ticket button --- app/assets/javascripts/app/controllers/chat.coffee | 3 +++ .../app/views/customer_chat/chat_footer.jst.eco | 3 +++ app/assets/stylesheets/zammad.scss | 14 +++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/app/views/customer_chat/chat_footer.jst.eco diff --git a/app/assets/javascripts/app/controllers/chat.coffee b/app/assets/javascripts/app/controllers/chat.coffee index 2357bb72d..eb5919bdf 100644 --- a/app/assets/javascripts/app/controllers/chat.coffee +++ b/app/assets/javascripts/app/controllers/chat.coffee @@ -601,6 +601,9 @@ class ChatWindow extends App.Controller @el.addClass('is-offline') @input.attr('disabled', true) + # add footer with create ticket button + @body.append App.view('customer_chat/chat_footer')() + maybeAddTimestamp: -> timestamp = Date.now() diff --git a/app/assets/javascripts/app/views/customer_chat/chat_footer.jst.eco b/app/assets/javascripts/app/views/customer_chat/chat_footer.jst.eco new file mode 100644 index 000000000..547c4142d --- /dev/null +++ b/app/assets/javascripts/app/views/customer_chat/chat_footer.jst.eco @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/zammad.scss b/app/assets/stylesheets/zammad.scss index 5fa47a3c0..36af9ea5c 100644 --- a/app/assets/stylesheets/zammad.scss +++ b/app/assets/stylesheets/zammad.scss @@ -7275,7 +7275,6 @@ output { } &.is-offline { - .chat-body-holder, .chat-controls { opacity: 0.5; } @@ -7286,7 +7285,7 @@ output { background: hsl(210,8%,95%); border: 1px solid hsl(0,0%,91%); border-radius: 3px 3px 0 0; - height: 37px; + height: 43px; line-height: 13px; flex-shrink: 0; display: flex; @@ -7336,7 +7335,7 @@ output { .chat-disconnect, .chat-close { cursor: pointer; - padding: 0 4px; + padding: 10px; .btn { min-width: 80px; @@ -7437,6 +7436,15 @@ output { 67% { opacity: 1; transform: scale(1); } } +.chat-footer { + border-top: 1px solid hsl(0,0%,93%); + padding: 10px; + display: flex; + justify-content: center; + align-self: stretch; + margin: 0 -10px; +} + .chat-controls { display: flex; align-items: flex-start; From f2d0eca3da4d922b8ac4f741af30cacd0f39acd4 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 13 Jan 2016 20:45:51 +0100 Subject: [PATCH 6/7] Improved background job for import. --- .../app/controllers/import_otrs.coffee | 41 +++++----- .../javascripts/app/views/import/otrs.jst.eco | 2 + app/controllers/import_otrs_controller.rb | 21 ++--- app/models/setting.rb | 16 +++- lib/import/otrs.rb | 77 +++++++++++++++++-- 5 files changed, 115 insertions(+), 42 deletions(-) diff --git a/app/assets/javascripts/app/controllers/import_otrs.coffee b/app/assets/javascripts/app/controllers/import_otrs.coffee index 887737c97..da6e8f92c 100644 --- a/app/assets/javascripts/app/controllers/import_otrs.coffee +++ b/app/assets/javascripts/app/controllers/import_otrs.coffee @@ -18,12 +18,6 @@ class Index extends App.ControllerContent @fetch() - @bind('import:finished', => - console.log('import:finished') - @Config.set('system_init_done', true) - @navigate '#' - ) - fetch: -> # get data @@ -95,7 +89,7 @@ class Index extends App.ControllerContent @nextStartMigration.addClass('hide') ) - @delay( callback, 700, 'import_otrs_url' ) + @delay(callback, 700, 'import_otrs_url') startMigration: (e) => e.preventDefault() @@ -106,10 +100,8 @@ class Index extends App.ControllerContent url: @apiPath + '/import/otrs/import_start', processData: true, success: (data, status, xhr) => - - # validate form if data.result is 'ok' - @delay( @updateMigration, 3000 ) + @delay(@updateMigration, 3000) ) @@ -127,17 +119,24 @@ class Index extends App.ControllerContent @navigate '#' return - for key, item of data.data - element = @$('.js-' + key.toLowerCase() ) - element.find('.js-done').text(item.done) - element.find('.js-total').text(item.total) - element.find('progress').attr('max', item.total ) - element.find('progress').attr('value', item.done ) - if item.total <= item.done - element.addClass('is-done') - else - element.removeClass('is-done') - @delay( @updateMigration, 5000 ) + if data.result is 'error' + @$('.js-error').removeClass('hide') + @$('.js-error').html(App.i18n.translateContent(data.message)) + else + @$('.js-error').addClass('hide') + + if data.result is 'in_progress' + for key, item of data.data + element = @$('.js-' + key.toLowerCase() ) + element.find('.js-done').text(item.done) + element.find('.js-total').text(item.total) + element.find('progress').attr('max', item.total ) + element.find('progress').attr('value', item.done ) + if item.total <= item.done + element.addClass('is-done') + else + element.removeClass('is-done') + @delay(@updateMigration, 6500) ) App.Config.set( 'import/otrs', Index, 'Routes' ) diff --git a/app/assets/javascripts/app/views/import/otrs.jst.eco b/app/assets/javascripts/app/views/import/otrs.jst.eco index 97def7444..caa7222c7 100644 --- a/app/assets/javascripts/app/views/import/otrs.jst.eco +++ b/app/assets/javascripts/app/views/import/otrs.jst.eco @@ -41,6 +41,8 @@

<%- @T('OTRS Migration') %>

+ +
diff --git a/app/controllers/import_otrs_controller.rb b/app/controllers/import_otrs_controller.rb index 24a174659..b92625a8d 100644 --- a/app/controllers/import_otrs_controller.rb +++ b/app/controllers/import_otrs_controller.rb @@ -80,7 +80,6 @@ class ImportOtrsController < ApplicationController def import_start return if setup_done_response - Setting.set('import_mode', true) welcome = Import::OTRS.connection_test if !welcome @@ -92,7 +91,10 @@ class ImportOtrsController < ApplicationController end # start migration - Import::OTRS.delay.start + Import::OTRS.delay.start_bg( + import_otrs_endpoint: Setting.get('import_otrs_endpoint'), + import_otrs_endpoint_key: Setting.get('import_otrs_endpoint_key'), + ) render json: { result: 'ok', @@ -100,18 +102,11 @@ class ImportOtrsController < ApplicationController end def import_status - if !Setting.get('import_mode') - render json: { - setup_done: true, - } - return + result = Import::OTRS.status_bg + if result[:setup_done] == true + Setting.reload end - - state = Import::OTRS.current_state - render json: { - data: state, - result: 'in_progress', - } + render json: result end private diff --git a/app/models/setting.rb b/app/models/setting.rb index abd47367c..495ba1713 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -77,13 +77,25 @@ reset config setting to default @@current[:settings_config][name] end +=begin + +reload config settings + + Setting.reload + +=end + + def self.reload + load(true) + end + private # load values and cache them - def self.load + def self.load(force = false) # check if config is already generated - if @@current[:settings_config] + if !force && @@current[:settings_config] return false if cache_valid? end diff --git a/lib/import/otrs.rb b/lib/import/otrs.rb index 0ec12c2ba..50b084d26 100644 --- a/lib/import/otrs.rb +++ b/lib/import/otrs.rb @@ -214,7 +214,7 @@ module Import::OTRS =begin - get object statistic from server ans save it in cache + get object statistic from remote server ans save it in cache result = statistic('Subaction=List') @@ -409,15 +409,80 @@ module Import::OTRS threads[thread].join } + true + end + +=begin + start import in background + + Import::OTRS.start_bg( + import_otrs_endpoint: 'http://vz599.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator +', + import_otrs_endpoint_key: '01234567899876543210', + ) +=end + + def self.start_bg(params) + Setting.set('import_mode', 'true') + Setting.set('import_backend', 'otrs') + Setting.set('import_otrs_endpoint', params[:import_otrs_endpoint]) + Setting.set('import_otrs_endpoint_key', params[:import_otrs_endpoint_key]) + + 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 5 + + begin + import_thread = Thread.new { + Import::OTRS.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) + end + import_thread.join + status_update_thread.exit + status_update_thread.join + Setting.set('system_init_done', true) Setting.set('import_mode', false) + end - # broadcast import finish - Sessions.broadcast( - event: 'import:finished', - ) +=begin - true + get import state from background process + + result = Import::OTRS.status_bg + +=end + + def self.status_bg + if !Setting.get('import_mode') + return { + setup_done: true, + } + end + state = Cache.get('import:state') + return state if state + { + message: 'not running', + } end def self.diff_worker From 388fcc65271ced879bbace02350644e495d02ea6 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 13 Jan 2016 22:21:34 +0100 Subject: [PATCH 7/7] Improved import workflow. --- .../app/controllers/import_otrs.coffee | 5 ++- app/controllers/import_otrs_controller.rb | 7 ++--- lib/import/otrs.rb | 31 +++++++++---------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/app/controllers/import_otrs.coffee b/app/assets/javascripts/app/controllers/import_otrs.coffee index da6e8f92c..01097e8dd 100644 --- a/app/assets/javascripts/app/controllers/import_otrs.coffee +++ b/app/assets/javascripts/app/controllers/import_otrs.coffee @@ -114,9 +114,8 @@ class Index extends App.ControllerContent processData: true, success: (data, status, xhr) => - if data.setup_done - @Config.set('system_init_done', true) - @navigate '#' + if data.result is 'import_done' + window.location.reload() return if data.result is 'error' diff --git a/app/controllers/import_otrs_controller.rb b/app/controllers/import_otrs_controller.rb index b92625a8d..42f4434f3 100644 --- a/app/controllers/import_otrs_controller.rb +++ b/app/controllers/import_otrs_controller.rb @@ -91,10 +91,7 @@ class ImportOtrsController < ApplicationController end # start migration - Import::OTRS.delay.start_bg( - import_otrs_endpoint: Setting.get('import_otrs_endpoint'), - import_otrs_endpoint_key: Setting.get('import_otrs_endpoint_key'), - ) + Import::OTRS.delay.start_bg render json: { result: 'ok', @@ -103,7 +100,7 @@ class ImportOtrsController < ApplicationController def import_status result = Import::OTRS.status_bg - if result[:setup_done] == true + if result[:result] == 'import_done' Setting.reload end render json: result diff --git a/lib/import/otrs.rb b/lib/import/otrs.rb index 50b084d26..b3e33d754 100644 --- a/lib/import/otrs.rb +++ b/lib/import/otrs.rb @@ -415,19 +415,15 @@ module Import::OTRS =begin start import in background - Import::OTRS.start_bg( - import_otrs_endpoint: 'http://vz599.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator -', - import_otrs_endpoint_key: '01234567899876543210', - ) + Import::OTRS.start_bg =end - def self.start_bg(params) - Setting.set('import_mode', 'true') - Setting.set('import_backend', 'otrs') - Setting.set('import_otrs_endpoint', params[:import_otrs_endpoint]) - Setting.set('import_otrs_endpoint_key', params[:import_otrs_endpoint_key]) + def self.start_bg + Setting.reload + Import::OTRS.connection_test + + # start thread to observe current state status_update_thread = Thread.new { loop do result = { @@ -438,9 +434,9 @@ module Import::OTRS sleep 8 end } + sleep 2 - sleep 5 - + # start thread to import data begin import_thread = Thread.new { Import::OTRS.start @@ -455,11 +451,17 @@ module Import::OTRS 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 @@ -473,11 +475,6 @@ module Import::OTRS =end def self.status_bg - if !Setting.get('import_mode') - return { - setup_done: true, - } - end state = Cache.get('import:state') return state if state {