Browse Source

Revise routing, part 4

imwald
Nuša Pukšič 4 months ago
parent
commit
d537a900e0
  1. 4
      assets/styles/app.css
  2. 12
      assets/styles/layout.css
  3. 3
      src/Controller/ArticleController.php
  4. 68
      src/Controller/DefaultController.php
  5. 17
      src/Twig/Components/Molecules/Card.php
  6. 3
      src/Twig/Components/Organisms/CardList.php
  7. 5
      src/Twig/Components/Organisms/FeaturedList.php
  8. 11
      templates/components/Molecules/Card.html.twig
  9. 2
      templates/components/Organisms/CardList.html.twig
  10. 4
      templates/components/Organisms/FeaturedList.html.twig
  11. 2
      templates/magazine/magazine-front.html.twig
  12. 10
      templates/pages/article.html.twig
  13. 10
      templates/pages/category.html.twig
  14. 6
      templates/pages/latest.html.twig
  15. 21
      templates/pages/magazine.html.twig
  16. 7
      templates/pages/newsstand.html.twig

4
assets/styles/app.css

@ -283,10 +283,6 @@ div:nth-child(odd) .featured-list {
.header .container { .header .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: start;
width: 100%;
max-width: 1200px;
padding: 0 20px;
} }
.header__categories ul { .header__categories ul {

12
assets/styles/layout.css

@ -9,6 +9,10 @@
* - Footer (footer) * - Footer (footer)
**/ **/
body {
position: relative;
}
/* Layout Container */ /* Layout Container */
.layout { .layout {
max-width: 100%; max-width: 100%;
@ -31,18 +35,12 @@ nav {
header { header {
position: fixed; position: fixed;
width: 100vw; width: 100%;
min-height: 60px; min-height: 60px;
top: 0; top: 0;
left: 0; left: 0;
} }
.header__logo {
display: flex;
width: 100%;
margin-left: 10px;
}
nav ul { nav ul {
list-style-type: none; list-style-type: none;
padding: 0; padding: 0;

3
src/Controller/ArticleController.php

@ -121,12 +121,15 @@ class ArticleController extends AbstractController
} }
} }
$canonical = $this->generateUrl('article-slug', ['slug' => $article->getSlug()], 0);
return $this->render('pages/article.html.twig', [ return $this->render('pages/article.html.twig', [
'article' => $article, 'article' => $article,
'author' => $author, 'author' => $author,
'npub' => $npub, 'npub' => $npub,
'content' => $cacheItem->get(), 'content' => $cacheItem->get(),
'canEdit' => $canEdit, 'canEdit' => $canEdit,
'canonical' => $canonical
]); ]);
} }

68
src/Controller/DefaultController.php

@ -4,16 +4,20 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\Entity\Article;
use App\Entity\Event; use App\Entity\Event;
use App\Enum\KindsEnum; use App\Enum\KindsEnum;
use App\Service\RedisCacheService; use App\Service\RedisCacheService;
use App\Util\CommonMark\Converter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Elastica\Collapse; use Elastica\Collapse;
use Elastica\Query; use Elastica\Query;
use Elastica\Query\Terms; use Elastica\Query\Terms;
use Exception; use Exception;
use FOS\ElasticaBundle\Finder\FinderInterface; use FOS\ElasticaBundle\Finder\FinderInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException; use Psr\Cache\InvalidArgumentException;
use swentel\nostr\Key\Key;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -218,6 +222,70 @@ class DefaultController extends AbstractController
]); ]);
} }
/**
* @throws InvalidArgumentException
*/
#[Route('/mag/{mag}/cat/{cat}/d/{slug}', name: 'magazine-category-article')]
public function magArticle($mag, $cat, $slug,
RedisCacheService $redisCacheService,
CacheItemPoolInterface $articlesCache,
EntityManagerInterface $entityManager,
Converter $converter,
LoggerInterface $logger): Response
{
$magazine = $redisCacheService->getMagazineIndex($mag);
$article = null;
// check if an item with same eventId already exists in the db
$repository = $entityManager->getRepository(Article::class);
// slug might be url encoded, decode it
$slug = urldecode($slug);
$articles = $repository->findBy(['slug' => $slug]);
$revisions = count($articles);
if ($revisions === 0) {
throw $this->createNotFoundException('The article could not be found');
}
if ($revisions > 1) {
// sort articles by created at date
usort($articles, function ($a, $b) {
return $b->getCreatedAt() <=> $a->getCreatedAt();
});
}
$article = $articles[0];
$cacheKey = 'article_' . $article->getEventId();
$cacheItem = $articlesCache->getItem($cacheKey);
if (!$cacheItem->isHit()) {
$cacheItem->set($converter->convertToHTML($article->getContent()));
$articlesCache->save($cacheItem);
}
$key = new Key();
$npub = $key->convertPublicKeyToBech32($article->getPubkey());
$author = $redisCacheService->getMetadata($npub);
// set canonical url to this article as article-slug path
$canonical = $this->generateUrl('article-slug', [
'slug' => $article->getSlug()
], 0);
return $this->render('pages/article.html.twig', [
'magazine' => $magazine,
'mag' => $mag,
'article' => $article,
'author' => $author,
'npub' => $npub,
'content' => $cacheItem->get(),
'canEdit' => false,
'canonical' => $canonical
]);
}
/** /**
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */

17
src/Twig/Components/Molecules/Card.php

@ -2,19 +2,26 @@
namespace App\Twig\Components\Molecules; namespace App\Twig\Components\Molecules;
use App\Entity\User; use swentel\nostr\Event\Event;
use App\Service\NostrClient;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent] #[AsTwigComponent]
final class Card final class Card
{ {
public string $category = ''; public ?Event $category = null; // category index passed from parent (optional)
public ?string $cat = "abc"; // computed category slug from $category (optional)
public ?string $mag = null; // magazine slug passed from parent (optional)
public object $article; public object $article;
public function __construct() public function mount($category)
{ {
if ($category) {
$tags = $category->getTags();
$dTag = array_filter($tags, function($tag) {
return ($tag[0] === 'd');
});
$this->cat = array_pop($dTag)[1];
}
} }
} }

3
src/Twig/Components/Organisms/CardList.php

@ -2,10 +2,13 @@
namespace App\Twig\Components\Organisms; namespace App\Twig\Components\Organisms;
use swentel\nostr\Event\Event;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent] #[AsTwigComponent]
final class CardList final class CardList
{ {
public array $list; public array $list;
public ?string $mag = null; // magazine slug passed from parent (optional)
public ?Event $category = null; // category index passed from parent (optional)
} }

5
src/Twig/Components/Organisms/FeaturedList.php

@ -13,7 +13,9 @@ use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent] #[AsTwigComponent]
final class FeaturedList final class FeaturedList
{ {
public string $mag;
public string $category; public string $category;
public string $catSlug;
public string $title; public string $title;
public array $list = []; public array $list = [];
@ -40,6 +42,9 @@ final class FeaturedList
if ($tag[0] === 'title') { if ($tag[0] === 'title') {
$this->title = $tag[1]; $this->title = $tag[1];
} }
if ($tag[0] === 'd') {
$this->catSlug = $tag[1];
}
if ($tag[0] === 'a') { if ($tag[0] === 'a') {
$parts = explode(':', $tag[1], 3); $parts = explode(':', $tag[1], 3);
$slugs[] = end($parts); $slugs[] = end($parts);

11
templates/components/Molecules/Card.html.twig

@ -1,18 +1,17 @@
{% if article is defined %} {% if article is defined %}
<div class="card"> <div class="card">
<div class="metadata"> <div class="metadata">
{% if category %}
<small>{{ category }}</small>
{% else %}
{% if not is_author_profile %} {% if not is_author_profile %}
<p>by <twig:Molecules:UserFromNpub ident="{{ article.pubkey }}" /></p> <p>by <twig:Molecules:UserFromNpub ident="{{ article.pubkey }}" /></p>
{% endif %} {% endif %}
<small>{{ article.createdAt|date('F j Y') }}</small> <small>{{ article.createdAt|date('F j Y') }}</small>
{% endif %}
</div> </div>
<a href="{{ path('article-slug', {slug: article.slug}) }}"> {% set link = path('article-slug', {slug: article.slug}) %}
{% if cat and mag %}
{% set link = path('magazine-category-article', {slug: article.slug, cat: cat, mag: mag}) %}
{% endif %}
<a href="{{ link }}">
<div class="card-header"> <div class="card-header">
{% if category %}<small class="text-uppercase">{{ category }}</small>{% endif %}
{% if article.image %} {% if article.image %}
<img src="{{ article.image }}" alt="Cover image for {{ article.title }}" onerror="this.style.display='none';" > <img src="{{ article.image }}" alt="Cover image for {{ article.title }}" onerror="this.style.display='none';" >
{% endif %} {% endif %}

2
templates/components/Organisms/CardList.html.twig

@ -2,7 +2,7 @@
{% set is_author_profile = is_author_profile|default(false) %} {% set is_author_profile = is_author_profile|default(false) %}
{% for item in list %} {% for item in list %}
{% if item.slug is not empty and item.title is not empty %} {% if item.slug is not empty and item.title is not empty %}
<twig:Molecules:Card :article="item" :is_author_profile="is_author_profile"></twig:Molecules:Card> <twig:Molecules:Card :article="item" :is_author_profile="is_author_profile" :category="category" :mag="mag"></twig:Molecules:Card>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>

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('article-slug', {slug: feature.slug}) }}"> <a href="{{ path('magazine-category-article', {slug: feature.slug, 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('article-slug', {slug: item.slug}) }}"> <a href="{{ path('magazine-category-article', {slug: feature.slug, 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">

2
templates/magazine/magazine-front.html.twig

@ -16,7 +16,7 @@
<section class="mb-5"> <section class="mb-5">
{% if categoryTags is not empty %} {% if categoryTags is not empty %}
{% for cat in categoryTags %} {% for cat in categoryTags %}
<twig:Organisms:FeaturedList category="{{ cat }}" class="featured-list"/> <twig:Organisms:FeaturedList :mag="mag" category="{{ cat }}" class="featured-list"/>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</section> </section>

10
templates/pages/article.html.twig

@ -3,7 +3,7 @@
{% block ogtags %} {% block ogtags %}
<meta property="og:title" content="{{ article.title }}"> <meta property="og:title" content="{{ article.title }}">
<meta property="og:type" content="article"> <meta property="og:type" content="article">
<meta property="og:url" content="{{ app.request.uri }}"> <meta property="og:url" content="{{ canonical }}">
{% if article.image %} {% if article.image %}
<meta property="og:image" content="{{ article.image }}"> <meta property="og:image" content="{{ article.image }}">
{% endif %} {% endif %}
@ -12,6 +12,9 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{% if magazine is defined %}
<twig:Organisms:MagazineHero :mag="mag" :magazine="magazine" />
{% endif %}
<div class="article-actions"> <div class="article-actions">
{% if canEdit %} {% if canEdit %}
@ -25,6 +28,7 @@
{% endif %} {% endif %}
</div> </div>
<div class="w-container">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h1 class="card-title">{{ article.title }}</h1> <h1 class="card-title">{{ article.title }}</h1>
@ -76,10 +80,8 @@
<hr class="divider" /> <hr class="divider" />
{# <pre>#}
{# {{ article.content }}#}
{# </pre>#}
<twig:Organisms:Comments current="30023:{{ article.pubkey }}:{{ article.slug|e }}"></twig:Organisms:Comments> <twig:Organisms:Comments current="30023:{{ article.pubkey }}:{{ article.slug|e }}"></twig:Organisms:Comments>
</div>
{% endblock %} {% endblock %}
{% block aside %} {% block aside %}

10
templates/pages/category.html.twig

@ -8,16 +8,8 @@
<meta property="og:site_name" content="Newsroom"> <meta property="og:site_name" content="Newsroom">
{% endblock %} {% endblock %}
{% block nav %}
{% endblock %}
{% block body %} {% block body %}
<twig:Organisms:MagazineHero :mag="mag" :magazine="magazine" /> <twig:Organisms:MagazineHero :mag="mag" :magazine="magazine" />
<twig:Organisms:CardList :list="list" class="article-list" /> <twig:Organisms:CardList :list="list" :category="index" :mag="mag" class="article-list" />
{% endblock %}
{% block aside %}
{# <h6>Magazines</h6>#}
{# <twig:Organisms:ZineList />#}
{% endblock %} {% endblock %}

6
templates/pages/latest.html.twig

@ -1,6 +1,12 @@
{% extends 'layout.html.twig' %} {% extends 'layout.html.twig' %}
{% block body %} {% block body %}
<section class="d-flex gap-3 center ln-section--newsstand mb-3">
<div class="container mt-5 mb-5">
<h1>Hot</h1>
<p class="eyebrow">off the presses</p>
</div>
</section>
<div class="w-container"> <div class="w-container">
<twig:Organisms:CardList :list="latest" /> <twig:Organisms:CardList :list="latest" />
</div> </div>

21
templates/pages/magazine.html.twig

@ -1,21 +0,0 @@
{% extends 'layout.html.twig' %}
{% block ogtags %}
<meta property="og:title" content="{{ magazine.title }}">
<meta property="og:type" content="website">
<meta property="og:url" content="{{ app.request.uri }}">
<meta property="og:description" content="{{ magazine.summary }}">
<meta property="og:site_name" content="Newsroom">
{% endblock %}
{% block nav %}
{% endblock %}
{% block body %}
{# hero #}
<twig:Organisms:MagazineHero :magazine="magazine" class="mb-4"/>
{# content #}
{% for item in indices %}
<twig:Organisms:FeaturedList :category="item" class="featured-list"/>
{% endfor %}
{% endblock %}

7
templates/pages/newsstand.html.twig

@ -10,6 +10,13 @@
<section class="mb-5"> <section class="mb-5">
<twig:Organisms:ZineList /> <twig:Organisms:ZineList />
</section> </section>
<section class="d-flex gap-3 center ln-section--newsroom">
<div class="container mt-5 mb-5">
<h1>More magazines soon</h1>
<p class="eyebrow">this is only the beginning</p>
</div>
</section>
{% endblock %} {% endblock %}
{% block aside %} {% block aside %}

Loading…
Cancel
Save