diff options
-rw-r--r-- | app/controllers/issues_controller.rb | 1 | ||||
-rw-r--r-- | app/controllers/projects_controller.rb | 38 | ||||
-rw-r--r-- | app/models/issue.rb | 7 | ||||
-rw-r--r-- | app/views/issues/context_menu.rhtml | 2 | ||||
-rw-r--r-- | app/views/issues/show.rhtml | 1 | ||||
-rw-r--r-- | app/views/projects/add_issue.rhtml | 6 | ||||
-rw-r--r-- | lang/en.yml | 1 | ||||
-rw-r--r-- | lang/fr.yml | 1 | ||||
-rw-r--r-- | public/images/copy.png | bin | 0 -> 291 bytes | |||
-rw-r--r-- | public/stylesheets/application.css | 1 | ||||
-rw-r--r-- | test/functional/projects_controller_test.rb | 21 | ||||
-rw-r--r-- | test/unit/issue_test.rb | 12 |
12 files changed, 68 insertions, 23 deletions
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index d3949cbee..228597931 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -174,6 +174,7 @@ class IssuesController < ApplicationController @assignables << @issue.assigned_to if @issue.assigned_to && !@assignables.include?(@issue.assigned_to) @can = {:edit => User.current.allowed_to?(:edit_issues, @project), :change_status => User.current.allowed_to?(:change_issue_status, @project), + :add => User.current.allowed_to?(:add_issues, @project), :move => User.current.allowed_to?(:move_issues, @project), :delete => User.current.allowed_to?(:delete_issues, @project)} render :layout => false diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 377073fc9..394e545d0 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -192,43 +192,45 @@ class ProjectsController < ApplicationController end # Add a new issue to @project + # The new issue will be created from an existing one if copy_from parameter is given def add_issue - @tracker = Tracker.find(params[:tracker_id]) - @priorities = Enumeration::get_values('IPRI') + @issue = params[:copy_from] ? Issue.new.copy_from(params[:copy_from]) : Issue.new(params[:issue]) + @issue.project = @project + @issue.author = User.current + @issue.tracker ||= Tracker.find(params[:tracker_id]) default_status = IssueStatus.default unless default_status - flash.now[:error] = 'No default issue status defined. Please check your configuration.' + flash.now[:error] = 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").' render :nothing => true, :layout => true return - end - @issue = Issue.new(:project => @project, :tracker => @tracker) + end @issue.status = default_status @allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker))if logged_in_user + if request.get? - @issue.start_date = Date.today - @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) } + @issue.start_date ||= Date.today + @custom_values = @issue.custom_values.empty? ? + @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) } : + @issue.custom_values else - @issue.attributes = params[:issue] - requested_status = IssueStatus.find_by_id(params[:issue][:status_id]) + # Check that the user is allowed to apply the requested status @issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status - - @issue.author_id = self.logged_in_user.id if self.logged_in_user - # Multiple file upload - @attachments = [] - params[:attachments].each { |a| - @attachments << Attachment.new(:container => @issue, :file => a, :author => logged_in_user) unless a.size == 0 - } if params[:attachments] and params[:attachments].is_a? Array - @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } + @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } @issue.custom_values = @custom_values if @issue.save - @attachments.each(&:save) + if params[:attachments] && params[:attachments].is_a?(Array) + # Save attachments + params[:attachments].each {|a| Attachment.create(:container => @issue, :file => a, :author => User.current) unless a.size == 0} + end flash[:notice] = l(:notice_successful_create) Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added') redirect_to :action => 'list_issues', :id => @project + return end end + @priorities = Enumeration::get_values('IPRI') end # Show filtered/sorted issues list of @project diff --git a/app/models/issue.rb b/app/models/issue.rb index 972bf0135..0d2d6fc0d 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -54,6 +54,13 @@ class Issue < ActiveRecord::Base end end + def copy_from(arg) + issue = arg.is_a?(Issue) ? arg : Issue.find(arg) + self.attributes = issue.attributes.dup + self.custom_values = issue.custom_values.collect {|v| v.clone} + self + end + def priority_id=(pid) self.priority = nil write_attribute(:priority_id, pid) diff --git a/app/views/issues/context_menu.rhtml b/app/views/issues/context_menu.rhtml index caf6a76ea..798fd42c3 100644 --- a/app/views/issues/context_menu.rhtml +++ b/app/views/issues/context_menu.rhtml @@ -31,6 +31,8 @@ :selected => @issue.assigned_to.nil?, :disabled => !(@can[:edit] || @can[:change_status]) %></li> </ul> </li> + <li><%= context_menu_link l(:button_copy), {:controller => 'projects', :action => 'add_issue', :id => @project, :copy_from => @issue}, + :class => 'icon-copy', :disabled => !@can[:add] %></li> <li><%= context_menu_link l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, :class => 'icon-move', :disabled => !@can[:move] %> <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, diff --git a/app/views/issues/show.rhtml b/app/views/issues/show.rhtml index ed615c69f..dfeccc669 100644 --- a/app/views/issues/show.rhtml +++ b/app/views/issues/show.rhtml @@ -3,6 +3,7 @@ <%= link_to_if_authorized l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon icon-edit', :accesskey => accesskey(:edit) %> <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time' %> <%= watcher_tag(@issue, User.current) %> +<%= link_to_if_authorized l(:button_copy), {:controller => 'projects', :action => 'add_issue', :id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %> <%= link_to_if_authorized l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, :class => 'icon icon-move' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> </div> diff --git a/app/views/projects/add_issue.rhtml b/app/views/projects/add_issue.rhtml index 8382d6c9f..a68922906 100644 --- a/app/views/projects/add_issue.rhtml +++ b/app/views/projects/add_issue.rhtml @@ -1,10 +1,10 @@ -<h2><%=l(:label_issue_new)%>: <%= @tracker.name %></h2> +<h2><%=l(:label_issue_new)%>: <%= @issue.tracker %></h2> <% labelled_tabular_form_for :issue, @issue, :url => {:action => 'add_issue'}, :html => {:multipart => true, :id => 'issue-form'} do |f| %> - <%= hidden_field_tag 'tracker_id', @tracker.id %> - <%= render :partial => 'issues/form', :locals => {:f => f} %> + <%= f.hidden_field :tracker_id %> + <%= render :partial => 'issues/form', :locals => {:f => f} %> <%= submit_tag l(:button_create) %> <%= link_to_remote l(:label_preview), { :url => { :controller => 'issues', :action => 'preview', :id => @issue }, diff --git a/lang/en.yml b/lang/en.yml index ec0ee3077..4a52d281b 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -476,6 +476,7 @@ button_unarchive: Unarchive button_reset: Reset button_rename: Rename button_change_password: Change password +button_copy: Copy status_active: active status_registered: registered diff --git a/lang/fr.yml b/lang/fr.yml index 0aeed308b..e5a2b843f 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -476,6 +476,7 @@ button_unarchive: Désarchiver button_reset: Réinitialiser button_rename: Renommer button_change_password: Changer de mot de passe +button_copy: Copier status_active: actif status_registered: enregistré diff --git a/public/images/copy.png b/public/images/copy.png Binary files differnew file mode 100644 index 000000000..dccaa0614 --- /dev/null +++ b/public/images/copy.png diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index d1041f162..97d4a291d 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -421,6 +421,7 @@ vertical-align: middle; .icon-add { background-image: url(../images/add.png); } .icon-edit { background-image: url(../images/edit.png); } +.icon-copy { background-image: url(../images/copy.png); } .icon-del { background-image: url(../images/delete.png); } .icon-move { background-image: url(../images/move.png); } .icon-save { background-image: url(../images/save.png); } diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index b7d7962b6..744cc49d6 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -22,7 +22,7 @@ require 'projects_controller' class ProjectsController; def rescue_action(e) raise e end; end class ProjectsControllerTest < Test::Unit::TestCase - fixtures :projects, :users, :roles, :enabled_modules, :enumerations + fixtures :projects, :users, :roles, :members, :issues, :enabled_modules, :enumerations def setup @controller = ProjectsController.new @@ -143,4 +143,23 @@ class ProjectsControllerTest < Test::Unit::TestCase assert_redirected_to 'admin/projects' assert Project.find(1).active? end + + def test_add_issue + @request.session[:user_id] = 2 + get :add_issue, :id => 1, :tracker_id => 1 + assert_response :success + assert_template 'add_issue' + post :add_issue, :id => 1, :issue => {:tracker_id => 1, :subject => 'This is the test_add_issue issue', :description => 'This is the description', :priority_id => 5} + assert_redirected_to 'projects/list_issues' + assert Issue.find_by_subject('This is the test_add_issue issue') + end + + def test_copy_issue + @request.session[:user_id] = 2 + get :add_issue, :id => 1, :copy_from => 1 + assert_template 'add_issue' + assert_not_nil assigns(:issue) + orig = Issue.find(1) + assert_equal orig.subject, assigns(:issue).subject + end end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index 254bffa20..5ddd4bde4 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -18,13 +18,23 @@ require File.dirname(__FILE__) + '/../test_helper' class IssueTest < Test::Unit::TestCase - fixtures :projects, :users, :members, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues + fixtures :projects, :users, :members, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values def test_category_based_assignment issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1) assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to end + def test_copy + issue = Issue.new.copy_from(1) + assert issue.save + issue.reload + orig = Issue.find(1) + assert_equal orig.subject, issue.subject + assert_equal orig.tracker, issue.tracker + assert_equal orig.custom_values.first.value, issue.custom_values.first.value + end + def test_close_duplicates # Create 3 issues issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Duplicates test', :description => 'Duplicates test') |