Improved ticket update (take response and show changes without additional ajax request).

This commit is contained in:
Martin Edenhofer 2016-09-04 23:24:19 +02:00
parent d5c8fa3348
commit 71a2a26ea8
5 changed files with 137 additions and 91 deletions

View file

@ -44,35 +44,17 @@ class App.TicketZoom extends App.Controller
return if data.id.toString() isnt @ticket_id.toString() return if data.id.toString() isnt @ticket_id.toString()
# check if we already have the request queued # check if we already have the request queued
#@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCallRequested) #@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCall)
@fetchMayBe(data, true) @fetchMayBe(data)
) )
fetchStart: => fetchMayBe: (data) =>
if @fetchIsRunning if @ticketUpdatedAtLastCall
@fetchIsRunningAgain = true if new Date(data.updated_at).getTime() is new Date(@ticketUpdatedAtLastCall).getTime()
return false @log('debug', 'no fetch, current ticket already there or requested')
@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'
return return
if new Date(data.updated_at).getTime() < new Date(@ticketUpdatedAtLastCallRequested).getTime() if new Date(data.updated_at).getTime() < new Date(@ticketUpdatedAtLastCall).getTime()
@log 'debug', 'no fetch, current ticket already newser or requested' @log('debug', 'no fetch, current ticket already newser or requested')
return
@ticketUpdatedAtLastCallRequested = data.updated_at
if delay isnt true
@fetch()
return return
fetchDelayed = => fetchDelayed = =>
@ -81,7 +63,6 @@ class App.TicketZoom extends App.Controller
fetch: => fetch: =>
return if !@Session.get() return if !@Session.get()
return if !@fetchStart()
# get data # get data
@ajax( @ajax(
@ -90,22 +71,20 @@ class App.TicketZoom extends App.Controller
url: "#{@apiPath}/tickets/#{@ticket_id}?all=true" url: "#{@apiPath}/tickets/#{@ticket_id}?all=true"
processData: true processData: true
success: (data, status, xhr) => success: (data, status, xhr) =>
@fetchDone()
# check if ticket has changed # check if ticket has changed
newTicketRaw = data.assets.Ticket[@ticket_id] newTicketRaw = data.assets.Ticket[@ticket_id]
if @ticketUpdatedAtLastCallDone if @ticketUpdatedAtLastCall
# return if ticket hasnt changed # 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 # notify if ticket changed not by my self
if newTicketRaw.updated_by_id isnt @Session.get('id') if newTicketRaw.updated_by_id isnt @Session.get('id')
App.TaskManager.notify(@task_key) App.TaskManager.notify(@task_key)
# remember current data # remember current data
@ticketUpdatedAtLastCallRequested = newTicketRaw.updated_at @ticketUpdatedAtLastCall = newTicketRaw.updated_at
@ticketUpdatedAtLastCallDone = newTicketRaw.updated_at
@load(data) @load(data)
App.SessionStorage.set(@key, data) App.SessionStorage.set(@key, data)
@ -115,7 +94,6 @@ class App.TicketZoom extends App.Controller
@recentView('Ticket', @ticket_id) @recentView('Ticket', @ticket_id)
error: (xhr) => error: (xhr) =>
@fetchDone()
statusText = xhr.statusText statusText = xhr.statusText
status = xhr.status status = xhr.status
@ -127,7 +105,7 @@ class App.TicketZoom extends App.Controller
@renderDone = false @renderDone = false
# if ticket is already loaded, ignore status "0" - network issues e. g. temp. not connection # 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) console.log('network issues e. g. temp. not connection', status, statusText, detail)
return return
@ -174,6 +152,9 @@ class App.TicketZoom extends App.Controller
@ticket = App.Ticket.fullLocal(@ticket_id) @ticket = App.Ticket.fullLocal(@ticket_id)
@ticket.article = undefined @ticket.article = undefined
# remember current data
@ticketUpdatedAtLastCall = @ticket.updated_at
# render page # render page
@render() @render()
@ -714,28 +695,34 @@ class App.TicketZoom extends App.Controller
ticket.article = article ticket.article = article
# submit changes # submit changes
ui = @ @ajax(
ticket.save( id: "ticket_update_#{ticket.id}"
done: (r) -> 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 # reset article - should not be resubmited on next ticket update
ticket.article = undefined ticket.article = undefined
# reset form after save # reset form after save
ui.reset() @reset()
if taskAction is 'closeNextInOverview' if taskAction is 'closeNextInOverview'
if ui.overview_id if @overview_id
current_position = 0 current_position = 0
overview = App.Overview.find(ui.overview_id) overview = App.Overview.find(@overview_id)
list = App.OverviewListCollection.get(overview.link) list = App.OverviewListCollection.get(overview.link)
for ticket in list.tickets for ticket in list.tickets
current_position += 1 current_position += 1
if ticket.id is ui.ticket_id if ticket.id is @ticket_id
next = list.tickets[current_position] next = list.tickets[current_position]
if next if next
# close task # close task
App.TaskManager.remove(ui.task_key) App.TaskManager.remove(@task_key)
# open task via task manager to get overview information # open task via task manager to get overview information
App.TaskManager.execute( App.TaskManager.execute(
@ -743,34 +730,31 @@ class App.TicketZoom extends App.Controller
controller: 'TicketZoom' controller: 'TicketZoom'
params: params:
ticket_id: next.id ticket_id: next.id
overview_id: ui.overview_id overview_id: @overview_id
show: true show: true
) )
ui.navigate "ticket/zoom/#{next.id}" @navigate "ticket/zoom/#{next.id}"
return return
# fallback, close task # fallback, close task
taskAction = 'closeTab' taskAction = 'closeTab'
if taskAction is 'closeTab' if taskAction is 'closeTab'
App.TaskManager.remove(ui.task_key) App.TaskManager.remove(@task_key)
nextTaskUrl = App.TaskManager.nextTaskUrl() nextTaskUrl = App.TaskManager.nextTaskUrl()
if nextTaskUrl if nextTaskUrl
ui.navigate nextTaskUrl @navigate nextTaskUrl
return return
ui.navigate '#' @navigate '#'
return return
ui.autosaveStart() @autosaveStart()
ui.muteTask() @muteTask()
ui.fetchMayBe({ id: @id, updated_at: @updated_at }, true) @formEnable(e)
# enable form
ui.formEnable(e)
App.Event.trigger('overview:fetch') App.Event.trigger('overview:fetch')
fail: (settings, details) =>
error: (settings, details) =>
App.Event.trigger 'notify', { App.Event.trigger 'notify', {
type: 'error' type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update!') msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update!')

View file

@ -15,8 +15,8 @@ class ApplicationController < ActionController::Base
:model_index_render :model_index_render
skip_before_action :verify_authenticity_token skip_before_action :verify_authenticity_token
before_action :set_interface_handle, :set_user, :session_update, :user_device_check, :cors_preflight_check before_action :transaction_begin, :set_user, :session_update, :user_device_check, :cors_preflight_check
after_action :trigger_events, :http_log, :set_access_control_headers after_action :transaction_end, :http_log, :set_access_control_headers
rescue_from StandardError, with: :server_error rescue_from StandardError, with: :server_error
rescue_from ExecJS::RuntimeError, with: :server_error rescue_from ExecJS::RuntimeError, with: :server_error
@ -58,13 +58,15 @@ class ApplicationController < ActionController::Base
private private
def set_interface_handle def transaction_begin
ApplicationHandleInfo.current = 'application_server' ApplicationHandleInfo.current = 'application_server'
PushMessages.init
end end
# execute events def transaction_end
def trigger_events
Observer::Transaction.commit Observer::Transaction.commit
PushMessages.finish
ActiveSupport::Dependencies::Reference.clear!
end end
# Finds the User with the ID stored in the session with the key # Finds the User with the ID stored in the session with the key

View file

@ -161,12 +161,17 @@ class TicketsController < ApplicationController
end end
if params[:expand] if params[:expand]
result = ticket.attributes_with_relation_names result = ticket.reload.attributes_with_relation_names
render json: result, status: :created render json: result, status: :created
return return
end end
render json: ticket, status: :created if params[:all]
render json: ticket_all(ticket.reload)
return
end
render json: ticket.reload, status: :created
end end
# PUT /api/v1/tickets/1 # PUT /api/v1/tickets/1
@ -193,12 +198,17 @@ class TicketsController < ApplicationController
end end
if params[:expand] if params[:expand]
result = ticket.attributes_with_relation_names result = ticket.reload.attributes_with_relation_names
render json: result, status: :ok render json: result, status: :ok
return return
end end
render json: ticket, status: :ok if params[:all]
render json: ticket_all(ticket.reload)
return
end
render json: ticket.reload, status: :ok
end end
# DELETE /api/v1/tickets/1 # DELETE /api/v1/tickets/1

View file

@ -477,21 +477,34 @@ returns
end end
def cache_delete def cache_delete
keys = []
# delete by id caches # delete by id caches
key = "#{self.class}::#{id}" keys.push "#{self.class}::#{id}"
Cache.delete(key)
# delete by id with attributes_with_associations caches # delete by id with attributes_with_associations caches
key = "#{self.class}::aws::#{id}" 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) Cache.delete(key)
}
# delete old name / login caches # delete old name / login caches
if changed? if changed?
if changes.key?('name') if changes.key?('name')
name = changes['name'][0] name = changes['name'][0]
key = "#{self.class}::#{name}" key = "#{self.class}::#{name}"
Cache.delete(key.to_s) Cache.delete(key)
end end
if changes.key?('login') if changes.key?('login')
name = changes['login'][0] name = changes['login'][0]
@ -500,16 +513,6 @@ returns
end end
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 end
def self.cache_set(data_id, data) 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 logger.debug "#{self.class.name}.find(#{id}) notify created " + created_at.to_s
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
Sessions.broadcast( PushMessages.send(
message: {
event: class_name + ':create', event: class_name + ':create',
data: { id: id, updated_at: updated_at } data: { id: id, updated_at: updated_at }
},
type: 'authenticated',
) )
end end
@ -951,9 +957,12 @@ class OwnModel < ApplicationModel
logger.debug "#{self.class.name}.find(#{id}) notify UPDATED " + updated_at.to_s logger.debug "#{self.class.name}.find(#{id}) notify UPDATED " + updated_at.to_s
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
Sessions.broadcast( PushMessages.send(
message: {
event: class_name + ':update', event: class_name + ':update',
data: { id: id, updated_at: updated_at } data: { id: id, updated_at: updated_at }
},
type: 'authenticated',
) )
end end
@ -980,9 +989,12 @@ class OwnModel < ApplicationModel
logger.debug "#{self.class.name}.find(#{id}) notify TOUCH " + updated_at.to_s logger.debug "#{self.class.name}.find(#{id}) notify TOUCH " + updated_at.to_s
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
Sessions.broadcast( PushMessages.send(
message: {
event: class_name + ':touch', event: class_name + ':touch',
data: { id: id, updated_at: updated_at } data: { id: id, updated_at: updated_at }
},
type: 'authenticated',
) )
end end
@ -1008,9 +1020,12 @@ class OwnModel < ApplicationModel
logger.debug "#{self.class.name}.find(#{id}) notify DESTOY " + updated_at.to_s logger.debug "#{self.class.name}.find(#{id}) notify DESTOY " + updated_at.to_s
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
Sessions.broadcast( PushMessages.send(
message: {
event: class_name + ':destroy', event: class_name + ':destroy',
data: { id: id, updated_at: updated_at } data: { id: id, updated_at: updated_at }
},
type: 'authenticated',
) )
end end

35
lib/push_messages.rb Normal file
View file

@ -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