diff --git a/apps/OpenSign/package-lock.json b/apps/OpenSign/package-lock.json
index c9de1b9a3..311171281 100644
--- a/apps/OpenSign/package-lock.json
+++ b/apps/OpenSign/package-lock.json
@@ -34,6 +34,7 @@
"react-konva": "^18.2.10",
"react-modal": "^3.16.1",
"react-pdf": "^7.7.1",
+ "react-quill": "^2.0.0",
"react-redux": "^9.1.0",
"react-rnd": "^10.4.1",
"react-router-dom": "^6.22.3",
@@ -6209,6 +6210,14 @@
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz",
"integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg=="
},
+ "node_modules/@types/quill": {
+ "version": "1.3.10",
+ "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
+ "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
+ "dependencies": {
+ "parchment": "^1.1.2"
+ }
+ },
"node_modules/@types/range-parser": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz",
@@ -9432,6 +9441,25 @@
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
"integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
},
+ "node_modules/deep-equal": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
+ "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
+ "dependencies": {
+ "is-arguments": "^1.1.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.5.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -10990,6 +11018,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
"node_modules/external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -12616,6 +12649,21 @@
"node": ">= 10"
}
},
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-array-buffer": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
@@ -16845,6 +16893,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object-is": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -17198,6 +17261,11 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/parchment": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
+ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -19138,6 +19206,50 @@
}
]
},
+ "node_modules/quill": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
+ "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+ "dependencies": {
+ "clone": "^2.1.1",
+ "deep-equal": "^1.0.1",
+ "eventemitter3": "^2.0.3",
+ "extend": "^3.0.2",
+ "parchment": "^1.1.4",
+ "quill-delta": "^3.6.2"
+ }
+ },
+ "node_modules/quill-delta": {
+ "version": "3.6.3",
+ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
+ "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+ "dependencies": {
+ "deep-equal": "^1.0.1",
+ "extend": "^3.0.2",
+ "fast-diff": "1.1.2"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/quill-delta/node_modules/fast-diff": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
+ "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+ },
+ "node_modules/quill/node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/quill/node_modules/eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+ },
"node_modules/radix-ui": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.0.1.tgz",
@@ -19749,6 +19861,20 @@
}
}
},
+ "node_modules/react-quill": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
+ "integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
+ "dependencies": {
+ "@types/quill": "^1.3.10",
+ "lodash": "^4.17.4",
+ "quill": "^1.3.7"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
"node_modules/react-reconciler": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
diff --git a/apps/OpenSign/package.json b/apps/OpenSign/package.json
index a90a5ea44..801361767 100644
--- a/apps/OpenSign/package.json
+++ b/apps/OpenSign/package.json
@@ -29,6 +29,7 @@
"react-konva": "^18.2.10",
"react-modal": "^3.16.1",
"react-pdf": "^7.7.1",
+ "react-quill": "^2.0.0",
"react-redux": "^9.1.0",
"react-rnd": "^10.4.1",
"react-router-dom": "^6.22.3",
diff --git a/apps/OpenSign/src/components/Header.js b/apps/OpenSign/src/components/Header.js
index eb8416b6d..94737f8a7 100644
--- a/apps/OpenSign/src/components/Header.js
+++ b/apps/OpenSign/src/components/Header.js
@@ -28,13 +28,15 @@ const Header = ({ showSidebar }) => {
}, []);
async function checkSubscription() {
if (isEnableSubscription) {
- const applogo = await getAppLogo();
- if (applogo) {
- setAppLogo(applogo);
- } else {
- setAppLogo(localStorage.getItem("appLogo") || "");
- }
const getIsSubscribe = await checkIsSubscribed();
+ if (getIsSubscribe) {
+ const applogo = await getAppLogo();
+ if (applogo) {
+ setAppLogo(applogo);
+ } else {
+ setAppLogo(localStorage.getItem("appLogo") || "");
+ }
+ }
setIsPro(getIsSubscribe);
setIsSubscribe(getIsSubscribe);
}
diff --git a/apps/OpenSign/src/components/pdf/EditorToolbar.js b/apps/OpenSign/src/components/pdf/EditorToolbar.js
new file mode 100644
index 000000000..0dd3f90d7
--- /dev/null
+++ b/apps/OpenSign/src/components/pdf/EditorToolbar.js
@@ -0,0 +1,157 @@
+import React from "react";
+import { Quill } from "react-quill";
+
+// Custom Undo button icon component for Quill editor. You can import it directly
+// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
+// handle them correctly
+const CustomUndo = () => (
+
+
+
+
+);
+
+// Redo button icon component for Quill editor
+const CustomRedo = () => (
+
+
+
+
+);
+
+// Undo and redo functions for Custom Toolbar
+function undoChange() {
+ this.quill.history.undo();
+}
+function redoChange() {
+ this.quill.history.redo();
+}
+
+// Add sizes to whitelist and register them
+const Size = Quill.import("formats/size");
+Size.whitelist = ["extra-small", "small", "medium", "large"];
+Quill.register(Size, true);
+
+// Add fonts to whitelist and register them
+const Font = Quill.import("formats/font");
+Font.whitelist = [
+ "arial",
+ "comic-sans",
+ "courier-new",
+ "georgia",
+ "helvetica",
+ "lucida"
+];
+Quill.register(Font, true);
+
+// Modules object for setting up the Quill editor
+export const module1 = {
+ toolbar: {
+ container: "#toolbar1",
+ handlers: {
+ undo: undoChange,
+ redo: redoChange
+ }
+ },
+ history: {
+ delay: 500,
+ maxStack: 100,
+ userOnly: true
+ }
+};
+// Formats objects for setting up the Quill editor
+export const formats = [
+ "header",
+ "font",
+ "size",
+ "bold",
+ "italic",
+ "underline",
+ "align",
+ "strike",
+ "script",
+ "blockquote",
+ "background",
+ "list",
+ "bullet",
+ "indent",
+ "link",
+ "image",
+ "color",
+ "code-block"
+];
+// Quill Toolbar component
+export const QuillToolbar = ({ containerId }) => (
+
+
+
+ Arial
+ Comic Sans
+ Courier New
+ Georgia
+ Helvetica
+ Lucida
+
+
+ Size 1
+ Size 2
+ Size 3
+ Size 4
+
+
+ Heading
+ Subheading
+ Normal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export default QuillToolbar;
diff --git a/apps/OpenSign/src/components/pdf/EmailBody.js b/apps/OpenSign/src/components/pdf/EmailBody.js
new file mode 100644
index 000000000..629213c3f
--- /dev/null
+++ b/apps/OpenSign/src/components/pdf/EmailBody.js
@@ -0,0 +1,52 @@
+import React from "react";
+import Tooltip from "../../primitives/Tooltip";
+
+import ReactQuill from "react-quill";
+import "react-quill/dist/quill.snow.css";
+import EditorToolbar, { module1, formats } from "./EditorToolbar";
+
+export function EmailBody(props) {
+ return (
+
+
+
+ );
+}
diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js
index 089c66149..5c220092f 100644
--- a/apps/OpenSign/src/constant/Utils.js
+++ b/apps/OpenSign/src/constant/Utils.js
@@ -1,6 +1,6 @@
import axios from "axios";
import moment from "moment";
-import { themeColor } from "./const";
+import { isEnableSubscription, themeColor } from "./const";
import React from "react";
import { rgb } from "pdf-lib";
import Parse from "parse";
@@ -501,14 +501,32 @@ export const signPdfFun = async (
base64Url,
documentId,
signerObjectId,
- setIsAlert
+ setIsAlert,
+ objectId,
+ isSubscribed
) => {
- let singleSign;
+ let singleSign,
+ isCustomCompletionMail = false;
+
+ //get tenant details
+ const tenantDetails = await getTenantDetails(objectId);
+ if (tenantDetails && tenantDetails === "user does not exist!") {
+ alert("User does not exist");
+ } else {
+ if (
+ tenantDetails?.CompletionBody &&
+ tenantDetails?.CompletionSubject &&
+ (!isEnableSubscription || isSubscribed)
+ ) {
+ isCustomCompletionMail = true;
+ }
+ }
singleSign = {
pdfFile: base64Url,
docId: documentId,
- userId: signerObjectId
+ userId: signerObjectId,
+ isCustomCompletionMail: isCustomCompletionMail
};
const response = await axios
@@ -1211,8 +1229,8 @@ export const multiSignEmbed = async (
position.type === radioButtonWidget
? 10
: position.type === "checkbox"
- ? 10
- : newUpdateHeight;
+ ? 10
+ : newUpdateHeight;
const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight;
if (signyourself) {
@@ -1804,3 +1822,21 @@ export const getAppLogo = async () => {
return null;
}
};
+
+export const getTenantDetails = async (objectId) => {
+ try {
+ const tenantCreditsQuery = new Parse.Query("partners_Tenant");
+ tenantCreditsQuery.equalTo("UserId", {
+ __type: "Pointer",
+ className: "_User",
+ objectId: objectId
+ });
+ const res = await tenantCreditsQuery.first();
+ if (res) {
+ const updateRes = JSON.parse(JSON.stringify(res));
+ return updateRes;
+ }
+ } catch (e) {
+ return "user does not exist!";
+ }
+};
diff --git a/apps/OpenSign/src/pages/GuestLogin.js b/apps/OpenSign/src/pages/GuestLogin.js
index cce8cb208..6e0bdd831 100644
--- a/apps/OpenSign/src/pages/GuestLogin.js
+++ b/apps/OpenSign/src/pages/GuestLogin.js
@@ -3,8 +3,8 @@ import { useNavigate, useParams } from "react-router-dom";
import "../styles/loginPage.css";
import loader from "../assets/images/loader2.gif";
import axios from "axios";
-import { themeColor } from "../constant/const";
-import { contractUsers } from "../constant/Utils";
+import { isEnableSubscription, themeColor } from "../constant/const";
+import { contractUsers, getAppLogo } from "../constant/Utils";
function GuestLogin() {
const { id, userMail, contactBookId, serverUrl } = useParams();
@@ -14,14 +14,27 @@ function GuestLogin() {
const [EnterOTP, setEnterOtp] = useState(false);
const [loading, setLoading] = useState(false);
const [isLoading, setIsLoading] = useState(true);
+ const [appLogo, setAppLogo] = useState(
+ "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"
+ );
useEffect(() => {
handleServerUrl();
+
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//function generate serverUrl and parseAppId from url and save it in local storage
- const handleServerUrl = () => {
+ const handleServerUrl = async () => {
+ if (isEnableSubscription) {
+ const applogo = await getAppLogo();
+ if (applogo) {
+ setAppLogo(applogo);
+ } else {
+ setAppLogo(localStorage.getItem("appLogo") || "");
+ }
+ }
+
//split url in array from '&'
localStorage.clear();
const checkSplit = serverUrl.split("&");
@@ -164,11 +177,12 @@ function GuestLogin() {
}}
>
-
diff --git a/apps/OpenSign/src/pages/Login.js b/apps/OpenSign/src/pages/Login.js
index f4dad1810..8c9820061 100644
--- a/apps/OpenSign/src/pages/Login.js
+++ b/apps/OpenSign/src/pages/Login.js
@@ -58,11 +58,13 @@ function Login() {
}, []);
const saveLogo = async () => {
- const logo = await getAppLogo();
- if (logo) {
- setImage(logo);
- } else {
- setImage(appInfo?.applogo || undefined);
+ if (isEnableSubscription) {
+ const logo = await getAppLogo();
+ if (logo) {
+ setImage(logo);
+ } else {
+ setImage(appInfo?.applogo || undefined);
+ }
}
};
const handleChange = (event) => {
diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js
index 1334e999f..b27f62ca8 100644
--- a/apps/OpenSign/src/pages/PdfRequestFiles.js
+++ b/apps/OpenSign/src/pages/PdfRequestFiles.js
@@ -567,14 +567,17 @@ function PdfRequestFiles() {
flag,
containerWH
);
-
+ //get ExistUserPtr object id of user class to get tenantDetails
+ const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
//function for call to embed signature in pdf and get digital signature pdf
try {
const res = await signPdfFun(
pdfBytes,
documentId,
signerObjectId,
- setIsAlert
+ setIsAlert,
+ objectId,
+ isSubscribed
);
if (res && res.status === "success") {
setPdfUrl(res.data);
@@ -586,10 +589,12 @@ function PdfRequestFiles() {
const index = pdfDetails?.[0].Signers.findIndex(
(x) => x.Email === jsonSender.email
);
+ const requestBody = pdfDetails?.[0]?.RequestBody;
+ const requestSubject = pdfDetails?.[0]?.RequestSubject;
+
const newIndex = index + 1;
const user = pdfDetails?.[0].Signers[newIndex];
if (user) {
- // console.log("pdfDetails", pdfDetails);
const expireDate = pdfDetails?.[0].ExpiryDate.iso;
const newDate = new Date(expireDate);
const localExpireDate = newDate.toLocaleDateString("en-US", {
@@ -597,7 +602,10 @@ function PdfRequestFiles() {
month: "long",
year: "numeric"
});
- let sender = pdfDetails?.[0].ExtUserPtr.Email;
+ let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
+ let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
+ const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
+ let emailBodyWithValue, emailSubjectWithValue;
try {
const imgPng =
@@ -625,33 +633,81 @@ function PdfRequestFiles() {
? pdfDetails[0].ExtUserPtr.Company
: "";
const themeBGcolor = themeColor;
+ if (
+ requestBody &&
+ requestSubject &&
+ (!isEnableSubscription || isSubscribed)
+ ) {
+ const replacedRequestBody = requestBody.replace(
+ /"/g,
+ "'"
+ );
+ const htmlReqBody =
+ "
" +
+ replacedRequestBody +
+ " ";
+
+ emailBodyWithValue = htmlReqBody
+ .replace(/\{{sender_name}}/g, senderName)
+ .replace(/\{{document_title}}/g, pdfDetails?.[0].Name)
+ .replace(
+ /\{{signing_url}}/g,
+ `
Sign here `
+ )
+ .replace(/\{{sender_mail}}/g, senderEmail)
+ .replace(/\{{sender_phone}}/g, senderPhone)
+ .replace(/\{{expiry_date}}}/g, localExpireDate)
+ .replace(/\{{company_name}}/g, orgName)
+ .replace(/\{{receiver_name}}/g, user.Name)
+ .replace(/\{{receiver_email}}/g, user.Email)
+ .replace(/\{{receiver_phone}}/g, user.Phone);
+
+ emailSubjectWithValue = requestSubject
+ .replace(/\{{sender_name}}/g, senderName)
+ .replace(/\{{document_title}}/g, pdfDetails?.[0].Name)
+ .replace(
+ /\{{signing_url}}/g,
+ `
Sign here `
+ )
+ .replace(/\{{sender_mail}}/g, senderEmail)
+ .replace(/\{{sender_phone}}/g, senderPhone)
+ .replace(/\{{expiry_date}}}/g, localExpireDate)
+ .replace(/\{{company_name}}/g, orgName)
+ .replace(/\{{receiver_name}}/g, user.Name)
+ .replace(/\{{receiver_email}}/g, user.Email)
+ .replace(/\{{receiver_phone}}/g, user.Phone);
+ }
+
let params = {
extUserId: extUserId,
recipient: user.Email,
- subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`,
- from: sender,
- html:
- "
Digital Signature Request
" +
- pdfDetails?.[0].ExtUserPtr.Name +
- " has requested you to review and sign " +
- pdfDetails?.[0].Name +
- " .
Sender " +
- sender +
- " Organization " +
- orgName +
- " Expires on " +
- localExpireDate +
- "
This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
- sender +
- " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here .
"
+ subject: requestSubject
+ ? emailSubjectWithValue
+ : `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`,
+ from: senderEmail,
+ html: requestBody
+ ? emailBodyWithValue
+ : "
Digital Signature Request
" +
+ pdfDetails?.[0].ExtUserPtr.Name +
+ " has requested you to review and sign " +
+ pdfDetails?.[0].Name +
+ " .
Sender " +
+ senderEmail +
+ " Organization " +
+ orgName +
+ " Expires on " +
+ localExpireDate +
+ "
This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
+ senderEmail +
+ " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here .
"
};
await axios.post(url, params, {
headers: headers
@@ -689,6 +745,7 @@ function PdfRequestFiles() {
});
}
}
+
//function for update TourStatus
const closeTour = async () => {
setWidgetsTour(false);
@@ -1052,9 +1109,9 @@ function PdfRequestFiles() {
isDecline.currnt === "Sure"
? "Are you sure want to decline this document ?"
: isDecline.currnt === "YouDeclined"
- ? "You have declined this document!"
- : isDecline.currnt === "another" &&
- "You cannot sign this document as it has been declined by one or more recipient(s)."
+ ? "You have declined this document!"
+ : isDecline.currnt === "another" &&
+ "You cannot sign this document as it has been declined by one or more recipient(s)."
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js
index 2162b3202..a5345391c 100644
--- a/apps/OpenSign/src/pages/PlaceHolderSign.js
+++ b/apps/OpenSign/src/pages/PlaceHolderSign.js
@@ -28,7 +28,8 @@ import {
textInputWidget,
textWidget,
radioButtonWidget,
- color
+ color,
+ getTenantDetails
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import { useNavigate } from "react-router-dom";
@@ -40,8 +41,11 @@ import ModalUi from "../primitives/ModalUi";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import WidgetNameModal from "../components/pdf/WidgetNameModal";
import { SaveFileSize } from "../constant/saveFileSize";
+import { EmailBody } from "../components/pdf/EmailBody";
+import Upgrade from "../primitives/Upgrade";
function PlaceHolderSign() {
+ const editorRef = useRef();
const navigate = useNavigate();
const { state } = useLocation();
const [pdfDetails, setPdfDetails] = useState([]);
@@ -83,6 +87,8 @@ function PlaceHolderSign() {
const [signKey, setSignKey] = useState();
const [tempSignerId, setTempSignerId] = useState("");
const [blockColor, setBlockColor] = useState("");
+ const [defaultBody, setDefaultBody] = useState("");
+ const [defaultSubject, setDefaultSubject] = useState("");
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -106,11 +112,14 @@ function PlaceHolderSign() {
const [mailStatus, setMailStatus] = useState("");
const [isCurrUser, setIsCurrUser] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
+ const [requestSubject, setRequestSubject] = useState("");
+ const [requestBody, setRequestBody] = useState("");
const [isAlreadyPlace, setIsAlreadyPlace] = useState({
status: false,
message: ""
});
const [extUserId, setExtUserId] = useState("");
+ const [isCustomize, setIsCustomize] = useState(false);
const isMobile = window.innerWidth < 767;
const [, drop] = useDrop({
accept: "BOX",
@@ -170,6 +179,48 @@ function PlaceHolderSign() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
+ //function to fetch tenant Details
+ const fetchTenantDetails = async () => {
+ const user = JSON.parse(
+ localStorage.getItem(
+ `Parse/${localStorage.getItem("parseAppId")}/currentUser`
+ )
+ );
+
+ if (user) {
+ try {
+ const tenantDetails = await getTenantDetails(user?.objectId);
+ if (tenantDetails && tenantDetails === "user does not exist!") {
+ alert("User does not exist");
+ } else if (tenantDetails) {
+ const defaultRequestBody = `
Hi {{receiver_name}},
We hope this email finds you well. {{sender_name}} has requested you to review and sign {{document_title}}.
Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.
{{signing_url}}
If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.
Thanks
Team OpenSign™
`;
+ if (tenantDetails?.RequestBody) {
+ setRequestBody(tenantDetails?.RequestBody);
+ setRequestSubject(tenantDetails?.RequestSubject);
+
+ setDefaultBody(defaultRequestBody);
+ setDefaultSubject(
+ `{{senderName}} has requested you to sign {{documentName}}`
+ );
+ } else {
+ setRequestBody(defaultRequestBody);
+ setRequestSubject(
+ `{{senderName}} has requested you to sign {{documentName}}`
+ );
+ setDefaultBody(defaultRequestBody);
+ setDefaultSubject(
+ `{{senderName}} has requested you to sign {{documentName}}`
+ );
+ }
+ }
+ } catch (e) {
+ alert("User does not exist");
+ }
+ } else {
+ alert("User does not exist");
+ }
+ };
+
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
@@ -204,6 +255,7 @@ function PlaceHolderSign() {
}
//function for get document details
const getDocumentDetails = async () => {
+ fetchTenantDetails();
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
@@ -816,6 +868,7 @@ function PlaceHolderSign() {
};
const sendEmailToSigners = async () => {
+ let htmlReqBody;
setIsUiLoading(true);
const pdfUrl = await embedPrefilllData();
setIsSendAlert({});
@@ -827,12 +880,15 @@ function PlaceHolderSign() {
month: "long",
year: "numeric"
});
- let sender = pdfDetails?.[0].ExtUserPtr.Email;
+
+ let senderEmail = pdfDetails?.[0]?.ExtUserPtr?.Email;
+ let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
let signerMail = signersdata.slice();
if (pdfDetails?.[0]?.SendinOrder && pdfDetails?.[0]?.SendinOrder === true) {
signerMail.splice(1);
}
+
for (let i = 0; i < signerMail.length; i++) {
try {
const imgPng =
@@ -857,34 +913,78 @@ function PlaceHolderSign() {
? pdfDetails[0].ExtUserPtr.Company
: "";
const themeBGcolor = themeColor;
+ const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
+ const documentName = `${pdfDetails?.[0].Name}`;
+ let emailBodyWithValue, emailSubjectWithValue;
+ if (
+ requestBody &&
+ requestSubject &&
+ isCustomize &&
+ (isSubscribe || !isEnableSubscription)
+ ) {
+ const replacedRequestBody = requestBody.replace(/"/g, "'");
+ htmlReqBody =
+ "
" +
+ replacedRequestBody +
+ " ";
+
+ emailBodyWithValue = htmlReqBody
+ .replace(/\{{sender_name}}/g, senderName)
+ .replace(/\{{document_title}}/g, documentName)
+ .replace(/\{{signing_url}}/g, `
Sign here `)
+ .replace(/\{{sender_mail}}/g, senderEmail)
+ .replace(/\{{sender_phone}}/g, senderPhone)
+ .replace(/\{{expiry_date}}}/g, localExpireDate)
+ .replace(/\{{company_name}}/g, orgName)
+ .replace(/\{{receiver_name}}/g, signerMail[i].Name)
+ .replace(/\{{receiver_email}}/g, signerMail[i].Email)
+ .replace(/\{{receiver_phone}}/g, signerMail[i].Phone);
+
+ emailSubjectWithValue = requestSubject
+ .replace(/\{{sender_name}}/g, senderName)
+ .replace(/\{{document_title}}/g, documentName)
+ .replace(/\{{signing_url}}/g, `
Sign here `)
+ .replace(/\{{sender_mail}}/g, senderEmail)
+ .replace(/\{{sender_phone}}/g, senderPhone)
+ .replace(/\{{expiry_date}}}/g, localExpireDate)
+ .replace(/\{{company_name}}/g, orgName)
+ .replace(/\{{receiver_name}}/g, signerMail[i].Name)
+ .replace(/\{{receiver_email}}/g, signerMail[i].Email)
+ .replace(/\{{receiver_phone}}/g, signerMail[i].Phone);
+ }
+
let params = {
extUserId: extUserId,
recipient: signerMail[i].Email,
- subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`,
- from: sender,
- html:
- "
Digital Signature Request
" +
- pdfDetails?.[0].ExtUserPtr.Name +
- " has requested you to review and sign " +
- pdfDetails?.[0].Name +
- " .
Sender " +
- sender +
- " Organization " +
- orgName +
- " Expire on " +
- localExpireDate +
- "
This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
- sender +
- " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here .
"
+ subject: isCustomize
+ ? emailSubjectWithValue
+ : `${senderName} has requested you to sign ${documentName}`,
+ from: senderEmail,
+ html: isCustomize
+ ? emailBodyWithValue
+ : "
Digital Signature Request
" +
+ pdfDetails?.[0].ExtUserPtr.Name +
+ " has requested you to review and sign " +
+ pdfDetails?.[0].Name +
+ " .
Sender " +
+ senderEmail +
+ " Organization " +
+ orgName +
+ " Expire on " +
+ localExpireDate +
+ "
This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
+ senderEmail +
+ " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here .
"
};
+
sendMail = await axios.post(url, params, { headers: headers });
} catch (error) {
console.log("error", error);
@@ -923,21 +1023,45 @@ function PlaceHolderSign() {
try {
if (updateExpiryDate) {
- data = {
- Placeholders: filterPrefill,
- SignedUrl: pdfUrl,
- Signers: signers,
- ExpiryDate: {
- iso: updateExpiryDate,
- __type: "Date"
- }
- };
+ if (isCustomize) {
+ data = {
+ RequestBody: htmlReqBody,
+ RequestSubject: requestSubject,
+ Placeholders: filterPrefill,
+ SignedUrl: pdfUrl,
+ Signers: signers,
+ ExpiryDate: {
+ iso: updateExpiryDate,
+ __type: "Date"
+ }
+ };
+ } else {
+ data = {
+ Placeholders: filterPrefill,
+ SignedUrl: pdfUrl,
+ Signers: signers,
+ ExpiryDate: {
+ iso: updateExpiryDate,
+ __type: "Date"
+ }
+ };
+ }
} else {
- data = {
- Placeholders: filterPrefill,
- SignedUrl: pdfUrl,
- Signers: signers
- };
+ if (isCustomize) {
+ data = {
+ RequestBody: htmlReqBody,
+ RequestSubject: requestSubject,
+ Placeholders: filterPrefill,
+ SignedUrl: pdfUrl,
+ Signers: signers
+ };
+ } else {
+ data = {
+ Placeholders: filterPrefill,
+ SignedUrl: pdfUrl,
+ Signers: signers
+ };
+ }
}
await axios
@@ -1394,6 +1518,15 @@ function PlaceHolderSign() {
const closePopup = () => {
setIsAddUser({});
};
+
+ //function for handle ontext change and save again text in delta in Request Email flow
+ const handleOnchangeRequest = () => {
+ if (editorRef.current) {
+ const html = editorRef.current.editor.root.innerHTML;
+ setRequestBody(html);
+ }
+ };
+
return (
<>
@@ -1475,20 +1608,78 @@ function PlaceHolderSign() {
: isSendAlert.mssg === "confirm" && "Send Mail"
}
handleClose={() => setIsSendAlert({})}
+ showHeaderMessage={isSendAlert.mssg === "confirm"}
>
-
+
{isSendAlert.mssg === "sure" ? (
-
Please add field for all recipients.
+
Please add field for all recipients.
) : isSendAlert.mssg === textWidget ? (
Please confirm that you have filled the text field.
) : (
isSendAlert.mssg === "confirm" && (
-
- Are you sure you want to send out this document for
- signatures?
-
+ <>
+
+ Are you sure you want to send out this document for
+ signatures?
+
+
+ <>
+
{
+ isSubscribe ||
+ (!isEnableSubscription &&
+ setIsCustomize(!isCustomize));
+ }}
+ >
+
+ Cutomize Email
+
+
+ {!isSubscribe && isEnableSubscription && (
+
+ )}
+
+ >
+
+ {isCustomize &&
+ (!isEnableSubscription || isSubscribe) && (
+ <>
+
+
{
+ setRequestBody(defaultBody);
+ setRequestSubject(defaultSubject);
+ }}
+ >
+ Reset to default
+
+ >
+ )}
+ >
)
)}
+
- Yes
+ Send
)}
+
{
}, []);
const saveLogo = async () => {
- const logo = await getAppLogo();
- if (logo) {
- setImage(logo);
- } else {
- setImage(appInfo?.applogo || undefined);
+ if (isEnableSubscription) {
+ const logo = await getAppLogo();
+ if (logo) {
+ setImage(logo);
+ } else {
+ setImage(appInfo?.applogo || undefined);
+ }
}
};
diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js
index 3777a2467..3be0dc283 100644
--- a/apps/OpenSign/src/pages/SignyourselfPdf.js
+++ b/apps/OpenSign/src/pages/SignyourselfPdf.js
@@ -1,7 +1,7 @@
import React, { useState, useRef, useEffect } from "react";
import { PDFDocument } from "pdf-lib";
import "../styles/signature.css";
-import { themeColor } from "../constant/const";
+import { isEnableSubscription, themeColor } from "../constant/const";
import axios from "axios";
import Loader from "../primitives/LoaderWithMsg";
import loader from "../assets/images/loader2.gif";
@@ -26,7 +26,9 @@ import {
contactBook,
randomId,
getDate,
- textWidget
+ textWidget,
+ getTenantDetails,
+ checkIsSubscribed
} from "../constant/Utils";
import { useParams } from "react-router-dom";
import Tour from "reactour";
@@ -431,13 +433,13 @@ function SignYourSelf() {
Width: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: dragTypeValue === "initials"
- ? defaultWidthHeight(dragTypeValue).width
- : "",
+ ? defaultWidthHeight(dragTypeValue).width
+ : "",
Height: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
- ? defaultWidthHeight(dragTypeValue).height
- : "",
+ ? defaultWidthHeight(dragTypeValue).height
+ : "",
options: addWidgetOptions(dragTypeValue)
};
@@ -595,9 +597,25 @@ function SignYourSelf() {
// console.log("signyourself", xyPostion);
//function for get digital signature
const signPdfFun = async (base64Url, documentId) => {
+ let isCustomCompletionMail = false;
+ const getIsSubscribe = await checkIsSubscribed();
+ const tenantDetails = await getTenantDetails(jsonSender.objectId);
+ if (tenantDetails && tenantDetails === "user does not exist!") {
+ alert("User does not exist");
+ } else {
+ if (
+ tenantDetails?.CompletionBody &&
+ tenantDetails?.CompletionSubject &&
+ (!isEnableSubscription || getIsSubscribe)
+ ) {
+ isCustomCompletionMail = true;
+ }
+ }
+
let singleSign = {
pdfFile: base64Url,
- docId: documentId
+ docId: documentId,
+ isCustomCompletionMail: isCustomCompletionMail
};
await axios
diff --git a/apps/OpenSign/src/primitives/ModalUi.js b/apps/OpenSign/src/primitives/ModalUi.js
index 7a7ef9aca..01b59d94b 100644
--- a/apps/OpenSign/src/primitives/ModalUi.js
+++ b/apps/OpenSign/src/primitives/ModalUi.js
@@ -1,4 +1,6 @@
import React from "react";
+import { isEnableSubscription } from "../constant/const";
+import PremiumAlertHeader from "./PremiumAlertHeader";
const ModalUi = ({
children,
@@ -8,12 +10,13 @@ const ModalUi = ({
handleClose,
showHeader = true,
showClose = true,
- styleClass
+ styleClass,
+ showHeaderMessage
}) => {
return (
<>
{isOpen && (
-
+
)}
+ {!isEnableSubscription && showHeaderMessage && (
+
+ )}
{children}
diff --git a/apps/OpenSign/src/styles/signature.css b/apps/OpenSign/src/styles/signature.css
index 7c901ff81..a9e7ef8e4 100644
--- a/apps/OpenSign/src/styles/signature.css
+++ b/apps/OpenSign/src/styles/signature.css
@@ -968,6 +968,9 @@ option {
}
}
+.scroll-hide::-webkit-scrollbar {
+ display: none;
+}
@media screen and (max-width: 350px) and (min-width: 311px) {
.signatureCanvas {
width: 280px;