Browse Source

Debug author pages, misc fixes

imwald
Nuša Pukšič 7 months ago
parent
commit
203b2e09d8
  1. 8
      assets/styles/app.css
  2. 26
      src/Command/NostrEventFromYamlDefinitionCommand.php
  3. 2
      src/Controller/AuthorController.php
  4. 47
      src/Controller/DefaultController.php
  5. 52
      src/Twig/Components/Organisms/FeaturedList.php
  6. 22
      src/Util/CommonMark/NostrSchemeExtension/NostrSchemeParser.php
  7. 4
      templates/base.html.twig
  8. 5
      templates/components/Footer.html.twig

8
assets/styles/app.css

@ -376,10 +376,10 @@ footer a {
transition: background-color 0.3s ease; /* Smooth hover effect */ transition: background-color 0.3s ease; /* Smooth hover effect */
} }
/* Hover effect for tags */ /*!* Hover effect for tags *!*/
.tag:hover { /*.tag:hover {*/
color: var(--color-text-contrast); /* color: var(--color-text-contrast);*/
} /*}*/
/* Optional: Responsive adjustments for smaller screens */ /* Optional: Responsive adjustments for smaller screens */
@media (max-width: 768px) { @media (max-width: 768px) {

26
src/Command/NostrEventFromYamlDefinitionCommand.php

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Command; namespace App\Command;
use App\Entity\Article;
use App\Enum\IndexStatusEnum; use App\Enum\IndexStatusEnum;
use App\Factory\ArticleFactory; use App\Factory\ArticleFactory;
use App\Service\NostrClient; use App\Service\NostrClient;
@ -103,31 +102,24 @@ class NostrEventFromYamlDefinitionCommand extends Command
// crawl relays for all the articles and save to db // crawl relays for all the articles and save to db
$fresh = $this->client->getArticles($articleSlugsList); $fresh = $this->client->getArticles($articleSlugsList);
$articles = [];
foreach ($fresh as $item) { foreach ($fresh as $item) {
$article = $this->factory->createFromLongFormContentEvent($item); $article = $this->factory->createFromLongFormContentEvent($item);
$article->setIndexStatus(IndexStatusEnum::TO_BE_INDEXED);
$this->entityManager->persist($article); $this->entityManager->persist($article);
} $articles[] = $article;
$this->entityManager->flush();
// look up all articles in the db and push to index whatever you find
$articles = $this->entityManager->getRepository(Article::class)->createQueryBuilder('a')
->where('a.slug IN (:slugs)')
->setParameter('slugs', $articleSlugsList)
->getQuery()
->getResult();
// mark all of those for indexing
foreach ($articles as $article) {
if ($article->getIndexStatus() === IndexStatusEnum::NOT_INDEXED) {
$article->setIndexStatus(IndexStatusEnum::TO_BE_INDEXED);
$this->entityManager->persist($article);
}
} }
$this->entityManager->flush(); $this->entityManager->flush();
// to elastic // to elastic
if (count($articles) > 0 ) { if (count($articles) > 0 ) {
$this->itemPersister->insertMany($articles); // Insert or skip existing $this->itemPersister->insertMany($articles); // Insert or skip existing
// Set all articles as indexed
foreach ($articles as $article) {
$article->setIndexStatus(IndexStatusEnum::INDEXED);
$this->entityManager->persist($article);
}
$this->entityManager->flush();
$output->writeln('<info>Added to index.</info>'); $output->writeln('<info>Added to index.</info>');
} }

2
src/Controller/AuthorController.php

@ -45,7 +45,7 @@ class AuthorController extends AbstractController
} }
} }
return $this->render('Pages/author.html.twig', [ return $this->render('pages/author.html.twig', [
'author' => $author, 'author' => $author,
'npub' => $npub, 'npub' => $npub,
'articles' => $articles 'articles' => $articles

47
src/Controller/DefaultController.php

@ -4,15 +4,15 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use Elastica\Query;
use Elastica\Query\Terms; use Elastica\Query\Terms;
use Exception;
use FOS\ElasticaBundle\Finder\FinderInterface; use FOS\ElasticaBundle\Finder\FinderInterface;
use Psr\Cache\InvalidArgumentException; use Psr\Cache\InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\CacheInterface;
use App\Service\NostrClient;
use App\Factory\ArticleFactory;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
class DefaultController extends AbstractController class DefaultController extends AbstractController
@ -23,7 +23,7 @@ class DefaultController extends AbstractController
} }
/** /**
* @throws \Exception * @throws Exception
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[Route('/', name: 'home')] #[Route('/', name: 'home')]
@ -51,12 +51,10 @@ class DefaultController extends AbstractController
#[Route('/cat/{slug}', name: 'magazine-category')] #[Route('/cat/{slug}', name: 'magazine-category')]
public function magCategory($slug, CacheInterface $redisCache, public function magCategory($slug, CacheInterface $redisCache,
FinderInterface $finder, FinderInterface $finder,
NostrClient $nostrClient,
ArticleFactory $articleFactory,
LoggerInterface $logger): Response LoggerInterface $logger): Response
{ {
$catIndex = $redisCache->get('magazine-' . $slug, function (){ $catIndex = $redisCache->get('magazine-' . $slug, function (){
throw new \Exception('Not found'); throw new Exception('Not found');
}); });
$list = []; $list = [];
@ -76,19 +74,21 @@ class DefaultController extends AbstractController
} }
} }
// Limit to first 9 coordinates to avoid excessive processing
$coordinates = array_slice($coordinates, 0, 9);
if (!empty($coordinates)) { if (!empty($coordinates)) {
// Extract slugs for elasticsearch query // Extract slugs for elasticsearch query
$slugs = array_map(function($coordinate) { $slugs = array_map(function($coordinate) {
$parts = explode(':', $coordinate); $parts = explode(':', $coordinate, 3);
return count($parts) === 3 ? $parts[2] : ''; return end($parts);
}, $coordinates); }, $coordinates);
$slugs = array_filter($slugs); // Remove empty values $slugs = array_filter($slugs); // Remove empty values
// Try to fetch articles from elasticsearch first // First filter to only include articles with the slugs we want
$query = new Terms('slug', array_values($slugs)); $termsQuery = new Terms('slug', array_values($slugs));
// Create a Query object to set the size parameter
$query = new Query($termsQuery);
$query->setSize(200); // Set size to exceed the number of articles we expect
$articles = $finder->find($query); $articles = $finder->find($query);
// Create a map of slug => item to remove duplicates // Create a map of slug => item to remove duplicates
@ -96,15 +96,24 @@ class DefaultController extends AbstractController
foreach ($articles as $item) { foreach ($articles as $item) {
$slug = $item->getSlug(); $slug = $item->getSlug();
if ($slug !== '') { if ($slug !== '') {
$slugMap[$slug] = $item; // If the slugMap doesn't contain it yet, add it
if (!isset($slugMap[$slug])) {
$slugMap[$slug] = $item;
} else {
// If it already exists, compare created_at timestamps and save newest
$existingItem = $slugMap[$slug];
if ($item->getCreatedAt() > $existingItem->getCreatedAt()) {
$slugMap[$slug] = $item;
}
}
} }
} }
// Find missing coordinates // Find missing coordinates
$missingCoordinates = []; $missingCoordinates = [];
foreach ($coordinates as $coordinate) { foreach ($coordinates as $coordinate) {
$parts = explode(':', $coordinate); $parts = explode(':', $coordinate, 3);
if (count($parts) === 3 && !isset($slugMap[$parts[2]])) { if (!isset($slugMap[end($parts)])) {
$missingCoordinates[] = $coordinate; $missingCoordinates[] = $coordinate;
} }
} }
@ -138,9 +147,9 @@ class DefaultController extends AbstractController
// Build ordered list based on original coordinates order // Build ordered list based on original coordinates order
foreach ($coordinates as $coordinate) { foreach ($coordinates as $coordinate) {
$parts = explode(':', $coordinate); $parts = explode(':', $coordinate,3);
if (count($parts) === 3 && isset($slugMap[$parts[2]])) { if (isset($slugMap[end($parts)])) {
$list[] = $slugMap[$parts[2]]; $list[] = $slugMap[end($parts)];
} }
} }
} }

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

@ -2,24 +2,18 @@
namespace App\Twig\Components\Organisms; namespace App\Twig\Components\Organisms;
use App\Entity\Article; use Elastica\Query;
use App\Factory\ArticleFactory;
use App\Service\NostrClient;
use Elastica\Query\MatchQuery;
use Elastica\Query\Terms; use Elastica\Query\Terms;
use FOS\ElasticaBundle\Finder\FinderInterface; use FOS\ElasticaBundle\Finder\FinderInterface;
use Psr\Cache\InvalidArgumentException; use Psr\Cache\InvalidArgumentException;
use swentel\nostr\Event\Event; use swentel\nostr\Event\Event;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\CacheInterface;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent] #[AsTwigComponent]
final class FeaturedList final class FeaturedList
{ {
public $category; public string $category;
public string $title; public string $title;
public array $list = []; public array $list = [];
@ -47,36 +41,40 @@ final class FeaturedList
$this->title = $tag[1]; $this->title = $tag[1];
} }
if ($tag[0] === 'a') { if ($tag[0] === 'a') {
$parts = explode(':', $tag[1]); $parts = explode(':', $tag[1], 3);
if (count($parts) === 3) { $slugs[] = end($parts);
$slugs[] = $parts[2]; if (count($slugs) >= 5) {
break; // Limit to 4 items
} }
} }
} }
$query = new Terms('slug', array_values($slugs)); $termsQuery = new Terms('slug', array_values($slugs));
$res = $this->finder->find($query); $query = new Query($termsQuery);
$query->setSize(200); // Set size to exceed the number of articles we expect
$articles = $this->finder->find($query);
// Create a map of slug => item to remove duplicates // Create a map of slug => item
$slugMap = []; $slugMap = [];
foreach ($articles as $article) {
foreach ($res as $item) { $slug = $article->getSlug();
$slug = $item->getSlug(); if ($slug !== '') {
if (!isset($slugMap[$slug])) {
if ($slug !== '' && !isset($slugMap[$slug])) { $slugMap[$slug] = $article;
$slugMap[$slug] = $item; } elseif ($article->getCreatedAt() > $slugMap[$slug]->getCreatedAt()) {
$slugMap[$slug] = $article;
}
} }
} }
if (!empty($res)) { // Build ordered list based on original slugs order
foreach ($res as $result) { $orderedList = [];
if (!isset($slugMap[$result->getSlug()])) { foreach ($slugs as $slug) {
$slugMap[$result->getSlug()] = $result; if (isset($slugMap[$slug])) {
} $orderedList[] = $slugMap[$slug];
} }
} }
$this->list = array_slice($orderedList, 0, 4);
$this->list = array_slice(array_values($slugMap), 0, 4);
} }
} }

22
src/Util/CommonMark/NostrSchemeExtension/NostrSchemeParser.php

@ -41,25 +41,25 @@ class NostrSchemeParser implements InlineParserInterface
case 'nprofile': case 'nprofile':
/** @var NProfile $decodedProfile */ /** @var NProfile $decodedProfile */
$decodedProfile = $decoded->data; $decodedProfile = $decoded->data;
$inlineContext->getContainer()->appendChild(new NostrMentionLink(null, $decodedProfile->getPubkey())); $inlineContext->getContainer()->appendChild(new NostrMentionLink(null, $decodedProfile->pubkey));
break; break;
case 'nevent': case 'nevent':
/** @var NEvent $decodedNpub */ /** @var NEvent $decodedNpub */
$decodedEvent = $decoded->data; $decodedEvent = $decoded->data;
$eventId = $decodedEvent->getId(); $eventId = $decodedEvent->id;
$relays = $decodedEvent->getRelays(); $relays = $decodedEvent->relays;
$author = $decodedEvent->getAuthor(); $author = $decodedEvent->author;
$kind = $decodedEvent->getKind(); $kind = $decodedEvent->kind;
$inlineContext->getContainer()->appendChild(new NostrSchemeData('nevent', $eventId, $relays, $author, $kind)); $inlineContext->getContainer()->appendChild(new NostrSchemeData('nevent', $bechEncoded, $relays, $author, $kind));
break; break;
case 'naddr': case 'naddr':
/** @var NAddr $decodedNpub */ /** @var NAddr $decodedNpub */
$decodedEvent = $decoded->data; $decodedEvent = $decoded->data;
$identifier = $decodedEvent->getIdentifier(); $identifier = $decodedEvent->identifier;
$pubkey = $decodedEvent->getPubkey(); $pubkey = $decodedEvent->pubkey;
$kind = $decodedEvent->getKind(); $kind = $decodedEvent->kind;
$relays = $decodedEvent->getRelays(); $relays = $decodedEvent->relays;
$inlineContext->getContainer()->appendChild(new NostrSchemeData('naddr', $identifier, $relays, $pubkey, $kind)); $inlineContext->getContainer()->appendChild(new NostrSchemeData('naddr', $bechEncoded, $relays, $pubkey, $kind));
break; break;
case 'nrelay': case 'nrelay':
// deprecated // deprecated

4
templates/base.html.twig

@ -10,9 +10,13 @@
<link rel="shortcut icon" href="{{ asset('icons/favicon.ico') }}" /> <link rel="shortcut icon" href="{{ asset('icons/favicon.ico') }}" />
<link rel="apple-touch-icon" href="{{ asset('icons/apple-touch-icon.png') }}"> <link rel="apple-touch-icon" href="{{ asset('icons/apple-touch-icon.png') }}">
<meta name="apple-mobile-web-app-title" content="Newsroom" /> <meta name="apple-mobile-web-app-title" content="Newsroom" />
<meta name="lightning" content="coffeecalm152228@getalby.com" />
<link rel="manifest" href="{{ path('pwa_manifest') }}"> <link rel="manifest" href="{{ path('pwa_manifest') }}">
{% block ogtags %} {% block ogtags %}
<meta property="og:image" content="{{ asset('icons/favicon.ico') }}" />
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}

5
templates/components/Footer.html.twig

@ -3,6 +3,7 @@
<a href="{{ path('app_static_roadmap') }}">Roadmap</a> - <a href="{{ path('app_static_roadmap') }}">Roadmap</a> -
{# <a href="{{ path('app_static_pricing') }}">Pricing</a> -#} {# <a href="{{ path('app_static_pricing') }}">Pricing</a> -#}
<a href="{{ path('app_static_tos') }}">Terms of service</a> <a href="{{ path('app_static_tos') }}">Terms of service</a>
{# <a href="https://geyser.fund/project/newsroom?hero=nuapuki">Decent Newsroom - Geyser fund</a>#} <br>
<a href="https://geyser.fund/project/newsroom" target="_blank">Decent Newsroom @ Geyser fund</a>
</div> </div>
<p>{{ "now"|date("Y") }} Decent Newsroom - Preprint</p> <p>{{ "now"|date("Y") }} Decent Newsroom - v0.0.1 Preprint</p>

Loading…
Cancel
Save