From a3d0ba8f4244044e89d515d55f20156a010fb311 Mon Sep 17 00:00:00 2001 From: Marius BALTEANU Date: Sun, 10 Oct 2021 20:39:04 +0300 Subject: [PATCH] Replace icon images with inline SVG icons. diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 15aa665a0..d6694c815 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -28,9 +28,11 @@ class ApplicationController < ActionController::Base include Redmine::Hook::Helper include RoutesHelper include AvatarsHelper + include IconsHelper helper :routes helper :avatars + helper :icons class_attribute :accept_api_auth_actions class_attribute :accept_rss_auth_actions diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 03fb26d4c..b0210c216 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -126,9 +126,14 @@ module ApplicationHelper # * :download - Force download (default: false) def link_to_attachment(attachment, options={}) text = options.delete(:text) || attachment.filename + icon = 'paperclip' + icon_only = false + if options.delete(:download) route_method = :download_named_attachment_url options[:filename] = attachment.filename + icon = 'download' + icon_only = true else route_method = :attachment_url # make sure we don't have an extraneous :filename in the options @@ -137,7 +142,7 @@ module ApplicationHelper html_options = options.slice!(:only_path, :filename) options[:only_path] = true unless options.key?(:only_path) url = send(route_method, attachment, options) - link_to text, url, html_options + link_to labeled_icon(text, icon, icon_only: icon_only, size: 12), url, html_options end # Generates a link to a SCM revision @@ -797,7 +802,7 @@ module ApplicationHelper content = capture(&block) if content.present? trigger = - content_tag('span', l(:button_actions), :class => 'icon-only icon-actions', + content_tag('span', labeled_icon(l(:button_actions), 'ellipsis-h', icon_only: true), :class => 'icon icon-actions icon-svg', :title => l(:button_actions)) trigger = content_tag('span', trigger, :class => 'drdn-trigger') content = content_tag('div', content, :class => 'drdn-items') @@ -1832,8 +1837,8 @@ module ApplicationHelper def copy_object_url_link(url) link_to_function( - l(:button_copy_link), 'copyTextToClipboard(this);', - class: 'icon icon-copy-link', + labeled_icon(l(:button_copy_link), 'link'), 'copyTextToClipboard(this);', + class: 'icon icon-copy-link icon-svg', data: {'clipboard-text' => url} ) end diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb new file mode 100644 index 000000000..1021534bf --- /dev/null +++ b/app/helpers/icons_helper.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module IconsHelper + DEFAULT_ICON_SIZE = 14 + DEFAULT_ICON_PATH = 'public/svgs' + + def labeled_icon(label, icon_name = nil, size: DEFAULT_ICON_SIZE, css_class: nil, icon_only: false, path: DEFAULT_ICON_PATH) + css_classes = [] + css_classes << "s#{size}" if size + css_classes << "#{css_class}" unless css_class.blank? + + svg = svg_file(icon_name, css_classes, path) + + if icon_only + svg + else + svg + label + end + end + + private + + def svg_file(icon, css_class, path) + file_path = "#{Rails.root}/#{path}/#{icon}.svg" + + if File.exists?(file_path) + # cache { File.read(file_path).html_safe } + file = File.read(file_path) + + doc = Nokogiri::HTML::DocumentFragment.parse file + svg = doc.at_css 'svg' + svg["class"] = css_class.join(' ') + else + doc = "" + end + + raw doc + end +end diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb index d95d2b77b..067e5a106 100644 --- a/app/helpers/journals_helper.rb +++ b/app/helpers/journals_helper.rb @@ -34,27 +34,27 @@ module JournalsHelper dropbown_links << copy_object_url_link(issue_url(issue, anchor: "note-#{indice}", only_path: false)) if journal.notes.present? if options[:reply_links] - links << link_to(l(:button_quote), + links << link_to(labeled_icon(l(:button_quote), 'quote-left', icon_only: true), quoted_issue_path(issue, :journal_id => journal, :journal_indice => indice), :remote => true, :method => 'post', :title => l(:button_quote), - :class => 'icon-only icon-comment' + :class => 'icon-only icon-comment icon-svg' ) end if journal.editable_by?(User.current) - links << link_to(l(:button_edit), + links << link_to(labeled_icon(l(:button_edit), 'pen-alt', icon_only: true), edit_journal_path(journal), :remote => true, :method => 'get', :title => l(:button_edit), - :class => 'icon-only icon-edit' + :class => 'icon-only icon-edit icon-svg' ) - dropbown_links << link_to(l(:button_delete), + dropbown_links << link_to(labeled_icon(l(:button_delete), 'trash-alt'), journal_path(journal, :journal => {:notes => ""}), :remote => true, :method => 'put', :data => {:confirm => l(:text_are_you_sure)}, - :class => 'icon icon-del' + :class => 'icon icon-del icon-svg' ) end end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index d00c5b776..f4a891a05 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -26,15 +26,16 @@ module WatchersHelper return '' unless objects.any? watched = Watcher.any_watched?(objects, user) - css = [watcher_css(objects), watched ? 'icon icon-fav' : 'icon icon-fav-off'].join(' ') + css = [watcher_css(objects), watched ? 'icon icon-fav' : 'icon icon-fav-off icon-svg'].join(' ') text = watched ? l(:button_unwatch) : l(:button_watch) url = watch_path( :object_type => objects.first.class.to_s.underscore, :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort) ) method = watched ? 'delete' : 'post' + icon = watched ? 'star' : 'star-off' - link_to text, url, :remote => true, :method => method, :class => css + link_to labeled_icon(text, icon), url, :remote => true, :method => method, :class => css end # Returns the css class used to identify watch links for a given +object+ diff --git a/app/views/attachments/_links.html.erb b/app/views/attachments/_links.html.erb index 25d022029..dbb777b44 100644 --- a/app/views/attachments/_links.html.erb +++ b/app/views/attachments/_links.html.erb @@ -1,23 +1,23 @@
- <%= link_to(l(:label_edit_attachments), + <%= link_to(labeled_icon(l(:label_edit_attachments), 'pen-alt', icon_only: true), container_attachments_edit_path(container), :title => l(:label_edit_attachments), - :class => 'icon-only icon-edit' + :class => 'icon-only icon-edit icon-svg' ) if options[:editable] %> - <%= link_to(l(:label_download_all_attachments), + <%= link_to(labeled_icon(l(:label_download_all_attachments), 'download', icon_only: true), container_attachments_download_path(container), :title => l(:label_download_all_attachments), - :class => 'icon-only icon-download' + :class => 'icon-only icon-download icon-svg' ) if attachments.size > 1 %>
<% for attachment in attachments %> diff --git a/app/views/issues/_action_menu.html.erb b/app/views/issues/_action_menu.html.erb index 1c0dd0545..bc8352524 100644 --- a/app/views/issues/_action_menu.html.erb +++ b/app/views/issues/_action_menu.html.erb @@ -1,16 +1,16 @@
-<%= link_to l(:button_edit), edit_issue_path(@issue), +<%= link_to labeled_icon(l(:button_edit), 'pen-alt'), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', - :class => 'icon icon-edit', :accesskey => accesskey(:edit) if @issue.editable? %> -<%= 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) %> + :class => 'icon icon-edit icon-svg', :accesskey => accesskey(:edit) if @issue.editable? %> +<%= link_to labeled_icon(l(:button_log_time), 'time-add'), new_issue_time_entry_path(@issue), + :class => 'icon icon-time-add icon-svg' if User.current.allowed_to?(:log_time, @project) %> <%= watcher_link(@issue, User.current) %> -<%= 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? %> +<%= link_to labeled_icon(l(:button_copy), 'copy'), project_copy_issue_path(@project, @issue), + :class => 'icon icon-copy icon-svg' if User.current.allowed_to?(:copy_issues, @project) && Issue.allowed_target_projects.any? %> <%= actions_dropdown do %> <%= copy_object_url_link(issue_url(@issue, only_path: false)) %> - <%= link_to l(:button_delete), issue_path(@issue), + <%= link_to labeled_icon(l(:button_delete), 'trash-alt'), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, - :method => :delete, :class => 'icon icon-del' if @issue.deletable? %> + :method => :delete, :class => 'icon icon-del icon-svg' if @issue.deletable? %> <% end %>
diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb index 880c953ea..bc7c4780d 100644 --- a/app/views/issues/index.html.erb +++ b/app/views/issues/index.html.erb @@ -1,6 +1,6 @@
<% if User.current.allowed_to?(:add_issues, @project, :global => true) && (@project.nil? || Issue.allowed_target_trackers(@project).any?) %> - <%= link_to l(:label_issue_new), _new_project_issue_path(@project), :class => 'icon icon-add new-issue' %> + <%= link_to labeled_icon(l(:label_issue_new), 'plus-circle'), _new_project_issue_path(@project), :class => 'icon icon-svg icon-add new-issue' %> <% end %> <%= actions_dropdown do %> <% if @project %> diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb index 390728ada..3125e7777 100644 --- a/app/views/issues/show.html.erb +++ b/app/views/issues/show.html.erb @@ -83,7 +83,7 @@ end %>
- <%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if @issue.notes_addable? %> + <%= link_to labeled_icon(l(:button_quote), 'quote-left'), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment icon-svg' if @issue.notes_addable? %>

<%=l(:field_description)%>

diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 791ef4c23..1e62d6f59 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -223,8 +223,8 @@ div + .drdn-items {border-top:1px solid #ccc;} .contextual .drdn-content {top:18px;} .contextual .drdn-items {padding:2px; min-width: 160px;} -.contextual .drdn-items>a {padding: 5px 8px;} -.contextual .drdn-items>a.icon {padding-left: 24px; background-position-x: 4px;} +.contextual .drdn-items>a {display: flex; padding: 5px 8px;} +.contextual .drdn-items>a.icon:not(.icon-svg) {padding-left: 24px; background-position-x: 4px;} .contextual .drdn-items>a:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;} #project-jump.drdn {width:200px;display:inline-block;} @@ -464,7 +464,7 @@ div.square { width: .6em; height: .6em; } .contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;} -.contextual .icon {padding-top: 2px; padding-bottom: 3px;} +.contextual .icon:not(.icon-svg) {padding-top: 2px; padding-bottom: 3px;} .contextual input, .contextual select {font-size:0.9em;} .message .contextual { margin-top: 0; } @@ -1497,37 +1497,48 @@ td.gantt_selected_column .gantt_hdr,.gantt_selected_column_container { white-space: pre-wrap; } +/***** SVGs ******/ +.s16 { + width: 16px; + height: 16px; +} + +.s14 { + width: 14px; + height: 14px; +} + +.s12 { + width: 12px; + height: 12px; +} + /***** Icons *****/ -.icon { +.icon:not(.icon-svg) { background-position: 0% 50%; background-repeat: no-repeat; padding-left: 20px; } -.icon-only { - background-position: 0% 50%; - background-repeat: no-repeat; - padding-left: 16px; - display: inline-block; - width: 0; - height: 16px; - overflow: hidden; - padding-top: 0; - padding-bottom: 0; - font-size: 8px; - vertical-align: middle; +.icon.icon-svg { + display: inline-flex; } -.icon-only::after { - content: "\a0"; + +a svg, .icon svg { + fill: #169; + margin-right: 4px; } -.icon-add { background-image: url(../images/add.png); } -.icon-edit { background-image: url(../images/edit.png); } -.icon-copy { background-image: url(../images/copy.png); } + +/*.icon-fav svg { fill: #fc8c12; }*/ + +.icon-add:not(.icon-svg) { background-image: url(../images/add.png); } +.icon-edit:not(.icon-svg) { background-image: url(../images/edit.png); } +.icon-copy:not(.icon-svg) { background-image: url(../images/copy.png); } .icon-duplicate { background-image: url(../images/duplicate.png); } -.icon-del { background-image: url(../images/delete.png); } +.icon-del:not(.icon-svg) { background-image: url(../images/delete.png); } .icon-move { background-image: url(../images/move.png); } .icon-save { background-image: url(../images/save.png); } -.icon-download { background-image: url(../images/download.png); } +.icon-download:not(.icon-svg) { background-image: url(../images/download.png); } .icon-cancel { background-image: url(../images/cancel.png); } .icon-multiple { background-image: url(../images/table_multiple.png); } .icon-folder { background-image: url(../images/folder.png); } @@ -1536,21 +1547,21 @@ td.gantt_selected_column .gantt_hdr,.gantt_selected_column_container { .icon-user { background-image: url(../images/user.png); } .icon-project, .icon-projects { background-image: url(../images/projects.png); } .icon-help { background-image: url(../images/help.png); } -.icon-attachment { background-image: url(../images/attachment.png); } +.icon-attachment:not(.icon-svg) { background-image: url(../images/attachment.png); } .icon-history { background-image: url(../images/history.png); } .icon-time-entry, .icon-time { background-image: url(../images/time.png); } -.icon-time-add { background-image: url(../images/time_add.png); } +.icon-time-add:not(.icon-svg) { background-image: url(../images/time_add.png); } .icon-stats { background-image: url(../images/stats.png); } .icon-warning { background-image: url(../images/warning.png); } .icon-error { background-image: url(../images/exclamation.png); } -.icon-fav { background-image: url(../images/fav.png); } -.icon-fav-off { background-image: url(../images/fav_off.png); } +.icon-fav:not(.icon-svg) { background-image: url(../images/fav.png); } +.icon-fav-off:not(.icon-svg) { background-image: url(../images/fav_off.png); } .icon-reload { background-image: url(../images/reload.png); } .icon-lock, .icon-locked { background-image: url(../images/locked.png); } .icon-unlock { background-image: url(../images/unlock.png); } .icon-checked { background-image: url(../images/toggle_check.png); } .icon-report { background-image: url(../images/report.png); } -.icon-comment, .icon-comments { background-image: url(../images/comment.png); } +.icon-comment:not(.icon-svg), .icon-comments { background-image: url(../images/comment.png); } .icon-summary { background-image: url(../images/lightning.png); } .icon-server-authentication { background-image: url(../images/server_key.png); } .icon-issue { background-image: url(../images/ticket.png); } @@ -1586,7 +1597,7 @@ td.gantt_selected_column .gantt_hdr,.gantt_selected_column_container { .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-actions:not(.icon-svg) { background-image: url(../images/3_bullets.png); } .icon-sort-handle { background-image: url(../images/reorder.png); } .icon-expended { background-image: url(../images/arrow_down.png); } .icon-collapsed { background-image: url(../images/arrow_right.png); } @@ -1618,7 +1629,7 @@ td.gantt_selected_column .gantt_hdr,.gantt_selected_column_container { .icon-file.application-pdf { background-image: url(../images/files/pdf.png); } .icon-file.application-zip { background-image: url(../images/files/zip.png); } .icon-file.application-gzip { background-image: url(../images/files/zip.png); } -.icon-copy-link { background-image: url(../images/copy_link.png); } +.icon-copy-link:not(.icon-svg) { background-image: url(../images/copy_link.png); } .sort-handle.ajax-loading { background-image: url(../images/loading.gif); } tr.ui-sortable-helper { border:1px solid #e4e4e4; } diff --git a/public/svgs/copy.svg b/public/svgs/copy.svg new file mode 100644 index 000000000..7b6a15bb9 --- /dev/null +++ b/public/svgs/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/download.svg b/public/svgs/download.svg new file mode 100644 index 000000000..935e5ee97 --- /dev/null +++ b/public/svgs/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/ellipsis-h.svg b/public/svgs/ellipsis-h.svg new file mode 100644 index 000000000..5d8aad2e8 --- /dev/null +++ b/public/svgs/ellipsis-h.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/link.svg b/public/svgs/link.svg new file mode 100644 index 000000000..f0fdbf4f7 --- /dev/null +++ b/public/svgs/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/paperclip.svg b/public/svgs/paperclip.svg new file mode 100644 index 000000000..76ef1a0bb --- /dev/null +++ b/public/svgs/paperclip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/pen-alt.svg b/public/svgs/pen-alt.svg new file mode 100644 index 000000000..da9c0bb40 --- /dev/null +++ b/public/svgs/pen-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/plus-circle.svg b/public/svgs/plus-circle.svg new file mode 100644 index 000000000..86d47f5f4 --- /dev/null +++ b/public/svgs/plus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/quote-left.svg b/public/svgs/quote-left.svg new file mode 100644 index 000000000..ba9977f3d --- /dev/null +++ b/public/svgs/quote-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/star-off.svg b/public/svgs/star-off.svg new file mode 100644 index 000000000..42caf5022 --- /dev/null +++ b/public/svgs/star-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/star.svg b/public/svgs/star.svg new file mode 100644 index 000000000..0d33b8eb3 --- /dev/null +++ b/public/svgs/star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/time-add.svg b/public/svgs/time-add.svg new file mode 100644 index 000000000..bafd3e001 --- /dev/null +++ b/public/svgs/time-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/trash-alt.svg b/public/svgs/trash-alt.svg new file mode 100644 index 000000000..393e5fcdf --- /dev/null +++ b/public/svgs/trash-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file -- 2.22.0
- <%= link_to_attachment attachment, class: 'icon icon-attachment' -%> + <%= link_to_attachment attachment, class: 'icon icon-attachment icon-svg' -%> (<%= number_to_human_size attachment.filesize %>) - <%= link_to_attachment attachment, class: 'icon-only icon-download', title: l(:button_download), download: true -%> + <%= link_to_attachment attachment, class: 'icon-only icon-download icon-svg', title: l(:button_download), download: true -%> <%= attachment.description unless attachment.description.blank? %> @@ -27,10 +27,10 @@ <% if options[:deletable] %> - <%= link_to l(:button_delete), attachment_path(attachment), + <%= link_to labeled_icon(l(:button_delete), 'trash-alt', icon_only: true, size: 12), attachment_path(attachment), :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, - :class => 'delete icon-only icon-del', + :class => 'delete icon-only icon-del icon-svg', :title => l(:button_delete) %> <% end %>