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('
testok
');
+ 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 @@
+
+
+
+
+ {{ $t("signature_confirmation") }}
+
+
+
+
{{ $t("electronic_signature_in_progress") }}
+
+
+
+
+
+
{{ $t("you_are_going_to_sign") }}
+
{{ $t("are_you_sure") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ page {{ page }} / {{ pageCount }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 }}
-
+
{{ 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