mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
add confirmation page for task
This commit is contained in:
parent
5ada6d913c
commit
52bda7c94f
@ -11,6 +11,11 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Chill\TaskBundle\Event\UI\UIEvent;
|
||||
use Chill\TaskBundle\Entity\AbstractTask;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Workflow\Transition;
|
||||
|
||||
|
||||
class TaskController extends Controller
|
||||
@ -41,7 +46,8 @@ class TaskController extends Controller
|
||||
Registry $registry,
|
||||
EntityManagerInterface $em,
|
||||
Request $request,
|
||||
TranslatorInterface $translator
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
switch ($kind) {
|
||||
case 'single-task':
|
||||
@ -49,9 +55,12 @@ class TaskController extends Controller
|
||||
->find($taskId)
|
||||
;
|
||||
$defaultReturnPath = $this->generateUrl(
|
||||
'chill_task_singletask_list',
|
||||
[ 'person_id' => $task->getPerson() ]
|
||||
);
|
||||
'chill_task_single_task_show',
|
||||
[
|
||||
'id' => $task->getId(),
|
||||
'list_params' => $request->query->get('list_params', [])
|
||||
]);
|
||||
$defaultTemplate = '@ChillTask/SingleTask/transition.html.twig';
|
||||
break;
|
||||
default:
|
||||
return new Response("The type '$kind' is not implemented",
|
||||
@ -59,27 +68,75 @@ class TaskController extends Controller
|
||||
}
|
||||
|
||||
if (NULL === $task) {
|
||||
$this->createNotFoundException("task with id '$taskId' and type "
|
||||
throw $this->createNotFoundException("task with id '$taskId' and type "
|
||||
. "'$type' does not exists");
|
||||
}
|
||||
|
||||
$workflow = $registry->get($task);
|
||||
|
||||
if (!$workflow->can($task, $transition)) {
|
||||
throw $this->createAccessDeniedException('You are not allowed to apply this transition');
|
||||
}
|
||||
$transitionInstance = \array_values( // array_values needed to reset keys (array_filter preserves keys)
|
||||
\array_filter(
|
||||
$workflow->getEnabledTransitions($task),
|
||||
function(Transition $t) use ($transition) {
|
||||
return $t->getName() === $transition;
|
||||
}
|
||||
))[0];
|
||||
|
||||
// we simply check that the user can see the task. Other ACL checks
|
||||
// should be performed using `guard` events.
|
||||
$this->denyAccessUnlessGranted(TaskVoter::SHOW, $task);
|
||||
|
||||
$form = $this->createTransitionForm($task);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
|
||||
$workflow = $registry->get($task);
|
||||
if ($workflow->can($task, $transition)) {
|
||||
$workflow->apply($task, $transition);
|
||||
|
||||
if ($workflow->can($task, $transition)) {
|
||||
$workflow->apply($task, $transition);
|
||||
$em->flush();
|
||||
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $translator->trans('The transition is successfully applied'));
|
||||
$this->addFlash('success', $translator->trans('The transition is successfully applied'));
|
||||
|
||||
} else {
|
||||
$this->addFlash('error', $translator->trans('The transition could not be applied'));
|
||||
}
|
||||
|
||||
return $this->redirect($defaultReturnPath);
|
||||
} else {
|
||||
$this->addFlash('error', $translator->trans('The transition could not be applied'));
|
||||
$event = (new UIEvent($kind, $task))
|
||||
->setForm($form)
|
||||
->setTransition($transitionInstance)
|
||||
;
|
||||
|
||||
$eventDispatcher->dispatch(UIEvent::SHOW_TRANSITION_PAGE, $event);
|
||||
|
||||
if ($event->hasResponse()) {
|
||||
return $event->getResponse();
|
||||
} else {
|
||||
return $this->render($defaultTemplate, [
|
||||
'task' => $task,
|
||||
'form' => $form->createView(),
|
||||
'transition' => $transitionInstance
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->redirect($request->query->get('return_path', $defaultReturnPath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Chill\TaskBundle\Controller\AbstractTask $task
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
*/
|
||||
protected function createTransitionForm(AbstractTask $task)
|
||||
{
|
||||
$builder = $this->createFormBuilder($task);
|
||||
$builder->add('submit', SubmitType::class);
|
||||
|
||||
return $builder->getForm();
|
||||
}
|
||||
}
|
||||
|
130
Event/UI/UIEvent.php
Normal file
130
Event/UI/UIEvent.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/*
|
||||
*
|
||||
*/
|
||||
namespace Chill\TaskBundle\Event\UI;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Chill\TaskBundle\Entity\AbstractTask;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Workflow\Transition;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class UIEvent extends Event
|
||||
{
|
||||
const SHOW_TRANSITION_PAGE = 'chill_task.show_transition_page';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $kind;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AbstractTask
|
||||
*/
|
||||
protected $task;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Response|null
|
||||
*/
|
||||
protected $response = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var FormInterface|null
|
||||
*/
|
||||
protected $form = null;
|
||||
|
||||
/**
|
||||
* @var Transition
|
||||
*/
|
||||
protected $transition = null;
|
||||
|
||||
public function __construct($kind, AbstractTask $task)
|
||||
{
|
||||
$this->kind = $kind;
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKind()
|
||||
{
|
||||
return $this->kind;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AbstractTask
|
||||
*/
|
||||
public function getTask(): AbstractTask
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return FormInterface|null
|
||||
*/
|
||||
public function getForm()
|
||||
{
|
||||
return $this->form;
|
||||
}
|
||||
|
||||
public function setForm(FormInterface $form)
|
||||
{
|
||||
$this->form = $form;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTransition()
|
||||
{
|
||||
return $this->transition;
|
||||
}
|
||||
|
||||
public function setTransition(Transition $transition)
|
||||
{
|
||||
$this->transition = $transition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getResponse(): Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Response $response
|
||||
* @return $this
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasResponse()
|
||||
{
|
||||
return $this->response instanceof Response;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -60,7 +60,7 @@ Associated person: Personne associée
|
||||
Default task: Tâche par défaut
|
||||
|
||||
|
||||
# transitions
|
||||
# transitions - default task definition
|
||||
'new': 'nouvelle'
|
||||
'in_progress': 'en cours'
|
||||
'closed': 'fermée'
|
||||
@ -68,10 +68,16 @@ Default task: Tâche par défaut
|
||||
start: démarrer
|
||||
close: clotûrer
|
||||
cancel: annuler
|
||||
Start_verb: Démarrer
|
||||
Close_verb: Clotûrer
|
||||
Set this task to cancel state: Marquer cette tâche comme annulée
|
||||
'%user% has closed the task': %user% a fermé la tâche
|
||||
'%user% has canceled the task': %user% a annulé la tâche
|
||||
'%user% has started the task': %user% a commencé la tâche
|
||||
'%user% has created the task': %user% a introduit la tâche
|
||||
Are you sure you want to close this task ?: Êtes-vous sûrs de vouloir clotûrer cette tâche ?
|
||||
Are you sure you want to cancel this task ?: Êtes-vous sûrs de vouloir annuler cette tâche ?
|
||||
Are you sure you want to start this task ?: Êtes-vous sûrs de vouloir démarrer cette tâche ?
|
||||
|
||||
#Flash messages
|
||||
'The task is created': 'La tâche a été créée'
|
||||
@ -88,4 +94,7 @@ cancel: annuler
|
||||
|
||||
#title
|
||||
My tasks near deadline: Mes tâches à échéance proche
|
||||
My tasks over deadline: Mes tâches à échéance dépassée
|
||||
My tasks over deadline: Mes tâches à échéance dépassée
|
||||
|
||||
#transition page
|
||||
Apply transition on task <em>%title%</em>: Appliquer la transition sur la tâche <em>%title%</em>
|
||||
|
@ -18,7 +18,7 @@
|
||||
{% for task in tasks %}
|
||||
<tr>
|
||||
<td>{{ task.title }}</td>
|
||||
<td>{{ task_workflow_metadata(task, 'definition.name') }}</td>
|
||||
<td>{{ task_workflow_metadata(task, 'definition.name')|trans }}</td>
|
||||
{% if person is null %}
|
||||
<td><a href="{{ path('chill_person_view', {person_id : task.person.Id}) }}">{{ task.person}}</a></td>
|
||||
{% endif %}
|
||||
@ -58,7 +58,7 @@
|
||||
<a href="" class="sc-button bt-task-exchange"> </a>
|
||||
<div class="bt-dropdown-content">
|
||||
{% for transition in workflow_transitions(task) %}
|
||||
<a href="{{ path('chill_task_task_transition', { 'taskId': task.id, 'transition': transition.name, 'kind': 'single-task', 'return_path': app.request.uri }) }}" class="{{ task_workflow_metadata(task, 'transition.class', transition)|e('html_attr') }}">{{ task_workflow_metadata(task, 'transition.verb', transition)|trans }}</a>
|
||||
<a href="{{ path('chill_task_task_transition', { 'taskId': task.id, 'transition': transition.name, 'kind': 'single-task', 'list_params': app.request.query.all }) }}" class="{{ task_workflow_metadata(task, 'transition.class', transition)|e('html_attr') }}">{{ task_workflow_metadata(task, 'transition.verb', transition)|trans }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@ -141,7 +141,7 @@
|
||||
{% import _self as helper %}
|
||||
|
||||
|
||||
<h1>{{ app.request.query.get('title', null)|default('Task list'|trans) }}</h1>
|
||||
<h1>{{ app.request.query.get('title', null)|escape('html')|default('Task list'|trans) }}</h1>
|
||||
|
||||
{% if false == app.request.query.boolean('hide_form', false) %}
|
||||
<h2>{{ 'Filter the tasks'|trans }}</h2>
|
||||
|
34
Resources/views/SingleTask/transition.html.twig
Normal file
34
Resources/views/SingleTask/transition.html.twig
Normal file
@ -0,0 +1,34 @@
|
||||
{% extends "ChillPersonBundle::layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_task_task_list' %}
|
||||
{% set person = task.person %}
|
||||
|
||||
{% block title 'Remove task'|trans %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
<h2>{{ 'Apply transition on task <em>%title%</em>'|trans({ '%title%': task.title } )|raw }}</h2>
|
||||
|
||||
|
||||
{% if task_workflow_metadata(task, 'transition.sentence_confirmation', transition) is not empty %}
|
||||
<p class="message-confirm">{{ task_workflow_metadata(task, 'transition.sentence_confirmation', transition)|trans }}</p>
|
||||
{% else %}
|
||||
<p>{{ 'Are you sure to apply the transition %name% on this task ?'|trans({ '%name%': task_workflow_metadata(task, 'transition.name', transition)|default(transition.name)|trans }) }}</p>
|
||||
{% endif %}
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_task_singletask_list', app.request.query.get('list_params', { }) ) }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_widget(form.submit, { 'attr' : { 'class' : "sc-button bt-task-exchange green" }, 'label': task_workflow_metadata(task, 'transition.apply_transition_submit_label', transition)|default('apply')|trans } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% endblock %}
|
@ -108,10 +108,16 @@ class CountNotificationTask implements NotificationCounterInterface
|
||||
$task = $e->getSubject();
|
||||
|
||||
if (NULL !== $task->getAssignee()) {
|
||||
$sumCache = $this->cachePool->getItem($this->getCacheKey($task->getAssignee()));
|
||||
|
||||
if ($sumCache->isHit()) {
|
||||
$this->cachePool->deleteItem($this->getCacheKey($task->getAssignee()));
|
||||
foreach ([
|
||||
SingleTaskRepository::DATE_STATUS_ENDED,
|
||||
SingleTaskRepository::DATE_STATUS_WARNING
|
||||
] as $status) {
|
||||
$key = $this->getCacheKey($task->getAssignee(), $status);
|
||||
$sumCache = $this->cachePool->getItem($key);
|
||||
|
||||
if ($sumCache->isHit()) {
|
||||
$this->cachePool->deleteItem($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,17 +32,23 @@ class DefaultTaskDefinition implements \Chill\TaskBundle\Workflow\TaskWorkflowDe
|
||||
'close' => [
|
||||
'verb' => 'close',
|
||||
'class' => 'sc-button bt-task-label bt-task-close',
|
||||
'sentence' => '%user% has closed the task'
|
||||
'sentence' => '%user% has closed the task',
|
||||
'sentence_confirmation' => 'Are you sure you want to close this task ?',
|
||||
'apply_transition_submit_label' => 'Close_verb'
|
||||
],
|
||||
'cancel' => [
|
||||
'verb' => 'cancel',
|
||||
'class' => 'sc-button bt-task-label bt-task-cancel',
|
||||
'sentence' => '%user% has canceled the task'
|
||||
'sentence' => '%user% has canceled the task',
|
||||
'sentence_confirmation' => 'Are you sure you want to cancel this task ?',
|
||||
'apply_transition_submit_label' => 'Set this task to cancel state'
|
||||
],
|
||||
'start' => [
|
||||
'verb' => 'start',
|
||||
'class' => 'sc-button bt-task-label bt-task-start',
|
||||
'sentence' => '%user% has started the task'
|
||||
'sentence' => '%user% has started the task',
|
||||
'sentence_confirmation' => 'Are you sure you want to start this task ?',
|
||||
'apply_transition_submit_label' => 'Start_verb'
|
||||
]
|
||||
];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user