From 4314823a703b9c22efead80233832456f6202e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 8 Feb 2022 19:36:45 +0100 Subject: [PATCH] change order for accompanying period work list --- CHANGELOG.md | 10 ++- .../AccompanyingCourseWorkController.php | 17 +++-- .../Menu/AccompanyingCourseMenuBuilder.php | 64 +++++++++++-------- .../AccompanyingPeriodWorkRepository.php | 36 +++++++++++ .../AccompanyingCourseWork/index.html.twig | 2 + .../AccompanyingPeriodWorkVoter.php | 36 +++++++++-- 6 files changed, 123 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b00be8bc..142d1f0be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ and this project adheres to ## Unreleased +* change order for accompanying course work list + + +## Test releases + +### test release 2021-02-01 + * renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche * renomme date de début en date d'ouverture dans le formulaire parcours * [homepage widget] improve content tables, improve counter pluralization with style on number @@ -29,9 +36,6 @@ and this project adheres to * [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413 * [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc. - -## Test releases - ### test release 2021-01-31 * [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php index 7e7b9a0c2..ec5db6222 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; @@ -23,7 +24,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Serializer\SerializerInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class AccompanyingCourseWorkController extends AbstractController { @@ -60,7 +61,7 @@ class AccompanyingCourseWorkController extends AbstractController */ public function createWork(AccompanyingPeriod $period): Response { - // TODO ACL + $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::CREATE, $period); if ($period->getSocialIssues()->count() === 0) { $this->addFlash( @@ -93,7 +94,8 @@ class AccompanyingCourseWorkController extends AbstractController */ public function deleteWork(AccompanyingPeriodWork $work, Request $request): Response { - // TODO ACL + $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work); + $em = $this->getDoctrine()->getManager(); $form = $this->createDeleteForm($work->getId()); @@ -138,7 +140,8 @@ class AccompanyingCourseWorkController extends AbstractController */ public function editWork(AccompanyingPeriodWork $work): Response { - // TODO ACL + $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work); + $json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]); return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [ @@ -157,13 +160,13 @@ class AccompanyingCourseWorkController extends AbstractController */ public function listWorkByAccompanyingPeriod(AccompanyingPeriod $period): Response { - // TODO ACL + $this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $period); + $totalItems = $this->workRepository->countByAccompanyingPeriod($period); $paginator = $this->paginator->create($totalItems); - $works = $this->workRepository->findByAccompanyingPeriod( + $works = $this->workRepository->findByAccompanyingPeriodOpenFirst( $period, - ['startDate' => 'DESC', 'endDate' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); diff --git a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index 0efbf9ac3..b65e3a515 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -13,7 +13,10 @@ namespace Chill\PersonBundle\Menu; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; use Knp\Menu\MenuItem; +use Symfony\Component\Security\Core\Security; use Symfony\Component\Workflow\Registry; use Symfony\Contracts\Translation\TranslatorInterface; @@ -24,15 +27,18 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface { protected Registry $registry; + protected Security $security; + /** * @var TranslatorInterface */ protected $translator; - public function __construct(TranslatorInterface $translator, Registry $registry) + public function __construct(TranslatorInterface $translator, Registry $registry, Security $security) { $this->translator = $translator; $this->registry = $registry; + $this->security = $security; } public function buildMenu($menuId, MenuItem $menu, array $parameters): void @@ -47,38 +53,46 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface ], ]) ->setExtras(['order' => 10]); - $menu->addChild($this->translator->trans('Edit Accompanying Course'), [ - 'route' => 'chill_person_accompanying_course_edit', - 'routeParameters' => [ - 'accompanying_period_id' => $period->getId(), - ], ]) - ->setExtras(['order' => 20]); + if ($this->security->isGranted(AccompanyingPeriodVoter::EDIT, $period)) { + $menu->addChild($this->translator->trans('Edit Accompanying Course'), [ + 'route' => 'chill_person_accompanying_course_edit', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 20]); + } if (AccompanyingPeriod::STEP_DRAFT === $period->getStep()) { // no more menu items if the period is draft return; } - $menu->addChild($this->translator->trans('Accompanying Course History'), [ - 'route' => 'chill_person_accompanying_course_history', - 'routeParameters' => [ - 'accompanying_period_id' => $period->getId(), - ], ]) - ->setExtras(['order' => 30]); + if ($this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $period)) { + $menu->addChild($this->translator->trans('Accompanying Course History'), [ + 'route' => 'chill_person_accompanying_course_history', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 30]); - $menu->addChild($this->translator->trans('Accompanying Course Action'), [ - 'route' => 'chill_person_accompanying_period_work_list', - 'routeParameters' => [ - 'id' => $period->getId(), - ], ]) - ->setExtras(['order' => 40]); - $menu->addChild($this->translator->trans('Accompanying Course Comment'), [ - 'route' => 'chill_person_accompanying_period_comment_list', - 'routeParameters' => [ - 'accompanying_period_id' => $period->getId(), - ], ]) - ->setExtras(['order' => 50]); + $menu->addChild($this->translator->trans('Accompanying Course Comment'), [ + 'route' => 'chill_person_accompanying_period_comment_list', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 50]); + } + + if ($this->security->isGranted(AccompanyingPeriodWorkVoter::SEE, $period)) { + $menu->addChild($this->translator->trans('Accompanying Course Action'), [ + 'route' => 'chill_person_accompanying_period_work_list', + 'routeParameters' => [ + 'id' => $period->getId(), + ], ]) + ->setExtras(['order' => 40]); + } + $workflow = $this->registry->get($period, 'accompanying_period_lifecycle'); diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 70e972aa5..7514517d5 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -16,8 +16,10 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\SocialWork\SocialAction; use DateTimeImmutable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; @@ -25,8 +27,11 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository { private EntityRepository $repository; + private EntityManagerInterface $em; + public function __construct(EntityManagerInterface $entityManager) { + $this->em = $entityManager; $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class); } @@ -78,6 +83,37 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return $this->repository->findByAccompanyingPeriod($period, $orderBy, $limit, $offset); } + /** + * Return a list of accompanying period with a defined order: + * + * * first, opened works + * * then, closed works + * + * @return AccompanyingPeriodWork[] + */ + public function findByAccompanyingPeriodOpenFirst(AccompanyingPeriod $period, int $limit = 10, int $offset = 0): array + { + $rsm = new ResultSetMappingBuilder($this->em); + $rsm->addRootEntityFromClassMetadata(AccompanyingPeriodWork::class, 'w'); + + $sql = "SELECT ${rsm} FROM chill_person_accompanying_period_work w + WHERE accompanyingPeriod_id = :periodId + ORDER BY + CASE WHEN enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC, + startdate DESC, + enddate DESC, + id DESC + LIMIT :limit OFFSET :offset"; + + $nq = $this->em->createNativeQuery($sql, $rsm) + ->setParameter('periodId', $period->getId(), Types::INTEGER) + ->setParameter('limit', $limit, Types::INTEGER) + ->setParameter('offset', $offset, Types::INTEGER) + ; + + return $nq->getResult(); + } + public function findNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until, int $limit = 20, int $offset = 0): array { return $this->buildQueryNearEndDateByUser($user, $since, $until) diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig index 7794a3e5f..d8125ef3e 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig @@ -23,6 +23,8 @@ {% endif %} + {{ chill_pagination(paginator) }} +