From b7beeee260c21d00c058f045c42d69245e43cd58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:14:13 +0000 Subject: [PATCH 01/11] build(deps-dev): bump lint-staged in /apps/OpenSign Bumps [lint-staged](https://github.com/okonet/lint-staged) from 15.2.4 to 15.2.5. - [Release notes](https://github.com/okonet/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md) - [Commits](https://github.com/okonet/lint-staged/compare/v15.2.4...v15.2.5) --- updated-dependencies: - dependency-name: lint-staged dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- apps/OpenSign/package-lock.json | 47 +++++++++++++-------------------- apps/OpenSign/package.json | 2 +- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/apps/OpenSign/package-lock.json b/apps/OpenSign/package-lock.json index a59f26945..55de2be44 100644 --- a/apps/OpenSign/package-lock.json +++ b/apps/OpenSign/package-lock.json @@ -60,7 +60,7 @@ "eslint": "^8.57.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.34.1", - "lint-staged": "^15.2.4", + "lint-staged": "^15.2.5", "postcss": "^8.4.38", "prettier": "^2.8.8", "pretty-quick": "^3.3.1", @@ -15562,21 +15562,21 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/lint-staged": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.4.tgz", - "integrity": "sha512-3F9KRQIS2fVDGtCkBp4Bx0jswjX7zUcKx6OF0ZeY1prksUyKPRIIUqZhIUYAstJfvj6i48VFs4dwVIbCYwvTYQ==", + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.5.tgz", + "integrity": "sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==", "dev": true, "dependencies": { - "chalk": "5.3.0", - "commander": "12.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.1.1", - "listr2": "8.2.1", - "micromatch": "4.0.6", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.4.2" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -16399,28 +16399,17 @@ } }, "node_modules/micromatch": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.6.tgz", - "integrity": "sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dependencies": { "braces": "^3.0.3", - "picomatch": "^4.0.2" + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", diff --git a/apps/OpenSign/package.json b/apps/OpenSign/package.json index 2c8820be3..ffe778fe0 100644 --- a/apps/OpenSign/package.json +++ b/apps/OpenSign/package.json @@ -90,7 +90,7 @@ "eslint": "^8.57.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.34.1", - "lint-staged": "^15.2.4", + "lint-staged": "^15.2.5", "postcss": "^8.4.38", "prettier": "^2.8.8", "pretty-quick": "^3.3.1", From 59f6d022cf228c33aa1dab530f37a7e55a524538 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:27:04 +0000 Subject: [PATCH 02/11] build(deps-dev): bump @babel/eslint-parser in /apps/OpenSignServer Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.24.5 to 7.24.6. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.24.6/eslint/babel-eslint-parser) --- updated-dependencies: - dependency-name: "@babel/eslint-parser" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- apps/OpenSignServer/package-lock.json | 8 ++++---- apps/OpenSignServer/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/OpenSignServer/package-lock.json b/apps/OpenSignServer/package-lock.json index 10bcaa5d1..5efa2c928 100644 --- a/apps/OpenSignServer/package-lock.json +++ b/apps/OpenSignServer/package-lock.json @@ -38,7 +38,7 @@ "posthog-node": "^4.0.1" }, "devDependencies": { - "@babel/eslint-parser": "^7.24.5", + "@babel/eslint-parser": "^7.24.6", "eslint": "^9.3.0", "jasmine": "^5.1.0", "mongodb-runner": "^5.6.2", @@ -1303,9 +1303,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.5.tgz", - "integrity": "sha512-gsUcqS/fPlgAw1kOtpss7uhY6E9SFFANQ6EFX5GTvzUwaV0+sGaZWk6xq22MOdeT9wfxyokW3ceCUvOiRtZciQ==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.6.tgz", + "integrity": "sha512-Q1BfQX42zXHx732PLW0w4+Y3wJjoZKEMaatFUEAmQ7Z+jCXxinzeqX9bvv2Q8xNPes/H6F0I23oGkcgjaItmLw==", "dev": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", diff --git a/apps/OpenSignServer/package.json b/apps/OpenSignServer/package.json index 8a322d2ef..f706ba2ba 100644 --- a/apps/OpenSignServer/package.json +++ b/apps/OpenSignServer/package.json @@ -48,7 +48,7 @@ }, "type": "module", "devDependencies": { - "@babel/eslint-parser": "^7.24.5", + "@babel/eslint-parser": "^7.24.6", "eslint": "^9.3.0", "jasmine": "^5.1.0", "mongodb-runner": "^5.6.2", From a86f4fd9b7857dd17f543127a31c61cf3e13c62b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:27:27 +0000 Subject: [PATCH 03/11] build(deps-dev): bump nodemon in /apps/OpenSignServer Bumps [nodemon](https://github.com/remy/nodemon) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/remy/nodemon/releases) - [Commits](https://github.com/remy/nodemon/compare/v3.1.0...v3.1.1) --- updated-dependencies: - dependency-name: nodemon dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- apps/OpenSignServer/package-lock.json | 8 ++++---- apps/OpenSignServer/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/OpenSignServer/package-lock.json b/apps/OpenSignServer/package-lock.json index 10bcaa5d1..5ce604ce9 100644 --- a/apps/OpenSignServer/package-lock.json +++ b/apps/OpenSignServer/package-lock.json @@ -42,7 +42,7 @@ "eslint": "^9.3.0", "jasmine": "^5.1.0", "mongodb-runner": "^5.6.2", - "nodemon": "^3.1.0", + "nodemon": "^3.1.1", "nyc": "15.1.0", "prettier": "^3.2.5", "uglify-js": "^3.17.4" @@ -8365,9 +8365,9 @@ } }, "node_modules/nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.1.tgz", + "integrity": "sha512-k43xGaDtaDIcufn0Fc6fTtsdKSkV/hQzoQFigNH//GaKta28yoKVYXCnV+KXRqfT/YzsFaQU9VdeEG+HEyxr6A==", "dev": true, "dependencies": { "chokidar": "^3.5.2", diff --git a/apps/OpenSignServer/package.json b/apps/OpenSignServer/package.json index 8a322d2ef..189acab89 100644 --- a/apps/OpenSignServer/package.json +++ b/apps/OpenSignServer/package.json @@ -52,7 +52,7 @@ "eslint": "^9.3.0", "jasmine": "^5.1.0", "mongodb-runner": "^5.6.2", - "nodemon": "^3.1.0", + "nodemon": "^3.1.1", "nyc": "15.1.0", "prettier": "^3.2.5", "uglify-js": "^3.17.4" From c3c6f6bab34c224e925781da8e485c384868c1a8 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Mon, 27 May 2024 11:59:25 +0530 Subject: [PATCH 04/11] fix: send mail only first signer if sendinorder, takeout quick send btn from 3 dots --- .../shared/fields/SuggestionInput.js | 2 +- apps/OpenSign/src/json/ReportJson.js | 23 +++++++++++-------- .../cloud/parsefunction/createBatchDocs.js | 12 +++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/apps/OpenSign/src/components/shared/fields/SuggestionInput.js b/apps/OpenSign/src/components/shared/fields/SuggestionInput.js index 6efaf66a8..aaefb2b30 100644 --- a/apps/OpenSign/src/components/shared/fields/SuggestionInput.js +++ b/apps/OpenSign/src/components/shared/fields/SuggestionInput.js @@ -66,7 +66,7 @@ const SuggestionInput = (props) => { type={props?.type || "text"} value={inputValue} onChange={handleInputChange} - placeholder="Enter text..." + placeholder="Enter Email..." className="w-full border-[1px] border-gray-400 p-2 text-black rounded" required={props.required} /> diff --git a/apps/OpenSign/src/json/ReportJson.js b/apps/OpenSign/src/json/ReportJson.js index f16efca1c..705ce8fb9 100644 --- a/apps/OpenSign/src/json/ReportJson.js +++ b/apps/OpenSign/src/json/ReportJson.js @@ -3,7 +3,7 @@ export default function reportJson(id) { const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"]; const contactbook = ["Sr.No", "Title", "Email", "Phone"]; const dashboardReportHead = ["Title", "File", "Owner", "Signers"]; - + const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"]; switch (id) { // draft documents report case "ByHuevtCFY": @@ -326,7 +326,7 @@ export default function reportJson(id) { case "6TeaPr321t": return { reportName: "Templates", - heading: head, + heading: templateReport, actions: [ { btnId: "2234", @@ -341,6 +341,17 @@ export default function reportJson(id) { message: "Click the 'Use' button to create a new document from an existing template. " }, + { + btnId: "1631", + btnLabel: "Quick send", + hoverLabel: "Quick send", + btnIcon: "fa-solid fa-envelope", + redirectUrl: "", + action: "bulksend", + selector: "tourbulksend", + message: + "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button." + }, { btnId: "2234", hoverLabel: "option", @@ -360,14 +371,6 @@ export default function reportJson(id) { redirectUrl: "template", action: "redirect" }, - { - btnId: "1631", - btnLabel: "Quick send", - hoverLabel: "Quick send", - btnIcon: "fa-solid fa-envelope", - redirectUrl: "", - action: "bulksend" - }, { btnId: "1834", btnLabel: "Delete", diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index b18f70a91..cb8524998 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -17,7 +17,12 @@ async function sendMail(document, sessionToken) { year: 'numeric', }); const sender = document.ExtUserPtr.Email; - const signerMail = document.Placeholders; + let signerMail = document.Placeholders; + + if (document.SendinOrder) { + signerMail = signerMail.slice(); + signerMail.splice(1); + } for (let i = 0; i < signerMail.length; i++) { try { const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png'; @@ -42,7 +47,7 @@ async function sendMail(document, sessionToken) { let params = { extUserId: document.ExtUserPtr.objectId, recipient: objectId ? signerMail[i].signerPtr.Email : signerMail[i].email, - subject: `${document.ExtUserPtr.Name} has requested you to sign ${document.Name}`, + subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`, from: sender, html: "
Date: Mon, 27 May 2024 12:59:43 +0530 Subject: [PATCH 05/11] Fix: issue of showing 'Please add Signers or Roles in template' even when roles are already exist in quick send --- apps/OpenSign/src/primitives/GetReportDisplay.js | 1 + apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 9e5b01a63..38b2e6492 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -648,6 +648,7 @@ const ReportTable = (props) => { const handleBulkSend = async (template) => { setIsBulkSend({ [template.objectId]: true }); setIsLoader({ [template.objectId]: true }); + setIsDocErr(false); try { const params = { templateId: template.objectId, diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index cb8524998..c58485c10 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -48,6 +48,7 @@ async function sendMail(document, sessionToken) { extUserId: document.ExtUserPtr.objectId, recipient: objectId ? signerMail[i].signerPtr.Email : signerMail[i].email, subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`, + mailProvider: document?.ExtUserPtr?.active_mail_adapter || '', from: sender, html: "
0) { + const AuditTrail = JSON.parse(JSON.stringify(data.AuditTrail)); + const existingIndex = AuditTrail.findIndex( + entry => entry.UserPtr.objectId === userId && entry.Activity !== 'Created' + ); + existingIndex !== -1 + ? (AuditTrail[existingIndex] = { ...AuditTrail[existingIndex], ...obj }) + : AuditTrail.push(obj); + + updateAuditTrail = AuditTrail; + } else { + updateAuditTrail = [obj]; + } + + const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed'); + let isCompleted = false; + if (data.Signers && data.Signers.length > 0) { + if (auditTrail.length === data.Placeholders.length) { + isCompleted = true; + } + } else { + isCompleted = true; + } + const body = { + SignedUrl: url, + AuditTrail: updateAuditTrail, + IsCompleted: isCompleted, + }; + const signedRes = await axios.put(serverUrl + '/classes/contracts_Document/' + docId, body, { + headers: { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': APPID, + 'X-Parse-Master-Key': masterKEY, + }, + }); + return { isCompleted: isCompleted, message: 'success', AuditTrail: updateAuditTrail }; + } catch (err) { + console.log('update doc err ', err); + return 'err'; + } +} + +// `sendCompletedMail` is used to send copy of completed document mail +async function sendCompletedMail(obj) { + const url = obj.url; + const doc = obj.doc; + const sender = obj.doc.ExtUserPtr; + const pdfName = doc.Name; + const mailLogo = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png'; + const recipient = sender.Email; + let subject = `Document "${pdfName}" has been signed by all parties`; + let body = + "

Document signed successfully

All parties have successfully signed the document " + + `"${pdfName}"` + + '. Kindly download the document from the attachment.

This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' + + sender.Email + + ' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here.

'; + + if (obj?.isCustomMail) { + try { + const tenantCreditsQuery = new Parse.Query('partners_Tenant'); + tenantCreditsQuery.equalTo('UserId', { + __type: 'Pointer', + className: '_User', + objectId: sender.UserId.objectId, + }); + const res = await tenantCreditsQuery.first(); + if (res) { + const _res = JSON.parse(JSON.stringify(res)); + if (_res?.CompletionSubject) { + subject = _res?.CompletionSubject; + } + if (_res?.CompletionBody) { + body = _res?.CompletionBody; + } + const expireDate = doc.ExpiryDate.iso; + const newDate = new Date(expireDate); + const localExpireDate = newDate.toLocaleDateString('en-US', { + day: 'numeric', + month: 'long', + year: 'numeric', + }); + + const variables = { + document_title: pdfName, + sender_name: sender.Name, + sender_mail: sender.Email, + sender_phone: sender.Phone, + receiver_name: sender.Name, + receiver_email: sender.Email, + receiver_phone: sender.Phone, + expiry_date: localExpireDate, + company_name: sender.Company, + }; + const replaceVar = replaceMailVaribles(subject, body, variables); + subject = replaceVar.subject; + body = replaceVar.body; + } + } catch (err) { + console.log('error in fetch tenant in signpdf', err.message); + } + } + const params = { + extUserId: sender.objectId, + url: url, + from: 'OpenSign™', + recipient: recipient, + subject: subject, + pdfName: pdfName, + html: body, + mailProvider: obj.mailProvider, + }; + const res = await axios.post(serverUrl + '/functions/sendmailv3', params, { + headers: { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': APPID, + 'X-Parse-Master-Key': masterKEY, + }, + }); + // console.log('Res ', res); +} + +// `sendDoctoWebhook` is used to send res data of document on webhook +async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) { + let signers = []; + if (signUser) { + signers = { + name: signUser?.Name, + email: signUser?.Email, + phone: signUser?.Phone, + }; + } else { + signers = doc?.Signers?.map(x => ({ + name: x.Name, + email: x.Email, + phone: x.Phone, + })) || [ + { + name: doc?.ExtUserPtr?.Name, + email: doc?.ExtUserPtr?.Email, + phone: doc?.ExtUserPtr?.Phone, + }, + ]; + } + + if (doc.ExtUserPtr?.Webhook) { + const time = + event === 'signed' + ? { signer: signers, signedAt: new Date() } + : { signers: signers, completedAt: new Date() }; + const certificate = certificateUrl ? { certificate: certificateUrl } : {}; + const params = { + event: event, + objectId: doc?.objectId, + file: Url || '', + ...certificate, + name: doc?.Name, + note: doc?.Note || '', + description: doc?.Description || '', + ...time, + createdAt: doc?.createdAt, + }; + axios + .post(doc?.ExtUserPtr?.Webhook, params, { + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => { + try { + // console.log('res ', res); + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', res?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: doc.ExtUserPtr.UserId.objectId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err.message); + } + }) + .catch(err => { + console.log('Err send data to webhook', err.message); + try { + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', err?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: doc.ExtUserPtr.UserId.objectId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err.message); + } + }); + // console.log('res ', res.data); + } +} + +// `sendMailsaveCertifcate` is used send completion mail and update complete status of document +const sendMailsaveCertifcate = async (doc, P12Buffer, url, isCustomMail, mailProvider, userId) => { + const certificate = await GenerateCertificate(doc); + const certificatePdf = await PDFDocument.load(certificate); + const p12 = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null }); + // `pdflibAddPlaceholder` is used to add code of only digitial sign in certificate + pdflibAddPlaceholder({ + pdfDoc: certificatePdf, + reason: 'Digitally signed by OpenSign.', + location: 'n/a', + name: eSignName, + contactInfo: eSigncontact, + signatureLength: 15000, + }); + const pdfWithPlaceholderBytes = await certificatePdf.save(); + const CertificateBuffer = Buffer.from(pdfWithPlaceholderBytes); + //`new signPDF` create new instance of CertificateBuffer and p12Buffer + const certificateOBJ = new SignPdf(); + // `signedCertificate` is used to sign certificate digitally + const signedCertificate = await certificateOBJ.sign(CertificateBuffer, p12); + + //below is used to save signed certificate in exports folder + fs.writeFileSync('./exports/certificate.pdf', signedCertificate); + const file = await uploadFile('certificate.pdf', './exports/certificate.pdf'); + const body = { CertificateUrl: file.imageUrl }; + await axios.put(serverUrl + '/classes/contracts_Document/' + doc.objectId, body, { + headers: { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': APPID, + 'X-Parse-Master-Key': masterKEY, + }, + }); + // used in API only + if (doc.IsSendMail && doc.IsSendMail === false) { + console.log("don't send mail"); + } else { + const mailObj = { + url: url, + isCustomMail: isCustomMail, + doc: doc, + mailProvider: mailProvider, + }; + sendCompletedMail(mailObj); + } + + saveFileUsage(CertificateBuffer.length, file.imageUrl, userId); + sendDoctoWebhook(doc, url, 'completed', '', file.imageUrl); +}; +/** + * + * @param docId Id of Document in which user is signing + * @param pdfFile base64 of pdfFile which you want sign + * @returns if success {status, data} else {status, message} + */ +async function PDF(req) { + try { + if (!req?.user) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.'); + } else { + const password = ''; + const authUser = req?.user?.toJSON(); + const docId = req.params.docId; + const reqUserId = req.params.userId; + const isCustomMail = req.params.isCustomCompletionMail || false; + const mailProvider = req.params.mailProvider || ''; + const sign = req.params.signature || ''; + // below bode is used to get info of docId + const docQuery = new Parse.Query('contracts_Document'); + docQuery.include('ExtUserPtr,Signers'); + docQuery.equalTo('objectId', docId); + const resDoc = await docQuery.first({ useMasterKey: true }); + if (!resDoc) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.'); + } + const _resDoc = resDoc?.toJSON(); + + let signUser; + let className; + // `reqUserId` is send throught pdfrequest signing flow + if (reqUserId) { + // to get contracts_Contactbook details for currentuser from reqUserId + const _contractUser = _resDoc.Signers.find(x => x.objectId === reqUserId); + if (_contractUser) { + signUser = _contractUser; + className = 'contracts_Contactbook'; + } + } else { + className = 'contracts_Users'; + signUser = _resDoc.ExtUserPtr; + } + + const username = signUser.Name; + const userEmail = signUser.Email; + if (req.params.pdfFile) { + // `PdfBuffer` used to create buffer from pdf file + let PdfBuffer = Buffer.from(req.params.pdfFile, 'base64'); + // `P12Buffer` used to create buffer from p12 certificate + const pfxFile = process.env.PFX_BASE64; + // const P12Buffer = fs.readFileSync(); + const P12Buffer = Buffer.from(pfxFile, 'base64'); + const p12Cert = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null }); + + const UserPtr = { + __type: 'Pointer', + className: className, + objectId: signUser.objectId, + }; + const obj = { + UserPtr: UserPtr, + SignedUrl: '', + Activity: 'Signed', + ipAddress: req.headers['x-real-ip'], + }; + let updateAuditTrail; + if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) { + updateAuditTrail = [..._resDoc.AuditTrail, obj]; + } else { + updateAuditTrail = [obj]; + } + + const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed'); + let isCompleted = false; + if (_resDoc.Signers && _resDoc.Signers.length > 0) { + if (auditTrail.length === _resDoc.Signers.length) { + isCompleted = true; + } + } else { + isCompleted = true; + } + const randomNumber = Math.floor(Math.random() * 5000); + const name = `exported_file_${randomNumber}.pdf`; + const pdfName = `./exports/${name}`; + let pdfSize = PdfBuffer.length; + if (isCompleted) { + const signersName = _resDoc.Signers?.map(x => x.Name + ' <' + x.Email + '>'); + if (signersName && signersName.length > 0) { + // `pdflibAddPlaceholder` is used to add code of only digitial sign without widget + const pdfDoc = await PDFDocument.load(PdfBuffer); + pdflibAddPlaceholder({ + pdfDoc: pdfDoc, + reason: 'Digitally signed by OpenSign for ' + signersName?.join(', '), + location: 'n/a', + name: eSignName, + contactInfo: eSigncontact, + signatureLength: 15000, + }); + const pdfWithPlaceholderBytes = await pdfDoc.save(); + PdfBuffer = Buffer.from(pdfWithPlaceholderBytes); + } else { + // `pdflibAddPlaceholder` is used to add code of only digitial sign without widget (signyourself) + const pdfDoc = await PDFDocument.load(PdfBuffer); + pdflibAddPlaceholder({ + pdfDoc: pdfDoc, + reason: 'Digitally signed by OpenSign for ' + username + ' <' + userEmail + '>', + location: 'n/a', + name: eSignName, + contactInfo: eSigncontact, + signatureLength: 15000, + }); + const pdfWithPlaceholderBytes = await pdfDoc.save(); + PdfBuffer = Buffer.from(pdfWithPlaceholderBytes); + } + //`new signPDF` create new instance of pdfBuffer and p12Buffer + const OBJ = new SignPdf(); + // `signedDocs` is used to signpdf digitally + const signedDocs = await OBJ.sign(PdfBuffer, p12Cert); + + //`saveUrl` is used to save signed pdf in exports folder + const saveUrl = fs.writeFileSync(pdfName, signedDocs); + pdfSize = signedDocs.length; + } else { + //`saveUrl` is used to save signed pdf in exports folder + const saveUrl = fs.writeFileSync(pdfName, PdfBuffer); + pdfSize = PdfBuffer.length; + } + + // `uploadFile` is used to upload pdf to aws s3 and get it's url + const data = await uploadFile(name, pdfName); + + if (data && data.imageUrl) { + // `axios` is used to update signed pdf url in contracts_Document classes for given DocId + const updatedDoc = await updateDoc( + req.params.docId, //docId + data.imageUrl, // url + signUser.objectId, // userID + req.headers['x-real-ip'], // client ipAddress, + _resDoc, // auditTrail, signers, etc data + className, + sign + ); + sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser); + saveFileUsage(pdfSize, data.imageUrl, authUser.objectId); + if (updatedDoc && updatedDoc.isCompleted) { + const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail }; + sendMailsaveCertifcate( + doc, + P12Buffer, + data.imageUrl, + isCustomMail, + mailProvider, + authUser.objectId + ); + } + // `fs.unlinkSync` is used to remove exported signed pdf file from exports folder + fs.unlinkSync(pdfName); + console.log(`New Signed PDF created called: ${pdfName}`); + if (updatedDoc.message === 'success') { + return { status: 'success', data: data.imageUrl }; + } else { + const error = new Error('Please provide required parameters!'); + error.code = 400; // Set the error code (e.g., 400 for bad request) + throw error; + } + } + } else { + const error = new Error('Pdf file not present!'); + error.code = 400; // Set the error code (e.g., 400 for bad request) + throw error; + } + } + } catch (err) { + console.log('Err in signpdf', err); + throw err; + } +} +export default PDF; diff --git a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js deleted file mode 100644 index d29c624c9..000000000 --- a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js +++ /dev/null @@ -1,337 +0,0 @@ -import fs from 'node:fs'; -import axios from 'axios'; -import { SignPdf } from '@signpdf/signpdf'; -import { P12Signer } from '@signpdf/signer-p12'; -import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib'; -import { PDFDocument } from 'pdf-lib'; -import { replaceMailVaribles, saveFileUsage } from '../../../Utils.js'; -import GenerateCertificate from './GenerateCertificate.js'; -const serverUrl = process.env.SERVER_URL, - APPID = process.env.APP_ID, - masterKEY = process.env.MASTER_KEY, - eSignName = 'opensign', - eSigncontact = 'hello@opensignlabs.com'; -async function uploadFile(e, t) { - try { - var a = fs.readFileSync(t), - r = new Parse.File(e, [...a], 'application/pdf'), - i = (await r.save({ useMasterKey: !0 }), r.url()); - return { imageUrl: i }; - } catch (e) { - console.log('Err ', e), fs.unlinkSync(t); - } -} -async function updateDoc(a, r, i, n, s, o, l) { - try { - var c, - d, - p = { - UserPtr: { __type: 'Pointer', className: o, objectId: i }, - SignedUrl: r, - Activity: 'Signed', - ipAddress: n, - SignedOn: new Date(), - Signature: l, - }; - let e; - var m = (e = - s.AuditTrail && 0 < s.AuditTrail.length - ? (-1 !== - (d = (c = JSON.parse(JSON.stringify(s.AuditTrail))).findIndex( - e => e.UserPtr.objectId === i && 'Created' !== e.Activity - )) - ? (c[d] = { ...c[d], ...p }) - : c.push(p), - c) - : [p]).filter(e => 'Signed' === e.Activity); - let t = !1; - !((s.Signers && 0 < s.Signers.length && m.length !== s.Signers.length) || !(t = !0)); - var g = { SignedUrl: r, AuditTrail: e, IsCompleted: t }; - await axios.put(serverUrl + '/classes/contracts_Document/' + a, g, { - headers: { - 'Content-Type': 'application/json', - 'X-Parse-Application-Id': APPID, - 'X-Parse-Master-Key': masterKEY, - }, - }); - return { isCompleted: t, message: 'success', AuditTrail: e }; - } catch (e) { - return console.log('update doc err ', e), 'err'; - } -} -async function sendCompletedMail(e) { - var t = e.url, - a = e.doc, - r = e.doc.ExtUserPtr, - i = a.Name, - n = r.Email; - let s = `Document "${i}" has been signed by all parties`, - o = - "

Document signed successfully

All parties have successfully signed the document " + - `"${i}"` + - '. Kindly download the document from the attachment.

This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' + - r.Email + - ' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here.

'; - if (e?.isCustomMail) - try { - var l, - c, - d, - p, - m, - g = new Parse.Query('partners_Tenant'); - g.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: r.UserId.objectId }); - const f = await g.first(); - f && - ((l = JSON.parse(JSON.stringify(f)))?.CompletionSubject && (s = l?.CompletionSubject), - l?.CompletionBody && (o = l?.CompletionBody), - (c = a.ExpiryDate.iso), - (d = new Date(c).toLocaleDateString('en-US', { - day: 'numeric', - month: 'long', - year: 'numeric', - })), - (p = { - document_title: i, - sender_name: r.Name, - sender_mail: r.Email, - sender_phone: r.Phone, - receiver_name: r.Name, - receiver_email: r.Email, - receiver_phone: r.Phone, - expiry_date: d, - company_name: r.Company, - }), - (m = replaceMailVaribles(s, o, p)), - (s = m.subject), - (o = m.body)); - } catch (e) { - console.log('error in fetch tenant in signpdf', e.message); - } - g = { - extUserId: r.objectId, - url: t, - from: 'OpenSign™', - recipient: n, - subject: s, - pdfName: i, - html: o, - mailProvider: e.mailProvider, - }; - await axios.post(serverUrl + '/functions/sendmailv3', g, { - headers: { - 'Content-Type': 'application/json', - 'X-Parse-Application-Id': APPID, - 'X-Parse-Master-Key': masterKEY, - }, - }); -} -async function sendDoctoWebhook(a, e, t, r, i) { - let n = []; - (n = r - ? { name: r?.Name, email: r?.Email, phone: r?.Phone } - : a?.Signers?.map(e => ({ name: e.Name, email: e.Email, phone: e.Phone })) || [ - { name: a?.ExtUserPtr?.Name, email: a?.ExtUserPtr?.Email, phone: a?.ExtUserPtr?.Phone }, - ]), - a.ExtUserPtr?.Webhook && - ((r = - 'signed' === t - ? { signer: n, signedAt: new Date() } - : { signers: n, completedAt: new Date() }), - (t = { - event: t, - objectId: a?.objectId, - file: e || '', - ...(i ? { certificate: i } : {}), - name: a?.Name, - note: a?.Note || '', - description: a?.Description || '', - ...r, - createdAt: a?.createdAt, - }), - axios - .post(a?.ExtUserPtr?.Webhook, t, { headers: { 'Content-Type': 'application/json' } }) - .then(e => { - try { - var t = new Parse.Object('contracts_Webhook'); - t.set('Log', e?.status), - t.set('UserId', { - __type: 'Pointer', - className: '_User', - objectId: a.ExtUserPtr.UserId.objectId, - }), - t.save(null, { useMasterKey: !0 }); - } catch (e) { - console.log('err save in contracts_Webhook', e.message); - } - }) - .catch(e => { - console.log('Err send data to webhook', e.message); - try { - var t = new Parse.Object('contracts_Webhook'); - t.set('Log', e?.status), - t.set('UserId', { - __type: 'Pointer', - className: '_User', - objectId: a.ExtUserPtr.UserId.objectId, - }), - t.save(null, { useMasterKey: !0 }); - } catch (e) { - console.log('err save in contracts_Webhook', e.message); - } - })); -} -const sendMailsaveCertifcate = async (e, t, a, r, i, n) => { - var s = await GenerateCertificate(e), - s = await PDFDocument.load(s), - t = new P12Signer(t, { passphrase: process.env.PASS_PHRASE || null }), - s = - (pdflibAddPlaceholder({ - pdfDoc: s, - reason: 'Digitally signed by OpenSign.', - location: 'n/a', - name: eSignName, - contactInfo: eSigncontact, - signatureLength: 15e3, - }), - await s.save()), - s = Buffer.from(s), - t = await new SignPdf().sign(s, t), - t = - (fs.writeFileSync('./exports/certificate.pdf', t), - await uploadFile('certificate.pdf', './exports/certificate.pdf')), - o = { CertificateUrl: t.imageUrl }; - await axios.put(serverUrl + '/classes/contracts_Document/' + e.objectId, o, { - headers: { - 'Content-Type': 'application/json', - 'X-Parse-Application-Id': APPID, - 'X-Parse-Master-Key': masterKEY, - }, - }), - e.IsSendMail && !1 === e.IsSendMail - ? console.log("don't send mail") - : sendCompletedMail({ url: a, isCustomMail: r, doc: e, mailProvider: i }), - saveFileUsage(s.length, t.imageUrl, n), - sendDoctoWebhook(e, a, 'completed', '', t.imageUrl); -}; -async function PDF(s) { - try { - if (!s?.user) - throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.'); - { - var o = s?.user?.toJSON(), - e = s.params.docId; - const C = s.params.userId; - var l = s.params.isCustomCompletionMail || !1, - c = s.params.mailProvider || '', - d = s.params.signature || '', - t = new Parse.Query('contracts_Document'), - a = - (t.include('ExtUserPtr,Signers'), - t.equalTo('objectId', e), - await t.first({ useMasterKey: !0 })); - if (!a) throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.'); - var r, - p = a?.toJSON(); - let i, n; - C - ? ((r = p.Signers.find(e => e.objectId === C)), - console.log('_contractUser ', r), - r && ((i = r), (n = 'contracts_Contactbook'))) - : ((n = 'contracts_Users'), (i = p.ExtUserPtr)); - var m, - g = i.Name, - f = i.Email; - if (!s.params.pdfFile) throw (((m = new Error('Pdf file not present!')).code = 400), m); - { - let e = Buffer.from(s.params.pdfFile, 'base64'); - var u = process.env.PFX_BASE64, - h = Buffer.from(u, 'base64'), - y = new P12Signer(h, { passphrase: process.env.PASS_PHRASE || null }), - P = { - UserPtr: { __type: 'Pointer', className: n, objectId: i.objectId }, - SignedUrl: '', - Activity: 'Signed', - ipAddress: s.headers['x-real-ip'], - }; - let t; - var v = (t = p.AuditTrail && 0 < p.AuditTrail.length ? [...p.AuditTrail, P] : [P]).filter( - e => 'Signed' === e.Activity - ); - let a = !1; - !((p.Signers && 0 < p.Signers.length && v.length !== p.Signers.length) || !(a = !0)); - var S, - b, - w, - U, - I, - _, - E = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`, - D = './exports/' + E; - let r = e.length; - r = ( - a - ? ((S = p.Signers?.map(e => e.Name + ' <' + e.Email + '>')), - (e = - S && 0 < S.length - ? ((b = await PDFDocument.load(e)), - pdflibAddPlaceholder({ - pdfDoc: b, - reason: 'Digitally signed by OpenSign for ' + S?.join(', '), - location: 'n/a', - name: eSignName, - contactInfo: eSigncontact, - signatureLength: 15e3, - }), - (w = await b.save()), - Buffer.from(w)) - : ((U = await PDFDocument.load(e)), - pdflibAddPlaceholder({ - pdfDoc: U, - reason: 'Digitally signed by OpenSign for ' + g + ' <' + f + '>', - location: 'n/a', - name: eSignName, - contactInfo: eSigncontact, - signatureLength: 15e3, - }), - (I = await U.save()), - Buffer.from(I))), - (_ = await new SignPdf().sign(e, y)), - fs.writeFileSync(D, _), - _) - : (fs.writeFileSync(D, e), e) - ).length; - var A = await uploadFile(E, D); - if (A && A.imageUrl) { - var x, - j, - N = await updateDoc( - s.params.docId, - A.imageUrl, - i.objectId, - s.headers['x-real-ip'], - p, - n, - d - ); - if ( - (sendDoctoWebhook(p, A.imageUrl, 'signed', i), - saveFileUsage(r, A.imageUrl, o.objectId), - N && - N.isCompleted && - ((x = { ...p, AuditTrail: N.AuditTrail }), - sendMailsaveCertifcate(x, h, A.imageUrl, l, c, o.objectId)), - fs.unlinkSync(D), - console.log('New Signed PDF created called: ' + D), - 'success' === N.message) - ) - return { status: 'success', data: A.imageUrl }; - throw (((j = new Error('Please provide required parameters!')).code = 400), j); - } - } - } - } catch (e) { - throw (console.log('Err in signpdf', e), e); - } -} -export default PDF; From f6ba4db62de7c347c1136cab214fc13ecc77c3c6 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Mon, 27 May 2024 20:06:06 +0530 Subject: [PATCH 08/11] Fix: Role, type are not visible on placeholder for non-exist contact --- apps/OpenSign/src/components/pdf/RenderPdf.js | 40 +++++++++---------- .../cloud/parsefunction/reportsJson.js | 4 +- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/apps/OpenSign/src/components/pdf/RenderPdf.js b/apps/OpenSign/src/components/pdf/RenderPdf.js index 5118dfcc1..716c404e2 100644 --- a/apps/OpenSign/src/components/pdf/RenderPdf.js +++ b/apps/OpenSign/src/components/pdf/RenderPdf.js @@ -211,27 +211,25 @@ function RenderPdf({ setCurrentSigner(true); } const handleAllUserName = (Id, Role, type) => { - return pdfDetails[0].Signers.map((signerData, key) => { - return ( - signerData.objectId === data.signerObjId && ( - - {signerData?.Name && ( -
- {signerData.Name} -
- )} - {type && ( -
{type}
- )} - {Role && ( -
- {`(${Role})`} -
- )} -
- ) - ); - }); + return ( + +
+ { + pdfDetails[0].Signers?.find( + (signer) => signer.objectId === data.signerObjId + )?.Name + } +
+ {type && ( +
{type}
+ )} + {Role && ( +
+ {`(${Role})`} +
+ )} +
+ ); }; return ( diff --git a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js index b94d2e82d..d3761e5ae 100644 --- a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js +++ b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js @@ -75,7 +75,7 @@ export default function reportJson(id, userId) { reportName: 'In-progress documents', params: { Type: { $ne: 'Folder' }, - Signers: { $exists: true, $ne: [] }, + SignedUrl: { $ne: null }, Placeholders: { $ne: null }, IsCompleted: { $ne: true }, IsDeclined: { $ne: true }, @@ -195,7 +195,7 @@ export default function reportJson(id, userId) { reportName: 'Recently sent for signatures', params: { Type: { $ne: 'Folder' }, - Signers: { $exists: true, $ne: [] }, + SignedUrl: { $ne: null }, Placeholders: { $ne: null }, IsCompleted: { $ne: true }, IsDeclined: { $ne: true }, From 07933b56b1b8ba06f05636bfc4f0d3b241fb2d42 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Mon, 27 May 2024 20:53:38 +0530 Subject: [PATCH 09/11] Fix: issue of 'something went wrong' err in guest login flow when using quick send --- .../src/primitives/GetReportDisplay.js | 18 +++++++++++------- .../cloud/parsefunction/createBatchDocs.js | 2 -- .../cloud/parsefunction/reportsJson.js | 2 ++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 52940e19c..88cb44c97 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -308,14 +308,18 @@ 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 - const encodeBase64 = btoa( - `${item.objectId}/${x.Email}/${x.objectId}/${sendMail}` - ); - return `${host}/login/${encodeBase64}`; + if (x.objectId) { + const encodeBase64 = btoa( + `${item.objectId}/${x.signerPtr.Email}/${x.signerPtr.objectId}/${sendMail}` + ); + return `${host}/login/${encodeBase64}`; + } else { + const encodeBase64 = btoa(`${item.objectId}/${x.email}`); + return `${host}/login/${encodeBase64}`; + } }; - - const urls = item.Signers.map((x) => ({ - email: x.Email, + const urls = item?.Placeholders?.map((x) => ({ + email: x.email ? x.email : x.signerPtr.Email, url: getUrl(x) })); setShareUrls(urls); diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index c58485c10..2f4aed714 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -166,8 +166,6 @@ export default async function createBatchDocs(request) { createdAt: response.data[i]?.success?.createdAt, })); for (let i = 0; i < updateDocuments.length; i++) { - console.log('updateDocuments ', updateDocuments); - sendMail(updateDocuments[i], sessionToken); } return 'success'; diff --git a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js index d3761e5ae..229d0b64c 100644 --- a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js +++ b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js @@ -102,6 +102,7 @@ export default function reportJson(id, userId) { 'AuditTrail.UserPtr', 'ExpiryDate', 'SendMail', + 'Placeholders', ], }; // completed documents report @@ -220,6 +221,7 @@ export default function reportJson(id, userId) { 'AuditTrail', 'AuditTrail.UserPtr', 'ExpiryDate', + 'Placeholders', ], }; // Recent signature requests report show on dashboard From c491595fc8e633aebe56fea33cef38fb6ad5c11c Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Tue, 28 May 2024 18:56:56 +0530 Subject: [PATCH 10/11] Fix: issues in quick send --- apps/OpenSign/src/components/pdf/PdfHeader.js | 36 ++++++-- apps/OpenSign/src/json/ReportJson.js | 2 +- apps/OpenSign/src/pages/PdfRequestFiles.js | 5 +- .../src/primitives/GetReportDisplay.js | 83 ++++++++++++++++--- .../cloud/parsefunction/linkContactToDoc.js | 4 +- .../cloud/parsefunction/reportsJson.js | 7 ++ apps/OpenSignServer/index.js | 2 +- 7 files changed, 116 insertions(+), 23 deletions(-) diff --git a/apps/OpenSign/src/components/pdf/PdfHeader.js b/apps/OpenSign/src/components/pdf/PdfHeader.js index 4d6a280f9..ad230f29d 100644 --- a/apps/OpenSign/src/components/pdf/PdfHeader.js +++ b/apps/OpenSign/src/components/pdf/PdfHeader.js @@ -40,7 +40,7 @@ function Header({ signerPos && signerPos?.filter((data) => data.Role !== "prefill"); const isMobile = window.innerWidth < 767; const navigate = useNavigate(); - const [isCertificate, setIsCertificate] = useState(false); + const [isDownloading, setIsDownloading] = useState(""); const isGuestSigner = localStorage.getItem("isGuestSigner"); //for go to previous page function previousPage() { @@ -62,7 +62,7 @@ function Header({ //function for print digital sign pdf const handleToPrint = async (event) => { event.preventDefault(); - + setIsDownloading("pdf"); try { // const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); const axiosRes = await axios.post( @@ -93,10 +93,13 @@ function Header({ const blob = new Blob([byteArray], { type: "application/pdf" }); const blobUrl = URL.createObjectURL(blob); window.open(blobUrl, "_blank"); + setIsDownloading(""); } else { printModule({ printable: pdf, type: "pdf", base64: true }); + setIsDownloading(""); } } catch (err) { + setIsDownloading(""); console.log("err in getsignedurl", err); alert("something went wrong, please try again later."); } @@ -104,6 +107,7 @@ function Header({ //handle download signed pdf const handleDownloadPdf = async () => { + setIsDownloading("pdf"); const pdfName = pdfDetails[0] && pdfDetails[0].Name; try { // const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); @@ -120,8 +124,10 @@ function Header({ ); const url = axiosRes.data.result; saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`); + setIsDownloading(""); } catch (err) { console.log("err in getsignedurl", err); + setIsDownloading(""); alert("something went wrong, please try again later."); } }; @@ -142,7 +148,7 @@ function Header({ console.log("err in download in certificate", err); } } else { - setIsCertificate(true); + setIsDownloading("certificate"); try { const data = { docId: pdfDetails[0]?.objectId @@ -164,12 +170,13 @@ function Header({ await fetch(doc?.CertificateUrl); const certificateUrl = doc?.CertificateUrl; saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`); - setIsCertificate(false); + setIsDownloading(""); } else { - setIsCertificate(true); + setIsDownloading("certificate"); } } } catch (err) { + setIsDownloading(""); console.log("err in download in certificate", err); alert("something went wrong, please try again later."); } @@ -628,12 +635,25 @@ function Header({ )}
)} + {isDownloading === "pdf" && ( +
+
+
+ )} setIsCertificate(false)} + isOpen={isDownloading === "certificate"} + title={ + isDownloading === "certificate" + ? "Generating certificate" + : "PDF Download" + } + handleClose={() => setIsDownloading("")} >
+ {isDownloading === "certificate"}{" "}

Your completion certificate is being generated. Please wait momentarily. diff --git a/apps/OpenSign/src/json/ReportJson.js b/apps/OpenSign/src/json/ReportJson.js index 705ce8fb9..e0cceda69 100644 --- a/apps/OpenSign/src/json/ReportJson.js +++ b/apps/OpenSign/src/json/ReportJson.js @@ -3,7 +3,7 @@ export default function reportJson(id) { const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"]; const contactbook = ["Sr.No", "Title", "Email", "Phone"]; const dashboardReportHead = ["Title", "File", "Owner", "Signers"]; - const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"]; + const templateReport = ["Sr.No", "Title", "File", "Owner", "Roles"]; switch (id) { // draft documents report case "ByHuevtCFY": diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 0cc5fb9c2..2b3a3f976 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -783,7 +783,10 @@ function PdfRequestFiles() { (x) => x.Email === jsonSender.email ); const newIndex = index + 1; - const user = pdfDetails?.[0].Signers[newIndex]; + const usermail = { + Email: pdfDetails?.[0]?.Placeholders[newIndex]?.email || "" + }; + const user = usermail || pdfDetails?.[0]?.Signers[newIndex]; if (sendmail !== "false" && sendInOrder) { const requestBody = pdfDetails?.[0]?.RequestBody; const requestSubject = pdfDetails?.[0]?.RequestSubject; diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 88cb44c97..412cb6550 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -43,7 +43,7 @@ const ReportTable = (props) => { const [templateDeatils, setTemplateDetails] = useState({}); const [placeholders, setPlaceholders] = useState([]); const [isLoader, setIsLoader] = useState({}); - + const [isViewShare, setIsViewShare] = useState({}); const startIndex = (currentPage - 1) * props.docPerPage; const { isMoreDocs, setIsNextRecord } = props; // For loop is used to calculate page numbers visible below table @@ -340,9 +340,9 @@ const ReportTable = (props) => { await axios .put( - `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( - "_appName" - )}_Document/${item.objectId}`, + `${localStorage.getItem("baseUrl")}classes/contracts_Document/${ + item.objectId + }`, data, { headers: { @@ -578,9 +578,15 @@ const ReportTable = (props) => { }; try { const res = await axios.post(url, params, { headers: headers }); - if (res) { + if (res?.data?.result?.status === "success") { setIsAlert(true); setAlertMsg({ type: "success", message: "Mail sent successfully." }); + } else { + setIsAlert(true); + setAlertMsg({ + type: "danger", + message: "Something went wrong, please try again later!" + }); } } catch (err) { console.log("err in sendmail", err); @@ -681,6 +687,9 @@ const ReportTable = (props) => { setTimeout(() => setIsAlert(false), 1500); } }; + const handleViewSigners = (item) => { + setIsViewShare({ [item.objectId]: true }); + }; return (

{Object.keys(actLoader)?.length > 0 && ( @@ -835,7 +844,17 @@ const ReportTable = (props) => { {formatRow(item?.ExtUserPtr)} - {item?.Signers ? formatRow(item?.Signers) : "-"} + {/* {item?.Signers ? formatRow(item?.Signers) : "-"} */} + {item?.Placeholders ? ( + + ) : ( + "-" + )} {props.actions?.length > 0 && @@ -865,19 +884,21 @@ const ReportTable = (props) => { )} {isOption[item.objectId] && act.action === "option" && ( -
+
{act.subaction?.map((subact) => (
handleActionBtn(subact, item) } title={subact.hoverLabel} > - + {subact.btnLabel && ( - + {subact.btnLabel} )} @@ -887,6 +908,48 @@ const ReportTable = (props) => { )} ))} + {isViewShare[item.objectId] && ( +
+
+
setIsViewShare({})} + > + × +
+ + + + + {props.ReportName === "Templates" && ( + + )} + + + + + {item.Placeholders.map((x, i) => ( + + {props.ReportName === "Templates" && ( + + )} + + + ))} + +
RolesSigners
+ {x.Role && x.Role} + + {x.email + ? x.email + : x?.signerPtr?.Email || "-"} +
+
+
+ )} {isDeleteModal[item.objectId] && ( Date: Wed, 29 May 2024 13:05:57 +0530 Subject: [PATCH 11/11] fix: issue of something went wrong due to quick send --- apps/OpenSign/src/json/ReportJson.js | 2 +- apps/OpenSign/src/pages/PdfRequestFiles.js | 15 +++++++++++---- apps/OpenSign/src/pages/PlanSubscriptions.js | 13 +++++++++++-- apps/OpenSign/src/primitives/GetReportDisplay.js | 6 +++--- .../cloud/parsefunction/ZohoDetails.js | 15 +++++++++------ 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/apps/OpenSign/src/json/ReportJson.js b/apps/OpenSign/src/json/ReportJson.js index e0cceda69..705ce8fb9 100644 --- a/apps/OpenSign/src/json/ReportJson.js +++ b/apps/OpenSign/src/json/ReportJson.js @@ -3,7 +3,7 @@ export default function reportJson(id) { const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"]; const contactbook = ["Sr.No", "Title", "Email", "Phone"]; const dashboardReportHead = ["Title", "File", "Owner", "Signers"]; - const templateReport = ["Sr.No", "Title", "File", "Owner", "Roles"]; + const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"]; switch (id) { // draft documents report case "ByHuevtCFY": diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 505b4b493..b0be26095 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -821,12 +821,19 @@ function PdfRequestFiles() { localStorage.getItem("parseAppId"), sessionToken: localStorage.getItem("accesstoken") }; - const objectId = user.objectId; + const objectId = user?.objectId; const hostUrl = window.location.origin; //encode this url value `${pdfDetails?.[0].objectId}/${user.Email}/${objectId}` to base64 using `btoa` function - const encodeBase64 = btoa( - `${pdfDetails?.[0].objectId}/${user.Email}/${objectId}` - ); + let encodeBase64; + if (objectId) { + encodeBase64 = btoa( + `${pdfDetails?.[0].objectId}/${user.Email}/${objectId}` + ); + } else { + encodeBase64 = btoa( + `${pdfDetails?.[0].objectId}/${user.Email}` + ); + } let signPdf = `${hostUrl}/login/${encodeBase64}`; const openSignUrl = "https://www.opensignlabs.com/contact-us"; diff --git a/apps/OpenSign/src/pages/PlanSubscriptions.js b/apps/OpenSign/src/pages/PlanSubscriptions.js index 1eeccd4ab..a8bfbd480 100644 --- a/apps/OpenSign/src/pages/PlanSubscriptions.js +++ b/apps/OpenSign/src/pages/PlanSubscriptions.js @@ -16,8 +16,17 @@ const PlanSubscriptions = () => { const navigate = useNavigate(); const [yearlyVisible, setYearlyVisible] = useState(false); const [isLoader, setIsLoader] = useState(true); - - const userDetails = JSON.parse(localStorage.getItem("userDetails")); + const extUser = + localStorage.getItem("Extand_Class") && + JSON.parse(localStorage.getItem("Extand_Class"))?.[0]; + const user = { + name: extUser?.Name, + email: extUser?.Email, + company: extUser?.Company, + phone: extUser?.Phone + }; + const userDetails = JSON.parse(localStorage.getItem("userDetails")) || user; + // console.log("userDetails ", userDetails); const name = userDetails && userDetails.name ? "first_name=" + encodeURIComponent(userDetails.name) diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 412cb6550..e898384ad 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -922,7 +922,7 @@ const ReportTable = (props) => { {props.ReportName === "Templates" && ( - Roles + Roles )} Signers @@ -934,11 +934,11 @@ const ReportTable = (props) => { className="text-sm font-normal text-black odd:bg-white even:bg-gray-200" > {props.ReportName === "Templates" && ( - + {x.Role && x.Role} )} - + {x.email ? x.email : x?.signerPtr?.Email || "-"} diff --git a/apps/OpenSignServer/cloud/parsefunction/ZohoDetails.js b/apps/OpenSignServer/cloud/parsefunction/ZohoDetails.js index f8ec7fb17..e926877ab 100644 --- a/apps/OpenSignServer/cloud/parsefunction/ZohoDetails.js +++ b/apps/OpenSignServer/cloud/parsefunction/ZohoDetails.js @@ -26,12 +26,15 @@ export default async function ZohoDetails(request) { // console.log("Access Token:", res.data); if (res.data.access_token) { const hostedpages = request.params.hostedpagesId; - const userData = await axios.get('https://billing.zoho.in/api/v1/hostedpages/' + hostedpages, { - headers: { - Authorization: 'Zoho-oauthtoken ' + res.data.access_token, - 'X-com-zoho-subscriptions-organizationid': process.env.ZOHO_BILLING_ORG_ID, - }, - }); + const userData = await axios.get( + 'https://www.zohoapis.in/billing/v1/hostedpages/' + hostedpages, + { + headers: { + Authorization: 'Zoho-oauthtoken ' + res.data.access_token, + 'X-com-zoho-subscriptions-organizationid': process.env.ZOHO_BILLING_ORG_ID, + }, + } + ); const first_name = userData.data.data.subscription.contactpersons[0].first_name || ''; const last_name = userData.data.data.subscription.contactpersons[0].last_name || '';