Skip to content
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

Add components for Article #24

Merged
merged 5 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ RSpec/ContextWording:
Prefixes:
- when
- given

Lint/MissingSuper:
Exclude:
- 'app/components/**/*'
11 changes: 11 additions & 0 deletions app/components/application_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class ApplicationComponent < ViewComponent::Base
def initialize(tag: nil, classes: nil, **options)
@tag = tag
@classes = classes
@options = options
end

def call
content_tag(@tag, content, class: @classes, **@options) if @tag
end
end
11 changes: 11 additions & 0 deletions app/components/articles/list_items/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="post-preview">
<%= link_to article do %>
<h2 class="post-title"><%= article.title %></h2>
<h3 class="post-subtitle"><%= truncate(article.content.to_plain_text, length: 100) %></h3>
<% end %>

<%= render PostingDetails::Component.new(name: 'Author', time: article.created_at) %>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Pager-->
15 changes: 15 additions & 0 deletions app/components/articles/list_items/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Articles
module ListItems
class Component < ApplicationComponent
attr_reader :article

with_collection_parameter :article

def initialize(article:)
@article = article
end
end
end
end
44 changes: 44 additions & 0 deletions app/components/base/button/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

module Base
module Button
class Component < ApplicationComponent
Copy link

@github-actions github-actions bot Sep 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Has 7 constants


attr_reader :type, :link

BASE_CLASSES = %w[btn].freeze

PRIMARY_CLASSES = %w[btn-primary].freeze
SECONDARY_CLASSES = %w[btn-secondary].freeze
SUCCESS_CLASSES = %w[btn-success].freeze
DANGER_CLASSES = %w[btn-danger].freeze
LINK_CLASSES = %w[btn-link].freeze

BUTTON_TYPE_MAPPING = {
primary: PRIMARY_CLASSES,
secondary: SECONDARY_CLASSES,
success: SUCCESS_CLASSES,
danger: DANGER_CLASSES,
link: LINK_CLASSES
}.freeze

def initialize(type: :primary, link: '#', **options)
@options = options

@options[:tag] ||= :a
Comment on lines +25 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering a few days ago how to have a clean solution that accepts both <button> and <a> tags :)

That way is nice!
One question though: If the tag is 'button', should we remove the default value of the link param?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Will do that,

@options[:href] = link
@options[:classes] = classes(type)
end

def call
render ApplicationComponent.new(**@options).with_content(content)
end

private

def classes(type)
Copy link

@github-actions github-actions bot Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Doesn't depend on instance state (maybe move it to another class?)

(BASE_CLASSES + BUTTON_TYPE_MAPPING[type]).join(' ')
end
end
end
end
3 changes: 0 additions & 3 deletions app/components/button_component.html.erb

This file was deleted.

43 changes: 0 additions & 43 deletions app/components/button_component.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<header class="masthead" style="background-image: url(<%= image_url "header-image.jpeg" %>)">
<header class="masthead" style="background-image: url(<%= image %>)">
<div class="container position-relative px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<div class="site-heading">
<h1>View Component Blog</h1>
<span class="subheading">Nimble Growth#35 Project</span>
<h1><%= heading %></h1>
<span class="subheading"><%= subheading %></span>
</div>
</div>
</div>
Expand Down
13 changes: 13 additions & 0 deletions app/components/header/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Header
class Component < ApplicationComponent
attr_reader :image, :heading, :subheading

def initialize(image:, heading:, subheading:)
@image = image
@heading = heading
@subheading = subheading
end
end
end
1 change: 1 addition & 0 deletions app/components/posting_details/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p class="post-meta">Posted by <a href="#"><%= name %></a> on <%= post_time(time) %></p>
13 changes: 13 additions & 0 deletions app/components/posting_details/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module PostingDetails
class Component < ApplicationComponent
attr_reader :time, :name
def initialize(name:, time:)
@name = name
@time = time
end

delegate :post_time, to: :helpers
end
end
16 changes: 8 additions & 8 deletions app/controllers/articles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ def destroy
end

private
# Use callbacks to share common setup or constraints between actions.
def set_article
@article = Article.find(params[:id])
end
# Use callbacks to share common setup or constraints between actions.
def set_article
@article = Article.find(params[:id])
end

# Only allow a list of trusted parameters through.
def article_params
params.require(:article).permit(:title, :content)
end
# Only allow a list of trusted parameters through.
def article_params
params.require(:article).permit(:title, :content, :avatar)
end
end
2 changes: 2 additions & 0 deletions app/models/article.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class Article < ApplicationRecord
has_many :comments

has_one_attached :avatar

validates :title, presence: true
has_rich_text :content
end
5 changes: 5 additions & 0 deletions app/views/articles/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<%= form.text_field :title, class: "form-control", placeholder: "Title of your blog" %>
</div>

<div class="form-group">
<%= form.label 'Cover image' %>
<%= form.file_field :avatar, class: "form-control" %>
</div>

<div class="form-group">
<%= form.label :content %>
<%= form.rich_text_area :content %>
Expand Down
4 changes: 4 additions & 0 deletions app/views/articles/edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<%= render Header::Component.new(image: image_url("write-blog.jpeg"),
heading: "Edit Blog",
subheading: @article.title) %>

<div class="container px-4 px-lg-5 mb-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div><h1 class="d-flex">Edit blog</h1></div>
Expand Down
22 changes: 5 additions & 17 deletions app/views/articles/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
<%= render Header::Component.new(image: image_url("header-image.jpeg"),
heading: "View Component in Real World",
subheading: "Growth#35 Project") %>

<p id="notice"><%= notice %></p>

<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<!-- Post preview-->
<% @articles.each do |article| %>
<div class="post-preview">
<%= link_to article do %>
<h2 class="post-title"><%= article.title %></h2>
<h3 class="post-subtitle"><%= truncate(article.content.to_plain_text, length: 100) %></h3>
<% end %>
<p class="post-meta">
Posted by
<a href="#!">Author</a>
on <%= post_time(article.created_at) %>
</p>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Pager-->
<% end %>
<%= render Articles::ListItems::Component.with_collection(@articles) %>

<%== pagy_bootstrap_nav(@pagy) %>
</div>
Expand Down
4 changes: 4 additions & 0 deletions app/views/articles/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<%= render Header::Component.new(image: image_url("write-blog.jpeg"),
heading: "Write A Blog",
subheading: "Publish to the world") %>

<div class="container px-4 px-lg-5 mb-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div><h1 class="d-flex">Create a blog</h1></div>
Expand Down
13 changes: 10 additions & 3 deletions app/views/articles/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
<%= render Header::Component.new(image: url_for(@article.avatar.attached? ? @article.avatar : nil),
heading: @article.title,
subheading: (render PostingDetails::Component
.new(name: "Author", time:@article.created_at))) %>

<p id="notice"><%= notice %></p>

<article class="mb-4">
Expand All @@ -6,9 +11,11 @@
<div class="col-md-10 col-lg-8 col-xl-7">
<%= @article.content %>
<div class="mt-5">
<%= link_to 'Edit Blog', edit_article_path(@article), class: "btn btn-primary" %>
<%= link_to 'Delete Blog', @article, method: :delete, class: "btn btn-danger",
data: { confirm: 'Are you sure?' } %>
<%= render ::Base::Button::Component.new(link: edit_article_path(@article))
.with_content('Edit Blog') %>
<%= render ::Base::Button::Component.new(link: @article, type: :danger, method: :delete,
data: { confirm: 'Are you sure?' })
.with_content('Delete Blog') %>
</div>

<% if @article.comments.present? %>
Expand Down
1 change: 0 additions & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

<body>
<%= render 'shared/navbar' %>
<%= render 'shared/header' %>
<%= yield %>
<%= render 'shared/footer' %>
</body>
Expand Down