diff options
Diffstat (limited to 'help')
26 files changed, 443 insertions, 307 deletions
| diff --git a/help/README.md b/help/README.md new file mode 100644 index 0000000..c9573e6 --- /dev/null +++ b/help/README.md @@ -0,0 +1 @@ +Implements a simple, clean, and easy to use help ticketing system.
\ No newline at end of file diff --git a/help/Readme.md b/help/Readme.md deleted file mode 100644 index e69de29..0000000 --- a/help/Readme.md +++ /dev/null diff --git a/help/app/assets/javascripts/tickets.js b/help/app/assets/javascripts/tickets.js index 5376a6e..bf7965c 100644 --- a/help/app/assets/javascripts/tickets.js +++ b/help/app/assets/javascripts/tickets.js @@ -1,4 +1,4 @@ -$(document).ready(function () { -  $.fn.editable.defaults.mode = 'inline'; -  $('#title').editable(); -});
\ No newline at end of file +//$(document).ready(function () { +//  $.fn.editable.defaults.mode = 'inline'; +//  $('#title').editable(); +//});
\ No newline at end of file diff --git a/help/app/controllers/tickets_controller.rb b/help/app/controllers/tickets_controller.rb index 6562048..094612c 100644 --- a/help/app/controllers/tickets_controller.rb +++ b/help/app/controllers/tickets_controller.rb @@ -1,12 +1,13 @@  class TicketsController < ApplicationController +  include AutoTicketsPathHelper    respond_to :html, :json    #has_scope :open, :type => boolean -  before_filter :set_strings -    before_filter :authorize, :only => [:index]    before_filter :fetch_ticket, :only => [:show, :update, :destroy] # don't now have an edit method +  before_filter :fetch_user +  before_filter :set_title    def new      @ticket = Ticket.new @@ -20,95 +21,134 @@ class TicketsController < ApplicationController      @ticket.created_by = current_user.id if logged_in?      @ticket.email = current_user.email_address if logged_in? and current_user.email_address -    flash[:notice] = 'Ticket was successfully created.' if @ticket.save +    if @ticket.save +      flash[:notice] = t(:thing_was_successfully_created, :thing => t(:ticket)) +    end      # cannot set this until ticket has been saved, as @ticket.id will not be set -    flash[:notice] += " " + t(:access_ticket_text, :full_url => ticket_url(@ticket.id)) if !logged_in? and flash[:notice] -    respond_with(@ticket) - -  end - -=begin -  def edit -    @ticket.comments.build -    # build ticket comments? +    if !logged_in? and flash[:notice] +      flash[:notice] += " " + t(:access_ticket_text, :full_url => ticket_url(@ticket.id)) +    end +    respond_with(@ticket, :location => auto_ticket_path(@ticket))    end -=end    def show      @comment = TicketComment.new      if !@ticket -      redirect_to tickets_path, :alert => "No such ticket" +      redirect_to auto_tickets_path, :alert => t(:no_such_thing, :thing => t(:ticket))        return      end    end    def update +    if params[:commit] == 'close' +      @ticket.is_open = false +      @ticket.save +      redirect_to_tickets +    elsif params[:commit] == 'open' +      @ticket.is_open = true +      @ticket.save +      redirect_to auto_ticket_path(@ticket) +    else +      @ticket.attributes = cleanup_ticket_params(params[:ticket]) -    if params[:post] #currently changes to title or is_open status -      @ticket.attributes = params[:post] -      # TODO: do we want to keep the history of title changes? one possibility was adding a comment that said something like 'user changed the title from a to b' +      if params[:commit] == 'reply_and_close' +        @ticket.close +      end -    else -      params[:ticket][:comments_attributes] = nil if params[:ticket][:comments_attributes].values.first[:body].blank? #unset comments hash if no new comment was typed -      @ticket.attributes = params[:ticket] #this will call comments_attributes= -      @ticket.close if params[:commit] == @reply_close_str #this overrides is_open selection -      # what if there is an update and no new comment? Confirm that there is a new comment to update posted_by: -      @ticket.comments.last.posted_by = (current_user ? current_user.id : nil) if @ticket.comments_changed? #protecting posted_by isn't working, so this should protect it. -    end -    if @ticket.changed? and @ticket.save -      flash[:notice] = 'Ticket was successfully updated.' -      if @ticket.is_open || !logged_in? -        respond_with @ticket -      else #for closed tickets with authenticated users, redirect to index. -        redirect_to tickets_path +      if @ticket.comments_changed? +        @ticket.comments.last.posted_by = (current_user ? current_user.id : nil)        end -    else -      #redirect_to [:show, @ticket] # -      flash[:alert] = 'Ticket has not been changed' -      redirect_to @ticket -      #respond_with(@ticket) # why does this go to edit?? redirect??? -    end +      if @ticket.changed? +        if @ticket.save +          flash[:notice] = t(:changes_saved) +          redirect_to_tickets +        else +          respond_with @ticket +        end +      else +        redirect_to auto_ticket_path(@ticket) +      end +    end    end    def index -    @all_tickets = Ticket.for_user(current_user, params, admin?) #for tests, useful to have as separate variable -    @tickets = @all_tickets.page(params[:page]).per(10) +    @all_tickets = Ticket.search(search_options(params)) +    @tickets = @all_tickets.page(params[:page]).per(APP_CONFIG[:pagination_size])    end    def destroy      # should we allow non-admins to delete their own tickets? i don't think necessary.      @ticket.destroy if admin? -    redirect_to tickets_path +    redirect_to auto_tickets_path +  end + +  protected + +  def set_title +    @title = t(:tickets)    end    private -  def ticket_access? -    @ticket and (admin? or !@ticket.created_by or (current_user and current_user.id == @ticket.created_by)) +  # +  # redirects to ticket index, if appropriate. +  # otherwise, just redirects to @ticket +  # +  def redirect_to_tickets +    if logged_in? +      if params[:commit] == t(:reply_and_close) +        redirect_to auto_tickets_path +      else +        redirect_to auto_ticket_path(@ticket) +      end +    else +      # if we are not logged in, there is no index to view +      redirect_to auto_ticket_path(@ticket) +    end    end -  def set_strings -    @post_reply_str = 'Post reply' #t :post_reply -    @reply_close_str = 'Reply and close' #t :reply_and_close +  # +  # unset comments hash if no new comment was typed +  # +  def cleanup_ticket_params(ticket) +    if ticket && ticket[:comments_attributes] +      if ticket[:comments_attributes].values.first[:body].blank? +        ticket[:comments_attributes] = nil +      end +    end +    return ticket +  end + +  def ticket_access? +    @ticket and (admin? or !@ticket.created_by or (current_user and current_user.id == @ticket.created_by))    end    def fetch_ticket      @ticket = Ticket.find(params[:id])      if !@ticket and admin? -      redirect_to tickets_path, :alert => t(:no_such_thing, :thing => 'ticket') +      redirect_to auto_tickets_path, :alert => t(:no_such_thing, :thing => 'ticket')        return      end      access_denied unless ticket_access?    end -  # not using now, as we are using comment_attributes= from the Ticket model -=begin -  def add_comment -    comment = TicketComment.new(params[:comment]) -    comment.posted_by = User.current.id if User.current #could be nil -    comment.posted_at = Time.now # TODO: it seems strange to have this here, and not in model -    @ticket.comments << comment + +  def fetch_user +    if params[:user_id] +      @user = User.find_by_param(params[:user_id]) +    end +  end + +  # +  # clean up params for ticket search +  # +  def search_options(params) +    params.merge( +      :admin_status => params[:user_id] ? 'mine' : 'all', +      :user_id      => @user ? @user.id : current_user.id, +      :is_admin     => admin? +    )    end -=end +  end diff --git a/help/app/helpers/auto_tickets_path_helper.rb b/help/app/helpers/auto_tickets_path_helper.rb new file mode 100644 index 0000000..bb71260 --- /dev/null +++ b/help/app/helpers/auto_tickets_path_helper.rb @@ -0,0 +1,51 @@ +# +# These "auto" forms of the normal ticket path route helpers allow us to do two things automatically: +# +# (1) include the user in the path if appropriate. +# (2) retain the sort params, if appropriate. +# +# Tickets views with a user_id are limited to that user. For admins, they don't need a user_id for any ticket action. +# +# This is available both to the views and the tickets_controller. +# +module AutoTicketsPathHelper + +  protected + +  def auto_tickets_path(options={}) +    options = ticket_view_options.merge options +    if @user +      user_tickets_path(@user, options) +    else +      tickets_path(options) +    end +  end + +  def auto_ticket_path(ticket, options={}) +    options = ticket_view_options.merge options +    if @user +      user_ticket_path(@user, ticket, options) +    else +      ticket_path(ticket, options) +    end +  end + +  def auto_new_ticket_path(options={}) +    options = ticket_view_options.merge options +    if @user +      new_user_ticket_path(@user, options) +    else +      new_ticket_path(options) +    end +  end + +  private + +  def ticket_view_options +    hsh = {} +    hsh[:open_status] = params[:open_status] if params[:open_status] && !params[:open_status].empty? +    hsh[:sort_order]  = params[:sort_order]  if params[:sort_order]  && !params[:sort_order].empty? +    hsh +  end + +end
\ No newline at end of file diff --git a/help/app/helpers/tickets_helper.rb b/help/app/helpers/tickets_helper.rb index bd2c069..7af50d6 100644 --- a/help/app/helpers/tickets_helper.rb +++ b/help/app/helpers/tickets_helper.rb @@ -1,27 +1,54 @@  module TicketsHelper +  # +  # FORM HELPERS +  # -  def status -    params[:open_status] || 'open' +  # +  # hidden fields that should be added to ever ticket form. +  # these are use for proper redirection after successful actions. +  # +  def hidden_ticket_fields +    haml_concat hidden_field_tag('open_status', params[:open_status]) +    haml_concat hidden_field_tag('sort_order', params[:sort_order]) +    haml_concat hidden_field_tag('user_id', params[:user_id]) +    ""    end -  def admin -    # do we not want this set for non-admins? the param will be viewable in the url -    params[:admin_status] || 'all' +  # +  # PARAM HELPERS +  # + +  def search_status +    if action?(:index) +      params[:open_status] || 'open' +    else +      nil +    end    end -  def order +  def search_order      params[:sort_order] || 'updated_at_desc'    end +  # +  # LINK HELPERS +  # +    def link_to_status(new_status) -    label = new_status + ' issues' -    link_to label, :open_status => new_status, :admin_status => admin, :sort_order => order +    if new_status == "open" +      label = t(:open_tickets) +    elsif new_status == "closed" +      label = t(:closed_tickets) +    elsif new_status == "all" +      label = t(:all_tickets) +    end +    link_to label, auto_tickets_path(:open_status => new_status, :sort_order => search_order)    end    def link_to_order(order_field) -    if order.start_with?(order_field) +    if search_order.start_with?(order_field)        # link for currently-filtered field. Link to other direction of this field. -      if order.end_with? 'asc' +      if search_order.end_with? 'asc'          direction = 'desc'          icon_direction = 'up'        else @@ -35,8 +62,14 @@ module TicketsHelper        direction = 'desc'      end -    link_to :sort_order => order_field + '_at_' + direction, :open_status => status, :admin_status => admin do -      arrow + order_field + ' at' +    if order_field == 'updated' +      label = t(:updated) +    elsif order_field == 'created' +      label = t(:created) +    end + +    link_to auto_tickets_path(:sort_order => order_field + '_at_' + direction, :open_status => search_status) do +      arrow + label      end    end diff --git a/help/app/models/ticket.rb b/help/app/models/ticket.rb index 738487a..8066d0d 100644 --- a/help/app/models/ticket.rb +++ b/help/app/models/ticket.rb @@ -1,49 +1,30 @@ +# +# TODO: thought i should reverse keys for descending, but that didn't work. +# look into whether that should be tweaked, and whether it works okay with +# pagination (seems to now...) +# +# TODO: better validation of email +# +# TODO: don't hardcode strings 'unknown user' and 'unauthenticated user' +#  class Ticket < CouchRest::Model::Base -  #include ActiveModel::Validations -    use_database "tickets" -  #require 'securerandom' -=begin -    title -    created_at -    updated_at -    email_address -    user -    user_verified? -    admins (list of admins who have commented on the ticket) -    code (secret url) -=end - -  #belongs_to :user #from leap_web_users. doesn't necessarily belong to a user though -  property :created_by, String, :protected => true #Integer #nil unless user was authenticated for ticket creation, #THIS should not be changed after being set -  property :regarding_user, String#Integer # form cannot be submitted if they type in a username w/out corresponding ID. this field can be nil. for authenticated ticket creation by non-admins, should this just automatically be set to be same as created_by?  or maybe we don't use this field unless created_by is nil? -  #also, both created_by and regarding_user could be nil---say user forgets username, or has general question -  property :title, String -  property :email, String #verify - -  #property :user_verified, TrueClass, :default => false #will be true exactly when user is set -  #admins -  #property :code, String, :protected => true # only should be set if created_by is nil #instead we will just use couchdb ID -  property :is_open, TrueClass, :default => true -  property :comments, [TicketComment] + +  property :created_by,     String, :protected => true  # nil for anonymous tickets, should never be changed +  property :regarding_user, String                      # may be nil or valid username +  property :title,          String +  property :email,          String +  property :is_open,        TrueClass, :default => true +  property :comments,       [TicketComment]    timestamps! -  #before_validation :set_created_by, :set_code, :set_email, :on => :create    before_validation :set_email, :set_regarding_user, :on => :create - -  #named_scope :open, :conditions => {:is_open => true} #?? -    design do -    #TODO--clean this all up -    #view :by_is_open -    #view :by_created_by -      view :by_updated_at      view :by_created_at -    #view :by_is_open_and_created_by      view :by_is_open_and_created_at      view :by_is_open_and_updated_at @@ -52,63 +33,31 @@ class Ticket < CouchRest::Model::Base    end    validates :title, :presence => true -  #validates :comments, :presence => true #do we want it like this? - - -  # html5 has built-in validation which isn't ideal, as it says 'please enter an email address' for invalid email addresses, which implies an email address is required, and it is not.    validates :email, :allow_blank => true, :format => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ -  #TODO: -  #def set_created_by -  #  self.created_by = User.current if User.current -  #end - -  def self.for_user(user, options = {}, is_admin = false) - -    # TODO: thought i  should reverse keys for descending, but that didn't work. look into whether that should be tweaked, and whether it works okay with pagination (seems to now...) - -    options[:user_id] = user.id -    options[:is_admin] = is_admin - +  def self.search(options = {})      @selection = TicketSelection.new(options)      @selection.tickets    end -  #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?      !!created_by    end -=begin -  def set_code #let's not use this---can use same show url -    # ruby 1.9 provides url-safe option---this is not necessarily url-safe -    self.code = SecureRandom.hex(8) if !is_creator_validated? -  end -=end - -    def set_email      self.email = nil if self.email == "" -    # in controller set to be current users email if that exists    end    def set_regarding_user      self.regarding_user = nil if self.regarding_user == ""    end -  #not saving with close and reopen, as we will save in update when they are called. -  #TODO: not sure if we should bother with these:    def close      self.is_open = false -    #save    end    def reopen      self.is_open = true -    #save    end    def commenters @@ -118,20 +67,21 @@ class Ticket < CouchRest::Model::Base          if user = User.find(comment.posted_by)            commenters << user.login if user and !commenters.include?(user.login)          else -          commenters << 'unknown user' if !commenters.include?('unknown user') #todo don't hardcode string 'unknown user' +          commenters << 'unknown user' if !commenters.include?('unknown user')          end        else -        commenters << 'unauthenticated user' if !commenters.include?('unauthenticated user') #todo don't hardcode string 'unauthenticated user' +        commenters << 'unauthenticated user' if !commenters.include?('unauthenticated user')        end      end      commenters.join(', ')    end +  # +  # update comments. User should be set by controller. +  #    def comments_attributes=(attributes) -    if attributes # could be empty as we will empty if nothing was typed in -      comment = TicketComment.new(attributes.values.first) #TicketComment.new(attributes) -      #comment.posted_by = User.current.id if User.current #we want to avoid User.current, and current_user won't work here. instead will set in tickets_controller -      # what about: comment.posted_by = self.updated_by  (will need to add ticket.updated_by) +    if attributes +      comment = TicketComment.new(attributes.values.first)        comment.posted_at = Time.now        comments << comment      end @@ -144,11 +94,5 @@ class Ticket < CouchRest::Model::Base    def regarding_user_actual_user      User.find_by_login(self.regarding_user)    end -=begin -  def validate -    if email_address and not email_address.strip =~ RFC822::EmailAddress -      errors.add 'email', 'contains an invalid address' -    end -  end -=end +  end diff --git a/help/app/models/ticket_selection.rb b/help/app/models/ticket_selection.rb index bebe5fc..74d5b78 100644 --- a/help/app/models/ticket_selection.rb +++ b/help/app/models/ticket_selection.rb @@ -1,10 +1,20 @@  class TicketSelection +  # +  # supported options: +  # +  # user_id:      id of the user (uuid string) +  # open_status:  open | closed | all +  # sort_order:   updated_at_desc | updated_at_asc | created_at_desc | created_at_asc +  # admin_status: mine | all +  # is_admin:     true | false +  #    def initialize(options = {}) -    @options = options -    @options[:open_status] ||= 'open' -    @options[:sort_order] ||= 'updated_at_desc' - +    @user_id      = options[:user_id].gsub /[^a-z0-9]/, '' +    @open_status  = allow options[:open_status],  'open', 'closed', 'all' +    @sort_order   = allow options[:sort_order],   'updated_at_desc', 'updated_at_asc', 'created_at_desc', 'created_at_asc' +    @admin_status = allow options[:admin_status], 'mine', 'all' +    @is_admin     = allow options[:is_admin],     false, true    end    def tickets @@ -13,25 +23,32 @@ class TicketSelection    protected +  def allow(source, *allowed) +    if allowed.include?(source) +      source +    else +      allowed.first +    end +  end    def finder_method      method = 'by_'      method += 'includes_post_by_and_' if only_mine? -    method += 'is_open_and_' if @options[:open_status] != 'all' -    method += @options[:sort_order].sub(/_(de|a)sc$/, '') +    method += 'is_open_and_' if @open_status != 'all' +    method += @sort_order.sub(/_(de|a)sc$/, '')    end    def startkey      startkeys = [] -    startkeys << @options[:user_id] if only_mine? -    startkeys << (@options[:open_status] == 'open') if @options[:open_status] != 'all' +    startkeys << @user_id if only_mine? +    startkeys << (@open_status == 'open') if @open_status != 'all'      startkeys << 0 -    startkeys = startkeys.join if startkeys.length == 1 #want string not array if just one thing in array +    startkeys = startkeys.join if startkeys.length == 1 # want string not array if just one thing in array      startkeys    end    def endkey -    endtime = Time.now + 2.days #TODO. this obviously isn't ideal +    endtime = Time.now + 2.days # TODO. this obviously isn't ideal      if self.startkey.is_a?(Array)        endkeys = self.startkey        endkeys.pop @@ -43,12 +60,12 @@ class TicketSelection    def order      # we have defined the ascending method to return the view itself: -    (@options[:sort_order].end_with? 'desc') ? 'descending' : 'ascending' +    (@sort_order.end_with? 'desc') ? 'descending' : 'ascending'    end    def only_mine? -    !@options[:is_admin] or (@options[:admin_status] == 'mine') +    !@is_admin || @admin_status == 'mine'    end  end diff --git a/help/app/views/tickets/_admin-nav.html.haml b/help/app/views/tickets/_admin-nav.html.haml deleted file mode 100644 index 0e45c40..0000000 --- a/help/app/views/tickets/_admin-nav.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -%ul.nav.nav-pills.nav-stacked -  %li{:class => ("active" if admin == 'mine')} -    = link_to 'tickets i admin', {:admin_status => 'mine', :open_status => status, :sort_order => order} -  %li{:class => ("active" if admin == 'all')}  -    = link_to 'all tickets', {:admin_status => 'all', :open_status => status, :sort_order => order} diff --git a/help/app/views/tickets/_comment.html.haml b/help/app/views/tickets/_comment.html.haml index 501ceec..4252eee 100644 --- a/help/app/views/tickets/_comment.html.haml +++ b/help/app/views/tickets/_comment.html.haml @@ -1,20 +1,20 @@ -- # style is super ugly but just for now  - if admin? or !comment.private # only show comment if user is admin or comment is not private    %tr -    %td -      - if comment.posted_by_user -        %b -          = 'Posted by' + (comment.posted_by_user.is_admin? ? ' admin' : '') + ':' -        = comment.posted_by_user.login -      - else -        %b -          Unauthenticated post +    %td.user +      %div +        %strong +          - if comment.posted_by_user +            = comment.posted_by_user.login +          - else +            = t(:anonymous) +      %div= comment.posted_at.to_s(:short) +      - if comment.posted_by_user && comment.posted_by_user.is_admin? +        %div +          %span.label.label-inverse +            = t(:admin)        - if comment.private -        (Private comment) -      .pull-right -        %b -          Posted at: -        = comment.posted_at.to_s(:short) -      %br -      = comment.body - +        %div +          %span.label.label-important +            = t(:private) +    %td.comment +      = comment.body
\ No newline at end of file diff --git a/help/app/views/tickets/_edit_form.html.haml b/help/app/views/tickets/_edit_form.html.haml new file mode 100644 index 0000000..5252c2e --- /dev/null +++ b/help/app/views/tickets/_edit_form.html.haml @@ -0,0 +1,48 @@ +:ruby +  # created by user link +  if @ticket.created_by_user +    created_by = link_to(@ticket.created_by_user.login, user_overview_path(@ticket.created_by_user)) +  else +    created_by = t(:anonymous) +  end + +  # regarding user link +  if admin? +    if @ticket.regarding_user_actual_user +      regarding_user_link = link_to @ticket.regarding_user_actual_user.login, user_overview_path(@ticket.regarding_user_actual_user) +    else +      regarding_user_link =  "(#{t(:unknown)})" +    end +  else +    regarding_user_link = '' +  end + += form_for @ticket do |f| +  = hidden_ticket_fields +  %p.first +    - if @ticket.is_open? +      %span.label.label-info= t(:open) +    - else +      %span.label.label-success= t(:closed) +    %span.label.label-clear= t(:created_by_on, :user => created_by, :time => @ticket.created_at.to_s(:short)).html_safe +  %div= t(:subject) +  = f.text_field :title, :class => 'large full-width' +  .row-fluid +    .span4 +      %div= t(:status) +      = f.select :is_open, [[t(:open), "true"], [t(:closed), "false"]] +    .span4 +      %div= t(:email) +      = f.text_field :email +    .span4 +      %div +        = t(:regarding_account) +        = regarding_user_link +      = f.text_field :regarding_user +  = f.button t(:save), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'save' +  - if @ticket.is_open? +    = f.button t(:close), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'close' +  - else +    = f.button t(:open), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'open' +  - if admin? +    = link_to t(:destroy), auto_ticket_path(@ticket),  :confirm => t(:are_you_sure), :method => :delete, :class => 'btn' diff --git a/help/app/views/tickets/_new_comment.html.haml b/help/app/views/tickets/_new_comment.html.haml deleted file mode 100644 index 96388ea..0000000 --- a/help/app/views/tickets/_new_comment.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -= f.simple_fields_for :comments, @comment do |c| -  = c.input :body, :label => 'Comment', :as => :text, :input_html => {:class => "span9", :rows=>4} -  - if admin? -    = c.input :private, :as => :boolean, :label => false, :inline_label => true diff --git a/help/app/views/tickets/_new_comment_form.html.haml b/help/app/views/tickets/_new_comment_form.html.haml new file mode 100644 index 0000000..8418e01 --- /dev/null +++ b/help/app/views/tickets/_new_comment_form.html.haml @@ -0,0 +1,13 @@ +-# +-# for posting a new comment to an existing ticket. +-# += simple_form_for @ticket, :html => {:class => 'slim'}  do |f| +  = hidden_ticket_fields +  = f.simple_fields_for :comments, @comment, :wrapper => :none, :html => {:class => 'slim'} do |c| +    = c.input :body, :label => false, :as => :text, :input_html => {:class => "full-width", :rows=> 5} +    - if admin? +      = c.input :private, :as => :boolean, :label => false, :inline_label => true +  = f.button :button, t(:post_reply), :name => 'commit', :class => 'btn-primary', :type => 'submit', :value => 'post_reply' +  - if logged_in? && @ticket.is_open +    = f.button :button, t(:reply_and_close), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'reply_and_close' +    = link_to t(:cancel), auto_tickets_path, :class => :btn diff --git a/help/app/views/tickets/_order-nav.html.haml b/help/app/views/tickets/_order-nav.html.haml deleted file mode 100644 index 9e8bcee..0000000 --- a/help/app/views/tickets/_order-nav.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -%ul.nav.nav-pills.pull-right -  %li{:class=> ("active" if order.start_with? 'created_at' )} -    = link_to_order('created') -  %li{:class=> ("active" if order.start_with? 'updated_at' )} -    = link_to_order('updated') diff --git a/help/app/views/tickets/_status-nav.html.haml b/help/app/views/tickets/_status-nav.html.haml deleted file mode 100644 index 69f4248..0000000 --- a/help/app/views/tickets/_status-nav.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%ul.nav.nav-tabs -  %li{:class => ("active" if status == 'open')} -    = link_to_status 'open' -  %li{:class => ("active" if status == 'closed')} -    = link_to_status 'closed' -  %li{:class => ("active" if status == 'all')} -    = link_to_status 'all' diff --git a/help/app/views/tickets/_table-nav.html.haml b/help/app/views/tickets/_table-nav.html.haml deleted file mode 100644 index 635b59b..0000000 --- a/help/app/views/tickets/_table-nav.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -.row -  .span6 -    = render 'tickets/status-nav' -  .span4 -    = render 'tickets/order-nav' diff --git a/help/app/views/tickets/_tabs.html.haml b/help/app/views/tickets/_tabs.html.haml new file mode 100644 index 0000000..b7b5d3a --- /dev/null +++ b/help/app/views/tickets/_tabs.html.haml @@ -0,0 +1,23 @@ +-# +-# SORT ORDER TABS +-# +- unless action?(:new) +  %ul.nav.nav-pills.pull-right.slim +    %li{:class=> ("active" if search_order.start_with? 'created_at')} +      = link_to_order('created') +    %li{:class=> ("active" if search_order.start_with? 'updated_at')} +      = link_to_order('updated') + +-# +-# STATUS FILTER TABS +-# +%ul.nav.nav-tabs +  - if logged_in? +    %li{:class => ("active" if search_status == 'open')} +      = link_to_status 'open' +    %li{:class => ("active" if search_status == 'closed')} +      = link_to_status 'closed' +    %li{:class => ("active" if search_status == 'all')} +      = link_to_status 'all' +  %li{:class => ("active" if action?(:new))} +    = link_to icon(:plus, :black) + t(:new_ticket), auto_new_ticket_path diff --git a/help/app/views/tickets/_ticket.html.haml b/help/app/views/tickets/_ticket.html.haml index 7b37652..a064c4e 100644 --- a/help/app/views/tickets/_ticket.html.haml +++ b/help/app/views/tickets/_ticket.html.haml @@ -1,17 +1,6 @@ -- updated_at_text = 'updated: ' + ticket.updated_at.to_s(:long) +- url = auto_ticket_path(ticket)  %tr -  %td -    %b -      = link_to ticket.title, ticket -    - if params[:controller] == 'tickets' -      %br -      %small -        created: -        = ticket.created_at.to_s(:long) -        = updated_at_text -      %small.pull-right -        comments by: -        = ticket.commenters -    - else -      %small -        = updated_at_text
\ No newline at end of file +  %td= link_to ticket.title, url +  %td= link_to ticket.created_at.to_s(:short), url +  %td= link_to ticket.updated_at.to_s(:short), url +  %td= ticket.commenters diff --git a/help/app/views/tickets/_ticket_data.html.haml b/help/app/views/tickets/_ticket_data.html.haml deleted file mode 100644 index 6a1a896..0000000 --- a/help/app/views/tickets/_ticket_data.html.haml +++ /dev/null @@ -1,35 +0,0 @@ -.spam12 -  %b -    Created by: -  - if @ticket.created_by_user -    = link_to @ticket.created_by_user.login, user_path(@ticket.created_by_user) -  - else -    Unauthenticated ticket creator -  - if @ticket.regarding_user -    %b -      Regarding user: -    - if admin? -      - if @ticket.regarding_user_actual_user -        = link_to @ticket.regarding_user_actual_user.login, user_path(@ticket.regarding_user_actual_user) -      - else -        = @ticket.regarding_user + ' (no such user)' -    - else # a non-admin is viewing the ticket, so they shouldn't see confirmation of whether the regarding_user exists or not. -      = @ticket.regarding_user -  - if @ticket.email -    %b -      email: -    = @ticket.email -  %b -    Created at: -  = @ticket.created_at.to_s(:short) -  %b -    Updated at: -  = @ticket.updated_at.to_s(:short) -  %b -    = "Status:" -  - if @ticket.is_open -    = 'open' -    = button_to 'Close', {:post => {:is_open => false}}, :method => :put, :class => 'btn btn-small' -  - else -    = 'closed' -    = button_to 'Open', {:post => {:is_open => true}}, :method => :put, :class => 'btn btn-small' diff --git a/help/app/views/tickets/index.html.haml b/help/app/views/tickets/index.html.haml index 23a503d..c02a326 100644 --- a/help/app/views/tickets/index.html.haml +++ b/help/app/views/tickets/index.html.haml @@ -1,17 +1,19 @@ -%h1 tickets index +- @show_navigation = !params[:user_id].nil? -Create a  -= link_to "new ticket", new_ticket_path += render 'tickets/tabs' -= #%div{"data-pjax-container" => ""} # not sure how to get this working right -.row -  .span2 -    - if admin? -      = render 'tickets/admin-nav' -  .span10 -    = render 'tickets/table-nav' -    %table.table-striped.table-bordered.table-hover{:style => "width:100%;"} -      %tbody -        = render @tickets.all -    = paginate @tickets +%table.table.table-striped.table-bordered +  %thead +    %tr +      %th= t(:subject) +      %th= t(:created) +      %th= t(:updated) +      %th= t(:voices) +  %tbody +    - if @tickets.any? +      = render @tickets.all +    - else +      %tr +        %td{:colspan=>4}= t(:none) += paginate @tickets diff --git a/help/app/views/tickets/new.html.haml b/help/app/views/tickets/new.html.haml index 1aa689b..c0a343d 100644 --- a/help/app/views/tickets/new.html.haml +++ b/help/app/views/tickets/new.html.haml @@ -1,10 +1,30 @@ -.span12 -  %h2=t :new_ticket -  = simple_form_for @ticket, :validate => true, :html => {:class => 'form-horizontal'}  do |f| -    = f.input :title -    = f.input :email if !current_user  #hmm--might authenticated users want to submit an alternate email? +- @show_navigation = !params[:user_id].nil? + += render 'tickets/tabs' + +- if admin? && @user +  - email = @user.email_address +  - regarding = @user.login +- elsif logged_in? +  - email = current_user.email_address +  - regarding = current_user.login + += simple_form_for @ticket, :validate => true, :html => {:class => 'form-horizontal'} do |f| +  = hidden_ticket_fields +  = f.input :title, :label => t(:subject) +  - if logged_in? +    = f.input :email, input_html: {value: email} +    = f.input :regarding_user, input_html: {value: regarding} +  - else +    = f.input :email      = f.input :regarding_user -    = render :partial => 'new_comment', :locals => {:f => f} -    .form-actions -      = f.button :submit, :class => 'btn-primary' -      = link_to t(:cancel), tickets_path, :class => :btn +  = f.simple_fields_for :comments, @comment do |c| +    = c.input :body, :label => t(:description), :as => :text, :input_html => {:class => "full-width", :rows=> 5} +    - if admin? +      = c.input :private, :as => :boolean, :label => false, :inline_label => true +  .form-actions +    = f.button :submit, :class => 'btn-primary', :value => t(:create_thing, :thing => t(:ticket)) +    - if logged_in? +      = link_to t(:cancel), auto_tickets_path, :class => :btn +    - else +      = link_to t(:cancel), root_path, :class => 'btn'
\ No newline at end of file diff --git a/help/app/views/tickets/show.html.haml b/help/app/views/tickets/show.html.haml index a69048b..bfdb773 100644 --- a/help/app/views/tickets/show.html.haml +++ b/help/app/views/tickets/show.html.haml @@ -1,18 +1,12 @@ -.spam12 -  %h2 -    %a#title.editable.editable-click{"data-name" => "title", "data-resource" => "post", "data-type" => "text", "data-url" => ticket_path(@ticket.id), "data-pk" => @ticket.id, :href => "#"}  -      = @ticket.title -  = render 'tickets/ticket_data' -  %table.table-striped.table-bordered.table-hover{:style => "width:100%;"} -    %tbody -    = render(:partial => "comment", :collection => @ticket.comments) -  = #render @ticket.comments should work if view is in /app/views/comments/_comment +- @show_navigation = !params[:user_id].nil? -  = simple_form_for @ticket, :html => {:class => 'form-horizontal'}  do |f| # don't need validations so long as this is so simple -    = render :partial => 'new_comment', :locals => {:f => f} -    .span10.offset3 -      = f.button :submit, @post_reply_str, :class => 'btn-primary' -      - if @ticket.is_open -        = f.button :submit, @reply_close_str -        = link_to t(:Destroy), ticket_path,  :confirm => 'are you sure?', :method => :delete, :class => 'btn btn-danger' if admin? -      = link_to t(:cancel), tickets_path, :class => :btn +.ticket +  = render 'tickets/edit_form' +  %table.table.table-striped.table-bordered +    %tbody +      = render :partial => 'tickets/comment', :collection => @ticket.comments +      %tr +        %td.user +          = logged_in? ? current_user.login : t(:anonymous) +        %td.comment +          = render 'tickets/new_comment_form'
\ No newline at end of file diff --git a/help/config/locales/en.yml b/help/config/locales/en.yml index 4ea662a..342adea 100644 --- a/help/config/locales/en.yml +++ b/help/config/locales/en.yml @@ -1,2 +1,22 @@  en: -  access_ticket_text: "You can later access this ticket at the url %{full_url}. You might want to bookmark this page to find it again. Anybody with this URL will be able to access this ticket, so if you are on a shared computer you might want to remove it from the browser history" +  access_ticket_text: > +    You can later access this ticket at the URL %{full_url}. You might want to bookmark this page to find it again. +    Anybody with this URL will be able to access this ticket, so if you are on a shared computer you might want to +    remove it from the browser history. +  support_tickets: "Support Tickets" +  all_tickets: "All Tickets" +  my_tickets: "My Tickets" +  open_tickets: "Open Tickets" +  closed_tickets: "Closed Tickets" +  new_ticket: "New Ticket" +  tickets: "Tickets" +  subject: "Subject" +  destroy: "Destroy" +  open: "Open" +  closed: "Closed" +  close: "Close" +  post_reply: "Post Reply" +  reply_and_close: "Reply and Close" +  description: "Description" +  ticket: "Ticket" +  regarding_account: "Regarding Account"
\ No newline at end of file diff --git a/help/config/routes.rb b/help/config/routes.rb index 86a9201..8f3241c 100644 --- a/help/config/routes.rb +++ b/help/config/routes.rb @@ -1,5 +1,6 @@  Rails.application.routes.draw do - -  resources :tickets, :only => [:new, :create, :index, :show, :update, :destroy] -  #resources :ticket, :only => [:show] +  resources :tickets, :except => :edit +  resources :users do +    resources :tickets, :except => :edit +  end  end diff --git a/help/leap_web_help.gemspec b/help/leap_web_help.gemspec index 09827dc..4914694 100644 --- a/help/leap_web_help.gemspec +++ b/help/leap_web_help.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s|    s.summary     = "Help Desk for LeapWeb"    s.description = "Managing Tickets for a Leap provider" -  s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "Readme.md"] +  s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]    s.test_files = Dir["test/**/*"]    s.add_dependency "leap_web_core", LeapWeb::VERSION diff --git a/help/test/functional/tickets_controller_test.rb b/help/test/functional/tickets_controller_test.rb index f8627d8..6479ba4 100644 --- a/help/test/functional/tickets_controller_test.rb +++ b/help/test/functional/tickets_controller_test.rb @@ -181,23 +181,24 @@ class TicketsControllerTest < ActionController::TestCase    test "admin_status mine vs all" do      testticket = FactoryGirl.create :ticket +    user = find_record :user      login :is_admin? => true, :email => nil -    get :index, {:admin_status => "all", :open_status => "open"} +    get :index, {:open_status => "open"}      assert assigns(:all_tickets).include?(testticket) -    get :index, {:admin_status => "mine", :open_status => "open"} +    get :index, {:user_id => user.id, :open_status => "open"}      assert !assigns(:all_tickets).include?(testticket)      testticket.destroy    end    test "commenting on a ticket adds to tickets that are mine" do      testticket = FactoryGirl.create :ticket -    login :is_admin? => true, :email => nil - -    get :index, {:admin_status => "mine", :open_status => "open"} +    user = find_record :admin_user +    login user +    get :index, {:user_id => user.id, :open_status => "open"}      assert_difference('assigns[:all_tickets].count') do        put :update, :id => testticket.id, :ticket => {:comments_attributes => {"0" => {"body" =>"NEWER comment"}}} -      get :index, {:admin_status => "mine", :open_status => "open"} +      get :index, {:user_id => user.id, :open_status => "open"}      end      assert assigns(:all_tickets).include?(assigns(:ticket)) | 
