Merge branch 'signature-app/zoom-button' into 'signature-app-master'

Signature app/zoom button

See merge request Chill-Projet/chill-bundles!751
This commit is contained in:
Julien Fastré 2024-11-06 18:34:14 +00:00
commit 9526d016c6
3 changed files with 165 additions and 80 deletions

View File

@ -130,3 +130,12 @@ export interface CheckSignature {
}
export type CanvasEvent = "select" | "add";
export interface ZoomLevel {
id: number;
zoom: number;
label: {
fr?: string,
nl?: string
};
}

View File

@ -28,24 +28,40 @@
</teleport>
<div class="col-12 m-auto">
<div class="row justify-content-center border-bottom pdf-tools d-md-none">
<div v-if="pageCount > 1" class="col text-center turn-page">
<button
class="btn btn-light btn-sm"
:disabled="page <= 1"
@click="turnPage(-1)"
<div class="col text-center turn-page">
<select
class="form-select form-select-sm"
id="zoomSelect"
v-model="zoomLevel"
@change="setZoomLevel(zoomLevel)"
>
</button>
<span>{{ page }}/{{ pageCount }}</span>
<button
class="btn btn-light btn-sm"
:disabled="page >= pageCount"
@click="turnPage(1)"
>
</button>
<option value="" selected disabled>Zoom</option>
<option v-for="z in zoomLevels" :value="z.zoom" :key="z.id">
{{ z.label.fr }}
</option>
</select>
<template v-if="pageCount > 1">
<button
class="btn btn-light btn-xs p-1"
:disabled="page <= 1"
@click="turnPage(-1)"
>
</button>
<span>{{ page }}/{{ pageCount }}</span>
<button
class="btn btn-light btn-xs p-1"
:disabled="page >= pageCount"
@click="turnPage(1)"
>
</button>
</template>
</div>
<div v-if="signature.zones.length > 1" class="col-3 p-0">
<div
v-if="signature.zones.length > 1"
class="col-5 p-0 text-center turnSignature"
>
<button
:disabled="userSignatureZone === null || userSignatureZone?.index < 1"
class="btn btn-light btn-sm"
@ -53,8 +69,7 @@
>
{{ $t("last_zone") }}
</button>
</div>
<div v-if="signature.zones.length > 1" class="col-3 p-0">
<span>|</span>
<button
:disabled="userSignatureZone?.index >= signature.zones.length - 1"
class="btn btn-light btn-sm"
@ -63,7 +78,7 @@
{{ $t("next_zone") }}
</button>
</div>
<div class="col text-end p-0">
<div class="col text-end" v-if="signedState !== 'signed'">
<button
class="btn btn-misc btn-sm"
:hidden="!userSignatureZone"
@ -81,8 +96,6 @@
>
{{ $t("cancel") }}
</button>
</div>
<div class="col-1" v-if="signedState !== 'signed'">
<button
class="btn btn-create btn-sm"
:class="{ active: canvasEvent === 'add' }"
@ -95,26 +108,39 @@
<div
class="row justify-content-center border-bottom pdf-tools d-none d-md-flex"
>
<div v-if="pageCount > 1" class="col-2 text-center turn-page p-0">
<button
class="btn btn-light btn-sm"
:disabled="page <= 1"
@click="turnPage(-1)"
<div class="col-3 text-center turn-page ps-3">
<select
class="form-select form-select-sm"
id="zoomSelect"
v-model="zoomLevel"
@change="setZoomLevel(zoomLevel)"
>
</button>
<span>{{ page }} / {{ pageCount }}</span>
<button
class="btn btn-light btn-sm"
:disabled="page >= pageCount"
@click="turnPage(1)"
>
</button>
<option value="" selected disabled>Zoom</option>
<option v-for="z in zoomLevels" :value="z.zoom" :key="z.id">
{{ z.label.fr }}
</option>
</select>
<template v-if="pageCount > 1">
<button
class="btn btn-light btn-xs p-1"
:disabled="page <= 1"
@click="turnPage(-1)"
>
</button>
<span>{{ page }} / {{ pageCount }}</span>
<button
class="btn btn-light btn-xs p-1"
:disabled="page >= pageCount"
@click="turnPage(1)"
>
</button>
</template>
</div>
<div
v-if="signature.zones.length > 1 && signedState !== 'signed'"
class="col text-end d-xl-none"
class="col-4 d-xl-none text-center turnSignature p-0"
>
<button
:disabled="userSignatureZone === null || userSignatureZone?.index < 1"
@ -123,11 +149,7 @@
>
{{ $t("last_zone") }}
</button>
</div>
<div
v-if="signature.zones.length > 1 && signedState !== 'signed'"
class="col text-start d-xl-none"
>
<span>|</span>
<button
:disabled="userSignatureZone?.index >= signature.zones.length - 1"
class="btn btn-light btn-sm"
@ -138,7 +160,7 @@
</div>
<div
v-if="signature.zones.length > 1 && signedState !== 'signed'"
class="col text-end d-none d-xl-flex p-0"
class="col-4 d-none d-xl-flex p-0 text-center turnSignature"
>
<button
:disabled="userSignatureZone === null || userSignatureZone?.index < 1"
@ -147,11 +169,7 @@
>
{{ $t("last_sign_zone") }}
</button>
</div>
<div
v-if="signature.zones.length > 1 && signedState !== 'signed'"
class="col text-start d-none d-xl-flex p-0"
>
<span>|</span>
<button
:disabled="userSignatureZone?.index >= signature.zones.length - 1"
class="btn btn-light btn-sm"
@ -160,7 +178,7 @@
{{ $t("next_sign_zone") }}
</button>
</div>
<div class="col text-end p-0" v-if="signedState !== 'signed'">
<div class="col text-end" v-if="signedState !== 'signed'">
<button
class="btn btn-misc btn-sm"
:hidden="!userSignatureZone"
@ -177,11 +195,6 @@
>
{{ $t("cancel") }}
</button>
</div>
<div
class="col text-end p-0 pe-2 pe-xxl-4"
v-if="signedState !== 'signed'"
>
<button
class="btn btn-create btn-sm"
:class="{ active: canvasEvent === 'add' }"
@ -199,7 +212,19 @@
<div class="col-xs-12 col-md-12 col-lg-9 m-auto p-4" id="action-buttons">
<div class="row">
<div class="col-4" v-if="signedState !== 'signed'">
<div class="col d-flex">
<a
class="btn btn-cancel"
v-if="signedState !== 'signed'"
:href="getReturnPath()"
>
{{ $t("cancel") }}
</a>
<a class="btn btn-misc" v-else :href="getReturnPath()">
{{ $t("return") }}
</a>
</div>
<div class="col text-end" v-if="signedState !== 'signed'">
<button
class="btn btn-action me-2"
:disabled="!userSignatureZone"
@ -209,18 +234,6 @@
</button>
</div>
<div class="col-4" v-else></div>
<div class="col-8 d-flex justify-content-end">
<a
class="btn btn-delete"
v-if="signedState !== 'signed'"
:href="getReturnPath()"
>
{{ $t("cancel_signing") }}
</a>
<a class="btn btn-misc" v-else :href="getReturnPath()">
{{ $t("return") }}
</a>
</div>
</div>
</div>
</template>
@ -235,6 +248,7 @@ import {
Signature,
SignatureZone,
SignedState,
ZoomLevel,
} from "../../types";
import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
import * as pdfjsLib from "pdfjs-dist";
@ -262,6 +276,52 @@ const canvasEvent: Ref<CanvasEvent> = ref("select");
const signedState: Ref<SignedState> = ref("pending");
const page: Ref<number> = ref(1);
const pageCount: Ref<number> = ref(0);
const zoom: Ref<number> = ref(1);
const zoomLevel = "";
const zoomLevels: Ref<ZoomLevel[]> = ref([
{
id: 0,
zoom: 0.75,
label: {
fr: "75%",
},
},
{
id: 1,
zoom: zoom.value,
label: {
fr: "100%",
},
},
{
id: 2,
zoom: 1.25,
label: {
fr: "125%",
},
},
{
id: 3,
zoom: 1.5,
label: {
fr: "150%",
},
},
{
id: 4,
zoom: 2,
label: {
fr: "200%",
},
},
{
id: 5,
zoom: 3,
label: {
fr: "300%",
},
},
]);
let userSignatureZone: Ref<null | SignatureZone> = ref(null);
let pdf = {} as PDFDocumentProxy;
@ -275,7 +335,11 @@ const $toast = useToast();
const signature = window.signature;
console.log(signature);
const setZoomLevel = (zoomLevel: string) => {
zoom.value = Number.parseFloat(zoomLevel);
setPage(page.value);
setTimeout(() => drawAllZones(page.value), 200);
};
const mountPdf = async (doc: ArrayBuffer) => {
const loadingTask = pdfjsLib.getDocument(doc);
@ -285,7 +349,7 @@ const mountPdf = async (doc: ArrayBuffer) => {
};
const getRenderContext = (pdfPage: PDFPageProxy) => {
const scale = 1;
const scale = 1 * zoom.value;
const viewport = pdfPage.getViewport({ scale });
const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement;
const context = canvas.getContext("2d") as CanvasRenderingContext2D;
@ -343,12 +407,12 @@ const hitSignature = (
scaleXToCanvas(zone.x, canvasWidth, zone.PDFPage.width) < xy[0] &&
xy[0] <
scaleXToCanvas(zone.x + zone.width, canvasWidth, zone.PDFPage.width) &&
zone.PDFPage.height -
zone.PDFPage.height * zoom.value -
scaleYToCanvas(zone.y, canvasHeight, zone.PDFPage.height) <
xy[1] &&
xy[1] <
scaleYToCanvas(zone.height - zone.y, canvasHeight, zone.PDFPage.height) +
zone.PDFPage.height;
zone.PDFPage.height * zoom.value;
const selectZone = (z: SignatureZone, canvas: HTMLCanvasElement) => {
userSignatureZone.value = z;
@ -425,19 +489,19 @@ const drawZone = (
ctx.lineJoin = "bevel";
ctx.strokeRect(
scaleXToCanvas(zone.x, canvasWidth, zone.PDFPage.width),
zone.PDFPage.height -
zone.PDFPage.height * zoom.value -
scaleYToCanvas(zone.y, canvasHeight, zone.PDFPage.height),
scaleXToCanvas(zone.width, canvasWidth, zone.PDFPage.width),
scaleYToCanvas(zone.height, canvasHeight, zone.PDFPage.height)
);
ctx.font = "bold 16px serif";
ctx.font = `bold ${16 * zoom.value}px serif`;
ctx.textAlign = "center";
ctx.fillStyle = "black";
const xText =
scaleXToCanvas(zone.x, canvasWidth, zone.PDFPage.width) +
scaleXToCanvas(zone.width, canvasWidth, zone.PDFPage.width) / 2;
const yText =
zone.PDFPage.height -
zone.PDFPage.height * zoom.value -
scaleYToCanvas(zone.y, canvasHeight, zone.PDFPage.height) +
scaleYToCanvas(zone.height, canvasHeight, zone.PDFPage.height) / 2;
if (userSignatureZone.value?.index === zone.index) {
@ -445,8 +509,8 @@ const drawZone = (
ctx.fillText("Signer ici", xText, yText);
} else {
ctx.fillStyle = unselectedBlue;
ctx.fillText("Choisir cette", xText, yText - 12);
ctx.fillText("zone de signature", xText, yText + 12);
ctx.fillText("Choisir cette", xText, yText - 12 * zoom.value);
ctx.fillText("zone de signature", xText, yText + 12 * zoom.value);
}
};
@ -616,16 +680,29 @@ div#action-buttons {
}
div.pdf-tools {
background-color: #f3f3f3;
font-size: 0.8rem;
font-size: 0.6rem;
button {
font-size: 0.75rem !important;
}
div.turnSignature {
span {
font-size: 1rem;
}
}
@media (min-width: 1400px) {
// background: none;
// border: none !important;
}
}
div.turn-page {
display: flex;
span {
font-size: 0.8rem;
margin: 0 0.4rem;
font-size: 0.75rem;
margin: auto 0.4rem;
}
select {
width: 5rem;
font-size: 0.75rem;
}
}
div.signature-modal-body {

View File

@ -12,7 +12,6 @@ const appMessages = {
sign: 'Signer',
choose_another_signature: 'Choisir une autre zone',
cancel: 'Annuler',
cancel_signing: 'Refuser de signer',
last_sign_zone: 'Zone de signature précédente',
next_sign_zone: 'Zone de signature suivante',
add_sign_zone: 'Ajouter une zone de signature',