diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php
index b451e9209..f0e728252 100644
--- a/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php
+++ b/src/Bundle/ChillMainBundle/Controller/WorkflowApiController.php
@@ -93,6 +93,45 @@ class WorkflowApiController
);
}
+ /**
+ * Return a list of workflow which are waiting an action for the user.
+ *
+ * @Route("/api/1.0/main/workflow/my-cc", methods={"GET"})
+ */
+ public function myWorkflowCc(Request $request): JsonResponse
+ {
+ if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) {
+ throw new AccessDeniedException();
+ }
+
+ $total = $this->entityWorkflowRepository->countByCc($this->security->getUser());
+
+ if ($request->query->getBoolean('countOnly', false)) {
+ return new JsonResponse(
+ $this->serializer->serialize(new Counter($total), 'json'),
+ JsonResponse::HTTP_OK,
+ [],
+ true
+ );
+ }
+
+ $paginator = $this->paginatorFactory->create($total);
+
+ $workflows = $this->entityWorkflowRepository->findByCc(
+ $this->security->getUser(),
+ ['id' => 'DESC'],
+ $paginator->getItemsPerPage(),
+ $paginator->getCurrentPageFirstItemNumber()
+ );
+
+ return new JsonResponse(
+ $this->serializer->serialize(new Collection($workflows, $paginator), 'json', ['groups' => ['read']]),
+ JsonResponse::HTTP_OK,
+ [],
+ true
+ );
+ }
+
/**
* @Route("/api/1.0/main/workflow/{id}/subscribe", methods={"POST"})
*/
diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
index 0f00a177f..ee09cc1a6 100644
--- a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
+++ b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
@@ -228,6 +228,33 @@ class WorkflowController extends AbstractController
);
}
+ /**
+ * @Route("/{_locale}/main/workflow/list/cc", name="chill_main_workflow_list_cc")
+ */
+ public function myWorkflowsCc(Request $request): Response
+ {
+ $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');
+
+ $total = $this->entityWorkflowRepository->countByDest($this->getUser());
+ $paginator = $this->paginatorFactory->create($total);
+
+ $workflows = $this->entityWorkflowRepository->findByCc(
+ $this->getUser(),
+ ['createdAt' => 'DESC'],
+ $paginator->getItemsPerPage(),
+ $paginator->getCurrentPageFirstItemNumber()
+ );
+
+ return $this->render(
+ '@ChillMain/Workflow/list.html.twig',
+ [
+ 'workflows' => $this->buildHandler($workflows),
+ 'paginator' => $paginator,
+ 'step' => 'cc',
+ ]
+ );
+ }
+
/**
* @Route("/{_locale}/main/workflow/list/dest", name="chill_main_workflow_list_dest")
*/
@@ -306,7 +333,11 @@ class WorkflowController extends AbstractController
$transitionForm = $this->createForm(
WorkflowStepType::class,
$entityWorkflow->getCurrentStep(),
- ['transition' => true, 'entity_workflow' => $entityWorkflow, 'suggested_users' => $usersInvolved]
+ [
+ 'transition' => true,
+ 'entity_workflow' => $entityWorkflow,
+ 'suggested_users' => $usersInvolved
+ ]
);
$transitionForm->handleRequest($request);
@@ -330,6 +361,7 @@ class WorkflowController extends AbstractController
}
// TODO symfony 5: add those "future" on context ($workflow->apply($entityWorkflow, $transition, $context)
+ $entityWorkflow->futureCcUsers = $transitionForm['future_cc_users']->getData();
$entityWorkflow->futureDestUsers = $transitionForm['future_dest_users']->getData();
$entityWorkflow->futureDestEmails = $transitionForm['future_dest_emails']->getData();
diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
index e4683f24b..d0f558cd5 100644
--- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
+++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
@@ -16,6 +16,7 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
use Chill\MainBundle\Entity\User;
+use Chill\MainBundle\Validator\Constraints\Entity\WorkflowStepUsersOnTransition;
use Chill\MainBundle\Workflow\Validator\EntityWorkflowCreation;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
@@ -24,6 +25,7 @@ use Doctrine\ORM\Mapping as ORM;
use Iterator;
use RuntimeException;
use Symfony\Component\Serializer\Annotation as Serializer;
+use Symfony\Component\Validator\Constraints as Assert;
use function count;
use function is_array;
@@ -41,6 +43,13 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
use TrackUpdateTrait;
+ /**
+ * a list of future cc users for the next steps.
+ *
+ * @var array|User[]
+ */
+ public array $futureCcUsers = [];
+
/**
* a list of future dest emails for the next steps.
*
@@ -90,7 +99,7 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
/**
* @ORM\OneToMany(targetEntity=EntityWorkflowStep::class, mappedBy="entityWorkflow", orphanRemoval=true, cascade={"persist"})
* @ORM\OrderBy({"transitionAt": "ASC", "id": "ASC"})
- *
+ * @Assert\Valid(traverse=true)
* @var Collection|EntityWorkflowStep[]
*/
private Collection $steps;
diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStep.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStep.php
index 4bff7a3f5..e43d524a4 100644
--- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStep.php
+++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowStep.php
@@ -32,6 +32,12 @@ class EntityWorkflowStep
*/
private string $accessKey;
+ /**
+ * @ORM\ManyToMany(targetEntity=User::class)
+ * @ORM\JoinTable(name="chill_main_workflow_entity_step_cc_user")
+ */
+ private Collection $ccUser;
+
/**
* @ORM\Column(type="text", options={"default": ""})
*/
@@ -114,11 +120,21 @@ class EntityWorkflowStep
public function __construct()
{
+ $this->ccUser = new ArrayCollection();
$this->destUser = new ArrayCollection();
$this->destUserByAccessKey = new ArrayCollection();
$this->accessKey = bin2hex(openssl_random_pseudo_bytes(32));
}
+ public function addCcUser(User $user): self
+ {
+ if (!$this->ccUser->contains($user)) {
+ $this->ccUser[] = $user;
+ }
+
+ return $this;
+ }
+
public function addDestEmail(string $email): self
{
if (!in_array($email, $this->destEmail, true)) {
@@ -167,6 +183,11 @@ class EntityWorkflowStep
);
}
+ public function getCcUser(): Collection
+ {
+ return $this->ccUser;
+ }
+
public function getComment(): string
{
return $this->comment;
@@ -261,6 +282,13 @@ class EntityWorkflowStep
return true;
}
+ public function removeCcUser(User $user): self
+ {
+ $this->ccUser->removeElement($user);
+
+ return $this;
+ }
+
public function removeDestEmail(string $email): self
{
$this->destEmail = array_filter($this->destEmail, static function (string $existing) use ($email) {
diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
index 1b18b3ef8..16dc0a4a5 100644
--- a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
+++ b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
@@ -156,6 +156,13 @@ class WorkflowStepType extends AbstractType
'mapped' => false,
'suggested' => $options['suggested_users'],
])
+ ->add('future_cc_users', PickUserDynamicType::class, [
+ 'label' => 'workflow.cc for next steps',
+ 'multiple' => true,
+ 'mapped' => false,
+ 'required' => false,
+ 'suggested' => $options['suggested_users'],
+ ])
->add('future_dest_emails', ChillCollectionType::class, [
'label' => 'workflow.dest by email',
'help' => 'workflow.dest by email help',
@@ -236,6 +243,20 @@ class WorkflowStepType extends AbstractType
}
}
),
+ new Callback(
+ function ($step, ExecutionContextInterface $context, $payload) {
+ $form = $context->getObject();
+
+ foreach($form->get('future_dest_users')->getData() as $u) {
+ if (in_array($u, $form->get('future_cc_users')->getData(), true)) {
+ $context
+ ->buildViolation('workflow.The user in cc cannot be a dest user in the same workflow step')
+ ->atPath('ccUsers')
+ ->addViolation();
+ }
+ }
+ }
+ )
]);
}
}
diff --git a/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php b/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php
index 8ccd420c5..0720c6da6 100644
--- a/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php
+++ b/src/Bundle/ChillMainBundle/Notification/Templating/NotificationTwigExtensionRuntime.php
@@ -74,7 +74,8 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
}
return $environment->render('@ChillMain/Notification/extension_list_notifications_for.html.twig', [
- 'notifications' => $notifications, 'appendCommentForms' => $appendCommentForms,
+ 'notifications' => $notifications,
+ 'appendCommentForms' => $appendCommentForms,
]);
}
}
diff --git a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php
index 1fc309d6e..a304ff6d7 100644
--- a/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php
+++ b/src/Bundle/ChillMainBundle/Repository/Workflow/EntityWorkflowRepository.php
@@ -27,6 +27,13 @@ class EntityWorkflowRepository implements ObjectRepository
$this->repository = $entityManager->getRepository(EntityWorkflow::class);
}
+ public function countByCc(User $user): int
+ {
+ $qb = $this->buildQueryByCc($user)->select('count(ew)');
+
+ return (int) $qb->getQuery()->getSingleScalarResult();
+ }
+
public function countByDest(User $user): int
{
$qb = $this->buildQueryByDest($user)->select('count(ew)');
@@ -103,6 +110,19 @@ class EntityWorkflowRepository implements ObjectRepository
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
+ public function findByCc(User $user, ?array $orderBy = null, $limit = null, $offset = null): array
+ {
+ $qb = $this->buildQueryByCc($user)->select('ew');
+
+ foreach ($orderBy as $key => $sort) {
+ $qb->addOrderBy('ew.' . $key, $sort);
+ }
+
+ $qb->setMaxResults($limit)->setFirstResult($offset);
+
+ return $qb->getQuery()->getResult();
+ }
+
public function findByDest(User $user, ?array $orderBy = null, $limit = null, $offset = null): array
{
$qb = $this->buildQueryByDest($user)->select('ew');
@@ -165,6 +185,25 @@ class EntityWorkflowRepository implements ObjectRepository
return EntityWorkflow::class;
}
+ private function buildQueryByCc(User $user): QueryBuilder
+ {
+ $qb = $this->repository->createQueryBuilder('ew');
+
+ $qb->join('ew.steps', 'step');
+
+ $qb->where(
+ $qb->expr()->andX(
+ $qb->expr()->isMemberOf(':user', 'step.ccUser'),
+ $qb->expr()->isNull('step.transitionAfter'),
+ $qb->expr()->eq('step.isFinal', "'FALSE'")
+ )
+ );
+
+ $qb->setParameter('user', $user);
+
+ return $qb;
+ }
+
private function buildQueryByDest(User $user): QueryBuilder
{
$qb = $this->repository->createQueryBuilder('ew');
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue
index fbf453b47..315fd863f 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/App.vue
@@ -46,8 +46,7 @@
:class="{'active': activeTab === 'MyTasks'}"
@click="selectTab('MyTasks')">
{{ $t('my_tasks.tab') }}
-
-
+
@@ -55,7 +54,7 @@
:class="{'active': activeTab === 'MyWorkflows'}"
@click="selectTab('MyWorkflows')">
{{ $t('my_workflows.tab') }}
-
+
@@ -150,4 +149,4 @@ export default {
a.nav-link {
cursor: pointer;
}
-
\ No newline at end of file
+
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflows.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflows.vue
index 1272a3c19..51bda315e 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflows.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflows.vue
@@ -1,88 +1,25 @@
+ {{ $t('my_workflows.description') }}
+
-{{ $t('my_workflows.description') }}
-{{ $t('no_data') }}
-
-
- {{ $t('Object_workflow') }} |
- {{ $t('Step') }} |
- {{ $t('concerned_users') }} |
- |
-
-
-
- {{ w.title }} |
-
-
-
-
- {{ getStep(w) }}
-
-
- |
-
-
-
-
-
- |
-
-
- {{ $t('show_entity', { entity: $t('the_workflow') }) }}
-
- |
-
-
-
-
+ {{ $t('my_workflows.description_cc') }}
+
-
-
+
\ No newline at end of file
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue
new file mode 100644
index 000000000..f98d7a5cb
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/MyWorkflowsTable.vue
@@ -0,0 +1,83 @@
+
+ {{ $t('no_data') }}
+
+
+ {{ $t('Object_workflow') }} |
+ {{ $t('Step') }} |
+ {{ $t('concerned_users') }} |
+ |
+
+
+
+ {{ w.title }} |
+
+
+
+
+ {{ getStep(w) }}
+
+
+ |
+
+
+
+
+
+ |
+
+
+ {{ $t('show_entity', { entity: $t('the_workflow') }) }}
+
+ |
+
+
+
+
+
+
+
+
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 edc781087..697074671 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/i18n.js
@@ -24,7 +24,8 @@ const appMessages = {
},
my_workflows: {
tab: "Mes workflows",
- description: "Liste des workflows en attente d'une action."
+ description: "Liste des workflows en attente d'une action.",
+ description_cc: "Liste des workflows dont je suis en copie."
},
opening_date: "Date d'ouverture",
social_issues: "Problématiques sociales",
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 44127da1c..088cb93b7 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/HomepageWidget/js/store.js
@@ -22,6 +22,7 @@ const store = createStore({
accompanyingCourses: {},
notifications: {},
workflows: {},
+ workflowsCc: {},
errorMsg: [],
loading: false
},
@@ -87,6 +88,9 @@ const store = createStore({
addWorkflows(state, workflows) {
state.workflows = workflows;
},
+ addWorkflowsCc(state, workflows) {
+ state.workflowsCc = workflows;
+ },
setLoading(state, bool) {
state.loading = bool;
},
@@ -195,17 +199,23 @@ const store = createStore({
case 'MyWorkflows':
if (!getters.isWorflowsLoaded) {
commit('setLoading', true);
- const url = '/api/1.0/main/workflow/my';
- makeFetch('GET', url)
- .then((response) => {
- console.log('workflows', response)
- commit('addWorkflows', response);
- commit('setLoading', false);
- })
- .catch((error) => {
- commit('catchError', error);
- throw error;
- });
+ makeFetch('GET', '/api/1.0/main/workflow/my')
+ .then((response) => {
+ commit('addWorkflows', response);
+ makeFetch('GET', '/api/1.0/main/workflow/my-cc')
+ .then((response) => {
+ commit('addWorkflowsCc', response);
+ commit('setLoading', false);
+ })
+ .catch((error) => {
+ commit('catchError', error);
+ throw error;
+ });
+ })
+ .catch((error) => {
+ commit('catchError', error);
+ throw error;
+ });
}
break;
default:
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/_list_item.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/_list_item.html.twig
index 1024d56b3..9bec09e4c 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Notification/_list_item.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/_list_item.html.twig
@@ -30,11 +30,27 @@
{% endif %}
{% if c.notification.addressees|length > 0 %}
-
+ {% if c.notification_cc is defined %}
+ {% if c.notification_cc %}
+
+
+ {{ 'notification.cc'|trans }} :
+
+
+ {% else %}
+
+
+ {{ 'notification.to'|trans }} :
+
+
+ {% endif %}
+ {% else %}
+
{{ 'notification.to'|trans }} :
+ {% endif %}
{% for a in c.notification.addressees %}
{{ a|chill_entity_render_string }}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/list.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/list.html.twig
index 1f1cbe673..6dff67299 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Notification/list.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/list.html.twig
@@ -50,7 +50,8 @@
{% for data in datas %}
{% set notification = data.notification %}
{% include 'ChillMainBundle:Notification:_list_item.html.twig' with {
- 'fold_item': true
+ 'fold_item': true,
+ 'notification_cc': data.template_data.notificationCc is defined ? data.template_data.notificationCc : false
} %}
{% endfor %}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/show.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/show.html.twig
index cce7ebd64..2f9d5d63f 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Notification/show.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/show.html.twig
@@ -27,7 +27,8 @@
},
'action_button': false,
'full_content': true,
- 'fold_item': false
+ 'fold_item': false,
+ 'notification_cc': handler.getTemplateData(notification).notificationCc is defined ? handler.getTemplateData(notification).notificationCc : false
} %}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig
index 0444abc69..2aec17cf9 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig
@@ -65,6 +65,8 @@
{{ form_row(transition_form.future_dest_users) }}
+ {{ form_row(transition_form.future_cc_users) }}
+
{{ form_row(transition_form.future_dest_emails) }}
{{ form_errors(transition_form.future_dest_users) }}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig
index 72aab397c..acbf97cf7 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig
@@ -81,6 +81,15 @@
{% endif %}
+ {% if step.ccUser|length > 0 %}
+ {{ 'workflow.Users put in Cc'|trans }} :
+
+ {% for u in step.ccUser %}
+ - {{ u|chill_entity_render_box }}
+ {% endfor %}
+
+ {% endif %}
+
{% if entity_workflow.currentStep.destEmail|length > 0 %}
{{ 'workflow.An access key was also sent to those addresses'|trans }} :
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig
index 85a521d2a..1099d8452 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/list.html.twig
@@ -7,7 +7,7 @@
{% endblock %}
{% block content %}
-
+
{{ block('title') }}
@@ -25,6 +25,12 @@
{{ 'workflow.dest'|trans }}
+
-
+
+ {{ 'workflow.cc'|trans }}
+
+
-
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig
index a62f37e0a..2ba893910 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/macro_breadcrumb.html.twig
@@ -15,6 +15,12 @@
{% for d in step.destUser %}{{ d|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}
+
-
+ {{ 'workflow.Cc'|trans ~ ' : ' }}
+
+ {% for u in step.ccUser %}{{ u|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}
+
+
{% else %}
-
{{ 'workflow.Created by'|trans ~ ' : ' }}
diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php
index 1729d0daa..192ca0712 100644
--- a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php
+++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php
@@ -50,6 +50,10 @@ class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterfac
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
+ foreach ($entityWorkflow->futureCcUsers as $user) {
+ $entityWorkflow->getCurrentStep()->addCcUser($user);
+ }
+
foreach ($entityWorkflow->futureDestUsers as $user) {
$entityWorkflow->getCurrentStep()->addDestUser($user);
}
diff --git a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php
index 7d2cadc37..f02341ff7 100644
--- a/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php
+++ b/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/NotificationOnTransition.php
@@ -85,7 +85,9 @@ class NotificationOnTransition implements EventSubscriberInterface
// the subscriber to final, only if final
$entityWorkflow->isFinal() ? $entityWorkflow->getSubscriberToFinal()->toArray() : [],
// the dests for the current step
- $entityWorkflow->getCurrentStep()->getDestUser()->toArray()
+ $entityWorkflow->getCurrentStep()->getDestUser()->toArray(),
+ // the cc users for the current step
+ $entityWorkflow->getCurrentStep()->getCcUser()->toArray()
) as $dest) {
$dests[spl_object_hash($dest)] = $dest;
}
diff --git a/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php b/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php
index 0d0c4305b..d3e848d41 100644
--- a/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php
+++ b/src/Bundle/ChillMainBundle/Workflow/Notification/WorkflowNotificationHandler.php
@@ -16,6 +16,7 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Notification\NotificationHandlerInterface;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
+use Symfony\Component\Security\Core\Security;
class WorkflowNotificationHandler implements NotificationHandlerInterface
{
@@ -23,10 +24,16 @@ class WorkflowNotificationHandler implements NotificationHandlerInterface
private EntityWorkflowRepository $entityWorkflowRepository;
- public function __construct(EntityWorkflowRepository $entityWorkflowRepository, EntityWorkflowManager $entityWorkflowManager)
- {
+ private Security $security;
+
+ public function __construct(
+ EntityWorkflowRepository $entityWorkflowRepository,
+ EntityWorkflowManager $entityWorkflowManager,
+ Security $security
+ ) {
$this->entityWorkflowRepository = $entityWorkflowRepository;
$this->entityWorkflowManager = $entityWorkflowManager;
+ $this->security = $security;
}
public function getTemplate(Notification $notification, array $options = []): string
@@ -37,13 +44,28 @@ class WorkflowNotificationHandler implements NotificationHandlerInterface
public function getTemplateData(Notification $notification, array $options = []): array
{
$entityWorkflow = $this->entityWorkflowRepository->find($notification->getRelatedEntityId());
-
return [
'entity_workflow' => $entityWorkflow,
'handler' => $this->entityWorkflowManager->getHandler($entityWorkflow),
+ 'notificationCc' => $this->isNotificationCc($notification),
];
}
+ private function isNotificationCc(Notification $notification): bool
+ {
+ $notificationCc = false;
+
+ if ($notification->getRelatedEntityClass() === EntityWorkflow::class) {
+ $relatedEntity = $this->entityWorkflowRepository->findOneBy(['id' => $notification->getRelatedEntityId()]);
+
+ if ($relatedEntity->getCurrentStepCreatedBy() !== $this->security->getUser()) {
+ $notificationCc = true;
+ }
+ }
+
+ return $notificationCc;
+ }
+
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() === EntityWorkflow::class;
diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml
index 133345a6f..98e0e915e 100644
--- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml
+++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml
@@ -826,4 +826,20 @@ paths:
$ref: '#/components/schemas/Workflow'
403:
description: "Unauthorized"
+ /1.0/main/workflow/my-cc:
+ get:
+ tags:
+ - workflow
+ summary: Return a list of workflows for which user was notified in Cc
+ responses:
+ 200:
+ description: "ok"
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Workflow'
+ 403:
+ description: "Unauthorized"
diff --git a/src/Bundle/ChillMainBundle/migrations/Version20230321134155.php b/src/Bundle/ChillMainBundle/migrations/Version20230321134155.php
new file mode 100644
index 000000000..6f3fabb5d
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/migrations/Version20230321134155.php
@@ -0,0 +1,39 @@
+addSql('ALTER TABLE chill_main_workflow_entity_step_cc_user DROP CONSTRAINT FK_9FC79037E6AF9D4');
+ $this->addSql('ALTER TABLE chill_main_workflow_entity_step_cc_user DROP CONSTRAINT FK_9FC7903A76ED395');
+ $this->addSql('DROP TABLE chill_main_workflow_entity_step_cc_user');
+ }
+
+ public function getDescription(): string
+ {
+ return 'Add cc User to workflow step';
+ }
+
+ public function up(Schema $schema): void
+ {
+ $this->addSql('CREATE TABLE chill_main_workflow_entity_step_cc_user (entityworkflowstep_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(entityworkflowstep_id, user_id))');
+ $this->addSql('CREATE INDEX IDX_9FC79037E6AF9D4 ON chill_main_workflow_entity_step_cc_user (entityworkflowstep_id)');
+ $this->addSql('CREATE INDEX IDX_9FC7903A76ED395 ON chill_main_workflow_entity_step_cc_user (user_id)');
+ $this->addSql('ALTER TABLE chill_main_workflow_entity_step_cc_user ADD CONSTRAINT FK_9FC79037E6AF9D4 FOREIGN KEY (entityworkflowstep_id) REFERENCES chill_main_workflow_entity_step (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_main_workflow_entity_step_cc_user ADD CONSTRAINT FK_9FC7903A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml
index be02987b3..369abf628 100644
--- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml
@@ -447,6 +447,7 @@ workflow:
Created by: Créé par
My decision: Ma décision
Next step: Prochaine étape
+ cc for next steps: Utilisateurs en copie
dest for next steps: Utilisateurs qui valideront la prochaine étape
Freeze: Geler
Freezed: Gelé
@@ -465,12 +466,14 @@ workflow:
Document (n°%doc%): "Document (n°%doc%)"
Work (n°%w%): "Action d'accompagnement (n°%w%)"
subscribed: Workflows suivis
+ cc: Workflows dont je suis en copie
dest: Workflows en attente d'action
you subscribed to all steps: Vous recevrez une notification à chaque étape
you subscribed to final step: Vous recevrez une notification à l'étape finale
Current step: Étape actuelle
Comment on last change: Commentaire à la transition précédente
Users allowed to apply transition: Utilisateurs pouvant valider cette étape
+ Users put in Cc: Utilisateurs mis en copie
Workflow deleted with success: Le workflow a été supprimé
Delete workflow ?: Supprimer le workflow ?
Are you sure you want to delete this workflow ?: Êtes-vous sûr·e de vouloir supprimer ce workflow ?
@@ -487,6 +490,7 @@ workflow:
Previous transitionned: Anciens workflows
Previous workflow transitionned help: Workflows où vous avez exécuté une action.
For: Pour
+ Cc: Cc
You must select a next step, pick another decision if no next steps are available: Il faut une prochaine étape. Choissisez une autre décision si nécessaire.
An access key was also sent to those addresses: Un lien d'accès a été envoyé à ces adresses
Those users are also granted to apply a transition by using an access key: Ces utilisateurs ont obtenu l'accès grâce au lien reçu par email
@@ -521,7 +525,9 @@ notification:
list: Notifications
Sent: Envoyé
to: À
+ cc: Cc
sent_to: Destinataire(s)
+ sent_cc: En copie
from: De
received_from: Expéditeur
you were notified by %sender%: Vous avez été notifié par %sender%
diff --git a/src/Bundle/ChillMainBundle/translations/messages.nl.yml b/src/Bundle/ChillMainBundle/translations/messages.nl.yml
index 97341dd3c..2e4ee5a88 100644
--- a/src/Bundle/ChillMainBundle/translations/messages.nl.yml
+++ b/src/Bundle/ChillMainBundle/translations/messages.nl.yml
@@ -373,6 +373,7 @@ workflow:
Created by: Créé par
My decision: Ma décision
Next step: Prochaine étape
+ cc for next steps: Utilisateurs en copie
dest for next steps: Utilisateurs qui valideront la prochaine étape
Freeze: Geler
Freezed: Gelé
@@ -392,11 +393,13 @@ workflow:
Work (n°%w%): "Action d'accompagnement (n°%w%)"
subscribed: Workflows suivis
dest: Workflows en attente d'action
+ cc: Workflows dont je suis en copie
you subscribed to all steps: Vous recevrez une notification à chaque étape
you subscribed to final step: Vous recevrez une notification à l'étape finale
Current step: Étape actuelle
Comment on last change: Commentaire à la transition précédente
Users allowed to apply transition: Utilisateurs pouvant valider cette étape
+ Users put in Cc: Utilisateurs mis en copie
Workflow deleted with success: Le workflow a été supprimé
Delete workflow ?: Supprimer le workflow ?
Are you sure you want to delete this workflow ?: Êtes-vous sûr·e de vouloir supprimer ce workflow ?
@@ -414,6 +417,7 @@ workflow:
Previous transitionned: Anciens workflows
Previous workflow transitionned help: Workflows où vous avez exécuté une action.
For: Pour
+ Cc: Cc
Subscribe final: Recevoir une notification à l'étape finale
@@ -442,7 +446,9 @@ notification:
list: Notifications
Sent: Envoyé
to: À
+ cc: Cc
sent_to: Destinataire(s)
+ sent_cc: En copie
from: De
received_from: Expéditeur
you were notified by %sender%: Vous avez été notifié par %sender%
diff --git a/src/Bundle/ChillMainBundle/translations/validators.fr.yml b/src/Bundle/ChillMainBundle/translations/validators.fr.yml
index 690629e44..4ab9bde34 100644
--- a/src/Bundle/ChillMainBundle/translations/validators.fr.yml
+++ b/src/Bundle/ChillMainBundle/translations/validators.fr.yml
@@ -11,6 +11,8 @@ A permission is already present for the same role and scope: Une permission est
#UserCircleConsistency
"{{ username }} is not allowed to see entities published in this circle": "{{ username }} n'est pas autorisé à voir l'élément publié dans ce cercle."
+The user in cc cannot be a dest user in the same workflow step: Un utilisateur en Cc ne peut pas être un utilisateur qui valide.
+
#password request
This username or email does not exists: Cet utilisateur ou email n'est pas présent dans la base de donnée
@@ -31,6 +33,7 @@ notification:
workflow:
You must add at least one dest user or email: Indiquez au moins un destinataire ou une adresse email
+ The user in cc cannot be a dest user in the same workflow step: L'utilisateur en copie ne peut pas être présent dans les utilisateurs qui valideront la prochaine étape
rolling_date:
- When fixed date is selected, you must provide a date: Indiquez la date fixe choisie
\ No newline at end of file
+ When fixed date is selected, you must provide a date: Indiquez la date fixe choisie