diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index db121ea82..da8aa687e 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -14,11 +14,14 @@ namespace Chill\CalendarBundle\Controller; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Form\CalendarType; use Chill\CalendarBundle\RemoteCalendar\Connector\RemoteCalendarConnectorInterface; +use Chill\CalendarBundle\Repository\CalendarACLAwareRepositoryInterface; use Chill\CalendarBundle\Repository\CalendarRepository; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\MainBundle\Templating\Listing\FilterOrderHelper; +use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Chill\ThirdPartyBundle\Entity\ThirdParty; @@ -37,11 +40,11 @@ use Symfony\Component\Serializer\SerializerInterface; class CalendarController extends AbstractController { - private AuthorizationHelper $authorizationHelper; - private CalendarRepository $calendarRepository; - private EventDispatcherInterface $eventDispatcher; + private CalendarACLAwareRepositoryInterface $calendarACLAwareRepository; + + private FilterOrderHelperFactoryInterface $filterOrderHelperFactory; private LoggerInterface $logger; @@ -54,18 +57,18 @@ class CalendarController extends AbstractController private UserRepository $userRepository; public function __construct( - AuthorizationHelper $authorizationHelper, CalendarRepository $calendarRepository, - EventDispatcherInterface $eventDispatcher, + CalendarACLAwareRepositoryInterface $calendarACLAwareRepository, + FilterOrderHelperFactoryInterface $filterOrderHelperFactory, LoggerInterface $logger, PaginatorFactory $paginator, RemoteCalendarConnectorInterface $remoteCalendarConnector, SerializerInterface $serializer, UserRepository $userRepository ) { - $this->authorizationHelper = $authorizationHelper; $this->calendarRepository = $calendarRepository; - $this->eventDispatcher = $eventDispatcher; + $this->calendarACLAwareRepository = $calendarACLAwareRepository; + $this->filterOrderHelperFactory = $filterOrderHelperFactory; $this->logger = $logger; $this->paginator = $paginator; $this->remoteCalendarConnector = $remoteCalendarConnector; @@ -193,48 +196,39 @@ class CalendarController extends AbstractController /** * Lists all Calendar entities. * - * @Route("/{_locale}/calendar/calendar/", name="chill_calendar_calendar_list") + * @Route("/{_locale}/calendar/calendar/by-period/{id}", name="chill_calendar_calendar_list_by_period") */ - public function listAction(Request $request): Response + public function listActionByCourse(AccompanyingPeriod $accompanyingPeriod): Response { - $view = null; + $filterOrder = $this->buildListFilterOrder(); + ['from' => $from, 'to' => $to] = $filterOrder->getDateRangeData('startDate'); - [$user, $accompanyingPeriod] = $this->getEntity($request); - - /* - dead code ? - if ($user instanceof User) { - $calendarItems = $this->calendarRepository->findByUser($user); - - $view = '@ChillCalendar/Calendar/listByUser.html.twig'; - - return $this->render($view, [ - 'calendarItems' => $calendarItems, - 'user' => $user, - ]); - } - */ - - if ($accompanyingPeriod instanceof AccompanyingPeriod) { - $total = $this->calendarRepository->countByAccompanyingPeriod($accompanyingPeriod); + $total = $this->calendarACLAwareRepository + ->countByAccompanyingPeriod($accompanyingPeriod, $from, $to); $paginator = $this->paginator->create($total); - $calendarItems = $this->calendarRepository->findBy( - ['accompanyingPeriod' => $accompanyingPeriod], + $calendarItems = $this->calendarACLAwareRepository->findByAccompanyingPeriod( + $accompanyingPeriod, + $from, + $to, ['startDate' => 'DESC'], - $paginator->getItemsPerPage(), - $paginator->getCurrentPageFirstItemNumber() + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() ); - $view = '@ChillCalendar/Calendar/listByAccompanyingCourse.html.twig'; - - return $this->render($view, [ + return $this->render('@ChillCalendar/Calendar/listByAccompanyingCourse.html.twig', [ 'calendarItems' => $calendarItems, 'accompanyingCourse' => $accompanyingPeriod, 'paginator' => $paginator, + 'filterOrder' => $filterOrder, ]); - } + } - throw new Exception('Unable to list actions.'); + private function buildListFilterOrder(): FilterOrderHelper + { + $filterOrder = $this->filterOrderHelperFactory->create(self::class); + $filterOrder->addDateRange('startDate', 'chill_calendar.start date filter', new \DateTimeImmutable('3 days ago'), null); + + return $filterOrder->build(); } /** diff --git a/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php index fdc07d56d..b3efc635f 100644 --- a/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -37,9 +37,9 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface if ($this->security->isGranted(CalendarVoter::SEE, $period)) { $menu->addChild($this->translator->trans('Calendar'), [ - 'route' => 'chill_calendar_calendar_list', + 'route' => 'chill_calendar_calendar_list_by_period', 'routeParameters' => [ - 'accompanying_period_id' => $period->getId(), + 'id' => $period->getId(), ], ]) ->setExtras(['order' => 35]); } diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepository.php new file mode 100644 index 000000000..e0a4ec0b0 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepository.php @@ -0,0 +1,75 @@ +em = $em; + } + + + /** + * @return array|Calendar[] + */ + public function findByAccompanyingPeriod(AccompanyingPeriod $period, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate, ?array $orderBy = [], ?int $offset = null, ?int $limit = null): array + { + $qb = $this->buildQueryByAccompanyingPeriod($period, $startDate, $endDate)->select('c'); + + foreach ($orderBy as $sort => $order) { + $qb->addOrderBy('c.'.$sort, $order); + } + + if (null !== $offset) { + $qb->setFirstResult($offset); + } + + if (null !== $limit) { + $qb->setMaxResults($limit); + } + + return $qb->getQuery()->getResult(); + } + + public function countByAccompanyingPeriod(AccompanyingPeriod $period, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate): int + { + $qb = $this->buildQueryByAccompanyingPeriod($period, $startDate, $endDate)->select('count(c)'); + + return $qb->getQuery()->getSingleScalarResult(); + } + + public function buildQueryByAccompanyingPeriod(AccompanyingPeriod $period, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate): QueryBuilder + { + $qb = $this->em->createQueryBuilder(); + $qb->from(Calendar::class, 'c'); + + $andX = $qb->expr()->andX($qb->expr()->eq('c.accompanyingPeriod', ':period')); + $qb->setParameter('period', $period); + + if (null !== $startDate) { + $andX->add($qb->expr()->gte('c.startDate', ':startDate')); + $qb->setParameter('startDate', $startDate); + } + + if (null !== $endDate) { + $andX->add($qb->expr()->lte('c.endDate', ':endDate')); + $qb->setParameter('endDate', $endDate); + } + + $qb->where($andX); + + return $qb; + } + +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepositoryInterface.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepositoryInterface.php new file mode 100644 index 000000000..c31a39e33 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarACLAwareRepositoryInterface.php @@ -0,0 +1,17 @@ +{{ 'Calendar list' |trans }} + {{ filterOrder|chill_render_filter_order_helper }} -{% if calendarItems|length == 0 %} + {% if calendarItems|length == 0 %}
{{ "There is no calendar items."|trans }} diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index d1f48c2fc..a038a11ea 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -43,6 +43,9 @@ chill_calendar: form: The main user is mandatory. He will organize the appointment.: L'utilisateur principal est obligatoire. Il est l'organisateur de l'événement. Create for referrer: Créer pour le référent + start date filter: Début du rendez-vous + From: Du + To: Au remote_ms_graph: freebusy_statuses: diff --git a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php index 2b6cdc21d..fade6230c 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Form\Type\Listing; +use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; @@ -70,10 +71,38 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType $builder->add($checkboxesBuilder); } + if (0 < count($helper->getDateRanges())) { + $dateRangesBuilder = $builder->create('dateRanges', null, ['compound' => true]); + + foreach ($helper->getDateRanges() as $name => $opts) { + $rangeBuilder = $dateRangesBuilder->create($name, null, [ + 'compound' => true, + 'label' => $opts['label'] ?? $name, + ]); + + $rangeBuilder->add( + 'from', + ChillDateType::class, + ['input' => 'datetime_immutable', 'required' => false] + ); + $rangeBuilder->add( + 'to', + ChillDateType::class, + ['input' => 'datetime_immutable', 'required' => false] + ); + + $dateRangesBuilder->add($rangeBuilder); + } + + $builder->add($dateRangesBuilder); + } + foreach ($this->requestStack->getCurrentRequest()->query->getIterator() as $key => $value) { switch ($key) { case 'q': case 'checkboxes' . $key: + case $key . '_from': + case $key . '_to': break; case 'page': diff --git a/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig b/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig index 515685b9e..bffd20a08 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/FilterOrder/base.html.twig @@ -10,6 +10,28 @@ {% endif %} + {% if form.dateRanges is defined %} + {% if form.dateRanges|length > 0 %} + {% for dateRangeName, _o in form.dateRanges %} +