OSDN Git Service

Keep track of issue description changes (#746).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 27 Feb 2011 13:34:41 +0000 (13:34 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 27 Feb 2011 13:34:41 +0000 (13:34 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4954 e93f8b46-1217-0410-a6f0-8f06a7374b81

13 files changed:
app/controllers/journals_controller.rb
app/helpers/issues_helper.rb
app/models/issue.rb
app/models/journal_detail.rb
app/views/journals/diff.html.erb [new file with mode: 0644]
config/locales/en.yml
config/locales/fr.yml
db/migrate/20110227125750_change_journal_details_values_to_text.rb [new file with mode: 0644]
lib/redmine.rb
public/stylesheets/application.css
test/fixtures/journal_details.yml
test/functional/journals_controller_test.rb
test/unit/issue_test.rb

index 189204e..37e52ca 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2008  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 class JournalsController < ApplicationController
-  before_filter :find_journal, :only => [:edit]
+  before_filter :find_journal, :only => [:edit, :diff]
   before_filter :find_issue, :only => [:new]
   before_filter :find_optional_project, :only => [:index]
-  before_filter :authorize, :only => [:new, :edit]
+  before_filter :authorize, :only => [:new, :edit, :diff]
   accept_key_auth :index
-
+  menu_item :issues
+  
   helper :issues
   helper :queries
   include QueriesHelper
@@ -43,6 +44,17 @@ class JournalsController < ApplicationController
     render_404
   end
   
+  def diff
+    @issue = @journal.issue
+    if params[:detail_id].present?
+      @detail = @journal.details.find_by_id(params[:detail_id])
+    else
+      @detail = @journal.details.detect {|d| d.prop_key == 'description'}
+    end
+    (render_404; return false) unless @issue && @detail
+    @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
+  end
+  
   def new
     journal = Journal.find(params[:journal_id]) if params[:journal_id]
     if journal
@@ -67,6 +79,7 @@ class JournalsController < ApplicationController
   end
   
   def edit
+    (render_403; return false) unless @journal.editable_by?(User.current)
     if request.post?
       @journal.update_attributes(:notes => params[:notes]) if params[:notes]
       @journal.destroy if @journal.details.empty? && @journal.notes.blank?
@@ -86,10 +99,10 @@ class JournalsController < ApplicationController
     end
   end
   
-private
+  private
+  
   def find_journal
     @journal = Journal.find(params[:id])
-    (render_403; return false) unless @journal.editable_by?(User.current)
     @project = @journal.journalized.project
   rescue ActiveRecord::RecordNotFound
     render_404
index ec027e2..f9f1c41 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -183,7 +183,16 @@ module IssuesHelper
       end
     end
     
-    if !detail.value.blank?
+    if detail.property == 'attr' && detail.prop_key == 'description'
+      s = l(:text_journal_changed_no_detail, :label => label)
+      unless no_html
+        diff_link = link_to 'diff', 
+          {:controller => 'journals', :action => 'diff', :id => detail.journal_id, :detail_id => detail.id},
+          :title => l(:label_view_diff)
+        s << " (#{ diff_link })"
+      end
+      s
+    elsif !detail.value.blank?
       case detail.property
       when 'attr', 'cf'
         if !detail.old_value.blank?
index 2810138..942b654 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -829,7 +829,7 @@ class Issue < ActiveRecord::Base
   def create_journal
     if @current_journal
       # attributes changes
-      (Issue.column_names - %w(id description root_id lft rgt lock_version created_on updated_on)).each {|c|
+      (Issue.column_names - %w(id root_id lft rgt lock_version created_on updated_on)).each {|c|
         @current_journal.details << JournalDetail.new(:property => 'attr',
                                                       :prop_key => c,
                                                       :old_value => @issue_before_change.send(c),
index 5823900..aa22e6f 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -17,9 +17,4 @@
 
 class JournalDetail < ActiveRecord::Base
   belongs_to :journal
-  
-  def before_save
-    self.value = value[0..254] if value && value.is_a?(String)
-    self.old_value = old_value[0..254] if old_value && old_value.is_a?(String)
-  end
 end
diff --git a/app/views/journals/diff.html.erb b/app/views/journals/diff.html.erb
new file mode 100644 (file)
index 0000000..21b8755
--- /dev/null
@@ -0,0 +1,10 @@
+<h2><%=h @issue.tracker %> #<%= @issue.id %></h2>
+<p><%= authoring @journal.created_on, @journal.user, :label => :label_updated_time_by %></p>
+
+<div class="text-diff">
+<%= simple_format_without_paragraph @diff.to_html %>
+</div>
+
+<p><%= link_to l(:button_back), issue_path(@issue), :onclick => 'history.back(); return false;' %></p>
+
+<% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
index 40ecbee..fb51c23 100644 (file)
@@ -860,6 +860,7 @@ en:
   text_are_you_sure: Are you sure ?
   text_are_you_sure_with_children: "Delete issue and all child issues?"
   text_journal_changed: "%{label} changed from %{old} to %{new}"
+  text_journal_changed_no_detail: "%{label} updated"
   text_journal_set_to: "%{label} set to %{value}"
   text_journal_deleted: "%{label} deleted (%{old})"
   text_journal_added: "%{label} %{value} added"
index 112fe5a..91a517d 100644 (file)
@@ -926,6 +926,7 @@ fr:
   error_no_tracker_in_project: "Aucun tracker n'est associé à ce projet. Vérifier la configuration du projet."
   error_no_default_issue_status: "Aucun statut de demande n'est défini par défaut. Vérifier votre configuration (Administration -> Statuts de demandes)."
   text_journal_changed: "%{label} changé de %{old} à %{new}"
+  text_journal_changed_no_detail: "%{label} mis à jour"
   text_journal_set_to: "%{label} mis à %{value}"
   text_journal_deleted: "%{label} %{old} supprimé"
   text_journal_added: "%{label} %{value} ajouté"
diff --git a/db/migrate/20110227125750_change_journal_details_values_to_text.rb b/db/migrate/20110227125750_change_journal_details_values_to_text.rb
new file mode 100644 (file)
index 0000000..2588657
--- /dev/null
@@ -0,0 +1,11 @@
+class ChangeJournalDetailsValuesToText < ActiveRecord::Migration
+  def self.up
+    change_column :journal_details, :old_value, :text
+    change_column :journal_details, :value, :text
+  end
+
+  def self.down
+    change_column :journal_details, :old_value, :string
+    change_column :journal_details, :value, :string
+  end
+end
index 7fcd764..87efc72 100644 (file)
@@ -62,7 +62,7 @@ Redmine::AccessControl.map do |map|
                                   :auto_complete => [:issues],
                                   :context_menus => [:issues],
                                   :versions => [:index, :show, :status_by],
-                                  :journals => :index,
+                                  :journals => [:index, :diff],
                                   :queries => :index,
                                   :reports => [:issue_report, :issue_report_details]}
     map.permission :add_issues, {:issues => [:new, :create, :update_form]}
index f7c76e4..911c7c8 100644 (file)
@@ -672,6 +672,13 @@ div.autocomplete ul li span.informal {
 .diff_out { background: #fcc; }
 .diff_in { background: #cfc; }
 
+.text-diff {
+padding: 1em;
+background-color:#f6f6f6;
+color:#505050;
+border: 1px solid #e4e4e4;
+}
+
 /***** Wiki *****/
 div.wiki table {
     border: 1px solid #505050;
index 046202d..5b2c651 100644 (file)
@@ -20,3 +20,10 @@ journal_details_003:
   value: "6"
   prop_key: fixed_version_id
   journal_id: 4
+journal_details_004:
+  old_value: "This word was removed and an other was"
+  property: attr
+  id: 4
+  value: "This word was and an other was added"
+  prop_key: description
+  journal_id: 3
index ff123f9..2060e9c 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2008  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -38,6 +38,19 @@ class JournalsControllerTest < ActionController::TestCase
     assert_equal 'application/atom+xml', @response.content_type
   end
   
+  def test_diff
+    get :diff, :id => 3, :detail_id => 4
+    assert_response :success
+    assert_template 'diff'
+    
+    assert_tag 'span',
+      :attributes => {:class => 'diff_out'},
+      :content => /removed/
+    assert_tag 'span',
+      :attributes => {:class => 'diff_in'},
+      :content => /added/
+  end
+  
   def test_reply_to_issue
     @request.session[:user_id] = 2
     get :new, :id => 6
index 0ecfa2e..003d513 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -621,6 +621,27 @@ class IssueTest < ActiveSupport::TestCase
     assert ActionMailer::Base.deliveries.empty?
   end
   
+  def test_journalized_description
+    i = Issue.first
+    old_description = i.description
+    new_description = "This is the new description"
+    
+    i.init_journal(User.find(2))
+    i.description = new_description
+    assert_difference 'Journal.count', 1 do
+      assert_difference 'JournalDetail.count', 1 do
+        i.save!
+      end
+    end
+    
+    detail = JournalDetail.first(:order => 'id DESC')
+    assert_equal i, detail.journal.journalized
+    assert_equal 'attr', detail.property
+    assert_equal 'description', detail.prop_key
+    assert_equal old_description, detail.old_value
+    assert_equal new_description, detail.value
+  end
+  
   def test_saving_twice_should_not_duplicate_journal_details
     i = Issue.find(:first)
     i.init_journal(User.find(2), 'Some notes')