]> source.dussan.org Git - redmine.git/commitdiff
Use button as additional option for contextmenu (#26655).
authorGo MAEDA <maeda@farend.jp>
Sat, 21 Apr 2018 12:00:22 +0000 (12:00 +0000)
committerGo MAEDA <maeda@farend.jp>
Sat, 21 Apr 2018 12:00:22 +0000 (12:00 +0000)
Patch by Felix Gliesche.

git-svn-id: http://svn.redmine.org/redmine/trunk@17298 e93f8b46-1217-0410-a6f0-8f06a7374b81

16 files changed:
app/helpers/application_helper.rb
app/helpers/issues_helper.rb
app/views/issues/_list.html.erb
app/views/my/blocks/_timelog.html.erb
app/views/timelog/_list.html.erb
app/views/versions/index.html.erb
app/views/versions/show.html.erb
config/locales/de.yml
config/locales/en.yml
public/images/3_bullets.png [new file with mode: 0644]
public/javascripts/context_menu.js
public/stylesheets/application.css
public/stylesheets/responsive.css
test/functional/issues_controller_test.rb
test/functional/my_controller_test.rb
test/test_helper.rb

index 00992a5bb9e5272057e022e129343c9670aed71e..be0813480341d61aa4892593b79dacb9748555a7 100644 (file)
@@ -1223,6 +1223,10 @@ module ApplicationHelper
     content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
   end
 
+  def link_to_context_menu
+    link_to l(:button_actions), '#', title: l(:button_actions), class: 'icon-only icon-actions js-contextmenu'
+  end
+
   # Helper to render JSON in views
   def raw_json(arg)
     arg.to_json.to_s.gsub('/', '\/').html_safe
index 972e6b9cb75baf785748860078f2d0edb8fb7b6c..1c2fd1b5d4398d00ce65304bc1109751a503b914 100644 (file)
@@ -99,7 +99,8 @@ module IssuesHelper
              content_tag('td', link_to_issue(child, :project => (issue.project_id != child.project_id)), :class => 'subject', :style => 'width: 50%') +
              content_tag('td', h(child.status), :class => 'status') +
              content_tag('td', link_to_user(child.assigned_to), :class => 'assigned_to') +
-             content_tag('td', child.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(child.done_ratio), :class=> 'done_ratio'),
+             content_tag('td', child.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(child.done_ratio), :class=> 'done_ratio') +
+             content_tag('td', link_to_context_menu, :class => 'buttons'),
              :class => css)
     end
     s << '</table>'
@@ -114,14 +115,15 @@ module IssuesHelper
     relations.each do |relation|
       other_issue = relation.other_issue(issue)
       css = "issue hascontextmenu #{other_issue.css_classes}"
-      link = manage_relations ? link_to(l(:label_relation_delete),
+      buttons = manage_relations ? link_to(l(:label_relation_delete),
                                   relation_path(relation),
                                   :remote => true,
                                   :method => :delete,
                                   :data => {:confirm => l(:text_are_you_sure)},
                                   :title => l(:label_relation_delete),
                                   :class => 'icon-only icon-link-break'
-                                 ) : nil
+                                 ) :"".html_safe
+      buttons << link_to_context_menu
 
       s << content_tag('tr',
              content_tag('td', check_box_tag("ids[]", other_issue.id, false, :id => nil), :class => 'checkbox') +
@@ -130,7 +132,7 @@ module IssuesHelper
              content_tag('td', other_issue.start_date, :class => 'start_date') +
              content_tag('td', other_issue.due_date, :class => 'due_date') +
              content_tag('td', other_issue.disabled_core_fields.include?('done_ratio') ? '' : progress_bar(other_issue.done_ratio), :class=> 'done_ratio') +
-             content_tag('td', link, :class => 'buttons'),
+             content_tag('td', buttons, :class => 'buttons'),
              :id => "relation-#{relation.id}",
              :class => css)
     end
index 8024a694822901ed2530fde1c9bc159343ad5abf..d704a58bbf6e75f82afdc24870e3fea10e6a0e43 100644 (file)
@@ -14,6 +14,7 @@
       <% query.inline_columns.each do |column| %>
         <%= column_header(query, column, query_options) %>
       <% end %>
+      <th class="buttons"></th>
     </tr>
   </thead>
   <tbody>
@@ -21,7 +22,7 @@
   <% if group_name %>
     <% reset_cycle %>
     <tr class="group open">
-      <td colspan="<%= query.inline_columns.size + 1 %>">
+      <td colspan="<%= query.inline_columns.size + 2 %>">
         <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
         <span class="name"><%= group_name %></span> <span class="count"><%= group_count %></span> <span class="totals"><%= group_totals %></span>
         <%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}",
     <% query.inline_columns.each do |column| %>
     <%= content_tag('td', column_content(column, issue), :class => column.css_classes) %>
     <% end %>
+    <td class="buttons"><%= link_to_context_menu %></td>
   </tr>
   <% query.block_columns.each do |column|
        if (text = column_content(column, issue)) && text.present? -%>
   <tr class="<%= current_cycle %>">
-    <td colspan="<%= query.inline_columns.size + 1 %>" class="<%= column.css_classes %>">
+    <td colspan="<%= query.inline_columns.size + 2 %>" class="<%= column.css_classes %>">
       <% if query.block_columns.count > 1 %>
         <span><%= column.caption %></span>
       <% end %>
index f96ee6c2e20f0e8f2dd3a1e39c3be760df93dc1e..7354c757d3c237f1382118f7ea9a3baa2fe8e9cb 100644 (file)
@@ -35,6 +35,7 @@
 <th><%= l(:label_project) %></th>
 <th><%= l(:field_comments) %></th>
 <th><%= l(:field_hours) %></th>
+<th></th>
 </tr></thead>
 <tbody>
 <% entries_by_day.keys.sort.reverse_each do |day| %>
@@ -42,6 +43,7 @@
     <td><strong><%= day == User.current.today ? l(:label_today).titleize : format_date(day) %></strong></td>
     <td colspan="2"></td>
     <td class="hours"><em><%= html_hours(format_hours(entries_by_day[day].sum(&:hours))) %></em></td>
+    <td></td>
   </tr>
   <% entries_by_day[day].each do |entry| -%>
   <tr id="time-entry-<%= entry.id %>" class="time-entry hascontextmenu">
@@ -52,6 +54,7 @@
     <td class="subject"><%= entry.project %> <%= h(' - ') + link_to_issue(entry.issue, :truncate => 50) if entry.issue %></td>
     <td class="comments"><%= entry.comments %></td>
     <td class="hours"><%= html_hours(format_hours(entry.hours)) %></td>
+    <td class="buttons"><%= link_to_context_menu %></td>
   </tr>
   <% end -%>
 <% end -%>
index 6f126b0f7a04bf5904fa52a52edb4d4638da0b1e..019ddbb53fe4bfa6ee16c5f06a0bd4f9094e09c2 100644 (file)
@@ -47,6 +47,7 @@
                     :title => l(:button_delete),
                     :class => 'icon-only icon-del' %>
     <% end -%>
+        <%= link_to_context_menu %>
     </td>
   </tr>
   <% @query.block_columns.each do |column|
index 2914a6dbc0f27ea8c07746fdb452aa2e4e00a610..eeb9f3f061b61ecb1aad638e9ac16a28346d38d1 100644 (file)
@@ -30,6 +30,7 @@
           <tr class="hascontextmenu">
             <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
             <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
+            <td class="buttons"><%= link_to_context_menu %></td>
           </tr>
         <% end -%>
         </table>
index a62b0a1d0ff4d67c8920d2c5ce0c207c23b005e8..677cc1410d2dbd0a8cb8476da13b60a1a311e2cf 100644 (file)
@@ -44,6 +44,7 @@
     <tr class="issue hascontextmenu">
       <td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td>
       <td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td>
+      <td class="buttons"><%= link_to_context_menu %></td>
     </tr>
   <% end %>
   </table>
index 62def24c49d09752f49912d4bb20494c4dd9c810..7d4a4582d28b3589e894b643bdd60c62f05f1f45 100644 (file)
@@ -203,6 +203,7 @@ de:
   button_update: Aktualisieren
   button_view: Anzeigen
   button_watch: Beobachten
+  button_actions: Aktionen
 
   default_activity_design: Design
   default_activity_development: Entwicklung
index d9095432ba5a39d2193d1db5b908c84aed0d2452..618ff3f2a75b19786adff39e75aa10f9c360fda0 100644 (file)
@@ -1079,6 +1079,7 @@ en:
   button_reopen: Reopen
   button_import: Import
   button_filter: Filter
+  button_actions: Actions
 
   status_active: active
   status_registered: registered
diff --git a/public/images/3_bullets.png b/public/images/3_bullets.png
new file mode 100644 (file)
index 0000000..616593b
Binary files /dev/null and b/public/images/3_bullets.png differ
index cd2cf0884891b37b606eb7eee1cbc0d85e970f2b..9bc64b171a55ba74785f3a17b0322a0f81ad4ac2 100644 (file)
@@ -5,7 +5,7 @@ var contextMenuObserving;
 
 function contextMenuRightClick(event) {
   var target = $(event.target);
-  if (target.is('a')) {return;}
+  if (target.is('a:not(.js-contextmenu)')) {return;}
   var tr = target.closest('.hascontextmenu').first();
   if (tr.length < 1) {return;}
   event.preventDefault();
@@ -218,6 +218,7 @@ function contextMenuInit() {
   if (!contextMenuObserving) {
     $(document).click(contextMenuClick);
     $(document).contextmenu(contextMenuRightClick);
+    $(document).on('click', '.js-contextmenu', contextMenuRightClick);
     contextMenuObserving = true;
   }
 }
index ab8f17efd71e938975706d12ecb5749a80c07efc..ebe2ae02e803c6638623c5f377e2b444d8835dfb 100644 (file)
@@ -228,6 +228,7 @@ table.list td.checkbox { width: 15px; padding: 2px 0 0 0; }
 table.list td.checkbox input {padding:0px;}
 table.list td.buttons, div.buttons { white-space:nowrap; text-align: right; }
 table.list td.buttons a, div.buttons a { margin-right: 0.6em; }
+table.list td.buttons a:last-child, div.buttons a:last-child { margin-right: 0; }
 table.list td.buttons img, div.buttons img {vertical-align:middle;}
 table.list td.reorder {width:15%; white-space:nowrap; text-align:center; }
 table.list table.progress td {padding-right:0px;}
@@ -473,7 +474,7 @@ div.issue.overdue .due-date .value { color: #c22; }
 
 #issue_tree table.issues, #relations table.issues { border: 0; }
 #issue_tree td.checkbox, #relations td.checkbox {display:none;}
-#relations td.buttons {padding:0;}
+#relations td.buttons, #issue_tree td.buttons {padding:0;}
 
 fieldset.collapsible {border-width: 1px 0 0 0;}
 fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
@@ -1308,6 +1309,7 @@ div.wiki img {vertical-align:middle; max-width:100%;}
 .icon-project { background-image: url(../images/projects.png); }
 .icon-add-bullet { background-image: url(../images/bullet_add.png); }
 .icon-shared { background-image: url(../images/link.png); }
+.icon-actions { background-image: url(../images/3_bullets.png); }
 
 .icon-file { background-image: url(../images/files/default.png); }
 .icon-file.text-plain { background-image: url(../images/files/text.png); }
index 76e2d59455a8a2cb08dc7d00014e3c832530aa18..fb156863a763987ef8e9bdcbfe3c1619e348a2cd 100644 (file)
     width: 33.33%; /* three columns for all cells that are not subject */
   }
 
+  #issue_tree .issues, #issue_tree .issue,
   #relations .issues, #relations .issue {
     position: relative; /* needed for .buttons positioning */
   }
 
   /* positioniong of unline button */
+  #issue_tree .issue > td.buttons,
   #relations .issue > td.buttons {
     text-align: right;
     position: absolute;
     padding-right: 0;
   }
 
+  #issue_tree .issue .buttons a,
   #relations .issue .buttons a {
     vertical-align: middle;
-    padding-right: 5px;
   }
 
+  #issue_tree .issue > td.subject,
   #relations .issue > td.subject {
     padding-right: 25px; /* this is the spaces that .buttons uses next to subject */
   }
index 9f62758e4caba4b85beddb927c669f37e436e73a..fc5b035766da850a726452eb57d8a61d69d812d2 100644 (file)
@@ -1004,7 +1004,7 @@ class IssuesControllerTest < Redmine::ControllerTest
   end
 
   def test_index_with_columns
-    columns = ['tracker', 'subject', 'assigned_to']
+    columns = ['tracker', 'subject', 'assigned_to', 'buttons']
     get :index, :params => {
         :set_filter => 1,
         :c => columns
@@ -1017,6 +1017,7 @@ class IssuesControllerTest < Redmine::ControllerTest
       assert_select 'th.tracker'
       assert_select 'th.subject'
       assert_select 'th.assigned_to'
+      assert_select 'th.buttons'
     end
 
     # columns should be stored in session
@@ -1245,8 +1246,8 @@ class IssuesControllerTest < Redmine::ControllerTest
         :c => %w(subject description)
       }
 
-    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
-    assert_select 'td.description[colspan="3"]', :text => 'Unable to print recipes'
+    assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
+    assert_select 'td.description[colspan="4"]', :text => 'Unable to print recipes'
 
     get :index, :params => {
         :set_filter => 1,
@@ -1264,10 +1265,10 @@ class IssuesControllerTest < Redmine::ControllerTest
       }
 
     assert_response :success
-    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
+    assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
 
-    assert_select 'td.last_notes[colspan="3"]', :text => 'Some notes with Redmine links: #2, r2.'
-    assert_select 'td.last_notes[colspan="3"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
+    assert_select 'td.last_notes[colspan="4"]', :text => 'Some notes with Redmine links: #2, r2.'
+    assert_select 'td.last_notes[colspan="4"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
 
     get :index, :params => {
         :set_filter => 1,
@@ -1288,7 +1289,7 @@ class IssuesControllerTest < Redmine::ControllerTest
         :c => %w(subject last_notes)
       }
     assert_response :success
-    assert_select 'td.last_notes[colspan="3"]', :text => 'Privates notes'
+    assert_select 'td.last_notes[colspan="4"]', :text => 'Privates notes'
 
     Role.find(1).remove_permission! :view_private_notes
 
@@ -1297,7 +1298,7 @@ class IssuesControllerTest < Redmine::ControllerTest
         :c => %w(subject last_notes)
       }
     assert_response :success
-    assert_select 'td.last_notes[colspan="3"]', :text => 'Public notes'
+    assert_select 'td.last_notes[colspan="4"]', :text => 'Public notes'
   end
 
   def test_index_with_description_and_last_notes_columns_should_display_column_name
@@ -1307,8 +1308,8 @@ class IssuesControllerTest < Redmine::ControllerTest
       }
     assert_response :success
 
-    assert_select 'td.last_notes[colspan="3"] span', :text => 'Last notes'
-    assert_select 'td.description[colspan="3"] span', :text => 'Description'
+    assert_select 'td.last_notes[colspan="4"] span', :text => 'Last notes'
+    assert_select 'td.description[colspan="4"] span', :text => 'Description'
   end
 
   def test_index_with_parent_column
index 206bba4cf24bca0e4e73b1dd6b84f4d3a2cc38ab..6a618c4a341d42113de52f87684eed8c2d44f8a2 100644 (file)
@@ -125,7 +125,7 @@ class MyControllerTest < Redmine::ControllerTest
     assert_select '#block-issuequery' do
       assert_select 'a[href=?]', "/issues?query_id=#{query.id}"
       # assert number of columns (columns from query + id column + checkbox column)
-      assert_select 'table.issues th', 6
+      assert_select 'table.issues th', 7
       # assert results limit
       assert_select 'table.issues tr.issue', 10
       assert_select 'table.issues td.assigned_to'
@@ -145,7 +145,7 @@ class MyControllerTest < Redmine::ControllerTest
     assert_select '#block-issuequery' do
       assert_select 'a[href=?]', "/projects/ecookbook/issues?query_id=#{query.id}"
       # assert number of columns (columns from query + id column + checkbox column)
-      assert_select 'table.issues th', 6
+      assert_select 'table.issues th', 7
       # assert results limit
       assert_select 'table.issues tr.issue', 10
       assert_select 'table.issues td.assigned_to'
@@ -164,7 +164,7 @@ class MyControllerTest < Redmine::ControllerTest
 
     assert_select '#block-issuequery' do
       # assert number of columns (columns from query + id column + checkbox column)
-      assert_select 'table.issues th', 4
+      assert_select 'table.issues th', 5
       assert_select 'table.issues th', :text => 'Due date'
     end
   end
index 34aebd4d2e46e3da9dd6d08d4ab9e56fffd60928..6dcdb7a7c6ed40f0a8a2c774f64339c450b5f8c3 100644 (file)
@@ -305,7 +305,7 @@ module Redmine
   
     # Return the columns that are displayed in the issue list
     def columns_in_issues_list
-      css_select('table.issues thead th:not(.checkbox)').map(&:text)
+      css_select('table.issues thead th:not(.checkbox)').map(&:text).select(&:present?)
     end
   
     # Return the columns that are displayed in the list