# frozen_string_literal: true require 'spree/preferences/configuration' module SolidusAdmin # Configuration for the admin interface. # # Ensure requiring this file after the Rails application has been created, # as some defaults depend on the application context. class Configuration < Spree::Preferences::Configuration ComponentNotFoundError = Class.new(NameError) ENGINE_ROOT = File.expand_path("#{__dir__}/../..") # Path to the logo used in the admin interface. # # It needs to be a path to an image file accessible by Sprockets. # The default value is the Solidus logo that lives in the solidus_core gem. preference :logo_path, :string, default: "logo/solidus.svg" # List of paths to watch for changes to trigger a cache sweep forcing a regeneration of the importmap. # # @see https://github.com/rails/importmap-rails#sweeping-the-cache-in-development-and-test preference :importmap_cache_sweepers, :array, default: [ "#{ENGINE_ROOT}/app/assets/javascripts", "#{ENGINE_ROOT}/app/javascript", "#{ENGINE_ROOT}/app/components", ] # List of paths to importmap files to be loaded. # # @see https://github.com/rails/importmap-rails#composing-import-maps preference :importmap_paths, :array, default: [ "#{ENGINE_ROOT}/config/importmap.rb", ] # @!attribute [rw] low_stock_value # @return [Integer] The low stock value determines the threshold at which products are considered low in stock. # Products with a count_on_hand less than or equal to this value will be considered low in stock. # Default: 10 preference :low_stock_value, :integer, default: 10 # @!attribute [rw] enable_alpha_features? # @return [Boolean] Determines whether alpha features are enabled or disabled in the application. # Setting this to `true` enables access to alpha stage features that might still be in testing or development. # Use with caution, as these features may not be fully stable or complete. # Default: false preference :enable_alpha_features, :boolean, default: false alias enable_alpha_features? enable_alpha_features preference :storefront_product_path_proc, :proc, default: ->(_version) { ->(product) { "/products/#{product.slug}" } } def storefront_product_path(product) storefront_product_path_proc.call(product) end # Gives access to the main navigation configuration # # @example # SolidusAdmin::Config.menu_items << { # key: :my_custom_link, # route: :products_path, # icon: "solidus_admin/price-tag-3-line.svg", # position: 80 # } # # @api public # @return [Array] def menu_items @menu_items ||= [ { key: "orders", route: -> { spree.admin_orders_path }, icon: "inbox-line", position: 10 }, { key: "products", route: :products_path, icon: "price-tag-3-line", position: 20, children: [ { key: "products", route: -> { solidus_admin.products_path }, match_path: -> { _1.start_with?("/admin/products/") }, position: 0 }, { key: "option_types", route: -> { spree.admin_option_types_path }, position: 10 }, { key: "property_types", route: -> { spree.admin_properties_path }, position: 20 }, { key: "taxonomies", route: -> { spree.admin_taxonomies_path }, position: 30 }, { key: "taxons", route: -> { spree.admin_taxons_path }, position: 40 } ] }, { key: "promotions", route: -> { spree.admin_promotions_path }, icon: "megaphone-line", position: 30, }, { key: "stock", route: -> { spree.admin_stock_items_path }, icon: "stack-line", position: 40 }, { key: "users", route: -> { spree.admin_users_path }, icon: "user-line", position: 50 }, { key: "settings", route: -> { spree.admin_stores_path }, icon: "settings-line", position: 60, } ] end def import_menu_items_from_backend! menu_item_to_hash = ->(item, index) do route = if item.url.is_a?(Symbol) -> { solidus_admin.public_send(item.url) } elsif item.url.is_a?(String) -> { item.url } elsif item.url.is_a?(Proc) item.url elsif item.url.nil? -> { spree.public_send(:"admin_#{item.label}_path") } else raise ArgumentError, "Unknown url type #{item.url.class}" end match_path = case item.match_path when Regexp then -> { _1 =~ item.match_path } when Proc then item.match_path when String then -> { _1.start_with?("/admin#{item.match_path}") } when nil then -> { _1.start_with?(route.call) } else raise ArgumentError, "Unknown match_path type #{item.match_path.class}" end icon = case item.icon when /^ri-/ item.icon.delete_prefix("ri-") when String 'record-circle-line' # fallback on a generic icon end { position: index, key: item.label, icon: icon, route: route, children: item.children.map.with_index(&menu_item_to_hash), match_path: match_path, } end @menu_items = Spree::Backend::Config.menu_items.map.with_index(&menu_item_to_hash) end def components @components ||= Hash.new do |_h, k| const_name = "solidus_admin/#{k}/component".classify unless Object.const_defined?(const_name) prefix = "#{ENGINE_ROOT}/app/components/solidus_admin/" suffix = "/component.rb" dictionary = Dir["#{prefix}**#{suffix}"].map { _1.delete_prefix(prefix).delete_suffix(suffix) } corrections = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(k.to_s) raise ComponentNotFoundError.new( "Unknown component #{k}#{DidYouMean.formatter.message_for(corrections)}", k.classify, receiver: ::SolidusAdmin ) end const_name.constantize end end # The method used to authenticate the user in the admin interface, it's expected to redirect the user to the login method # in case the authentication fails. preference :authentication_method, :string, default: :authenticate_solidus_backend_user! # The method used to retrieve the current user in the admin interface. preference :current_user_method, :string, default: :spree_current_user # The path used to logout the user in the admin interface. preference :logout_link_path, :string, default: '/admin/logout' # The HTTP method used to logout the user in the admin interface. preference :logout_link_method, :string, default: :delete # @!attribute [rw] themes # @return [Hash] A hash containing the themes that are available for the admin panel preference :themes, :hash, default: { solidus: 'solidus_admin/application', solidus_dark: 'solidus_admin/dark', solidus_dimmed: 'solidus_admin/dimmed', } # @!attribute [rw] theme # @return [String] Default admin theme name preference :theme, :string, default: 'solidus' # @!attribute [rw] dark_theme # @return [String] Default admin theme name preference :dark_theme, :string, default: 'solidus_dark' def theme_path(user_theme) themes.fetch(user_theme&.to_sym, themes[theme.to_sym]) end end end SolidusAdmin::Config = SolidusAdmin::Configuration.new