diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2007-10-09 19:07:19 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2007-10-09 19:07:19 +0000 |
commit | 2c4647f8c6d23c999ae959a047104eef49d00993 (patch) | |
tree | fa1241406a68d951ded62d04269d85dfb6883a2c /app | |
parent | df631e8c06d755fd673e4bbf072a7e15766d1e0c (diff) | |
download | redmine-2c4647f8c6d23c999ae959a047104eef49d00993.tar.gz redmine-2c4647f8c6d23c999ae959a047104eef49d00993.zip |
Added 'Bulk edit' functionality.
This can be done by clicking on the edit link (little pen icon) at the upper-left corner of the issue list.
Most properties can be set (priority, assignee, category, fixed version, start and due dates, done ratio) and a note can be entered.
Only issues of the current project can be selected for bulk edit (subproject issues can't).
git-svn-id: http://redmine.rubyforge.org/svn/trunk@817 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects_controller.rb | 30 | ||||
-rw-r--r-- | app/models/issue.rb | 2 | ||||
-rw-r--r-- | app/models/project.rb | 5 | ||||
-rw-r--r-- | app/views/issues/_bulk_edit_form.rhtml | 30 | ||||
-rw-r--r-- | app/views/issues/_list.rhtml | 9 | ||||
-rw-r--r-- | app/views/projects/list_issues.rhtml | 16 |
6 files changed, 85 insertions, 7 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index cf1325518..13253939a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -336,6 +336,36 @@ class ProjectsController < ApplicationController @options_for_rfpdf[:file_name] = "export.pdf" render :layout => false end + + # Bulk edit issues + def bulk_edit_issues + if request.post? + priority = Enumeration.find_by_id(params[:priority_id]) + assigned_to = User.find_by_id(params[:assigned_to_id]) + issues = @project.issues.find_all_by_id(params[:issue_ids]) + unsaved_issue_ids = [] + issues.each do |issue| + issue.init_journal(User.current, params[:notes]) + issue.priority = priority if priority + issue.assigned_to = assigned_to if assigned_to + issue.start_date = params[:start_date] unless params[:start_date].blank? + issue.due_date = params[:due_date] unless params[:due_date].blank? + issue.done_ratio = params[:done_ratio] unless params[:done_ratio].blank? + unsaved_issue_ids << issue.id unless issue.save + end + if unsaved_issue_ids.empty? + flash[:notice] = l(:notice_successful_update) unless issues.empty? + else + flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, issues.size, '#' + unsaved_issue_ids.join(', #')) + end + redirect_to :action => 'list_issues', :id => @project + return + end + render :update do |page| + page.hide 'query_form' + page.replace_html 'bulk-edit', :partial => 'issues/bulk_edit_form' + end + end def move_issues @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids] diff --git a/app/models/issue.rb b/app/models/issue.rb index 52e21b416..fc7f6e1b8 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -143,7 +143,7 @@ class Issue < ActiveRecord::Base # Users the issue can be assigned to def assignable_users - project.members.select {|m| m.role.assignable?}.collect {|m| m.user} + project.assignable_users end def spent_hours diff --git a/app/models/project.rb b/app/models/project.rb index b17f7ba74..3e6593f58 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -113,6 +113,11 @@ class Project < ActiveRecord::Base children.select {|child| child.active?} end + # Users issues can be assigned to + def assignable_users + members.select {|m| m.role.assignable?}.collect {|m| m.user} + end + # Returns an array of all custom fields enabled for project issues # (explictly associated custom fields and custom fields enabled for all projects) def custom_fields_for_issues(tracker) diff --git a/app/views/issues/_bulk_edit_form.rhtml b/app/views/issues/_bulk_edit_form.rhtml new file mode 100644 index 000000000..fc0972fd6 --- /dev/null +++ b/app/views/issues/_bulk_edit_form.rhtml @@ -0,0 +1,30 @@ +<div id="bulk-edit-fields"> +<fieldset class="box"><legend><%= l(:label_bulk_edit_selected_issues) %></legend> + +<p> +<label><%= l(:field_priority) %>: +<%= select_tag('priority_id', "<option>#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(Enumeration.get_values('IPRI'), :id, :name)) %></label> +<label><%= l(:field_assigned_to) %>: +<%= select_tag('assigned_to_id', "<option>#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.assignable_users, :id, :name)) %></label> +<label><%= l(:field_category) %>: +<%= select_tag('category_id', "<option>#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.issue_categories, :id, :name)) %></label> +<label><%= l(:field_fixed_version) %>: +<%= select_tag('fixed_version_id', "<option>#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.versions, :id, :name)) %></label> +</p> + +<p> +<label><%= l(:field_start_date) %>: +<%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %></label> +<label><%= l(:field_due_date) %>: +<%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %></label> +<label><%= l(:field_done_ratio) %>: +<%= select_tag 'done_ratio', options_for_select([l(:label_no_change_option)] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></label> +</p> + +<label for="notes"><%= l(:field_notes) %></label><br /> +<%= text_area_tag 'notes', '', :cols => 80, :rows => 5 %> + +</fieldset> +<p><%= submit_tag l(:button_apply) %> +<%= link_to l(:button_cancel), {}, :onclick => 'Element.hide("bulk-edit-fields"); if ($("query_form")) {Element.show("query_form")}; return false;' %></p> +</div> diff --git a/app/views/issues/_list.rhtml b/app/views/issues/_list.rhtml index 567ccba09..b81559c29 100644 --- a/app/views/issues/_list.rhtml +++ b/app/views/issues/_list.rhtml @@ -1,6 +1,11 @@ +<div id="bulk-edit"></div> <table class="list"> <thead><tr> - <th></th> + <th><%= link_to_remote(image_tag('edit.png'), + {:url => { :controller => 'projects', :action => 'bulk_edit_issues', :id => @project }, + :method => :get}, + {:title => l(:label_bulk_edit_selected_issues)}) if @project && User.current.allowed_to?(:edit_issues, @project) %> + </th> <%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %> <% query.columns.each do |column| %> <%= column_header(column) %> @@ -9,7 +14,7 @@ <tbody> <% issues.each do |issue| %> <tr class="issue <%= cycle('odd', 'even') %>"> - <td class="checkbox"><%= check_box_tag "issue_ids[]", issue.id, false, :id => "issue_#{issue.id}" %></td> + <td class="checkbox"><%= check_box_tag("issue_ids[]", issue.id, false, :id => "issue_#{issue.id}", :disabled => (!@project || @project != issue.project)) %></td> <td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> <% query.columns.each do |column| %> <%= content_tag 'td', column_content(column, issue), :class => column.name %> diff --git a/app/views/projects/list_issues.rhtml b/app/views/projects/list_issues.rhtml index 60e8f7be2..9f2ff870d 100644 --- a/app/views/projects/list_issues.rhtml +++ b/app/views/projects/list_issues.rhtml @@ -4,7 +4,6 @@ <% form_tag({ :controller => 'queries', :action => 'new', :project_id => @project }, :id => 'query_form') do %> <%= render :partial => 'queries/filters', :locals => {:query => @query} %> - <% end %> <div class="contextual"> <%= link_to_remote l(:button_apply), { :url => { :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 }, @@ -22,6 +21,8 @@ <% end %> </div> <br /> + + <% end %> <% else %> <div class="contextual"> <% if @query.editable_by?(User.current) %> @@ -31,6 +32,7 @@ </div> <h2><%= @query.name %></h2> + <div id="query_form"></div> <% set_html_title @query.name %> <% end %> <%= error_messages_for 'query' %> @@ -38,15 +40,14 @@ <% if @issues.empty? %> <p class="nodata"><%= l(:label_no_data) %></p> <% else %> - -<% form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) do %> +<% form_tag({:controller => 'projects', :action => 'bulk_edit_issues', :id => @project}, :id => 'issues_form', :onsubmit => "if (!checkBulkEdit(this)) {alert('#{l(:notice_no_issue_selected)}'); return false;}" ) do %> <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> <div class="contextual"> <%= l(:label_export_to) %> <%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'icon icon-csv' %>, <%= link_to 'PDF', {:action => 'export_issues_pdf', :id => @project}, :class => 'icon icon-pdf' %> </div> -<p><%= submit_tag(l(:button_move), :class => "button-small") if authorize_for('projects', 'move_issues') %> +<p> <%= pagination_links_full @issue_pages %> [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ] </p> @@ -57,3 +58,10 @@ <% content_for :sidebar do %> <%= render :partial => 'issues/sidebar' %> <% end %> + +<% content_for :header_tags do %> + <%= javascript_include_tag 'calendar/calendar' %> + <%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %> + <%= javascript_include_tag 'calendar/calendar-setup' %> + <%= stylesheet_link_tag 'calendar' %> +<% end %> |