diff --git a/app/controllers/custom_styles_controller.rb b/app/controllers/custom_styles_controller.rb index 0128d3a1ff2..3473bb4c780 100644 --- a/app/controllers/custom_styles_controller.rb +++ b/app/controllers/custom_styles_controller.rb @@ -30,9 +30,9 @@ class CustomStylesController < ApplicationController layout 'admin' menu_item :custom_style - before_action :require_admin, except: %i[logo_download favicon_download touch_icon_download] - before_action :require_ee_token, except: %i[upsale logo_download favicon_download touch_icon_download] - skip_before_action :check_if_login_required, only: %i[logo_download favicon_download touch_icon_download] + before_action :require_admin, except: %i[logo_download export_logo_download favicon_download touch_icon_download] + before_action :require_ee_token, except: %i[upsale logo_download export_logo_download favicon_download touch_icon_download] + skip_before_action :check_if_login_required, only: %i[logo_download export_logo_download favicon_download touch_icon_download] def show @custom_style = CustomStyle.current || CustomStyle.new @@ -66,6 +66,10 @@ class CustomStylesController < ApplicationController file_download(:logo_path) end + def export_logo_download + file_download(:export_logo_path) + end + def favicon_download file_download(:favicon_path) end @@ -78,6 +82,10 @@ class CustomStylesController < ApplicationController file_delete(:remove_logo) end + def export_logo_delete + file_delete(:remove_export_logo) + end + def favicon_delete file_delete(:remove_favicon) end @@ -141,7 +149,10 @@ class CustomStylesController < ApplicationController end def custom_style_params - params.require(:custom_style).permit(:logo, :remove_logo, :favicon, :remove_favicon, :touch_icon, :remove_touch_icon) + params.require(:custom_style).permit(:logo, :remove_logo, + :export_logo, :remove_export_logo, + :favicon, :remove_favicon, + :touch_icon, :remove_touch_icon) end def file_download(path_method) diff --git a/app/models/custom_style.rb b/app/models/custom_style.rb index 8ea464ed463..0cf8efc221c 100644 --- a/app/models/custom_style.rb +++ b/app/models/custom_style.rb @@ -1,5 +1,6 @@ class CustomStyle < ApplicationRecord mount_uploader :logo, OpenProject::Configuration.file_uploader + mount_uploader :export_logo, OpenProject::Configuration.file_uploader mount_uploader :favicon, OpenProject::Configuration.file_uploader mount_uploader :touch_icon, OpenProject::Configuration.file_uploader @@ -20,7 +21,7 @@ class CustomStyle < ApplicationRecord updated_at.to_i end - %i(favicon touch_icon logo).each do |name| + %i(favicon touch_icon export_logo logo).each do |name| define_method "#{name}_path" do image = send(name) diff --git a/app/views/custom_styles/show.html.erb b/app/views/custom_styles/show.html.erb index 826b2f74a46..dacc3e224f9 100644 --- a/app/views/custom_styles/show.html.erb +++ b/app/views/custom_styles/show.html.erb @@ -155,6 +155,40 @@ See COPYRIGHT and LICENSE files for more details. <% end %> +<%= form_for @custom_style, url: custom_style_path, html: { multipart: true, class: "form -vertical" } do |f| %> +
+
+ <%= I18n.t(:label_custom_export_logo) %> + + <% if @custom_style.id && @custom_style.export_logo.present? %> +
+ <%= tag('img', src: custom_style_export_logo_path(digest: @custom_style.digest, filename: @custom_style.export_logo_identifier), class: 'custom-export-logo-preview') %> + <%= link_to t(:button_delete), + custom_style_export_logo_delete_path, + method: :delete, + class: 'icon icon-delete confirm-form-submit' %> +
+ <% end %> + +
+
+
+
+ <%= f.file_field :export_logo, required: true, class: "attachment_choose_file", size: "15" %> +
+
+
+ <%= t('text_custom_export_logo_instructions') %> +
+
+
+ + <%= styled_button_tag t(@custom_style.export_logo.present? ? :button_replace : :button_upload), class: "button #{@custom_style.export_logo.blank? ? '-with-icon icon-add' : ''}" %> + +
+
+<% end %> + <%= form_tag update_design_colors_path, method: :post, class: "form" do %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 51ba555f916..fb965dcbc1f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1773,6 +1773,7 @@ en: label_logged_as: "Logged in as" label_login: "Sign in" label_custom_logo: "Custom logo" + label_custom_export_logo: "Custom export logo" label_custom_favicon: "Custom favicon" label_custom_touch_icon: "Custom touch icon" label_logout: "Sign out" @@ -2776,14 +2777,18 @@ en: A white logo on transparent background is recommended. For best results on both, conventional and retina displays, make sure your image's dimensions are 460px by 60px. + text_custom_export_logo_instructions: > + This is the logo that appears in your PDF exports. + It needs to be a PNG or JPEG image file. + A black or colored logo on transparent or white background is recommended. text_custom_favicon_instructions: > This is the tiny icon that appears in your browser window/tab next to the page's title. - It's needs to be a squared 32 by 32 pixels sized PNG image file with a transparent background. + It needs to be a squared 32 by 32 pixels sized PNG image file with a transparent background. text_custom_touch_icon_instructions: > This is the icon that appears in your mobile or tablet when you place a bookmark on your homescreen. - It's needs to be a squared 180 by 180 pixels sized PNG image file. Please + It needs to be a squared 180 by 180 pixels sized PNG image file. Please make sure the image's background is not transparent otherwise it will look bad on iOS. text_database_allows_tsv: "Database allows TSVector (optional)" diff --git a/config/routes.rb b/config/routes.rb index 3ccc8788750..27353d7237b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -131,6 +131,10 @@ OpenProject::Application.routes.draw do as: 'custom_style_logo', constraints: { filename: /[^\/]*/ } + get 'custom_style/:digest/export_logo/:filename' => 'custom_styles#export_logo_download', + as: 'custom_style_export_logo', + constraints: { filename: /[^\/]*/ } + get 'custom_style/:digest/favicon/:filename' => 'custom_styles#favicon_download', as: 'custom_style_favicon', constraints: { filename: /[^\/]*/ } @@ -341,6 +345,7 @@ OpenProject::Application.routes.draw do resources :enumerations delete 'design/logo' => 'custom_styles#logo_delete', as: 'custom_style_logo_delete' + delete 'design/export_logo' => 'custom_styles#export_logo_delete', as: 'custom_style_export_logo_delete' delete 'design/favicon' => 'custom_styles#favicon_delete', as: 'custom_style_favicon_delete' delete 'design/touch_icon' => 'custom_styles#touch_icon_delete', as: 'custom_style_touch_icon_delete' get 'design/upsale' => 'custom_styles#upsale', as: 'custom_style_upsale' diff --git a/db/migrate/20230613155001_add_export_logo_to_custom_style.rb b/db/migrate/20230613155001_add_export_logo_to_custom_style.rb new file mode 100644 index 00000000000..2a7de08852a --- /dev/null +++ b/db/migrate/20230613155001_add_export_logo_to_custom_style.rb @@ -0,0 +1,8 @@ +class AddExportLogoToCustomStyle < ActiveRecord::Migration[7.0] + def change + add_column :custom_styles, + :export_logo, + :string, + default: nil + end +end diff --git a/frontend/src/global_styles/content/_custom_logo.sass b/frontend/src/global_styles/content/_custom_logo.sass index 2dc14b8c712..29fb21d275a 100644 --- a/frontend/src/global_styles/content/_custom_logo.sass +++ b/frontend/src/global_styles/content/_custom_logo.sass @@ -1,10 +1,12 @@ img.custom-logo-preview, +img.custom-export-logo-preview, img.custom-favicon-preview, img.custom-touch-icon-preview box-shadow: 0 0 3px lightgrey background-color: var(--header-bg-color) -img.custom-logo-preview +img.custom-logo-preview, +img.custom-export-logo-preview height: 42px img.custom-favicon-preview diff --git a/spec/controllers/custom_styles_controller_spec.rb b/spec/controllers/custom_styles_controller_spec.rb index 37a0b391157..75dd1c68ade 100644 --- a/spec/controllers/custom_styles_controller_spec.rb +++ b/spec/controllers/custom_styles_controller_spec.rb @@ -227,6 +227,69 @@ RSpec.describe CustomStylesController do end end + describe "#export_logo_download" do + render_views + + before do + expect(CustomStyle).to receive(:current).and_return(custom_style) + allow(controller).to receive(:send_file) { controller.head 200 } + get :export_logo_download, params: { digest: "1234", filename: "export_logo_image.png" } + end + + context "when logo is present" do + let(:custom_style) { build(:custom_style_with_export_logo) } + + it 'will send a file' do + expect(response).to have_http_status(:ok) + end + end + + context "when no custom style is present" do + let(:custom_style) { nil } + + it 'renders with error' do + expect(controller).not_to receive(:send_file) + expect(response).to have_http_status(:not_found) + end + end + + context "when no export logo is present" do + let(:custom_style) { build_stubbed(:custom_style) } + + it 'renders with error' do + expect(controller).not_to receive(:send_file) + expect(response).to have_http_status(:not_found) + end + end + end + + describe "#export_logo_delete", with_ee: %i[define_custom_style] do + let(:custom_style) { create(:custom_style_with_export_logo) } + + context 'if it exists' do + before do + expect(CustomStyle).to receive(:current).and_return(custom_style) + expect(custom_style).to receive(:remove_logo).and_call_original + delete :logo_delete + end + + it 'removes the logo from custom_style' do + expect(response).to redirect_to action: :show + end + end + + context 'if it does not exist' do + before do + expect(CustomStyle).to receive(:current).and_return(nil) + delete :logo_delete + end + + it 'renders 404' do + expect(response).to have_http_status :not_found + end + end + end + describe "#favicon_download" do render_views diff --git a/spec/factories/custom_style_factory.rb b/spec/factories/custom_style_factory.rb index 6bacf272bdb..ca15872886f 100644 --- a/spec/factories/custom_style_factory.rb +++ b/spec/factories/custom_style_factory.rb @@ -37,6 +37,14 @@ FactoryBot.define do end end + factory :custom_style_with_export_logo, class: 'CustomStyle' do + export_logo do + Rack::Test::UploadedFile.new( + Rails.root.join('spec', 'support', 'custom_styles', 'logos', 'export_logo_image.png') + ) + end + end + factory :custom_style_with_favicon, class: 'CustomStyle' do favicon do Rack::Test::UploadedFile.new( diff --git a/spec/models/custom_style_spec.rb b/spec/models/custom_style_spec.rb index 72afbd187f5..f72bf35beff 100644 --- a/spec/models/custom_style_spec.rb +++ b/spec/models/custom_style_spec.rb @@ -63,5 +63,11 @@ RSpec.describe CustomStyle do let(:image) { "logo" } end end + + describe "#remove_export_logo" do + it_behaves_like "removing an image from a custom style" do + let(:image) { "export_logo" } + end + end end end