Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Hotwire #1

Merged
merged 11 commits into from
Nov 29, 2022
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
56 changes: 55 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,62 @@ AllCops:
TargetRubyVersion: 3.1.2
NewCops: enable

Style/Documentation:
Lint/Debugger:
Severity: error

Lint/MissingSuper:
Enabled: false

Metrics/AbcSize:
Enabled: false

Metrics/BlockNesting:
Enabled: false

Metrics/CyclomaticComplexity:
Enabled: false

Metrics/ClassLength:
Max: 100

Metrics/BlockLength:
Max: 50
Exclude:
- spec/**/*

Metrics/MethodLength:
Max: 25

Layout/LineLength:
Max: 120
IgnoredPatterns: ['\A\s*#']

Layout/ParameterAlignment:
EnforcedStyle: with_fixed_indentation

Layout/DotPosition:
EnforcedStyle: trailing

Layout/FirstHashElementIndentation:
EnforcedStyle: consistent

Layout/MultilineMethodCallIndentation:
EnforcedStyle: indented

Style/AsciiComments:
Enabled: false

Style/FormatStringToken:
EnforcedStyle: template

Style/FrozenStringLiteralComment:
Enabled: false

Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: comma

Style/Documentation:
Enabled: false

Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: comma
8 changes: 5 additions & 3 deletions app/components/search_list_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<%= form %>
<%= form if form? %>
<% if items? %>
<div class="mt-4">
<ul class="mb-6">
<% items.each do |item| %>
<%= item %>
<%= turbo_frame_tag "list_#{@resource.plural}" do %>
<% items.each do |item| %>
<%= item %>
<% end %>
<% end %>
</ul>
</div>
Expand Down
10 changes: 10 additions & 0 deletions app/components/search_list_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# frozen_string_literal: true

class SearchListComponent < ViewComponent::Base
include Turbo::FramesHelper

renders_one :form, SearchListFormComponent
renders_many :items, SearchListItemComponent

def before_render
@resource ||= form.ransack.object.model_name if form?
end

def initialize(resource: nil)
@resource = resource
end
end
2 changes: 1 addition & 1 deletion app/components/search_list_form_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= form_tag class: "relative" do |f| %>
<%= form_tag class: "relative", data: { turbo_frame: "list_#{@resource.plural}" } do |f| %>
<%= f.input_search @search_field, @search_value %>
<%= f.button do %>
<svg class="w-4 h-4 shrink-0 fill-current text-slate-400 group-hover:text-slate-500 ml-3 mr-2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
Expand Down
20 changes: 12 additions & 8 deletions app/components/search_list_form_component.rb
Original file line number Diff line number Diff line change
@@ -1,48 +1,52 @@
# frozen_string_literal: true

module SearchListFormHelper
def form_tag(options = {}, &proc)
def form_tag(options = {}, &)
options.merge!({ builder: SearchListBuilder })

search_form_for(@ransack, options, &proc)
search_form_for(@ransack, options, &)
end
end

class SearchListFormComponent < ViewComponent::Base
include Ransack::Helpers::FormHelper
include SearchListFormHelper

attr_reader :ransack

def before_render
@search_value = params[@search_field]
end

def initialize(ransack:, search_field: :name_cont)
@ransack = ransack
@search_field = search_field

@resource = ransack.object.model_name
end
end

class SearchListBuilder < ActionView::Helpers::FormBuilder
include SearchListFormHelper

def button(tag_value = nil, options = {}, &block)
def button(tag_value = nil, options = {}, &)
options.merge!({
type: 'submit',
class: "absolute inset-0 right-auto group"
class: 'absolute inset-0 right-auto group',
})

@template.button_tag(
tag_value, options, &block
tag_value, options, &
)
end

def input_search(method, tag_value, options = {})
def input_search(method, _tag_value, options = {})
options.merge!({
placeholder: 'Search...',
class: 'form-input w-full pl-9 focus:border-slate-300'
class: 'form-input w-full pl-9 focus:border-slate-300',
})

@template.label(@object_name, method, class: 'sr-only') +
@template.search_field(@object_name, method, options)
@template.search_field(@object_name, method, options)
end
end
23 changes: 14 additions & 9 deletions app/components/search_list_item_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class SearchListItemComponent < ViewComponent::Base
include Turbo::FramesHelper

def initialize(item, label: :name)
@item = item
@label = item.send(label)
Expand All @@ -12,19 +14,22 @@ def active?

def call
html_options = {
aria: { label: "Edit this #{@item.model_name.human.downcase}" },
aria: { label: "Edit this #{@item.model_name.singular}" },
data: { turbo_frame: "#{@item.model_name.singular}_form" },
class: class_names(
"flex items-center justify-between w-full p-2 rounded", {
"bg-indigo-100": active?
'flex items-center justify-between w-full p-2 rounded', {
'bg-indigo-100': active?,
}
)
),
}

content_tag :li, class: "-mx-2" do
link_to @item, html_options do
content_tag :div, class: "flex items-center truncate" do
content_tag :div, class: "truncate" do
content_tag :div, @label, class: "text-sm font-medium text-slate-800"
turbo_frame_tag dom_id(@item, 'list') do
content_tag :li, class: '-mx-2' do
link_to @item, html_options do
content_tag :div, class: 'flex items-center truncate' do
content_tag :div, class: 'truncate' do
content_tag :div, @label, class: 'text-sm font-medium text-slate-800'
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
class ApplicationController < ActionController::Base
include Pagy::Backend

before_action :turbo_frame_request_variant

private

def turbo_frame_request_variant
request.variant = :turbo_frame if turbo_frame_request?
end
end
28 changes: 21 additions & 7 deletions app/controllers/kit/products_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ class ProductsController < ApplicationController

# GET /kit/products or /kit/products.json
def index
@kit_product = @kit_products.first
@kit_product = Kit::Product.new
end

# GET /kit/products/1 or /kit/products/1.json
def show
respond_to do |format|
format.html { render(:index) }
format.html { render(turbo_frame_request? ? :show : :index) }
format.json { render(:show) }
end
end
Expand All @@ -22,7 +22,10 @@ def show
def new
@kit_product = Kit::Product.new

render(:index)
respond_to do |format|
format.html { render(turbo_frame_request? ? :show : :index) }
format.turbo_stream { render(:show) }
end
end

# POST /kit/products or /kit/products.json
Expand All @@ -31,7 +34,9 @@ def create

respond_to do |format|
if @kit_product.save
format.html { redirect_to(kit_product_url(@kit_product), notice: 'Product was successfully created.') }
flash.now[:notice] = 'Product was successfully created.'

format.html { redirect_to(@kit_product) }
format.json { render(:show, status: :created, location: @kit_product) }
else
format.html do
Expand All @@ -41,14 +46,18 @@ def create
end
format.json { render(json: @kit_product.errors, status: :unprocessable_entity) }
end

format.turbo_stream
end
end

# PATCH/PUT /kit/products/1 or /kit/products/1.json
def update
respond_to do |format|
if @kit_product.update(kit_product_params)
format.html { redirect_to(kit_product_url(@kit_product), notice: 'Product was successfully updated.') }
flash.now[:notice] = 'Product was successfully updated.'

format.html { redirect_to(@kit_product) }
format.json { render(:show, status: :ok, location: @kit_product) }
else
format.html do
Expand All @@ -58,23 +67,28 @@ def update
end
format.json { render(json: @kit_product.errors, status: :unprocessable_entity) }
end

format.turbo_stream
end
end

# DELETE /kit/products/1 or /kit/products/1.json
def destroy
@kit_product.destroy

flash.now[:notice] = 'Product was successfully destroyed.'

respond_to do |format|
format.html { redirect_to(kit_products_url, notice: 'Product was successfully destroyed.') }
format.html { redirect_to(kit_products_url) }
format.json { head(:no_content) }
format.turbo_stream
end
end

private

def load_kit_products
@q = Kit::Product.ransack(params[:q])
@q = Kit::Product.select(:id, :name).ransack(params[:q])
@pagy, @kit_products = pagy(@q.result)
end

Expand Down
1 change: 1 addition & 0 deletions app/views/kit/products/_list.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</div>
<%= link_to new_kit_product_path,
aria: { label: "New product" },
data: { turbo_frame: "#{Kit::Product.model_name.singular}_form" },
class: "p-1.5 shrink-0 rounded border border-slate-200 hover:border-slate-300 shadow-sm ml-2" do %>
<svg class="w-4 h-4 fill-current" viewBox="0 0 16 16">
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z"></path>
Expand Down
68 changes: 37 additions & 31 deletions app/views/kit/products/_product.html.erb
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
<h2 class="text-2xl text-slate-800 font-bold mb-6"><%= "#{product.persisted? ? 'Edit' : 'New'} Product" %></h2>
<%= turbo_frame_tag 'kit_product_form' do %>
<h2 class="text-2xl text-slate-800 font-bold mb-6"><%= "#{product.persisted? ? 'Edit' : 'New'} Product" %></h2>

<% if notice.present? %>
<div class="px-4 py-2 rounded-sm text-sm bg-emerald-100 border border-emerald-200 text-emerald-600">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z"></path>
</svg>
<div><%= notice %></div>
<% if notice.present? %>
<div class="px-4 py-2 rounded-sm text-sm bg-emerald-100 border border-emerald-200 text-emerald-600">
<div class="flex w-full justify-between items-start">
<div class="flex">
<svg class="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z"></path>
</svg>
<div><%= notice %></div>
</div>
</div>
</div>
</div>
<% end %>

<%= simple_form_for product, html: { class: 'grow space-y-6' } do |form| %>
<% if product.errors.any? %>
<div class="text-rose-500">
<h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>
</div>
<% end %>
<div class="grid gap-5 md:grid-cols-3">
<div>
<%= form.input :name %>
</div>
</div>
<footer>
<div class="flex flex-col py-5 border-t border-slate-200">
<div class="flex self-end">
<%= link_to "Destroy this product", product,
data: { turbo_method: :delete, turbo_confirm: "Are you sure?" },
class: "btn shadow-none text-rose-500 mr-3" if product.persisted? %>
<%= link_to "Back", product.persisted? ? kit_products_path : product, class: "btn border-slate-200 hover:border-slate-300 text-slate-600" %>
<%= form.button :submit, class: "bg-indigo-500 hover:bg-indigo-600 text-white ml-3" %>

<%= simple_form_for product, html: { class: 'grow space-y-6' } do |form| %>
<% if product.errors.any? %>
<div class="text-rose-500">
<h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>
</div>
<% end %>
<div class="grid gap-5 md:grid-cols-3">
<div>
<%= form.input :name %>
</div>
</div>
</footer>
<footer>
<div class="flex flex-col py-5 border-t border-slate-200">
<div class="flex self-end">
<% if product.persisted? %>
<%= link_to "Destroy this product", product,
data: { turbo_method: :delete, turbo_confirm: "Are you sure?" },
class: "btn shadow-none text-rose-500 mr-3" %>
<%= link_to "Back", new_kit_product_path,
data: { turbo_frame: 'kit_product_form' },
class: "btn border-slate-200 hover:border-slate-300 text-slate-600" %>
<% end %>
<%= form.button :submit, class: "bg-indigo-500 hover:bg-indigo-600 text-white ml-3" %>
</div>
</div>
</footer>
<% end %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/kit/products/_product.json.jbuilder
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# frozen_string_literal: true

json.extract!(kit_product, :id, :name, :created_at, :updated_at)
json.extract!(kit_product, :id, :name)
json.url(api_kit_product_url(kit_product, format: :json))
2 changes: 2 additions & 0 deletions app/views/kit/products/create.turbo_stream.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= turbo_stream.update "#{@kit_product.model_name.singular}_form", partial: "kit/products/product", locals: { lash: flash, product: @kit_product } %>
<%= turbo_stream.append "list_#{@kit_product.model_name.plural}", inline: render(SearchListItemComponent.new(@kit_product)) if @kit_product.persisted? %>
Loading