From 9b4baad5fb60ed45ac193fc36df3058070f4d127 Mon Sep 17 00:00:00 2001 From: Cory Dransfeldt Date: Sat, 24 May 2025 13:28:04 -0700 Subject: [PATCH] feat(artists): change albums table to grid on artist pages --- api/Classes/GlobalsFetcher.php | 22 ++++ package-lock.json | 4 +- package.json | 2 +- queries/views/media/music/artists.sql | 140 ++++++++++++++---------- server/utils/icons.php | 3 +- server/utils/media.php | 52 +++++++++ src/assets/styles/base/index.css | 4 +- src/includes/fetchers/artist.php.liquid | 5 +- src/includes/fetchers/book.php.liquid | 3 +- src/includes/fetchers/genre.php.liquid | 3 +- src/includes/fetchers/movie.php.liquid | 3 +- src/includes/fetchers/show.php.liquid | 3 +- src/includes/fetchers/tags.php.liquid | 3 +- src/pages/dynamic/artist.php.liquid | 21 ++-- 14 files changed, 180 insertions(+), 88 deletions(-) create mode 100644 api/Classes/GlobalsFetcher.php diff --git a/api/Classes/GlobalsFetcher.php b/api/Classes/GlobalsFetcher.php new file mode 100644 index 0000000..666a338 --- /dev/null +++ b/api/Classes/GlobalsFetcher.php @@ -0,0 +1,22 @@ +cacheGet($cacheKey); + + if ($cached) return $cached; + + $globals = $this->fetchFromApi("optimized_globals"); + + if (empty($globals)) return null; + + $this->cacheSet($cacheKey, $globals[0]); + + return $globals[0]; + } +} diff --git a/package-lock.json b/package-lock.json index a5d77b6..ba2db43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "coryd.dev", - "version": "6.1.14", + "version": "6.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "coryd.dev", - "version": "6.1.14", + "version": "6.2.0", "license": "MIT", "dependencies": { "minisearch": "^7.1.2", diff --git a/package.json b/package.json index bf6acb3..078cf60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coryd.dev", - "version": "6.1.14", + "version": "6.2.0", "description": "The source for my personal site. Built using 11ty (and other tools).", "type": "module", "engines": { diff --git a/queries/views/media/music/artists.sql b/queries/views/media/music/artists.sql index 040bb55..af8bc15 100644 --- a/queries/views/media/music/artists.sql +++ b/queries/views/media/music/artists.sql @@ -17,8 +17,7 @@ SELECT CONCAT('/', df.filename_disk) AS image, json_build_object( 'title', ar.name_string, - 'image', - CONCAT('/', df.filename_disk), + 'image', CONCAT('/', df.filename_disk), 'url', ar.slug, 'alt', CONCAT(to_char(ar.total_plays, 'FM999,999,999,999'), ' plays of ', ar.name_string), 'subtext', CONCAT(to_char(ar.total_plays, 'FM999,999,999,999'), ' plays') @@ -27,80 +26,107 @@ SELECT 'title', ar.name_string, 'genre', g.name, 'genre_url', g.slug, - 'emoji', CASE WHEN ar.emoji IS NOT NULL THEN ar.emoji ELSE g.emoji END, + 'emoji', COALESCE(ar.emoji, g.emoji), 'plays', to_char(ar.total_plays, 'FM999,999,999,999'), 'image', CONCAT('/', df.filename_disk), 'url', ar.slug, 'alt', CONCAT(to_char(ar.total_plays, 'FM999,999,999,999'), ' plays of ', ar.name_string) ) AS table, ( - SELECT - json_agg(json_build_object('name', a.name, 'release_year', a.release_year, 'total_plays', to_char(a.total_plays, 'FM999,999,999,999'), - 'art', df_album.filename_disk) - ORDER BY a.release_year) - FROM - albums a + SELECT json_agg( + json_build_object( + 'name', a.name, + 'release_year', a.release_year, + 'total_plays', to_char(a.total_plays, 'FM999,999,999,999'), + 'art', df_album.filename_disk, + 'grid', json_build_object( + 'title', a.name, + 'image', CONCAT('/', df_album.filename_disk), + 'alt', CONCAT(to_char(a.total_plays, 'FM999,999,999,999'), ' plays of ', a.name), + 'subtext', + CASE + WHEN a.total_plays > 0 + THEN CONCAT(a.release_year, ' • ', to_char(a.total_plays, 'FM999,999,999,999'), ' plays') + ELSE CONCAT(a.release_year, '') + END + ) + ) + ORDER BY a.release_year + ) + FROM albums a LEFT JOIN directus_files df_album ON a.art = df_album.id - WHERE - a.artist = ar.id) AS albums, + WHERE a.artist = ar.id + ) AS albums, ( - SELECT - json_agg(json_build_object('id', c.id, 'date', c.date, 'venue_name', v.name, 'venue_name_short', trim(split_part(v.name, ',', 1)), 'venue_latitude', v.latitude, 'venue_longitude', v.longitude, 'notes', c.notes) - ORDER BY c.date DESC) - FROM - concerts c + SELECT json_agg( + json_build_object( + 'id', c.id, + 'date', c.date, + 'venue_name', v.name, + 'venue_name_short', trim(split_part(v.name, ',', 1)), + 'venue_latitude', v.latitude, + 'venue_longitude', v.longitude, + 'notes', c.notes + ) + ORDER BY c.date DESC + ) + FROM concerts c LEFT JOIN venues v ON c.venue = v.id - WHERE - c.artist = ar.id) AS concerts, + WHERE c.artist = ar.id + ) AS concerts, ( - SELECT - json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug) - ORDER BY b.title ASC) - FROM - books_artists ba + SELECT json_agg( + json_build_object('title', b.title, 'author', b.author, 'url', b.slug) + ORDER BY b.title ASC + ) + FROM books_artists ba LEFT JOIN books b ON ba.books_id = b.id - WHERE - ba.artists_id = ar.id) AS books, + WHERE ba.artists_id = ar.id + ) AS books, ( - SELECT - json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug) - ORDER BY m.year DESC) - FROM - movies_artists ma + SELECT json_agg( + json_build_object('title', m.title, 'year', m.year, 'url', m.slug) + ORDER BY m.year DESC + ) + FROM movies_artists ma LEFT JOIN movies m ON ma.movies_id = m.id - WHERE - ma.artists_id = ar.id) AS movies, + WHERE ma.artists_id = ar.id + ) AS movies, ( - SELECT - json_agg(json_build_object('title', s.title, 'year', s.year, 'url', s.slug) - ORDER BY s.year DESC) - FROM - shows_artists sa + SELECT json_agg( + json_build_object('title', s.title, 'year', s.year, 'url', s.slug) + ORDER BY s.year DESC + ) + FROM shows_artists sa LEFT JOIN shows s ON sa.shows_id = s.id - WHERE - sa.artists_id = ar.id) AS shows, + WHERE sa.artists_id = ar.id + ) AS shows, ( - SELECT - json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) - ORDER BY p.date DESC) - FROM - posts_artists pa + SELECT json_agg( + json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC + ) + FROM posts_artists pa LEFT JOIN posts p ON pa.posts_id = p.id - WHERE - pa.artists_id = ar.id) AS posts, + WHERE pa.artists_id = ar.id + ) AS posts, ( - SELECT - json_agg(json_build_object('name', related_ar.name_string, 'url', related_ar.slug, 'country', related_ar.country, 'total_plays', to_char(related_ar.total_plays, 'FM999,999,999,999')) - ORDER BY related_ar.name_string) - FROM - related_artists ra + SELECT json_agg( + json_build_object( + 'name', related_ar.name_string, + 'url', related_ar.slug, + 'country', related_ar.country, + 'total_plays', to_char(related_ar.total_plays, 'FM999,999,999,999') + ) + ORDER BY related_ar.name_string + ) + FROM related_artists ra LEFT JOIN artists related_ar ON ra.related_artists_id = related_ar.id - WHERE - ra.artists_id = ar.id) AS related_artists -FROM - artists ar - LEFT JOIN directus_files df ON ar.art = df.id - LEFT JOIN genres g ON ar.genres = g.id + WHERE ra.artists_id = ar.id + ) AS related_artists +FROM artists ar +LEFT JOIN directus_files df ON ar.art = df.id +LEFT JOIN genres g ON ar.genres = g.id GROUP BY ar.id, df.filename_disk, diff --git a/server/utils/icons.php b/server/utils/icons.php index f95159b..1b39e12 100644 --- a/server/utils/icons.php +++ b/server/utils/icons.php @@ -10,7 +10,8 @@ 'device-tv-old' => '', 'headphones' => '', 'movie' => '', - 'star' => '' + 'star' => '', + 'vinyl' => '' ]; return $icons[$iconName] ?? '[Missing: ' . htmlspecialchars($iconName) . ']'; diff --git a/server/utils/media.php b/server/utils/media.php index 5b7195f..5439811 100644 --- a/server/utils/media.php +++ b/server/utils/media.php @@ -1,5 +1,57 @@ 0 ? $count : count($items); + + echo '
'; + foreach (array_slice($items, 0, $limit) as $item) { + $grid = $item['grid'] ?? $item; + $alt = htmlspecialchars($grid['alt'] ?? ''); + $image = htmlspecialchars($grid['image'] ?? ''); + $title = htmlspecialchars($grid['title'] ?? ''); + $subtext = htmlspecialchars($grid['subtext'] ?? ''); + $url = $grid['url'] ?? null; + + $openLink = $url ? '' : ''; + $closeLink = $url ? '' : ''; + + echo $openLink; + echo '
'; + + if ($title || $subtext) { + echo '
'; + if ($title) echo '
' . $title . '
'; + if ($subtext) echo '
' . $subtext . '
'; + echo '
'; + } + + echo '' . $alt . ''; + echo '
'; + echo $closeLink; + } + echo '
'; + } + function renderAssociatedMedia($artists = [], $books = [], $genres = [], $movies = [], $posts = [], $shows = []) { $media = array_merge($artists, $books, $genres, $movies, $posts, $shows); diff --git a/src/assets/styles/base/index.css b/src/assets/styles/base/index.css index a1e9d1d..14e6e4e 100644 --- a/src/assets/styles/base/index.css +++ b/src/assets/styles/base/index.css @@ -368,7 +368,9 @@ article { } h3 { - margin-top: 0; + &:not(:has(svg)) { + margin-top: 0; + } &:has(+ .tags) { margin-bottom: 0; diff --git a/src/includes/fetchers/artist.php.liquid b/src/includes/fetchers/artist.php.liquid index 0a2c8f6..0cff39f 100644 --- a/src/includes/fetchers/artist.php.liquid +++ b/src/includes/fetchers/artist.php.liquid @@ -3,6 +3,7 @@ require __DIR__ . "/../../vendor/autoload.php"; require __DIR__ . "/../../server/utils/init.php"; + use App\Classes\GlobalsFetcher; use App\Classes\ArtistFetcher; use voku\helper\HtmlMin; @@ -11,8 +12,8 @@ if (strpos($url, "music/artists/") !== 0) redirectTo404(); - $fetcher = new ArtistFetcher(); - $artist = $fetcher->fetch($url); + $globals = (new GlobalsFetcher())->fetch(); + $artist = (new ArtistFetcher())->fetch($url); if (!$artist) redirectTo404(); diff --git a/src/includes/fetchers/book.php.liquid b/src/includes/fetchers/book.php.liquid index c524f4a..4212623 100644 --- a/src/includes/fetchers/book.php.liquid +++ b/src/includes/fetchers/book.php.liquid @@ -11,8 +11,7 @@ if (!preg_match('/^reading\/books\/([\dXx-]+)$/', $url)) redirectTo404(); - $fetcher = new BookFetcher(); - $book = $fetcher->fetch($url); + $book = (new BookFetcher())->fetch($url); if (!$book) redirectTo404(); diff --git a/src/includes/fetchers/genre.php.liquid b/src/includes/fetchers/genre.php.liquid index 24d3506..9c07fe8 100644 --- a/src/includes/fetchers/genre.php.liquid +++ b/src/includes/fetchers/genre.php.liquid @@ -11,8 +11,7 @@ if (!preg_match('/^music\/genres\/[\w-]+$/', $url)) redirectTo404(); - $fetcher = new GenreFetcher(); - $genre = $fetcher->fetch($url); + $genre = (new GenreFetcher())->fetch($url); if (!$genre) redirectTo404(); diff --git a/src/includes/fetchers/movie.php.liquid b/src/includes/fetchers/movie.php.liquid index d30f3e0..a414a9b 100644 --- a/src/includes/fetchers/movie.php.liquid +++ b/src/includes/fetchers/movie.php.liquid @@ -11,8 +11,7 @@ if (!preg_match('/^watching\/movies\/[\w-]+$/', $url)) redirectTo404(); - $fetcher = new MovieFetcher(); - $movie = $fetcher->fetch($url); + $movie = (new MovieFetcher())->fetch($url); if (!$movie) redirectTo404(); diff --git a/src/includes/fetchers/show.php.liquid b/src/includes/fetchers/show.php.liquid index 3d78915..45b2441 100644 --- a/src/includes/fetchers/show.php.liquid +++ b/src/includes/fetchers/show.php.liquid @@ -11,8 +11,7 @@ if (!preg_match('/^watching\/shows\/[\w-]+$/', $url)) redirectTo404(); - $fetcher = new ShowFetcher(); - $show = $fetcher->fetch($url); + $show = (new ShowFetcher())->fetch($url); if (!$show) redirectTo404(); diff --git a/src/includes/fetchers/tags.php.liquid b/src/includes/fetchers/tags.php.liquid index 5895d8b..326916c 100644 --- a/src/includes/fetchers/tags.php.liquid +++ b/src/includes/fetchers/tags.php.liquid @@ -27,8 +27,7 @@ $page = isset($matches[2]) ? max(1, (int)$matches[2]) : 1; $pageSize = 20; - $fetcher = new TagFetcher(); - $tagged = $fetcher->fetch($tag, $page, $pageSize); + $tagged = (new TagFetcher())->fetch($tag, $page, $pageSize); if (!$tagged || count($tagged) === 0) { header("Location: /404/", true, 302); diff --git a/src/pages/dynamic/artist.php.liquid b/src/pages/dynamic/artist.php.liquid index 8009e59..ad41ff6 100644 --- a/src/pages/dynamic/artist.php.liquid +++ b/src/pages/dynamic/artist.php.liquid @@ -103,20 +103,13 @@ schema: artist - - - - - - - - - - - - - -
AlbumPlaysYear
0 ? $album["total_plays"] : "-" ?>
+ +

+ + Albums +

+ +