From 9cc2bfd71eef04af271d21390e74be7702968648 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 3 Nov 2012 17:45:57 +0100 Subject: [PATCH] Improved bulk action and overview. --- .../_application_controller.js.coffee | 2 +- .../controllers/agent_ticket_view.js.coffee | 256 +++++++++++------- .../controllers/agent_ticket_zoom.js.coffee | 136 +++++----- .../javascripts/app/models/overview.js.coffee | 2 +- .../app/views/generic/table.jst.eco | 6 +- app/controllers/overviews_controller.rb | 3 + app/models/ticket.rb | 6 +- db/migrate/20120101000010_create_ticket.rb | 1 + .../20121103114535_overview_update_2.rb | 8 + 9 files changed, 237 insertions(+), 183 deletions(-) create mode 100644 db/migrate/20121103114535_overview_update_2.rb diff --git a/app/assets/javascripts/app/controllers/_application_controller.js.coffee b/app/assets/javascripts/app/controllers/_application_controller.js.coffee index 09cbaa143..4140a5712 100644 --- a/app/assets/javascripts/app/controllers/_application_controller.js.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller.js.coffee @@ -136,7 +136,7 @@ class App.Controller extends Spine.Controller frontendTime: (timestamp) -> '?' - frontendTimeUpdate: -> + frontendTimeUpdate: => update = => ui = @ $('.humanTimeFromNow').each( -> diff --git a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee index fa5c7432a..a113fd33f 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee @@ -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) => diff --git a/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee index fb7a3039d..66faf1bdd 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee @@ -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 diff --git a/app/assets/javascripts/app/models/overview.js.coffee b/app/assets/javascripts/app/models/overview.js.coffee index b7b492476..6976f2083 100644 --- a/app/assets/javascripts/app/models/overview.js.coffee +++ b/app/assets/javascripts/app/models/overview.js.coffee @@ -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' diff --git a/app/assets/javascripts/app/views/generic/table.jst.eco b/app/assets/javascripts/app/views/generic/table.jst.eco index ea6a41017..cca67a726 100644 --- a/app/assets/javascripts/app/views/generic/table.jst.eco +++ b/app/assets/javascripts/app/views/generic/table.jst.eco @@ -20,9 +20,9 @@ <% groupLast = '' %> <% for object in @objects: %> <% if @groupBy: %> - <% if groupLast isnt object[@groupBy.data_id]: %> - <%- @P( object[@groupBy.data] ) %> - <% groupLast = object[@groupBy.data_id] %> + <% if groupLast isnt object[@groupBy.id]: %> + <%- @P( object[@groupBy.name] ) %> + <% groupLast = object[@groupBy.id] %> <% end %> <% end %> <% position++ %> diff --git a/app/controllers/overviews_controller.rb b/app/controllers/overviews_controller.rb index 89fff4edc..cdd5c155b 100644 --- a/app/controllers/overviews_controller.rb +++ b/app/controllers/overviews_controller.rb @@ -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, diff --git a/app/models/ticket.rb b/app/models/ticket.rb index f27d8b553..2fa28056b 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -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 = [] diff --git a/db/migrate/20120101000010_create_ticket.rb b/db/migrate/20120101000010_create_ticket.rb index 818f7b90c..5f1817cd6 100644 --- a/db/migrate/20120101000010_create_ticket.rb +++ b/db/migrate/20120101000010_create_ticket.rb @@ -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 diff --git a/db/migrate/20121103114535_overview_update_2.rb b/db/migrate/20121103114535_overview_update_2.rb new file mode 100644 index 000000000..f5d14caf7 --- /dev/null +++ b/db/migrate/20121103114535_overview_update_2.rb @@ -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