Moved to new task bar.
This commit is contained in:
parent
f11a12f98e
commit
6db776e722
6 changed files with 157 additions and 393 deletions
|
@ -1,6 +1,6 @@
|
|||
class App.Navigation extends App.Controller
|
||||
className: 'navigation flex vertical'
|
||||
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
@ -201,6 +201,11 @@ class App.Navigation extends App.Controller
|
|||
@delay( searchFunction, 220, 'search' )
|
||||
)
|
||||
|
||||
|
||||
if !@taskBar
|
||||
@taskBar = true
|
||||
new App.TaskbarWidget( el: @el.find('.tasks') )
|
||||
|
||||
getItems: (data) ->
|
||||
navbar = _.values(data.navbar)
|
||||
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
class App.TaskWidget extends App.Controller
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
# render on generic ui call
|
||||
@bind 'ui:rerender', => @render()
|
||||
|
||||
# render on login
|
||||
@bind 'auth:login', => @render()
|
||||
|
||||
# reset current tasks on logout
|
||||
@bind 'auth:logout', => @el.html('')
|
||||
|
||||
# only do take over check after spool messages are finised
|
||||
App.Event.bind(
|
||||
'spool:sent'
|
||||
=>
|
||||
@spoolSent = true
|
||||
|
||||
# broadcast to other browser instance
|
||||
App.WebSocket.send(
|
||||
action: 'broadcast'
|
||||
event: 'session:takeover'
|
||||
spool: true
|
||||
recipient:
|
||||
user_id: [ App.Session.get( 'id' ) ]
|
||||
data:
|
||||
taskbar_id: App.TaskManager.TaskbarId()
|
||||
)
|
||||
'task'
|
||||
)
|
||||
|
||||
# session take over message
|
||||
App.Event.bind(
|
||||
'session:takeover'
|
||||
(data) =>
|
||||
|
||||
# only if spool messages are already sent
|
||||
return if !@spoolSent
|
||||
|
||||
# check if error message is already shown
|
||||
if !@error
|
||||
|
||||
# only if new client id isnt own client id
|
||||
if data.taskbar_id isnt App.TaskManager.TaskbarId()
|
||||
@error = new App.SessionMessage(
|
||||
title: 'Session'
|
||||
message: 'Session taken over... please reload page or work with other browser window.'
|
||||
keyboard: false
|
||||
backdrop: true
|
||||
close: true
|
||||
button: 'Reload application'
|
||||
forceReload: true
|
||||
)
|
||||
@disconnectClient()
|
||||
'task'
|
||||
)
|
||||
|
||||
render: ->
|
||||
return if _.isEmpty( @Session.all() )
|
||||
|
||||
@html App.view('task_widget')(
|
||||
taskBarActions: @_getTaskActions()
|
||||
)
|
||||
@el.find('.taskbar-items').html('')
|
||||
new Taskbar(
|
||||
el: @el.find('.taskbar-items')
|
||||
)
|
||||
|
||||
_getTaskActions: ->
|
||||
roles = App.Session.get( 'roles' )
|
||||
navbar = _.values( @Config.get( 'TaskActions' ) )
|
||||
level1 = []
|
||||
|
||||
for item in navbar
|
||||
if typeof item.callback is 'function'
|
||||
data = item.callback() || {}
|
||||
for key, value of data
|
||||
item[key] = value
|
||||
if !item.parent
|
||||
match = 0
|
||||
if !item.role
|
||||
match = 1
|
||||
if !roles && item.role
|
||||
match = _.include( item.role, 'Anybody' )
|
||||
if roles
|
||||
for role in roles
|
||||
if !match
|
||||
match = _.include( item.role, role.name )
|
||||
|
||||
if match
|
||||
level1.push item
|
||||
level1
|
||||
|
||||
class Taskbar extends App.Controller
|
||||
events:
|
||||
'click [data-type="close"]': 'remove'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
# on window resize
|
||||
resizeTasksDelay = =>
|
||||
App.Delay.set( @resizeTasks, 60, 'resizeTasks', 'task' )
|
||||
$(window).off( 'resize.taskbar' ).on( 'resize.taskbar', resizeTasksDelay )
|
||||
|
||||
# render view
|
||||
@bind 'task:render', => @render()
|
||||
|
||||
# reset current tasks on logout
|
||||
@bind 'auth:logout', => @el.html('')
|
||||
|
||||
render: ->
|
||||
return if _.isEmpty( @Session.all() )
|
||||
|
||||
tasks = App.TaskManager.all()
|
||||
item_list = []
|
||||
for task in tasks
|
||||
|
||||
# collect meta data of task for task bar item
|
||||
data =
|
||||
url: '#'
|
||||
id: false
|
||||
title: App.i18n.translateInline('Loading...')
|
||||
head: App.i18n.translateInline('Loading...')
|
||||
worker = App.TaskManager.worker( task.key )
|
||||
if worker
|
||||
meta = worker.meta()
|
||||
|
||||
# apply meta data of controller
|
||||
if meta
|
||||
for key, value of meta
|
||||
data[key] = value
|
||||
|
||||
# collect new task bar items
|
||||
item = {}
|
||||
item.task = task
|
||||
item.data = data
|
||||
item_list.push item
|
||||
|
||||
# set title
|
||||
if task.active
|
||||
@title data.title
|
||||
|
||||
@html App.view('task_widget_tasks')(
|
||||
item_list: item_list
|
||||
)
|
||||
|
||||
@resizeTasks()
|
||||
|
||||
dndOptions =
|
||||
tolerance: 'pointer'
|
||||
distance: 15
|
||||
opacity: 0.6
|
||||
forcePlaceholderSize: true
|
||||
items: '> a'
|
||||
update: =>
|
||||
items = @el.find('> a')
|
||||
order = []
|
||||
for item in items
|
||||
key = $(item).data('key')
|
||||
if !key
|
||||
throw "No such key attributes found for task item"
|
||||
order.push key
|
||||
App.TaskManager.reorder( order )
|
||||
|
||||
@el.sortable( dndOptions )
|
||||
|
||||
remove: (e, key = false, force = false) =>
|
||||
e.preventDefault()
|
||||
if !key
|
||||
key = $(e.target).parent().data('key')
|
||||
if !key
|
||||
throw "No such key attributes found for task item"
|
||||
|
||||
# check if input has changed
|
||||
worker = App.TaskManager.worker( key )
|
||||
if !force && worker && worker.changed
|
||||
if worker.changed()
|
||||
new Remove(
|
||||
key: key
|
||||
ui: @
|
||||
)
|
||||
return
|
||||
|
||||
# check if active task is closed
|
||||
currentTask = App.TaskManager.get( key )
|
||||
tasks = App.TaskManager.all()
|
||||
active_is_closed = false
|
||||
for task in tasks
|
||||
if currentTask.active && task.key is key
|
||||
active_is_closed = true
|
||||
|
||||
# remove task
|
||||
App.TaskManager.remove( key )
|
||||
|
||||
@resizeTasks()
|
||||
|
||||
# navigate to next task if needed
|
||||
tasks = App.TaskManager.all()
|
||||
if active_is_closed && !_.isEmpty( tasks )
|
||||
task_last = undefined
|
||||
for task in tasks
|
||||
task_last = task
|
||||
if task_last
|
||||
worker = App.TaskManager.worker( task_last.key )
|
||||
if worker
|
||||
@navigate worker.url()
|
||||
return
|
||||
if _.isEmpty( tasks )
|
||||
@navigate '#'
|
||||
|
||||
resizeTasks: ->
|
||||
width = $('#task .taskbar-items').width()# - $('#task .taskbar-new').width() - 200
|
||||
task_count = App.TaskManager.all().length
|
||||
task_size = ( width / task_count ) - 40
|
||||
elementsOversize = 0
|
||||
elementsOversizeLeftTotal = 0
|
||||
$('#task .task').each(
|
||||
(position, element) ->
|
||||
widthTask = $(element).width()
|
||||
if widthTask > task_size
|
||||
elementsOversize++
|
||||
else
|
||||
elementsOversizeLeftTotal += task_size - widthTask
|
||||
)
|
||||
|
||||
addOversize = elementsOversizeLeftTotal / elementsOversize
|
||||
task_size += addOversize
|
||||
if task_size < 40
|
||||
$('#task .task').css('max-width', '40px')
|
||||
else if task_size < 130
|
||||
$('#task .task').css('max-width', task_size + 'px')
|
||||
else
|
||||
$('#task .task').css('max-width', '130px')
|
||||
|
||||
class Remove extends App.ControllerModal
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
render: ->
|
||||
@html App.view('modal')(
|
||||
title: 'Confirm'
|
||||
message: 'Tab has changed, you really want to close it?'
|
||||
close: true
|
||||
button: 'Close'
|
||||
)
|
||||
@modalShow(
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
)
|
||||
|
||||
submit: (e) =>
|
||||
@modalHide()
|
||||
@ui.remove(e, @key, true)
|
||||
|
||||
App.Config.set( 'task', App.TaskWidget, 'Widgets' )
|
136
app/assets/javascripts/app/controllers/taskbar_widget.js.coffee
Normal file
136
app/assets/javascripts/app/controllers/taskbar_widget.js.coffee
Normal file
|
@ -0,0 +1,136 @@
|
|||
class App.TaskbarWidget extends App.Controller
|
||||
events:
|
||||
'click [data-type="close"]': 'remove'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
# render on generic ui call
|
||||
@bind 'ui:rerender', => @render()
|
||||
|
||||
# render view
|
||||
@bind 'task:render', => @render()
|
||||
|
||||
# render on login
|
||||
@bind 'auth:login', => @render()
|
||||
|
||||
# reset current tasks on logout
|
||||
@bind 'auth:logout', => @render()
|
||||
|
||||
render: ->
|
||||
return if _.isEmpty( @Session.all() )
|
||||
|
||||
tasks = App.TaskManager.all()
|
||||
item_list = []
|
||||
for task in tasks
|
||||
|
||||
# collect meta data of task for task bar item
|
||||
data =
|
||||
url: '#'
|
||||
id: false
|
||||
title: App.i18n.translateInline('Loading...')
|
||||
head: App.i18n.translateInline('Loading...')
|
||||
worker = App.TaskManager.worker( task.key )
|
||||
if worker
|
||||
meta = worker.meta()
|
||||
|
||||
# apply meta data of controller
|
||||
if meta
|
||||
for key, value of meta
|
||||
data[key] = value
|
||||
|
||||
# collect new task bar items
|
||||
item = {}
|
||||
item.task = task
|
||||
item.data = data
|
||||
item_list.push item
|
||||
|
||||
# set title
|
||||
if task.active
|
||||
@title data.title
|
||||
|
||||
@html App.view('task_widget_tasks')(
|
||||
item_list: item_list
|
||||
)
|
||||
|
||||
dndOptions =
|
||||
tolerance: 'pointer'
|
||||
distance: 15
|
||||
opacity: 0.6
|
||||
forcePlaceholderSize: true
|
||||
items: '> a'
|
||||
update: =>
|
||||
items = @el.find('> a')
|
||||
order = []
|
||||
for item in items
|
||||
key = $(item).data('key')
|
||||
if !key
|
||||
throw "No such key attributes found for task item"
|
||||
order.push key
|
||||
App.TaskManager.reorder( order )
|
||||
|
||||
@el.sortable( dndOptions )
|
||||
|
||||
remove: (e, key = false, force = false) =>
|
||||
e.preventDefault()
|
||||
if !key
|
||||
key = $(e.target).parent().parent().data('key')
|
||||
if !key
|
||||
throw "No such key attributes found for task item"
|
||||
|
||||
# check if input has changed
|
||||
worker = App.TaskManager.worker( key )
|
||||
if !force && worker && worker.changed
|
||||
if worker.changed()
|
||||
new Remove(
|
||||
key: key
|
||||
ui: @
|
||||
)
|
||||
return
|
||||
|
||||
# check if active task is closed
|
||||
currentTask = App.TaskManager.get( key )
|
||||
tasks = App.TaskManager.all()
|
||||
active_is_closed = false
|
||||
for task in tasks
|
||||
if currentTask.active && task.key is key
|
||||
active_is_closed = true
|
||||
|
||||
# remove task
|
||||
App.TaskManager.remove( key )
|
||||
|
||||
# navigate to next task if needed
|
||||
tasks = App.TaskManager.all()
|
||||
if active_is_closed && !_.isEmpty( tasks )
|
||||
task_last = undefined
|
||||
for task in tasks
|
||||
task_last = task
|
||||
if task_last
|
||||
worker = App.TaskManager.worker( task_last.key )
|
||||
if worker
|
||||
@navigate worker.url()
|
||||
return
|
||||
if _.isEmpty( tasks )
|
||||
@navigate '#'
|
||||
|
||||
class Remove extends App.ControllerModal
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
render: ->
|
||||
@html App.view('modal')(
|
||||
title: 'Confirm'
|
||||
message: 'Tab has changed, you really want to close it?'
|
||||
close: true
|
||||
button: 'Close'
|
||||
)
|
||||
@modalShow(
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
)
|
||||
|
||||
submit: (e) =>
|
||||
@modalHide()
|
||||
@ui.remove(e, @key, true)
|
|
@ -147,7 +147,7 @@ class _taskManagerSingleton extends App.Controller
|
|||
|
||||
# create div for permanent content
|
||||
if !$("#content_permanent")[0]
|
||||
$('#app section').append('<div id="content_permanent" class="content"></div>')
|
||||
$('#app').append('<div id="content_permanent" class="content"></div>')
|
||||
|
||||
# empty static content if task is shown
|
||||
if active
|
||||
|
|
|
@ -2,22 +2,16 @@
|
|||
<input id="global-search" class="flex" type="search" autocomplete="off">
|
||||
<div class="logo" title="<%- @C( 'product_name' ) %>"></div>
|
||||
<ul id="global-search-result" class="dropdown-menu" role="menu">
|
||||
|
||||
|
||||
<li class="divider" style="padding: 2px 10px; height: auto; margin: 4px 0px;">Ticket</li>
|
||||
|
||||
|
||||
<li><a href="#ticket/zoom/1" class="ticket-popover" data-id="1" data-original-title="" title="">#10001 - Welcome to Zammad! - 5 d 19 h</a></li>
|
||||
|
||||
|
||||
<li class="divider" style="padding: 2px 10px; height: auto; margin: 4px 0px;">User</li>
|
||||
|
||||
<li class="divider" style="padding: 2px 10px; height: auto; margin: 4px 0px;">User</li>
|
||||
<li><a href="#user/zoom/2" class="user-popover" data-id="2" data-original-title="" title="">Nicole Braun</a></li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</form>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dashboard active"><a href="#">Dashboard</a></li>
|
||||
<% for item in @navbar_left: %>
|
||||
<% if item.child: %>
|
||||
<li class="dropdown <% if @open_tab[item.target] : %>open<% end %>">
|
||||
|
@ -35,130 +29,14 @@
|
|||
</ul>
|
||||
</li>
|
||||
<% else: %>
|
||||
<li class="overviews <% if @active_tab[item.target] : %>active<% end %>"><a href="<%= item.target %>"><%- @T( item.name ) %></a></li>
|
||||
<li class="<%= item.class %> <% if @active_tab[item.target] : %>active<% end %>"><a href="<%= item.target %>"><%- @T( item.name ) %></a></li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<li class="customers"><a href="#">Customers</a></li>
|
||||
<li class="customers"><a href="#to_somewhere">Customers</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tasks flex">
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Klischee nicht sauber ausgearbeitet</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="modified priority icon"></div>
|
||||
<div class="name contain-text flex">Probleme mit Siebdruck</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-3 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="modified priority icon"></div>
|
||||
<div class="name contain-text flex">Tonerstaub unter Glasplatte</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="modified priority icon"></div>
|
||||
<div class="name contain-text flex">Super Service!</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Probleme mit Siebdruck</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-3 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Tonerstaub unter Glasplatte</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Super Service!</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Probleme mit Siebdruck</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-3 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-2 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Tonerstaub unter Glasplatte</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Programmfehler</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task level-1 horizontal center">
|
||||
<div class="priority icon"></div>
|
||||
<div class="name contain-text flex">Super Service!</div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tasks flex"></div>
|
||||
|
||||
<script>
|
||||
$('.task').click(function(){ $(this).toggleClass('active') })
|
||||
</script>
|
||||
<!-- <div class="spinner"></div> -->
|
||||
|
||||
<% if !_.isEmpty(@user): %>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
<% for item in @item_list: %>
|
||||
<a href="<%- item.data.url %>" title="<%= item.data.title %>" class="btn btn-small <% if item.task.active: %>active btn-primary<% 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="glyphicon glyphicon-remove-circle" title="<%- @T('close') %>"></a>
|
||||
<% end %>
|
||||
<a href="<%- item.data.url %>" title="<%= item.data.title %>" class="task <%= item.data.class %> horizontal center <% if item.task.active: %>active<% end %>" data-key="<%- item.task.key %>">
|
||||
<div class="priority icon <% if item.task.notify: %>modified<% end %>"></div>
|
||||
<div class="name contain-text flex"><%= item.data.head %></div>
|
||||
<div class="close-task button horizontal centered">
|
||||
<div class="close-task icon" title="<%- @T('close') %>" data-type="close"></div>
|
||||
</div>
|
||||
</a>
|
||||
<% end %>
|
Loading…
Reference in a new issue