diff --git a/package.json b/package.json index 2873e1317..d36197aa9 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "marked": "^12.0.2", "masonry-layout": "^4.2.2", "mime": "^4.0.0", + "pdfjs-dist": "^4.3.136", "swagger-ui": "^4.15.5", "vis-network": "^9.1.0", "vue": "^3.2.37", diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php index ad58b6e0c..ba17c1c73 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php @@ -26,6 +26,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Contracts\Translation\TranslatorInterface; +use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneParser; +use Chill\DocStoreBundle\Service\StoredObjectManagerInterface; /** * Class DocumentPersonController. @@ -40,6 +42,8 @@ class DocumentPersonController extends AbstractController protected TranslatorInterface $translator, protected EventDispatcherInterface $eventDispatcher, protected AuthorizationHelper $authorizationHelper, + protected PDFSignatureZoneParser $PDFSignatureZoneParser, + protected StoredObjectManagerInterface $storedObjectManagerInterface, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry ) {} @@ -197,4 +201,36 @@ class DocumentPersonController extends AbstractController ['document' => $document, 'person' => $person] ); } + + #[Route(path: '/{id}/signature', name: 'person_document_signature', methods: 'GET')] + public function signature(Person $person, PersonDocument $document): Response + { + $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); + $this->denyAccessUnlessGranted('CHILL_PERSON_DOCUMENT_SEE', $document); + + $event = new PrivacyEvent($person, [ + 'element_class' => PersonDocument::class, + 'element_id' => $document->getId(), + 'action' => 'show', + ]); + $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT); + + $storedObject = $document->getObject(); + $content = $this->storedObjectManagerInterface->read($storedObject); + $zones = $this->PDFSignatureZoneParser->findSignatureZones($content); + + $signature = []; + $signature['id'] = 1; + $signature['storedObject'] = [ // TEMP + 'filename' => $storedObject->getFilename(), + 'iv' => $storedObject->getIv(), + 'keyInfos' => $storedObject->getKeyInfos(), + ]; + $signature['zones'] = $zones; + + return $this->render( + '@ChillDocStore/PersonDocument/signature.html.twig', + ['document' => $document, 'person' => $person, 'signature' => $signature] + ); + } } diff --git a/src/Bundle/ChillDocStoreBundle/Controller/SignatureRequestController.php b/src/Bundle/ChillDocStoreBundle/Controller/SignatureRequestController.php index d76e9e5db..363ecafd4 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/SignatureRequestController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/SignatureRequestController.php @@ -11,12 +11,14 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Controller; -use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage; use Chill\DocStoreBundle\Service\Signature\PDFPage; use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone; use Chill\DocStoreBundle\Service\StoredObjectManagerInterface; -use Symfony\Component\HttpFoundation\Response; +use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature; +use Chill\MainBundle\Workflow\EntityWorkflowManager; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Routing\Annotation\Route; @@ -25,22 +27,41 @@ class SignatureRequestController public function __construct( private MessageBusInterface $messageBus, private StoredObjectManagerInterface $storedObjectManager, + private EntityWorkflowManager $entityWorkflowManager, ) {} #[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')] - public function processSignature(StoredObject $storedObject): Response + public function processSignature(EntityWorkflowStepSignature $signature, Request $request): JsonResponse { + $entityWorkflow = $signature->getStep()->getEntityWorkflow(); + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow); $content = $this->storedObjectManager->read($storedObject); + $data = \json_decode((string) $request->getContent(), true, 512, JSON_THROW_ON_ERROR); // TODO parse payload: json_decode ou, mieux, dataTransfertObject + $zone = new PDFSignatureZone( + $data['zone']['index'], + $data['zone']['x'], + $data['zone']['y'], + $data['zone']['height'], + $data['zone']['width'], + new PDFPage($data['zone']['PDFPage']['index'], $data['zone']['PDFPage']['width'], $data['zone']['PDFPage']['height']) + ); + $this->messageBus->dispatch(new RequestPdfSignMessage( - 0, - new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)), - 0, - 'test signature', - 'Mme Caroline Diallo', + $signature->getId(), + $zone, + $data['zone']['index'], + 'test signature', // reason (string) + 'Mme Caroline Diallo', // signerText (string) $content )); - return new Response('test

ok

'); + return new JsonResponse(null, JsonResponse::HTTP_OK, []); + } + + #[Route('/api/1.0/document/workflow/{id}/check-signature', name: 'chill_docstore_check_signature')] + public function checkSignature(EntityWorkflowStepSignature $signature): JsonResponse + { + return new JsonResponse($signature->getState(), JsonResponse::HTTP_OK, []); } } diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/types.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/types.ts index 25d956312..1fc8b1cdd 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/types.ts +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/types.ts @@ -26,11 +26,11 @@ export interface StoredObject { } export interface StoredObjectCreated { - status: "stored_object_created", - filename: string, - iv: Uint8Array, - keyInfos: object, - type: string, + status: "stored_object_created", + filename: string, + iv: Uint8Array, + keyInfos: object, + type: string, } export interface StoredObjectStatusChange { @@ -51,14 +51,35 @@ export type WopiEditButtonExecutableBeforeLeaveFunction = { * Object containing information for performering a POST request to a swift object store */ export interface PostStoreObjectSignature { - method: "POST", - max_file_size: number, - max_file_count: 1, - expires: number, - submit_delay: 180, - redirect: string, - prefix: string, - url: string, - signature: string, + method: "POST", + max_file_size: number, + max_file_count: 1, + expires: number, + submit_delay: 180, + redirect: string, + prefix: string, + url: string, + signature: string, } +export interface PDFPage { + index: number, + width: number, + height: number, +} +export interface SignatureZone { + index: number, + x: number, + y: number, + width: number, + height: number, + PDFPage: PDFPage, +} + +export interface Signature { + id: number, + storedObject: StoredObject, + zones: SignatureZone[], +} + +export type SignedState = 'pending' | 'signed' | 'rejected' | 'canceled' | 'error'; \ No newline at end of file diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue new file mode 100644 index 000000000..6773b5590 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue @@ -0,0 +1,426 @@ + + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts new file mode 100644 index 000000000..264622e72 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts @@ -0,0 +1,30 @@ +import { createApp } from "vue"; +// @ts-ignore +import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n"; +import App from "./App.vue"; + +const appMessages = { + fr: { + yes: 'Oui', + are_you_sure: 'Êtes-vous sûr·e?', + you_are_going_to_sign: 'Vous allez signer le document', + signature_confirmation: 'Confirmation de la signature', + sign: 'Signer', + choose_another_signature: 'Choisir une autre signature', + cancel: 'Annuler', + cancel_signing: 'Refuser de signer', + last_sign_zone: 'Zone de signature précédente', + next_sign_zone: 'Zone de signature suivante', + electronic_signature_in_progress: 'Signature électronique en cours...', + loading: 'Chargement...' + } +} + +const i18n = _createI18n(appMessages); + +const app = createApp({ + template: ``, +}) + .use(i18n) + .component("app", App) + .mount("#document-signature"); diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/signature.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/signature.html.twig new file mode 100644 index 000000000..b410f70d3 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/signature.html.twig @@ -0,0 +1,38 @@ + + + + + + + + Signature + + {{ encore_entry_link_tags('mod_bootstrap') }} + {{ encore_entry_link_tags('mod_forkawesome') }} + {{ encore_entry_link_tags('chill') }} + {{ encore_entry_link_tags('vue_document_signature') }} + + + + + + {% block js %} + {{ encore_entry_script_tags('mod_document_action_buttons_group') }} + + {{ encore_entry_script_tags('vue_document_signature') }} + {% endblock %} + +
+
+
+
+

{{ 'Document %title%' | trans({ '%title%': document.title }) }}

+
+
+
+
+
+ + diff --git a/src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandler.php b/src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandler.php index 81fb97dbf..5cb31de96 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandler.php +++ b/src/Bundle/ChillDocStoreBundle/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandler.php @@ -12,9 +12,12 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner; use Chill\DocStoreBundle\Service\StoredObjectManagerInterface; +use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum; use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureRepository; use Chill\MainBundle\Workflow\EntityWorkflowManager; +use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\Clock\ClockInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; final readonly class PdfSignedMessageHandler implements MessageHandlerInterface @@ -29,6 +32,8 @@ final readonly class PdfSignedMessageHandler implements MessageHandlerInterface private EntityWorkflowManager $entityWorkflowManager, private StoredObjectManagerInterface $storedObjectManager, private EntityWorkflowStepSignatureRepository $entityWorkflowStepSignatureRepository, + private EntityManagerInterface $entityManager, + private ClockInterface $clock, ) {} public function __invoke(PdfSignedMessage $message): void @@ -48,5 +53,9 @@ final readonly class PdfSignedMessageHandler implements MessageHandlerInterface } $this->storedObjectManager->write($storedObject, $message->content); + + $signature->setState(EntityWorkflowSignatureStateEnum::SIGNED)->setStateDate($this->clock->now()); + $this->entityManager->flush(); + $this->entityManager->clear(); } } diff --git a/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZone.php b/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZone.php index bdb4dcd65..c21b2fdc2 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZone.php +++ b/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZone.php @@ -16,6 +16,8 @@ use Symfony\Component\Serializer\Annotation\Groups; final readonly class PDFSignatureZone { public function __construct( + #[Groups(['read'])] + public int $index, #[Groups(['read'])] public float $x, #[Groups(['read'])] @@ -31,7 +33,8 @@ final readonly class PDFSignatureZone public function equals(self $other): bool { return - $this->x == $other->x + $this->index == $other->index + && $this->x == $other->x && $this->y == $other->y && $this->height == $other->height && $this->width == $other->width diff --git a/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneParser.php b/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneParser.php index d57b98abf..082d1afa2 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneParser.php +++ b/src/Bundle/ChillDocStoreBundle/Service/Signature/PDFSignatureZoneParser.php @@ -20,7 +20,7 @@ class PDFSignatureZoneParser private Parser $parser; public function __construct( - public float $defaultHeight = 180.0, + public float $defaultHeight = 90.0, public float $defaultWidth = 180.0, ) { $this->parser = new Parser(); @@ -37,6 +37,7 @@ class PDFSignatureZoneParser $defaults = $pdf->getObjectsByType('Pages'); $defaultPage = reset($defaults); $defaultPageDetails = $defaultPage->getDetails(); + $zoneIndex = 0; foreach ($pdf->getPages() as $index => $page) { $details = $page->getDetails(); @@ -48,7 +49,8 @@ class PDFSignatureZoneParser foreach ($page->getDataTm() as $dataTm) { if (str_starts_with($dataTm[1], self::ZONE_SIGNATURE_START)) { - $zones[] = new PDFSignatureZone((float) $dataTm[0][4], (float) $dataTm[0][5], $this->defaultHeight, $this->defaultWidth, $pdfPage); + $zones[] = new PDFSignatureZone($zoneIndex, (float) $dataTm[0][4], (float) $dataTm[0][5], $this->defaultHeight, $this->defaultWidth, $pdfPage); + ++$zoneIndex; } } } diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandlerTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandlerTest.php index 62d50c03f..eb2142175 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandlerTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/PdfSignedMessageHandlerTest.php @@ -22,8 +22,10 @@ use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureRepository; use Chill\MainBundle\Workflow\EntityWorkflowManager; use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; use Chill\PersonBundle\Entity\Person; +use Doctrine\ORM\EntityManagerInterface; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; +use Symfony\Component\Clock\MockClock; /** * @internal @@ -48,12 +50,16 @@ class PdfSignedMessageHandlerTest extends TestCase new NullLogger(), $this->buildEntityWorkflowManager($storedObject), $this->buildStoredObjectManager($storedObject, $expectedContent = '1234'), - $this->buildSignatureRepository($signature) + $this->buildSignatureRepository($signature), + $this->buildEntityManager(true), + new MockClock('now'), ); // we simply call the handler. The mocked StoredObjectManager will check that the "write" method is invoked once // with the content "1234" $handler(new PdfSignedMessage(10, $expectedContent)); + + self::assertEquals('signed', $signature->getState()->value); } private function buildSignatureRepository(EntityWorkflowStepSignature $signature): EntityWorkflowStepSignatureRepository @@ -81,4 +87,13 @@ class PdfSignedMessageHandlerTest extends TestCase return $storedObjectManager; } + + private function buildEntityManager(bool $willFlush): EntityManagerInterface + { + $em = $this->createMock(EntityManagerInterface::class); + $em->expects($willFlush ? $this->once() : $this->never())->method('flush'); + $em->expects($willFlush ? $this->once() : $this->never())->method('clear'); + + return $em; + } } diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializerTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializerTest.php index 6fda535df..312fabb19 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializerTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/Driver/BaseSigner/RequestPdfSignMessageSerializerTest.php @@ -36,7 +36,7 @@ class RequestPdfSignMessageSerializerTest extends TestCase $envelope = new Envelope( $request = new RequestPdfSignMessage( 0, - new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)), + new PDFSignatureZone(0, 10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)), 0, 'metadata to add to the signature', 'Mme Caroline Diallo', @@ -66,7 +66,7 @@ class RequestPdfSignMessageSerializerTest extends TestCase $request = new RequestPdfSignMessage( 0, - new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)), + new PDFSignatureZone(0, 10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)), 0, 'metadata to add to the signature', 'Mme Caroline Diallo', @@ -121,7 +121,7 @@ class RequestPdfSignMessageSerializerTest extends TestCase $denormalizer = new class () implements DenormalizerInterface { public function denormalize($data, string $type, ?string $format = null, array $context = []) { - return new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)); + return new PDFSignatureZone(0, 10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)); } public function supportsDenormalization($data, string $type, ?string $format = null) diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneParserTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneParserTest.php index 5a78c8bbf..4b70e61fc 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneParserTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Service/Signature/PDFSignatureZoneParserTest.php @@ -58,16 +58,18 @@ class PDFSignatureZoneParserTest extends TestCase __DIR__.'/data/signature_2_signature_page_1.pdf', [ new PDFSignatureZone( + 0, 127.7, 95.289, - 180.0, + 90.0, 180.0, $page = new PDFPage(0, 595.30393, 841.8897) ), new PDFSignatureZone( + 1, 269.5, 95.289, - 180.0, + 90.0, 180.0, $page, ), diff --git a/src/Bundle/ChillDocStoreBundle/chill.webpack.config.js b/src/Bundle/ChillDocStoreBundle/chill.webpack.config.js index 5d021462d..0a95f61b0 100644 --- a/src/Bundle/ChillDocStoreBundle/chill.webpack.config.js +++ b/src/Bundle/ChillDocStoreBundle/chill.webpack.config.js @@ -5,4 +5,5 @@ module.exports = function(encore) }); encore.addEntry('mod_async_upload', __dirname + '/Resources/public/module/async_upload/index.ts'); encore.addEntry('mod_document_action_buttons_group', __dirname + '/Resources/public/module/document_action_buttons_group/index'); + encore.addEntry('vue_document_signature', __dirname + '/Resources/public/vuejs/DocumentSignature/index.ts'); }; diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php index cdd432cf7..7d277ef0e 100644 --- a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php @@ -11,6 +11,8 @@ declare(strict_types=1); namespace Chill\MainBundle\Controller; +use Chill\DocStoreBundle\Service\StoredObjectManagerInterface; +use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneParser; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep; @@ -32,6 +34,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Registry; @@ -44,6 +47,7 @@ class WorkflowController extends AbstractController private readonly EntityWorkflowManager $entityWorkflowManager, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly ValidatorInterface $validator, + private readonly StoredObjectManagerInterface $storedObjectManagerInterface, private readonly PaginatorFactory $paginatorFactory, private readonly Registry $registry, private readonly EntityManagerInterface $entityManager, @@ -51,6 +55,7 @@ class WorkflowController extends AbstractController private readonly ChillSecurity $security, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, private readonly ClockInterface $clock, + private readonly PDFSignatureZoneParser $PDFSignatureZoneParser, ) {} #[Route(path: '/{_locale}/main/workflow/create', name: 'chill_main_workflow_create')] @@ -377,7 +382,7 @@ class WorkflowController extends AbstractController $signature = $this->entityManager->getRepository(EntityWorkflowStepSignature::class)->find($signature_id); if ($signature->getSigner() instanceof User) { - return $this->redirectToRoute('signature_route_user'); + return $this->redirectToRoute('chill_main_workflow_signature', ['signature_id' => $signature_id]); } $metadataForm = $this->createForm(WorkflowSignatureMetadataType::class); @@ -401,8 +406,7 @@ class WorkflowController extends AbstractController $this->entityManager->persist($signature); $this->entityManager->flush(); - // Todo should redirect to document for actual signing? To be adjusted still - return $this->redirectToRoute('chill_main_workflow_show', ['id' => $signature->getStep()->getEntityWorkflow()->getId()]); + return $this->redirectToRoute('chill_main_workflow_signature', ['signature_id' => $signature_id]); } return $this->render( @@ -413,4 +417,36 @@ class WorkflowController extends AbstractController ] ); } + + #[Route(path: '/{_locale}/main/workflow/signature/{signature_id}/sign', name: 'chill_main_workflow_signature', methods: 'GET')] + public function addSignature(int $signature_id, Request $request): Response + { + $signature = $this->entityManager->getRepository(EntityWorkflowStepSignature::class)->find($signature_id); + $entityWorkflow = $signature->getStep()->getEntityWorkflow(); + + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow); + if (null === $storedObject) { + throw new NotFoundHttpException('No stored object found'); + } + + $zones = []; + $content = $this->storedObjectManagerInterface->read($storedObject); + if (null != $content) { + $zones = $this->PDFSignatureZoneParser->findSignatureZones($content); + } + + $signatureClient = []; + $signatureClient['id'] = $signature->getId(); + $signatureClient['storedObject'] = [ + 'filename' => $storedObject->getFilename(), + 'iv' => $storedObject->getIv(), + 'keyInfos' => $storedObject->getKeyInfos(), + ]; + $signatureClient['zones'] = $zones; + + return $this->render( + '@ChillMain/Workflow/_signature_sign.html.twig', + ['signature' => $signatureClient] + ); + } } diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig index a61808500..f613b69dd 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature.html.twig @@ -1,19 +1,20 @@

{{ 'workflow.signature_zone.title'|trans }}

-
-
+
+
{% for s in signatures %} -
-
{{ s.signer|chill_entity_render_box }}
-
- {{ 'workflow.signature_zone.button_sign'|trans }} - {% if s.state is same as('signed') %} -

{{ s.stateDate }}

- {% endif %} -
+
{{ s.signer|chill_entity_render_box }}
+
+
{% endfor %}
- diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig new file mode 100644 index 000000000..8b2770952 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_signature_sign.html.twig @@ -0,0 +1,37 @@ + + + + + + + + Signature + + {{ encore_entry_link_tags('mod_bootstrap') }} + {{ encore_entry_link_tags('mod_forkawesome') }} + {{ encore_entry_link_tags('chill') }} + {{ encore_entry_link_tags('vue_document_signature') }} + + + + + + {% block js %} + {{ encore_entry_script_tags('mod_document_action_buttons_group') }} + + {{ encore_entry_script_tags('vue_document_signature') }} + {% endblock %} + +
+
+
+
+
+
+
+
+
+ + \ No newline at end of file