From 027d384802a21fef7c90fa60bbc4a3ae7f786003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Thu, 16 Oct 2025 16:53:38 +0200 Subject: [PATCH] Lists --- .../reading_list_dropdown_controller.js | 29 ++++++++++++++----- src/Controller/DefaultController.php | 2 +- src/Twig/Components/ReadingListDropdown.php | 8 ++++- src/Twig/Components/ReadingListList.php | 24 ++++++++++++--- .../Organisms/FeaturedList.html.twig | 4 +-- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/assets/controllers/reading_list_dropdown_controller.js b/assets/controllers/reading_list_dropdown_controller.js index 830e9e9..687f81e 100644 --- a/assets/controllers/reading_list_dropdown_controller.js +++ b/assets/controllers/reading_list_dropdown_controller.js @@ -123,16 +123,36 @@ export default class extends Controller { // Build tags array const tags = []; tags.push(['d', listData.slug]); - tags.push(['type', 'reading-list']); tags.push(['title', listData.title]); if (listData.summary) { tags.push(['summary', listData.summary]); } + // Find type tag and duplicate that (there should only be one) + if (listData.eventJson) { + const existingTags = JSON.parse(listData.eventJson); + const typeTag = existingTags.find(t => t[0] === 'type'); + tags.push(typeTag || ['type', 'reading_list']); + } + // Add existing articles (avoid duplicates) const articleSet = new Set(); - if (listData.articles && Array.isArray(listData.articles)) { + + // Add the new article first + if (this.coordinateValue) { + articleSet.add(this.coordinateValue); + } + + if (listData.eventJson) { + const existingTags = JSON.parse(listData.eventJson); + const existingA = existingTags.filter(t => t[0] === 'a').map(t => t[1]); + existingA.forEach(coord => { + if (coord && typeof coord === 'string') { + articleSet.add(coord); + } + }); + } else if (listData.articles && Array.isArray(listData.articles)) { listData.articles.forEach(coord => { if (coord && typeof coord === 'string') { articleSet.add(coord); @@ -140,11 +160,6 @@ export default class extends Controller { }); } - // Add the new article - if (this.coordinateValue) { - articleSet.add(this.coordinateValue); - } - // Convert set to tags articleSet.forEach(coord => { tags.push(['a', coord]); diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php index 3336b07..9454ce5 100644 --- a/src/Controller/DefaultController.php +++ b/src/Controller/DefaultController.php @@ -316,7 +316,7 @@ class DefaultController extends AbstractController /** * @throws InvalidArgumentException */ - #[Route('/mag/{mag}/cat/{cat}/d/{slug}', name: 'magazine-category-article')] + #[Route('/mag/{mag}/cat/{cat}/d/{slug}', name: 'magazine-category-article', requirements: ['slug' => '.+'])] public function magArticle($mag, $cat, $slug, RedisCacheService $redisCacheService, CacheItemPoolInterface $articlesCache, diff --git a/src/Twig/Components/ReadingListDropdown.php b/src/Twig/Components/ReadingListDropdown.php index 2c31a48..66d8b41 100644 --- a/src/Twig/Components/ReadingListDropdown.php +++ b/src/Twig/Components/ReadingListDropdown.php @@ -5,6 +5,8 @@ namespace App\Twig\Components; use App\Service\ReadingListManager; use Symfony\Bundle\SecurityBundle\Security; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; +use Doctrine\ORM\EntityManagerInterface; +use App\Entity\Event; // Add this line #[AsTwigComponent] final class ReadingListDropdown @@ -14,6 +16,7 @@ final class ReadingListDropdown public function __construct( private readonly ReadingListManager $readingListManager, private readonly Security $security, + private readonly EntityManagerInterface $entityManager, // Inject EntityManagerInterface ) {} public function getUserLists(): array @@ -31,10 +34,13 @@ final class ReadingListDropdown // Fetch full article data for each list foreach ($lists as &$list) { + $event = $this->entityManager->getRepository(Event::class)->find($list['id']); // Modify this line + if ($event) { + $list['eventJson'] = json_encode($event->getTags()); + } $list['articles'] = $this->readingListManager->getArticleCoordinatesForList($list['slug']); } return $lists; } } - diff --git a/src/Twig/Components/ReadingListList.php b/src/Twig/Components/ReadingListList.php index 8265c63..3cff82a 100644 --- a/src/Twig/Components/ReadingListList.php +++ b/src/Twig/Components/ReadingListList.php @@ -3,6 +3,7 @@ namespace App\Twig\Components; use App\Entity\Event; +use App\Enum\KindsEnum; use Doctrine\ORM\EntityManagerInterface; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; @@ -28,23 +29,38 @@ final class ReadingListList $out = []; $seen = []; foreach ($events as $ev) { + $hasArticles = false; $tags = $ev->getTags(); - $isReadingList = false; $title = null; $slug = null; foreach ($tags as $t) { if (!is_array($t)) continue; - if (($t[0] ?? null) === 'type' && ($t[1] ?? null) === 'reading-list') { $isReadingList = true; } if (($t[0] ?? null) === 'title') { $title = (string)$t[1]; } if (($t[0] ?? null) === 'd') { $slug = (string)$t[1]; } } - if (!$isReadingList) continue; // Require slug; skip malformed events without slug if (!$slug) continue; - // Collapse newest by slug + // Collapse the newest by slug if (isset($seen[$slug])) continue; $seen[$slug] = true; + // Make sure the 'a' tags contain long form articles + foreach ($tags as $t) { + if (!is_array($t)) continue; + if (($t[0] ?? null) === 'a') { + // Split coordinate by colon and check first part + $coordParts = explode(':', $t[1] ?? '', 3); + if (count($coordParts) < 2) continue; + $kind = (int)$coordParts[0]; + if ($kind == KindsEnum::LONGFORM->value) { + $hasArticles = true; + break; + } + } + } + + if (!$hasArticles) continue; + $out[] = [ 'title' => $title ?: '(untitled)', 'slug' => $slug, diff --git a/templates/components/Organisms/FeaturedList.html.twig b/templates/components/Organisms/FeaturedList.html.twig index e616add..047e5e4 100644 --- a/templates/components/Organisms/FeaturedList.html.twig +++ b/templates/components/Organisms/FeaturedList.html.twig @@ -7,7 +7,7 @@
{% set feature = list[0] %}