Feature #29824 » 0001-Render-user-s-initals-by-default-when-Gravatar-servi.patch
app/assets/stylesheets/application.css | ||
---|---|---|
413 | 413 |
tr.entry.file td.filename_no_report a { margin-left: 16px; } |
414 | 414 | |
415 | 415 |
tr span.expander, .gantt_subjects div > span.expander {margin-left: 0; cursor: pointer;} |
416 |
.gantt_subjects div > span .icon-gravatar {float: none;}
|
|
416 |
.gantt_subjects .avatar {margin-right: 4px;}
|
|
417 | 417 |
.gantt_subjects div.project-name a, .gantt_subjects div.version-name a {margin-left: 4px;} |
418 | 418 | |
419 | 419 |
tr.changeset { height: 20px } |
... | ... | |
445 | 445 |
tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; } |
446 | 446 | |
447 | 447 |
#principals_for_new_member .icon-user, #users_for_watcher .icon-user {background:transparent;} |
448 |
#principals_for_new_member svg, #principals_for_new_member img {margin-right: 4px;}
|
|
448 |
#principals_for_new_member svg, #principals_for_new_member .avatar {margin-right: 4px;}
|
|
449 | 449 | |
450 | 450 |
tr.user td {width:13%;white-space: nowrap;} |
451 | 451 |
td.username, td.firstname, td.lastname, td.email {text-align:left !important;} |
... | ... | |
549 | 549 |
td.center {text-align:center;} |
550 | 550 | |
551 | 551 |
#watchers select {width: 95%; display: block;} |
552 |
#watchers img.gravatar {margin: 0 4px 2px 0;}
|
|
552 |
#watchers .avatar {margin: 0 4px 2px 0;}
|
|
553 | 553 |
#watchers svg.icon-svg {margin: 0 2px 2px 0;} |
554 |
#users_for_watcher img.gravatar {padding-bottom: 2px; margin-right: 4px;}
|
|
554 |
#users_for_watcher .avatar {padding-bottom: 2px; margin-right: 4px;}
|
|
555 | 555 |
#users_for_watcher svg {margin-right: 4px;} |
556 | 556 |
#users_for_watcher span.icon-user {display: inline;} |
557 | 557 | |
... | ... | |
1445 | 1445 |
.tooltip span.tip{display: none; text-align:left;} |
1446 | 1446 |
.tooltip span.tip a { color: #169 !important; } |
1447 | 1447 | |
1448 |
.tooltip span.tip img.gravatar {
|
|
1448 |
.tooltip span.tip .avatar {
|
|
1449 | 1449 |
float: none; |
1450 | 1450 |
margin: 0; |
1451 | 1451 |
} |
... | ... | |
1799 | 1799 |
} |
1800 | 1800 |
.gantt_subjects div.issue-subject:hover { background-color:#ffffdd; } |
1801 | 1801 |
.gantt_selected_column_content { padding-left: 3px; padding-right: 3px;} |
1802 |
.gantt_subjects .issue-subject img.icon-gravatar { |
|
1803 |
margin: 2px 5px 0px 2px; |
|
1804 |
} |
|
1805 | 1802 | |
1806 | 1803 |
.gantt_hdr_selected_column_name { |
1807 | 1804 |
position: absolute; |
... | ... | |
2112 | 2109 | |
2113 | 2110 |
.contextual>*:not(:first-child), .buttons>.icon:not(:first-child), .contextual .journal-actions>*:not(:first-child) { margin-left: 5px; } |
2114 | 2111 | |
2115 |
img.gravatar { |
|
2116 |
vertical-align: middle; |
|
2117 |
border-radius: 20%; |
|
2118 |
} |
|
2119 | ||
2120 |
div.issue img.gravatar { |
|
2112 |
div.issue .avatar { |
|
2121 | 2113 |
float: left; |
2122 | 2114 |
margin: 0 12px 6px 0; |
2123 | 2115 |
} |
2124 | 2116 | |
2125 |
div.gravatar-with-child {
|
|
2117 |
div.avatar-with-child { |
|
2126 | 2118 |
position: relative; |
2127 | 2119 |
} |
2128 | 2120 | |
2129 |
div.gravatar-with-child > img.gravatar:nth-child(2) {
|
|
2121 |
div.avatar-with-child > .avatar:nth-child(2) {
|
|
2130 | 2122 |
position: absolute; |
2131 | 2123 |
top: 30px; |
2132 | 2124 |
left: 30px; |
... | ... | |
2134 | 2126 |
border: 2px solid rgba(255, 255, 255, 0.9); |
2135 | 2127 |
} |
2136 | 2128 | |
2137 |
h2 img.gravatar, h3 img.gravatar {margin-right: 4px;}
|
|
2129 |
h2 .avatar, h3 .avatar {margin-right: 4px;}
|
|
2138 | 2130 |
h4 img.gravatar {margin: -2px 4px -4px 0;} |
2131 |
/*# TODO: check where this rule is still used*/ |
|
2139 | 2132 |
td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;} |
2140 |
#activity dt img.gravatar {margin: 0 1em 0 0;} |
|
2141 |
/* Used on 12px Gravatar img tags without the icon background */ |
|
2142 |
.icon-gravatar {float: left; margin-right: 4px;} |
|
2133 |
#activity dt .avatar {margin: 0 1em 0 0;} |
|
2143 | 2134 | |
2144 | 2135 |
#activity dt, .journal {clear: left;} |
2145 | 2136 | |
... | ... | |
2162 | 2153 | |
2163 | 2154 |
img.filecontent.image {background-image: url(/transparent.png);} |
2164 | 2155 | |
2156 |
/* Avatar styles */ |
|
2157 |
.avatar { |
|
2158 |
border-radius: 20%; |
|
2159 |
display: inline-flex; |
|
2160 |
vertical-align: middle; |
|
2161 |
} |
|
2162 | ||
2163 |
span[role="img"].avatar { |
|
2164 |
font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif; |
|
2165 |
align-items: center; |
|
2166 |
display: inline-flex; |
|
2167 |
font-size: calc(24px * .4); |
|
2168 |
justify-content: center; |
|
2169 |
user-select: none; |
|
2170 |
font-weight: 700; |
|
2171 |
} |
|
2172 |
.avatar.s13 { |
|
2173 |
block-size: 13px; |
|
2174 |
inline-size: 13px; |
|
2175 |
} |
|
2176 |
span[role="img"].avatar.s13 { |
|
2177 |
font-size: calc(16px * .3); |
|
2178 |
} |
|
2179 |
.avatar.s16 { |
|
2180 |
block-size: 16px; |
|
2181 |
inline-size: 16px; |
|
2182 |
} |
|
2183 |
span[role="img"].avatar.s16 { |
|
2184 |
font-size: calc(16px * .4); |
|
2185 |
} |
|
2186 |
.avatar.s22 { |
|
2187 |
block-size: 22px; |
|
2188 |
inline-size: 22px; |
|
2189 |
} |
|
2190 |
span[role="img"].avatar.s22 { |
|
2191 |
font-size: calc(22px * .4); |
|
2192 |
} |
|
2193 |
.avatar.s24 { |
|
2194 |
block-size: 24px; |
|
2195 |
inline-size: 24px; |
|
2196 |
} |
|
2197 |
span[role="img"].avatar.s24 { |
|
2198 |
font-size: calc(24px * .4); |
|
2199 |
} |
|
2200 |
.avatar.s40 { |
|
2201 |
block-size: 40px; |
|
2202 |
inline-size: 40px; |
|
2203 |
} |
|
2204 |
span[role="img"].avatar.s40 { |
|
2205 |
font-size: calc(40px * .4); |
|
2206 |
} |
|
2207 |
.avatar.s50 { |
|
2208 |
block-size: 50px; |
|
2209 |
inline-size: 50px; |
|
2210 |
} |
|
2211 |
span[role="img"].avatar.s50 { |
|
2212 |
font-size: calc(50px * .4); |
|
2213 |
} |
|
2214 | ||
2215 |
.avatar-color-0 { |
|
2216 |
background-color: #880000; |
|
2217 |
color: #FFFFFF; |
|
2218 |
} |
|
2219 |
.avatar-color-1 { |
|
2220 |
background-color: #ff0000; |
|
2221 |
color: #000000; |
|
2222 |
} |
|
2223 |
.avatar-color-2 { |
|
2224 |
background-color: #00ff00; |
|
2225 |
color: #000000; |
|
2226 |
} |
|
2227 |
.avatar-color-3 { |
|
2228 |
background-color: #008800; |
|
2229 |
color: #FFFFFF; |
|
2230 |
} |
|
2231 |
.avatar-color-4 { |
|
2232 |
background-color: #0000ff; |
|
2233 |
color: #FFFFFF; |
|
2234 |
} |
|
2235 |
.avatar-color-5 { |
|
2236 |
background-color: #000088; |
|
2237 |
color: #FFFFFF; |
|
2238 |
} |
|
2239 |
.avatar-color-6 { |
|
2240 |
background-color: #ff8800; |
|
2241 |
color: #000000; |
|
2242 |
} |
|
2243 |
.avatar-color-7 { |
|
2244 |
background-color: #ff0088; |
|
2245 |
color: #000000; |
|
2246 |
} |
|
2247 | ||
2165 | 2248 |
/* Reaction styles */ |
2166 | 2249 |
.reaction-button:hover, .reaction-button:active { |
2167 | 2250 |
text-decoration: none; |
app/helpers/avatars_helper.rb | ||
---|---|---|
57 | 57 |
else |
58 | 58 |
nil |
59 | 59 |
end |
60 |
elsif user.respond_to?(:initials) |
|
61 |
size = options.delete(:size) || GravatarHelper::DEFAULT_OPTIONS[:size] |
|
62 |
css_class = "avatar-color-#{user.id % 8} avatar s#{size}" |
|
63 |
css_class += " #{options[:class]}" if options[:class] |
|
64 |
content_tag('span', user.initials, role: 'img', class: css_class) |
|
60 | 65 |
else |
61 | 66 |
'' |
62 | 67 |
end |
app/models/group.rb | ||
---|---|---|
53 | 53 |
name.to_s |
54 | 54 |
end |
55 | 55 | |
56 |
def initials |
|
57 |
name[0, 1] |
|
58 |
end |
|
59 | ||
56 | 60 |
def builtin_type |
57 | 61 |
nil |
58 | 62 |
end |
app/views/issues/show.html.erb | ||
---|---|---|
32 | 32 |
</div> |
33 | 33 |
<% end %> |
34 | 34 | |
35 |
<div class="gravatar-with-child">
|
|
35 |
<div class="avatar-with-child"> |
|
36 | 36 |
<%= author_avatar(@issue.author, :size => "50") %> |
37 |
<%= assignee_avatar(@issue.assigned_to, :size => "22", :class => "gravatar-child") if @issue.assigned_to %>
|
|
37 |
<%= assignee_avatar(@issue.assigned_to, :size => "22", :class => "avatar-child") if @issue.assigned_to %> |
|
38 | 38 |
</div> |
39 | 39 | |
40 | 40 |
<div data-controller="sticky-issue-header"> |
app/views/layouts/base.html.erb | ||
---|---|---|
36 | 36 |
<% end %> |
37 | 37 | |
38 | 38 |
<% if User.current.logged? %> |
39 |
<div class="flyout-menu__avatar <% if !Setting.gravatar_enabled? %>flyout-menu__avatar--no-avatar<% end %>"> |
|
40 |
<% if Setting.gravatar_enabled? %> |
|
41 |
<%= link_to(avatar(User.current, :size => "80"), user_path(User.current)) %> |
|
42 |
<% end %> |
|
43 |
<%= link_to_user(User.current, :format => :username) %> |
|
39 |
<div class="flyout-menu__avatar"> |
|
40 |
<%= link_to(avatar(User.current, :size => "40"), user_path(User.current)) %> |
|
41 |
<%= link_to_user(User.current, :format => :username) %> |
|
44 | 42 |
</div> |
45 | 43 |
<% end %> |
46 | 44 |
lib/plugins/gravatar/lib/gravatar.rb | ||
---|---|---|
32 | 32 |
:title => '', |
33 | 33 | |
34 | 34 |
# The class to assign to the img tag for the gravatar. |
35 |
:class => 'gravatar', |
|
35 |
:class => 'gravatar avatar',
|
|
36 | 36 |
} |
37 | 37 | |
38 | 38 |
# The methods that will be made available to your views. |
lib/redmine/helpers/gantt.rb | ||
---|---|---|
731 | 731 |
css_classes = +'' |
732 | 732 |
css_classes << ' issue-overdue' if issue.overdue? |
733 | 733 |
css_classes << ' issue-behind-schedule' if issue.behind_schedule? |
734 |
css_classes << ' icon icon-issue' unless Setting.gravatar_enabled? && issue.assigned_to
|
|
734 |
css_classes << ' icon icon-issue' unless issue.assigned_to |
|
735 | 735 |
css_classes << ' issue-closed' if issue.closed? |
736 | 736 |
if issue.start_date && issue.due_before && issue.done_ratio |
737 | 737 |
progress_date = calc_progress_date(issue.start_date, |
... | ... | |
740 | 740 |
css_classes << ' over-end-date' if progress_date > self.date_to && issue.done_ratio > 0 |
741 | 741 |
end |
742 | 742 |
s = (+"").html_safe |
743 |
s << view.sprite_icon('issue').html_safe unless Setting.gravatar_enabled? && issue.assigned_to
|
|
744 |
s << view.assignee_avatar(issue.assigned_to, :size => 13, :class => 'icon-gravatar')
|
|
743 |
s << view.sprite_icon('issue').html_safe unless issue.assigned_to |
|
744 |
s << view.assignee_avatar(issue.assigned_to, :size => 13, :class => 'icon-avatar') |
|
745 | 745 |
s << view.link_to_issue(issue).html_safe |
746 | 746 |
s << view.content_tag(:input, nil, :type => 'checkbox', :name => 'ids[]', |
747 | 747 |
:value => issue.id, :style => 'display:none;', |
test/functional/calendars_controller_test.rb | ||
---|---|---|
57 | 57 |
) do |
58 | 58 |
assert_select 'a.issue[href=?]', '/issues/2', :text => 'Feature request #2' |
59 | 59 |
assert_select 'span.tip' do |
60 |
assert_select 'img[class="gravatar"]' |
|
60 |
assert_select 'img[class="gravatar avatar"]'
|
|
61 | 61 |
end |
62 | 62 |
assert_select 'input[name=?][type=?][value=?]', 'ids[]', 'checkbox', '2' |
63 | 63 |
end |
test/functional/gantts_controller_test.rb | ||
---|---|---|
58 | 58 |
# Assert context menu on issues subject and gantt bar |
59 | 59 |
assert_select 'div[class=?]', 'issue-subject hascontextmenu' |
60 | 60 |
assert_select 'div.tooltip.hascontextmenu' do |
61 |
assert_select 'img[class="gravatar"]' |
|
61 |
assert_select 'img[class="gravatar avatar"]'
|
|
62 | 62 |
end |
63 | 63 |
assert_select "form[data-cm-url=?]", '/issues/context_menu' |
64 | 64 |
test/functional/issues_controller_test.rb | ||
---|---|---|
2816 | 2816 |
assert_select 'h3', {text: /Watchers \(\d*\)/, count: 0} |
2817 | 2817 |
end |
2818 | 2818 | |
2819 |
def test_show_should_display_watchers_with_gravatars
|
|
2819 |
def test_show_should_display_watchers_with_avatars |
|
2820 | 2820 |
@request.session[:user_id] = 2 |
2821 | 2821 |
issue = Issue.find(1) |
2822 | 2822 |
issue.add_watcher User.find(2) |
... | ... | |
2824 | 2824 |
with_settings :gravatar_enabled => '1' do |
2825 | 2825 |
get(:show, :params => {:id => 1}) |
2826 | 2826 |
end |
2827 | ||
2827 | 2828 |
assert_select 'div#watchers ul' do |
2828 | 2829 |
assert_select 'li.user-2' do |
2829 |
assert_select 'img.gravatar[title=?]', 'John Smith'
|
|
2830 |
assert_select '.avatar[title=?]', 'John Smith'
|
|
2830 | 2831 |
assert_select 'a[href="/users/2"]' |
2831 | 2832 |
assert_select 'a[class*=delete]' |
2832 | 2833 |
end |
... | ... | |
8786 | 8787 |
assert_select 'a[href=?][onclick=?]', "/issues/1", "", :text => 'Cancel' |
8787 | 8788 |
end |
8788 | 8789 | |
8789 |
def test_show_should_display_author_gravatar_only_when_not_assigned
|
|
8790 |
def test_show_should_display_author_avatar_only_when_not_assigned |
|
8790 | 8791 |
issue = Issue.find(1) |
8791 | 8792 |
assert_nil issue.assigned_to_id |
8792 | 8793 |
@request.session[:user_id] = 1 |
8793 | 8794 | |
8794 |
with_settings :gravatar_enabled => '1' do |
|
8795 |
get :show, :params => {:id => issue.id} |
|
8796 |
assert_select 'div.gravatar-with-child' do |
|
8797 |
assert_select 'img.gravatar', 1 |
|
8798 |
end |
|
8795 |
get :show, :params => {:id => issue.id} |
|
8796 |
assert_select 'div.avatar-with-child' do |
|
8797 |
assert_select '.avatar', 1 |
|
8799 | 8798 |
end |
8800 | 8799 |
end |
8801 | 8800 | |
8802 |
def test_show_should_display_author_and_assignee_gravatars_when_assigned
|
|
8801 |
def test_show_should_display_author_and_assignee_avatars_when_assigned |
|
8803 | 8802 |
issue = Issue.find(1) |
8804 | 8803 |
issue.assigned_to_id = 2 |
8805 | 8804 |
issue.save! |
8806 | 8805 |
@request.session[:user_id] = 1 |
8807 | 8806 | |
8808 |
with_settings :gravatar_enabled => '1' do |
|
8809 |
get :show, :params => {:id => issue.id} |
|
8810 |
assert_select 'div.gravatar-with-child' do |
|
8811 |
assert_select 'img.gravatar', 2 |
|
8812 |
assert_select 'img.gravatar-child', 1 |
|
8813 |
end |
|
8807 |
get :show, :params => {:id => issue.id} |
|
8808 |
assert_select 'div.avatar-with-child' do |
|
8809 |
assert_select '.avatar', 2 |
|
8810 |
assert_select '.avatar-child', 1 |
|
8814 | 8811 |
end |
8815 | 8812 |
end |
8816 | 8813 |
test/functional/messages_controller_test.rb | ||
---|---|---|
28 | 28 |
get(:show, :params => {:board_id => 1, :id => 1}) |
29 | 29 |
assert_response :success |
30 | 30 | |
31 |
assert_select 'h2', :text => 'First post'
|
|
31 |
assert_select 'h2', :text => "RAFirst post"
|
|
32 | 32 |
end |
33 | 33 | |
34 | 34 |
def test_show_should_contain_reply_field_tags_for_quoting |
test/functional/news_controller_test.rb | ||
---|---|---|
75 | 75 |
get(:show, :params => {:id => 1}) |
76 | 76 |
assert_response :success |
77 | 77 |
assert_select 'p.breadcrumb a[href=?]', '/projects/ecookbook/news', :text => 'News' |
78 |
assert_select 'h2', :text => 'eCookbook first release !' |
|
78 |
assert_select 'h2', :text => 'JS eCookbook first release !'
|
|
79 | 79 |
end |
80 | 80 | |
81 | 81 |
def test_show_should_show_attachments |
test/helpers/application_helper_test.rb | ||
---|---|---|
2053 | 2053 |
end |
2054 | 2054 |
end |
2055 | 2055 | |
2056 |
def test_principals_check_box_tag_without_avatar |
|
2057 |
principals = [User.find(1), Group.find(10)] |
|
2058 |
Setting.gravatar_enabled = '1' |
|
2059 |
avatar_tags = principals.collect{|p| avatar(p, :size => 16)} |
|
2060 | ||
2061 |
with_settings :gravatar_enabled => '0' do |
|
2062 |
tags = principals_check_box_tags(name, principals) |
|
2063 |
principals.each_with_index do |principal, i| |
|
2064 |
assert_not_include avatar_tags[i], tags |
|
2065 |
assert_include content_tag('span', principal_icon(principal), :class => "name icon icon-#{principal.class.name.downcase}"), tags |
|
2066 |
end |
|
2067 |
end |
|
2068 |
end |
|
2069 | ||
2070 | 2056 |
def test_principals_options_for_select_with_users |
2071 | 2057 |
User.current = nil |
2072 | 2058 |
users = [User.find(2), User.find(4)] |
test/helpers/avatars_helper_test.rb | ||
---|---|---|
63 | 63 |
end |
64 | 64 | |
65 | 65 |
def test_avatar_css_class |
66 |
# The default class of the img tag should be gravatar
|
|
67 |
assert_include 'class="gravatar"', avatar('jsmith <jsmith@somenet.foo>') |
|
68 |
assert_include 'class="gravatar picture"', avatar('jsmith <jsmith@somenet.foo>', :class => 'picture') |
|
66 |
# The default classes of the img tag should be gravatar and avatar
|
|
67 |
assert_include 'class="gravatar avatar"', avatar('jsmith <jsmith@somenet.foo>')
|
|
68 |
assert_include 'class="gravatar avatar picture"', avatar('jsmith <jsmith@somenet.foo>', :class => 'picture')
|
|
69 | 69 |
end |
70 | 70 | |
71 | 71 |
def test_avatar_with_initials |
... | ... | |
80 | 80 |
end |
81 | 81 |
end |
82 | 82 | |
83 |
def test_avatar_disabled |
|
83 |
def test_avatar_disabled_should_display_user_initials
|
|
84 | 84 |
with_settings :gravatar_enabled => '0' do |
85 |
assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
|
|
85 |
assert_equal "<span role=\"img\" class=\"avatar-color-2 avatar s24\">JS</span>", avatar(User.find_by_mail('jsmith@somenet.foo'))
|
|
86 | 86 |
end |
87 | 87 |
end |
88 | 88 |
test/integration/api_test/authentication_test.rb | ||
---|---|---|
127 | 127 |
assert_response :unauthorized |
128 | 128 |
end |
129 | 129 | |
130 |
# TODO: check why this test does not use the API endpoint |
|
130 | 131 |
def test_api_should_accept_switch_user_header_for_admin_user |
131 | 132 |
user = User.find(1) |
132 | 133 |
su = User.find(4) |
133 | 134 | |
134 | 135 |
get '/users/current', :headers => {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login} |
135 | 136 |
assert_response :success |
136 |
assert_select 'h2', :text => su.name
|
|
137 |
assert_select 'h2', :text => "#{su.initials} #{su.name}"
|
|
137 | 138 |
end |
138 | 139 | |
140 |
# TODO: check why this test does not use the API endpoint |
|
139 | 141 |
def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user |
140 | 142 |
get '/users/current', :headers => {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => 'foobar'} |
141 | 143 |
assert_response :precondition_failed |
142 | 144 |
end |
143 | 145 | |
146 |
# TODO: check why this test does not use the API endpoint |
|
144 | 147 |
def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user |
145 | 148 |
user = User.find(5) |
146 | 149 |
assert user.locked? |
... | ... | |
149 | 152 |
assert_response :precondition_failed |
150 | 153 |
end |
151 | 154 | |
155 |
# TODO: check why this test does not use the API endpoint |
|
152 | 156 |
def test_api_should_not_accept_switch_user_header_for_non_admin_user |
153 | 157 |
user = User.find(2) |
154 | 158 |
su = User.find(4) |
155 | 159 | |
156 | 160 |
get '/users/current', :headers => {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login} |
157 | 161 |
assert_response :success |
158 |
assert_select 'h2', :text => user.name
|
|
162 |
assert_select 'h2', :text => "#{user.initials} #{user.name}"
|
|
159 | 163 |
end |
160 | 164 |
end |
- « Previous
- 1
- …
- 3
- 4
- 5
- Next »