Add podcasts and map view
This commit is contained in:
23
Rakefile
23
Rakefile
@@ -29,4 +29,27 @@ namespace :blog do
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
task load_from_overcast: ["blog:load_environment"] do
|
||||||
|
require "nokogiri"
|
||||||
|
require "hanami/prepare"
|
||||||
|
require "down"
|
||||||
|
|
||||||
|
podcast_repo = Adamantium::Container["repos.podcast_repo"]
|
||||||
|
settings = Adamantium::Container["settings"]
|
||||||
|
|
||||||
|
doc = File.open("tmp/overcast.opml") { |f| Nokogiri::XML(f) }
|
||||||
|
doc.xpath("//outline[@type='rss']").each do |outline|
|
||||||
|
overcast_id = outline.get_attribute("overcastId")
|
||||||
|
url = "https://public.overcast-cdn.com/art/#{overcast_id}_thumb"
|
||||||
|
destination = File.join("public", "media", "podcast_art", "#{overcast_id}.jpg")
|
||||||
|
Down.download(url, destination: destination)
|
||||||
|
|
||||||
|
podcast_repo.create(
|
||||||
|
name: outline.get_attribute("title"),
|
||||||
|
url: outline.get_attribute("htmlUrl"),
|
||||||
|
overcast_id: outline.get_attribute("overcastId")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
13
app/actions/places/map_page.rb
Normal file
13
app/actions/places/map_page.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
module Adamantium
|
||||||
|
module Actions
|
||||||
|
module Places
|
||||||
|
class MapPage < Action
|
||||||
|
include Deps["views.places.map_page"]
|
||||||
|
|
||||||
|
def handle(req, res)
|
||||||
|
res.render map_page
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
13
app/actions/podcasts/index.rb
Normal file
13
app/actions/podcasts/index.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
module Adamantium
|
||||||
|
module Actions
|
||||||
|
module Podcasts
|
||||||
|
class Index < Action
|
||||||
|
include Deps["views.podcasts.index"]
|
||||||
|
|
||||||
|
def handle(req, res)
|
||||||
|
res.render index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
15
app/repos/podcast_repo.rb
Normal file
15
app/repos/podcast_repo.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
module Adamantium
|
||||||
|
module Repos
|
||||||
|
class PodcastRepo < Adamantium::Repo[:podcasts]
|
||||||
|
commands :create
|
||||||
|
|
||||||
|
def listing
|
||||||
|
podcasts.order(:name).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_all
|
||||||
|
podcasts.delete
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -118,7 +118,8 @@ module Adamantium
|
|||||||
|
|
||||||
def places_listing(limit: nil)
|
def places_listing(limit: nil)
|
||||||
posts
|
posts
|
||||||
.where(post_type: "checkin")
|
.where(post_type: ["checkin", "post"])
|
||||||
|
.exclude(location: nil)
|
||||||
.published
|
.published
|
||||||
.combine(:tags)
|
.combine(:tags)
|
||||||
.order(Sequel.desc(:published_at))
|
.order(Sequel.desc(:published_at))
|
||||||
|
34
app/templates/layouts/map.html.slim
Normal file
34
app/templates/layouts/map.html.slim
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
html
|
||||||
|
head
|
||||||
|
meta charest="utf-8"
|
||||||
|
|
||||||
|
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
||||||
|
|
||||||
|
meta name="theme-color" content="rgb(37, 99, 235)"
|
||||||
|
|
||||||
|
title #{context.content_for(:title)} Daniel Nitsikopoulos
|
||||||
|
|
||||||
|
link rel="authorization_endpoint" href=Hanami.app.settings.micropub_authorization_endpoint
|
||||||
|
link rel="token_endpoint" href=Hanami.app.settings.micropub_token_endpoint
|
||||||
|
link rel="micropub" href="#{URI.join(Hanami.app.settings.micropub_site_url, "micropub")}"
|
||||||
|
|
||||||
|
link rel="webmention" href=Hanami.app.settings.webmention_url
|
||||||
|
link rel="pingback" href=Hanami.app.settings.pingback_url
|
||||||
|
link rel="feed" type="text/html" href="/posts"
|
||||||
|
link rel="feed alternate" type="application/rss+xml" href="/feeds/rss"
|
||||||
|
link rel="feed alternate" type="application/rss+xml" href="/feeds/statuses_rss"
|
||||||
|
|
||||||
|
link rel="me" href=Hanami.app.settings.mastodon_url
|
||||||
|
link rel="me" href=Hanami.app.settings.github_url
|
||||||
|
|
||||||
|
link rel="stylesheet" href=asset_from_manifest("index.css")
|
||||||
|
link rel="icon" type="image/x-icon" href="/assets/favicon.ico"
|
||||||
|
|
||||||
|
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'
|
||||||
|
|
||||||
|
script data-domain="dnitza.com" src="https://stats.dnitza.com/js/script.js" defer="true"
|
||||||
|
script src=asset_from_manifest("index.js")
|
||||||
|
|
||||||
|
body class="bg-white dark:bg-black selection:bg-blue-100 selection:text-blue-900 dark:selection:bg-blue-600 dark:selection:text-blue-100"
|
||||||
|
== yield
|
@@ -15,5 +15,6 @@ div class="mb-12 max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
|||||||
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="/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="/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-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-200 text-blue-900 hover:bg-blue-300 text-center rounded-lg" href="/podcasts" 🎙️ Podcasts
|
||||||
/ 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
|
/ 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
|
||||||
|
|
||||||
|
@@ -1,8 +1,14 @@
|
|||||||
- context.content_for(:title, "Places | ")
|
- context.content_for(:title, "Places | ")
|
||||||
|
|
||||||
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
div class="mb-4 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
||||||
h1 Places
|
h1 Places
|
||||||
/ div id='map' data-markers="#{JSON.generate(places.map{|p| [p.lon,p.lat]})}" style='width: 400px; height: 300px;'
|
|
||||||
|
div class="mb-12 max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
||||||
|
nav class="space-x-1 text-sm md:text-sm uppercase md:block"
|
||||||
|
span
|
||||||
|
| 🗺️
|
||||||
|
a href="/places/map" View map
|
||||||
|
|
||||||
|
|
||||||
div class="mb-12 max-w-prose mx-auto"
|
div class="mb-12 max-w-prose mx-auto"
|
||||||
- places.each do |post|
|
- places.each do |post|
|
||||||
|
3
app/templates/places/map_page.html.slim
Normal file
3
app/templates/places/map_page.html.slim
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
div class="p-2 bg-white absolute bg-opacity-75 z-40 w-screen"
|
||||||
|
button id="go-back" ← Back
|
||||||
|
div id='map' style='width: 100%; height: 100%;' data-markers="#{JSON.generate(places.map(&:value))}"
|
20
app/templates/podcasts/index.html.slim
Normal file
20
app/templates/podcasts/index.html.slim
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
- context.content_for(:title, "Podcasts | ")
|
||||||
|
|
||||||
|
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
|
||||||
|
h1 Podcasts
|
||||||
|
|
||||||
|
div class="mb-12 max-w-prose mx-auto"
|
||||||
|
table class="prose dark:prose-invert table-auto"
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
td Name
|
||||||
|
- podcasts.each do |podcast|
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
img class="w-14 m-0 p-0 rounded" src="/media/podcast_art/#{podcast.overcast_id}.jpg"
|
||||||
|
td class="p-0 align-middle"
|
||||||
|
a class="block" href="#{podcast.url}"
|
||||||
|
= podcast.name
|
||||||
|
|
||||||
|
div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"
|
18
app/views/places/map_page.rb
Normal file
18
app/views/places/map_page.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module Adamantium
|
||||||
|
module Views
|
||||||
|
module Places
|
||||||
|
class MapPage < Adamantium::View
|
||||||
|
include Deps["repos.post_repo"]
|
||||||
|
|
||||||
|
config.layout = "map"
|
||||||
|
|
||||||
|
expose :places do
|
||||||
|
post_repo.places_listing.map do |post|
|
||||||
|
p = Decorators::Posts::Decorator.new(post)
|
||||||
|
[p.lon, p.lat]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
13
app/views/podcasts/index.rb
Normal file
13
app/views/podcasts/index.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
module Adamantium
|
||||||
|
module Views
|
||||||
|
module Podcasts
|
||||||
|
class Index < View
|
||||||
|
include Deps["repos.podcast_repo"]
|
||||||
|
|
||||||
|
expose :podcasts do
|
||||||
|
podcast_repo.listing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -34,6 +34,7 @@ module Adamantium
|
|||||||
|
|
||||||
get "/photos", to: "photos.index"
|
get "/photos", to: "photos.index"
|
||||||
get "/places", to: "places.index"
|
get "/places", to: "places.index"
|
||||||
|
get "/places/map", to: "places.map_page"
|
||||||
get "/statuses", to: "statuses.index"
|
get "/statuses", to: "statuses.index"
|
||||||
|
|
||||||
get "/tags", to: "tags.index"
|
get "/tags", to: "tags.index"
|
||||||
@@ -56,6 +57,8 @@ module Adamantium
|
|||||||
get "/trips", to: "trips.index"
|
get "/trips", to: "trips.index"
|
||||||
get "/trips/:id", to: "trips.show"
|
get "/trips/:id", to: "trips.show"
|
||||||
|
|
||||||
|
get "/podcasts", to: "podcasts.index"
|
||||||
|
|
||||||
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"
|
||||||
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"
|
||||||
|
|
||||||
|
12
db/migrate/20230618050051_create_podcasts.rb
Normal file
12
db/migrate/20230618050051_create_podcasts.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
ROM::SQL.migration do
|
||||||
|
change do
|
||||||
|
create_table :podcasts do
|
||||||
|
primary_key :id
|
||||||
|
column :name, :text, null: false
|
||||||
|
column :url, :text, null: false
|
||||||
|
column :overcast_id, :text, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
13
lib/adamantium/persistence/relations/podcasts.rb
Normal file
13
lib/adamantium/persistence/relations/podcasts.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Adamantium
|
||||||
|
module Persistence
|
||||||
|
module Relations
|
||||||
|
class Podcasts < ROM::Relation[:sql]
|
||||||
|
schema :podcasts, infer: true
|
||||||
|
|
||||||
|
auto_struct(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
File diff suppressed because one or more lines are too long
@@ -7,29 +7,50 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const times = document.querySelectorAll('time');
|
const times = document.querySelectorAll('time');
|
||||||
times.forEach((time) => {
|
times.forEach((time) => {
|
||||||
const oldDtime = Date.parse(time.dateTime);
|
const oldDtime = Date.parse(time.dateTime);
|
||||||
time.innerHTML = new Date(oldDtime).toLocaleDateString(navigator.language, { weekday:"long", year:"numeric", month:"short", day:"numeric"});
|
time.innerHTML = new Date(oldDtime).toLocaleDateString(navigator.language, { weekday:"long", year:"numeric", month:"short", day:"numeric"});
|
||||||
|
|
||||||
md_gallery({
|
md_gallery({
|
||||||
"class_name": "grid gap-4 grid-cols-2 prose-img:m-0"
|
"class_name": "grid gap-4 grid-cols-2 prose-img:m-0"
|
||||||
|
});
|
||||||
|
|
||||||
|
htmx.on('#media_form', 'htmx:xhr:progress', function(evt) {
|
||||||
|
htmx.find('#progress').setAttribute('value', evt.detail.loaded/evt.detail.total * 100)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
htmx.on('#media_form', 'htmx:xhr:progress', function(evt) {
|
const mapContainer = document.getElementById("map");
|
||||||
htmx.find('#progress').setAttribute('value', evt.detail.loaded/evt.detail.total * 100)
|
if (mapContainer !== undefined) {
|
||||||
|
document.getElementById("go-back").addEventListener("click", () => {
|
||||||
|
history.back();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
// mapboxgl.accessToken = 'pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIyY3ZzaTE0cjUzdm4xdnZ6czRlYjUifQ.FRETOXYRID6T2IoB7qqRLg';
|
mapboxgl.accessToken = 'pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIyY3ZzaTE0cjUzdm4xdnZ6czRlYjUifQ.FRETOXYRID6T2IoB7qqRLg';
|
||||||
// var map = new mapboxgl.Map({
|
var map = new mapboxgl.Map({
|
||||||
// container: 'map',
|
container: 'map',
|
||||||
// style: 'mapbox://styles/mapbox/streets-v11'
|
style: 'mapbox://styles/mapbox/streets-v11',
|
||||||
// });
|
maxZoom: 8
|
||||||
// const mapContainer = document.getElementById("map");
|
});
|
||||||
// const markers = JSON.parse(mapContainer.dataset["markers"]);
|
|
||||||
// for (var i = 0; i < markers.length; i++) {
|
const markers = JSON.parse(mapContainer.dataset["markers"]);
|
||||||
// const marker = markers[i];
|
|
||||||
// new mapboxgl.Marker()
|
const bounds = new mapboxgl.LngLatBounds(markers[0], markers[0]);
|
||||||
// .setLngLat(marker)
|
|
||||||
// .addTo(map);
|
for (var i = 0; i < markers.length; i++) {
|
||||||
// }
|
bounds.extend(markers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.fitBounds(bounds, { padding: 60 });
|
||||||
|
|
||||||
|
for (var i = 0; i < markers.length; i++) {
|
||||||
|
const marker = markers[i];
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.className = "map-marker";
|
||||||
|
|
||||||
|
new mapboxgl.Marker(el)
|
||||||
|
.setLngLat(marker)
|
||||||
|
.addTo(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
Reference in New Issue
Block a user