commit b6dffc9391a9419658813f8d31254fe448c8e5c0 Author: Marius BALTEANU Date: Tue Jul 25 21:44:57 2017 +0000 added feature diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb old mode 100644 new mode 100755 index 6bd7ab3..c327f0e --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -164,8 +164,18 @@ class TimelogController < ApplicationController end def bulk_edit - @available_activities = @projects.map(&:activities).reduce(:&) + @target_projects = Project.allowed_to(:log_time).to_a @custom_fields = TimeEntry.first.available_custom_fields.select {|field| field.format.bulk_edit_supported} + if params[:time_entry] + @target_project = @target_projects.detect {|p| p.id.to_s == params[:time_entry][:project_id].to_s} + end + if @target_project + @available_activities = @target_project.activities + else + @available_activities = @projects.map(&:activities).reduce(:&) + end + @time_entry_params = params[:time_entry] || {} + @time_entry_params[:custom_field_values] ||= {} end def bulk_update diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb old mode 100644 new mode 100755 index 16aea97..dc89d15 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1479,6 +1479,20 @@ module ApplicationHelper encoding = l(:general_csv_encoding) end + # Returns an array of error messages for bulk edited items (issues, time entries) + def bulk_edit_error_messages(items) + messages = {} + items.each do |item| + item.errors.full_messages.each do |message| + messages[message] ||= [] + messages[message] << item + end + end + messages.map { |message, items| + "#{message}: " + items.map {|i| "##{i.id}"}.join(', ') + } + end + private def wiki_helper diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb old mode 100644 new mode 100755 index f867760..74b0386 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -164,20 +164,6 @@ module IssuesHelper end end - # Returns an array of error messages for bulk edited issues - def bulk_edit_error_messages(issues) - messages = {} - issues.each do |issue| - issue.errors.full_messages.each do |message| - messages[message] ||= [] - messages[message] << issue - end - end - messages.map { |message, issues| - "#{message}: " + issues.map {|i| "##{i.id}"}.join(', ') - } - end - # Returns a link for adding a new subtask to the given issue def link_to_new_subtask(issue) attrs = { diff --git a/app/views/timelog/_form.html.erb b/app/views/timelog/_form.html.erb old mode 100644 new mode 100755 diff --git a/app/views/timelog/bulk_edit.html.erb b/app/views/timelog/bulk_edit.html.erb old mode 100644 new mode 100755 index 96c9531..5d82c54 --- a/app/views/timelog/bulk_edit.html.erb +++ b/app/views/timelog/bulk_edit.html.erb @@ -28,34 +28,42 @@

+ + <%= select_tag('time_entry[project_id]', project_tree_options_for_select(@target_projects, + :include_blank => l(:label_no_change_option), :selected => @target_project), + :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')" ) %> +

+

<%= text_field :time_entry, :issue_id, :size => 6 %> + +

- <%= date_field :time_entry, :spent_on, :size => 10 %><%= calendar_for('time_entry_spent_on') %> + <%= date_field :time_entry, :spent_on, :size => 10, :value => @time_entry_params[:spent_on] %><%= calendar_for('time_entry_spent_on') %>

- <%= text_field :time_entry, :hours, :size => 6 %> + <%= text_field :time_entry, :hours, :size => 6, :value => @time_entry_params[:hours] %>

<% if @available_activities.any? %>

- <%= select_tag('time_entry[activity_id]', content_tag('option', l(:label_no_change_option), :value => '') + options_from_collection_for_select(@available_activities, :id, :name)) %> + <%= select_tag('time_entry[activity_id]', content_tag('option', l(:label_no_change_option), :value => '') + options_from_collection_for_select(@available_activities, :id, :name, @time_entry_params[:activity_id])) %>

<% end %>

- <%= text_field(:time_entry, :comments, :size => 100) %> + <%= text_field(:time_entry, :comments, :size => 100, :value => @time_entry_params[:comments]) %>

<% @custom_fields.each do |custom_field| %> -

<%= custom_field_tag_for_bulk_edit('time_entry', custom_field, @time_entries) %>

+

<%= custom_field_tag_for_bulk_edit('time_entry', custom_field, @time_entries, @time_entry_params[:custom_field_values][custom_field.id.to_s]) %>

<% end %> <%= call_hook(:view_time_entries_bulk_edit_details_bottom, { :time_entries => @time_entries }) %> @@ -64,3 +72,47 @@

<%= submit_tag l(:button_submit) %>

<% end %> + +<%= javascript_tag do %> + $(document).ready(function(){ + $('#time_entry_project_id').change(function(){ + + $('#time_entry_issue').text(''); + }); + }); + + <% if @project || @target_project %> + observeAutocompleteField('time_entry_issue_id', + function(request, callback) { + var url = '<%= j auto_complete_issues_path %>'; + var data = { + term: request.term + }; + var project_id; + <% if @project %> + project_id = '<%= @project.id %>'; + <% end %> + + current_project_id = $('#time_entry_project_id').val(); + if(current_project_id === ''){ + data['project_id'] = project_id; + } else { + data['project_id'] = current_project_id; + } + + $.get(url, data, null, 'json') + .done(function(data){ + callback(data); + }) + .fail(function(jqXHR, status, error){ + callback([]); + }); + }, + { + select: function(event, ui, data) { + $('#time_entry_issue').text(ui.item.label); + } + } + ); + <% end %> +<% end %> \ No newline at end of file diff --git a/app/views/timelog/bulk_edit.js.erb b/app/views/timelog/bulk_edit.js.erb new file mode 100644 index 0000000..ab07f01 --- /dev/null +++ b/app/views/timelog/bulk_edit.js.erb @@ -0,0 +1 @@ +$('#content').html('<%= escape_javascript(render :template => 'timelog/bulk_edit', :formats => [:html]) %>'); diff --git a/config/routes.rb b/config/routes.rb old mode 100644 new mode 100755 index a08ca10..074109b --- a/config/routes.rb +++ b/config/routes.rb @@ -158,7 +158,7 @@ Rails.application.routes.draw do end end end - + match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get resources :wiki, :except => [:index, :create], :as => 'wiki_page' do member do @@ -234,6 +234,8 @@ Rails.application.routes.draw do match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete # Used to update the new time entry form post '/time_entries/new', :to => 'timelog#new' + # Used to update the bulk edit time entry form + post '/time_entries/bulk_edit', :to => 'timelog#bulk_edit' get 'projects/:id/activity', :to => 'activities#index', :as => :project_activity get 'activity', :to => 'activities#index' diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb old mode 100644 new mode 100755 index 37c5844..6d15f3f --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -545,6 +545,11 @@ class TimelogControllerTest < Redmine::ControllerTest end assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do + assert_select 'select[name=?]', 'time_entry[project_id]' + + # Clear issue checkbox + assert_select 'input[name=?][value=?]', 'time_entry[issue_id]', 'none' + # System wide custom field assert_select 'select[name=?]', 'time_entry[custom_field_values][10]' @@ -563,6 +568,34 @@ class TimelogControllerTest < Redmine::ControllerTest assert_response :success end + def test_get_bulk_edit_on_different_projects_should_propose_only_common_activites + project = Project.find(3) + TimeEntryActivity.create!(:name => 'QA', :project => project, :parent => TimeEntryActivity.find_by_name('QA'), :active => false) + @request.session[:user_id] = 1 + + get :bulk_edit, :params => {:ids => [1, 2, 4]} + assert_response :success + assert_select 'select[id=?]', 'time_entry_activity_id' do + assert_select 'option', 3 + assert_select 'option[value=?]', '11', 0, :text => 'QA' + end + end + + def test_get_bulk_edit_on_same_project_should_propose_project_activities + project = Project.find(1) + override_activity = TimeEntryActivity.create!({:name => "QA override", :parent => TimeEntryActivity.find_by_name("QA"), :project => project}) + + @request.session[:user_id] = 1 + + get :bulk_edit, :params => {:ids => [1, 2]} + assert_response :success + + assert_select 'select[id=?]', 'time_entry_activity_id' do + assert_select 'option', 4 + assert_select 'option[value=?]', override_activity.id.to_s, :text => 'QA override' + end + end + def test_bulk_edit_with_edit_own_time_entries_permission @request.session[:user_id] = 2 Role.find_by_name('Manager').remove_permission! :edit_time_entries diff --git a/test/integration/routing/timelog_test.rb b/test/integration/routing/timelog_test.rb old mode 100644 new mode 100755 index fd20dd5..0f7f8e4 --- a/test/integration/routing/timelog_test.rb +++ b/test/integration/routing/timelog_test.rb @@ -55,6 +55,7 @@ class RoutingTimelogsTest < Redmine::RoutingTest def test_timelogs_bulk_edit should_route 'GET /time_entries/bulk_edit' => 'timelog#bulk_edit' + should_route 'POST /time_entries/bulk_edit' => 'timelog#bulk_edit' should_route 'POST /time_entries/bulk_update' => 'timelog#bulk_update' should_route 'DELETE /time_entries/destroy' => 'timelog#destroy' end