Improved bulk action and overview.

This commit is contained in:
Martin Edenhofer 2012-11-03 17:45:57 +01:00
parent fcb5ae524b
commit 9cc2bfd71e
9 changed files with 237 additions and 183 deletions

View file

@ -136,7 +136,7 @@ class App.Controller extends Spine.Controller
frontendTime: (timestamp) ->
'<span class="humanTimeFromNow" data-time="' + timestamp + '">?</span>'
frontendTimeUpdate: ->
frontendTimeUpdate: =>
update = =>
ui = @
$('.humanTimeFromNow').each( ->

View file

@ -46,7 +46,7 @@ class Index extends App.Controller
# get meta data
@overview = data.overview
App.Overview.refresh( @overview, options: { clear: true } )
App.Overview.refresh( @overview, { clear: true } )
App.Overview.unbind('local:rerender')
App.Overview.bind 'local:rerender', (record) =>
@ -86,6 +86,8 @@ class Index extends App.Controller
render: ->
@selected = @bulkGetSelected()
# set page title
@title @overview.meta.name
@ -99,23 +101,23 @@ class Index extends App.Controller
edit = false
view_modes = [
{
name: 'S',
type: 's',
class: 'active' if @view_mode is 's',
name: 'S'
type: 's'
class: 'active' if @view_mode is 's'
},
{
name: 'M',
type: 'm',
class: 'active' if @view_mode is 'm',
name: 'M'
type: 'm'
class: 'active' if @view_mode is 'm'
}
]
html = App.view('agent_ticket_view')(
overview: @overview,
view_modes: view_modes,
pages_total: pages_total,
start_page: @start_page,
checkbox: true,
edit: edit,
overview: @overview
view_modes: view_modes
pages_total: pages_total
start_page: @start_page
checkbox: true
edit: edit
)
html = $(html)
# html.find('li').removeClass('active')
@ -127,9 +129,9 @@ class Index extends App.Controller
table = ''
if @view_mode is 'm'
table = App.view('agent_ticket_view/detail')(
overview: @overview,
objects: @ticket_list_show,
checkbox: checkbox,
overview: @overview
objects: @ticket_list_show
checkbox: checkbox
)
table = $(table)
table.delegate('[name="bulk_all"]', 'click', (e) ->
@ -141,18 +143,30 @@ class Index extends App.Controller
@el.find('.table-overview').append(table)
else
shown_all_attributes = @ticketTableAttributes( App.Overview.find( @overview.id ).view.s.overview )
groupBy = undefined
if @overview.group_by
group_by =
name: @overview.group_by
id: @overview.group_by + '_id'
# remove group by attribute from show attributes list
shown_all_attributes = _.filter(
shown_all_attributes
(item) =>
return item if item.name isnt @overview.group_by
return
)
new App.ControllerTable(
el: @el.find('.table-overview'),
overview_extended: shown_all_attributes,
model: App.Ticket,
objects: @ticket_list_show,
checkbox: checkbox,
groupBy:
display: 'roup'
data: 'group',
data_id: 'group_id',
el: @el.find('.table-overview')
overview_extended: shown_all_attributes
model: App.Ticket
objects: @ticket_list_show
checkbox: checkbox
groupBy: group_by
)
@bulkSetSelected( @selected )
# start user popups
@userPopups()
@ -161,6 +175,8 @@ class Index extends App.Controller
# start bulk action observ
@el.find('.bulk-action').append( @bulk_form() )
if @el.find('.table-overview').find('[name="bulk"]:checked').length isnt 0
@el.find('.bulk-action').removeClass('hide')
# show/hide bulk action
@el.find('.table-overview').delegate('[name="bulk"], [name="bulk_all"]', 'click', (e) =>
@ -214,6 +230,22 @@ class Index extends App.Controller
)
return html
bulkGetSelected: ->
@ticketIDs = []
@el.find('.table-overview').find('[name="bulk"]:checked').each( (index, element) =>
ticket_id = $(element).val()
@ticketIDs.push ticket_id
)
@ticketIDs
bulkSetSelected: (ticketIDs) ->
@el.find('.table-overview').find('[name="bulk"]').each( (index, element) =>
ticket_id = $(element).val()
for ticket_id_selected in ticketIDs
if ticket_id_selected is ticket_id
$(element).attr( 'checked', true )
)
bulk_submit: (e) =>
@bulk_count = @el.find('.table-overview').find('[name="bulk"]:checked').length
@bulk_count_index = 0
@ -282,81 +314,92 @@ class Settings extends App.ControllerModal
# { name: 'ticket_article_type_id', display: 'Type', tag: 'select', multiple: false, null: true, relation: 'TicketArticleType', default: '9', class: 'medium', item_class: 'keepleft' },
# { name: 'internal', display: 'Visability', tag: 'radio', default: false, null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: 'keepleft' },
{
name: 'per_page',
display: 'Items per page',
tag: 'select',
multiple: false,
null: false,
default: @overview.view[@view_mode].per_page,
options: {
15: 15,
20: 20,
25: 25,
30: 30,
35: 35,
},
class: 'medium',
# item_class: 'keepleft',
name: 'per_page'
display: 'Items per page'
tag: 'select'
multiple: false
null: false
default: @overview.view[@view_mode].per_page
options:
15: 15
20: 20
25: 25
30: 30
35: 35
class: 'medium'
# item_class: 'keepleft'
},
{
name: 'attributes',
display: 'Attributes',
tag: 'checkbox',
default: @overview.view[@view_mode].overview,
null: false,
options: {
# true: 'internal',
# false: 'public',
number: 'Number',
title: 'Title',
customer: 'Customer',
ticket_state: 'State',
ticket_priority: 'Priority',
group: 'Group',
owner: 'Owner',
created_at: 'Alter',
last_contact: 'Last Contact',
last_contact_agent: 'Last Contact Agent',
last_contact_customer: 'Last Contact Customer',
first_response: 'First Response',
close_time: 'Close Time',
},
class: 'medium',
name: 'attributes'
display: 'Attributes'
tag: 'checkbox'
default: @overview.view[@view_mode].overview
null: false
options:
# true: 'internal'
# false: 'public'
number: 'Number'
title: 'Title'
customer: 'Customer'
ticket_state: 'State'
ticket_priority: 'Priority'
group: 'Group'
owner: 'Owner'
created_at: 'Alter'
last_contact: 'Last Contact'
last_contact_agent: 'Last Contact Agent'
last_contact_customer: 'Last Contact Customer'
first_response: 'First Response'
close_time: 'Close Time'
class: 'medium'
},
{
name: 'order_by',
display: 'Order',
tag: 'select',
default: @overview.order.by,
null: false,
options: {
number: 'Number',
title: 'Title',
customer: 'Customer',
ticket_state: 'State',
ticket_priority: 'Priority',
group: 'Group',
owner: 'Owner',
created_at: 'Alter',
last_contact: 'Last Contact',
last_contact_agent: 'Last Contact Agent',
last_contact_customer: 'Last Contact Customer',
first_response: 'First Response',
close_time: 'Close Time',
},
class: 'medium',
name: 'order_by'
display: 'Order'
tag: 'select'
default: @overview.order.by
null: false
options:
number: 'Number'
title: 'Title'
customer: 'Customer'
ticket_state: 'State'
ticket_priority: 'Priority'
group: 'Group'
owner: 'Owner'
created_at: 'Alter'
last_contact: 'Last Contact'
last_contact_agent: 'Last Contact Agent'
last_contact_customer: 'Last Contact Customer'
first_response: 'First Response'
close_time: 'Close Time'
class: 'medium'
},
{
name: 'order_by_direction',
display: 'Direction',
tag: 'select',
default: @overview.order.direction,
null: false,
options: {
ASC: 'up',
DESC: 'down',
},
class: 'medium',
name: 'order_by_direction'
display: 'Direction'
tag: 'select'
default: @overview.order.direction
null: false
options:
ASC: 'up'
DESC: 'down'
class: 'medium'
},
{
name: 'group_by'
display: 'Group by'
tag: 'select'
default: @overview.group_by
null: true
nulloption: true
options:
customer: 'Customer'
ticket_state: 'State'
ticket_priority: 'Priority'
group: 'Group'
owner: 'Owner'
class: 'medium'
},
# {
# name: 'condition',
@ -372,9 +415,9 @@ class Settings extends App.ControllerModal
]
new App.ControllerForm(
el: @el.find('#form-setting'),
model: { configure_attributes: @configure_attributes_article },
autofocus: false,
el: @el.find('#form-setting')
model: { configure_attributes: @configure_attributes_article }
autofocus: false
)
@modalShow()
@ -397,6 +440,10 @@ class Settings extends App.ControllerModal
@overview.order['direction'] = params['order_by_direction']
@reload_needed = 1
if @overview['group_by'] isnt params['group_by']
@overview['group_by'] = params['group_by']
@reload_needed = 1
@overview.view[@view_mode]['overview'] = params['attributes']
@overview.save(
@ -423,14 +470,13 @@ class Router extends App.Controller
@redirect()
else
App.Com.ajax(
type: 'GET',
url: '/api/ticket_overviews',
data: {
view: @view,
array: true,
}
processData: true,
success: @load
type: 'GET'
url: '/api/ticket_overviews'
data:
view: @view
array: true
processData: true
success: @load
)
load: (data) =>

View file

@ -2,14 +2,14 @@ $ = jQuery.sub()
class Index extends App.Controller
events:
'click .submit': 'update',
'click [data-type=reply]': 'reply',
# 'click [data-type=reply-all]': 'replyall',
'click [data-type=public]': 'public_internal',
'click [data-type=internal]': 'public_internal',
'change [name="ticket_article_type_id"]': 'form_update',
'click .show_toogle': 'show_toogle',
'blur .title_update': 'title_update',
'click .submit': 'update'
'click [data-type=reply]': 'reply'
# 'click [data-type=reply-all]': 'replyall'
'click [data-type=public]': 'public_internal'
'click [data-type=internal]': 'public_internal'
'change [name="ticket_article_type_id"]': 'form_update'
'click .show_toogle': 'show_toogle'
'blur .title_update': 'title_update'
constructor: (params) ->
super
@ -20,10 +20,10 @@ class Index extends App.Controller
@navupdate '#'
@edit_form = undefined
@ticket_id = params.ticket_id
@article_id = params.article_id
@signature = undefined
@edit_form = undefined
@ticket_id = params.ticket_id
@article_id = params.article_id
@signature = undefined
@signature_used = undefined
@key = 'ticket::' + @ticket_id
@ -36,13 +36,12 @@ class Index extends App.Controller
# get data
App.Com.ajax(
id: 'ticket_zoom',
type: 'GET',
url: '/api/ticket_full/' + ticket_id,
data: {
id: 'ticket_zoom'
type: 'GET'
url: '/api/ticket_full/' + ticket_id
data:
view: @view
}
processData: true,
processData: true
success: (data, status, xhr) =>
@load(data)
App.Store.write( @key, data )
@ -119,30 +118,25 @@ class Index extends App.Controller
]
@html App.view('agent_ticket_zoom')(
ticket: @ticket,
articles: @articles,
nav: @nav,
ticket: @ticket
articles: @articles
nav: @nav
)
new App.ControllerForm(
el: @el.find('#form-ticket-update'),
model: {
configure_attributes: @configure_attributes_ticket,
className: 'create',
},
params: @ticket
form_data: @edit_form,
el: @el.find('#form-ticket-update')
model:
configure_attributes: @configure_attributes_ticket
className: 'create'
params: @ticket
form_data: @edit_form
)
new App.ControllerForm(
el: @el.find('#form-article-update'),
model: {
configure_attributes: @configure_attributes_article,
},
# params: {
# body: @signature.body,
# }
form_data: @edit_form,
el: @el.find('#form-article-update')
model:
configure_attributes: @configure_attributes_article
form_data: @edit_form
)
@el.find('textarea').elastic()
@ -168,13 +162,12 @@ class Index extends App.Controller
u: =>
uploader = new qq.FileUploader(
element: document.getElementById('file-uploader'),
action: '/api/ticket_attachment_new',
params: {
form: 'TicketZoom',
form_id: @ticket.id,
},
debug: false
element: document.getElementById('file-uploader')
action: '/api/ticket_attachment_new'
params:
form: 'TicketZoom'
form_id: @ticket.id
debug: false
)
ticket_action_row: =>
@ -182,34 +175,33 @@ class Index extends App.Controller
# start customer info controller
if !@isRole('Customer')
new App.UserInfo(
el: @el.find('#customer_info'),
user_id: @ticket.customer_id,
ticket: @ticket,
el: @el.find('#customer_info')
user_id: @ticket.customer_id
ticket: @ticket
)
# start action controller
if !@isRole('Customer')
new TicketActionRow(
el: @el.find('#action_info'),
ticket: @ticket,
zoom: @,
el: @el.find('#action_info')
ticket: @ticket
zoom: @
)
# start link info controller
if !@isRole('Customer')
new App.LinkInfo(
el: @el.find('#link_info'),
object_type: 'Ticket',
object: @ticket,
el: @el.find('#link_info')
object_type: 'Ticket'
object: @ticket
)
# show text module UI
if !@isRole('Customer')
new App.TextModuleUI(
el: @el.find('#text_module'),
data: {
ticket: @ticket,
},
el: @el.find('#text_module')
data:
ticket: @ticket
)
show_toogle: (e) ->
@ -484,15 +476,15 @@ class Article extends App.Controller
if @article.internal is true
actions = [
{
name: 'set to public',
type: 'public',
name: 'set to public'
type: 'public'
}
]
else
actions = [
{
name: 'set to internal',
type: 'internal',
name: 'set to internal'
type: 'internal'
}
]
if @article.article_type.name is 'note'
@ -500,19 +492,19 @@ class Article extends App.Controller
else
if @article.article_sender.name is 'Customer'
actions.push {
name: 'reply',
type: 'reply',
href: '#',
name: 'reply'
type: 'reply'
href: '#'
}
# actions.push {
# name: 'reply all',
# type: 'reply-all',
# href: '#',
# name: 'reply all'
# type: 'reply-all'
# href: '#'
# }
actions.push {
name: 'split',
type: 'split',
href: '#ticket_create/' + @article.ticket_id + '/' + @article.id,
name: 'split'
type: 'split'
href: '#ticket_create/' + @article.ticket_id + '/' + @article.id
}
@article.actions = actions
@ -523,9 +515,9 @@ class Article extends App.Controller
class TicketActionRow extends App.Controller
events:
'click [data-type=history]': 'history_dialog',
'click [data-type=merge]': 'merge_dialog',
'click [data-type=customer]': 'customer_dialog',
'click [data-type=history]': 'history_dialog'
'click [data-type=merge]': 'merge_dialog'
'click [data-type=customer]': 'customer_dialog'
constructor: ->
super

View file

@ -1,4 +1,4 @@
class App.Overview extends Spine.Model
@configure 'Overview', 'name', 'meta', 'condition', 'order', 'view', 'user_id', 'group_ids'
@configure 'Overview', 'name', 'meta', 'condition', 'order', 'group_by', 'view', 'user_id', 'group_ids'
@extend Spine.Model.Ajax
@url: '/api/overviews'

View file

@ -20,9 +20,9 @@
<% groupLast = '' %>
<% for object in @objects: %>
<% if @groupBy: %>
<% if groupLast isnt object[@groupBy.data_id]: %>
<tr class=""><td colspan="<%= @overview.length + 1 %>"><b><%- @P( object[@groupBy.data] ) %></b></td></tr>
<% groupLast = object[@groupBy.data_id] %>
<% if groupLast isnt object[@groupBy.id]: %>
<tr class=""><td colspan="<%= @overview.length + 1 %>"><b><%- @P( object[@groupBy.name] ) %></b></td></tr>
<% groupLast = object[@groupBy.id] %>
<% end %>
<% end %>
<% position++ %>

View file

@ -13,6 +13,7 @@ Example:
"meta":{"m_a":1,"m_b":2},
"condition":{"c_a":1,"c_b":2},
"order":{"o_a":1,"o_b":2},
"group_by":"group",
"view":{"v_a":1,"v_b":2},
"user_id": null,
"role_id": null,
@ -84,6 +85,7 @@ Payload:
"meta":{"m_a":1,"m_b":2},
"condition":{"c_a":1,"c_b":2},
"order":{"o_a":1,"o_b":2},
"group_by":"group",
"view":{"v_a":1,"v_b":2},
"user_id": null,
"role_id": null,
@ -116,6 +118,7 @@ Payload:
"meta":{"m_a":1,"m_b":2},
"condition":{"c_a":1,"c_b":2},
"order":{"o_a":1,"o_b":2},
"group_by":"group",
"view":{"v_a":1,"v_b":2},
"user_id": null,
"role_id": null,

View file

@ -259,10 +259,14 @@ class Ticket < ApplicationModel
# get result list
if data[:array]
order_by = overview_selected[:order][:by].to_s + ' ' + overview_selected[:order][:direction].to_s
if overview_selected.group_by && !overview_selected.group_by.empty?
order_by = overview_selected.group_by + '_id, ' + order_by
end
tickets = Ticket.select( 'id' ).
where( :group_id => group_ids ).
where( overview_selected.condition ).
order( 'group_id, ' + overview_selected[:order][:by].to_s + ' ' + overview_selected[:order][:direction].to_s ).
order( order_by ).
limit( 500 )
ticket_ids = []

View file

@ -152,6 +152,7 @@ class CreateTicket < ActiveRecord::Migration
t.column :meta, :string, :limit => 1000, :null => false
t.column :condition, :string, :limit => 2500, :null => false
t.column :order, :string, :limit => 2500, :null => false
t.column :group_by, :string, :limit => 250, :null => true
t.column :view, :string, :limit => 1000, :null => false
t.column :updated_by_id, :integer, :null => false
t.column :created_by_id, :integer, :null => false

View file

@ -0,0 +1,8 @@
class OverviewUpdate2 < ActiveRecord::Migration
def up
add_column :overviews, :group_by, :string, :limit => 250, :null => true
end
def down
end
end