Feature #7996 » bulk_time_entry_edit.diff
app/controllers/context_menus_controller.rb | ||
---|---|---|
40 | 40 |
|
41 | 41 |
render :layout => false |
42 | 42 |
end |
43 |
|
|
43 | ||
44 |
def time_entries |
|
45 |
@time_entries = TimeEntry.all(:conditions => {:id => params[:ids]}, :include => :project) |
|
46 |
|
|
47 |
@projects = @time_entries.collect(&:project).compact.uniq |
|
48 |
@project = @projects.first if @projects.size == 1 |
|
49 |
|
|
50 |
@activities = TimeEntryActivity.shared.active |
|
51 | ||
52 |
@can = {:edit => User.current.allowed_to?(:log_time, @projects), |
|
53 |
:update => User.current.allowed_to?(:log_time, @projects), |
|
54 |
:delete => User.current.allowed_to?(:log_time, @projects) |
|
55 |
} |
|
56 | ||
57 |
@back = back_url |
|
58 | ||
59 |
render :layout => false |
|
60 |
end |
|
44 | 61 |
end |
app/controllers/timelog_controller.rb | ||
---|---|---|
18 | 18 |
class TimelogController < ApplicationController |
19 | 19 |
menu_item :issues |
20 | 20 |
before_filter :find_project, :only => [:new, :create] |
21 |
before_filter :find_time_entry, :only => [:show, :edit, :update, :destroy] |
|
21 |
before_filter :find_time_entry, :only => [:show, :edit, :update] |
|
22 |
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy] |
|
22 | 23 |
before_filter :authorize, :except => [:index] |
23 | 24 |
before_filter :find_optional_project, :only => [:index] |
24 | 25 |
accept_key_auth :index, :show, :create, :update, :destroy |
... | ... | |
160 | 161 |
end |
161 | 162 |
end |
162 | 163 | |
164 |
def bulk_edit |
|
165 |
@available_activities = TimeEntryActivity.shared.active |
|
166 |
@custom_fields = TimeEntry.first.available_custom_fields |
|
167 |
end |
|
168 | ||
169 |
def bulk_update |
|
170 |
attributes = parse_params_for_bulk_time_entry_attributes(params) |
|
171 | ||
172 |
unsaved_time_entry_ids = [] |
|
173 |
@time_entries.each do |time_entry| |
|
174 |
time_entry.reload |
|
175 |
time_entry.attributes = attributes |
|
176 |
call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry }) |
|
177 |
unless time_entry.save |
|
178 |
# Keep unsaved time_entry ids to display them in flash error |
|
179 |
unsaved_time_entry_ids << time_entry.id |
|
180 |
end |
|
181 |
end |
|
182 |
set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids) |
|
183 |
redirect_back_or_default({:controller => 'timelog', :action => 'index', :project_id => @projects.first}) |
|
184 |
end |
|
185 | ||
163 | 186 |
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } |
164 | 187 |
def destroy |
165 |
if @time_entry.destroy && @time_entry.destroyed? |
|
166 |
respond_to do |format| |
|
167 |
format.html { |
|
168 |
flash[:notice] = l(:notice_successful_delete) |
|
169 |
redirect_to :back |
|
170 |
} |
|
171 |
format.api { head :ok } |
|
172 |
end |
|
173 |
else |
|
174 |
respond_to do |format| |
|
175 |
format.html { |
|
176 |
flash[:error] = l(:notice_unable_delete_time_entry) |
|
177 |
redirect_to :back |
|
178 |
} |
|
179 |
format.api { render_validation_errors(@time_entry) } |
|
188 |
@time_entries.each do |t| |
|
189 |
begin |
|
190 |
unless t.destroy && t.destroyed? |
|
191 |
respond_to do |format| |
|
192 |
format.html { |
|
193 |
flash[:error] = l(:notice_unable_delete_time_entry) |
|
194 |
redirect_to :back |
|
195 |
} |
|
196 |
format.api { render_validation_errors(t) } |
|
197 |
end |
|
198 |
end |
|
199 |
rescue ::ActionController::RedirectBackError |
|
200 |
redirect_to :action => 'index', :project_id => @projects.first |
|
180 | 201 |
end |
181 | 202 |
end |
182 |
rescue ::ActionController::RedirectBackError |
|
183 |
redirect_to :action => 'index', :project_id => @time_entry.project |
|
203 | ||
204 |
respond_to do |format| |
|
205 |
format.html { |
|
206 |
flash[:notice] = l(:notice_successful_delete) |
|
207 |
redirect_back_or_default(:action => 'index', :project_id => @projects.first) |
|
208 |
} |
|
209 |
format.api { head :ok } |
|
210 |
end |
|
184 | 211 |
end |
185 | 212 | |
186 | 213 |
private |
... | ... | |
195 | 222 |
render_404 |
196 | 223 |
end |
197 | 224 | |
225 |
def find_time_entries |
|
226 |
@time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids]) |
|
227 |
raise ActiveRecord::RecordNotFound if @time_entries.empty? |
|
228 |
@projects = @time_entries.collect(&:project).compact.uniq |
|
229 |
@project = @projects.first if @projects.size == 1 |
|
230 |
rescue ActiveRecord::RecordNotFound |
|
231 |
render_404 |
|
232 |
end |
|
233 | ||
234 |
def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids) |
|
235 |
if unsaved_time_entry_ids.empty? |
|
236 |
flash[:notice] = l(:notice_successful_update) unless time_entries.empty? |
|
237 |
else |
|
238 |
flash[:error] = l(:notice_failed_to_save_time_entries, |
|
239 |
:count => unsaved_time_entry_ids.size, |
|
240 |
:total => time_entries.size, |
|
241 |
:ids => '#' + unsaved_time_entry_ids.join(', #')) |
|
242 |
end |
|
243 |
end |
|
244 | ||
198 | 245 |
def find_project |
199 | 246 |
if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present? |
200 | 247 |
@issue = Issue.find(issue_id) |
... | ... | |
265 | 312 |
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) |
266 | 313 |
end |
267 | 314 | |
315 |
def parse_params_for_bulk_time_entry_attributes(params) |
|
316 |
attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?} |
|
317 |
attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'} |
|
318 |
attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values] |
|
319 |
attributes |
|
320 |
end |
|
268 | 321 |
end |
app/models/project.rb | ||
---|---|---|
431 | 431 |
def all_issue_custom_fields |
432 | 432 |
@all_issue_custom_fields ||= (IssueCustomField.for_all + issue_custom_fields).uniq.sort |
433 | 433 |
end |
434 | ||
435 |
# Returns an array of all custom fields enabled for project time entries |
|
436 |
# (explictly associated custom fields and custom fields enabled for all projects) |
|
437 |
def all_time_entry_custom_fields |
|
438 |
@all_time_entry_custom_fields ||= (TimeEntryCustomField.for_all + time_entry_custom_fields).uniq.sort |
|
439 |
end |
|
434 | 440 |
|
435 | 441 |
def project |
436 | 442 |
self |
app/views/context_menus/time_entries.html.erb | ||
---|---|---|
1 |
<ul> |
|
2 |
<%= call_hook(:view_time_entries_context_menu_start, {:time_entries => @time_entries, :can => @can, :back => @back }) %> |
|
3 | ||
4 |
<% if !@time_entry.nil? -%> |
|
5 |
<li><%= context_menu_link l(:button_edit), {:controller => 'timelog', :action => 'edit', :id => @time_entry}, |
|
6 |
:class => 'icon-edit', :disabled => !@can[:edit] %></li> |
|
7 |
<% else %> |
|
8 |
<li><%= context_menu_link l(:button_edit), {:controller => 'timelog', :action => 'bulk_edit', :ids => @time_entries.collect(&:id)}, |
|
9 |
:class => 'icon-edit', :disabled => !@can[:edit] %></li> |
|
10 |
<% end %> |
|
11 |
<% if @activities.present? -%> |
|
12 |
<li class="folder"> |
|
13 |
<a href="#" class="submenu"><%= l(:field_activity) %></a> |
|
14 |
<ul> |
|
15 |
<% @activities.each do |u| -%> |
|
16 |
<li><%= context_menu_link u.name, {:controller => 'timelog', :action => 'bulk_edit', :ids => @time_entries.collect(&:id), :time_entry => {'activity_id' => u}, :back_url => @back}, :method => :post, |
|
17 |
:selected => (@time_entry && u == @time_entry.activity), :disabled => !@can[:update] %></li> |
|
18 |
<% end -%> |
|
19 |
<li><%= context_menu_link l(:label_nobody), {:controller => 'timelog', :action => 'bulk_edit', :ids => @time_entries.collect(&:id), :time_entry => {'activity_id' => 'none'}, :back_url => @back}, :method => :post, |
|
20 |
:selected => (@time_entry && @time_entry.activity.nil?), :disabled => !@can[:update] %></li> |
|
21 |
</ul> |
|
22 |
</li> |
|
23 |
<% end %> |
|
24 | ||
25 |
<li> |
|
26 |
<%= context_menu_link l(:button_delete), |
|
27 |
{:controller => 'timelog', :action => 'destroy', :ids => @time_entries.collect(&:id), :back_url => @back}, |
|
28 |
:method => :delete, :confirm => l(:text_time_entries_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %> |
|
29 |
</li> |
|
30 | ||
31 |
<%= call_hook(:view_time_entries_context_menu_end, {:time_entries => @time_entries, :can => @can, :back => @back }) %> |
|
32 |
</ul> |
app/views/timelog/_list.rhtml | ||
---|---|---|
1 |
<% content_for :header_tags do %> |
|
2 |
<%= javascript_include_tag 'context_menu' %> |
|
3 |
<%= stylesheet_link_tag 'context_menu' %> |
|
4 |
<%= stylesheet_link_tag 'context_menu_rtl' if l(:direction) == 'rtl' %> |
|
5 |
<% end %> |
|
6 | ||
7 |
<% form_tag({}) do -%> |
|
8 |
<%= hidden_field_tag 'back_url', url_for(params) %> |
|
1 | 9 |
<table class="list time-entries"> |
2 | 10 |
<thead> |
3 | 11 |
<tr> |
12 |
<th class="checkbox hide-when-print"> |
|
13 |
<%= link_to image_tag('toggle_check.png'), |
|
14 |
{}, |
|
15 |
:onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;', |
|
16 |
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %> |
|
17 |
</th> |
|
4 | 18 |
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %> |
5 | 19 |
<%= sort_header_tag('user', :caption => l(:label_member)) %> |
6 | 20 |
<%= sort_header_tag('activity', :caption => l(:label_activity)) %> |
... | ... | |
13 | 27 |
</thead> |
14 | 28 |
<tbody> |
15 | 29 |
<% entries.each do |entry| -%> |
16 |
<tr class="time-entry <%= cycle("odd", "even") %>"> |
|
30 |
<tr class="time-entry <%= cycle("odd", "even") %> hascontextmenu"> |
|
31 |
<td class="checkbox hide-when-print"><%= check_box_tag("ids[]", entry.id, false, :id => nil) %></td> |
|
17 | 32 |
<td class="spent_on"><%= format_date(entry.spent_on) %></td> |
18 | 33 |
<td class="user"><%=h entry.user %></td> |
19 | 34 |
<td class="activity"><%=h entry.activity %></td> |
... | ... | |
39 | 54 |
<% end -%> |
40 | 55 |
</tbody> |
41 | 56 |
</table> |
57 |
<% end -%> |
|
58 | ||
59 |
<%= context_menu time_entries_context_menu_path %> |
app/views/timelog/bulk_edit.rhtml | ||
---|---|---|
1 |
<h2><%= l(:label_bulk_edit_selected_time_entries) %></h2> |
|
2 | ||
3 |
<ul><%= @time_entries.collect {|i| content_tag('li', link_to(h("#{i.spent_on.strftime("%Y-%m-%d")} -- #{i.project}: #{l(:label_f_hour_plural, :value => i.hours)}"), { :action => 'edit', :id => i }))} %></ul> |
|
4 | ||
5 |
<% form_tag(:action => 'bulk_update') do %> |
|
6 |
<%= @time_entries.collect {|i| hidden_field_tag('ids[]', i.id)}.join %> |
|
7 |
<div class="box tabular"> |
|
8 |
<fieldset class="attributes"> |
|
9 |
<legend><%= l(:label_change_properties) %></legend> |
|
10 |
<div> |
|
11 |
<p> |
|
12 |
<label><%= l(:field_issue) %></label> |
|
13 |
<%= text_field :time_entry, :issue_id, :size => 6 %> |
|
14 |
</p> |
|
15 | ||
16 |
<p> |
|
17 |
<label><%= l(:field_spent_on) %></label> |
|
18 |
<%= text_field :time_entry, :spent_on, :size => 10 %><%= calendar_for('time_entry_spent_on') %> |
|
19 |
</p> |
|
20 | ||
21 |
<p> |
|
22 |
<label><%= l(:field_hours) %></label> |
|
23 |
<%= text_field :time_entry, :hours, :size => 6 %> |
|
24 |
</p> |
|
25 | ||
26 |
<% if @available_activities.any? %> |
|
27 |
<p> |
|
28 |
<label><%= l(:field_activity) %></label> |
|
29 |
<%= select_tag('time_entry[activity_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_activities, :id, :name)) %> |
|
30 |
</p> |
|
31 |
<% end %> |
|
32 | ||
33 |
<p> |
|
34 |
<label><%= l(:field_comments) %></label> |
|
35 |
<%= text_field(:time_entry, :comments, :size => 100) %> |
|
36 |
</p> |
|
37 | ||
38 |
<% @custom_fields.each do |custom_field| %> |
|
39 |
<p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('time_entry', custom_field) %></p> |
|
40 |
<% end %> |
|
41 | ||
42 |
<%= call_hook(:view_time_entries_bulk_edit_details_bottom, { :time_entries => @time_entries }) %> |
|
43 |
</div> |
|
44 | ||
45 |
</fieldset> |
|
46 |
</div> |
|
47 | ||
48 |
<p><%= submit_tag l(:button_submit) %></p> |
|
49 |
<% end %> |
config/locales/bg.yml | ||
---|---|---|
943 | 943 | |
944 | 944 |
button_expand_all: Expand all |
945 | 945 |
button_collapse_all: Collapse all |
946 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
947 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/bs.yml | ||
---|---|---|
957 | 957 |
label_news_comment_added: Comment added to a news |
958 | 958 |
button_expand_all: Expand all |
959 | 959 |
button_collapse_all: Collapse all |
960 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
961 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/ca.yml | ||
---|---|---|
946 | 946 |
label_news_comment_added: Comment added to a news |
947 | 947 |
button_expand_all: Expand all |
948 | 948 |
button_collapse_all: Collapse all |
949 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
950 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/cs.yml | ||
---|---|---|
947 | 947 |
label_news_comment_added: Comment added to a news |
948 | 948 |
button_expand_all: Expand all |
949 | 949 |
button_collapse_all: Collapse all |
950 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
951 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/da.yml | ||
---|---|---|
959 | 959 |
label_news_comment_added: Comment added to a news |
960 | 960 |
button_expand_all: Expand all |
961 | 961 |
button_collapse_all: Collapse all |
962 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
963 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/de.yml | ||
---|---|---|
960 | 960 |
label_news_comment_added: Comment added to a news |
961 | 961 |
button_expand_all: Expand all |
962 | 962 |
button_collapse_all: Collapse all |
963 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
964 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/el.yml | ||
---|---|---|
943 | 943 |
label_news_comment_added: Comment added to a news |
944 | 944 |
button_expand_all: Expand all |
945 | 945 |
button_collapse_all: Collapse all |
946 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
947 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/en-GB.yml | ||
---|---|---|
947 | 947 |
label_news_comment_added: Comment added to a news |
948 | 948 |
button_expand_all: Expand all |
949 | 949 |
button_collapse_all: Collapse all |
950 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
951 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/en.yml | ||
---|---|---|
735 | 735 |
label_default_columns: Default columns |
736 | 736 |
label_no_change_option: (No change) |
737 | 737 |
label_bulk_edit_selected_issues: Bulk edit selected issues |
738 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
738 | 739 |
label_theme: Theme |
739 | 740 |
label_default: Default |
740 | 741 |
label_search_titles_only: Search titles only |
... | ... | |
891 | 892 |
text_status_changed_by_changeset: "Applied in changeset %{value}." |
892 | 893 |
text_time_logged_by_changeset: "Applied in changeset %{value}." |
893 | 894 |
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s) ?' |
895 |
text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies) ?' |
|
894 | 896 |
text_select_project_modules: 'Select modules to enable for this project:' |
895 | 897 |
text_default_administrator_account_changed: Default administrator account changed |
896 | 898 |
text_file_repository_writable: Attachments directory writable |
config/locales/es.yml | ||
---|---|---|
980 | 980 |
label_news_comment_added: Comment added to a news |
981 | 981 |
button_expand_all: Expand all |
982 | 982 |
button_collapse_all: Collapse all |
983 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
984 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/eu.yml | ||
---|---|---|
947 | 947 |
label_news_comment_added: Comment added to a news |
948 | 948 |
button_expand_all: Expand all |
949 | 949 |
button_collapse_all: Collapse all |
950 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
951 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/fa.yml | ||
---|---|---|
946 | 946 |
label_news_comment_added: Comment added to a news |
947 | 947 |
button_expand_all: Expand all |
948 | 948 |
button_collapse_all: Collapse all |
949 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
950 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/fi.yml | ||
---|---|---|
964 | 964 |
label_news_comment_added: Comment added to a news |
965 | 965 |
button_expand_all: Expand all |
966 | 966 |
button_collapse_all: Collapse all |
967 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
968 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/fr.yml | ||
---|---|---|
961 | 961 |
field_member_of_group: Groupe de l'assigné |
962 | 962 |
field_assigned_to_role: Rôle de l'assigné |
963 | 963 |
setting_emails_header: En-tête des emails |
964 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
965 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/gl.yml | ||
---|---|---|
955 | 955 |
label_news_comment_added: Comment added to a news |
956 | 956 |
button_expand_all: Expand all |
957 | 957 |
button_collapse_all: Collapse all |
958 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
959 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/he.yml | ||
---|---|---|
948 | 948 |
label_news_comment_added: Comment added to a news |
949 | 949 |
button_expand_all: Expand all |
950 | 950 |
button_collapse_all: Collapse all |
951 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
952 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/hr.yml | ||
---|---|---|
950 | 950 |
label_news_comment_added: Comment added to a news |
951 | 951 |
button_expand_all: Expand all |
952 | 952 |
button_collapse_all: Collapse all |
953 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
954 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/hu.yml | ||
---|---|---|
962 | 962 |
label_news_comment_added: Comment added to a news |
963 | 963 |
button_expand_all: Expand all |
964 | 964 |
button_collapse_all: Collapse all |
965 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
966 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/id.yml | ||
---|---|---|
951 | 951 |
label_news_comment_added: Comment added to a news |
952 | 952 |
button_expand_all: Expand all |
953 | 953 |
button_collapse_all: Collapse all |
954 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
955 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/it.yml | ||
---|---|---|
944 | 944 |
label_news_comment_added: Comment added to a news |
945 | 945 |
button_expand_all: Expand all |
946 | 946 |
button_collapse_all: Collapse all |
947 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
948 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/ja.yml | ||
---|---|---|
964 | 964 |
label_news_comment_added: Comment added to a news |
965 | 965 |
button_expand_all: Expand all |
966 | 966 |
button_collapse_all: Collapse all |
967 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
968 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/ko.yml | ||
---|---|---|
995 | 995 |
label_news_comment_added: Comment added to a news |
996 | 996 |
button_expand_all: Expand all |
997 | 997 |
button_collapse_all: Collapse all |
998 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
999 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/lt.yml | ||
---|---|---|
1003 | 1003 |
label_news_comment_added: Comment added to a news |
1004 | 1004 |
button_expand_all: Expand all |
1005 | 1005 |
button_collapse_all: Collapse all |
1006 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
1007 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/lv.yml | ||
---|---|---|
938 | 938 |
label_news_comment_added: Comment added to a news |
939 | 939 |
button_expand_all: Expand all |
940 | 940 |
button_collapse_all: Collapse all |
941 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
942 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/mk.yml | ||
---|---|---|
943 | 943 |
label_news_comment_added: Comment added to a news |
944 | 944 |
button_expand_all: Expand all |
945 | 945 |
button_collapse_all: Collapse all |
946 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
947 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/mn.yml | ||
---|---|---|
944 | 944 |
label_news_comment_added: Comment added to a news |
945 | 945 |
button_expand_all: Expand all |
946 | 946 |
button_collapse_all: Collapse all |
947 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
948 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/nl.yml | ||
---|---|---|
925 | 925 |
label_news_comment_added: Commentaar toegevoegd aan een nieuwsitem |
926 | 926 |
button_expand_all: Expand all |
927 | 927 |
button_collapse_all: Collapse all |
928 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
929 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/no.yml | ||
---|---|---|
930 | 930 |
label_news_comment_added: Comment added to a news |
931 | 931 |
button_expand_all: Expand all |
932 | 932 |
button_collapse_all: Collapse all |
933 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
934 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/pl.yml | ||
---|---|---|
960 | 960 |
label_news_comment_added: Comment added to a news |
961 | 961 |
button_expand_all: Expand all |
962 | 962 |
button_collapse_all: Collapse all |
963 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
964 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/pt-BR.yml | ||
---|---|---|
966 | 966 |
label_news_comment_added: Notícia recebeu um comentário |
967 | 967 |
button_expand_all: Expand all |
968 | 968 |
button_collapse_all: Collapse all |
969 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
970 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/pt.yml | ||
---|---|---|
947 | 947 |
label_news_comment_added: Comment added to a news |
948 | 948 |
button_expand_all: Expand all |
949 | 949 |
button_collapse_all: Collapse all |
950 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
951 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/ro.yml | ||
---|---|---|
936 | 936 |
label_news_comment_added: Comment added to a news |
937 | 937 |
button_expand_all: Expand all |
938 | 938 |
button_collapse_all: Collapse all |
939 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
940 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/ru.yml | ||
---|---|---|
1056 | 1056 |
label_news_comment_added: Comment added to a news |
1057 | 1057 |
button_expand_all: Expand all |
1058 | 1058 |
button_collapse_all: Collapse all |
1059 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
1060 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/sk.yml | ||
---|---|---|
938 | 938 |
label_news_comment_added: Comment added to a news |
939 | 939 |
button_expand_all: Expand all |
940 | 940 |
button_collapse_all: Collapse all |
941 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
942 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/sl.yml | ||
---|---|---|
939 | 939 |
label_news_comment_added: Comment added to a news |
940 | 940 |
button_expand_all: Expand all |
941 | 941 |
button_collapse_all: Collapse all |
942 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
943 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/sr-YU.yml | ||
---|---|---|
943 | 943 |
label_news_comment_added: Comment added to a news |
944 | 944 |
button_expand_all: Expand all |
945 | 945 |
button_collapse_all: Collapse all |
946 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
947 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/sr.yml | ||
---|---|---|
944 | 944 |
label_news_comment_added: Comment added to a news |
945 | 945 |
button_expand_all: Expand all |
946 | 946 |
button_collapse_all: Collapse all |
947 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
948 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/sv.yml | ||
---|---|---|
984 | 984 |
label_news_comment_added: Comment added to a news |
985 | 985 |
button_expand_all: Expand all |
986 | 986 |
button_collapse_all: Collapse all |
987 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
988 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/th.yml | ||
---|---|---|
940 | 940 |
label_news_comment_added: Comment added to a news |
941 | 941 |
button_expand_all: Expand all |
942 | 942 |
button_collapse_all: Collapse all |
943 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
944 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/tr.yml | ||
---|---|---|
962 | 962 |
label_news_comment_added: Comment added to a news |
963 | 963 |
button_expand_all: Expand all |
964 | 964 |
button_collapse_all: Collapse all |
965 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
966 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/uk.yml | ||
---|---|---|
939 | 939 |
label_news_comment_added: Comment added to a news |
940 | 940 |
button_expand_all: Expand all |
941 | 941 |
button_collapse_all: Collapse all |
942 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
943 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/vi.yml | ||
---|---|---|
994 | 994 |
label_news_comment_added: Comment added to a news |
995 | 995 |
button_expand_all: Expand all |
996 | 996 |
button_collapse_all: Collapse all |
997 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
998 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/zh-TW.yml | ||
---|---|---|
1025 | 1025 |
label_news_comment_added: Comment added to a news |
1026 | 1026 |
button_expand_all: Expand all |
1027 | 1027 |
button_collapse_all: Collapse all |
1028 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
1029 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/locales/zh.yml | ||
---|---|---|
957 | 957 |
label_news_comment_added: Comment added to a news |
958 | 958 |
button_expand_all: Expand all |
959 | 959 |
button_collapse_all: Collapse all |
960 |
label_bulk_edit_selected_time_entries: Bulk edit selected time entries |
|
961 |
text_time_entries_destroy_confirmation: Are you sure you want to delete the selected time entr(y/ies) ? |
config/routes.rb | ||
---|---|---|
21 | 21 |
time_report.connect 'projects/:project_id/time_entries/report.:format' |
22 | 22 |
end |
23 | 23 | |
24 |
map.bulk_edit_time_entry 'time_entries/bulk_edit', :controller => 'timelog', :action => 'bulk_edit', :conditions => { :method => :get } |
|
25 |
map.bulk_update_time_entry 'time_entries/bulk_edit', :controller => 'timelog', :action => 'bulk_update', :conditions => { :method => :post } |
|
26 |
map.time_entries_context_menu '/time_entries/context_menu', :controller => 'context_menus', :action => 'time_entries' |
|
27 | ||
24 | 28 |
# TODO: wasteful since this is also nested under issues, projects, and projects/issues |
25 | 29 |
map.resources :time_entries, :controller => 'timelog' |
26 | 30 |
|
... | ... | |
101 | 105 |
map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues| |
102 | 106 |
issues.resources :time_entries, :controller => 'timelog' |
103 | 107 |
end |
108 |
# map.time_entries_context_menu '/time_entries/context_menu', :controller => 'context_menus', :action => 'time_entries' |
|
104 | 109 | |
105 | 110 |
map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations| |
106 | 111 |
relations.connect 'issues/:issue_id/relations/:id', :action => 'new' |
lib/redmine.rb | ||
---|---|---|
84 | 84 |
end |
85 | 85 |
|
86 | 86 |
map.project_module :time_tracking do |map| |
87 |
map.permission :log_time, {:timelog => [:new, :create, :edit, :update]}, :require => :loggedin |
|
87 |
map.permission :log_time, {:timelog => [:new, :create, :edit, :update, :bulk_edit, :bulk_update]}, :require => :loggedin
|
|
88 | 88 |
map.permission :view_time_entries, :timelog => [:index, :show], :time_entry_reports => [:report] |
89 |
map.permission :edit_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :member |
|
90 |
map.permission :edit_own_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin |
|
89 |
map.permission :edit_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
|
|
90 |
map.permission :edit_own_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
|
|
91 | 91 |
map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member |
92 | 92 |
end |
93 | 93 |
|
test/fixtures/custom_fields.yml | ||
---|---|---|
129 | 129 |
field_format: date |
130 | 130 |
default_value: "" |
131 | 131 |
editable: true |
132 |
custom_fields_010: |
|
133 |
name: Overtime |
|
134 |
min_length: 0 |
|
135 |
regexp: "" |
|
136 |
is_for_all: false |
|
137 |
is_filter: false |
|
138 |
type: TimeEntryCustomField |
|
139 |
max_length: 0 |
|
140 |
possible_values: "" |
|
141 |
id: 10 |
|
142 |
is_required: false |
|
143 |
field_format: bool |
|
144 |
default_value: 0 |
|
145 |
editable: true |
test/fixtures/time_entries.yml | ||
---|---|---|
55 | 55 |
hours: 7.65 |
56 | 56 |
user_id: 1 |
57 | 57 |
tyear: 2007 |
58 |
time_entries_005: |
|
59 |
created_on: 2011-03-22 12:20:48 +02:00 |
|
60 |
tweek: 12 |
|
61 |
tmonth: 3 |
|
62 |
project_id: 5 |
|
63 |
comments: Time spent on a subproject |
|
64 |
updated_on: 2011-03-22 12:20:48 +02:00 |
|
65 |
activity_id: 10 |
|
66 |
spent_on: 2011-03-22 |
|
67 |
issue_id: |
|
68 |
id: 5 |
|
69 |
hours: 7.65 |
|
70 |
user_id: 1 |
|
71 |
tyear: 2011 |
|
58 | 72 |
|
test/functional/timelog_controller_test.rb | ||
---|---|---|
131 | 131 |
assert_equal 2, entry.issue_id |
132 | 132 |
assert_equal 2, entry.user_id |
133 | 133 |
end |
134 | ||
135 |
def test_get_bulk_edit |
|
136 |
@request.session[:user_id] = 2 |
|
137 |
get :bulk_edit, :ids => [1, 2] |
|
138 |
assert_response :success |
|
139 |
assert_template 'bulk_edit' |
|
140 |
|
|
141 |
# System wide custom field |
|
142 |
assert_tag :select, :attributes => {:name => 'time_entry[custom_field_values][10]'} |
|
143 |
end |
|
144 | ||
145 |
def test_get_bulk_edit_on_different_projects |
|
146 |
@request.session[:user_id] = 2 |
|
147 |
get :bulk_edit, :ids => [1, 2, 6] |
|
148 |
assert_response :success |
|
149 |
assert_template 'bulk_edit' |
|
150 |
end |
|
151 | ||
152 |
def test_bulk_update |
|
153 |
@request.session[:user_id] = 2 |
|
154 |
# update time entry activity |
|
155 |
post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9} |
|
156 |
|
|
157 |
assert_response 302 |
|
158 |
# check that the issues were updated |
|
159 |
assert_equal [9, 9], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.activity_id} |
|
160 |
end |
|
161 | ||
162 |
def test_bulk_update_on_different_projects |
|
163 |
@request.session[:user_id] = 2 |
|
164 |
# update time entry activity |
|
165 |
post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 } |
|
166 |
|
|
167 |
assert_response 302 |
|
168 |
# check that the issues were updated |
|
169 |
assert_equal [9, 9, 9], TimeEntry.find_all_by_id([1, 2, 4]).collect {|i| i.activity_id} |
|
170 |
end |
|
171 | ||
172 |
def test_bulk_update_on_different_projects_without_rights |
|
173 |
@request.session[:user_id] = 3 |
|
174 |
user = User.find(3) |
|
175 |
action = { :controller => "timelog", :action => "bulk_update" } |
|
176 |
assert user.allowed_to?(action, TimeEntry.find(1).project) |
|
177 |
assert ! user.allowed_to?(action, TimeEntry.find(5).project) |
|
178 |
post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 } |
|
179 |
assert_response 403 |
|
180 |
end |
|
181 | ||
182 |
def test_bulk_update_custom_field |
|
183 |
@request.session[:user_id] = 2 |
|
184 |
post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} } |
|
185 |
|
|
186 |
assert_response 302 |
|
187 |
assert_equal ["0", "0"], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.custom_value_for(10).value} |
|
188 |
end |
|
189 | ||
190 |
def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter |
|
191 |
@request.session[:user_id] = 2 |
|
192 |
post :bulk_update, :ids => [1,2], :back_url => '/time_entries' |
|
193 | ||
194 |
assert_response :redirect |
|
195 |
assert_redirected_to '/time_entries' |
|
196 |
end |
|
197 | ||
198 |
def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host |
|
199 |
@request.session[:user_id] = 2 |
|
200 |
post :bulk_update, :ids => [1,2], :back_url => 'http://google.com' |
|
201 | ||
202 |
assert_response :redirect |
|
203 |
assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier |
|
204 |
end |
|
134 | 205 |
|
135 | 206 |
def test_destroy |
136 | 207 |
@request.session[:user_id] = 2 |
... | ... | |
236 | 307 |
get :index, :format => 'csv' |
237 | 308 |
assert_response :success |
238 | 309 |
assert_equal 'text/csv', @response.content_type |
239 |
assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment\n") |
|
240 |
assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\"\n") |
|
310 |
assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n")
|
|
311 |
assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n")
|
|
241 | 312 |
end |
242 | 313 |
|
243 | 314 |
def test_index_csv_export |
... | ... | |
245 | 316 |
get :index, :project_id => 1, :format => 'csv' |
246 | 317 |
assert_response :success |
247 | 318 |
assert_equal 'text/csv', @response.content_type |
248 |
assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment\n") |
|
249 |
assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\"\n") |
|
319 |
assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n")
|
|
320 |
assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n")
|
|
250 | 321 |
end |
251 | 322 |
end |