Feature #23980 » font_awesome_icons.patch
| Gemfile | ||
|---|---|---|
| 18 | 18 |
# Request at least nokogiri 1.6.7.2 because of security advisories |
| 19 | 19 |
gem "nokogiri", ">= 1.6.7.2" |
| 20 | 20 | |
| 21 |
# Request at least rails-html-sanitizer 1.0.3 because of security advisories
|
|
| 21 |
# Request at least rails-html-sanitizer 1.0.3 because of security advisories |
|
| 22 | 22 |
gem "rails-html-sanitizer", ">= 1.0.3" |
| 23 | 23 | |
| 24 | 24 |
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem |
| app/helpers/application_helper.rb | ||
|---|---|---|
| 1358 | 1358 |
encoding = l(:general_csv_encoding) |
| 1359 | 1359 |
end |
| 1360 | 1360 | |
| 1361 |
# Creates an icon tag given an icon name and possible icon |
|
| 1362 |
# modifiers. |
|
| 1363 |
# |
|
| 1364 |
# Examples |
|
| 1365 |
# |
|
| 1366 |
# fa_icon "camera-retro" |
|
| 1367 |
# # => <i class="fa fa-camera-retro"></i> |
|
| 1368 |
# |
|
| 1369 |
# fa_icon "camera-retro", text: "Take a photo" |
|
| 1370 |
# # => <i class="fa fa-camera-retro"></i> Take a photo |
|
| 1371 |
# fa_icon "chevron-right", text: "Get started", right: true |
|
| 1372 |
# # => Get started <i class="fa fa-chevron-right"></i> |
|
| 1373 |
# |
|
| 1374 |
# fa_icon "camera-retro 2x" |
|
| 1375 |
# # => <i class="fa fa-camera-retro fa-2x"></i> |
|
| 1376 |
# fa_icon ["camera-retro", "4x"] |
|
| 1377 |
# # => <i class="fa fa-camera-retro fa-4x"></i> |
|
| 1378 |
# fa_icon "spinner spin lg" |
|
| 1379 |
# # => <i class="fa fa-spinner fa-spin fa-lg"> |
|
| 1380 |
# |
|
| 1381 |
# fa_icon "quote-left 4x", class: "pull-left" |
|
| 1382 |
# # => <i class="fa fa-quote-left fa-4x pull-left"></i> |
|
| 1383 |
# |
|
| 1384 |
# fa_icon "user", data: { id: 123 }
|
|
| 1385 |
# # => <i class="fa fa-user" data-id="123"></i> |
|
| 1386 |
# |
|
| 1387 |
# content_tag(:li, fa_icon("check li", text: "Bulleted list item"))
|
|
| 1388 |
# # => <li><i class="fa fa-check fa-li"></i> Bulleted list item</li> |
|
| 1389 |
def fa_icon(names = "flag", options = {})
|
|
| 1390 |
classes = ["fa"] |
|
| 1391 |
classes.concat icon_names(names) |
|
| 1392 |
classes.concat Array(options.delete(:class)) |
|
| 1393 |
text = options.delete(:text) |
|
| 1394 |
icon_only = options.delete(:icon_only) |
|
| 1395 |
right_icon = options.delete(:right) |
|
| 1396 |
icon = content_tag(:i, nil, options.merge(:class => classes)) |
|
| 1397 |
icon_join(icon, text, right_icon, icon_only) |
|
| 1398 |
end |
|
| 1399 | ||
| 1400 |
# Creates an stack set of icon tags given a base icon name, a main icon |
|
| 1401 |
# name, and possible icon modifiers. |
|
| 1402 |
# |
|
| 1403 |
# Examples |
|
| 1404 |
# |
|
| 1405 |
# fa_stacked_icon "twitter", base: "square-o" |
|
| 1406 |
# # => <span class="fa-stack"> |
|
| 1407 |
# # => <i class="fa fa-square-o fa-stack-2x"></i> |
|
| 1408 |
# # => <i class="fa fa-twitter fa-stack-1x"></i> |
|
| 1409 |
# # => </span> |
|
| 1410 |
# |
|
| 1411 |
# fa_stacked_icon "terminal inverse", base: "square", class: "pull-right", text: "Hi!" |
|
| 1412 |
# # => <span class="fa-stack pull-right"> |
|
| 1413 |
# # => <i class="fa fa-square fa-stack-2x"></i> |
|
| 1414 |
# # => <i class="fa fa-terminal fa-inverse fa-stack-1x"></i> |
|
| 1415 |
# # => </span> Hi! |
|
| 1416 |
# |
|
| 1417 |
# fa_stacked_icon "camera", base: "ban-circle", reverse: true |
|
| 1418 |
# # => <span class="fa-stack"> |
|
| 1419 |
# # => <i class="fa fa-camera fa-stack-1x"></i> |
|
| 1420 |
# # => <i class="fa fa-ban-circle fa-stack-2x"></i> |
|
| 1421 |
# # => </span> |
|
| 1422 |
def fa_stacked_icon(names = "flag", options = {})
|
|
| 1423 |
classes = icon_names("stack").concat(Array(options.delete(:class)))
|
|
| 1424 |
base_names = array_value(options.delete(:base) || "square-o").push("stack-2x")
|
|
| 1425 |
names = array_value(names).push("stack-1x")
|
|
| 1426 |
base = fa_icon(base_names, options.delete(:base_options) || {})
|
|
| 1427 |
icon = fa_icon(names, options.delete(:icon_options) || {})
|
|
| 1428 |
icons = [base, icon] |
|
| 1429 |
icons.reverse! if options.delete(:reverse) |
|
| 1430 |
text = options.delete(:text) |
|
| 1431 |
right_icon = options.delete(:right) |
|
| 1432 |
icon_only = options.delete(:icon_only) |
|
| 1433 |
stacked_icon = content_tag(:span, safe_join(icons), options.merge(:class => classes)) |
|
| 1434 |
icon_join(stacked_icon, text, right_icon, icon_only) |
|
| 1435 |
end |
|
| 1436 | ||
| 1361 | 1437 |
private |
| 1362 | 1438 | |
| 1363 | 1439 |
def wiki_helper |
| ... | ... | |
| 1365 | 1441 |
extend helper |
| 1366 | 1442 |
return self |
| 1367 | 1443 |
end |
| 1444 | ||
| 1445 |
def icon_join(icon, text, reverse_order = false, icon_only = false) |
|
| 1446 |
return icon if text.blank? |
|
| 1447 |
text = icon_only ? content_tag("span", text, :class => "sr-only") : ERB::Util.html_escape(text)
|
|
| 1448 |
elements = [icon, text] |
|
| 1449 |
elements.reverse! if reverse_order |
|
| 1450 |
safe_join(elements, " ") |
|
| 1451 |
end |
|
| 1452 | ||
| 1453 |
def icon_names(names = []) |
|
| 1454 |
array_value(names).map { |n| "fa-#{n}" }
|
|
| 1455 |
end |
|
| 1456 | ||
| 1457 |
def array_value(value = []) |
|
| 1458 |
value.is_a?(Array) ? value : value.to_s.split(/\s+/) |
|
| 1459 |
end |
|
| 1368 | 1460 |
end |
| app/helpers/journals_helper.rb | ||
|---|---|---|
| 30 | 30 |
css_classes = "wiki" |
| 31 | 31 |
links = [] |
| 32 | 32 |
if journal.notes.present? |
| 33 |
links << link_to(l(:button_quote),
|
|
| 33 |
links << link_to(fa_icon("quote-left", :text => l(:label_quote), :icon_only => true),
|
|
| 34 | 34 |
quoted_issue_path(issue, :journal_id => journal), |
| 35 | 35 |
:remote => true, |
| 36 | 36 |
:method => 'post', |
| 37 | 37 |
:title => l(:button_quote), |
| 38 |
:class => 'icon-only icon-comment'
|
|
| 38 |
:class => 'icon' |
|
| 39 | 39 |
) if options[:reply_links] |
| 40 | 40 | |
| 41 | 41 |
if journal.editable_by?(User.current) |
| 42 |
links << link_to(l(:button_edit),
|
|
| 42 |
links << link_to(fa_icon("pencil", :text => l(:label_edit), :icon_only => true),
|
|
| 43 | 43 |
edit_journal_path(journal), |
| 44 | 44 |
:remote => true, |
| 45 | 45 |
:method => 'get', |
| 46 | 46 |
:title => l(:button_edit), |
| 47 |
:class => 'icon-only icon-edit'
|
|
| 47 |
:class => 'icon' |
|
| 48 | 48 |
) |
| 49 |
links << link_to(l(:button_delete),
|
|
| 49 |
links << link_to(fa_icon("trash", :text => l(:label_delete), :icon_only => true),
|
|
| 50 | 50 |
journal_path(journal, :journal => {:notes => ""}),
|
| 51 | 51 |
:remote => true, |
| 52 |
:method => 'put', :data => {:confirm => l(:text_are_you_sure)},
|
|
| 52 |
:method => 'put', :data => {:confirm => l(:text_are_you_sure)},
|
|
| 53 | 53 |
:title => l(:button_delete), |
| 54 |
:class => 'icon-only icon-del'
|
|
| 54 |
:class => 'icon' |
|
| 55 | 55 |
) |
| 56 | 56 |
css_classes << " editable" |
| 57 | 57 |
end |
| app/helpers/watchers_helper.rb | ||
|---|---|---|
| 25 | 25 |
return '' unless objects.any? |
| 26 | 26 | |
| 27 | 27 |
watched = Watcher.any_watched?(objects, user) |
| 28 |
css = [watcher_css(objects), watched ? 'icon icon-fav' : 'icon icon-fav-off'].join(' ')
|
|
| 29 |
text = watched ? l(:button_unwatch) : l(:button_watch)
|
|
| 28 |
css = [watcher_css(objects), watched ? 'icon' : 'icon'].join(' ')
|
|
| 29 |
text = watched ? fa_icon("star", :text => l(:button_unwatch)) : fa_icon("star-o", :text => l(:button_watch))
|
|
| 30 | 30 |
url = watch_path( |
| 31 | 31 |
:object_type => objects.first.class.to_s.underscore, |
| 32 | 32 |
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort) |
| ... | ... | |
| 58 | 58 |
:object_id => object.id, |
| 59 | 59 |
:user_id => user} |
| 60 | 60 |
s << ' ' |
| 61 |
s << link_to(l(:button_delete), url,
|
|
| 61 |
s << link_to(fa_icon("trash", :text => l(:button_delete), :icon_only => true), url,
|
|
| 62 | 62 |
:remote => true, :method => 'delete', |
| 63 |
:class => "delete icon-only icon-del",
|
|
| 63 |
:class => "delete icon", |
|
| 64 | 64 |
:title => l(:button_delete)) |
| 65 | 65 |
end |
| 66 | 66 |
content << content_tag('li', s, :class => "user-#{user.id}")
|
| app/views/attachments/_links.html.erb | ||
|---|---|---|
| 1 | 1 |
<div class="attachments"> |
| 2 | 2 |
<div class="contextual"> |
| 3 |
<%= link_to(l(:label_edit_attachments),
|
|
| 3 |
<%= link_to(fa_icon("pencil", :text => l(:label_edit_attachments), :icon_only => true),
|
|
| 4 | 4 |
container_attachments_edit_path(container), |
| 5 | 5 |
:title => l(:label_edit_attachments), |
| 6 |
:class => 'icon-only icon-edit'
|
|
| 6 |
:class => 'icon' |
|
| 7 | 7 |
) if options[:editable] %> |
| 8 | 8 |
</div> |
| 9 | 9 |
<% for attachment in attachments %> |
| 10 |
<p><%= link_to_attachment attachment, :class => 'icon icon-attachment', :download => true -%>
|
|
| 10 |
<p><%= link_to_attachment attachment, :class => 'icon', :download => true -%> |
|
| 11 | 11 |
<% if attachment.is_text? || attachment.is_image? %> |
| 12 |
<%= link_to l(:button_view),
|
|
| 12 |
<%= link_to fa_icon("search", :text => l(:button_view), :icon_only => true),
|
|
| 13 | 13 |
{ :controller => 'attachments', :action => 'show',
|
| 14 | 14 |
:id => attachment, :filename => attachment.filename }, |
| 15 |
:class => 'icon-only icon-magnifier',
|
|
| 15 |
:class => 'icon', |
|
| 16 | 16 |
:title => l(:button_view) %> |
| 17 | 17 |
<% end %> |
| 18 | 18 |
<%= " - #{attachment.description}" unless attachment.description.blank? %>
|
| 19 | 19 |
<span class="size">(<%= number_to_human_size attachment.filesize %>)</span> |
| 20 | 20 |
<% if options[:deletable] %> |
| 21 |
<%= link_to l(:button_delete), attachment_path(attachment),
|
|
| 21 |
<%= link_to fa_icon("trash", :text => l(:button_delete), :icon_only => true), attachment_path(attachment),
|
|
| 22 | 22 |
:data => {:confirm => l(:text_are_you_sure)},
|
| 23 | 23 |
:method => :delete, |
| 24 |
:class => 'delete icon-only icon-del',
|
|
| 24 |
:class => 'delete icon', |
|
| 25 | 25 |
:title => l(:button_delete) %> |
| 26 | 26 |
<% end %> |
| 27 | 27 |
<% if options[:author] %> |
| app/views/issues/_action_menu.html.erb | ||
|---|---|---|
| 1 | 1 |
<div class="contextual"> |
| 2 |
<%= link_to l(:button_edit), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit) if @issue.editable? %>
|
|
| 3 |
<%= link_to l(:button_log_time), new_issue_time_entry_path(@issue), :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project) %>
|
|
| 2 |
<%= link_to fa_icon("pencil", :text => l(:button_edit)), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', :class => 'icon', :accesskey => accesskey(:edit) if @issue.editable? %>
|
|
| 3 |
<%= link_to fa_icon("clock-o", :text => l(:button_log_time)), new_issue_time_entry_path(@issue), :class => 'icon' if User.current.allowed_to?(:log_time, @project) %>
|
|
| 4 | 4 |
<%= watcher_link(@issue, User.current) %> |
| 5 |
<%= link_to l(:button_copy), project_copy_issue_path(@project, @issue), :class => 'icon icon-copy' if User.current.allowed_to?(:copy_issues, @project) && Issue.allowed_target_projects.any? %>
|
|
| 6 |
<%= link_to l(:button_delete), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if @issue.deletable? %>
|
|
| 5 |
<%= link_to fa_icon("clone", :text => l(:button_copy)), project_copy_issue_path(@project, @issue), :class => 'icon' if User.current.allowed_to?(:copy_issues, @project) && Issue.allowed_target_projects.any? %>
|
|
| 6 |
<%= link_to fa_icon("trash", :text => l(:button_delete)), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon' if @issue.deletable? %>
|
|
| 7 | 7 |
</div> |
| app/views/issues/_relations.html.erb | ||
|---|---|---|
| 19 | 19 |
<td class="status"><%= other_issue.status.name %></td> |
| 20 | 20 |
<td class="start_date"><%= format_date(other_issue.start_date) %></td> |
| 21 | 21 |
<td class="due_date"><%= format_date(other_issue.due_date) %></td> |
| 22 |
<td class="buttons"><%= link_to(l(:label_relation_delete),
|
|
| 22 |
<td class="buttons"><%= link_to(fa_icon("chain-broken", :text => l(:label_relation_delete), :icon_only => true),
|
|
| 23 | 23 |
relation_path(relation), |
| 24 | 24 |
:remote => true, |
| 25 | 25 |
:method => :delete, |
| 26 | 26 |
:data => {:confirm => l(:text_are_you_sure)},
|
| 27 | 27 |
:title => l(:label_relation_delete), |
| 28 |
:class => 'icon-only icon-link-break'
|
|
| 28 |
:class => 'icon' |
|
| 29 | 29 |
) if User.current.allowed_to?(:manage_issue_relations, @project) %></td> |
| 30 | 30 |
</tr> |
| 31 | 31 |
<% end %> |
| app/views/issues/show.html.erb | ||
|---|---|---|
| 37 | 37 |
<%= issue_fields_rows do |rows| |
| 38 | 38 |
rows.left l(:field_status), @issue.status.name, :class => 'status' |
| 39 | 39 |
rows.left l(:field_priority), @issue.priority.name, :class => 'priority' |
| 40 | ||
| 41 | 40 |
unless @issue.disabled_core_fields.include?('assigned_to_id')
|
| 42 | 41 |
rows.left l(:field_assigned_to), avatar(@issue.assigned_to, :size => "14").to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to' |
| 43 | 42 |
end |
| ... | ... | |
| 47 | 46 |
unless @issue.disabled_core_fields.include?('fixed_version_id') || (@issue.fixed_version.nil? && @issue.assignable_versions.none?)
|
| 48 | 47 |
rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version' |
| 49 | 48 |
end |
| 50 | ||
| 51 | 49 |
unless @issue.disabled_core_fields.include?('start_date')
|
| 52 | 50 |
rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date' |
| 53 | 51 |
end |
| ... | ... | |
| 77 | 75 |
<% if @issue.description? %> |
| 78 | 76 |
<div class="description"> |
| 79 | 77 |
<div class="contextual"> |
| 80 |
<%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if @issue.notes_addable? %>
|
|
| 78 |
<%= link_to fa_icon("quote-left", :text => l(:button_quote)), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon' if @issue.notes_addable? %>
|
|
| 81 | 79 |
</div> |
| 82 | 80 | |
| 83 | 81 |
<p><strong><%=l(:field_description)%></strong></p> |
| app/views/layouts/base.html.erb | ||
|---|---|---|
| 16 | 16 |
<%= call_hook :view_layouts_base_html_head %> |
| 17 | 17 |
<!-- page specific tags --> |
| 18 | 18 |
<%= yield :header_tags -%> |
| 19 |
<script src="https://use.fontawesome.com/185de4555c.js"></script> |
|
| 19 | 20 |
</head> |
| 20 | 21 |
<body class="<%= body_css_classes %>"> |
| 21 | 22 |
<%= call_hook :view_layouts_base_body_top %> |
| public/stylesheets/application.css | ||
|---|---|---|
| 1128 | 1128 |
.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
|
| 1129 | 1129 | |
| 1130 | 1130 |
/***** Icons *****/ |
| 1131 |
.icon {
|
|
| 1132 |
background-position: 0% 50%; |
|
| 1133 |
background-repeat: no-repeat; |
|
| 1134 |
padding-left: 20px; |
|
| 1135 |
padding-top: 2px; |
|
| 1136 |
padding-bottom: 3px; |
|
| 1137 |
} |
|
| 1131 |
.icon {}
|
|
| 1138 | 1132 |
.icon-only {
|
| 1139 | 1133 |
background-position: 0% 50%; |
| 1140 | 1134 |
background-repeat: no-repeat; |
| ... | ... | |
| 1387 | 1381 |
height:1px; |
| 1388 | 1382 |
overflow:hidden; |
| 1389 | 1383 |
} |
| 1384 | ||
| 1385 |
a.icon i.fa {
|
|
| 1386 |
font-size: 13px; |
|
| 1387 |
} |
|