From 37d787fc4278d60eb357ef0b4972be916ca3264e Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 3 Feb 2016 10:54:52 +0100 Subject: [PATCH 01/19] Do not open/close widget on render result. --- .../javascripts/app/lib/base/jquery.textmodule.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/assets/javascripts/app/lib/base/jquery.textmodule.js b/app/assets/javascripts/app/lib/base/jquery.textmodule.js index 21ea38609..0165f988a 100644 --- a/app/assets/javascripts/app/lib/base/jquery.textmodule.js +++ b/app/assets/javascripts/app/lib/base/jquery.textmodule.js @@ -367,14 +367,6 @@ this.$widget.find('ul').html('') this.log('result', term, result) - if (!result[0]) { - result = [{id:'', name: '-'}] - } - - if (!this.active) { - this.open() - } - var elements = $() for (var i = 0; i < result.length; i++) { @@ -383,7 +375,7 @@ element.attr('data-id', item.id) element.text(App.Utils.htmlEscape(item.name)) element.addClass('u-clickable u-textTruncate') - if (i == result.length-1 && item.id != '') { + if (i == result.length-1) { element.addClass('is-active') } if (item.keywords) { From 0acedd39c261f52bac6754f25bfb18bc0af51bfe Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 3 Feb 2016 10:59:12 +0100 Subject: [PATCH 02/19] Code improvements. --- lib/import/zendesk.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/import/zendesk.rb b/lib/import/zendesk.rb index 8ebc8b3d4..f654037f7 100644 --- a/lib/import/zendesk.rb +++ b/lib/import/zendesk.rb @@ -148,7 +148,7 @@ module Import::Zendesk initialize_client # retrive statistic - statistic = { + result = { 'Tickets' => 0, 'TicketFields' => 0, 'UserFields' => 0, @@ -162,20 +162,20 @@ module Import::Zendesk 'Automations' => 0, } - statistic.each { |object, _score| + result.each { |object, _score| counter = 0 @client.send( object.underscore.to_sym ).all do |_resource| counter += 1 end - statistic[ object ] = counter + result[ object ] = counter } - if statistic - Cache.write('import_zendesk_stats', statistic) + if result + Cache.write('import_zendesk_stats', result) end - statistic + result end =begin @@ -763,7 +763,6 @@ module Import::Zendesk elsif zendesk_article.via.channel == 'twitter' local_article_fields[:message_id] = zendesk_article.id - # TODO local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'mention' article_type_twitter_status.id else @@ -776,7 +775,6 @@ module Import::Zendesk local_article_fields[:to] = zendesk_article.via.source.to.facebook_id local_article_fields[:message_id] = zendesk_article.id - # TODO local_article_fields[:type_id] = if zendesk_article.via.source.rel == 'post' article_type_facebook_feed_post.id else From 3202f8a51a11a19371a2a665b9e694716deca7e0 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 3 Feb 2016 11:02:07 +0100 Subject: [PATCH 03/19] Fixed bug: Results have to get compared in the browser since the backend runs in the test mode and the frontend in production. --- .../app/controllers/import_zendesk.coffee | 6 +++- .../zendesk_import_browser_test.rb | 33 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/app/controllers/import_zendesk.coffee b/app/assets/javascripts/app/controllers/import_zendesk.coffee index a94f5631c..e0f1519cc 100644 --- a/app/assets/javascripts/app/controllers/import_zendesk.coffee +++ b/app/assets/javascripts/app/controllers/import_zendesk.coffee @@ -151,7 +151,11 @@ class Index extends App.ControllerContent success: (data, status, xhr) => if data.result is 'import_done' - window.location.reload() + delay = 0 + if @Config.get('developer_mode') is true + delay = 5000 + + @delay(window.location.reload, delay) return if data.result is 'error' diff --git a/test/integration/zendesk_import_browser_test.rb b/test/integration/zendesk_import_browser_test.rb index f2e90468d..b40b378c7 100644 --- a/test/integration/zendesk_import_browser_test.rb +++ b/test/integration/zendesk_import_browser_test.rb @@ -79,17 +79,32 @@ class ZendeskImportBrowserTest < TestCase click(css: '.js-migration-start') watch_for( - css: 'body', - value: 'login', + css: '.js-group .js-done', + value: '2', + timeout: 60, + ) + + watch_for( + css: '.js-organization .js-done', + value: '1', + timeout: 60, + ) + + watch_for( + css: '.js-user .js-done', + value: '141', + timeout: 60, + ) + + watch_for( + css: '.js-ticket .js-done', + value: '143', timeout: 300, ) - assert_equal( 143, User.count, 'users' ) - assert_equal( 3, Group.count, 'groups' ) - assert_equal( 5, Role.count, 'roles' ) - assert_equal( 2, Organization.count, 'organizations' ) - assert_equal( 144, Ticket.count, 'tickets' ) - assert_equal( 151, Ticket::Article.count, 'ticket articles' ) - assert_equal( 2, Store.count, 'ticket article attachments' ) + watch_for( + css: 'body', + value: 'login', + ) end end From 22d9cebae34605f52806d67ce301f9082afd02e3 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 3 Feb 2016 11:23:26 +0100 Subject: [PATCH 04/19] Reworked to the functionality to import objects in the fetch loop instead of fetching all in the first place. Issue is caused by the Zendesk API or Gem. For more information see: https://github.com/zendesk/zendesk_api_client_rb/issues/290 . --- lib/import/zendesk.rb | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/lib/import/zendesk.rb b/lib/import/zendesk.rb index f654037f7..9f947a2ed 100644 --- a/lib/import/zendesk.rb +++ b/lib/import/zendesk.rb @@ -317,12 +317,7 @@ module Import::Zendesk local_fields = local_object.constantize.column_names - zendesk_object_fields = [] @client.send("#{local_object.downcase}_fields").all { |zendesk_object_field| - zendesk_object_fields.push(zendesk_object_field) - } - - zendesk_object_fields.each { |zendesk_object_field| if local_object == 'Ticket' mapped_object_field = method("mapping_#{local_object.downcase}_field").call( zendesk_object_field.type ) @@ -472,13 +467,7 @@ module Import::Zendesk def import_groups @zendesk_group_mapping = {} - zendesk_groups = [] @client.groups.all { |zendesk_group| - zendesk_groups.push(zendesk_group) - } - - zendesk_groups.each { |zendesk_group| - local_group = Group.create_if_not_exists( name: zendesk_group.name, active: !zendesk_group.deleted, @@ -526,12 +515,7 @@ module Import::Zendesk role_agent = Role.lookup(name: 'Agent') role_customer = Role.lookup(name: 'Customer') - zendesk_users = [] @client.users.all { |zendesk_user| - zendesk_users.push(zendesk_user) - } - - zendesk_users.each { |zendesk_user| local_user_fields = { login: zendesk_user.id.to_s, # Zendesk users may have no other identifier than the ID, e.g. twitter users @@ -602,12 +586,7 @@ module Import::Zendesk @zendesk_user_group_mapping = {} - zendesk_group_memberships = [] @client.group_memberships.all { |zendesk_group_membership| - zendesk_group_memberships.push(zendesk_group_membership) - } - - zendesk_group_memberships.each { |zendesk_group_membership| @zendesk_user_group_mapping[ zendesk_group_membership.user_id ] ||= [] @zendesk_user_group_mapping[ zendesk_group_membership.user_id ].push( zendesk_group_membership.group_id ) @@ -641,12 +620,7 @@ module Import::Zendesk article_type_facebook_feed_post = Ticket::Article::Type.lookup(name: 'facebook feed post') article_type_facebook_feed_comment = Ticket::Article::Type.lookup(name: 'facebook feed comment') - zendesk_tickets = [] @client.tickets.all { |zendesk_ticket| - zendesk_tickets.push(zendesk_ticket) - } - - zendesk_tickets.each { |zendesk_ticket| zendesk_ticket_fields = {} zendesk_ticket.custom_fields.each { |zendesk_ticket_field| @@ -840,12 +814,7 @@ module Import::Zendesk # https://developer.zendesk.com/rest_api/docs/core/macros def import_macros - zendesk_macros = [] @client.macros.all { |zendesk_macro| - zendesk_macros.push(zendesk_macro) - } - - zendesk_macros.each { |zendesk_macro| # TODO next if !zendesk_macro.active @@ -897,12 +866,7 @@ module Import::Zendesk # https://developer.zendesk.com/rest_api/docs/core/views def import_views - zendesk_views = [] @client.views.all { |zendesk_view| - zendesk_views.push(zendesk_view) - } - - zendesk_views.each { |zendesk_view| # "url" => "https://example.zendesk.com/api/v2/views/59511071.json" # "id" => 59511071 @@ -1031,12 +995,7 @@ module Import::Zendesk # https://developer.zendesk.com/rest_api/docs/core/automations def import_automations - zendesk_automations = [] @client.automations.all { |zendesk_automation| - zendesk_automations.push(zendesk_automation) - } - - zendesk_automations.each { |zendesk_automation| # "url" => "https://example.zendesk.com/api/v2/automations/60037892.json" # "id" => 60037892 From 89c24149a3b867f244c726c1421b5b930a7469ab Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 3 Feb 2016 12:50:30 +0100 Subject: [PATCH 05/19] Start clues on initial login for every agent. --- .../_dashboard/first_steps_clues.coffee | 32 ++++++------------- .../app/controllers/dashboard.coffee | 16 +++++++++- .../javascripts/app/lib/app_post/i18n.coffee | 6 ++++ .../first_steps_clues_content.jst.eco | 2 +- public/assets/tests/core.js | 24 ++++++++++++++ test/browser_test_helper.rb | 14 ++++++++ 6 files changed, 70 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee index db2f3cb78..970be7da8 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee @@ -1,18 +1,22 @@ class App.FirstStepsClues extends App.Controller clues: [ + { + container: '.js-dashboardMenuItem' + headline: 'Dashboard' + text: 'Here you see a quick overview about your and other agents performance.' + actions: [ + 'hover' + ] + } { container: '.search-holder' headline: 'Search' - text: 'Here you can search for ticket, customers and organizations. To find everything use the *-Placeholder' - #headline: 'Suche' - #text: 'Um alles zu finden nutze den *-Platzhalter' + text: 'Here you can search for ticket, customers and organizations. To find everything use the §*§-Placeholder' } { container: '.user-menu' headline: 'Create' text: 'Here you can create new tickets. Also if you have the permissions you can create new customers and organizations.' - #headline: 'Erstellen' - #text: 'Hier kannst du Tickets, Kunden und Organisationen anlegen.' actions: [ 'click .add .js-action', 'hover .add' @@ -22,8 +26,6 @@ class App.FirstStepsClues extends App.Controller container: '.user-menu' headline: 'Personal Settings' text: 'Here you can sign out, change the frontend language or see your latest views items.' - #headline: 'Persönliches Menü' - #text: 'Hier findest du den Logout, den Weg zu deinen Einstellungen und deinen Verlauf.' actions: [ 'click .user .js-action', 'hover .user' @@ -33,18 +35,6 @@ class App.FirstStepsClues extends App.Controller container: '.js-overviewsMenuItem' headline: 'Overviews' text: 'Here you find your ticket overviews for open, my assigned or escalated tickets.' - #headline: 'Übersichten' - #text: 'Hier findest du eine Liste aller Tickets.' - actions: [ - 'hover' - ] - } - { - container: '.js-dashboardMenuItem' - headline: 'Dashboard' - text: 'Here you see a quick overview about your and other agents performance.' - #headline: 'Dashboard' - #text: 'Hier siehst du auf einem Blick ob sich alle Agenten an die Spielregeln halten.' actions: [ 'hover' ] @@ -78,8 +68,6 @@ class App.FirstStepsClues extends App.Controller onComplete: a callback for when the user is done ### - - @options.onComplete = -> null @position = 0 @render() @@ -235,7 +223,7 @@ class App.FirstStepsClues extends App.Controller left = maxWidth - modal.width if top < 0 - moveArrow = modal.height/2 + height + moveArrow = modal.height/2 + top top = 0 else if top + modal.height > maxHeight moveArrow = modal.height/2 + maxHeight - (top + modal.height) diff --git a/app/assets/javascripts/app/controllers/dashboard.coffee b/app/assets/javascripts/app/controllers/dashboard.coffee index 57e0e9e9f..aaa241397 100644 --- a/app/assets/javascripts/app/controllers/dashboard.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.coffee @@ -18,6 +18,11 @@ class App.Dashboard extends App.Controller return if !@authenticate(true) @render() + # start intro + preferences = @Session.get('preferences') + if !preferences['intro'] + @clues() + render: -> @html App.view('dashboard')( @@ -35,9 +40,18 @@ class App.Dashboard extends App.Controller ) clues: (e) => - e.preventDefault() + if e + e.preventDefault() new App.FirstStepsClues( el: @el + onComplete: => + @ajax( + id: 'preferences' + type: 'PUT' + url: @apiPath + '/users/preferences' + data: JSON.stringify({user:{intro:true}}) + processData: true + ) ) active: (state) => diff --git a/app/assets/javascripts/app/lib/app_post/i18n.coffee b/app/assets/javascripts/app/lib/app_post/i18n.coffee index f0b1ba8c7..6183be418 100644 --- a/app/assets/javascripts/app/lib/app_post/i18n.coffee +++ b/app/assets/javascripts/app/lib/app_post/i18n.coffee @@ -184,6 +184,12 @@ class _i18nSingleton extends Spine.Module translated = App.Utils.htmlEscape(@translate(string, args)) + # apply inline markup + translated + .replace(/\*(.+?)\*/gm, '$1') + .replace(/_(.+?)_/gm, '$1') + .replace(/§(.+?)§/gm, '$1') + translatePlain: (string, args) => @translate(string, args) diff --git a/app/assets/javascripts/app/views/dashboard/first_steps_clues_content.jst.eco b/app/assets/javascripts/app/views/dashboard/first_steps_clues_content.jst.eco index 3dd37d1d4..d05b95e31 100644 --- a/app/assets/javascripts/app/views/dashboard/first_steps_clues_content.jst.eco +++ b/app/assets/javascripts/app/views/dashboard/first_steps_clues_content.jst.eco @@ -4,7 +4,7 @@ <%- @Icon('diagonal-cross') %> - +