From 405f0346b3d9df033915bdbfe7f1a4a0f9fb4552 Mon Sep 17 00:00:00 2001 From: Grzegorz Sadowski Date: Thu, 21 May 2026 06:23:24 +0200 Subject: [PATCH 1/2] [Admin] Support clickable navbar notifications with translation parameters --- .../NotificationProviderInterface.php | 12 ++++++++++++ .../twig_hooks/common/component/navbar.yaml | 5 +++++ .../components/navbar/notifications.html.twig | 13 +------------ .../navbar/notifications/item.html.twig | 17 +++++++++++++++++ .../Navbar/NotificationsComponentTest.php | 19 +++++++++++++++++++ 5 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig diff --git a/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php b/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php index 28d8cf3768..e5972d4115 100644 --- a/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php +++ b/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php @@ -16,6 +16,18 @@ namespace Sylius\Bundle\AdminBundle\Notification; interface NotificationProviderInterface { /** + * Each notification is identified by a string key. The value is a map with the following keys honored by the + * default admin navbar notifications template: + * + * - `message` (string, required): translation key passed to the `trans` filter. + * - `message_parameters` (array, optional): parameters passed to the `trans` filter. + * - `route` (string, optional): when present, the notification renders as a link to this route. + * - `route_parameters` (array, optional): parameters passed to `path()` together with `route`. + * - `translation_domain` (string, optional): translation domain passed to the `trans` filter. + * - `type` (string, optional): one of `info`, `warning`, `danger`. Defaults to `danger`. + * + * Providers MAY include additional keys for their own purposes; the default template ignores them. + * * @param array $context * * @return array diff --git a/src/Sylius/Bundle/AdminBundle/Resources/config/app/twig_hooks/common/component/navbar.yaml b/src/Sylius/Bundle/AdminBundle/Resources/config/app/twig_hooks/common/component/navbar.yaml index dcba3a7842..d101e98acd 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/config/app/twig_hooks/common/component/navbar.yaml +++ b/src/Sylius/Bundle/AdminBundle/Resources/config/app/twig_hooks/common/component/navbar.yaml @@ -27,3 +27,8 @@ sylius_twig_hooks: search: template: '@SyliusAdmin/shared/crud/common/navbar/menu/search.html.twig' priority: 0 + + 'sylius_admin.common.component.navbar.items.notifications.item': + default: + template: '@SyliusAdmin/shared/components/navbar/notifications/item.html.twig' + priority: 0 diff --git a/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications.html.twig b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications.html.twig index 6aa44b5bb0..3ff7e8c90e 100644 --- a/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications.html.twig +++ b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications.html.twig @@ -25,18 +25,7 @@ {% else %}
{% for notification in notifications %} -
-
-
- -
-
-
- {{ notification.message|trans }} -
-
-
-
+ {% hook 'notifications.item' with { notification } %} {% endfor %}
{% endif %} diff --git a/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig new file mode 100644 index 0000000000..f31d8a1567 --- /dev/null +++ b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig @@ -0,0 +1,17 @@ +{% set notification = hookable_metadata.context.notification %} +{% set has_route = notification.route is defined and notification.route %} +{% set type = notification.type|default('danger') %} +{% set tag = has_route ? 'a' : 'div' %} + +<{{ tag }} class="list-group-item{% if has_route %} list-group-item-action{% endif %}"{% if has_route %} href="{{ path(notification.route, notification.route_parameters|default({})) }}"{% endif %}> +
+
+ +
+
+
+ {{ notification.message|trans(notification.message_parameters|default({}), notification.translation_domain|default(null)) }} +
+
+
+ diff --git a/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php b/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php index 1b916c0d72..414fc10da2 100644 --- a/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php +++ b/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php @@ -48,4 +48,23 @@ final class NotificationsComponentTest extends TestCase 'message' => 'sylius.ui.notifications.new_version_of_sylius_available', ]); } + + #[Test] + public function it_propagates_optional_notification_fields_unchanged(): void + { + $notification = [ + 'message' => 'app.notification.legacy_secret_key', + 'message_parameters' => ['%gateway_name%' => 'Stripe EU'], + 'route' => 'sylius_admin_payment_method_update', + 'route_parameters' => ['id' => 42], + 'translation_domain' => 'messages', + 'type' => 'warning', + ]; + + $this->notificationProvider->method('getNotifications')->willReturn(['legacy_secret_key.42' => $notification]); + + $notifications = $this->notificationsComponent->getNotifications(); + + $this->assertSame($notification, $notifications['legacy_secret_key.42']); + } } From d42ea9117e4c3ffdd569a390844390e63e6141f5 Mon Sep 17 00:00:00 2001 From: Grzegorz Sadowski Date: Thu, 21 May 2026 12:50:12 +0200 Subject: [PATCH 2/2] [Admin] Support plain URIs in navbar notifications and refine item template --- .../NotificationProviderInterface.php | 3 ++- .../navbar/notifications/item.html.twig | 19 +++++++++++++++---- .../Navbar/NotificationsComponentTest.php | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php b/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php index e5972d4115..e24e20fc26 100644 --- a/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php +++ b/src/Sylius/Bundle/AdminBundle/Notification/NotificationProviderInterface.php @@ -21,7 +21,8 @@ interface NotificationProviderInterface * * - `message` (string, required): translation key passed to the `trans` filter. * - `message_parameters` (array, optional): parameters passed to the `trans` filter. - * - `route` (string, optional): when present, the notification renders as a link to this route. + * - `uri` (string, optional): plain URI used as the notification link. Takes precedence over `route` when both are present. + * - `route` (string, optional): when present (and `uri` is not), the notification renders as a link to this route. * - `route_parameters` (array, optional): parameters passed to `path()` together with `route`. * - `translation_domain` (string, optional): translation domain passed to the `trans` filter. * - `type` (string, optional): one of `info`, `warning`, `danger`. Defaults to `danger`. diff --git a/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig index f31d8a1567..a62e29c1d6 100644 --- a/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig +++ b/src/Sylius/Bundle/AdminBundle/templates/shared/components/navbar/notifications/item.html.twig @@ -1,9 +1,20 @@ {% set notification = hookable_metadata.context.notification %} -{% set has_route = notification.route is defined and notification.route %} {% set type = notification.type|default('danger') %} -{% set tag = has_route ? 'a' : 'div' %} -<{{ tag }} class="list-group-item{% if has_route %} list-group-item-action{% endif %}"{% if has_route %} href="{{ path(notification.route, notification.route_parameters|default({})) }}"{% endif %}> +{% set href = null %} +{% if notification.uri is defined and notification.uri %} + {% set href = notification.uri %} +{% elseif notification.route is defined and notification.route %} + {% set href = path(notification.route, notification.route_parameters|default({})) %} +{% endif %} + +{% set has_link = href is not null %} +{% set element = has_link ? 'a' : 'div' %} + +<{{ element }} + class="list-group-item{% if has_link %} list-group-item-action{% endif %}" + {% if has_link %}href="{{ href }}"{% endif %} +>
@@ -14,4 +25,4 @@
- + diff --git a/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php b/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php index 414fc10da2..98d0557c92 100644 --- a/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php +++ b/src/Sylius/Bundle/AdminBundle/tests/Twig/Component/Shared/Navbar/NotificationsComponentTest.php @@ -55,6 +55,7 @@ final class NotificationsComponentTest extends TestCase $notification = [ 'message' => 'app.notification.legacy_secret_key', 'message_parameters' => ['%gateway_name%' => 'Stripe EU'], + 'uri' => 'https://dashboard.stripe.com/apikeys', 'route' => 'sylius_admin_payment_method_update', 'route_parameters' => ['id' => 42], 'translation_domain' => 'messages',