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 |