Rewritten taskbar manager.

This commit is contained in:
Martin Edenhofer 2013-05-31 13:29:48 +02:00
parent 2dd3853e96
commit 6f278fa8f7
7 changed files with 173 additions and 196 deletions

View file

@ -89,7 +89,7 @@ class App.TicketCreate extends App.Controller
if !@autosaveLast || ( diff && !_.isEmpty( diff ) )
@autosaveLast = data
console.log('form hash changed', diff, data)
App.TaskManager.update( @task_key, { 'state': data })
App.TaskManager.update( 'TicketCreateScreen', @type + '-' + @id, { 'state': data })
@interval( update, 10000, @id, @auto_save_key )
# get data / in case also ticket data for split
@ -302,7 +302,7 @@ class App.TicketCreate extends App.Controller
# create new create screen
# ui.render()
App.TaskManager.remove( ui.task_key )
App.TaskManager.remove( 'TicketCreateScreen', ui.type + '-' + ui.id )
# scroll to top
ui.scrollTo()

View file

@ -133,7 +133,7 @@ class App.TicketMerge extends App.ControllerModal
msg: App.i18n.translateContent( 'Ticket %s merged!', data.slave_ticket['number'] ),
timeout: 4000,
App.TaskManager.remove( @task_key )
App.TaskManager.remove( 'Ticket', data.slave_ticket['id'] )
else

View file

@ -11,7 +11,7 @@ class App.TicketZoom extends App.Controller
constructor: (params) ->
super
@log 'zoom', params
# console.log 'zoom', params
# check authentication
return if !@authenticate()
@ -31,7 +31,7 @@ class App.TicketZoom extends App.Controller
if cache
@load(cache)
update = =>
@fetch( @ticket_id, false)
@fetch( @ticket_id, false )
@interval( update, 30000, @key, 'ticket_zoom' )
# start auto save
@ -73,7 +73,7 @@ class App.TicketZoom extends App.Controller
if !@autosaveLast || ( diff && !_.isEmpty( diff ) )
@autosaveLast = data
console.log('form hash changed', diff, data)
App.TaskManager.update( @task_key, { 'state': data })
App.TaskManager.update( 'Ticket', @ticket_id, { 'state': data })
@interval( update, 10000, @id, @auto_save_key )
fetch: (ticket_id, force) ->
@ -93,7 +93,7 @@ class App.TicketZoom extends App.Controller
return if _.isEqual( @dataLastCall.ticket, data.ticket)
diff = difference( @dataLastCall.ticket, data.ticket )
console.log('diff', diff)
App.TaskManager.notify(@task_key)
App.TaskManager.notify( 'Ticket', @ticket_id )
if $('[name="body"]').val()
App.Event.trigger 'notify', {
type: 'success'
@ -293,7 +293,6 @@ class App.TicketZoom extends App.Controller
internal = true
if article.internal == true
internal = false
article.updateAttributes(
internal: internal
)

View file

@ -10,37 +10,31 @@ class App.TaskWidget extends App.Controller
App.Event.bind 'ui:rerender', (data) =>
@render()
# rebuild chat widget
# rebuild taskbar widget
App.Event.bind 'auth', (user) =>
App.TaskManager.reset()
@el.html('')
sync = =>
App.TaskManager.sync()
@delay( sync, 3000, 'task-widget' )
@delay( sync, 5000, 'task-widget' )
render: ->
return if _.isEmpty( @Session.all() )
tasks = App.TaskManager.all()
item_list = []
for key, task of tasks
for task in tasks
data =
url: '#'
id: false
title: App.i18n.translateInline('Loading...')
head: App.i18n.translateInline('Loading...')
if task.worker
meta = task.worker.meta()
worker = App.TaskManager.worker( task.type, task.type_id )
if worker
meta = worker.meta()
if meta
data = meta
data.title = App.i18n.escape( data.title )
data.head = App.i18n.escape( data.head )
item = {}
item.key = key
item.task = task
item.data = data
item_list.push item
@ -52,34 +46,41 @@ class App.TaskWidget extends App.Controller
remove: (e) =>
e.preventDefault()
key = $(e.target).parent().data('id')
type_id = $(e.target).parent().data('type-id')
type = $(e.target).parent().data('type')
if !type_id && !type
throw "No such type and type-id attributes found for task item"
# check if input has changed
task = App.TaskManager.get( key )
if task.worker && task.worker.changed
if task.worker.changed()
worker = App.TaskManager.worker( type, type_id )
if worker && worker.changed
if worker.changed()
return if !window.confirm( App.i18n.translateInline('Tab has changed, you really want to close it?') )
# check if active task is closed
task_last = undefined
tasks_all = App.TaskManager.all()
currentTask = App.TaskManager.get( type, type_id )
tasks = App.TaskManager.all()
active_is_closed = false
for task_key, task of tasks_all
if task.active && task_key.toString() is key.toString()
for task in tasks
if currentTask.active && task.type is type && task.type_id.toString() is type_id.toString()
active_is_closed = true
# remove task
App.TaskManager.remove( key )
App.TaskManager.remove( type, type_id )
@render()
# navigate to next task if needed
if active_is_closed && !_.isEmpty( tasks_all )
for key, task of tasks_all
tasks = App.TaskManager.all()
if active_is_closed && !_.isEmpty( tasks )
task_last = undefined
for task in tasks
task_last = task
if task_last
@navigate task_last.worker.url()
worker = App.TaskManager.worker( task_last.type, task_last.type_id )
if worker
@navigate worker.url()
return
if _.isEmpty( tasks_all )
if _.isEmpty( tasks )
@navigate '#'
_getTaskActions: ->

View file

@ -14,240 +14,216 @@ class App.TaskManager
_instance ?= new _Singleton
_instance.add( type, type_id, callback, params, to_not_show, state )
@get: ( key ) ->
@get: ( type, type_id ) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.get( key )
_instance.get( type, type_id )
@update: ( key, params ) ->
@update: ( type, type_id, params ) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.update( key, params )
_instance.update( type, type_id, params )
@remove: ( key ) ->
@remove: ( type, type_id ) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.remove( key )
_instance.remove( type, type_id )
@notify: ( key ) ->
@notify: ( type, type_id ) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.notify( key )
_instance.notify( type, type_id )
@reset: ->
if _instance == undefined
_instance ?= new _Singleton
_instance.reset()
@syncInitial: ->
@worker: ( type, type_id ) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.syncTasksInitial()
_instance.worker( type, type_id )
@syncSave: ->
@workerAll: ->
if _instance == undefined
_instance ?= new _Singleton
_instance.syncSave()
@sync: ->
if _instance == undefined
_instance ?= new _Singleton
_instance.syncTasks()
_instance.workerAll()
class _Singleton extends App.Controller
@include App.Log
constructor: ->
@tasks = {}
@task_count = 0
@syncTasksInitial()
@workers = {}
@workersStarted = {}
@activeTask = undefined
@tasksInitial()
all: ->
@tasks
App.Taskbar.all()
worker: ( type, type_id ) ->
key = @keyGenerate(type, type_id)
return @workers[ key ] if @workers[ key ]
return
workerAll: ->
@workers
add: ( type, type_id, callback, params, to_not_show = false, state ) ->
for key, task of @tasks
if task.type is type && task.type_id is type_id
return key if to_not_show
$('#content').empty()
$('.content_permanent').hide()
$('.content_permanent').removeClass('active')
$('#content_permanent_' + key ).show()
$('#content_permanent_' + key ).addClass('active')
@tasks[key].worker.activate()
@tasks[key].notify = false
for task_key, task of @tasks
if task_key isnt key
task.active = false
else
task.active = true
App.Event.trigger 'ui:rerender'
App.Event.trigger 'ui:rerender:content'
return key
@task_count++
if !to_not_show
for task_key, task of @tasks
task.active = false
active = true
if to_not_show
active = false
# create new task if not exists
task = @get( type, type_id )
# console.log('add', type, type_id, callback, params, to_not_show, state, task)
if !task
task = new App.Taskbar
task.load(
type: type
type_id: type_id
params: params
callback: callback
notify: false
active: active
)
task.save()
tasks = @all()
# empty static content if task is shown
key = @keyGenerate(type, type_id)
if active
@activeTask = key
$('#content').empty()
$('#content_permanent').append('<div id="content_permanent_' + @task_count + '" class="content_permanent"></div>')
if active
# hide all tasks
$('.content_permanent').hide()
$('.content_permanent').removeClass('active')
$('#content_permanent_' + @task_count ).show()
$('#content_permanent_' + @task_count ).addClass('active')
# create div for task if not exists
if !$("#content_permanent_#{key}")[0]
$('#content_permanent').append('<div id="content_permanent_' + key + '" class="content_permanent"></div>')
# set task to shown and active
if @activeTask is key
$('#content_permanent_' + key ).show()
$('#content_permanent_' + key ).addClass('active')
else
$('#content_permanent_' + @task_count ).removeClass('active')
$('#content_permanent_' + @task_count ).hide()
$('#content_permanent_' + key ).hide()
$('#content_permanent_' + key ).removeClass('active')
# set all tasks to active false, only new/selected one to active
if active
for task in tasks
task_key = @keyGenerate(task.type, task.type_id)
if task_key isnt key
task.active = false
else
task.active = true
task.save()
else
for task in tasks
task_key = @keyGenerate(task.type, task.type_id)
if @activeTask isnt task_key
if task.active
task.active = false
task.save()
# start worker for task if not exists
@startController(type, type_id, callback, params, state, key, to_not_show)
App.Event.trigger 'ui:rerender'
App.Event.trigger 'ui:rerender:content'
return key
startController: (type, type_id, callback, params, state, key, to_not_show) =>
# console.log('controller started...', callback, type, type_id, params, state)
# activate controller
worker = @worker( type, type_id )
if worker && worker.activate
worker.activate()
# return if controller is alreary started
return if @workersStarted[key]
@workersStarted[key] = true
# create new controller instanz
params_app = _.clone(params)
params_app['el'] = $('#content_permanent_' + @task_count )
params_app['task_key'] = @task_count
params_app['el'] = $('#content_permanent_' + key )
params_app['task_key'] = key
# check if we have old state there
if !state
oldTask = @get_by_type( type, type_id )
oldTask = @get( type, type_id )
if oldTask
state = oldTask.state
params_app['form_state'] = state
if to_not_show
params_app['doNotLog'] = 1
a = new App[callback]( params_app )
# remember new controller / prepare for task storage
task =
type: type
type_id: type_id
params: params
callback: callback
worker: a
active: active
@tasks[@task_count] = task
@workers[ key ] = a
# activate controller
if !to_not_show
a.activate()
App.Event.trigger 'ui:rerender'
return a
# add new controller to task storage
if !to_not_show
@syncAdd(task)
get: ( type, type_id ) =>
tasks = App.Taskbar.all()
for task in tasks
return task if task.type is type && task.type_id.toString() is type_id.toString()
return
# throw "No such task with '#{type}' and '#{type_id}'"
@task_count
get: ( key ) =>
return @tasks[key]
update: ( key, params ) =>
return false if !@tasks[key]
update: ( type, type_id, params ) =>
task = @get( type, type_id )
if !task
throw "No such task with '#{type}' and '#{type_id}' to update"
for item, value of params
@tasks[key][item] = value
@syncSave()
task.updateAttribute(item, value)
# task.save()
remove: ( key, to_not_show = false ) =>
if @tasks[key]
@tasks[key].worker.release()
if !to_not_show
@syncRemove( @tasks[key] )
delete @tasks[key]
remove: ( type, type_id, to_not_show = false ) =>
task = @get( type, type_id )
if !task
throw "No such task with '#{type}' and '#{type_id}' to remove"
worker = @worker( type, type_id )
if worker && worker.release
worker.release()
@workersStarted[ @keyGenerate(type, type_id) ] = false
task.destroy()
App.Event.trigger 'ui:rerender'
notify: ( key ) =>
@tasks[key].notify = true
notify: ( type, type_id ) =>
task = @get( type, type_id )
if !task
throw "No such task with '#{type}' and '#{type_id}' to notify"
task.notify = true
reset: =>
@tasks = {}
App.Taskbar.deleteAll()
App.Event.trigger 'ui:rerender'
get_by_type: (type, type_id) =>
store = @syncLoad() || []
for item in store
return item if item.type is type && item.type_id is type_id
syncAdd: (task) =>
store = @syncLoad() || []
for item in store
return if item.type is task.type && item.type_id is task.type_id
item =
type: task.type
type_id: task.type_id
params: task.params
callback: task.callback
store.push item
App.Store.write( 'tasks', store )
syncRemove: (task) =>
store = @syncLoad() || []
storeNew = []
for item in store
if item.type isnt task.type || item.type_id isnt task.type_id
storeNew.push item
App.Store.write( 'tasks', storeNew )
syncSave: =>
store = @syncLoad() || []
storeNew = []
for item in store
for key, task of @tasks
if task.type is item.type && task.type_id is item.type_id
console.log('MATCH', item)
if @tasks[key]['state']
item['state'] = @tasks[key]['state']
storeNew.push item
# if @tasks[key]
# @tasks[key].worker.release()
#
# storeNew.push item
# item =
# type: task.type
# type_id: task.type_id
# params: task.params
# callback: task.callback
App.Store.write( 'tasks', storeNew )
syncLoad: =>
App.Store.get( 'tasks' )
syncTasksInitial: =>
tasksInitial: =>
# reopen tasks
store = _.clone(@syncLoad())
return if !store
App.Taskbar.fetch()
tasks = @all()
return if !tasks
task_count = 0
for task in store
for task in tasks
task_count += 1
@delay(
=>
task = store.shift()
task = tasks.shift()
@add(task.type, task.type_id, task.callback, task.params, true, task.state)
task_count * 500
)
syncTasks: =>
store = @syncLoad() || []
# open tasks
for item in store
existsLocal = false
for task_key, task of @tasks
if item.type is task.type && item.type_id is task.type_id
# also open here
existsLocal = true
if !existsLocal
@add(item.type, item.type_id, item.callback, item.params, true)
# close tasks
for task_key, task of @tasks
onlyLocal = true
for item in store
if item.type is task.type && item.type_id is task.type_id
onlyLocal = false
if onlyLocal
@remove( task_key, true )
keyGenerate: ( type, type_id )->
"#{type}_#{type_id}"

View file

@ -1,6 +1,6 @@
<div class="well taskbar">
<div class="taskbar">
<% for item in @item_list: %>
<a href="<%- item.data.url %>" title="<%= item.data.title %>" class="btn btn-mini <% if item.task.active: %>active btn-success<% else if item.task.notify: %>active btn-warning<% else: %>btn-default<% end %>" data-id="<%- item.key %>"><span class="task"><%- item.data.head %></span><span data-type="close" class="icon-remove-circle" title="<%- @T('close') %>"></a>
<a href="<%- item.data.url %>" title="<%= item.data.title %>" class="btn btn-mini <% if item.task.active: %>active btn-success<% else if item.task.notify: %>active btn-warning<% else: %>btn-default<% end %>" data-type="<%- item.task.type %>" data-type-id="<%- item.task.type_id %>"><span class="task"><%- item.data.head %></span><span data-type="close" class="icon-remove-circle" title="<%- @T('close') %>"></a>
<% end %>
<% if !_.isEmpty( @taskBarActions ): %>
<div class="taskbar-new">

View file

@ -12,6 +12,7 @@
//not_used= require_tree ./app/lib/spine
//= require ./app/lib/spine/spine.js
//= require ./app/lib/spine/ajax.js
//= require ./app/lib/spine/local.js
//= require ./app/lib/spine/route.js
//= require ./app/lib/flot/jquery.flot.js