Moved to new task manager api (now also with browser tests).

This commit is contained in:
Martin Edenhofer 2015-02-19 20:32:37 +01:00
parent dfe7d33bd1
commit def1aacb20
13 changed files with 684 additions and 288 deletions

View file

@ -576,7 +576,12 @@ class Router extends App.ControllerPermanent
type: params.type type: params.type
id: params.id id: params.id
App.TaskManager.add( 'TicketCreateScreen-' + params['id'], 'TicketCreate', clean_params ) App.TaskManager.execute(
key: 'TicketCreateScreen-' + params['id']
controller: 'TicketCreate'
params: clean_params
show: true
)
# create new ticket routes/controller # create new ticket routes/controller
App.Config.set( 'ticket/create', Router, 'Routes' ) App.Config.set( 'ticket/create', Router, 'Routes' )

View file

@ -90,9 +90,6 @@ class Index extends App.ControllerContent
success: (data, status, xhr) => success: (data, status, xhr) =>
# rebuild navbar with ticket overview counter
App.WebSocket.send( event: 'navupdate_ticket_overview' )
# redirect to # # redirect to #
requested_url = @Config.get( 'requested_url' ) requested_url = @Config.get( 'requested_url' )
if requested_url && requested_url isnt '#login' if requested_url && requested_url isnt '#login'

View file

@ -155,6 +155,11 @@ class Router extends App.ControllerPermanent
clean_params = clean_params =
organization_id: params.organization_id organization_id: params.organization_id
App.TaskManager.add( 'Organization-' + @organization_id, 'OrganizationProfile', clean_params ) App.TaskManager.execute(
key: 'Organization-' + @organization_id
controller: 'OrganizationProfile'
params: clean_params
show: true
)
App.Config.set( 'organization/profile/:organization_id', Router, 'Routes' ) App.Config.set( 'organization/profile/:organization_id', Router, 'Routes' )

View file

@ -101,18 +101,15 @@ class App.TaskbarWidget extends App.Controller
# remove task # remove task
App.TaskManager.remove( key ) App.TaskManager.remove( key )
# navigate to next task if needed # if we do not need to move to an other task
tasks = App.TaskManager.all() return if !active_is_closed
if active_is_closed && !_.isEmpty( tasks )
task_last = undefined # get new task url
for task in tasks nextTaskUrl = App.TaskManager.nextTaskUrl()
task_last = task if nextTaskUrl
if task_last @navigate nextTaskUrl
worker = App.TaskManager.worker( task_last.key )
if worker
@navigate worker.url()
return return
if _.isEmpty( tasks )
@navigate '#' @navigate '#'
class Remove extends App.ControllerModal class Remove extends App.ControllerModal

View file

@ -1,32 +1,75 @@
class Index extends App.Controller class App.TicketOverview extends App.Controller
constructor: -> constructor: ->
super super
# check authentication
return if !@authenticate()
@render() @render()
render: -> render: ->
@html App.view('ticket_overview')()
@html App.view('agent_ticket_view')() @navBarController = new Navbar(
# redirect to first view
if !@view
cache = App.Store.get( 'navupdate_ticket_overview' )
if cache && !_.isEmpty( cache )
view = cache[0].link
@navigate "ticket/view/#{view}"
return
new Navbar(
el: @el.find('.sidebar') el: @el.find('.sidebar')
view: @view view: @view
) )
if @view @contentController = new Table(
new Table(
el: @el.find('.main') el: @el.find('.main')
view: @view view: @view
) )
class Table extends App.ControllerContent active: (state) =>
@activeState = state
isActive: =>
@activeState
url: =>
'#ticket/view/' + @view
show: (params) =>
# highlight navbar
@navupdate '#ticket/view'
# redirect to last overview if we got called in first level
@view = params['view']
if !@view && @viewLast
@navigate "ticket/view/#{@viewLast}"
return
# build nav bar
if @navBarController
@navBarController.update(
view: @view
activeState: true
)
# do not rerender overview if current overview is requested again
return if @viewLast is @view
# remember last view
@viewLast = @view
# build content
if @contentController
@contentController.update(
view: @view
)
hide: =>
if @navBarController
@navBarController.active(false)
changed: =>
false
release: =>
# no
class Table extends App.Controller
events: events:
'click [data-type=edit]': 'zoom' 'click [data-type=edit]': 'zoom'
'click [data-type=settings]': 'settings' 'click [data-type=settings]': 'settings'
@ -36,37 +79,34 @@ class Table extends App.ControllerContent
constructor: -> constructor: ->
super super
# check authentication @cache = {}
return if !@authenticate()
# rebuild ticket overview data
@bind 'ticket_overview_rebuild', (data) =>
console.log('EVENT ticket_overview_rebuild', @view, data.view)
# remeber bulk attributes
@bulk = data.bulk
@cache[data.view] = data
# check if current view is updated
if @view is data.view
@render()
update: (params) =>
for key, value of params
@[key] = value
@view_mode = localStorage.getItem( "mode:#{@view}" ) || 's' @view_mode = localStorage.getItem( "mode:#{@view}" ) || 's'
@log 'notice', 'view:', @view, @view_mode @log 'notice', 'view:', @view, @view_mode
# set title @render()
@title ''
@navupdate '#ticket/view'
@meta = {}
@bulk = {}
# set new key
@key = 'ticket_overview_' + @view
# bind to rebuild view event
@bind( 'ticket_overview_rebuild', @fetch )
# render
@fetch()
fetch: (force) => fetch: (force) =>
# use cache of first page
cache = App.Store.get( @key )
if !force && cache
@load(cache)
# init fetch via ajax, all other updates on time via websockets # init fetch via ajax, all other updates on time via websockets
else
@ajax( @ajax(
id: 'ticket_overview_' + @key id: 'ticket_overview_' + @key
type: 'GET' type: 'GET'
@ -76,65 +116,42 @@ class Table extends App.ControllerContent
view_mode: @view_mode view_mode: @view_mode
processData: true processData: true
success: (data) => success: (data) =>
data.ajax = true if data.assets
@load(data)
)
load: (data) =>
return if !data
return if !data.ticket_ids
return if !data.overview
@overview = data.overview
@tickets_count = data.tickets_count
@ticket_ids = data.ticket_ids
if data.ajax
data.ajax = false
App.Store.write( @key, data )
# load assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets( data.assets )
# get meta data
@overview = data.overview
App.Overview.refresh( @overview, { clear: true } )
App.Overview.unbind('local:rerender')
App.Overview.bind 'local:rerender', (record) =>
@log 'notice', 'rerender...', record
@render()
App.Overview.unbind('local:refetch')
App.Overview.bind 'local:refetch', (record) =>
@log 'notice', 'refetch...', record
@fetch(true)
@ticket_list_show = []
for ticket_id in @ticket_ids
@ticket_list_show.push App.Ticket.fullLocal( ticket_id )
# remeber bulk attributes # remeber bulk attributes
@bulk = data.bulk @bulk = data.bulk
# set cache @cache[data.view] = data
# App.Store.write( @key, data )
# render page
@render() @render()
)
render: -> render: ->
return if !@cache
return if !@cache[@view]
overview = @cache[@view].overview
tickets_count = @cache[@view].tickets_count
ticket_ids = @cache[@view].ticket_ids
# get meta data
overview = @cache[@view].overview
App.Overview.refresh( overview, { clear: true } )
# get ticket list
ticket_list_show = []
for ticket_id in ticket_ids
ticket_list_show.push App.Ticket.fullLocal( ticket_id )
# if customer and no ticket exists, show the following message only # if customer and no ticket exists, show the following message only
if !@ticket_list_show[0] && @isRole('Customer') if !ticket_list_show[0] && @isRole('Customer')
@html App.view('customer_not_ticket_exists')() @html App.view('customer_not_ticket_exists')()
return return
@selected = @bulkGetSelected() @selected = @bulkGetSelected()
# set page title # set page title
@overview = App.Overview.find( @overview.id ) overview = App.Overview.find( overview.id )
@title @overview.name
# render init page # render init page
checkbox = true checkbox = true
@ -157,7 +174,7 @@ class Table extends App.ControllerContent
if @isRole('Customer') if @isRole('Customer')
view_modes = [] view_modes = []
html = App.view('agent_ticket_view/content')( html = App.view('agent_ticket_view/content')(
overview: @overview overview: overview
view_modes: view_modes view_modes: view_modes
checkbox: checkbox checkbox: checkbox
edit: edit edit: edit
@ -172,16 +189,17 @@ class Table extends App.ControllerContent
table = '' table = ''
if @view_mode is 'm' if @view_mode is 'm'
table = App.view('agent_ticket_view/detail')( table = App.view('agent_ticket_view/detail')(
overview: @overview overview: overview
objects: @ticket_list_show objects: ticket_list_show
checkbox: checkbox checkbox: checkbox
) )
table = $(table) table = $(table)
table.delegate('[name="bulk_all"]', 'click', (e) -> table.delegate('[name="bulk_all"]', 'click', (e) ->
console.log('OOOO', $(e.target).attr('checked') )
if $(e.target).attr('checked') if $(e.target).attr('checked')
$(e.target).parents().find('[name="bulk"]').attr('checked', true) $(e.target).closest('table').find('[name="bulk"]').attr('checked', true)
else else
$(e.target).parents().find('[name="bulk"]').attr('checked', false) $(e.target).closest('table').find('[name="bulk"]').attr('checked', false)
) )
@el.find('.table-overview').append(table) @el.find('.table-overview').append(table)
else else
@ -226,12 +244,12 @@ class Table extends App.ControllerContent
value value
new App.ControllerTable( new App.ControllerTable(
overview: @overview.view.s overview: overview.view.s
el: @el.find('.table-overview') el: @$('.table-overview')
model: App.Ticket model: App.Ticket
objects: @ticket_list_show objects: ticket_list_show
checkbox: checkbox checkbox: checkbox
groupBy: @overview.group_by groupBy: overview.group_by
bindRow: bindRow:
events: events:
'click': openTicket 'click': openTicket
@ -452,9 +470,6 @@ class Table extends App.ControllerContent
# refresh view after all tickets are proceeded # refresh view after all tickets are proceeded
if @bulk_count_index == @bulk_count if @bulk_count_index == @bulk_count
# rebuild navbar with updated ticket count of overviews
App.WebSocket.send( event: 'navupdate_ticket_overview' )
# fetch overview data again # fetch overview data again
@fetch() @fetch()
) )
@ -687,17 +702,17 @@ class Navbar extends App.Controller
super super
# rebuild ticket overview data # rebuild ticket overview data
@bind 'navupdate_ticket_overview', (data) => @bind 'ticket_overview_index', (data) =>
if !_.isEmpty(data) #console.log('EVENT ticket_overview_index')
App.Store.write( 'navupdate_ticket_overview', data ) @cache = data
@render(data) @update()
cache = App.Store.get( 'navupdate_ticket_overview' ) # init fetch via ajax
if cache ajaxInit = =>
@render( cache )
else
@render( [] )
# ignore if already pushed via websockets
return if @cache
#console.log('AJAX CALLL')
# init fetch via ajax, all other updates on time via websockets # init fetch via ajax, all other updates on time via websockets
@ajax( @ajax(
id: 'ticket_overviews', id: 'ticket_overviews',
@ -705,17 +720,37 @@ class Navbar extends App.Controller
url: @apiPath + '/ticket_overviews', url: @apiPath + '/ticket_overviews',
processData: true, processData: true,
success: (data) => success: (data) =>
App.Store.write( 'navupdate_ticket_overview', data ) @cache = data
@render(data) @update()
) )
@delay( ajaxInit, 5000 )
render: (dataOrig) -> active: (state) =>
@activeState = state
data = _.clone(dataOrig) update: (params = {}) ->
for key, value of params
@[key] = value
@render()
if @activeState
meta =
title: ''
if @cache
for item in @cache
if item.link is @view
meta.title = item.name
@title meta.title
render: =>
#console.log('RENDER NAV')
return if !@cache
data = _.clone(@cache)
# redirect to first view # redirect to first view
if !@view && !_.isEmpty(data) if @activeState && !@view && !_.isEmpty(data)
view = data[0].link view = data[0].link
#console.log('REDIRECT', "ticket/view/#{view}")
@navigate "ticket/view/#{view}" @navigate "ticket/view/#{view}"
return return
@ -724,6 +759,7 @@ class Navbar extends App.Controller
item.target = '#ticket/view/' + item.link item.target = '#ticket/view/' + item.link
if item.link is @view if item.link is @view
item.active = true item.active = true
activeOverview = item
else else
item.active = false item.active = false
@ -784,8 +820,26 @@ class Router extends App.Controller
else else
@navigate 'ticket/zoom/' + @ticket_ids[ @position - 1 ] + '/nav/true' @navigate 'ticket/zoom/' + @ticket_ids[ @position - 1 ] + '/nav/true'
App.Config.set( 'ticket/view', Index, 'Routes' ) class TicketOverviewRouter extends App.ControllerPermanent
App.Config.set( 'ticket/view/:view', Index, 'Routes' ) constructor: (params) ->
super
# cleanup params
clean_params =
view: params.view
App.TaskManager.execute(
key: 'TicketOverview'
controller: 'TicketOverview'
params: clean_params
show: true
persistent: true
)
App.Config.set( 'ticket/view', TicketOverviewRouter, 'Routes' )
App.Config.set( 'ticket/view/:view', TicketOverviewRouter, 'Routes' )
#App.Config.set( 'ticket/view/:view/:position/:direction', Router, 'Routes' ) #App.Config.set( 'ticket/view/:view/:position/:direction', Router, 'Routes' )
App.Config.set( 'TicketOverview', 'TicketOverview', 'permanentTask' )
App.Config.set( 'TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', role: ['Agent', 'Customer'], class: 'overviews' }, 'NavBar' ) App.Config.set( 'TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', role: ['Agent', 'Customer'], class: 'overviews' }, 'NavBar' )

View file

@ -1730,7 +1730,12 @@ class TicketZoomRouter extends App.ControllerPermanent
article_id: params.article_id article_id: params.article_id
nav: params.nav nav: params.nav
App.TaskManager.add( 'Ticket-' + @ticket_id, 'TicketZoom', clean_params ) App.TaskManager.execute(
key: 'Ticket-' + @ticket_id
controller: 'TicketZoom'
params: clean_params
show: true
)
App.Config.set( 'ticket/zoom/:ticket_id', TicketZoomRouter, 'Routes' ) App.Config.set( 'ticket/zoom/:ticket_id', TicketZoomRouter, 'Routes' )
App.Config.set( 'ticket/zoom/:ticket_id/nav/:nav', TicketZoomRouter, 'Routes' ) App.Config.set( 'ticket/zoom/:ticket_id/nav/:nav', TicketZoomRouter, 'Routes' )

View file

@ -158,6 +158,12 @@ class Router extends App.ControllerPermanent
clean_params = clean_params =
user_id: params.user_id user_id: params.user_id
App.TaskManager.add( 'User-' + @user_id, 'UserProfile', clean_params ) App.TaskManager.execute(
key: 'User-' + @user_id
controller: 'UserProfile'
params: clean_params
show: true
)
App.Config.set( 'user/profile/:user_id', Router, 'Routes' ) App.Config.set( 'user/profile/:user_id', Router, 'Routes' )

View file

@ -1,18 +1,18 @@
class App.TaskManager class App.TaskManager
_instance = undefined _instance = undefined
@init: -> @init: ( params ) ->
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton( params )
@all: -> @all: ->
if _instance == undefined if _instance == undefined
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton
_instance.all() _instance.all()
@add: ( key, callback, params, to_not_show ) -> @execute: ( params ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton
_instance.add( key, callback, params, to_not_show ) _instance.execute( params )
@get: ( key ) -> @get: ( key ) ->
if _instance == undefined if _instance == undefined
@ -49,26 +49,31 @@ class App.TaskManager
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton
_instance.worker( key ) _instance.worker( key )
@workerAll: -> @nextTaskUrl: ->
if _instance == undefined if _instance == undefined
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton
_instance.workerAll() _instance.nextTaskUrl()
@TaskbarId: -> @TaskbarId: ->
if _instance == undefined if _instance == undefined
_instance ?= new _taskManagerSingleton _instance ?= new _taskManagerSingleton
_instance.TaskbarId() _instance.TaskbarId()
class _taskManagerSingleton extends App.Controller class _taskManagerSingleton extends Spine.Module
@include App.LogInclude @include App.LogInclude
constructor: -> constructor: (params = {}) ->
super super
if params.el
@el = params.el
else
@el = $('#app')
@offlineModus = params.offlineModus
@workers = {} @workers = {}
@workersStarted = {} @workersStarted = {}
@allTasks = [] @allTasks = []
@tasksToUpdate = {} @tasksToUpdate = {}
@activeTask = undefined @activeTaskHistory = []
@tasksInitial() @tasksInitial()
# render on login # render on login
@ -106,36 +111,44 @@ class _taskManagerSingleton extends App.Controller
prio++ prio++
prio prio
# generate dom id for task
domID: (key) ->
"content_permanent_#{key}"
worker: ( key ) -> worker: ( key ) ->
return @workers[ key ] if @workers[ key ] return @workers[ key ] if @workers[ key ]
return return
workerAll: -> execute: ( params ) ->
@workers
add: ( key, callback, params, to_not_show = false ) ->
# input validation # input validation
key = App.Utils.htmlAttributeCleanup(key) params.key = App.Utils.htmlAttributeCleanup(params.key)
active = true # in case later araives an init execute, ignore it
if to_not_show if params.init && @workers[ params.key ]
active = false console.log('IGNORE LATER INIT', params)
return
# remember latest active controller
if params.show
@activeTaskHistory.push _.clone(params)
# create new task if not exists # create new task if not exists
task = @get( key ) task = @get( params.key )
@log 'debug', 'add', key, callback, params, to_not_show, task, active #console.log 'debug', 'execute', params, 'task', task
if !task
# create new online task if not exists and if not persistent
if !task && !params.persistent
@log 'debug', 'add, create new taskbar in backend' @log 'debug', 'add, create new taskbar in backend'
task = new App.Taskbar task = new App.Taskbar
task.load( task.load(
key: key key: params.key
params: params params: params.params
callback: callback callback: params.controller
client_id: 123 client_id: 123
prio: @newPrio() prio: @newPrio()
notify: false notify: false
active: active active: params.show
) )
@allTasks.push task.attributes() @allTasks.push task.attributes()
@ -150,27 +163,20 @@ class _taskManagerSingleton extends App.Controller
) )
# empty static content if task is shown # empty static content if task is shown
if active if params.show
@activeTask = key @el.find('#content').empty()
$('#content').empty()
# hide all tasks # hide all tasks
$('.content').addClass('hide').removeClass('active') @el.find('.content').addClass('hide').removeClass('active')
# create div for task if not exists # create div for task if not exists
if !$("#content_permanent_#{key}")[0] if !@el.find("##{@domID(params.key)}")[0]
$('#app').append('<div id="content_permanent_' + key + '" class="content horizontal flex"></div>') @el.append("<div id=\"#{@domID(params.key)}\" class=\"content horizontal flex\"></div>")
# set task to shown and active
if @activeTask is key
$('#content_permanent_' + key).removeClass('hide').addClass('active')
else
$('#content_permanent_' + key).addClass('hide').removeClass('active')
# set all tasks to active false, only new/selected one to active # set all tasks to active false, only new/selected one to active
if active if params.show
for task in @allTasks for task in @allTasks
if task.key isnt key if task.key isnt params.key
if task.active if task.active
task.active = false task.active = false
@taskUpdate( task ) @taskUpdate( task )
@ -184,72 +190,87 @@ class _taskManagerSingleton extends App.Controller
task.notify = false task.notify = false
if changed if changed
@taskUpdate( task ) @taskUpdate( task )
else
for task in @allTasks
if @activeTask isnt task.key
if task.active
task.active = false
@taskUpdate( task )
# start worker for task if not exists # start worker for task if not exists
@startController(key, callback, params, to_not_show) @startController(params)
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
return key
startController: (key, callback, params, to_not_show) => startController: (params) =>
@log 'debug', 'controller start try...', callback, key @log 'debug', 'controller start try...', params
# create params # create clean params
params_app = _.clone(params) params_app = _.clone(params.params)
params_app['el'] = $('#content_permanent_' + key ) params_app['el'] = $("##{@domID(params.key)}")
params_app['task_key'] = key params_app['task_key'] = params.key
if to_not_show if !params.show
params_app['doNotLog'] = 1 params_app['doNotLog'] = 1
# return if controller is already started # start controller if not already started
if @workersStarted[key] if !@workersStarted[params.key]
if !to_not_show @workersStarted[params.key] = true
@showController( key, params_app )
return
@workersStarted[key] = true
# create new controller instanz # create new controller instanz
a = new App[callback]( params_app ) @workers[params.key] = new App[params.controller]( params_app )
@workers[ key ] = a
# activate controller # if controller is started hidden, call hide of controller
if !to_not_show if !params.show
@showController( key, params_app ) @hide(params.key)
return a # hide all other controller / show current controller
else
@showControllerHideOthers( params.key, params_app )
showController: ( thisKey, params_app ) => showControllerHideOthers: ( thisKey, params_app ) =>
for key of @workersStarted for key of @workersStarted
controller = @workers[ key ]
if controller
if key is thisKey if key is thisKey
@show(key, params_app)
else
@hide(key)
# show task content
show: (key, params_app) ->
@el.find("##{@domID(key)}").removeClass('hide').addClass('active')
controller = @workers[ key ]
return false if !controller
# set controller state to active
if controller.active
controller.active(true)
# execute controllers show # execute controllers show
if controller.show if controller.show
controller.show(params_app) controller.show(params_app)
App.Event.trigger('ui:rerender:task') App.Event.trigger('ui:rerender:task')
else
true
# hide task content
hide: (key) ->
@el.find("##{@domID(key)}").addClass('hide').removeClass('active')
controller = @workers[ key ]
return false if !controller
# set controller state to active
if controller.active
controller.active(false)
# execute controllers hide # execute controllers hide
if controller.hide if controller.hide
controller.hide() controller.hide()
true
# get task
get: ( key ) => get: ( key ) =>
for task in @allTasks for task in @allTasks
if task.key is key if task.key is key
return task return task
# return task if task.key is key
return
# throw "No such task with '#{key}'"
# update task
update: ( key, params ) => update: ( key, params ) =>
task = @get( key ) task = @get( key )
if !task if !task
@ -258,11 +279,12 @@ class _taskManagerSingleton extends App.Controller
task[item] = value task[item] = value
@taskUpdate( task ) @taskUpdate( task )
remove: ( key, to_not_show = false ) => # remove task certain task from tasks
remove: ( key ) =>
task = @get( key ) task = @get( key )
if !task return if !task
throw "No such task with '#{key}' to remove"
# update @allTasks
allTasks = _.filter( allTasks = _.filter(
@allTasks @allTasks
(taskLocal) -> (taskLocal) ->
@ -271,21 +293,16 @@ class _taskManagerSingleton extends App.Controller
) )
@allTasks = allTasks || [] @allTasks = allTasks || []
try # release task from dom and destroy controller
$('#content_permanent_' + key ).html('') @release(key)
$('#content_permanent_' + key ).remove()
catch
@log 'notice', "invalid key '#{key}'"
delete @workersStarted[ key ]
delete @workers[ key ]
# rerender taskbar
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
# destroy in backend # destroy in backend storage
@taskDestroy(task) @taskDestroy(task)
# set notify of task
notify: ( key ) => notify: ( key ) =>
task = @get( key ) task = @get( key )
if !task if !task
@ -293,6 +310,7 @@ class _taskManagerSingleton extends App.Controller
task.notify = true task.notify = true
@taskUpdate( task ) @taskUpdate( task )
# set new order of tasks (needed for dnd)
reorder: ( order ) => reorder: ( order ) =>
prio = 0 prio = 0
for key in order for key in order
@ -304,23 +322,32 @@ class _taskManagerSingleton extends App.Controller
task.prio = prio task.prio = prio
@taskUpdate( task ) @taskUpdate( task )
reset: => # release one task
release: (key) =>
# release tasks
for task in @allTasks
try try
$('#content_permanent_' + task.key ).html('') @el.find( "##{@domID(key)}" ).html('')
$('#content_permanent_' + task.key ).remove() @el.find( "##{@domID(key)}" ).remove()
catch catch
@log 'notice', "invalid key '#{key}'" @log 'notice', "invalid key '#{key}'"
delete @workersStarted[ task.key ] delete @workersStarted[ key ]
delete @workers[ task.key ] delete @workers[ key ]
# reset while tasks
reset: =>
# release touch tasks
for task in @allTasks
@release(key)
# release persistent tasks
for key, controller of @workers
@release(key)
# clear instance vars # clear instance vars
@tasksToUpdate = {} @tasksToUpdate = {}
@allTasks = [] @allTasks = []
@activeTask = undefined @activeTaskHistory = []
# clear in mem tasks # clear in mem tasks
App.Taskbar.deleteAll() App.Taskbar.deleteAll()
@ -328,6 +355,27 @@ class _taskManagerSingleton extends App.Controller
# rerender task bar # rerender task bar
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
nextTaskUrl: =>
# activate latest controller based on history
loop
controllerParams = @activeTaskHistory.pop()
break if !controllerParams
break if !controllerParams.key
controller = @workers[ controllerParams.key ]
if controller && controller.url
return controller.url()
# activate latest controller with highest prio
tasks = @all()
taskNext = tasks[tasks.length-1]
if taskNext
controller = @workers[ taskNext.key ]
if controller && controller.url
return controller.url()
false
TaskbarId: => TaskbarId: =>
if !@TaskbarIdInt if !@TaskbarIdInt
@TaskbarIdInt = Math.floor( Math.random() * 99999999 ) @TaskbarIdInt = Math.floor( Math.random() * 99999999 )
@ -339,6 +387,7 @@ class _taskManagerSingleton extends App.Controller
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
taskUpdateLoop: => taskUpdateLoop: =>
return if @offlineModus
for key of @tasksToUpdate for key of @tasksToUpdate
continue if !key continue if !key
task = @get( key ) task = @get( key )
@ -381,26 +430,52 @@ class _taskManagerSingleton extends App.Controller
tasksInitial: => tasksInitial: =>
# reopen tasks
App.Event.trigger 'taskbar:init'
# initial load of permanent tasks
task_count = 0
permanentTask = App.Config.get( 'permanentTask' )
if permanentTask
for key, callback of permanentTask
task_count += 1
do (task) =>
App.Delay.set(
=>
@execute(
key: key
controller: callback
params: {}
show: false
persistent: true
init: true
)
task_count * 50
undefined
'task'
)
# initial load of taskbar collection # initial load of taskbar collection
tasks = App.Taskbar.all() tasks = App.Taskbar.all()
@allTasks = [] @allTasks = []
for task in tasks for task in tasks
@allTasks.push task.attributes() @allTasks.push task.attributes()
# reopen tasks
App.Event.trigger 'taskbar:init'
task_count = 0
for task in @allTasks for task in @allTasks
task_count += 1 task_count += 1
do (task) => do (task) =>
App.Delay.set( App.Delay.set(
=> =>
@add(task.key, task.callback, task.params, true) @execute(
key: task.key
controller: task.callback
params: task.params
show: false
persistent: false
init: true
)
task_count * 600 task_count * 600
undefined undefined
'task' 'task'
) )
App.Event.trigger 'taskbar:ready' App.Event.trigger 'taskbar:ready'

View file

@ -0,0 +1,16 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.10.0.css">
<script src="/assets/tests/qunit-1.10.0.js"></script>
<script src="/assets/tests/taskbar.js"></script>
<style type="text/css">
body {
padding-top: 0px;
}
</style>
<script type="text/javascript">
</script>
<div id="qunit"></div>
<div id="taskbars"></div>

View file

@ -9,6 +9,7 @@ Zammad::Application.routes.draw do
match '/tests-form-validation', :to => 'tests#form_validation', :via => :get match '/tests-form-validation', :to => 'tests#form_validation', :via => :get
match '/tests-table', :to => 'tests#table', :via => :get match '/tests-table', :to => 'tests#table', :via => :get
match '/tests-html-utils', :to => 'tests#html_utils', :via => :get match '/tests-html-utils', :to => 'tests#html_utils', :via => :get
match '/tests-taskbar', :to => 'tests#taskbar', :via => :get
match '/tests/wait/:sec', :to => 'tests#wait', :via => :get match '/tests/wait/:sec', :to => 'tests#wait', :via => :get
end end

View file

@ -44,14 +44,14 @@ class Sessions::Backend::TicketOverviewIndex
if !@client if !@client
return { return {
:event => 'navupdate_ticket_overview', :event => 'ticket_overview_index',
:data => data, :data => data,
} }
end end
@client.log 'notify', "push overview_index for user #{ @user.id }" @client.log 'notify', "push overview_index for user #{ @user.id }"
@client.send({ @client.send({
:event => 'navupdate_ticket_overview', :event => ['ticket_overview_index'],
:data => data, :data => data,
}) })
end end

View file

@ -105,6 +105,7 @@ class Sessions::Backend::TicketOverviewList
}) })
@client.send({ @client.send({
:data => { :data => {
:view => item[:index].link.to_s,
:overview => overview_data[:overview], :overview => overview_data[:overview],
:ticket_ids => overview_data[:ticket_ids], :ticket_ids => overview_data[:ticket_ids],
:tickets_count => overview_data[:tickets_count], :tickets_count => overview_data[:tickets_count],
@ -114,7 +115,6 @@ class Sessions::Backend::TicketOverviewList
}, },
}, },
:event => [ 'ticket_overview_rebuild' ], :event => [ 'ticket_overview_rebuild' ],
:collection => 'ticket_overview_' + item[:index].link.to_s,
}) })
end end
} }

View file

@ -0,0 +1,235 @@
window.onload = function() {
test( "taskbar basic tests", function() {
// create task bar div
$('#taskbars').append('<hr><h1>taskbar basic tests</h1><div id="taskbar1"></div>')
App.TaskManager.init({
el: $('#taskbar1'),
offlineModus: true,
})
// add tasks
App.TaskManager.execute({
key: 'TestKey1',
controller: 'TestController1',
params: {
message: '#1',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#1',show:'true',hide:'false',active:'true'", "check active content!" );
App.TaskManager.execute({
key: 'TestKey2',
controller: 'TestController1',
params: {
message: '#2',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 2, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
// check task history
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#2')
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#1')
App.TaskManager.execute({
key: 'TestKey3',
controller: 'TestController1',
params: {
message: '#3',
},
show: false,
persistent: false,
})
equal( $('#taskbars .content').length, 3, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'false',hide:'true',active:'false'", "check active content!" );
App.TaskManager.execute({
key: 'TestKey4',
controller: 'TestController1',
params: {
message: '#4',
},
show: false,
persistent: true,
})
equal( $('#taskbars .content').length, 4, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#2',show:'true',hide:'false',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
App.TaskManager.execute({
key: 'TestKey5',
controller: 'TestController1',
params: {
message: '#5',
},
show: true,
persistent: true,
})
equal( $('#taskbars .content').length, 5, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#5',show:'true',hide:'false',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
App.TaskManager.execute({
key: 'TestKey6',
controller: 'TestController1',
params: {
message: '#6',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 6, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey2').text(), "some test controller message:'#2',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!" );
// remove task#2
App.TaskManager.remove('TestKey2')
equal( $('#taskbars .content').length, 5, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#6',show:'true',hide:'false',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!" );
// activate task#3
App.TaskManager.execute({
key: 'TestKey3',
controller: 'TestController1',
params: {
message: '#3',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 5, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#3',show:'true',hide:'true',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey1').text(), "some test controller message:'#1',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!" );
// activate task#1
App.TaskManager.execute({
key: 'TestKey1',
controller: 'TestController1',
params: {
message: '#1',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 5, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#1',show:'true',hide:'true',active:'true'" );
equal( $('#taskbars #content_permanent_TestKey3').text(), "some test controller message:'#3',show:'true',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey4').text(), "some test controller message:'#4',show:'false',hide:'true',active:'false'", "check active content!" );
equal( $('#taskbars #content_permanent_TestKey5').text(), "some test controller message:'#5',show:'true',hide:'true',active:'false'", "check active content!" );
// remove task#1
App.TaskManager.remove('TestKey1')
// verify if task#3 is active
equal( $('#taskbars .content').length, 4, "check available active contents" );
equal( $('#taskbars .content.active').length, 0, "check available active contents" );
equal( $('#taskbars .content.active').text(), "" );
// remove task#3
App.TaskManager.remove('TestKey3')
// verify if task#5 is active
equal( $('#taskbars .content').length, 3, "check available active contents" );
equal( $('#taskbars .content.active').length, 0, "check available active contents" );
equal( $('#taskbars .content.active').text(), "" );
// remove task#5 // can not get removed because of permanent task
App.TaskManager.remove('TestKey5')
// verify if task#5 is active
equal( $('#taskbars .content').length, 3, "check available active contents" );
equal( $('#taskbars .content.active').length, 0, "check available active contents" );
equal( $('#taskbars .content.active').text(), "" );
// create task#7
App.TaskManager.execute({
key: 'TestKey7',
controller: 'TestController1',
params: {
message: '#7',
},
show: true,
persistent: false,
})
equal( $('#taskbars .content').length, 4, "check available active contents" );
equal( $('#taskbars .content.active').length, 1, "check available active contents" );
equal( $('#taskbars .content.active').text(), "some test controller message:'#7',show:'true',hide:'false',active:'true'", "check active content!" );
// remove task#7
App.TaskManager.remove('TestKey7')
// verify if task#5 is active
equal( $('#taskbars .content').length, 3, "check available active contents" );
equal( $('#taskbars .content.active').length, 0, "check available active contents" );
equal( $('#taskbars .content.active').text(), "" );
// check task history
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#6')
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#5')
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#6')
equal( App.TaskManager.nextTaskUrl(), '#/some/url/#6')
// remove task#6
App.TaskManager.remove('TestKey6')
// check task history
equal( App.TaskManager.nextTaskUrl(), false)
equal( App.TaskManager.nextTaskUrl(), false)
// destroy task bar
App.TaskManager.reset()
// check if any taskar exists
equal( $('#taskbars .content').length, 0, "check available active contents" );
})
}