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 4113b681e..1e91e4379 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee @@ -8,8 +8,6 @@ class App.DashboardActivityStream extends App.Controller super @items = [] - # refresh list ever 140 sec. -# @interval( @fetch, 1400000, 'dashboard_activity_stream' ) @fetch() # bind to rebuild view event @@ -22,17 +20,20 @@ class App.DashboardActivityStream extends App.Controller if cache @load( cache ) -# # get data -# App.Com.ajax( -# id: 'dashoard_activity_stream', -# type: 'GET', -# url: '/api/activity_stream', -# data: { -# limit: @limit, -# } -# processData: true, -# success: @load -# ) + # init fetch via ajax, all other updates on time via websockets + else + App.Com.ajax( + id: 'dashoard_activity_stream' + type: 'GET' + url: '/api/activity_stream' + data: { + limit: 8 + } + processData: true + success: (data) => + App.Store.write( 'activity_stream', data ) + @load(data) + ) load: (data) => items = data.activity_stream diff --git a/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee index d95af74bd..b3130f8dd 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/rss.js.coffee @@ -11,19 +11,42 @@ class App.DashboardRss extends App.Controller @fetch() fetch: => + + # get data from cache cache = App.Store.get( 'dashboard_rss' ) if cache - @load( cache ) + @render( cache ) - load: (data) => - items = data.items || [] - @head = data.head || '?' - @render(items) + # init fetch via ajax, all other updates on time via websockets + else + App.Com.ajax( + id: 'dashboard_rss' + type: 'GET' + url: '/api/rss_fetch' + data: { + limit: 8 + url: 'http://www.heise.de/newsticker/heise-atom.xml' + } + processData: true + success: (data) => + if data.message + @render( + head: 'Heise ATOM' + message: data.message + ) + else + App.Store.write( 'dashboard_rss', data ) + @render(data) + error: => + @render( + head: 'Heise ATOM' + message: 'Unable to fetch rss!' + ) + ) - render: (items) -> - html = App.view('dashboard/rss')( - head: @head, - items: items + render: (data) -> + @html App.view('dashboard/rss')( + head: data.head, + items: data.item || [] + message: data.message ) - html = $(html) - @html html diff --git a/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee index ce25164c2..9bb961166 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/ticket.js.coffee @@ -8,7 +8,7 @@ class App.DashboardTicket extends App.Controller constructor: -> super - @start_page = 1 + @start_page = 1 @navupdate '#' # set new key @@ -25,25 +25,37 @@ class App.DashboardTicket extends App.Controller # use cache of first page cache = App.Store.get( @key ) if cache -# @render( cache ) @load( cache ) - # get data -# App.Com.ajax( -# id: 'dashboard_ticket_' + @key, -# type: 'GET', -# url: '/api/ticket_overviews', -# data: { -# view: @view, -# view_mode: 'd', -# start_page: @start_page, -# } -# processData: true, -# success: @load -# ) + # init fetch via ajax, all other updates on time via websockets + else + App.Com.ajax( + id: 'dashboard_ticket_' + @key, + type: 'GET', + url: '/api/ticket_overviews', + data: { + view: @view, + view_mode: 'd', + start_page: @start_page, + } + processData: true, + success: (data) => + data.ajax = true + @load(data) + ) load: (data) => + if data.ajax + data.ajax = false + App.Store.write( @key, data ) + + # load user collection + App.Collection.load( type: 'User', data: data.collections.users ) + + # load ticket collection + App.Collection.load( type: 'Ticket', data: data.collections.tickets ) + # get meta data App.Overview.refresh( data.overview, options: { clear: true } ) @@ -57,11 +69,12 @@ class App.DashboardTicket extends App.Controller @log 'refetch...', record @fetch() -# App.Store.write( @key, data ) - @render( data ) render: (data) -> + return if !data + return if !data.ticket_list + return if !data.overview @overview = data.overview @tickets_count = data.tickets_count 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 3f1ad4bec..cc8f28b63 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee @@ -37,12 +37,42 @@ class Index extends App.Controller # use cache of first page cache = App.Store.get( @key ) if cache - @overview = cache.overview - @tickets_count = cache.tickets_count - @ticket_list = cache.ticket_list @load(cache) + # init fetch via ajax, all other updates on time via websockets + else + App.Com.ajax( + id: 'ticket_overview_' + @key, + type: 'GET', + url: '/api/ticket_overviews', + data: { + view: @view, + view_mode: @view_mode, + } + processData: true, + success: (data) => + data.ajax = true + @load(data) + ) + load: (data) => + return if !data + return if !data.ticket_list + return if !data.overview + + @overview = data.overview + @tickets_count = data.tickets_count + @ticket_list = data.ticket_list + + if data.ajax + data.ajax = false + App.Store.write( @key, data ) + + # load user collection + App.Collection.load( type: 'User', data: data.collections.users ) + + # load ticket collection + App.Collection.load( type: 'Ticket', data: data.collections.tickets ) # get meta data @overview = data.overview diff --git a/app/assets/javascripts/app/lib/app_post/ajax.js.coffee b/app/assets/javascripts/app/lib/app_post/ajax.js.coffee index df6efca59..5d33741d8 100644 --- a/app/assets/javascripts/app/lib/app_post/ajax.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/ajax.js.coffee @@ -5,9 +5,7 @@ class App.Com @ajax: (args) -> # Must be a static method if _instance == undefined _instance ?= new _Singleton - _instance.ajax(args) - _instance # The actual Singleton class class _Singleton diff --git a/app/assets/javascripts/app/lib/app_post/websocket.js.coffee b/app/assets/javascripts/app/lib/app_post/websocket.js.coffee index 013210b3f..65ed5428f 100644 --- a/app/assets/javascripts/app/lib/app_post/websocket.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/websocket.js.coffee @@ -9,7 +9,7 @@ class App.WebSocket @close: (args) -> # Must be a static method if _instance isnt undefined - _instance.close() + _instance.close(args) @send: (args) -> # Must be a static method @connect() @@ -20,6 +20,7 @@ class App.WebSocket _instance.auth(args) @_spool: -> + @connect() _instance.spool() # The actual Singleton class @@ -27,9 +28,12 @@ class _Singleton extends App.Controller @include App.Log queue: [] - supported: true - lastSpoolMessage: undefined - connectionEstablished: false + supported: true + lastSpoolMessage: undefined + connectionEstablished: false + connectionWasEstablished: false + backend: 'websocket' + client_id: undefined constructor: (@args) -> @@ -46,19 +50,22 @@ class _Singleton extends App.Controller @connect() send: (data) => - return if !@supported -# console.log 'ws:send trying', data, @ws, @ws.readyState - - # A value of 0 indicates that the connection has not yet been established. - # A value of 1 indicates that the connection is established and communication is possible. - # A value of 2 indicates that the connection is going through the closing handshake. - # A value of 3 indicates that the connection has been closed or could not be opened. - if @ws.readyState is 0 - @queue.push data + if @backend is 'ajax' + @_ajaxSend(data) else -# console.log( 'ws:send', data ) - string = JSON.stringify( data ) - @ws.send(string) + +# console.log 'ws:send trying', data, @ws, @ws.readyState + + # A value of 0 indicates that the connection has not yet been established. + # A value of 1 indicates that the connection is established and communication is possible. + # A value of 2 indicates that the connection is going through the closing handshake. + # A value of 3 indicates that the connection has been closed or could not be opened. + if @ws.readyState is 0 + @queue.push data + else +# console.log( 'ws:send', data ) + string = JSON.stringify( data ) + @ws.send(string) auth: (data) => return if !@supported @@ -77,7 +84,7 @@ class _Singleton extends App.Controller if @lastSpoolMessage data['timestamp'] = @lastSpoolMessage - @log 'Event', 'debug', 'spool', data + @log 'Websocket', 'debug', 'spool', data # ask for spool messages App.Event.trigger( @@ -89,37 +96,38 @@ class _Singleton extends App.Controller @lastSpoolMessage = Math.round( +new Date()/1000 ) close: => - return if !@supported + return if @backend is 'ajax' @ws.close() ping: => - return if !@supported + return if @backend is 'ajax' - @log 'Event', 'debug', 'send websockend ping' + @log 'Websocket', 'debug', 'send websockend ping' @send( { action: 'ping' } ) # check if ping is back within 2 min @clearDelay('websocket-ping-check') check = => - @log 'Event', 'notice', 'no websockend ping response, reconnect...' + @log 'Websocket', 'notice', 'no websockend ping response, reconnect...' @close() @delay check, 120000, 'websocket-ping-check' pong: -> - return if !@supported - @log 'Event', 'debug', 'received websockend ping' + return if @backend is 'ajax' + + @log 'Websocket', 'debug', 'received websockend ping' # test again after 1 min @delay @ping, 60000 connect: => + return if @backend is 'ajax' if !window.WebSocket - @error = new App.ErrorModal( - message: 'Sorry, no websocket support!' - ) - @supported = false + @backend = 'ajax' + @log 'WebSocket', 'notice', 'no support of websocket, use ajax long polling' + @_ajaxInit() return protocol = 'ws://' @@ -130,9 +138,10 @@ class _Singleton extends App.Controller # Set event handlers. @ws.onopen = => - @log 'Event', 'notice', 'new websocked connection open' + @log 'Websocket', 'notice', 'new websocket connection open' @connectionEstablished = true + @connectionWasEstablished = true # close error message show up (because try so connect again) if exists @clearDelay('websocket-no-connection-try-reconnect') @@ -144,7 +153,7 @@ class _Singleton extends App.Controller # empty queue for item in @queue - @log 'Event', 'debug', 'empty ws queue', item + @log 'Websocket', 'debug', 'empty ws queue', item @send(item) @queue = [] @@ -153,41 +162,31 @@ class _Singleton extends App.Controller @ws.onmessage = (e) => pipe = JSON.parse( e.data ) - @log 'Event', 'debug', 'ws:onmessage', pipe - - # go through all blocks - for item in pipe - - # reset reconnect loop - if item['action'] is 'pong' - @pong() - - # fill collection - if item['collection'] - @log 'Event', 'debug', "ws:onmessage collection:" + item['collection'] - App.Store.write( item['collection'], item['data'] ) - - # fire event - if item['event'] - if typeof item['event'] is 'object' - for event in item['event'] - @log 'Event', 'debug', "ws:onmessage event:" + event - App.Event.trigger( event, item['data'] ) - else - @log 'Event', 'debug', "ws:onmessage event:" + item['event'] - App.Event.trigger( item['event'], item['data'] ) + @log 'Websocket', 'debug', 'ws:onmessage', pipe + @_receiveMessage(pipe) @ws.onclose = (e) => - @log 'Event', 'debug', "ws:onclose", e + @log 'Websocket', 'debug', "ws:onclose", e # set timestamp to get spool messages later if @connectionEstablished @lastSpoolMessage = Math.round( +new Date()/1000 ) @connectionEstablished = false + return if @backend is 'ajax' + # show error message, first try to reconnect if !@error message = => + + # use fallback if no connection was possible + if !@connectionWasEstablished + @backend = 'ajax' + @log 'WebSocket', 'notice', 'No connection to websocket, use use ajax long polling as fallback' + @_ajaxInit() + return + + # show reconnect message @error = new App.ErrorModal( message: 'No connection to websocket, trying to reconnect...' ) @@ -197,5 +196,110 @@ class _Singleton extends App.Controller @delay @connect, 4500 @ws.onerror = (e) => - @log 'Event', 'debug', "ws:onerror", e + @log 'Websocket', 'debug', "ws:onerror", e + _receiveMessage: (data = []) => + + # go through all blocks + for item in data + + # reset reconnect loop + if item['action'] is 'pong' + @pong() + + # fill collection + if item['collection'] + @log 'Websocket', 'debug', "onmessage collection:" + item['collection'] + App.Store.write( item['collection'], item['data'] ) + + # fire event + if item['event'] + if typeof item['event'] is 'object' + for event in item['event'] + @log 'Websocket', 'debug', "onmessage event:" + event + App.Event.trigger( event, item['data'] ) + else + @log 'Websocket', 'debug', "onmessage event:" + item['event'] + App.Event.trigger( item['event'], item['data'] ) + + _ajaxInit: (data = {}) => + + # return if init is already done and not forced + return if @_ajaxInitDone && !data.force + + # stop init request if new one is started + if @_ajaxInitWorking + console.log '@_ajaxInitWorking', @_ajaxInitWorking + @_ajaxInitWorking.abort() + + # call init request + @_ajaxInitWorking = App.Com.ajax( + type: 'POST' + url: '/api/message_send' + data: JSON.stringify({ data: { action: 'login' } }) + processData: false + queue: false + success: (data) => + if data.client_id + @log 'Websocket', 'notice', 'ajax:new client_id', data.client_id + @client_id = data.client_id + @_ajaxReceive() + @_ajaxSendQueue() + @_ajaxInitDone = true + @_ajaxInitWorking = false + error: => + @_ajaxInitDone = true + @_ajaxInitWorking = false + ) + + _ajaxSend: (data) => + @log 'Websocket', 'debug', 'ajax:sendmessage', data + if !@client_id || @client_id is undefined || !@_ajaxInitDone + @_ajaxInit() + @queue.push data + else + @queue.push data + @_ajaxSendQueue() + + _ajaxSendQueue: => + while !_.isEmpty(@queue) + data = @queue.shift() + App.Com.ajax( + type: 'POST' + url: '/api/message_send' + data: JSON.stringify({ client_id: @client_id, data: data }) + processData: false + queue: true + success: (data) => + if data && data.error + @client_id = undefined + @_ajaxInit( force: true ) + error: => + @client_id = undefined + @_ajaxInit( force: true ) + ) + + _ajaxReceive: => + return if !@client_id + return if @_ajaxReceiveWorking is true + @_ajaxReceiveWorking = true + App.Com.ajax( + id: 'message_receive', + type: 'POST' + url: '/api/message_receive' + data: JSON.stringify({ client_id: @client_id }) + processData: false + success: (data) => + @log 'Websocket', 'notice', 'ajax:onmessage', data + @_receiveMessage(data) + if data && data.error + @client_id = undefined + @_ajaxInit( force: true ) + @_ajaxReceiveWorking = false + @_ajaxReceive() + error: (data) => + @client_id = undefined + @_ajaxInit( force: true ) + @_ajaxReceiveWorking = false + @delay @_ajaxReceive, 5000 + ) diff --git a/app/assets/javascripts/app/views/dashboard/rss.jst.eco b/app/assets/javascripts/app/views/dashboard/rss.jst.eco index 171869459..5b849e6c2 100644 --- a/app/assets/javascripts/app/views/dashboard/rss.jst.eco +++ b/app/assets/javascripts/app/views/dashboard/rss.jst.eco @@ -1,6 +1,9 @@

<%- @T( @head ) %>

+ <% if @message: %> + <%- @T(@message) %> + <% end %>