From 290046427242abf85f0e24ab8ec7b1e16935d7cc Mon Sep 17 00:00:00 2001 From: RaktimaNXG Date: Fri, 7 Jun 2024 14:20:36 +0530 Subject: [PATCH 1/4] fix: display the list of unsigned signers in the 'Yet to Sign' panel using the QuickSend flow. --- apps/OpenSign/src/components/pdf/RenderPdf.js | 12 +- apps/OpenSign/src/pages/PdfRequestFiles.js | 123 ++++++++++-------- 2 files changed, 79 insertions(+), 56 deletions(-) diff --git a/apps/OpenSign/src/components/pdf/RenderPdf.js b/apps/OpenSign/src/components/pdf/RenderPdf.js index 716c404e2..44f15881c 100644 --- a/apps/OpenSign/src/components/pdf/RenderPdf.js +++ b/apps/OpenSign/src/components/pdf/RenderPdf.js @@ -204,9 +204,15 @@ function RenderPdf({ }; //function for render placeholder block over pdf document const checkSignedSignes = (data) => { - const checkSign = signedSigners.filter( - (sign) => sign.objectId === data.signerObjId - ); + let checkSign = []; + //condition to handle quick send flow and using normal request sign flow + if (signedSigners[0]?.Id) { + checkSign = signedSigners.filter((sign) => sign.Id === data.Id); + } else { + checkSign = signedSigners.filter( + (sign) => sign.objectId === data.signerObjId + ); + } if (data.signerObjId === signerObjectId) { setCurrentSigner(true); } diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index f054f7530..97f2c71be 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -32,7 +32,8 @@ import { contactBook, handleDownloadPdf, handleToPrint, - handleDownloadCertificate + handleDownloadCertificate, + darkenColor } from "../constant/Utils"; import Loader from "../primitives/LoaderWithMsg"; import HandleError from "../primitives/HandleError"; @@ -74,7 +75,7 @@ function PdfRequestFiles() { const [selectWidgetId, setSelectWidgetId] = useState(""); const [otpLoader, setOtpLoader] = useState(false); const [isCelebration, setIsCelebration] = useState(false); - const [requestSignTour, setRequestSignTour] = useState(true); + const [requestSignTour, setRequestSignTour] = useState(false); const [tourStatus, setTourStatus] = useState([]); const [isLoading, setIsLoading] = useState({ isLoad: true, @@ -296,6 +297,10 @@ function PdfRequestFiles() { setExpiredDate(expireDateFormat); } // Check if the current signer is not a last signer and handle the complete message. else if (isNextUser) { + setIsCelebration(true); + setTimeout(() => { + setIsCelebration(false); + }, 5000); setIsCompleted({ isModal: true, message: @@ -330,7 +335,7 @@ function PdfRequestFiles() { } } } - const checkDocIdExist = + const audittrailData = documentData[0].AuditTrail && documentData[0].AuditTrail.length > 0 && documentData[0].AuditTrail.filter((data) => data.Activity === "Signed"); @@ -398,41 +403,49 @@ function PdfRequestFiles() { let signers = []; let unSignedSigner = []; + //`emailExist` variable to handle condition for quick send flow and show unsigned signers list + const emailExist = documentData[0].Placeholders[0]?.email; - //check document is signed or not - if (checkDocIdExist && checkDocIdExist.length > 0) { + //condition to check already signed document by someone + if (audittrailData && audittrailData.length > 0) { setIsDocId(true); - const signerRes = documentData[0].Signers; - //comparison auditTrail user details with signers user details - for (let i = 0; i < signerRes.length; i++) { - const signerId = signerRes[i].objectId; + const placeholdersOrSigners = emailExist + ? documentData[0].Placeholders + : documentData[0].Signers; + for (const item of placeholdersOrSigners) { + //if email exist then compare user signed by using email else signers objectId + const emailOrId = emailExist ? item.email : item.objectId; + //`isSignedSignature` variable to handle break loop whenever it get true let isSignedSignature = false; - for (let j = 0; j < checkDocIdExist.length; j++) { - const signedExist = - checkDocIdExist[j] && checkDocIdExist[j].UserPtr.objectId; - //checking signerObjId and auditTrail User objId - // if match then add signed data in signer array and break loop + //checking the signer who signed the document by using audit trail details. + //and save signedSigners and unsignedSigners details + for (const doc of audittrailData) { + const signedExist = emailExist + ? doc?.UserPtr.Email + : doc?.UserPtr.objectId; - if (signerId === signedExist) { - signers.push({ ...signerRes[i], ...signerRes[i] }); + if (emailOrId === signedExist) { + signers.push({ ...item }); isSignedSignature = true; break; } - // if does not match then add unsigned data in unSignedSigner array } if (!isSignedSignature) { - unSignedSigner.push({ ...signerRes[i], ...signerRes[i] }); + unSignedSigner.push({ ...item }); } } setSignedSigners(signers); setUnSignedSigners(unSignedSigner); setSignerPos(documentData[0].Placeholders); } else { + //else condition is show there are no details in audit trail then direct push all signers details + //in unsignedsigners array let unsigned = []; - for (let i = 0; i < documentData.length; i++) { - unsigned.push(documentData[i].Signers); - } + const placeholdersOrSigners = emailExist + ? documentData[0].Placeholders + : documentData[0].Signers; + unsigned.push(placeholdersOrSigners); setUnSignedSigners(unsigned[0]); setSignerPos(documentData[0].Placeholders); } @@ -447,7 +460,7 @@ function PdfRequestFiles() { declined || currDate > expireUpdateDate ) { - setRequestSignTour(false); + setRequestSignTour(true); } else { //else condition to check current user exist in contracts_Users class and check tour message status //if not then check user exist in contracts_Contactbook class and check tour message status @@ -463,33 +476,25 @@ function PdfRequestFiles() { setContractName("_Users"); currUserId = res[0].objectId; setSignerUserId(currUserId); - const tourstatus = res[0].TourStatus && res[0].TourStatus; - if (tourstatus && tourstatus.length > 0) { - setTourStatus(tourstatus); - const checkTourRequestSign = tourstatus.filter( - (data) => data.requestSign - ); - if (checkTourRequestSign && checkTourRequestSign.length > 0) { - setRequestSignTour(checkTourRequestSign[0].requestSign); - } + const tourData = res[0].TourStatus && res[0].TourStatus; + if (tourData && tourData.length > 0) { + setTourStatus(tourData); + setRequestSignTour(tourData[0]?.requestSign || false); } } else if (res?.length === 0) { const res = await contactBook(currUserId); + if (res === "Error: Something went wrong!") { setHandleError("Error: Something went wrong!"); } else if (res[0] && res.length) { setContractName("_Contactbook"); const objectId = res[0].objectId; setSignerUserId(objectId); - const tourstatus = res[0].TourStatus && res[0].TourStatus; - if (tourstatus && tourstatus.length > 0) { - setTourStatus(tourstatus); - const checkTourRequestSign = tourstatus.filter( - (data) => data.requestSign - ); - if (checkTourRequestSign && checkTourRequestSign.length > 0) { - setRequestSignTour(checkTourRequestSign[0].requestSign); - } + const tourData = res[0].TourStatus && res[0].TourStatus; + + if (tourData && tourData.length > 0) { + setTourStatus(tourData); + setRequestSignTour(tourData[0]?.requestSign || false); } } else if (res.length === 0) { setHandleError("Error: User does not exist!"); @@ -552,7 +557,6 @@ function PdfRequestFiles() { setIsLoading(loadObj); }); }; - //function for embed signature or image url in pdf async function embedWidgetsData() { try { @@ -1109,9 +1113,19 @@ function PdfRequestFiles() { }; const checkSignerBackColor = (obj) => { - const data = signerPos.filter((data) => data.signerObjId === obj.objectId); + let data = ""; + if (obj?.Id) { + data = signerPos.filter((data) => data.Id === obj.Id); + } else { + data = signerPos.filter((data) => data.signerObjId === obj.objectId); + } return data && data.length > 0 && data[0].blockColor; }; + const checkUserNameColor = (obj) => { + const getBackColor = checkSignerBackColor(obj); + const color = darkenColor(getBackColor, 0.4); + return color; + }; //function for set decline true on press decline button const declineDoc = async () => { @@ -1210,7 +1224,7 @@ function PdfRequestFiles() { }; //function to close tour and save tour status const closeRequestSignTour = async () => { - setRequestSignTour(false); + setRequestSignTour(true); if (isDontShow) { let updatedTourStatus = []; if (tourStatus.length > 0) { @@ -1332,7 +1346,6 @@ function PdfRequestFiles() { /> ); }; - return ( @@ -1401,7 +1414,7 @@ function PdfRequestFiles() { }} ref={divRef} > - {requestSignTour && requestSignTourFunction()} + {!requestSignTour && requestSignTourFunction()} <ModalUi headerColor={"#dc3545"} isOpen={isAlert.isShow} @@ -1781,7 +1794,7 @@ function PdfRequestFiles() { <div className="signerStyle" style={{ - background: "#abd1d0", + background: checkUserNameColor(obj), width: 30, height: 30, display: "flex", @@ -1800,7 +1813,7 @@ function PdfRequestFiles() { textTransform: "uppercase" }} > - {getFirstLetter(obj.Name)} + {getFirstLetter(obj?.Name || obj?.Role)} </span> </div> <div @@ -1809,9 +1822,11 @@ function PdfRequestFiles() { flexDirection: "column" }} > - <span className="userName">{obj.Name}</span> + <span className="userName"> + {obj?.Name || obj?.Role} + </span> <span className="useEmail"> - {obj.Email} + {obj?.Email || obj?.email} </span> </div> </div> @@ -1850,7 +1865,7 @@ function PdfRequestFiles() { <div className="signerStyle" style={{ - background: "#abd1d0", + background: checkUserNameColor(obj), width: 30, height: 30, display: "flex", @@ -1869,7 +1884,7 @@ function PdfRequestFiles() { textTransform: "uppercase" }} > - {getFirstLetter(obj.Name)} + {getFirstLetter(obj?.Name || obj?.email)} </span> </div> <div @@ -1878,9 +1893,11 @@ function PdfRequestFiles() { flexDirection: "column" }} > - <span className="userName">{obj.Name}</span> + <span className="userName"> + {obj?.Name || obj?.Role} + </span> <span className="useEmail"> - {obj.Email} + {obj?.Email || obj?.email} </span> </div> <hr /> From 5c3f967128f7c91f414273cc7e413f738fb2f3d2 Mon Sep 17 00:00:00 2001 From: RaktimaNXG <raktima.c@nxglabs.com> Date: Fri, 7 Jun 2024 19:07:56 +0530 Subject: [PATCH 2/4] fix: add validation of signature widgetat in quick send flow, update SentToOthers field when document is in inProgress , resolve resend nonexist email issue --- apps/OpenSign/src/components/BulkSendUi.js | 137 ++++++++++-------- apps/OpenSign/src/components/pdf/RenderPdf.js | 10 +- apps/OpenSign/src/constant/Utils.js | 1 + apps/OpenSign/src/pages/PdfRequestFiles.js | 44 +++--- apps/OpenSign/src/pages/PlaceHolderSign.js | 4 +- .../src/primitives/GetReportDisplay.js | 121 ++++++++++------ .../v1/routes/CreateDocumentWithTemplate.js | 1 + .../v1/routes/createDocumentwithCoordinate.js | 1 + .../cloud/parsefunction/createBatchDocs.js | 2 + 9 files changed, 194 insertions(+), 127 deletions(-) diff --git a/apps/OpenSign/src/components/BulkSendUi.js b/apps/OpenSign/src/components/BulkSendUi.js index c5445ad66..98ba5c0b8 100644 --- a/apps/OpenSign/src/components/BulkSendUi.js +++ b/apps/OpenSign/src/components/BulkSendUi.js @@ -9,7 +9,22 @@ const BulkSendUi = (props) => { const [scrollOnNextUpdate, setScrollOnNextUpdate] = useState(false); const [isSubmit, setIsSubmit] = useState(false); const [allowedForm, setAllowedForm] = useState(0); + const [isSignatureExist, setIsSignatureExist] = useState(); const allowedSigners = 50; + useEffect(() => { + signatureExist(); + }, []); + + //function to check atleast one signature field exist + const signatureExist = () => { + const getPlaceholder = props.item?.Placeholders; + const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) => + placeholderObj?.placeHolder?.some((holder) => + holder?.pos?.some((posItem) => posItem?.type === "signature") + ) + ); + setIsSignatureExist(checkIsSignatureExistt); + }; useEffect(() => { if (scrollOnNextUpdate && formRef.current) { formRef.current.scrollIntoView({ @@ -165,65 +180,73 @@ const BulkSendUi = (props) => { </div> )} {props.Placeholders?.length > 0 ? ( - <> - {props.Placeholders?.some((x) => !x.signerObjId) ? ( - <form onSubmit={handleSubmit}> - <div className=" min-h-max max-h-[250px] overflow-y-auto"> - {forms?.map((form, index) => ( - <div - key={form.Id} - className="p-3 rounded-xl border-[1px] border-gray-400 m-4 bg-white text-black grid grid-cols-1 md:grid-cols-2 gap-2 relative" + isSignatureExist ? ( + <> + {props.Placeholders?.some((x) => !x.signerObjId) ? ( + <form onSubmit={handleSubmit}> + <div className=" min-h-max max-h-[250px] overflow-y-auto"> + {forms?.map((form, index) => ( + <div + key={form.Id} + className="p-3 rounded-xl border-[1px] border-gray-400 m-4 bg-white text-black grid grid-cols-1 md:grid-cols-2 gap-2 relative" + > + {form?.fields?.map((field, fieldIndex) => ( + <div className="flex flex-col " key={field.fieldId}> + <label>{field.label}</label> + <SuggestionInput + required + type="email" + value={field.value} + index={fieldIndex} + onChange={(signer) => + handleInputChange(index, signer, fieldIndex) + } + /> + </div> + ))} + {forms?.length > 1 && ( + <button + onClick={() => handleRemoveForm(index)} + className="absolute right-3 top-1 border border-gray-300 rounded-lg px-2 py-1" + > + <i className="fa-solid fa-trash"></i> + </button> + )} + <div ref={formRef}></div> + </div> + ))} + </div> + <div className="flex flex-col mx-4 mb-4 gap-3"> + <button + onClick={handleAddForm} + className="bg-[#32a3ac] p-2 text-white w-full rounded-full focus:outline-none" > - {form?.fields?.map((field, fieldIndex) => ( - <div className="flex flex-col " key={field.fieldId}> - <label>{field.label}</label> - <SuggestionInput - required - type="email" - value={field.value} - index={fieldIndex} - onChange={(signer) => - handleInputChange(index, signer, fieldIndex) - } - /> - </div> - ))} - {forms?.length > 1 && ( - <button - onClick={() => handleRemoveForm(index)} - className="absolute right-3 top-1 border border-gray-300 rounded-lg px-2 py-1" - > - <i className="fa-solid fa-trash"></i> - </button> - )} - <div ref={formRef}></div> - </div> - ))} + <i className="fa-solid fa-plus"></i> <span>Add new</span> + </button> + <button + type="submit" + className="bg-[#32a3ac] p-2 text-white w-full rounded-full focus:outline-none" + > + <i className="fa-solid fa-paper-plane"></i>{" "} + <span>Send</span> + </button> + </div> + </form> + ) : ( + <div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center"> + All roles in this document are currently linked to contacts. To + 'quick send' copies of this template to multiple + signers, please ensure that at least one role is not linked to + any contact. </div> - <div className="flex flex-col mx-4 mb-4 gap-3"> - <button - onClick={handleAddForm} - className="bg-[#32a3ac] p-2 text-white w-full rounded-full focus:outline-none" - > - <i className="fa-solid fa-plus"></i> <span>Add new</span> - </button> - <button - type="submit" - className="bg-[#32a3ac] p-2 text-white w-full rounded-full focus:outline-none" - > - <i className="fa-solid fa-paper-plane"></i> <span>Send</span> - </button> - </div> - </form> - ) : ( - <div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center"> - All roles in this document are currently linked to contacts. To - 'quick send' copies of this template to multiple - signers, please ensure that at least one role is not linked to any - contact. - </div> - )} - </> + )} + </> + ) : ( + <div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center"> + Please ensure there's at least one signature widget added for + all recipients. + </div> + ) ) : ( <div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center"> Please add at least one role to this template in order to 'quick diff --git a/apps/OpenSign/src/components/pdf/RenderPdf.js b/apps/OpenSign/src/components/pdf/RenderPdf.js index 44f15881c..2bac6b85e 100644 --- a/apps/OpenSign/src/components/pdf/RenderPdf.js +++ b/apps/OpenSign/src/components/pdf/RenderPdf.js @@ -206,13 +206,9 @@ function RenderPdf({ const checkSignedSignes = (data) => { let checkSign = []; //condition to handle quick send flow and using normal request sign flow - if (signedSigners[0]?.Id) { - checkSign = signedSigners.filter((sign) => sign.Id === data.Id); - } else { - checkSign = signedSigners.filter( - (sign) => sign.objectId === data.signerObjId - ); - } + checkSign = signedSigners.filter( + (sign) => sign?.Id === data?.Id || sign?.objectId === data?.signerObjId + ); if (data.signerObjId === signerObjectId) { setCurrentSigner(true); } diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js index 3a24c4398..25a91a20c 100644 --- a/apps/OpenSign/src/constant/Utils.js +++ b/apps/OpenSign/src/constant/Utils.js @@ -669,6 +669,7 @@ export const createDocument = async (template, placeholders, signerData) => { Name: Doc.Name, URL: Doc.URL, SignedUrl: Doc.SignedUrl, + SentToOthers: Doc.SentToOthers, Description: Doc.Description, Note: Doc.Note, Placeholders: placeholdersArr, diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 97f2c71be..426a3aadf 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -403,25 +403,34 @@ function PdfRequestFiles() { let signers = []; let unSignedSigner = []; - //`emailExist` variable to handle condition for quick send flow and show unsigned signers list - const emailExist = documentData[0].Placeholders[0]?.email; + const placeholdersOrSigners = []; + for (const placeholder of documentData[0].Placeholders) { + //`emailExist` variable to handle condition for quick send flow and show unsigned signers list + const emailExist = placeholder?.email; + if (emailExist) { + placeholdersOrSigners.push(placeholder); + } else { + const getSignerData = documentData[0].Signers.filter( + (data) => data.objectId === placeholder?.signerObjId + ); + placeholdersOrSigners.push(getSignerData[0]); + } + } //condition to check already signed document by someone if (audittrailData && audittrailData.length > 0) { setIsDocId(true); - const placeholdersOrSigners = emailExist - ? documentData[0].Placeholders - : documentData[0].Signers; for (const item of placeholdersOrSigners) { + const checkEmail = item?.email; //if email exist then compare user signed by using email else signers objectId - const emailOrId = emailExist ? item.email : item.objectId; + const emailOrId = checkEmail ? item.email : item.objectId; //`isSignedSignature` variable to handle break loop whenever it get true let isSignedSignature = false; //checking the signer who signed the document by using audit trail details. //and save signedSigners and unsignedSigners details for (const doc of audittrailData) { - const signedExist = emailExist + const signedExist = checkEmail ? doc?.UserPtr.Email : doc?.UserPtr.objectId; @@ -441,12 +450,7 @@ function PdfRequestFiles() { } else { //else condition is show there are no details in audit trail then direct push all signers details //in unsignedsigners array - let unsigned = []; - const placeholdersOrSigners = emailExist - ? documentData[0].Placeholders - : documentData[0].Signers; - unsigned.push(placeholdersOrSigners); - setUnSignedSigners(unsigned[0]); + setUnSignedSigners(placeholdersOrSigners); setSignerPos(documentData[0].Placeholders); } setPdfDetails(documentData); @@ -1000,8 +1004,10 @@ function PdfRequestFiles() { } const getFirstLetter = (name) => { - const firstLetter = name.charAt(0); - return firstLetter; + if (name) { + const firstLetter = name.charAt(0); + return firstLetter; + } }; //function for image upload or update const onImageChange = (event) => { @@ -1123,8 +1129,12 @@ function PdfRequestFiles() { }; const checkUserNameColor = (obj) => { const getBackColor = checkSignerBackColor(obj); - const color = darkenColor(getBackColor, 0.4); - return color; + if (getBackColor) { + const color = darkenColor(getBackColor, 0.4); + return color; + } else { + return "#abd1d0"; + } }; //function for set decline true on press decline button diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js index 6e9fa46a9..3f25695f5 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.js +++ b/apps/OpenSign/src/pages/PlaceHolderSign.js @@ -936,6 +936,7 @@ function PlaceHolderSign() { Placeholders: filterPrefill, SignedUrl: pdfUrl, Signers: signers, + SentToOthers: true, ExpiryDate: { iso: updateExpiryDate, __type: "Date" @@ -945,7 +946,8 @@ function PlaceHolderSign() { data = { Placeholders: filterPrefill, SignedUrl: pdfUrl, - Signers: signers + Signers: signers, + SentToOthers: true }; } await axios diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 0a04073bf..45011e213 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -143,6 +143,7 @@ const ReportTable = (props) => { Name: Doc.Name, URL: Doc.URL, SignedUrl: Doc.SignedUrl, + SentToOthers: Doc?.SentToOthers || false, Description: Doc.Description, Note: Doc.Note, Placeholders: placeholdersArr, @@ -338,7 +339,7 @@ const ReportTable = (props) => { const sendMail = item?.SendMail || false; const getUrl = (x) => { //encode this url value `${item.objectId}/${x.Email}/${x.objectId}` to base64 using `btoa` function - if (x.objectId) { + if (x?.signerObjId) { const encodeBase64 = btoa( `${item.objectId}/${x.signerPtr.Email}/${x.signerPtr.objectId}/${sendMail}` ); @@ -495,9 +496,9 @@ const ReportTable = (props) => { // `handleSubjectChange` is used to add or change subject of resend mail const handleSubjectChange = (subject, doc) => { - const encodeBase64 = btoa( - `${doc.objectId}/${userDetails.Email}/${userDetails.objectId}` - ); + const encodeBase64 = userDetails?.objectId + ? btoa(`${doc.objectId}/${userDetails.Email}/${userDetails.objectId}`) + : btoa(`${doc.objectId}/${userDetails.Email}`); const expireDate = doc.ExpiryDate.iso; const newDate = new Date(expireDate); const localExpireDate = newDate.toLocaleDateString("en-US", { @@ -511,8 +512,8 @@ const ReportTable = (props) => { sender_name: doc.ExtUserPtr.Name, sender_mail: doc.ExtUserPtr.Email, sender_phone: doc.ExtUserPtr?.Phone || "", - receiver_name: userDetails.Name, - receiver_email: userDetails.Email, + receiver_name: userDetails?.Name, + receiver_email: userDetails?.Email, receiver_phone: userDetails?.Phone || "", expiry_date: localExpireDate, company_name: doc.ExtUserPtr.Company, @@ -524,9 +525,9 @@ const ReportTable = (props) => { }; // `handlebodyChange` is used to add or change body of resend mail const handlebodyChange = (body, doc) => { - const encodeBase64 = btoa( - `${doc.objectId}/${userDetails.Email}/${userDetails.objectId}` - ); + const encodeBase64 = userDetails?.objectId + ? btoa(`${doc.objectId}/${userDetails.Email}/${userDetails.objectId}`) + : btoa(`${doc.objectId}/${userDetails.Email}`); const expireDate = doc.ExpiryDate.iso; const newDate = new Date(expireDate); const localExpireDate = newDate.toLocaleDateString("en-US", { @@ -540,8 +541,8 @@ const ReportTable = (props) => { sender_name: doc.ExtUserPtr.Name, sender_mail: doc.ExtUserPtr.Email, sender_phone: doc.ExtUserPtr?.Phone || "", - receiver_name: userDetails.Name, - receiver_email: userDetails.Email, + receiver_name: userDetails?.Name || "", + receiver_email: userDetails?.Email || "", receiver_phone: userDetails?.Phone || "", expiry_date: localExpireDate, company_name: doc.ExtUserPtr.Company, @@ -556,8 +557,18 @@ const ReportTable = (props) => { // `handleNextBtn` is used to open edit mail template screen in resend mail modal // as well as replace variable with original one const handleNextBtn = (user, doc) => { - setUserDetails(user); - const encodeBase64 = btoa(`${doc.objectId}/${user.Email}/${user.objectId}`); + const userdata = { + Name: user?.signerPtr?.Name, + Email: user.email ? user?.email : user.signerPtr?.Email, + Phone: user?.signerPtr?.Phone, + objectId: user?.signerPtr?.objectId + }; + setUserDetails(userdata); + const encodeBase64 = user.email + ? btoa(`${doc.objectId}/${user.email}`) + : btoa( + `${doc.objectId}/${user.signerPtr.Email}/${user.signerPtr.objectId}` + ); const expireDate = doc.ExpiryDate.iso; const newDate = new Date(expireDate); const localExpireDate = newDate.toLocaleDateString("en-US", { @@ -571,9 +582,9 @@ const ReportTable = (props) => { sender_name: doc.ExtUserPtr.Name, sender_mail: doc.ExtUserPtr.Email, sender_phone: doc.ExtUserPtr?.Phone || "", - receiver_name: user.Name, - receiver_email: user.Email, - receiver_phone: user?.Phone || "", + receiver_name: user?.signerPtr?.Name || "", + receiver_email: user?.email ? user?.email : user?.signerPtr?.Email, + receiver_phone: user?.signerPtr?.Phone || "", expiry_date: localExpireDate, company_name: doc?.ExtUserPtr?.Company || "", signing_url: `<a href=${signPdf}>Sign here</a>` @@ -584,14 +595,14 @@ const ReportTable = (props) => { `{{sender_name}} has requested you to sign "{{document_title}}"`; const body = doc?.RequestBody || - `<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign <b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br></body> </html>`; + `<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign <b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br></body> </html>`; const res = replaceMailVaribles(subject, body, variables); setMail((prev) => ({ ...prev, subject: res.subject, body: res.body })); - setIsNextStep({ [user.objectId]: true }); + setIsNextStep({ [user.Id]: true }); }; const handleResendMail = async (e, doc, user) => { e.preventDefault(); - setActLoader({ [user.objectId]: true }); + setActLoader({ [user?.Id]: true }); const url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`; const headers = { "Content-Type": "application/json", @@ -601,7 +612,7 @@ const ReportTable = (props) => { let params = { mailProvider: doc?.ExtUserPtr?.active_mail_adapter, extUserId: doc?.ExtUserPtr?.objectId, - recipient: userDetails.Email, + recipient: userDetails?.Email, subject: mail.subject, from: doc?.ExtUserPtr?.Email, html: mail.body @@ -633,9 +644,9 @@ const ReportTable = (props) => { } }; const fetchUserStatus = (user, doc) => { - const audit = doc?.AuditTrail?.find( - (x) => x.UserPtr.objectId === user.objectId - ); + const email = user.email ? user.email : user.signerPtr.Email; + const audit = doc?.AuditTrail?.find((x) => x.UserPtr.Email === email); + return ( <div className="flex flex-row gap-2 justify-center items-center"> <div className="flex justify-center items-center bg-gray-200 text-xs text-black shadow rounded-full w-[65px] h-[23px] cursor-default"> @@ -789,23 +800,38 @@ const ReportTable = (props) => { const getPlaceholder = item?.Placeholders; //condiiton to check role is exist or not if (getPlaceholder && getPlaceholder.length > 0) { - let extendUser = JSON.parse(localStorage.getItem("Extand_Class")); - const userName = extendUser[0]?.UserName; - setIsPublicUserName(extendUser[0]?.UserName); - //condition to check user have public url or not - if (userName) { - setIsPublic((prevStates) => ({ - ...prevStates, - [item.objectId]: e.target.checked - })); - const getPlaceholder = item?.Placeholders; - if (getPlaceholder.length === 1) { - setSelectedPublicRole(getPlaceholder[0]?.Role); - } + const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) => + placeholderObj?.placeHolder?.some((holder) => + holder?.pos?.some((posItem) => posItem?.type === "signature") + ) + ); + if (checkIsSignatureExistt) { + let extendUser = JSON.parse(localStorage.getItem("Extand_Class")); + const userName = extendUser[0]?.UserName; + setIsPublicUserName(extendUser[0]?.UserName); + //condition to check user have public url or not + if (userName) { + setIsPublic((prevStates) => ({ + ...prevStates, + [item.objectId]: e.target.checked + })); + const getPlaceholder = item?.Placeholders; + if (getPlaceholder.length === 1) { + setSelectedPublicRole(getPlaceholder[0]?.Role); + } - setIsMakePublic({ [item.objectId]: true }); + setIsMakePublic({ [item.objectId]: true }); + } else { + setIsPublicProfile({ [item.objectId]: true }); + } } else { - setIsPublicProfile({ [item.objectId]: true }); + setIsAlert(true); + setAlertMsg({ + type: "danger", + message: + " Please ensure there's at least one signature widget added for all recipients." + }); + setTimeout(() => setIsAlert(false), 5000); } } else { setIsAlert(true); @@ -813,7 +839,7 @@ const ReportTable = (props) => { type: "danger", message: "Please assign at least one role to make this template public." }); - setTimeout(() => setIsAlert(false), 3000); + setTimeout(() => setIsAlert(false), 5000); } }; @@ -1240,11 +1266,11 @@ const ReportTable = (props) => { }} > <div className=" overflow-y-auto max-h-[340px] md:max-h-[400px]"> - {item?.Signers.map((user) => ( - <React.Fragment key={user.objectId}> - {isNextStep[user.objectId] && ( + {item?.Placeholders?.map((user) => ( + <React.Fragment key={user.Id}> + {isNextStep[user.Id] && ( <div className="relative "> - {actLoader[user.objectId] && ( + {actLoader[user.Id] && ( <div className="absolute w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-30"> <div style={{ @@ -1264,7 +1290,7 @@ const ReportTable = (props) => { > <div className="absolute right-5 text-xs z-40"> <Tooltip - id={`${user.objectId}_help`} + id={`${user.Id}_help`} message={ "You can use following variables which will get replaced with their actual values:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}." } @@ -1322,7 +1348,12 @@ const ReportTable = (props) => { {Object?.keys(isNextStep) <= 0 && ( <div className="flex justify-between items-center gap-2 my-2 px-3"> <div className="text-black"> - {user.Name} {`<${user.Email}>`} + {user?.signerPtr?.Name || "-"}{" "} + {`<${ + user?.email + ? user.email + : user.signerPtr.Email + }>`} </div> <>{fetchUserStatus(user, item)}</> </div> diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js index aa3d327ea..758ff7971 100644 --- a/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js @@ -179,6 +179,7 @@ export default async function createDocumentWithTemplate(request, response) { } object.set('URL', template.URL); object.set('SignedUrl', template.URL); + object.set('SentToOthers', true); if (TimeToCompleteDays) { object.set('TimeToCompleteDays', TimeToCompleteDays); } diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js index 32df43ad0..f00161a2b 100644 --- a/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js @@ -141,6 +141,7 @@ export default async function createDocumentwithCoordinate(request, response) { } object.set('URL', fileUrl); object.set('SignedUrl', fileUrl); + object.set('SentToOthers', true); object.set('CreatedBy', userPtr); object.set('ExtUserPtr', extUserPtr); if (TimeToCompleteDays) { diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index 2f4aed714..602ddb9db 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -140,12 +140,14 @@ export default async function createBatchDocs(request) { : { ...y, signerPtr: {}, signerObjId: '' } ), SignedUrl: x.URL || x.SignedUrl, + SentToOthers: true, Signers: allSigner?.map(y => ({ __type: 'Pointer', className: 'contracts_Contactbook', objectId: y.objectId, })), ACL: Acl, + SentToOthers: true, RemindOnceInEvery: x.RemindOnceInEvery || 5, AutomaticReminders: x.AutomaticReminders || false, TimeToCompleteDays: x.TimeToCompleteDays || 15, From 74f66122712dff9e1a0e90e9feadc7c8146df155 Mon Sep 17 00:00:00 2001 From: RaktimaNXG <raktima.c@nxglabs.com> Date: Fri, 7 Jun 2024 19:33:28 +0530 Subject: [PATCH 3/4] refactor code --- apps/OpenSign/src/components/BulkSendUi.js | 1 + apps/OpenSign/src/pages/UserProfile.js | 94 +++--- .../src/primitives/GetReportDisplay.js | 293 +++++++++--------- 3 files changed, 198 insertions(+), 190 deletions(-) diff --git a/apps/OpenSign/src/components/BulkSendUi.js b/apps/OpenSign/src/components/BulkSendUi.js index 98ba5c0b8..6e4aa5e76 100644 --- a/apps/OpenSign/src/components/BulkSendUi.js +++ b/apps/OpenSign/src/components/BulkSendUi.js @@ -13,6 +13,7 @@ const BulkSendUi = (props) => { const allowedSigners = 50; useEffect(() => { signatureExist(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); //function to check atleast one signature field exist diff --git a/apps/OpenSign/src/pages/UserProfile.js b/apps/OpenSign/src/pages/UserProfile.js index cbc0d2429..a7599666e 100644 --- a/apps/OpenSign/src/pages/UserProfile.js +++ b/apps/OpenSign/src/pages/UserProfile.js @@ -1,4 +1,8 @@ -import React, { useState, useEffect, useRef } from "react"; +import React, { + useState, + useEffect + // useRef +} from "react"; import { Navigate, useNavigate } from "react-router-dom"; import Parse from "parse"; import { SaveFileSize } from "../constant/saveFileSize"; @@ -27,10 +31,10 @@ function UserProfile() { const [percentage, setpercentage] = useState(0); const [isDisableDocId, setIsDisableDocId] = useState(false); const [isSubscribe, setIsSubscribe] = useState(false); - const [publicUserName, setPublicUserName] = useState( - extendUser && extendUser?.[0]?.UserName - ); - const previousPublicUserName = useRef(publicUserName); + // const [publicUserName, setPublicUserName] = useState( + // extendUser && extendUser?.[0]?.UserName + // ); + // const previousPublicUserName = useRef(publicUserName); const [company, setCompany] = useState( extendUser && extendUser?.[0]?.Company ); @@ -41,7 +45,7 @@ function UserProfile() { const [otp, setOtp] = useState(""); const [otpLoader, setOtpLoader] = useState(false); const [isEmailVerified, setIsEmailVerified] = useState(false); - const [userNameError, setUserNameError] = useState(""); + // const [userNameError, setUserNameError] = useState(""); useEffect(() => { getUserDetail(); }, []); @@ -80,31 +84,31 @@ function UserProfile() { } }; //function to check public username already exist - const handleCheckPublicUserName = async () => { - try { - const res = await Parse.Cloud.run("getpublicusername", { - username: publicUserName - }); - if (res) { - setIsLoader(false); - setUserNameError("user name already exist"); - setTimeout(() => { - setUserNameError(""); - }, 3000); - return res; - } - } catch (e) { - console.log("error in getpublicusername cloud function"); - } - }; + // const handleCheckPublicUserName = async () => { + // try { + // const res = await Parse.Cloud.run("getpublicusername", { + // username: publicUserName + // }); + // if (res) { + // setIsLoader(false); + // setUserNameError("user name already exist"); + // setTimeout(() => { + // setUserNameError(""); + // }, 3000); + // return res; + // } + // } catch (e) { + // console.log("error in getpublicusername cloud function"); + // } + // }; const handleSubmit = async (e) => { e.preventDefault(); let phn = Phone, - res; + res = ""; //condition to call cloud function when user change publicUserName - if (previousPublicUserName.current !== publicUserName) { - res = await handleCheckPublicUserName(); - } + // if (previousPublicUserName.current !== publicUserName) { + // res = await handleCheckPublicUserName(); + // } if (!res) { setIsLoader(true); try { @@ -158,8 +162,8 @@ function UserProfile() { Name: obj.Name, HeaderDocId: isDisableDocId, JobTitle: jobTitle, - Company: company, - UserName: publicUserName || "" + Company: company + // UserName: publicUserName || "" }; await axios.put( @@ -273,23 +277,23 @@ function UserProfile() { alert("OTP sent on you email"); }; //function to handle onchange username and restrict 6-characters username for free users - const handleOnchangeUserName = (e) => { - const value = e.target.value; - if (value.length > 6 && !isSubscribe) { - setUserNameError("Please upgrade to allow more than 6 characters."); - setTimeout(() => { - setUserNameError(""); - }, 2000); - } else { - setPublicUserName(e.target.value); - } - }; + // const handleOnchangeUserName = (e) => { + // const value = e.target.value; + // if (value.length > 6 && !isSubscribe) { + // setUserNameError("Please upgrade to allow more than 6 characters."); + // setTimeout(() => { + // setUserNameError(""); + // }, 2000); + // } else { + // setPublicUserName(e.target.value); + // } + // }; const handleCancel = () => { setEditMode(false); SetName(localStorage.getItem("username")); SetPhone(UserProfile && UserProfile.phone); setImage(localStorage.getItem("profileImg")); - setPublicUserName(extendUser && extendUser?.[0]?.UserName); + // setPublicUserName(extendUser && extendUser?.[0]?.UserName); setCompany(extendUser && extendUser?.[0]?.Company); setJobTitle(extendUser?.[0]?.JobTitle); }; @@ -315,13 +319,13 @@ function UserProfile() { </div> ) : ( <div className="flex justify-center items-center w-full relative"> - {userNameError && ( + {/* {userNameError && ( <div className={`z-[1000] fixed top-[50%] transform border-[1px] text-sm border-[#f0a8a8] bg-[#f4bebe] text-[#c42121] rounded py-[.75rem] px-[1.25rem]`} > {userNameError} </div> - )} + )} */} <div className="bg-white flex flex-col justify-center shadow rounded w-[450px]"> <div className="flex flex-col justify-center items-center my-4"> <div className="w-[200px] h-[200px] overflow-hidden rounded-full"> @@ -449,7 +453,7 @@ function UserProfile() { )} </span> </li> - {isEnableSubscription && ( + {/* {isEnableSubscription && ( <li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all"> <span className="font-semibold"> Public profile :{" "} @@ -479,7 +483,7 @@ function UserProfile() { )} </div> </li> - )} + )} */} <li className="border-y-[1px] border-gray-300 break-all"> <div className="flex justify-between items-center py-2"> <span diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 45011e213..8d599aaac 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -6,8 +6,8 @@ import ModalUi from "./ModalUi"; import AddSigner from "../components/AddSigner"; import { modalSubmitBtnColor, - modalCancelBtnColor, - isEnableSubscription + modalCancelBtnColor + // isEnableSubscription } from "../constant/const"; import Alert from "./Alert"; import Tooltip from "./Tooltip"; @@ -15,8 +15,11 @@ import { RWebShare } from "react-web-share"; import Tour from "reactour"; import Parse from "parse"; import { saveAs } from "file-saver"; -import { copytoData, replaceMailVaribles } from "../constant/Utils"; -import Confetti from "react-confetti"; +import { + // copytoData, + replaceMailVaribles +} from "../constant/Utils"; +// import Confetti from "react-confetti"; import EditorToolbar, { module1, formats @@ -41,7 +44,7 @@ const ReportTable = (props) => { const [isTour, setIsTour] = useState(false); const [tourStatusArr, setTourStatusArr] = useState([]); const [isResendMail, setIsResendMail] = useState({}); - const [isMakePublic, setIsMakePublic] = useState({}); + // const [isMakePublic, setIsMakePublic] = useState({}); const [mail, setMail] = useState({ subject: "", body: "" }); const [userDetails, setUserDetails] = useState({}); const [isNextStep, setIsNextStep] = useState({}); @@ -49,12 +52,12 @@ const ReportTable = (props) => { const [templateDeatils, setTemplateDetails] = useState({}); const [placeholders, setPlaceholders] = useState([]); const [isLoader, setIsLoader] = useState({}); - const [selectedPublicRole, setSelectedPublicRole] = useState(""); - const [isCelebration, setIsCelebration] = useState(false); + // const [selectedPublicRole, setSelectedPublicRole] = useState(""); + // const [isCelebration, setIsCelebration] = useState(false); const [currentLists, setCurrentLists] = useState([]); - const [isPublic, setIsPublic] = useState({}); - const [isPublicProfile, setIsPublicProfile] = useState({}); - const [publicUserName, setIsPublicUserName] = useState(""); + // const [isPublic, setIsPublic] = useState({}); + // const [isPublicProfile, setIsPublicProfile] = useState({}); + // const [publicUserName, setIsPublicUserName] = useState(""); const [isViewShare, setIsViewShare] = useState({}); const startIndex = (currentPage - 1) * props.docPerPage; const { isMoreDocs, setIsNextRecord } = props; @@ -251,12 +254,12 @@ const ReportTable = (props) => { // `currentLists` is total record render on current page const currentList = props.List?.slice(indexOfFirstDoc, indexOfLastDoc); //check public template and save in a object to show public and private template - setIsPublic( - currentList.reduce((acc, item) => { - acc[item.objectId] = item?.IsPublic || false; - return acc; - }, {}) - ); + // setIsPublic( + // currentList.reduce((acc, item) => { + // acc[item.objectId] = item?.IsPublic || false; + // return acc; + // }, {}) + // ); setCurrentLists(currentList); // eslint-disable-next-line react-hooks/exhaustive-deps }, [indexOfLastDoc, indexOfFirstDoc]); @@ -321,16 +324,16 @@ const ReportTable = (props) => { setActLoader({}); } }; - const handleClose = (item) => { + const handleClose = () => { setIsRevoke({}); setIsDeleteModal({}); - setIsMakePublic({}); - setSelectedPublicRole(""); - setIsPublic((prevStates) => ({ - ...prevStates, - [item.objectId]: !prevStates[item.objectId] - })); - setIsPublicProfile({}); + // setIsMakePublic({}); + // setSelectedPublicRole(""); + // setIsPublic((prevStates) => ({ + // ...prevStates, + // [item.objectId]: !prevStates[item.objectId] + // })); + // setIsPublicProfile({}); }; const handleShare = (item) => { @@ -730,130 +733,130 @@ const ReportTable = (props) => { }; //function to make template public and set public role - const handlePublicTemplate = async (item) => { - if (selectedPublicRole || !isPublic[item.objectId]) { - setActLoader({ [item.objectId]: true }); - setIsMakePublic(false); - try { - const res = await Parse.Cloud.run("createpublictemplate", { - templateid: item.objectId, - ispublic: isPublic[item.objectId], - publicrole: [selectedPublicRole] - }); + // const handlePublicTemplate = async (item) => { + // if (selectedPublicRole || !isPublic[item.objectId]) { + // setActLoader({ [item.objectId]: true }); + // setIsMakePublic(false); + // try { + // const res = await Parse.Cloud.run("createpublictemplate", { + // templateid: item.objectId, + // ispublic: isPublic[item.objectId], + // publicrole: [selectedPublicRole] + // }); - if (res.status === "success") { - setIsAlert(true); - setTimeout(() => setIsAlert(false), 1500); - if (isPublic[item.objectId]) { - setAlertMsg({ - type: "success", - message: "You have successfully made the template public." - }); - setIsCelebration(true); - setTimeout(() => { - setIsCelebration(false); - }, 5000); - setIsPublicProfile({ [item.objectId]: isPublic[item.objectId] }); - } else { - setAlertMsg({ - type: "success", - message: "You have successfully made the template private." - }); - setSelectedPublicRole(""); - } - const updateList = props.List.map((x) => - x.objectId === item.objectId - ? { ...x, IsPublic: isPublic[item.objectId] } - : x - ); - props.setList(updateList); - setActLoader({}); - } - } catch (e) { - console.log("error in createpublictemplate", e); - setIsAlert(true); - setAlertMsg({ - type: "danger", - message: "Something went wrong, Please try again later!" - }); - setTimeout(() => setIsAlert(false), 1500); - setIsPublic((prevStates) => ({ - ...prevStates, - [item.objectId]: !prevStates[item.objectId] - })); - } - } else { - setIsAlert(true); - setAlertMsg({ - type: "danger", - message: "You need to select a role for the public signers." - }); - setTimeout(() => setIsAlert(false), 1500); - } - }; + // if (res.status === "success") { + // setIsAlert(true); + // setTimeout(() => setIsAlert(false), 1500); + // if (isPublic[item.objectId]) { + // setAlertMsg({ + // type: "success", + // message: "You have successfully made the template public." + // }); + // setIsCelebration(true); + // setTimeout(() => { + // setIsCelebration(false); + // }, 5000); + // setIsPublicProfile({ [item.objectId]: isPublic[item.objectId] }); + // } else { + // setAlertMsg({ + // type: "success", + // message: "You have successfully made the template private." + // }); + // setSelectedPublicRole(""); + // } + // const updateList = props.List.map((x) => + // x.objectId === item.objectId + // ? { ...x, IsPublic: isPublic[item.objectId] } + // : x + // ); + // props.setList(updateList); + // setActLoader({}); + // } + // } catch (e) { + // console.log("error in createpublictemplate", e); + // setIsAlert(true); + // setAlertMsg({ + // type: "danger", + // message: "Something went wrong, Please try again later!" + // }); + // setTimeout(() => setIsAlert(false), 1500); + // setIsPublic((prevStates) => ({ + // ...prevStates, + // [item.objectId]: !prevStates[item.objectId] + // })); + // } + // } else { + // setIsAlert(true); + // setAlertMsg({ + // type: "danger", + // message: "You need to select a role for the public signers." + // }); + // setTimeout(() => setIsAlert(false), 1500); + // } + // }; const handleViewSigners = (item) => { setIsViewShare({ [item.objectId]: true }); }; //function to handle change template status is public or private - const handlePublicChange = async (e, item) => { - const getPlaceholder = item?.Placeholders; - //condiiton to check role is exist or not - if (getPlaceholder && getPlaceholder.length > 0) { - const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) => - placeholderObj?.placeHolder?.some((holder) => - holder?.pos?.some((posItem) => posItem?.type === "signature") - ) - ); - if (checkIsSignatureExistt) { - let extendUser = JSON.parse(localStorage.getItem("Extand_Class")); - const userName = extendUser[0]?.UserName; - setIsPublicUserName(extendUser[0]?.UserName); - //condition to check user have public url or not - if (userName) { - setIsPublic((prevStates) => ({ - ...prevStates, - [item.objectId]: e.target.checked - })); - const getPlaceholder = item?.Placeholders; - if (getPlaceholder.length === 1) { - setSelectedPublicRole(getPlaceholder[0]?.Role); - } + // const handlePublicChange = async (e, item) => { + // const getPlaceholder = item?.Placeholders; + // //condiiton to check role is exist or not + // if (getPlaceholder && getPlaceholder.length > 0) { + // const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) => + // placeholderObj?.placeHolder?.some((holder) => + // holder?.pos?.some((posItem) => posItem?.type === "signature") + // ) + // ); + // if (checkIsSignatureExistt) { + // let extendUser = JSON.parse(localStorage.getItem("Extand_Class")); + // const userName = extendUser[0]?.UserName; + // setIsPublicUserName(extendUser[0]?.UserName); + // //condition to check user have public url or not + // if (userName) { + // setIsPublic((prevStates) => ({ + // ...prevStates, + // [item.objectId]: e.target.checked + // })); + // const getPlaceholder = item?.Placeholders; + // if (getPlaceholder.length === 1) { + // setSelectedPublicRole(getPlaceholder[0]?.Role); + // } - setIsMakePublic({ [item.objectId]: true }); - } else { - setIsPublicProfile({ [item.objectId]: true }); - } - } else { - setIsAlert(true); - setAlertMsg({ - type: "danger", - message: - " Please ensure there's at least one signature widget added for all recipients." - }); - setTimeout(() => setIsAlert(false), 5000); - } - } else { - setIsAlert(true); - setAlertMsg({ - type: "danger", - message: "Please assign at least one role to make this template public." - }); - setTimeout(() => setIsAlert(false), 5000); - } - }; + // setIsMakePublic({ [item.objectId]: true }); + // } else { + // setIsPublicProfile({ [item.objectId]: true }); + // } + // } else { + // setIsAlert(true); + // setAlertMsg({ + // type: "danger", + // message: + // " Please ensure there's at least one signature widget added for all recipients." + // }); + // setTimeout(() => setIsAlert(false), 5000); + // } + // } else { + // setIsAlert(true); + // setAlertMsg({ + // type: "danger", + // message: "Please assign at least one role to make this template public." + // }); + // setTimeout(() => setIsAlert(false), 5000); + // } + // }; //function to copy public profile links - const copytoProfileLink = () => { - const url = `https://opensign-me.vercel.app/${publicUserName}`; - copytoData(url); - setIsAlert(true); - setAlertMsg({ - type: "success", - message: "Copied." - }); - setTimeout(() => setIsAlert(false), 1500); - }; + // const copytoProfileLink = () => { + // const url = `https://opensign-me.vercel.app/${publicUserName}`; + // copytoData(url); + // setIsAlert(true); + // setAlertMsg({ + // type: "success", + // message: "Copied." + // }); + // setTimeout(() => setIsAlert(false), 1500); + // }; return ( <div className="relative"> @@ -866,11 +869,11 @@ const ReportTable = (props) => { </div> )} <div className="p-2 overflow-x-scroll w-full bg-white rounded-md"> - {isCelebration && ( + {/* {isCelebration && ( <div style={{ position: "relative", zIndex: "1000" }}> <Confetti width={window.innerWidth} height={window.innerHeight} /> </div> - )} + )} */} {isAlert && <Alert type={alertMsg.type}>{alertMsg.message}</Alert>} {props.tourData && props.ReportName === "Templates" && ( <Tour @@ -917,9 +920,9 @@ const ReportTable = (props) => { {props.actions?.length > 0 && ( <th className="px-4 py-2 font-thin">Action</th> )} - {props.ReportName === "Templates" && isEnableSubscription && ( + {/* {props.ReportName === "Templates" && isEnableSubscription && ( <th className="px-4 py-2 font-thin">Public</th> - )} + )} */} </tr> </thead> <tbody className="text-[12px]"> @@ -1364,7 +1367,7 @@ const ReportTable = (props) => { </ModalUi> )} </td> - {isEnableSubscription && ( + {/* {isEnableSubscription && ( <td className=" pl-[20px] py-2 "> {props.ReportName === "Templates" && ( <div className=" flex flex-row-"> @@ -1527,7 +1530,7 @@ const ReportTable = (props) => { </ModalUi> )} </td> - )} + )} */} </tr> ) )} From 90b5e3c860139982564a7e60c60589fcbe04ee87 Mon Sep 17 00:00:00 2001 From: RaktimaNXG <raktima.c@nxglabs.com> Date: Fri, 7 Jun 2024 19:55:40 +0530 Subject: [PATCH 4/4] fix: exist contact not recieving maiin in quick send flow --- apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index 602ddb9db..d04ece47b 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -35,8 +35,10 @@ async function sendMail(document, sessionToken) { const objectId = signerMail[i]?.signerObjId; const hostUrl = baseUrl.origin; let encodeBase64; + let existSigner = {}; if (objectId) { - encodeBase64 = btoa(`${document.objectId}/${signerMail[i].signerPtr.Email}/${objectId}`); + existSigner = document?.Signers?.find(user => user.objectId === objectId); + encodeBase64 = btoa(`${document.objectId}/${existSigner?.Email}/${objectId}`); } else { encodeBase64 = btoa(`${document.objectId}/${signerMail[i].email}`); } @@ -46,7 +48,7 @@ async function sendMail(document, sessionToken) { const themeBGcolor = '#47a3ad'; let params = { extUserId: document.ExtUserPtr.objectId, - recipient: objectId ? signerMail[i].signerPtr.Email : signerMail[i].email, + recipient: objectId ? existSigner?.Email : signerMail[i].email, subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`, mailProvider: document?.ExtUserPtr?.active_mail_adapter || '', from: sender,