notification: add show action

This commit is contained in:
Julien Fastré 2021-12-28 22:35:15 +01:00
parent f453dbb543
commit 1ad6a958e2
5 changed files with 133 additions and 13 deletions

View File

@ -18,6 +18,7 @@ use Chill\MainBundle\Notification\Exception\NotificationHandlerNotFound;
use Chill\MainBundle\Notification\NotificationHandlerManager;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\NotificationRepository;
use Chill\MainBundle\Security\Authorization\NotificationVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -169,6 +170,26 @@ class NotificationController extends AbstractController
]);
}
/**
* @Route("/{id}/show", name="chill_main_notification_show")
*/
public function showAction(Notification $notification, Request $request): Response
{
$this->denyAccessUnlessGranted(NotificationVoter::SEE, $notification);
$response = $this->render('@ChillMain/Notification/show.html.twig', [
'notification' => $notification,
'handler' => $this->notificationHandlerManager->getHandler($notification),
]);
if ($this->getUser() instanceof User && !$notification->isReadBy($this->getUser())) {
$notification->markAsReadBy($this->getUser());
$this->em->flush();
}
return $response;
}
private function countUnread(): array
{
return [

View File

@ -12,9 +12,11 @@
<li class="nav-item">
<a class="nav-link {% if step == 'inbox' %}active{% endif %}" href="{{ path('chill_main_notification_my') }}">
{{ 'notification.Notifications received'|trans }}
{% if unreads['inbox'] > 0 %}
<span class="badge rounded-pill bg-danger">
{{ unreads['inbox'] }}
</span>
{% endif %}
</a>
</li>
<li class="nav-item">
@ -39,19 +41,35 @@
<div class="flex-table">
{% for data in datas %}
{% set notification = data.notification %}
<div class="item-row">
{% include data.template with data.template_data %}
</div>
<div class="item-row separator">
{% if step == 'inbox' %}
<div>{{ 'notification.from'|trans }}: {{ notification.sender|chill_entity_render_string }}</div>
{% endif %}
<div>{{ 'notification.adressees'|trans }}{% for a in notification.addressees %}{{ a|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}</div>
<div>{{ notification.date|format_datetime('long', 'short') }}</div>
<div>
<blockquote class="chill-user-quote">
{{ notification.message|u.truncate(250, '…', false)|chill_markdown_to_html }}
</blockquote>
<div class="item-bloc {% if not notification.isReadBy(app.user) %}unread{% else %}read{% endif %}">
<div class="item-row">
<div>
{% if step == 'inbox' %}
{{ 'notification.from'|trans }}: {{ notification.sender|chill_entity_render_string }}
{% endif %}
{% if not notification.isReadBy(app.user) %}
<div class="badge bg-danger">{{ 'notification.is_unread'|trans }}</div>
{% endif %}
</div>
<div>{{ 'notification.adressees'|trans }}{% for a in notification.addressees %}{{ a|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}</div>
<div>{{ notification.date|format_datetime('long', 'short') }}</div>
</div>
<div class="item-row">
<div>
<blockquote class="chill-user-quote">
{{ notification.message|u.truncate(250, '…', false)|chill_markdown_to_html }}
</blockquote>
</div>
</div>
<div class="item-row">
{% include data.template with data.template_data %}
</div>
<div class="item-row">
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}) }}" class="btn btn-show"></a>
</li>
</ul>
</div>
</div>
{% endfor %}

View File

@ -0,0 +1,28 @@
{% extends "@ChillMain/layout.html.twig" %}
{% block title 'notification.show notification from %sender%'|trans({ '%sender%': notification.sender|chill_entity_render_string }) %}
{% block content %}
<div class="row">
<div class="col-md-10">
<h1>{{ 'notification.Notification'|trans }}</h1>
<div>
{% include handler.getTemplate(notification) with handler.getTemplateData(notification) %}
</div>
<div>
{# à remplacer par un commentEmbeddable #}
{{ notification.message|chill_markdown_to_html }}
</div>
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a href="{{ chill_return_path_or('chill_main_notification_my') }}" class="btn btn-cancel">
{{ 'Cancel'|trans|chill_return_path_label }}
</a>
</li>
</ul>
</div>
</div>
{% endblock content %}

View File

@ -0,0 +1,51 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use UnexpectedValueException;
final class NotificationVoter extends Voter
{
public const SEE = 'chill_main_notification_see';
public const UPDATE = 'chill_main_notification_update';
protected function supports($attribute, $subject): bool
{
return $subject instanceof Notification;
}
/**
* @param string $attribute
* @param Notification $subject
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
switch ($attribute) {
case self::SEE:
return $subject->getSender() === $user || $subject->getAddressees()->contains($user);
default:
throw new UnexpectedValueException("this subject {$subject} is not implemented");
}
}
}

View File

@ -24,6 +24,8 @@ services:
Chill\MainBundle\Security\Authorization\DefaultVoterHelperFactory: ~
Chill\MainBundle\Security\Authorization\NotificationVoter: ~
Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface: '@Chill\MainBundle\Security\Authorization\DefaultVoterHelperFactory'
chill.main.security.authorization.helper: