Patch #42938 » adds_subitem_icon.patch
app/assets/stylesheets/application.css | ||
---|---|---|
388 | 388 |
table.issues td.block_column>span {font-weight: bold; display: block; margin-bottom: 4px;} |
389 | 389 |
table.issues td.block_column>pre {white-space:normal;} |
390 | 390 | |
391 |
tr.idnt td.subject, tr.idnt td.name {background: url(/chevron-right-idnt.svg) no-repeat 2px 50%;} |
|
392 |
tr.idnt-1 td.subject, tr.idnt-1 td.name {padding-left: 24px; background-position: 4px 50%;} |
|
393 |
tr.idnt-2 td.subject, tr.idnt-2 td.name {padding-left: 40px; background-position: 20px 50%;} |
|
394 |
tr.idnt-3 td.subject, tr.idnt-3 td.name {padding-left: 56px; background-position: 36px 50%;} |
|
395 |
tr.idnt-4 td.subject, tr.idnt-4 td.name {padding-left: 72px; background-position: 52px 50%;} |
|
396 |
tr.idnt-5 td.subject, tr.idnt-5 td.name {padding-left: 88px; background-position: 68px 50%;} |
|
397 |
tr.idnt-6 td.subject, tr.idnt-6 td.name {padding-left: 104px; background-position: 84px 50%;} |
|
398 |
tr.idnt-7 td.subject, tr.idnt-7 td.name {padding-left: 120px; background-position: 100px 50%;} |
|
399 |
tr.idnt-8 td.subject, tr.idnt-8 td.name {padding-left: 136px; background-position: 116px 50%;} |
|
400 |
tr.idnt-9 td.subject, tr.idnt-9 td.name {padding-left: 152px; background-position: 132px 50%;} |
|
391 |
tr.idnt-1 td.subject, tr.idnt-1 td.name {padding-left: 0;} |
|
392 |
tr.idnt-2 td.subject, tr.idnt-2 td.name {padding-left: 20px;} |
|
393 |
tr.idnt-3 td.subject, tr.idnt-3 td.name {padding-left: 36px;} |
|
394 |
tr.idnt-4 td.subject, tr.idnt-4 td.name {padding-left: 52px;} |
|
395 |
tr.idnt-5 td.subject, tr.idnt-5 td.name {padding-left: 68px;} |
|
396 |
tr.idnt-6 td.subject, tr.idnt-6 td.name {padding-left: 84px;} |
|
397 |
tr.idnt-7 td.subject, tr.idnt-7 td.name {padding-left: 100px;} |
|
398 |
tr.idnt-8 td.subject, tr.idnt-8 td.name {padding-left: 116px;} |
|
399 |
tr.idnt-9 td.subject, tr.idnt-9 td.name {padding-left: 132px;} |
|
401 | 400 | |
402 | 401 |
table.issue-report {table-layout:fixed;} |
403 | 402 |
table.issue-report tr.total, table.issue-report-detailed tr.total { font-weight: bold; border-top:2px solid #d0d7de;} |
app/helpers/application_helper.rb | ||
---|---|---|
191 | 191 |
h(project.name) |
192 | 192 |
else |
193 | 193 |
link_to project.name, |
194 |
project_url(project, {:only_path => true}.merge(options)), |
|
194 |
# if it is a Struct it comes from ProjectQueriesHelper#project_with_optional_icon |
|
195 |
project_url(project.is_a?(Struct) ? project.item : project, {:only_path => true}.merge(options)), |
|
195 | 196 |
html_options |
196 | 197 |
end |
197 | 198 |
end |
app/helpers/projects_queries_helper.rb | ||
---|---|---|
24 | 24 |
case column.name |
25 | 25 |
when :name |
26 | 26 |
link_to_project(item) + |
27 |
(tag.span(sprite_icon('user', l(:label_my_projects), icon_only: true), class: 'icon-only icon-user my-project') if User.current.member_of?(item)) + |
|
28 |
(tag.span(sprite_icon('bookmarked', l(:label_my_bookmarks), icon_only: true), class: 'icon-only icon-bookmarked-project') if User.current.bookmarked_project_ids.include?(item.id)) |
|
27 |
user_project_icons(item) |
|
29 | 28 |
when :short_description |
30 | 29 |
if item.description? |
31 | 30 |
# Sets :inline_attachments to false to avoid performance issues |
... | ... | |
56 | 55 |
end |
57 | 56 |
end |
58 | 57 | |
58 |
def column_content_with_subitem_icon(column, item, value, level) |
|
59 |
if item.is_a?(Project) |
|
60 |
content = |
|
61 |
case column.name |
|
62 |
when :name |
|
63 |
name = (item.child? && level&.positive?) ? sprite_icon('angle-right', item.name) : item.name |
|
64 |
link_to_project(project_with_subitem_icon(item, name)) + |
|
65 |
user_project_icons(item) |
|
66 |
else |
|
67 |
column_value(column, item, value) |
|
68 |
end |
|
69 | ||
70 |
content |
|
71 |
end |
|
72 |
end |
|
73 | ||
59 | 74 |
def csv_value(column, object, value) |
60 | 75 |
if object.is_a?(Project) |
61 | 76 |
case column.name |
... | ... | |
71 | 86 | |
72 | 87 |
private |
73 | 88 | |
89 |
def user_project_icons(item) |
|
90 |
content = + '' |
|
91 |
content += tag.span(sprite_icon('user', l(:label_my_projects), icon_only: true), class: 'icon-only icon-user my-project') if User.current.member_of?(item) |
|
92 |
content += tag.span(sprite_icon('bookmarked', l(:label_my_bookmarks), icon_only: true), class: 'icon-only icon-bookmarked-project') if User.current.bookmarked_project_ids.include?(item.id) |
|
93 |
content.html_safe |
|
94 |
end |
|
95 | ||
96 |
# Struct object that behaves like Project#archived? and Project#name |
|
97 |
# |
|
98 |
# @param item [Project] Instance of a Project |
|
99 |
# @param name [String|ActiveSupport::SafeBuffer] If name is not a String |
|
100 |
# the object should hold the angle-right icon |
|
101 |
# with the subprojects name |
|
102 |
# @return [Struct] Object responding to item, name, and archived? |
|
103 |
def project_with_subitem_icon(item, name) |
|
104 |
Struct.new(:item, :name) do |
|
105 |
def archived? |
|
106 |
item.archived? |
|
107 |
end |
|
108 |
end.new(item, name) |
|
109 |
end |
|
110 | ||
74 | 111 |
def get_project_status_label |
75 | 112 |
{ |
76 | 113 |
Project::STATUS_ACTIVE => l(:project_status_active), |
app/helpers/queries_helper.rb | ||
---|---|---|
237 | 237 |
content_tag('th', content, :class => column.css_classes) |
238 | 238 |
end |
239 | 239 | |
240 |
def column_content(column, item) |
|
240 |
def column_content(column, item, level = nil)
|
|
241 | 241 |
value = column.value_object(item) |
242 | 242 |
content = |
243 | 243 |
if value.is_a?(Array) |
244 | 244 |
values = value.filter_map {|v| column_value(column, item, v)} |
245 | 245 |
safe_join(values, ', ') |
246 | 246 |
else |
247 |
column_value(column, item, value) |
|
247 |
level ? column_content_with_subitem_icon(column, item, value, level) : column_value(column, item, value)
|
|
248 | 248 |
end |
249 | 249 | |
250 | 250 |
call_hook(:helper_queries_column_content, |
251 |
{:content => content, :column => column, :item => item}) |
|
251 |
{:content => content, :column => column, :item => item, :level =>level}) |
|
252 | ||
253 |
content |
|
254 |
end |
|
255 | ||
256 |
def column_content_with_subitem_icon(column, item, value, level) |
|
257 |
content = |
|
258 |
case column.name |
|
259 |
when :subject |
|
260 |
subject = (item.child? && level&.positive?) ? sprite_icon('angle-right', value) : value |
|
261 |
link_to subject, issue_path(item) |
|
262 |
else |
|
263 |
column_value(column, item, value) |
|
264 |
end |
|
265 | ||
266 |
call_hook(:helper_queries_column_value, |
|
267 |
{:content => content, :column => column, :item => item, :value => value}) |
|
252 | 268 | |
253 | 269 |
content |
254 | 270 |
end |
app/views/issues/_list.html.erb | ||
---|---|---|
34 | 34 |
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> |
35 | 35 |
<td class="checkbox hide-when-print"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td> |
36 | 36 |
<% query.inline_columns.each do |column| %> |
37 |
<%= content_tag('td', column_content(column, issue), :class => column.css_classes) %> |
|
37 |
<%= content_tag('td', column_content(column, issue, level), :class => column.css_classes) %>
|
|
38 | 38 |
<% end %> |
39 | 39 |
<td class="buttons"><%= link_to_context_menu %></td> |
40 | 40 |
</tr> |
app/views/projects/_list.html.erb | ||
---|---|---|
49 | 49 |
<% end %> |
50 | 50 |
<% end %> |
51 | 51 |
<% @query.inline_columns.each do |column| %> |
52 |
<%= content_tag('td', column_content(column, entry), :class => column.css_classes) %> |
|
52 |
<%= content_tag('td', column_content(column, entry, level), :class => column.css_classes) %>
|
|
53 | 53 |
<% end %> |
54 | 54 |
<% if @admin_list %> |
55 | 55 |
<% if !entry.scheduled_for_deletion? %> |
test/helpers/application_helper_test.rb | ||
---|---|---|
22 | 22 |
class ApplicationHelperTest < Redmine::HelperTest |
23 | 23 |
include ERB::Util |
24 | 24 |
include AvatarsHelper |
25 |
include ProjectsQueriesHelper |
|
25 | 26 | |
26 | 27 |
def setup |
27 | 28 |
super |
... | ... | |
1974 | 1975 |
link_to_project(project, {:only_path => false, :jump => 'blah'}) |
1975 | 1976 |
end |
1976 | 1977 | |
1978 |
def test_link_to_project_with_subitem_icon |
|
1979 |
item = Project.find(3) |
|
1980 |
level = 1 |
|
1981 |
name = (item.child? && level&.positive?) ? sprite_icon('angle-right', item.name) : item.name |
|
1982 |
# requires ProjectsQueriesHelper |
|
1983 |
project = project_with_subitem_icon(item, name) |
|
1984 |
assert_equal %(<a href=\"/projects/subproject1\"><svg class=\"s18 icon-svg\" aria-hidden=\"true\"><use href=\"/assets/icons-1857f271.svg#icon--angle-right\"></use></svg><span class=\"icon-label\">eCookbook Subproject 1</span></a>), |
|
1985 |
link_to_project(project) |
|
1986 |
end |
|
1987 | ||
1977 | 1988 |
def test_link_to_project_settings |
1978 | 1989 |
project = Project.find(1) |
1979 | 1990 |
assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project) |
test/helpers/projects_queries_helper_test.rb | ||
---|---|---|
29 | 29 |
assert_equal "active", csv_value(c_status, Project.find(1), 1) |
30 | 30 |
assert_equal "eCookbook", csv_value(c_parent_id, Project.find(4), 1) |
31 | 31 |
end |
32 | ||
33 |
def test_column_content_with_subitem_icon |
|
34 |
column = QueryColumn.new(:name) |
|
35 |
item = Project.find(3) |
|
36 |
value = Project.name |
|
37 |
level = 1 |
|
38 | ||
39 |
content = column_content_with_subitem_icon(column, item, value, level) |
|
40 |
name_with_subitem_icon = %(<a href=\"/projects/subproject1\"><svg class=\"s18 icon-svg\" aria-hidden=\"true\"><use href=\"/assets/icons-1857f271.svg#icon--angle-right\"></use></svg><span class=\"icon-label\">eCookbook Subproject 1</span></a>) |
|
41 |
assert_equal name_with_subitem_icon, content |
|
42 |
end |
|
32 | 43 |
end |
test/helpers/queries_helper_test.rb | ||
---|---|---|
109 | 109 |
assert_select_in options, 'option[value=?]', "cf_#{i_cf.id}.cf_#{u_cf.id}", text: "User's Phone number" |
110 | 110 |
assert_select_in options, 'optgroup[label=?]', 'User', 1 |
111 | 111 |
end |
112 | ||
113 |
def test_column_content_should_use_column_content_with_subitem_icon |
|
114 |
item = Issue.generate!(parent_id: 2) |
|
115 |
column = QueryColumn.new(:subject) |
|
116 |
value = item.subject |
|
117 |
level = 1 |
|
118 |
content = column_content(column, item, level) |
|
119 |
assert_equal name_with_subitem_icon(item), content |
|
120 |
end |
|
121 | ||
122 |
private |
|
123 | ||
124 |
def name_with_subitem_icon(item) |
|
125 |
%(<a href=\"/issues/#{item.id}\"><svg class=\"s18 icon-svg\" aria-hidden=\"true\"><use href=\"/assets/icons-1857f271.svg#icon--angle-right\"></use></svg><span class=\"icon-label\">Generated</span></a>) |
|
126 |
end |
|
112 | 127 |
end |
- « Previous
- 1
- 2
- 3
- Next »