Feature #13596 » 0001-Adds-setting-to-allow-timelog-on-closed-issues.patch
| app/controllers/context_menus_controller.rb | ||
|---|---|---|
| 33 | 33 | |
| 34 | 34 |
@can = {
|
| 35 | 35 |
:edit => @issues.all?(&:attributes_editable?), |
| 36 |
:log_time => (@project && User.current.allowed_to?(:log_time, @project)),
|
|
| 36 |
:log_time => @issue&.time_loggable?,
|
|
| 37 | 37 |
:copy => User.current.allowed_to?(:copy_issues, @projects) && Issue.allowed_target_projects.any?, |
| 38 | 38 |
:add_watchers => User.current.allowed_to?(:add_issue_watchers, @projects), |
| 39 | 39 |
:delete => @issues.all?(&:deletable?), |
| app/models/issue.rb | ||
|---|---|---|
| 188 | 188 |
end |
| 189 | 189 |
end |
| 190 | 190 | |
| 191 |
# Returns true if user or current user is allowed to log time on the issue |
|
| 192 |
def time_loggable?(user=User.current) |
|
| 193 |
user.allowed_to?(:log_time, project) && (!Setting.timelog_accept_future_dates? || !closed?) |
|
| 194 |
end |
|
| 195 | ||
| 191 | 196 |
# Returns true if user or current user is allowed to edit or add notes to the issue |
| 192 | 197 |
def editable?(user=User.current) |
| 193 | 198 |
attributes_editable?(user) || notes_addable?(user) |
| app/models/time_entry.rb | ||
|---|---|---|
| 182 | 182 |
if spent_on && spent_on_changed? && user |
| 183 | 183 |
errors.add :base, I18n.t(:error_spent_on_future_date) if !Setting.timelog_accept_future_dates? && (spent_on > user.today) |
| 184 | 184 |
end |
| 185 |
if !Setting.timelog_accept_closed_issues? && issue&.closed? && issue&.was_closed? |
|
| 186 |
errors.add :base, I18n.t(:error_spent_on_closed_issue) |
|
| 187 |
end |
|
| 185 | 188 |
end |
| 186 | 189 | |
| 187 | 190 |
def hours=(h) |
| app/views/issues/_action_menu.html.erb | ||
|---|---|---|
| 3 | 3 |
:onclick => 'showAndScrollTo("update", "issue_notes"); return false;',
|
| 4 | 4 |
:class => 'icon icon-edit ', :accesskey => accesskey(:edit) if @issue.editable? %> |
| 5 | 5 |
<%= link_to sprite_icon('time-add', l(:button_log_time)), new_issue_time_entry_path(@issue),
|
| 6 |
:class => 'icon icon-time-add ' if User.current.allowed_to?(:log_time, @project) %>
|
|
| 6 |
:class => 'icon icon-time-add ' if @issue.time_loggable? %>
|
|
| 7 | 7 |
<%= watcher_link(@issue, User.current) %> |
| 8 | 8 |
<%= link_to sprite_icon('copy', l(:button_copy)), project_copy_issue_path(@project, @issue),
|
| 9 | 9 |
:class => 'icon icon-copy ' if User.current.allowed_to?(:copy_issues, @project) && Issue.allowed_target_projects.any? %> |
| app/views/issues/_edit.html.erb | ||
|---|---|---|
| 9 | 9 |
</div> |
| 10 | 10 |
</fieldset> |
| 11 | 11 |
<% end %> |
| 12 |
<% if User.current.allowed_to?(:log_time, @issue.project) %>
|
|
| 12 |
<% if @issue.time_loggable? %>
|
|
| 13 | 13 |
<fieldset class="tabular" id="log_time"><legend><%= l(:button_log_time) %></legend> |
| 14 | 14 |
<%= labelled_fields_for :time_entry, @time_entry do |time_entry| %> |
| 15 | 15 |
<div class="splitcontent"> |
| app/views/settings/_timelog.html.erb | ||
|---|---|---|
| 9 | 9 |
<p><%= setting_check_box :timelog_accept_0_hours %></p> |
| 10 | 10 | |
| 11 | 11 |
<p><%= setting_check_box :timelog_accept_future_dates %></p> |
| 12 | ||
| 13 |
<p><%= setting_check_box :timelog_accept_closed_issues %></p> |
|
| 12 | 14 |
</div> |
| 13 | 15 | |
| 14 | 16 |
<fieldset class="box"> |
| config/locales/en.yml | ||
|---|---|---|
| 235 | 235 |
error_exceeds_maximum_hours_per_day: "Cannot log more than %{max_hours} hours on the same day (%{logged_hours} hours have already been logged)"
|
| 236 | 236 |
error_can_not_delete_auth_source: "This authentication mode is in use and cannot be deleted." |
| 237 | 237 |
error_spent_on_future_date: "Cannot log time on a future date" |
| 238 |
error_spent_on_closed_issue: "Cannot log time on a closed issue" |
|
| 238 | 239 |
error_not_allowed_to_log_time_for_other_users: "You are not allowed to log time for other users" |
| 239 | 240 |
error_can_not_execute_macro_html: "Error executing the <strong>%{name}</strong> macro (%{error})"
|
| 240 | 241 |
error_macro_does_not_accept_block: "This macro does not accept a block of text" |
| ... | ... | |
| 519 | 520 |
setting_timelog_accept_0_hours: Accept time logs with 0 hours |
| 520 | 521 |
setting_timelog_max_hours_per_day: Maximum hours that can be logged per day and user |
| 521 | 522 |
setting_timelog_accept_future_dates: Accept time logs on future dates |
| 523 |
setting_timelog_accept_closed_issues: Accept time logs on closed issues |
|
| 522 | 524 |
setting_show_status_changes_in_mail_subject: Show status changes in issue mail notifications subject |
| 523 | 525 |
setting_project_list_defaults: Projects list defaults |
| 524 | 526 |
setting_twofa: Two-factor authentication |
| config/settings.yml | ||
|---|---|---|
| 347 | 347 |
default: 999 |
| 348 | 348 |
timelog_accept_future_dates: |
| 349 | 349 |
default: 1 |
| 350 |
timelog_accept_closed_issues: |
|
| 351 |
default: 1 |
|
| 350 | 352 |
show_status_changes_in_mail_subject: |
| 351 | 353 |
default: 1 |
| 352 | 354 |
wiki_tablesort_enabled: |
| test/functional/issues_controller_test.rb | ||
|---|---|---|
| 5885 | 5885 |
assert_select 'input[name=?]', 'time_entry[hours]', 0 |
| 5886 | 5886 |
end |
| 5887 | 5887 | |
| 5888 |
def test_get_edit_should_not_display_the_time_entry_form_on_closed_issue |
|
| 5889 |
with_settings :timelog_accept_closed_issues => '0' do |
|
| 5890 |
@request.session[:user_id] = 2 |
|
| 5891 |
issue = Issue.find(1) |
|
| 5892 |
issue.update :status => IssueStatus.find(5) |
|
| 5893 |
get(:edit, :params => {:id => 1})
|
|
| 5894 |
assert_select 'input[name=?]', 'time_entry[hours]', 0 |
|
| 5895 |
end |
|
| 5896 |
end |
|
| 5897 | ||
| 5888 | 5898 |
def test_get_edit_with_params |
| 5889 | 5899 |
@request.session[:user_id] = 2 |
| 5890 | 5900 |
get( |
| ... | ... | |
| 6341 | 6351 |
assert mail.subject.include?("(#{IssueStatus.find(2).name})")
|
| 6342 | 6352 |
end |
| 6343 | 6353 | |
| 6354 |
def test_update_should_accept_time_entry_when_closing_issue |
|
| 6355 |
with_settings :timelog_accept_closed_issues => '0' do |
|
| 6356 |
issue = Issue.find(1) |
|
| 6357 |
assert_equal 1, issue.status_id |
|
| 6358 |
@request.session[:user_id] = 2 |
|
| 6359 |
assert_difference('TimeEntry.count', 1) do
|
|
| 6360 |
put( |
|
| 6361 |
:update, |
|
| 6362 |
:params => {
|
|
| 6363 |
:id => 1, |
|
| 6364 |
:issue => {
|
|
| 6365 |
:status_id => 5, |
|
| 6366 |
}, |
|
| 6367 |
:time_entry => {
|
|
| 6368 |
:hours => '2', |
|
| 6369 |
:comments => '', |
|
| 6370 |
:activity_id => TimeEntryActivity.first |
|
| 6371 |
} |
|
| 6372 |
} |
|
| 6373 |
) |
|
| 6374 |
end |
|
| 6375 |
assert_redirected_to :action => 'show', :id => '1' |
|
| 6376 |
issue.reload |
|
| 6377 |
assert issue.closed? |
|
| 6378 |
end |
|
| 6379 |
end |
|
| 6380 | ||
| 6381 |
def test_update_should_not_accept_time_entry_on_closed_issue |
|
| 6382 |
with_settings :timelog_accept_closed_issues => '0' do |
|
| 6383 |
issue = Issue.find(1) |
|
| 6384 |
issue.update :status => IssueStatus.find(5) |
|
| 6385 |
@request.session[:user_id] = 2 |
|
| 6386 |
assert_no_difference('TimeEntry.count') do
|
|
| 6387 |
put( |
|
| 6388 |
:update, |
|
| 6389 |
:params => {
|
|
| 6390 |
:id => 1, |
|
| 6391 |
:issue => {
|
|
| 6392 |
}, |
|
| 6393 |
:time_entry => {
|
|
| 6394 |
:hours => '2', |
|
| 6395 |
:comments => '', |
|
| 6396 |
:activity_id => TimeEntryActivity.first |
|
| 6397 |
} |
|
| 6398 |
} |
|
| 6399 |
) |
|
| 6400 |
end |
|
| 6401 |
assert_response :success |
|
| 6402 |
end |
|
| 6403 |
end |
|
| 6404 | ||
| 6344 | 6405 |
def test_put_update_with_note_only |
| 6345 | 6406 |
notes = 'Note added by IssuesControllerTest#test_update_with_note_only' |
| 6346 | 6407 | |
| test/unit/time_entry_test.rb | ||
|---|---|---|
| 175 | 175 |
end |
| 176 | 176 |
end |
| 177 | 177 | |
| 178 |
def test_should_not_accept_closed_issue |
|
| 179 |
with_settings :timelog_accept_closed_issues => '0' do |
|
| 180 |
project = Project.find(1) |
|
| 181 |
entry = TimeEntry.generate project: project |
|
| 182 |
issue = project.issues.to_a.detect(&:closed?) |
|
| 183 |
entry.issue = issue |
|
| 184 |
assert !entry.save |
|
| 185 |
assert entry.errors[:base].present? |
|
| 186 |
assert_equal 'Cannot log time on a closed issue', entry.errors[:base].first |
|
| 187 |
end |
|
| 188 |
end |
|
| 189 | ||
| 178 | 190 |
def test_should_require_spent_on |
| 179 | 191 |
with_settings :timelog_accept_future_dates => '0' do |
| 180 | 192 |
entry = TimeEntry.find(1) |
- « Previous
- 1
- 2
- Next »