Refactoring of sidebar and sidebar tabs backends. Added config option to show sidebar customer ticket indicator colored.

This commit is contained in:
Martin Edenhofer 2018-02-02 07:34:57 +01:00
parent 0d62ee7b9a
commit f67dce2266
15 changed files with 303 additions and 122 deletions

View file

@ -680,26 +680,48 @@ class App.Sidebar extends App.Controller
@toggleTabAction(name) @toggleTabAction(name)
render: => render: =>
itemsLocal = []
for item in @items
itemLocal = item.sidebarItem()
if itemLocal
itemsLocal.push itemLocal
# container
localEl = $(App.view('generic/sidebar_tabs')( localEl = $(App.view('generic/sidebar_tabs')(
items: @items items: itemsLocal
scrollbarWidth: App.Utils.getScrollBarWidth() scrollbarWidth: App.Utils.getScrollBarWidth()
dir: App.i18n.dir() dir: App.i18n.dir()
)) ))
# init content callback # init sidebar badget
for item in @items for item in itemsLocal
area = localEl.filter('.sidebar[data-tab="' + item.name + '"]') el = localEl.find('.tabsSidebar-tab[data-tab="' + item.name + '"]')
if item.callback if item.badgeCallback
item.callback(area.find('.sidebar-content')) item.badgeCallback(el)
if !_.isEmpty(item.actions) else
@badgeRender(el, item)
# init sidebar content
for item in itemsLocal
if item.sidebarCallback
el = localEl.filter('.sidebar[data-tab="' + item.name + '"]')
item.sidebarCallback(el.find('.sidebar-content'))
if !_.isEmpty(item.sidebarActions)
new App.ActionRow( new App.ActionRow(
el: area.find('.js-actions') el: el.find('.js-actions')
items: item.actions items: item.sidebarActions
type: 'small' type: 'small'
) )
@html localEl @html localEl
badgeRender: (el, item) =>
@badgeEl = el
@badgeRenderLocal(item)
badgeRenderLocal: (item) =>
@badgeEl.html(App.view('generic/sidebar_tabs_item')(icon: item.badgeIcon))
toggleDropdown: (e) -> toggleDropdown: (e) ->
e.stopPropagation() e.stopPropagation()
$(e.currentTarget).next('.js-actions').find('.dropdown-toggle').dropdown('toggle') $(e.currentTarget).next('.js-actions').find('.dropdown-toggle').dropdown('toggle')

View file

@ -32,9 +32,7 @@ class App.TicketCreateSidebar extends App.Controller
params: @params params: @params
query: @query query: @query
) )
item = @sidebarBackends[key].sidebarItem() @sidebarItems.push @sidebarBackends[key]
if item
@sidebarItems.push item
new App.Sidebar( new App.Sidebar(
el: @el el: @el

View file

@ -2,48 +2,61 @@ class SidebarCustomer extends App.Controller
sidebarItem: => sidebarItem: =>
return if !@permissionCheck('ticket.agent') return if !@permissionCheck('ticket.agent')
return if _.isEmpty(@params.customer_id) return if _.isEmpty(@params.customer_id)
counter = '' @item = {
if App.User.exists(@params.customer_id)
user = App.User.find(@params.customer_id)
counter = @sidebarItemCounter(user)
{
head: 'Customer'
name: 'customer' name: 'customer'
icon: 'person' badgeCallback: @badgeRender
counter: counter sidebarHead: 'Customer'
counterPossible: true sidebarCallback: @showCustomer
actions: [ sidebarActions: [
{ {
title: 'Edit Customer' title: 'Edit Customer'
name: 'customer-edit' name: 'customer-edit'
callback: @editCustomer callback: @editCustomer
}, },
] ]
callback: @showCustomer
} }
metaBadge: (user) =>
counter = ''
cssClass = ''
counter = @sidebarItemCounter(user)
if @Config.get('ui_sidebar_open_ticket_indicator_colored') is true
if counter == 1
cssClass = 'tabsSidebar-tab-count--warning'
if counter > 1
cssClass = 'tabsSidebar-tab-count--danger'
{
name: 'customer'
icon: 'person'
counterPossible: true
counter: counter
cssClass: cssClass
}
badgeRender: (el) =>
@badgeEl = el
if App.User.exists(@params.customer_id)
user = App.User.find(@params.customer_id)
@badgeRenderLocal(user)
badgeRenderLocal: (user) =>
@badgeEl.html(App.view('generic/sidebar_tabs_item')(@metaBadge(user)))
sidebarItemCounter: (user) -> sidebarItemCounter: (user) ->
counter = '' counter = ''
if user && user.preferences && user.preferences.tickets_open if user && user.preferences && user.preferences.tickets_open
counter = user.preferences.tickets_open counter = user.preferences.tickets_open
counter counter
sidebarItemUpdate: (user) =>
counter = @sidebarItemCounter(user)
element = @el.closest('.tabsSidebar-holder').find('.tabsSidebar .tabsSidebar-tabs .tabsSidebar-tab[data-tab=customer] .js-tabCounter')
if !counter || counter is 0
element.addClass('hide')
else
element.removeClass('hide')
element.text(counter)
showCustomer: (el) => showCustomer: (el) =>
@el = el @elSidebar = el
return if _.isEmpty(@params.customer_id) return if _.isEmpty(@params.customer_id)
new App.WidgetUser( new App.WidgetUser(
el: @el el: @elSidebar
user_id: @params.customer_id user_id: @params.customer_id
callback: @sidebarItemUpdate callback: @badgeRenderLocal
) )
editCustomer: => editCustomer: =>
@ -55,7 +68,7 @@ class SidebarCustomer extends App.Controller
title: 'Users' title: 'Users'
object: 'User' object: 'User'
objects: 'Users' objects: 'Users'
container: @el.closest('.content') container: @elSidebar.closest('.content')
) )
App.Config.set('200-Customer', SidebarCustomer, 'TicketCreateSidebar') App.Config.set('200-Customer', SidebarCustomer, 'TicketCreateSidebar')

View file

@ -6,24 +6,25 @@ class SidebarOrganization extends App.Controller
customer = App.User.find(@params.customer_id) customer = App.User.find(@params.customer_id)
@organization_id = customer.organization_id @organization_id = customer.organization_id
return if !@organization_id return if !@organization_id
{ @item = {
head: 'Organization'
name: 'organization' name: 'organization'
icon: 'group' badgeIcon: 'group'
actions: [ sidebarHead: 'Organization'
sidebarCallback: @showOrganization
sidebarActions: [
{ {
title: 'Edit Organization' title: 'Edit Organization'
name: 'organization-edit' name: 'organization-edit'
callback: @editOrganization callback: @editOrganization
}, },
] ]
callback: @showOrganization
} }
@item
showOrganization: (el) => showOrganization: (el) =>
@el = el @elSidebar = el
new App.WidgetOrganization( new App.WidgetOrganization(
el: @el el: @elSidebar
organization_id: @organization_id organization_id: @organization_id
) )
@ -35,7 +36,7 @@ class SidebarOrganization extends App.Controller
title: 'Organizations' title: 'Organizations'
object: 'Organization' object: 'Organization'
objects: 'Organizations' objects: 'Organizations'
container: @el.closest('.content') container: @elSidebar.closest('.content')
) )
App.Config.set('300-Organization', SidebarOrganization, 'TicketCreateSidebar') App.Config.set('300-Organization', SidebarOrganization, 'TicketCreateSidebar')

View file

@ -1,13 +1,15 @@
class SidebarTemplate extends App.Controller class SidebarTemplate extends App.Controller
sidebarItem: => sidebarItem: =>
return if !@permissionCheck('ticket.agent') return if !@permissionCheck('ticket.agent')
{ @item = {
head: 'Templates'
name: 'template' name: 'template'
icon: 'templates' badgeIcon: 'templates'
actions: [] badgeCallback: @badgeRender
callback: @showTemplates sidebarHead: 'Templates'
sidebarActions: []
sidebarCallback: @showTemplates
} }
@item
showTemplates: (el) => showTemplates: (el) =>
@el = el @el = el

View file

@ -39,9 +39,7 @@ class App.TicketZoomSidebar extends App.ObserverController
tags: @tags tags: @tags
links: @links links: @links
) )
item = @sidebarBackends[key].sidebarItem() @sidebarItems.push @sidebarBackends[key]
if item
@sidebarItems.push item
new App.Sidebar( new App.Sidebar(
el: @el.find('.tabsSidebar') el: @el.find('.tabsSidebar')

View file

@ -1,32 +1,54 @@
class SidebarCustomer extends App.Controller class SidebarCustomer extends App.Controller
sidebarItem: => sidebarItem: =>
return if !@permissionCheck('ticket.agent') return if !@permissionCheck('ticket.agent')
counter = '' @item = {
if App.User.exists(@ticket.customer_id)
user = App.User.find(@ticket.customer_id)
counter = @sidebarItemCounter(user)
items = {
head: 'Customer'
name: 'customer' name: 'customer'
icon: 'person' badgeCallback: @badgeRender
counter: counter sidebarHead: 'Customer'
counterPossible: true sidebarCallback: @showCustomer
actions: [ sidebarActions: [
{ {
title: 'Change Customer' title: 'Change Customer'
name: 'customer-change' name: 'customer-change'
callback: @changeCustomer callback: @changeCustomer
}, },
] ]
callback: @showCustomer
} }
return items if @ticket && @ticket.customer_id == 1 return @item if @ticket && @ticket.customer_id == 1
items.actions.push { @item.sidebarActions.push {
title: 'Edit Customer' title: 'Edit Customer'
name: 'customer-edit' name: 'customer-edit'
callback: @editCustomer callback: @editCustomer
} }
items @item
metaBadge: (user) =>
counter = ''
cssClass = ''
counter = @sidebarItemCounter(user)
if @Config.get('ui_sidebar_open_ticket_indicator_colored') is true
if counter == 1
cssClass = 'tabsSidebar-tab-count--warning'
if counter > 1
cssClass = 'tabsSidebar-tab-count--danger'
{
name: 'customer'
icon: 'person'
counterPossible: true
counter: counter
cssClass: cssClass
}
badgeRender: (el) =>
@badgeEl = el
if App.User.exists(@ticket.customer_id)
user = App.User.find(@ticket.customer_id)
@badgeRenderLocal(user)
badgeRenderLocal: (user) =>
@badgeEl.html(App.view('generic/sidebar_tabs_item')(@metaBadge(user)))
sidebarItemCounter: (user) -> sidebarItemCounter: (user) ->
counter = '' counter = ''
@ -34,21 +56,12 @@ class SidebarCustomer extends App.Controller
counter = user.preferences.tickets_open counter = user.preferences.tickets_open
counter counter
sidebarItemUpdate: (user) =>
counter = @sidebarItemCounter(user)
element = @el.closest('.tabsSidebar-holder').find('.tabsSidebar .tabsSidebar-tabs .tabsSidebar-tab[data-tab=customer] .js-tabCounter')
if !counter || counter is 0
element.addClass('hide')
else
element.removeClass('hide')
element.text(counter)
showCustomer: (el) => showCustomer: (el) =>
@el = el @elSidebar = el
new App.WidgetUser( new App.WidgetUser(
el: @el el: @elSidebar
user_id: @ticket.customer_id user_id: @ticket.customer_id
callback: @sidebarItemUpdate callback: @badgeRenderLocal
) )
editCustomer: => editCustomer: =>
@ -60,13 +73,13 @@ class SidebarCustomer extends App.Controller
title: 'Users' title: 'Users'
object: 'User' object: 'User'
objects: 'Users' objects: 'Users'
container: @el.closest('.content') container: @elSidebar.closest('.content')
) )
changeCustomer: => changeCustomer: =>
new App.TicketCustomer( new App.TicketCustomer(
ticket_id: @ticket.id ticket_id: @ticket.id
container: @el.closest('.content') container: @elSidebar.closest('.content')
) )
App.Config.set('200-Customer', SidebarCustomer, 'TicketZoomSidebar') App.Config.set('200-Customer', SidebarCustomer, 'TicketZoomSidebar')

View file

@ -1,19 +1,20 @@
class SidebarIdoit extends App.Controller class SidebarIdoit extends App.Controller
sidebarItem: => sidebarItem: =>
return if !@Config.get('idoit_integration') return if !@Config.get('idoit_integration')
{ @item = {
head: 'i-doit'
name: 'idoit' name: 'idoit'
icon: 'printer' badgeIcon: 'printer'
actions: [ sidebarHead: 'i-doit'
sidebarCallback: @showObjects
sidebarActions: [
{ {
title: 'Change Objects' title: 'Change Objects'
name: 'objects-change' name: 'objects-change'
callback: @changeObjects callback: @changeObjects
}, },
] ]
callback: @showObjects
} }
@item
changeObjects: => changeObjects: =>
new App.IdoitObjectSelector( new App.IdoitObjectSelector(

View file

@ -2,24 +2,25 @@ class SidebarOrganization extends App.Controller
sidebarItem: => sidebarItem: =>
return if !@permissionCheck('ticket.agent') return if !@permissionCheck('ticket.agent')
return if !@ticket.organization_id return if !@ticket.organization_id
{ @item = {
head: 'Organization'
name: 'organization' name: 'organization'
icon: 'group' badgeIcon: 'group'
actions: [ sidebarHead: 'Organization'
sidebarCallback: @showOrganization
sidebarActions: [
{ {
title: 'Edit Organization' title: 'Edit Organization'
name: 'organization-edit' name: 'organization-edit'
callback: @editOrganization callback: @editOrganization
}, },
] ]
callback: @showOrganization
} }
@item
showOrganization: (el) => showOrganization: (el) =>
@el = el @elSidebar = el
new App.WidgetOrganization( new App.WidgetOrganization(
el: @el el: @elSidebar
organization_id: @ticket.organization_id organization_id: @ticket.organization_id
) )
@ -31,7 +32,7 @@ class SidebarOrganization extends App.Controller
title: 'Organizations' title: 'Organizations'
object: 'Organization' object: 'Organization'
objects: 'Organizations' objects: 'Organizations'
container: @el.closest('.content') container: @elSidebar.closest('.content')
) )
App.Config.set('300-Organization', SidebarOrganization, 'TicketZoomSidebar') App.Config.set('300-Organization', SidebarOrganization, 'TicketZoomSidebar')

View file

@ -37,14 +37,14 @@ class Edit extends App.ObserverController
class SidebarTicket extends App.Controller class SidebarTicket extends App.Controller
sidebarItem: => sidebarItem: =>
sidebarItem = { @item = {
head: 'Ticket'
name: 'ticket' name: 'ticket'
icon: 'message' badgeIcon: 'message'
callback: @editTicket sidebarHead: 'Ticket'
sidebarCallback: @editTicket
} }
if @permissionCheck('ticket.agent') if @permissionCheck('ticket.agent')
sidebarItem['actions'] = [ @item.sidebarActions = [
{ {
title: 'History' title: 'History'
name: 'ticket-history' name: 'ticket-history'
@ -61,7 +61,7 @@ class SidebarTicket extends App.Controller
callback: @changeCustomer callback: @changeCustomer
}, },
] ]
sidebarItem @item
reload: (args) => reload: (args) =>
@ -80,7 +80,7 @@ class SidebarTicket extends App.Controller
editTicket: (el) => editTicket: (el) =>
@el = el @el = el
localEl = $( App.view('ticket_zoom/sidebar_ticket')() ) localEl = $(App.view('ticket_zoom/sidebar_ticket')())
@edit = new Edit( @edit = new Edit(
object_id: @ticket.id object_id: @ticket.id

View file

@ -1,7 +1,7 @@
<% for item in @items: %> <% for item in @items: %>
<div class="sidebar bottom-form-shadow flex hide" data-tab="<%= item.name %>"> <div class="sidebar bottom-form-shadow flex hide" data-tab="<%= item.name %>">
<div class="sidebar-header"> <div class="sidebar-header">
<h2 class="sidebar-header-headline js-headline"><%- @T(item.head) %></h2> <h2 class="sidebar-header-headline js-headline"><%- @T(item.sidebarHead) %></h2>
<div class="sidebar-header-actions js-actions"></div> <div class="sidebar-header-actions js-actions"></div>
<div class="tabsSidebar-close"> <div class="tabsSidebar-close">
<%- @Icon('long-arrow-right') %> <%- @Icon('long-arrow-right') %>
@ -13,11 +13,6 @@
<% end %> <% end %>
<div class="tabsSidebar-tabs" style="<%- if @dir is 'rtl' then 'margin-right' else 'margin-left' %>: -<%- @scrollbarWidth %>px"> <div class="tabsSidebar-tabs" style="<%- if @dir is 'rtl' then 'margin-right' else 'margin-left' %>: -<%- @scrollbarWidth %>px">
<% for item in @items: %> <% for item in @items: %>
<div class="tabsSidebar-tab" data-tab="<%= item.name %>"> <div class="tabsSidebar-tab" data-tab="<%= item.name %>"></div>
<% if item.counterPossible is true: %>
<div class="tabsSidebar-tab-count js-tabCounter <% if !item.counter || item.counter is 0: %>hide<% end %>"><%= item.counter %></div>
<% end %>
<%- @Icon(item.icon) %>
</div>
<% end %> <% end %>
</div> </div>

View file

@ -0,0 +1,4 @@
<% if @counterPossible is true: %>
<div class="tabsSidebar-tab-count js-tabCounter <% if !@counter || @counter is 0: %>hide<% end %><% if @cssClass: %><%= @cssClass %><% end %>"><%= @counter %></div>
<% end %>
<%- @Icon(@icon) %>

View file

@ -5563,6 +5563,42 @@ footer {
&:after { &:after {
border-right-color: hsl(206,7%,37%); border-right-color: hsl(206,7%,37%);
} }
&.tabsSidebar-tab-count--info {
background: hsl(203,65%,55%);
opacity: 1;
&:after {
border-right-color: hsl(203,65%,55%);
}
}
&.tabsSidebar-tab-count--success {
background: hsl(145,51%,45%);
opacity: 1;
&:after {
border-right-color: hsl(145,51%,45%);
}
}
&.tabsSidebar-tab-count--warning {
background: hsl(45,98%,63%);
opacity: 1;
&:after {
border-right-color: hsl(45,98%,63%);
}
}
&.tabsSidebar-tab-count--danger {
background: hsl(11,85%,48%);
opacity: 1;
&:after {
border-right-color: hsl(11,85%,48%);
}
}
} }
.icon { .icon {
@ -5603,6 +5639,42 @@ footer {
border-bottom: 3px solid transparent; border-bottom: 3px solid transparent;
border-right: 5px solid hsl(197,19%,78%); border-right: 5px solid hsl(197,19%,78%);
} }
&.tabsSidebar-tab-count--info {
background: hsl(203,65%,55%);
opacity: .5;
&:after {
border-right-color: hsl(203,65%,55%);
}
}
&.tabsSidebar-tab-count--success {
background: hsl(145,51%,45%);
opacity: .5;
&:after {
border-right-color: hsl(145,51%,45%);
}
}
&.tabsSidebar-tab-count--warning {
background: hsl(45,98%,63%);
opacity: .5;
&:after {
border-right-color: hsl(45,98%,63%);
}
}
&.tabsSidebar-tab-count--danger {
background: hsl(11,85%,48%);
opacity: .5;
&:after {
border-right-color: hsl(11,85%,48%);
}
}
} }
.sidebar .text-muted { .sidebar .text-muted {

View file

@ -0,0 +1,34 @@
class SidebarCustomerOpenTicketColored < ActiveRecord::Migration[5.1]
def up
# return if it's a new setup
return if !Setting.find_by(name: 'system_init_done')
Setting.create_if_not_exists(
title: 'Open ticket indicator',
name: 'ui_sidebar_open_ticket_indicator_colored',
area: 'UI::Sidebar',
description: 'Color representation of the open ticket indicator in the sidebar.',
options: {
form: [
{
display: '',
null: true,
name: 'ui_sidebar_open_ticket_indicator_colored',
tag: 'boolean',
translate: true,
options: {
true => 'yes',
false => 'no',
},
},
],
},
state: false,
preferences: {
permission: ['admin.ui'],
},
frontend: true
)
end
end

View file

@ -713,6 +713,33 @@ Setting.create_if_not_exists(
frontend: true frontend: true
) )
Setting.create_if_not_exists(
title: 'Open ticket indicator',
name: 'ui_sidebar_open_ticket_indicator_colored',
area: 'UI::Sidebar',
description: 'Color representation of the open ticket indicator in the sidebar.',
options: {
form: [
{
display: '',
null: true,
name: 'ui_sidebar_open_ticket_indicator_colored',
tag: 'boolean',
translate: true,
options: {
true => 'yes',
false => 'no',
},
},
],
},
state: false,
preferences: {
permission: ['admin.ui'],
},
frontend: true
)
Setting.create_if_not_exists( Setting.create_if_not_exists(
title: 'New User Accounts', title: 'New User Accounts',
name: 'user_create_account', name: 'user_create_account',