Merge branch 'develop' of git.znuny.com:zammad/zammad into develop

This commit is contained in:
Muhammad Nuzaihan 2018-02-02 18:55:11 +08:00
commit 7f45bf69fc
17 changed files with 307 additions and 130 deletions

View file

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

View file

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

View file

@ -2,48 +2,61 @@ class SidebarCustomer extends App.Controller
sidebarItem: =>
return if !@permissionCheck('ticket.agent')
return if _.isEmpty(@params.customer_id)
counter = ''
if App.User.exists(@params.customer_id)
user = App.User.find(@params.customer_id)
counter = @sidebarItemCounter(user)
{
head: 'Customer'
name: 'customer'
icon: 'person'
counter: counter
counterPossible: true
actions: [
@item = {
name: 'customer'
badgeCallback: @badgeRender
sidebarHead: 'Customer'
sidebarCallback: @showCustomer
sidebarActions: [
{
title: 'Edit Customer'
name: 'customer-edit'
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) ->
counter = ''
if user && user.preferences && user.preferences.tickets_open
counter = user.preferences.tickets_open
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) =>
@el = el
@elSidebar = el
return if _.isEmpty(@params.customer_id)
new App.WidgetUser(
el: @el
el: @elSidebar
user_id: @params.customer_id
callback: @sidebarItemUpdate
callback: @badgeRenderLocal
)
editCustomer: =>
@ -55,7 +68,7 @@ class SidebarCustomer extends App.Controller
title: 'Users'
object: 'User'
objects: 'Users'
container: @el.closest('.content')
container: @elSidebar.closest('.content')
)
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)
@organization_id = customer.organization_id
return if !@organization_id
{
head: 'Organization'
@item = {
name: 'organization'
icon: 'group'
actions: [
badgeIcon: 'group'
sidebarHead: 'Organization'
sidebarCallback: @showOrganization
sidebarActions: [
{
title: 'Edit Organization'
name: 'organization-edit'
callback: @editOrganization
},
]
callback: @showOrganization
}
@item
showOrganization: (el) =>
@el = el
@elSidebar = el
new App.WidgetOrganization(
el: @el
el: @elSidebar
organization_id: @organization_id
)
@ -35,7 +36,7 @@ class SidebarOrganization extends App.Controller
title: 'Organizations'
object: 'Organization'
objects: 'Organizations'
container: @el.closest('.content')
container: @elSidebar.closest('.content')
)
App.Config.set('300-Organization', SidebarOrganization, 'TicketCreateSidebar')

View file

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

View file

@ -32,16 +32,14 @@ class App.TicketZoomSidebar extends App.ObserverController
)
else
@sidebarBackends[key].reload(
params: @params
query: @query
params: @params
query: @query
formMeta: @formMeta
markForm: @markForm
tags: @tags
links: @links
)
item = @sidebarBackends[key].sidebarItem()
if item
@sidebarItems.push item
@sidebarItems.push @sidebarBackends[key]
new App.Sidebar(
el: @el.find('.tabsSidebar')

View file

@ -1,32 +1,54 @@
class SidebarCustomer extends App.Controller
sidebarItem: =>
return if !@permissionCheck('ticket.agent')
counter = ''
if App.User.exists(@ticket.customer_id)
user = App.User.find(@ticket.customer_id)
counter = @sidebarItemCounter(user)
items = {
head: 'Customer'
name: 'customer'
icon: 'person'
counter: counter
counterPossible: true
actions: [
@item = {
name: 'customer'
badgeCallback: @badgeRender
sidebarHead: 'Customer'
sidebarCallback: @showCustomer
sidebarActions: [
{
title: 'Change Customer'
name: 'customer-change'
callback: @changeCustomer
},
]
callback: @showCustomer
}
return items if @ticket && @ticket.customer_id == 1
items.actions.push {
return @item if @ticket && @ticket.customer_id == 1
@item.sidebarActions.push {
title: 'Edit Customer'
name: 'customer-edit'
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) ->
counter = ''
@ -34,21 +56,12 @@ class SidebarCustomer extends App.Controller
counter = user.preferences.tickets_open
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) =>
@el = el
@elSidebar = el
new App.WidgetUser(
el: @el
el: @elSidebar
user_id: @ticket.customer_id
callback: @sidebarItemUpdate
callback: @badgeRenderLocal
)
editCustomer: =>
@ -60,13 +73,13 @@ class SidebarCustomer extends App.Controller
title: 'Users'
object: 'User'
objects: 'Users'
container: @el.closest('.content')
container: @elSidebar.closest('.content')
)
changeCustomer: =>
new App.TicketCustomer(
ticket_id: @ticket.id
container: @el.closest('.content')
container: @elSidebar.closest('.content')
)
App.Config.set('200-Customer', SidebarCustomer, 'TicketZoomSidebar')

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
<% 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.sidebarHead) %></h2>
<div class="sidebar-header-actions js-actions"></div>
<div class="tabsSidebar-close">
<%- @Icon('long-arrow-right') %>
@ -13,11 +13,6 @@
<% end %>
<div class="tabsSidebar-tabs" style="<%- if @dir is 'rtl' then 'margin-right' else 'margin-left' %>: -<%- @scrollbarWidth %>px">
<% for item in @items: %>
<div class="tabsSidebar-tab" data-tab="<%= item.name %>">
<% 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>
<div class="tabsSidebar-tab" data-tab="<%= item.name %>"></div>
<% end %>
</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

@ -1,5 +1,5 @@
<div class="js-pager"></div>
<table class="table table-hover<%- " #{@class}" if @class %>">
<table class="table table-hover<% if @class: %> <%= @class %><% end %>">
<thead>
<tr>
<% if @sortable: %>
@ -19,14 +19,10 @@
<th style="width: 40px" class="table-radio"></th>
<% end %>
<% for header, i in @headers: %>
<th class="js-tableHead<%= " #{ header.className }" if header.className %><%= " align-#{ header.align }" if header.align %>" style="<% if header.displayWidth: %>width:<%= header.displayWidth %>px<% end %>" data-column-key="<%= header.name %>">
<th class="js-tableHead<% if header.className: %> <%= header.className %><% end %><% if header.align: %> align-<%= header.align %><% end %>" style="<% if header.displayWidth: %>width:<%= header.displayWidth %>px<% end %>" data-column-key="<%= header.name %>">
<div class="table-column-head<%= ' js-sort' if @tableId %>">
<div class="table-column-title"><%- @T(header.display) %></div>
<div class="table-column-sortIcon">
<% if header.sortOrderIcon: %>
<%- @Icon(header.sortOrderIcon[0], header.sortOrderIcon[1]) %>
<% end %>
</div>
<div class="table-column-sortIcon"><% if header.sortOrderIcon: %><%- @Icon(header.sortOrderIcon[0], header.sortOrderIcon[1]) %><% end %></div>
</div>
<% if @tableId && !header.unresizable && i < @headers.length - 1: %>
<div class="table-col-resize js-col-resize"></div>

View file

@ -31,7 +31,7 @@
<% end %>
<% end %>
<% end %>
<td<%- " class='#{ header.parentClass }'" if header.parentClass %><%- " title='#{ header.title }'" if header.title %><%- " style='text-align:#{ header.align }'" if header.align %>>
<td<% if header.parentClass: %> class="<%= header.parentClass %>"<% end %><% if header.title: %> title="<%= header.title %>"<% end %><% if header.align: %> style="text-align:<%= header.align %>"<% end %>>
<% if header.name is 'icon': %>
<%- @Icon('task-state', header.class) %>
<% else if header.icon: %>

View file

@ -5559,10 +5559,46 @@ footer {
.tabsSidebar-tab.active {
.tabsSidebar-tab-count {
background: hsl(206,7%,37%);
&:after {
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 {
@ -5582,10 +5618,10 @@ footer {
font-size: 9px;
line-height: 14px;
color: hsl(197,20%,93%);
[data-tab="organization"] & {
left: 7px;
+ .icon {
margin-left: 3px;
}
@ -5594,7 +5630,7 @@ footer {
+ .icon {
margin-top: 6px;
}
&:after {
content: "";
position: absolute;
@ -5603,6 +5639,42 @@ footer {
border-bottom: 3px solid transparent;
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 {

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
)
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(
title: 'New User Accounts',
name: 'user_create_account',