diff --git a/src/Event/NotificationEvent.php b/src/Event/NotificationEvent.php index e743a8c..955461a 100644 --- a/src/Event/NotificationEvent.php +++ b/src/Event/NotificationEvent.php @@ -10,34 +10,151 @@ namespace KevinPapst\TablerBundle\Event; use KevinPapst\TablerBundle\Model\NotificationInterface; +use KevinPapst\TablerBundle\Model\NotificationV2Interface; class NotificationEvent extends ThemeEvent { + private ?string $title = null; + + private ?string $titleEmpty = null; + + private ?string $titleHtml = null; + + private bool $withArrow = true; + + private string $badgeColor = 'red'; + + private bool $showBadgeTotal = true; + + private int $maxDisplay = 10; + /** - * @var array + * @var array */ private array $notifications = []; + public function getTotal(): int + { + return \count($this->getNotifications(null)); + } + + public function isVisible(): bool + { + return $this->getTotal() > 0 || ($this->getTotal() === 0 && $this->showIfEmpty); + } + + public function __construct( + private bool $showIfEmpty = false, + ) { + } + + public function isShowIfEmpty(): bool + { + return $this->showIfEmpty; + } + + public function setShowIfEmpty(bool $showIfEmpty): void + { + $this->showIfEmpty = $showIfEmpty; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(?string $title): void + { + $this->title = $title; + } + + public function getTitleEmpty(): ?string + { + return $this->titleEmpty; + } + + public function setTitleEmpty(?string $titleEmpty): void + { + $this->titleEmpty = $titleEmpty; + } + + public function getTitleHtml(): ?string + { + return $this->titleHtml; + } + + public function setTitleHtml(?string $titleHtml): void + { + $this->titleHtml = $titleHtml; + } + + public function isWithArrow(): bool + { + return $this->withArrow; + } + + public function setWithArrow(bool $withArrow): void + { + $this->withArrow = $withArrow; + } + + public function getBadgeColor(): string + { + return $this->badgeColor; + } + + public function setBadgeColor(string $badgeColor): void + { + $this->badgeColor = $badgeColor; + } + + public function isShowBadgeTotal(): bool + { + return $this->showBadgeTotal; + } + + public function setShowBadgeTotal(bool $showBadgeTotal): void + { + $this->showBadgeTotal = $showBadgeTotal; + } + + public function getMaxDisplay(): int + { + return $this->maxDisplay; + } + + public function setMaxDisplay(int $maxDisplay): void + { + $this->maxDisplay = $maxDisplay; + } + /** - * @param int|null $max - * @return NotificationInterface[] + * @return array */ public function getNotifications(?int $max = 10): array { - if (null !== $max) { - return \array_slice($this->notifications, 0, $max); + if ($max === null) { + return $this->notifications; + } elseif ($max !== 10) { + trigger_deprecation('kevinpapst/tabler-bundle', '1.1.0', 'Setting `$max` parameter is deprecated. Use setMaxDisplay() instead!'); } - return $this->notifications; + return \array_slice($this->notifications, 0, $this->maxDisplay); } - public function addNotification(NotificationInterface $notificationInterface): void + public function addNotification(NotificationV2Interface|NotificationInterface $notification): void { - $this->notifications[] = $notificationInterface; +// if (($notification instanceof NotificationV2Interface) === false) { +// trigger_deprecation('kevinpapst/tabler-bundle', '1.2.0', 'Notification should implement NotificationV2Interface::class!'); +// } + + $this->notifications[] = $notification; } - public function getTotal(): int + public function removeNotification(NotificationInterface $notification): void { - return \count($this->notifications); + if (($key = array_search($notification, $this->notifications)) !== false) { + unset($this->notifications[$key]); + } } } diff --git a/src/Event/NotificationEventInterface.php b/src/Event/NotificationEventInterface.php new file mode 100644 index 0000000..45967ba --- /dev/null +++ b/src/Event/NotificationEventInterface.php @@ -0,0 +1,41 @@ + + */ + public function getNotifications(?int $max = 10): array; +} diff --git a/src/Model/NotificationModel.php b/src/Model/NotificationModel.php index 2b227ac..41b4ab4 100644 --- a/src/Model/NotificationModel.php +++ b/src/Model/NotificationModel.php @@ -11,12 +11,21 @@ use KevinPapst\TablerBundle\Helper\Constants; -class NotificationModel implements NotificationInterface +class NotificationModel implements NotificationV2Interface { private ?string $url = null; + private bool $active = false; + private bool $disabled = false; + private bool $withBadge = true; + private bool $badgeAnimated = true; - public function __construct(private string $id, private string $message, private string $type = Constants::TYPE_INFO) - { + private bool $html = false; + + public function __construct( + private readonly string $id, + private string $message, + private string $type = Constants::TYPE_INFO + ) { } public function getIdentifier(): string @@ -24,14 +33,64 @@ public function getIdentifier(): string return $this->id; } - public function getType(): string + public function getUrl(): ?string { - return $this->type; + return $this->url; } - public function setMessage(string $message): void + public function setUrl(?string $url): void { - $this->message = $message; + $this->url = $url; + } + + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): void + { + $this->active = $active; + } + + public function isDisabled(): bool + { + return $this->disabled; + } + + public function setDisabled(bool $disabled): void + { + $this->disabled = $disabled; + } + + public function isWithBadge(): bool + { + return $this->withBadge; + } + + public function setWithBadge(bool $withBadge): void + { + $this->withBadge = $withBadge; + } + + public function isBadgeAnimated(): bool + { + return $this->badgeAnimated; + } + + public function setBadgeAnimated(bool $badgeAnimated): void + { + $this->badgeAnimated = $badgeAnimated; + } + + public function isHtml(): bool + { + return $this->html; + } + + public function setHtml(bool $html): void + { + $this->html = $html; } public function getMessage(): string @@ -39,13 +98,18 @@ public function getMessage(): string return $this->message; } - public function setUrl(?string $url): void + public function setMessage(string $message): void { - $this->url = $url; + $this->message = $message; } - public function getUrl(): ?string + public function getType(): string { - return $this->url; + return $this->type; + } + + public function setType(string $type): void + { + $this->type = $type; } } diff --git a/src/Model/NotificationV2Interface.php b/src/Model/NotificationV2Interface.php new file mode 100644 index 0000000..3bd8495 --- /dev/null +++ b/src/Model/NotificationV2Interface.php @@ -0,0 +1,28 @@ + $routes * @param array $icons */ - public function __construct(private EventDispatcherInterface $eventDispatcher, private ContextHelper $helper, private array $routes, private array $icons) - { + public function __construct( + private EventDispatcherInterface $eventDispatcher, + private ContextHelper $helper, + private array $routes, + private array $icons + ) { } public function getRouteByAlias(string $routeName): string @@ -68,6 +72,7 @@ public function containerClass(string $class = ''): string /** * @param Request $request + * * @return MenuItemInterface[]|null */ public function getMenu(Request $request): ?array @@ -82,19 +87,15 @@ public function getMenu(Request $request): ?array return $event->getItems(); } - public function getNotifications(): ?NotificationEvent + public function getNotifications(): NotificationEvent { if (!$this->eventDispatcher->hasListeners(NotificationEvent::class)) { - return null; + return new NotificationEvent(false); } /** @var NotificationEvent $listEvent */ $listEvent = $this->eventDispatcher->dispatch(new NotificationEvent()); - if ($listEvent->getTotal() === 0) { - return null; - } - return $listEvent; } diff --git a/templates/includes/navbar_notifications.html.twig b/templates/includes/navbar_notifications.html.twig index 9653bb0..f285fd1 100644 --- a/templates/includes/navbar_notifications.html.twig +++ b/templates/includes/navbar_notifications.html.twig @@ -1,22 +1,79 @@ -{% set notifications = tabler_notifications() %} -{% if notifications is not null %} - {% set total = notifications.total %} - {% set notifications = notifications.notifications %} - -{% endif %} +{# @var notificationEvent \KevinPapst\TablerBundle\Event\NotificationEvent #} +{% set notificationEvent = tabler_notifications() %} + +{% if notificationEvent.visible %} + +{% endif %} diff --git a/tests/Event/NotificationEventTest.php b/tests/Event/NotificationEventTest.php index 93b75ff..60a1e58 100644 --- a/tests/Event/NotificationEventTest.php +++ b/tests/Event/NotificationEventTest.php @@ -28,33 +28,120 @@ public function testDefaults(): void public function testTotalsAndReceiveLimitedSet(): void { $event = new NotificationEvent(); - $notifications = $this->generateNbNotifications(7); + $notifications = $this->generateNbNotifications(); foreach ($notifications as $notification) { $event->addNotification($notification); } - $this->assertEquals(7, $event->getTotal()); - $this->assertEquals(7, \count($event->getNotifications())); - $this->assertEquals(3, \count($event->getNotifications(3))); + $this->assertEquals(\count($notifications), $event->getTotal()); + $this->assertCount(\count($notifications), $event->getNotifications()); + + $event->setMaxDisplay(7); + $this->assertEquals(\count($notifications), $event->getTotal()); + $this->assertCount(7, $event->getNotifications()); + } + + public function testVisible(): void + { + $event = new NotificationEvent(); + // Should be hidden by default + $this->assertFalse($event->isVisible()); + + $event->addNotification(new NotificationModel('visible', 'Message')); + // Even with a single valid item, should be visible + $this->assertTrue($event->isVisible()); + + $event = new NotificationEvent(true); + // Forced to always visible + $this->assertTrue($event->isVisible()); } /** - * Generate an array of nb tasks - * @param int $number - * @param string $type - * @return array|NotificationModel[] + * Generate an array NotificationModel + * + * @return array */ - private function generateNbNotifications($number, $type = Constants::TYPE_INFO): array + private function generateNbNotifications(): array { - $tasks = []; - for ($i = 0; $i < $number; $i++) { - $tasks[] = new NotificationModel( - 'Message ' . $i, - $type - ); - } + $arr = []; + + // 1 + $activeNotification = new NotificationModel('active', 'My active Message', Constants::TYPE_WARNING); + $activeNotification->setActive(true); + $arr[] = $activeNotification; + + // 2 + $defaultNotification = new NotificationModel('default', 'My default Message'); + $arr[] = $defaultNotification; + + // 3 + $disabledNotification = new NotificationModel('disabled', 'My disabled Message'); + $disabledNotification->setDisabled(true); + $disabledNotification->setBadgeAnimated(false); + $arr[] = $disabledNotification; + + // 4 + $customizeNotification = new NotificationModel('customize', 'Link to Google', Constants::TYPE_SUCCESS); + $customizeNotification->setBadgeAnimated(false); + $customizeNotification->setUrl('https://www.google.com'); + $arr[] = $customizeNotification; + + // 5 + $htmlNotification = new NotificationModel('html', ' +
+
+
+
+ Example 1 +
+ Change deprecated html tags to text decoration classes (#29604) +
+
+
+ + + +
+
+
+ '); + $htmlNotification->setHtml(true); + $arr[] = $htmlNotification; + + // 6 + $badgeNotification = new NotificationModel('badge', ' +
  • + Notification with badge + 14 +
  • + '); + $badgeNotification->setHtml(true); + $arr[] = $badgeNotification; + + // 7 + $flexBoxNotification = new NotificationModel('flexbox', ' + +
    +
    List group item heading
    + 3 days ago +
    +

    Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.

    + Donec id elit non mi porta. +
    + '); + $flexBoxNotification->setHtml(true); + $arr[] = $flexBoxNotification; + + // 8 + $moreThanMaxNotification = + new NotificationModel('max', 'Will not be displayed as max notification is set to 7'); + $arr[] = $moreThanMaxNotification; + + // 9 + $extraNotification = new NotificationModel('extra', 'One more not displayed'); + $arr[] = $extraNotification; - return $tasks; + return $arr; } } diff --git a/tests/Model/NotificationModelTest.php b/tests/Model/NotificationModelTest.php index 4a0a7b8..0c959e1 100644 --- a/tests/Model/NotificationModelTest.php +++ b/tests/Model/NotificationModelTest.php @@ -24,11 +24,14 @@ public function testGetIdentifier(): void $this->assertEquals('foo', $sut->getIdentifier()); $this->assertEquals('bar', $sut->getMessage()); $this->assertEquals(Constants::TYPE_INFO, $sut->getType()); + $this->assertNull($sut->getUrl()); $sut->setUrl('https://tabler.io'); $this->assertEquals('https://tabler.io', $sut->getUrl()); + $sut->setUrl(null); $this->assertNull($sut->getUrl()); + $sut->setMessage('hello world'); $this->assertEquals('hello world', $sut->getMessage()); } diff --git a/translations/TablerBundle.de.xlf b/translations/TablerBundle.de.xlf index 6051cb9..d26ee9c 100644 --- a/translations/TablerBundle.de.xlf +++ b/translations/TablerBundle.de.xlf @@ -146,6 +146,18 @@ Next Weiter + + Show notifications + Zeige Benachrichtigungen + + + You have no notification + Es gibt keine Benachrichtigungen + + + And %count% more… + Und %count% weitere… + diff --git a/translations/TablerBundle.en.xlf b/translations/TablerBundle.en.xlf index d24da92..5f4d5ba 100644 --- a/translations/TablerBundle.en.xlf +++ b/translations/TablerBundle.en.xlf @@ -146,6 +146,18 @@ Next Next + + Show notifications + Show notifications + + + You have no notification + You have no notification + + + And %count% more… + And %count% more… + diff --git a/translations/TablerBundle.fr.xlf b/translations/TablerBundle.fr.xlf index 1f5767c..95c038f 100644 --- a/translations/TablerBundle.fr.xlf +++ b/translations/TablerBundle.fr.xlf @@ -146,6 +146,18 @@ or ou + + Show notifications + Afficher notifications + + + You have no notification + Vous avez aucune notification + + + And %count% more… + Et %count% autres… +