diff --git a/CHANGELOG.md b/CHANGELOG.md index 885af7493..8fe60496a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,14 @@ and this project adheres to ## Unreleased - * [person] AccompanyingCourseWorkEdit: fix deleting evaluation documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/546) * [person] AccompanyingCourseWorkEdit: download existing documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/512) * [person] AccompanyingCourseWorkEdit: replace document by a new one (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/511) - +* [person] AccompanyingPeriodWork: add referrers to work, add doctrine event listener to add logged user to referrers collection and display a referrers list in work list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/502) +* [person] AccompanyingPeriodWorkEvaluation: fix circular reference when serialising (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/495) +* [person] order accompanying period by opening date in search persons, person and household period lists (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/493) +* [parcours] autosave of the pinned comment for draft accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/477) +* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472) * [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472) * [person] Add url in accompanying period work evaluations entity and form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/476) * [person] Add document generation in admin and in person/{id}/document (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/464) @@ -35,13 +38,21 @@ and this project adheres to * [confidential] Fix position of toggle button so it does not cover text nor fall outside of box (no issue) * [parcours] Fix edit of both thirdparty and contact name (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/474) * [template] do not list inactive templates (for doc generator) +* [household] bugfix if position of member is null, renderbox no longer throws an error (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/480) * [parcours] location cannot be removed if linked to a user (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/478) * [person] email added to twig personRenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/490) * [person] Add link to current household in person banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/484) +* [address] person badge in address history changed to open OnTheFly with all person info (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/489) * [person] Change 'personne' with 'usager' and '&' with 'ET' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/499) * [thirdparty] Add parameter condition to display centers or not (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/500) * [phonenumber] Remove placeholder in phonenumber field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/496) +* [person_resource] separate create page created to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/504) * [contact] add contact button color changed plus the pipe at the side removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/506) +* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505) +* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486) +* [parcours] List of parcours for a specific user so they can be reassigned in case of absence (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/509) +* [thirdparty] Thirdparty view page, english text translated (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/534) +* [social_action] Translation changed in evaluation section (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/512) ## Test releases diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/listPerson.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/listPerson.html.twig index ac4266f8c..8b30bc6c7 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/listPerson.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/listPerson.html.twig @@ -46,7 +46,7 @@ {% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %} - {% if is_granted('CHILL_ACTIVITY_CREATE', person) %} + {% if is_granted('CHILL_ACTIVITY_CREATE_PERSON', person) %} + + + + + {% endfor %} + + {{ chill_pagination(paginator) }} + +{% endblock %} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php index 3562c1361..7eb323754 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/PhonenumberNormalizer.php @@ -16,10 +16,10 @@ use libphonenumber\PhoneNumber; use libphonenumber\PhoneNumberUtil; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterface +class PhonenumberNormalizer implements ContextAwareNormalizerInterface, DenormalizerInterface { private string $defaultCarrierCode; @@ -53,6 +53,10 @@ class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterfac public function normalize($object, ?string $format = null, array $context = []): string { + if ('docgen' === $format && null === $object) { + return ''; + } + return $this->phoneNumberUtil->formatOutOfCountryCallingNumber($object, $this->defaultCarrierCode); } @@ -61,8 +65,18 @@ class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterfac return 'libphonenumber\PhoneNumber' === $type; } - public function supportsNormalization($data, ?string $format = null) + public function supportsNormalization($data, ?string $format = null, array $context = []): bool { - return $data instanceof PhoneNumber; + if ($data instanceof PhoneNumber && 'json' === $format) { + return true; + } + + if ('docgen' === $format && ( + $data instanceof PhoneNumber || PhoneNumber::class === ($context['docgen:expects'] ?? null) + )) { + return true; + } + + return false; } } diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index bb0081c27..c34702ad1 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -222,6 +222,10 @@ class AccompanyingPeriodController extends AbstractController $accompanyingPeriodsRaw = $this->accompanyingPeriodACLAwareRepository ->findByPerson($person, AccompanyingPeriodVoter::SEE); + usort($accompanyingPeriodsRaw, static function ($a, $b) { + return $b->getOpeningDate() > $a->getOpeningDate(); + }); + // filter visible or not visible $accompanyingPeriods = array_filter($accompanyingPeriodsRaw, function (AccompanyingPeriod $ap) { return $this->isGranted(AccompanyingPeriodVoter::SEE, $ap); diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php index 22e92eb02..1144688fe 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php @@ -134,7 +134,7 @@ class HouseholdCompositionController extends AbstractController public function index(Household $household, Request $request): Response { if (!$this->security->isGranted(HouseholdVoter::SEE, $household)) { - throw new AccessDeniedException('not allowed to edit an household'); + throw new AccessDeniedException('not allowed to edit a household'); } $count = $this->householdCompositionRepository->countByHousehold($household); @@ -146,6 +146,20 @@ class HouseholdCompositionController extends AbstractController $paginator->getCurrentPageFirstItemNumber() ); + return new Response($this->engine->render( + '@ChillPerson/HouseholdComposition/index.html.twig', + [ + 'household' => $household, + 'compositions' => $compositions, + ] + )); + } + + /** + * @Route("/{_locale}/person/household/{id}/composition/new", name="chill_person_household_composition_new") + */ + public function newAction(Household $household, Request $request): Response + { if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) { $isEdit = $request->query->has('edit'); @@ -195,10 +209,9 @@ class HouseholdCompositionController extends AbstractController } return new Response($this->engine->render( - '@ChillPerson/HouseholdComposition/index.html.twig', + '@ChillPerson/HouseholdComposition/create.html.twig', [ 'household' => $household, - 'compositions' => $compositions, 'form' => isset($form) ? $form->createView() : null, 'isPosted' => isset($form) ? $form->isSubmitted() : false, 'editId' => $request->query->getInt('edit', -1), diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php index 07fa34b5a..0a8b7eea1 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdController.php @@ -78,6 +78,10 @@ class HouseholdController extends AbstractController } } + usort($accompanyingPeriods, static function ($a, $b) { + return $b->getOpeningDate() > $a->getOpeningDate(); + }); + $oldMembers = $household->getNonCurrentMembers(); $accompanyingPeriodsOld = []; diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php b/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php index 210b507e5..004961594 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonResourceController.php @@ -133,6 +133,19 @@ final class PersonResourceController extends AbstractController $personResources = []; $personResources = $this->personResourceRepository->findBy(['personOwner' => $personOwner->getId()]); + return $this->render( + 'ChillPersonBundle:PersonResource:list.html.twig', + [ + 'person' => $personOwner, + 'personResources' => $personResources, + ] + ); + } + + public function newAction(Request $request, $person_id) + { + $personOwner = $this->personRepository->find($person_id); + $form = $this->createForm(PersonResourceType::class); $form->handleRequest($request); @@ -165,11 +178,10 @@ final class PersonResourceController extends AbstractController } return $this->render( - 'ChillPersonBundle:PersonResource:list.html.twig', + 'ChillPersonBundle:PersonResource:create.html.twig', [ - 'person' => $personOwner, - 'personResources' => $personResources, 'form' => $form->createView(), + 'person' => $personOwner, ] ); } diff --git a/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php new file mode 100644 index 000000000..ac5b6dfab --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php @@ -0,0 +1,115 @@ +accompanyingPeriodACLAwareRepository = $accompanyingPeriodACLAwareRepository; + $this->engine = $engine; + $this->formFactory = $formFactory; + $this->paginatorFactory = $paginatorFactory; + $this->security = $security; + $this->userRepository = $userRepository; + $this->userRender = $userRender; + } + + /** + * @Route("/{_locale}/person/accompanying-periods/reassign", name="chill_course_list_reassign") + */ + public function listAction(Request $request): Response + { + if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) { + throw new AccessDeniedException(); + } + + $form = $this->buildFilterForm(); + + $form->handleRequest($request); + + $total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod( + $form['user']->getData() + ); + $paginator = $this->paginatorFactory->create($total); + $periods = $this->accompanyingPeriodACLAwareRepository + ->findByUserOpenedAccompanyingPeriod( + $form['user']->getData(), + ['openingDate' => 'ASC'], + $paginator->getItemsPerPage(), + $paginator->getCurrentPageFirstItemNumber() + ); + + return new Response( + $this->engine->render('@ChillPerson/AccompanyingPeriod/reassign_list.html.twig', [ + 'paginator' => $paginator, + 'periods' => $periods, + 'form' => $form->createView(), + ]) + ); + } + + private function buildFilterForm(): FormInterface + { + $data = [ + 'user' => null, + ]; + $builder = $this->formFactory->createBuilder(FormType::class, $data, [ + 'method' => 'get', 'csrf_protection' => false, ]); + + $builder + ->add('user', EntityType::class, [ + 'class' => User::class, + 'choices' => $this->userRepository->findByActive(['username' => 'ASC']), + 'choice_label' => function (User $u) { + return $this->userRender->renderString($u, []); + }, + 'multiple' => false, + 'label' => 'User', + 'required' => false, + ]); + + return $builder->getForm(); + } +} diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index b05da5626..1f85e4ad0 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -15,6 +15,7 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException; use Chill\MainBundle\Security\Authorization\ChillExportVoter; use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController; use Chill\PersonBundle\Doctrine\DQL\AddressPart; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Chill\PersonBundle\Security\Authorization\PersonVoter; @@ -415,6 +416,25 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], ], ], + [ + 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\Comment::class, + 'name' => 'accompanying_period_comment', + 'base_path' => '/api/1.0/person/accompanying-period/comment', + 'base_role' => 'ROLE_USER', + 'actions' => [ + '_entity' => [ + 'methods' => [ + Request::METHOD_GET => false, + Request::METHOD_PATCH => true, + Request::METHOD_HEAD => false, + Request::METHOD_DELETE => false, + ], + 'roles' => [ + Request::METHOD_PATCH => AccompanyingPeriodCommentVoter::EDIT, + ], + ], + ], + ], [ 'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\Resource::class, 'name' => 'accompanying_period_resource', diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index d75ade12b..bd3211c5d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -257,9 +257,11 @@ class AccompanyingPeriod implements /** * @ORM\ManyToOne( - * targetEntity=Comment::class + * targetEntity=Comment::class, + * cascade={"persist"}, * ) * @Groups({"read"}) + * @ORM\JoinColumn(onDelete="SET NULL") */ private ?Comment $pinnedComment = null; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index ed00c8611..95ec008d9 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -142,6 +142,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues */ private Collection $persons; + /** + * @ORM\ManyToMany(targetEntity=User::class) + * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer") + * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"accompanying_period_work:create"}) + */ + private Collection $referrers; + /** * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks") * @ORM\JoinTable(name="chill_person_accompanying_period_work_result") @@ -196,6 +205,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues $this->thirdParties = new ArrayCollection(); $this->persons = new ArrayCollection(); $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); + $this->referrers = new ArrayCollection(); } public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self @@ -227,6 +237,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this; } + public function addReferrer(User $referrer): self + { + if (!$this->referrers->contains($referrer)) { + $this->referrers[] = $referrer; + } + + return $this; + } + public function addResult(Result $result): self { if (!$this->results->contains($result)) { @@ -308,6 +327,14 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this->persons; } + /** + * @return Collection|User[] + */ + public function getReferrers(): Collection + { + return $this->referrers; + } + /** * @return Collection|Result[] */ @@ -382,6 +409,13 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this; } + public function removeReferrer(User $referrer): self + { + $this->referrers->removeElement($referrer); + + return $this; + } + public function removeResult(Result $result): self { $this->results->removeElement($result); diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php index 07c9f526c..ed3200370 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php @@ -124,6 +124,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @Serializer\Groups({"read", "docgen:read"}) + * @Serializer\Groups({"write"}) * @Serializer\Groups({"accompanying_period_work_evaluation:create"}) */ private ?DateTimeImmutable $maxDate = null; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index fab4b2845..fd07b0489 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -109,6 +109,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, * mappedBy="person", * cascade={"persist", "remove", "merge", "detach"}) + * @ORM\OrderBy({"startDate": "DESC"}) */ private $accompanyingPeriodParticipations; diff --git a/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php new file mode 100644 index 000000000..c9b11ea71 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php @@ -0,0 +1,30 @@ +security = $security; + } + + public function prePersistAccompanyingPeriodWork(AccompanyingPeriodWork $work): void + { + $work->addReferrer($this->security->getUser()); + } +} diff --git a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index 827dfb0a6..929fb2ae0 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -68,12 +68,14 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface } 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 History'), [ + 'route' => 'chill_person_accompanying_course_history', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 30]); + */ $menu->addChild($this->translator->trans('Accompanying Course Comment'), [ 'route' => 'chill_person_accompanying_period_comment_list', diff --git a/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php index 04f989d84..4635eb4fc 100644 --- a/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/SectionMenuBuilder.php @@ -22,15 +22,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class SectionMenuBuilder implements LocalMenuBuilderInterface { - /** - * @var AuthorizationCheckerInterface - */ - protected $authorizationChecker; + protected AuthorizationCheckerInterface $authorizationChecker; - /** - * @var TranslatorInterface - */ - protected $translator; + protected TranslatorInterface $translator; /** * SectionMenuBuilder constructor. @@ -63,6 +57,14 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface 'order' => 11, 'icons' => ['plus'], ]); + + $menu->addChild($this->translator->trans('Accompanying courses of users'), [ + 'route' => 'chill_course_list_reassign', + ]) + ->setExtras([ + 'order' => 12, + 'icons' => ['task'], + ]); } public static function getMenuIds(): array diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php index 3178aa6e2..3273e3a7d 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php @@ -87,9 +87,12 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository ->join('work.accompanyingPeriod', 'period') ->where( $qb->expr()->andX( - $qb->expr()->eq('period.user', ':user'), $qb->expr()->isNull('e.endDate'), - $qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval')) + $qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval')), + $qb->expr()->orX( + $qb->expr()->eq('period.user', ':user'), + $qb->expr()->isMemberOf(':user', 'work.referrers') + ) ) ) ->setParameters([ diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 9e67da458..dd27cf434 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -159,9 +159,12 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository ->join('w.accompanyingPeriod', 'period') ->where( $qb->expr()->andX( - $qb->expr()->eq('period.user', ':user'), $qb->expr()->gte('w.endDate', ':since'), - $qb->expr()->lte('w.startDate', ':until') + $qb->expr()->lte('w.startDate', ':until'), + $qb->expr()->orX( + $qb->expr()->eq('period.user', ':user'), + $qb->expr()->isMemberOf(':user', 'w.referrers') + ) ) ) ->setParameters([ diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php index 6e6c3ca44..f4c9a52a3 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Repository; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; @@ -41,6 +42,37 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC $this->centerResolverDispatcher = $centerResolverDispatcher; } + public function buildQueryOpenedAccompanyingCourseByUser(?User $user) + { + $qb = $this->accompanyingPeriodRepository->createQueryBuilder('ap'); + + $qb->where($qb->expr()->eq('ap.user', ':user')) + ->andWhere( + $qb->expr()->neq('ap.step', ':draft'), + $qb->expr()->orX( + $qb->expr()->isNull('ap.closingDate'), + $qb->expr()->gt('ap.closingDate', ':now') + ) + ) + ->setParameter('user', $user) + ->setParameter('now', new \DateTime('now')) + ->setParameter('draft', AccompanyingPeriod::STEP_DRAFT); + + return $qb; + } + + public function countByUserOpenedAccompanyingPeriod(?User $user): int + { + if (null === $user) { + return 0; + } + + return $this->buildQueryOpenedAccompanyingCourseByUser($user) + ->select('COUNT(ap)') + ->getQuery() + ->getSingleScalarResult(); + } + public function findByPerson( Person $person, string $role, @@ -92,4 +124,25 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC return $qb->getQuery()->getResult(); } + + /** + * @return array|AccompanyingPeriod[] + */ + public function findByUserOpenedAccompanyingPeriod(?User $user, array $orderBy = [], int $limit = 0, int $offset = 50): array + { + if (null === $user) { + return []; + } + + $qb = $this->buildQueryOpenedAccompanyingCourseByUser($user); + + $qb->setFirstResult($offset) + ->setMaxResults($limit); + + foreach ($orderBy as $field => $direction) { + $qb->addOrderBy('ap.'.$field, $direction); + } + + return $qb->getQuery()->getResult(); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php index 778e8d8fe..0c5af217f 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Repository; +use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\Person; interface AccompanyingPeriodACLAwareRepositoryInterface @@ -22,4 +23,8 @@ interface AccompanyingPeriodACLAwareRepositoryInterface ?int $limit = null, ?int $offset = null ): array; + + public function findByUserOpenedAccompanyingPeriod(?User $user, array $orderBy = [], int $limit = 0, int $offset = 50): array; + + public function countByUserOpenedAccompanyingPeriod(?User $user): int; } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php index 122b658bd..ab7006fd8 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php @@ -78,6 +78,16 @@ final class AccompanyingPeriodRepository implements ObjectRepository ->getResult(); } + public function findConfirmedByUser(User $user) + { + $qb = $this->createQueryBuilder('ap'); + $qb->where($qb->expr()->eq('ap.user', ':user')) + ->andWhere('ap.step', 'CONFIRMED') + ->setParameter('user', $user); + + return $qb; + } + public function findOneBy(array $criteria): ?AccompanyingPeriod { return $this->findOneBy($criteria); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss index 92542f178..fba0516a7 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss +++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss @@ -33,6 +33,8 @@ div.banner { padding-top: 1em; padding-bottom: 1em; div.contact { + display: flex; + align-content: center; & > * { margin-right: 1em; } diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue index a852d71a0..8ae7dfff4 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue @@ -14,24 +14,27 @@ -
- {{ $t('comment.created_by', [ - pinnedComment.creator.text, - $d(pinnedComment.createdAt.datetime, 'long') - ]) }} +
+ +
+ +