diff --git a/locales/fr_FR/LC_MESSAGES/main.mo b/locales/fr_FR/LC_MESSAGES/main.mo index 04afd8ff..c25891d5 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..cca53109 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:41+0100\n" +"PO-Revision-Date: 2024-03-25 15:41+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:70 msgid "Mark all as read" msgstr "Tout marquer comme lu" @@ -2110,15 +2110,23 @@ 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:23 views/read/index.phtml:40 +msgid "today" +msgstr "aujourd’hui" + +#: views/news/index.phtml:25 views/read/index.phtml:42 +msgid "yesterday" +msgstr "hier" + +#: views/news/index.phtml:59 msgid "Empty the news" msgstr "Vider le journal" -#: views/news/index.phtml:62 +#: views/news/index.phtml:80 msgid "Read the links later" msgstr "Lire les liens plus tard" -#: views/news/index.phtml:71 +#: views/news/index.phtml:89 msgid "" "You’ll remove all the news links, this action cannot be canceled. Are you " "sure?" @@ -2126,41 +2134,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:97 msgid "Never see the links again" msgstr "Ne plus revoir les liens" -#: views/news/index.phtml:87 +#: views/news/index.phtml:105 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:119 msgid "Refresh the news" msgstr "Rafraichir le journal" -#: views/news/index.phtml:106 +#: views/news/index.phtml:124 msgid "Fill the news with…" msgstr "Remplissez votre journal avec…" -#: views/news/index.phtml:129 +#: views/news/index.phtml:147 msgid "the latest publications" msgstr "les dernières publications" -#: views/news/index.phtml:130 +#: views/news/index.phtml:148 msgid "from your followed feeds" msgstr "depuis vos flux suivis" -#: views/news/index.phtml:145 +#: views/news/index.phtml:163 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:164 views/news/index.phtml:180 msgid "from your bookmarks" msgstr "depuis vos signets" -#: views/news/index.phtml:161 +#: views/news/index.phtml:179 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..ca4ce0c2 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'), ]); } @@ -70,7 +74,7 @@ public function create(Request $request): Response if (!\Minz\Csrf::validate($csrf)) { return Response::badRequest('news/index.phtml', [ 'news' => $news, - 'links' => [], + 'links_timeline' => new utils\LinksTimeline([]), 'no_news' => false, 'error' => _('A security verification failed: you should retry to submit the form.'), ]); 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..635aca6a --- /dev/null +++ b/src/utils/LinksTimeline/DateGroup.php @@ -0,0 +1,34 @@ + + * @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'); + } + + public function isYesterday(): bool + { + $yesterday = \Minz\Time::ago(1, 'day'); + return $this->date->format('Y-m-d') === $yesterday->format('Y-m-d'); + } +} diff --git a/src/views/news/index.phtml b/src/views/news/index.phtml index 18263d0a..650fcba2 100644 --- a/src/views/news/index.phtml +++ b/src/views/news/index.phtml @@ -12,22 +12,40 @@

- -
- - 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): ?> +
+
+

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

+ +
+
+ +
+ 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): ?> +
+
+

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

+ +
+
+ +
+ 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()); + } +}