Add reactions to posts
This commit is contained in:
2
Gemfile
2
Gemfile
@@ -67,7 +67,7 @@ gem "warning"
|
||||
group :cli, :development do
|
||||
gem "irb"
|
||||
gem "hanami-reloader", "~> 2.1.0.rc"
|
||||
gem 'rubocop', require: false
|
||||
gem "rubocop", require: false
|
||||
end
|
||||
|
||||
group :cli, :development, :test do
|
||||
|
@@ -11,6 +11,8 @@ module Adamantium
|
||||
has_many :post_trips
|
||||
has_many :trips, through: :post_trips
|
||||
|
||||
has_many :reactions
|
||||
|
||||
has_many :webmentions
|
||||
end
|
||||
end
|
||||
|
15
app/relations/reactions.rb
Normal file
15
app/relations/reactions.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Adamantium
|
||||
module Relations
|
||||
class Reactions < ROM::Relation[:sql]
|
||||
schema :reactions, infer: true do
|
||||
associations do
|
||||
belongs_to :post
|
||||
end
|
||||
end
|
||||
|
||||
auto_struct(true)
|
||||
end
|
||||
end
|
||||
end
|
14
db/migrate/20240330213418_create_reactions.rb
Normal file
14
db/migrate/20240330213418_create_reactions.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
ROM::SQL.migration do
|
||||
change do
|
||||
create_table :reactions do
|
||||
primary_key :id
|
||||
foreign_key :post_id, :posts, null: false
|
||||
column :visitor_identifier, :text, null: false
|
||||
|
||||
index :post_id
|
||||
unique [:post_id, :visitor_identifier]
|
||||
end
|
||||
end
|
||||
end
|
@@ -64,6 +64,7 @@ module Admin
|
||||
def list
|
||||
posts
|
||||
.where(post_type: ["post", "checkin", "code"])
|
||||
.combine(:reactions, :webmentions)
|
||||
.order(Sequel.lit("published_at desc"))
|
||||
.to_a
|
||||
end
|
||||
|
@@ -9,6 +9,8 @@ div class="max-w-prose mx-auto" x-data="{ activeTab: 0 }"
|
||||
thead
|
||||
th Details
|
||||
th Date
|
||||
th Mentions
|
||||
th Reactions
|
||||
th colspan="2" Actions
|
||||
tbody class="{ 'active': activeTab === 0 }" x-show.transition.in.opacity.duration.600="activeTab === 0"
|
||||
- published_posts.each do |post|
|
||||
@@ -20,6 +22,10 @@ div class="max-w-prose mx-auto" x-data="{ activeTab: 0 }"
|
||||
small class="text-gray-400 dark:text-gray-600" = post.slug
|
||||
td
|
||||
= post.published_at&.strftime("%d %b %Y")
|
||||
td
|
||||
= post.webmentions.count
|
||||
td
|
||||
= post.reactions.count
|
||||
td
|
||||
a href="/admin/posts/#{post.id}" edit
|
||||
td
|
||||
@@ -36,6 +42,10 @@ div class="max-w-prose mx-auto" x-data="{ activeTab: 0 }"
|
||||
small class="text-gray-400 dark:text-gray-600" = post.slug
|
||||
td
|
||||
= post.published_at&.strftime("%d %b %Y")
|
||||
td
|
||||
= post.webmentions.count
|
||||
td
|
||||
= post.reactions.count
|
||||
td
|
||||
a href="/admin/posts/#{post.id}" edit
|
||||
td
|
||||
|
23
slices/main/actions/posts/react.rb
Normal file
23
slices/main/actions/posts/react.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Main
|
||||
module Actions
|
||||
module Posts
|
||||
class React < Action
|
||||
|
||||
include Deps["repos.reaction_repo", "repos.post_repo"]
|
||||
|
||||
def handle(req, res)
|
||||
post = post_repo.fetch!(req.params[:slug])
|
||||
|
||||
reaction_repo.create(post_id: post.id, visitor_identifier: Digest::SHA1.hexdigest(req.ip))
|
||||
|
||||
reaction_count = reaction_repo.count(post_id: post.id)
|
||||
|
||||
res.body = "👍 #{reaction_count}"
|
||||
res.status = 201
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@@ -50,6 +50,8 @@ module Main
|
||||
|
||||
get "/timemachine/:year/:month/:day", to: "timemachine.show"
|
||||
|
||||
post "/posts/:slug/react", to: "posts.react"
|
||||
|
||||
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"
|
||||
end
|
||||
|
@@ -184,7 +184,7 @@ module Main
|
||||
def fetch!(slug)
|
||||
posts
|
||||
.published
|
||||
.combine(:tags, :trips, :webmentions)
|
||||
.combine(:tags, :trips, :webmentions, :reactions)
|
||||
.node(:webmentions) { |webmention|
|
||||
webmention.published.where(type: "reply")
|
||||
}
|
||||
|
11
slices/main/repos/reaction_repo.rb
Normal file
11
slices/main/repos/reaction_repo.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
module Main
|
||||
module Repos
|
||||
class ReactionRepo < Adamantium::Repo[:reactions]
|
||||
commands :create
|
||||
|
||||
def count(post_id:)
|
||||
reactions.where(post_id: post_id).count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@@ -57,8 +57,8 @@ article class="h-entry"
|
||||
|
||||
- if post.location
|
||||
img loading="lazy" class="shadow-solid shadow-pink-100 dark:shadow-pink-200 rounded mb-4" src=post.large_map
|
||||
- if post.webmentions && post.webmentions.count == 0 && post.commentable
|
||||
a href="mailto:blog@dnitza.com?subject=About that post of yours&body=%0A%0A---%0A(In reply to #{post.permalink})" Reply
|
||||
div class="max-w-prose mx-auto text-gray-600 dark:text-gray-200 flex"
|
||||
= render "shared/reactions", post: post
|
||||
- if post.webmentions && post.webmentions.count > 0
|
||||
div class="mt-12"
|
||||
h3
|
||||
|
3
slices/main/templates/shared/_reactions.html.slim
Normal file
3
slices/main/templates/shared/_reactions.html.slim
Normal file
@@ -0,0 +1,3 @@
|
||||
button hx-post="/posts/#{post.slug}/react" hx-trigger="click" class="px-2 py-1 border rounded border-indigo-900 hover:border-indigo-400 text-indigo-200 mr-2" 👍 #{post.reactions.count}
|
||||
- if post.webmentions && post.webmentions.count == 0 && post.commentable
|
||||
a class="no-underline px-2 py-1 border rounded border-indigo-900 hover:border-indigo-400 text-indigo-200 mr-2" href="mailto:blog@dnitza.com?subject=About that post of yours&body=%0A%0A---%0A(In reply to #{post.permalink})" ✉️ Reply
|
Reference in New Issue
Block a user