Project

General

Profile

Patch #42972 » 0001-Unify-the-look-and-feel-of-issue-notes-news-replies-.patch

Marius BĂLTEANU, 2025-07-07 23:28

View differences:

app/assets/javascripts/application-legacy.js
426 426
      tab_content.find('.journal').show();
427 427
      tab_content.find('.journal:not(.has-notes)').hide();
428 428
      tab_content.find('.journal .wiki').show();
429
      tab_content.find('.journal .contextual .journal-actions > *').show();
429
      tab_content.find('.journal .journal-actions > *').show();
430 430

  
431 431
      // always show thumbnails in notes tab
432 432
      var thumbnails = tab_content.find('.journal .thumbnails');
......
439 439
      tab_content.find('.journal:not(.has-details)').hide();
440 440
      tab_content.find('.journal .wiki').hide();
441 441
      tab_content.find('.journal .thumbnails').hide();
442
      tab_content.find('.journal .contextual .journal-actions > *').hide();
442
      tab_content.find('.journal .journal-actions > *').hide();
443 443
      // Show reaction button in properties tab
444
      tab_content.find('.journal .contextual .journal-actions .reaction-button-wrapper').show();
444
      tab_content.find('.journal .journal-actions .reaction-button-wrapper').show();
445 445
      break;
446 446
    default:
447 447
      tab_content.find('.journal').show();
448 448
      tab_content.find('.journal .wiki').show();
449 449
      tab_content.find('.journal .thumbnails').show();
450
      tab_content.find('.journal .contextual .journal-actions > *').show();
450
      tab_content.find('.journal .journal-actions > *').show();
451 451
  }
452 452

  
453 453
  return false;
app/assets/stylesheets/application.css
306 306
}
307 307
.drdn-items>span {color:#999;}
308 308

  
309
.contextual .drdn-content {top:18px;}
310
.contextual .drdn-items {padding:2px; min-width: 160px;}
311
.contextual .drdn-items>a {display: flex; padding: 5px 8px;}
312
.contextual .drdn-items>a.icon:not(:has(svg)) {padding-left: 24px; background-position-x: 4px;}
313
.contextual .drdn-items>a:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;}
309
.contextual .drdn-content, .journal-actions .drdn-content {
310
  top: 18px;
311
}
312

  
313
.contextual .drdn-items, .journal-actions .drdn-items {
314
  padding: 2px;
315
  min-width: 160px;
316
}
317

  
318
.contextual .drdn-items > a, .journal-actions .drdn-items > a {
319
  display: flex;
320
  padding: 5px 8px;
321
}
322

  
323
.contextual .drdn-items > a.icon:not(:has(svg)), .journal-actions .drdn-items > a.icon:not(:has(svg)) {
324
  padding-left: 24px;
325
  background-position-x: 4px;
326
}
327

  
328
.contextual .drdn-items > a:hover, .journal-actions .drdn-items > a:hover {
329
  color: #2A5685;
330
  border: 1px solid #628db6;
331
  background-color: #eef5fd;
332
  border-radius: 3px;
333
}
314 334

  
315 335
#project-jump.drdn {width:200px;display:inline-block;}
316 336
#project-jump .drdn-trigger {
......
436 456
tr.message.sticky td.subject { font-weight: bold; }
437 457
tr.message td.subject:not(:has(.icon)) { padding-left: 20px; }
438 458

  
439
body.avatars-on #replies .message.reply {padding-left: 32px;}
440
#replies .reply:target h4.reply-header {background-color:#DDEEFF;}
441
#replies h4 img.gravatar {margin-left:-32px;}
442

  
443 459
tr.version.closed, tr.version.closed a { color: #999; }
444 460
tr.version:not(.shared) td.name { padding-left: 20px; }
445 461
tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; }
......
593 609
}
594 610
.contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;}
595 611
.contextual input, .contextual select {font-size:0.9em;}
596
.message .contextual, #comments .contextual { margin-top: 0; }
597 612

  
598 613
.splitcontent {overflow: auto; display: flex; flex-wrap: wrap;}
599 614
.splitcontentleft {flex: 1; margin-right: 5px;}
......
775 790
div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
776 791
.changeset-comments {margin-bottom:1em;}
777 792

  
778
div.journal .contextual {margin-top: 0;}
779
div.journal.private-notes .wiki {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;}
780
div.journal ul.details, ul.revision-info {color:#959595; margin-bottom: 1.5em;}
781
div.journal ul.details a, ul.revision-info a {color:#70A7CD;}
782
div.journal ul.details a:hover, ul.revision-info a:hover {color:#D14848;}
783
body.avatars-on div.journal {padding-left:32px;}
784
div.journal h4 img.gravatar {margin-left:-32px;}
785
div.journal span.update-info {color: #666; font-size: 0.9em;}
786

  
787 793
#update {margin-bottom: 1.4em;}
788 794

  
789
#history .tab-content {
790
  padding: 0 8px;
791
  margin-bottom: 10px;
792
  border-right: 1px solid #d0d7de;
793
  border-bottom: 1px solid #d0d7de;
794
  border-left: 1px solid #d0d7de;
795
  border-radius: 0 0 3px 3px / 0 0 3px 3px;
796
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
797
}
798

  
799
#history div:target h4.note-header {background-color:#DDEEFF;}
800 795
#history p.nodata {display: none;}
801 796
/* Prevent content from being hidden behind a #sticky-issue-header when scrolling via anchor links. */
802 797
.controller-issues.action-show div.wiki a[name],
......
1193 1188
div.thumbnails {margin:0.6em;}
1194 1189
div.thumbnail {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
1195 1190
div.thumbnail img {margin: 3px; vertical-align: middle;}
1196
#history div.thumbnails {margin-left: 2em;}
1197 1191

  
1198 1192
p.other-formats { text-align: right; font-size:0.9em; color: #666; }
1199 1193
.other-formats span + span:before { content: "| "; }
......
1745 1739
.handle {cursor: move;}
1746 1740

  
1747 1741
#my-page .list th.checkbox, #my-page .list td.checkbox {display:none;}
1742

  
1748 1743
/***** Gantt chart *****/
1749 1744
table.gantt-table {
1750 1745
  width: 100%;
......
1858 1853
.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;}
1859 1854
.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
1860 1855

  
1856
/***** User events (ex: journal, notes, replies, comments) *****/
1857
.journals h4.journal-header {
1858
  background-color: #f6f7f8;
1859
  border-bottom: 0;
1860
  padding: 8px;
1861
  align-items: center;
1862
  display: flex;
1863
  justify-content: space-between;
1864
}
1865

  
1866
.journals h4.journal-header .update-info {
1867
  color: #666;
1868
  font-size: 0.9em;
1869
}
1870

  
1871
.journals h4.journal-header .badge {
1872
  position: static;
1873
}
1874

  
1875
.journals div:target h4.journal-header {
1876
  background-color:#DDEEFF;
1877
}
1878

  
1879
.journals .journal-content {
1880
  padding-left: 8px;
1881
  margin-bottom: 1.2em;
1882
}
1883

  
1884
.journals .journal .journal-content .wiki {
1885
  margin-left: 0.6em;
1886
}
1887

  
1888
.journals .private-notes  {
1889
  border-left: 2px solid #d22;
1890
}
1891

  
1892
.journals .journal-meta, .journals .journal-actions  {
1893
  display: inline-flex;
1894
  gap: 10px;
1895
}
1896

  
1897
.journals .journal-meta .journal-link {
1898
  color: #555;
1899
}
1900

  
1901
.journals .journal-actions .reaction-button-wrapper {
1902
  display: inline-flex;
1903
}
1904

  
1905
.journals .journal-details, ul.revision-info {
1906
  color: #959595;
1907
  margin-bottom: 1.5em;
1908
}
1909

  
1910
.journals .journal-details a, ul.revision-info a {
1911
  color: #70A7CD;
1912
}
1913

  
1914
.journals .journal-details a:hover, ul.revision-info a:hover {
1915
  color: #D14848;
1916
}
1917

  
1861 1918
/***** Badges *****/
1862 1919
.badge {
1863 1920
  position:relative;
......
2135 2192
}
2136 2193

  
2137 2194
h2 img.gravatar, h3 img.gravatar {margin-right: 4px;}
2138
h4 img.gravatar {margin: -2px 4px -4px 0;}
2139 2195
td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;}
2140 2196
#activity dt img.gravatar {margin: 0 1em 0 0;}
2141 2197
/* Used on 12px Gravatar img tags without the icon background */
app/helpers/journals_helper.rb
70 70

  
71 71
  def render_notes(issue, journal, options={})
72 72
    content_tag('div', textilizable(journal, :notes),
73
      id: "journal-#{journal.id}-notes", class: "wiki", data: { quote_reply_target: 'content' })
73
      id: "journal-#{journal.id}-notes", class: "wiki journal-note", data: { quote_reply_target: 'content' })
74 74
  end
75 75

  
76 76
  def render_private_notes_indicator(journal)
app/views/issues/show.html.erb
131 131

  
132 132
<%= render partial: 'action_menu_edit' if User.current.wants_comments_in_reverse_order? %>
133 133

  
134
<div id="history">
134
<div id="history" class="journals">
135 135
<%= render_tabs issue_history_tabs, issue_history_default_tab %>
136 136
</div>
137 137

  
app/views/issues/tabs/_changesets.html.erb
1 1
<% @changesets.each do |changeset| %>
2 2
  <div id="changeset-<%= changeset.id %>" class="changeset journal">
3
    <div class="note">
4
    <h4 class='note-header'>
5
      <%= avatar(changeset.user, :size => "24") %>
6
      <%= authoring changeset.committed_on, changeset.author, :label => :label_added_time_by %>
3
    <h4 class='journal-header'>
4
        <span class="journal-info">
5
          <%= avatar(changeset.user, :size => "24") %>
6
          <%= authoring changeset.committed_on, changeset.author, :label => :label_added_time_by %>
7
        </span>
7 8
    </h4>
8
    <p>
9
    <%= "#{changeset.project.name} - " unless changeset.project == project %>
10
    <%= link_to_revision(changeset, changeset.repository,
11
                        :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
12
    <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
13
    (<%= link_to(l(:label_diff),
14
           :controller => 'repositories',
15
           :action => 'diff',
16
           :id     => changeset.project,
17
           :repository_id => changeset.repository.identifier_param,
18
           :path   => "",
19
           :rev    => changeset.identifier) %>)
20
    <% end %></p>
21

  
22
    <div class="wiki changeset-comments">
23
      <%= format_changeset_comments changeset %>
24
    </div>
9
    <div class="journal-content">
10
      <p>
11
        <%= "#{changeset.project.name} - " unless changeset.project == project %>
12
        <%= link_to_revision(changeset, changeset.repository,
13
                             :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
14
        <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
15
          (<%= link_to(l(:label_diff),
16
                       :controller => 'repositories',
17
                       :action => 'diff',
18
                       :id => changeset.project,
19
                       :repository_id => changeset.repository.identifier_param,
20
                       :path => "",
21
                       :rev => changeset.identifier) %>)
22
        <% end %>
23
      </p>
24
      <div class="wiki changeset-comments">
25
        <%= format_changeset_comments changeset %>
26
      </div>
25 27
    </div>
26 28
  </div>
27 29
  <%= call_hook(:view_issues_history_changeset_bottom, { :changeset => changeset }) %>
app/views/issues/tabs/_history.html.erb
7 7
<% for journal in journals %>
8 8
  <div id="change-<%= journal.id %>" class="<%= journal.css_classes %>" data-controller="quote-reply">
9 9
    <div id="note-<%= journal.indice %>" class="note">
10
    <div class="contextual">
11
      <span class="journal-actions"><%= render_journal_actions(issue, journal, :reply_links => reply_links) %></span>
12
      <a href="#note-<%= journal.indice %>" class="journal-link">#<%= journal.indice %></a>
13
    </div>
14
    <h4 class='note-header'>
15
      <%= avatar(journal.user) %>
16
      <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
17
      <%= render_private_notes_indicator(journal) %>
18
      <%= render_journal_update_info(journal) %>
19
    </h4>
20

  
21
    <% if journal.details.any? %>
22
    <ul class="details">
23
      <% details_to_strings(journal.visible_details).each do |string| %>
24
       <li><%= string %></li>
25
      <% end %>
26
    </ul>
27
    <% if Setting.thumbnails_enabled? && (thumbnail_attachments = journal_thumbnail_attachments(journal)).any? %>
28
      <div class="thumbnails">
29
        <% thumbnail_attachments.each do |attachment| %>
30
          <%= thumbnail_tag(attachment) %>
10
      <h4 class='journal-header'>
11
        <span class="journal-info">
12
          <%= avatar(journal.user) %>
13
          <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
14
          <%= render_private_notes_indicator(journal) %>
15
          <%= render_journal_update_info(journal) %>
16
        </span>
17
        <span class="journal-meta">
18
          <span class="journal-actions">
19
            <%= render_journal_actions(issue, journal, :reply_links => reply_links) %>
20
          </span>
21
          <a href="#note-<%= journal.indice %>" class="journal-link">#<%= journal.indice %></a>
22
        </span>
23
      </h4>
24
      <div class="journal-content">
25
        <% if journal.details.any? %>
26
          <ul class="journal-details">
27
            <% details_to_strings(journal.visible_details).each do |string| %>
28
              <li><%= string %></li>
29
            <% end %>
30
          </ul>
31
          <% if Setting.thumbnails_enabled? && (thumbnail_attachments = journal_thumbnail_attachments(journal)).any? %>
32
            <div class="thumbnails">
33
              <% thumbnail_attachments.each do |attachment| %>
34
                <%= thumbnail_tag(attachment) %>
35
              <% end %>
36
            </div>
37
          <% end %>
31 38
        <% end %>
39
        <%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
32 40
      </div>
33
    <% end %>
34
    <% end %>
35
    <%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
36 41
    </div>
37 42
  </div>
38 43
  <%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
app/views/issues/tabs/_time_entries.html.erb
1
<% for time_entry in time_entries%>
1
<% for time_entry in time_entries %>
2 2
  <div id="time-entry-<%= time_entry.id %>" class="time_entry journal">
3
    <div class="note">
4
    <% if time_entry.editable_by?(User.current) -%>
5
      <div class="contextual">
6
        <span class="journal-actions">
7
        <%= link_to sprite_icon('edit', l(:button_edit)), edit_time_entry_path(time_entry),
8
                    :title => l(:button_edit),
9
                    :class => 'icon-only icon-edit ' %>
10
        <%= link_to sprite_icon('del', l(:button_delete)), time_entry_path(time_entry),
11
                    :data => {:confirm => l(:text_are_you_sure)},
12
                    :method => :delete,
13
                    :title => l(:button_delete),
14
                    :class => 'icon-only icon-del ' %>
3
    <h4 class='journal-header'>
4
        <span class="journal-info">
5
          <%= avatar(time_entry.user, :size => "24") %>
6
          <%= authoring time_entry.created_on, time_entry.user, :label => :label_added_time_by %>
15 7
        </span>
16
      </div>
17
    <% end -%>
18
    <h4 class='note-header'>
19
      <%= avatar(time_entry.user, :size => "24") %>
20
      <%= authoring time_entry.created_on, time_entry.user, :label => :label_added_time_by %>
8
      <% if time_entry.editable_by?(User.current) -%>
9
          <span class="journal-meta">
10
            <%= link_to sprite_icon('edit', l(:button_edit)), edit_time_entry_path(time_entry),
11
                        :title => l(:button_edit),
12
                        :class => 'icon-only icon-edit' %>
13
            <%= link_to sprite_icon('del', l(:button_delete)), time_entry_path(time_entry),
14
                        :data => { :confirm => l(:text_are_you_sure) },
15
                        :method => :delete,
16
                        :title => l(:button_delete),
17
                        :class => 'icon-only icon-del' %>
18
          </span>
19
      <% end -%>
21 20
    </h4>
22
    <ul class="details">
23
      <li>
24
        <strong><%= l(:label_time_entry_plural) %></strong>:
25
        <%= l_hours_short time_entry.hours %>
26
      </li>
27
    </ul>
28
    <p><%= time_entry.comments %></p>
21
    <div class="journal-content">
22
      <ul class="journal-details">
23
        <li>
24
          <strong><%= l(:label_time_entry_plural) %></strong>:
25
          <%= l_hours_short time_entry.hours %>
26
        </li>
27
      </ul>
28
      <div class="journal-note">
29
        <%= time_entry.comments %>
30
      </div>
29 31
    </div>
30 32
  </div>
31 33
  <%= call_hook(:view_issues_history_time_entry_bottom, { :time_entry => time_entry }) %>
app/views/journals/update.js.erb
7 7
  $("#journal-<%= @journal.id %>-notes").replaceWith('<%= escape_javascript(render_notes(@journal.issue, @journal, :reply_links => authorize_for('issues', 'edit'))) %>');
8 8
  $("#journal-<%= @journal.id %>-notes").show();
9 9
  $("#journal-<%= @journal.id %>-form").remove();
10
  var journal_header = $("#change-<%= @journal.id %>>div.note>h4.note-header");
10
  var journal_header = $("#change-<%= @journal.id %>>div.note>h4.journal-header>.journal-info");
11 11
  var journal_updated_info = journal_header.find("span.update-info");
12 12
  if (journal_updated_info.length > 0) {
13 13
    journal_updated_info.replaceWith('<%= escape_javascript(render_journal_update_info(@journal)) %>');
app/views/messages/show.html.erb
8 8
        ) if !@topic.locked? && authorize_for('messages', 'reply') %>
9 9
    <%= link_to(
10 10
          sprite_icon('edit', l(:button_edit)),
11
          {:action => 'edit', :id => @topic},
11
          { :action => 'edit', :id => @topic },
12 12
          :class => 'icon icon-edit'
13 13
        ) if @message.editable_by?(User.current) %>
14 14
    <%= link_to(
15 15
          sprite_icon('del', l(:button_delete)),
16
          {:action => 'destroy', :id => @topic},
16
          { :action => 'destroy', :id => @topic },
17 17
          :method => :post,
18
          :data => {:confirm => l(:text_are_you_sure)},
18
          :data => { :confirm => l(:text_are_you_sure) },
19 19
          :class => 'icon icon-del'
20 20
        ) if @message.destroyable_by?(User.current) %>
21 21
  </div>
......
33 33
    <%= link_to_attachments @topic, :author => false, :thumbnails => true %>
34 34
  </div>
35 35
</div>
36
<br />
36
<br/>
37 37

  
38 38
<% unless @replies.empty? %>
39
<div id="replies">
40
<h3 class="comments icon icon-comments"><%= sprite_icon('comments', l(:label_reply_plural)) %> (<%= @reply_count %>)</h3>
41
<% if !@topic.locked? && authorize_for('messages', 'reply') && @replies.size >= 3 %>
42
  <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content', :scroll => "message_content" %></p>
43
<% end %>
44
<% @replies.each do |message| %>
45
  <div class="message reply" id="<%= "message-#{message.id}" %>" data-controller="quote-reply">
46
    <div class="contextual">
47
      <%= reaction_button message %>
48
      <%= quote_reply_button(
49
            url: url_for(action: 'quote', id: message, format: 'js'),
50
            icon_only: true
51
          ) if !@topic.locked? && authorize_for('messages', 'reply') %>
52
      <%= link_to(
53
            sprite_icon('edit', l(:button_edit), icon_only: true),
54
            {:action => 'edit', :id => message},
55
            :title => l(:button_edit),
56
            :class => 'icon icon-edit'
57
          ) if message.editable_by?(User.current) %>
58
      <%= link_to(
59
            sprite_icon('del', l(:button_delete), icon_only: true),
60
            {:action => 'destroy', :id => message},
61
            :method => :post,
62
            :data => {:confirm => l(:text_are_you_sure)},
63
            :title => l(:button_delete),
64
            :class => 'icon icon-del'
65
          ) if message.destroyable_by?(User.current) %>
66
    </div>
67
  <h4 class='reply-header'>
68
    <%= avatar(message.author) %>
69
    <%= link_to message.subject, { :controller => 'messages', :action => 'show', :board_id => @board, :id => @topic, :r => message, :anchor => "message-#{message.id}" } %>
70
    -
71
    <%= authoring message.created_on, message.author %>
72
  </h4>
73
  <div class="wiki" data-quote-reply-target="content">
74
    <%= textilizable message, :content, :attachments => message.attachments %>
39
  <div id="replies" class="journals">
40
    <h3 class="comments icon icon-comments"><%= sprite_icon('comments', l(:label_reply_plural)) %>
41
      (<%= @reply_count %>)</h3>
42
    <% if !@topic.locked? && authorize_for('messages', 'reply') && @replies.size >= 3 %>
43
      <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content', :scroll => "message_content" %></p>
44
    <% end %>
45
    <% @replies.each do |message| %>
46
      <div class="message reply journal" id="<%= "message-#{message.id}" %>" data-controller="quote-reply">
47
        <h4 class='reply-header journal-header'>
48
    <span class="journal-info">
49
      <%= avatar(message.author) %>
50
      <%= link_to message.subject, { :controller => 'messages', :action => 'show', :board_id => @board, :id => @topic, :r => message, :anchor => "message-#{message.id}" } %>
51
      -
52
      <%= authoring message.created_on, message.author %>
53
    </span>
54
          <span class="journal-meta">
55
            <%= reaction_button message %>
56
            <%= quote_reply_button(
57
                  url: url_for(action: 'quote', id: message, format: 'js'),
58
                  icon_only: true
59
                ) if !@topic.locked? && authorize_for('messages', 'reply') %>
60
            <%= link_to(
61
                  sprite_icon('edit', l(:button_edit), icon_only: true),
62
                  { :action => 'edit', :id => message },
63
                  :title => l(:button_edit),
64
                  :class => 'icon icon-edit'
65
                ) if message.editable_by?(User.current) %>
66
            <%= link_to(
67
                  sprite_icon('del', l(:button_delete), icon_only: true),
68
                  { :action => 'destroy', :id => message },
69
                  :method => :post,
70
                  :data => { :confirm => l(:text_are_you_sure) },
71
                  :title => l(:button_delete),
72
                  :class => 'icon icon-del'
73
                ) if message.destroyable_by?(User.current) %>
74
          </span>
75
        </h4>
76
        <div class="wiki journal-content" data-quote-reply-target="content">
77
          <%= textilizable message, :content, :attachments => message.attachments %>
78
        </div>
79
        <%= link_to_attachments message, :author => false, :thumbnails => true %>
80
      </div>
81
    <% end %>
75 82
  </div>
76
  <%= link_to_attachments message, :author => false, :thumbnails => true %>
77
  </div>
78
<% end %>
79
</div>
80
<span class="pagination"><%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false %></span>
83
  <span class="pagination"><%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false %></span>
81 84
<% end %>
82 85

  
83 86
<% if !@topic.locked? && authorize_for('messages', 'reply') %>
84
<p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
85
<div id="reply" style="display:none;">
86
<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
87
  <%= render :partial => 'form', :locals => {:f => f, :replying => true} %>
88
  <%= submit_tag l(:button_submit) %>
89
<% end %>
90
</div>
87
  <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
88
  <div id="reply" style="display:none;">
89
    <%= form_for @reply, :as => :reply, :url => { :action => 'reply', :id => @topic }, :html => { :multipart => true, :id => 'message-form' } do |f| %>
90
      <%= render :partial => 'form', :locals => { :f => f, :replying => true } %>
91
      <%= submit_tag l(:button_submit) %>
92
    <% end %>
93
  </div>
91 94
<% end %>
92 95

  
93 96
<% html_title @topic.subject %>
94 97
<% content_for :sidebar do %>
95 98
  <% if User.current.allowed_to?(:add_message_watchers, @project) ||
96
    (@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %>
99
        (@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %>
97 100
    <div id="watchers">
98
      <%= render :partial => 'watchers/watchers', :locals => {:watched => @topic} %>
101
      <%= render :partial => 'watchers/watchers', :locals => { :watched => @topic } %>
99 102
    </div>
100 103
  <% end %>
101 104
<% end %>
app/views/news/show.html.erb
35 35
</div>
36 36
<br />
37 37

  
38
<div id="comments" style="margin-bottom:16px;">
39
<h3 class="comments"><%= l(:label_comment_plural) %></h3>
38
<div id="comments" class="journals">
39
<h3 class="comments journal-header"><%= l(:label_comment_plural) %></h3>
40 40
<% if @news.commentable? && @comments.size >= 3 %>
41 41
  <p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments", :scroll => "comment_comments" %></p>
42 42
<% end %>
43 43
<% @comments.each do |comment| %>
44
    <% next if comment.new_record? %>
45
    <div class="contextual">
46
    <%= reaction_button comment %>
47
    <%= link_to_if_authorized sprite_icon('del', l(:button_delete)), { :controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
48
                              :data => {:confirm => l(:text_are_you_sure)}, :method => :delete,
49
                              :title => l(:button_delete),
50
                              :class => 'icon-only icon-del' %>
51
    </div>
52
    <h4><%= avatar(comment.author) %><%= authoring comment.created_on, comment.author %></h4>
53
    <div class="wiki">
54
    <%= textilizable(comment.comments) %>
44
    <div class="message reply journal-entry" id="<%= "message-#{comment.id}" %>">
45
      <% next if comment.new_record? %>
46
      <h4 class="reply-header journal-header">
47
        <span class="journal-info">
48
          <%= avatar(comment.author) %>
49
          <%= authoring comment.created_on, comment.author %>
50
        </span>
51
        <span class="journal-meta">
52
          <%= reaction_button comment %>
53
          <%= link_to_if_authorized sprite_icon('del', l(:button_delete)), { :controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
54
                                    :data => {:confirm => l(:text_are_you_sure)}, :method => :delete,
55
                                    :title => l(:button_delete),
56
                                    :class => 'icon-only icon-del' %>
57
        </span>
58
      </h4>
59
      <div class="wiki journal-content">
60
        <%= textilizable(comment.comments) %>
61
      </div>
55 62
    </div>
56 63
<% end if @comments.any? %>
57 64
</div>
test/functional/issues_controller_test.rb
2485 2485
    end
2486 2486
    assert_select 'div#tab-content-history' do
2487 2487
      assert_select 'div[id=?]', "change-#{Issue.find(1).journals.last.id}" do
2488
        assert_select 'ul.details', :text => "Subtask ##{issue.id} added"
2488
        assert_select 'ul.journal-details', :text => "Subtask ##{issue.id} added"
2489 2489
      end
2490 2490
    end
2491 2491
  end
......
3305 3305
      assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
3306 3306
      assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
3307 3307

  
3308
      assert_select 'ul[class=?]', 'details', :text => /1.00 h/
3308
      assert_select 'ul[class=?]', 'journal-details', :text => /1.00 h/
3309 3309
    end
3310 3310
  end
3311 3311

  
......
8697 8697

  
8698 8698
    assert_select 'div#tab-content-history' do
8699 8699
      assert_select 'div[id=?]', "change-#{parent.journals.last.id}" do
8700
        assert_select 'ul.details', :text => "Subtask deleted (##{child.id})"
8700
        assert_select 'ul.journal-details', :text => "Subtask deleted (##{child.id})"
8701 8701
      end
8702 8702
    end
8703 8703
  end
test/functional/issues_custom_fields_visibility_test.rb
101 101
      get(:show, :params => {:id => @issue.id})
102 102
      @fields.each_with_index do |field, i|
103 103
        if fields.include?(field)
104
          assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
104
          assert_select 'ul.journal-details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
105 105
        else
106
          assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
106
          assert_select 'ul.journal-details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
107 107
        end
108 108
      end
109 109
    end
test/integration/issues_test.rb
355 355
      end
356 356
      # Issue view
357 357
      follow_redirect!
358
      assert_select 'ul.details li', :text => "Tester changed from #{tester} to #{new_tester}"
358
      assert_select 'ul.journal-details li', :text => "Tester changed from #{tester} to #{new_tester}"
359 359
    end
360 360
  end
361 361

  
test/system/issues_reply_test.rb
93 93
      # Select the entire details of the note#1 and the part of the note#1's text.
94 94
      page.execute_script <<-JS
95 95
        const range = document.createRange();
96
        range.setStartBefore(document.querySelector('#change-1 .details'));
96
        range.setStartBefore(document.querySelector('#change-1 .journal-details'));
97 97
        // Select only the text "Journal" from the text "Journal notes" in the note-1.
98 98
        range.setEnd(document.querySelector('#change-1 .wiki > p').childNodes[0], 7);
99 99

  
    (1-1/1)