diff --git a/app/controllers/admin/creator_settings_controller.rb b/app/controllers/admin/creator_settings_controller.rb index 6b1b22510..9c49d05b6 100644 --- a/app/controllers/admin/creator_settings_controller.rb +++ b/app/controllers/admin/creator_settings_controller.rb @@ -15,8 +15,7 @@ module Admin checked_terms_and_conditions: current_user.checked_terms_and_conditions, ) @max_file_size = LogoUploader::MAX_FILE_SIZE - @logo_allowed_types = (LogoUploader::CONTENT_TYPE_ALLOWLIST + - LogoUploader::EXTENSION_ALLOWLIST.map { |extension| ".#{extension}" }).join(",") + @logo_allowed_types = LogoUploader::ALLOWED_TYPES end def create diff --git a/app/controllers/admin/settings/general_settings_controller.rb b/app/controllers/admin/settings/general_settings_controller.rb index 5d9b20586..be7747e72 100644 --- a/app/controllers/admin/settings/general_settings_controller.rb +++ b/app/controllers/admin/settings/general_settings_controller.rb @@ -6,6 +6,7 @@ module Admin SPECIAL_PARAMS_TO_ADD = %w[ credit_prices_in_cents meta_keywords + logo ].freeze def create diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index e319e49ce..1fc655c74 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -10,6 +10,8 @@ module Admin layout "admin" def show + @logo_allowed_types = LogoUploader::ALLOWED_TYPES + @logo_max_file_size = LogoUploader::MAX_FILE_SIZE @confirmation_text = "My username is @#{current_user.username} and this action is 100% safe and appropriate." end diff --git a/app/javascript/admin/controllers/config_controller.js b/app/javascript/admin/controllers/config_controller.js index a77144512..06fdf317f 100644 --- a/app/javascript/admin/controllers/config_controller.js +++ b/app/javascript/admin/controllers/config_controller.js @@ -102,6 +102,8 @@ export default class ConfigController extends Controller { async updateConfigurationSettings(event) { event.preventDefault(); + let errored = false; + try { const body = new FormData(event.target); const response = await fetch(event.target.action, { @@ -117,9 +119,35 @@ export default class ConfigController extends Controller { const outcome = await response.json(); + errored = outcome.error != null; displaySnackbar(outcome.message ?? outcome.error); } catch (err) { - displaySnackbar(err.message); + errored = true; + displaySnackbar('An error occurred. Please try again.'); + } finally { + // Only update the site logo in the header if the new logo is uploaded successfully. + if (!errored && event.target.elements.settings_general_logo) { + this.updateLogo(); + } + } + } + + /** + * Updates the site logo in the header with the same URL as the preview logo. + */ + updateLogo() { + const previewLogo = document.querySelector( + '#logo-upload-preview .site-logo__img', + ); + + if (!previewLogo) { + return; + } + + for (const logo of document.querySelectorAll('.site-logo__img')) { + if (logo !== previewLogo) { + logo.src = previewLogo.src; + } } } diff --git a/app/javascript/admin/controllers/logo_upload_controller.js b/app/javascript/admin/controllers/logo_upload_controller.js index d254bdb6c..7d5ff00f9 100644 --- a/app/javascript/admin/controllers/logo_upload_controller.js +++ b/app/javascript/admin/controllers/logo_upload_controller.js @@ -31,7 +31,7 @@ export class LogoUploadController extends Controller { const imageURL = reader.result; const image = document.createElement('img'); image.src = imageURL; - image.className = 'site-logo'; + image.className = 'site-logo__img'; // The logo preview image is purely visual so no need to communicate this to assistive technology. image.alt = 'preview of logo selected'; @@ -43,10 +43,14 @@ export class LogoUploadController extends Controller { target: { width, height }, } = event; - this.previewLogoTarget.replaceChild( - image, - this.previewLogoTarget.firstChild, - ); + if (this.previewLogoTarget.firstElementChild) { + this.previewLogoTarget.replaceChild( + image, + this.previewLogoTarget.firstElementChild, + ); + } else { + this.previewLogoTarget.appendChild(image); + } const maxLogoPreviewWidth = parseInt( getComputedStyle(image).getPropertyValue('--max-width'), diff --git a/app/services/settings/general/upsert.rb b/app/services/settings/general/upsert.rb index 6bdbf9bd6..318aa7f35 100644 --- a/app/services/settings/general/upsert.rb +++ b/app/services/settings/general/upsert.rb @@ -5,7 +5,15 @@ module Settings TAG_PARAMS = %w[sidebar_tags suggested_tags].freeze def self.call(settings) - cleaned_params = clean_params(settings) + params_to_clean = settings.except(:logo) + + if settings[:logo].present? + logo_uploader = upload_logo(settings[:logo]) + logo_settings = { original_logo: logo_uploader.url, resized_logo: logo_uploader.resized_logo.url } + params_to_clean = params_to_clean.merge(logo_settings) + end + + cleaned_params = clean_params(params_to_clean) result = ::Settings::Upsert.call(cleaned_params, ::Settings::General) return result unless result.success? @@ -29,6 +37,14 @@ module Settings tags = Settings::General.suggested_tags + Settings::General.sidebar_tags Tag.find_or_create_all_with_like_by_name(tags) end + + def self.upload_logo(image) + LogoUploader.new.tap do |uploader| + uploader.store!(image) + end + end + + private_class_method :upload_logo end end end diff --git a/app/uploaders/logo_uploader.rb b/app/uploaders/logo_uploader.rb index 2ee5ff33a..fd8e12410 100644 --- a/app/uploaders/logo_uploader.rb +++ b/app/uploaders/logo_uploader.rb @@ -4,6 +4,7 @@ class LogoUploader < BaseUploader EXTENSION_ALLOWLIST = %w[png jpg jpeg jpe].freeze IMAGE_TYPE_ALLOWLIST = %i[png jpg jpeg jpe].freeze CONTENT_TYPE_ALLOWLIST = %w[image/png image/jpg image/jpeg].freeze + ALLOWED_TYPES = (CONTENT_TYPE_ALLOWLIST + EXTENSION_ALLOWLIST.map { |extension| ".#{extension}" }).join(",") def store_dir STORE_DIRECTORY diff --git a/app/views/admin/creator_settings/_form.html.erb b/app/views/admin/creator_settings/_form.html.erb index 79278f3ce..b428e0878 100644 --- a/app/views/admin/creator_settings/_form.html.erb +++ b/app/views/admin/creator_settings/_form.html.erb @@ -7,7 +7,7 @@ <%= f.text_field :community_name, placeholder: "Climbing Life", class: "crayons-textfield", required: true %> -<%= render partial: "admin/shared/logo_upload", locals: { allowed_types: @logo_allowed_types, max_file_size: @max_file_size, f: f } %> +<%= render partial: "admin/shared/logo_upload", locals: { allowed_types: @logo_allowed_types, max_file_size: @max_file_size, f: f, logo: Settings::General.resized_logo } %>
Your logo will display in the upper left hand corner of your Forem. Upload a PNG or JPEG file.
<% end %> +Your logo will display in the upper left hand corner of your Forem. Upload a PNG or JPEG file.