From 71a2a26ea8932b38c1a04c657d4ececb39fd6873 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 4 Sep 2016 23:24:19 +0200 Subject: [PATCH] Improved ticket update (take response and show changes without additional ajax request). --- .../app/controllers/ticket_zoom.coffee | 94 ++++++++----------- app/controllers/application_controller.rb | 12 ++- app/controllers/tickets_controller.rb | 18 +++- app/models/application_model.rb | 69 ++++++++------ lib/push_messages.rb | 35 +++++++ 5 files changed, 137 insertions(+), 91 deletions(-) create mode 100644 lib/push_messages.rb diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index 75f462d62..617531723 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -44,44 +44,25 @@ class App.TicketZoom extends App.Controller return if data.id.toString() isnt @ticket_id.toString() # check if we already have the request queued - #@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCallRequested) - @fetchMayBe(data, true) + #@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCall) + @fetchMayBe(data) ) - fetchStart: => - if @fetchIsRunning - @fetchIsRunningAgain = true - return false - @fetchIsRunning = true - true - - fetchDone: => - @fetchIsRunning = false - if @fetchIsRunningAgain - @fetchIsRunningAgain = false - @fetch() - - fetchMayBe: (data, delay = true) => - if @ticketUpdatedAtLastCallRequested - if new Date(data.updated_at).getTime() is new Date(@ticketUpdatedAtLastCallRequested).getTime() - @log 'debug', 'no fetch, current ticket already there or requested' + fetchMayBe: (data) => + if @ticketUpdatedAtLastCall + if new Date(data.updated_at).getTime() is new Date(@ticketUpdatedAtLastCall).getTime() + @log('debug', 'no fetch, current ticket already there or requested') return - if new Date(data.updated_at).getTime() < new Date(@ticketUpdatedAtLastCallRequested).getTime() - @log 'debug', 'no fetch, current ticket already newser or requested' + if new Date(data.updated_at).getTime() < new Date(@ticketUpdatedAtLastCall).getTime() + @log('debug', 'no fetch, current ticket already newser or requested') return - @ticketUpdatedAtLastCallRequested = data.updated_at - if delay isnt true - @fetch() - return - fetchDelayed = => @fetch() @delay(fetchDelayed, 1200, "ticket-zoom-#{@ticket_id}") fetch: => return if !@Session.get() - return if !@fetchStart() # get data @ajax( @@ -90,22 +71,20 @@ class App.TicketZoom extends App.Controller url: "#{@apiPath}/tickets/#{@ticket_id}?all=true" processData: true success: (data, status, xhr) => - @fetchDone() # check if ticket has changed newTicketRaw = data.assets.Ticket[@ticket_id] - if @ticketUpdatedAtLastCallDone + if @ticketUpdatedAtLastCall # return if ticket hasnt changed - return if @ticketUpdatedAtLastCallDone is newTicketRaw.updated_at + return if @ticketUpdatedAtLastCall is newTicketRaw.updated_at # notify if ticket changed not by my self if newTicketRaw.updated_by_id isnt @Session.get('id') App.TaskManager.notify(@task_key) # remember current data - @ticketUpdatedAtLastCallRequested = newTicketRaw.updated_at - @ticketUpdatedAtLastCallDone = newTicketRaw.updated_at + @ticketUpdatedAtLastCall = newTicketRaw.updated_at @load(data) App.SessionStorage.set(@key, data) @@ -115,7 +94,6 @@ class App.TicketZoom extends App.Controller @recentView('Ticket', @ticket_id) error: (xhr) => - @fetchDone() statusText = xhr.statusText status = xhr.status @@ -127,7 +105,7 @@ class App.TicketZoom extends App.Controller @renderDone = false # if ticket is already loaded, ignore status "0" - network issues e. g. temp. not connection - if @ticketUpdatedAtLastCallRequested && status is 0 + if @ticketUpdatedAtLastCall && status is 0 console.log('network issues e. g. temp. not connection', status, statusText, detail) return @@ -174,6 +152,9 @@ class App.TicketZoom extends App.Controller @ticket = App.Ticket.fullLocal(@ticket_id) @ticket.article = undefined + # remember current data + @ticketUpdatedAtLastCall = @ticket.updated_at + # render page @render() @@ -714,28 +695,34 @@ class App.TicketZoom extends App.Controller ticket.article = article # submit changes - ui = @ - ticket.save( - done: (r) -> + @ajax( + id: "ticket_update_#{ticket.id}" + type: 'PUT' + url: "#{App.Ticket.url}/#{ticket.id}?all=true" + data: JSON.stringify(ticket.attributes()) + processData: true + success: (data) => + App.SessionStorage.set(@key, data) + @load(data) # reset article - should not be resubmited on next ticket update ticket.article = undefined # reset form after save - ui.reset() + @reset() if taskAction is 'closeNextInOverview' - if ui.overview_id + if @overview_id current_position = 0 - overview = App.Overview.find(ui.overview_id) + overview = App.Overview.find(@overview_id) list = App.OverviewListCollection.get(overview.link) for ticket in list.tickets current_position += 1 - if ticket.id is ui.ticket_id + if ticket.id is @ticket_id next = list.tickets[current_position] if next # close task - App.TaskManager.remove(ui.task_key) + App.TaskManager.remove(@task_key) # open task via task manager to get overview information App.TaskManager.execute( @@ -743,34 +730,31 @@ class App.TicketZoom extends App.Controller controller: 'TicketZoom' params: ticket_id: next.id - overview_id: ui.overview_id + overview_id: @overview_id show: true ) - ui.navigate "ticket/zoom/#{next.id}" + @navigate "ticket/zoom/#{next.id}" return # fallback, close task taskAction = 'closeTab' if taskAction is 'closeTab' - App.TaskManager.remove(ui.task_key) + App.TaskManager.remove(@task_key) nextTaskUrl = App.TaskManager.nextTaskUrl() if nextTaskUrl - ui.navigate nextTaskUrl + @navigate nextTaskUrl return - ui.navigate '#' + @navigate '#' return - ui.autosaveStart() - ui.muteTask() - ui.fetchMayBe({ id: @id, updated_at: @updated_at }, true) - - # enable form - ui.formEnable(e) - + @autosaveStart() + @muteTask() + @formEnable(e) App.Event.trigger('overview:fetch') - fail: (settings, details) => + + error: (settings, details) => App.Event.trigger 'notify', { type: 'error' msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update!') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8db91f5ea..bea253172 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,8 +15,8 @@ class ApplicationController < ActionController::Base :model_index_render skip_before_action :verify_authenticity_token - before_action :set_interface_handle, :set_user, :session_update, :user_device_check, :cors_preflight_check - after_action :trigger_events, :http_log, :set_access_control_headers + before_action :transaction_begin, :set_user, :session_update, :user_device_check, :cors_preflight_check + after_action :transaction_end, :http_log, :set_access_control_headers rescue_from StandardError, with: :server_error rescue_from ExecJS::RuntimeError, with: :server_error @@ -58,13 +58,15 @@ class ApplicationController < ActionController::Base private - def set_interface_handle + def transaction_begin ApplicationHandleInfo.current = 'application_server' + PushMessages.init end - # execute events - def trigger_events + def transaction_end Observer::Transaction.commit + PushMessages.finish + ActiveSupport::Dependencies::Reference.clear! end # Finds the User with the ID stored in the session with the key diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 4b8ac988c..cf37b24f8 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -161,12 +161,17 @@ class TicketsController < ApplicationController end if params[:expand] - result = ticket.attributes_with_relation_names + result = ticket.reload.attributes_with_relation_names render json: result, status: :created return end - render json: ticket, status: :created + if params[:all] + render json: ticket_all(ticket.reload) + return + end + + render json: ticket.reload, status: :created end # PUT /api/v1/tickets/1 @@ -193,12 +198,17 @@ class TicketsController < ApplicationController end if params[:expand] - result = ticket.attributes_with_relation_names + result = ticket.reload.attributes_with_relation_names render json: result, status: :ok return end - render json: ticket, status: :ok + if params[:all] + render json: ticket_all(ticket.reload) + return + end + + render json: ticket.reload, status: :ok end # DELETE /api/v1/tickets/1 diff --git a/app/models/application_model.rb b/app/models/application_model.rb index 8a39b67c3..bb29ff5d6 100644 --- a/app/models/application_model.rb +++ b/app/models/application_model.rb @@ -477,21 +477,34 @@ returns end def cache_delete + keys = [] # delete by id caches - key = "#{self.class}::#{id}" - Cache.delete(key) + keys.push "#{self.class}::#{id}" # delete by id with attributes_with_associations caches - key = "#{self.class}::aws::#{id}" - Cache.delete(key) + keys.push "#{self.class}::aws::#{id}" + + # delete by name caches + if self[:name] + keys.push "#{self.class}::#{name}" + end + + # delete by login caches + if self[:login] + keys.push "#{self.class}::#{login}" + end + + keys.each { |key| + Cache.delete(key) + } # delete old name / login caches if changed? if changes.key?('name') name = changes['name'][0] key = "#{self.class}::#{name}" - Cache.delete(key.to_s) + Cache.delete(key) end if changes.key?('login') name = changes['login'][0] @@ -500,16 +513,6 @@ returns end end - # delete by name caches - if self[:name] - key = "#{self.class}::#{self.name}" - Cache.delete(key) - end - - # delete by login caches - return if !self[:login] - - Cache.delete("#{self.class}::#{login}") end def self.cache_set(data_id, data) @@ -922,9 +925,12 @@ class OwnModel < ApplicationModel logger.debug "#{self.class.name}.find(#{id}) notify created " + created_at.to_s class_name = self.class.name class_name.gsub!(/::/, '') - Sessions.broadcast( - event: class_name + ':create', - data: { id: id, updated_at: updated_at } + PushMessages.send( + message: { + event: class_name + ':create', + data: { id: id, updated_at: updated_at } + }, + type: 'authenticated', ) end @@ -951,9 +957,12 @@ class OwnModel < ApplicationModel logger.debug "#{self.class.name}.find(#{id}) notify UPDATED " + updated_at.to_s class_name = self.class.name class_name.gsub!(/::/, '') - Sessions.broadcast( - event: class_name + ':update', - data: { id: id, updated_at: updated_at } + PushMessages.send( + message: { + event: class_name + ':update', + data: { id: id, updated_at: updated_at } + }, + type: 'authenticated', ) end @@ -980,9 +989,12 @@ class OwnModel < ApplicationModel logger.debug "#{self.class.name}.find(#{id}) notify TOUCH " + updated_at.to_s class_name = self.class.name class_name.gsub!(/::/, '') - Sessions.broadcast( - event: class_name + ':touch', - data: { id: id, updated_at: updated_at } + PushMessages.send( + message: { + event: class_name + ':touch', + data: { id: id, updated_at: updated_at } + }, + type: 'authenticated', ) end @@ -1008,9 +1020,12 @@ class OwnModel < ApplicationModel logger.debug "#{self.class.name}.find(#{id}) notify DESTOY " + updated_at.to_s class_name = self.class.name class_name.gsub!(/::/, '') - Sessions.broadcast( - event: class_name + ':destroy', - data: { id: id, updated_at: updated_at } + PushMessages.send( + message: { + event: class_name + ':destroy', + data: { id: id, updated_at: updated_at } + }, + type: 'authenticated', ) end diff --git a/lib/push_messages.rb b/lib/push_messages.rb new file mode 100644 index 000000000..74c9f4bda --- /dev/null +++ b/lib/push_messages.rb @@ -0,0 +1,35 @@ +module PushMessages + + def self.enabled? + return true if Thread.current[:push_messages].class == Array + false + end + + def self.init + Thread.current[:push_messages] = [] + end + + def self.send(data) + if !PushMessages.enabled? + Sessions.broadcast( + data[:message], + data[:type], + data[:current_user_id], + ) + return true + end + Thread.current[:push_messages].push data + end + + def self.finish + Thread.current[:push_messages].each { |data| + Sessions.broadcast( + data[:message], + data[:type], + data[:current_user_id], + ) + } + Thread.current[:push_messages] = nil + end + +end