diff --git a/apps/OpenSign/src/pages/Form.js b/apps/OpenSign/src/pages/Form.js index 98192793e..3dfee1aa9 100644 --- a/apps/OpenSign/src/pages/Form.js +++ b/apps/OpenSign/src/pages/Form.js @@ -12,6 +12,7 @@ import Title from "../components/Title"; import PageNotFound from "./PageNotFound"; import { SaveFileSize } from "../constant/saveFileSize"; import { getFileName } from "../constant/Utils"; +import { PDFDocument } from "pdf-lib"; // `Form` render all type of Form on this basis of their provided in path function Form() { @@ -41,7 +42,7 @@ const Forms = (props) => { TimeToCompleteDays: 15, SendinOrder: "false" }); - const [fileupload, setFileUpload] = useState([]); + const [fileupload, setFileUpload] = useState(""); const [fileload, setfileload] = useState(false); const [percentage, setpercentage] = useState(0); const [isReset, setIsReset] = useState(false); @@ -55,7 +56,23 @@ const Forms = (props) => { handleReset(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.title]); - const handleFileInput = (e) => { + + function getFileAsArrayBuffer(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = (e) => { + resolve(e.target.result); + }; + + reader.onerror = (e) => { + reject(e.target.error); + }; + + reader.readAsArrayBuffer(file); + }); + } + const handleFileInput = async (e) => { setpercentage(0); try { let files = e.target.files; @@ -65,11 +82,21 @@ const Forms = (props) => { alert( `The selected file size is too large. Please select a file less than ${maxFileSize} MB` ); - setFileUpload([]); + setFileUpload(""); e.target.value = ""; return; } else { - handleFileUpload(files[0]); + try { + const res = await getFileAsArrayBuffer(files[0]); + const pdfBytes = await PDFDocument.load(res); + console.log("pdfbytes ", pdfBytes); + handleFileUpload(files[0]); + } catch (err) { + alert(`Currently encrypted pdf files are not supported.`); + setFileUpload(""); + e.target.value = ""; + console.log("err ", err); + } } } else { alert("Please select file."); @@ -162,64 +189,68 @@ const Forms = (props) => { const handleSubmit = async (e) => { e.preventDefault(); e.stopPropagation(); - setIsSubmit(true); - try { - const currentUser = Parse.User.current(); - const object = new Parse.Object(props.Cls); - object.set("Name", formData?.Name); - object.set("Description", formData?.Description); - object.set("Note", formData?.Note); - if (props.title === "Request Signatures") { - object.set( - "TimeToCompleteDays", - parseInt(formData?.TimeToCompleteDays) - ); - } - if (props.title !== "Sign Yourself") { - const isChecked = formData.SendinOrder === "false" ? false : true; - object.set("SendinOrder", isChecked); - } - object.set("URL", fileupload); - object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); - if (folder && folder.ObjectId) { - object.set("Folder", { + if (fileupload) { + setIsSubmit(true); + try { + const currentUser = Parse.User.current(); + const object = new Parse.Object(props.Cls); + object.set("Name", formData?.Name); + object.set("Description", formData?.Description); + object.set("Note", formData?.Note); + if (props.title === "Request Signatures") { + object.set( + "TimeToCompleteDays", + parseInt(formData?.TimeToCompleteDays) + ); + } + if (props.title !== "Sign Yourself") { + const isChecked = formData.SendinOrder === "false" ? false : true; + object.set("SendinOrder", isChecked); + } + object.set("URL", fileupload); + object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); + if (folder && folder.ObjectId) { + object.set("Folder", { + __type: "Pointer", + className: props.Cls, + objectId: folder.ObjectId + }); + } + if (signers && signers.length > 0) { + object.set("Signers", signers); + } + const ExtCls = JSON.parse(localStorage.getItem("Extand_Class")); + object.set("ExtUserPtr", { __type: "Pointer", - className: props.Cls, - objectId: folder.ObjectId + className: "contracts_Users", + objectId: ExtCls[0].objectId }); - } - if (signers && signers.length > 0) { - object.set("Signers", signers); - } - const ExtCls = JSON.parse(localStorage.getItem("Extand_Class")); - object.set("ExtUserPtr", { - __type: "Pointer", - className: "contracts_Users", - objectId: ExtCls[0].objectId - }); - const res = await object.save(); - if (res) { - setSigners([]); - setFolder({ ObjectId: "", Name: "" }); - setFormData({ - Name: "", - Description: "", - Note: "" - }); - setFileUpload([]); - setpercentage(0); - navigate(`/${props?.redirectRoute}/${res.id}`); + const res = await object.save(); + if (res) { + setSigners([]); + setFolder({ ObjectId: "", Name: "" }); + setFormData({ + Name: "", + Description: "", + Note: "" + }); + setFileUpload(""); + setpercentage(0); + navigate(`/${props?.redirectRoute}/${res.id}`); + } + } catch (err) { + console.log("err ", err); + setIsErr(true); + } finally { + setIsAlert(true); + setTimeout(() => { + setIsAlert(false); + }, 1000); + setIsSubmit(false); } - } catch (err) { - console.log("err ", err); - setIsErr(true); - } finally { - setIsAlert(true); - setTimeout(() => { - setIsAlert(false); - }, 1000); - setIsSubmit(false); + } else { + alert("Please wait until the PDF has been uploading."); } }; @@ -251,11 +282,11 @@ const Forms = (props) => { TimeToCompleteDays: 15, SendinOrder: "true" }); - setFileUpload([]); + setFileUpload(""); setpercentage(0); setTimeout(() => setIsReset(false), 50); }; - + return (
@@ -303,7 +334,7 @@ const Forms = (props) => { file selected : {getFileName(fileupload)} </div> <div - onClick={() => setFileUpload([])} + onClick={() => setFileUpload("")} className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" > <i className="fa-solid fa-xmark"></i> diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 4f173f34c..e3ec3012f 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -439,112 +439,114 @@ function PdfRequestFiles() { async function embedWidgetsData() { // const validateSigning = checkSendInOrder(); // if (validateSigning) { - const checkUser = signerPos.filter( - (data) => data.signerObjId === signerObjectId - ); - if (checkUser && checkUser.length > 0) { - let checkboxExist, - requiredRadio, - showAlert = false, - widgetKey, - radioExist, - requiredCheckbox; + try { + const checkUser = signerPos.filter( + (data) => data.signerObjId === signerObjectId + ); + if (checkUser && checkUser.length > 0) { + let checkboxExist, + requiredRadio, + showAlert = false, + widgetKey, + radioExist, + requiredCheckbox; - for (let i = 0; i < checkUser[0].placeHolder.length; i++) { - for (let j = 0; j < checkUser[0].placeHolder[i].pos.length; j++) { - checkboxExist = - checkUser[0].placeHolder[i].pos[j].type === "checkbox"; - radioExist = - checkUser[0].placeHolder[i].pos[j].type === radioButtonWidget; - if (checkboxExist) { - requiredCheckbox = checkUser[0].placeHolder[i].pos.filter( - (position) => - !position.options?.isReadOnly && position.type === "checkbox" - ); + for (let i = 0; i < checkUser[0].placeHolder.length; i++) { + for (let j = 0; j < checkUser[0].placeHolder[i].pos.length; j++) { + checkboxExist = + checkUser[0].placeHolder[i].pos[j].type === "checkbox"; + radioExist = + checkUser[0].placeHolder[i].pos[j].type === radioButtonWidget; + if (checkboxExist) { + requiredCheckbox = checkUser[0].placeHolder[i].pos.filter( + (position) => + !position.options?.isReadOnly && position.type === "checkbox" + ); - if (requiredCheckbox && requiredCheckbox.length > 0) { - for (let i = 0; i < requiredCheckbox.length; i++) { - const minCount = - requiredCheckbox[i].options?.validation?.minRequiredCount; - const parseMin = minCount && parseInt(minCount); - const maxCount = - requiredCheckbox[i].options?.validation?.maxRequiredCount; - const parseMax = maxCount && parseInt(maxCount); - const response = requiredCheckbox[i].options?.response?.length; - const defaultValue = - requiredCheckbox[i].options?.defaultValue?.length; - if (parseMin === 0 && parseMax === 0) { - if (!showAlert) { - showAlert = false; - setminRequiredCount(null); - } - } else if (parseMin === 0 && parseMax > 0) { - if (!showAlert) { - showAlert = false; - setminRequiredCount(null); - } - } else if (!response) { - if (!defaultValue) { + if (requiredCheckbox && requiredCheckbox.length > 0) { + for (let i = 0; i < requiredCheckbox.length; i++) { + const minCount = + requiredCheckbox[i].options?.validation?.minRequiredCount; + const parseMin = minCount && parseInt(minCount); + const maxCount = + requiredCheckbox[i].options?.validation?.maxRequiredCount; + const parseMax = maxCount && parseInt(maxCount); + const response = requiredCheckbox[i].options?.response?.length; + const defaultValue = + requiredCheckbox[i].options?.defaultValue?.length; + if (parseMin === 0 && parseMax === 0) { + if (!showAlert) { + showAlert = false; + setminRequiredCount(null); + } + } else if (parseMin === 0 && parseMax > 0) { + if (!showAlert) { + showAlert = false; + setminRequiredCount(null); + } + } else if (!response) { + if (!defaultValue) { + if (!showAlert) { + showAlert = true; + widgetKey = requiredCheckbox[i].key; + setminRequiredCount(parseMin); + } + } + } else if (parseMin > 0 && parseMin > response) { if (!showAlert) { showAlert = true; widgetKey = requiredCheckbox[i].key; setminRequiredCount(parseMin); } } - } else if (parseMin > 0 && parseMin > response) { - if (!showAlert) { - showAlert = true; - widgetKey = requiredCheckbox[i].key; - setminRequiredCount(parseMin); - } } } - } - } else if (radioExist) { - requiredRadio = checkUser[0].placeHolder[i].pos.filter( - (position) => - !position.options?.isReadOnly && - position.type === radioButtonWidget - ); - if (requiredRadio && requiredRadio?.length > 0) { - let checkSigned; - for (let i = 0; i < requiredRadio?.length; i++) { - checkSigned = requiredRadio[i]?.options.response; - if (!checkSigned) { - let checkDefaultSigned = - requiredRadio[i]?.options.defaultValue; - if (!checkDefaultSigned) { - if (!showAlert) { - showAlert = true; - widgetKey = requiredRadio[i].key; - setminRequiredCount(null); + } else if (radioExist) { + requiredRadio = checkUser[0].placeHolder[i].pos.filter( + (position) => + !position.options?.isReadOnly && + position.type === radioButtonWidget + ); + if (requiredRadio && requiredRadio?.length > 0) { + let checkSigned; + for (let i = 0; i < requiredRadio?.length; i++) { + checkSigned = requiredRadio[i]?.options.response; + if (!checkSigned) { + let checkDefaultSigned = + requiredRadio[i]?.options.defaultValue; + if (!checkDefaultSigned) { + if (!showAlert) { + showAlert = true; + widgetKey = requiredRadio[i].key; + setminRequiredCount(null); + } } } } } - } - } else { - const requiredWidgets = checkUser[0].placeHolder[i].pos.filter( - (position) => - position.options?.status === "required" && - position.type !== radioButtonWidget && - position.type !== "checkbox" - ); - if (requiredWidgets && requiredWidgets?.length > 0) { - let checkSigned; - for (let i = 0; i < requiredWidgets?.length; i++) { - checkSigned = requiredWidgets[i]?.options?.response; - if (!checkSigned) { - const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; + } else { + const requiredWidgets = checkUser[0].placeHolder[i].pos.filter( + (position) => + position.options?.status === "required" && + position.type !== radioButtonWidget && + position.type !== "checkbox" + ); + if (requiredWidgets && requiredWidgets?.length > 0) { + let checkSigned; + for (let i = 0; i < requiredWidgets?.length; i++) { + checkSigned = requiredWidgets[i]?.options?.response; + if (!checkSigned) { + const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; - let checkDefaultSigned = - requiredWidgets[i]?.options?.defaultValue; - if (!checkSignUrl) { - if (!checkDefaultSigned) { - if (!showAlert) { - showAlert = true; - widgetKey = requiredWidgets[i].key; - setminRequiredCount(null); + let checkDefaultSigned = + requiredWidgets[i]?.options?.defaultValue; + if (!checkSignUrl) { + if (!checkDefaultSigned) { + if (!showAlert) { + showAlert = true; + widgetKey = requiredWidgets[i].key; + setminRequiredCount(null); + } } } } @@ -553,216 +555,223 @@ function PdfRequestFiles() { } } } - } - if (checkboxExist && requiredCheckbox && showAlert) { - setUnSignedWidgetId(widgetKey); - setWidgetsTour(true); - } else if (radioExist && showAlert) { - setUnSignedWidgetId(widgetKey); - setWidgetsTour(true); - } else if (showAlert) { - setUnSignedWidgetId(widgetKey); - setWidgetsTour(true); - } else { - setIsUiLoading(true); - const pngUrl = checkUser[0].placeHolder; - // Load a PDFDocument from the existing PDF bytes - const existingPdfBytes = pdfArrayBuffer; - const pdfDoc = await PDFDocument.load(existingPdfBytes, { - ignoreEncryption: true - }); - const isSignYourSelfFlow = false; - const extUserPtr = pdfDetails[0].ExtUserPtr; - const HeaderDocId = extUserPtr?.HeaderDocId; - //embed document's object id to all pages in pdf document - if (!HeaderDocId) { - if (!isDocId) { - await embedDocId(pdfDoc, documentId, allPages); - } - } - //embed multi signature in pdf - const pdfBytes = await multiSignEmbed( - pngUrl, - pdfDoc, - pdfOriginalWidth, - isSignYourSelfFlow, - containerWH - ); - //get ExistUserPtr object id of user class to get tenantDetails - const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; - - const res = await contractUsers(jsonSender?.email); - console.log("res", res); - let activeMailAdapter = ""; - if (res === "Error: Something went wrong!") { - setHandleError("Error: Something went wrong!"); - setIsLoading({ - isLoad: false + if (checkboxExist && requiredCheckbox && showAlert) { + setUnSignedWidgetId(widgetKey); + setWidgetsTour(true); + } else if (radioExist && showAlert) { + setUnSignedWidgetId(widgetKey); + setWidgetsTour(true); + } else if (showAlert) { + setUnSignedWidgetId(widgetKey); + setWidgetsTour(true); + } else { + setIsUiLoading(true); + const pngUrl = checkUser[0].placeHolder; + // Load a PDFDocument from the existing PDF bytes + const existingPdfBytes = pdfArrayBuffer; + const pdfDoc = await PDFDocument.load(existingPdfBytes, { + ignoreEncryption: true }); - } else if (!res || res?.length === 0) { - activeMailAdapter = ""; - } else if (res[0] && res.length) { - activeMailAdapter = res[0]?.active_mail_adapter; - } - //function for call to embed signature in pdf and get digital signature pdf - try { - const res = await signPdfFun( - pdfBytes, - documentId, - signerObjectId, - setIsAlert, - objectId, - isSubscribed, - activeMailAdapter + const isSignYourSelfFlow = false; + const extUserPtr = pdfDetails[0].ExtUserPtr; + const HeaderDocId = extUserPtr?.HeaderDocId; + //embed document's object id to all pages in pdf document + if (!HeaderDocId) { + if (!isDocId) { + await embedDocId(pdfDoc, documentId, allPages); + } + } + //embed multi signature in pdf + const pdfBytes = await multiSignEmbed( + pngUrl, + pdfDoc, + pdfOriginalWidth, + isSignYourSelfFlow, + containerWH ); - if (res && res.status === "success") { - setPdfUrl(res.data); - setIsSigned(true); - setSignedSigners([]); - setUnSignedSigners([]); - getDocumentDetails(); - const index = pdfDetails?.[0].Signers.findIndex( - (x) => x.Email === jsonSender.email + //get ExistUserPtr object id of user class to get tenantDetails + const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; + //get ExistUserPtr email to get userDetails + const currentUserEmail = pdfDetails?.[0]?.ExtUserPtr?.Email; + const res = await contractUsers(currentUserEmail); + let activeMailAdapter = ""; + if (res === "Error: Something went wrong!") { + setHandleError("Error: Something went wrong!"); + setIsLoading({ + isLoad: false + }); + } else if (!res || res?.length === 0) { + activeMailAdapter = ""; + } else if (res[0] && res.length) { + activeMailAdapter = res[0]?.active_mail_adapter; + } + //function for call to embed signature in pdf and get digital signature pdf + try { + const res = await signPdfFun( + pdfBytes, + documentId, + signerObjectId, + setIsAlert, + objectId, + isSubscribed, + activeMailAdapter ); - const newIndex = index + 1; - const user = pdfDetails?.[0].Signers[newIndex]; - if (user) { - setIsCompleted({ - isModal: true, - message: - "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers." - }); - } - if (sendInOrder) { - const requestBody = pdfDetails?.[0]?.RequestBody; - const requestSubject = pdfDetails?.[0]?.RequestSubject; + if (res && res.status === "success") { + setPdfUrl(res.data); + setIsSigned(true); + setSignedSigners([]); + setUnSignedSigners([]); + getDocumentDetails(); + const index = pdfDetails?.[0].Signers.findIndex( + (x) => x.Email === jsonSender.email + ); + const newIndex = index + 1; + const user = pdfDetails?.[0].Signers[newIndex]; if (user) { - const expireDate = pdfDetails?.[0].ExpiryDate.iso; - const newDate = new Date(expireDate); - const localExpireDate = newDate.toLocaleDateString("en-US", { - day: "numeric", - month: "long", - year: "numeric" + setIsCompleted({ + isModal: true, + message: + "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers." }); - let senderEmail = pdfDetails?.[0].ExtUserPtr.Email; - let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone; - const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`; + } + if (sendInOrder) { + const requestBody = pdfDetails?.[0]?.RequestBody; + const requestSubject = pdfDetails?.[0]?.RequestSubject; + if (user) { + const expireDate = pdfDetails?.[0].ExpiryDate.iso; + const newDate = new Date(expireDate); + const localExpireDate = newDate.toLocaleDateString("en-US", { + day: "numeric", + month: "long", + year: "numeric" + }); + let senderEmail = pdfDetails?.[0].ExtUserPtr.Email; + let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone; + const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`; - try { - const imgPng = - "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; - let url = `${localStorage.getItem( - "baseUrl" - )}functions/sendmailv3/`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": - localStorage.getItem("parseAppId"), - sessionToken: localStorage.getItem("accesstoken") - }; - const serverUrl = localStorage.getItem("baseUrl"); - const newServer = serverUrl.replaceAll("/", "%2F"); - const objectId = user.objectId; - const serverParams = `${newServer}&${localStorage.getItem( - "parseAppId" - )}&${localStorage.getItem("_appName")}`; - const hostUrl = window.location.origin; - let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`; - const openSignUrl = "https://www.opensignlabs.com/contact-us"; - const orgName = pdfDetails[0]?.ExtUserPtr.Company - ? pdfDetails[0].ExtUserPtr.Company - : ""; - const themeBGcolor = themeColor; - let replaceVar; - if ( - requestBody && - requestSubject && - (!isEnableSubscription || isSubscribed) - ) { - const replacedRequestBody = requestBody.replace(/"/g, "'"); - const htmlReqBody = - "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" + - replacedRequestBody + - "</body> </html>"; + try { + const imgPng = + "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; + let url = `${localStorage.getItem( + "baseUrl" + )}functions/sendmailv3/`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": + localStorage.getItem("parseAppId"), + sessionToken: localStorage.getItem("accesstoken") + }; + const serverUrl = localStorage.getItem("baseUrl"); + const newServer = serverUrl.replaceAll("/", "%2F"); + const objectId = user.objectId; + const serverParams = `${newServer}&${localStorage.getItem( + "parseAppId" + )}&${localStorage.getItem("_appName")}`; + const hostUrl = window.location.origin; + let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`; + const openSignUrl = "https://www.opensignlabs.com/contact-us"; + const orgName = pdfDetails[0]?.ExtUserPtr.Company + ? pdfDetails[0].ExtUserPtr.Company + : ""; + const themeBGcolor = themeColor; + let replaceVar; + if ( + requestBody && + requestSubject && + (!isEnableSubscription || isSubscribed) + ) { + const replacedRequestBody = requestBody.replace(/"/g, "'"); + const htmlReqBody = + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" + + replacedRequestBody + + "</body> </html>"; - const variables = { - document_title: pdfDetails?.[0].Name, - sender_name: senderName, - sender_mail: senderEmail, - sender_phone: senderPhone, - receiver_name: user.Name, - receiver_email: user.Email, - receiver_phone: user.Phone, - expiry_date: localExpireDate, - company_name: orgName, - signing_url: `<a href=${signPdf}>Sign here</a>` + const variables = { + document_title: pdfDetails?.[0].Name, + sender_name: senderName, + sender_mail: senderEmail, + sender_phone: senderPhone, + receiver_name: user.Name, + receiver_email: user.Email, + receiver_phone: user.Phone, + expiry_date: localExpireDate, + company_name: orgName, + signing_url: `<a href=${signPdf}>Sign here</a>` + }; + replaceVar = replaceMailVaribles( + requestSubject, + htmlReqBody, + variables + ); + } + + let params = { + mailProvider: activeMailAdapter, + extUserId: extUserId, + recipient: user.Email, + subject: requestSubject + ? replaceVar?.subject + : `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, + from: senderEmail, + html: requestBody + ? replaceVar?.body + : "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + + imgPng + + " height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" + + themeBGcolor + + ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + + pdfDetails?.[0].ExtUserPtr.Name + + " has requested you to review and sign <strong> " + + pdfDetails?.[0].Name + + "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + + senderEmail + + "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + + orgName + + "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + + localExpireDate + + "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + + signPdf + + "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + + senderEmail + + " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " + + openSignUrl + + " target=_blank>here</a>.</p> </div></div></body> </html>" }; - replaceVar = replaceMailVaribles( - requestSubject, - htmlReqBody, - variables - ); + await axios.post(url, params, { + headers: headers + }); + } catch (error) { + console.log("error", error); } - - let params = { - mailProvider: activeMailAdapter, - extUserId: extUserId, - recipient: user.Email, - subject: requestSubject - ? replaceVar?.subject - : `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, - from: senderEmail, - html: requestBody - ? replaceVar?.body - : "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + - imgPng + - " height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" + - themeBGcolor + - ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + - pdfDetails?.[0].ExtUserPtr.Name + - " has requested you to review and sign <strong> " + - pdfDetails?.[0].Name + - "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + - senderEmail + - "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + - orgName + - "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + - localExpireDate + - "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + - signPdf + - "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + - senderEmail + - " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " + - openSignUrl + - " target=_blank>here</a>.</p> </div></div></body> </html>" - }; - await axios.post(url, params, { - headers: headers - }); - } catch (error) { - console.log("error", error); } } + } else { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); } - } else { + } catch (err) { setIsAlert({ isShow: true, alertMessage: "something went wrong" }); } - } catch (err) { - setIsAlert({ - isShow: true, - alertMessage: "something went wrong" - }); } + setIsSignPad(false); + } else { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); } - setIsSignPad(false); - } else { + } catch (err) { + console.log("err in embedsign", err); + setIsUiLoading(false); setIsAlert({ isShow: true, - alertMessage: "something went wrong" + alertMessage: "something went wrong, please try again later." }); } diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js index cb8928940..d161c032b 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.js +++ b/apps/OpenSign/src/pages/PlaceHolderSign.js @@ -173,15 +173,6 @@ function PlaceHolderSign() { : rowLevel?.objectId && rowLevel.objectId; const documentId = docId ? docId : objectId && objectId; - const senderUser = - localStorage.getItem( - `Parse/${localStorage.getItem("parseAppId")}/currentUser` - ) && - localStorage.getItem( - `Parse/${localStorage.getItem("parseAppId")}/currentUser` - ); - const jsonSender = JSON.parse(senderUser); - useEffect(() => { if (documentId) { getDocumentDetails(); @@ -406,7 +397,8 @@ function PlaceHolderSign() { }; setIsLoading(loadObj); } - const res = await contractUsers(jsonSender.email); + const currentUserEmail = documentData[0]?.ExtUserPtr?.Email; + const res = await contractUsers(currentUserEmail); if (res === "Error: Something went wrong!") { const loadObj = { isLoad: false diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index b14c6934c..1babe9128 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -443,13 +443,13 @@ function SignYourSelf() { Width: widgetTypeExist ? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth : dragTypeValue === "initials" - ? defaultWidthHeight(dragTypeValue).width - : "", + ? defaultWidthHeight(dragTypeValue).width + : "", Height: widgetTypeExist ? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight : dragTypeValue === "initials" - ? defaultWidthHeight(dragTypeValue).height - : "", + ? defaultWidthHeight(dragTypeValue).height + : "", options: addWidgetOptions(dragTypeValue) }; @@ -530,70 +530,79 @@ function SignYourSelf() { //function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url async function embedWidgetsData() { let showAlert = false; - - for (let i = 0; i < xyPostion?.length; i++) { - const requiredWidgets = xyPostion[i].pos.filter( - (position) => position.type !== "checkbox" - ); - if (requiredWidgets && requiredWidgets?.length > 0) { - let checkSigned; - for (let i = 0; i < requiredWidgets?.length; i++) { - checkSigned = requiredWidgets[i]?.options?.response; - if (!checkSigned) { - const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; - let checkDefaultSigned = requiredWidgets[i]?.options?.defaultValue; - if (!checkSignUrl) { - if (!checkDefaultSigned) { - if (!showAlert) { - showAlert = true; + try { + for (let i = 0; i < xyPostion?.length; i++) { + const requiredWidgets = xyPostion[i].pos.filter( + (position) => position.type !== "checkbox" + ); + if (requiredWidgets && requiredWidgets?.length > 0) { + let checkSigned; + for (let i = 0; i < requiredWidgets?.length; i++) { + checkSigned = requiredWidgets[i]?.options?.response; + if (!checkSigned) { + const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; + let checkDefaultSigned = + requiredWidgets[i]?.options?.defaultValue; + if (!checkSignUrl) { + if (!checkDefaultSigned) { + if (!showAlert) { + showAlert = true; + } } } } } } } - } - if (xyPostion.length === 0) { - setIsAlert({ - isShow: true, - alertMessage: "Please complete your signature!" - }); - return; - } else if (showAlert) { + if (xyPostion.length === 0) { + setIsAlert({ + isShow: true, + alertMessage: "Please complete your signature!" + }); + return; + } else if (showAlert) { + setIsAlert({ + isShow: true, + alertMessage: "Please complete your signature!" + }); + return; + } else { + setIsCeleb(true); + setTimeout(() => { + setIsCeleb(false); + }, 3000); + setIsUiLoading(true); + const existingPdfBytes = pdfArrayBuffer; + // Load a PDFDocument from the existing PDF bytes + const pdfDoc = await PDFDocument.load(existingPdfBytes, { + ignoreEncryption: true + }); + const isSignYourSelfFlow = true; + const extUserPtr = pdfDetails[0].ExtUserPtr; + const HeaderDocId = extUserPtr?.HeaderDocId; + //embed document's object id to all pages in pdf document + if (!HeaderDocId) { + await embedDocId(pdfDoc, documentId, allPages); + } + //embed multi signature in pdf + const pdfBytes = await multiSignEmbed( + xyPostion, + pdfDoc, + pdfOriginalWidth, + isSignYourSelfFlow, + containerWH + ); + // console.log("pdf", pdfBytes); + //function for call to embed signature in pdf and get digital signature pdf + await signPdfFun(pdfBytes, documentId); + } + } catch (err) { + console.log("err in embedselfsign ", err ); + setIsUiLoading(false); setIsAlert({ isShow: true, - alertMessage: "Please complete your signature!" + alertMessage: "something went wrong, please try again later." }); - return; - } else { - setIsCeleb(true); - setTimeout(() => { - setIsCeleb(false); - }, 3000); - setIsUiLoading(true); - const existingPdfBytes = pdfArrayBuffer; - // Load a PDFDocument from the existing PDF bytes - const pdfDoc = await PDFDocument.load(existingPdfBytes, { - ignoreEncryption: true - }); - const isSignYourSelfFlow = true; - const extUserPtr = pdfDetails[0].ExtUserPtr; - const HeaderDocId = extUserPtr?.HeaderDocId; - //embed document's object id to all pages in pdf document - if (!HeaderDocId) { - await embedDocId(pdfDoc, documentId, allPages); - } - //embed multi signature in pdf - const pdfBytes = await multiSignEmbed( - xyPostion, - pdfDoc, - pdfOriginalWidth, - isSignYourSelfFlow, - containerWH - ); - // console.log("pdf", pdfBytes); - //function for call to embed signature in pdf and get digital signature pdf - await signPdfFun(pdfBytes, documentId); } } // console.log("signyourself", xyPostion); diff --git a/apps/OpenSignServer/Utils.js b/apps/OpenSignServer/Utils.js index 18d90138b..038f66aec 100644 --- a/apps/OpenSignServer/Utils.js +++ b/apps/OpenSignServer/Utils.js @@ -1,4 +1,6 @@ import axios from 'axios'; +import dotenv from 'dotenv'; +dotenv.config(); const appId = process.env.APP_ID; const serverUrl = process.env.SERVER_URL; @@ -243,3 +245,5 @@ export function sanitizeFileName(fileName) { const removedot = file.replace(/\.(?=.*\.)/g, ''); return removedot.replace(/[^a-zA-Z0-9._-]/g, ''); } + +export const useLocal = process.env.USE_LOCAL ? process.env.USE_LOCAL.toLowerCase() : 'false'; diff --git a/apps/OpenSignServer/cloud/customRoute/uploadFile.js b/apps/OpenSignServer/cloud/customRoute/uploadFile.js index 352f7711b..dd1e681a2 100644 --- a/apps/OpenSignServer/cloud/customRoute/uploadFile.js +++ b/apps/OpenSignServer/cloud/customRoute/uploadFile.js @@ -3,6 +3,7 @@ import multer from 'multer'; import multerS3 from 'multer-s3'; import aws from 'aws-sdk'; import dotenv from 'dotenv'; +import { useLocal } from '../../Utils.js'; dotenv.config(); function sanitizeFileName(fileName) { @@ -51,7 +52,7 @@ async function uploadFile(req, res) { const parseBaseUrl = process.env.SERVER_URL; const parseAppId = process.env.APP_ID; let fileStorage; - if (process.env.USE_LOCAL == 'TRUE') { + if (useLocal === 'true') { fileStorage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'files/files'); @@ -147,7 +148,7 @@ async function uploadFile(req, res) { const status = 'Success'; //res.header("Access-Control-Allow-Headers", "Content-Type"); //res.setHeader("Access-Control-Allow-Origin", "*"); - if (process.env.USE_LOCAL == 'TRUE') { + if (useLocal === 'true') { console.log(req.file); var fileUrl = `${parseBaseUrl}/files/${parseAppId}/${req.file.filename}`; } else { diff --git a/apps/OpenSignServer/cloud/parsefunction/DocumentAfterFind.js b/apps/OpenSignServer/cloud/parsefunction/DocumentAfterFind.js index f913b1e66..2ae392cd9 100644 --- a/apps/OpenSignServer/cloud/parsefunction/DocumentAfterFind.js +++ b/apps/OpenSignServer/cloud/parsefunction/DocumentAfterFind.js @@ -1,23 +1,25 @@ +import { useLocal } from '../../Utils.js'; import getPresignedUrl from './getSignedUrl.js'; async function DocumentAfterFind(request) { - if (request.objects.length === 1) { - if (request.objects) { - const obj = request.objects[0]; - const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl'); - const Url = obj?.get('URL') && obj?.get('URL'); - const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl'); - if (SignedUrl) { - obj.set('SignedUrl', getPresignedUrl(SignedUrl)); + if (useLocal !== 'true') { + if (request.objects.length === 1) { + if (request.objects) { + const obj = request.objects[0]; + const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl'); + const Url = obj?.get('URL') && obj?.get('URL'); + const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl'); + if (SignedUrl) { + obj.set('SignedUrl', getPresignedUrl(SignedUrl)); + } + if (Url) { + obj.set('URL', getPresignedUrl(Url)); + } + if (certificateUrl) { + obj.set('CertificateUrl', getPresignedUrl(certificateUrl)); + } + return [obj]; } - if (Url) { - obj.set('URL', getPresignedUrl(Url)); - } - if (certificateUrl) { - obj.set('CertificateUrl', getPresignedUrl(certificateUrl)); - } - - return [obj]; } } } diff --git a/apps/OpenSignServer/cloud/parsefunction/SignatureAfterFind.js b/apps/OpenSignServer/cloud/parsefunction/SignatureAfterFind.js index 45ca5a8b5..1d1174324 100644 --- a/apps/OpenSignServer/cloud/parsefunction/SignatureAfterFind.js +++ b/apps/OpenSignServer/cloud/parsefunction/SignatureAfterFind.js @@ -1,21 +1,21 @@ +import { useLocal } from '../../Utils.js'; import getPresignedUrl from './getSignedUrl.js'; async function SignatureAfterFind(request) { - if (request.objects.length === 1) { - if (request.objects) { - const obj = request.objects[0]; - const ImageURL = obj?.get('ImageURL') && obj?.get('ImageURL'); - const Initials = obj?.get('Initials') && obj?.get('Initials'); - - if (ImageURL) { - obj.set('ImageURL', getPresignedUrl(ImageURL)); - } - - if (Initials) { - obj.set('Initials', getPresignedUrl(Initials)); + if (useLocal !== 'true') { + if (request.objects.length === 1) { + if (request.objects) { + const obj = request.objects[0]; + const ImageURL = obj?.get('ImageURL') && obj?.get('ImageURL'); + const Initials = obj?.get('Initials') && obj?.get('Initials'); + if (ImageURL) { + obj.set('ImageURL', getPresignedUrl(ImageURL)); + } + if (Initials) { + obj.set('Initials', getPresignedUrl(Initials)); + } + return [obj]; } - - return [obj]; } } } diff --git a/apps/OpenSignServer/cloud/parsefunction/TemplateAfterFind.js b/apps/OpenSignServer/cloud/parsefunction/TemplateAfterFind.js index 10f730669..6fab363c8 100644 --- a/apps/OpenSignServer/cloud/parsefunction/TemplateAfterFind.js +++ b/apps/OpenSignServer/cloud/parsefunction/TemplateAfterFind.js @@ -1,23 +1,26 @@ +import { useLocal } from '../../Utils.js'; import getPresignedUrl from './getSignedUrl.js'; async function TemplateAfterFind(request) { - if (request.objects.length === 1) { - if (request.objects) { - const obj = request.objects[0]; - const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl'); - const Url = obj?.get('URL') && obj?.get('URL'); - const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl'); - if (SignedUrl) { - obj.set('SignedUrl', getPresignedUrl(SignedUrl)); - } - if (Url) { - obj.set('URL', getPresignedUrl(Url)); - } - if (certificateUrl) { - obj.set('CertificateUrl', getPresignedUrl(certificateUrl)); - } + if (useLocal !== 'true') { + if (request.objects.length === 1) { + if (request.objects) { + const obj = request.objects[0]; + const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl'); + const Url = obj?.get('URL') && obj?.get('URL'); + const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl'); + if (SignedUrl) { + obj.set('SignedUrl', getPresignedUrl(SignedUrl)); + } + if (Url) { + obj.set('URL', getPresignedUrl(Url)); + } + if (certificateUrl) { + obj.set('CertificateUrl', getPresignedUrl(certificateUrl)); + } - return [obj]; + return [obj]; + } } } } diff --git a/apps/OpenSignServer/cloud/parsefunction/TenantAfterFind.js b/apps/OpenSignServer/cloud/parsefunction/TenantAfterFind.js index 2af96c4d5..bb520928f 100644 --- a/apps/OpenSignServer/cloud/parsefunction/TenantAfterFind.js +++ b/apps/OpenSignServer/cloud/parsefunction/TenantAfterFind.js @@ -1,14 +1,17 @@ +import { useLocal } from '../../Utils.js'; import getPresignedUrl from './getSignedUrl.js'; async function TenantAterFind(request) { - if (request.objects.length === 1) { - if (request.objects) { - const obj = request.objects[0]; - const Logo = obj?.get('Logo') && obj?.get('Logo'); - if (Logo) { - obj.set('Logo', getPresignedUrl(Logo)); + if (useLocal !== 'true') { + if (request.objects.length === 1) { + if (request.objects) { + const obj = request.objects[0]; + const Logo = obj?.get('Logo') && obj?.get('Logo'); + if (Logo) { + obj.set('Logo', getPresignedUrl(Logo)); + } + return [obj]; } - return [obj]; } } } diff --git a/apps/OpenSignServer/cloud/parsefunction/UserAfterFInd.js b/apps/OpenSignServer/cloud/parsefunction/UserAfterFInd.js index b27d2d272..5a414e1ac 100644 --- a/apps/OpenSignServer/cloud/parsefunction/UserAfterFInd.js +++ b/apps/OpenSignServer/cloud/parsefunction/UserAfterFInd.js @@ -1,16 +1,17 @@ +import { useLocal } from '../../Utils.js'; import getPresignedUrl from './getSignedUrl.js'; async function UserAfterFind(request) { - if (request.objects.length === 1) { - if (request.objects) { - const obj = request.objects[0]; - const ProfilePic = obj?.get('ProfilePic') && obj?.get('ProfilePic'); - - if (ProfilePic) { - obj.set('ProfilePic', getPresignedUrl(ProfilePic)); + if (useLocal !== 'true') { + if (request.objects.length === 1) { + if (request.objects) { + const obj = request.objects[0]; + const ProfilePic = obj?.get('ProfilePic') && obj?.get('ProfilePic'); + if (ProfilePic) { + obj.set('ProfilePic', getPresignedUrl(ProfilePic)); + } + return [obj]; } - - return [obj]; } } } diff --git a/apps/OpenSignServer/index.js b/apps/OpenSignServer/index.js index 43a4bd591..a9432da6b 100644 --- a/apps/OpenSignServer/index.js +++ b/apps/OpenSignServer/index.js @@ -1,9 +1,5 @@ -// Example express application adding the parse-server module to expose Parse -// compatible API routes. - import dotenv from 'dotenv'; dotenv.config(); - import express from 'express'; import cors from 'cors'; import { ParseServer } from 'parse-server'; @@ -21,9 +17,10 @@ import { exec } from 'child_process'; import { createTransport } from 'nodemailer'; import { app as v1 } from './cloud/customRoute/v1/apiV1.js'; import { PostHog } from 'posthog-node'; -// console.log("configuration ", configuration); +import { useLocal } from './Utils.js'; + let fsAdapter; -if (process.env.USE_LOCAL !== 'TRUE') { +if (useLocal !== 'true') { try { const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT); const s3Options = { @@ -98,6 +95,7 @@ export const config = { import('./cloud/main.js'); }, appId: process.env.APP_ID || 'myAppId', + logLevel: ['error'], maxLimit: 500, maxUploadSize: '30mb', masterKey: process.env.MASTER_KEY, //Add your master key here. Keep it secret!