From a4e4f5da0d8db2b77559adfa1661fc0ebad26122 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Fri, 14 Aug 2020 13:03:08 +0200 Subject: [PATCH] WIP|Allow to mark entries as read and unread Add new read link to each entry. If entry was read the link will be replaced with an unread link. Clicking the link will mark the entry as read or unread. Afterwards a redirect to referrer happens. If it is unkown, for whatever reason, fallback to start. Flash messages are added and rendered to let user know what happened. Also respect already read entries when opening a feed. WIP: Still need to adjust entry listing for buckets. Still need to add tests for new feature. Still need to add new start page to show newest unread entries from all buckets. --- assets/sass/_variables.scss | 4 ++ assets/sass/components/_content.scss | 1 + assets/sass/components/content/_flash.scss | 20 +++++++++ config/routes.yaml | 8 ++++ public/css/style.css | 17 +++++++ src/Controller/EntryController.php | 52 +++++++++++++++++++++- src/Entity/Bucket.php | 4 +- src/Entity/Entry.php | 13 +++++- src/Entity/Feed.php | 8 ++++ templates/base.html.twig | 10 +++++ templates/bucket/show.html.twig | 2 +- templates/entry/_single.html.twig | 6 +++ templates/feed/entries.html.twig | 10 +++-- templates/feed/show.html.twig | 2 +- 14 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 assets/sass/components/content/_flash.scss diff --git a/assets/sass/_variables.scss b/assets/sass/_variables.scss index 71cbe5a..dc7852c 100644 --- a/assets/sass/_variables.scss +++ b/assets/sass/_variables.scss @@ -3,6 +3,10 @@ --color-foreground: #D3D7CF; --color-blue-light: #9CD9F0; --color-blue-dark: #72B3CC; + --color-green-light: #CDEE69; + --color-green-dark: #8EB33B; + --color-yellow-light: #FFE377; + --color-yellow-dark: #D0B03C; --color-black-light: #5D5D5D; --color-black-dark: #000000; --color-white-light: #F7F7F7; diff --git a/assets/sass/components/_content.scss b/assets/sass/components/_content.scss index 8b51a5e..7eb90d8 100644 --- a/assets/sass/components/_content.scss +++ b/assets/sass/components/_content.scss @@ -5,4 +5,5 @@ body > main { } } +@import 'content/flash'; @import 'content/entries'; diff --git a/assets/sass/components/content/_flash.scss b/assets/sass/components/content/_flash.scss new file mode 100644 index 0000000..430d1d2 --- /dev/null +++ b/assets/sass/components/content/_flash.scss @@ -0,0 +1,20 @@ +body > aside { + ul { + list-style: none; + color: var(--color-black-dark); + margin: var(--spacing-elements); + + li { + padding: var(--spacing-small-elements); + } + + &.success { + background-color: var(--color-green-dark); + border: var(--color-green-light) solid var(--width-border-default); + } + &.notice { + background-color: var(--color-yellow-dark); + border: var(--color-yellow-light) solid var(--width-border-default); + } + } +} diff --git a/config/routes.yaml b/config/routes.yaml index f6d5ae1..33d8948 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -17,3 +17,11 @@ feed: entry: path: /entry/{slug} controller: App\Controller\EntryController::show + +entry-mark-as-read: + path: /entry/{slug}/mark/read + controller: App\Controller\EntryController::read + +entry-mark-as-un-read: + path: /entry/{slug}/mark/un-read + controller: App\Controller\EntryController::unRead diff --git a/public/css/style.css b/public/css/style.css index 208e190..a832f3e 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -3,6 +3,10 @@ --color-foreground: #D3D7CF; --color-blue-light: #9CD9F0; --color-blue-dark: #72B3CC; + --color-green-light: #CDEE69; + --color-green-dark: #8EB33B; + --color-yellow-light: #FFE377; + --color-yellow-dark: #D0B03C; --color-black-light: #5D5D5D; --color-black-dark: #000000; --color-white-light: #F7F7F7; @@ -56,6 +60,19 @@ body > main { body > main header h1 { margin: 0; } +body > aside ul { + list-style: none; + color: var(--color-black-dark); + margin: var(--spacing-elements); } + body > aside ul li { + padding: var(--spacing-small-elements); } + body > aside ul.success { + background-color: var(--color-green-dark); + border: var(--color-green-light) solid var(--width-border-default); } + body > aside ul.notice { + background-color: var(--color-yellow-dark); + border: var(--color-yellow-light) solid var(--width-border-default); } + article { display: grid; grid-template-columns: 50em var(--width-sidebar-max); diff --git a/src/Controller/EntryController.php b/src/Controller/EntryController.php index f579517..08e18cd 100644 --- a/src/Controller/EntryController.php +++ b/src/Controller/EntryController.php @@ -3,14 +3,64 @@ namespace App\Controller; use App\Entity\Entry; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; class EntryController extends AbstractController { - public function show(Entry $entry) + /** + * @var EntityManagerInterface + */ + private $entityManager; + + public function __construct( + EntityManagerInterface $entityManager + ) { + $this->entityManager = $entityManager; + } + + public function show(Entry $entry): Response { return $this->render('entry/show.html.twig', [ 'entry' => $entry, ]); } + + public function read(Entry $entry, Request $request): Response + { + if ($entry->wasRead()) { + $this->addFlash('notice', sprintf('Entry "%s" was already marked as read.', $entry->getName())); + } else { + $entry->markAsRead(); + $this->entityManager->flush(); + $this->addFlash('success', sprintf('Entry "%s" was marked as read.', $entry->getName())); + } + + return $this->getRedirectResponseAfterModification($request); + } + + public function unRead(Entry $entry, Request $request): Response + { + if ($entry->wasRead()) { + $entry->markAsUnRead(); + $this->entityManager->flush(); + $this->addFlash('success', sprintf('Entry "%s" was marked as un read.', $entry->getName())); + } else { + $this->addFlash('notice', sprintf('Entry "%s" was not yet marked as read.', $entry->getName())); + } + + return $this->getRedirectResponseAfterModification($request); + } + + private function getRedirectResponseAfterModification(Request $request): Response + { + $redirectTarget = $request->headers->get('referer'); + if (is_string($redirectTarget)) { + return $this->redirect($redirectTarget, 307); + } + + return $this->redirectToRoute('start', [], 307); + } } diff --git a/src/Entity/Bucket.php b/src/Entity/Bucket.php index 582a16a..3410451 100644 --- a/src/Entity/Bucket.php +++ b/src/Entity/Bucket.php @@ -5,6 +5,7 @@ namespace App\Entity; use App\Repository\BucketRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping as ORM; /** @@ -59,9 +60,6 @@ class Bucket return $this->slug; } - /** - * @return Collection|Feed[] - */ public function getFeeds(): Collection { return $this->feeds; diff --git a/src/Entity/Entry.php b/src/Entity/Entry.php index 1c5c40c..66d15c9 100644 --- a/src/Entity/Entry.php +++ b/src/Entity/Entry.php @@ -128,9 +128,18 @@ class Entry return $this->content; } - // TODO: Rename into is / was ? - public function getRead(): bool + public function wasRead(): bool { return $this->read; } + + public function markAsRead(): void + { + $this->read = true; + } + + public function markAsUnRead(): void + { + $this->read = false; + } } diff --git a/src/Entity/Feed.php b/src/Entity/Feed.php index fce96fd..38de218 100644 --- a/src/Entity/Feed.php +++ b/src/Entity/Feed.php @@ -5,6 +5,7 @@ namespace App\Entity; use App\Repository\FeedRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping as ORM; /** @@ -100,4 +101,11 @@ class Feed { return $this->entries; } + + public function getUnreadEntries(): Collection + { + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('read', false)); + return $this->entries->matching($criteria); + } } diff --git a/templates/base.html.twig b/templates/base.html.twig index 650e014..82bb885 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -12,6 +12,16 @@

{{ app_name }}

+ +
{% block body %}{% endblock %}
diff --git a/templates/bucket/show.html.twig b/templates/bucket/show.html.twig index 67648bb..f8ed1e6 100644 --- a/templates/bucket/show.html.twig +++ b/templates/bucket/show.html.twig @@ -9,7 +9,7 @@ {# TODO: collect newest entries of all feeds in controller #} - {{ include('feed/entries.html.twig', {entries: bucket.feeds.first.entries | slice(0, 10) }) }} + {{ include('feed/entries.html.twig', {entries: bucket.feeds.first.unreadEntries | slice(0, 10) }) }}