Index: app/models/issue.rb =================================================================== --- app/models/issue.rb (revision 8743) +++ app/models/issue.rb (working copy) @@ -635,7 +635,7 @@ rescue ActiveRecord::StaleObjectError attachments[:files].each(&:destroy) errors.add :base, l(:notice_locking_conflict) - raise ActiveRecord::Rollback + raise ActiveRecord::StaleObjectError end end end Index: app/controllers/issues_controller.rb =================================================================== --- app/controllers/issues_controller.rb (revision 8743) +++ app/controllers/issues_controller.rb (working copy) @@ -111,6 +111,7 @@ def show @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC") @journals.each_with_index {|j,i| j.indice = i+1} + @latest_journal = @journals.last @journals.reverse! if User.current.wants_comments_in_reverse_order? if User.current.allowed_to?(:view_changesets, @project) @@ -175,23 +176,65 @@ end def update + if params[:conflict_resolution].present? + case params[:conflict_resolution] + when 'none' + redirect_to :controller => 'issues', :action => 'show', :id => @issue + return + when 'notes' + # update notes only + params.delete(:attachments) + params.delete(:issue) + params.delete(:time_entry) + when 'all' + ; + end + end + update_issue_from_params - if @issue.save_issue_with_child_records(params, @time_entry) - render_attachment_warning_if_needed(@issue) - flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? - - respond_to do |format| - format.html { redirect_back_or_default({:action => 'show', :id => @issue}) } - format.api { head :ok } + begin + if @issue.save_issue_with_child_records(params, @time_entry) + render_attachment_warning_if_needed(@issue) + flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? + + respond_to do |format| + format.html { redirect_back_or_default({:action => 'show', :id => @issue}) } + format.api { head :ok } + end + else + render_attachment_warning_if_needed(@issue) + flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? + @journal = @issue.current_journal + + respond_to do |format| + format.html { render :action => 'edit' } + format.api { render_validation_errors(@issue) } + end end - else + rescue ActiveRecord::StaleObjectError + # mid-air conflict + @conflict_detected = true + + @issue.reload + params[:issue].delete(:lock_version) if params[:issue] + update_issue_from_params + + @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC") + @journals.each_with_index {|j,i| j.indice = i+1} + @latest_journal = @journals.last + if params[:latest_journal].present? + latest_journal_id = params[:latest_journal].to_i + @journals = @journals.select{|journal| latest_journal_id < journal.id } + end + @journals.reverse! if User.current.wants_comments_in_reverse_order? + render_attachment_warning_if_needed(@issue) flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? @journal = @issue.current_journal - + respond_to do |format| - format.html { render :action => 'edit' } + format.html { render :action => 'conflict' } format.api { render_validation_errors(@issue) } end end Index: app/views/issues/_edit.html.erb =================================================================== --- app/views/issues/_edit.html.erb (revision 8743) +++ app/views/issues/_edit.html.erb (working copy) @@ -6,8 +6,27 @@ :multipart => true} do |f| %> <%= error_messages_for 'issue', 'time_entry' %>