Rewrite of taskbar manager.

This commit is contained in:
Martin Edenhofer 2013-06-01 01:09:09 +02:00
parent 74434d559e
commit 19079731cb
10 changed files with 126 additions and 129 deletions

View file

@ -50,7 +50,10 @@ class App.TicketCreate extends App.Controller
@render(defaults) @render(defaults)
# start auto save # start auto save
@autosave() @delay(
=> @autosave(),
5000
)
meta: => meta: =>
text = App.i18n.translateInline( @article_attributes['title'] ) text = App.i18n.translateInline( @article_attributes['title'] )
@ -68,7 +71,7 @@ class App.TicketCreate extends App.Controller
activate: => activate: =>
@navupdate '#' @navupdate '#'
@title @article_attributes['title'] @title @meta().title
changed: => changed: =>
formCurrent = @formParam( @el.find('.ticket-create') ) formCurrent = @formParam( @el.find('.ticket-create') )
@ -89,7 +92,7 @@ class App.TicketCreate extends App.Controller
if !@autosaveLast || ( diff && !_.isEmpty( diff ) ) if !@autosaveLast || ( diff && !_.isEmpty( diff ) )
@autosaveLast = data @autosaveLast = data
console.log('form hash changed', diff, data) console.log('form hash changed', diff, data)
App.TaskManager.update( 'TicketCreateScreen', @type + '-' + @id, { 'state': data }) App.TaskManager.update( @task_key, { 'state': data })
@interval( update, 10000, @id, @auto_save_key ) @interval( update, 10000, @id, @auto_save_key )
# get data / in case also ticket data for split # get data / in case also ticket data for split
@ -296,13 +299,13 @@ class App.TicketCreate extends App.Controller
# notify UI # notify UI
ui.notify ui.notify
type: 'success', type: 'success',
msg: App.i18n.translateContent( 'Ticket %s created!', @number ), msg: App.i18n.translateInline( 'Ticket %s created!', @number ),
link: "#ticket/zoom/#{@id}" link: "#ticket/zoom/#{@id}"
timeout: 12000, timeout: 12000,
# create new create screen # create new create screen
# ui.render() # ui.render()
App.TaskManager.remove( 'TicketCreateScreen', ui.type + '-' + ui.id ) App.TaskManager.remove( ui.task_key )
# scroll to top # scroll to top
ui.scrollTo() ui.scrollTo()
@ -394,7 +397,7 @@ class TicketCreateRouter extends App.ControllerPermanent
type: params.type type: params.type
id: params.id id: params.id
App.TaskManager.add( 'TicketCreateScreen', params['type'] + '-' + params['id'], 'TicketCreate', clean_params ) App.TaskManager.add( 'TicketCreateScreen-' + params['type'] + '-' + params['id'], 'TicketCreate', clean_params )
# split ticket # split ticket
App.Config.set( 'ticket_create/:ticket_id/:article_id', TicketCreateRouter, 'Routes' ) App.Config.set( 'ticket_create/:ticket_id/:article_id', TicketCreateRouter, 'Routes' )

View file

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

View file

@ -34,14 +34,11 @@ class App.TicketZoom extends App.Controller
@fetch( @ticket_id, false ) @fetch( @ticket_id, false )
@interval( update, 30000, @key, 'ticket_zoom' ) @interval( update, 30000, @key, 'ticket_zoom' )
# start auto save
@autosave()
meta: => meta: =>
return if !@ticket return if !@ticket
meta = meta =
url: @url() url: @url()
head: @ticket.title head: @ticket.title + ' ' + @ticket.title
title: @ticket.number + ' ' + @ticket.title title: @ticket.number + ' ' + @ticket.title
id: @ticket.id id: @ticket.id
@ -51,9 +48,9 @@ class App.TicketZoom extends App.Controller
activate: => activate: =>
@navupdate '#' @navupdate '#'
if @ticket if @ticket
@title 'Ticket Zoom ' + @ticket.number @title App.i18n.translateInline('Ticket Zoom') + ' ' + @ticket.number + ' ' + @ticket.title
# else else
# @title 'Loading...' @title App.i18n.translateInline('Loading...')
changed: => changed: =>
formCurrent = @formParam( @el.find('.ticket-update') ) formCurrent = @formParam( @el.find('.ticket-update') )
@ -73,7 +70,7 @@ class App.TicketZoom extends App.Controller
if !@autosaveLast || ( diff && !_.isEmpty( diff ) ) if !@autosaveLast || ( diff && !_.isEmpty( diff ) )
@autosaveLast = data @autosaveLast = data
console.log('form hash changed', diff, data) console.log('form hash changed', diff, data)
App.TaskManager.update( 'Ticket', @ticket_id, { 'state': data }) App.TaskManager.update( @task_key, { 'state': data })
@interval( update, 10000, @id, @auto_save_key ) @interval( update, 10000, @id, @auto_save_key )
fetch: (ticket_id, force) -> fetch: (ticket_id, force) ->
@ -93,11 +90,11 @@ class App.TicketZoom extends App.Controller
return if _.isEqual( @dataLastCall.ticket, data.ticket) return if _.isEqual( @dataLastCall.ticket, data.ticket)
diff = difference( @dataLastCall.ticket, data.ticket ) diff = difference( @dataLastCall.ticket, data.ticket )
console.log('diff', diff) console.log('diff', diff)
App.TaskManager.notify( 'Ticket', @ticket_id ) App.TaskManager.notify( @task_key )
if $('[name="body"]').val() if $('[name="body"]').val()
App.Event.trigger 'notify', { App.Event.trigger 'notify', {
type: 'success' type: 'success'
msg: App.i18n.translateContent('Ticket has changed!') msg: App.i18n.translateInline('Ticket has changed!')
timeout: 30000 timeout: 30000
} }
return return
@ -106,6 +103,9 @@ class App.TicketZoom extends App.Controller
@load(data) @load(data)
App.Store.write( @key, data ) App.Store.write( @key, data )
# start auto save
@autosave()
error: (xhr, status, error) => error: (xhr, status, error) =>
# do not close window if request is abort or network error exists # do not close window if request is abort or network error exists
@ -645,7 +645,7 @@ 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.add( 'Ticket-' + @ticket_id, 'TicketZoom', clean_params )
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

@ -27,7 +27,7 @@ class App.TaskWidget extends App.Controller
id: false id: false
title: App.i18n.translateInline('Loading...') title: App.i18n.translateInline('Loading...')
head: App.i18n.translateInline('Loading...') head: App.i18n.translateInline('Loading...')
worker = App.TaskManager.worker( task.type, task.type_id ) worker = App.TaskManager.worker( task.key )
if worker if worker
meta = worker.meta() meta = worker.meta()
if meta if meta
@ -46,27 +46,26 @@ class App.TaskWidget extends App.Controller
remove: (e) => remove: (e) =>
e.preventDefault() e.preventDefault()
type_id = $(e.target).parent().data('type-id') key = $(e.target).parent().data('key')
type = $(e.target).parent().data('type') if !key
if !type_id && !type throw "No such key attributes found for task item"
throw "No such type and type-id attributes found for task item"
# check if input has changed # check if input has changed
worker = App.TaskManager.worker( type, type_id ) worker = App.TaskManager.worker( key )
if worker && worker.changed if worker && worker.changed
if worker.changed() if worker.changed()
return if !window.confirm( App.i18n.translateInline('Tab has changed, you really want to close it?') ) return if !window.confirm( App.i18n.translateInline('Tab has changed, you really want to close it?') )
# check if active task is closed # check if active task is closed
currentTask = App.TaskManager.get( type, type_id ) currentTask = App.TaskManager.get( key )
tasks = App.TaskManager.all() tasks = App.TaskManager.all()
active_is_closed = false active_is_closed = false
for task in tasks for task in tasks
if currentTask.active && task.type is type && task.type_id.toString() is type_id.toString() if currentTask.active && task.key is key
active_is_closed = true active_is_closed = true
# remove task # remove task
App.TaskManager.remove( type, type_id ) App.TaskManager.remove( key )
@render() @render()
# navigate to next task if needed # navigate to next task if needed
@ -76,7 +75,7 @@ class App.TaskWidget extends App.Controller
for task in tasks for task in tasks
task_last = task task_last = task
if task_last if task_last
worker = App.TaskManager.worker( task_last.type, task_last.type_id ) worker = App.TaskManager.worker( task_last.key )
if worker if worker
@navigate worker.url() @navigate worker.url()
return return
@ -108,5 +107,4 @@ class App.TaskWidget extends App.Controller
level1.push item level1.push item
level1 level1
App.Config.set( 'task', App.TaskWidget, 'Widgets' ) App.Config.set( 'task', App.TaskWidget, 'Widgets' )

View file

@ -9,40 +9,40 @@ class App.TaskManager
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.all() _instance.all()
@add: ( type, type_id, callback, params, to_not_show, state ) -> @add: ( key, callback, params, to_not_show, state ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.add( type, type_id, callback, params, to_not_show, state ) _instance.add( key, callback, params, to_not_show, state )
@get: ( type, type_id ) -> @get: ( key ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.get( type, type_id ) _instance.get( key )
@update: ( type, type_id, params ) -> @update: ( key, params ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.update( type, type_id, params ) _instance.update( key, params )
@remove: ( type, type_id ) -> @remove: ( key ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.remove( type, type_id ) _instance.remove( key )
@notify: ( type, type_id ) -> @notify: ( key ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.notify( type, type_id ) _instance.notify( key )
@reset: -> @reset: ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.reset() _instance.reset()
@worker: ( type, type_id ) -> @worker: ( key ) ->
if _instance == undefined if _instance == undefined
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.worker( type, type_id ) _instance.worker( key )
@workerAll: -> @workerAll: ->
if _instance == undefined if _instance == undefined
@ -61,29 +61,28 @@ class _Singleton extends App.Controller
all: -> all: ->
App.Taskbar.all() App.Taskbar.all()
worker: ( type, type_id ) -> worker: ( key ) ->
key = @keyGenerate(type, type_id)
return @workers[ key ] if @workers[ key ] return @workers[ key ] if @workers[ key ]
return return
workerAll: -> workerAll: ->
@workers @workers
add: ( type, type_id, callback, params, to_not_show = false, state ) -> add: ( key, callback, params, to_not_show = false, state ) ->
active = true active = true
if to_not_show if to_not_show
active = false active = false
# create new task if not exists # create new task if not exists
task = @get( type, type_id ) task = @get( key )
# console.log('add', type, type_id, callback, params, to_not_show, state, task) # console.log('add', key, callback, params, to_not_show, state, task)
if !task if !task
task = new App.Taskbar task = new App.Taskbar
task.load( task.load(
type: type key: key
type_id: type_id
params: params params: params
callback: callback callback: callback
client_id: 123
notify: false notify: false
active: active active: active
) )
@ -92,7 +91,6 @@ class _Singleton extends App.Controller
tasks = @all() tasks = @all()
# empty static content if task is shown # empty static content if task is shown
key = @keyGenerate(type, type_id)
if active if active
@activeTask = key @activeTask = key
$('#content').empty() $('#content').empty()
@ -116,33 +114,37 @@ class _Singleton extends App.Controller
# 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 active
for task in tasks for task in tasks
task_key = @keyGenerate(task.type, task.type_id) if task.key isnt key
if task_key isnt key if task.active
task.active = false task.active = false
console.log(111, 'save')
task.save()
else else
if !task.active
console.log(222, 'save')
task.active = true task.active = true
task.save() task.save()
else else
for task in tasks for task in tasks
task_key = @keyGenerate(task.type, task.type_id) if @activeTask isnt task.key
if @activeTask isnt task_key
if task.active if task.active
task.active = false task.active = false
console.log(333, 'save')
task.save() task.save()
# start worker for task if not exists # start worker for task if not exists
@startController(type, type_id, callback, params, state, key, to_not_show) @startController(key, callback, params, state, to_not_show)
App.Event.trigger 'ui:rerender' App.Event.trigger 'ui:rerender'
App.Event.trigger 'ui:rerender:content' App.Event.trigger 'ui:rerender:content'
return key return key
startController: (type, type_id, callback, params, state, key, to_not_show) => startController: (key, callback, params, state, to_not_show) =>
# console.log('controller started...', callback, type, type_id, params, state) # console.log('controller started...', callback, key, params, state)
# activate controller # activate controller
worker = @worker( type, type_id ) worker = @worker( key )
if worker && worker.activate if worker && worker.activate
worker.activate() worker.activate()
@ -157,7 +159,7 @@ class _Singleton extends App.Controller
# check if we have old state there # check if we have old state there
if !state if !state
oldTask = @get( type, type_id ) oldTask = @get( key )
if oldTask if oldTask
state = oldTask.state state = oldTask.state
params_app['form_state'] = state params_app['form_state'] = state
@ -173,37 +175,37 @@ class _Singleton extends App.Controller
return a return a
get: ( type, type_id ) => get: ( key ) =>
tasks = App.Taskbar.all() tasks = App.Taskbar.all()
for task in tasks for task in tasks
return task if task.type is type && task.type_id.toString() is type_id.toString() return task if task.key is key
return return
# throw "No such task with '#{type}' and '#{type_id}'" # throw "No such task with '#{key}'"
update: ( type, type_id, params ) => update: ( key, params ) =>
task = @get( type, type_id ) task = @get( key )
if !task if !task
throw "No such task with '#{type}' and '#{type_id}' to update" throw "No such task with '#{key}' to update"
for item, value of params for item, value of params
task.updateAttribute(item, value) task.updateAttribute(item, value)
# task.save() # task.save()
remove: ( type, type_id, to_not_show = false ) => remove: ( key, to_not_show = false ) =>
task = @get( type, type_id ) task = @get( key )
if !task if !task
throw "No such task with '#{type}' and '#{type_id}' to remove" throw "No such task with '#{key}' to remove"
worker = @worker( type, type_id ) worker = @worker( key )
if worker && worker.release if worker && worker.release
worker.release() worker.release()
@workersStarted[ @keyGenerate(type, type_id) ] = false @workersStarted[ key ] = false
task.destroy() task.destroy()
App.Event.trigger 'ui:rerender' App.Event.trigger 'ui:rerender'
notify: ( type, type_id ) => notify: ( key ) =>
task = @get( type, type_id ) task = @get( key )
if !task if !task
throw "No such task with '#{type}' and '#{type_id}' to notify" throw "No such task with '#{key}' to notify"
task.notify = true task.notify = true
reset: => reset: =>
@ -212,7 +214,7 @@ class _Singleton extends App.Controller
tasksInitial: => tasksInitial: =>
# reopen tasks # reopen tasks
App.Taskbar.fetch() # App.Taskbar.fetch()
tasks = @all() tasks = @all()
return if !tasks return if !tasks
task_count = 0 task_count = 0
@ -221,9 +223,7 @@ class _Singleton extends App.Controller
@delay( @delay(
=> =>
task = tasks.shift() task = tasks.shift()
@add(task.type, task.type_id, task.callback, task.params, true, task.state) @add(task.key, task.callback, task.params, true, task.state)
task_count * 500 task_count * 500
) )
keyGenerate: ( type, type_id )->
"#{type}_#{type_id}"

View file

@ -1,4 +1,5 @@
class App.Taskbar extends App.Model class App.Taskbar extends App.Model
@configure 'Taskbar', 'type', 'type_id', 'callback', 'state', 'params', 'notify', 'active' @configure 'Taskbar', 'key', 'client_id', 'callback', 'state', 'params', 'notify', 'active'
@extend Spine.Model.Local # @extend Spine.Model.Local
# @url: 'api/taskbar' @extend Spine.Model.Ajax
@url: 'api/taskbar'

View file

@ -1,6 +1,6 @@
<div class="taskbar"> <div class="well taskbar">
<% for item in @item_list: %> <% 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-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> <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-key="<%- item.task.key %>"><span class="task"><%- item.data.head %></span><span data-type="close" class="icon-remove-circle" title="<%- @T('close') %>"></a>
<% end %> <% end %>
<% if !_.isEmpty( @taskBarActions ): %> <% if !_.isEmpty( @taskBarActions ): %>
<div class="taskbar-new"> <div class="taskbar-new">

View file

@ -2,7 +2,7 @@ module ExtraCollection
def session( collections, user ) def session( collections, user )
# all base stuff # all base stuff
collections['Taskbar'] = Taskbar.all collections['Taskbar'] = Taskbar.where( :user_id => user.id )
collections['Role'] = Role.all collections['Role'] = Role.all
collections['Group'] = Group.all collections['Group'] = Group.all

View file

@ -10,47 +10,39 @@ class TaskbarController < ApplicationController
def show def show
taskbar = Taskbar.find( params[:id] ) taskbar = Taskbar.find( params[:id] )
return if !access(taskbar)
if taskbar.user_id != current_user.id
render :json => { :error => 'Not allowed to show this task.' }, :status => :unprocessable_entity
return
end
model_show_render_item(taskbar) model_show_render_item(taskbar)
end end
def create def create
params[:user_id] = current_user.id params[:user_id] = current_user.id
model_create_render(Taskbar,params) model_create_render(Taskbar,params)
end end
def update def update
params[:user_id] = current_user.id
taskbar = Taskbar.find( params[:id] ) taskbar = Taskbar.find( params[:id] )
return if !access(taskbar)
if taskbar.user_id != current_user.id params[:user_id] = current_user.id
render :json => { :error => 'Not allowed to update this task.' }, :status => :unprocessable_entity taskbar.update_attributes!( Taskbar.param_cleanup(params) )
return
end
model_update_render_item(taskbar) model_update_render_item(taskbar)
end end
def destroy def destroy
params[:user_id] = current_user.id
taskbar = Taskbar.find( params[:id] ) taskbar = Taskbar.find( params[:id] )
return if !access(taskbar)
if taskbar.user_id != current_user.id
render :json => { :error => 'Not allowed to delete this task.' }, :status => :unprocessable_entity
return
end
model_destory_render_item()
taskbar.destroy taskbar.destroy
model_destory_render_item()
end
private
def access(taskbar)
if taskbar.user_id != current_user.id
render :json => { :error => 'Not allowed to access this task.' }, :status => :unprocessable_entity
return false
end
return true
end end
end end

View file

@ -4,11 +4,14 @@ class Taskbar < ActiveRecord::Migration
t.column :user_id, :integer, :null => false t.column :user_id, :integer, :null => false
t.column :last_contact, :datetime, :null => false t.column :last_contact, :datetime, :null => false
t.column :client_id, :string, :null => false t.column :client_id, :string, :null => false
t.column :key, :string, :limit => 100, :null => false
t.column :callback, :string, :limit => 100, :null => false
t.column :state, :string, :limit => 8000, :null => true t.column :state, :string, :limit => 8000, :null => true
t.column :params, :string, :limit => 2000, :null => true t.column :params, :string, :limit => 2000, :null => true
t.column :notify, :boolean, :null => false, :default => false
t.column :active, :boolean, :null => false, :default => false
t.timestamps t.timestamps
end end
end end
def down def down