Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UserNotification] Add more configuration options #176

Merged
merged 17 commits into from
Dec 12, 2023
33 changes: 24 additions & 9 deletions src/Event/NotificationEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,37 @@

class NotificationEvent extends ThemeEvent
{
/**
* @var array<NotificationInterface>
*/
public ?string $title = null;
cavasinf marked this conversation as resolved.
Show resolved Hide resolved

public ?string $emptyTitle = null;

public bool $withArrow = true;

public string $badgeColor = 'red';

public bool $showBadgeTotal = true;

private array $notifications = [];

public int $maxDisplay = 10;

/**
* @param int|null $max
* @return NotificationInterface[]
* @return array<int,NotificationInterface>
*/
public function getNotifications(?int $max = 10): array
{
if (null !== $max) {
return \array_slice($this->notifications, 0, $max);
$notifications = array_filter(
$this->notifications,
fn(NotificationInterface $notification) => $notification->isValid()
kevinpapst marked this conversation as resolved.
Show resolved Hide resolved
);

if ($max === null) {
return $notifications;
} elseif ($max !== 10) {
trigger_deprecation('kevinpapst/tabler-bundle', '1.1.0', 'Using $max is this function is deprecated. Set $maxDisplay inside the event instead!');
}

return $this->notifications;
return \array_slice($notifications, 0, $this->maxDisplay);
}

public function addNotification(NotificationInterface $notificationInterface): void
Expand All @@ -38,6 +53,6 @@ public function addNotification(NotificationInterface $notificationInterface): v

public function getTotal(): int
{
return \count($this->notifications);
return \count($this->getNotifications(null));
}
}
54 changes: 33 additions & 21 deletions src/Model/NotificationInterface.php
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
<?php

/*
* This file is part of the Tabler bundle, created by Kevin Papst (www.kevinpapst.de).
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace KevinPapst\TablerBundle\Model;

interface NotificationInterface
{
public function getIdentifier(): string;

public function getMessage(): string;

public function getType(): string;

public function getUrl(): ?string;
}
<?php

/*
* This file is part of the Tabler bundle, created by Kevin Papst (www.kevinpapst.de).
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace KevinPapst\TablerBundle\Model;

interface NotificationInterface
{
kevinpapst marked this conversation as resolved.
Show resolved Hide resolved
public function isValid(): bool;

public function getIdentifier(): string;

public function getMessage(): ?string;

public function getType(): ?string;

public function getUrl(): ?string;

public function isActive(): bool;

public function isDisabled(): bool;

public function isWithBadge(): bool;

public function isBadgeAnimated(): bool;

public function getHtml(): ?string;
}
112 changes: 103 additions & 9 deletions src/Model/NotificationModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,133 @@

class NotificationModel implements NotificationInterface
{
private ?string $url = null;
private string $id;

public function __construct(private string $id, private string $message, private string $type = Constants::TYPE_INFO)
// Simple link
private ?string $message = null;
private ?string $type = null;
private ?string $url = null;
private bool $active = false;
private bool $disabled = false;
private bool $withBadge = true;
private bool $badgeAnimated = true;

// Custom HTML
private ?string $html = null;

public function isValid(): bool
{
return $this->message || $this->html;
}

public function __construct(
string $id,
cavasinf marked this conversation as resolved.
Show resolved Hide resolved
?string $message = null,
?string $type = Constants::TYPE_INFO
) {
$this->id = $id;
$this->message = $message;
$this->type = $type;
}

public function getIdentifier(): string
{
return $this->id;
}

public function getType(): string
public function getMessage(): ?string
{
return $this->type;
return $this->message;
}

public function setMessage(string $message): void
public function setMessage(?string $message): self
{
$this->message = $message;

return $this;
cavasinf marked this conversation as resolved.
Show resolved Hide resolved
}

public function getMessage(): string
public function getType(): ?string
{
return $this->message;
return $this->type;
}

public function setUrl(?string $url): void
public function setType(?string $type): self
{
$this->url = $url;
$this->type = $type;

return $this;
}

public function getUrl(): ?string
{
return $this->url;
}

public function setUrl(?string $url): self
{
$this->url = $url;

return $this;
}

public function isActive(): bool
{
return $this->active;
}

public function setActive(bool $active): self
{
$this->active = $active;

return $this;
}

public function isDisabled(): bool
{
return $this->disabled;
}

public function setDisabled(bool $disabled): self
{
$this->disabled = $disabled;

return $this;
}

public function isWithBadge(): bool
{
return $this->withBadge;
}

public function setWithBadge(bool $withBadge): self
{
$this->withBadge = $withBadge;

return $this;
}

public function isBadgeAnimated(): bool
{
return $this->badgeAnimated;
}

public function setBadgeAnimated(bool $badgeAnimated): self
{
$this->badgeAnimated = $badgeAnimated;

return $this;
}

public function getHtml(): ?string
{
return $this->html;
}

public function setHtml(?string $html): self
{
$this->html = $html;

return $this;
}
}
4 changes: 0 additions & 4 deletions src/Twig/RuntimeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ public function getNotifications(): ?NotificationEvent
/** @var NotificationEvent $listEvent */
$listEvent = $this->eventDispatcher->dispatch(new NotificationEvent());

if ($listEvent->getTotal() === 0) {
return null;
}

return $listEvent;
}

Expand Down
90 changes: 68 additions & 22 deletions templates/includes/navbar_notifications.html.twig
Original file line number Diff line number Diff line change
@@ -1,22 +1,68 @@
{% set notifications = tabler_notifications() %}
{% if notifications is not null %}
{% set total = notifications.total %}
{% set notifications = notifications.notifications %}
<div class="nav-item dropdown d-none d-md-flex me-3">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="{{ 'You have %count% notifications'|trans({'%count%': total}, 'TablerBundle') }}">
<i class="icon far fa-bell"></i>
<span class="badge bg-red"></span>
</a>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-card">
<div class="card">
<div class="card-header text-nowrap">{{ 'You have %count% notifications'|trans({'%count%': total}, 'TablerBundle') }}</div>
{% for notice in notifications|slice(0, 9) %}
<a class="dropdown-item" href="{% if notice.url is null %}#{% else %}{{ notice.url }}{% endif %}">
<span class="badge bg-{{ notice.type }} me-1"></span>
{{ notice.message }}
</a>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{# @var notificationEvent \KevinPapst\TablerBundle\Event\NotificationEvent #}
{% set notificationEvent = tabler_notifications() %}

{% if notificationEvent %}
<div class="nav-item dropdown d-none d-md-flex me-3">
cavasinf marked this conversation as resolved.
Show resolved Hide resolved
{# Notification Icon #}
<a class="nav-link px-0" href="#"
data-bs-toggle="dropdown" tabindex="-1"
aria-label="{{ 'Show notifications'|trans({}, 'TablerBundle') }}"
>
<i class="icon far fa-bell"></i>
{% if notificationEvent.total > 0 -%}
<span class="badge bg-{{ notificationEvent.badgeColor }}">
{%- if notificationEvent.showBadgeTotal -%}
{{ notificationEvent.total }}
{%- endif -%}
</span>
{%- endif %}
</a>

<div class="dropdown-menu {% if notificationEvent.withArrow %}dropdown-menu-arrow{% endif %} dropdown-menu-end dropdown-menu-card">
<div class="card">
{# Header #}
<div class="card-header">
<div class="card-title text-truncate">
{% if notificationEvent.total > 0 %}
{{ notificationEvent.title ?? 'You have %count% notifications'|trans({'%count%': notificationEvent.total}, 'TablerBundle') }}
{% else %}
{{ notificationEvent.emptyTitle ?? 'You have no notification'|trans({}, 'TablerBundle') }}
{% endif %}
</div>
</div>

{# Notifications #}
{% if notificationEvent.total > 0 %}
<div class="list-group list-group-flush list-group-hoverable">
{% for notification in notificationEvent.notifications %}
{% if notification.valid %}
{% if notification.html is not null %}
{{ notification.html | raw }}
{% else %}
<div class="list-group-item {% if notification.active %}active{% endif %} {% if notification.disabled %}disabled{% endif %}">
<div class="row align-items-center">
{% if notification.withBadge %}
<div class='col-auto'>
<div class="col-auto">
<span class="status-dot {% if notification.badgeAnimated %}status-dot-animated{% endif %} {% if notification.type is not null %}bg-{{ notification.type }}{% endif %} d-block"></span>
</div>
</div>
{% endif %}
<div class="col text-truncate">
<a class='text-muted text-truncate'
href="{{ notification.url ?? '#' }}">{{ notification.message }}</a>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% if notificationEvent.total > notificationEvent.maxDisplay %}
<li class="list-group-item disabled">{{ 'And %count% more...' | trans({'%count%' : notificationEvent.total - notificationEvent.maxDisplay}, 'TablerBundle') }}</li>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
{% endif %}
12 changes: 12 additions & 0 deletions translations/TablerBundle.en.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,18 @@
<source>Next</source>
<target>Next</target>
</trans-unit>
<trans-unit id="465zeJ" resname="Show notifications">
<source>Show notifications</source>
<target>Show notifications</target>
</trans-unit>
<trans-unit id="F5Dfzd" resname="You have no notification">
<source>You have no notification</source>
<target>You have no notification</target>
</trans-unit>
<trans-unit id="Pf48Zd" resname="And %count% more...">
<source>And %count% more...</source>
<target>And %count% more...</target>
</trans-unit>
</body>
</file>
</xliff>
12 changes: 12 additions & 0 deletions translations/TablerBundle.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,18 @@
<source>or</source>
<target state="translated">ou</target>
</trans-unit>
<trans-unit id="465zeJ" resname="Show notifications">
<source>Show notifications</source>
<target>Afficher notifications</target>
</trans-unit>
<trans-unit id="F5Dfzd" resname="You have no notification">
<source>You have no notification</source>
<target>Vous avez aucune notification</target>
</trans-unit>
<trans-unit id="Pf48Zd" resname="And %count% more...">
<source>And %count% more...</source>
<target>Et %count% autres...</target>
cavasinf marked this conversation as resolved.
Show resolved Hide resolved
</trans-unit>
</body>
</file>
</xliff>
Loading