feat: support nav and pages in cms
This commit is contained in:
parent
e1b0dc5243
commit
f5adf0ba06
35 changed files with 235 additions and 444 deletions
|
@ -37,7 +37,7 @@ const fetchAlbumReleases = async () => {
|
|||
timestamp: DateTime.fromISO(album['release_date']).toSeconds(),
|
||||
type: 'album-release'
|
||||
}
|
||||
)).sort((a, b) => a.timestamp - b.timestamp)
|
||||
)).sort((a, b) => a['timestamp'] - b['timestamp'])
|
||||
}
|
||||
|
||||
export default async function () {
|
||||
|
|
|
@ -14,5 +14,5 @@ export default async function () {
|
|||
},
|
||||
}).catch()
|
||||
const pages = await res
|
||||
return pages.results.filter((p) => p.page.includes('posts'))
|
||||
return pages['results'].filter((p) => p['page'].includes('posts'))
|
||||
}
|
|
@ -37,7 +37,7 @@ async function fetchAllBooks() {
|
|||
}
|
||||
|
||||
for (const book of data) {
|
||||
book.tags = await fetchTagsForBook(book.id)
|
||||
book.tags = await fetchTagsForBook(book['id'])
|
||||
}
|
||||
|
||||
books = books.concat(data)
|
||||
|
|
|
@ -30,9 +30,9 @@ const fetchGenresWithArtists = async () => {
|
|||
}
|
||||
|
||||
data.forEach(genre => {
|
||||
genre.artists = genre.artists.map(artist => ({
|
||||
genre['artists'] = genre['artists'].map(artist => ({
|
||||
...artist,
|
||||
country: parseCountryField(artist.country)
|
||||
country: parseCountryField(artist['country'])
|
||||
}))
|
||||
})
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ const fetchAllLinks = async () => {
|
|||
if (data.length < PAGE_SIZE) fetchMore = false
|
||||
|
||||
for (const link of data) {
|
||||
link.tags = await fetchTagsForLink(link.id)
|
||||
link.type = 'link'
|
||||
link['tags'] = await fetchTagsForLink(link.id)
|
||||
link['type'] = 'link'
|
||||
}
|
||||
|
||||
links = links.concat(data)
|
||||
|
|
|
@ -1,30 +1,50 @@
|
|||
export default async function () {
|
||||
return {
|
||||
menu: [
|
||||
{ name: 'Posts', url: '/posts', icon: 'article'},
|
||||
{ name: 'Music', url: '/music', icon: 'headphones' },
|
||||
{ name: 'Watching', url: '/watching', icon: 'device-tv' },
|
||||
{ name: 'Books', url: '/books', icon: 'books' },
|
||||
{ name: 'Links', icon: 'link' },
|
||||
{ name: 'About', url: '/about', icon: 'info-circle' },
|
||||
{ name: 'Search', icon: 'search' },
|
||||
{ name: 'Feeds', icon: 'rss' },
|
||||
{ name: 'Mastodon', icon: 'brand-mastodon' },
|
||||
],
|
||||
footer: [
|
||||
{ name: 'Uses' },
|
||||
{ name: 'Colophon' },
|
||||
{ name: 'Blogroll' },
|
||||
{ name: 'Save' },
|
||||
],
|
||||
social: [
|
||||
{ name: 'Email', url: '/contact', icon: 'at' },
|
||||
{ name: 'GitHub', url: 'https://github.com/cdransf', icon: 'brand-github' },
|
||||
{ name: 'npm', url: 'https://www.npmjs.com/~cdransf', icon: 'brand-npm'},
|
||||
{ name: 'Mastodon', url: 'https://social.lol/@cory', icon: 'brand-mastodon' },
|
||||
{ name: 'Coffee', url: 'https://buymeacoffee.com/cory', icon: 'coffee' },
|
||||
{ name: 'Now', url: '/now', icon: 'clock-hour-3' },
|
||||
{ name: 'Webrings', url: '/webrings', icon: 'heart-handshake' },
|
||||
],
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const SUPABASE_URL = process.env.SUPABASE_URL
|
||||
const SUPABASE_KEY = process.env.SUPABASE_KEY
|
||||
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
|
||||
|
||||
const fetchAllNavigation = async () => {
|
||||
const { data, error } = await supabase
|
||||
.from('navigation')
|
||||
.select(`
|
||||
*,
|
||||
pages(title, permalink)
|
||||
`)
|
||||
|
||||
if (error) {
|
||||
console.error('Error fetching navigation data:', error)
|
||||
return null
|
||||
}
|
||||
|
||||
const menu = {}
|
||||
data.forEach(item => {
|
||||
const menuItem = item.pages ? {
|
||||
title: item.pages.title,
|
||||
permalink: item.pages.permalink,
|
||||
icon: item.icon,
|
||||
position: item.position
|
||||
} : {
|
||||
title: item.title,
|
||||
permalink: item.permalink,
|
||||
icon: item.icon,
|
||||
position: item.position
|
||||
}
|
||||
|
||||
if (!menu[item.menu_location]) {
|
||||
menu[item.menu_location] = [menuItem]
|
||||
} else {
|
||||
menu[item.menu_location].push(menuItem)
|
||||
}
|
||||
})
|
||||
|
||||
Object.keys(menu).forEach(location => {
|
||||
menu[location].sort((a, b) => a.position - b.position)
|
||||
})
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
export default async function () {
|
||||
return await fetchAllNavigation()
|
||||
}
|
82
src/_data/pages.js
Normal file
82
src/_data/pages.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const SUPABASE_URL = process.env.SUPABASE_URL
|
||||
const SUPABASE_KEY = process.env.SUPABASE_KEY
|
||||
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
|
||||
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
const fetchBlockData = async (collection, itemId) => {
|
||||
const { data, error } = await supabase
|
||||
.from(collection)
|
||||
.select(collection === 'hero' ? '*, image(filename_disk)' : '*')
|
||||
.eq('id', itemId)
|
||||
.single()
|
||||
|
||||
if (error) {
|
||||
console.error(`Error fetching data from ${collection} for item ${itemId}:`, error)
|
||||
return null
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
const fetchBlocksForPage = async (pageId) => {
|
||||
const { data, error } = await supabase
|
||||
.from('pages_blocks')
|
||||
.select('collection, item')
|
||||
.eq('pages_id', pageId)
|
||||
|
||||
if (error) {
|
||||
console.error(`Error fetching blocks for page ${pageId}:`, error)
|
||||
return []
|
||||
}
|
||||
|
||||
const blocks = await Promise.all(data.map(async block => {
|
||||
const blockData = await fetchBlockData(block.collection, block.item)
|
||||
|
||||
return {
|
||||
type: block['collection'],
|
||||
...blockData
|
||||
}
|
||||
}))
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
const fetchAllPages = async () => {
|
||||
let pages = []
|
||||
let page = 0
|
||||
let fetchMore = true
|
||||
|
||||
while (fetchMore) {
|
||||
const { data, error } = await supabase
|
||||
.from('pages')
|
||||
.select(`
|
||||
*,
|
||||
open_graph_image(filename_disk)
|
||||
`)
|
||||
.range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1)
|
||||
|
||||
if (error) {
|
||||
console.error('Error fetching pages:', error)
|
||||
return pages
|
||||
}
|
||||
|
||||
if (data.length < PAGE_SIZE) fetchMore = false
|
||||
|
||||
for (const page of data) {
|
||||
page['blocks'] = await fetchBlocksForPage(page['id'])
|
||||
if (page['open_graph_image']) page['open_graph_image'] = page['open_graph_image']['filename_disk']
|
||||
pages.push(page)
|
||||
}
|
||||
|
||||
page++
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
export default async function () {
|
||||
return await fetchAllPages()
|
||||
}
|
|
@ -26,7 +26,7 @@ const fetchAllRobots = async () => {
|
|||
if (data.length < PAGE_SIZE) break
|
||||
}
|
||||
|
||||
return robots.map(robot => robot.user_agent)
|
||||
return robots.map(robot => robot['user_agent'])
|
||||
}
|
||||
|
||||
export default async function () {
|
||||
|
|
|
@ -8,5 +8,5 @@ export default async function () {
|
|||
}).catch()
|
||||
const status = await res
|
||||
|
||||
return status.response['statuses'][0]
|
||||
return status['response']['statuses'][0]
|
||||
}
|
||||
|
|
|
@ -47,20 +47,20 @@ const fetchAllShows = async () => {
|
|||
const prepareShowData = (show) => {
|
||||
return {
|
||||
...show,
|
||||
image: show.art?.filename_disk ? `/${show.art.filename_disk}` : '',
|
||||
backdrop: show.backdrop?.filename_disk ? `/${show.backdrop.filename_disk}` : ''
|
||||
image: show['art']?.['filename_disk'] ? `/${show['art']['filename_disk']}` : '',
|
||||
backdrop: show['backdrop']?.['filename_disk'] ? `/${show['backdrop']['filename_disk']}` : ''
|
||||
}
|
||||
}
|
||||
|
||||
const prepareEpisodeData = (show) => {
|
||||
return show.episodes.map(episode => ({
|
||||
return show['episodes'].map(episode => ({
|
||||
...episode,
|
||||
show_title: show.title,
|
||||
show_tmdb_id: show.tmdb_id,
|
||||
collected: show.collected,
|
||||
favorite: show.favorite,
|
||||
image: show.image,
|
||||
backdrop: show.backdrop
|
||||
show_title: show['title'],
|
||||
show_tmdb_id: show['tmdb_id'],
|
||||
collected: show['collected'],
|
||||
favorite: show['favorite'],
|
||||
image: show['image'],
|
||||
backdrop: show['backdrop']
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -76,15 +76,15 @@ export default async function () {
|
|||
const showEpisodesMap = {}
|
||||
|
||||
episodes.forEach(episode => {
|
||||
const showTitle = episode.show_title
|
||||
const showTmdbId = episode.show_tmdb_id
|
||||
const episodeNumber = episode.episode_number
|
||||
const seasonNumber = episode.season_number
|
||||
const lastWatchedAt = episode.last_watched_at
|
||||
const collected = episode.collected
|
||||
const favorite = episode.favorite
|
||||
const image = episode.image
|
||||
const backdrop = episode.backdrop
|
||||
const showTitle = episode['show_title']
|
||||
const showTmdbId = episode['show_tmdb_id']
|
||||
const episodeNumber = episode['episode_number']
|
||||
const seasonNumber = episode['season_number']
|
||||
const lastWatchedAt = episode['last_watched_at']
|
||||
const collected = episode['collected']
|
||||
const favorite = episode['favorite']
|
||||
const image = episode['image']
|
||||
const backdrop = episode['backdrop']
|
||||
|
||||
if (!showEpisodesMap[showTmdbId]) {
|
||||
showEpisodesMap[showTmdbId] = {
|
||||
|
@ -115,16 +115,16 @@ export default async function () {
|
|||
})
|
||||
})
|
||||
|
||||
const sortedShows = Object.values(showEpisodesMap).sort((a, b) => new Date(b.episodes[0].lastWatchedAt) - new Date(a.episodes[0].lastWatchedAt))
|
||||
const sortedShows = Object.values(showEpisodesMap).sort((a, b) => new Date(b.episodes[0]['lastWatchedAt']) - new Date(a.episodes[0]['lastWatchedAt']))
|
||||
|
||||
const episodeData = []
|
||||
sortedShows.forEach(show => {
|
||||
const startingEpisode = show.episodes[show.episodes.length - 1].episode
|
||||
const startingSeason = show.episodes[show.episodes.length - 1].season
|
||||
const endingEpisode = show.episodes[0].episode
|
||||
const endingSeason = show.episodes[0].season
|
||||
const startingEpisode = show['episodes'][show['episodes'].length - 1]['episode']
|
||||
const startingSeason = show['episodes'][show['episodes'].length - 1]['season']
|
||||
const endingEpisode = show['episodes'][0].episode
|
||||
const endingSeason = show['episodes'][0].season
|
||||
|
||||
if (show.episodes.length > 1) {
|
||||
if (show['episodes'].length > 1) {
|
||||
episodeData.push({
|
||||
name: show.title,
|
||||
url: `/watching/shows/${show.tmdbId}`,
|
||||
|
@ -141,11 +141,11 @@ export default async function () {
|
|||
backdrop: show.backdrop
|
||||
})
|
||||
} else {
|
||||
const singleEpisode = show.episodes[0]
|
||||
singleEpisode.collected = show.collected
|
||||
singleEpisode.favorite = show.favorite
|
||||
singleEpisode.image = show.image
|
||||
singleEpisode.backdrop = show.backdrop
|
||||
const singleEpisode = show['episodes'][0]
|
||||
singleEpisode.collected = show['collected']
|
||||
singleEpisode.favorite = show['favorite']
|
||||
singleEpisode.image = show['image']
|
||||
singleEpisode.backdrop = show['backdrop']
|
||||
episodeData.push(singleEpisode)
|
||||
}
|
||||
})
|
||||
|
@ -153,12 +153,12 @@ export default async function () {
|
|||
return episodeData
|
||||
}
|
||||
|
||||
const favoriteShows = shows.filter(show => show.favorite)
|
||||
const favoriteShows = shows.filter(show => show['favorite'])
|
||||
|
||||
return {
|
||||
shows,
|
||||
watchHistory: formatEpisodeData(episodes),
|
||||
recentlyWatched: formatEpisodeData(episodes.slice(0, 225)),
|
||||
favorites: formatEpisodeData(favoriteShows.flatMap(prepareEpisodeData)).sort((a, b) => a.name.localeCompare(b.name))
|
||||
favorites: formatEpisodeData(favoriteShows.flatMap(prepareEpisodeData)).sort((a, b) => a['name'].localeCompare(b['name']))
|
||||
}
|
||||
}
|
Reference in a new issue