diff --git a/locales/fr_FR/LC_MESSAGES/main.mo b/locales/fr_FR/LC_MESSAGES/main.mo index 04afd8ff..6465f675 100644 Binary files a/locales/fr_FR/LC_MESSAGES/main.mo and b/locales/fr_FR/LC_MESSAGES/main.mo differ diff --git a/locales/fr_FR/LC_MESSAGES/main.po b/locales/fr_FR/LC_MESSAGES/main.po index 51df75ca..44d9f317 100644 --- a/locales/fr_FR/LC_MESSAGES/main.po +++ b/locales/fr_FR/LC_MESSAGES/main.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: flusio\n" -"POT-Creation-Date: 2024-03-24 20:14+0100\n" -"PO-Revision-Date: 2024-03-24 20:14+0100\n" +"POT-Creation-Date: 2024-03-25 15:13+0100\n" +"PO-Revision-Date: 2024-03-25 15:13+0100\n" "Last-Translator: Marien Fressinaud \n" "Language-Team: \n" "Language: fr_FR\n" @@ -50,7 +50,7 @@ msgstr "Afficher" #: controllers/Feeds.php:107 controllers/Groups.php:90 #: controllers/Links.php:270 controllers/Links.php:442 #: controllers/Mastodon.php:211 controllers/Mastodon.php:297 -#: controllers/News.php:75 controllers/Passwords.php:89 +#: controllers/News.php:79 controllers/Passwords.php:89 #: controllers/Passwords.php:192 controllers/Registrations.php:103 #: controllers/Sessions.php:85 controllers/Support.php:70 #: controllers/collections/Filters.php:105 @@ -455,20 +455,20 @@ msgstr "plateforme inconnue" msgid "%s on %s" msgstr "%s sur %s" -#: utils/view_helpers.php:102 +#: utils/view_helpers.php:81 msgid "< 1 min" msgstr "< 1 min" -#: utils/view_helpers.php:104 +#: utils/view_helpers.php:83 #, php-format msgid "%s min" msgstr "%s min" -#: utils/view_helpers.php:222 +#: utils/view_helpers.php:201 msgid "There are no relevant links to suggest at this time." msgstr "Il n'y a aucun lien pertinent à vous proposer pour le moment." -#: utils/view_helpers.php:224 +#: utils/view_helpers.php:203 #, php-format msgid "" "You can add links to your bookmarks to read them later." @@ -476,7 +476,7 @@ msgstr "" "Vous pouvez placer des liens dans vos signets pour les " "lire plus tard." -#: utils/view_helpers.php:254 views/links/show.phtml:73 +#: utils/view_helpers.php:233 views/links/show.phtml:73 msgid "you" msgstr "vous" @@ -1143,7 +1143,7 @@ msgstr "Régler pour le journal" msgid "Copy the link" msgstr "Copier le lien" -#: views/collections/show_public.phtml:165 views/news/index.phtml:52 +#: views/collections/show_public.phtml:165 views/news/index.phtml:68 msgid "Mark all as read" msgstr "Tout marquer comme lu" @@ -2110,15 +2110,19 @@ msgstr "Toujours rien ? Avez-vous vérifié votre spam ?" msgid "Didn’t receive the email? Resend it" msgstr "Courriel non reçu ? Renvoyer" -#: views/news/index.phtml:41 +#: views/news/index.phtml:21 views/read/index.phtml:38 +msgid "Today" +msgstr "Aujourd’hui" + +#: views/news/index.phtml:57 msgid "Empty the news" msgstr "Vider le journal" -#: views/news/index.phtml:62 +#: views/news/index.phtml:78 msgid "Read the links later" msgstr "Lire les liens plus tard" -#: views/news/index.phtml:71 +#: views/news/index.phtml:87 msgid "" "You’ll remove all the news links, this action cannot be canceled. Are you " "sure?" @@ -2126,41 +2130,41 @@ msgstr "" "Vous allez retirer tous les liens du journal, cette action ne peut pas être " "annulée. Confirmez-vous ?" -#: views/news/index.phtml:79 +#: views/news/index.phtml:95 msgid "Never see the links again" msgstr "Ne plus revoir les liens" -#: views/news/index.phtml:87 +#: views/news/index.phtml:103 msgid "" "Fill your news feed with the content published by the feeds that you follow." msgstr "" "Remplissez votre journal avec le contenu publié par les flux que vous suivez." -#: views/news/index.phtml:101 +#: views/news/index.phtml:117 msgid "Refresh the news" msgstr "Rafraichir le journal" -#: views/news/index.phtml:106 +#: views/news/index.phtml:122 msgid "Fill the news with…" msgstr "Remplissez votre journal avec…" -#: views/news/index.phtml:129 +#: views/news/index.phtml:145 msgid "the latest publications" msgstr "les dernières publications" -#: views/news/index.phtml:130 +#: views/news/index.phtml:146 msgid "from your followed feeds" msgstr "depuis vos flux suivis" -#: views/news/index.phtml:145 +#: views/news/index.phtml:161 msgid "3 links of -10 minutes" msgstr "3 liens de -10 minutes" -#: views/news/index.phtml:146 views/news/index.phtml:162 +#: views/news/index.phtml:162 views/news/index.phtml:178 msgid "from your bookmarks" msgstr "depuis vos signets" -#: views/news/index.phtml:161 +#: views/news/index.phtml:177 msgid "1 link of +10 minutes" msgstr "1 lien de +10 minutes" diff --git a/src/controllers/News.php b/src/controllers/News.php index 4ea68765..65ceec2e 100644 --- a/src/controllers/News.php +++ b/src/controllers/News.php @@ -7,6 +7,7 @@ use flusio\auth; use flusio\models; use flusio\services; +use flusio\utils; /** * Handle the requests related to the news. @@ -33,9 +34,12 @@ public function index(): Response } $news = $user->news(); + $links = $news->links(['published_at', 'number_comments']); + $links_timeline = new utils\LinksTimeline($links); + return Response::ok('news/index.phtml', [ 'news' => $news, - 'links' => $news->links(['published_at', 'number_comments']), + 'links_timeline' => $links_timeline, 'no_news' => \Minz\Flash::pop('no_news'), ]); } diff --git a/src/controllers/Read.php b/src/controllers/Read.php index 2432e534..2d0c581d 100644 --- a/src/controllers/Read.php +++ b/src/controllers/Read.php @@ -45,16 +45,19 @@ public function index(Request $request): Response ]); } + $links = $read_list->links( + ['published_at', 'number_comments'], + [ + 'offset' => $pagination->currentOffset(), + 'limit' => $pagination->numberPerPage(), + 'context_user_id' => $user->id, + ] + ); + $links_timeline = new utils\LinksTimeline($links); + return Response::ok('read/index.phtml', [ 'collection' => $read_list, - 'links' => $read_list->links( - ['published_at', 'number_comments'], - [ - 'offset' => $pagination->currentOffset(), - 'limit' => $pagination->numberPerPage(), - 'context_user_id' => $user->id, - ] - ), + 'links_timeline' => $links_timeline, 'pagination' => $pagination, ]); } diff --git a/src/utils/LinksTimeline.php b/src/utils/LinksTimeline.php new file mode 100644 index 00000000..063f10f0 --- /dev/null +++ b/src/utils/LinksTimeline.php @@ -0,0 +1,52 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class LinksTimeline +{ + /** @var array */ + private array $dates_groups = []; + + /** + * @param models\Link[] $links + */ + public function __construct(array $links) + { + foreach ($links as $link) { + if (!$link->published_at) { + continue; + } + + $date_key = $link->published_at->format('Y-m-d'); + if (isset($this->dates_groups[$date_key])) { + $date_group = $this->dates_groups[$date_key]; + } else { + $date_group = new LinksTimeline\DateGroup($link->published_at); + $this->dates_groups[$date_key] = $date_group; + } + + $date_group->links[] = $link; + } + } + + /** + * @return array + */ + public function datesGroups(): array + { + return $this->dates_groups; + } + + public function empty(): bool + { + return empty($this->dates_groups); + } +} diff --git a/src/utils/LinksTimeline/DateGroup.php b/src/utils/LinksTimeline/DateGroup.php new file mode 100644 index 00000000..727dc8d5 --- /dev/null +++ b/src/utils/LinksTimeline/DateGroup.php @@ -0,0 +1,28 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class DateGroup +{ + public \DateTimeImmutable $date; + + /** @var models\Link[] */ + public array $links = []; + + public function __construct(\DateTimeImmutable $date) + { + $this->date = $date; + } + + public function isToday(): bool + { + $today = \Minz\Time::now(); + return $this->date->format('Y-m-d') === $today->format('Y-m-d'); + } +} diff --git a/src/views/news/index.phtml b/src/views/news/index.phtml index 18263d0a..900d30eb 100644 --- a/src/views/news/index.phtml +++ b/src/views/news/index.phtml @@ -12,22 +12,38 @@

- -
- - include('links/_link.phtml', [ - 'link' => $link, - 'from' => \Minz\Url::for('news'), - 'display_edit' => true, - 'display_repair' => true, - 'display_via' => true, - 'display_read_later' => true, - 'display_mark_as_read' => true, - 'display_never' => true, - 'storing_must_mark_as_read' => true, - ]); ?> - -
+empty()): ?> + datesGroups() as $date_group): ?> +
+
+

+ isToday()): ?> + ⋅ + + + date, 'dd MMMM') ?> +

+ +
+
+ +
+ links as $link): ?> + include('links/_link.phtml', [ + 'link' => $link, + 'from' => \Minz\Url::for('news'), + 'display_edit' => true, + 'display_repair' => true, + 'display_via' => true, + 'display_read_later' => true, + 'display_mark_as_read' => true, + 'display_never' => true, + 'storing_must_mark_as_read' => true, + ]); ?> + +
+
+
-
- - include('links/_link.phtml', [ - 'link' => $link, - 'from' => \Minz\Url::for('read list', $current_url_params), - 'display_via' => $link->via_type !== 'bookmarks', - 'display_comments' => true, - 'display_edit' => true, - 'display_repair' => true, - 'display_delete' => true, - 'display_read_later' => 'auto', - 'display_mark_as_unread' => true, - ]); ?> - - - -
- -
+datesGroups() as $date_group): ?> +
+
+

+ isToday()): ?> + ⋅ + + + date, 'dd MMMM') ?> +

+ +
+
+ +
+ links as $link): ?> + include('links/_link.phtml', [ + 'link' => $link, + 'from' => \Minz\Url::for('read list', $current_url_params), + 'display_via' => $link->via_type !== 'bookmarks', + 'display_comments' => true, + 'display_edit' => true, + 'display_repair' => true, + 'display_delete' => true, + 'display_read_later' => 'auto', + 'display_mark_as_unread' => true, + ]); ?> + +
+
+ include('_pagination.phtml', ['pagination' => $pagination, 'url' => url('read list')]) ?> diff --git a/tests/utils/LinksTimelineTest.php b/tests/utils/LinksTimelineTest.php new file mode 100644 index 00000000..28faf348 --- /dev/null +++ b/tests/utils/LinksTimelineTest.php @@ -0,0 +1,55 @@ +published_at = new \DateTimeImmutable('2024-03-20 18:00'); + $link2 = LinkFactory::create(); + $link2->published_at = new \DateTimeImmutable('2024-03-22 12:00'); + $link3 = LinkFactory::create(); + $link3->published_at = new \DateTimeImmutable('2024-03-20 12:00'); + $links = [$link1, $link2, $link3]; + + $timeline = new LinksTimeline($links); + + $this->assertFalse($timeline->empty()); + $dates_groups = $timeline->datesGroups(); + $this->assertSame(2, count($dates_groups)); + $group1 = $dates_groups['2024-03-20']; + $group2 = $dates_groups['2024-03-22']; + $this->assertEquals($link1->published_at, $group1->date); + $this->assertSame(2, count($group1->links)); + $this->assertSame($link1->id, $group1->links[0]->id); + $this->assertSame($link3->id, $group1->links[1]->id); + $this->assertEquals($link2->published_at, $group2->date); + $this->assertSame(1, count($group2->links)); + $this->assertSame($link2->id, $group2->links[0]->id); + } + + public function testEmptyReturnsTrue(): void + { + $links = []; + + $timeline = new LinksTimeline($links); + + $this->assertTrue($timeline->empty()); + } + + public function testConstructIgnoresLinksWithoutPublishedAt(): void + { + $link = LinkFactory::create(); + $links = [$link]; + + $timeline = new LinksTimeline($links); + + $this->assertTrue($timeline->empty()); + } +}