Fix admin entity decoration

This commit is contained in:
2024-03-29 13:48:24 +11:00
parent 1364d78f29
commit 59f42c235c
8 changed files with 370 additions and 6 deletions

View File

@@ -0,0 +1,56 @@
# frozen_string_literal: false
# auto_register: false
module Admin
module Decorators
module Bookmarks
class Decorator < SimpleDelegator
def display_published_at
published_at.strftime("%e %B, %Y")
end
def display_title
"🔖: #{name}"
end
def feed_content
content || ""
end
def permalink
"#{Hanami.app.settings.micropub_site_url}/bookmark/#{slug}"
end
def machine_published_at
published_at.rfc2822
end
def syndicated?
!syndication_sources.empty?
end
def template_type
:bookmark
end
def syndicated_to
syndication_sources.map do |source, url|
{
location: source,
url: url
}
end
end
def youtube_embed
pattern = /watch[?]v=(\w*)/i
code = url.scan(pattern).flatten.first
if code
"<div class='video-container'><iframe width='100%' src='https://www.youtube.com/embed/#{code}' title='YouTube video player' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' allowfullscreen></iframe></div>"
end
end
end
end
end
end

View File

@@ -0,0 +1,53 @@
# frozen_string_literal: false
# auto_register: false
module Admin
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
def authors
book_author.split(";").join(" ")
end
def status_colour
case book_status
when "read" || "finished"
"text-green-100 bg-green-500"
when "to-read"
"text-blue-100 bg-blue-500"
when "reading"
"text-orange-100 bg-orange-500"
end
end
def status_label
case book_status
when "read" || "finished"
"Read"
when "to-read"
"To read"
when "reading"
"Reading"
end
end
end
end
end
end

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: false
# auto_register: false
module Admin
module Decorators
module Movies
class Decorator < SimpleDelegator
include Deps["clients.omdb"]
def poster
omdb_record&.poster
end
def omdb_record
@omdb_record ||= omdb.call(imdb_id: imdb_id)
end
end
end
end
end

View File

@@ -0,0 +1,211 @@
# frozen_string_literal: false
# auto_register: false
require "rexml/parsers/pullparser"
require "sanitize"
require "nokogiri"
require "unicode/emoji"
module Admin
module Decorators
module Posts
class Decorator < SimpleDelegator
def syndicated?
!syndication_sources.empty?
end
def syndicated_to
syndication_sources.map do |source, url|
{
location: source,
url: url
}
end
end
def photos?
__getobj__.photos.count { |p| !p["value"].end_with?("mp4") } > 0
end
def photos
__getobj__.photos.select { |p| !p["value"].end_with?("mp4") }
end
def videos?
__getobj__.photos.count { |p| p["value"].end_with?("mp4") } > 0
end
def videos
__getobj__.photos.select { |p| p["value"].end_with?("mp4") }
end
def key_image
if photos?
return photos.first["url"]
end
inline_images.first[1] if inline_images
end
def inline_images
doc = Nokogiri::HTML(content)
doc.at("//img")
end
def inline_image_sources
inline_images
&.select {|attr, _value| attr == "src"}
&.map {|img| img[1] } || []
end
def photo_sources
photos.map{|photo| photo["value"]}
end
def prefix_emoji
if name
nil
elsif photos? && content == ""
"📷"
elsif __getobj__.emoji
__getobj__.emoji
else
@prefix_emoji ||= if (match = content.match(Unicode::Emoji::REGEX))
match
else
"💬"
end
end
end
def display_title
title = name
"#{prefix_emoji} #{title}"
end
def display_published_at
published_at.strftime("%e %B, %Y")
end
def machine_published_at
published_at.rfc2822
end
def feed_content
photos? ? "<div>#{photos.map { |p| "<img src='#{p["value"]}'/>" }.join("")} #{content}</div>" : content
end
def raw_content
res = Sanitize.fragment(content)
res.gsub(prefix_emoji[0], "") if prefix_emoji
end
def excerpt
name ? truncate_html(content, 240, true) : content
end
def permalink
"#{Hanami.app.settings.micropub_site_url}/post/#{slug}"
end
def lat
geo[0]
end
def lon
geo[1]
end
def small_map
"https://api.mapbox.com/styles/v1/dnitza/cleb2o734000k01pbifls5620/static/pin-s+555555(#{lon},#{lat})/#{lon},#{lat},14,0/200x100@2x?access_token=pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIzOHFmazBkODIzdm9kZHgxdDF4ajQifQ.mSneE-1SKeju8AOz5gp4BQ"
end
def large_map
"https://api.mapbox.com/styles/v1/dnitza/cleb2o734000k01pbifls5620/static/pin-s+555555(#{lon},#{lat})/#{lon},#{lat},14,0/620x310@2x?access_token=pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIzOHFmazBkODIzdm9kZHgxdDF4ajQifQ.mSneE-1SKeju8AOz5gp4BQ"
end
def template_type
:post
end
def posted_in
if name.nil?
:statuses
elsif post_type.to_sym == :book
:bookshelf
elsif location.nil?
:posts
else
:places
end
end
def trips
__getobj__.trips
end
def to_h
clean_content = CGI::unescapeHTML(content.gsub(/<\/?[^>]*>/, "")).strip
clean_content = clean_content.gsub(prefix_emoji[0], "") if prefix_emoji
{
id: slug,
emoji: prefix_emoji,
content: clean_content,
images: (inline_image_sources + photo_sources).compact,
published_at: display_published_at
}
end
private
# e.g. geo:-37.75188,144.90417;u=35
def geo
loc = location.split(":")[1]
p = loc.split(";")[0]
p.split(",")
end
def truncate_html(content, len = 30, at_end = nil)
return content if content.to_s.length <= len
p = REXML::Parsers::PullParser.new(content)
tags = []
new_len = len
results = ""
while p.has_next? && new_len > 0
p_e = p.pull
case p_e.event_type
when :start_element
tags.push p_e[0]
results << "<#{tags.last}#{attrs_to_s(p_e[1])}>"
when :end_element
results << "</#{tags.pop}>"
when :text
results << p_e[0][0..new_len]
new_len -= p_e[0].length
else
results << "<!-- #{p_e.inspect} -->"
end
end
if at_end
results << "..."
end
tags.reverse_each do |tag|
results << "</#{tag}>"
end
results
end
def attrs_to_s(attrs)
if attrs.empty?
""
else
" " + attrs.to_a.map { |attr| %(#{attr[0]}="#{attr[1]}") }.join(" ")
end
end
end
end
end
end

View File

@@ -0,0 +1,23 @@
# frozen_string_literal: false
# auto_register: false
require "rexml/parsers/pullparser"
require "sanitize"
require "nokogiri"
module Admin
module Decorators
module Statuses
class Decorator < Main::Decorators::Posts::Decorator
def raw_content
res = Sanitize.fragment(content,
elements: ["img", "p"],
attributes: {"img" => ["alt", "src", "title"]})
res.gsub(prefix_emoji[0], "") if prefix_emoji
end
end
end
end
end

View File

@@ -2,14 +2,14 @@ div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:
h1 Admin // Merge Tags h1 Admin // Merge Tags
div class="max-w-prose mx-auto prose dark:prose-invert" div class="max-w-prose mx-auto prose dark:prose-invert"
h3 Pick a tag to merge in to #{tag.label} h3 Pick a tag to merge in to "#{post_tag.label}"
form action="/admin/tags/merge" method="POST" form action="/admin/tags/merge" method="POST"
input type="hidden" name="target_id" value=tag.id input type="hidden" name="target_id" value=post_tag.id
div class="mb-4" div class="mb-4"
select class="text-gray-800" name="source_id" select class="text-gray-800" name="source_id"
- tags.each do |source_tag| - post_tags.each do |source_tag|
option value=source_tag.id option value=source_tag.id
= source_tag.label = source_tag.label
div class="mb-4" div class="mb-4"

View File

@@ -4,11 +4,11 @@ module Admin
class New < Admin::View class New < Admin::View
include Deps["repos.tag_repo"] include Deps["repos.tag_repo"]
expose :tag do |id:| expose :post_tag do |id:|
tag_repo.fetch(id) tag_repo.fetch(id)
end end
expose :tags do |id:| expose :post_tags do |id:|
tag_repo.list.reject { |t| t.id.to_s == id.to_s } tag_repo.list.reject { |t| t.id.to_s == id.to_s }
end end
end end

View File

@@ -16,7 +16,7 @@ module Admin
expose :posts do |trip| expose :posts do |trip|
post_repo.created_between(trip.start_date, trip.end_date).map do |post| post_repo.created_between(trip.start_date, trip.end_date).map do |post|
Adamantium::Decorators::Posts::Decorator.new(post) Admin::Decorators::Posts::Decorator.new(post)
end end
end end
end end