diff --git a/apps/OpenSign/src/components/pdf/PdfZoom.js b/apps/OpenSign/src/components/pdf/PdfZoom.js index c12868e01..4a0c54927 100644 --- a/apps/OpenSign/src/components/pdf/PdfZoom.js +++ b/apps/OpenSign/src/components/pdf/PdfZoom.js @@ -1,5 +1,6 @@ import React from "react"; import { useTranslation } from "react-i18next"; +import { rotatePdfPage } from "../../constant/Utils"; function PdfZoom(props) { const { t } = useTranslation(); @@ -17,9 +18,40 @@ function PdfZoom(props) { props.setZoomPercent(props.zoomPercent - 10); } }; - const handleReset = () => { - props.setScale(1); - props.setZoomPercent(0); + const handleRotationFun = async (rotateDegree) => { + const urlDetails = await rotatePdfPage( + props.file, + rotateDegree, + props.pageNumber - 1, + props.pdfRotateBase64 + ); + props.setPdfArrayBuffer(urlDetails.arrayBuffer); + props.setPdfRotatese64(urlDetails.base64); + }; + + const handleRotateRight = () => { + let rotateDegree; + if (props.rotateDegree < 360) { + rotateDegree = props.rotateDegree + 90; + props.setRotateDegree(rotateDegree); + handleRotationFun(rotateDegree); + } else { + rotateDegree = 90; + props.setRotateDegree(rotateDegree); + handleRotationFun(rotateDegree); + } + }; + const handleRotateLeft = () => { + let rotateDegree; + if (props.rotateDegree > -360) { + rotateDegree = props.rotateDegree - 90; + props.setRotateDegree(rotateDegree); + handleRotationFun(rotateDegree); + } else { + rotateDegree = -90; + props.setRotateDegree(rotateDegree); + handleRotationFun(rotateDegree); + } }; return ( // md:mt-[41px] xl:mt-[63px]mt=[] @@ -32,11 +64,26 @@ function PdfZoom(props) { handleRotateRight()} + title={t("Rotate right")} + > + + + + {/* + */} + handleRotateLeft()} + > +
@@ -78,7 +81,7 @@ function RenderAllPdfPage({ {Array.from(new Array(allPages), (el, index) => (
{ setPageNumber(index + 1); + setRotateDegree(0); if (setSignBtnPosition) { setSignBtnPosition([]); } diff --git a/apps/OpenSign/src/components/pdf/RenderPdf.js b/apps/OpenSign/src/components/pdf/RenderPdf.js index 4e1fe3fe2..dc9ec6386 100644 --- a/apps/OpenSign/src/components/pdf/RenderPdf.js +++ b/apps/OpenSign/src/components/pdf/RenderPdf.js @@ -61,7 +61,8 @@ function RenderPdf({ scale, setIsSelectId, ispublicTemplate, - handleUserDetails + handleUserDetails, + pdfRotateBase64 }) { const { t } = useTranslation(); const isMobile = window.innerWidth < 767; @@ -248,6 +249,8 @@ function RenderPdf({ ); } }; + const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`; + return ( <> {successEmail && ( @@ -405,7 +408,11 @@ function RenderPdf({ setSelectWidgetId(""); } }} - file={pdfDetails[0]?.SignedUrl || pdfDetails[0]?.URL} + file={ + (pdfRotateBase64 && pdfDataBase64) || + pdfDetails[0]?.SignedUrl || + pdfDetails[0].URL + } > { }; } }; + +//function to rotate pdf page +export async function rotatePdfPage( + url, + rotateDegree, + pageNumber, + pdfRotateBase64 +) { + let file; + if (pdfRotateBase64) { + file = base64ToArrayBuffer(pdfRotateBase64); + } else { + file = await convertPdfArrayBuffer(pdfRotateBase64 || url); + } + // Load the existing PDF + const pdfDoc = await PDFDocument.load(file); + // Get the page according to page number + const page = pdfDoc.getPage(pageNumber); + // Rotate the page + page.setRotation(degrees(rotateDegree)); + // Serialize the PDFDocument to bytes (a Uint8Array) + const base64 = await pdfDoc.saveAsBase64({ useObjectStreams: false }); + // console.log("pdfBytes",base64) + //convert base64 to arraybuffer + const arrayBuffer = base64ToArrayBuffer(base64); + return { arrayBuffer: arrayBuffer, base64: base64 }; +} +function base64ToArrayBuffer(base64) { + // Decode the base64 string to a binary string + const binaryString = atob(base64); + // Create a new ArrayBuffer with the same length as the binary string + const len = binaryString.length; + const bytes = new Uint8Array(len); + // Convert the binary string to a byte array + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + // Return the ArrayBuffer + return bytes.buffer; +} diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index e8a422fad..d3dbbcf43 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -132,6 +132,9 @@ function PdfRequestFiles(props) { const [res, setRes] = useState({}); const [documentId, setDocumentId] = useState(""); const [isPublicContact, setIsPublicContact] = useState(false); + const [rotateDegree, setRotateDegree] = useState(0); + const [pdfRotateBase64, setPdfRotatese64] = useState(""); + const [pdfArrayBuffer, setPdfArrayBuffer] = useState(""); const isHeader = useSelector((state) => state.showHeader); const divRef = useRef(null); @@ -298,6 +301,20 @@ function PdfRequestFiles(props) { : []; if (documentData && documentData.length > 0) { + const url = + documentData[0] && + (documentData[0]?.SignedUrl || documentData[0]?.URL); + if (url) { + //convert document url in array buffer format to use embed widgets in pdf using pdf-lib + const arrayBuffer = await convertPdfArrayBuffer(url); + if (arrayBuffer === "Error") { + setHandleError(t("something-went-wrong-mssg")); + } else { + setPdfArrayBuffer(arrayBuffer); + } + } else { + setHandleError(t("something-went-wrong-mssg")); + } setIsPublicTemplate(true); const getPublicRole = documentData[0]?.PublicRole[0]; const getUniqueIdDetails = documentData[0]?.Placeholders.find( @@ -361,6 +378,20 @@ function PdfRequestFiles(props) { //getting document details const documentData = await contractDocument(documentId || docId); if (documentData && documentData.length > 0) { + const url = + documentData[0] && + (documentData[0]?.SignedUrl || documentData[0]?.URL); + if (url) { + //convert document url in array buffer format to use embed widgets in pdf using pdf-lib + const arrayBuffer = await convertPdfArrayBuffer(url); + if (arrayBuffer === "Error") { + setHandleError(t("something-went-wrong-mssg")); + } else { + setPdfArrayBuffer(arrayBuffer); + } + } else { + setHandleError(t("something-went-wrong-mssg")); + } setExtUserId(documentData[0]?.ExtUserPtr?.objectId); const isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted; @@ -643,6 +674,7 @@ function PdfRequestFiles(props) { } }; + console.log("base64", pdfRotateBase64); //function for embed signature or image url in pdf async function embedWidgetsData() { //for emailVerified data checking first in localstorage @@ -818,30 +850,9 @@ function PdfRequestFiles(props) { setIsUiLoading(true); // `widgets` is Used to return widgets details with page number of current user const widgets = checkUser?.[0]?.placeHolder; - let pdfArrBuffer; - //`contractDocument` function used to get updated SignedUrl - //resolved issue of sign document by multiple signers simultaneously - const documentData = await contractDocument(documentId); - if (documentData && documentData.length > 0) { - const url = documentData[0]?.SignedUrl || documentData[0]?.URL; - //convert document url in array buffer format to use embed widgets in pdf using pdf-lib - const arrayBuffer = await convertPdfArrayBuffer(url); - if (arrayBuffer === "Error") { - setHandleError(t("invalid-document")); - } else { - pdfArrBuffer = arrayBuffer; - } - } else if ( - documentData === "Error: Something went wrong!" || - (documentData.result && documentData.result.error) - ) { - setHandleError(t("something-went-wrong-mssg")); - } else { - setHandleError(t("document-not-found")); - } // Load a PDFDocument from the existing PDF bytes - const existingPdfBytes = pdfArrBuffer; + const existingPdfBytes = pdfArrayBuffer; try { const pdfDoc = await PDFDocument.load(existingPdfBytes); const isSignYourSelfFlow = false; @@ -1111,6 +1122,7 @@ function PdfRequestFiles(props) { //function for change page function changePage(offset) { setPageNumber((prevPageNumber) => prevPageNumber + offset); + setRotateDegree(0); } //function for image upload or update @@ -1911,6 +1923,8 @@ function PdfRequestFiles(props) { setPageNumber={setPageNumber} pageNumber={pageNumber} containerWH={containerWH} + setRotateDegree={setRotateDegree} + pdfRotateBase64={pdfRotateBase64} /> {/* pdf render view */}
@@ -1920,6 +1934,16 @@ function PdfRequestFiles(props) { containerWH={containerWH} setZoomPercent={setZoomPercent} zoomPercent={zoomPercent} + setRotateDegree={setRotateDegree} + rotateDegree={rotateDegree} + file={ + pdfDetails[0] && + (pdfDetails[0].SignedUrl || pdfDetails[0].URL) + } + setPdfArrayBuffer={setPdfArrayBuffer} + setPdfRotatese64={setPdfRotatese64} + pageNumber={pageNumber} + pdfRotateBase64={pdfRotateBase64} />
{/* this modal is used show this document is already sign */} @@ -2108,6 +2132,7 @@ function PdfRequestFiles(props) { uniqueId={uniqueId} ispublicTemplate={isPublicTemplate} handleUserDetails={handleUserDetails} + pdfRotateBase64={pdfRotateBase64} /> )}
diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js index 3b8c99634..59cbeb693 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.js +++ b/apps/OpenSign/src/pages/PlaceHolderSign.js @@ -141,6 +141,8 @@ function PlaceHolderSign() { const [isCustomize, setIsCustomize] = useState(false); const [zoomPercent, setZoomPercent] = useState(0); const [scale, setScale] = useState(1); + const [rotateDegree, setRotateDegree] = useState(0); + const [pdfRotateBase64, setPdfRotatese64] = useState(""); const isMobile = window.innerWidth < 767; const [, drop] = useDrop({ accept: "BOX", @@ -805,6 +807,7 @@ function PlaceHolderSign() { function changePage(offset) { setSignBtnPosition([]); setPageNumber((prevPageNumber) => prevPageNumber + offset); + setRotateDegree(0); } //function for capture position on hover or touch widgets @@ -853,7 +856,7 @@ function PlaceHolderSign() { }); const isSignYourSelfFlow = false; try { - const pdfBytes = await multiSignEmbed( + const pdfBase64 = await multiSignEmbed( placeholder, pdfDoc, isSignYourSelfFlow, @@ -863,18 +866,29 @@ function PlaceHolderSign() { ); const fileName = sanitizeFileName(pdfDetails[0].Name) + ".pdf"; - const pdfFile = new Parse.File(fileName, { base64: pdfBytes }); + const pdfFile = new Parse.File(fileName, { base64: pdfBase64 }); // Save the Parse File if needed const pdfData = await pdfFile.save(); const pdfUrl = pdfData.url(); const tenantId = localStorage.getItem("TenantId"); - const buffer = atob(pdfBytes); + const buffer = atob(pdfBase64); SaveFileSize(buffer.length, pdfUrl, tenantId); return pdfUrl; } catch (e) { console.log("error", e); } + } else if (pdfRotateBase64) { + const fileName = sanitizeFileName(pdfDetails[0].Name) + ".pdf"; + const pdfFile = new Parse.File(fileName, { base64: pdfRotateBase64 }); + + // Save the Parse File if needed + const pdfData = await pdfFile.save(); + const pdfUrl = pdfData.url(); + const tenantId = localStorage.getItem("TenantId"); + const buffer = atob(pdfRotateBase64); + SaveFileSize(buffer.length, pdfUrl, tenantId); + return pdfUrl; } else { return pdfDetails[0].URL; } @@ -1739,6 +1753,8 @@ function PlaceHolderSign() { setPageNumber={setPageNumber} setSignBtnPosition={setSignBtnPosition} pageNumber={pageNumber} + setRotateDegree={setRotateDegree} + pdfRotateBase64={pdfRotateBase64} /> {/* pdf render view */}
@@ -1748,6 +1764,16 @@ function PlaceHolderSign() { containerWH={containerWH} setZoomPercent={setZoomPercent} zoomPercent={zoomPercent} + setRotateDegree={setRotateDegree} + rotateDegree={rotateDegree} + file={ + pdfDetails[0] && + (pdfDetails[0].SignedUrl || pdfDetails[0].URL) + } + setPdfArrayBuffer={setPdfArrayBuffer} + setPdfRotatese64={setPdfRotatese64} + pageNumber={pageNumber} + pdfRotateBase64={pdfRotateBase64} />
{/* this modal is used show alert set placeholder for all signers before send mail */} @@ -2025,6 +2051,7 @@ function PlaceHolderSign() { setScale={setScale} scale={scale} setIsSelectId={setIsSelectId} + pdfRotateBase64={pdfRotateBase64} /> )}
diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index 20b1b58e1..f8bc6d573 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -123,6 +123,8 @@ function SignYourSelf() { const [zoomPercent, setZoomPercent] = useState(0); const isHeader = useSelector((state) => state.showHeader); const [scale, setScale] = useState(1); + const [rotateDegree, setRotateDegree] = useState(0); + const [pdfRotateBase64, setPdfRotatese64] = useState(""); const divRef = useRef(null); const nodeRef = useRef(null); const [, drop] = useDrop({ @@ -862,6 +864,7 @@ function SignYourSelf() { function changePage(offset) { setSignBtnPosition([]); setPageNumber((prevPageNumber) => prevPageNumber + offset); + setRotateDegree(0); } //function for image upload or update const onImageChange = (event) => { @@ -1213,6 +1216,8 @@ function SignYourSelf() { setSignBtnPosition={setSignBtnPosition} pageNumber={pageNumber} containerWH={containerWH} + setRotateDegree={setRotateDegree} + pdfRotateBase64={pdfRotateBase64} />
)}
diff --git a/apps/OpenSign/src/pages/TemplatePlaceholder.js b/apps/OpenSign/src/pages/TemplatePlaceholder.js index 18c350ec8..3dc2b9258 100644 --- a/apps/OpenSign/src/pages/TemplatePlaceholder.js +++ b/apps/OpenSign/src/pages/TemplatePlaceholder.js @@ -26,7 +26,8 @@ import { radioButtonWidget, fetchSubscription, getContainerScale, - openInNewTab + openInNewTab, + convertPdfArrayBuffer } from "../constant/Utils"; import RenderPdf from "../components/pdf/RenderPdf"; import "../styles/AddUser.css"; @@ -93,6 +94,9 @@ const TemplatePlaceholder = () => { const [isNameModal, setIsNameModal] = useState(false); const [isTextSetting, setIsTextSetting] = useState(false); const [pdfLoad, setPdfLoad] = useState(false); + const [rotateDegree, setRotateDegree] = useState(0); + const [pdfRotateBase64, setPdfRotatese64] = useState(""); + const [pdfArrayBuffer, setPdfArrayBuffer] = useState(""); const color = [ "#93a3db", "#e6c3db", @@ -230,6 +234,18 @@ const TemplatePlaceholder = () => { : []; if (documentData && documentData.length > 0) { + const url = documentData[0] && documentData[0]?.URL; + if (url) { + //convert document url in array buffer format to use embed widgets in pdf using pdf-lib + const arrayBuffer = await convertPdfArrayBuffer(url); + if (arrayBuffer === "Error") { + setHandleError(t("something-went-wrong-mssg")); + } else { + setPdfArrayBuffer(arrayBuffer); + } + } else { + setHandleError(t("something-went-wrong-mssg")); + } if (isEnableSubscription) { checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email); } @@ -691,6 +707,7 @@ const TemplatePlaceholder = () => { function changePage(offset) { setSignBtnPosition([]); setPageNumber((prevPageNumber) => prevPageNumber + offset); + setRotateDegree(0); } //function for capture position on hover or touch widgets @@ -1321,6 +1338,16 @@ const TemplatePlaceholder = () => { containerWH={containerWH} setZoomPercent={setZoomPercent} zoomPercent={zoomPercent} + setRotateDegree={setRotateDegree} + rotateDegree={rotateDegree} + file={ + pdfDetails[0] && + (pdfDetails[0].SignedUrl || pdfDetails[0].URL) + } + setPdfArrayBuffer={setPdfArrayBuffer} + setPdfRotatese64={setPdfRotatese64} + pageNumber={pageNumber} + pdfRotateBase64={pdfRotateBase64} />
{/* this modal is used show alert set placeholder for all signers before send mail */} @@ -1496,6 +1523,7 @@ const TemplatePlaceholder = () => { setScale={setScale} scale={scale} setIsSelectId={setIsSelectId} + pdfRotateBase64={pdfRotateBase64} /> )}