From 0a49faf417a993e838d1c37361d573bb86223f75 Mon Sep 17 00:00:00 2001 From: jessib Date: Thu, 29 Nov 2012 15:56:41 -0800 Subject: Not yet done, but more sophisticated and refactored ticket filtering. Still have to do more, including allowing user to pick sort order. --- help/app/controllers/tickets_controller.rb | 7 +- help/app/models/ticket.rb | 117 ++++++++++++++--------------- help/test/unit/ticket_test.rb | 15 ++-- 3 files changed, 66 insertions(+), 73 deletions(-) diff --git a/help/app/controllers/tickets_controller.rb b/help/app/controllers/tickets_controller.rb index 2e55c36..1a73df9 100644 --- a/help/app/controllers/tickets_controller.rb +++ b/help/app/controllers/tickets_controller.rb @@ -82,11 +82,8 @@ class TicketsController < ApplicationController def index #TODO: we will need pagination - if admin? - @tickets = Ticket.for_admin(current_user, params) - else - @tickets = Ticket.for_user(current_user, params) - end + @tickets = Ticket.for_user(current_user, params, admin?) + #below works if @tickets is a CouchRest::Model::Designs::View, but not if it is an Array @tickets = @tickets.page(params[:page]).per(10) #TEST #respond_with(@tickets) diff --git a/help/app/models/ticket.rb b/help/app/models/ticket.rb index 1ed2ed4..e06180f 100644 --- a/help/app/models/ticket.rb +++ b/help/app/models/ticket.rb @@ -42,42 +42,55 @@ class Ticket < CouchRest::Model::Base view :by_updated_at # - view :by_title, #test - :map => - "function(doc) { - emit(doc._id, doc); - }" view :by_is_open_and_created_by view :by_is_open_and_created_at - view :by_updated_at_and_is_open, + view :by_is_open_and_updated_at + + view :includes_post_by, :map => "function(doc) { - if (doc['type'] == 'Ticket' && doc.is_open == true) { - emit(doc.updated_at, doc); + var arr = {} + if (doc['type'] == 'Ticket' && doc.comments) { + doc.comments.forEach(function(comment){ + if (comment.posted_by && !arr[comment.posted_by]) { + //don't add duplicates + arr[comment.posted_by] = true; + emit(comment.posted_by, doc); + } + }); } - }" - view :by_updated_at_and_is_closed, + }" + + view :includes_post_by_and_open_status_and_updated_at, :map => "function(doc) { - if (doc['type'] == 'Ticket' && doc.is_open == false) { - emit(doc.updated_at, doc); - } - }" - view :by_commented_by, - :map => - "function(doc) { + var arr = {} + if (doc['type'] == 'Ticket' && doc.comments) { doc.comments.forEach(function(comment){ - emit(comment.posted_by, doc); + if (comment.posted_by && !arr[comment.posted_by]) { + //don't add duplicates + arr[comment.posted_by] = true; + emit([comment.posted_by, doc.is_open, doc.updated_at], doc); + } }); - }" + } + }" - view :by_commented_by_and_commented_at, + view :includes_post_by_and_updated_at, :map => - "function(doc) { + "function(doc) { + var arr = {} + if (doc['type'] == 'Ticket' && doc.comments) { doc.comments.forEach(function(comment){ - emit([comment.posted_by, comment.posted_at], doc); + if (comment.posted_by && !arr[comment.posted_by]) { + //don't add duplicates + arr[comment.posted_by] = true; + emit([comment.posted_by, doc.updated_at], doc); + } }); - }" + } + }" + end @@ -93,49 +106,29 @@ class Ticket < CouchRest::Model::Base # self.created_by = User.current if User.current #end - def self.for_user(user, options = {}) - if options[:open_status] == 'open' - Ticket.by_is_open_and_created_by.key([true, user.id]) - elsif options[:open_status] == 'closed' - Ticket.by_is_open_and_created_by.key([false, user.id]) - else - Ticket.by_created_by(:key => user.id) - end - #TODO---if, when logged in, user accessed unauthenticated ticket, then seems okay to list it in their list of tickets. Thus, include all tickets that the user has posted to, not just those that they created. - # todo. presumably quite inefficent. sorts by updated_at increasing. would also make it an array, so pagination wouldn't work - # @tickets = @tickets.sort{|x,y| x.updated_at <=> y.updated_at} - end - - def self.for_admin(user, options = {}) - if options[:admin_status] == 'mine' - self.tickets_by_admin(user.id, options) #returns Array so pagination does not work - elsif options[:open_status] == 'open' - Ticket.by_updated_at_and_is_open - # Ticket.by_is_open.key(true) #returns CouchRest::Model::Designs::View - elsif options[:open_status] == 'closed' - Ticket.by_updated_at_and_is_closed - # Ticket.by_is_open.key(false) #returns CouchRest::Model::Designs::View + def self.for_user(user, options = {}, is_admin = false) + # TODO: sorting + # TODO: do these correctly default to showing open? + # TODO: Time.now + 2.days is to catch tickets created in future. shouldn't happen but does on my computer now, so this at least catches for now. + if (is_admin && (options[:admin_status] != 'mine')) + # show all (selected) tickets to admin + if options[:open_status] == 'all' + Ticket.by_updated_at + else + Ticket.by_is_open_and_updated_at.startkey([(options[:open_status] == 'open'), 0]).endkey([(options[:open_status] == 'open'), Time.now + 2.days]) + end else - # Ticket.all #returns CouchRest::Model::Designs::View - Ticket.by_updated_at + # only show tickets this user has commented on, as user is non-admin or admin viewing only their tickets + if options[:open_status] == 'all' + Ticket.includes_post_by_and_updated_at.startkey([user.id, 0]).endkey([user.id, Time.now + 2.days]) + else + Ticket.includes_post_by_and_open_status_and_updated_at.startkey([user.id, (options[:open_status] == 'open'), 0]).endkey([user.id, (options[:open_status] == 'open'), Time.now + 2.days]) + end end end - #returns Array which doesn't work for pagination, as it is now. - def self.tickets_by_admin(id, options = {}) - admin_tickets = [] - tickets = Ticket.all - tickets.each do |ticket| - ticket.comments.each do |comment| - if comment.posted_by == id and (options[:open_status] != 'open' or ticket.is_open) and (options[:open_status] != 'closed' or !ticket.is_open) #limit based on whether the ticket is open if open_status is set to open or closed - admin_tickets << ticket - break - end - end - end - # TODO. is this inefficent?: - # this sorts by updated at increasing: - admin_tickets.sort{|x,y| x.updated_at <=> y.updated_at} + def self.tickets_by_commenter(user_id)#, options = {}) + Ticket.includes_post_by_and_updated_at.startkey([user_id, 0]).endkey([user_id, Time.now]) end def is_creator_validated? diff --git a/help/test/unit/ticket_test.rb b/help/test/unit/ticket_test.rb index 691597a..e93a121 100644 --- a/help/test/unit/ticket_test.rb +++ b/help/test/unit/ticket_test.rb @@ -64,27 +64,30 @@ class TicketTest < ActiveSupport::TestCase end test "find tickets user commented on" do + # clear old tickets just in case - Ticket.by_commented_by.key('123').each {|t| t.destroy} + # this will cause RestClient::ResourceNotFound errors if there are multiple copies of the same ticket returned + Ticket.includes_post_by.key('123').each {|t| t.destroy} testticket = Ticket.create :title => "test retrieving commented tickets" comment = TicketComment.new :body => "my email broke", :posted_by => "123" assert_equal 0, testticket.comments.count - assert_equal [], Ticket.by_commented_by.key('123').all; + assert_equal [], Ticket.includes_post_by.key('123').all testticket.comments << comment testticket.save assert_equal 1, testticket.reload.comments.count - assert_equal [testticket], Ticket.by_commented_by.key('123').all; + assert_equal [testticket], Ticket.includes_post_by.key('123').all comment = TicketComment.new :body => "another comment", :posted_by => "123" testticket.comments << comment testticket.save - #this will now fail, as Ticket.by_commented_by will return 2 copies of the same ticket as both of the ticket's comments match - assert_equal [testticket], Ticket.by_commented_by.key('123').all; + + # this will ensure that the ticket is only included once, even though the user has commented on the ticket twice: + assert_equal [testticket], Ticket.includes_post_by.key('123').all testticket.destroy - assert_equal [], Ticket.by_commented_by.key('123').all; + assert_equal [], Ticket.includes_post_by.key('123').all; end end -- cgit v1.2.3