Patch #7610 » rollback-1.1.0.patch
| redmine-1.1.0-rollback/app/controllers/journals_controller.rb 2011-02-11 17:15:13.829487200 -0700 | ||
|---|---|---|
| 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] |
|
| 19 |
before_filter :find_journal, :only => [:edit, :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] |
|
| 22 |
before_filter :authorize, :only => [:new, :edit, :rollback]
|
|
| 23 | 23 |
accept_key_auth :index |
| 24 | 24 |
|
| 25 | 25 |
helper :issues |
| ... | ... | |
| 67 | 67 |
end |
| 68 | 68 |
|
| 69 | 69 |
def edit |
| 70 |
(render_403; return false) unless @journal.editable_by?(User.current) |
|
| 71 |
|
|
| 70 | 72 |
if request.post? |
| 71 | 73 |
@journal.update_attributes(:notes => params[:notes]) if params[:notes] |
| 72 | 74 |
@journal.destroy if @journal.details.empty? && @journal.notes.blank? |
| ... | ... | |
| 77 | 79 |
end |
| 78 | 80 |
end |
| 79 | 81 |
end |
| 82 |
|
|
| 83 |
def rollback |
|
| 84 |
(render_403; return false) unless @journal.can_rollback?(User.current) |
|
| 85 |
|
|
| 86 |
if @journal.rollback |
|
| 87 |
flash[:notice] = l(:notice_successful_update) |
|
| 88 |
else |
|
| 89 |
# can't seem to bring in the helper method 'error_messages_for' |
|
| 90 |
# and injecting it into show.rhtml doesn't seem to work, since |
|
| 91 |
# the @issue loses the errors on redirect (due to issue reload) |
|
| 92 |
flash[:error] = "<ul>" + @journal.errors.full_messages.map {|msg| "<li>" + ERB::Util.html_escape(msg) + "</li>"}.join + "</ul>"
|
|
| 93 |
end |
|
| 94 |
respond_to do |format| |
|
| 95 |
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
|
|
| 96 |
format.api { render_validation_errors(@issue) }
|
|
| 97 |
end |
|
| 98 |
end |
|
| 80 | 99 |
|
| 81 | 100 |
private |
| 82 | 101 |
def find_journal |
| 83 | 102 |
@journal = Journal.find(params[:id]) |
| 84 |
(render_403; return false) unless @journal.editable_by?(User.current) |
|
| 85 | 103 |
@project = @journal.journalized.project |
| 86 | 104 |
rescue ActiveRecord::RecordNotFound |
| 87 | 105 |
render_404 |
| redmine-1.1.0-rollback/app/models/issue.rb 2011-02-11 17:17:51.065874800 -0700 | ||
|---|---|---|
| 182 | 182 |
end |
| 183 | 183 |
issue |
| 184 | 184 |
end |
| 185 |
|
|
| 186 |
# parent_id is never set directly, see :after_save |
|
| 187 |
def parent_id=(id) |
|
| 188 |
@parent_issue = Issue.find_by_id(id) |
|
| 189 |
end |
|
| 185 | 190 |
|
| 186 | 191 |
def status_id=(sid) |
| 187 | 192 |
self.status = nil |
| ... | ... | |
| 358 | 363 |
@current_journal |
| 359 | 364 |
end |
| 360 | 365 |
|
| 366 |
# rollback the changes in a journal, the journal is destroyed on success |
|
| 367 |
def rollback(journal) |
|
| 368 |
# only allow rollback of journal details for the last journal |
|
| 369 |
(errors.add_to_base(l(:notice_locking_conflict)); return) if journal != journals.last |
|
| 370 |
|
|
| 371 |
# avoid the creation of journals during rollback (see 'attachment removed') |
|
| 372 |
@rolling_back = true |
|
| 373 |
|
|
| 374 |
# roll back each change detailed by the journal |
|
| 375 |
journal.details.each do |d| |
|
| 376 |
case d.property |
|
| 377 |
# issue attribute change |
|
| 378 |
when 'attr'; send("#{d.prop_key}=", d.old_value)
|
|
| 379 |
# rollback custom field change |
|
| 380 |
when 'cf'; custom_field_values.each {|v| v.value = d.old_value if v.custom_field_id == d.prop_key.to_i}
|
|
| 381 |
# remove any added attachments (we can't recover removed attachments) |
|
| 382 |
when 'attachment'; attachments.each {|v| attachments.delete(v) if v.id == d.prop_key.to_i}
|
|
| 383 |
end |
|
| 384 |
end |
|
| 385 |
|
|
| 386 |
# allow the creation of journals again |
|
| 387 |
remove_instance_variable(:@rolling_back) |
|
| 388 |
|
|
| 389 |
# destroy the journal once we save the issue changes |
|
| 390 |
journal.destroy if save(false) |
|
| 391 |
end |
|
| 392 |
|
|
| 361 | 393 |
# Return true if the issue is closed, otherwise false |
| 362 | 394 |
def closed? |
| 363 | 395 |
self.status.is_closed? |
| ... | ... | |
| 785 | 817 |
|
| 786 | 818 |
# Callback on attachment deletion |
| 787 | 819 |
def attachment_removed(obj) |
| 820 |
return if @rolling_back |
|
| 788 | 821 |
journal = init_journal(User.current) |
| 789 | 822 |
journal.details << JournalDetail.new(:property => 'attachment', |
| 790 | 823 |
:prop_key => obj.id, |
| redmine-1.1.0-rollback/app/models/journal.rb 2011-02-11 17:10:38.544713600 -0700 | ||
|---|---|---|
| 58 | 58 |
usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project))) |
| 59 | 59 |
end |
| 60 | 60 |
|
| 61 |
def can_rollback?(usr = nil) |
|
| 62 |
user = usr || User.current |
|
| 63 |
editable_by?(user) && (details.empty? || user.allowed_to?(:rollback_issue_notes, project)) |
|
| 64 |
end |
|
| 65 |
|
|
| 66 |
# rollback the changes in a journal, the journal is destroyed on success |
|
| 67 |
def rollback |
|
| 68 |
# we could have details to rollback, so let the issue |
|
| 69 |
# take care of this more complicated task |
|
| 70 |
journalized.rollback(self) || |
|
| 71 |
# on failure, collect the error messages from the issue on failure |
|
| 72 |
(journalized.errors.each_full {|msg| errors.add_to_base(msg)}; false)
|
|
| 73 |
end |
|
| 74 |
|
|
| 61 | 75 |
def project |
| 62 | 76 |
journalized.respond_to?(:project) ? journalized.project : nil |
| 63 | 77 |
end |
| redmine-1.1.0-rollback/app/views/issues/_history.rhtml 2011-02-11 17:10:38.560338800 -0700 | ||
|---|---|---|
| 2 | 2 |
<% for journal in journals %> |
| 3 | 3 |
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>"> |
| 4 | 4 |
<h4><div class="journal-link"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div>
|
| 5 |
<% if journal == journals.last && journal.can_rollback? %> |
|
| 6 |
<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(:label_rollback)) %> </div>
|
|
| 7 |
<% end %> |
|
| 5 | 8 |
<%= avatar(journal.user, :size => "24") %> |
| 6 | 9 |
<%= content_tag('a', '', :name => "note-#{journal.indice}")%>
|
| 7 | 10 |
<%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %></h4> |
| redmine-1.1.0-rollback/config/locales/en.yml 2011-02-11 17:10:38.560338800 -0700 | ||
|---|---|---|
| 378 | 378 |
permission_add_issue_notes: Add notes |
| 379 | 379 |
permission_edit_issue_notes: Edit notes |
| 380 | 380 |
permission_edit_own_issue_notes: Edit own notes |
| 381 |
permission_rollback_issue_notes: Rollback issue notes |
|
| 381 | 382 |
permission_move_issues: Move issues |
| 382 | 383 |
permission_delete_issues: Delete issues |
| 383 | 384 |
permission_manage_public_queries: Manage public queries |
| ... | ... | |
| 793 | 794 |
label_project_copy_notifications: Send email notifications during the project copy |
| 794 | 795 |
label_principal_search: "Search for user or group:" |
| 795 | 796 |
label_user_search: "Search for user:" |
| 797 |
label_rollback: Rollback |
|
| 796 | 798 |
|
| 797 | 799 |
button_login: Login |
| 798 | 800 |
button_submit: Submit |
| redmine-1.1.0-rollback/lib/redmine.rb 2011-02-11 17:10:38.575964000 -0700 | ||
|---|---|---|
| 72 | 72 |
map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
|
| 73 | 73 |
map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
|
| 74 | 74 |
map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
|
| 75 |
map.permission :rollback_issue_notes, {:journals => [:rollback]}
|
|
| 75 | 76 |
map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
|
| 76 | 77 |
map.permission :delete_issues, {:issues => :destroy}, :require => :member
|
| 77 | 78 |
# Queries |
| redmine-1.1.0-rollback/public/stylesheets/application.css 2011-02-11 15:59:42.537112400 -0700 | ||
|---|---|---|
| 938 | 938 |
float: right; |
| 939 | 939 |
} |
| 940 | 940 |
|
| 941 |
.journal-rollback {
|
|
| 942 |
float: right; |
|
| 943 |
} |
|
| 944 |
|
|
| 941 | 945 |
h2 img { vertical-align:middle; }
|
| 942 | 946 |
|
| 943 | 947 |
.hascontextmenu { cursor: context-menu; }
|