From a609b13825c968d76fa62e43bd26b46392ca34d4 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 17 Nov 2015 15:04:36 +0100 Subject: [PATCH 1/2] Refactoring, improved handling of from meta params on changes. --- .../_application_controller.coffee | 6 +- .../controllers/agent_ticket_create.coffee | 99 ++++++++----------- .../controllers/customer_ticket_create.coffee | 47 ++------- .../app/controllers/ticket_zoom.coffee | 8 +- .../controllers/ticket_zoom/sidebar.coffee | 2 +- .../local_storage.coffee | 0 .../session_storage.coffee | 0 .../app/lib/app_post/_collection_base.coffee | 69 +++++++++++++ .../app_post/overview_index_collection.coffee | 77 ++------------- .../app_post/ticket_create_collection.coffee | 24 +++++ app/controllers/tickets_controller.rb | 50 ++++------ app/models/ticket/screen_options.rb | 14 +-- config/routes/ticket.rb | 1 + lib/sessions/backend/ticket_create.rb | 12 +-- 14 files changed, 190 insertions(+), 219 deletions(-) rename app/assets/javascripts/app/lib/{app_post => app_init}/local_storage.coffee (100%) rename app/assets/javascripts/app/lib/{app_post => app_init}/session_storage.coffee (100%) create mode 100644 app/assets/javascripts/app/lib/app_post/_collection_base.coffee create mode 100644 app/assets/javascripts/app/lib/app_post/ticket_create_collection.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller.coffee b/app/assets/javascripts/app/controllers/_application_controller.coffee index e695c369e..baf264dee 100644 --- a/app/assets/javascripts/app/controllers/_application_controller.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller.coffee @@ -505,10 +505,10 @@ class App.Controller extends Spine.Controller # central method, is getting called on every ticket form change ticketFormChanges: (params, attribute, attributes, classname, form, ui) => - if @form_meta.dependencies && @form_meta.dependencies[attribute.name] - dependency = @form_meta.dependencies[attribute.name][ parseInt(params[attribute.name]) ] + if @formMeta.dependencies && @formMeta.dependencies[attribute.name] + dependency = @formMeta.dependencies[attribute.name][ parseInt(params[attribute.name]) ] if !dependency - dependency = @form_meta.dependencies[attribute.name][ params[attribute.name] ] + dependency = @formMeta.dependencies[attribute.name][ params[attribute.name] ] if dependency for fieldNameToChange of dependency filter = [] diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee index c4c681f4d..5a6dfe37a 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee @@ -12,12 +12,9 @@ class App.TicketCreate extends App.Controller # check authentication if !@authenticate() - App.TaskManager.remove( @task_key ) + App.TaskManager.remove(@task_key) return - # set title - @form_meta = undefined - # define default type @default_type = 'phone-in' @@ -29,8 +26,6 @@ class App.TicketCreate extends App.Controller # update navbar highlighting @navupdate '#ticket/create/id/' + @id + split - @fetch(params) - # lisen if view need to be rerendered @bind 'ticket_create_rerender', (defaults) => @log 'notice', 'error', defaults @@ -41,9 +36,11 @@ class App.TicketCreate extends App.Controller return if !@authenticate(true) @render() - # bind on new ticket_create_attributes updates - @bind 'ticket_create_attributes', (data) => - App.SessionStorage.set('ticket_create_attributes', data) + load = (data) => + App.Collection.loadAssets(data.assets) + @formMeta = data.form_meta + @buildScreen(params) + @bindId = App.TicketCreateCollection.one(load) changeFormType: (e) => type = $(e.target).data('type') @@ -121,9 +118,6 @@ class App.TicketCreate extends App.Controller return false if !diff || _.isEmpty( diff ) return true - release: -> - # nothing - autosave: => update = => data = @formParam( @el.find('.ticket-create') ) @@ -135,59 +129,44 @@ class App.TicketCreate extends App.Controller @interval( update, 3000, @id ) # get data / in case also ticket data for split - fetch: (params) -> - - # use cache - cache = App.SessionStorage.get('ticket_create_attributes') - - if cache && !params.ticket_id && !params.article_id - - # get edit form attributes - @form_meta = cache.form_meta - - # load assets - App.Collection.loadAssets(cache.assets) + buildScreen: (params) => + if !params.ticket_id && !params.article_id @render() - else - @ajax( - id: 'ticket_create' + @task_key - type: 'GET' - url: @apiPath + '/ticket_create' - data: - ticket_id: params.ticket_id - article_id: params.article_id - processData: true - success: (data, status, xhr) => + return - # cache request - App.SessionStorage.set('ticket_create_attributes', data) + # fetch split ticket data + @ajax( + id: 'ticket_split' + @task_key + type: 'GET' + url: @apiPath + '/ticket_split' + data: + ticket_id: params.ticket_id + article_id: params.article_id + processData: true + success: (data, status, xhr) => - # get edit form attributes - @form_meta = data.form_meta + # load assets + App.Collection.loadAssets(data.assets) - # load assets - App.Collection.loadAssets(data.assets) + # prefill with split ticket + t = App.Ticket.find( params.ticket_id ).attributes() + a = App.TicketArticle.find( params.article_id ) - # split ticket - if data.split && data.split.ticket_id && data.split.article_id - t = App.Ticket.find( params.ticket_id ).attributes() - a = App.TicketArticle.find( params.article_id ) + # reset owner + t.owner_id = 0 + t.customer_id_completion = a.from + t.subject = a.subject || t.title - # reset owner - t.owner_id = 0 - t.customer_id_completion = a.from - t.subject = a.subject || t.title + # convert non text/html from text 2 html + if a.content_type.match(/\/html/) + t.body = a.body + else + t.body = App.Utils.text2html( a.body ) - # convert non text/html from text 2 html - if a.content_type.match(/\/html/) - t.body = a.body - else - t.body = App.Utils.text2html( a.body ) - - # render page - @render( options: t ) - ) + # render page + @render( options: t ) + ) render: (template = {}) -> @@ -259,7 +238,7 @@ class App.TicketCreate extends App.Controller @ticketFormChanges, signatureChanges, ] - filter: @form_meta.filter + filter: @formMeta.filter autofocus: true params: params ) @@ -282,7 +261,7 @@ class App.TicketCreate extends App.Controller @ticketFormChanges, signatureChanges, ] - filter: @form_meta.filter + filter: @formMeta.filter params: params noFieldset: true ) @@ -297,7 +276,7 @@ class App.TicketCreate extends App.Controller @ticketFormChanges, signatureChanges, ] - filter: @form_meta.filter + filter: @formMeta.filter params: params ) diff --git a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee index 8b4eb820e..6243707cc 100644 --- a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee +++ b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee @@ -13,45 +13,14 @@ class Index extends App.ControllerContent # set title @title 'New Ticket' @form_id = App.ControllerForm.formId() - @form_meta = undefined - @fetch(params) @navupdate '#customer_ticket_new' - # get data / in case also ticket data for split - fetch: (params) -> - - # use cache - cache = App.SessionStorage.get( 'ticket_create_attributes' ) - - if cache - - # get edit form attributes - @form_meta = cache.form_meta - - # load assets - App.Collection.loadAssets( cache.assets ) - + load = (data) => + App.Collection.loadAssets(data.assets) + @formMeta = data.form_meta @render() - else - @ajax( - id: 'ticket_create', - type: 'GET', - url: @apiPath + '/ticket_create', - processData: true, - success: (data, status, xhr) => - - # cache request - App.SessionStorage.set( 'ticket_create_attributes', data ) - - # get edit form attributes - @form_meta = data.form_meta - - # load assets - App.Collection.loadAssets( data.assets ) - - @render() - ) + @bindId = App.TicketCreateCollection.one(load) render: (template = {}) -> @@ -62,7 +31,7 @@ class Index extends App.ControllerContent if groupFilter if !_.isArray(groupFilter) groupFilter = [groupFilter] - @form_meta.filter.group_id = groupFilter + @formMeta.filter.group_id = groupFilter @html App.view('customer_ticket_create')( head: 'New Ticket' @@ -77,7 +46,7 @@ class Index extends App.ControllerContent handlers: [ @ticketFormChanges ] - filter: @form_meta.filter + filter: @formMeta.filter autofocus: true params: defaults ) @@ -97,7 +66,7 @@ class Index extends App.ControllerContent handlers: [ @ticketFormChanges ] - filter: @form_meta.filter + filter: @formMeta.filter params: defaults noFieldset: true ) @@ -109,7 +78,7 @@ class Index extends App.ControllerContent # handlers: [ # formChanges # ] - # filter: @form_meta.filter + # filter: @formMeta.filter # params: defaults #) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index 0e8dda366..5d388b32e 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -17,7 +17,7 @@ class App.TicketZoom extends App.Controller App.TaskManager.remove(@task_key) return - @form_meta = undefined + @formMeta = undefined @ticket_id = params.ticket_id @article_id = params.article_id @sidebarState = {} @@ -235,7 +235,7 @@ class App.TicketZoom extends App.Controller @tags = data.tags # get edit form attributes - @form_meta = data.form_meta + @formMeta = data.form_meta # load assets App.Collection.loadAssets(data.assets) @@ -331,7 +331,7 @@ class App.TicketZoom extends App.Controller ticket: @ticket ticket_id: @ticket.id el: @$('.article-new') - form_meta: @form_meta + formMeta: @formMeta form_id: @form_id defaults: @taskGet('article') task_key: @task_key @@ -365,7 +365,7 @@ class App.TicketZoom extends App.Controller task_key: @task_key tags: @tags links: @links - form_meta: @form_meta + formMeta: @formMeta ) # show article diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee index 9395e5d75..4ea89f01b 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee @@ -33,7 +33,7 @@ class App.TicketZoomSidebar extends App.Controller handlers: [ @ticketFormChanges ] - filter: @form_meta.filter + filter: @formMeta.filter params: defaults #bookmarkable: true ) diff --git a/app/assets/javascripts/app/lib/app_post/local_storage.coffee b/app/assets/javascripts/app/lib/app_init/local_storage.coffee similarity index 100% rename from app/assets/javascripts/app/lib/app_post/local_storage.coffee rename to app/assets/javascripts/app/lib/app_init/local_storage.coffee diff --git a/app/assets/javascripts/app/lib/app_post/session_storage.coffee b/app/assets/javascripts/app/lib/app_init/session_storage.coffee similarity index 100% rename from app/assets/javascripts/app/lib/app_post/session_storage.coffee rename to app/assets/javascripts/app/lib/app_init/session_storage.coffee diff --git a/app/assets/javascripts/app/lib/app_post/_collection_base.coffee b/app/assets/javascripts/app/lib/app_post/_collection_base.coffee new file mode 100644 index 000000000..99cb98541 --- /dev/null +++ b/app/assets/javascripts/app/lib/app_post/_collection_base.coffee @@ -0,0 +1,69 @@ +class App._CollectionSingletonBase + event: 'to_be_defined' + restEndpoint: '/to_be_defined' + + constructor: -> + @callbacks = {} + @counter = 0 + + # read from cache + cache = App.SessionStorage.get("collection-#{@event}") + if cache + @set(cache) + + # websocket updates + App.Event.bind @event, (data) => + @set(data) + @callback(data) + + get: -> + @collection_data + + set: (data) -> + App.SessionStorage.set("collection-#{@event}", data) + @collection_data = data + + bind: (callback, init = true, one = false) -> + @counter += 1 + + # start init call if needed + if init + if @collection_data is undefined + @fetch() + else + callback(@collection_data) + return if one + + @callbacks[@counter] = + callback: callback + one: one + + unbind: (callback) -> + for counter, attr of @callbacks + if callback is attr.callback + delete @callbacks[counter] + + fetch: => + return if @fetchActive + @fetchActive = true + App.Ajax.request( + id: "collection-#{@event}" + type: 'GET' + url: App.Config.get('api_path') + @restEndpoint + processData: true + success: (data) => + @fetchActive = false + @set(data) + @callback(data) + error: => + @fetchActive = false + ) + + trigger: => + @callback(@get()) + + callback: (data) => + for counter, attr of @callbacks + attr.callback(data) + if attr.one + delete @callbacks[counter] diff --git a/app/assets/javascripts/app/lib/app_post/overview_index_collection.coffee b/app/assets/javascripts/app/lib/app_post/overview_index_collection.coffee index 196fdc996..d0664dd14 100644 --- a/app/assets/javascripts/app/lib/app_post/overview_index_collection.coffee +++ b/app/assets/javascripts/app/lib/app_post/overview_index_collection.coffee @@ -1,81 +1,24 @@ +class _Singleton extends App._CollectionSingletonBase + event: 'ticket_overview_index' + restEndpoint: '/ticket_overviews' + class App.OverviewIndexCollection - _instance = undefined # Must be declared here to force the closure on the class + _instance = new _Singleton @get: -> - if _instance == undefined - _instance ?= new _Singleton _instance.get() - @bind: (callback) -> - if _instance == undefined - _instance ?= new _Singleton - _instance.bind(callback) + @one: (callback, init = true) -> + _instance.bind(callback, init, true) + + @bind: (callback, init = true) -> + _instance.bind(callback, init, false) @unbind: (callback) -> - if _instance == undefined - _instance ?= new _Singleton _instance.unbind(callback) @trigger: -> - if _instance == undefined - _instance ?= new _Singleton _instance.trigger() @fetch: -> - if _instance == undefined - _instance ?= new _Singleton _instance.fetch() - -# The actual Singleton class -class _Singleton - constructor: -> - @callbacks = {} - @counter = 0 - - # websocket updates - App.Event.bind 'ticket_overview_index', (data) => - @overview_index = data - @callback(data) - - get: -> - @overview_index - - bind: (callback, init = true) -> - @counter += 1 - - # start init call if needed - if init - if @overview_index is undefined - @fetch() - else - @callback(@overview_index) - - @callbacks[@counter] = callback - - unbind: (callback) -> - for counter, localCallback of @callbacks - if callback is localCallback - delete @callbacks[counter] - - fetch: => - return if @fetchActive - @fetchActive = true - App.Ajax.request( - id: 'ticket_overviews', - type: 'GET', - url: App.Config.get('api_path') + '/ticket_overviews', - processData: true, - success: (data) => - @fetchActive = false - @overview_index = data - @callback(data) - error: => - @fetchActive = false - ) - - trigger: => - @callback(@get()) - - callback: (data) => - for counter, callback of @callbacks - callback(data) diff --git a/app/assets/javascripts/app/lib/app_post/ticket_create_collection.coffee b/app/assets/javascripts/app/lib/app_post/ticket_create_collection.coffee new file mode 100644 index 000000000..623b1290e --- /dev/null +++ b/app/assets/javascripts/app/lib/app_post/ticket_create_collection.coffee @@ -0,0 +1,24 @@ +class _Singleton extends App._CollectionSingletonBase + event: 'ticket_create_attributes' + restEndpoint: '/ticket_create' + +class App.TicketCreateCollection + _instance = new _Singleton + + @get: -> + _instance.get() + + @one: (callback, init = true) -> + _instance.bind(callback, init, true) + + @bind: (callback, init = true) -> + _instance.bind(callback, init, false) + + @unbind: (callback) -> + _instance.unbind(callback) + + @trigger: -> + _instance.trigger() + + @fetch: -> + _instance.fetch() diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 67d8a02d5..ae819aa2d 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -169,7 +169,7 @@ class TicketsController < ApplicationController def ticket_merge # check master ticket - ticket_master = Ticket.where( number: params[:master_ticket_number] ).first + ticket_master = Ticket.find_by(number: params[:master_ticket_number]) if !ticket_master render json: { result: 'faild', @@ -182,7 +182,7 @@ class TicketsController < ApplicationController return if !ticket_permission(ticket_master) # check slave ticket - ticket_slave = Ticket.where( id: params[:slave_ticket_id] ).first + ticket_slave = Ticket.find_by(id: params[:slave_ticket_id] ) if !ticket_slave render json: { result: 'faild', @@ -282,39 +282,31 @@ class TicketsController < ApplicationController } end - # GET /api/v1/ticket_create/1 + # GET /api/v1/ticket_split + def ticket_split + + # permission check + ticket = Ticket.find(params[:ticket_id]) + return if !ticket_permission(ticket) + assets = ticket.assets({}) + + # get related articles + article = Ticket::Article.find(params[:article_id]) + assets = article.assets(assets) + + render json: { + assets: assets + } + end + + # GET /api/v1/ticket_create def ticket_create # get attributes to update attributes_to_change = Ticket::ScreenOptions.attributes_to_change( user: current_user, - ticket_id: params[:ticket_id], - article_id: params[:article_id] ) - - assets = attributes_to_change[:assets] - # split data - split = {} - if params[:ticket_id] && params[:article_id] - ticket = Ticket.find( params[:ticket_id] ) - split[:ticket_id] = ticket.id - assets = ticket.assets(assets) - - # get related articles - article = Ticket::Article.find( params[:article_id] ) - split[:article_id] = article.id - assets = article.assets(assets) - end - - # return result - render json: { - split: split, - assets: assets, - form_meta: { - filter: attributes_to_change[:filter], - dependencies: attributes_to_change[:dependencies], - } - } + render json: attributes_to_change end # GET /api/v1/tickets/search diff --git a/app/models/ticket/screen_options.rb b/app/models/ticket/screen_options.rb index 0bc52e6a8..68ec807c3 100644 --- a/app/models/ticket/screen_options.rb +++ b/app/models/ticket/screen_options.rb @@ -27,10 +27,10 @@ returns def self.attributes_to_change(params) if params[:ticket_id] - params[:ticket] = Ticket.find( params[:ticket_id] ) + params[:ticket] = Ticket.find(params[:ticket_id]) end if params[:article_id] - params[:article] = Ticket::Article.find( params[:article_id] ) + params[:article] = Ticket::Article.find(params[:article_id]) end filter = {} @@ -46,7 +46,7 @@ returns state_ids.push params[:ticket].state.id end state_types.each {|type| - state_type = Ticket::StateType.find_by( name: type ) + state_type = Ticket::StateType.find_by(name: type) next if !state_type @@ -59,7 +59,7 @@ returns # get priorities priority_ids = [] - Ticket::Priority.where( active: true ).each { |priority| + Ticket::Priority.where(active: true).each { |priority| assets = priority.assets(assets) priority_ids.push priority.id } @@ -99,8 +99,10 @@ returns { assets: assets, - filter: filter, - dependencies: dependencies, + form_meta: { + filter: filter, + dependencies: dependencies, + } } end diff --git a/config/routes/ticket.rb b/config/routes/ticket.rb index 29ac05365..4e09d5725 100644 --- a/config/routes/ticket.rb +++ b/config/routes/ticket.rb @@ -9,6 +9,7 @@ Zammad::Application.routes.draw do match api_path + '/tickets', to: 'tickets#create', via: :post match api_path + '/tickets/:id', to: 'tickets#update', via: :put match api_path + '/ticket_create', to: 'tickets#ticket_create', via: :get + match api_path + '/ticket_split', to: 'tickets#ticket_split', via: :get match api_path + '/ticket_full/:id', to: 'tickets#ticket_full', via: :get match api_path + '/ticket_history/:id', to: 'tickets#ticket_history', via: :get match api_path + '/ticket_customer', to: 'tickets#ticket_customer', via: :get diff --git a/lib/sessions/backend/ticket_create.rb b/lib/sessions/backend/ticket_create.rb index 210675641..1c130eeb5 100644 --- a/lib/sessions/backend/ticket_create.rb +++ b/lib/sessions/backend/ticket_create.rb @@ -39,17 +39,9 @@ class Sessions::Backend::TicketCreate # set new timeout Sessions::CacheIn.set( client_key, true, { expires_in: @ttl.seconds } ) - ticket_create_attributes = load + data = load - return if !ticket_create_attributes - - data = { - assets: ticket_create_attributes[:assets], - form_meta: { - filter: ticket_create_attributes[:filter], - dependencies: ticket_create_attributes[:dependencies], - } - } + return if !data if !@client return { From 8f2eb904aee15b005d162af786c9b2f5f3def8de Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 17 Nov 2015 15:28:00 +0100 Subject: [PATCH 2/2] Improved scroll_to behaviour. --- test/browser_test_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/browser_test_helper.rb b/test/browser_test_helper.rb index b24511eb0..cd57feeb7 100644 --- a/test/browser_test_helper.rb +++ b/test/browser_test_helper.rb @@ -291,7 +291,7 @@ class TestCase < Test::Unit::TestCase execute( browser: instance, - js: "\$('#{params[:css]}').get(0).scrollIntoView(true)", + js: "\$('#{params[:css]}').get(0).scrollIntoView(false)", mute_log: params[:mute_log] ) sleep 0.4