New user and org zoom.
This commit is contained in:
parent
c3025f87c3
commit
7b4015179f
12 changed files with 413 additions and 457 deletions
|
@ -1,7 +1,4 @@
|
||||||
class App.OrganizationZoom extends App.Controller
|
class App.OrganizationZoom extends App.Controller
|
||||||
elements:
|
|
||||||
'.tabsSidebar' : 'sidebar'
|
|
||||||
|
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -12,7 +9,11 @@ class App.OrganizationZoom extends App.Controller
|
||||||
|
|
||||||
@navupdate '#'
|
@navupdate '#'
|
||||||
|
|
||||||
App.Organization.full( @organization_id, @render )
|
# subscribe and reload data / fetch new data if triggered
|
||||||
|
@subscribeId = App.Organization.full( @organization_id, @render, false, true )
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
App.Organization.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
meta: =>
|
meta: =>
|
||||||
meta =
|
meta =
|
||||||
|
@ -36,10 +37,7 @@ class App.OrganizationZoom extends App.Controller
|
||||||
@navupdate '#'
|
@navupdate '#'
|
||||||
|
|
||||||
changed: =>
|
changed: =>
|
||||||
formCurrent = @formParam( @el.find('.ticket-update') )
|
false
|
||||||
diff = difference( @formDefault, formCurrent )
|
|
||||||
return false if !diff || _.isEmpty( diff )
|
|
||||||
return true
|
|
||||||
|
|
||||||
render: (organization) =>
|
render: (organization) =>
|
||||||
|
|
||||||
|
@ -47,12 +45,38 @@ class App.OrganizationZoom extends App.Controller
|
||||||
@doNotLog = 1
|
@doNotLog = 1
|
||||||
@recentView( 'Organization', @organization_id )
|
@recentView( 'Organization', @organization_id )
|
||||||
|
|
||||||
|
# get display data
|
||||||
|
organizationData = []
|
||||||
|
for item2 in App.Organization.configure_attributes
|
||||||
|
item = _.clone( item2 )
|
||||||
|
|
||||||
|
# check if value for _id exists
|
||||||
|
itemNameValue = item.name
|
||||||
|
itemNameValueNew = itemNameValue.substr( 0, itemNameValue.length - 3 )
|
||||||
|
if itemNameValueNew of organization
|
||||||
|
item.name = itemNameValueNew
|
||||||
|
|
||||||
|
# add to show if value exists
|
||||||
|
if organization[item.name] || item.tag is 'textarea'
|
||||||
|
|
||||||
|
# do not show firstname and lastname / already show via diplayName()
|
||||||
|
if item.name isnt 'name'
|
||||||
|
if item.info
|
||||||
|
organizationData.push item
|
||||||
|
|
||||||
@html App.view('organization_zoom')(
|
@html App.view('organization_zoom')(
|
||||||
organization: organization
|
organization: organization
|
||||||
|
organizationData: organizationData
|
||||||
)
|
)
|
||||||
|
|
||||||
new Overviews(
|
@$('[contenteditable]').ce({
|
||||||
el: @el
|
mode: 'textonly'
|
||||||
|
multiline: true
|
||||||
|
maxlength: 250
|
||||||
|
})
|
||||||
|
|
||||||
|
new App.TicketStats(
|
||||||
|
el: @$('.js-ticket-stats')
|
||||||
organization: organization
|
organization: organization
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,125 +84,38 @@ class App.OrganizationZoom extends App.Controller
|
||||||
genericObject: organization
|
genericObject: organization
|
||||||
)
|
)
|
||||||
|
|
||||||
new App.UpdateHeader(
|
|
||||||
el: @el
|
|
||||||
genericObject: organization
|
|
||||||
)
|
|
||||||
|
|
||||||
# start action controller
|
# start action controller
|
||||||
showHistory = =>
|
showHistory = =>
|
||||||
new App.OrganizationHistory( organization_id: organization.id )
|
new App.OrganizationHistory( organization_id: organization.id )
|
||||||
|
editOrganization = =>
|
||||||
|
new App.ControllerGenericEdit(
|
||||||
|
id: organization.id
|
||||||
|
genericObject: 'Organization'
|
||||||
|
screen: 'edit'
|
||||||
|
pageData:
|
||||||
|
title: 'Organizations'
|
||||||
|
object: 'Organization'
|
||||||
|
objects: 'Organizations'
|
||||||
|
)
|
||||||
|
|
||||||
actions = [
|
actions = [
|
||||||
|
{
|
||||||
|
name: 'edit'
|
||||||
|
title: 'Edit'
|
||||||
|
callback: editOrganization
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name: 'history'
|
name: 'history'
|
||||||
title: 'History'
|
title: 'History'
|
||||||
callback: showHistory
|
callback: showHistory
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
new App.ActionRow(
|
new App.ActionRow(
|
||||||
el: @el.find('.action')
|
el: @el.find('.action')
|
||||||
items: actions
|
items: actions
|
||||||
)
|
)
|
||||||
|
|
||||||
new Sidebar(
|
|
||||||
el: @sidebar
|
|
||||||
organization: organization
|
|
||||||
)
|
|
||||||
|
|
||||||
class Overviews extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
|
||||||
@subscribeId = App.Organization.full( @organization.id, @render, false, true )
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
App.Organization.unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
render: (organization) =>
|
|
||||||
|
|
||||||
plugins =
|
|
||||||
main:
|
|
||||||
my_organization:
|
|
||||||
controller: App.DashboardTicketSearch,
|
|
||||||
params:
|
|
||||||
name: 'Tickets of Organization'
|
|
||||||
condition:
|
|
||||||
'tickets.state_id': [ 1,2,3,4,6 ]
|
|
||||||
'tickets.organization_id': organization.id
|
|
||||||
order:
|
|
||||||
by: 'created_at'
|
|
||||||
direction: 'DESC'
|
|
||||||
view:
|
|
||||||
d: [ 'number', 'title', 'customer', 'state', 'priority', 'created_at' ]
|
|
||||||
view_mode_default: 'd'
|
|
||||||
|
|
||||||
for area, plugins of plugins
|
|
||||||
for name, plugin of plugins
|
|
||||||
target = area + '_' + name
|
|
||||||
@el.find('.' + area + '-overviews').append('<div class="" id="' + target + '"></div>')
|
|
||||||
if plugin.controller
|
|
||||||
params = plugin.params || {}
|
|
||||||
params.el = @el.find( '#' + target )
|
|
||||||
new plugin.controller( params )
|
|
||||||
|
|
||||||
dndOptions =
|
|
||||||
handle: 'h2.can-move'
|
|
||||||
placeholder: 'can-move-plcaeholder'
|
|
||||||
tolerance: 'pointer'
|
|
||||||
distance: 15
|
|
||||||
opacity: 0.6
|
|
||||||
forcePlaceholderSize: true
|
|
||||||
|
|
||||||
@el.find( '#sortable' ).sortable( dndOptions )
|
|
||||||
@el.find( '#sortable-sidebar' ).sortable( dndOptions )
|
|
||||||
|
|
||||||
|
|
||||||
class Sidebar extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# render ui
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: ->
|
|
||||||
|
|
||||||
items = []
|
|
||||||
|
|
||||||
editOrganization = (e, el) =>
|
|
||||||
new App.ControllerGenericEdit(
|
|
||||||
id: @organization.id
|
|
||||||
genericObject: 'Organization'
|
|
||||||
pageData:
|
|
||||||
title: 'Organizations'
|
|
||||||
object: 'Organization'
|
|
||||||
objects: 'Organizations'
|
|
||||||
)
|
|
||||||
showOrganization = (el) =>
|
|
||||||
new App.WidgetOrganization(
|
|
||||||
el: el
|
|
||||||
organization_id: @organization.id
|
|
||||||
)
|
|
||||||
items.push {
|
|
||||||
head: 'Organization'
|
|
||||||
name: 'organization'
|
|
||||||
icon: 'group'
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
name: 'Edit Organization'
|
|
||||||
class: 'glyphicon glyphicon-edit'
|
|
||||||
callback: editOrganization
|
|
||||||
},
|
|
||||||
]
|
|
||||||
callback: showOrganization
|
|
||||||
}
|
|
||||||
|
|
||||||
new App.Sidebar(
|
|
||||||
el: @el
|
|
||||||
items: items
|
|
||||||
)
|
|
||||||
|
|
||||||
class Router extends App.ControllerPermanent
|
class Router extends App.ControllerPermanent
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
|
@ -77,12 +77,7 @@ class App.UserZoom extends App.Controller
|
||||||
maxlength: 250
|
maxlength: 250
|
||||||
})
|
})
|
||||||
|
|
||||||
#new Overviews(
|
new App.TicketStats(
|
||||||
# el: @el
|
|
||||||
# user: user
|
|
||||||
#)
|
|
||||||
|
|
||||||
new TicketStats(
|
|
||||||
el: @$('.js-ticket-stats')
|
el: @$('.js-ticket-stats')
|
||||||
user: user
|
user: user
|
||||||
)
|
)
|
||||||
|
@ -132,220 +127,6 @@ class App.UserZoom extends App.Controller
|
||||||
user.updateAttributes( note: note )
|
user.updateAttributes( note: note )
|
||||||
@log 'notice', 'update', e, note, user
|
@log 'notice', 'update', e, note, user
|
||||||
|
|
||||||
|
|
||||||
class TicketStats extends App.Controller
|
|
||||||
events:
|
|
||||||
'click .js-userTab': 'showUserTab'
|
|
||||||
'click .js-orgTab': 'showOrgTab'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
|
||||||
@subscribeId = App.User.full( @user.id, @load, false, true )
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
App.User.unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
load: (user) =>
|
|
||||||
@ajax(
|
|
||||||
id: 'ticket_stats_' + user.id,
|
|
||||||
type: 'GET',
|
|
||||||
url: @apiPath + '/ticket_stats/' + user.id,
|
|
||||||
success: (data) =>
|
|
||||||
# load assets
|
|
||||||
App.Collection.loadAssets( data.assets )
|
|
||||||
|
|
||||||
@render(data)
|
|
||||||
)
|
|
||||||
|
|
||||||
showOrgTab: =>
|
|
||||||
@$('.js-userTab').removeClass('active')
|
|
||||||
@$('.js-orgTab').addClass('active')
|
|
||||||
@$('.js-user').addClass('hide')
|
|
||||||
@$('.js-org').removeClass('hide')
|
|
||||||
|
|
||||||
showUserTab: =>
|
|
||||||
@$('.js-userTab').addClass('active')
|
|
||||||
@$('.js-orgTab').removeClass('active')
|
|
||||||
@$('.js-user').removeClass('hide')
|
|
||||||
@$('.js-org').addClass('hide')
|
|
||||||
|
|
||||||
render: (data) =>
|
|
||||||
|
|
||||||
@html App.view('user_zoom/ticket_stats')(
|
|
||||||
user: @user
|
|
||||||
)
|
|
||||||
|
|
||||||
limit = 5
|
|
||||||
new TicketStatsList(
|
|
||||||
el: @$('.js-user-open-tickets')
|
|
||||||
user: @user
|
|
||||||
head: 'Open Ticket'
|
|
||||||
ticket_ids: data.user_tickets_open_ids
|
|
||||||
limit: limit
|
|
||||||
)
|
|
||||||
new TicketStatsList(
|
|
||||||
el: @$('.js-user-closed-tickets')
|
|
||||||
user: @user
|
|
||||||
head: 'Closed Ticket'
|
|
||||||
ticket_ids: data.user_tickets_closed_ids
|
|
||||||
limit: limit
|
|
||||||
)
|
|
||||||
new TicketStatsFrequency(
|
|
||||||
el: @$('.js-user-frequency')
|
|
||||||
user: @user
|
|
||||||
ticket_volume_by_year: data.user_ticket_volume_by_year
|
|
||||||
)
|
|
||||||
|
|
||||||
new TicketStatsList(
|
|
||||||
el: @$('.js-org-open-tickets')
|
|
||||||
user: @user
|
|
||||||
head: 'Open Ticket'
|
|
||||||
ticket_ids: data.org_tickets_open_ids
|
|
||||||
limit: limit
|
|
||||||
)
|
|
||||||
new TicketStatsList(
|
|
||||||
el: @$('.js-org-closed-tickets')
|
|
||||||
user: @user
|
|
||||||
head: 'Closed Ticket'
|
|
||||||
ticket_ids: data.org_tickets_closed_ids
|
|
||||||
limit: limit
|
|
||||||
)
|
|
||||||
new TicketStatsFrequency(
|
|
||||||
el: @$('.js-org-frequency')
|
|
||||||
user: @user
|
|
||||||
ticket_volume_by_year: data.org_ticket_volume_by_year
|
|
||||||
)
|
|
||||||
|
|
||||||
class TicketStatsList extends App.Controller
|
|
||||||
events:
|
|
||||||
'click .js-showAll': 'showAll'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: =>
|
|
||||||
|
|
||||||
ticket_ids_show = []
|
|
||||||
if !@all
|
|
||||||
count = 0
|
|
||||||
for ticket_id in @ticket_ids
|
|
||||||
count += 1
|
|
||||||
if count <= @limit
|
|
||||||
ticket_ids_show.push ticket_id
|
|
||||||
else
|
|
||||||
ticket_ids_show = @ticket_ids
|
|
||||||
|
|
||||||
@html App.view('user_zoom/ticket_stats_list')(
|
|
||||||
user: @user
|
|
||||||
head: @head
|
|
||||||
ticket_ids: @ticket_ids
|
|
||||||
ticket_ids_show: ticket_ids_show
|
|
||||||
limit: @limit
|
|
||||||
)
|
|
||||||
@frontendTimeUpdate()
|
|
||||||
@ticketPopups()
|
|
||||||
|
|
||||||
showAll: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@all = true
|
|
||||||
@render()
|
|
||||||
|
|
||||||
class TicketStatsFrequency extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data) =>
|
|
||||||
|
|
||||||
# find 100%
|
|
||||||
max = 0
|
|
||||||
for item in @ticket_volume_by_year
|
|
||||||
if item.closed > max
|
|
||||||
max = item.closed
|
|
||||||
if item.created > max
|
|
||||||
max = item.created
|
|
||||||
console.log('MM', max)
|
|
||||||
for item in @ticket_volume_by_year
|
|
||||||
item.created_in_percent = 100 / max * item.created
|
|
||||||
item.closed_in_percent = 100 / max * item.closed
|
|
||||||
|
|
||||||
@html App.view('user_zoom/ticket_stats_frequency')(
|
|
||||||
user: @user
|
|
||||||
ticket_volume_by_year: @ticket_volume_by_year.reverse()
|
|
||||||
)
|
|
||||||
|
|
||||||
class Overviews extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
|
||||||
@subscribeId = App.User.full( @user.id, @render, false, true )
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
App.User.unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
render: (user) =>
|
|
||||||
|
|
||||||
plugins = {
|
|
||||||
main: {
|
|
||||||
my_assigned: {
|
|
||||||
controller: App.DashboardTicketSearch,
|
|
||||||
params: {
|
|
||||||
name: 'Tickets of User'
|
|
||||||
condition:
|
|
||||||
'tickets.state_id': [ 1,2,3,4,6 ]
|
|
||||||
'tickets.customer_id': user.id
|
|
||||||
order:
|
|
||||||
by: 'created_at'
|
|
||||||
direction: 'DESC'
|
|
||||||
view:
|
|
||||||
d: [ 'number', 'title', 'state', 'priority', 'created_at' ]
|
|
||||||
view_mode_default: 'd'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if user.organization_id
|
|
||||||
plugins.main.my_organization = {
|
|
||||||
controller: App.DashboardTicketSearch,
|
|
||||||
params: {
|
|
||||||
name: 'Tickets of Organization'
|
|
||||||
condition:
|
|
||||||
'tickets.state_id': [ 1,2,3,4,6 ]
|
|
||||||
'tickets.organization_id': user.organization_id
|
|
||||||
order:
|
|
||||||
by: 'created_at'
|
|
||||||
direction: 'DESC'
|
|
||||||
view:
|
|
||||||
d: [ 'number', 'title', 'customer', 'state', 'priority', 'created_at' ]
|
|
||||||
view_mode_default: 'd'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for area, plugins of plugins
|
|
||||||
for name, plugin of plugins
|
|
||||||
target = area + '_' + name
|
|
||||||
@el.find('.' + area + '-overviews').append('<div class="" id="' + target + '"></div>')
|
|
||||||
if plugin.controller
|
|
||||||
params = plugin.params || {}
|
|
||||||
params.el = @el.find( '#' + target )
|
|
||||||
new plugin.controller( params )
|
|
||||||
|
|
||||||
dndOptions =
|
|
||||||
handle: 'h2.can-move'
|
|
||||||
placeholder: 'can-move-plcaeholder'
|
|
||||||
tolerance: 'pointer'
|
|
||||||
distance: 15
|
|
||||||
opacity: 0.6
|
|
||||||
forcePlaceholderSize: true
|
|
||||||
|
|
||||||
@el.find( '#sortable' ).sortable( dndOptions )
|
|
||||||
@el.find( '#sortable-sidebar' ).sortable( dndOptions )
|
|
||||||
|
|
||||||
|
|
||||||
class Router extends App.ControllerPermanent
|
class Router extends App.ControllerPermanent
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
class App.TicketStats extends App.Controller
|
||||||
|
events:
|
||||||
|
'click .js-userTab': 'showUserTab'
|
||||||
|
'click .js-orgTab': 'showOrgTab'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# subscribe and reload data / fetch new data if triggered
|
||||||
|
if @user
|
||||||
|
@subscribeId = App.User.full( @user.id, @load, false, true )
|
||||||
|
if @organization
|
||||||
|
@subscribeId = App.Organization.full( @organization.id, @load, false, true )
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
App.User.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
load: (object) =>
|
||||||
|
if @organization
|
||||||
|
ajaxKey = "org_" + @organization.id
|
||||||
|
data =
|
||||||
|
organization_id: @organization.id
|
||||||
|
else
|
||||||
|
ajaxKey = "user_" + @user.id
|
||||||
|
data =
|
||||||
|
user_id: @user.id
|
||||||
|
organization_id: @user.organization_id
|
||||||
|
@ajax(
|
||||||
|
id: 'ticket_stats_' + ajaxKey
|
||||||
|
type: 'GET'
|
||||||
|
url: @apiPath + '/ticket_stats'
|
||||||
|
data: data
|
||||||
|
processData: true
|
||||||
|
success: (data) =>
|
||||||
|
# load assets
|
||||||
|
App.Collection.loadAssets( data.assets )
|
||||||
|
|
||||||
|
@render(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
showOrgTab: =>
|
||||||
|
@$('.js-userTab').removeClass('active')
|
||||||
|
@$('.js-orgTab').addClass('active')
|
||||||
|
@$('.js-user').addClass('hide')
|
||||||
|
@$('.js-org').removeClass('hide')
|
||||||
|
|
||||||
|
showUserTab: =>
|
||||||
|
@$('.js-userTab').addClass('active')
|
||||||
|
@$('.js-orgTab').removeClass('active')
|
||||||
|
@$('.js-user').removeClass('hide')
|
||||||
|
@$('.js-org').addClass('hide')
|
||||||
|
|
||||||
|
render: (data) =>
|
||||||
|
|
||||||
|
@html App.view('widget/ticket_stats')(
|
||||||
|
user: @user
|
||||||
|
organization: @organization
|
||||||
|
)
|
||||||
|
|
||||||
|
if @organization
|
||||||
|
@showOrgTab()
|
||||||
|
|
||||||
|
limit = 5
|
||||||
|
new TicketStatsList(
|
||||||
|
el: @$('.js-user-open-tickets')
|
||||||
|
user: @user
|
||||||
|
head: 'Open Ticket'
|
||||||
|
ticket_ids: data.user_tickets_open_ids
|
||||||
|
limit: limit
|
||||||
|
)
|
||||||
|
new TicketStatsList(
|
||||||
|
el: @$('.js-user-closed-tickets')
|
||||||
|
user: @user
|
||||||
|
head: 'Closed Ticket'
|
||||||
|
ticket_ids: data.user_tickets_closed_ids
|
||||||
|
limit: limit
|
||||||
|
)
|
||||||
|
new TicketStatsFrequency(
|
||||||
|
el: @$('.js-user-frequency')
|
||||||
|
user: @user
|
||||||
|
ticket_volume_by_year: data.user_ticket_volume_by_year
|
||||||
|
)
|
||||||
|
|
||||||
|
new TicketStatsList(
|
||||||
|
el: @$('.js-org-open-tickets')
|
||||||
|
user: @user
|
||||||
|
head: 'Open Ticket'
|
||||||
|
ticket_ids: data.org_tickets_open_ids
|
||||||
|
limit: limit
|
||||||
|
)
|
||||||
|
new TicketStatsList(
|
||||||
|
el: @$('.js-org-closed-tickets')
|
||||||
|
user: @user
|
||||||
|
head: 'Closed Ticket'
|
||||||
|
ticket_ids: data.org_tickets_closed_ids
|
||||||
|
limit: limit
|
||||||
|
)
|
||||||
|
new TicketStatsFrequency(
|
||||||
|
el: @$('.js-org-frequency')
|
||||||
|
user: @user
|
||||||
|
ticket_volume_by_year: data.org_ticket_volume_by_year
|
||||||
|
)
|
||||||
|
|
||||||
|
class TicketStatsList extends App.Controller
|
||||||
|
events:
|
||||||
|
'click .js-showAll': 'showAll'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
|
||||||
|
ticket_ids_show = []
|
||||||
|
if !@all
|
||||||
|
count = 0
|
||||||
|
for ticket_id in @ticket_ids
|
||||||
|
count += 1
|
||||||
|
if count <= @limit
|
||||||
|
ticket_ids_show.push ticket_id
|
||||||
|
else
|
||||||
|
ticket_ids_show = @ticket_ids
|
||||||
|
|
||||||
|
@html App.view('widget/ticket_stats_list')(
|
||||||
|
user: @user
|
||||||
|
head: @head
|
||||||
|
ticket_ids: @ticket_ids
|
||||||
|
ticket_ids_show: ticket_ids_show
|
||||||
|
limit: @limit
|
||||||
|
)
|
||||||
|
@frontendTimeUpdate()
|
||||||
|
@ticketPopups()
|
||||||
|
|
||||||
|
showAll: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@all = true
|
||||||
|
@render()
|
||||||
|
|
||||||
|
class TicketStatsFrequency extends App.Controller
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: (data) =>
|
||||||
|
|
||||||
|
# find 100%
|
||||||
|
max = 0
|
||||||
|
for item in @ticket_volume_by_year
|
||||||
|
if item.closed > max
|
||||||
|
max = item.closed
|
||||||
|
if item.created > max
|
||||||
|
max = item.created
|
||||||
|
|
||||||
|
for item in @ticket_volume_by_year
|
||||||
|
item.created_in_percent = 100 / max * item.created
|
||||||
|
item.closed_in_percent = 100 / max * item.closed
|
||||||
|
|
||||||
|
@html App.view('widget/ticket_stats_frequency')(
|
||||||
|
user: @user
|
||||||
|
ticket_volume_by_year: @ticket_volume_by_year.reverse()
|
||||||
|
)
|
|
@ -1,18 +1,49 @@
|
||||||
<div class="flex vertical">
|
<div class="flex userZoom">
|
||||||
<div class="flex u-positionOrigin horizontal">
|
|
||||||
<div class="main flex tabsSidebar-sidebarSpacer tabsSidebar-tabsSpacer">
|
|
||||||
<div class="organizationZoom">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1><%- @T( @head ) %></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="main-overviews" id="sortable"></div>
|
<div class="userZoom-window">
|
||||||
|
<div class="userZoom-section vertical centered">
|
||||||
|
<div class="align-right userZoom-action dropdown dropdown--actions action"></div>
|
||||||
|
<h1><%= @organization.displayName() %></h1>
|
||||||
|
</div>
|
||||||
|
<div class="userZoom-section">
|
||||||
|
<div class="userZoom-details horizontal wrap">
|
||||||
|
<% for row in @organizationData: %>
|
||||||
|
<% if @organization[row.name]: %>
|
||||||
|
<% if row.tag isnt 'textarea': %>
|
||||||
|
<div class="userZoom-detailsEntry">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<%- @L( @P( @organization[row.name] ) ) %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% for row in @organizationData: %>
|
||||||
|
<% if row.tag is 'textarea': %>
|
||||||
|
<div class="userZoom-detailsEntry" style="width: 100%;">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%= @organization[row.name] %></div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tabsSidebar vertical"></div>
|
<% if @organization.members: %>
|
||||||
|
<div class="userZoom-section">
|
||||||
|
<label><%- @T('Member') %></label>
|
||||||
|
<div class="userZoom-details horizontal wrap">
|
||||||
|
|
||||||
|
<% for user in @organization.members: %>
|
||||||
|
<div class="userZoom-detailsEntry">
|
||||||
|
<a href="<%- user.uiUrl() %>" class="user-popover" data-id="<%- user.id %>"><%= user.displayName() %></a>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="userZoom-section js-ticket-stats"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="bottom-form form-inline horizontal" role="form">
|
|
||||||
<div class="action"></div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
|
@ -24,7 +24,7 @@
|
||||||
<div class="u-textTruncate"><%- @T( @ticket.priority.name ) %></div>
|
<div class="u-textTruncate"><%- @T( @ticket.priority.name ) %></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h3><%- @T( 'Age' ) %></h3>
|
<h3><%- @T( 'Created' ) %></h3>
|
||||||
<div class="u-textTruncate"><%- @P( @ticket.humanTime ) %></div>
|
<div class="u-textTruncate"><%- @P( @ticket.humanTime ) %></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
|
|
@ -365,50 +365,96 @@ class TicketsController < ApplicationController
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /api/v1/ticket_stats/1
|
# GET /api/v1/ticket_stats
|
||||||
def stats
|
def stats
|
||||||
user = User.find(params[:id])
|
|
||||||
|
if !params[:user_id] && !params[:organization_id]
|
||||||
|
raise "Need user_id or organization_id as param"
|
||||||
|
end
|
||||||
|
|
||||||
# permissin check
|
# permissin check
|
||||||
#return if !ticket_permission(ticket)
|
#return if !ticket_permission(ticket)
|
||||||
|
|
||||||
# lookup open user tickets
|
# lookup open user tickets
|
||||||
limit = 100
|
limit = 100
|
||||||
assets = {}
|
assets = {}
|
||||||
condition = {
|
access_condition = Ticket.access_condition( current_user )
|
||||||
'tickets.state_id' => Ticket::State.by_category('open'),
|
now = DateTime.now
|
||||||
'tickets.customer_id' => user.id,
|
user_tickets_open_ids = []
|
||||||
}
|
user_tickets_closed_ids = []
|
||||||
user_tickets_open = Ticket.search(
|
user_ticket_volume_by_year = []
|
||||||
:limit => limit,
|
if params[:user_id]
|
||||||
#:query => params[:term],
|
user = User.find( params[:user_id] )
|
||||||
:condition => condition,
|
condition = {
|
||||||
:current_user => current_user,
|
'tickets.state_id' => Ticket::State.by_category('open'),
|
||||||
:detail => true,
|
'tickets.customer_id' => user.id,
|
||||||
)
|
}
|
||||||
user_tickets_open_ids = assets_of_tickets(user_tickets_open, assets)
|
user_tickets_open = Ticket.search(
|
||||||
|
:limit => limit,
|
||||||
|
#:query => params[:term],
|
||||||
|
:condition => condition,
|
||||||
|
:current_user => current_user,
|
||||||
|
:detail => true,
|
||||||
|
)
|
||||||
|
user_tickets_open_ids = assets_of_tickets(user_tickets_open, assets)
|
||||||
|
|
||||||
# lookup closed user tickets
|
# lookup closed user tickets
|
||||||
condition = {
|
condition = {
|
||||||
'tickets.state_id' => Ticket::State.by_category('closed'),
|
'tickets.state_id' => Ticket::State.by_category('closed'),
|
||||||
'tickets.customer_id' => user.id,
|
'tickets.customer_id' => user.id,
|
||||||
}
|
}
|
||||||
user_tickets_closed = Ticket.search(
|
user_tickets_closed = Ticket.search(
|
||||||
:limit => limit,
|
:limit => limit,
|
||||||
#:query => params[:term],
|
#:query => params[:term],
|
||||||
:condition => condition,
|
:condition => condition,
|
||||||
:current_user => current_user,
|
:current_user => current_user,
|
||||||
:detail => true,
|
:detail => true,
|
||||||
)
|
)
|
||||||
user_tickets_closed_ids = assets_of_tickets(user_tickets_closed, assets)
|
user_tickets_closed_ids = assets_of_tickets(user_tickets_closed, assets)
|
||||||
|
|
||||||
|
# generate stats by user
|
||||||
|
(0..11).each {|month_back|
|
||||||
|
date_to_check = DateTime.now - month_back.month
|
||||||
|
date_start = "#{date_to_check.year}-#{date_to_check.month}-#{01} 00:00:00"
|
||||||
|
date_end = "#{date_to_check.year}-#{date_to_check.month}-#{date_to_check.end_of_month.day} 00:00:00"
|
||||||
|
|
||||||
|
condition = {
|
||||||
|
'tickets.customer_id' => user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
# created
|
||||||
|
created = Ticket.where('created_at > ? AND created_at < ?', date_start, date_end ).
|
||||||
|
where(access_condition).
|
||||||
|
where(condition).
|
||||||
|
count
|
||||||
|
|
||||||
|
# closed
|
||||||
|
closed = Ticket.where('close_time > ? AND close_time < ?', date_start, date_end ).
|
||||||
|
where(access_condition).
|
||||||
|
where(condition).
|
||||||
|
count
|
||||||
|
|
||||||
|
data = {
|
||||||
|
:month => date_to_check.month,
|
||||||
|
:year => date_to_check.year,
|
||||||
|
:text => Date::MONTHNAMES[date_to_check.month],
|
||||||
|
:created => created,
|
||||||
|
:closed => closed,
|
||||||
|
}
|
||||||
|
user_ticket_volume_by_year.push data
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# lookup open org tickets
|
# lookup open org tickets
|
||||||
org_tickets_open_ids = []
|
org_tickets_open_ids = []
|
||||||
if user.organization_id
|
org_tickets_closed_ids = []
|
||||||
|
org_ticket_volume_by_year = []
|
||||||
|
if params[:organization_id] && !params[:organization_id].empty?
|
||||||
|
organization = Organization.find( params[:organization_id] )
|
||||||
|
|
||||||
condition = {
|
condition = {
|
||||||
'tickets.state_id' => Ticket::State.by_category('open'),
|
'tickets.state_id' => Ticket::State.by_category('open'),
|
||||||
'tickets.organization_id' => user.organization_id,
|
'tickets.organization_id' => params[:organization_id],
|
||||||
}
|
}
|
||||||
org_tickets_open = Ticket.search(
|
org_tickets_open = Ticket.search(
|
||||||
:limit => limit,
|
:limit => limit,
|
||||||
|
@ -418,14 +464,11 @@ class TicketsController < ApplicationController
|
||||||
:detail => true,
|
:detail => true,
|
||||||
)
|
)
|
||||||
org_tickets_open_ids = assets_of_tickets(org_tickets_open, assets)
|
org_tickets_open_ids = assets_of_tickets(org_tickets_open, assets)
|
||||||
end
|
|
||||||
|
|
||||||
# lookup closed org tickets
|
# lookup closed org tickets
|
||||||
org_tickets_closed_ids = []
|
|
||||||
if user.organization_id
|
|
||||||
condition = {
|
condition = {
|
||||||
'tickets.state_id' => Ticket::State.by_category('closed'),
|
'tickets.state_id' => Ticket::State.by_category('closed'),
|
||||||
'tickets.organization_id' => user.organization_id,
|
'tickets.organization_id' => params[:organization_id],
|
||||||
}
|
}
|
||||||
org_tickets_closed = Ticket.search(
|
org_tickets_closed = Ticket.search(
|
||||||
:limit => limit,
|
:limit => limit,
|
||||||
|
@ -435,64 +478,34 @@ class TicketsController < ApplicationController
|
||||||
:detail => true,
|
:detail => true,
|
||||||
)
|
)
|
||||||
org_tickets_closed_ids = assets_of_tickets(org_tickets_closed, assets)
|
org_tickets_closed_ids = assets_of_tickets(org_tickets_closed, assets)
|
||||||
|
|
||||||
|
# generate stats by org
|
||||||
|
(0..11).each {|month_back|
|
||||||
|
date_to_check = DateTime.now - month_back.month
|
||||||
|
date_start = "#{date_to_check.year}-#{date_to_check.month}-#{01} 00:00:00"
|
||||||
|
date_end = "#{date_to_check.year}-#{date_to_check.month}-#{date_to_check.end_of_month.day} 00:00:00"
|
||||||
|
|
||||||
|
condition = {
|
||||||
|
'tickets.organization_id' => params[:organization_id],
|
||||||
|
}
|
||||||
|
|
||||||
|
# created
|
||||||
|
created = Ticket.where('created_at > ? AND created_at < ?', date_start, date_end ).where(condition).count
|
||||||
|
|
||||||
|
# closed
|
||||||
|
closed = Ticket.where('close_time > ? AND close_time < ?', date_start, date_end ).where(condition).count
|
||||||
|
|
||||||
|
data = {
|
||||||
|
:month => date_to_check.month,
|
||||||
|
:year => date_to_check.year,
|
||||||
|
:text => Date::MONTHNAMES[date_to_check.month],
|
||||||
|
:created => created,
|
||||||
|
:closed => closed,
|
||||||
|
}
|
||||||
|
org_ticket_volume_by_year.push data
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# generate stats by user
|
|
||||||
user_ticket_volume_by_year = []
|
|
||||||
now = DateTime.now
|
|
||||||
(0..11).each {|month_back|
|
|
||||||
date_to_check = DateTime.now - month_back.month
|
|
||||||
date_start = "#{date_to_check.year}-#{date_to_check.month}-#{01} 00:00:00"
|
|
||||||
date_end = "#{date_to_check.year}-#{date_to_check.month}-#{date_to_check.end_of_month.day} 00:00:00"
|
|
||||||
|
|
||||||
condition = {
|
|
||||||
'tickets.customer_id' => user.id,
|
|
||||||
}
|
|
||||||
|
|
||||||
# created
|
|
||||||
created = Ticket.where('created_at > ? AND created_at < ?', date_start, date_end ).where(condition).count
|
|
||||||
|
|
||||||
# closed
|
|
||||||
closed = Ticket.where('close_time > ? AND close_time < ?', date_start, date_end ).where(condition).count
|
|
||||||
|
|
||||||
data = {
|
|
||||||
:month => date_to_check.month,
|
|
||||||
:year => date_to_check.year,
|
|
||||||
:text => Date::MONTHNAMES[date_to_check.month],
|
|
||||||
:created => created,
|
|
||||||
:closed => closed,
|
|
||||||
}
|
|
||||||
user_ticket_volume_by_year.push data
|
|
||||||
}
|
|
||||||
|
|
||||||
# generate stats by org
|
|
||||||
org_ticket_volume_by_year = []
|
|
||||||
now = DateTime.now
|
|
||||||
(0..11).each {|month_back|
|
|
||||||
date_to_check = DateTime.now - month_back.month
|
|
||||||
date_start = "#{date_to_check.year}-#{date_to_check.month}-#{01} 00:00:00"
|
|
||||||
date_end = "#{date_to_check.year}-#{date_to_check.month}-#{date_to_check.end_of_month.day} 00:00:00"
|
|
||||||
|
|
||||||
condition = {
|
|
||||||
'tickets.organization_id' => user.organization_id,
|
|
||||||
}
|
|
||||||
|
|
||||||
# created
|
|
||||||
created = Ticket.where('created_at > ? AND created_at < ?', date_start, date_end ).where(condition).count
|
|
||||||
|
|
||||||
# closed
|
|
||||||
closed = Ticket.where('close_time > ? AND close_time < ?', date_start, date_end ).where(condition).count
|
|
||||||
|
|
||||||
data = {
|
|
||||||
:month => date_to_check.month,
|
|
||||||
:year => date_to_check.year,
|
|
||||||
:text => Date::MONTHNAMES[date_to_check.month],
|
|
||||||
:created => created,
|
|
||||||
:closed => closed,
|
|
||||||
}
|
|
||||||
org_ticket_volume_by_year.push data
|
|
||||||
}
|
|
||||||
|
|
||||||
# return result
|
# return result
|
||||||
render :json => {
|
render :json => {
|
||||||
:user_tickets_open_ids => user_tickets_open_ids,
|
:user_tickets_open_ids => user_tickets_open_ids,
|
||||||
|
|
|
@ -79,6 +79,36 @@ returns
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
|
get user access conditions
|
||||||
|
|
||||||
|
connditions = Ticket.access_condition( User.find(1) )
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
result = [user1, user2, ...]
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.access_condition(user)
|
||||||
|
access_condition = []
|
||||||
|
if user.is_role('Agent')
|
||||||
|
group_ids = Group.select( 'groups.id' ).joins(:users).
|
||||||
|
where( 'groups_users.user_id = ?', user.id ).
|
||||||
|
where( 'groups.active = ?', true ).
|
||||||
|
map( &:id )
|
||||||
|
access_condition = [ 'group_id IN (?)', group_ids ]
|
||||||
|
else
|
||||||
|
if !user.organization || ( !user.organization.shared || user.organization.shared == false )
|
||||||
|
access_condition = [ 'customer_id = ?', user.id ]
|
||||||
|
else
|
||||||
|
access_condition = [ '( customer_id = ? OR organization_id = ? )', user.id, user.organization.id ]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
access_condition
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
merge tickets
|
merge tickets
|
||||||
|
|
||||||
ticket = Ticket.find(123)
|
ticket = Ticket.find(123)
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Ticket::Search
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
search tickets
|
search tickets via search index
|
||||||
|
|
||||||
result = Ticket.search(
|
result = Ticket.search(
|
||||||
:current_user => User.find(123),
|
:current_user => User.find(123),
|
||||||
|
@ -17,7 +17,7 @@ returns
|
||||||
result = [ticket_model1, ticket_model2]
|
result = [ticket_model1, ticket_model2]
|
||||||
|
|
||||||
|
|
||||||
search tickets
|
search tickets via search index
|
||||||
|
|
||||||
result = Ticket.search(
|
result = Ticket.search(
|
||||||
:current_user => User.find(123),
|
:current_user => User.find(123),
|
||||||
|
@ -30,6 +30,22 @@ returns
|
||||||
|
|
||||||
result = [1,3,5,6,7]
|
result = [1,3,5,6,7]
|
||||||
|
|
||||||
|
|
||||||
|
search tickets via database
|
||||||
|
|
||||||
|
result = Ticket.search(
|
||||||
|
:current_user => User.find(123),
|
||||||
|
:condition => '',
|
||||||
|
:detail => true,
|
||||||
|
:limit => 15,
|
||||||
|
:full => 0
|
||||||
|
)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
result = [1,3,5,6,7]
|
||||||
|
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def search (params)
|
def search (params)
|
||||||
|
@ -94,20 +110,7 @@ returns
|
||||||
end
|
end
|
||||||
|
|
||||||
# fallback do sql query
|
# fallback do sql query
|
||||||
access_condition = []
|
access_condition = Ticket.access_condition( current_user )
|
||||||
if current_user.is_role('Agent')
|
|
||||||
group_ids = Group.select( 'groups.id' ).joins(:users).
|
|
||||||
where( 'groups_users.user_id = ?', current_user.id ).
|
|
||||||
where( 'groups.active = ?', true ).
|
|
||||||
map( &:id )
|
|
||||||
access_condition = [ 'group_id IN (?)', group_ids ]
|
|
||||||
else
|
|
||||||
if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false )
|
|
||||||
access_condition = [ 'customer_id = ?', current_user.id ]
|
|
||||||
else
|
|
||||||
access_condition = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# do query
|
# do query
|
||||||
# - stip out * we already search for *query* -
|
# - stip out * we already search for *query* -
|
||||||
|
|
|
@ -13,7 +13,7 @@ Zammad::Application.routes.draw do
|
||||||
match api_path + '/ticket_customer', :to => 'tickets#ticket_customer', :via => :get
|
match api_path + '/ticket_customer', :to => 'tickets#ticket_customer', :via => :get
|
||||||
match api_path + '/ticket_related/:ticket_id', :to => 'tickets#ticket_related', :via => :get
|
match api_path + '/ticket_related/:ticket_id', :to => 'tickets#ticket_related', :via => :get
|
||||||
match api_path + '/ticket_merge/:slave_ticket_id/:master_ticket_number', :to => 'tickets#ticket_merge', :via => :get
|
match api_path + '/ticket_merge/:slave_ticket_id/:master_ticket_number', :to => 'tickets#ticket_merge', :via => :get
|
||||||
match api_path + '/ticket_stats/:id', :to => 'tickets#stats', :via => :get
|
match api_path + '/ticket_stats', :to => 'tickets#stats', :via => :get
|
||||||
|
|
||||||
# ticket overviews
|
# ticket overviews
|
||||||
match api_path + '/ticket_overviews', :to => 'ticket_overviews#show', :via => :get
|
match api_path + '/ticket_overviews', :to => 'ticket_overviews#show', :via => :get
|
||||||
|
|
Loading…
Reference in a new issue