diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php index 310aa2e..f56a06d 100644 --- a/src/Controller/DefaultController.php +++ b/src/Controller/DefaultController.php @@ -61,30 +61,6 @@ class DefaultController extends AbstractController return $this->render('pages/lists.html.twig'); } - /** - * @throws InvalidArgumentException - */ - #[Route('/latest', name: 'latest')] - public function latest() : Response - { - $cacheKey = 'home-latest-articles'; - $latest = $this->redisCache->get($cacheKey, function (ItemInterface $item) { - $item->expiresAfter(13600); // about 4 hours - // get latest articles - $q = new Query(); - $q->setSize(12); - $q->setSort(['createdAt' => ['order' => 'desc']]); - $col = new Collapse(); - $col->setFieldname('pubkey'); - $q->setCollapse($col); - return $this->finder->find($q); - }); - - return $this->render('pages/latest.html.twig', [ - 'latest' => $latest - ]); - } - /** * Magazine front page: title, summary, category links, featured list. * @throws InvalidArgumentException @@ -286,17 +262,6 @@ class DefaultController extends AbstractController ]); } - /** - * @throws InvalidArgumentException - */ - #[Route('/list/{slug}', name: 'reading-list')] - public function readingList($slug, CacheInterface $redisCache, - FinderInterface $finder, - LoggerInterface $logger): Response - { - return new Response('Not implemented yet', 501); - } - /** * OG Preview endpoint for URLs diff --git a/src/Controller/ReadingListController.php b/src/Controller/ReadingListController.php index 77084ba..bead369 100644 --- a/src/Controller/ReadingListController.php +++ b/src/Controller/ReadingListController.php @@ -5,11 +5,19 @@ declare(strict_types=1); namespace App\Controller; use App\Entity\Event; +use App\Enum\KindsEnum; use Doctrine\ORM\EntityManagerInterface; +use Elastica\Query; +use Elastica\Query\BoolQuery; +use Elastica\Query\Term; +use FOS\ElasticaBundle\Finder\FinderInterface; +use Psr\Cache\InvalidArgumentException; +use Psr\Log\LoggerInterface; use swentel\nostr\Key\Key; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Contracts\Cache\CacheInterface; class ReadingListController extends AbstractController { @@ -19,7 +27,7 @@ class ReadingListController extends AbstractController $lists = []; $user = $this->getUser(); $pubkeyHex = null; - if ($user && method_exists($user, 'getUserIdentifier')) { + if ($user) { try { $key = new Key(); $pubkeyHex = $key->convertToHex($user->getUserIdentifier()); @@ -59,6 +67,7 @@ class ReadingListController extends AbstractController 'summary' => $summary, 'slug' => $slug, 'createdAt' => $ev->getCreatedAt(), + 'pubkey' => $ev->getPubkey(), ]; } } @@ -74,4 +83,68 @@ class ReadingListController extends AbstractController { return $this->render('reading_list/compose.html.twig'); } + + /** + * + * @throws InvalidArgumentException + */ + #[Route('/p/{pubkey}/list/{slug}', name: 'reading-list')] + public function readingList($pubkey, $slug, CacheInterface $redisCache, + EntityManagerInterface $em, + FinderInterface $finder, + LoggerInterface $logger): Response + { + $key = 'single-reading-list-' . $pubkey . '-' . $slug; + $logger->info(sprintf('Reading list: %s', $key)); + $list = $redisCache->get($key, function() use ($em, $pubkey, $slug) { + // find reading list by pubkey+slug, kind 30040 + $lists = $em->getRepository(Event::class)->findBy(['pubkey' => $pubkey, 'kind' => KindsEnum::PUBLICATION_INDEX]); + // filter by tag d = $slug + $lists = array_filter($lists, function($ev) use ($slug) { + return $ev->getSlug() === $slug; + }); + // sort revisions and keep latest + usort($lists, function($a, $b) { + return $b->getCreatedAt() <=> $a->getCreatedAt(); + }); + return array_pop($lists); + }); + + // fetch articles listed in the list's a tags + $coordinates = []; // Store full coordinates (kind:author:slug) + // Extract category metadata and article coordinates + foreach ($list->getTags() as $tag) { + if ($tag[0] === 'a') { + $coordinates[] = $tag[1]; // Store the full coordinate + } + } + $articles = []; + if (count($coordinates) > 0) { + $boolQuery = new BoolQuery(); + foreach ($coordinates as $coord) { + $parts = explode(':', $coord, 3); + [$kind, $author, $slug] = $parts; + $termQuery = new BoolQuery(); + $termQuery->addMust(new Term(['kind' => (int)$kind])); + $termQuery->addMust(new Term(['pubkey' => strtolower($author)])); + $termQuery->addMust(new Term(['slug' => $slug])); + $boolQuery->addShould($termQuery); + } + $finalQuery = new Query($boolQuery); + $finalQuery->setSize(100); // Limit to 100 results + $results = $finder->find($finalQuery); + // Index results by their full coordinate for easy lookup + foreach ($results as $result) { + if ($result instanceof Event) { + $coordKey = sprintf('%d:%s:%s', $result->getKind(), strtolower($result->getPubkey()), $result->getSlug()); + $articles[$coordKey] = $result; + } + } + } + + return $this->render('pages/list.html.twig', [ + 'list' => $list, + 'articles' => $articles, + ]); + } } diff --git a/templates/components/Organisms/MagazineHero.html.twig b/templates/components/Organisms/MagazineHero.html.twig index 23bbddd..a1f5d38 100644 --- a/templates/components/Organisms/MagazineHero.html.twig +++ b/templates/components/Organisms/MagazineHero.html.twig @@ -1,11 +1,13 @@
-
+

{{ magazine.title|default(magazine.slug|default(mag)) }}

{% if magazine.summary is defined and magazine.summary %}

{{ magazine.summary }}

{% endif %} - +
by
+
+
{# Use computed property via this.categoryTags #} {% if this.categoryTags is not empty %}
    diff --git a/templates/components/Organisms/ReadingListList.html.twig b/templates/components/Organisms/ReadingListList.html.twig index d247942..6197c35 100644 --- a/templates/components/Organisms/ReadingListList.html.twig +++ b/templates/components/Organisms/ReadingListList.html.twig @@ -1,16 +1,17 @@
    {% set items = this.lists %} {% if items is not empty %} -
      {% for item in items %} -
    • - {{ item.title }} -
      {{ item.createdAt|date('Y-m-d') }}
      -
    • +
      +

      {{ item.title }}

      +

      by

      + {{ item.createdAt|date('Y-m-d') }} + {% if item.summary is defined and item.summary %} +

      {{ item.summary }}

      + {% endif %} +
      {% endfor %} -
    {% else %}

    No reading lists yet.

    {% endif %}
    - diff --git a/templates/layout.html.twig b/templates/layout.html.twig index c50f900..35ba9e3 100644 --- a/templates/layout.html.twig +++ b/templates/layout.html.twig @@ -17,9 +17,6 @@
  • {{ 'heading.search'|trans }}
  • -
  • - Latest -
{% block nav %}{% endblock %} diff --git a/templates/pages/latest.html.twig b/templates/pages/latest.html.twig deleted file mode 100644 index c6fb36d..0000000 --- a/templates/pages/latest.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'layout.html.twig' %} - -{% block body %} -
-
-

Hot

-

off the presses

-
-
-
- -
-{% endblock %} diff --git a/templates/pages/list.html.twig b/templates/pages/list.html.twig new file mode 100644 index 0000000..58d5a3d --- /dev/null +++ b/templates/pages/list.html.twig @@ -0,0 +1,21 @@ +{% extends 'layout.html.twig' %} + +{% block ogtags %} + + + + + +{% endblock %} + +{% block body %} +
+
+

{{ list.title }}

+

{{ list.summary }}

+
+
+ + + +{% endblock %} diff --git a/templates/pages/lists.html.twig b/templates/pages/lists.html.twig index 3595934..40b6687 100644 --- a/templates/pages/lists.html.twig +++ b/templates/pages/lists.html.twig @@ -1,7 +1,7 @@ {% extends 'layout.html.twig' %} {% block body %} -
+

Reading Lists

for collections, curations, courses and more

diff --git a/templates/pages/newsstand.html.twig b/templates/pages/newsstand.html.twig index a722397..8be9c0e 100644 --- a/templates/pages/newsstand.html.twig +++ b/templates/pages/newsstand.html.twig @@ -20,6 +20,6 @@ {% endblock %} {% block aside %} -
Lists
- +{#
Lists
#} +{# #} {% endblock %} diff --git a/templates/reading_list/index.html.twig b/templates/reading_list/index.html.twig index 5a062ca..dafacb7 100644 --- a/templates/reading_list/index.html.twig +++ b/templates/reading_list/index.html.twig @@ -24,9 +24,9 @@
Open Composer {% if item.slug %} - View + View - + diff --git a/templates/reading_list/reading_setup.html.twig b/templates/reading_list/reading_setup.html.twig index fac9c82..35f81cd 100644 --- a/templates/reading_list/reading_setup.html.twig +++ b/templates/reading_list/reading_setup.html.twig @@ -8,7 +8,7 @@ {{ form_row(form.summary) }} {{ form_row(form.tags) }} -
+
Cancel