From 3fddc1757e75e1575fdf221c55674497d09a36a2 Mon Sep 17 00:00:00 2001 From: Daniel Nitsikopoulos Date: Sun, 7 May 2023 11:31:15 +1000 Subject: [PATCH] Add bookmark admin --- Gemfile | 2 ++ Gemfile.lock | 8 +++++ app/templates/bookmarks/show.html.slim | 9 +++++- app/templates/layouts/app.html.slim | 1 + config/app.rb | 3 +- config/routes.rb | 4 +++ ...30507001217_add_cached_bookmark_to_post.rb | 9 ++++++ slices/admin/actions/bookmarks/cache.rb | 20 ++++++++++++ slices/admin/actions/bookmarks/delete.rb | 17 ++++++++++ slices/admin/actions/bookmarks/index.rb | 14 +++++++++ slices/admin/commands/bookmarks/cache.rb | 25 +++++++++++++++ slices/admin/repos/bookmark_repo.rb | 23 ++++++++++++++ slices/admin/repos/post_tag_repo.rb | 4 +++ .../admin/templates/bookmarks/index.html.slim | 31 +++++++++++++++++++ slices/admin/templates/index.html.slim | 2 ++ slices/admin/templates/layouts/app.html.slim | 2 ++ slices/admin/views/bookmarks/index.rb | 14 +++++++++ 17 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20230507001217_add_cached_bookmark_to_post.rb create mode 100644 slices/admin/actions/bookmarks/cache.rb create mode 100644 slices/admin/actions/bookmarks/delete.rb create mode 100644 slices/admin/actions/bookmarks/index.rb create mode 100644 slices/admin/commands/bookmarks/cache.rb create mode 100644 slices/admin/repos/bookmark_repo.rb create mode 100644 slices/admin/templates/bookmarks/index.html.slim create mode 100644 slices/admin/views/bookmarks/index.rb diff --git a/Gemfile b/Gemfile index 2c03f22..db7d9b6 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,8 @@ gem "gpx" gem "gnuplot" gem "matrix" +gem "ruby-readability", :require => "readability" +gem "down" gem "httparty" gem "redcarpet" gem "reverse_markdown" diff --git a/Gemfile.lock b/Gemfile.lock index ce85681..2abcb69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,6 +76,8 @@ GEM domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.8.1) + down (5.4.0) + addressable (~> 2.8) dry-auto_inject (1.0.1) dry-core (~> 1.0) zeitwerk (~> 2.6) @@ -165,6 +167,7 @@ GEM guard (~> 2.14) guard-compat (~> 1.2) puma (>= 4.0, < 7) + guess_html_encoding (0.0.11) hanami (2.0.3) bundler (>= 1.16, < 3) dry-configurable (~> 1.0, < 2) @@ -375,6 +378,9 @@ GEM rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) ruby-progressbar (1.13.0) + ruby-readability (0.7.0) + guess_html_encoding (>= 0.0.4) + nokogiri (>= 1.6.0) ruby2_keywords (0.0.5) sanitize (6.0.1) crass (~> 1.0.2) @@ -433,6 +439,7 @@ DEPENDENCIES capistrano3-puma! database_cleaner-sequel dotenv + down dry-matcher dry-monads dry-types @@ -463,6 +470,7 @@ DEPENDENCIES rom-factory rom-sql ruby-filemagic! + ruby-readability sanitize scraperd! slim diff --git a/app/templates/bookmarks/show.html.slim b/app/templates/bookmarks/show.html.slim index 9b858d4..7afa88a 100644 --- a/app/templates/bookmarks/show.html.slim +++ b/app/templates/bookmarks/show.html.slim @@ -1,13 +1,20 @@ div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200" h1 = bookmark.name -div class="mb-12 prose max-w-prose mx-auto text-gray-800 dark:text-gray-200" +div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200" x-data="{ open: false }" a class="text-blue-600 no-underline hover:underline" href=bookmark.url p class="text-xl" = bookmark.url == bookmark.content + - unless bookmark.cached_content.nil? + button @click="open = ! open" Toggle cached version + + span x-show="open" + div class="rounded bg-blue-50 px-4 py-2" + == bookmark.cached_content + div class="prose max-w-prose mx-auto text-gray-800 dark:text-gray-200 grid grid-cols-5 gap-2" hx-get="/bookmarks/metadata/#{bookmark.id}" hx-trigger="load" div class="mb-8 max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600" diff --git a/app/templates/layouts/app.html.slim b/app/templates/layouts/app.html.slim index 87e3303..e01d0e4 100644 --- a/app/templates/layouts/app.html.slim +++ b/app/templates/layouts/app.html.slim @@ -28,6 +28,7 @@ html script src="/assets/index.js" script src="https://unpkg.com/htmx.org@1.8.4" integrity="sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV" crossorigin="anonymous" + script src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.0/dist/cdn.min.js" defer="true" script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js" link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet" diff --git a/config/app.rb b/config/app.rb index fe9dde7..4768e8f 100644 --- a/config/app.rb +++ b/config/app.rb @@ -4,11 +4,12 @@ require "hanami" module Adamantium class App < Hanami::App - config.actions.content_security_policy[:script_src] += " https://gist.github.com" + config.actions.content_security_policy[:script_src] += " 'unsafe-eval' https://gist.github.com" config.actions.content_security_policy[:script_src] += " *.dnitza.com" config.actions.content_security_policy[:script_src] += " https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js" config.actions.content_security_policy[:media_src] += " https://dnitza.com" config.actions.content_security_policy[:script_src] += " https://unpkg.com/htmx.org@1.8.4 https://unpkg.com/htmx.org@1.9.2" + config.actions.content_security_policy[:script_src] += " https://cdn.jsdelivr.net/npm/alpinejs@3.12.0/dist/cdn.min.js" config.actions.content_security_policy[:connect_src] += " https://stats.dnitza.com/api/event https://*.mapbox.com" config.actions.content_security_policy[:frame_src] += " https://embed.music.apple.com" config.actions.content_security_policy[:style_src] += " https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" diff --git a/config/routes.rb b/config/routes.rb index 672e7b2..7612534 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -65,6 +65,10 @@ module Adamantium get "/tags/auto_tagging/new", to: "auto_tagging.new" post "/tags/auto_tagging", to: "auto_tagging.create" delete "/tags/auto_taggings/:id", to: "auto_tagging.delete" + + get "/bookmarks", to: "bookmarks.index" + delete "/bookmarks/:id", to: "bookmarks.delete" + post "/bookmarks/cache/:id", to: "bookmarks.cache" end end end diff --git a/db/migrate/20230507001217_add_cached_bookmark_to_post.rb b/db/migrate/20230507001217_add_cached_bookmark_to_post.rb new file mode 100644 index 0000000..4779a06 --- /dev/null +++ b/db/migrate/20230507001217_add_cached_bookmark_to_post.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +ROM::SQL.migration do + change do + alter_table(:posts) do + add_column :cached_content, :text + end + end +end diff --git a/slices/admin/actions/bookmarks/cache.rb b/slices/admin/actions/bookmarks/cache.rb new file mode 100644 index 0000000..7235779 --- /dev/null +++ b/slices/admin/actions/bookmarks/cache.rb @@ -0,0 +1,20 @@ +module Admin + module Actions + module Bookmarks + class Cache < Action + + include Deps["commands.bookmarks.cache"] + + def handle(req, res) + bookmark_id = req.params[:id] + + if cache.(bookmark_id: bookmark_id).success? + res.body = "Success" + else + res.body = "Failed" + end + end + end + end + end +end \ No newline at end of file diff --git a/slices/admin/actions/bookmarks/delete.rb b/slices/admin/actions/bookmarks/delete.rb new file mode 100644 index 0000000..1bdb93b --- /dev/null +++ b/slices/admin/actions/bookmarks/delete.rb @@ -0,0 +1,17 @@ +module Admin + module Actions + module Bookmarks + class Delete < Action + + include Deps["repos.bookmark_repo", "repos.post_tag_repo"] + + def handle(req, res) + bookmark_id = req.params[:id] + + post_tag_repo.delete_by_post_id(post_id: bookmark_id) + bookmark_repo.delete(id: bookmark_id) + end + end + end + end +end \ No newline at end of file diff --git a/slices/admin/actions/bookmarks/index.rb b/slices/admin/actions/bookmarks/index.rb new file mode 100644 index 0000000..c673080 --- /dev/null +++ b/slices/admin/actions/bookmarks/index.rb @@ -0,0 +1,14 @@ +module Admin + module Actions + module Bookmarks + class Index < Action + + include Deps["views.bookmarks.index"] + + def handle(req, res) + res.render index + end + end + end + end +end \ No newline at end of file diff --git a/slices/admin/commands/bookmarks/cache.rb b/slices/admin/commands/bookmarks/cache.rb new file mode 100644 index 0000000..a65463d --- /dev/null +++ b/slices/admin/commands/bookmarks/cache.rb @@ -0,0 +1,25 @@ +require "readability" +require "down" + +module Admin + module Commands + module Bookmarks + class Cache + include Dry::Monads[:result] + include Deps["repos.bookmark_repo"] + + def call(bookmark_id: ) + bookmark = bookmark_repo.fetch(id: bookmark_id) + bookmark.url + + tempfile = Down.download(bookmark.url) + content = Readability::Document.new(tempfile.read, tags: %w[div p h1 h2 h3 h4 h5 h6]).content + + bookmark_repo.update(id: bookmark_id, cached_content: content) + + Success() + end + end + end + end +end diff --git a/slices/admin/repos/bookmark_repo.rb b/slices/admin/repos/bookmark_repo.rb new file mode 100644 index 0000000..b94d8d9 --- /dev/null +++ b/slices/admin/repos/bookmark_repo.rb @@ -0,0 +1,23 @@ +module Admin + module Repos + class BookmarkRepo < Adamantium::Repo[:posts] + def list + posts + .where(post_type: "bookmark") + .to_a + end + + def fetch(id:) + posts.where(id: id).one + end + + def delete(id:) + posts.where(id: id).delete + end + + def update(id:, cached_content:) + posts.where(id: id).update(cached_content: cached_content) + end + end + end +end \ No newline at end of file diff --git a/slices/admin/repos/post_tag_repo.rb b/slices/admin/repos/post_tag_repo.rb index 093a99f..39f687d 100644 --- a/slices/admin/repos/post_tag_repo.rb +++ b/slices/admin/repos/post_tag_repo.rb @@ -5,6 +5,10 @@ module Admin def delete(tag_id:) post_tags.where(tag_id: tag_id).delete end + + def delete_by_post_id(post_id:) + post_tags.where(post_id: post_id).delete + end end end end diff --git a/slices/admin/templates/bookmarks/index.html.slim b/slices/admin/templates/bookmarks/index.html.slim new file mode 100644 index 0000000..f95cb19 --- /dev/null +++ b/slices/admin/templates/bookmarks/index.html.slim @@ -0,0 +1,31 @@ +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" + table class="prose dark:prose-invert table-auto prose-a:text-blue-600 prose-a:no-underline" + thead + th Details + th Date + th Actions + tbody + - 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 + - else + button hx-post="/admin/bookmarks/cache/#{bookmark.id}" No cached content, cache now? + td + = bookmark.published_at&.strftime("%d %b %Y") + td + button hx-delete="/admin/bookmarks/#{bookmark.id}" hx-target="#bookmark-#{bookmark.id}" delete + +div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600" + + + diff --git a/slices/admin/templates/index.html.slim b/slices/admin/templates/index.html.slim index a43abad..cf354f2 100644 --- a/slices/admin/templates/index.html.slim +++ b/slices/admin/templates/index.html.slim @@ -7,6 +7,8 @@ div class="max-w-prose mx-auto prose dark:prose-invert" a href="/admin/tags" Tags li a href="/admin/tags/auto_tagging" Auto tagging + li + a href="/admin/bookmarks" Bookmarks div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600" diff --git a/slices/admin/templates/layouts/app.html.slim b/slices/admin/templates/layouts/app.html.slim index 55e62ab..0c56574 100644 --- a/slices/admin/templates/layouts/app.html.slim +++ b/slices/admin/templates/layouts/app.html.slim @@ -47,6 +47,8 @@ html a class="p-1 rounded text-gray-400 hover:bg-red-100 hover:text-red-400 dark:hover:bg-red-200 #{link_active?('about') ? 'text-red-600 dark:text-red-400' : ''}" href="/admin/tags" Tags span class="text-gray-400 dark:text-gray-600" = "/" + a class="p-1 rounded text-gray-400 hover:bg-red-100 hover:text-red-400 dark:hover:bg-red-200 #{link_active?('about') ? 'text-red-600 dark:text-red-400' : ''}" href="/admin/bookmarks" Bookmarks + == yield div class="px-4 max-w-screen-md mx-auto pb-10" p class="float-left text-gray-200 dark:text-gray-600" © 2023 Daniel Nitsikopoulos. All rights reserved. diff --git a/slices/admin/views/bookmarks/index.rb b/slices/admin/views/bookmarks/index.rb new file mode 100644 index 0000000..8051912 --- /dev/null +++ b/slices/admin/views/bookmarks/index.rb @@ -0,0 +1,14 @@ +module Admin + module Views + module Bookmarks + class Index < Admin::View + + include Deps["repos.bookmark_repo"] + + expose :bookmarks do + bookmark_repo.list + end + end + end + end +end \ No newline at end of file