Browse Source

Lists

imwald
Nuša Pukšič 3 months ago
parent
commit
027d384802
  1. 29
      assets/controllers/reading_list_dropdown_controller.js
  2. 2
      src/Controller/DefaultController.php
  3. 8
      src/Twig/Components/ReadingListDropdown.php
  4. 24
      src/Twig/Components/ReadingListList.php
  5. 4
      templates/components/Organisms/FeaturedList.html.twig

29
assets/controllers/reading_list_dropdown_controller.js

@ -123,16 +123,36 @@ export default class extends Controller {
// Build tags array // Build tags array
const tags = []; const tags = [];
tags.push(['d', listData.slug]); tags.push(['d', listData.slug]);
tags.push(['type', 'reading-list']);
tags.push(['title', listData.title]); tags.push(['title', listData.title]);
if (listData.summary) { if (listData.summary) {
tags.push(['summary', 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) // Add existing articles (avoid duplicates)
const articleSet = new Set(); 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 => { listData.articles.forEach(coord => {
if (coord && typeof coord === 'string') { if (coord && typeof coord === 'string') {
articleSet.add(coord); 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 // Convert set to tags
articleSet.forEach(coord => { articleSet.forEach(coord => {
tags.push(['a', coord]); tags.push(['a', coord]);

2
src/Controller/DefaultController.php

@ -316,7 +316,7 @@ class DefaultController extends AbstractController
/** /**
* @throws InvalidArgumentException * @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, public function magArticle($mag, $cat, $slug,
RedisCacheService $redisCacheService, RedisCacheService $redisCacheService,
CacheItemPoolInterface $articlesCache, CacheItemPoolInterface $articlesCache,

8
src/Twig/Components/ReadingListDropdown.php

@ -5,6 +5,8 @@ namespace App\Twig\Components;
use App\Service\ReadingListManager; use App\Service\ReadingListManager;
use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Event; // Add this line
#[AsTwigComponent] #[AsTwigComponent]
final class ReadingListDropdown final class ReadingListDropdown
@ -14,6 +16,7 @@ final class ReadingListDropdown
public function __construct( public function __construct(
private readonly ReadingListManager $readingListManager, private readonly ReadingListManager $readingListManager,
private readonly Security $security, private readonly Security $security,
private readonly EntityManagerInterface $entityManager, // Inject EntityManagerInterface
) {} ) {}
public function getUserLists(): array public function getUserLists(): array
@ -31,10 +34,13 @@ final class ReadingListDropdown
// Fetch full article data for each list // Fetch full article data for each list
foreach ($lists as &$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']); $list['articles'] = $this->readingListManager->getArticleCoordinatesForList($list['slug']);
} }
return $lists; return $lists;
} }
} }

24
src/Twig/Components/ReadingListList.php

@ -3,6 +3,7 @@
namespace App\Twig\Components; namespace App\Twig\Components;
use App\Entity\Event; use App\Entity\Event;
use App\Enum\KindsEnum;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
@ -28,23 +29,38 @@ final class ReadingListList
$out = []; $out = [];
$seen = []; $seen = [];
foreach ($events as $ev) { foreach ($events as $ev) {
$hasArticles = false;
$tags = $ev->getTags(); $tags = $ev->getTags();
$isReadingList = false;
$title = null; $slug = null; $title = null; $slug = null;
foreach ($tags as $t) { foreach ($tags as $t) {
if (!is_array($t)) continue; 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) === 'title') { $title = (string)$t[1]; }
if (($t[0] ?? null) === 'd') { $slug = (string)$t[1]; } if (($t[0] ?? null) === 'd') { $slug = (string)$t[1]; }
} }
if (!$isReadingList) continue;
// Require slug; skip malformed events without slug // Require slug; skip malformed events without slug
if (!$slug) continue; if (!$slug) continue;
// Collapse newest by slug // Collapse the newest by slug
if (isset($seen[$slug])) continue; if (isset($seen[$slug])) continue;
$seen[$slug] = true; $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[] = [ $out[] = [
'title' => $title ?: '(untitled)', 'title' => $title ?: '(untitled)',
'slug' => $slug, 'slug' => $slug,

4
templates/components/Organisms/FeaturedList.html.twig

@ -7,7 +7,7 @@
<div> <div>
{% set feature = list[0] %} {% set feature = list[0] %}
<div class="card"> <div class="card">
<a href="{{ path('magazine-category-article', {slug: feature.slug, cat: catSlug, mag: mag}) }}"> <a href="{{ path('magazine-category-article', {slug: feature.slug|url_encode, cat: catSlug, mag: mag}) }}">
<div class="card-header"> <div class="card-header">
{% if feature.image %} {% if feature.image %}
<img src="{{ feature.image }}" alt="Cover image for {{ feature.title }}"> <img src="{{ feature.image }}" alt="Cover image for {{ feature.title }}">
@ -26,7 +26,7 @@
{% for item in list %} {% for item in list %}
{% if item != feature %} {% if item != feature %}
<div class="card"> <div class="card">
<a href="{{ path('magazine-category-article', {slug: feature.slug, cat: catSlug, mag: mag}) }}"> <a href="{{ path('magazine-category-article', {slug: item.slug|url_encode, cat: catSlug, mag: mag}) }}">
<div class="card-body"> <div class="card-body">
<h2 class="card-title">{{ item.title }}</h2> <h2 class="card-title">{{ item.title }}</h2>
<p class="lede truncate"> <p class="lede truncate">

Loading…
Cancel
Save