diff --git a/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee new file mode 100644 index 000000000..f2288d253 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee @@ -0,0 +1,132 @@ +class App.DashboardTicketSearch extends App.Controller + events: + 'click [data-type=page]': 'page' + + constructor: -> + super + @start_page = 1 + @navupdate '#' + + # render + @fetch() + + fetch: (force) => + + @ajax( + id: 'dashboard_ticket_search' + @name, + type: 'GET', + url: @apiPath + '/tickets/search', + data: + condition: @condition + order: @order + detail: true + limit: 200 + processData: true, + success: (data) => + + @load( data, true ) + ) + + load: (data = false, ajax = false) => + + if ajax + App.Store.write( 'dashboard_ticket_search' + @name, data ) + + # load assets + App.Collection.loadAssets( data.assets ) + + @render( data ) + + else + data = App.Store.get( 'dashboard_ticket_search' + @name ) + if data + @render( data ) + + + render: (data) -> + return if !data + return if !data.tickets + + @overview = + name: @name + @tickets_count = data.tickets_count + @ticket_ids = data.tickets + per_page = @per_page || 5 + pages_total = parseInt( ( @tickets_count / per_page ) + 0.99999 ) || 1 + html = App.view('dashboard/ticket')( + overview: @overview, + pages_total: pages_total, + start_page: @start_page, + ) + html = $(html) + html.find('li').removeClass('active') + html.find(".page [data-id=\"#{@start_page}\"]").parents('li').addClass('active') + + @tickets_in_table = [] + start = ( @start_page-1 ) * 5 + end = ( @start_page ) * 5 + i = start + while i < end + i = i + 1 + if @ticket_ids[ i - 1 ] + @tickets_in_table.push App.Ticket.fullLocal( @ticket_ids[ i - 1 ] ) + + openTicket = (id,e) => + ticket = App.Ticket.fullLocal(id) + @navigate ticket.uiUrl() + callbackTicketTitleAdd = (value, object, attribute, attributes, refObject) => + attribute.title = object.title + value + callbackLinkToTicket = (value, object, attribute, attributes, refObject) => + attribute.link = object.uiUrl() + value + callbackResetLink = (value, object, attribute, attributes, refObject) => + attribute.link = undefined + value + callbackUserPopover = (value, object, attribute, attributes, refObject) => + attribute.class = 'user-popover' + attribute.data = + id: refObject.id + value + + new App.ControllerTable( + overview: @view.d + el: html.find('.table-overview'), + model: App.Ticket + objects: @tickets_in_table, + checkbox: false + groupBy: @group_by + bindRow: + events: + 'click': openTicket + callbackAttributes: + customer_id: + [ callbackResetLink, callbackUserPopover ] + owner_id: + [ callbackResetLink, callbackUserPopover ] + title: + [ callbackLinkToTicket, callbackTicketTitleAdd ] + number: + [ callbackLinkToTicket, callbackTicketTitleAdd ] + ) + + @html html + + # show frontend times + @frontendTimeUpdate() + + # start user popups + @userPopups() + + zoom: (e) => + e.preventDefault() + id = $(e.target).parents('[data-id]').data('id') + + @navigate 'ticket/zoom/' + id + + page: (e) => + e.preventDefault() + id = $(e.target).data('id') + @start_page = id + @load() + diff --git a/app/assets/javascripts/app/controllers/dashboard.js.coffee b/app/assets/javascripts/app/controllers/dashboard.js.coffee index 009b71b1b..cba98dee8 100644 --- a/app/assets/javascripts/app/controllers/dashboard.js.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.js.coffee @@ -2,7 +2,7 @@ class Index extends App.ControllerContent constructor: -> super - + # check authentication return if !@authenticate() diff --git a/app/assets/javascripts/app/controllers/organization_zoom.js.coffee b/app/assets/javascripts/app/controllers/organization_zoom.js.coffee index f1f50a851..027f370a7 100644 --- a/app/assets/javascripts/app/controllers/organization_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/organization_zoom.js.coffee @@ -38,6 +38,11 @@ class App.OrganizationZoom extends App.Controller organization: organization ) + new Overviews( + el: @el + organization: organization + ) + new App.UpdateTastbar( genericObject: organization ) @@ -60,6 +65,55 @@ class App.OrganizationZoom extends App.Controller ui: @ ) +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('
') + 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 Widgets extends App.Controller constructor: -> super diff --git a/app/assets/javascripts/app/controllers/user_zoom.js.coffee b/app/assets/javascripts/app/controllers/user_zoom.js.coffee index d5360887c..a63ba95ff 100644 --- a/app/assets/javascripts/app/controllers/user_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/user_zoom.js.coffee @@ -34,10 +34,16 @@ class App.UserZoom extends App.Controller render: (user) => + @html App.view('user_zoom')( user: user ) + new Overviews( + el: @el + user: user + ) + new App.UpdateTastbar( genericObject: user ) @@ -60,6 +66,74 @@ class App.UserZoom extends App.Controller ui: @ ) +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('
') + 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 Widgets extends App.Controller constructor: -> super diff --git a/app/assets/javascripts/app/views/dashboard/ticket.jst.eco b/app/assets/javascripts/app/views/dashboard/ticket.jst.eco index 34387c912..a18c37ad1 100644 --- a/app/assets/javascripts/app/views/dashboard/ticket.jst.eco +++ b/app/assets/javascripts/app/views/dashboard/ticket.jst.eco @@ -1,7 +1,7 @@
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/user_zoom.jst.eco b/app/assets/javascripts/app/views/user_zoom.jst.eco index 36e2ee833..5ad33ddbc 100644 --- a/app/assets/javascripts/app/views/user_zoom.jst.eco +++ b/app/assets/javascripts/app/views/user_zoom.jst.eco @@ -9,10 +9,7 @@

-
-
-
-
+
\ No newline at end of file diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 326ccde40..05c2e7837 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -364,7 +364,9 @@ class TicketsController < ApplicationController tickets = Ticket.search( :limit => params[:limit], :query => params[:term], + :condition => params[:condition], :current_user => current_user, + :detail => params[:detail] ) assets = {} ticket_result = [] @@ -375,8 +377,9 @@ class TicketsController < ApplicationController # return result render :json => { - :tickets => ticket_result, - :assets => assets, + :tickets => ticket_result, + :tickets_count => tickets.count, + :assets => assets, } end diff --git a/app/models/ticket/search.rb b/app/models/ticket/search.rb index 14abbacb2..0d9b5c113 100644 --- a/app/models/ticket/search.rb +++ b/app/models/ticket/search.rb @@ -16,6 +16,20 @@ returns result = [ticket_model1, ticket_model2] + +search tickets + + result = Ticket.search( + :current_user => User.find(123), + :query => 'search something', + :limit => 15, + :full => 0 + ) + +returns + + result = [1,3,5,6,7] + =end def search (params) @@ -24,9 +38,13 @@ returns query = params[:query] limit = params[:limit] || 12 current_user = params[:current_user] + full = false + if params[:full] || !params.has_key?(:full) + full = true + end # try search index backend - if SearchIndexBackend.enabled? + if !params[:detail] && SearchIndexBackend.enabled? query_extention = {} query_extention['bool'] = {} query_extention['bool']['must'] = [] @@ -39,28 +57,31 @@ returns groups.each {|group| group_condition.push group.name } - condition = { + access_condition = { 'query_string' => { 'default_field' => 'Ticket.group.name', 'query' => "\"#{group_condition.join('" OR "')}\"" } } - query_extention['bool']['must'].push condition + query_extention['bool']['must'].push access_condition else if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false ) - condition = { + access_condition = { 'query_string' => { 'default_field' => 'Ticket.customer_id', 'query' => current_user.id } } # customer_id: XXX # conditions = [ 'customer_id = ?', current_user.id ] else - condition = { + access_condition = { 'query_string' => { 'query' => "Ticket.customer_id:#{current_user.id} OR Ticket.organization_id:#{current_user.organization.id}" } } # customer_id: XXX OR organization_id: XXX # conditions = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] end - query_extention['bool']['must'].push condition + query_extention['bool']['must'].push access_condition end ids = SearchIndexBackend.search( query, limit, 'Ticket', query_extention ) + if !full + return ids + end tickets = [] ids.each { |id| tickets.push Ticket.lookup( :id => id ) @@ -69,38 +90,53 @@ returns end # fallback do sql query - conditions = [] + access_condition = [] 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 ) - conditions = [ 'group_id IN (?)', group_ids ] + access_condition = [ 'group_id IN (?)', group_ids ] else if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false ) - conditions = [ 'customer_id = ?', current_user.id ] + access_condition = [ 'customer_id = ?', current_user.id ] else - conditions = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] + access_condition = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] end end # do query # - stip out * we already search for *query* - - query.gsub! '*', '' - tickets_all = Ticket.select('DISTINCT(tickets.id)'). - where(conditions). - where( '( `tickets`.`title` LIKE ? OR `tickets`.`number` LIKE ? OR `ticket_articles`.`body` LIKE ? OR `ticket_articles`.`from` LIKE ? OR `ticket_articles`.`to` LIKE ? OR `ticket_articles`.`subject` LIKE ?)', "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%" ). - joins(:articles). - order('`tickets`.`created_at` DESC'). - limit(limit) - - # build result list - tickets = [] - tickets_all.each do |ticket| - tickets.push Ticket.lookup( :id => ticket.id ) + if query + query.gsub! '*', '' + tickets_all = Ticket.select('DISTINCT(tickets.id)'). + where(access_condition). + where( '( `tickets`.`title` LIKE ? OR `tickets`.`number` LIKE ? OR `ticket_articles`.`body` LIKE ? OR `ticket_articles`.`from` LIKE ? OR `ticket_articles`.`to` LIKE ? OR `ticket_articles`.`subject` LIKE ?)', "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%" ). + joins(:articles). + order('`tickets`.`created_at` DESC'). + limit(limit) + else + tickets_all = Ticket.select('DISTINCT(tickets.id)'). + where(access_condition). + where(params[:condition]). + order('`tickets`.`created_at` DESC'). + limit(limit) end - tickets + # build result list + if !full + ids = [] + tickets_all.each { |ticket| + ids.push ticket.id + } + return ids + end + + tickets = [] + tickets_all.each { |ticket| + tickets.push Ticket.lookup( :id => ticket.id ) + } + return tickets end end