Patch #7610 » rollback-2.1.0-v2.patch
| redmine-2.1.0-modified/app/controllers/journals_controller.rb 2012-10-04 13:06:21.013138052 -0600 | ||
|---|---|---|
| 16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
| 17 | 17 | |
| 18 | 18 | class JournalsController < ApplicationController | 
| 19 | before_filter :find_journal, :only => [:edit, :diff] | |
| 19 |   before_filter :find_journal, :only => [:edit, :diff, :rollback] | |
| 20 | 20 | before_filter :find_issue, :only => [:new] | 
| 21 | 21 | before_filter :find_optional_project, :only => [:index] | 
| 22 | before_filter :authorize, :only => [:new, :edit, :diff] | |
| 22 |   before_filter :authorize, :only => [:new, :edit, :diff, :rollback] | |
| 23 | 23 | accept_rss_auth :index | 
| 24 | 24 | menu_item :issues | 
| 25 | 25 | |
| ... | ... | |
| 92 | 92 | end | 
| 93 | 93 | end | 
| 94 | 94 | |
| 95 | private | |
| 95 | def rollback | |
| 96 | (render_403; return false) unless @journal.can_rollback?(User.current) | |
| 97 | ||
| 98 | if @journal.rollback | |
| 99 | flash[:notice] = l(:notice_successful_update) | |
| 100 | else | |
| 101 | # can't seem to bring in the helper method 'error_messages_for' | |
| 102 | # and injecting it into show.rhtml doesn't seem to work, since | |
| 103 | # the @issue loses the errors on redirect (due to issue reload) | |
| 104 |       flash[:error] = "<ul>" + @journal.errors.full_messages.map {|msg| "<li>" + ERB::Util.html_escape(msg) + "</li>"}.join + "</ul>" | |
| 105 | end | |
| 106 | respond_to do |format| | |
| 107 |       format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id } | |
| 108 |       format.api  { render_validation_errors(@issue) } | |
| 109 | end | |
| 110 | end | |
| 111 | ||
| 112 | private | |
| 96 | 113 | |
| 97 | 114 | def find_journal | 
| 98 | 115 | @journal = Journal.find(params[:id]) | 
| redmine-2.1.0-modified/app/models/issue.rb 2012-10-05 10:00:05.257588764 -0600 | ||
|---|---|---|
| 597 | 597 | scope | 
| 598 | 598 | end | 
| 599 | 599 | |
| 600 | # rollback the changes in a journal, the journal is destroyed on success | |
| 601 | def rollback(journal) | |
| 602 | # only allow rollback of journal details for the last journal | |
| 603 | (errors.add_to_base(l(:notice_locking_conflict)); return) if !journal.last_valid_journal?(journals) | |
| 604 | ||
| 605 | # avoid the creation of journals during rollback (see 'attachment removed') | |
| 606 | @rolling_back = true | |
| 607 | ||
| 608 | # roll back each change detailed by the journal | |
| 609 | journal.details.each do |d| | |
| 610 | case d.property | |
| 611 | # issue attribute change | |
| 612 |         when 'attr'; send "#{d.prop_key}=", d.old_value | |
| 613 | # rollback custom field change | |
| 614 |         when 'cf'; custom_field_values.each {|v| v.value = d.old_value if v.custom_field_id == d.prop_key.to_i} | |
| 615 | # remove any added attachments (we can't recover removed attachments) | |
| 616 |         when 'attachment'; attachments.each {|v| attachments.delete(v) if v.id == d.prop_key.to_i} | |
| 617 | end | |
| 618 | end | |
| 619 | ||
| 620 | # allow the creation of journals again | |
| 621 | remove_instance_variable(:@rolling_back) | |
| 622 | ||
| 623 | # destroy the journal once we save the issue changes | |
| 624 | if save(:validate => false) | |
| 625 | journal.rolled_back = true | |
| 626 | journal.save | |
| 627 | end | |
| 628 | end | |
| 629 | ||
| 600 | 630 | # Return true if the issue is closed, otherwise false | 
| 601 | 631 | def closed? | 
| 602 | 632 | self.status.is_closed? | 
| redmine-2.1.0-modified/app/models/journal.rb 2012-10-05 10:47:26.589561668 -0600 | ||
|---|---|---|
| 62 | 62 | usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project))) | 
| 63 | 63 | end | 
| 64 | 64 | |
| 65 | def last_valid_journal?(journals) | |
| 66 | self == journals.last | |
| 67 | end | |
| 68 | ||
| 69 | def can_rollback?(usr = nil) | |
| 70 | user ||= User.current | |
| 71 | editable_by?(user) && (details.empty? || user.allowed_to?(:rollback_issue_notes, project)) | |
| 72 | end | |
| 73 |  | |
| 74 | def show? | |
| 75 | !self.rolled_back || User.current.pref.hide_rolled_back_issue_notes == '0' | |
| 76 | end | |
| 77 | ||
| 78 | # rollback the changes in a journal, the journal is destroyed on success | |
| 79 | def rollback | |
| 80 | # we could have details to rollback, so let the issue take care of this more complicated task | |
| 81 | journalized.rollback(self) || | |
| 82 | # on failure, collect the error messages from the issue on failure | |
| 83 |       (journalized.errors.each_full {|msg| errors.add_to_base(msg)}; false) | |
| 84 | end | |
| 85 | ||
| 65 | 86 | def project | 
| 66 | 87 | journalized.respond_to?(:project) ? journalized.project : nil | 
| 67 | 88 | end | 
| redmine-2.1.0-modified/app/models/user_preference.rb 2012-10-05 10:48:30.269561061 -0600 | ||
|---|---|---|
| 56 | 56 | |
| 57 | 57 | def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end | 
| 58 | 58 | def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end | 
| 59 | ||
| 60 | def hide_rolled_back_issue_notes; self[:hide_rolled_back_issue_notes] || '0'; end | |
| 61 | def hide_rolled_back_issue_notes=(value); self[:hide_rolled_back_issue_notes]=value; end | |
| 59 | 62 | end | 
| redmine-2.1.0-modified/app/views/issues/_history.html.erb 2012-10-05 10:51:24.237559399 -0600 | ||
|---|---|---|
| 1 | 1 | <% reply_links = authorize_for('issues', 'edit') -%> | 
| 2 | 2 | <% for journal in journals %> | 
| 3 | <% if journal.show? %> | |
| 4 | ||
| 5 | <% if journal.rolled_back? %> | |
| 6 | <strike> | |
| 7 | <% end %> | |
| 8 | ||
| 3 | 9 | <div id="change-<%= journal.id %>" class="<%= journal.css_classes %>"> | 
| 4 | 10 | <div id="note-<%= journal.indice %>"> | 
| 5 | 11 |     <h4><%= link_to "##{journal.indice}", {:anchor => "note-#{journal.indice}"}, :class => "journal-link" %> | 
| 12 | <% if journal.last_valid_journal?(journals) && journal.can_rollback? %> | |
| 13 |       <div class="journal-rollback"><%= link_to(image_tag('cancel.png'), {:controller => 'journals', :action => 'rollback', :id => journal}, :confirm => l(:text_are_you_sure), :method => :post, :title => l(:button_rollback_journal)) %> </div> | |
| 14 | <% end %> | |
| 6 | 15 | <%= avatar(journal.user, :size => "24") %> | 
| 7 | 16 | <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %></h4> | 
| 8 | 17 | |
| ... | ... | |
| 17 | 26 | </div> | 
| 18 | 27 | </div> | 
| 19 | 28 |   <%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %> | 
| 29 | ||
| 30 | <% if journal.rolled_back? %> | |
| 31 | </strike> | |
| 32 | <% end %> | |
| 33 | ||
| 34 | <% end %> | |
| 20 | 35 | <% end %> | 
| 21 | 36 | |
| 22 | 37 | <% heads_for_wiki_formatter if User.current.allowed_to?(:edit_issue_notes, issue.project) || User.current.allowed_to?(:edit_own_issue_notes, issue.project) %> | 
| redmine-2.1.0-modified/app/views/users/_preferences.html.erb 2012-10-05 10:40:22.869565707 -0600 | ||
|---|---|---|
| 3 | 3 | <p><%= pref_fields.time_zone_select :time_zone, nil, :include_blank => true %></p> | 
| 4 | 4 | <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p> | 
| 5 | 5 | <p><%= pref_fields.check_box :warn_on_leaving_unsaved %></p> | 
| 6 | <p><%= pref_fields.check_box :hide_rolled_back_issue_notes %></p> | |
| 6 | 7 | <% end %> | 
| redmine-2.1.0-modified/config/locales/en.yml 2012-10-05 10:57:21.185555995 -0600 | ||
|---|---|---|
| 331 | 331 | field_core_fields: Standard fields | 
| 332 | 332 | field_timeout: "Timeout (in seconds)" | 
| 333 | 333 | field_board_parent: Parent forum | 
| 334 | field_hide_rolled_back_issue_notes: "Hide rolled-back issue notes" | |
| 334 | 335 | setting_app_title: Application title | 
| 335 | 336 | setting_app_subtitle: Application subtitle | 
| ... | ... | |
| 457 | 458 | permission_export_wiki_pages: Export wiki pages | 
| 458 | 459 | permission_manage_subtasks: Manage subtasks | 
| 459 | 460 | permission_manage_related_issues: Manage related issues | 
| 461 | permission_rollback_issue_notes: Rollback issue notes | |
| 460 | 462 | project_module_issue_tracking: Issue tracking | 
| 461 | 463 | project_module_time_tracking: Time tracking | 
| ... | ... | |
| 923 | 925 | button_delete_my_account: Delete my account | 
| 924 | 926 | button_close: Close | 
| 925 | 927 | button_reopen: Reopen | 
| 928 | button_rollback: Rollback | |
| 926 | 929 | status_active: active | 
| 927 | 930 | status_registered: registered | 
| redmine-2.1.0-modified/db/migrate/20130128120000_add_journals_rolled_back.rb 2013-01-28 12:19:17.517695320 -0700 | ||
|---|---|---|
| 1 | class AddJournalsRolledBack < ActiveRecord::Migration | |
| 2 | def up | |
| 3 | add_column :journals, :rolled_back, :boolean, :default => 0 | |
| 4 | end | |
| 5 | ||
| 6 | def down | |
| 7 | remove_column :journals, :rolled_back | |
| 8 | end | |
| 9 | end | |