mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 03:08:25 +00:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			fix_calend
			...
			issue706_c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b59c69bce4 | ||
| 
						 | 
					6f9da67942 | ||
| 
						 | 
					609e2e1610 | ||
| 
						 | 
					d940d13d7d | ||
| 
						 | 
					1cf99b4383 | ||
| 
						 | 
					c969b35fd1 | ||
| 
						 | 
					cbf8a9ff71 | ||
| 
						 | 
					7c18899249 | ||
| 
						 | 
					f4f465b33a | ||
| 
						 | 
					aed7fcebae | 
@@ -14,6 +14,7 @@ namespace Chill\MainBundle\Controller;
 | 
			
		||||
use Chill\MainBundle\Entity\Notification;
 | 
			
		||||
use Chill\MainBundle\Entity\NotificationComment;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
 | 
			
		||||
use Chill\MainBundle\Form\NotificationCommentType;
 | 
			
		||||
use Chill\MainBundle\Form\NotificationType;
 | 
			
		||||
use Chill\MainBundle\Notification\Exception\NotificationHandlerNotFound;
 | 
			
		||||
@@ -21,6 +22,7 @@ use Chill\MainBundle\Notification\NotificationHandlerManager;
 | 
			
		||||
use Chill\MainBundle\Pagination\PaginatorFactory;
 | 
			
		||||
use Chill\MainBundle\Repository\NotificationRepository;
 | 
			
		||||
use Chill\MainBundle\Repository\UserRepository;
 | 
			
		||||
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
 | 
			
		||||
use Chill\MainBundle\Security\Authorization\NotificationVoter;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Psr\Log\LoggerInterface;
 | 
			
		||||
@@ -68,7 +70,8 @@ class NotificationController extends AbstractController
 | 
			
		||||
        NotificationHandlerManager $notificationHandlerManager,
 | 
			
		||||
        PaginatorFactory $paginatorFactory,
 | 
			
		||||
        TranslatorInterface $translator,
 | 
			
		||||
        UserRepository $userRepository
 | 
			
		||||
        UserRepository $userRepository,
 | 
			
		||||
        EntityWorkflowRepository $entityWorkflowRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->em = $em;
 | 
			
		||||
        $this->logger = $logger;
 | 
			
		||||
@@ -79,6 +82,7 @@ class NotificationController extends AbstractController
 | 
			
		||||
        $this->paginatorFactory = $paginatorFactory;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
        $this->userRepository = $userRepository;
 | 
			
		||||
        $this->entityWorkflowRepository = $entityWorkflowRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -345,6 +349,7 @@ class NotificationController extends AbstractController
 | 
			
		||||
            'appendCommentForm' => isset($appendCommentForm) ? $appendCommentForm->createView() : null,
 | 
			
		||||
            'editedCommentForm' => isset($editedCommentForm) ? $editedCommentForm->createView() : null,
 | 
			
		||||
            'editedCommentId' => $commentId ?? null,
 | 
			
		||||
            'notificationCc' => $this->isNotificationCc($notification),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        // we mark the notification as read after having computed the response
 | 
			
		||||
@@ -364,6 +369,21 @@ class NotificationController extends AbstractController
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function itemsForTemplate(array $notifications): array
 | 
			
		||||
    {
 | 
			
		||||
        $templateData = [];
 | 
			
		||||
@@ -373,6 +393,7 @@ class NotificationController extends AbstractController
 | 
			
		||||
                'template' => $this->notificationHandlerManager->getTemplate($notification),
 | 
			
		||||
                'template_data' => $this->notificationHandlerManager->getTemplateData($notification),
 | 
			
		||||
                'notification' => $notification,
 | 
			
		||||
                'isNotificationCc' => $this->isNotificationCc($notification),
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"})
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -224,6 +224,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")
 | 
			
		||||
     */
 | 
			
		||||
@@ -318,6 +345,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();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,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.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -155,6 +155,12 @@ class WorkflowStepType extends AbstractType
 | 
			
		||||
                    'multiple' => true,
 | 
			
		||||
                    'mapped' => false,
 | 
			
		||||
                ])
 | 
			
		||||
                ->add('future_cc_users', PickUserDynamicType::class, [
 | 
			
		||||
                    'label' => 'workflow.cc for next steps',
 | 
			
		||||
                    'multiple' => true,
 | 
			
		||||
                    'mapped' => false,
 | 
			
		||||
                    'required' => false,
 | 
			
		||||
                ])
 | 
			
		||||
                ->add('future_dest_emails', ChillCollectionType::class, [
 | 
			
		||||
                    'label' => 'workflow.dest by email',
 | 
			
		||||
                    'help' => 'workflow.dest by email help',
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,9 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $environment->render('@ChillMain/Notification/extension_list_notifications_for.html.twig', [
 | 
			
		||||
            'notifications' => $notifications, 'appendCommentForms' => $appendCommentForms,
 | 
			
		||||
            'notifications' => $notifications,
 | 
			
		||||
            'appendCommentForms' => $appendCommentForms,
 | 
			
		||||
            'notificationCc' => false,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,88 +1,25 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="alert alert-light">{{ $t('my_workflows.description') }}</div>
 | 
			
		||||
    <my-workflows-table :workflows="workflows" />
 | 
			
		||||
 | 
			
		||||
<div class="alert alert-light">{{ $t('my_workflows.description') }}</div>
 | 
			
		||||
<span v-if="noResults" class="chill-no-data-statement">{{ $t('no_data') }}</span>
 | 
			
		||||
<tab-table v-else>
 | 
			
		||||
    <template v-slot:thead>
 | 
			
		||||
        <th scope="col">{{ $t('Object_workflow') }}</th>
 | 
			
		||||
        <th scope="col">{{ $t('Step') }}</th>
 | 
			
		||||
        <th scope="col">{{ $t('concerned_users') }}</th>
 | 
			
		||||
        <th scope="col"></th>
 | 
			
		||||
    </template>
 | 
			
		||||
    <template v-slot:tbody>
 | 
			
		||||
        <tr v-for="(w, i) in workflows.results" :key="`workflow-${i}`">
 | 
			
		||||
            <td>{{ w.title }}</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <div class="workflow">
 | 
			
		||||
                    <div class="breadcrumb">
 | 
			
		||||
                        <i class="fa fa-circle me-1 text-chill-yellow mx-2"></i>
 | 
			
		||||
                        <span class="mx-2">{{ getStep(w) }}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td v-if="w.datas.persons !== null">
 | 
			
		||||
                <span v-for="p in w.datas.persons" class="me-1" :key="p.id">
 | 
			
		||||
                    <on-the-fly
 | 
			
		||||
                        :type="p.type"
 | 
			
		||||
                        :id="p.id"
 | 
			
		||||
                        :buttonText="p.textAge"
 | 
			
		||||
                        :displayBadge="'true' === 'true'"
 | 
			
		||||
                        action="show">
 | 
			
		||||
                    </on-the-fly>
 | 
			
		||||
                </span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
            <a class="btn btn-sm btn-show" :href="getUrl(w)">
 | 
			
		||||
                {{ $t('show_entity', { entity: $t('the_workflow') }) }}
 | 
			
		||||
            </a>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </template>
 | 
			
		||||
</tab-table>
 | 
			
		||||
 | 
			
		||||
    <div class="alert alert-light">{{ $t('my_workflows.description_cc') }}</div>
 | 
			
		||||
    <my-workflows-table :workflows="workflowsCc" />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { mapState, mapGetters } from "vuex";
 | 
			
		||||
import TabTable from "./TabTable";
 | 
			
		||||
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly';
 | 
			
		||||
import { mapState } from "vuex";
 | 
			
		||||
import MyWorkflowsTable from './MyWorkflowsTable.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    name: "MyWorkflows",
 | 
			
		||||
    components: {
 | 
			
		||||
        TabTable,
 | 
			
		||||
        OnTheFly
 | 
			
		||||
        MyWorkflowsTable
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
        ...mapState([
 | 
			
		||||
            'workflows',
 | 
			
		||||
            'workflowsCc',
 | 
			
		||||
        ]),
 | 
			
		||||
        ...mapGetters([
 | 
			
		||||
            'isWorkflowsLoaded',
 | 
			
		||||
        ]),
 | 
			
		||||
        noResults() {
 | 
			
		||||
            if (!this.isWorkflowsLoaded) {
 | 
			
		||||
                return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                return this.workflows.count === 0;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        getUrl(w) {
 | 
			
		||||
            return `/fr/main/workflow/${w.id}/show`;
 | 
			
		||||
        },
 | 
			
		||||
        getStep(w) {
 | 
			
		||||
            const lastStep = w.steps.length - 1
 | 
			
		||||
            return w.steps[lastStep].currentStep.text;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
span.outdated {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: var(--bs-warning);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
</script>
 | 
			
		||||
@@ -0,0 +1,83 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <span v-if="hasNoResults(workflows)" class="chill-no-data-statement">{{ $t('no_data') }}</span>
 | 
			
		||||
    <tab-table v-else>
 | 
			
		||||
        <template v-slot:thead>
 | 
			
		||||
            <th scope="col">{{ $t('Object_workflow') }}</th>
 | 
			
		||||
            <th scope="col">{{ $t('Step') }}</th>
 | 
			
		||||
            <th scope="col">{{ $t('concerned_users') }}</th>
 | 
			
		||||
            <th scope="col"></th>
 | 
			
		||||
        </template>
 | 
			
		||||
        <template v-slot:tbody>
 | 
			
		||||
            <tr v-for="(w, i) in workflows.results" :key="`workflow-${i}`">
 | 
			
		||||
                <td>{{ w.title }}</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <div class="workflow">
 | 
			
		||||
                        <div class="breadcrumb">
 | 
			
		||||
                            <i class="fa fa-circle me-1 text-chill-yellow mx-2"></i>
 | 
			
		||||
                            <span class="mx-2">{{ getStep(w) }}</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td v-if="w.datas.persons !== null">
 | 
			
		||||
                    <span v-for="p in w.datas.persons" class="me-1" :key="p.id">
 | 
			
		||||
                        <on-the-fly
 | 
			
		||||
                            :type="p.type"
 | 
			
		||||
                            :id="p.id"
 | 
			
		||||
                            :buttonText="p.textAge"
 | 
			
		||||
                            :displayBadge="'true' === 'true'"
 | 
			
		||||
                            action="show">
 | 
			
		||||
                        </on-the-fly>
 | 
			
		||||
                    </span>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                <a class="btn btn-sm btn-show" :href="getUrl(w)">
 | 
			
		||||
                    {{ $t('show_entity', { entity: $t('the_workflow') }) }}
 | 
			
		||||
                </a>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </template>
 | 
			
		||||
    </tab-table>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { mapGetters } from "vuex";
 | 
			
		||||
import TabTable from "./TabTable";
 | 
			
		||||
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    name: "MyWorkflows",
 | 
			
		||||
    components: {
 | 
			
		||||
        TabTable,
 | 
			
		||||
        OnTheFly
 | 
			
		||||
    },
 | 
			
		||||
    props: ['workflows'],
 | 
			
		||||
    computed: {
 | 
			
		||||
        ...mapGetters([
 | 
			
		||||
            'isWorkflowsLoaded',
 | 
			
		||||
        ]),
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        hasNoResults(workflows) {
 | 
			
		||||
            if (!this.isWorkflowsLoaded) {
 | 
			
		||||
                return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                return workflows.count === 0;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        getUrl(w) {
 | 
			
		||||
            return `/fr/main/workflow/${w.id}/show`;
 | 
			
		||||
        },
 | 
			
		||||
        getStep(w) {
 | 
			
		||||
            const lastStep = w.steps.length - 1
 | 
			
		||||
            return w.steps[lastStep].currentStep.text;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
span.outdated {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: var(--bs-warning);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -30,11 +30,27 @@
 | 
			
		||||
                {% endif %}
 | 
			
		||||
                {% if c.notification.addressees|length > 0 %}
 | 
			
		||||
                    <li class="notification-to">
 | 
			
		||||
                        <span class="item-key">
 | 
			
		||||
                        {% if c.notification_cc is defined %}
 | 
			
		||||
                            {% if c.notification_cc %}
 | 
			
		||||
                            <span class="item-key">
 | 
			
		||||
                                <abbr title="{{ 'notification.sent_cc'|trans }}">
 | 
			
		||||
                                    {{ 'notification.cc'|trans }} :
 | 
			
		||||
                                </abbr>
 | 
			
		||||
                            </span>
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                            <span class="item-key">
 | 
			
		||||
                                <abbr title="{{ 'notification.sent_to'|trans }}">
 | 
			
		||||
                                    {{ 'notification.to'|trans }} :
 | 
			
		||||
                                </abbr>
 | 
			
		||||
                            </span>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                        {% else %}
 | 
			
		||||
                          <span class="item-key">
 | 
			
		||||
                            <abbr title="{{ 'notification.sent_to'|trans }}">
 | 
			
		||||
                                {{ 'notification.to'|trans }} :
 | 
			
		||||
                            </abbr>
 | 
			
		||||
                        </span>
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
                        {% for a in c.notification.addressees %}
 | 
			
		||||
                            <span class="badge-user">
 | 
			
		||||
                                {{ a|chill_entity_render_string }}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
            'full_content': true,
 | 
			
		||||
            'fold_item': true,
 | 
			
		||||
            'action_button': true,
 | 
			
		||||
            'notification_cc': notificationCc,
 | 
			
		||||
        } %}{#
 | 
			
		||||
    #}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.isNotificationCc
 | 
			
		||||
                } %}
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,8 @@
 | 
			
		||||
            },
 | 
			
		||||
            'action_button': false,
 | 
			
		||||
            'full_content': true,
 | 
			
		||||
            'fold_item': false
 | 
			
		||||
            'fold_item': false,
 | 
			
		||||
            'notification_cc': notificationCc
 | 
			
		||||
        } %}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,8 @@
 | 
			
		||||
    <div id="futureDests">
 | 
			
		||||
        {{ form_row(transition_form.future_dest_users) }}
 | 
			
		||||
 | 
			
		||||
        {{ form_row(transition_form.future_cc_users) }}
 | 
			
		||||
 | 
			
		||||
        {{ form_row(transition_form.future_dest_emails) }}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,15 @@
 | 
			
		||||
                            </ul>
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
 | 
			
		||||
                        {% if step.ccUser|length > 0 %}
 | 
			
		||||
                            <p><b>{{ 'workflow.Users put in Cc'|trans }} : </b></p>
 | 
			
		||||
                            <ul>
 | 
			
		||||
                                {% for u in step.ccUser %}
 | 
			
		||||
                                    <li>{{ u|chill_entity_render_box }}</li>
 | 
			
		||||
                                {% endfor %}
 | 
			
		||||
                            </ul>
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
 | 
			
		||||
                        {% if entity_workflow.currentStep.destEmail|length > 0 %}
 | 
			
		||||
                            <p><b>{{ 'workflow.An access key was also sent to those addresses'|trans }} :</b></p>
 | 
			
		||||
                            <ul>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="col-10 workflow">
 | 
			
		||||
<div class="col-12 workflow">
 | 
			
		||||
 | 
			
		||||
    <h1 class="mb-5">{{ block('title') }}</h1>
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +25,12 @@
 | 
			
		||||
                {{ 'workflow.dest'|trans }}
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a href="{{ path('chill_main_workflow_list_cc') }}"
 | 
			
		||||
                class="nav-link {% if step == 'cc' %}active{% endif %}">
 | 
			
		||||
                {{ 'workflow.cc'|trans }}
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a href="{{ path('chill_main_workflow_list_previous_without_reaction') }}"
 | 
			
		||||
               class="nav-link {% if step == 'previous_without_reaction' %}active{% endif %}">
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,12 @@
 | 
			
		||||
                    {% for d in step.destUser %}{{ d|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}
 | 
			
		||||
                </b>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li>
 | 
			
		||||
                <span class="item-key">{{ 'workflow.Cc'|trans ~ ' : ' }}</span>
 | 
			
		||||
                <b>
 | 
			
		||||
                    {% for u in step.ccUser %}{{ u|chill_entity_render_string }}{% if not loop.last %}, {% endif %}{% endfor %}
 | 
			
		||||
                </b>
 | 
			
		||||
            </li>
 | 
			
		||||
        {% else %}
 | 
			
		||||
            <li>
 | 
			
		||||
                <span class="item-key">{{ 'workflow.Created by'|trans ~ ' : ' }}</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,39 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Chill is a software for social workers
 | 
			
		||||
 *
 | 
			
		||||
 * For the full copyright and license information, please view
 | 
			
		||||
 * the LICENSE file that was distributed with this source code.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\Migrations\Main;
 | 
			
		||||
 | 
			
		||||
use Doctrine\DBAL\Schema\Schema;
 | 
			
		||||
use Doctrine\Migrations\AbstractMigration;
 | 
			
		||||
 | 
			
		||||
final class Version20230321134155 extends AbstractMigration
 | 
			
		||||
{
 | 
			
		||||
    public function down(Schema $schema): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->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');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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%
 | 
			
		||||
 
 | 
			
		||||
@@ -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%
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user