diff --git a/CHANGELOG.md b/CHANGELOG.md index ce9fe509f..b3b7f67c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,15 @@ and this project adheres to * [person] accompanying course work: fix on-the-fly update of thirdParty * [on-the-fly] close modal only after validation * [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433) +* change order for accompanying course work list +* [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432) +* ajoute un ordre dans les localisation (api) +## Test releases + +### test release 2021-02-01 +>>>>>>> master * 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 @@ -35,9 +42,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/ChillActivityBundle/Controller/ActivityController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php index d46136173..3858979ef 100644 --- a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php +++ b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php @@ -220,7 +220,7 @@ final class ActivityController extends AbstractController $this->entityManager->persist($entity); $this->entityManager->flush(); - if ($form->has('gendocTemplateId') && '' !== $form['gendocTemplateId']) { + if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) { return $this->redirectToRoute( 'chill_docgenerator_generate_from_template', [ @@ -437,7 +437,7 @@ final class ActivityController extends AbstractController $this->entityManager->persist($entity); $this->entityManager->flush(); - if ($form->has('gendocTemplateId') && '' !== $form['gendocTemplateId']) { + if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) { return $this->redirectToRoute( 'chill_docgenerator_generate_from_template', [ diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 8966ecca8..05dc362b4 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -97,7 +97,6 @@ class CalendarType extends AbstractType return $res; }, static function (?string $dateAsString): DateTimeImmutable { - return new DateTimeImmutable($dateAsString); } )); diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig index 0a1942f6d..6c664b314 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig @@ -8,14 +8,13 @@

{{ document.title }}

- {{ document.object.type }} - + {% if document.description is not empty %}
{{ document.description }}
{% endif %} - +
@@ -32,6 +31,13 @@ {% if display_action is defined and display_action == true %} -{% endif %} \ No newline at end of file +{% endif %} diff --git a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php index 250d92980..2cf5caaf9 100644 --- a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php @@ -12,6 +12,8 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\Pagination\PaginatorInterface; +use Doctrine\ORM\QueryBuilder; use Symfony\Component\HttpFoundation\Request; /** @@ -19,7 +21,7 @@ use Symfony\Component\HttpFoundation\Request; */ class LocationApiController extends ApiController { - public function customizeQuery(string $action, Request $request, $query): void + protected function customizeQuery(string $action, Request $request, $query): void { $query ->leftJoin('e.locationType', 'lt') @@ -31,4 +33,14 @@ class LocationApiController extends ApiController ) ); } + + /** + * @param QueryBuilder $query + * @param mixed $_format + */ + protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format) + { + return $query + ->addOrderBy('e.name', 'ASC'); + } } diff --git a/src/Bundle/ChillMainBundle/Controller/NotificationController.php b/src/Bundle/ChillMainBundle/Controller/NotificationController.php index 52f58ed68..af9e1b2b1 100644 --- a/src/Bundle/ChillMainBundle/Controller/NotificationController.php +++ b/src/Bundle/ChillMainBundle/Controller/NotificationController.php @@ -236,6 +236,10 @@ class NotificationController extends AbstractController '_fragment' => 'comment-' . $commentId, ]); } + + if ($editedCommentForm->isSubmitted() && !$editedCommentForm->isValid()) { + $this->addFlash('error', $this->translator->trans('This form contains errors')); + } } } @@ -257,6 +261,10 @@ class NotificationController extends AbstractController 'id' => $notification->getId(), ]); } + + if ($appendCommentForm->isSubmitted() && !$appendCommentForm->isValid()) { + $this->addFlash('error', $this->translator->trans('This form contains errors')); + } } } diff --git a/src/Bundle/ChillMainBundle/Entity/NotificationComment.php b/src/Bundle/ChillMainBundle/Entity/NotificationComment.php index 01911c729..5275010e6 100644 --- a/src/Bundle/ChillMainBundle/Entity/NotificationComment.php +++ b/src/Bundle/ChillMainBundle/Entity/NotificationComment.php @@ -18,6 +18,7 @@ use DateTimeInterface; use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Event\PreFlushEventArgs; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Entity @@ -28,6 +29,7 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac { /** * @ORM\Column(type="text") + * @Assert\NotBlank(message="notification.Comment content might not be blank") */ private string $content = ''; @@ -136,9 +138,9 @@ class NotificationComment implements TrackCreationInterface, TrackUpdateInterfac $this->recentlyPersisted = true; } - public function setContent(string $content): self + public function setContent(?string $content): self { - $this->content = $content; + $this->content = (string) $content; return $this; } diff --git a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php index e04a96af0..ce5587ed9 100644 --- a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php +++ b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php @@ -79,11 +79,8 @@ class NotificationMailer continue; } - $email = new Email(); - $email - ->subject($notification->getTitle()); - if ($notification->isSystem()) { + $email = new Email(); $email ->text($notification->getMessage()); } else { @@ -96,7 +93,9 @@ class NotificationMailer ]); } - $email->to($addressee->getEmail()); + $email + ->subject($notification->getTitle()) + ->to($addressee->getEmail()); try { $this->mailer->send($email); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/PickWorkflow.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/PickWorkflow.vue index e74cd7ef2..826917fbb 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/PickWorkflow.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/PickWorkflow.vue @@ -47,7 +47,8 @@ export default { console.log('goToGenerateWorkflow', event, workflowName); if (!this.$props.preventDefaultMoveToGenerate) { - event.target.click(); + console.log('to go generate'); + window.location.assign(this.makeLink(workflowName)); } this.$emit('goToGenerateWorkflow', {event, workflowName, link: this.makeLink(workflowName)}); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js index c1eac0b06..0f2b52568 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js @@ -91,11 +91,11 @@ export const multiSelectMessages = { multiselect: { placeholder: 'Choisir', tag_placeholder: 'Créer un nouvel élément', - select_label: 'Appuyer sur "Entrée" pour sélectionner', - deselect_label: 'Appuyer sur "Entrée" pour désélectionner', + select_label: '"Entrée" ou cliquez pour sélectionner', + deselect_label: '"Entrée" ou cliquez pour désélectionner', select_group_label: 'Appuyer sur "Entrée" pour sélectionner ce groupe', deselect_group_label: 'Appuyer sur "Entrée" pour désélectionner ce groupe', selected_label: 'Sélectionné' } } -}; \ No newline at end of file +}; diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/_item_comments.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/_item_comments.html.twig index b741abf4a..121111b03 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Notification/_item_comments.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/_item_comments.html.twig @@ -15,11 +15,11 @@

{{ 'notification.comments_list'|trans }}

- + {% if notification.comments|length > 0 %}
{% for comment in notification.comments %} - + {% if editedCommentForm is null or editedCommentId != comment.id %} {{ m.show_comment(comment, { 'recordAction': _self.recordAction(comment) @@ -28,10 +28,11 @@
- + {{ form_start(editedCommentForm) }} {{ form_errors(editedCommentForm) }} {{ form_widget(editedCommentForm.content) }} + {{ form_errors(editedCommentForm.content) }}
  • @@ -46,24 +47,25 @@
{{ form_end(editedCommentForm) }} - +
{% endif %} - + {% endfor %}
{% else %} {{ 'No comments'|trans }} {% endif %} - + {% if appendCommentForm is not null %}

{{ 'Write a new comment'|trans }}

- + {{ form_start(appendCommentForm) }} {{ form_errors(appendCommentForm) }} {{ form_widget(appendCommentForm.content) }} + {{ form_errors(appendCommentForm.content) }} {{ form_end(appendCommentForm) }} - +
{% endif %} -
\ No newline at end of file + diff --git a/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php b/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php index 6a61e7de4..41ffd63c2 100644 --- a/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php +++ b/src/Bundle/ChillMainBundle/Workflow/Counter/WorkflowByUserCounter.php @@ -16,16 +16,16 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepRepository; use Chill\MainBundle\Templating\UI\NotificationCounterInterface; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Workflow\Event\Event; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; final class WorkflowByUserCounter implements NotificationCounterInterface, EventSubscriberInterface { - private EntityWorkflowStepRepository $workflowStepRepository; - private CacheItemPoolInterface $cacheItemPool; + private EntityWorkflowStepRepository $workflowStepRepository; + public function __construct(EntityWorkflowStepRepository $workflowStepRepository, CacheItemPoolInterface $cacheItemPool) { $this->workflowStepRepository = $workflowStepRepository; @@ -54,14 +54,21 @@ final class WorkflowByUserCounter implements NotificationCounterInterface, Event return $nb; } + public static function generateCacheKeyWorkflowByUser(User $user): string + { + return 'chill_main_workflow_by_u_' . $user->getId(); + } + public function getCountUnreadByUser(User $user): int { return $this->workflowStepRepository->countUnreadByUser($user); } - public static function generateCacheKeyWorkflowByUser(User $user): string + public static function getSubscribedEvents() { - return 'chill_main_workflow_by_u_'.$user->getId(); + return [ + 'workflow.leave' => 'resetWorkflowCache', + ]; } public function resetWorkflowCache(Event $event): void @@ -74,11 +81,12 @@ final class WorkflowByUserCounter implements NotificationCounterInterface, Event $entityWorkflow = $event->getSubject(); $step = $entityWorkflow->getCurrentStep(); - if ($step === null) { + if (null === $step) { return; } $keys = []; + foreach ($step->getDestUser() as $user) { $keys[] = self::generateCacheKeyWorkflowByUser($user); } @@ -86,15 +94,5 @@ final class WorkflowByUserCounter implements NotificationCounterInterface, Event if ([] !== $keys) { $this->cacheItemPool->deleteItems($keys); } - } - - public static function getSubscribedEvents() - { - return [ - 'workflow.leave' => 'resetWorkflowCache', - ]; - } - - } diff --git a/src/Bundle/ChillMainBundle/translations/validators.fr.yml b/src/Bundle/ChillMainBundle/translations/validators.fr.yml index 7bd943f25..33973f9d7 100644 --- a/src/Bundle/ChillMainBundle/translations/validators.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/validators.fr.yml @@ -27,4 +27,4 @@ address: notification: At least one addressee: Indiquez au moins un destinataire Title must be defined: Un titre doit être indiqué - + Comment content might not be blank: Le commentaire ne peut pas être vide 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/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index dff4ee38f..b7e8d1c5d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -44,8 +44,8 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues { /** * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) - * @Serializer\Groups({"read","read:accompanyingPeriodWork:light"}) - * @Serializer\Context(normalizationContext={"groups"={"read"}}, groups={"read:accompanyingPeriodWork:light"}) + * @Serializer\Groups({"read", "read:accompanyingPeriodWork:light"}) + * @Serializer\Context(normalizationContext={"groups": {"read"}}, groups={"read:accompanyingPeriodWork:light"}) */ private ?AccompanyingPeriod $accompanyingPeriod = null; diff --git a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index 0efbf9ac3..827dfb0a6 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,44 @@ 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..9e67da458 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -16,17 +16,22 @@ 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; final class AccompanyingPeriodWorkRepository implements ObjectRepository { + private EntityManagerInterface $em; + private EntityRepository $repository; public function __construct(EntityManagerInterface $entityManager) { + $this->em = $entityManager; $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class); } @@ -78,6 +83,36 @@ 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/public/vuejs/AccompanyingCourse/components/Confirm.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Confirm.vue index faba287c5..d12bd1184 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Confirm.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Confirm.vue @@ -60,14 +60,14 @@