Splited ticket sidebar into separate backend to make it pluggable.

This commit is contained in:
Martin Edenhofer 2017-03-15 11:29:56 +01:00
parent 6ce85513f9
commit 22e8836cff
10 changed files with 272 additions and 202 deletions

View file

@ -95,8 +95,8 @@ class App.ControllerGenericEdit extends App.ControllerModal
class App.ControllerGenericIndex extends App.Controller
events:
'click [data-type=edit]': 'edit'
'click [data-type=new]': 'new'
'click .js-description': 'description'
'click [data-type=new]': 'new'
'click .js-description': 'description'
constructor: ->
super
@ -621,10 +621,10 @@ class App.ActionRow extends App.Controller
for item in @items
do (item) =>
@$('[data-type="' + item.name + '"]').on(
'click',
(e) ->
'click'
(e) =>
e.preventDefault()
item.callback()
item.callback(@el)
)
class App.Sidebar extends App.Controller
@ -657,24 +657,25 @@ class App.Sidebar extends App.Controller
@toggleTabAction(name)
render: =>
@html App.view('generic/sidebar_tabs')
localEl = $(App.view('generic/sidebar_tabs')(
items: @items
scrollbarWidth: App.Utils.getScrollBarWidth()
))
# init content callback
for item in @items
area = localEl.filter('.sidebar[data-tab="' + item.name + '"]')
if item.callback
item.callback( @$( '.sidebar[data-tab="' + item.name + '"] .sidebar-content' ) )
# add item acctions
for item in @items
item.callback( area.find('.sidebar-content') )
if item.actions
new App.ActionRow(
el: @$('.sidebar[data-tab="' + item.name + '"] .js-actions')
el: area.find('.js-actions')
items: item.actions
type: 'small'
)
@html localEl
toggleDropdown: (e) ->
e.stopPropagation()
$(e.currentTarget).next('.js-actions').find('.dropdown-toggle').dropdown('toggle')

View file

@ -486,14 +486,10 @@ class App.TicketZoom extends App.Controller
)
if @sidebar
# update tags
if @sidebar.tagWidget
@sidebar.tagWidget.reload(@tags)
# update links
if @sidebar.linkWidget
@sidebar.linkWidget.reload(@links)
@sidebar.reload(
tags: @tags
links: @links
)
if !@initDone
if @article_id
@ -681,12 +677,12 @@ class App.TicketZoom extends App.Controller
callback:
tagAdd: (tag) =>
return if !@sidebar
return if !@sidebar.tagWidget
@sidebar.tagWidget.add(tag)
return if !@sidebar.reload
@sidebar.reload(tagAdd: tag)
tagRemove: (tag) =>
return if !@sidebar
return if !@sidebar.tagWidget
@sidebar.tagWidget.remove(tag)
return if !@sidebar.reload
@sidebar.reload(tagRemove: tag)
)
# set defaults

View file

@ -1,182 +1,30 @@
class Edit extends App.ObserverController
model: 'Ticket'
observeNot:
created_at: true
updated_at: true
globalRerender: false
render: (ticket, diff) =>
defaults = ticket.attributes()
delete defaults.article # ignore article infos
taskState = @taskGet('ticket')
if !_.isEmpty(taskState)
defaults = _.extend(defaults, taskState)
new App.ControllerForm(
elReplace: @el
model: App.Ticket
screen: 'edit'
handlers: [
@ticketFormChanges
]
filter: @formMeta.filter
params: defaults
#bookmarkable: true
)
@markForm(true)
return if @resetBind
@resetBind = true
@bind('ui::ticket::taskReset', (data) =>
return if data.ticket_id.toString() isnt ticket.id.toString()
@render(ticket)
)
class App.TicketZoomSidebar extends App.ObserverController
model: 'Ticket'
observe:
customer_id: true
organization_id: true
reload: (args) =>
for key, backend of @sidebarBackends
if backend && backend.reload
backend.reload(args)
render: (ticket) =>
editTicket = (el) =>
el.append(App.view('ticket_zoom/sidebar_ticket')())
@edit = new Edit(
object_id: ticket.id
el: el.find('.edit')
taskGet: @taskGet
formMeta: @formMeta
markForm: @markForm
@sidebarBackends = {}
@sidebarItems = []
sidebarBackends = App.Config.get('TicketZoomSidebar')
keys = _.keys(sidebarBackends).sort()
for key in keys
@sidebarBackends[key] = new sidebarBackends[key](
ticket: ticket
taskGet: @taskGet
formMeta: @formMeta
markForm: @markForm
)
item = @sidebarBackends[key].sidebarItem()
if item
@sidebarItems.push item
if @permissionCheck('ticket.agent')
@tagWidget = new App.WidgetTag(
el: @el.find('.tags')
object_type: 'Ticket'
object: ticket
tags: @tags
)
@linkWidget = new App.WidgetLink(
el: @el.find('.links')
object_type: 'Ticket'
object: ticket
links: @links
)
@timeUnitWidget = new App.TicketZoomTimeUnit(
el: @el.find('.js-timeUnit')
object_id: ticket.id
)
showTicketHistory = =>
new App.TicketHistory(
ticket_id: ticket.id
container: @el.closest('.content')
)
showTicketMerge = =>
new App.TicketMerge(
ticket: ticket
task_key: @task_key
container: @el.closest('.content')
)
changeCustomer = (e, el) =>
new App.TicketCustomer(
ticket_id: ticket.id
container: @el.closest('.content')
)
@sidebarItems = [
{
head: 'Ticket'
name: 'ticket'
icon: 'message'
callback: editTicket
}
]
if @permissionCheck('ticket.agent')
@sidebarItems[0]['actions'] = [
{
name: 'ticket-history'
title: 'History'
callback: showTicketHistory
},
{
name: 'ticket-merge'
title: 'Merge'
callback: showTicketMerge
},
{
title: 'Change Customer'
name: 'customer-change'
callback: changeCustomer
},
]
if @permissionCheck('ticket.agent')
editCustomer = (e, el) =>
new App.ControllerGenericEdit(
id: ticket.customer_id
genericObject: 'User'
screen: 'edit'
pageData:
title: 'Users'
object: 'User'
objects: 'Users'
container: @el.closest('.content')
)
showCustomer = (el) ->
new App.WidgetUser(
el: el
user_id: ticket.customer_id
)
@sidebarItems.push {
head: 'Customer'
name: 'customer'
icon: 'person'
actions: [
{
title: 'Change Customer'
name: 'customer-change'
callback: changeCustomer
},
{
title: 'Edit Customer'
name: 'customer-edit'
callback: editCustomer
},
]
callback: showCustomer
}
if ticket.organization_id
editOrganization = (e, el) =>
new App.ControllerGenericEdit(
id: ticket.organization_id,
genericObject: 'Organization'
pageData:
title: 'Organizations'
object: 'Organization'
objects: 'Organizations'
container: @el.closest('.content')
)
showOrganization = (el) ->
new App.WidgetOrganization(
el: el
organization_id: ticket.organization_id
)
@sidebarItems.push {
head: 'Organization'
name: 'organization'
icon: 'group'
actions: [
{
title: 'Edit Organization'
name: 'organization-edit'
callback: editOrganization
},
]
callback: showOrganization
}
new App.Sidebar(
el: @el.find('.tabsSidebar')
sidebarState: @sidebarState

View file

@ -0,0 +1,48 @@
class SidebarCustomer extends App.Controller
sidebarItem: =>
return if !@permissionCheck('ticket.agent')
{
head: 'Customer'
name: 'customer'
icon: 'person'
actions: [
{
title: 'Change Customer'
name: 'customer-change'
callback: @changeCustomer
},
{
title: 'Edit Customer'
name: 'customer-edit'
callback: @editCustomer
},
]
callback: @showCustomer
}
showCustomer: (el) =>
@el = el
new App.WidgetUser(
el: @el
user_id: @ticket.customer_id
)
editCustomer: =>
new App.ControllerGenericEdit(
id: @ticket.customer_id
genericObject: 'User'
screen: 'edit'
pageData:
title: 'Users'
object: 'User'
objects: 'Users'
container: @el.closest('.content')
)
changeCustomer: =>
new App.TicketCustomer(
ticket_id: @ticket.id
container: @el.closest('.content')
)
App.Config.set('200-Customer', SidebarCustomer, 'TicketZoomSidebar')

View file

@ -0,0 +1,36 @@
class SidebarOrganization extends App.Controller
sidebarItem: =>
return if !@ticket.organization_id
{
head: 'Organization'
name: 'organization'
icon: 'group'
actions: [
{
title: 'Edit Organization'
name: 'organization-edit'
callback: @editOrganization
},
]
callback: @showOrganization
}
showOrganization: (el) =>
@el = el
new App.WidgetOrganization(
el: @el
organization_id: @ticket.organization_id
)
editOrganization: =>
new App.ControllerGenericEdit(
id: @ticket.organization_id,
genericObject: 'Organization'
pageData:
title: 'Organizations'
object: 'Organization'
objects: 'Organizations'
container: @el.closest('.content')
)
App.Config.set('300-Organization', SidebarOrganization, 'TicketZoomSidebar')

View file

@ -0,0 +1,130 @@
class Edit extends App.ObserverController
model: 'Ticket'
observeNot:
created_at: true
updated_at: true
globalRerender: false
render: (ticket, diff) =>
defaults = ticket.attributes()
delete defaults.article # ignore article infos
taskState = @taskGet('ticket')
if !_.isEmpty(taskState)
defaults = _.extend(defaults, taskState)
new App.ControllerForm(
elReplace: @el
model: App.Ticket
screen: 'edit'
handlers: [
@ticketFormChanges
]
filter: @formMeta.filter
params: defaults
#bookmarkable: true
)
@markForm(true)
return if @resetBind
@resetBind = true
@bind('ui::ticket::taskReset', (data) =>
return if data.ticket_id.toString() isnt ticket.id.toString()
@render(ticket)
)
class SidebarTicket extends App.Controller
sidebarItem: =>
sidebarItem = {
head: 'Ticket'
name: 'ticket'
icon: 'message'
callback: @editTicket
}
if @permissionCheck('ticket.agent')
sidebarItem['actions'] = [
{
title: 'History'
name: 'ticket-history'
callback: @showTicketHistory
},
{
title: 'Merge'
name: 'ticket-merge'
callback: @showTicketMerge
},
{
title: 'Change Customer'
name: 'customer-change'
callback: @changeCustomer
},
]
sidebarItem
reload: (args) =>
# apply tag changes
if @tagWidget
if args.tags
@tagWidget.reload(args.tags)
if args.tagAdd
@tagWidget.add(args.tagAdd)
if args.tagRemove
@tagWidget.remove(args.tagRemove)
# apply link changes
if @linkWidget && args.links
@linkWidget.reload(args.links)
editTicket: (el) =>
@el = el
localEl = $( App.view('ticket_zoom/sidebar_ticket')() )
@edit = new Edit(
object_id: @ticket.id
el: localEl.find('.edit')
taskGet: @taskGet
formMeta: @formMeta
markForm: @markForm
)
if @permissionCheck('ticket.agent')
@tagWidget = new App.WidgetTag(
el: localEl.filter('.tags')
object_type: 'Ticket'
object: @ticket
tags: @tags
)
@linkWidget = new App.WidgetLink(
el: localEl.filter('.links')
object_type: 'Ticket'
object: @ticket
links: @links
)
@timeUnitWidget = new App.TicketZoomTimeUnit(
el: localEl.filter('.js-timeUnit')
object_id: @ticket.id
)
@html localEl
showTicketHistory: =>
new App.TicketHistory(
ticket_id: @ticket.id
container: @el.closest('.content')
)
showTicketMerge: =>
new App.TicketMerge(
ticket: @ticket
task_key: @task_key
container: @el.closest('.content')
)
changeCustomer: =>
new App.TicketCustomer(
ticket_id: @ticket.id
container: @el.closest('.content')
)
App.Config.set('100-TicketEdit', SidebarTicket, 'TicketZoomSidebar')

View file

@ -185,4 +185,14 @@ class App.LinkAdd extends App.ControllerModal
success: (data, status, xhr) =>
@close()
@parent.fetch()
error: (xhr, statusText, error) =>
detailsRaw = xhr.responseText
details = {}
if !_.isEmpty(detailsRaw)
details = JSON.parse(detailsRaw)
@notify(
type: 'error'
msg: App.i18n.translateContent(details.error)
removeAll: true
)
)

View file

@ -53,9 +53,8 @@ class App.WidgetTag extends App.Controller
@html App.view('widget/tag')(
tags: @localTags || [],
)
source = "#{App.Config.get('api_path')}/tag_search"
@el.find('.js-newTagInput').autocomplete(
@$('.js-newTagInput').autocomplete(
source: source
minLength: 2
response: (e, ui) =>

View file

@ -1,16 +1,14 @@
<% for item in @items: %>
<div class="sidebar bottom-form-shadow flex hide" data-tab="<%= item.name %>">
<div class="sidebar-header">
<h2 class="sidebar-header-headline js-headline"><%- @T( item.head ) %></h2>
<h2 class="sidebar-header-headline js-headline"><%- @T(item.head) %></h2>
<div class="sidebar-header-actions js-actions"></div>
<div class="tabsSidebar-close">
<%- @Icon('long-arrow-right') %>
</div>
</div>
<hr>
<div class="sidebar-content"></div>
</div>
<% end %>
<div class="tabsSidebar-tabs" style="margin-left: -<%- @scrollbarWidth %>px">

View file

@ -15,7 +15,7 @@ class LinksController < ApplicationController
links.each { |item|
link_list.push item
if item['link_object'] == 'Ticket'
ticket = Ticket.lookup( id: item['link_object_value'] )
ticket = Ticket.lookup(id: item['link_object_value'])
assets = ticket.assets(assets)
end
}
@ -30,14 +30,18 @@ class LinksController < ApplicationController
# POST /api/v1/links/add
def add
# lookup object id
object_id = Ticket.where( number: params[:link_object_source_number] ).first.id
object = Ticket.find_by(number: params[:link_object_source_number])
if !object
render json: { error: 'No such object!' }, status: :unprocessable_entity
return
end
link = Link.add(
link_type: params[:link_type],
link_object_target: params[:link_object_target],
link_object_target_value: params[:link_object_target_value],
link_object_source: params[:link_object_source],
link_object_source_value: object_id
link_object_source_value: object.id,
)
if link