Skip to content

Add manual component installation instructions #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 8 additions & 31 deletions app/components/component_setup/cli_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,16 @@ def initialize(component_name:)
def view_template
div(class: "max-w-2xl mx-auto w-full py-10 space-y-6") do
Heading(level: 4, class: "pb-4 border-b") { "Using RubyUI CLI" }
Text do
"We provide a Ruby gem with useful generators to help you to setup RubyUI components in your apps."
end

render Steps::Builder.new do |steps|
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add RubyUI gem to your Gemfile if you don't have it yet"
end

code = <<~CODE
bundle add ruby_ui --group development --require false
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
"Run the install command"
end
Text(size: "4", weight: "semibold") do
"Run the install command"
end

code = <<~CODE
rails g ruby_ui:component #{component_name.camelcase}
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
code = <<~CODE
rails g ruby_ui:component #{component_name.camelcase}
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
Expand Down
220 changes: 220 additions & 0 deletions app/components/component_setup/manual_steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
module Components
module ComponentSetup
class ManualSteps < Components::Base
def initialize(component_name:)
@component_name = component_name
@dependencies = RubyUI::FileManager.dependencies(@component_name)
end

private

attr_reader :component_name, :dependencies

def view_template
div(class: "max-w-2xl mx-auto w-full py-10 space-y-6") do
Heading(level: 4, class: "pb-4 border-b") { "Manual installation" }

render Steps::Builder.new do |steps|
main_component_step(steps)
related_component_steps(steps)
stimulus_controller_steps(steps)
js_dependencies_steps(steps)
ruby_dependencies_steps(steps)
component_dependencies_steps(steps)
end
end
end

def main_component_step(steps)
main_component_code = RubyUI::FileManager.main_component_code(component_name)

return if main_component_code.blank?

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { "RubyUI::#{component_name.camelcase}" }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/components/ruby_ui/#{component_name.underscore}.rb" }
end

div(class: "w-full") do
Codeblock(main_component_code, syntax: :ruby)
end
end
end
end

def related_component_steps(steps)
related_component_file_paths = RubyUI::FileManager.related_component_file_paths(component_name)

return if related_component_file_paths.empty?

related_component_file_paths.each do |component_path|
related_component_class = component_path.split("/").last.delete_suffix(".rb").camelcase
related_component_file_name = component_path.split("/").last
related_component_code = RubyUI::FileManager.component_code(component_path)
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { "RubyUI::#{related_component_class}" }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/components/ruby_ui/#{component_name.underscore}/#{related_component_file_name}" }
end

div(class: "w-full") do
Codeblock(related_component_code, syntax: :ruby)
end
end
end
end
end

def stimulus_controller_steps(steps)
stimulus_controller_file_paths = RubyUI::FileManager.stimulus_controller_file_paths(component_name)

return if stimulus_controller_file_paths.empty?

stimulus_controller_file_paths.each do |controller_path|
controller_file_name = controller_path.split("/").last
controller_code = RubyUI::FileManager.component_code(controller_path)
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { controller_file_name }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/javascript/controllers/ruby_ui/#{controller_file_name}" }
end

div(class: "w-full") do
Codeblock(controller_code, syntax: :javascript)
end
end
end
end

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Update the Stimulus controllers manifest file"
end

Alert(variant: :destructive) do
AlertTitle { "Importmap!" }
AlertDescription { "You don't need to run this command if you are using Importmap" }
end

div(class: "w-full") do
Codeblock("rake stimulus:manifest:update", syntax: :javascript)
end
end
end
end

def js_dependencies_steps(steps)
return unless dependencies["js_packages"].present?

dependencies["js_packages"].each do |js_package|
steps.add_step do
code = <<~CODE
// with yarn
yarn add #{js_package}
// with npm
npm install #{js_package}
// with importmaps
#{pin_importmap_instructions(js_package)}
CODE

render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install "
InlineCode(class: "whitespace-nowrap") { js_package }
plain " Javascript dependency"
end

div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
end
end

def ruby_dependencies_steps(steps)
return unless dependencies["gems"].present?

dependencies["gems"].each do |gem|
steps.add_step do
code = <<~CODE
bundle add #{gem}
CODE

render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install "
InlineCode(class: "whitespace-nowrap") { gem }
plain " Ruby gem"
end

div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
end
end

def component_dependencies_steps(steps)
return unless dependencies["components"].present?

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install required components"
end

Text do
plain "Component "
InlineCode(class: "whitespace-nowrap") { component_name.camelcase }
plain " relies on the following RubyUI components. Refer to their individual installation guides for setup instructions:"
end

TypographyList do
dependencies["components"].each do |component|
TypographyListItem do
Link(size: :lg, target: "_blank", href: public_send(:"docs_#{component.underscore}_path")) do
span(class: "font-bold") { component.camelcase }
span { " - Installation guide" }
end
end
end
end
end
end
end

# Temporary solution while we don't remove
# motion adn tippy.js dependencies
def pin_importmap_instructions(js_package)
case js_package
when "motion"
<<~CODE
// Add to your config/importmap.rb
pin "motion", to: "https://cdn.jsdelivr.net/npm/motion@10.18.0/+esm"
CODE
when "tippy.js"
<<~CODE
// Add to your config/importmap.rb
pin "tippy.js", to: "https://cdn.jsdelivr.net/npm/tippy.js@6.3.7/+esm"
pin "@popperjs/core", to: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/+esm"\n
CODE
else
"bin/importmap pin #{js_package}"
end
end
end
end
end
2 changes: 1 addition & 1 deletion app/components/component_setup/tabs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def view_template
end

TabsContent(value: "manual") do
Text { "Coming soon" }
render ManualSteps.new(component_name:)
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions app/lib/ruby_ui/file_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module RubyUI
module FileManager
extend self

def main_component_code(component_name)
component_code main_component_file_path(component_name)
end

def component_code(file_path)
File.read(file_path) if File.exist?(file_path)
end

def main_component_file_path(component_name)
component_name = component_name.underscore
File.join(component_folder(component_name), "#{component_name}.rb")
end

def related_component_file_paths(component_name)
Dir[File.join(component_folder(component_name), "*.rb")] - [main_component_file_path(component_name)]
end

def stimulus_controller_file_paths(component_name)
Dir[File.join(component_folder(component_name), "*.js")]
end

def component_folder(component_name)
component_name = component_name.underscore
File.join(gem_path, "lib", "ruby_ui", component_name)
end

def dependencies(component_name)
DEPENDENCIES[component_name.underscore].to_h
end

def gem_path
@gem_path ||= Gem::Specification.find_by_name("ruby_ui").gem_dir
end

DEPENDENCIES = YAML.load_file(File.join(gem_path, "lib/generators/ruby_ui/dependencies.yml")).freeze
end
end