More details on posts and error reporting

This commit is contained in:
2023-05-31 22:12:48 +10:00
parent b034ecb3ab
commit 2c1122c9d7
20 changed files with 177 additions and 39 deletions

View File

@@ -49,6 +49,8 @@ gem "connection_pool"
gem "omdb-api", require: false
gem "image_processing", "~> 1.0"
gem "sentry-ruby"
group :cli, :development do
gem "hanami-reloader"
end

View File

@@ -405,6 +405,8 @@ GEM
sanitize (6.0.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
sentry-ruby (5.9.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
sequel (5.68.0)
shellany (0.0.1)
simple-rss (1.3.3)
@@ -500,6 +502,7 @@ DEPENDENCIES
ruby-readability
sanitize
scraperd!
sentry-ruby
slim
standardrb
time_math2

View File

@@ -9,12 +9,17 @@ require "dry/matcher/result_matcher"
module Adamantium
class Action < Hanami::Action
include Deps["logger", "settings", not_found_view: "views.not_found"]
include Deps["logger",
"settings",
not_found_view: "views.not_found",
error_view: "views.error",
sentry: "sentry.client"]
include Dry::Matcher.for(:handle, with: Dry::Matcher::ResultMatcher)
include Dry::Monads[:result]
handle_exception ROM::TupleCountMismatchError => :not_found
handle_exception StandardError => :handle_error
def authenticate!(req, res)
if Hanami.env == :development || Hanami.env == :test
@@ -47,6 +52,16 @@ module Adamantium
res.render not_found_view
end
def handle_error(req, res, exception)
raise exception if settings.raise_exceptions
sentry.capture_exception(exception)
res.status = 500
res.render error_view
res.headers["Cache-Control"] = "no-store, max-age=0"
end
def verify_scope(req:, scope:)
req.env[:scopes].include? scope
end

View File

@@ -97,6 +97,16 @@ module Adamantium
:post
end
def posted_in
if name.nil?
:statuses
elsif location.nil?
:posts
else
:places
end
end
private
# e.g. geo:-37.75188,144.90417;u=35

View File

@@ -27,6 +27,9 @@ div class="max-w-prose mx-auto text-gray-600 dark:text-gray-200 flex"
= "Published "
time class="dt-published" datetime=bookmark.machine_published_at
= bookmark.display_published_at
p
span in&nbsp;
a class="hover:underline" href="/bookmarks" bookmarks
span class="text-right flex-1"
== render "shared/tags", tags: bookmark.tags

View File

@@ -0,0 +1,2 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 There was an error!

View File

@@ -4,16 +4,16 @@ div class="mb-12 max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h2 class="text-xl" Explore posts
div class="grid grid-cols-4 grid-flow-col gap-2 mb-6"
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/tags" 🔖 By tag
/ a class="block p-1 border border-lime-200 bg-lime-300 text-lime-900 hover:bg-lime-200 text-center rounded-lg" href="/years" 🗓️ By year
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/posts" 🪧 All posts
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/tags" 🔖 By tag
/ a class="block p-1 border border-blue-200 bg-blue-300 text-blue-900 hover:bg-blue-200 text-center rounded-lg" href="/years" 🗓️ By year
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/posts" 🪧 All posts
h2 class="text-xl" Explore everything else
div class="grid grid-cols-4 grid-flow-col gap-2 mb-6"
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/colophon" 🧱 Colophon
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/hikes" 🥾 Hikes
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/movies" 🍿 Movies
a class="block p-1 border border-lime-200 bg-lime-200 text-lime-900 hover:bg-lime-300 text-center rounded-lg" href="/trips" 🛫 Trips
/ a class="block p-1 border border-lime-200 bg-lime-300 text-lime-900 hover:bg-lime-200 text-center rounded-lg" href="/art" 🎨 Art things
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/colophon" 🧱 Colophon
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/hikes" 🥾 Hikes
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/movies" 🍿 Movies
a class="block p-1 border border-blue-200 bg-blue-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/trips" 🛫 Trips
/ a class="block p-1 border border-blue-200 bg-blue-300 text-blue-900 hover:bg-blue-200 text-center rounded-lg" href="/art" 🎨 Art things

View File

@@ -1,3 +1,2 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 Not Found!

View File

@@ -89,6 +89,14 @@ article class="h-entry"
p
a class="p-author h-card" href=Hanami.app.settings.micropub_site_url
= "by #{Hanami.app.settings.site_name}"
p
span in&nbsp;
- if post.posted_in == :posts
a class="hover:underline" href="/posts" posts
- if post.posted_in == :places
a class="hover:underline" href="/places" places
- if post.posted_in == :statuses
a class="hover:underline" href="/statuses" statuses
span class="text-right flex-1 leading-6"
== render "shared/tags", tags: post.tags
div class="mb-2 max-w-prose mx-auto text-gray-600 dark:text-gray-200 flex"

6
app/views/error.rb Normal file
View File

@@ -0,0 +1,6 @@
module Adamantium
module Views
class Error < View
end
end
end

View File

@@ -0,0 +1,14 @@
require "sentry-ruby"
Hanami.app.register_provider :sentry, namespace: true do
prepare do
Sentry.init do |config|
config.dsn = target["settings"].sentry_dsn
config.traces_sample_rate = 0.25
end
end
start do
register "client", Sentry
end
end

View File

@@ -25,6 +25,7 @@ module Adamantium
get "/post/top_tracks/:slug", to: "posts.top_tracks"
get "/post/:slug", to: "posts.show"
get "/posts", to: "posts.index"
# get "/posts/archive", to: "posts.archive"
get "/posts/archive/:year", to: "posts.archive"
get "/bookmarks", to: "bookmarks.index"
@@ -82,6 +83,7 @@ module Adamantium
get "/posts", to: "posts.index"
delete "/posts/:id", to: "posts.delete"
post "/posts/:id/archive", to: "posts.archive"
post "/posts/:id/publish", to: "posts.publish"
get "/media", to: "photos.index"

View File

@@ -50,5 +50,8 @@ module Adamantium
setting :basic_auth_username, default: nil
setting :basic_auth_password, default: nil
setting :sentry_dsn, default: nil
setting :raise_exceptions, default: true
end
end

View File

@@ -4,6 +4,7 @@ module Admin
def list
posts
.where(post_type: "bookmark")
.order(Sequel.lit("published_at desc"))
.to_a
end

View File

@@ -38,6 +38,7 @@ module Admin
def list
posts
.where(post_type: "post")
.order(Sequel.lit("published_at desc"))
.to_a
end
@@ -45,6 +46,10 @@ module Admin
posts.where(id: id).delete
end
def publish(id:)
posts.where(id: id).update(published_at: Time.now)
end
def archive(id:)
posts.where(id: id).update(published_at: nil)
end

View File

@@ -1,17 +1,42 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 Admin // Bookmarks
div class="max-w-prose mx-auto"
button class="rounded bg-blue-100 hover:bg-blue-200 text-blue-600 px-2 hover:cursor-pointer" hx-post="/admin/bookmarks/clean" Check for dead links
div class="max-w-prose mx-auto" x-data="{ activeTab: 0 }"
- if running_jobs
div class="text-center bg-blue-100 mb-4 p-2 rounded" Job already queued
- else
button class="block rounded bg-blue-100 hover:bg-blue-200 text-blue-600 mb-4 p-2 hover:cursor-pointer" hx-post="/admin/bookmarks/clean" Check for dead links
div class="flex"
a href="#" class="text-gray-200 cursor-pointer p-2 border-2 mr-2 rounded border-blue-400" :class="{ 'bg-blue-400 text-blue-900': activeTab === 0 }" @click="activeTab = 0" class="tab-control" Published
a href="#" class="text-gray-200 cursor-pointer p-2 border-2 rounded border-blue-400" :class="{ 'bg-blue-400 text-blue-900': activeTab === 1 }" @click="activeTab = 1" class="tab-control" Un published
table class="prose dark:prose-invert table-auto prose-a:text-blue-600 prose-a:no-underline"
thead
th Details
th Date
th colspan="2" Actions
tbody
- bookmarks.each do |bookmark|
tbody class="{ 'active': activeTab === 0 }" x-show.transition.in.opacity.duration.600="activeTab === 0"
- published_bookmarks.each do |bookmark|
tr id="bookmark-#{bookmark.id}"
td
div
= bookmark.name
a class="no-underline" href=bookmark.url
small class="text-gray-400 dark:text-gray-600" = bookmark.url
div
- if bookmark.cached_content
a href="/bookmark/#{bookmark.slug}" View cached version
span &nbsp; — &nbsp;
button hx-post="/admin/bookmarks/cache/#{bookmark.id}" Re-cache
- else
button hx-post="/admin/bookmarks/cache/#{bookmark.id}" No cached content, cache now?
td
= bookmark.published_at&.strftime("%d %b %Y")
td
button class="text-red-600" hx-delete="/admin/bookmarks/#{bookmark.id}" hx-target="#bookmark-#{bookmark.id}" delete
td
button hx-post="/admin/bookmarks/#{bookmark.id}/archive" archive
tbody class="{ 'active': activeTab === 1 }" x-show.transition.in.opacity.duration.600="activeTab === 1"
- unpublished_bookmarks.each do |bookmark|
tr id="bookmark-#{bookmark.id}"
td
div

View File

@@ -18,4 +18,4 @@ div class="mb-4 max-w-prose mx-auto prose dark:prose-invert"
div class="rounded max-w-xs" x-data=""
img class="rounded object-cover hover:opacity-80 h-48 w-48" src="/#{photo.gsub("public/", "")}"
button class="hover:text-blue-400 p-2 bg-blue-100 rounded text-blue-600 mr-4 no-underline" @click="$clipboard('#{Hanami.app.settings.micropub_site_url}/#{photo.gsub("public/", "")}')" Copy URL
button class="text-red-600 hover:text-red-400" Delete
button class="text-red-600 hover:text-red-400" hx-delete="/admin/media/#{photo}" hx-target="#post-#{photo}" Delete

View File

@@ -1,26 +1,43 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 Admin // Posts
div class="max-w-prose mx-auto"
table class="prose dark:prose-invert table-auto prose-a:text-blue-600 prose-a:no-underline"
thead
th Details
th Date
th colspan="2" Actions
tbody
- posts.each do |post|
tr id="post-#{post.id}"
td
div
= post.name
a class="no-underline" href="/post/#{post.slug}"
small class="text-gray-400 dark:text-gray-600" = post.slug
td
= post.published_at&.strftime("%d %b %Y")
td
button class="text-red-600" hx-delete="/admin/bookmarks/#{post.id}" hx-target="#post-#{post.id}" delete
td
button hx-post="/admin/bookmarks/#{post.id}/archive" unpublish
div class="max-w-prose mx-auto" x-data="{ activeTab: 0 }"
div class="flex"
a href="#" class="text-gray-200 cursor-pointer p-2 border-2 mr-2 rounded border-blue-400" :class="{ 'bg-blue-400 text-blue-900': activeTab === 0 }" @click="activeTab = 0" class="tab-control" Published
a href="#" class="text-gray-200 cursor-pointer p-2 border-2 rounded border-blue-400" :class="{ 'bg-blue-400 text-blue-900': activeTab === 1 }" @click="activeTab = 1" class="tab-control" Un published
table class="prose dark:prose-invert table-auto prose-a:text-blue-600 prose-a:no-underline"
thead
th Details
th Date
th colspan="2" Actions
tbody class="{ 'active': activeTab === 0 }" x-show.transition.in.opacity.duration.600="activeTab === 0"
- published_posts.each do |post|
tr id="post-#{post.id}"
td
div
= post.name
a class="no-underline" href="/post/#{post.slug}"
small class="text-gray-400 dark:text-gray-600" = post.slug
td
= post.published_at&.strftime("%d %b %Y")
td
button class="text-red-600" hx-delete="/admin/posts/#{post.id}" hx-target="#post-#{post.id}" delete
td
button hx-post="/admin/posts/#{post.id}/archive" unpublish
tbody class="{ 'active': activeTab === 1 }" x-show.transition.in.opacity.duration.600="activeTab === 1"
- unpublished_posts.each do |post|
tr id="post-#{post.id}"
td
div
= post.name
a class="no-underline" href="/post/#{post.slug}"
small class="text-gray-400 dark:text-gray-600" = post.slug
td
= post.published_at&.strftime("%d %b %Y")
td
button class="text-red-600" hx-delete="/admin/posts/#{post.id}" hx-target="#post-#{post.id}" delete
td
button hx-post="/admin/posts/#{post.id}/publish" publish
div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"

View File

@@ -1,3 +1,5 @@
require "que"
module Admin
module Views
module Bookmarks
@@ -5,8 +7,21 @@ module Admin
include Deps["repos.bookmark_repo"]
expose :published_bookmarks do |bookmarks|
bookmarks[0]
end
expose :unpublished_bookmarks do |bookmarks|
bookmarks[1]
end
expose :bookmarks do
bookmark_repo.list
bookmark_repo.list.partition{|p| p.published_at }
end
expose :running_jobs do
Que.connection = Adamantium::Container["persistence.db"]
Que.job_stats.any? { |job| job[:job_class] == Adamantium::Jobs::RemoveDeadBookmarks.name }
end
end
end

View File

@@ -5,8 +5,16 @@ module Admin
include Deps["repos.post_repo"]
expose :published_posts do |posts|
posts[0]
end
expose :unpublished_posts do |posts|
posts[1]
end
expose :posts do
post_repo.list
post_repo.list.partition{|p| p.published_at }
end
end
end