diff --git a/Controller/SingleTaskController.php b/Controller/SingleTaskController.php index a887b0b01..a4cf1c4ef 100644 --- a/Controller/SingleTaskController.php +++ b/Controller/SingleTaskController.php @@ -18,6 +18,8 @@ use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\TaskBundle\Repository\SingleTaskRepository; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Security\Authorization\PersonVoter; +use Chill\PersonBundle\Entity\PersonRepository; +use Chill\MainBundle\Entity\UserRepository; class SingleTaskController extends Controller { @@ -41,7 +43,7 @@ class SingleTaskController extends Controller ->find($personId); if ($person === null) { - throw $this->createNotFoundException("Invalid person id"); + $this->createNotFoundException("Invalid person id"); } $task = (new SingleTask()) @@ -280,44 +282,96 @@ class SingleTaskController extends Controller return $form; } - + + /** * @Route( - * "/{_locale}/task/task/list/person/{personId}", - * name="chill_task_task_list_by_person" + * "/{_locale}/task/singletask/list", + * name="chill_task_singletask_list" * ) */ public function listAction( - Request $request, - Person $personId, - PaginatorFactory $paginatorFactory, - SingleTaskRepository $taskRepository + Request $request, + PaginatorFactory $paginatorFactory, + SingleTaskRepository $taskRepository, + PersonRepository $personRepository ) { - $person = $personId; /* @var $viewParams array The parameters for the view */ - $viewParams['person'] = $person; + /* @var $params array The parameters for the query */ + + $viewParams['person'] = null; + $params['person'] = null; + $viewParams['user'] = null; + $params['user'] = null; + $viewParams['center'] = null; + $params['center'] = null; + + // Get parameters from url + if ($request->query->has('person_id')) { + $personId = $request->query->get('person_id'); + $person = $personRepository->find($personId); + + if ($person === null) { + throw $this->createNotFoundException("This person ' $personId ' does not exist."); + } + + $this->denyAccessUnlessGranted(PersonVoter::SEE, $person); + + $viewParams['person'] = $person; + $params['person'] = $person; + } + + if ($request->query->has('user_id')) { + + $userId = $request->query->get('user_id'); + $user = $this->getDoctrine()->getManager() + ->getRepository('ChillMainBundle:User') + ->find($userId); + + if ($user === null) { + throw $this->createNotFoundException("This user ' $userId ' does not exist."); + } + + $viewParams['user'] = $user; + $params['user'] = $user; + } + + if ($request->query->has('scope_id')) { + + $scopeId = $request->query->get('scope_id'); + $scope = $this->getDoctrine()->getManager() + ->getRepository('ChillMainBundle:Scope') + ->find($scopeId); + + if ($scope === null) { + throw $this->createNotFoundException("This scope' $scopeId 'does not exist."); + } + + $viewParams['scope'] = $scope; + $params['scope'] = $scope; + } + // collect parameters for filter - $params['person'] = $person; $possibleStatuses = \array_merge(SingleTaskRepository::DATE_STATUSES, [ 'closed' ]); $statuses = $request->query->get('status', $possibleStatuses); - + // check for invalid statuses $diff = \array_diff($statuses, $possibleStatuses); if (count($diff) > 0) { return new Response( - 'date_status not allowed: '. \implode(', ', $diff), + 'date_status not allowed: '. \implode(', ', $diff), Response::HTTP_BAD_REQUEST ); } - + $viewParams['isSingleStatus'] = $singleStatus = count($statuses) === 1; - + foreach($statuses as $status) { - if($request->query->has('status') + if($request->query->has('status') && FALSE === \in_array($status, $statuses)) { continue; } - + // different query if regarding to date or 'closed' if (in_array($status, SingleTaskRepository::DATE_STATUSES)) { $params['date_status'] = $status; @@ -326,23 +380,30 @@ class SingleTaskController extends Controller $params['date_status'] = null; $params['is_closed'] = true; } - + $count = $taskRepository ->countByParameters($params, $this->getUser()) ; $paginator = $paginatorFactory->create($count); + $viewParams['single_task_'.$status.'_count'] = $count; $viewParams['single_task_'.$status.'_paginator'] = $paginator; $viewParams['single_task_'.$status.'_tasks'] = $taskRepository - ->findByParameters($params, $this->getUser(), - $singleStatus ? $paginator->getCurrentPage()->getFirstItemNumber() : 0, + ->findByParameters($params, $this->getUser(), + $singleStatus ? $paginator->getCurrentPage()->getFirstItemNumber() : 0, $singleStatus ? $paginator->getItemsPerPage() : 10) ; } - - return $this->render('ChillTaskBundle:Task:index.html.twig', $viewParams); + + if ($request->query->has('person_id')){ + $viewParams['layout'] = 'ChillPersonBundle::layout.html.twig'; + } else { + $viewParams['layout'] = 'ChillMainBundle::layout.html.twig'; + } + + return $this->render('ChillTaskBundle:SingleTask:index.html.twig', $viewParams); } - + protected function getPersonParam(Request $request, EntityManagerInterface $em) { $person = $em->getRepository(Person::class) @@ -358,7 +419,7 @@ class SingleTaskController extends Controller return $person; } - + protected function getUserParam(Request $request, EntityManagerInterface $em) { $user = $em->getRepository(User::class) diff --git a/Controller/TaskController.php b/Controller/TaskController.php index d90ddf08c..0648225f0 100644 --- a/Controller/TaskController.php +++ b/Controller/TaskController.php @@ -16,12 +16,12 @@ class TaskController extends Controller { /** * Apply a transition to a task - * + * * @Route( * "/{_locale}/task/transition/{kind}/{taskId}/{transition}", * name="chill_task_task_transition" * ) - * + * * @param string $kind * @param int $taskId * @param string $transition @@ -32,7 +32,7 @@ class TaskController extends Controller * @return Response */ public function applyTransitionAction( - $kind, + $kind, $taskId, $transition, SingleTaskRepository $singleTaskRepository, @@ -51,32 +51,32 @@ class TaskController extends Controller ); break; default: - return new Response("The type '$kind' is not implemented", + return new Response("The type '$kind' is not implemented", Response::HTTP_BAD_REQUEST); } - + if (NULL === $task) { - $this->createHttpNotFoundException("task with id '$taskId' and type " + $this->createNotFoundException("task with id '$taskId' and type " . "'$type' does not exists"); } - + // we simply check that the user can see the task. Other ACL checks // should be performed using `guard` events. $this->denyAccessUnlessGranted(TaskVoter::SHOW, $task); - + $workflow = $registry->get($task); - + if ($workflow->can($task, $transition)) { $workflow->apply($task, $transition); - + $em->flush(); - + $this->addFlash('success', 'The transition is sucessfully appliyed'); } else { $this->addFlash('error', 'The transition could not be appliyed'); } - + return $this->redirect($request->query->get('return_path', $defaultReturnPath)); } } diff --git a/Repository/SingleTaskRepository.php b/Repository/SingleTaskRepository.php index c4a3d3bc9..9f7d0f0c5 100644 --- a/Repository/SingleTaskRepository.php +++ b/Repository/SingleTaskRepository.php @@ -14,35 +14,35 @@ use Doctrine\DBAL\Types\Type; */ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository { - + const DATE_STATUS_ENDED = 'ended'; const DATE_STATUS_WARNING = 'warning'; const DATE_STATUS_CURRENT = 'current'; const DATE_STATUS_NOT_STARTED = 'not_started'; - + const DATE_STATUSES = [ self::DATE_STATUS_ENDED, self::DATE_STATUS_WARNING, self::DATE_STATUS_CURRENT, self::DATE_STATUS_NOT_STARTED ]; - + /** * * @var AuthorizationHelper */ protected $authorizationHelper; - + public function setAuthorizationHelper(AuthorizationHelper $authorizationHelper) { $this->authorizationHelper = $authorizationHelper; } - + /** - * Count the tasks for given parameters. - * + * Count the tasks for given parameters. + * * The parameters are describe in @see SingleTaskRepository::filterByParameters. - * + * * @see SingleTaskRepository::filterByParameters * @param array $params * @param User $currentUser @@ -52,26 +52,28 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository { $qb = $this->createQueryBuilder('st') ->select('COUNT(st)'); - + $this->buildQuery($qb, $params, $currentUser); - + return (int) $qb ->getQuery() ->getSingleScalarResult() ; } - + /** * Find task for given parameters. - * - * Available parameters: - * + * + * Available parameters: + * * - `person` : filter by person associated with the task ; + * - `user` : filter by user that created the task ; + * - `scope` : filter by scope associated with the task ; * - `date_status`: type of task. To choose between : - * `ended`, `warning`, `current`, `not_started` - * - `is_closed`: boolean. Indicate if the tasks must be closed (true) or + * `ended`, `warning`, `current`, `not_started` ; + * - `is_closed`: boolean. Indicate if the tasks must be closed (true) or * opened - * + * * @param type $params * @param User $currentUser * @param int $firstResult @@ -81,56 +83,69 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository public function findByParameters($params, User $currentUser, int $firstResult = 0, int $maxResults = 50) { $qb = $this->createQueryBuilder('st'); - + $this->buildQuery($qb, $params, $currentUser); - + $qb ->setMaxResults($maxResults) ->setFirstResult($firstResult) ; - + return $qb ->getQuery() ->getResult() ; } - + protected function buildQuery(QueryBuilder $qb, $params, User $currentUser) { $this->buildACLQuery($qb, $currentUser); - + if (\array_key_exists('person', $params) and !empty($params['person'])) { $qb->andWhere($qb->expr()->eq('st.person', ':person')); $qb->setParameter('person', $params['person']); } - + + if (\array_key_exists('user', $params) and !empty($params['user'])) { + $qb->andWhere($qb->expr()->eq('st.assignee', ':user')); + $qb->setParameter('user', $params['user']); + } + + if (\array_key_exists('scope', $params) and !empty($params['scope'])) { + $qb->andWhere($qb->expr()->eq('st.circle', ':scope')); + $qb->setParameter('scope', $params['scope']); + } + + if (\array_key_exists('date_status', $params) and !empty($params['date_status'])) { $this->addTypeFilter($qb, $params); } - + if (\array_key_exists('is_closed', $params)) { $qb->andWhere($this->buildIsClosed($qb, !$params['is_closed'])); } + + } - - protected function addTypeFilter(QueryBuilder $qb, $params) + + protected function addTypeFilter(QueryBuilder $qb, $params) { $andWhere = $qb->expr()->andX(); - + switch ($params['date_status']) { - case self::DATE_STATUS_ENDED: + case self::DATE_STATUS_ENDED: $andWhere ->add($this->buildNowIsAfterEndDate($qb)) ; break; - + case self::DATE_STATUS_WARNING: $andWhere ->add($this->buildNowIsAfterEndDate($qb, true)) ->add($this->buildNowIsAfterWarningDate($qb)) ; break; - + case self::DATE_STATUS_CURRENT: // st.endDate is NULL or (st.endDate is not null and st.endDate < now)) $andWhere @@ -139,7 +154,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository ->add($this->buildNowIsAfterStartDate($qb, false)) ; break; - + case self::DATE_STATUS_NOT_STARTED: $andWhere ->add($this->buildNowIsAfterEndDate($qb, true)) @@ -150,7 +165,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository $qb->setParameter('now', new \DateTime('today'), Type::DATE); $qb->andWhere($andWhere); } - + private function buildNowIsAfterEndDate(QueryBuilder $qb, $negative = false) { if ($negative === false) { @@ -169,7 +184,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository ; } } - + private function buildNowIsAfterWarningDate(QueryBuilder $qb, bool $negative = false) { if ($negative === false) { @@ -195,7 +210,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository ; } } - + private function buildNowIsAfterStartDate(QueryBuilder $qb, bool $negative = false) { if ($negative === false) { @@ -211,7 +226,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository ; } } - + private function buildIsClosed(QueryBuilder $qb, bool $negative = false) { if ($negative === false) { @@ -220,8 +235,8 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository return $qb->expr()->eq('st.closed', "'FALSE'"); } } - - + + protected function buildACLQuery(QueryBuilder $qb, User $currentUser) { if (NULL === $this->authorizationHelper) { @@ -230,23 +245,23 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository . "to initialize this repository or use the method " . "`setAuthorizationHelper`"); } - + $role = new Role(TaskVoter::SHOW); $qb->join('st.person', 'p'); - + $centers = $this->authorizationHelper ->getReachableCenters($currentUser, $role) ; - + $i = 0; $where = $qb->expr()->orX(); - + foreach($centers as $center) { $circles = $this->authorizationHelper ->getReachableCircles($currentUser, $role, $center); - + $centerWhere = $qb->expr()->andX(); - + $centerWhere->add($qb->expr()->eq('p.center', ':center_'.$i)); $qb->setParameter('center_'.$i, $center); $centerWhere->add($qb->expr()->in('st.circle', ':circles_'.$i)); @@ -254,7 +269,7 @@ class SingleTaskRepository extends \Doctrine\ORM\EntityRepository $where->add($centerWhere); $i ++; } - + $qb->where($where); } } diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 85d9b9f83..7d242163e 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -5,9 +5,9 @@ Description: Description Assignee: 'Personne assignée' Scope: Cercle 'Start date': 'Date de début' -'End date': 'Date de fin' +'End date': "Date d'échéance" 'Warning date': "Date d'avertissement" -'Warning interval': "Délai d'avertissement" +'Warning interval': "Délai d'avertissement de la date d'échéance" 'N': '' 'Unit': '' Task: Tâche @@ -17,15 +17,15 @@ Scope: Cercle Date: Date User: Utilisateur 'Task list': 'Liste de tâches' -'Tasks with expired deadline': 'Tâches avec une date limite dépassée' +'Tasks with expired deadline': "Tâches avec une date d'échéance dépassée" 'Tasks with warning deadline reached': "Tâches avec une date d'avertissement atteinte" 'Current tasks': 'Tâches en cours' 'Tasks not started': 'Tâches non commencées' -'Task start date': 'Date de début de la tâche' -'Task warning date': "Date d'avertissement de la tâche" -'Task end date': 'Date de fin de la tâche' -'Task type': 'Type de tâche' -'Task status': 'Status de la tâche' +'Task start date': 'Date de début' +'Task warning date': "Date d'avertissement" +'Task end date': "Date d'échéance" +'Task type': 'Type' +'Task status': 'Statut' 'Edit the task': 'Éditer la tâche' 'Edit task': 'Éditer la tâche' 'Save task': 'Enregistrer la tâche' diff --git a/Resources/views/Task/index.html.twig b/Resources/views/SingleTask/_list.html.twig similarity index 78% rename from Resources/views/Task/index.html.twig rename to Resources/views/SingleTask/_list.html.twig index 93fdb82ac..1fdb7efc6 100644 --- a/Resources/views/Task/index.html.twig +++ b/Resources/views/SingleTask/_list.html.twig @@ -1,34 +1,4 @@ -{# - * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -#} -{% extends "ChillPersonBundle::layout.html.twig" %} - -{% set activeRouteKey = 'chill_task_single_task_new' %} - -{% block title %}{{ 'Task list'|trans }}{% endblock %} - -{% macro thead() %} - -{% endmacro %} - -{% macro row(task) %} - -{% endmacro %} - -{% macro date_status(title, tasks, count, paginator, status, isSingleStatus, person) %} +{% macro date_status(title, tasks, count, paginator, status, isSingleStatus, person, user) %} {% if tasks|length > 0 %}

{{ title|trans }}

@@ -52,7 +22,7 @@ {% for place in workflow_marked_places(task) %} {{ place }} {% endfor %} - + {% for transition in workflow_transitions(task) %} {{ task_workflow_metadata(task, 'transition.verb', transition) }} {% endfor %} @@ -82,7 +52,7 @@ - + {% if isSingleStatus %} {% if tasks|length > paginator.getTotalItems %} {{ chill_pagination(paginator) }} @@ -91,23 +61,45 @@ {% else %} {% endif %} @@ -116,9 +108,7 @@ {% import _self as helper %} -{# filter tasks #} -{% block personcontent %}

{{ 'Task list'|trans }}

{% if single_task_ended_tasks is defined %} @@ -136,7 +126,7 @@ {% if single_task_not_started_tasks is defined %} {{ helper.date_status('Tasks not started', single_task_not_started_tasks, single_task_not_started_count, single_task_not_started_paginator, 'not_started', isSingleStatus, person) }} {% endif %} - + {% if single_task_closed_tasks is defined %} {{ helper.date_status('Closed', single_task_closed_tasks, single_task_closed_count, single_task_closed_paginator, 'closed', isSingleStatus, person) }} {% endif %} @@ -144,11 +134,16 @@ {% if isSingleStatus == false %} {% endif %} - -{% endblock %} diff --git a/Resources/views/SingleTask/edit.html.twig b/Resources/views/SingleTask/edit.html.twig index ba6515b74..cc82eea62 100644 --- a/Resources/views/SingleTask/edit.html.twig +++ b/Resources/views/SingleTask/edit.html.twig @@ -34,7 +34,6 @@ {{ form_row(form.endDate) }} {{ form_row(form.warningInterval) }} - {{ form_widget(form) }} diff --git a/Resources/views/SingleTask/index.html.twig b/Resources/views/SingleTask/index.html.twig new file mode 100644 index 000000000..94759c632 --- /dev/null +++ b/Resources/views/SingleTask/index.html.twig @@ -0,0 +1,43 @@ +{# + * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +#} + +{% extends layout %} + +{% set activeRouteKey = 'chill_task_single_task_new' %} + +{% block title %}{{ 'Task list'|trans }}{% endblock %} + +{% macro thead() %} + +{% endmacro %} + +{% macro row(task) %} + +{% endmacro %} + + +{# filter tasks #} + +{% if person is not null and user is null %} + {% block personcontent %} + {% include 'ChillTaskBundle:SingleTask:_list.html.twig' %} + {% endblock %} +{% elseif user is not null and person is null %} + {% block content %} + {% include 'ChillTaskBundle:SingleTask:_list.html.twig' %} + {% endblock %} +{% endif %}