diff --git a/.changes/unreleased/Feature-20241205-172341.yaml b/.changes/unreleased/Feature-20241205-172341.yaml new file mode 100644 index 000000000..8a7117d38 --- /dev/null +++ b/.changes/unreleased/Feature-20241205-172341.yaml @@ -0,0 +1,5 @@ +kind: Feature +body: Show all the pages of the documents in the signature app +time: 2024-12-05T17:23:41.866322287+01:00 +custom: + Issue: "318" diff --git a/config/packages/chill_workflow_signature_documents.yaml b/config/packages/chill_workflow_signature_documents.yaml new file mode 100644 index 000000000..5784f55e7 --- /dev/null +++ b/config/packages/chill_workflow_signature_documents.yaml @@ -0,0 +1,11 @@ +chill_main: + workflow_signature: + base_signer: + document_kinds: + - { key: id_card, labels: [ { lang: fr, label: "Carte d'identité" } ] } + - { key: passport, labels: [ { lang: fr, label: "Passeport" } ] } + - { key: drivers_license, labels: [ { lang: fr, label: "Permis de conduire" } ] } + - { key: visa_long_stay, labels: [ { lang: fr, label: "Visa de long séjour" } ] } + - { key: resident_permit, labels: [ { lang: fr, label: "Carte de séjour" } ] } + - { key: residency_card, labels: [ { lang: fr, label: "Carte de résident" } ] } + - { key: provisionary_residency_permit, labels: [ { lang: fr, label: "Autorisation provisoire de séjour" } ] } diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue index 483db281f..fb3b82459 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue @@ -26,9 +26,9 @@ -
+
-
+
❯ + +
+ +
+
-
@@ -298,6 +340,7 @@ import {download_and_decrypt_doc, download_doc_as_pdf} from "../StoredObjectButt pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs"; +const multiPage: Ref = ref(true); const modalOpen: Ref = ref(false); const loading: Ref = ref(false); const adding: Ref = ref(false); @@ -364,23 +407,37 @@ const $toast = useToast(); const signature = window.signature; -const setZoomLevel = (zoomLevel: string) => { +const setZoomLevel = async (zoomLevel: string) => { zoom.value = Number.parseFloat(zoomLevel); - setPage(page.value); - setTimeout(() => drawAllZones(page.value), 200); + await resetPages(); + setTimeout(drawAllZones, 200); }; const mountPdf = async (doc: ArrayBuffer) => { const loadingTask = pdfjsLib.getDocument(doc); pdf = await loadingTask.promise; pageCount.value = pdf.numPages; - await setPage(page.value); + if (multiPage.value) { + await setAllPages(); + } else { + await setPage(1); + } +}; + +const getCanvas = (page: number) => + multiPage.value + ? (document.getElementById(`canvas-${page}`) as HTMLCanvasElement) + : (document.querySelectorAll("canvas")[0] as HTMLCanvasElement); + +const getCanvasId = (canvas: HTMLCanvasElement) => { + const number = canvas.id.split("-").pop(); + return number ? parseInt(number) : 0; }; const getRenderContext = (pdfPage: PDFPageProxy) => { const scale = 1 * zoom.value; const viewport = pdfPage.getViewport({ scale }); - const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement; + const canvas = getCanvas(pdfPage.pageNumber); const context = canvas.getContext("2d") as CanvasRenderingContext2D; canvas.height = viewport.height; canvas.width = viewport.width; @@ -391,6 +448,9 @@ const getRenderContext = (pdfPage: PDFPageProxy) => { }; }; +const setAllPages = async () => + Array.from(Array(pageCount.value).keys()).map((p) => setPage(p + 1)); + const setPage = async (page: number) => { const pdfPage = await pdf.getPage(page); const renderContext = getRenderContext(pdfPage); @@ -412,10 +472,34 @@ async function downloadAndOpen(): Promise { return raw; } +const addCanvasEvents = () => { + if (multiPage.value) { + Array.from(Array(pageCount.value).keys()).map((p) => { + const canvas = getCanvas(p + 1); + canvas.addEventListener( + "pointerup", + (e) => canvasClick(e, canvas), + false + ); + }); + } else { + const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement; + canvas.addEventListener("pointerup", (e) => canvasClick(e, canvas), false); + } +}; + const initPdf = () => { - const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement; - canvas.addEventListener("pointerup", canvasClick, false); - setTimeout(() => drawAllZones(page.value), 800); + addCanvasEvents(); + setTimeout(drawAllZones, 800); +}; + +const resetPages = () => + multiPage.value ? setAllPages() : setPage(page.value); + +const toggleMultiPage = async () => { + await resetPages(); + setTimeout(drawAllZones, 200); + addCanvasEvents(); }; const scaleXToCanvas = (x: number, canvasWidth: number, PDFWidth: number) => @@ -427,35 +511,36 @@ const scaleYToCanvas = (h: number, canvasHeight: number, PDFHeight: number) => const hitSignature = ( zone: SignatureZone, xy: number[], - canvasWidth: number, - canvasHeight: number + canvas: HTMLCanvasElement ) => - scaleXToCanvas(zone.x, canvasWidth, zone.PDFPage.width) < xy[0] && + scaleXToCanvas(zone.x, canvas.width, zone.PDFPage.width) < xy[0] && xy[0] < - scaleXToCanvas(zone.x + zone.width, canvasWidth, zone.PDFPage.width) && + scaleXToCanvas(zone.x + zone.width, canvas.width, zone.PDFPage.width) && zone.PDFPage.height * zoom.value - - scaleYToCanvas(zone.y, canvasHeight, zone.PDFPage.height) < + scaleYToCanvas(zone.y, canvas.height, zone.PDFPage.height) < xy[1] && xy[1] < - scaleYToCanvas(zone.height - zone.y, canvasHeight, zone.PDFPage.height) + + scaleYToCanvas(zone.height - zone.y, canvas.height, zone.PDFPage.height) + zone.PDFPage.height * zoom.value; -const selectZone = (z: SignatureZone, canvas: HTMLCanvasElement) => { +const selectZone = async (z: SignatureZone, canvas: HTMLCanvasElement) => { userSignatureZone.value = z; const ctx = canvas.getContext("2d"); if (ctx) { - setPage(page.value); - setTimeout(() => drawAllZones(page.value), 200); + await resetPages(); + setTimeout(drawAllZones, 200); } }; const selectZoneEvent = (e: PointerEvent, canvas: HTMLCanvasElement) => signature.zones - .filter((z) => z.PDFPage.index + 1 === page.value) + .filter( + (z) => + (z.PDFPage.index + 1 === getCanvasId(canvas) && multiPage.value) || + (z.PDFPage.index + 1 === page.value && !multiPage.value) + ) .map((z) => { - if ( - hitSignature(z, [e.offsetX, e.offsetY], canvas.width, canvas.height) - ) { + if (hitSignature(z, [e.offsetX, e.offsetY], canvas)) { if (userSignatureZone.value === null) { selectZone(z, canvas); } else { @@ -466,18 +551,20 @@ const selectZoneEvent = (e: PointerEvent, canvas: HTMLCanvasElement) => } }); -const canvasClick = (e: PointerEvent) => { - const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement; +const canvasClick = (e: PointerEvent, canvas: HTMLCanvasElement) => canvasEvent.value === "select" ? selectZoneEvent(e, canvas) : addZoneEvent(e, canvas); -}; const turnPage = async (upOrDown: number) => { - //userSignatureZone.value = null; // desactivate the reset of the zone when turning page page.value = page.value + upOrDown; - await setPage(page.value); - setTimeout(() => drawAllZones(page.value), 200); + if (multiPage.value) { + const canvas = getCanvas(page.value); + canvas.scrollIntoView(); + } else { + await setPage(page.value); + setTimeout(drawAllZones, 200); + } }; const turnSignature = async (upOrDown: number) => { @@ -493,9 +580,9 @@ const turnSignature = async (upOrDown: number) => { let currentZone = signature.zones[zoneIndex]; if (currentZone) { page.value = currentZone.PDFPage.index + 1; - userSignatureZone.value = currentZone; - const canvas = document.querySelectorAll("canvas")[0]; + const canvas = getCanvas(currentZone.PDFPage.index + 1); selectZone(currentZone, canvas); + canvas.scrollIntoView(); } }; @@ -540,19 +627,25 @@ const drawZone = ( } }; -const drawAllZones = (page: number) => { - const canvas = document.querySelectorAll("canvas")[0]; - const ctx = canvas.getContext("2d"); - if (ctx && signedState.value !== "signed") { +const drawAllZones = () => { + if (signedState.value !== "signed") { signature.zones - .filter((z) => z.PDFPage.index + 1 === page) + .filter( + (z) => + multiPage.value || + (z.PDFPage.index + 1 === page.value && !multiPage.value) + ) .map((z) => { - if (userSignatureZone.value) { - if (userSignatureZone.value?.index === z.index) { + const canvas = getCanvas(z.PDFPage.index + 1); + const ctx = canvas.getContext("2d"); + if (ctx) { + if (userSignatureZone.value) { + if (userSignatureZone.value?.index === z.index) { + drawZone(z, ctx, canvas.width, canvas.height); + } + } else { drawZone(z, ctx, canvas.width, canvas.height); } - } else { - drawZone(z, ctx, canvas.width, canvas.height); } }); } @@ -638,8 +731,8 @@ const confirmSign = () => { const undoSign = async () => { signature.zones = signature.zones.filter((z) => z.index !== null); - await setPage(page.value); - setTimeout(() => drawAllZones(page.value), 200); + await resetPages(); + setTimeout(drawAllZones, 200); userSignatureZone.value = null; adding.value = false; canvasEvent.value = "select"; @@ -671,7 +764,7 @@ const addZoneEvent = async (e: PointerEvent, canvas: HTMLCanvasElement) => { width: BOX_WIDTH * zoom.value, height: BOX_HEIGHT * zoom.value, PDFPage: { - index: page.value - 1, + index: multiPage.value ? getCanvasId(canvas) - 1 : page.value - 1, width: PDFPageWidth, height: PDFPageHeight, }, @@ -679,8 +772,8 @@ const addZoneEvent = async (e: PointerEvent, canvas: HTMLCanvasElement) => { signature.zones.push(newZone); userSignatureZone.value = newZone; - await setPage(page.value); - setTimeout(() => drawAllZones(page.value), 200); + await resetPages(); + setTimeout(drawAllZones, 200); canvasEvent.value = "select"; adding.value = true; }; @@ -695,14 +788,15 @@ init();