Add reactions to posts

This commit is contained in:
2024-03-31 09:03:40 +11:00
parent 185d363fbe
commit 03ba5ae54a
12 changed files with 85 additions and 4 deletions

View File

@@ -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

View File

@@ -11,6 +11,8 @@ module Adamantium
has_many :post_trips
has_many :trips, through: :post_trips
has_many :reactions
has_many :webmentions
end
end

View 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

View 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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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")
}

View 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

View File

@@ -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

View 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