diff --git a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php index b11601589..90ec16ec3 100644 --- a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php +++ b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php @@ -472,7 +472,11 @@ final class SingleTaskController extends AbstractController $filterOrder->getQueryString(), $flags, $paginator->getCurrentPageFirstItemNumber(), - $paginator->getItemsPerPage() + $paginator->getItemsPerPage(), + [ + 'startDate' => 'DESC', + 'endDate' => 'DESC', + ] ); return $this->render('@ChillTask/SingleTask/List/index.html.twig', [ @@ -694,6 +698,7 @@ final class SingleTaskController extends AbstractController } + /* protected function getPersonParam(EntityManagerInterface $em) { $person = $em->getRepository(Person::class) @@ -722,6 +727,7 @@ final class SingleTaskController extends AbstractController return $user; } + */ /** * Creates a form to delete a Task entity by id. @@ -750,34 +756,40 @@ final class SingleTaskController extends AbstractController public function listCourseTasks( AccompanyingPeriod $course, - SingleTaskRepository $taskRepository, FormFactoryInterface $formFactory, Request $request ): Response { - - $em = $this->getDoctrine()->getManager(); - - $tasks = $taskRepository - ->findBy( - array('course' => $course) - ); - - $form = $formFactory->createNamed(null, SingleTaskListType::class, null, [ - 'accompanyingCourse' => $course, - 'method' => Request::METHOD_GET, - 'csrf_protection' => false, - 'add_type' => true - ]); + $filterOrder = $this->buildFilterOrder(); + $flags = \array_merge( + $filterOrder->getCheckboxData('status'), + \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states')) + ); + $nb = $this->singleTaskAclAwareRepository->countByCourse( + $course, + $filterOrder->getQueryString(), + $flags + ); + $paginator = $this->paginatorFactory->create($nb); + $tasks = $this->singleTaskAclAwareRepository->findByCourse( + $course, + $filterOrder->getQueryString(), + $flags, + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage(), + [ + 'startDate' => 'DESC', + 'endDate' => 'DESC', + ] + ); return $this->render( - '@ChillTask/SingleTask/index.html.twig', + '@ChillTask/SingleTask/AccompanyingCourse/list.html.twig', [ 'tasks' => $tasks, 'accompanyingCourse' => $course, - 'layout' => '@ChillPerson/AccompanyingCourse/layout.html.twig', - 'form' => $form->createView(), - 'title' => $this->translator->trans('Tasks for this accompanying period') + 'paginator' => $paginator, + 'filter_order' => $filterOrder ]); } diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php index bc5124d95..cd3f819f4 100644 --- a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php +++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php @@ -2,20 +2,32 @@ namespace Chill\TaskBundle\Repository; +use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; +use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\TaskBundle\Entity\SingleTask; +use Chill\TaskBundle\Security\Authorization\TaskVoter; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Security\Core\Security; final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepositoryInterface { + private AuthorizationHelperInterface $authorizationHelper; private EntityManagerInterface $em; private Security $security; + private CenterResolverDispatcher $centerResolverDispatcher; - public function __construct(EntityManagerInterface $em, Security $security) - { + public function __construct( + CenterResolverDispatcher $centerResolverDispatcher, + EntityManagerInterface $em, + Security $security, + AuthorizationHelperInterface $authorizationHelper + ) { + $this->centerResolverDispatcher = $centerResolverDispatcher; $this->em = $em; $this->security = $security; + $this->authorizationHelper = $authorizationHelper; } public function findByCurrentUsersTasks( @@ -26,12 +38,83 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository ?array $orderBy = [] ): array { $qb = $this->buildQueryMyTasks($pattern, $flags); + + return $this->getResult($qb, $start, $limit, $orderBy); + } + + public function countByCurrentUsersTasks( + ?string $pattern = null, + ?array $flags = [] + ): int { + return $this->buildQueryMyTasks($pattern, $flags) + ->select('COUNT(t)') + ->getQuery()->getSingleScalarResult(); + } + + public function findByCourse( + AccompanyingPeriod $course, + ?string $pattern = null, + ?array $flags = [], + ?int $start = 0, + ?int $limit = 50, + ?array $orderBy = [] + ): array { + $qb = $this->buildQueryByCourse($course, $pattern, $flags); + $qb = $this->addACL($qb, $course); + + return $this->getResult($qb, $start, $limit, $orderBy); + } + + public function countByCourse( + AccompanyingPeriod $course, + ?string $pattern = null, + ?array $flags = [] + ): int { + $qb = $this->buildQueryByCourse($course, $pattern, $flags); + + return $this + ->addACL($qb, $course) + ->select('COUNT(t)') + ->getQuery()->getSingleScalarResult(); + } + + public function buildQueryByCourse( + AccompanyingPeriod $course, + ?string $pattern = null, + ?array $flags = [] + ) : QueryBuilder { + $qb = $this->buildBaseQuery($pattern, $flags); + + return $qb + ->andWhere($qb->expr()->eq('t.course', ':course')) + ->setParameter('course', $course) + ; + } + + public function buildQueryMyTasks( + ?string $pattern = null, + ?array $flags = [] + ): QueryBuilder { + $qb = $this->buildBaseQuery($pattern, $flags); + + return $qb + ->andWhere($qb->expr()->eq('t.assignee', ':user')) + ->setParameter('user', $this->security->getUser()) + ; + } + + public function getResult( + QueryBuilder $qb, + ?int $start = 0, + ?int $limit = 50, + ?array $orderBy = [] + ): array { $qb->select('t'); $qb ->setFirstResult($start) ->setMaxResults($limit) - ; + ; foreach ($orderBy as $field => $direction) { $qb->addOrderBy('t.'.$field, $direction); @@ -40,25 +123,24 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository return $qb->getQuery()->getResult(); } - public function countByCurrentUsersTasks( - ?string $pattern = null, - ?array $flags = [] - ): int { - $qb = $this->buildQueryMyTasks($pattern, $flags); - $qb->select('COUNT(t)'); + public function addACL( + QueryBuilder $qb, + $entity + ): QueryBuilder { + $scopes = $this->authorizationHelper->getReachableScopes($this->security->getUser(), + TaskVoter::SHOW, $this->centerResolverDispatcher->resolveCenter($entity)); - return $qb->getQuery()->getSingleScalarResult(); + return $qb->andWhere($qb->expr()->in('t.circle', ':scopes')) + ->setParameter('scopes', $scopes); } - public function buildQueryMyTasks( + public function buildBaseQuery ( ?string $pattern = null, ?array $flags = [] ): QueryBuilder { $qb = $this->em->createQueryBuilder(); $qb ->from(SingleTask::class, 't') - ->where($qb->expr()->eq('t.assignee', ':user')) - ->setParameter('user', $this->security->getUser()) ; if (!empty($pattern)) { diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php index b5d83a5f0..55c5f07ff 100644 --- a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php +++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php @@ -2,9 +2,27 @@ namespace Chill\TaskBundle\Repository; +use Chill\PersonBundle\Entity\AccompanyingPeriod; + interface SingleTaskAclAwareRepositoryInterface { public function findByCurrentUsersTasks(?string $pattern = null, ?array $flags = [], ?int $start = 0, ?int $limit = 50, ?array $orderBy = []): array; public function countByCurrentUsersTasks(?string $pattern = null, ?array $flags = []): int; + + public function findByCourse( + AccompanyingPeriod $course, + ?string $pattern = null, + ?array $flags = [], + ?int $start = 0, + ?int $limit = 50, + ?array $orderBy = [] + ): array; + + public function countByCourse( + AccompanyingPeriod $course, + ?string $pattern = null, + ?array $flags = [] + ): int; + } diff --git a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/AccompanyingCourse/list.html.twig b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/AccompanyingCourse/list.html.twig index be491e2f9..480ea705f 100644 --- a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/AccompanyingCourse/list.html.twig +++ b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/AccompanyingCourse/list.html.twig @@ -1,106 +1,42 @@ -{% if tasks|length > 0 %} -

{{ title|trans }}

+{% extends '@ChillPerson/AccompanyingCourse/layout.html.twig' %} - - - {% for task in tasks %} - - - - - {% endfor %} - -
-
- {{ task.title }} -
+{% block title 'Tasks for this accompanying period'|trans %} -
- {{ task_workflow_metadata(task, 'definition.name')|trans }} -
+{% block content %} +
-
- {% for place in workflow_marked_places(task) %} - {{ place|trans }} - {% endfor %} - {% if task.assignee is not null %} -
- {{ 'By'|trans }} : - {{ task.assignee.username }}
- {% endif %} -
+

{{ block('title') }}

- {% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %} -
-
    - {% if task.startDate is not null %} -
  • - - {{ task.startDate|format_date('medium') }} -
  • - {% endif %} - {% if task.warningDate is not null %} -
  • - - {{ task.warningDate|format_date('medium') }} -
  • - {% endif %} - {% if task.endDate is not null %} -
  • - - {{ task.endDate|format_date('medium') }} -
  • - {% endif %} -
-
- {% endif %} + {{ filter_order|chill_render_filter_order_helper }} -
-
    - {% if workflow_transitions(task)|length > 0 %} -
  • -
    - - -
    -
  • - {% endif %} + {% if tasks|length == 0 %} +

    {{ 'Any tasks'|trans }}

    + {% else %} +
    + {% for task in tasks %} + {% include 'ChillTaskBundle:SingleTask/List:index_item.html.twig' with { 'showContext' : false } %} + {% endfor %} +
    + {% endif %} -
  • - -
  • + {{ chill_pagination(paginator) }} - {# {% if is_granted('CHILL_TASK_TASK_UPDATE', task) %} #} -
  • - -
  • - {# {% endif %} #} + - {# {% if is_granted('CHILL_TASK_TASK_DELETE', task) %} #} -
  • - -
  • - {# {% endif %} #} -
-
-{% endif %} + +{% endblock %} - +{% block css %} + {{ encore_entry_link_tags('page_task_list') }} +{% endblock %} +{% block js %} + {{ encore_entry_script_tags('page_task_list') }} +{% endblock %} diff --git a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig index c7c622692..14bac167e 100644 --- a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig +++ b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig @@ -14,130 +14,7 @@ {% else %}
{% for task in tasks %} -
-
-
-
- {{ task.title }} - {% for place in workflow_marked_places(task) %} - - {{ place|trans }} - - {% endfor %} -
- {% if task.type != 'task_default'%} - - {{ task_workflow_metadata(task, 'definition.name')|trans }} - - {% endif %} -
- {% if task.person is not null %} - - {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { - targetEntity: { name: 'person', id: task.person.id }, - action: 'show', - displayBadge: true, - buttonText: task.person|chill_entity_render_string - } %} - - {% elseif task.course is not null %} - - - - - {% for part in task.course.currentParticipations %} - {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { - targetEntity: { name: 'person', id: part.person.id }, - action: 'show', - displayBadge: true, - buttonText: part.person|chill_entity_render_string - } %} - {% endfor %} - - {% endif %} -
-
- - -
-
- {% if task.assignee is not null %} -
- {{ 'By'|trans }} : - {{ task.assignee.username }} -
- {% endif %} - - {% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %} -
-
    - {% if task.startDate is not null %} -
  • - - {{ task.startDate|format_date('medium') }} -
  • - {% endif %} - {% if task.warningDate is not null %} -
  • - - {{ task.warningDate|format_date('medium') }} -
  • - {% endif %} - {% if task.endDate is not null %} -
  • - - {{ task.endDate|format_date('medium') }} -
  • - {% endif %} -
-
- {% endif %} -
- -
- -
-
- - -
-
+ {% include 'ChillTaskBundle:SingleTask/List:index_item.html.twig' with { 'showContext' : true} %} {% endfor %}
{% endif %} diff --git a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index_item.html.twig b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index_item.html.twig new file mode 100644 index 000000000..284769448 --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index_item.html.twig @@ -0,0 +1,125 @@ +
+
+
+
+ {{ task.title }} + {% for place in workflow_marked_places(task) %} + + {{ place|trans }} + + {% endfor %} +
+ {% if task.type != 'task_default'%} + + {{ task_workflow_metadata(task, 'definition.name')|trans }} + + {% endif %} + {% if showContext %} +
+ {% if task.person is not null %} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + targetEntity: { name: 'person', id: task.person.id }, + action: 'show', + displayBadge: true, + buttonText: task.person|chill_entity_render_string + } %} + + {% elseif task.course is not null %} + + + + + {% for part in task.course.currentParticipations %} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + targetEntity: { name: 'person', id: part.person.id }, + action: 'show', + displayBadge: true, + buttonText: part.person|chill_entity_render_string + } %} + {% endfor %} + + {% endif %} +
+ {% endif %} +
+ + +
+
+ {% if task.assignee is not null %} +
+ {{ task.assignee|chill_entity_render_box }} +
+ {% endif %} + + {% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %} +
+
    + {% if task.startDate is not null %} +
  • + + {{ task.startDate|format_date('medium') }} +
  • + {% endif %} + {% if task.warningDate is not null %} +
  • + + {{ task.warningDate|format_date('medium') }} +
  • + {% endif %} + {% if task.endDate is not null %} +
  • + + {{ task.endDate|format_date('medium') }} +
  • + {% endif %} +
+
+ {% endif %} +
+ +
+ +
+
+ + +
+