From 7ae1f503f67b7857ebabed9d9ffb5c40bb7d30fd Mon Sep 17 00:00:00 2001 From: Marius BALTEANU Date: Sun, 2 Jun 2019 13:41:26 +0000 Subject: [PATCH] Mark edited journal notes as "Edited" --- app/controllers/journals_controller.rb | 4 +++- app/helpers/journals_helper.rb | 6 ++++++ app/models/journal.rb | 2 ++ app/views/issues/tabs/_history.html.erb | 1 + app/views/journals/update.js.erb | 7 +++++++ config/locales/en.yml | 2 ++ db/migrate/20190802185259_add_journal_updated_on.rb | 10 ++++++++++ db/migrate/20190802185309_add_journal_updated_by.rb | 9 +++++++++ public/stylesheets/application.css | 1 + test/fixtures/journals.yml | 6 ++++++ test/functional/issues_controller_test.rb | 12 ++++++++++++ 11 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190802185259_add_journal_updated_on.rb create mode 100644 db/migrate/20190802185309_add_journal_updated_by.rb diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb index f4d165ac3..c1c485100 100644 --- a/app/controllers/journals_controller.rb +++ b/app/controllers/journals_controller.rb @@ -89,7 +89,9 @@ class JournalsController < ApplicationController def update (render_403; return false) unless @journal.editable_by?(User.current) - @journal.safe_attributes = params[:journal] + journal_attributes = params[:journal] + journal_attributes[:updated_by] = User.current + @journal.safe_attributes = journal_attributes @journal.save @journal.destroy if @journal.details.empty? && @journal.notes.blank? call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params}) diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb index d947f8233..9d666b6a2 100644 --- a/app/helpers/journals_helper.rb +++ b/app/helpers/journals_helper.rb @@ -68,4 +68,10 @@ module JournalsHelper css_classes = journal.private_notes? ? 'badge badge-private private' : '' content_tag('span', content.html_safe, :id => "journal-#{journal.id}-private_notes", :class => css_classes) end + + def render_journal_update_info(journal) + if journal.created_on != journal.updated_on + content_tag('span', "· #{l(:label_edited)}", :title => l(:label_time_by_author, :time => format_time(journal.updated_on), :author => journal.updated_by), :class => 'update-info') + end + end end diff --git a/app/models/journal.rb b/app/models/journal.rb index e60605161..a2e927abe 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -26,6 +26,7 @@ class Journal < ActiveRecord::Base belongs_to :issue, :foreign_key => :journalized_id belongs_to :user + belongs_to :updated_by, :class_name => 'User' has_many :details, :class_name => "JournalDetail", :dependent => :delete_all, :inverse_of => :journal attr_accessor :indice @@ -61,6 +62,7 @@ class Journal < ActiveRecord::Base safe_attributes( 'private_notes', :if => lambda {|journal, user| user.allowed_to?(:set_notes_private, journal.project)}) + safe_attributes 'updated_by' # Returns a SQL condition to filter out journals with notes that are not visible to user def self.visible_notes_condition(user=User.current, options={}) diff --git a/app/views/issues/tabs/_history.html.erb b/app/views/issues/tabs/_history.html.erb index 0769f5725..4a18d6b8a 100644 --- a/app/views/issues/tabs/_history.html.erb +++ b/app/views/issues/tabs/_history.html.erb @@ -15,6 +15,7 @@ <%= avatar(journal.user) %> <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %> <%= render_private_notes_indicator(journal) %> + <%= render_journal_update_info(journal) %> <% if journal.details.any? %> diff --git a/app/views/journals/update.js.erb b/app/views/journals/update.js.erb index 47dfdebec..cb796bfa3 100644 --- a/app/views/journals/update.js.erb +++ b/app/views/journals/update.js.erb @@ -7,6 +7,13 @@ $("#journal-<%= @journal.id %>-notes").replaceWith('<%= escape_javascript(render_notes(@journal.issue, @journal, :reply_links => authorize_for('issues', 'edit'))) %>'); $("#journal-<%= @journal.id %>-notes").show(); $("#journal-<%= @journal.id %>-form").remove(); + var journal_header = $("#change-<%= @journal.id %> h4"); + var journal_updated_info = journal_header.find("span.update-info"); + if (journal_updated_info.length > 0) { + journal_updated_info.replaceWith('<%= escape_javascript(render_journal_update_info(@journal)) %>'); + } else { + journal_header.append('<%= escape_javascript(render_journal_update_info(@journal)) %>'); + } <% end %> <%= call_hook(:view_journals_update_js_bottom, { :journal => @journal }) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index efaea5252..a7c494e14 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1087,6 +1087,8 @@ en: label_display_type_board: Board label_my_bookmarks: My bookmarks label_assign_to_me: Assign to me + label_edited: Edited + label_time_by_author: "%{time} by %{author}" button_login: Login button_submit: Submit diff --git a/db/migrate/20190802185259_add_journal_updated_on.rb b/db/migrate/20190802185259_add_journal_updated_on.rb new file mode 100644 index 000000000..bf2c1b0cd --- /dev/null +++ b/db/migrate/20190802185259_add_journal_updated_on.rb @@ -0,0 +1,10 @@ +class AddJournalUpdatedOn < ActiveRecord::Migration[5.2] + def up + add_column :journals, :updated_on, :datetime, :after => :created_on + Journal.update_all('updated_on = created_on') + end + + def down + remove_column :journals, :updated_on + end +end diff --git a/db/migrate/20190802185309_add_journal_updated_by.rb b/db/migrate/20190802185309_add_journal_updated_by.rb new file mode 100644 index 000000000..e465e07d2 --- /dev/null +++ b/db/migrate/20190802185309_add_journal_updated_by.rb @@ -0,0 +1,9 @@ +class AddJournalUpdatedBy < ActiveRecord::Migration[5.2] + def up + add_column :journals, :updated_by_id, :integer, :default => nil, :after => :updated_on + end + + def down + remove_column :journals, :updated_by + end +end diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index a7512bd48..3f756a0bc 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -577,6 +577,7 @@ div.journal ul.details a, ul.revision-info a {color:#70A7CD;} div.journal ul.details a:hover, ul.revision-info a:hover {color:#D14848;} body.avatars-on div.journal {padding-left:32px;} div.journal h4 img.gravatar {margin-left:-32px;} +div.journal span.update-info {color: #666; font-size: 0.9em;} #history .tab-content { padding: 0 6px; diff --git a/test/fixtures/journals.yml b/test/fixtures/journals.yml index bc7bc91b9..e6cbd95cf 100644 --- a/test/fixtures/journals.yml +++ b/test/fixtures/journals.yml @@ -1,13 +1,16 @@ --- journals_001: created_on: <%= 2.days.ago.to_date.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "Journal notes" id: 1 journalized_type: Issue user_id: 1 journalized_id: 1 + updated_by_id: 1 journals_002: created_on: <%= 1.days.ago.to_date.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "Some notes with Redmine links: #2, r2." id: 2 journalized_type: Issue @@ -15,6 +18,7 @@ journals_002: journalized_id: 1 journals_003: created_on: <%= 1.days.ago.to_date.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2." id: 3 journalized_type: Issue @@ -22,6 +26,7 @@ journals_003: journalized_id: 2 journals_004: created_on: <%= 1.days.ago.to_date.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "A comment with a private version." id: 4 journalized_type: Issue @@ -30,6 +35,7 @@ journals_004: journals_005: id: 5 created_on: <%= 1.days.ago.to_date.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "A comment on a private issue." user_id: 2 journalized_type: Issue diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 21b43d7c9..b3bfad1f4 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -2714,6 +2714,18 @@ class IssuesControllerTest < Redmine::ControllerTest assert_select "#change-#{not_visible.id}", 0 end + def test_show_should_mark_notes_as_edited_only_for_edited_notes + get :show, :params => { + :id => 1 + } + assert_response :success + + journal = Journal.find(1) + journal_title = l(:label_time_by_author, :time => format_time(journal.updated_on), :author => journal.updated_by) + assert_select "#change-1 h4 span.update-info[title=?]", journal_title, :text => '· Edited' + assert_select "#change-2 h4 span.update-info", 0 + end + def test_show_atom get( :show, -- 2.22.0