Merge branch 'notifications3' into 'master'

Notifications3

See merge request Chill-Projet/chill-bundles!89
This commit is contained in:
Marc Ducobu 2021-07-22 17:44:37 +00:00
commit 18369a6c0a
18 changed files with 319 additions and 7 deletions

View File

@ -22,6 +22,7 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt
'entityRef' => 'activity_gerard depardieu',
'sender' => 'center a_social',
'addressees' => [
'center a_social',
'center a_administrative',
'center a_direction',
'multi_center'

View File

@ -0,0 +1,24 @@
<?php
namespace Chill\ActivityBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\ActivityBundle\Entity\Activity;
final class ActivityNotificationRenderer
{
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
public function getTemplate()
{
return '@ChillActivity/Activity/showInNotification.html.twig';
}
public function getTemplateData(Notification $notification)
{
return ['notification' => $notification];
}
}

View File

@ -0,0 +1,4 @@
{{ dump(notification) }}
<a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId }) }}">Go to Activity</a>

View File

@ -33,3 +33,8 @@ services:
autoconfigure: true
resource: '../Menu/'
tags: ['chill.menu_builder']
Chill\ActivityBundle\Notification\:
autowire: true
autoconfigure: true
resource: '../Notification'

View File

@ -0,0 +1,59 @@
<?php
namespace Chill\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Chill\MainBundle\Repository\NotificationRepository;
use Chill\MainBundle\Notification\NotificationRenderer;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Routing\Annotation\Route;
use Chill\MainBundle\Pagination\PaginatorFactory;
/**
* @Route("/{_locale}/notification")
*/
class NotificationController extends AbstractController
{
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
/**
* @Route("/show", name="chill_main_notification_show")
*/
public function showAction(
NotificationRepository $notificationRepository, NotificationRenderer $notificationRenderer,
PaginatorFactory $paginatorFactory)
{
$currentUser = $this->security->getUser();
$notificationsNbr = $notificationRepository->countAllForAttendee(($currentUser));
$paginator = $paginatorFactory->create($notificationsNbr);
$notifications = $notificationRepository->findAllForAttendee(
$currentUser,
$limit=$paginator->getItemsPerPage(),
$offset= $paginator->getCurrentPage()->getFirstItemNumber());
$templateData = array();
foreach ($notifications as $notification) {
$data = [
'template' => $notificationRenderer->getTemplate($notification),
'template_data' => $notificationRenderer->getTemplateData($notification),
'notification' => $notification
];
$templateData[] = $data;
}
return $this->render('@ChillMain/Notification/show.html.twig', [
'datas' => $templateData,
'notifications' => $notifications,
'paginator' => $paginator,
]);
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Chill\MainBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\PersonBundle\Notification\AccompanyingPeriodNotificationRenderer;
use Chill\ActivityBundle\Notification\ActivityNotificationRenderer;
final class NotificationRenderer
{
private array $renderers;
public function __construct(
AccompanyingPeriodNotificationRenderer $accompanyingPeriodNotificationRenderer,
ActivityNotificationRenderer $activityNotificationRenderer)
{
// TODO configure automatically
// TODO CREER UNE INTERFACE POUR ETRE SUR QUE LES RENDERERS SONT OK
$this->renderers[] = $accompanyingPeriodNotificationRenderer;
$this->renderers[] = $activityNotificationRenderer;
}
private function getRenderer(Notification $notification)
{
foreach ($this->renderers as $renderer) {
if($renderer->supports($notification)) {
return $renderer;
}
}
throw new \Exception('No renderer for '. $notification);
}
public function getTemplate(Notification $notification)
{
return $this->getRenderer($notification)->getTemplate();
}
public function getTemplateData(Notification $notification)
{
return $this->getRenderer($notification)->getTemplateData($notification);
}
}

View File

@ -23,6 +23,8 @@ use Chill\MainBundle\Entity\Notification;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
use Chill\MainBundle\Entity\User;
use Doctrine\ORM\Query;
final class NotificationRepository implements ObjectRepository
{
@ -59,8 +61,54 @@ final class NotificationRepository implements ObjectRepository
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
private function queryAllForAttendee(User $addressee, bool $countQuery=False): Query
{
$qb = $this->repository->createQueryBuilder('n');
$select = 'n';
if($countQuery) {
$select = 'count(n)';
}
$qb
->select($select)
->join('n.addressees', 'a')
->where('a = :addressee')
->setParameter('addressee', $addressee);
return $qb->getQuery();
}
/**
* @return int
*/
public function countAllForAttendee(User $addressee): int // TODO passer à attendees avec S
{
$query = $this->queryAllForAttendee($addressee, $countQuery=True);
return $query->getSingleScalarResult();
}
/**
* @return Notification[]
*/
public function findAllForAttendee(User $addressee, $limit = null, $offset = null): array // TODO passer à attendees avec S
{
$query = $this->queryAllForAttendee($addressee);
if($limit) {
$query = $query->setMaxResults($limit);
}
if($offset) {
$query = $query->setFirstResult($offset);
}
return $query->getResult();
}
public function getClassName() {
return Notification::class;
}
}

View File

@ -0,0 +1,42 @@
{% extends "@ChillMain/layout.html.twig" %}
{% block content %}
<div id="container content">
<div class="grid-8 centered">
<h1>{{ "Notifications list" | trans }}</h1>
<!-- TODO : UNREAD & READ -->
{%for data in datas %}
{% set notification = data.notification %}
<dl class="chill_view_data">
<dt class="inline">{{ 'Message'|trans }}</dt>
<dd>{{ notification.message }}</dd>
</dl>
<dl class="chill_view_data">
<dt class="inline">{{ 'Date'|trans }}</dt>
<dd>{{ notification.date | date('long') }}</dd>
</dl>
<dl class="chill_view_data">
<dt class="inline">{{ 'Sender'|trans }}</dt>
<dd>{{ notification.sender }}</dd>
</dl>
<dl class="chill_view_data">
<dt class="inline">{{ 'Addressees'|trans }}</dt>
<dd>{{ notification.addressees |join(', ') }}</dd>
</dl>
<dl class="chill_view_data">
<dt class="inline">{{ 'Entity'|trans }}</dt>
<dd>
{% include data.template with data.template_data %}
</dd>
</dl>
{% endfor %}
</div>
</div>
{% endblock content %}

View File

@ -34,6 +34,10 @@ chill_password_recover:
resource: "@ChillMainBundle/config/routes/password_recover.yaml"
prefix: "public/{_locale}/password"
chill_main_notification:
resource: "@ChillMainBundle/config/routes/notification.yaml"
prefix: "{_locale}/notification"
chill_crud:
resource: "@ChillMainBundle"
type: CRUD

View File

@ -33,3 +33,8 @@ services:
$logger: '@Psr\Log\LoggerInterface'
$validator: '@Symfony\Component\Validator\Validator\ValidatorInterface'
tags: ['controller.service_arguments']
Chill\MainBundle\Controller\NotificationController:
arguments:
$security: '@Symfony\Component\Security\Core\Security'
tags: ['controller.service_arguments']

View File

@ -8,3 +8,7 @@ services:
$router: '@Symfony\Component\Routing\RouterInterface'
$translator: '@Symfony\Component\Translation\TranslatorInterface'
$routeParameters: '%chill_main.notifications%'
Chill\MainBundle\Notification\NotificationRenderer:
autoconfigure: true
autowire: true

View File

@ -2,6 +2,8 @@ services:
chill_main.paginator_factory:
class: Chill\MainBundle\Pagination\PaginatorFactory
public: true
autowire: true
autoconfigure: true
arguments:
- "@request_stack"
- "@router"

View File

@ -0,0 +1,39 @@
<?php
namespace Chill\PersonBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait;
use Chill\PersonBundle\DataFixtures\ORM\LoadAccompanyingPeriod;
/**
* Load notififications into database
*/
class LoadAccompanyingPeriodNotifications extends AbstractFixture implements DependentFixtureInterface
{
use LoadAbstractNotificationsTrait;
public $notifs = [
[
'message' => 'Hello !',
'entityClass' => AccompanyingPeriod::class,
'entityRef' => LoadAccompanyingPeriod::ACCOMPANYING_PERIOD,
'sender' => 'center a_social',
'addressees' => [
'center a_social',
'center a_administrative',
'center a_direction',
'multi_center'
],
]
];
public function getDependencies()
{
return [
LoadAccompanyingPeriod::class,
];
}
}

View File

@ -74,6 +74,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
$loader->load('services/form.yaml');
$loader->load('services/alt_names.yaml');
$loader->load('services/household.yaml');
$loader->load('services/notification.yaml');
// We can get rid of this file when the service 'chill.person.repository.person' is no more used.
// We should use the PersonRepository service instead of a custom service name.
$loader->load('services/repository.yaml');

View File

@ -0,0 +1,24 @@
<?php
namespace Chill\PersonBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
final class AccompanyingPeriodNotificationRenderer
{
public function supports(Notification $notification)
{
return $notification->getRelatedEntityClass() == AccompanyingPeriod::class;
}
public function getTemplate()
{
return 'ChillPersonBundle:AccompanyingPeriod:showInNotification.html.twig';
}
public function getTemplateData(Notification $notification)
{
return ['notification' => $notification];
}
}

View File

@ -0,0 +1,3 @@
<a href="{{ path('chill_person_accompanying_course_index', {'accompanying_period_id': notification.relatedEntityId }) }}">
Go to Acc. period.
</a>

View File

@ -0,0 +1,3 @@
services:
Chill\PersonBundle\Notification\AccompanyingPeriodNotificationRenderer:
autowire: true