diff --git a/Controller/SingleTaskController.php b/Controller/SingleTaskController.php index 8456e0e5b..f163b57d0 100644 --- a/Controller/SingleTaskController.php +++ b/Controller/SingleTaskController.php @@ -75,7 +75,7 @@ class SingleTaskController extends Controller if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); - + $dispatcher->dispatch(TaskEvent::PERSIST, new TaskEvent($task)); $em->flush(); @@ -133,8 +133,12 @@ class SingleTaskController extends Controller throw $this->createNotFoundException('Unable to find Task entity.'); } + $timeline = $this->get('chill.main.timeline_builder') + ->getTimelineHTML('task', array('task' => $task)); + return $this->render('ChillTaskBundle:SingleTask:show.html.twig', array( 'task' => $task, + 'timeline' => $timeline )); } @@ -146,8 +150,8 @@ class SingleTaskController extends Controller * ) */ public function editAction( - Request $request, - $id, + Request $request, + $id, TranslatorInterface $translator ) { /* @var $taskRepository SingleTaskRepository */ @@ -213,7 +217,7 @@ class SingleTaskController extends Controller * ) */ public function deleteAction( - Request $request, + Request $request, $id, TranslatorInterface $translator ) { @@ -221,7 +225,7 @@ class SingleTaskController extends Controller $taskRepository = $this->get('chill_task.single_task_repository'); $task = $taskRepository->find($id); - + if (!$task) { throw $this->createNotFoundException('Unable to find Task entity.'); } @@ -321,18 +325,18 @@ class SingleTaskController extends Controller } /** - * + * * Arguments: * - user_id * - scope_id * - person_id * - hide_form (hide the form to filter the tasks) * - status: date state, amongst SingleTaskRepository::DATE_STATUSES, or 'closed' - * + * * @Route( * "/{_locale}/task/singletask/list", * name="chill_task_singletask_list", - * options={ "menus": { + * options={ "menus": { * "person" : { "order": 400, "label": "Associated tasks" } , * "section": { "order": 400, "label": "Tasks", "icons": "tasks" } * }} @@ -354,7 +358,7 @@ class SingleTaskController extends Controller $params['user'] = null; $viewParams['center'] = null; $params['center'] = null; - + // Get parameters from url if (!empty($request->query->get('person_id', NULL))) { $personId = $request->query->getInt('person_id'); @@ -469,7 +473,7 @@ class SingleTaskController extends Controller $form->handleRequest($request); - return $this->render('ChillTaskBundle:SingleTask:index.html.twig', + return $this->render('ChillTaskBundle:SingleTask:index.html.twig', \array_merge($viewParams, [ 'form' => $form->createView() ])); } diff --git a/Resources/config/services/timeline.yml b/Resources/config/services/timeline.yml index 50187f14b..4903dc2cb 100644 --- a/Resources/config/services/timeline.yml +++ b/Resources/config/services/timeline.yml @@ -5,4 +5,9 @@ services: $registry: '@Symfony\Component\Workflow\Registry' tags: - { name: 'chill.timeline', context: 'person' } - \ No newline at end of file + Chill\TaskBundle\Timeline\SingleTaskTaskLifeCycleEventTimelineProvider: + arguments: + $em: '@Doctrine\ORM\EntityManagerInterface' + $registry: '@Symfony\Component\Workflow\Registry' + tags: + - { name: 'chill.timeline', context: 'task' } diff --git a/Resources/views/SingleTask/show.html.twig b/Resources/views/SingleTask/show.html.twig index 11667a4e9..805c01887 100644 --- a/Resources/views/SingleTask/show.html.twig +++ b/Resources/views/SingleTask/show.html.twig @@ -81,6 +81,11 @@ {% endif %} + {% if timeline is not null %} +

{{"Timeline"|trans}}

+ {{ timeline|raw }} + {% endif %} + - {% endblock %} diff --git a/Resources/views/Timeline/single_task_transition_task_context.html.twig b/Resources/views/Timeline/single_task_transition_task_context.html.twig new file mode 100644 index 000000000..57b48aa16 --- /dev/null +++ b/Resources/views/Timeline/single_task_transition_task_context.html.twig @@ -0,0 +1,13 @@ +
+

+ {{ event.datetime|localizeddate('long', 'short') }} + / {{ 'Task'|trans }} / + {% if transition is not null %} + {{ task_workflow_metadata(event.task, 'transition.sentence', transition)|trans({ '%user%': event.author.username }) }} + "{{ event.task.title }}" + {% else %} + {{ '%user% has created the task'|trans({ '%user%': event.author.username }) }} + "{{ event.task.title }}" + {% endif %} +

+
diff --git a/Timeline/SingleTaskTaskLifeCycleEventTimelineProvider.php b/Timeline/SingleTaskTaskLifeCycleEventTimelineProvider.php new file mode 100644 index 000000000..4f107f1cd --- /dev/null +++ b/Timeline/SingleTaskTaskLifeCycleEventTimelineProvider.php @@ -0,0 +1,132 @@ + + * + * 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 . + */ +namespace Chill\TaskBundle\Timeline; + +use Chill\MainBundle\Timeline\TimelineProviderInterface; +use Doctrine\ORM\EntityManagerInterface; +use Chill\TaskBundle\Entity\Task\SingleTaskPlaceEvent; +use Chill\TaskBundle\Entity\SingleTask; +use Symfony\Component\Workflow\Registry; +use Symfony\Component\Workflow\Workflow; + +/** + * + * + * @author Julien Fastré + */ +class SingleTaskTaskLifeCycleEventTimelineProvider implements TimelineProviderInterface +{ + /** + * + * @var EntityManagerInterface + */ + protected $em; + + /** + * + * @var Registry + */ + protected $registry; + + const TYPE = 'chill_task.transition'; + + public function __construct(EntityManagerInterface $em, Registry $registry) + { + $this->em = $em; + $this->registry = $registry; + } + + public function fetchQuery($context, $args) + { + if ($context !== 'task') { + throw new \LogicException(sprintf('%s is not able ' + . 'to render context %s', self::class, $context)); + } + + $metadata = $this->em + ->getClassMetadata(SingleTaskPlaceEvent::class); + $singleTaskMetadata = $this->em + ->getClassMetadata(SingleTask::class); + + return [ + 'id' => sprintf('%s.%s.%s', $metadata->getSchemaName(), $metadata->getTableName(), $metadata->getColumnName('id')), + 'type' => self::TYPE, + 'date' => $metadata->getColumnName('datetime'), + 'FROM' => sprintf('%s JOIN %s ON %s = %s', + sprintf('%s.%s', $metadata->getSchemaName(), $metadata->getTableName()), + sprintf('%s.%s', $singleTaskMetadata->getSchemaName(), $singleTaskMetadata->getTableName()), + $metadata->getAssociationMapping('task')['joinColumns'][0]['name'], + sprintf('%s.%s.%s', $singleTaskMetadata->getSchemaName(), $singleTaskMetadata->getTableName(), $singleTaskMetadata->getColumnName('id')) + ), + 'WHERE' => sprintf('%s.%s = %d', + sprintf('%s.%s', $singleTaskMetadata->getSchemaName(), $singleTaskMetadata->getTableName()), + $singleTaskMetadata->getColumnName('id'), + $args['task']->getId() + ) + ]; + + } + + public function getEntities(array $ids) + { + $events = $this->em + ->getRepository(SingleTaskPlaceEvent::class) + ->findBy([ 'id' => $ids ]) + ; + + return \array_combine( + \array_map(function($e) { return $e->getId(); }, $events ), + $events + ); + } + + public function getEntityTemplate($entity, $context, array $args) + { + $workflow = $this->registry->get($entity->getTask(), $entity->getData['workflow']); + $transition = $this->getTransitionByName($entity->getTransition(), $workflow); + + return [ + 'template' => 'ChillTaskBundle:Timeline:single_task_transition_task_context.html.twig', + 'template_data' => [ + 'task' => $args['task'], + 'event' => $entity, + 'transition' => $transition + ] + ]; + } + + /** + * + * @param string $name + * @param Workflow $workflow + * @return \Symfony\Component\Workflow\Transition + */ + protected function getTransitionByName($name, Workflow $workflow) + { + foreach ($workflow->getDefinition()->getTransitions() as $transition) { + if ($transition->getName() === $name) { + return $transition; + } + } + } + + public function supportsType($type): bool + { + return $type === self::TYPE; + } +}