Patch #1717 » issue_description_diff.patch
app/views/issues/diff.rhtml (revision 0) | ||
---|---|---|
1 |
<% content_for :header_tags do -%> |
|
2 |
<%= stylesheet_link_tag "scm" -%> |
|
3 |
<% end -%> |
|
4 |
|
|
5 |
<% html_title "##{@issue.id}: #{@issue.subject} - change #{@detail.id}" %> |
|
6 |
|
|
7 |
<%= l(:field_issue) %>: <%= link_to( "##{@issue.id} " + h(@issue.subject), |
|
8 |
:controller => 'issues', :action => 'show', :id => @issue) %> |
|
9 |
<p> |
|
10 |
<div><%= l(:label_diff) %>: </div> |
|
11 |
<%= render :partial => 'common/diff', :locals => {:diff => @diff, |
|
12 |
:diff_type => 'inline'} %> |
|
13 |
</p> |
|
14 |
|
|
15 |
<p> |
|
16 |
<div><a href="javascript:void()" onclick="$('old_value').toggle();"> |
|
17 |
<%= l(:label_show_old_value) %> |
|
18 |
</a></div> |
|
19 |
<div id="old_value" style="display:none;"> |
|
20 |
<%= textilizable @detail, :old_value %> |
|
21 |
</div> |
|
22 |
|
|
23 |
</p> |
|
24 |
<p> |
|
25 |
<div><a href="javascript:void()" onclick="$('new_value').toggle();"> |
|
26 |
<%= l(:label_show_new_value) %> |
|
27 |
</a></div> |
|
28 |
<div id="new_value" style="display:none;"> |
|
29 |
<%= textilizable @detail, :value %> |
|
30 |
</div> |
|
31 |
</p> |
app/controllers/issues_controller.rb (working copy) | ||
---|---|---|
22 | 22 |
before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment] |
23 | 23 |
before_filter :find_issues, :only => [:bulk_edit, :move, :destroy] |
24 | 24 |
before_filter :find_project, :only => [:new, :update_form, :preview] |
25 |
before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu] |
|
25 |
|
|
26 |
before_filter :authorize, :except => [:index, :changes, :preview, |
|
27 |
:update_form, :context_menu, :diff] |
|
28 |
|
|
26 | 29 |
before_filter :find_optional_project, :only => [:index, :changes] |
27 | 30 |
accept_key_auth :index, :changes |
28 | 31 | |
... | ... | |
360 | 363 |
render :partial => 'common/preview' |
361 | 364 |
end |
362 | 365 |
|
363 |
private |
|
366 |
#warning - relies on availability of 'diff' utility |
|
367 |
def diff |
|
368 |
@detail = JournalDetail.find(params[:id]) |
|
369 |
@issue = @detail.journal.issue |
|
370 |
Tempfile.open 'issue_description_oldval', 'tmp' do |old_val_file| |
|
371 |
old_val_file.write normalize(@detail.old_value) |
|
372 |
Tempfile.open 'issue_description_oldval', 'tmp' do |new_val_file| |
|
373 |
new_val_file.write normalize(@detail.value) |
|
374 |
old_val_file.close |
|
375 |
new_val_file.close |
|
376 |
#at this moment old_val_file and new_val_file files still exist - they |
|
377 |
# will disappear after these objects finalization |
|
378 |
@diff = `diff #{old_val_file.path} #{new_val_file.path} -U 3` |
|
379 |
end |
|
380 |
end |
|
381 |
end |
|
382 | ||
383 |
private |
|
364 | 384 |
def find_issue |
365 | 385 |
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category]) |
366 | 386 |
@project = @issue.project |
... | ... | |
427 | 447 |
end |
428 | 448 |
end |
429 | 449 |
end |
450 | ||
451 |
#Converts \n-terminated string to \r\n-teminated. At least FF on Windows |
|
452 |
# inserts \r\n everywhere, even if original text was \n-terminated (that's |
|
453 |
# how it is after Trac migration) |
|
454 |
def normalize(long_string) |
|
455 |
#we assume that if one line is \r\n\'ed, all others are too |
|
456 |
return long_string if long_string["\r\n"] |
|
457 |
long_string.split("\n").join("\r\n") |
|
458 |
end |
|
459 | ||
430 | 460 |
end |
app/helpers/issues_helper.rb (working copy) | ||
---|---|---|
75 | 75 |
when 'fixed_version_id' |
76 | 76 |
v = Version.find_by_id(detail.value) and value = v.name if detail.value |
77 | 77 |
v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value |
78 |
when 'description' |
|
79 |
return content_tag('strong', l(:field_description)) + ' ' + |
|
80 |
link_to(l(:text_journal_just_changed), |
|
81 |
:controller => 'issues', :action => 'diff', :id => detail.id) |
|
78 | 82 |
end |
79 | 83 |
when 'cf' |
80 | 84 |
custom_field = CustomField.find_by_id(detail.prop_key) |
app/models/issue.rb (working copy) | ||
---|---|---|
136 | 136 |
def before_save |
137 | 137 |
if @current_journal |
138 | 138 |
# attributes changes |
139 |
(Issue.column_names - %w(id description)).each {|c|
|
|
139 |
(Issue.column_names - ['id']).each {|c|
|
|
140 | 140 |
@current_journal.details << JournalDetail.new(:property => 'attr', |
141 | 141 |
:prop_key => c, |
142 | 142 |
:old_value => @issue_before_change.send(c), |
app/models/journal_detail.rb (working copy) | ||
---|---|---|
17 | 17 | |
18 | 18 |
class JournalDetail < ActiveRecord::Base |
19 | 19 |
belongs_to :journal |
20 |
|
|
21 |
def before_save |
|
22 |
self.value = value[0..254] if value && value.is_a?(String) |
|
23 |
self.old_value = old_value[0..254] if old_value && old_value.is_a?(String) |
|
24 |
end |
|
25 | 20 |
end |
db/migrate/096_allow_long_journal_details_values.rb (revision 0) | ||
---|---|---|
1 |
class AllowLongJournalDetailsValues < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
change_column :journal_details, :old_value, :text |
|
4 |
change_column :journal_details, :value, :text |
|
5 |
end |
|
6 |
|
|
7 |
def self.down |
|
8 |
#no need |
|
9 |
end |
|
10 |
end |
lang/en.yml (working copy) | ||
---|---|---|
521 | 521 |
label_planning: Planning |
522 | 522 |
label_incoming_emails: Incoming emails |
523 | 523 |
label_generate_key: Generate a key |
524 |
label_diff: Difference |
|
525 |
label_show_old_value: Show old value |
|
526 |
label_show_new_value: Show new value |
|
524 | 527 | |
525 | 528 |
button_login: Login |
526 | 529 |
button_submit: Submit |
... | ... | |
572 | 575 |
text_workflow_edit: Select a role and a tracker to edit the workflow |
573 | 576 |
text_are_you_sure: Are you sure ? |
574 | 577 |
text_journal_changed: changed from %s to %s |
578 |
text_journal_just_changed: changed |
|
575 | 579 |
text_journal_set_to: set to %s |
576 | 580 |
text_journal_deleted: deleted |
577 | 581 |
text_tip_task_begin_day: task beginning this day |
lang/ru.yml (working copy) | ||
---|---|---|
471 | 471 |
label_associated_revisions: Связанные редакции |
472 | 472 |
label_issues_by: Сортировать по %s |
473 | 473 |
label_display_per_page: 'На страницу: %s' |
474 |
label_diff: Различия |
|
475 |
label_show_old_value: Показать старое значение |
|
476 |
label_show_new_value: Показать новое значение |
|
474 | 477 | |
475 | 478 |
button_login: Вход |
476 | 479 |
button_submit: Принять |
... | ... | |
521 | 524 |
text_are_you_sure: Подтвердите |
522 | 525 |
text_journal_changed: параметр изменился с %s на %s |
523 | 526 |
text_journal_set_to: параметр изменился на %s |
527 |
text_journal_just_changed: параметр изменился |
|
524 | 528 |
text_journal_deleted: удалено |
525 | 529 |
text_tip_task_begin_day: дата начала задачи |
526 | 530 |
text_tip_task_end_day: дата завершения задачи |
test/fixtures/journal_details.yml (working copy) | ||
---|---|---|
13 | 13 |
value: "30" |
14 | 14 |
prop_key: done_ratio |
15 | 15 |
journal_id: 1 |
16 |
description_change: |
|
17 |
old_value: "one two three" |
|
18 |
property: attr |
|
19 |
id: 3 |
|
20 |
value: "one one two three" |
|
21 |
prop_key: description |
|
22 |
journal_id: 1 |
test/functional/issues_controller_test.rb (working copy) | ||
---|---|---|
638 | 638 |
j = issue.journals.find(:first, :order => 'created_on DESC') |
639 | 639 |
assert_equal 'attachment', j.details.first.property |
640 | 640 |
end |
641 |
|
|
642 |
def test_diff |
|
643 |
@request.session[:user_id] = 2 |
|
644 |
get :diff, :id => journal_details(:description_change).id |
|
645 |
assert_response :success |
|
646 |
end |
|
641 | 647 |
end |