Skip to content

Commit

Permalink
Merge pull request #5099 from solidusio/waiting-for-dev/extending_com…
Browse files Browse the repository at this point in the history
…ponents

Use and extend view components in Solidus Admin
  • Loading branch information
waiting-for-dev authored Jun 6, 2023
2 parents b2a5bc7 + bedf820 commit 80f2434
Show file tree
Hide file tree
Showing 18 changed files with 260 additions and 21 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ commands:
cat /tmp/.gems-versions
- restore_cache:
keys:
- solidus-installer-v7-{{ checksum "/tmp/.ruby-versions" }}-{{ checksum "/tmp/.gems-versions" }}
- solidus-installer-v7-{{ checksum "/tmp/.ruby-versions" }}-
- solidus-installer-v8-{{ checksum "/tmp/.ruby-versions" }}-{{ checksum "/tmp/.gems-versions" }}
- solidus-installer-v8-{{ checksum "/tmp/.ruby-versions" }}-
- run:
name: "Prepare the rails application"
command: |
Expand Down
11 changes: 11 additions & 0 deletions admin/app/components/solidus_admin/base_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require "solidus_admin/system/import"

module SolidusAdmin
# BaseComponent is the base class for all components in Solidus Admin.
class BaseComponent < ViewComponent::Base
include ViewComponent::InlineTemplate
include SolidusAdmin::ContainerHelper
end
end
27 changes: 27 additions & 0 deletions admin/app/components/solidus_admin/main_nav_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module SolidusAdmin
# Renders the main navigation of Solidus Admin.
class MainNavComponent < BaseComponent
include Import[
"main_nav_item_component",
items: "main_nav_items"
]

erb_template <<~ERB
<nav>
<%=
render main_nav_item_component.with_collection(
sorted_items
)
%>
</nav>
ERB

private

def sorted_items
items.sort_by(&:position)
end
end
end
21 changes: 21 additions & 0 deletions admin/app/components/solidus_admin/main_nav_item_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module SolidusAdmin
# Menu item within a {MainNavComponent}
class MainNavItemComponent < BaseComponent
with_collection_parameter :item

attr_reader :item

def initialize(item:)
@item = item
super
end

erb_template <<~ERB
<a href="#">
<%= item.title %>
</a>
ERB
end
end
2 changes: 2 additions & 0 deletions admin/app/controllers/solidus_admin/orders_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true

module SolidusAdmin
# rubocop:disable Rails/ApplicationController
class OrdersController < ActionController::Base
layout 'solidus_admin/application'
end
# rubocop:enable Rails/ApplicationController
end
15 changes: 15 additions & 0 deletions admin/app/helpers/solidus_admin/container_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require "solidus_admin/container"

module SolidusAdmin
module ContainerHelper
def container
SolidusAdmin::Container
end

def component(name)
container.resolve("#{name}_component")
end
end
end
1 change: 1 addition & 0 deletions admin/app/views/layouts/solidus_admin/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</head>
<body>
<h1 class="text-4xl">Layout is rendered</h1>
<%= render component("main_nav").new %>
<%= yield %>
</body>
</html>
22 changes: 12 additions & 10 deletions admin/lib/solidus_admin/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,29 @@ class Configuration < Spree::Preferences::Configuration
#
# You can modify this list to include your own paths:
#
# SolidusAdmin::Config.tailwind_content << Rails.root.join("app", "my", "custom", "path")
# SolidusAdmin::Config.tailwind_content << Rails.root.join("app/my/custom/path")
#
# Recompile with `bin/rails solidus_admin:tailwindcss:build` after changing this list.
#
# @see https://tailwindcss.com/docs/configuration#content
preference :tailwind_content, :array, default: [
SolidusAdmin::Engine.root.join("public", "*.html"),
SolidusAdmin::Engine.root.join("app", "helpers", "**", "*.rb"),
SolidusAdmin::Engine.root.join("app", "assets", "javascripts", "**", "*.js"),
SolidusAdmin::Engine.root.join("app", "views", "**", "*.{erb,haml,html,slim}"),
Rails.root.join("public", "solidus_admin", "*.html"),
Rails.root.join("app", "helpers", "solidus_admin", "**", "*.rb"),
Rails.root.join("app", "assets", "javascripts", "solidus_admin", "**", "*.js"),
Rails.root.join("app", "views", "solidus_admin", "**", "*.{erb,haml,html,slim}")
SolidusAdmin::Engine.root.join("public/*.html"),
SolidusAdmin::Engine.root.join("app/helpers/**/*.rb"),
SolidusAdmin::Engine.root.join("app/assets/javascripts/**/*.js"),
SolidusAdmin::Engine.root.join("app/views/**/*.{erb,haml,html,slim}"),
SolidusAdmin::Engine.root.join("app/components/**/*.rb"),
Rails.root.join("public/solidus_admin/*.html"),
Rails.root.join("app/helpers/solidus_admin/**/*.rb"),
Rails.root.join("app/assets/javascripts/solidus_admin/**/*.js"),
Rails.root.join("app/views/solidus_admin/**/*.{erb,haml,html,slim}"),
Rails.root.join("app/components/solidus_admin/**/*.rb")
]

# List of Tailwind CSS files to be combined into the final stylesheet.
#
# You can modify this list to include your own files:
#
# SolidusAdmin::Config.tailwind_stylesheets << Rails.root.join("app", "assets", "stylesheets", "solidus_admin", "application.tailwind.css")
# SolidusAdmin::Config.tailwind_stylesheets << Rails.root.join("app/assets/stylesheets/solidus_admin/application.tailwind.css")
#
# Recompile with `bin/rails solidus_admin:tailwindcss:build` after changing this list.
preference :tailwind_stylesheets, :array, default: []
Expand Down
34 changes: 34 additions & 0 deletions admin/lib/solidus_admin/container.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require "dry/system"
require "dry/system/container"
require "dry/system/component"
require "view_component"
require "solidus_admin/system/loaders/host_overridable_constant"

module SolidusAdmin
# Global registry for host-injectable components.
#
# We use this container to register all the components that can be
# overridden by the host application.
#
# @api private
class Container < Dry::System::Container
configure do |config|
config.root = Pathname(__FILE__).dirname.join("../..").realpath
config.component_dirs.add("app/components") do |dir|
dir.loader = System::Loaders::HostOverridableConstant.method(:call).curry["components"]
dir.namespaces.add "solidus_admin", key: nil
end
end

# Returns all the registered components for a given namespace.
#
# @api private
def self.within_namespace(namespace)
keys.filter_map do
_1.start_with?("#{namespace}#{config.namespace_separator}") && resolve(_1)
end
end
end
end
9 changes: 9 additions & 0 deletions admin/lib/solidus_admin/engine.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# frozen_string_literal: true

require "view_component"
require "solidus_admin/container"

module SolidusAdmin
class Engine < ::Rails::Engine
isolate_namespace SolidusAdmin
Expand All @@ -11,5 +14,11 @@ class Engine < ::Rails::Engine
initializer "solidus_admin.assets" do |app|
app.config.assets.precompile += %w[solidus_admin/application.css]
end

initializer "solidus_admin.main_nav_items_provider" do
require "solidus_admin/system/providers/main_nav"

Container.start("main_nav")
end
end
end
15 changes: 15 additions & 0 deletions admin/lib/solidus_admin/main_nav_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module SolidusAdmin
# Encapsulates the data for a main nav item.
class MainNavItem
attr_reader :title, :position

# @param title [String]
# @param position [Integer]
def initialize(title:, position:)
@title = title
@position = position
end
end
end
15 changes: 15 additions & 0 deletions admin/lib/solidus_admin/system/import.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require "solidus_admin/container"

module SolidusAdmin
# Auto-imports container dependencies.
#
# @example
# class Foo
# # Foo.new will have a `#bar` instance method that returns the
# # result of `Container["bar"]`.
# include Import["bar"]
# end
Import = Container.injector
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# frozen_string_literal: true

module SolidusAdmin
module System
module Loaders
# Loader that resolves constants that can be overriden by the host.
#
# For instance, when the loader is configured like this:
#
# ```ruby
# config.component_dirs.add "app/components" do |dir|
# dir.loader = SolidusAdmin::System::Loaders::HostOverridableConstant.method(:call).curry["components"]
# end
# ```
#
# When `Container["foo"]` is given and the loader is used:
#
# - It will return a `MyApp::SolidusAdmin::Foo` constant if `app/components/my_app/solidus_admin/foo.rb` exists.
# - Otherwise, it will return the resolved constant from the engine.
#
# @api private
class HostOverridableConstant < Dry::System::Loader
# @param [String] namespace
def self.call(namespace, component, *_args)
return override_constant(component) if override_path(namespace, component).exist?

require!(component)
constant(component)
end

class << self
private

def application
Rails.application
end

def application_name
Rails.application.class.module_parent.name
end

def override_path(namespace, component)
application
.root
.join(
"app",
namespace,
application_name.underscore,
"solidus_admin",
"#{component.identifier.key}.rb"
)
end

def override_constant(component)
"#{application_name}::SolidusAdmin::#{component.identifier.key.camelize}".constantize
end
end
end
end
end
end
22 changes: 22 additions & 0 deletions admin/lib/solidus_admin/system/providers/main_nav.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require "solidus_admin/container"
require "solidus_admin/main_nav_item"

module SolidusAdmin
module Providers
Container.register_provider("main_nav") do
start do
container.namespace("main_nav") do
register("first_item", MainNavItem.new(title: "First item", position: "10"))
register("second_item", MainNavItem.new(title: "Second item", position: "20"))
register("third_item", MainNavItem.new(title: "Third item", position: "30"))
end

container.register("main_nav_items") do
Container.within_namespace("main_nav")
end
end
end
end
end
14 changes: 7 additions & 7 deletions admin/lib/solidus_admin/tailwindcss.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def run(args = "")
"application.tailwind.css"
)

system "#{::Tailwindcss::Engine.root.join("exe/tailwindcss")} \
system "#{::Tailwindcss::Engine.root.join('exe/tailwindcss')} \
-i #{stylesheet_file.path} \
-o #{Rails.root.join("app/assets/builds/solidus_admin/tailwind.css")} \
-o #{Rails.root.join('app/assets/builds/solidus_admin/tailwind.css')} \
-c #{config_file.path} \
#{args}"
ensure
Expand All @@ -28,25 +28,25 @@ def run(args = "")
end

def config_app_path
Rails.root.join("config", "solidus_admin", "tailwind.config.js.erb")
Rails.root.join("config/solidus_admin/tailwind.config.js.erb")
end

def config_engine_path
SolidusAdmin::Engine.root.join("config", "solidus_admin", "tailwind.config.js.erb")
SolidusAdmin::Engine.root.join("config/solidus_admin/tailwind.config.js.erb")
end

def stylesheet_app_path
Rails.root.join("app", "assets", "stylesheets", "solidus_admin", "application.tailwind.css.erb")
Rails.root.join("app/assets/stylesheets/solidus_admin/application.tailwind.css.erb")
end

def stylesheet_engine_path
SolidusAdmin::Engine.root.join("app", "assets", "stylesheets", "solidus_admin", "application.tailwind.css.erb")
SolidusAdmin::Engine.root.join("app/assets/stylesheets/solidus_admin/application.tailwind.css.erb")
end

def compile_to_tempfile(path, name)
Tempfile.new(name).tap do |file|
path
.then { |path| File.read(path) }
.then { File.read(_1) }
.then { |content| ERB.new(content) }
.then { |erb| erb.result }
.then { |compiled_content| file.write(compiled_content) && file.rewind }
Expand Down
2 changes: 2 additions & 0 deletions admin/lib/tasks/tailwindcss.rake
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

namespace :solidus_admin do
namespace :tailwindcss do
require "solidus_admin/tailwindcss"
Expand Down
4 changes: 3 additions & 1 deletion admin/solidus_admin.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require_relative '../core/lib/spree/core/version.rb'
require_relative '../core/lib/spree/core/version'

Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
Expand All @@ -23,6 +23,8 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 3.0.0'
s.required_rubygems_version = '>= 1.8.23'

s.add_dependency 'dry-system', '~> 1.0'
s.add_dependency 'solidus_core', s.version
s.add_dependency 'tailwindcss-rails', '~> 2.0'
s.add_dependency 'view_component', '~> 3.0'
end
2 changes: 1 addition & 1 deletion solidus.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 3.0.0'
s.required_rubygems_version = '>= 1.8.23'

s.add_dependency 'solidus_admin', s.version
s.add_dependency 'solidus_api', s.version
s.add_dependency 'solidus_backend', s.version
s.add_dependency 'solidus_core', s.version
s.add_dependency 'solidus_sample', s.version
s.add_dependency 'solidus_admin', s.version
end

0 comments on commit 80f2434

Please sign in to comment.