mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'notification/improve' into 'master'
Improve notifications See merge request Chill-Projet/chill-bundles!294
This commit is contained in:
commit
2b47868d88
@ -12,6 +12,12 @@ and this project adheres to
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
|
||||
* [notification: formulaire création] descend la box avec la description dans le bas du formulaire
|
||||
* [notification for activity]: fix link to activity
|
||||
* [notification] add "URGENT" before accompanying course with emergency = true
|
||||
* [notification] add a "read more" button on system notification
|
||||
* [notification] add `[Chill]` in the subject of each notification, automatically
|
||||
* [notification] add a counter for notification in activity list and accompanying period list, and search results
|
||||
* [parcours] bugfix if deathdate is not defined (eg. for a thirdparty) parcours is still displayed. Gave error before.
|
||||
|
||||
## Test releases
|
||||
|
@ -31,6 +31,7 @@ use DateTime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
@ -38,8 +39,8 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use function array_key_exists;
|
||||
|
||||
final class ActivityController extends AbstractController
|
||||
@ -471,20 +472,21 @@ final class ActivityController extends AbstractController
|
||||
|
||||
public function showAction(Request $request, int $id): Response
|
||||
{
|
||||
$view = null;
|
||||
$entity = $this->activityRepository->find($id);
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
if (null === $entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
}
|
||||
|
||||
$accompanyingPeriod = $entity->getAccompanyingPeriod();
|
||||
$person = $entity->getPerson();
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
|
||||
} elseif ($person instanceof Person) {
|
||||
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
|
||||
}
|
||||
|
||||
$entity = $this->activityRepository->find($id);
|
||||
|
||||
if (null === $entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
} else {
|
||||
throw new RuntimeException('the activity should be linked with a period or person');
|
||||
}
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
@ -493,8 +495,7 @@ final class ActivityController extends AbstractController
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
}
|
||||
|
||||
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $entity);
|
||||
|
||||
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
{% macro recordAction(activity, context = null, person_id = null, accompanying_course_id = null) %}
|
||||
{% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %}
|
||||
{% if no_action is not defined or no_action == false %}
|
||||
{% set notif_counter = chill_count_notifications('Chill\\ActivityBundle\\Entity\\Activity', activity.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<li>{{ chill_counter_notifications('Chill\\ActivityBundle\\Entity\\Activity', activity.id) }}</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a class="btn btn-notify" href="{{ chill_path_add_return_path('chill_main_notification_create', {
|
||||
'entityClass': 'Chill\\ActivityBundle\\Entity\\Activity',
|
||||
@ -54,6 +59,7 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
<div class="context-{{ context }}">
|
||||
|
@ -168,6 +168,7 @@ class ChillMainExtension extends Extension implements
|
||||
$loader->load('services/timeline.yaml');
|
||||
$loader->load('services/search.yaml');
|
||||
$loader->load('services/serializer.yaml');
|
||||
$loader->load('services/mailer.yaml');
|
||||
|
||||
$this->configureCruds($container, $config['cruds'], $config['apis'], $loader);
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(
|
||||
* name="chill_main_notification",
|
||||
* indexes={
|
||||
* @ORM\Index(name="chill_main_notification_related_entity_idx", columns={"relatedentityclass", "relatedentityid"})
|
||||
* }
|
||||
* )
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@ class NotificationMailer
|
||||
$email = new TemplatedEmail();
|
||||
$email
|
||||
->to($dest->getEmail())
|
||||
->subject('Re: [Chill] ' . $comment->getNotification()->getTitle())
|
||||
->subject('Re: ' . $comment->getNotification()->getTitle())
|
||||
->textTemplate('@ChillMain/Notification/email_notification_comment_persist.fr.md.twig')
|
||||
->context([
|
||||
'comment' => $comment,
|
||||
@ -79,11 +79,13 @@ class NotificationMailer
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($notification->isSystem()) {
|
||||
$email = new Email();
|
||||
$email
|
||||
->text($notification->getMessage())
|
||||
->subject('[Chill] ' . $notification->getTitle());
|
||||
->subject($notification->getTitle());
|
||||
|
||||
if ($notification->isSystem()) {
|
||||
$email
|
||||
->text($notification->getMessage());
|
||||
} else {
|
||||
$email = new TemplatedEmail();
|
||||
$email
|
||||
|
@ -15,12 +15,15 @@ use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Repository\NotificationRepository;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use function array_key_exists;
|
||||
|
||||
/**
|
||||
* Helps to find if a notification exist for a given entity.
|
||||
*/
|
||||
class NotificationPresence
|
||||
{
|
||||
private array $cache = [];
|
||||
|
||||
private NotificationRepository $notificationRepository;
|
||||
|
||||
private Security $security;
|
||||
@ -31,6 +34,29 @@ class NotificationPresence
|
||||
$this->notificationRepository = $notificationRepository;
|
||||
}
|
||||
|
||||
public function countNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
|
||||
{
|
||||
if (array_key_exists($relatedEntityClass, $this->cache) && array_key_exists($relatedEntityId, $this->cache[$relatedEntityClass])) {
|
||||
return $this->cache[$relatedEntityClass][$relatedEntityId];
|
||||
}
|
||||
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if ($user instanceof User) {
|
||||
$counter = $this->notificationRepository->countNotificationByRelatedEntityAndUserAssociated(
|
||||
$relatedEntityClass,
|
||||
$relatedEntityId,
|
||||
$user
|
||||
);
|
||||
|
||||
$this->cache[$relatedEntityClass][$relatedEntityId] = $counter;
|
||||
|
||||
return $counter;
|
||||
}
|
||||
|
||||
return ['unread' => 0, 'read' => 0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Notification[]
|
||||
*/
|
||||
|
@ -23,6 +23,13 @@ class NotificationTwigExtension extends AbstractExtension
|
||||
'needs_environment' => true,
|
||||
'is_safe' => ['html'],
|
||||
]),
|
||||
new TwigFunction('chill_count_notifications', [NotificationTwigExtensionRuntime::class, 'countNotificationsFor'], [
|
||||
'is_safe' => [],
|
||||
]),
|
||||
new TwigFunction('chill_counter_notifications', [NotificationTwigExtensionRuntime::class, 'counterNotificationFor'], [
|
||||
'needs_environment' => true,
|
||||
'is_safe' => ['html'],
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,21 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
|
||||
$this->notificationPresence = $notificationPresence;
|
||||
}
|
||||
|
||||
public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
|
||||
{
|
||||
return $environment->render(
|
||||
'@ChillMain/Notification/extension_counter_notifications_for.html.twig',
|
||||
[
|
||||
'counter' => $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function countNotificationsFor(string $relatedEntityClass, int $relatedEntityId, array $options = []): array
|
||||
{
|
||||
return $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
|
||||
}
|
||||
|
||||
public function listNotificationsFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
|
||||
{
|
||||
$notifications = $this->notificationPresence->getNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
|
||||
|
@ -13,6 +13,7 @@ namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\DBAL\Statement;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
@ -24,6 +25,8 @@ final class NotificationRepository implements ObjectRepository
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private ?Statement $notificationByRelatedEntityAndUserAssociatedStatement = null;
|
||||
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
@ -48,6 +51,30 @@ final class NotificationRepository implements ObjectRepository
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function countNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
|
||||
{
|
||||
if (null === $this->notificationByRelatedEntityAndUserAssociatedStatement) {
|
||||
$sql =
|
||||
'SELECT
|
||||
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_unread cmnau WHERE user_id = 1812 and cmnau.notification_id = cmn.id))::int) AS unread,
|
||||
SUM((cmn.sender_id = 1812)::int) AS sent,
|
||||
COUNT(cmn.*) AS total
|
||||
FROM chill_main_notification cmn
|
||||
WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
|
||||
$this->notificationByRelatedEntityAndUserAssociatedStatement =
|
||||
$this->em->getConnection()->prepare($sql);
|
||||
}
|
||||
|
||||
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
|
||||
->executeQuery(['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId]);
|
||||
|
||||
$result = $results->fetchAssociative();
|
||||
|
||||
$results->free();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function countUnreadByUser(User $user): int
|
||||
{
|
||||
$sql = 'SELECT count(*) AS c FROM chill_main_notification_addresses_unread WHERE user_id = :userId';
|
||||
@ -153,11 +180,29 @@ final class NotificationRepository implements ObjectRepository
|
||||
* @return array|Notification[]
|
||||
*/
|
||||
public function findNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
|
||||
{
|
||||
return
|
||||
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user)
|
||||
->select('n')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria, ?array $orderBy = null): ?Notification
|
||||
{
|
||||
return $this->repository->findOneBy($criteria, $orderBy);
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return Notification::class;
|
||||
}
|
||||
|
||||
private function buildQueryNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): QueryBuilder
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('n');
|
||||
|
||||
$qb
|
||||
->select('n')
|
||||
->where($qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'))
|
||||
->andWhere($qb->expr()->eq('n.relatedEntityId', ':relatedEntityId'))
|
||||
->andWhere($qb->expr()->isNotNull('n.sender'))
|
||||
@ -171,17 +216,7 @@ final class NotificationRepository implements ObjectRepository
|
||||
->setParameter('relatedEntityId', $relatedEntityId)
|
||||
->setParameter('user', $user);
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria, ?array $orderBy = null): ?Notification
|
||||
{
|
||||
return $this->repository->findOneBy($criteria, $orderBy);
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return Notification::class;
|
||||
return $qb;
|
||||
}
|
||||
|
||||
private function queryByAddressee(User $addressee, bool $countQuery = false): QueryBuilder
|
||||
|
@ -62,6 +62,7 @@
|
||||
{{ c.notification.message|chill_markdown_to_html }}
|
||||
{% else %}
|
||||
{{ c.notification.message|u.truncate(250, '…', false)|chill_markdown_to_html }}
|
||||
<p class="read-more"><a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': c.notification.id}) }}">{{ 'Read more'|trans }}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -85,7 +86,13 @@
|
||||
{% if is_granted('CHILL_MAIN_NOTIFICATION_SEE', c.notification) %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': c.notification.id}) }}"
|
||||
class="btn btn-show change-icon" title="{{ 'notification.see_comments_thread'|trans }}"><i class="fa fa-comment"></i></a>
|
||||
class="btn {% if not c.notification.isSystem %}btn-show change-icon{% else %}btn-misc{% endif %}" title="{{ 'notification.see_comments_thread'|trans }}">
|
||||
{% if not c.notification.isSystem() %}
|
||||
<i class="fa fa-comment"></i>
|
||||
{% else %}
|
||||
{{ 'Read more'|trans }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
@ -21,8 +21,6 @@
|
||||
{{ form_row(form.title, { 'label': 'notification.subject'|trans }) }}
|
||||
{{ form_row(form.addressees, { 'label': 'notification.sent_to'|trans }) }}
|
||||
|
||||
{% include handler.template(notification) with handler.templateData(notification) %}
|
||||
|
||||
<div class="mb-3 row">
|
||||
<label class="col-form-label col-sm-4" for="notification_message">{{ form_label(form.message) }}</label>
|
||||
<div class="col-12">
|
||||
@ -30,6 +28,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include handler.template(notification) with handler.templateData(notification) %}
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
|
@ -0,0 +1,2 @@
|
||||
{% if counter.total > 0 %}<span class="badge rounded-pill bg-primary">{{ 'notification.counter total notifications'|trans({'total': counter.total }) }}</span>{% endif %}
|
||||
{% if counter.unread > 0 %}<span class="badge rounded-pill bg-danger">{{ 'notification.counter unread notifications'|trans({'unread': counter.unread })}}</span>{% endif %}
|
@ -18,7 +18,7 @@
|
||||
data-notification-id="{{ notification.id }}"
|
||||
data-notification-current-is-read="{{ notification.isReadBy(app.user) }}"
|
||||
data-container="notification-status"
|
||||
data-show-button-url="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}) }}"
|
||||
data-show-button-url="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}, false) }}"
|
||||
data-button-class="btn-outline-primary"
|
||||
data-button-text="false"
|
||||
></span>
|
||||
|
50
src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php
Normal file
50
src/Bundle/ChillMainBundle/Service/Mailer/ChillMailer.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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\Service\Mailer;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Mime\RawMessage;
|
||||
|
||||
class ChillMailer implements MailerInterface
|
||||
{
|
||||
private LoggerInterface $chillLogger;
|
||||
|
||||
private MailerInterface $initial;
|
||||
|
||||
private string $prefix = '[Chill] ';
|
||||
|
||||
public function __construct(MailerInterface $initial, LoggerInterface $chillLogger)
|
||||
{
|
||||
$this->initial = $initial;
|
||||
$this->chillLogger = $chillLogger;
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, ?Envelope $envelope = null): void
|
||||
{
|
||||
if ($message instanceof Email) {
|
||||
$message->subject($this->prefix . $message->getSubject());
|
||||
}
|
||||
|
||||
$this->chillLogger->info('chill email sent', [
|
||||
'to' => array_map(static function (Address $address) {
|
||||
return $address->getAddress();
|
||||
}, $message->getTo()),
|
||||
'subject' => $message->getSubject(),
|
||||
]);
|
||||
|
||||
$this->initial->send($message, $envelope);
|
||||
}
|
||||
}
|
10
src/Bundle/ChillMainBundle/config/services/mailer.yaml
Normal file
10
src/Bundle/ChillMainBundle/config/services/mailer.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\MainBundle\Service\Mailer\:
|
||||
resource: '../../Service/Mailer'
|
||||
|
||||
Chill\MainBundle\Service\Mailer\ChillMailer:
|
||||
decorates: Symfony\Component\Mailer\MailerInterface
|
@ -0,0 +1,33 @@
|
||||
<?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\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20220120155303 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP INDEX chill_main_notification_related_entity_idx');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create index for counting notifications';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE INDEX chill_main_notification_related_entity_idx ON chill_main_notification (relatedentityclass, relatedentityid DESC)');
|
||||
}
|
||||
}
|
@ -13,3 +13,19 @@ notification:
|
||||
few {# notifications}
|
||||
other {# notifications}
|
||||
}
|
||||
|
||||
counter total notifications: >-
|
||||
{total, plural,
|
||||
=0 {Aucune notification}
|
||||
one {# notification}
|
||||
few {# notifications}
|
||||
other {# notifications}
|
||||
}
|
||||
|
||||
counter unread notifications: >-
|
||||
{unread, plural,
|
||||
=0 {Aucune non-lue}
|
||||
one {# non-lue}
|
||||
few {# non-lues}
|
||||
other {# non-lues}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ comment: commentaire
|
||||
Comment: Commentaire
|
||||
Pinned comment: Commentaire épinglé
|
||||
Any comment: Aucun commentaire
|
||||
Read more: Lire la suite
|
||||
|
||||
# comment embeddable
|
||||
No comment associated: Aucun commentaire
|
||||
|
@ -9,19 +9,20 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\AccompanyingPeriod\Workflow;
|
||||
namespace Chill\PersonBundle\AccompanyingPeriod\Events;
|
||||
|
||||
use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
use Symfony\Component\Workflow\Event\EnteredEvent;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class WorkflowEventSubscriber implements EventSubscriberInterface
|
||||
class UserRefEventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
@ -55,15 +56,30 @@ class WorkflowEventSubscriber implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function onPeriodConfirmed(AccompanyingPeriod $period)
|
||||
public function postUpdate(AccompanyingPeriod $period, LifecycleEventArgs $args): void
|
||||
{
|
||||
if ($period->hasPreviousUser()
|
||||
&& $period->getUser() !== $this->security->getUser()
|
||||
&& $period->getStep() !== AccompanyingPeriod::STEP_DRAFT
|
||||
) {
|
||||
$this->generateNotificationToUser($period);
|
||||
}
|
||||
|
||||
// we are just out of a flush operation. Launch a new one
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
private function generateNotificationToUser(AccompanyingPeriod $period)
|
||||
{
|
||||
if ($period->getUser() instanceof User
|
||||
&& $period->getUser() !== $this->security->getUser()) {
|
||||
$notification = new Notification();
|
||||
|
||||
$urgentStatement =
|
||||
$period->isEmergency() ? strtoupper($this->translator->trans('accompanying_period.emergency')) . ' ' : '';
|
||||
|
||||
$notification
|
||||
->setRelatedEntityId($period->getId())
|
||||
->setRelatedEntityClass(AccompanyingPeriod::class)
|
||||
->setTitle($this->translator->trans('period_notification.period_designated_subject'))
|
||||
->setTitle($urgentStatement . $this->translator->trans('period_notification.period_designated_subject'))
|
||||
->setMessage($this->engine->render(
|
||||
'@ChillPerson/Notification/accompanying_course_designation.md.twig',
|
||||
[
|
||||
@ -71,7 +87,15 @@ class WorkflowEventSubscriber implements EventSubscriberInterface
|
||||
]
|
||||
))
|
||||
->addAddressee($period->getUser());
|
||||
|
||||
$this->em->persist($notification);
|
||||
}
|
||||
|
||||
private function onPeriodConfirmed(AccompanyingPeriod $period)
|
||||
{
|
||||
if ($period->getUser() instanceof User
|
||||
&& $period->getUser() !== $this->security->getUser()) {
|
||||
$this->generateNotificationToUser($period);
|
||||
}
|
||||
}
|
||||
}
|
@ -327,6 +327,13 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* Temporary field, which is filled when the user is changed.
|
||||
*
|
||||
* Used internally for listener when user change
|
||||
*/
|
||||
private ?User $userPrevious = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity=AccompanyingPeriodWork::class,
|
||||
@ -755,6 +762,11 @@ class AccompanyingPeriod implements
|
||||
return $this->pinnedComment;
|
||||
}
|
||||
|
||||
public function getPreviousUser(): ?User
|
||||
{
|
||||
return $this->userPrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|SocialAction[] All the descendant social actions of all
|
||||
* the descendants of the entity
|
||||
@ -868,6 +880,11 @@ class AccompanyingPeriod implements
|
||||
return $this->works;
|
||||
}
|
||||
|
||||
public function hasPreviousUser(): bool
|
||||
{
|
||||
return null !== $this->userPrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the closing date is after the opening date.
|
||||
*/
|
||||
@ -1172,6 +1189,10 @@ class AccompanyingPeriod implements
|
||||
|
||||
public function setUser(User $user): self
|
||||
{
|
||||
if ($this->user !== $user) {
|
||||
$this->userPrevious = $this->user;
|
||||
}
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
|
@ -61,13 +61,13 @@ final class CreationPersonType extends AbstractType
|
||||
'required' => false,
|
||||
])
|
||||
->add('phonenumber', TelType::class, [
|
||||
'required' => false
|
||||
'required' => false,
|
||||
])
|
||||
->add('mobilenumber', TelType::class, [
|
||||
'required' => false
|
||||
'required' => false,
|
||||
])
|
||||
->add('email', EmailType::class, [
|
||||
'required' => false
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
if ($this->askCenters) {
|
||||
|
@ -131,6 +131,10 @@
|
||||
{{ 'le ' ~ w.updatedAt|format_datetime('long', 'short') }}
|
||||
</div>
|
||||
<ul class="record_actions">
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<li>{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) }}</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
{% macro recordAction(period, contextEntity) %}
|
||||
{# TODO if enable_accompanying_course_with_multiple_persons is true ... #}
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<li>{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) }}</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_accompanying_course_index', { 'accompanying_period_id': period.id }) }}"
|
||||
class="btn btn-show" title="{{ 'See accompanying period'|trans }}">{# {{ 'See this period'|trans }} #}</a>
|
||||
|
@ -118,6 +118,10 @@
|
||||
{{ 'File number'|trans }} {{ acp.id }}
|
||||
</div>
|
||||
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', acp.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<div class="counter">{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', acp.id) }}</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
|
@ -20,9 +20,19 @@ services:
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Suggestion\ReferralsSuggestionInterface: '@Chill\PersonBundle\AccompanyingPeriod\Suggestion\ReferralsSuggestion'
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Workflow\:
|
||||
resource: './../../AccompanyingPeriod/Workflow'
|
||||
Chill\PersonBundle\AccompanyingPeriod\Events\:
|
||||
resource: './../../AccompanyingPeriod/Events'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Events\UserRefEventSubscriber:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
tags:
|
||||
- # these are the options required to define the entity listener
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'postUpdate'
|
||||
entity: 'Chill\PersonBundle\Entity\AccompanyingPeriod'
|
||||
|
||||
# set the 'lazy' option to TRUE to only instantiate listeners when they are used
|
||||
lazy: true
|
||||
|
Loading…
x
Reference in New Issue
Block a user