Implemented poc of issue #57 - Keep inactive tickets/cases in a task bar.
This commit is contained in:
parent
e41c964be9
commit
8ec3f8acec
33 changed files with 222 additions and 80 deletions
|
@ -309,6 +309,17 @@ class App.Controller extends Spine.Controller
|
|||
ws_send: (data) ->
|
||||
App.Event.trigger( 'ws:send', JSON.stringify(data) )
|
||||
|
||||
class App.ControllerPermanent extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
$('#content_permanent').show()
|
||||
@el.find('#content').empty()
|
||||
|
||||
class App.ControllerContent extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
$('#content_permanent').hide()
|
||||
|
||||
class App.ControllerModal extends App.Controller
|
||||
className: 'modal hide fade',
|
||||
tag: 'div',
|
||||
|
|
|
@ -106,7 +106,7 @@ class App.ControllerGenericEdit extends App.ControllerModal
|
|||
ui.modalHide()
|
||||
)
|
||||
|
||||
class App.ControllerGenericIndex extends App.Controller
|
||||
class App.ControllerGenericIndex extends App.ControllerContent
|
||||
events:
|
||||
'click [data-type=edit]': 'edit'
|
||||
'click [data-type=destroy]': 'destroy'
|
||||
|
@ -195,7 +195,7 @@ class App.ControllerGenericIndex extends App.Controller
|
|||
genericObject: @genericObject
|
||||
)
|
||||
|
||||
class App.ControllerLevel2 extends App.Controller
|
||||
class App.ControllerLevel2 extends App.ControllerContent
|
||||
events:
|
||||
'click [data-toggle="tabnav"]': 'toggle',
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'click .customer_new': 'userNew'
|
||||
'submit form': 'submit'
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'click [data-type=edit]': 'zoom'
|
||||
'click [data-type=settings]': 'settings'
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class TicketZoom extends App.Controller
|
||||
events:
|
||||
'click .submit': 'update'
|
||||
'click [data-type=reply]': 'reply'
|
||||
|
@ -34,7 +32,11 @@ class Index extends App.Controller
|
|||
@load(cache)
|
||||
update = =>
|
||||
@fetch( @ticket_id, false)
|
||||
@interval( update, 30000, 'zoom_check', 'page' )
|
||||
@interval( update, 30000, @key, 'ticket_zoom' )
|
||||
|
||||
release: =>
|
||||
@clearInterval( @key, 'ticket_zoom' )
|
||||
@el.remove()
|
||||
|
||||
fetch: (ticket_id, force) ->
|
||||
|
||||
|
@ -143,7 +145,7 @@ class Index extends App.Controller
|
|||
)
|
||||
|
||||
new App.ControllerForm(
|
||||
el: @el.find('#form-ticket-update')
|
||||
el: @el.find('[data-id="form-ticket-update"]')
|
||||
form_id: @form_id
|
||||
model:
|
||||
configure_attributes: @configure_attributes_ticket
|
||||
|
@ -153,7 +155,7 @@ class Index extends App.Controller
|
|||
)
|
||||
|
||||
new App.ControllerForm(
|
||||
el: @el.find('#form-article-update')
|
||||
el: @el.find('[data-id="form-article-update"]')
|
||||
form_id: @form_id
|
||||
model:
|
||||
configure_attributes: @configure_attributes_article
|
||||
|
@ -184,7 +186,7 @@ class Index extends App.Controller
|
|||
# start customer info controller
|
||||
if !@isRole('Customer')
|
||||
new App.UserInfo(
|
||||
el: @el.find('#customer_info')
|
||||
el: @el.find('[data-id="customer_info"]')
|
||||
user_id: @ticket.customer_id
|
||||
ticket: @ticket
|
||||
)
|
||||
|
@ -192,7 +194,7 @@ class Index extends App.Controller
|
|||
# start action controller
|
||||
if !@isRole('Customer')
|
||||
new TicketActionRow(
|
||||
el: @el.find('#action_info')
|
||||
el: @el.find('[data-id="action_info"]')
|
||||
ticket: @ticket
|
||||
zoom: @
|
||||
)
|
||||
|
@ -200,7 +202,7 @@ class Index extends App.Controller
|
|||
# start tag controller
|
||||
if !@isRole('Customer')
|
||||
new App.TagWidget(
|
||||
el: @el.find('#tag_info')
|
||||
el: @el.find('[data-id="tag_info"]')
|
||||
object_type: 'Ticket'
|
||||
object: @ticket
|
||||
)
|
||||
|
@ -208,7 +210,7 @@ class Index extends App.Controller
|
|||
# start link info controller
|
||||
if !@isRole('Customer')
|
||||
new App.LinkInfo(
|
||||
el: @el.find('#link_info')
|
||||
el: @el.find('[data-id="link_info"]')
|
||||
object_type: 'Ticket'
|
||||
object: @ticket
|
||||
)
|
||||
|
@ -216,7 +218,7 @@ class Index extends App.Controller
|
|||
# show text module UI
|
||||
if !@isRole('Customer')
|
||||
new App.TextModuleUI(
|
||||
el: @el.find('#text_module')
|
||||
el: @el.find('[data-id="text_module"]')
|
||||
data:
|
||||
ticket: @ticket
|
||||
)
|
||||
|
@ -580,6 +582,12 @@ class TicketActionRow extends App.Controller
|
|||
e.preventDefault()
|
||||
new App.TicketCustomer( ticket_id: @ticket.id, zoom: @zoom )
|
||||
|
||||
App.Config.set( 'ticket/zoom/:ticket_id', Index, 'Routes' )
|
||||
App.Config.set( 'ticket/zoom/:ticket_id/nav/:nav', Index, 'Routes' )
|
||||
App.Config.set( 'ticket/zoom/:ticket_id/:article_id', Index, 'Routes' )
|
||||
class TicketZoomRouter extends App.ControllerPermanent
|
||||
constructor: (params) ->
|
||||
super
|
||||
@log 'zoom router', params
|
||||
App.TaskManager.add( 'Ticket', @ticket_id, { callback: TicketZoom } )
|
||||
|
||||
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/:article_id', TicketZoomRouter, 'Routes' )
|
|
@ -1,5 +1,3 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.ControllerLevel2
|
||||
# toggleable: true
|
||||
toggleable: false
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class App.ChatWidget extends App.Controller
|
||||
events:
|
||||
'submit #chat_form': 'submitMessage'
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
class App.ContentPermanentWidget extends App.ControllerPermanent
|
||||
className: 'container aaa'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
App.Config.set( 'content_permanent', App.ContentPermanentWidget, 'Widgets' )
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'submit form': 'submit',
|
||||
'click .submit': 'submit',
|
||||
|
@ -112,7 +110,6 @@ class Index extends App.Controller
|
|||
|
||||
# generate form
|
||||
configure_attributes = [
|
||||
# { name: 'customer_id', display: 'Customer', tag: 'autocompletion', type: 'text', limit: 100, null: false, relation: 'User', class: 'span7', autocapitalize: false, help: 'Select the customer of the Ticket or create one.', link: '<a href="" class="customer_new">»</a>', callback: @userInfo },
|
||||
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: groupFilter, nulloption: true, relation: 'Group', default: defaults['group_id'], class: 'span7', },
|
||||
# { name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', },
|
||||
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: false, default: defaults['subject'], class: 'span7', },
|
||||
|
@ -120,7 +117,7 @@ class Index extends App.Controller
|
|||
# { name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['ticket_state_id'], translate: true, class: 'medium' },
|
||||
# { name: 'ticket_priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['ticket_priority_id'], translate: true, class: 'medium' },
|
||||
]
|
||||
@html App.view('agent_ticket_create')( head: 'New Ticket' )
|
||||
@html App.view('customer_ticket_create')( head: 'New Ticket' )
|
||||
|
||||
new App.ControllerForm(
|
||||
el: @el.find('#form_create')
|
||||
|
@ -146,7 +143,6 @@ class Index extends App.Controller
|
|||
|
||||
# get params
|
||||
params = @formParam(e.target)
|
||||
@log 'CustomerTicketCreate', 'notice', 'params', params
|
||||
|
||||
# set customer id
|
||||
params.customer_id = @Session.get('id')
|
||||
|
@ -183,7 +179,6 @@ class Index extends App.Controller
|
|||
ticket_article_sender_id: sender.id
|
||||
form_id: @form_id
|
||||
}
|
||||
# console.log('params', params)
|
||||
|
||||
object.load(params)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class App.LinkInfo extends App.Controller
|
||||
events:
|
||||
'click [data-type=add]': 'add',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'submit #login': 'login',
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
@signout()
|
||||
|
|
|
@ -6,7 +6,7 @@ $.fn.item = ->
|
|||
elementID or= $(@).parents('[data-id]').data('id')
|
||||
Note.find(elementID)
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'click [data-type=network-new]': 'network_new'
|
||||
'click [data-type=network-edit]': 'network_edit'
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'click .action': 'action'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
className: 'container'
|
||||
|
||||
events:
|
||||
|
@ -66,7 +66,7 @@ class Index extends App.Controller
|
|||
|
||||
App.Config.set( 'reset_password', Index, 'Routes' )
|
||||
|
||||
class Verify extends App.Controller
|
||||
class Verify extends App.ControllerContent
|
||||
className: 'container'
|
||||
|
||||
events:
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
className: 'container signup'
|
||||
|
||||
events:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
42
app/assets/javascripts/app/controllers/task_widget.js.coffee
Normal file
42
app/assets/javascripts/app/controllers/task_widget.js.coffee
Normal file
|
@ -0,0 +1,42 @@
|
|||
class App.TaskWidget extends App.Controller
|
||||
events:
|
||||
'click [data-type="close"]': 'remove'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
# rerender view
|
||||
App.Event.bind 'ui:rerender', (data) =>
|
||||
@render()
|
||||
|
||||
# rebuild chat widget
|
||||
App.Event.bind 'auth', (user) =>
|
||||
App.TaskManager.reset()
|
||||
@el.html('')
|
||||
|
||||
render: ->
|
||||
|
||||
return if _.isEmpty( @Session.all() )
|
||||
|
||||
tasks = App.TaskManager.all()
|
||||
item_list = []
|
||||
for key, task of tasks
|
||||
item = {}
|
||||
item.key = key
|
||||
item.data = App[task.type].find( task.type_id )
|
||||
item_list.push item
|
||||
|
||||
@html App.view('task_widget')(
|
||||
item_list: item_list
|
||||
)
|
||||
|
||||
remove: (e) =>
|
||||
e.preventDefault()
|
||||
key = $(e.target).parent().data('id')
|
||||
App.TaskManager.remove( key )
|
||||
@render()
|
||||
if _.isEmpty( App.TaskManager.all() )
|
||||
@navigate '#'
|
||||
|
||||
App.Config.set( 'task', App.TaskWidget, 'Widgets' )
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
@ -30,5 +28,4 @@ class Index extends App.Controller
|
|||
)
|
||||
|
||||
App.Config.set( 'users', Index, 'Routes' )
|
||||
|
||||
App.Config.set( 'User', { prio: 1000, parent: '#admin', name: 'Users', target: '#users', role: ['Admin'] }, 'NavBar' )
|
||||
|
|
|
@ -113,12 +113,19 @@ class App.Auth
|
|||
@_logout: (data) ->
|
||||
App.Log.log 'Auth', 'notice', '_logout'
|
||||
|
||||
# empty session
|
||||
App.Session.init()
|
||||
|
||||
# update websocket auth info
|
||||
App.WebSocket.auth()
|
||||
|
||||
# clear store
|
||||
App.Store.clear('all')
|
||||
|
||||
# rebuild navbar
|
||||
App.Event.trigger( 'auth' )
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
|
||||
@_loginError: (xhr, statusText, error) ->
|
||||
App.Log.log 'Auth', 'notice', '_loginError:error'
|
||||
|
||||
|
@ -129,4 +136,8 @@ class App.Auth
|
|||
App.WebSocket.auth()
|
||||
|
||||
# clear store
|
||||
App.Store.clear('all')
|
||||
App.Store.clear('all')
|
||||
|
||||
# rebuild navbar
|
||||
App.Event.trigger( 'auth' )
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class App.i18n
|
||||
_instance = undefined
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
class App.Run extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
class App.TaskManager
|
||||
_instance = undefined
|
||||
|
||||
@init: ->
|
||||
_instance ?= new _Singleton
|
||||
|
||||
@all: ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _Singleton
|
||||
_instance.all()
|
||||
|
||||
@add: ( type, type_id, params ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _Singleton
|
||||
_instance.add( type, type_id, params )
|
||||
|
||||
@remove: ( key ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _Singleton
|
||||
_instance.remove( key )
|
||||
|
||||
@reset: ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _Singleton
|
||||
_instance.reset()
|
||||
|
||||
class _Singleton extends Spine.Module
|
||||
@include App.Log
|
||||
|
||||
constructor: ->
|
||||
@tasks = {}
|
||||
@task_count = 0
|
||||
|
||||
all: ->
|
||||
@tasks
|
||||
|
||||
add: ( type, type_id, params ) ->
|
||||
for key, task of @tasks
|
||||
if task.type is type && task.type_id is type_id
|
||||
$('#content').empty()
|
||||
$('.content_permanent').hide()
|
||||
$('#content_permanent_' + key ).show()
|
||||
return key
|
||||
|
||||
@task_count++
|
||||
|
||||
$('#content').empty()
|
||||
$('#content_permanent').append('<div id="content_permanent_' + @task_count + '" class="content_permanent"></div>')
|
||||
$('.content_permanent').hide()
|
||||
$('#content_permanent_' + @task_count ).show()
|
||||
a = new params.callback( el: $('#content_permanent_' + @task_count ), ticket_id: type_id )
|
||||
task =
|
||||
type: type
|
||||
type_id: type_id
|
||||
params: params
|
||||
worker: a
|
||||
@tasks[@task_count] = task
|
||||
App.Event.trigger 'ui:rerender'
|
||||
|
||||
@task_count
|
||||
|
||||
remove: ( key ) =>
|
||||
if @tasks[key]
|
||||
console.log('rrrelease', @tasks[key], @tasks[key].worker)
|
||||
@tasks[key].worker.release()
|
||||
delete @tasks[key]
|
||||
App.Event.trigger 'ui:rerender'
|
||||
|
||||
reset: =>
|
||||
@tasks = {}
|
||||
App.Event.trigger 'ui:rerender'
|
||||
|
|
@ -83,8 +83,8 @@
|
|||
</div>
|
||||
<div class="span8 well-muted article-message">
|
||||
<form class="form-stacked pull-left">
|
||||
<div id="form-ticket-update"></div>
|
||||
<div id="form-article-update"></div>
|
||||
<div data-id="form-ticket-update"></div>
|
||||
<div data-id="form-article-update"></div>
|
||||
<button type="submit" class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -93,11 +93,11 @@
|
|||
</div>
|
||||
|
||||
<div class="span3">
|
||||
<div id="customer_info"></div>
|
||||
<div id="action_info"></div>
|
||||
<div id="tag_info"></div>
|
||||
<div id="link_info"></div>
|
||||
<div id="text_module"></div>
|
||||
<div data-id="customer_info"></div>
|
||||
<div data-id="action_info"></div>
|
||||
<div data-id="tag_info"></div>
|
||||
<div data-id="link_info"></div>
|
||||
<div data-id="text_module"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
5
app/assets/javascripts/app/views/task_widget.jst.eco
Normal file
5
app/assets/javascripts/app/views/task_widget.jst.eco
Normal file
|
@ -0,0 +1,5 @@
|
|||
<div class="well" style="position: fixed; top: 40px; width: 100%; padding: 5px;">
|
||||
<% for item in @item_list: %>
|
||||
<span class="label label-success" data-id="<%- item.key %>"><span class="task"><a style="color: #ffffff;" href="#ticket/zoom/<%- item.data.id %>" title="<%= item.data.title %>"><%= item.data.title %></a></span> <a href="#" data-type="close" class="icon-remove-circle" title="<%- @T('close') %>"></a></span>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,5 +1,5 @@
|
|||
body {
|
||||
padding-top:50px;
|
||||
padding-top:74px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,17 @@ table th, table td {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.task {
|
||||
display: inline-block;
|
||||
max-width: 120px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.task > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.max-size-scroll {
|
||||
max-height: 240px;
|
||||
overflow-y: scroll;
|
||||
|
@ -87,6 +98,16 @@ h4 {
|
|||
padding: 10px 12px 10px;
|
||||
}
|
||||
|
||||
/*
|
||||
.container,
|
||||
*/
|
||||
.navbar-static-top .container,
|
||||
.navbar-fixed-top .container,
|
||||
.navbar-fixed-bottom .container {
|
||||
width: 96%;
|
||||
min-width: 940px;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootstrap changes
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue