diff --git a/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee index 9ec2ac570..0d9994a11 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee @@ -7,7 +7,7 @@ class App.DashboardActivityStream extends App.Controller constructor: -> super @items = [] - + # refresh list ever 140 sec. # @interval( @fetch, 1400000, 'dashboard_activity_stream' ) @fetch() @@ -16,11 +16,12 @@ class App.DashboardActivityStream extends App.Controller @fetch() fetch: => - + # use cache of first page - if window.LastRefresh[ 'activity_stream' ] - @load( window.LastRefresh[ 'activity_stream' ] ) - + cache = App.Store.get( 'activity_stream' ) + if cache + @load( cache ) + # # get data # App.Com.ajax( # id: 'dashoard_activity_stream', @@ -45,9 +46,6 @@ class App.DashboardActivityStream extends App.Controller # load article collection @loadCollection( type: 'TicketArticle', data: data.articles ) - # set cache - window.LastRefresh[ 'dashboard_activity_stream' ] = items - @render(items) render: (items) -> diff --git a/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee index 111cdaf07..ae54f94c8 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee @@ -9,8 +9,9 @@ class App.DashboardRss extends App.Controller @load(data) # use cache of first page - if window.LastRefresh[ 'dashboard_rss' ] - @load( window.LastRefresh[ 'dashboard_rss' ] ) + cache = App.Store.get( 'dashboard_rss' ) + if cache + @load( cache ) load: (data) => items = data.items || [] diff --git a/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee index 190c09c4a..a77cfb214 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee @@ -13,31 +13,38 @@ class App.DashboardTicket extends App.Controller @start_page = 1 @navupdate '#' - # refresh list ever 40 sec. - @interval( @fetch, 400000, 'dashboard_ticket_overview_' + @view ) + # bind new events + Spine.bind 'ticket_overview_rebuild', (data) => + @log 'ticket_overview_rebuild', data + @fetch() + + # render + @fetch() fetch: => # set new key - @key = '#dashboard_ticket_overview_' + @view + @key = 'ticket_overview_' + @view # use cache of first page - if window.LastRefresh[ @key ] && @start_page is 1 - @render( window.LastRefresh[ @key ] ) + cache = App.Store.get( @key ) + if cache +# @render( cache ) + @load( cache ) # get data - App.Com.ajax( - id: 'dashboard_ticket_' + @key, - type: 'GET', - url: '/ticket_overviews', - data: { - view: @view, - view_mode: 'd', - start_page: @start_page, - } - processData: true, - success: @load - ) +# App.Com.ajax( +# id: 'dashboard_ticket_' + @key, +# type: 'GET', +# url: '/ticket_overviews', +# data: { +# view: @view, +# view_mode: 'd', +# start_page: @start_page, +# } +# processData: true, +# success: @load +# ) load: (data) => @@ -60,9 +67,7 @@ class App.DashboardTicket extends App.Controller # load ticket collection @loadCollection( type: 'Ticket', data: data.tickets ) - # set cache - if @start_page is 1 - window.LastRefresh[ @key ] = data + App.Store.write( @key, data ) @render( data ) @@ -82,12 +87,20 @@ class App.DashboardTicket extends App.Controller html.find('li').removeClass('active') html.find(".page [data-id=\"#{@start_page}\"]").parents('li').addClass('active') + @tickets_in_table = [] + start = ( @start_page-1 ) * 5 + end = ( @start_page ) * 5 + i = start + while i < end + i = i + 1 + if @tickets[ i - 1 ] + @tickets_in_table.push @tickets[ i - 1 ] shown_all_attributes = @ticketTableAttributes( App.Overview.find(@overview.id).view.d.overview ) table = @table( overview_extended: shown_all_attributes, model: App.Ticket, - objects: @tickets, + objects: @tickets_in_table, checkbox: false, ) diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee index de13f1925..3194e8a1b 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee @@ -29,13 +29,15 @@ class Index extends App.Controller fetch: (params) -> # use cache - if window.LastRefresh[ 'ticket_create_attributes' ] && !params.ticket_id && !params.article_id + cache = App.Store.get( 'ticket_create_attributes' ) + + if cache && !params.ticket_id && !params.article_id # get edit form attributes - @edit_form = window.LastRefresh[ 'ticket_create_attributes' ].edit_form + @edit_form = cache.edit_form # load user collection - @loadCollection( type: 'User', data: window.LastRefresh[ 'ticket_create_attributes' ].users ) + @loadCollection( type: 'User', data: cache.users ) @render() else @@ -51,7 +53,7 @@ class Index extends App.Controller success: (data, status, xhr) => # cache request - window.LastRefresh[ 'ticket_create_attributes' ] = data + App.Store.write( 'ticket_create_attributes', data ) # get edit form attributes @edit_form = data.edit_form diff --git a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee index fa592c37a..8b4d99d97 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee @@ -29,34 +29,40 @@ class Index extends App.Controller # set controller to active Config['ActiveController'] = '#ticket_overview_' + @view - # refresh list ever 40 sec. - @interval( @fetch, 400000, 'ticket_overview_' + @view ) + # bind new events + Spine.bind 'ticket_overview_rebuild', (data) => + @log 'ticket_overview_rebuild', data + @fetch() + + # render + @fetch() fetch: => # set new key - @key = '#ticket/view/' + @view + @key = 'ticket_overview_' + @view # use cache of first page - if window.LastRefresh[ @key ] && @start_page is 1 - @overview = window.LastRefresh[ @key ].overview - @tickets_count = window.LastRefresh[ @key ].tickets_count - @tickets = window.LastRefresh[ @key ].tickets - @render() + cache = App.Store.get( @key ) + if cache + @overview = cache.overview + @tickets_count = cache.tickets_count + @tickets = cache.tickets + @load(cache) # get data - App.Com.ajax( - id: 'ticket_overview_' + @start_page, - type: 'GET', - url: '/ticket_overviews', - data: { - view: @view, - view_mode: @view_mode, - start_page: @start_page, - } - processData: true, - success: @load - ) +# App.Com.ajax( +# id: 'ticket_overview_' + @start_page, +# type: 'GET', +# url: '/ticket_overviews', +# data: { +# view: @view, +# view_mode: @view_mode, +# start_page: @start_page, +# } +# processData: true, +# success: @load +# ) load: (data) => @@ -93,8 +99,7 @@ class Index extends App.Controller @bulk = data.bulk # set cache - if @start_page is 1 - window.LastRefresh[ @key ] = data +# App.Store.write( @key, data ) # render page @render() @@ -189,8 +194,8 @@ class Index extends App.Controller # alert('You have scrolled to an entry.') @start_page = @start_page + 1 @fetch() - - $('footer').waypoint( a, { offset: '150%', triggerOnce: true } ) + +# $('footer').waypoint( a, { offset: '150%', triggerOnce: true } ) page: (e) => e.preventDefault() @@ -282,7 +287,7 @@ class Index extends App.Controller e.preventDefault() id = $(e.target).parents('[data-id]').data('id') position = $(e.target).parents('[data-position]').data('position') - + # set last overview Config['LastOverview'] = @view Config['LastOverviewPosition'] = position @@ -444,9 +449,10 @@ class Router extends App.Controller @key = '#ticket/view/array/' + @view # get data - if window.LastRefresh[ @key ] - @tickets_count = window.LastRefresh[ @key ].tickets_count - @tickets = window.LastRefresh[ @key ].tickets + cache = App.Store.get( @key ) + if cache + @tickets_count = cache.tickets_count + @tickets = cache.tickets @redirect() else App.Com.ajax( @@ -463,9 +469,7 @@ class Router extends App.Controller load: (data) => @tickets = data.tickets @tickets_count = data.tickets_count - window.LastRefresh[ @key ] = {} - window.LastRefresh[ @key ]['tickets_count'] = @tickets_count - window.LastRefresh[ @key ]['tickets'] = @tickets + App.Store.write( data ) @redirect() redirect: => diff --git a/app/assets/javascripts/app/lib/store.js.coffee b/app/assets/javascripts/app/lib/store.js.coffee new file mode 100644 index 000000000..2d8e80b67 --- /dev/null +++ b/app/assets/javascripts/app/lib/store.js.coffee @@ -0,0 +1,42 @@ +class App.Store + _instance = undefined # Must be declared here to force the closure on the class + @write: (key, value) -> + if _instance == undefined + _instance ?= new _Singleton + _instance.write(key, value) + + @get: (args) -> + if _instance == undefined + _instance ?= new _Singleton + _instance.get(args) + + @delete: (args) -> + if _instance == undefined + _instance ?= new _Singleton + _instance.delete(args) + + @list: () -> + if _instance == undefined + _instance ?= new _Singleton + _instance.list() + +# The actual Singleton class +class _Singleton + store: {} + + constructor: (@args) -> + + write: (key, value) -> + @store[ key ] = value + + get: (key) -> + @store[ key ] + + delete: (key) -> + delete @store[ key ] + + list: () -> + list = [] + for key of @store + list.push key + list \ No newline at end of file diff --git a/app/assets/javascripts/app/lib/websocket.js.coffee b/app/assets/javascripts/app/lib/websocket.js.coffee index 41b8dbe87..82227882f 100644 --- a/app/assets/javascripts/app/lib/websocket.js.coffee +++ b/app/assets/javascripts/app/lib/websocket.js.coffee @@ -86,7 +86,7 @@ class _Singleton extends Spine.Controller # fill collection if item['collection'] console.log( "ws:onmessage collection:" + item['collection'] ) - window.LastRefresh[ item['collection'] ] = item['data'] + App.Store.write( item['collection'], item['data'] ) # fire event if item['event'] diff --git a/app/assets/javascripts/init.js b/app/assets/javascripts/init.js index 5c7f95d3d..77042730e 100644 --- a/app/assets/javascripts/init.js +++ b/app/assets/javascripts/init.js @@ -5,5 +5,4 @@ Config.NavBarRight = {}; Config.product_name = 'Zammad' Config.requested_url = '' var Store = {}; -var Session = {}; -var LastRefresh = {}; +var Session = {}; \ No newline at end of file diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 5cde892be..823252143 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -127,6 +127,14 @@ class Ticket < ApplicationModel return subject end + +# Ticket.overview_list( +# :current_user_id => 123, +# ) + def self.overview_list (data) + Overview.all + end + # Ticket.overview( # :view => 'some_view_url', # :current_user_id => 123, @@ -343,159 +351,4 @@ class Ticket < ApplicationModel after_update :cache_delete after_destroy :cache_delete end - - class Article < ApplicationModel - before_create :fillup - after_create :attachment_check, :communicate - belongs_to :ticket - belongs_to :ticket_article_type, :class_name => 'Ticket::Article::Type' - belongs_to :ticket_article_sender, :class_name => 'Ticket::Article::Sender' - belongs_to :created_by, :class_name => 'User' - - after_create :cache_delete - after_update :cache_delete - after_destroy :cache_delete - - private - def fillup - - # if sender is customer, do not change anything - sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first - return if sender == nil || sender['name'] == 'Customer' - - type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first - ticket = Ticket.find(self.ticket_id) - - # set from if not given - if !self.from - user = User.find(self.created_by_id) - self.from = "#{user.firstname} #{user.lastname}" - end - - # set email attributes - if type['name'] == 'email' - - # set subject if empty - if !self.subject || self.subject == '' - self.subject = ticket.title - end - - # clean subject - self.subject = ticket.subject_clean(self.subject) - - # generate message id - fqdn = Setting.get('fqdn') - self.message_id = '<' + DateTime.current.to_s(:number) + '.' + self.ticket_id.to_s + '.' + rand(999999).to_s() + '@' + fqdn + '>' - - # set sender - if Setting.get('ticket_define_email_from') == 'AgentNameSystemAddressName' - seperator = Setting.get('ticket_define_email_from_seperator') - sender = User.find(self.created_by_id) - system_sender = Setting.get('system_sender') - self.from = "#{sender.firstname} #{sender.lastname} #{seperator} #{system_sender}" - else - self.from = Setting.get('system_sender') - end - end - end - def attachment_check - - # do nothing if no attachment exists - return 1 if self['attachments'] == nil - - # store attachments - article_store = [] - self.attachments.each do |attachment| - article_store.push Store.add( - :object => 'Ticket::Article', - :o_id => self.id, - :data => attachment.store_file.data, - :filename => attachment.filename, - :preferences => attachment.preferences - ) - end - self.attachments = article_store - end - - def communicate - - # if sender is customer, do not communication - sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first - return 1 if sender == nil || sender['name'] == 'Customer' - - type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first - ticket = Ticket.find(self.ticket_id) - - # if sender is agent or system - - # create tweet - if type['name'] == 'twitter direct-message' || type['name'] == 'twitter status' - a = Channel::Twitter2.new - message = a.send( - { - :type => type['name'], - :to => self.to, - :body => self.body, - :in_reply_to => self.in_reply_to - }, - Rails.application.config.channel_twitter - ) - self.message_id = message.id - self.save - end - - # post facebook comment - if type['name'] == 'facebook' - a = Channel::Facebook.new - a.send( - { - :from => 'me@znuny.com', - :to => 'medenhofer', - :body => self.body - } - ) - end - - # send email - if type['name'] == 'email' - - # build subject - subject = ticket.subject_build(self.subject) - - # send email - a = Channel::IMAP.new - message = a.send( - { - :message_id => self.message_id, - :in_reply_to => self.in_reply_to, - :from => self.from, - :to => self.to, - :cc => self.cc, - :subject => subject, - :body => self.body, - :attachments => self.attachments - } - ) - - # store mail plain - Store.add( - :object => 'Ticket::Article::Mail', - :o_id => self.id, - :data => message.to_s, - :filename => "ticket-#{ticket.number}-#{self.id}.eml", - :preferences => {} - ) - end - end - - class Flag < ApplicationModel - end - - class Sender < ApplicationModel - end - - class Type < ApplicationModel - end - end - end \ No newline at end of file diff --git a/app/models/ticket/article.rb b/app/models/ticket/article.rb new file mode 100644 index 000000000..ae83bb6e3 --- /dev/null +++ b/app/models/ticket/article.rb @@ -0,0 +1,153 @@ +class Ticket::Article < ApplicationModel + before_create :fillup + after_create :attachment_check, :communicate + belongs_to :ticket + belongs_to :ticket_article_type, :class_name => 'Ticket::Article::Type' + belongs_to :ticket_article_sender, :class_name => 'Ticket::Article::Sender' + belongs_to :created_by, :class_name => 'User' + + after_create :cache_delete + after_update :cache_delete + after_destroy :cache_delete + + private + def fillup + + # if sender is customer, do not change anything + sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first + return if sender == nil || sender['name'] == 'Customer' + + type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first + ticket = Ticket.find(self.ticket_id) + + # set from if not given + if !self.from + user = User.find(self.created_by_id) + self.from = "#{user.firstname} #{user.lastname}" + end + + # set email attributes + if type['name'] == 'email' + + # set subject if empty + if !self.subject || self.subject == '' + self.subject = ticket.title + end + + # clean subject + self.subject = ticket.subject_clean(self.subject) + + # generate message id + fqdn = Setting.get('fqdn') + self.message_id = '<' + DateTime.current.to_s(:number) + '.' + self.ticket_id.to_s + '.' + rand(999999).to_s() + '@' + fqdn + '>' + + # set sender + if Setting.get('ticket_define_email_from') == 'AgentNameSystemAddressName' + seperator = Setting.get('ticket_define_email_from_seperator') + sender = User.find(self.created_by_id) + system_sender = Setting.get('system_sender') + self.from = "#{sender.firstname} #{sender.lastname} #{seperator} #{system_sender}" + else + self.from = Setting.get('system_sender') + end + end + end + def attachment_check + + # do nothing if no attachment exists + return 1 if self['attachments'] == nil + + # store attachments + article_store = [] + self.attachments.each do |attachment| + article_store.push Store.add( + :object => 'Ticket::Article', + :o_id => self.id, + :data => attachment.store_file.data, + :filename => attachment.filename, + :preferences => attachment.preferences + ) + end + self.attachments = article_store + end + + def communicate + + # if sender is customer, do not communication + sender = Ticket::Article::Sender.where( :id => self.ticket_article_sender_id ).first + return 1 if sender == nil || sender['name'] == 'Customer' + + type = Ticket::Article::Type.where( :id => self.ticket_article_type_id ).first + ticket = Ticket.find(self.ticket_id) + + # if sender is agent or system + + # create tweet + if type['name'] == 'twitter direct-message' || type['name'] == 'twitter status' + a = Channel::Twitter2.new + message = a.send( + { + :type => type['name'], + :to => self.to, + :body => self.body, + :in_reply_to => self.in_reply_to + }, + Rails.application.config.channel_twitter + ) + self.message_id = message.id + self.save + end + + # post facebook comment + if type['name'] == 'facebook' + a = Channel::Facebook.new + a.send( + { + :from => 'me@znuny.com', + :to => 'medenhofer', + :body => self.body + } + ) + end + + # send email + if type['name'] == 'email' + + # build subject + subject = ticket.subject_build(self.subject) + + # send email + a = Channel::IMAP.new + message = a.send( + { + :message_id => self.message_id, + :in_reply_to => self.in_reply_to, + :from => self.from, + :to => self.to, + :cc => self.cc, + :subject => subject, + :body => self.body, + :attachments => self.attachments + } + ) + + # store mail plain + Store.add( + :object => 'Ticket::Article::Mail', + :o_id => self.id, + :data => message.to_s, + :filename => "ticket-#{ticket.number}-#{self.id}.eml", + :preferences => {} + ) + end + end + + class Flag < ApplicationModel + end + + class Sender < ApplicationModel + end + + class Type < ApplicationModel + end +end diff --git a/lib/web_socket.rb b/lib/web_socket.rb index cafed55c0..d5b3038c8 100644 --- a/lib/web_socket.rb +++ b/lib/web_socket.rb @@ -81,7 +81,52 @@ module Session end # ticket overview lists -# list = Ticket.overview_list() + overviews = Ticket.overview_list( + :current_user_id => user.id, + ) + if !state_client_ids[client_id][:overview_data] + state_client_ids[client_id][:overview_data] = {} + end + overviews.each { |overview| + overview_data = Ticket.overview( + :view => overview.meta[:url], +# :view_mode => params[:view_mode], + :current_user_id => user.id, + :array => true, + ) + + if state_client_ids[client_id][:overview_data][ overview.meta[:url] ] != overview_data + state_client_ids[client_id][:overview_data][ overview.meta[:url] ] = overview_data +puts 'push overview ' + overview.meta[:url].to_s + users = {} + tickets = [] + overview_data[:tickets].each {|ticket| + data = Ticket.full_data(ticket.id) + tickets.push data + if !users[ data['owner_id'] ] + users[ data['owner_id'] ] = User.user_data_full( data['owner_id'] ) + end + if !users[ data['customer_id'] ] + users[ data['customer_id'] ] = User.user_data_full( data['customer_id'] ) + end + if !users[ data['created_by_id'] ] + users[ data['created_by_id'] ] = User.user_data_full( data['created_by_id'] ) + end + } + + # send update to browser + Session.transaction( client_id, { + :data => { + :overview => overview_data[:overview], + :tickets => tickets, + :tickets_count => overview_data[:tickets_count], + :users => users, + }, + :event => 'ticket_overview_rebuild', + :collection => 'ticket_overview_' + overview.meta[:url].to_s, + }) + end + } # recent viewed recent_viewed = History.recent_viewed(user) @@ -111,6 +156,7 @@ module Session :collection => 'activity_stream', :data => activity_stream, }) + end # ticket create ticket_create_attributes = Ticket.create_attributes( @@ -128,7 +174,7 @@ module Session # system settings - end + # rss view rss_items = RSS.fetch( 'http://www.heise.de/newsticker/heise-atom.xml', 8 )