diff --git a/apps/OpenSign/public/version.txt b/apps/OpenSign/public/version.txt
index e69de29bb..3c61df3f2 100644
--- a/apps/OpenSign/public/version.txt
+++ b/apps/OpenSign/public/version.txt
@@ -0,0 +1 @@
+v1.1.1-beta
diff --git a/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js b/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js
index 2d6d391c0..b9585b119 100644
--- a/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js
+++ b/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js
@@ -20,7 +20,7 @@ import multer from 'multer';
// import fs from 'node:fs';
import updateDocument from './routes/updateDocument.js';
import deleteDocument from './routes/deleteDocument.js';
-// import createDocumentWithTemplate from './routes/CreateDocumentWithTemplate.js';
+import createDocumentWithTemplate from './routes/CreateDocumentWithTemplate.js';
dotenv.config();
const storage = multer.memoryStorage();
@@ -49,7 +49,8 @@ app.get('/contactlist', getContactList);
app.post('/createdocument', upload.array('file', 1), createDocument);
// create Document with templateId
-// app.post('/createdocument/:template_id', createDocumentWithTemplate);
+app.post('/createdocument/:template_id', createDocumentWithTemplate);
+
// get Document on the basis of id
app.get('/document/:document_id', getDocument);
diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js
new file mode 100644
index 000000000..3ae07bac3
--- /dev/null
+++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js
@@ -0,0 +1,98 @@
+const randomId = () => Math.floor(1000 + Math.random() * 9000);
+export default async function createDocumentWithTemplate(request, response) {
+ const signers = request.body.Signers;
+ const folderId = request.body.FolderId;
+ const templateId = request.params.template_id;
+ const url = process.env.SERVER_URL;
+ try {
+ const reqToken = request.headers['x-api-token'];
+ if (!reqToken) {
+ return response.status(400).json({ error: 'Please Provide API Token' });
+ }
+ const tokenQuery = new Parse.Query('appToken');
+ tokenQuery.equalTo('token', reqToken);
+ const token = await tokenQuery.first({ useMasterKey: true });
+ if (token !== undefined) {
+ // Valid Token then proceed request
+ const userPtr = token.get('userId');
+
+ const templateQyuery = new Parse.Query('contracts_Template');
+ const templateRes = await templateQyuery.get(templateId, { useMasterKey: true });
+ if (templateRes) {
+ const template = JSON.parse(JSON.stringify(templateRes));
+ if (template?.Placeholders?.length > 0) {
+ let isValid = template?.Placeholders?.length <= signers?.length;
+ let updateSigners = template?.Placeholders?.every(y =>
+ signers?.some(x => x.Role === y.Role)
+ );
+ if (isValid && updateSigners) {
+ const folderPtr = {
+ __type: 'Pointer',
+ className: 'contracts_Document',
+ objectId: folderId,
+ };
+ const template = JSON.parse(JSON.stringify(templateRes));
+ const object = new Parse.Object('contracts_Document');
+ object.set('Name', template.Name);
+ if (template?.Note) {
+ object.set('Note', template.Note);
+ }
+ if (template?.Description) {
+ object.set('Description', template.Description);
+ }
+ if (template?.Signers) {
+ object.set('Signers', template?.Signers);
+ }
+ object.set('URL', template.URL);
+ object.set('CreatedBy', template.CreatedBy);
+ object.set('ExtUserPtr', template.ExtUserPtr);
+ if (signers) {
+ const placeholders = template?.Placeholders?.map(placeholder => {
+ let matchingSigner = signers.find(y => y.Role === placeholder.Role);
+ if (matchingSigner) {
+ return {
+ ...placeholder,
+ email: matchingSigner.Email,
+ signerObjId: '',
+ signerPtr: {},
+ };
+ } else {
+ return {
+ ...placeholder,
+ };
+ }
+ });
+ console.log('placeholders ', placeholders);
+ object.set('Placeholders', placeholders);
+ }
+ if (folderId) {
+ object.set('Folder', folderPtr);
+ }
+ const newACL = new Parse.ACL();
+ newACL.setPublicReadAccess(false);
+ newACL.setPublicWriteAccess(false);
+ newACL.setReadAccess(userPtr.id, true);
+ newACL.setWriteAccess(userPtr.id, true);
+ object.setACL(newACL);
+ const res = await object.save(null, { useMasterKey: true });
+ return response.json({ objectId: res.id, url: url });
+ } else {
+ return response.status(400).json({ error: 'Please provide signers properly!' });
+ }
+ } else {
+ return response.status(400).json({ error: 'Please setup template properly!' });
+ }
+ } else {
+ return response.status(404).json({ error: 'Invalid template id!' });
+ }
+ } else {
+ return response.status(405).json({ error: 'Invalid API Token!' });
+ }
+ } catch (err) {
+ console.log('err ', err);
+ if (err.code === 101) {
+ return response.status(404).json({ error: 'Invalid template id!' });
+ }
+ return response.status(400).json({ error: 'Something went wrong!' });
+ }
+}
diff --git a/microfrontends/SignDocuments/src/Routes.js b/microfrontends/SignDocuments/src/Routes.js
index 1b1cba4d5..58039a599 100644
--- a/microfrontends/SignDocuments/src/Routes.js
+++ b/microfrontends/SignDocuments/src/Routes.js
@@ -10,6 +10,7 @@ import LegaDrive from "./Component/LegaDrive/LegaDrive";
import PageNotFound from "./Component/PageNotFound";
import TemplatePlaceHolder from "./Component/TemplatePlaceholder";
import Parse from "parse";
+import GuestLogin from "./premitives/GuestLogin";
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
// `AppRoutes` is used to define route path of app and
@@ -50,6 +51,8 @@ function AppRoutes() {
} />
{/* Page Not Found */}
} />
+ } />
+
} />
diff --git a/microfrontends/SignDocuments/src/premitives/GuestLogin.js b/microfrontends/SignDocuments/src/premitives/GuestLogin.js
new file mode 100644
index 000000000..4df8a9960
--- /dev/null
+++ b/microfrontends/SignDocuments/src/premitives/GuestLogin.js
@@ -0,0 +1,294 @@
+import React, { useState } from "react";
+import ModalUi from './ModalUi'
+import "../css/LoginPage.css";
+import loader from "../assests/loader2.gif";
+import axios from "axios";
+import { useParams } from "react-router-dom";
+import { themeColor } from "../utils/ThemeColor/backColor";
+import { useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import GuestSign from "./GuestSign";
+
+function GuestLogin({children, userdetails}) {
+ const { id, userMail, contactBookId, serverUrl } = useParams();
+ let navigate = useNavigate();
+ const [email, setEmail] = useState(userMail || "prafull.navkar@nxglabs.com");
+ const [OTP, setOTP] = useState("");
+ const [EnterOTP, setEnterOtp] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ handleServerUrl();
+ }, []);
+
+ //function generate serverUrl and parseAppId from url and save it in local storage
+ const handleServerUrl = () => {
+ //split url in array from '&'
+ localStorage.clear();
+ // const checkSplit = serverUrl?.split("&");
+ // const server = checkSplit?.[0];
+ // const parseId = checkSplit?.[1];
+ // const appName = checkSplit?.[2];
+
+ // const newServer = server.replaceAll("%2F", "/");
+ // localStorage.setItem("baseUrl", newServer);
+ // localStorage.setItem("parseAppId", parseId);
+ // localStorage.setItem("_appName", appName);
+
+ localStorage.setItem("baseUrl", "https://staging-app.opensignlabs.com/api/app/");
+ localStorage.setItem("parseAppId", "opensignstgn");
+ localStorage.setItem("_appName", "contracts");
+ setIsLoading(false);
+ };
+
+ const handleChange = (event) => {
+ const { value } = event.target;
+ setOTP(value);
+ };
+
+ //send email OTP function
+ const SendOtp = async (e) => {
+ const serverUrl =
+ localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl");
+ const parseId =
+ localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId");
+ if (serverUrl && localStorage) {
+ setLoading(true);
+ e.preventDefault();
+ setEmail(email);
+
+ try {
+ let url = `${serverUrl}functions/SendOTPMailV1/`;
+ const headers = {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": parseId
+ };
+ let body = {
+ email: email.toString()
+ };
+ let Otp = await axios.post(url, body, { headers: headers });
+
+ if (Otp) {
+ setLoading(false);
+ setEnterOtp(true);
+ }
+ } catch (error) {
+ alert("something went wrong!");
+ }
+ } else {
+ alert("something went wrong!");
+ }
+ };
+
+ //verify OTP send on via email
+ const VerifyOTP = async (e) => {
+ e.preventDefault();
+ const serverUrl =
+ localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl");
+ const parseId =
+ localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId");
+ if (OTP) {
+ setLoading(true);
+ try {
+ let url = `${serverUrl}functions/AuthLoginAsMail/`;
+ const headers = {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": parseId
+ };
+ let body = {
+ email: email,
+ otp: OTP
+ };
+ let user = await axios.post(url, body, { headers: headers });
+ if (user.data.result === "Invalid Otp") {
+ alert("Invalid Otp");
+ setLoading(false);
+ } else if (user.data.result === "user not found!") {
+ alert("User not found!");
+ setLoading(false);
+ } else {
+ let _user = user.data.result;
+ const parseId = localStorage.getItem("parseAppId");
+ localStorage.setItem("UserInformation", JSON.stringify(_user));
+ localStorage.setItem(
+ `Parse/${parseId}/currentUser`,
+ JSON.stringify(_user)
+ );
+ localStorage.setItem("username", _user.name);
+ localStorage.setItem("accesstoken", _user.sessionToken);
+ //save isGuestSigner true in local to handle login flow header in mobile view
+ localStorage.setItem("isGuestSigner", true);
+ setLoading(false);
+ // uKymQWaYL6
+ navigate(
+ `/loadmf/signmicroapp/recipientSignPdf/${id}/${contactBookId}`
+ );
+ }
+ } catch (error) {}
+ } else {
+ alert("Please Enter OTP!");
+ }
+ };
+
+ return (
+
+
+<>
+ {isLoading ? (
+
+

+
+ {isLoading.message}
+
+
+ ) : (
+
+
+
+

+
+
+
+ {!EnterOTP ? (
+
+
+
Welcome Back !
+
+
+ Verification code is sent to your email
+
+
+
+ {loading ? (
+
+ ) : (
+
+ )}
+
+
+
+ ) : (
+
+
+
Welcome Back !
+
+
You will get a OTP via Email
+
+
+
+
+
+
+
+
+
+ {loading ? (
+
+ ) : (
+
+ )}
+
+
+
+ )}
+
+ )}
+ >
+
+
+
+ );
+}
+
+export default GuestLogin;
diff --git a/microfrontends/SignDocuments/src/premitives/GuestSign.js b/microfrontends/SignDocuments/src/premitives/GuestSign.js
new file mode 100644
index 000000000..99bc0e11f
--- /dev/null
+++ b/microfrontends/SignDocuments/src/premitives/GuestSign.js
@@ -0,0 +1,1002 @@
+import React, { useState, useRef, useEffect } from "react";
+import { themeColor } from "../utils/ThemeColor/backColor";
+import { PDFDocument } from "pdf-lib";
+import "../css/signature.css";
+import axios from "axios";
+import loader from "../assests/loader2.gif";
+import { DndProvider } from "react-dnd";
+import { HTML5Backend } from "react-dnd-html5-backend";
+import { useParams } from "react-router-dom";
+import SignPad from "../Component/component/signPad";
+import RenderAllPdfPage from "../Component/component/renderAllPdfPage";
+import {
+ contractDocument,
+ multiSignEmbed,
+ embedDocId,
+ pdfNewWidthFun,
+ signPdfFun,
+ onImageSelect,
+ onSaveSign,
+ onSaveImage,
+ addDefaultSignatureImg
+} from "../utils/Utils";
+import Loader from "../Component/component/loader";
+import HandleError from "../Component/component/HandleError";
+import Nodata from "../Component/component/Nodata";
+import Header from "../Component/component/header";
+import RenderPdf from "../Component/component/renderPdf";
+import CustomModal from "../Component/component/CustomModal";
+import Title from "../Component/component/Title";
+import DefaultSignature from "../Component/component/defaultSignature";
+import ModalUi from "./ModalUi";
+
+function GuestSign() {
+ const { docId } = useParams();
+ const [pdfDetails, setPdfDetails] = useState([]);
+ const [signedSigners, setSignedSigners] = useState([]);
+ const [unsignedSigners, setUnSignedSigners] = useState([]);
+ const [isSignPad, setIsSignPad] = useState(false);
+ const [pdfUrl, setPdfUrl] = useState();
+ const [allPages, setAllPages] = useState(null);
+ const numPages = 1;
+ const [pageNumber, setPageNumber] = useState(1);
+ const [image, setImage] = useState(null);
+ const [isImageSelect, setIsImageSelect] = useState(false);
+ const [signature, setSignature] = useState();
+ const [isStamp, setIsStamp] = useState(false);
+ const [signKey, setSignKey] = useState();
+ const [imgWH, setImgWH] = useState({});
+ const imageRef = useRef(null);
+ const [handleError, setHandleError] = useState();
+ const [isLoading, setIsLoading] = useState({
+ isLoad: true,
+ message: "This might take some time"
+ });
+ const [defaultSignImg, setDefaultSignImg] = useState();
+ const [isDocId, setIsDocId] = useState(false);
+ const [pdfNewWidth, setPdfNewWidth] = useState();
+ const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
+ const [signerPos, setSignerPos] = useState([]);
+ const [noData, setNoData] = useState(false);
+ const [signerObjectId, setSignerObjectId] = useState();
+ const [isUiLoading, setIsUiLoading] = useState(false);
+ const [isDecline, setIsDecline] = useState({ isDeclined: false });
+ const [currentSigner, setCurrentSigner] = useState(false);
+ const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
+ const [defaultSignAlert, setDefaultSignAlert] = useState({
+ isShow: false,
+ alertMessage: ""
+ });
+ const [isCompleted, setIsCompleted] = useState({
+ isCertificate: false,
+ isModal: false
+ });
+ const [pdfLoadFail, setPdfLoadFail] = useState({
+ status: false,
+ type: "load"
+ });
+ const [isSigned, setIsSigned] = useState(false);
+ const [isExpired, setIsExpired] = useState(false);
+ const [alreadySign, setAlreadySign] = useState(false);
+ const [containerWH, setContainerWH] = useState({});
+ const divRef = useRef(null);
+ const isMobile = window.innerWidth < 767;
+ const rowLevel =
+ localStorage.getItem("rowlevel") &&
+ JSON.parse(localStorage.getItem("rowlevel"));
+
+ const objectId =
+ rowLevel && rowLevel.id
+ ? rowLevel.id
+ : rowLevel?.objectId && rowLevel.objectId;
+ const documentId = "uKymQWaYL6"//docId ? docId : objectId && objectId;
+
+ const senderUser =
+ localStorage.getItem(
+ `Parse/${localStorage.getItem("parseAppId")}/currentUser`
+ ) &&
+ localStorage.getItem(
+ `Parse/${localStorage.getItem("parseAppId")}/currentUser`
+ );
+ const jsonSender = JSON.parse(senderUser);
+
+ useEffect(() => {
+ if (documentId) {
+ getDocumentDetails();
+ }
+ }, []);
+ useEffect(() => {
+ if (divRef.current) {
+ const pdfWidth = pdfNewWidthFun(divRef);
+ setPdfNewWidth(pdfWidth);
+ setContainerWH({
+ width: divRef.current.offsetWidth,
+ height: divRef.current.offsetHeight
+ });
+ }
+ }, [divRef.current]);
+
+ //function for get document details for perticular signer with signer'object id
+ const getDocumentDetails = async () => {
+ //getting document details
+ const documentData = await contractDocument(documentId);
+ if (documentData && documentData.length > 0) {
+ const isCompleted =
+ documentData[0].IsCompleted && documentData[0].IsCompleted;
+ const expireDate = documentData[0].ExpiryDate.iso;
+ const declined = documentData[0].IsDeclined && documentData[0].IsDeclined;
+ const expireUpdateDate = new Date(expireDate).getTime();
+ const currDate = new Date().getTime();
+ const getSigners = documentData[0].Signers;
+ const getCurrentSigner =
+ getSigners &&
+ getSigners.filter(
+ (data) => data.UserId.objectId === jsonSender.objectId
+ );
+
+ const currUserId = getCurrentSigner[0]
+ ? getCurrentSigner[0].objectId
+ : "";
+ setSignerObjectId(currUserId);
+ if (documentData[0].SignedUrl) {
+ setPdfUrl(documentData[0].SignedUrl);
+ } else {
+ setPdfUrl(documentData[0].URL);
+ }
+ if (isCompleted) {
+ setIsSigned(true);
+ const data = {
+ isCertificate: true,
+ isModal: true
+ };
+ setAlreadySign(true);
+ setIsCompleted(data);
+ } else if (declined) {
+ const currentDecline = {
+ currnt: "another",
+ isDeclined: true
+ };
+ setIsDecline(currentDecline);
+ } else if (currDate > expireUpdateDate) {
+ setIsExpired(true);
+ }
+
+ if (documentData.length > 0) {
+ const checkDocIdExist =
+ documentData[0].AuditTrail &&
+ documentData[0].AuditTrail.length > 0 &&
+ documentData[0].AuditTrail.filter(
+ (data) => data.Activity === "Signed"
+ );
+
+ const checkAlreadySign =
+ documentData[0].AuditTrail &&
+ documentData[0].AuditTrail.length > 0 &&
+ documentData[0].AuditTrail.filter(
+ (data) =>
+ data.UserPtr.objectId === currUserId && data.Activity === "Signed"
+ );
+ if (
+ checkAlreadySign &&
+ checkAlreadySign[0] &&
+ checkAlreadySign.length > 0
+ ) {
+ setAlreadySign(true);
+ }
+
+ let signers = [];
+ let unSignedSigner = [];
+
+ //check document is signed or not
+ if (checkDocIdExist && checkDocIdExist.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;
+
+ 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
+
+ if (signerId === signedExist) {
+ signers.push({ ...signerRes[i], ...signerRes[i] });
+ isSignedSignature = true;
+ break;
+ }
+ // if does not match then add unsigned data in unSignedSigner array
+ }
+ if (!isSignedSignature) {
+ unSignedSigner.push({ ...signerRes[i], ...signerRes[i] });
+ }
+ }
+ setSignedSigners(signers);
+ setUnSignedSigners(unSignedSigner);
+
+ setSignerPos(documentData[0].Placeholders);
+ } else {
+ let unsigned = [];
+ for (let i = 0; i < documentData.length; i++) {
+ unsigned.push(documentData[i].Signers);
+ }
+ setUnSignedSigners(unsigned[0]);
+ setSignerPos(documentData[0].Placeholders);
+ }
+ setPdfDetails(documentData);
+ setIsUiLoading(false);
+ } else {
+ alert("No data found!");
+ }
+ } else if (
+ documentData === "Error: Something went wrong!" ||
+ (documentData.result && documentData.result.error)
+ ) {
+ const loadObj = {
+ isLoad: false
+ };
+ setHandleError("Error: Something went wrong!");
+ setIsLoading(loadObj);
+ } else {
+ setNoData(true);
+ const loadObj = {
+ isLoad: false
+ };
+ setIsLoading(loadObj);
+ setIsUiLoading(false);
+ }
+if(jsonSender?.objectId){ await axios
+ .get(
+ `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
+ "_appName"
+ )}_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
+ jsonSender?.objectId
+ }"}}`,
+ {
+ headers: {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
+ "X-Parse-Session-Token": localStorage.getItem("accesstoken")
+ }
+ }
+ )
+ .then((Listdata) => {
+ const json = Listdata.data;
+ const res = json.results;
+
+ if (res[0] && res.length > 0) {
+ setDefaultSignImg(res[0].ImageURL);
+ }
+ const loadObj = {
+ isLoad: false
+ };
+ setIsLoading(loadObj);
+ })
+ .catch((err) => {
+ const loadObj = {
+ isLoad: false
+ };
+ setHandleError("Error: Something went wrong!");
+ setIsLoading(loadObj);
+ });}
+ };
+
+ //function for embed signature or image url in pdf
+ async function embedImages() {
+ const checkUser = signerPos.filter(
+ (data) => data.signerObjId === signerObjectId
+ );
+ if (checkUser && checkUser.length > 0) {
+ let checkSignUrl = [];
+ const checkSign = checkUser[0].placeHolder.filter(
+ (data, ind) => data.pos
+ );
+ for (let i = 0; i < checkSign.length; i++) {
+ const posData = checkSign[i].pos.filter((pos) => !pos.SignUrl);
+ if (posData && posData.length > 0) {
+ checkSignUrl.push(posData);
+ }
+ }
+
+ if (checkSignUrl && checkSignUrl.length > 0) {
+ setIsAlert({
+ isShow: true,
+ alertMessage: "Please complete your signature!"
+ });
+ } else {
+ setIsUiLoading(true);
+ const pngUrl = checkUser[0].placeHolder;
+ // Load a PDFDocument from the existing PDF bytes
+ const existingPdfBytes = await fetch(pdfUrl).then((res) =>
+ res.arrayBuffer()
+ );
+ const pdfDoc = await PDFDocument.load(existingPdfBytes, {
+ ignoreEncryption: true
+ });
+ // let pdfBase64;
+ // //else if signature is more than one then embed all sign with the use of pdf-lib
+ // else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) {
+ const flag = false;
+ //embed document's object id to all pages in pdf document
+ if (!isDocId) {
+ await embedDocId(pdfDoc, documentId, allPages);
+ }
+ //embed multi signature in pdf
+ const pdfBytes = await multiSignEmbed(
+ pngUrl,
+ pdfDoc,
+ pdfOriginalWidth,
+ flag,
+ containerWH
+ );
+ //function for call to embed signature in pdf and get digital signature pdf
+ try {
+ const res = await signPdfFun(
+ pdfBytes,
+ documentId,
+ signerObjectId,
+ pdfOriginalWidth,
+ pngUrl,
+ containerWH,
+ setIsAlert
+ );
+ if (res && res.status === "success") {
+ setPdfUrl(res.data);
+ setIsSigned(true);
+ setSignedSigners([]);
+ setUnSignedSigners([]);
+ getDocumentDetails();
+ } else {
+ setIsAlert({
+ isShow: true,
+ alertMessage: "something went wrong"
+ });
+ }
+ } catch (err) {
+ setIsAlert({
+ isShow: true,
+ alertMessage: "something went wrong"
+ });
+ }
+ }
+
+ setIsSignPad(false);
+ // }
+ } else {
+ setIsAlert({
+ isShow: true,
+ alertMessage: "something went wrong"
+ });
+ }
+ }
+
+ //function for get pdf page details
+ const pageDetails = async (pdf) => {
+ const load = {
+ status: true
+ };
+ setPdfLoadFail(load);
+ pdf.getPage(1).then((pdfPage) => {
+ const pageWidth = pdfPage.view[2];
+
+ setPdfOriginalWidth(pageWidth);
+ });
+ };
+
+ //function for change page
+ function changePage(offset) {
+ setPageNumber((prevPageNumber) => prevPageNumber + offset);
+ }
+
+ const getFirstLetter = (name) => {
+ const firstLetter = name.charAt(0);
+ return firstLetter;
+ };
+ //function for image upload or update
+ const onImageChange = (event) => {
+ if (event.target.files && event.target.files[0]) {
+ onImageSelect(event, setImgWH, setImage);
+ }
+ };
+ //function for upload stamp image
+ const saveImage = () => {
+ //get current signers placeholder position data
+ const currentSigner = signerPos.filter(
+ (data) => data.signerObjId === signerObjectId
+ );
+ //get current pagenumber placeholder index
+ const getIndex = currentSigner[0].placeHolder.findIndex((object) => {
+ return object.pageNumber === pageNumber;
+ });
+ //get current signer placeholder position data
+ const placeholderPosition = currentSigner[0].placeHolder;
+ //function of save image and get updated position with image url
+ const getUpdatePosition = onSaveImage(
+ placeholderPosition,
+ getIndex,
+ signKey,
+ imgWH,
+ image
+ );
+
+ //replace updated placeholder position with old data
+ placeholderPosition.splice(
+ 0,
+ placeholderPosition.length,
+ ...getUpdatePosition
+ );
+ //get current signers placeholder position data index number in array
+ const indexofSigner = signerPos.findIndex((object) => {
+ return object.signerObjId === signerObjectId;
+ });
+ //update current signers data with new placeholder position array data
+ setSignerPos((prevState) => {
+ const newState = [...prevState]; // Create a copy of the state
+ newState.splice(indexofSigner, 1, ...currentSigner); // Modify the copy
+ return newState; // Update the state with the modified copy
+ });
+ };
+
+ //function for save button to save signature or image url
+ const saveSign = (isDefaultSign, width, height) => {
+ const isTypeText = width && height ? true : false;
+ const signatureImg = isDefaultSign ? defaultSignImg : signature;
+ let imgWH = { width: width ? width : "", height: height ? height : "" };
+ setIsSignPad(false);
+ setIsImageSelect(false);
+ setImage();
+
+ //get current signers placeholder position data
+ const currentSigner = signerPos.filter(
+ (data) => data.signerObjId === signerObjectId
+ );
+ //get current pagenumber placeholder index
+ const getIndex = currentSigner[0].placeHolder.findIndex((object) => {
+ return object.pageNumber === pageNumber;
+ });
+
+ //set default signature image width and height
+ if (isDefaultSign) {
+ const img = new Image();
+ img.src = defaultSignImg;
+ if (img.complete) {
+ imgWH = {
+ width: img.width,
+ height: img.height
+ };
+ }
+ }
+ //get current signer placeholder position data
+ const placeholderPosition = currentSigner[0].placeHolder;
+ //function of save signature image and get updated position with signature image url
+ const getUpdatePosition = onSaveSign(
+ placeholderPosition,
+ getIndex,
+ signKey,
+ signatureImg,
+ imgWH,
+ isDefaultSign,
+ isTypeText
+ );
+
+ const updateSignerData = currentSigner.map((obj, ind) => {
+ if (obj.signerObjId === signerObjectId) {
+ return { ...obj, placeHolder: getUpdatePosition };
+ }
+ return obj;
+ });
+
+ const index = signerPos.findIndex(
+ (data) => data.signerObjId === signerObjectId
+ );
+ setSignerPos((prevState) => {
+ const newState = [...prevState];
+ newState.splice(index, 1, ...updateSignerData);
+ return newState;
+ });
+ };
+
+ const checkSignerBackColor = (obj) => {
+ const data = signerPos.filter((data) => data.signerObjId === obj.objectId);
+ return data && data.length > 0 && data[0].blockColor;
+ };
+
+ //function for set decline true on press decline button
+ const declineDoc = async () => {
+ setIsDecline({ isDeclined: false });
+ const data = {
+ IsDeclined: true
+ };
+ setIsUiLoading(true);
+
+ await axios
+ .put(
+ `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
+ "_appName"
+ )}_Document/${documentId}`,
+ data,
+ {
+ headers: {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
+ "X-Parse-Session-Token": localStorage.getItem("accesstoken")
+ }
+ }
+ )
+ .then((result) => {
+ const res = result.data;
+ if (res) {
+ const currentDecline = {
+ currnt: "YouDeclined",
+ isDeclined: true
+ };
+ setIsDecline(currentDecline);
+ setIsUiLoading(false);
+ }
+ })
+ .catch((err) => {
+ console.log("error updating field is decline ", err);
+ });
+ };
+ //function to add default signature for all requested placeholder of sign
+ const addDefaultSignature = () => {
+ //get current signers placeholder position data
+ const currentSignerPosition = signerPos.filter(
+ (data) => data.signerObjId === signerObjectId
+ );
+ //function for save default signature url for all placeholder position
+ const updatePlace = addDefaultSignatureImg(
+ currentSignerPosition[0].placeHolder,
+ defaultSignImg
+ );
+
+ const updatesignerPos = signerPos.map((x) =>
+ x.signerObjId === signerObjectId ? { ...x, placeHolder: updatePlace } : x
+ );
+ setSignerPos(updatesignerPos);
+ setDefaultSignAlert({
+ isShow: false,
+ alertMessage: ""
+ });
+ };
+
+ return (
+
+
+ {isLoading.isLoad ? (
+
+ ) : handleError ? (
+
+ ) : noData ? (
+
+ ) : (
+
+ {isUiLoading && (
+
+

+
+ This might take some time
+
+
+ )}
+
+
+
{
+ setIsAlert({
+ isShow: false,
+ alertMessage: ""
+ });
+ }}
+ >
+
+
{isAlert.alertMessage}
+
+
+
+
+
+
+ {/* this modal is used to show decline alert */}
+
+ 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 person(s).
+
+ )
+ )
+ }
+ footerMessage={isDecline.currnt === "Sure"}
+ declineDoc={declineDoc}
+ setIsDecline={setIsDecline}
+ />
+ {/* this modal is used for show expired alert */}
+
+ {
+ setDefaultSignAlert({
+ isShow: false,
+ alertMessage: ""
+ });
+ }}
+ >
+
+
{defaultSignAlert.alertMessage}
+
+
+ {defaultSignImg ? (
+ <>
+
+
+ >
+ ) : (
+
+ )}
+
+
+ {/* this component used to render all pdf pages in left side */}
+
+
+ {/* pdf render view */}
+ 500 && "20px",
+ marginRight: !isMobile && pdfOriginalWidth > 500 && "20px"
+ }}
+ >
+ {/* this modal is used show this document is already sign */}
+
{
+ setIsCompleted({ isModal: false, isCertificate: true });
+ }}
+ >
+
+
This document has been signed by all Signers.
+
+
+
+
+
+
+ {/* this component is used for signature pad modal */}
+
+ {/* pdf header which contain funish back button */}
+
+ {containerWH && (
+
+ )}
+
+
+
+
+ {signedSigners.length > 0 && (
+ <>
+
+ Signed by
+
+
+ {signedSigners.map((obj, ind) => {
+ return (
+
+
+
+ {getFirstLetter(obj.Name)}
+
+
+
+ {obj.Name}
+ {obj.Email}
+
+
+ );
+ })}
+
+ >
+ )}
+
+ {unsignedSigners.length > 0 && (
+ <>
+
0 && "20px"
+ }}
+ >
+ Yet to sign
+
+
+ {unsignedSigners.map((obj, ind) => {
+ return (
+
+
+
+ {getFirstLetter(obj.Name)}
+
+
+
+ {obj.Name}
+ {obj.Email}
+
+
+
+ );
+ })}
+
+ >
+ )}
+ {defaultSignImg && !alreadySign && (
+
+ )}
+
+
+
+
+
+ )}
+
+ );
+}
+
+export default GuestSign;