Project

General

Profile

Patch #26655 » 0001-Use-button-as-additional-option-for-contextmenu.patch

Felix Gliesche, 2018-04-19 16:05

View differences:

app/helpers/application_helper.rb
1223 1223
    content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
1224 1224
  end
1225 1225

  
1226
  def link_to_context_menu
1227
    link_to l(:button_actions), '#', title: l(:button_actions), class: 'icon-only icon-actions js-contextmenu'
1228
  end
1229

  
1226 1230
  # Helper to render JSON in views
1227 1231
  def raw_json(arg)
1228 1232
    arg.to_json.to_s.gsub('/', '\/').html_safe
app/helpers/issues_helper.rb
99 99
             content_tag('td', link_to_issue(child, :project => (issue.project_id != child.project_id)), :class => 'subject', :style => 'width: 50%') +
100 100
             content_tag('td', h(child.status), :class => 'status') +
101 101
             content_tag('td', link_to_user(child.assigned_to), :class => 'assigned_to') +
102
             content_tag('td', child.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(child.done_ratio), :class=> 'done_ratio'),
102
             content_tag('td', child.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(child.done_ratio), :class=> 'done_ratio') +
103
             content_tag('td', link_to_context_menu, :class => 'buttons'),
103 104
             :class => css)
104 105
    end
105 106
    s << '</table>'
......
114 115
    relations.each do |relation|
115 116
      other_issue = relation.other_issue(issue)
116 117
      css = "issue hascontextmenu #{other_issue.css_classes}"
117
      link = manage_relations ? link_to(l(:label_relation_delete),
118
      buttons = manage_relations ? link_to(l(:label_relation_delete),
118 119
                                  relation_path(relation),
119 120
                                  :remote => true,
120 121
                                  :method => :delete,
121 122
                                  :data => {:confirm => l(:text_are_you_sure)},
122 123
                                  :title => l(:label_relation_delete),
123 124
                                  :class => 'icon-only icon-link-break'
124
                                 ) : nil
125
                                 ) :"".html_safe
126
      buttons << link_to_context_menu
125 127

  
126 128
      s << content_tag('tr',
127 129
             content_tag('td', check_box_tag("ids[]", other_issue.id, false, :id => nil), :class => 'checkbox') +
......
130 132
             content_tag('td', other_issue.start_date, :class => 'start_date') +
131 133
             content_tag('td', other_issue.due_date, :class => 'due_date') +
132 134
             content_tag('td', other_issue.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(other_issue.done_ratio), :class=> 'done_ratio') +
133
             content_tag('td', link, :class => 'buttons'),
135
             content_tag('td', buttons, :class => 'buttons'),
134 136
             :id => "relation-#{relation.id}",
135 137
             :class => css)
136 138
    end
app/views/issues/_list.html.erb
14 14
      <% query.inline_columns.each do |column| %>
15 15
        <%= column_header(query, column, query_options) %>
16 16
      <% end %>
17
      <th class="buttons"></th>
17 18
    </tr>
18 19
  </thead>
19 20
  <tbody>
......
21 22
  <% if group_name %>
22 23
    <% reset_cycle %>
23 24
    <tr class="group open">
24
      <td colspan="<%= query.inline_columns.size + 1 %>">
25
      <td colspan="<%= query.inline_columns.size + 2 %>">
25 26
        <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
26 27
        <span class="name"><%= group_name %></span> <span class="count"><%= group_count %></span> <span class="totals"><%= group_totals %></span>
27 28
        <%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}",
......
34 35
    <% query.inline_columns.each do |column| %>
35 36
    <%= content_tag('td', column_content(column, issue), :class => column.css_classes) %>
36 37
    <% end %>
38
    <td class="buttons"><%= link_to_context_menu %></td>
37 39
  </tr>
38 40
  <% query.block_columns.each do |column|
39 41
       if (text = column_content(column, issue)) && text.present? -%>
40 42
  <tr class="<%= current_cycle %>">
41
    <td colspan="<%= query.inline_columns.size + 1 %>" class="<%= column.css_classes %>">
43
    <td colspan="<%= query.inline_columns.size + 2 %>" class="<%= column.css_classes %>">
42 44
      <% if query.block_columns.count > 1 %>
43 45
        <span><%= column.caption %></span>
44 46
      <% end %>
app/views/my/blocks/_timelog.html.erb
35 35
<th><%= l(:label_project) %></th>
36 36
<th><%= l(:field_comments) %></th>
37 37
<th><%= l(:field_hours) %></th>
38
<th></th>
38 39
</tr></thead>
39 40
<tbody>
40 41
<% entries_by_day.keys.sort.reverse_each do |day| %>
......
42 43
    <td><strong><%= day == User.current.today ? l(:label_today).titleize : format_date(day) %></strong></td>
43 44
    <td colspan="2"></td>
44 45
    <td class="hours"><em><%= html_hours(format_hours(entries_by_day[day].sum(&:hours))) %></em></td>
46
    <td></td>
45 47
  </tr>
46 48
  <% entries_by_day[day].each do |entry| -%>
47 49
  <tr id="time-entry-<%= entry.id %>" class="time-entry hascontextmenu">
......
52 54
    <td class="subject"><%= entry.project %> <%= h(' - ') + link_to_issue(entry.issue, :truncate => 50) if entry.issue %></td>
53 55
    <td class="comments"><%= entry.comments %></td>
54 56
    <td class="hours"><%= html_hours(format_hours(entry.hours)) %></td>
57
    <td class="buttons"><%= link_to_context_menu %></td>
55 58
  </tr>
56 59
  <% end -%>
57 60
<% end -%>
app/views/timelog/_list.html.erb
47 47
                    :title => l(:button_delete),
48 48
                    :class => 'icon-only icon-del' %>
49 49
    <% end -%>
50
        <%= link_to_context_menu %>
50 51
    </td>
51 52
  </tr>
52 53
  <% @query.block_columns.each do |column|
app/views/versions/index.html.erb
30 30
          <tr class="hascontextmenu">
31 31
            <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
32 32
            <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
33
            <td class="buttons"><%= link_to_context_menu %></td>
33 34
          </tr>
34 35
        <% end -%>
35 36
        </table>
app/views/versions/show.html.erb
44 44
    <tr class="issue hascontextmenu">
45 45
      <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
46 46
      <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
47
      <td class="buttons"><%= link_to_context_menu %></td>
47 48
    </tr>
48 49
  <% end %>
49 50
  </table>
config/locales/de.yml
203 203
  button_update: Aktualisieren
204 204
  button_view: Anzeigen
205 205
  button_watch: Beobachten
206
  button_actions: Aktionen
206 207

  
207 208
  default_activity_design: Design
208 209
  default_activity_development: Entwicklung
config/locales/en.yml
1079 1079
  button_reopen: Reopen
1080 1080
  button_import: Import
1081 1081
  button_filter: Filter
1082
  button_actions: Actions
1082 1083

  
1083 1084
  status_active: active
1084 1085
  status_registered: registered
public/javascripts/context_menu.js
5 5

  
6 6
function contextMenuRightClick(event) {
7 7
  var target = $(event.target);
8
  if (target.is('a')) {return;}
8
  if (target.is('a:not(.js-contextmenu)')) {return;}
9 9
  var tr = target.closest('.hascontextmenu').first();
10 10
  if (tr.length < 1) {return;}
11 11
  event.preventDefault();
......
218 218
  if (!contextMenuObserving) {
219 219
    $(document).click(contextMenuClick);
220 220
    $(document).contextmenu(contextMenuRightClick);
221
    $(document).on('click', '.js-contextmenu', contextMenuRightClick);
221 222
    contextMenuObserving = true;
222 223
  }
223 224
}
public/stylesheets/application.css
228 228
table.list td.checkbox input {padding:0px;}
229 229
table.list td.buttons, div.buttons { white-space:nowrap; text-align: right; }
230 230
table.list td.buttons a, div.buttons a { margin-right: 0.6em; }
231
table.list td.buttons a:last-child, div.buttons a:last-child { margin-right: 0; }
231 232
table.list td.buttons img, div.buttons img {vertical-align:middle;}
232 233
table.list td.reorder {width:15%; white-space:nowrap; text-align:center; }
233 234
table.list table.progress td {padding-right:0px;}
......
473 474

  
474 475
#issue_tree table.issues, #relations table.issues { border: 0; }
475 476
#issue_tree td.checkbox, #relations td.checkbox {display:none;}
476
#relations td.buttons {padding:0;}
477
#relations td.buttons, #issue_tree td.buttons {padding:0;}
477 478

  
478 479
fieldset.collapsible {border-width: 1px 0 0 0;}
479 480
fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
......
1308 1309
.icon-project { background-image: url(../images/projects.png); }
1309 1310
.icon-add-bullet { background-image: url(../images/bullet_add.png); }
1310 1311
.icon-shared { background-image: url(../images/link.png); }
1312
.icon-actions { background-image: url(../images/3_bullets.png); }
1311 1313

  
1312 1314
.icon-file { background-image: url(../images/files/default.png); }
1313 1315
.icon-file.text-plain { background-image: url(../images/files/text.png); }
public/stylesheets/responsive.css
793 793
    width: 33.33%; /* three columns for all cells that are not subject */
794 794
  }
795 795

  
796
  #issue_tree .issues, #issue_tree .issue,
796 797
  #relations .issues, #relations .issue {
797 798
    position: relative; /* needed for .buttons positioning */
798 799
  }
799 800

  
800 801
  /* positioniong of unline button */
802
  #issue_tree .issue > td.buttons,
801 803
  #relations .issue > td.buttons {
802 804
    text-align: right;
803 805
    position: absolute;
......
806 808
    padding-right: 0;
807 809
  }
808 810

  
811
  #issue_tree .issue .buttons a,
809 812
  #relations .issue .buttons a {
810 813
    vertical-align: middle;
811
    padding-right: 5px;
812 814
  }
813 815

  
816
  #issue_tree .issue > td.subject,
814 817
  #relations .issue > td.subject {
815 818
    padding-right: 25px; /* this is the spaces that .buttons uses next to subject */
816 819
  }
test/functional/issues_controller_test.rb
1004 1004
  end
1005 1005

  
1006 1006
  def test_index_with_columns
1007
    columns = ['tracker', 'subject', 'assigned_to']
1007
    columns = ['tracker', 'subject', 'assigned_to', 'buttons']
1008 1008
    get :index, :params => {
1009 1009
        :set_filter => 1,
1010 1010
        :c => columns
......
1017 1017
      assert_select 'th.tracker'
1018 1018
      assert_select 'th.subject'
1019 1019
      assert_select 'th.assigned_to'
1020
      assert_select 'th.buttons'
1020 1021
    end
1021 1022

  
1022 1023
    # columns should be stored in session
......
1245 1246
        :c => %w(subject description)
1246 1247
      }
1247 1248

  
1248
    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
1249
    assert_select 'td.description[colspan="3"]', :text => 'Unable to print recipes'
1249
    assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
1250
    assert_select 'td.description[colspan="4"]', :text => 'Unable to print recipes'
1250 1251

  
1251 1252
    get :index, :params => {
1252 1253
        :set_filter => 1,
......
1264 1265
      }
1265 1266

  
1266 1267
    assert_response :success
1267
    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
1268
    assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
1268 1269

  
1269
    assert_select 'td.last_notes[colspan="3"]', :text => 'Some notes with Redmine links: #2, r2.'
1270
    assert_select 'td.last_notes[colspan="3"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
1270
    assert_select 'td.last_notes[colspan="4"]', :text => 'Some notes with Redmine links: #2, r2.'
1271
    assert_select 'td.last_notes[colspan="4"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
1271 1272

  
1272 1273
    get :index, :params => {
1273 1274
        :set_filter => 1,
......
1288 1289
        :c => %w(subject last_notes)
1289 1290
      }
1290 1291
    assert_response :success
1291
    assert_select 'td.last_notes[colspan="3"]', :text => 'Privates notes'
1292
    assert_select 'td.last_notes[colspan="4"]', :text => 'Privates notes'
1292 1293

  
1293 1294
    Role.find(1).remove_permission! :view_private_notes
1294 1295

  
......
1297 1298
        :c => %w(subject last_notes)
1298 1299
      }
1299 1300
    assert_response :success
1300
    assert_select 'td.last_notes[colspan="3"]', :text => 'Public notes'
1301
    assert_select 'td.last_notes[colspan="4"]', :text => 'Public notes'
1301 1302
  end
1302 1303

  
1303 1304
  def test_index_with_description_and_last_notes_columns_should_display_column_name
......
1307 1308
      }
1308 1309
    assert_response :success
1309 1310

  
1310
    assert_select 'td.last_notes[colspan="3"] span', :text => 'Last notes'
1311
    assert_select 'td.description[colspan="3"] span', :text => 'Description'
1311
    assert_select 'td.last_notes[colspan="4"] span', :text => 'Last notes'
1312
    assert_select 'td.description[colspan="4"] span', :text => 'Description'
1312 1313
  end
1313 1314

  
1314 1315
  def test_index_with_parent_column
test/functional/my_controller_test.rb
125 125
    assert_select '#block-issuequery' do
126 126
      assert_select 'a[href=?]', "/issues?query_id=#{query.id}"
127 127
      # assert number of columns (columns from query + id column + checkbox column)
128
      assert_select 'table.issues th', 6
128
      assert_select 'table.issues th', 7
129 129
      # assert results limit
130 130
      assert_select 'table.issues tr.issue', 10
131 131
      assert_select 'table.issues td.assigned_to'
......
145 145
    assert_select '#block-issuequery' do
146 146
      assert_select 'a[href=?]', "/projects/ecookbook/issues?query_id=#{query.id}"
147 147
      # assert number of columns (columns from query + id column + checkbox column)
148
      assert_select 'table.issues th', 6
148
      assert_select 'table.issues th', 7
149 149
      # assert results limit
150 150
      assert_select 'table.issues tr.issue', 10
151 151
      assert_select 'table.issues td.assigned_to'
......
164 164

  
165 165
    assert_select '#block-issuequery' do
166 166
      # assert number of columns (columns from query + id column + checkbox column)
167
      assert_select 'table.issues th', 4
167
      assert_select 'table.issues th', 5
168 168
      assert_select 'table.issues th', :text => 'Due date'
169 169
    end
170 170
  end
test/test_helper.rb
305 305
  
306 306
    # Return the columns that are displayed in the issue list
307 307
    def columns_in_issues_list
308
      css_select('table.issues thead th:not(.checkbox)').map(&:text)
308
      css_select('table.issues thead th:not(.checkbox)').map(&:text).select(&:present?)
309 309
    end
310 310
  
311 311
    # Return the columns that are displayed in the list
(7-7/7)