From 20a4950c60a6d493f7d4b637e68ed50f17d57284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 13:23:50 +0100 Subject: [PATCH 01/60] accompanying period work list for my, near end date --- .../AccompanyingCourseWorkApiController.php | 32 ++++++++++++++ .../AccompanyingPeriodWorkRepository.php | 42 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php index 95cbaf023..7b6013019 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php @@ -12,10 +12,21 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\MainBundle\Serializer\Model\Collection; +use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Annotation\Route; class AccompanyingCourseWorkApiController extends ApiController { + private AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository; + + public function __construct(AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository) + { + $this->accompanyingPeriodWorkRepository = $accompanyingPeriodWorkRepository; + } + protected function getContextForSerialization(string $action, Request $request, string $_format, $entity): array { switch ($action) { @@ -28,4 +39,25 @@ class AccompanyingCourseWorkApiController extends ApiController return parent::getContextForSerialization($action, $request, $_format, $entity); } + + /** + * @Route("/api/1.0/person/accompanying-period/work/my-near-end") + * + * @param Request $request + * @return JsonResponse + */ + public function myWorksNearEndDate(Request $request): JsonResponse + { + $since = (new \DateTimeImmutable('now'))->sub(new \DateInterval('P15D')); + $until = (new \DateTimeImmutable('now'))->add(new \DateInterval('P15D')); + $total = $this->accompanyingPeriodWorkRepository + ->countNearEndDateByUser($this->getUser(), $since, $until); + $paginator = $this->getPaginatorFactory()->create($total); + $works = $this->accompanyingPeriodWorkRepository + ->findNearEndDateByUser($this->getUser(), $since, $until, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + + $collection = new Collection($works, $paginator); + + return $this->json($collection, 200, [], ['groups' => ['read']]); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 23ccf57a9..b7ea9459e 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -11,10 +11,12 @@ declare(strict_types=1); namespace Chill\PersonBundle\Repository\AccompanyingPeriod; +use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; final class AccompanyingPeriodWorkRepository implements ObjectRepository @@ -111,4 +113,44 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return $qb; } + + public function findNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until, int $limit = 20, int $offset = 0): array + { + return $this->buildQueryNearEndDateByUser($user, $since, $until) + ->select('w') + ->setFirstResult($offset) + ->setMaxResults($limit) + ->getQuery() + ->getResult(); + } + + public function countNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until): int + { + return $this->buildQueryNearEndDateByUser($user, $since, $until) + ->select('count(w)')->getQuery()->getSingleScalarResult(); + } + + public function buildQueryNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until): QueryBuilder + { + $qb = $this->repository->createQueryBuilder('w'); + + $qb + ->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') + ) + ) + ->setParameters([ + 'user' => $user, + 'since' => $since, + 'until' => $until + ]); + + return $qb; + } + + } From c08bd76e4b6dfac6f33f929e9ce731f3275dce1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 21:52:16 +0100 Subject: [PATCH 02/60] adding parameter until and since on 'work near end' --- .../Controller/AccompanyingCourseWorkApiController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php index 7b6013019..96b3438dc 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php @@ -48,8 +48,10 @@ class AccompanyingCourseWorkApiController extends ApiController */ public function myWorksNearEndDate(Request $request): JsonResponse { - $since = (new \DateTimeImmutable('now'))->sub(new \DateInterval('P15D')); - $until = (new \DateTimeImmutable('now'))->add(new \DateInterval('P15D')); + $since = (new \DateTimeImmutable('now')) + ->sub(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); + $until = (new \DateTimeImmutable('now')) + ->add(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); $total = $this->accompanyingPeriodWorkRepository ->countNearEndDateByUser($this->getUser(), $since, $until); $paginator = $this->getPaginatorFactory()->create($total); From a786578cbe07c6039a4daeef77a223dc0df53352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 21:52:27 +0100 Subject: [PATCH 03/60] fix cs --- .../AccompanyingCourseWorkApiController.php | 45 ++++++----- .../Form/CreationPersonType.php | 6 +- .../AccompanyingPeriodWorkRepository.php | 79 +++++++++---------- 3 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php index 96b3438dc..7f3caa675 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkApiController.php @@ -14,6 +14,8 @@ namespace Chill\PersonBundle\Controller; use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\MainBundle\Serializer\Model\Collection; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; +use DateInterval; +use DateTimeImmutable; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; @@ -27,6 +29,26 @@ class AccompanyingCourseWorkApiController extends ApiController $this->accompanyingPeriodWorkRepository = $accompanyingPeriodWorkRepository; } + /** + * @Route("/api/1.0/person/accompanying-period/work/my-near-end") + */ + public function myWorksNearEndDate(Request $request): JsonResponse + { + $since = (new DateTimeImmutable('now')) + ->sub(new DateInterval('P' . $request->query->getInt('since', 15) . 'D')); + $until = (new DateTimeImmutable('now')) + ->add(new DateInterval('P' . $request->query->getInt('since', 15) . 'D')); + $total = $this->accompanyingPeriodWorkRepository + ->countNearEndDateByUser($this->getUser(), $since, $until); + $paginator = $this->getPaginatorFactory()->create($total); + $works = $this->accompanyingPeriodWorkRepository + ->findNearEndDateByUser($this->getUser(), $since, $until, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + + $collection = new Collection($works, $paginator); + + return $this->json($collection, 200, [], ['groups' => ['read']]); + } + protected function getContextForSerialization(string $action, Request $request, string $_format, $entity): array { switch ($action) { @@ -39,27 +61,4 @@ class AccompanyingCourseWorkApiController extends ApiController return parent::getContextForSerialization($action, $request, $_format, $entity); } - - /** - * @Route("/api/1.0/person/accompanying-period/work/my-near-end") - * - * @param Request $request - * @return JsonResponse - */ - public function myWorksNearEndDate(Request $request): JsonResponse - { - $since = (new \DateTimeImmutable('now')) - ->sub(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); - $until = (new \DateTimeImmutable('now')) - ->add(new \DateInterval('P'.$request->query->getInt('since', 15).'D')); - $total = $this->accompanyingPeriodWorkRepository - ->countNearEndDateByUser($this->getUser(), $since, $until); - $paginator = $this->getPaginatorFactory()->create($total); - $works = $this->accompanyingPeriodWorkRepository - ->findNearEndDateByUser($this->getUser(), $since, $until, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); - - $collection = new Collection($works, $paginator); - - return $this->json($collection, 200, [], ['groups' => ['read']]); - } } diff --git a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php index 82437eb30..a33858c02 100644 --- a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php @@ -61,13 +61,13 @@ final class CreationPersonType extends AbstractType 'required' => false, ]) ->add('phonenumber', TelType::class, [ - 'required' => false + 'required' => false, ]) ->add('mobilenumber', TelType::class, [ - 'required' => false + 'required' => false, ]) ->add('email', EmailType::class, [ - 'required' => false + 'required' => false, ]); if ($this->askCenters) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index b7ea9459e..60ad31de0 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Repository\AccompanyingPeriod; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; +use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; @@ -28,6 +29,28 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class); } + public function buildQueryNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): QueryBuilder + { + $qb = $this->repository->createQueryBuilder('w'); + + $qb + ->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') + ) + ) + ->setParameters([ + 'user' => $user, + 'since' => $since, + 'until' => $until, + ]); + + return $qb; + } + public function countByAccompanyingPeriod(AccompanyingPeriod $period): int { return $this->repository->countByAccompanyingPeriod($period); @@ -43,6 +66,12 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository ->getSingleScalarResult(); } + public function countNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): int + { + return $this->buildQueryNearEndDateByUser($user, $since, $until) + ->select('count(w)')->getQuery()->getSingleScalarResult(); + } + public function find($id): ?AccompanyingPeriodWork { return $this->repository->find($id); @@ -70,6 +99,16 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return $this->repository->findByAccompanyingPeriod($period, $orderBy, $limit, $offset); } + public function findNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until, int $limit = 20, int $offset = 0): array + { + return $this->buildQueryNearEndDateByUser($user, $since, $until) + ->select('w') + ->setFirstResult($offset) + ->setMaxResults($limit) + ->getQuery() + ->getResult(); + } + public function findOneBy(array $criteria): ?AccompanyingPeriodWork { return $this->repository->findOneBy($criteria); @@ -113,44 +152,4 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return $qb; } - - public function findNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until, int $limit = 20, int $offset = 0): array - { - return $this->buildQueryNearEndDateByUser($user, $since, $until) - ->select('w') - ->setFirstResult($offset) - ->setMaxResults($limit) - ->getQuery() - ->getResult(); - } - - public function countNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until): int - { - return $this->buildQueryNearEndDateByUser($user, $since, $until) - ->select('count(w)')->getQuery()->getSingleScalarResult(); - } - - public function buildQueryNearEndDateByUser(User $user, \DateTimeImmutable $since, \DateTimeImmutable $until): QueryBuilder - { - $qb = $this->repository->createQueryBuilder('w'); - - $qb - ->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') - ) - ) - ->setParameters([ - 'user' => $user, - 'since' => $since, - 'until' => $until - ]); - - return $qb; - } - - } From 1faa9812db22b59ebc1ed0c8f12cc91250ab08d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 22:24:48 +0100 Subject: [PATCH 04/60] fix variable name in work list page --- .../Resources/views/AccompanyingCourseWork/index.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig index 3bb34a22d..83a047c98 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig @@ -70,7 +70,7 @@ action: 'show', displayBadge: true, targetEntity: { name: 'person', id: p.id }, buttonText: p|chill_entity_render_string, - isDead: entity.deathdate is not null + isDead: p.deathdate is not null } %} {% endfor %} From 6ab8f95f7d914807257f99cff28510f8f37300f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 22:25:29 +0100 Subject: [PATCH 05/60] list of "my evaluation near end" --- ...nyingPeriodWorkEvaluationApiController.php | 39 +++++++- ...mpanyingPeriodWorkEvaluationRepository.php | 95 +++++++++++++++++++ .../AccompanyingPeriodWorkRepository.php | 2 +- 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php index de9433558..a1b857ac2 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php @@ -17,9 +17,14 @@ use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Serializer\Model\Collection; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; use Chill\PersonBundle\Entity\SocialWork\Evaluation; +use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationRepository; +use DateTimeImmutable; +use DateInterval; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\SerializerInterface; @@ -28,20 +33,28 @@ use function in_array; class AccompanyingPeriodWorkEvaluationApiController { + private AccompanyingPeriodWorkEvaluationRepository $accompanyingPeriodWorkEvaluationRepository; + private DocGeneratorTemplateRepository $docGeneratorTemplateRepository; private PaginatorFactory $paginatorFactory; private SerializerInterface $serializer; + private Security $security; + public function __construct( + AccompanyingPeriodWorkEvaluationRepository $accompanyingPeriodWorkEvaluationRepository, DocGeneratorTemplateRepository $docGeneratorTemplateRepository, SerializerInterface $serializer, - PaginatorFactory $paginatorFactory + PaginatorFactory $paginatorFactory, + Security $security ) { + $this->accompanyingPeriodWorkEvaluationRepository = $accompanyingPeriodWorkEvaluationRepository; $this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository; $this->serializer = $serializer; $this->paginatorFactory = $paginatorFactory; + $this->security = $security; } /** @@ -76,4 +89,28 @@ class AccompanyingPeriodWorkEvaluationApiController ] ), JsonResponse::HTTP_OK, [], true); } + + /** + * @Route("/api/1.0/person/accompanying-period/work/evaluation/my-near-end") + * @param Request $request + * @return JsonResponse + */ + public function myWorksNearEndDate(Request $request): JsonResponse + { + $total = $this->accompanyingPeriodWorkEvaluationRepository + ->countNearMaxDateByUser($this->security->getUser()); + $paginator = $this->paginatorFactory->create($total); + $works = $this->accompanyingPeriodWorkEvaluationRepository + ->findNearMaxDateByUser($this->security->getUser(), + $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + + $collection = new Collection($works, $paginator); + + return new JsonResponse( + $this->serializer->serialize($collection, 'json', ['groups' => 'read']), + JsonResponse::HTTP_OK, + [], + true + ); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php new file mode 100644 index 000000000..bf273b502 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php @@ -0,0 +1,95 @@ +repository = $entityManager->getRepository(AccompanyingPeriodWorkEvaluation::class); + } + + public function find($id): ?AccompanyingPeriodWorkEvaluation + { + return $this->repository->find($id); + } + + /** + * @return array|object[]|AccompanyingPeriodWorkEvaluation[] + */ + public function findAll(): array + { + return $this->repository->findAll(); + } + + /** + * @param array $criteria + * @param array|null $orderBy + * @param int $limit + * @param int $offset + * @return array|AccompanyingPeriodWorkEvaluation[]|object[] + */ + public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria): ?AccompanyingPeriodWorkEvaluation + { + return $this->repository->findOneBy($criteria); + } + + public function getClassName(): string + { + return AccompanyingPeriodWorkEvaluation::class; + } + + public function countNearMaxDateByUser(User $user): int + { + return $this->buildQueryNearMaxDateByUser($user) + ->select('count(e)')->getQuery()->getSingleScalarResult(); + } + + public function findNearMaxDateByUser(User $user, int $limit = 20, int $offset = 0): array + { + return $this->buildQueryNearMaxDateByUser($user) + ->select('e') + ->setFirstResult($offset) + ->setMaxResults($limit) + ->getQuery() + ->getResult(); + } + + private function buildQueryNearMaxDateByUser(User $user): QueryBuilder + { + $qb = $this->repository->createQueryBuilder('e'); + + $qb + ->join('e.accompanyingPeriodWork', 'work') + ->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')) + ) + ) + ->setParameters([ + 'user' => $user, + 'now' => new \DateTimeImmutable('now') + ]); + + return $qb; + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 60ad31de0..dfd556e2a 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -29,7 +29,7 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class); } - public function buildQueryNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): QueryBuilder + private function buildQueryNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): QueryBuilder { $qb = $this->repository->createQueryBuilder('w'); From 7e2fbf93f9956d82094ec43a80597708eec83933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 23:13:25 +0100 Subject: [PATCH 06/60] task: api endpoint for my tasks --- .../Controller/SingleTaskController.php | 34 +++++++++++++++---- .../ChillTaskBundle/Entity/AbstractTask.php | 12 +++++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php index 490d50da1..fae54b6ae 100644 --- a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php +++ b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php @@ -13,6 +13,7 @@ namespace Chill\TaskBundle\Controller; use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; +use Chill\MainBundle\Serializer\Model\Collection; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface; use Chill\MainBundle\Timeline\TimelineBuilder; @@ -31,6 +32,8 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\HttpFoundation\Exception\BadRequestException; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -431,10 +434,15 @@ final class SingleTaskController extends AbstractController * @return Response * @Route( * "/{_locale}/task/single-task/list/my", - * name="chill_task_singletask_my_tasks" + * name="chill_task_singletask_my_tasks", + * defaults={"_format": "html"} + * ) + * @Route( + * "/api/1.0/task/single-task/list/my", + * defaults={"_format": "json"} * ) */ - public function myTasksAction() + public function myTasksAction(string $_format) { $this->denyAccessUnlessGranted('ROLE_USER'); @@ -459,11 +467,23 @@ final class SingleTaskController extends AbstractController ] ); - return $this->render('@ChillTask/SingleTask/List/index_my_tasks.html.twig', [ - 'tasks' => $tasks, - 'paginator' => $paginator, - 'filter_order' => $filterOrder, - ]); + switch ($_format) { + case 'html': + return $this->render('@ChillTask/SingleTask/List/index_my_tasks.html.twig', [ + 'tasks' => $tasks, + 'paginator' => $paginator, + 'filter_order' => $filterOrder, + ]); + + case 'json': + $collection = new Collection($tasks, $paginator); + + return $this->json($collection, JsonResponse::HTTP_OK, [], + ['groups' => ['read']]); + + default: + throw new BadRequestException("format not supported: $format"); + } } /** diff --git a/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php b/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php index 8b44ebf8f..a4b154d2b 100644 --- a/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php +++ b/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; use function array_fill_keys; @@ -27,6 +28,9 @@ use function array_keys; * AbstractTask. * * @ORM\MappedSuperclass + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "single_task": SingleTask::class + * }) */ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface { @@ -35,6 +39,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * @ORM\ManyToOne( * targetEntity="\Chill\MainBundle\Entity\User" * ) + * @Serializer\Groups({"read"}) */ private $assignee; @@ -49,12 +54,14 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface /** * @var bool * @ORM\Column(name="closed", type="boolean", options={ "default": false }) + * @Serializer\Groups({"read"}) */ private $closed = false; /** * @var AccompanyingPeriod * @ORM\ManyToOne(targetEntity="\Chill\PersonBundle\Entity\AccompanyingPeriod") + * @Serializer\Groups({"read"}) */ private $course; @@ -62,6 +69,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * @var json * * @ORM\Column(name="current_states", type="json") + * @Serializer\Groups({"read"}) */ private $currentStates = []; @@ -69,6 +77,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * @var string * * @ORM\Column(name="description", type="text") + * @Serializer\Groups({"read"}) */ private $description = ''; @@ -77,6 +86,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * @ORM\ManyToOne( * targetEntity="\Chill\PersonBundle\Entity\Person" * ) + * @Serializer\Groups({"read"}) */ private $person; @@ -85,6 +95,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * * @ORM\Column(name="title", type="text") * @Assert\NotBlank + * @Serializer\Groups({"read"}) */ private $title = ''; @@ -92,6 +103,7 @@ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface * @var string * * @ORM\Column(name="type", type="string", length=255) + * @Serializer\Groups({"read"}) */ private $type; From eccc75aecf402ea830248b7a5a9d299750bab617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 23 Jan 2022 23:22:04 +0100 Subject: [PATCH 07/60] fix cs --- ...nyingPeriodWorkEvaluationApiController.php | 15 +++--- ...mpanyingPeriodWorkEvaluationRepository.php | 47 +++++++++++-------- .../AccompanyingPeriodWorkRepository.php | 44 ++++++++--------- .../Controller/SingleTaskController.php | 10 ++-- .../ChillTaskBundle/Entity/AbstractTask.php | 4 +- 5 files changed, 65 insertions(+), 55 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php index a1b857ac2..e82877637 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationApiController.php @@ -18,8 +18,6 @@ use Chill\MainBundle\Serializer\Model\Collection; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; use Chill\PersonBundle\Entity\SocialWork\Evaluation; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationRepository; -use DateTimeImmutable; -use DateInterval; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -39,10 +37,10 @@ class AccompanyingPeriodWorkEvaluationApiController private PaginatorFactory $paginatorFactory; - private SerializerInterface $serializer; - private Security $security; + private SerializerInterface $serializer; + public function __construct( AccompanyingPeriodWorkEvaluationRepository $accompanyingPeriodWorkEvaluationRepository, DocGeneratorTemplateRepository $docGeneratorTemplateRepository, @@ -92,8 +90,6 @@ class AccompanyingPeriodWorkEvaluationApiController /** * @Route("/api/1.0/person/accompanying-period/work/evaluation/my-near-end") - * @param Request $request - * @return JsonResponse */ public function myWorksNearEndDate(Request $request): JsonResponse { @@ -101,8 +97,11 @@ class AccompanyingPeriodWorkEvaluationApiController ->countNearMaxDateByUser($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $works = $this->accompanyingPeriodWorkEvaluationRepository - ->findNearMaxDateByUser($this->security->getUser(), - $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber()); + ->findNearMaxDateByUser( + $this->security->getUser(), + $paginator->getItemsPerPage(), + $paginator->getCurrentPageFirstItemNumber() + ); $collection = new Collection($works, $paginator); diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php index bf273b502..ca1a01157 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php @@ -1,5 +1,14 @@ repository = $entityManager->getRepository(AccompanyingPeriodWorkEvaluation::class); } + public function countNearMaxDateByUser(User $user): int + { + return $this->buildQueryNearMaxDateByUser($user) + ->select('count(e)')->getQuery()->getSingleScalarResult(); + } + public function find($id): ?AccompanyingPeriodWorkEvaluation { return $this->repository->find($id); @@ -34,10 +48,9 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository } /** - * @param array $criteria - * @param array|null $orderBy * @param int $limit * @param int $offset + * * @return array|AccompanyingPeriodWorkEvaluation[]|object[] */ public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array @@ -45,22 +58,6 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } - public function findOneBy(array $criteria): ?AccompanyingPeriodWorkEvaluation - { - return $this->repository->findOneBy($criteria); - } - - public function getClassName(): string - { - return AccompanyingPeriodWorkEvaluation::class; - } - - public function countNearMaxDateByUser(User $user): int - { - return $this->buildQueryNearMaxDateByUser($user) - ->select('count(e)')->getQuery()->getSingleScalarResult(); - } - public function findNearMaxDateByUser(User $user, int $limit = 20, int $offset = 0): array { return $this->buildQueryNearMaxDateByUser($user) @@ -71,6 +68,16 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository ->getResult(); } + public function findOneBy(array $criteria): ?AccompanyingPeriodWorkEvaluation + { + return $this->repository->findOneBy($criteria); + } + + public function getClassName(): string + { + return AccompanyingPeriodWorkEvaluation::class; + } + private function buildQueryNearMaxDateByUser(User $user): QueryBuilder { $qb = $this->repository->createQueryBuilder('e'); @@ -87,7 +94,7 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository ) ->setParameters([ 'user' => $user, - 'now' => new \DateTimeImmutable('now') + 'now' => new DateTimeImmutable('now'), ]); return $qb; diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index dfd556e2a..1b56b6cdf 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -29,28 +29,6 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class); } - private function buildQueryNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): QueryBuilder - { - $qb = $this->repository->createQueryBuilder('w'); - - $qb - ->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') - ) - ) - ->setParameters([ - 'user' => $user, - 'since' => $since, - 'until' => $until, - ]); - - return $qb; - } - public function countByAccompanyingPeriod(AccompanyingPeriod $period): int { return $this->repository->countByAccompanyingPeriod($period); @@ -152,4 +130,26 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return $qb; } + + private function buildQueryNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until): QueryBuilder + { + $qb = $this->repository->createQueryBuilder('w'); + + $qb + ->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') + ) + ) + ->setParameters([ + 'user' => $user, + 'since' => $since, + 'until' => $until, + ]); + + return $qb; + } } diff --git a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php index fae54b6ae..bac4c1a2a 100644 --- a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php +++ b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php @@ -478,11 +478,15 @@ final class SingleTaskController extends AbstractController case 'json': $collection = new Collection($tasks, $paginator); - return $this->json($collection, JsonResponse::HTTP_OK, [], - ['groups' => ['read']]); + return $this->json( + $collection, + JsonResponse::HTTP_OK, + [], + ['groups' => ['read']] + ); default: - throw new BadRequestException("format not supported: $format"); + throw new BadRequestException("format not supported: {$format}"); } } diff --git a/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php b/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php index a4b154d2b..267bd8bcd 100644 --- a/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php +++ b/src/Bundle/ChillTaskBundle/Entity/AbstractTask.php @@ -29,8 +29,8 @@ use function array_keys; * * @ORM\MappedSuperclass * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ - * "single_task": SingleTask::class - * }) + * "single_task": SingleTask::class + * }) */ abstract class AbstractTask implements HasCenterInterface, HasScopeInterface { From e23ef35b750aa16d28f141fb6bf81aa0d4dd0d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 24 Jan 2022 00:24:20 +0100 Subject: [PATCH 08/60] list of unread notificaiton api endpoint --- .../Controller/NotificationApiController.php | 45 +++++++++++- .../Repository/NotificationRepository.php | 23 ++++++ .../Normalizer/NotificationNormalizer.php | 70 +++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php diff --git a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php index 8751aa50a..c50564d58 100644 --- a/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/NotificationApiController.php @@ -13,13 +13,17 @@ namespace Chill\MainBundle\Controller; use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Pagination\PaginatorFactory; +use Chill\MainBundle\Repository\NotificationRepository; use Chill\MainBundle\Security\Authorization\NotificationVoter; +use Chill\MainBundle\Serializer\Model\Collection; use Doctrine\ORM\EntityManagerInterface; use RuntimeException; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Security; +use Symfony\Component\Serializer\SerializerInterface; use UnexpectedValueException; /** @@ -29,12 +33,26 @@ class NotificationApiController { private EntityManagerInterface $entityManager; + private NotificationRepository $notificationRepository; + + private PaginatorFactory $paginatorFactory; + private Security $security; - public function __construct(EntityManagerInterface $entityManager, Security $security) - { + private SerializerInterface $serializer; + + public function __construct( + EntityManagerInterface $entityManager, + NotificationRepository $notificationRepository, + PaginatorFactory $paginatorFactory, + Security $security, + SerializerInterface $serializer + ) { $this->entityManager = $entityManager; + $this->notificationRepository = $notificationRepository; + $this->paginatorFactory = $paginatorFactory; $this->security = $security; + $this->serializer = $serializer; } /** @@ -53,6 +71,29 @@ class NotificationApiController return $this->markAs('unread', $notification); } + /** + * @Route("/my/unread") + */ + public function myUnreadNotifications(): JsonResponse + { + $total = $this->notificationRepository->countUnreadByUser($this->security->getUser()); + $paginator = $this->paginatorFactory->create($total); + $notifications = $this->notificationRepository->findUnreadByUser( + $this->security->getUser(), + $paginator->getItemsPerPage(), + $paginator->getCurrentPageFirstItemNumber() + ); + dump($notifications); + $collection = new Collection($notifications, $paginator); + + return new JsonResponse( + $this->serializer->serialize($collection, 'json', ['groups' => ['read']]), + JsonResponse::HTTP_OK, + [], + true + ); + } + private function markAs(string $target, Notification $notification): JsonResponse { if (!$this->security->isGranted(NotificationVoter::NOTIFICATION_TOGGLE_READ_STATUS, $notification)) { diff --git a/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php b/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php index 35ec64114..1580cfa6a 100644 --- a/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/NotificationRepository.php @@ -179,6 +179,29 @@ final class NotificationRepository implements ObjectRepository return $this->repository->findOneBy($criteria, $orderBy); } + /** + * @return array|Notification[] + */ + public function findUnreadByUser(User $user, int $limit = 20, int $offset = 0): array + { + $rsm = new Query\ResultSetMappingBuilder($this->em); + $rsm->addRootEntityFromClassMetadata(Notification::class, 'cmn'); + + $sql = 'SELECT ' . $rsm->generateSelectClause(['cmn' => 'cmn']) . ' ' . + 'FROM chill_main_notification cmn ' . + 'WHERE ' . + 'EXISTS (select 1 FROM chill_main_notification_addresses_unread cmnau WHERE cmnau.user_id = :userId and cmnau.notification_id = cmn.id) ' . + 'ORDER BY cmn.date DESC ' . + 'LIMIT :limit OFFSET :offset'; + + $nq = $this->em->createNativeQuery($sql, $rsm) + ->setParameter('userId', $user->getId()) + ->setParameter('limit', $limit) + ->setParameter('offset', $offset); + + return $nq->getResult(); + } + public function getClassName() { return Notification::class; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php new file mode 100644 index 000000000..89f2285f2 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/NotificationNormalizer.php @@ -0,0 +1,70 @@ +notificationHandlerManager = $notificationHandlerManager; + $this->entityManager = $entityManager; + $this->security = $security; + } + + /** + * @param Notification $object + * + * @return array|ArrayObject|bool|float|int|string|void|null + */ + public function normalize($object, ?string $format = null, array $context = []) + { + dump($object); + $entity = $this->entityManager + ->getRepository($object->getRelatedEntityClass()) + ->find($object->getRelatedEntityId()); + + return [ + 'type' => 'notification', + 'addressees' => $this->normalizer->normalize($object->getAddressees(), $format, $context), + 'date' => $this->normalizer->normalize($object->getDate(), $format, $context), + 'isRead' => $object->isReadBy($this->security->getUser()), + 'message' => $object->getMessage(), + 'relatedEntityClass' => $object->getRelatedEntityClass(), + 'relatedEntityId' => $object->getRelatedEntityId(), + 'sender' => $this->normalizer->normalize($object->getSender(), $format, $context), + 'title' => $object->getTitle(), + 'entity' => null !== $entity ? $this->normalizer->normalize($entity, $format, $context) : null, + ]; + } + + public function supportsNormalization($data, ?string $format = null) + { + return $data instanceof Notification && 'json' === $format; + } +} From c42f62de4c9abf2b1dafff6c80142c26b426ccb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 24 Jan 2022 00:32:47 +0100 Subject: [PATCH 09/60] fix phpstan errors: undefined variable or type invalid --- phpstan-baseline.neon | 5 ---- phpstan-critical.neon | 30 ------------------- phpstan-types.neon | 5 ---- .../AccompanyingPeriodWorkRepository.php | 21 ++----------- .../Controller/SingleTaskController.php | 2 +- 5 files changed, 4 insertions(+), 59 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d996ff3b8..20970a799 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -80,11 +80,6 @@ parameters: count: 1 path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php - - - message: "#^Foreach overwrites \\$action with its value variable\\.$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - message: "#^Foreach overwrites \\$action with its value variable\\.$#" count: 1 diff --git a/phpstan-critical.neon b/phpstan-critical.neon index b214654bf..632356aa6 100644 --- a/phpstan-critical.neon +++ b/phpstan-critical.neon @@ -30,36 +30,6 @@ parameters: count: 2 path: src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php - - - message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - - - message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:countBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - - - message: "#^Undefined variable\\: \\$action$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - - - message: "#^Undefined variable\\: \\$limit$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - - - message: "#^Undefined variable\\: \\$offset$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - - - message: "#^Undefined variable\\: \\$orderBy$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - message: "#^Variable variables are not allowed\\.$#" count: 4 diff --git a/phpstan-types.neon b/phpstan-types.neon index 949ff774a..2cc55255a 100644 --- a/phpstan-types.neon +++ b/phpstan-types.neon @@ -400,11 +400,6 @@ parameters: count: 1 path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php - - - message: "#^Method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid return type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\QueryBuilder\\.$#" - count: 1 - path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" count: 3 diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 1b56b6cdf..70e972aa5 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Repository\AccompanyingPeriod; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; +use Chill\PersonBundle\Entity\SocialWork\SocialAction; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; @@ -97,22 +98,6 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository return AccompanyingPeriodWork::class; } - public function toDelete() - { - $qb = $this->buildQueryBySocialActionWithDescendants($action); - $qb->select('g'); - - foreach ($orderBy as $sort => $order) { - $qb->addOrderBy('g.' . $sort, $order); - } - - return $qb - ->setMaxResults($limit) - ->setFirstResult($offset) - ->getQuery() - ->getResult(); - } - private function buildQueryBySocialActionWithDescendants(SocialAction $action): QueryBuilder { $actions = $action->getDescendantsWithThis(); @@ -122,9 +107,9 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository $orx = $qb->expr()->orX(); $i = 0; - foreach ($actions as $action) { + foreach ($actions as $a) { $orx->add(":action_{$i} MEMBER OF g.socialActions"); - $qb->setParameter("action_{$i}", $action); + $qb->setParameter("action_{$i}", $a); } $qb->where($orx); diff --git a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php index bac4c1a2a..61ca37ba0 100644 --- a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php +++ b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php @@ -486,7 +486,7 @@ final class SingleTaskController extends AbstractController ); default: - throw new BadRequestException("format not supported: {$format}"); + throw new BadRequestException("format not supported: {$_format}"); } } From 320d11671aa37e72b5f0ab3799376c23d95c8087 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 10:54:08 +0100 Subject: [PATCH 10/60] prepare homepage_widget template --- .../Resources/public/chill/chillmain.scss | 15 ++++++ .../Resources/views/Homepage/index.html.twig | 46 +++++++++++++++++++ .../views/Homepage/sticky_button.html.twig | 10 ++++ .../Resources/views/layout.html.twig | 40 ++++++++-------- 4 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Homepage/sticky_button.html.twig diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss index 39f8b3f8a..99d31e103 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss @@ -490,3 +490,18 @@ div.popover { div.v-toast { z-index: 10000!important; } + +// +div.sticky-buttons { + position: fixed; + bottom: 3em; + right: 2em; + .btn-circle { + width: 60px; height: 60px; + border-radius: 50%; + text-align: center; + padding: 0.9rem 1rem; + display: block; + margin-bottom: 0.35rem; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig new file mode 100644 index 000000000..24aa8aec9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig @@ -0,0 +1,46 @@ +
+ + {# vue component #} +
+ + + + {% include '@ChillMain/Homepage/sticky_button.html.twig' %} +
+ +{% block css %} +{% endblock %} + +{% block js %} +{% endblock %} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/Homepage/sticky_button.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Homepage/sticky_button.html.twig new file mode 100644 index 000000000..27dd4fe5d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Homepage/sticky_button.html.twig @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig b/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig index a123ce405..15d57cff3 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig @@ -59,26 +59,26 @@ {% endif %} {% block content %} - - - - {{ chill_widget('homepage', {} ) }} + + + {# DISABLED {{ chill_widget('homepage', {} ) }} #} + + {% include '@ChillMain/Homepage/index.html.twig' %} + {% endblock %} From 0e2772336f0ae69c603db242ea62ca28123f18a7 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 11:27:31 +0100 Subject: [PATCH 11/60] create new app vue homepage_widget, with store --- .../public/page/homepage_widget/index.js | 16 +++++++ .../public/vuejs/HomepageWidget/App.vue | 46 +++++++++++++++++++ .../public/vuejs/HomepageWidget/js/i18n.js | 11 +++++ .../public/vuejs/HomepageWidget/js/store.js | 14 ++++++ .../Resources/views/Homepage/index.html.twig | 35 +------------- .../ChillMainBundle/chill.webpack.config.js | 1 + 6 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/public/page/homepage_widget/index.js create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js diff --git a/src/Bundle/ChillMainBundle/Resources/public/page/homepage_widget/index.js b/src/Bundle/ChillMainBundle/Resources/public/page/homepage_widget/index.js new file mode 100644 index 000000000..698302ebb --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/page/homepage_widget/index.js @@ -0,0 +1,16 @@ +import { createApp } from 'vue'; +import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'; +import { appMessages } from 'ChillMainAssets/vuejs/HomepageWidget/js/i18n'; +import { store } from 'ChillMainAssets/vuejs/HomepageWidget/js/store'; +import App from 'ChillMainAssets/vuejs/HomepageWidget/App'; + +const i18n = _createI18n(appMessages); + +const app = createApp({ + template: ``, +}) +.use(store) +.use(i18n) +.component('app', App) +.mount('#homepage_widget') +; diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue new file mode 100644 index 000000000..dee05b285 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -0,0 +1,46 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js new file mode 100644 index 000000000..0eff7fa96 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js @@ -0,0 +1,11 @@ +const appMessages = { + fr: { + + } +}; + +Object.assign(appMessages.fr); + +export { + appMessages +}; \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js new file mode 100644 index 000000000..bb9af47e6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js @@ -0,0 +1,14 @@ +import 'es6-promise/auto'; +import { createStore } from 'vuex'; + +const debug = process.env.NODE_ENV !== 'production'; + +const store = createStore({ + strict: debug, + state: {}, + getters: {}, + mutations: {}, + actions: {}, +}); + +export { store }; \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig index 24aa8aec9..ba53f8fdd 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Homepage/index.html.twig @@ -3,44 +3,13 @@ {# vue component #}
- - {% include '@ChillMain/Homepage/sticky_button.html.twig' %} {% block css %} + {{ encore_entry_link_tags('page_homepage_widget') }} {% endblock %} {% block js %} + {{ encore_entry_script_tags('page_homepage_widget') }} {% endblock %} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/chill.webpack.config.js b/src/Bundle/ChillMainBundle/chill.webpack.config.js index 113d326c1..93f71dd94 100644 --- a/src/Bundle/ChillMainBundle/chill.webpack.config.js +++ b/src/Bundle/ChillMainBundle/chill.webpack.config.js @@ -53,6 +53,7 @@ module.exports = function(encore, entries) encore.addEntry('page_login', __dirname + '/Resources/public/page/login/index.js'); encore.addEntry('page_location', __dirname + '/Resources/public/page/location/index.js'); encore.addEntry('page_workflow_show', __dirname + '/Resources/public/page/workflow-show/index.js'); + encore.addEntry('page_homepage_widget', __dirname + '/Resources/public/page/homepage_widget/index.js'); buildCKEditor(encore); From 502f2aceed94b4a68b1df301978045246c89c82c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 12:44:39 +0100 Subject: [PATCH 12/60] init sub-components and active tab mechanism --- .../public/vuejs/HomepageWidget/App.vue | 85 ++++++++++++++++--- .../HomepageWidget/MyAccompanyingCourses.vue | 13 +++ .../public/vuejs/HomepageWidget/MyCustoms.vue | 13 +++ .../vuejs/HomepageWidget/MyEvaluations.vue | 13 +++ .../vuejs/HomepageWidget/MyNotifications.vue | 13 +++ .../public/vuejs/HomepageWidget/MyTasks.vue | 13 +++ .../public/vuejs/HomepageWidget/MyWorks.vue | 13 +++ .../public/vuejs/HomepageWidget/js/i18n.js | 6 +- 8 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue index dee05b285..ea50a7bf7 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -2,43 +2,102 @@ - +
+ + + + + + + + + + + + +
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue new file mode 100644 index 000000000..31107b564 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue new file mode 100644 index 000000000..cc7831104 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue new file mode 100644 index 000000000..019628a28 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue new file mode 100644 index 000000000..a8b811fbd --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue new file mode 100644 index 000000000..c61cf51b2 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue new file mode 100644 index 000000000..9f7f71bc4 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js index 0eff7fa96..e67b7f5d3 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js @@ -1,6 +1,10 @@ const appMessages = { fr: { - + my_works: "Actions d'accompagnement", + my_evaluations: "Évaluations", + my_task: "Tâches", + my_accompanying_courses: "Parcours", + my_notifications: "Notifications", } }; From fb720a382f0ebffe030aa3c47b2981b8454323de Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 14:32:57 +0100 Subject: [PATCH 13/60] sticky buttons smaller --- .../ChillMainBundle/Resources/public/chill/chillmain.scss | 4 ++-- .../Resources/public/vuejs/HomepageWidget/App.vue | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss index 99d31e103..a1d9ee519 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss @@ -497,10 +497,10 @@ div.sticky-buttons { bottom: 3em; right: 2em; .btn-circle { - width: 60px; height: 60px; + width: 50px; height: 50px; border-radius: 50%; text-align: center; - padding: 0.9rem 1rem; + padding: 0.45rem 0.7rem; display: block; margin-bottom: 0.35rem; } diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue index ea50a7bf7..cf8ad2a1d 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -102,4 +102,7 @@ export default { \ No newline at end of file From 8fce27a128ee205a781f4e54e9d09e9da673f64c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 15:43:45 +0100 Subject: [PATCH 14/60] move styles in better place --- .../Resources/public/chill/chillmain.scss | 15 --------------- .../Resources/public/chill/scss/buttons.scss | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss index a1d9ee519..39f8b3f8a 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/chillmain.scss @@ -490,18 +490,3 @@ div.popover { div.v-toast { z-index: 10000!important; } - -// -div.sticky-buttons { - position: fixed; - bottom: 3em; - right: 2em; - .btn-circle { - width: 50px; height: 50px; - border-radius: 50%; - text-align: center; - padding: 0.45rem 0.7rem; - display: block; - margin-bottom: 0.35rem; - } -} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss index 1eb437a2a..8f69d7955 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss @@ -133,3 +133,18 @@ $chill-theme-buttons: ( .btn-sm, .btn-group-sm > .btn { min-width: 36px; } + +// Homepage special fast action buttons +div.sticky-buttons { + position: fixed; + bottom: 3em; + right: 2em; + .btn-circle { + width: 50px; height: 50px; + border-radius: 50%; + text-align: center; + padding: 0.45rem 0.7rem; + display: block; + margin-bottom: 0.35rem; + } +} \ No newline at end of file From e4629ed599921dc14f185fa91d62daf18ffe58bc Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 17:30:09 +0100 Subject: [PATCH 15/60] store first makeFetch, with loading spinner --- .../Resources/public/chill/scss/buttons.scss | 2 +- .../public/vuejs/HomepageWidget/App.vue | 12 +++- .../HomepageWidget/MyAccompanyingCourses.vue | 12 +++- .../public/vuejs/HomepageWidget/MyCustoms.vue | 13 +++- .../public/vuejs/HomepageWidget/js/store.js | 59 +++++++++++++++++-- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss index 8f69d7955..fda1cb5ed 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/buttons.scss @@ -145,6 +145,6 @@ div.sticky-buttons { text-align: center; padding: 0.45rem 0.7rem; display: block; - margin-bottom: 0.35rem; + margin-bottom: 0.5rem; } } \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue index cf8ad2a1d..973dacad6 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -13,6 +13,7 @@ :class="{'active': activeTab === 'MyWorks'}" @click="selectTab('MyWorks')"> {{ $t('my_works') }} + +
@@ -74,6 +78,7 @@ import MyEvaluations from './MyEvaluations'; import MyTasks from './MyTasks'; import MyAccompanyingCourses from './MyAccompanyingCourses'; import MyNotifications from './MyNotifications'; +import { mapState, mapGetters } from "vuex"; export default { name: "App", @@ -91,11 +96,16 @@ export default { } }, computed: { + ...mapState([ + 'loading', + ]), + ...mapGetters([ + ]) }, methods: { selectTab(tab) { - console.log('load tab content', tab); this.activeTab = tab; + this.$store.dispatch('getByTab', tab); } } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue index 31107b564..f94a042dc 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyAccompanyingCourses.vue @@ -3,8 +3,18 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue index cc7831104..28a2ec93b 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyCustoms.vue @@ -1,5 +1,11 @@ \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js index bb9af47e6..b9888da7b 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js @@ -1,14 +1,65 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; +import { makeFetch } from "ChillMainAssets/lib/api/apiMethods"; const debug = process.env.NODE_ENV !== 'production'; +const isEmpty = (obj) => { + return obj + && Object.keys(obj).length === 0 + && Object.getPrototypeOf(obj) === Object.prototype; +}; + const store = createStore({ strict: debug, - state: {}, - getters: {}, - mutations: {}, - actions: {}, + state: { + accompanyingCourses: {}, + errorMsg: [], + loading: false + }, + getters: { + isAccompanyingCoursesLoaded(state) { + return !isEmpty(state.accompanyingCourses); + }, + }, + mutations: { + addCourses(state, courses) { + console.log('addCourses', courses); + state.accompanyingCourses = courses; + }, + setLoading(state, bool) { + state.loading = bool; + }, + catchError(state, error) { + state.errorMsg.push(error); + } + }, + actions: { + getByTab({ commit, getters }, tab) { + switch (tab) { + case 'MyAccompanyingCourses': + if (!getters.isAccompanyingCoursesLoaded) { + commit('setLoading', true); + const url = `/api/1.0/person/accompanying-period/work/my-near-end`; + makeFetch('GET', url) + .then((response) => { + commit('addCourses', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + } + break; + case 'MyCustoms': + break; + default: + throw 'tab '+ tab; + + } + } + }, }); export { store }; \ No newline at end of file From 2144b247b3a726492b9de500fc4791dffb2c75e6 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 18:20:29 +0100 Subject: [PATCH 16/60] store all makeFetch, with isLoaded check --- .../public/vuejs/HomepageWidget/App.vue | 8 +- .../vuejs/HomepageWidget/MyEvaluations.vue | 12 +- .../vuejs/HomepageWidget/MyNotifications.vue | 12 +- .../public/vuejs/HomepageWidget/MyTasks.vue | 13 +- .../public/vuejs/HomepageWidget/MyWorks.vue | 12 +- .../public/vuejs/HomepageWidget/js/store.js | 131 +++++++++++++++++- 6 files changed, 178 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue index 973dacad6..d357a2b00 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -78,7 +78,7 @@ import MyEvaluations from './MyEvaluations'; import MyTasks from './MyTasks'; import MyAccompanyingCourses from './MyAccompanyingCourses'; import MyNotifications from './MyNotifications'; -import { mapState, mapGetters } from "vuex"; +import { mapState } from "vuex"; export default { name: "App", @@ -99,8 +99,10 @@ export default { ...mapState([ 'loading', ]), - ...mapGetters([ - ]) + // just to see all in devtool : + ...mapState({ + state: (state) => state, + }), }, methods: { selectTab(tab) { diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue index 019628a28..1998e2fac 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyEvaluations.vue @@ -3,8 +3,18 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue index a8b811fbd..78e0fdb0f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyNotifications.vue @@ -3,8 +3,18 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue index c61cf51b2..0378ea092 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyTasks.vue @@ -3,8 +3,19 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue index 9f7f71bc4..b3bfdbbb7 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorks.vue @@ -3,8 +3,18 @@ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js index b9888da7b..991486dab 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js @@ -1,6 +1,12 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; import { makeFetch } from "ChillMainAssets/lib/api/apiMethods"; +import MyCustoms from "../MyCustoms"; +import MyWorks from "../MyWorks"; +import MyEvaluations from "../MyEvaluations"; +import MyTasks from "../MyTasks"; +import MyAccompanyingCourses from "../MyAccompanyingCourses"; +import MyNotifications from "../MyNotifications"; const debug = process.env.NODE_ENV !== 'production'; @@ -13,20 +19,62 @@ const isEmpty = (obj) => { const store = createStore({ strict: debug, state: { + works: {}, + evaluations: {}, + tasks: { + warning: {}, + alert: {} + }, accompanyingCourses: {}, + notifications: {}, errorMsg: [], loading: false }, getters: { + isWorksLoaded(state) { + return !isEmpty(state.works); + }, + isEvaluationsLoaded(state) { + return !isEmpty(state.evaluations); + }, + isTasksWarningLoaded(state) { + return !isEmpty(state.tasks.warning); + }, + isTasksAlertLoaded(state) { + return !isEmpty(state.tasks.alert); + }, isAccompanyingCoursesLoaded(state) { return !isEmpty(state.accompanyingCourses); }, + isNotificationsLoaded(state) { + return !isEmpty(state.notifications); + }, }, mutations: { + addWorks(state, works) { + console.log('addWorks', works); + state.works = works; + }, + addEvaluations(state, evaluations) { + console.log('addEvaluations', evaluations); + state.evaluations = evaluations; + }, + addTasksWarning(state, tasks) { + console.log('addTasksWarning', tasks); + state.tasks.warning = tasks; + }, + addTasksAlert(state, tasks) { + console.log('addTasksAlert', tasks); + state.tasks.alert = tasks; + }, addCourses(state, courses) { console.log('addCourses', courses); state.accompanyingCourses = courses; }, + addNotifications(state, notifications) { + console.log('addNotifications', notifications); + state.notifications = notifications; + }, setLoading(state, bool) { state.loading = bool; }, @@ -37,10 +85,73 @@ const store = createStore({ actions: { getByTab({ commit, getters }, tab) { switch (tab) { + case 'MyCustoms': + break; + case 'MyWorks': + if (!getters.isWorksLoaded) { + commit('setLoading', true); + const url = `/api/1.0/person/accompanying-period/work/my-near-end`; + makeFetch('GET', url) + .then((response) => { + commit('addWorks', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + ; + } + break; + case 'MyEvaluations': + if (!getters.isEvaluationsLoaded) { + commit('setLoading', true); + const url = `/api/1.0/person/accompanying-period/work/evaluation/my-near-end`; + makeFetch('GET', url) + .then((response) => { + commit('addEvaluations', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + ; + } + break; + case 'MyTasks': + if (!(getters.isTasksWarningLoaded && getters.isTasksAlertLoaded)) { + commit('setLoading', true); + const + urlWarning = `/api/1.0/task/single-task/list/my?f[q]=&f[checkboxes][status][]=warning&f[checkboxes][states][]=new&f[checkboxes][states][]=in_progress`, + urlAlert = `/api/1.0/task/single-task/list/my?f[q]=&f[checkboxes][status][]=alert&f[checkboxes][states][]=new&f[checkboxes][states][]=in_progress` //&f[f]= + ; + makeFetch('GET', urlWarning) + .then((response) => { + commit('addTasksWarning', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + ; + makeFetch('GET', urlAlert) + .then((response) => { + commit('addTasksAlert', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + ; + } + break; case 'MyAccompanyingCourses': if (!getters.isAccompanyingCoursesLoaded) { commit('setLoading', true); - const url = `/api/1.0/person/accompanying-period/work/my-near-end`; + const url = `/api/1.0/`; makeFetch('GET', url) .then((response) => { commit('addCourses', response); @@ -50,13 +161,27 @@ const store = createStore({ commit('catchError', error); throw error; }) + ; } break; - case 'MyCustoms': + case 'MyNotifications': + if (!getters.isNotificationsLoaded) { + commit('setLoading', true); + const url = `/api/1.0/main/notification/my/unread`; + makeFetch('GET', url) + .then((response) => { + commit('addNotifications', response); + commit('setLoading', false); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) + ; + } break; default: throw 'tab '+ tab; - } } }, From fc1ed8b71ee761ba99dd44d14d6ab5676a206913 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 25 Jan 2022 20:08:39 +0100 Subject: [PATCH 17/60] display table with notifications datas, prepare others tabs to render datas --- .../public/vuejs/HomepageWidget/App.vue | 12 ++-- .../HomepageWidget/MyAccompanyingCourses.vue | 13 +++- .../vuejs/HomepageWidget/MyEvaluations.vue | 13 +++- .../vuejs/HomepageWidget/MyNotifications.vue | 65 ++++++++++++++++++- .../public/vuejs/HomepageWidget/MyTasks.vue | 24 ++++++- .../public/vuejs/HomepageWidget/MyWorks.vue | 13 +++- .../public/vuejs/HomepageWidget/TabTable.vue | 21 ++++++ .../public/vuejs/HomepageWidget/js/i18n.js | 32 +++++++-- 8 files changed, 175 insertions(+), 18 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/TabTable.vue diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue index d357a2b00..85f20b455 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue @@ -12,7 +12,7 @@ - {{ $t('my_works') }} + {{ $t('my_works.tab') }} @@ -20,28 +20,28 @@ - {{ $t('my_evaluations') }} + {{ $t('my_evaluations.tab') }}