summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Balteanu <marius.balteanu@zitec.com>2025-07-14 21:33:33 +0000
committerMarius Balteanu <marius.balteanu@zitec.com>2025-07-14 21:33:33 +0000
commite940540e2e22dbde15fe72c99358756b7dd6b841 (patch)
tree2a840aa8fbc03d9d81148fa2dd7f2363609fec3b
parent36446be97cae4b10f61b2006a72146a5f70e101d (diff)
downloadredmine-e940540e2e22dbde15fe72c99358756b7dd6b841.tar.gz
redmine-e940540e2e22dbde15fe72c99358756b7dd6b841.zip
Refactor, refresh UI and unify the structure of journals, replies and comments (#42972, #40744).
git-svn-id: https://svn.redmine.org/redmine/trunk@23887 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/assets/javascripts/application-legacy.js8
-rw-r--r--app/assets/stylesheets/application.css120
-rw-r--r--app/helpers/journals_helper.rb2
-rw-r--r--app/views/issues/show.html.erb2
-rw-r--r--app/views/issues/tabs/_changesets.html.erb44
-rw-r--r--app/views/issues/tabs/_history.html.erb53
-rw-r--r--app/views/issues/tabs/_time_entries.html.erb52
-rw-r--r--app/views/journals/update.js.erb2
-rw-r--r--app/views/messages/show.html.erb111
-rw-r--r--app/views/news/show.html.erb31
-rw-r--r--test/functional/issues_controller_test.rb6
-rw-r--r--test/functional/issues_custom_fields_visibility_test.rb4
-rw-r--r--test/integration/issues_test.rb2
-rw-r--r--test/system/issues_reply_test.rb2
14 files changed, 257 insertions, 182 deletions
diff --git a/app/assets/javascripts/application-legacy.js b/app/assets/javascripts/application-legacy.js
index f7c1de95c..1219e1ef8 100644
--- a/app/assets/javascripts/application-legacy.js
+++ b/app/assets/javascripts/application-legacy.js
@@ -426,7 +426,7 @@ function showIssueHistory(journal, url) {
tab_content.find('.journal').show();
tab_content.find('.journal:not(.has-notes)').hide();
tab_content.find('.journal .wiki').show();
- tab_content.find('.journal .contextual .journal-actions > *').show();
+ tab_content.find('.journal .journal-actions > *').show();
// always show thumbnails in notes tab
var thumbnails = tab_content.find('.journal .thumbnails');
@@ -439,15 +439,15 @@ function showIssueHistory(journal, url) {
tab_content.find('.journal:not(.has-details)').hide();
tab_content.find('.journal .wiki').hide();
tab_content.find('.journal .thumbnails').hide();
- tab_content.find('.journal .contextual .journal-actions > *').hide();
+ tab_content.find('.journal .journal-actions > *').hide();
// Show reaction button in properties tab
- tab_content.find('.journal .contextual .journal-actions .reaction-button-wrapper').show();
+ tab_content.find('.journal .journal-actions .reaction-button-wrapper').show();
break;
default:
tab_content.find('.journal').show();
tab_content.find('.journal .wiki').show();
tab_content.find('.journal .thumbnails').show();
- tab_content.find('.journal .contextual .journal-actions > *').show();
+ tab_content.find('.journal .journal-actions > *').show();
}
return false;
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 37713c984..ca7c0df10 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -306,11 +306,31 @@ div + .drdn-items {border-top:1px solid #ccc;}
}
.drdn-items>span {color:#999;}
-.contextual .drdn-content {top:18px;}
-.contextual .drdn-items {padding:2px; min-width: 160px;}
-.contextual .drdn-items>a {display: flex; padding: 5px 8px;}
-.contextual .drdn-items>a.icon:not(:has(svg)) {padding-left: 24px; background-position-x: 4px;}
-.contextual .drdn-items>a:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;}
+.contextual .drdn-content, .journal-actions .drdn-content {
+ top: 18px;
+}
+
+.contextual .drdn-items, .journal-actions .drdn-items {
+ padding: 2px;
+ min-width: 160px;
+}
+
+.contextual .drdn-items > a, .journal-actions .drdn-items > a {
+ display: flex;
+ padding: 5px 8px;
+}
+
+.contextual .drdn-items > a.icon:not(:has(svg)), .journal-actions .drdn-items > a.icon:not(:has(svg)) {
+ padding-left: 24px;
+ background-position-x: 4px;
+}
+
+.contextual .drdn-items > a:hover, .journal-actions .drdn-items > a:hover {
+ color: #2A5685;
+ border: 1px solid #628db6;
+ background-color: #eef5fd;
+ border-radius: 3px;
+}
#project-jump.drdn {width:200px;display:inline-block;}
#project-jump .drdn-trigger {
@@ -436,10 +456,6 @@ tr.message td.last_message { font-size: 93%; white-space: nowrap; }
tr.message.sticky td.subject { font-weight: bold; }
tr.message td.subject:not(:has(.icon)) { padding-left: 20px; }
-body.avatars-on #replies .message.reply {padding-left: 32px;}
-#replies .reply:target h4.reply-header {background-color:#DDEEFF;}
-#replies h4 img.gravatar {margin-left:-32px;}
-
tr.version.closed, tr.version.closed a { color: #999; }
tr.version:not(.shared) td.name { padding-left: 20px; }
tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; }
@@ -593,7 +609,6 @@ div.square {
}
.contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;}
.contextual input, .contextual select {font-size:0.9em;}
-.message .contextual, #comments .contextual { margin-top: 0; }
.splitcontent {overflow: auto; display: flex; flex-wrap: wrap;}
.splitcontentleft {flex: 1; margin-right: 5px;}
@@ -775,28 +790,8 @@ div#issue-changesets div.changeset {border-bottom: 1px solid #ddd; padding: 4px;
div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
.changeset-comments {margin-bottom:1em;}
-div.journal .contextual {margin-top: 0;}
-div.journal.private-notes .wiki {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;}
-div.journal ul.details, ul.revision-info {color:#959595; margin-bottom: 1.5em;}
-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;}
-
#update {margin-bottom: 1.4em;}
-#history .tab-content {
- padding: 0 8px;
- margin-bottom: 10px;
- border-right: 1px solid #d0d7de;
- border-bottom: 1px solid #d0d7de;
- border-left: 1px solid #d0d7de;
- border-radius: 0 0 3px 3px / 0 0 3px 3px;
- box-shadow: 0 1px 2px rgba(0,0,0,0.05);
-}
-
-#history div:target h4.note-header {background-color:#DDEEFF;}
#history p.nodata {display: none;}
/* Prevent content from being hidden behind a #sticky-issue-header when scrolling via anchor links. */
.controller-issues.action-show div.wiki a[name],
@@ -1193,7 +1188,6 @@ div.attachments span.author { font-size: 0.9em; color: #888; }
div.thumbnails {margin:0.6em;}
div.thumbnail {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
div.thumbnail img {margin: 3px; vertical-align: middle;}
-#history div.thumbnails {margin-left: 2em;}
p.other-formats { text-align: right; font-size:0.9em; color: #666; }
.other-formats span + span:before { content: "| "; }
@@ -1745,6 +1739,7 @@ div.wiki .task-list input.task-list-item-checkbox {
.handle {cursor: move;}
#my-page .list th.checkbox, #my-page .list td.checkbox {display:none;}
+
/***** Gantt chart *****/
table.gantt-table {
width: 100%;
@@ -1858,6 +1853,68 @@ td.gantt_selected_column .gantt_hdr,.gantt_selected_column_container {
.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;}
.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
+/***** User events (ex: journal, notes, replies, comments) *****/
+.journals h4.journal-header {
+ background-color: #f6f7f8;
+ border-bottom: 0;
+ padding: 8px;
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+}
+
+.journals h4.journal-header .update-info {
+ color: #666;
+ font-size: 0.9em;
+}
+
+.journals h4.journal-header .badge {
+ position: static;
+}
+
+.journals div:target h4.journal-header {
+ background-color:#DDEEFF;
+}
+
+.journals .journal-content {
+ padding-left: 8px;
+ margin-bottom: 1.2em;
+}
+
+.journals .journal .journal-content .wiki {
+ margin-left: 0.6em;
+}
+
+.journals .private-notes {
+ border-left: 2px solid #d22;
+}
+
+.journals .journal-meta, .journals .journal-actions {
+ display: inline-flex;
+ gap: 10px;
+}
+
+.journals .journal-meta .journal-link {
+ color: #555;
+}
+
+.journals .journal-actions .reaction-button-wrapper {
+ display: inline-flex;
+}
+
+.journals .journal-details, ul.revision-info {
+ color: #959595;
+ margin-bottom: 1.5em;
+}
+
+.journals .journal-details a, ul.revision-info a {
+ color: #70A7CD;
+}
+
+.journals .journal-details a:hover, ul.revision-info a:hover {
+ color: #D14848;
+}
+
/***** Badges *****/
.badge {
position:relative;
@@ -2135,7 +2192,6 @@ div.gravatar-with-child > img.gravatar:nth-child(2) {
}
h2 img.gravatar, h3 img.gravatar {margin-right: 4px;}
-h4 img.gravatar {margin: -2px 4px -4px 0;}
td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;}
#activity dt img.gravatar {margin: 0 1em 0 0;}
/* Used on 12px Gravatar img tags without the icon background */
diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb
index 19dab692c..0ddbc34b8 100644
--- a/app/helpers/journals_helper.rb
+++ b/app/helpers/journals_helper.rb
@@ -70,7 +70,7 @@ module JournalsHelper
def render_notes(issue, journal, options={})
content_tag('div', textilizable(journal, :notes),
- id: "journal-#{journal.id}-notes", class: "wiki", data: { quote_reply_target: 'content' })
+ id: "journal-#{journal.id}-notes", class: "wiki journal-note", data: { quote_reply_target: 'content' })
end
def render_private_notes_indicator(journal)
diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb
index 38ec5b376..696b8f0ec 100644
--- a/app/views/issues/show.html.erb
+++ b/app/views/issues/show.html.erb
@@ -131,7 +131,7 @@ end %>
<%= render partial: 'action_menu_edit' if User.current.wants_comments_in_reverse_order? %>
-<div id="history">
+<div id="history" class="journals">
<%= render_tabs issue_history_tabs, issue_history_default_tab %>
</div>
diff --git a/app/views/issues/tabs/_changesets.html.erb b/app/views/issues/tabs/_changesets.html.erb
index bf00dcb7b..2df4d40c2 100644
--- a/app/views/issues/tabs/_changesets.html.erb
+++ b/app/views/issues/tabs/_changesets.html.erb
@@ -1,27 +1,29 @@
<% @changesets.each do |changeset| %>
<div id="changeset-<%= changeset.id %>" class="changeset journal">
- <div class="note">
- <h4 class='note-header'>
- <%= avatar(changeset.user, :size => "24") %>
- <%= authoring changeset.committed_on, changeset.author, :label => :label_added_time_by %>
+ <h4 class="journal-header">
+ <span class="journal-info">
+ <%= avatar(changeset.user, :size => "24") %>
+ <%= authoring changeset.committed_on, changeset.author, :label => :label_added_time_by %>
+ </span>
</h4>
- <p>
- <%= "#{changeset.project.name} - " unless changeset.project == project %>
- <%= link_to_revision(changeset, changeset.repository,
- :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
- <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
- (<%= link_to(l(:label_diff),
- :controller => 'repositories',
- :action => 'diff',
- :id => changeset.project,
- :repository_id => changeset.repository.identifier_param,
- :path => "",
- :rev => changeset.identifier) %>)
- <% end %></p>
-
- <div class="wiki changeset-comments">
- <%= format_changeset_comments changeset %>
- </div>
+ <div class="journal-content">
+ <p>
+ <%= "#{changeset.project.name} - " unless changeset.project == project %>
+ <%= link_to_revision(changeset, changeset.repository,
+ :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
+ <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
+ (<%= link_to(l(:label_diff),
+ :controller => 'repositories',
+ :action => 'diff',
+ :id => changeset.project,
+ :repository_id => changeset.repository.identifier_param,
+ :path => "",
+ :rev => changeset.identifier) %>)
+ <% end %>
+ </p>
+ <div class="wiki changeset-comments">
+ <%= format_changeset_comments changeset %>
+ </div>
</div>
</div>
<%= call_hook(:view_issues_history_changeset_bottom, { :changeset => changeset }) %>
diff --git a/app/views/issues/tabs/_history.html.erb b/app/views/issues/tabs/_history.html.erb
index d2d50ee09..b416a9d37 100644
--- a/app/views/issues/tabs/_history.html.erb
+++ b/app/views/issues/tabs/_history.html.erb
@@ -7,32 +7,37 @@
<% for journal in journals %>
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>" data-controller="quote-reply">
<div id="note-<%= journal.indice %>" class="note">
- <div class="contextual">
- <span class="journal-actions"><%= render_journal_actions(issue, journal, :reply_links => reply_links) %></span>
- <a href="#note-<%= journal.indice %>" class="journal-link">#<%= journal.indice %></a>
- </div>
- <h4 class='note-header'>
- <%= avatar(journal.user) %>
- <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
- <%= render_private_notes_indicator(journal) %>
- <%= render_journal_update_info(journal) %>
- </h4>
-
- <% if journal.details.any? %>
- <ul class="details">
- <% details_to_strings(journal.visible_details).each do |string| %>
- <li><%= string %></li>
- <% end %>
- </ul>
- <% if Setting.thumbnails_enabled? && (thumbnail_attachments = journal_thumbnail_attachments(journal)).any? %>
- <div class="thumbnails">
- <% thumbnail_attachments.each do |attachment| %>
- <%= thumbnail_tag(attachment) %>
+ <h4 class="journal-header">
+ <span class="journal-info">
+ <%= avatar(journal.user) %>
+ <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
+ <%= render_private_notes_indicator(journal) %>
+ <%= render_journal_update_info(journal) %>
+ </span>
+ <span class="journal-meta">
+ <span class="journal-actions">
+ <%= render_journal_actions(issue, journal, :reply_links => reply_links) %>
+ </span>
+ <a href="#note-<%= journal.indice %>" class="journal-link">#<%= journal.indice %></a>
+ </span>
+ </h4>
+ <div class="journal-content">
+ <% if journal.details.any? %>
+ <ul class="journal-details">
+ <% details_to_strings(journal.visible_details).each do |string| %>
+ <li><%= string %></li>
+ <% end %>
+ </ul>
+ <% if Setting.thumbnails_enabled? && (thumbnail_attachments = journal_thumbnail_attachments(journal)).any? %>
+ <div class="thumbnails">
+ <% thumbnail_attachments.each do |attachment| %>
+ <%= thumbnail_tag(attachment) %>
+ <% end %>
+ </div>
+ <% end %>
<% end %>
+ <%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
</div>
- <% end %>
- <% end %>
- <%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
</div>
</div>
<%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
diff --git a/app/views/issues/tabs/_time_entries.html.erb b/app/views/issues/tabs/_time_entries.html.erb
index 4cbf5d01e..86a23d0c5 100644
--- a/app/views/issues/tabs/_time_entries.html.erb
+++ b/app/views/issues/tabs/_time_entries.html.erb
@@ -1,31 +1,33 @@
-<% for time_entry in time_entries%>
+<% for time_entry in time_entries %>
<div id="time-entry-<%= time_entry.id %>" class="time_entry journal">
- <div class="note">
- <% if time_entry.editable_by?(User.current) -%>
- <div class="contextual">
- <span class="journal-actions">
- <%= link_to sprite_icon('edit', l(:button_edit)), edit_time_entry_path(time_entry),
- :title => l(:button_edit),
- :class => 'icon-only icon-edit ' %>
- <%= link_to sprite_icon('del', l(:button_delete)), time_entry_path(time_entry),
- :data => {:confirm => l(:text_are_you_sure)},
- :method => :delete,
- :title => l(:button_delete),
- :class => 'icon-only icon-del ' %>
+ <h4 class="journal-header">
+ <span class="journal-info">
+ <%= avatar(time_entry.user, :size => "24") %>
+ <%= authoring time_entry.created_on, time_entry.user, :label => :label_added_time_by %>
</span>
- </div>
- <% end -%>
- <h4 class='note-header'>
- <%= avatar(time_entry.user, :size => "24") %>
- <%= authoring time_entry.created_on, time_entry.user, :label => :label_added_time_by %>
+ <% if time_entry.editable_by?(User.current) -%>
+ <span class="journal-meta">
+ <%= link_to sprite_icon('edit', l(:button_edit)), edit_time_entry_path(time_entry),
+ :title => l(:button_edit),
+ :class => 'icon-only icon-edit' %>
+ <%= link_to sprite_icon('del', l(:button_delete)), time_entry_path(time_entry),
+ :data => { :confirm => l(:text_are_you_sure) },
+ :method => :delete,
+ :title => l(:button_delete),
+ :class => 'icon-only icon-del' %>
+ </span>
+ <% end -%>
</h4>
- <ul class="details">
- <li>
- <strong><%= l(:label_time_entry_plural) %></strong>:
- <%= l_hours_short time_entry.hours %>
- </li>
- </ul>
- <p><%= time_entry.comments %></p>
+ <div class="journal-content">
+ <ul class="journal-details">
+ <li>
+ <strong><%= l(:label_time_entry_plural) %></strong>:
+ <%= l_hours_short time_entry.hours %>
+ </li>
+ </ul>
+ <div class="journal-note">
+ <%= time_entry.comments %>
+ </div>
</div>
</div>
<%= call_hook(:view_issues_history_time_entry_bottom, { :time_entry => time_entry }) %>
diff --git a/app/views/journals/update.js.erb b/app/views/journals/update.js.erb
index 1c7da09a1..cf6bcd28f 100644
--- a/app/views/journals/update.js.erb
+++ b/app/views/journals/update.js.erb
@@ -7,7 +7,7 @@
$("#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 %>>div.note>h4.note-header");
+ var journal_header = $("#change-<%= @journal.id %>>div.note>h4.journal-header>.journal-info");
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)) %>');
diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb
index 55209d528..e60c803b7 100644
--- a/app/views/messages/show.html.erb
+++ b/app/views/messages/show.html.erb
@@ -8,14 +8,14 @@
) if !@topic.locked? && authorize_for('messages', 'reply') %>
<%= link_to(
sprite_icon('edit', l(:button_edit)),
- {:action => 'edit', :id => @topic},
+ { :action => 'edit', :id => @topic },
:class => 'icon icon-edit'
) if @message.editable_by?(User.current) %>
<%= link_to(
sprite_icon('del', l(:button_delete)),
- {:action => 'destroy', :id => @topic},
+ { :action => 'destroy', :id => @topic },
:method => :post,
- :data => {:confirm => l(:text_are_you_sure)},
+ :data => { :confirm => l(:text_are_you_sure) },
:class => 'icon icon-del'
) if @message.destroyable_by?(User.current) %>
</div>
@@ -33,69 +33,72 @@
<%= link_to_attachments @topic, :author => false, :thumbnails => true %>
</div>
</div>
-<br />
+<br/>
<% unless @replies.empty? %>
-<div id="replies">
-<h3 class="comments icon icon-comments"><%= sprite_icon('comments', l(:label_reply_plural)) %> (<%= @reply_count %>)</h3>
-<% if !@topic.locked? && authorize_for('messages', 'reply') && @replies.size >= 3 %>
- <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content', :scroll => "message_content" %></p>
-<% end %>
-<% @replies.each do |message| %>
- <div class="message reply" id="<%= "message-#{message.id}" %>" data-controller="quote-reply">
- <div class="contextual">
- <%= reaction_button message %>
- <%= quote_reply_button(
- url: url_for(action: 'quote', id: message, format: 'js'),
- icon_only: true
- ) if !@topic.locked? && authorize_for('messages', 'reply') %>
- <%= link_to(
- sprite_icon('edit', l(:button_edit), icon_only: true),
- {:action => 'edit', :id => message},
- :title => l(:button_edit),
- :class => 'icon icon-edit'
- ) if message.editable_by?(User.current) %>
- <%= link_to(
- sprite_icon('del', l(:button_delete), icon_only: true),
- {:action => 'destroy', :id => message},
- :method => :post,
- :data => {:confirm => l(:text_are_you_sure)},
- :title => l(:button_delete),
- :class => 'icon icon-del'
- ) if message.destroyable_by?(User.current) %>
- </div>
- <h4 class='reply-header'>
- <%= avatar(message.author) %>
- <%= link_to message.subject, { :controller => 'messages', :action => 'show', :board_id => @board, :id => @topic, :r => message, :anchor => "message-#{message.id}" } %>
- -
- <%= authoring message.created_on, message.author %>
- </h4>
- <div class="wiki" data-quote-reply-target="content">
- <%= textilizable message, :content, :attachments => message.attachments %>
+ <div id="replies" class="journals">
+ <h3 class="comments icon icon-comments"><%= sprite_icon('comments', l(:label_reply_plural)) %>
+ (<%= @reply_count %>)</h3>
+ <% if !@topic.locked? && authorize_for('messages', 'reply') && @replies.size >= 3 %>
+ <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content', :scroll => "message_content" %></p>
+ <% end %>
+ <% @replies.each do |message| %>
+ <div class="message reply journal" id="<%= "message-#{message.id}" %>" data-controller="quote-reply">
+ <h4 class='reply-header journal-header'>
+ <span class="journal-info">
+ <%= avatar(message.author) %>
+ <%= link_to message.subject, { :controller => 'messages', :action => 'show', :board_id => @board, :id => @topic, :r => message, :anchor => "message-#{message.id}" } %>
+ -
+ <%= authoring message.created_on, message.author %>
+ </span>
+ <span class="journal-meta">
+ <%= reaction_button message %>
+ <%= quote_reply_button(
+ url: url_for(action: 'quote', id: message, format: 'js'),
+ icon_only: true
+ ) if !@topic.locked? && authorize_for('messages', 'reply') %>
+ <%= link_to(
+ sprite_icon('edit', l(:button_edit), icon_only: true),
+ { :action => 'edit', :id => message },
+ :title => l(:button_edit),
+ :class => 'icon icon-edit'
+ ) if message.editable_by?(User.current) %>
+ <%= link_to(
+ sprite_icon('del', l(:button_delete), icon_only: true),
+ { :action => 'destroy', :id => message },
+ :method => :post,
+ :data => { :confirm => l(:text_are_you_sure) },
+ :title => l(:button_delete),
+ :class => 'icon icon-del'
+ ) if message.destroyable_by?(User.current) %>
+ </span>
+ </h4>
+ <div class="wiki journal-content" data-quote-reply-target="content">
+ <%= textilizable message, :content, :attachments => message.attachments %>
+ </div>
+ <%= link_to_attachments message, :author => false, :thumbnails => true %>
+ </div>
+ <% end %>
</div>
- <%= link_to_attachments message, :author => false, :thumbnails => true %>
- </div>
-<% end %>
-</div>
-<span class="pagination"><%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false %></span>
+ <span class="pagination"><%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false %></span>
<% end %>
<% if !@topic.locked? && authorize_for('messages', 'reply') %>
-<p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
-<div id="reply" style="display:none;">
-<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
- <%= render :partial => 'form', :locals => {:f => f, :replying => true} %>
- <%= submit_tag l(:button_submit) %>
-<% end %>
-</div>
+ <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
+ <div id="reply" style="display:none;">
+ <%= form_for @reply, :as => :reply, :url => { :action => 'reply', :id => @topic }, :html => { :multipart => true, :id => 'message-form' } do |f| %>
+ <%= render :partial => 'form', :locals => { :f => f, :replying => true } %>
+ <%= submit_tag l(:button_submit) %>
+ <% end %>
+ </div>
<% end %>
<% html_title @topic.subject %>
<% content_for :sidebar do %>
<% if User.current.allowed_to?(:add_message_watchers, @project) ||
- (@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %>
+ (@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %>
<div id="watchers">
- <%= render :partial => 'watchers/watchers', :locals => {:watched => @topic} %>
+ <%= render :partial => 'watchers/watchers', :locals => { :watched => @topic } %>
</div>
<% end %>
<% end %>
diff --git a/app/views/news/show.html.erb b/app/views/news/show.html.erb
index 601f12072..f80af8f18 100644
--- a/app/views/news/show.html.erb
+++ b/app/views/news/show.html.erb
@@ -35,23 +35,30 @@
</div>
<br />
-<div id="comments" style="margin-bottom:16px;">
+<div id="comments" class="journals">
<h3 class="comments"><%= l(:label_comment_plural) %></h3>
<% if @news.commentable? && @comments.size >= 3 %>
<p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments", :scroll => "comment_comments" %></p>
<% end %>
<% @comments.each do |comment| %>
- <% next if comment.new_record? %>
- <div class="contextual">
- <%= reaction_button comment %>
- <%= link_to_if_authorized sprite_icon('del', l(:button_delete)), { :controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
- :data => {:confirm => l(:text_are_you_sure)}, :method => :delete,
- :title => l(:button_delete),
- :class => 'icon-only icon-del' %>
- </div>
- <h4><%= avatar(comment.author) %><%= authoring comment.created_on, comment.author %></h4>
- <div class="wiki">
- <%= textilizable(comment.comments) %>
+ <div class="message reply journal-entry" id="<%= "message-#{comment.id}" %>">
+ <% next if comment.new_record? %>
+ <h4 class="reply-header journal-header">
+ <span class="journal-info">
+ <%= avatar(comment.author) %>
+ <%= authoring comment.created_on, comment.author %>
+ </span>
+ <span class="journal-meta">
+ <%= reaction_button comment %>
+ <%= link_to_if_authorized sprite_icon('del', l(:button_delete)), { :controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
+ :data => {:confirm => l(:text_are_you_sure)}, :method => :delete,
+ :title => l(:button_delete),
+ :class => 'icon-only icon-del' %>
+ </span>
+ </h4>
+ <div class="wiki journal-content">
+ <%= textilizable(comment.comments) %>
+ </div>
</div>
<% end if @comments.any? %>
</div>
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index 48304c868..d19c09f33 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -2485,7 +2485,7 @@ class IssuesControllerTest < Redmine::ControllerTest
end
assert_select 'div#tab-content-history' do
assert_select 'div[id=?]', "change-#{Issue.find(1).journals.last.id}" do
- assert_select 'ul.details', :text => "Subtask ##{issue.id} added"
+ assert_select 'ul.journal-details', :text => "Subtask ##{issue.id} added"
end
end
end
@@ -3305,7 +3305,7 @@ class IssuesControllerTest < Redmine::ControllerTest
assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
- assert_select 'ul[class=?]', 'details', :text => /1.00 h/
+ assert_select 'ul[class=?]', 'journal-details', :text => /1.00 h/
end
end
@@ -8697,7 +8697,7 @@ class IssuesControllerTest < Redmine::ControllerTest
assert_select 'div#tab-content-history' do
assert_select 'div[id=?]', "change-#{parent.journals.last.id}" do
- assert_select 'ul.details', :text => "Subtask deleted (##{child.id})"
+ assert_select 'ul.journal-details', :text => "Subtask deleted (##{child.id})"
end
end
end
diff --git a/test/functional/issues_custom_fields_visibility_test.rb b/test/functional/issues_custom_fields_visibility_test.rb
index 3955ef861..6bcf2ad4f 100644
--- a/test/functional/issues_custom_fields_visibility_test.rb
+++ b/test/functional/issues_custom_fields_visibility_test.rb
@@ -101,9 +101,9 @@ class IssuesCustomFieldsVisibilityTest < Redmine::ControllerTest
get(:show, :params => {:id => @issue.id})
@fields.each_with_index do |field, i|
if fields.include?(field)
- assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
+ assert_select 'ul.journal-details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
else
- assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
+ assert_select 'ul.journal-details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
end
end
end
diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb
index ac8d432f1..d0763091e 100644
--- a/test/integration/issues_test.rb
+++ b/test/integration/issues_test.rb
@@ -355,7 +355,7 @@ class IssuesTest < Redmine::IntegrationTest
end
# Issue view
follow_redirect!
- assert_select 'ul.details li', :text => "Tester changed from #{tester} to #{new_tester}"
+ assert_select 'ul.journal-details li', :text => "Tester changed from #{tester} to #{new_tester}"
end
end
diff --git a/test/system/issues_reply_test.rb b/test/system/issues_reply_test.rb
index 86cd21f16..76ed485a5 100644
--- a/test/system/issues_reply_test.rb
+++ b/test/system/issues_reply_test.rb
@@ -93,7 +93,7 @@ class IssuesReplyTest < ApplicationSystemTestCase
# Select the entire details of the note#1 and the part of the note#1's text.
page.execute_script <<-JS
const range = document.createRange();
- range.setStartBefore(document.querySelector('#change-1 .details'));
+ range.setStartBefore(document.querySelector('#change-1 .journal-details'));
// Select only the text "Journal" from the text "Journal notes" in the note-1.
range.setEnd(document.querySelector('#change-1 .wiki > p').childNodes[0], 7);