Add books page
This commit is contained in:
13
app/actions/books/index.rb
Normal file
13
app/actions/books/index.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Adamantium
|
||||
module Actions
|
||||
module Books
|
||||
class Index < Action
|
||||
include Deps["views.books.index"]
|
||||
|
||||
def handle(req, res)
|
||||
res.render index
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
app/commands/posts/create_book_post.rb
Normal file
19
app/commands/posts/create_book_post.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require "dry/monads"
|
||||
|
||||
module Adamantium
|
||||
module Commands
|
||||
module Posts
|
||||
class CreateBookPost < Command
|
||||
include Deps["repos.post_repo"]
|
||||
|
||||
include Dry::Monads[:result]
|
||||
|
||||
def call(post)
|
||||
created_post = post_repo.create(post)
|
||||
|
||||
Success(created_post)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@@ -6,9 +6,11 @@ module Adamantium
|
||||
"validation.posts.post_contract",
|
||||
"validation.posts.bookmark_contract",
|
||||
"validation.posts.checkin_contract",
|
||||
"validation.posts.book_contract",
|
||||
"commands.posts.create_entry",
|
||||
"commands.posts.create_bookmark",
|
||||
"commands.posts.create_checkin"
|
||||
"commands.posts.create_checkin",
|
||||
"commands.posts.create_book_post"
|
||||
]
|
||||
|
||||
def call(entry_type:)
|
||||
@@ -17,6 +19,8 @@ module Adamantium
|
||||
{command: create_bookmark, validation: bookmark_contract}
|
||||
in Entities::CheckinRequest
|
||||
{command: create_checkin, validation: checkin_contract}
|
||||
in Entities::BookRequest
|
||||
{command: create_book_post, validation: book_contract}
|
||||
else
|
||||
{command: create_entry, validation: post_contract}
|
||||
end
|
||||
|
27
app/decorators/books/decorator.rb
Normal file
27
app/decorators/books/decorator.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: false
|
||||
|
||||
# auto_register: false
|
||||
|
||||
module Adamantium
|
||||
module Decorators
|
||||
module Books
|
||||
class Decorator < SimpleDelegator
|
||||
def display_published_at
|
||||
published_at.strftime("%e %B, %Y")
|
||||
end
|
||||
|
||||
def machine_published_at
|
||||
published_at.rfc2822
|
||||
end
|
||||
|
||||
def syndicated?
|
||||
!syndication_sources.empty?
|
||||
end
|
||||
|
||||
def template_type
|
||||
:book
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
15
app/entities/book_request.rb
Normal file
15
app/entities/book_request.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Adamantium
|
||||
module Entities
|
||||
class BookRequest < Dry::Struct
|
||||
attribute :h, Types::Coercible::String
|
||||
attribute :content, Types::Coercible::String
|
||||
attribute :book_status, Types::Coercible::String
|
||||
attribute :name, Types::Coercible::String
|
||||
attribute :book_author, Types::Coercible::String
|
||||
attribute :slug, Types::Coercible::String
|
||||
attribute :category, Types::Array.of(Types::Coercible::String)
|
||||
attribute :published_at, Types::Nominal::DateTime
|
||||
attribute :post_type, Types::Coercible::String
|
||||
end
|
||||
end
|
||||
end
|
@@ -127,6 +127,15 @@ module Adamantium
|
||||
.to_a
|
||||
end
|
||||
|
||||
def books_listing(limit: nil)
|
||||
posts
|
||||
.where(post_type: "book")
|
||||
.published
|
||||
.order(Sequel.desc(:published_at))
|
||||
.limit(limit)
|
||||
.to_a
|
||||
end
|
||||
|
||||
def bookmark_listing(query: nil)
|
||||
base = posts
|
||||
.where(post_type: "bookmark")
|
||||
|
23
app/templates/books/index.html.slim
Normal file
23
app/templates/books/index.html.slim
Normal file
@@ -0,0 +1,23 @@
|
||||
- context.content_for(:title, "Books | ")
|
||||
|
||||
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
||||
h1 Books
|
||||
|
||||
div class="mb-12 max-w-prose mx-auto"
|
||||
table class="prose dark:prose-invert table-auto"
|
||||
thead
|
||||
tr
|
||||
td Title
|
||||
td Author
|
||||
td Status
|
||||
- books.each do |book|
|
||||
tr
|
||||
td
|
||||
/ a href="/books/#{book.slug}"
|
||||
= book.name
|
||||
td
|
||||
= book.book_author
|
||||
td
|
||||
= book.book_status
|
||||
|
||||
div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"
|
18
app/validation/posts/book_contract.rb
Normal file
18
app/validation/posts/book_contract.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module Adamantium
|
||||
module Validation
|
||||
module Posts
|
||||
class BookContract < Dry::Validation::Contract
|
||||
params do
|
||||
required(:name).maybe(:string)
|
||||
required(:content).filled(:string)
|
||||
required(:category).array(:string)
|
||||
required(:published_at).maybe(:time)
|
||||
required(:slug).filled(:string)
|
||||
required(:post_type).value(included_in?: %w[book])
|
||||
required(:book_author).maybe(:string)
|
||||
required(:book_status).value(included_in?: %w[to-read reading read])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
15
app/views/books/index.rb
Normal file
15
app/views/books/index.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Adamantium
|
||||
module Views
|
||||
module Books
|
||||
class Index < Adamantium::View
|
||||
include Deps["repos.post_repo"]
|
||||
|
||||
expose :books do
|
||||
post_repo.books_listing.map do |book|
|
||||
Decorators::Books::Decorator.new book
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@@ -59,6 +59,8 @@ module Adamantium
|
||||
|
||||
get "/podcasts", to: "podcasts.index"
|
||||
|
||||
get "/books", to: "books.index"
|
||||
|
||||
redirect "deploying-a-hanami-app-to-fly-io", to: "/post/deploying-a-hanami-20-app-to-flyio"
|
||||
redirect "deploying-a-hanami-app-to-fly-io/", to: "/post/deploying-a-hanami-20-app-to-flyio"
|
||||
|
||||
|
10
db/migrate/20230626090009_add_book_posts.rb
Normal file
10
db/migrate/20230626090009_add_book_posts.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
ROM::SQL.migration do
|
||||
change do
|
||||
alter_table :posts do
|
||||
add_column :book_status, :text, default: nil
|
||||
add_column :book_author, :text, default: nil
|
||||
end
|
||||
end
|
||||
end
|
@@ -13,6 +13,9 @@ module Adamantium
|
||||
when :checkin
|
||||
checkin_params = parse_checkin_params(params)
|
||||
Entities::CheckinRequest.new(checkin_params)
|
||||
when :book
|
||||
book_params = parse_book_params(params)
|
||||
Entities::BookRequest.new(book_params)
|
||||
else
|
||||
req_params = parse_post_params(req_type, cont_type, params)
|
||||
Entities::PostRequest.new(req_params)
|
||||
@@ -23,6 +26,7 @@ module Adamantium
|
||||
|
||||
def content_type(params)
|
||||
return :bookmark if params[:"bookmark-of"]
|
||||
return :book if params.dig(:properties, :"read-of")
|
||||
return :checkin if params.dig(:properties, :checkin)
|
||||
:post
|
||||
end
|
||||
@@ -110,5 +114,23 @@ module Adamantium
|
||||
new_params[:location] = "geo:#{location.dig(:latitude).first},#{location.dig(:longitude).first};u=0"
|
||||
new_params
|
||||
end
|
||||
|
||||
def parse_book_params(params)
|
||||
new_params = {}
|
||||
new_params[:post_type] = "book"
|
||||
|
||||
entry = params[:properties]
|
||||
new_params[:h] = "entry"
|
||||
new_params[:content] = entry[:summary].first
|
||||
new_params[:book_status] = entry[:"read-status"].first
|
||||
|
||||
book = params.dig(:properties, :"read-of").first[:properties]
|
||||
new_params[:name] = book[:name].first
|
||||
new_params[:book_author] = book[:author].first
|
||||
new_params[:slug] = book[:uid].first
|
||||
new_params[:category] = []
|
||||
new_params[:published_at] = Time.now
|
||||
new_params
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -9,5 +9,5 @@ div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:
|
||||
button hx-post="/admin/posts/#{post.id}/syndicate/day_one" Send to Day One
|
||||
article class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200 prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline prose-img:rounded"
|
||||
h1= post.name
|
||||
textarea class="w-full border-pink-200 border-2 rounded p-2" x-data="{ resize: () => { $el.style.height = '5px'; $el.style.height = $el.scrollHeight + 'px' } }" x-init="resize()" @input="resize()"
|
||||
textarea class="text-gray-800 w-full border-blue-200 border-2 rounded p-2" x-data="{ resize: () => { $el.style.height = '5px'; $el.style.height = $el.scrollHeight + 'px' } }" x-init="resize()" @input="resize()"
|
||||
== markdown_body
|
Reference in New Issue
Block a user