notification: add comment in show and append comment

This commit is contained in:
Julien Fastré 2021-12-28 23:25:12 +01:00
parent 9647785d8b
commit cb88a37885
5 changed files with 113 additions and 7 deletions

View File

@ -12,7 +12,9 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller; namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\NotificationComment;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\NotificationCommentType;
use Chill\MainBundle\Form\NotificationType; use Chill\MainBundle\Form\NotificationType;
use Chill\MainBundle\Notification\Exception\NotificationHandlerNotFound; use Chill\MainBundle\Notification\Exception\NotificationHandlerNotFound;
use Chill\MainBundle\Notification\NotificationHandlerManager; use Chill\MainBundle\Notification\NotificationHandlerManager;
@ -177,11 +179,28 @@ class NotificationController extends AbstractController
{ {
$this->denyAccessUnlessGranted(NotificationVoter::SEE, $notification); $this->denyAccessUnlessGranted(NotificationVoter::SEE, $notification);
$notification->addComment($appendComment = new NotificationComment());
$appendCommentForm = $this->createForm(NotificationCommentType::class, $appendComment);
$appendCommentForm->handleRequest($request);
if ($appendCommentForm->isSubmitted() && $appendCommentForm->isValid()) {
$this->em->persist($appendComment);
$this->em->flush();
$this->addFlash('success', $this->translator->trans('notification.comment_appended'));
return $this->redirectToRoute('chill_main_notification_show', [
'id' => $notification->getId(),
]);
}
$response = $this->render('@ChillMain/Notification/show.html.twig', [ $response = $this->render('@ChillMain/Notification/show.html.twig', [
'notification' => $notification, 'notification' => $notification,
'handler' => $this->notificationHandlerManager->getHandler($notification), 'handler' => $this->notificationHandlerManager->getHandler($notification),
'appendCommentForm' => $appendCommentForm->createView(),
]); ]);
// we mark the notification as read after having computed the response
if ($this->getUser() instanceof User && !$notification->isReadBy($this->getUser())) { if ($this->getUser() instanceof User && !$notification->isReadBy($this->getUser())) {
$notification->markAsReadBy($this->getUser()); $notification->markAsReadBy($this->getUser());
$this->em->flush(); $this->em->flush();

View File

@ -68,6 +68,16 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac
return $this->content; return $this->content;
} }
public function getCreatedAt(): ?DateTimeImmutable
{
return $this->createdAt;
}
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
@ -83,6 +93,11 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac
return $this->updateAt; return $this->updateAt;
} }
public function getUpdatedBy(): ?User
{
return $this->updatedBy;
}
public function setContent(string $content): self public function setContent(string $content): self
{ {
$this->content = $content; $this->content = $content;

View File

@ -0,0 +1,26 @@
<?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\Form;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class NotificationCommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('content', ChillTextareaType::class, [
'required' => false,
]);
}
}

View File

@ -16,6 +16,37 @@
{{ notification.message|chill_markdown_to_html }} {{ notification.message|chill_markdown_to_html }}
</div> </div>
{% if notification.comments|length > 0 %}
{% for comment in notification.comments %}
<div>
<blockquote class="chill-user-quote">
{{ comment.content|chill_markdown_to_html }}
</blockquote>
{% if is_granted('CHILL_MAIN_NOTIFICATION_COMMENT_EDIT', comment) %}
<ul class="record_actions">
<li>
<a href="#" class="btn btn-edit"></a>
</li>
</ul>
{% endif %}
</div>
{% endfor %}
{% endif %}
{% if appendCommentForm is defined %}
<div>
{{ form_start(appendCommentForm) }}
{{ form_widget(appendCommentForm) }}
<ul class="record_actions">
<li>
<button type="submit" class="btn btn-save">{{ 'notification.append_comment'|trans }}</button>
</li>
</ul>
{{ form_end(appendCommentForm) }}
</div>
{% endif %}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">
<li class="cancel"> <li class="cancel">
<a href="{{ chill_return_path_or('chill_main_notification_my') }}" class="btn btn-cancel"> <a href="{{ chill_return_path_or('chill_main_notification_my') }}" class="btn btn-cancel">

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Security\Authorization; namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\NotificationComment;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
@ -19,18 +20,20 @@ use UnexpectedValueException;
final class NotificationVoter extends Voter final class NotificationVoter extends Voter
{ {
public const COMMENT_EDIT = 'CHILL_MAIN_NOTIFICATION_COMMENT_EDIT';
public const SEE = 'chill_main_notification_see'; public const SEE = 'chill_main_notification_see';
public const UPDATE = 'chill_main_notification_update'; public const UPDATE = 'chill_main_notification_update';
protected function supports($attribute, $subject): bool protected function supports($attribute, $subject): bool
{ {
return $subject instanceof Notification; return $subject instanceof Notification || $subject instanceof NotificationComment;
} }
/** /**
* @param string $attribute * @param string $attribute
* @param Notification $subject * @param mixed $subject
*/ */
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{ {
@ -40,12 +43,24 @@ final class NotificationVoter extends Voter
return false; return false;
} }
switch ($attribute) { if ($subject instanceof Notification) {
case self::SEE: switch ($attribute) {
return $subject->getSender() === $user || $subject->getAddressees()->contains($user); case self::SEE:
return $subject->getSender() === $user || $subject->getAddressees()->contains($user);
default: default:
throw new UnexpectedValueException("this subject {$subject} is not implemented"); throw new UnexpectedValueException("this subject {$attribute} is not implemented");
}
} elseif ($subject instanceof NotificationComment) {
switch ($attribute) {
case self::COMMENT_EDIT:
return $subject->getCreatedBy() === $user;
default:
throw new UnexpectedValueException("this subject {$attribute} is not implemented");
}
} }
throw new UnexpectedValueException();
} }
} }