From 4e8988bf5742e22c848706a2954d048e9854a162 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Tue, 19 Dec 2023 18:58:28 +0530 Subject: [PATCH] add template feature --- apps/OpenSign/src/primitives/TemplateForm.js | 27 +- .../src/Component/TemplatePlaceholder.js | 185 +++- .../src/Component/component/AddUser.js | 293 ++++++ .../src/Component/component/SelectSigners.js | 85 ++ .../src/Component/component/renderPdf.js | 131 ++- .../Component/component/signerListPlace.js | 44 +- .../src/Component/placeHolderSign.js | 854 +++++++++++------- .../SignDocuments/src/css/AddUser.css | 72 ++ .../SignDocuments/src/css/signature.css | 32 + .../SignDocuments/src/utils/Utils.js | 31 +- 10 files changed, 1330 insertions(+), 424 deletions(-) create mode 100644 microfrontends/SignDocuments/src/Component/component/AddUser.js create mode 100644 microfrontends/SignDocuments/src/Component/component/SelectSigners.js create mode 100644 microfrontends/SignDocuments/src/css/AddUser.css diff --git a/apps/OpenSign/src/primitives/TemplateForm.js b/apps/OpenSign/src/primitives/TemplateForm.js index fe433af24..d478f670b 100644 --- a/apps/OpenSign/src/primitives/TemplateForm.js +++ b/apps/OpenSign/src/primitives/TemplateForm.js @@ -4,7 +4,7 @@ import Parse from "parse"; import DropboxChooser from "../components/fields/DropboxChoose"; import Alert from "./Alert"; import SelectFolder from "../components/fields/SelectFolder"; -import SignersInput from "../components/fields/SignersInput"; +// import SignersInput from "../components/fields/SignersInput"; import Title from "../components/Title"; import { useNavigate } from "react-router-dom"; import { templateCls } from '../constant/const' @@ -14,7 +14,7 @@ const TemplateForm = () => { const [signers, setSigners] = useState([]); const [folder, setFolder] = useState({ ObjectId: "", Name: "" }); const [formData, setFormData] = useState({ - Name: "", + Name: "Please review and sign this document", Description: "", Note: "" }); @@ -179,16 +179,16 @@ const TemplateForm = () => { const handleFolder = (data) => { setFolder(data); }; - const handleSigners = (data) => { - if (data && data.length > 0) { - const updateSigners = data.map((x) => ({ - __type: "Pointer", - className: "contracts_Contactbook", - objectId: x - })); - setSigners(updateSigners); - } - }; + // const handleSigners = (data) => { + // if (data && data.length > 0) { + // const updateSigners = data.map((x) => ({ + // __type: "Pointer", + // className: "contracts_Contactbook", + // objectId: x + // })); + // setSigners(updateSigners); + // } + // }; const handleReset = () => { setSigners([]); @@ -281,6 +281,7 @@ const TemplateForm = () => { className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" value={formData.Note} onChange={(e) => handleStrInput(e)} + required />
@@ -292,7 +293,7 @@ const TemplateForm = () => { onChange={(e) => handleStrInput(e)} />
- + {/* */}
+
+
+ + + Add/choose user + closePopup()} + > + X + + + + {isAddUser && isAddUser[uniqueId] && ( + <> + + + + )} + + +
+
); }; diff --git a/microfrontends/SignDocuments/src/Component/component/AddUser.js b/microfrontends/SignDocuments/src/Component/component/AddUser.js new file mode 100644 index 000000000..b4c76395b --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/component/AddUser.js @@ -0,0 +1,293 @@ +import React, { useState, useEffect } from "react"; +import Parse from "parse"; +import axios from "axios"; +import "../../css/AddUser.css"; +const AddUser = (props) => { + const [name, setName] = useState(""); + const [phone, setPhone] = useState(""); + const [email, setEmail] = useState(""); + const [addYourself, setAddYourself] = useState(false); + const [isLoader, setIsLoader] = useState(false); + const [isUserExist, setIsUserExist] = useState(false); + const parseBaseUrl = localStorage.getItem("baseUrl"); + const parseAppId = localStorage.getItem("parseAppId"); + Parse.serverURL = parseBaseUrl; + Parse.initialize(parseAppId); + + useEffect(() => { + checkUserExist(); + }, []); + // Load user details from localStorage when the component mounts + useEffect(() => { + const savedUserDetails = JSON.parse( + localStorage.getItem("UserInformation") + ); + if (savedUserDetails && addYourself) { + setName(savedUserDetails.name); + setPhone(savedUserDetails.phone); + setEmail(savedUserDetails.email); + } + }, [addYourself]); + + const checkUserExist = async () => { + const user = Parse.User.current(); + try { + const query = new Parse.Query("contracts_Contactbook"); + query.equalTo("CreatedBy", user); + query.notEqualTo("IsDeleted", true); + query.equalTo("Email", user.getEmail()); + const res = await query.first(); + // console.log(res); + if (!res) { + setIsUserExist(true); + } + } catch (err) { + console.log("err", err); + } + }; + // Define a function to handle form submission + const handleSubmit = async (e) => { + e.preventDefault(); + e.stopPropagation(); + setIsLoader(true); + Parse.serverURL = parseBaseUrl; + Parse.initialize(parseAppId); + try { + const contactQuery = new Parse.Object("contracts_Contactbook"); + contactQuery.set("Name", name); + contactQuery.set("Phone", phone); + contactQuery.set("Email", email); + contactQuery.set("UserRole", "contracts_Guest"); + + if (localStorage.getItem("TenetId")) { + contactQuery.set("TenantId", { + __type: "Pointer", + className: "partners_Tenant", + objectId: localStorage.getItem("TenetId") + }); + } + + try { + const _users = Parse.Object.extend("User"); + const _user = new _users(); + _user.set("name", name); + _user.set("username", email); + _user.set("email", email); + _user.set("phone", phone); + _user.set("password", phone); + + const user = await _user.save(); + if (user) { + const roleurl = `${parseBaseUrl}functions/AddUserToRole`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessionToken: localStorage.getItem("accesstoken") + }; + const body = { + appName: localStorage.getItem("_appName"), + roleName: "contracts_Guest", + userId: user.id + }; + await axios.post(roleurl, body, { headers: headers }); + const currentUser = Parse.User.current(); + contactQuery.set( + "CreatedBy", + Parse.User.createWithoutData(currentUser.id) + ); + + contactQuery.set("UserId", user); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + acl.setPublicWriteAccess(true); + acl.setReadAccess(currentUser.id, true); + acl.setWriteAccess(currentUser.id, true); + + contactQuery.setACL(acl); + + const res = await contactQuery.save(); + + const parseData = JSON.parse(JSON.stringify(res)); + props.details(parseData); + if (props.closePopup) { + props.closePopup(); + } + + setIsLoader(false); + // Reset the form fields + setAddYourself(false); + setName(""); + setPhone(""); + setEmail(""); + } + } catch (err) { + console.log("err ", err); + if (err.code === 202) { + const params = { email: email }; + const userRes = await Parse.Cloud.run("getUserId", params); + const roleurl = `${parseBaseUrl}functions/AddUserToRole`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessionToken: localStorage.getItem("accesstoken") + }; + const body = { + appName: localStorage.getItem("_appName"), + roleName: "contracts_Guest", + userId: userRes.id + }; + await axios.post(roleurl, body, { headers: headers }); + const currentUser = Parse.User.current(); + contactQuery.set( + "CreatedBy", + Parse.User.createWithoutData(currentUser.id) + ); + + contactQuery.set("UserId", { + __type: "Pointer", + className: "_User", + objectId: userRes.id + }); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + acl.setPublicWriteAccess(true); + acl.setReadAccess(currentUser.id, true); + acl.setWriteAccess(currentUser.id, true); + + contactQuery.setACL(acl); + const res = await contactQuery.save(); + + const parseData = JSON.parse(JSON.stringify(res)); + props.details({ + value: parseData[props.valueKey], + label: parseData[props.displayKey] + }); + if (props.closePopup) { + props.closePopup(); + } + setIsLoader(false); + // Reset the form fields + setAddYourself(false); + setName(""); + setPhone(""); + setEmail(""); + } + } + } catch (err) { + // console.log("err", err); + setIsLoader(false); + alert("something went wrong!"); + } + }; + + // Define a function to handle the "add yourself" checkbox + const handleAddYourselfChange = () => { + if (addYourself) { + setAddYourself(false); + setName(""); + setPhone(""); + setEmail(""); + } else { + setAddYourself(true); + } + }; + const handleReset = () => { + setAddYourself(false); + }; + + return ( +
+ {isLoader && ( +
+
+
+ )} +
+
Add User
+ + {isUserExist && ( +
+ + +
+ )} +
+
+ + setName(e.target.value)} + required + disabled={addYourself} + className="addUserInput" + /> +
+
+ + setEmail(e.target.value)} + required + disabled={addYourself} + className="addUserInput" + /> +
+
+ + setPhone(e.target.value)} + required + disabled={addYourself} + className="addUserInput" + /> +
+ +
+ + +
+
+
+
+ ); +}; + +export default AddUser; diff --git a/microfrontends/SignDocuments/src/Component/component/SelectSigners.js b/microfrontends/SignDocuments/src/Component/component/SelectSigners.js new file mode 100644 index 000000000..88c83d8d0 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/component/SelectSigners.js @@ -0,0 +1,85 @@ +import React, { useState, useEffect } from "react"; +import Parse from "parse"; +import "../../css/AddUser.css"; + +const SelectSigners = (props) => { + const [userList, setUserList] = useState([]); + const [selected, setSelected] = useState(); + const [userData, setUserData] = useState({}); + const parseBaseUrl = localStorage.getItem("baseUrl"); + const parseAppId = localStorage.getItem("parseAppId"); + Parse.serverURL = parseBaseUrl; + Parse.initialize(parseAppId); + + const GetUserList = async () => { + try { + const currentUser = Parse.User.current(); + const contactbook = new Parse.Query("contracts_Contactbook"); + contactbook.equalTo( + "CreatedBy", + Parse.User.createWithoutData(currentUser.id) + ); + contactbook.notEqualTo("IsDeleted", true); + const contactRes = await contactbook.find(); + if (contactRes) { + const res = JSON.parse(JSON.stringify(contactRes)); + + console.log("userList ", res) + setUserList(res); + } + } catch (error) { + console.log("err", error); + } + }; + + useEffect(() => { + GetUserList(); + }, []); + + // `handleOptions` is used to set just save from quick form to selected option in dropdown + + const handleOptions = (e) => { + setSelected(e.target.value); + const userData = userList.filter((x) => x.objectId === e.target.value); + if(userData.length > 0){ + setUserData(userData[0]); + } + }; + const handleAdd = () => { + if (props.closePopup) { + props.closePopup(); + } + console.log("userData ", userData) + props.details(userData); + }; + return ( +
+
+
+ + +
+ +
+ +
+
+
+ ); +}; + +export default SelectSigners; diff --git a/microfrontends/SignDocuments/src/Component/component/renderPdf.js b/microfrontends/SignDocuments/src/Component/component/renderPdf.js index 7a68b0362..6c13b259d 100644 --- a/microfrontends/SignDocuments/src/Component/component/renderPdf.js +++ b/microfrontends/SignDocuments/src/Component/component/renderPdf.js @@ -1,4 +1,3 @@ - import React from "react"; import RSC from "react-scrollbars-custom"; import { Rnd } from "react-rnd"; @@ -49,7 +48,9 @@ function RenderPdf({ index, containerWH, setIsResize, - setZIndex + setZIndex, + handleLinkUser, + setUniqueId }) { const isMobile = window.innerWidth < 767; const newWidth = containerWH.width; @@ -472,20 +473,22 @@ function RenderPdf({ ? pos.Width / pos.Height : 2.5 } - onDragStop={(event, dragElement) => - handleStop( - event, - dragElement, - data.Id, - pos.key - ) + onDragStop={ + (event, dragElement) => + handleStop( + event, + dragElement, + data.Id, + pos.key + ) // data.signerObjId, } default={{ x: xPos(pos), y: !pos.isMobile ? pos.yPosition / scale - : pos.yPosition * (pos.scale / scale) + : pos.yPosition * + (pos.scale / scale) }} // default={{ // x: pos.xPosition, @@ -932,11 +935,13 @@ function RenderPdf({ bounds="parent" style={{ cursor: "all-scroll", - background: data.blockColor, + // background: data.blockColor, borderColor: themeColor(), - zIndex: pos.zIndex ? pos.zIndex : "1" + zIndex: pos.zIndex + ? pos.zIndex + : "1" }} - className="placeholderBlock" + className="signWidgetblock" onDrag={() => handleTabDrag(pos.key)} size={{ width: pos.Width ? pos.Width : 150, @@ -947,14 +952,15 @@ function RenderPdf({ ? pos.Width / pos.Height : 2.5 } - onDragStop={(event, dragElement) => - handleStop( - event, - dragElement, - data.Id, - pos.key - ) - // data.signerObjId, + onDragStop={ + (event, dragElement) => + handleStop( + event, + dragElement, + data.Id, + pos.key + ) + // data.signerObjId, } default={{ x: pos.xPosition, @@ -989,33 +995,70 @@ function RenderPdf({ >
{ - e.stopPropagation(); - handleDeleteSign( - pos.key, - data.Id - ); - // data.signerObjId - }} style={{ - background: themeColor() + borderColor: themeColor(), + background: data.blockColor, + width: pos.Width + ? pos.Width - 20 + : 130, + height: pos.Height + ? pos.Height - 8 + : 52, + border: "1px solid red", + overflow: "hidden" }} - className="placeholdCloseBtn" > - x -
-
{ + e.stopPropagation(); + handleLinkUser(data.Id) + setUniqueId(data.Id) + }} + style={{ + color: "#188ae2", + right: 45 - marginTop: "0px" - }} - > - {pos.isStamp - ? "stamp" - : "signature"} + }} + > + { + // e.stopPropagation(); + // setIsPageCopy(true); + // setSignKey(pos.key); + // }} + style={{ + color: "#188ae2" + }} + > + { + e.stopPropagation(); + handleDeleteSign( + pos.key, + data.Id + ); + // data.signerObjId + }} + style={{ + color: "#188ae2" + }} + > + +
+ {pos.isStamp + ? "stamp" + : "signature"} +
); diff --git a/microfrontends/SignDocuments/src/Component/component/signerListPlace.js b/microfrontends/SignDocuments/src/Component/component/signerListPlace.js index 4905da542..d4c3e523e 100644 --- a/microfrontends/SignDocuments/src/Component/component/signerListPlace.js +++ b/microfrontends/SignDocuments/src/Component/component/signerListPlace.js @@ -12,7 +12,9 @@ function SignerListPlace({ setContractName, handleAddSigner, setUniqueId, - setRoleName + setRoleName, + handleDeleteUser, + handleRoleChange }) { const color = [ "#93a3db", @@ -45,7 +47,6 @@ function SignerListPlace({ ]; const [isHover, setIsHover] = useState(); - console.log("signerPos", signerPos); //function for onhover signer name change background color const onHoverStyle = (ind) => { const style = { @@ -108,7 +109,7 @@ function SignerListPlace({ setIsSelectId(ind); setContractName(obj?.className); setUniqueId(obj.Id); - setRoleName(obj.Role) + setRoleName(obj.Role); }} >
{obj.Name} ) : ( - {obj.Role} + <> + {handleRoleChange ? ( + handleRoleChange(e, obj.Id)} + > + {obj.Role} + + ) : ( + {obj.Role} + )} + )} {obj.Email && ( {obj.Email} )}
+ {handleDeleteUser && ( +
{ + e.stopPropagation(); + handleDeleteUser(obj.Id); + }} + style={{ cursor: "pointer" }} + > + +
+ )} {signerPos.map((data, key) => { return ( data.Id === obj.Id && ( @@ -182,12 +206,12 @@ function SignerListPlace({ })} - {handleAddSigner && ( -
handleAddSigner()}> - - Add -
- )} + {handleAddSigner && ( +
handleAddSigner()}> + + Add +
+ )} ); } diff --git a/microfrontends/SignDocuments/src/Component/placeHolderSign.js b/microfrontends/SignDocuments/src/Component/placeHolderSign.js index a0d532b12..a341e3879 100644 --- a/microfrontends/SignDocuments/src/Component/placeHolderSign.js +++ b/microfrontends/SignDocuments/src/Component/placeHolderSign.js @@ -22,11 +22,14 @@ import { contractDocument, contractUsers, getHostUrl, - addZIndex + addZIndex, + randomId } from "../utils/Utils"; import RenderPdf from "./component/renderPdf"; import ModalComponent from "./component/modalComponent"; import { useNavigate } from "react-router-dom"; +import AddUser from "./component/AddUser"; +import SelectSigners from "./component/SelectSigners"; function PlaceHolderSign() { const navigate = useNavigate(); @@ -72,6 +75,9 @@ function PlaceHolderSign() { status: false, type: "load" }); + const [uniqueId, setUniqueId] = useState(""); + const [roleName, setRoleName] = useState(""); + const [isAddUser, setIsAddUser] = useState({}); const color = [ "#93a3db", "#e6c3db", @@ -184,28 +190,96 @@ function PlaceHolderSign() { //getting document details const documentData = await contractDocument(documentId); if (documentData && documentData.length > 0) { - const alreadyPlaceholder = - documentData[0].Placeholders && documentData[0].Placeholders; + // const alreadyPlaceholder = + // documentData[0].Placeholders && documentData[0].Placeholders; // if (alreadyPlaceholder && alreadyPlaceholder.length > 0) { // setIsAlreadyPlace(true); // } setPdfDetails(documentData); - const currEmail = documentData[0].ExtUserPtr.Email; - const filterCurrEmail = documentData[0].Signers.filter( - (data) => data.Email === currEmail - ); - setCurrentEmail(filterCurrEmail); - setSignersData(documentData[0]); + // setSignersData(documentData[0]); - setSignerObjId(documentData[0].Signers[0].objectId); - setContractName(documentData[0].Signers[0].className); - setIsSelectId(0); - if (documentData[0].Placeholders && documentData[0].Placeholders.length > 0){ - setSignerPos(documentData[0].Placeholders) - } - if (documentData[0].Signers && documentData[0].Signers.length > 0){ - setSignersData(documentData[0].Signers) + // setSignerObjId(documentData[0].Signers[0].objectId); + // setContractName(documentData[0].Signers[0].className); + // setIsSelectId(0); + + if (documentData[0].Signers && documentData[0].Signers.length > 0) { + const currEmail = documentData[0].ExtUserPtr.Email; + const filterCurrEmail = documentData[0].Signers.filter( + (data) => data.Email === currEmail + ); + setCurrentEmail(filterCurrEmail); + // const updateSigners = documentData[0].Signers.map((x, index) => ({ + // ...x, + // Id: randomId(), + // Role: "User " + (index + 1) + // })); + const updateSigners = documentData[0].Signers; + // console.log("documentData[0] ", documentData[0]); + // console.log("updateSigners ", updateSigners); + // setSignersData(updateSigners); + + setUniqueId(updateSigners[0].Id); + setSignerObjId(documentData[0].Signers[0].objectId); + setContractName(documentData[0].Signers[0].className); + setIsSelectId(0); + if ( + documentData[0].Placeholders && + documentData[0].Placeholders.length > 0 + ) { + setSignerPos(documentData[0].Placeholders); + + let updateArr = [...updateSigners]; + console.log("updateArr ", updateArr); + let arr = documentData[0].Placeholders.map((x) => { + let matchingSigner = updateArr.find( + (y) => x.signerObjId && x.signerObjId === y.objectId + ); + + if (matchingSigner) { + return { + ...matchingSigner, + Role: x.Role ? x.Role : matchingSigner.Role, + Id: x.Id + }; + } else { + return { + Role: x.Role, + Id: x.Id + }; + } + }); + setSignersData(arr); + } else { + const updateSigners = documentData[0].Signers.map((x, index) => ({ + ...x, + Id: randomId(), + Role: "User " + (index + 1) + })); + setSignersData(updateSigners); + } + } else { + setRoleName("User 1"); + if ( + documentData[0].Placeholders && + documentData[0].Placeholders.length > 0 + ) { + const arr = documentData[0].Placeholders?.filter( + (x) => !x.signerObjId + ); + // console.log("arr ", arr); + let updateArr = []; + arr.forEach((x) => { + const obj = { + Role: x.Role, + Id: x.Id + }; + updateArr.push(obj); + }); + setSignerPos(documentData[0].Placeholders); + setSignersData(updateArr); + setIsSelectId(0); + } } } else if ( documentData === "Error: Something went wrong!" || @@ -276,9 +350,11 @@ function PlaceHolderSign() { const newWidth = containerWH.width; const scale = pdfOriginalWidth / newWidth; const key = Math.floor(1000 + Math.random() * 9000); - let filterSignerPos = signerPos.filter( - (data) => data.signerObjId === signerObjId - ); + // let filterSignerPos = signerPos.filter( + // (data) => data.signerObjId === signerObjId + // ); + let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId); + let dropData = []; let xyPosArr = []; let xyPos = {}; @@ -336,9 +412,11 @@ function PlaceHolderSign() { //add signers objId first inseretion if (filterSignerPos.length > 0) { - const colorIndex = signerPos - .map((e) => e.signerObjId) - .indexOf(signerObjId); + // const colorIndex = signerPos + // .map((e) => e.signerObjId) + // .indexOf(signerObjId); + + const colorIndex = signerPos.map((e) => e.Id).indexOf(uniqueId); const getPlaceHolder = filterSignerPos[0].placeHolder; const updatePlace = getPlaceHolder.filter( @@ -357,16 +435,30 @@ function PlaceHolderSign() { pos: newSignPos }; updatePlace.push(xyPos); - let placeHolderPos = { - blockColor: color[isSelectListId], - signerObjId: signerObjId, - placeHolder: updatePlace, - signerPtr: { - __type: "Pointer", - className: `${contractName}`, - objectId: signerObjId - } - }; + let placeHolderPos; + if (contractName) { + placeHolderPos = { + blockColor: color[isSelectListId], + signerObjId: signerObjId, + placeHolder: updatePlace, + signerPtr: { + __type: "Pointer", + className: `${contractName}`, + objectId: signerObjId + }, + Role: roleName, + Id: uniqueId + }; + } else { + placeHolderPos = { + blockColor: color[isSelectListId], + signerObjId: "", + placeHolder: updatePlace, + signerPtr: {}, + Role: roleName, + Id: uniqueId + }; + } // signerPos.splice(colorIndex, 1, placeHolderPos); const newArry = [placeHolderPos]; const newArray = [ @@ -374,21 +466,33 @@ function PlaceHolderSign() { ...newArry, ...signerPos.slice(colorIndex + 1) ]; - setSignerPos(newArray); } else { const newSignPoss = getPlaceHolder.concat(xyPosArr[0]); - - let placeHolderPos = { - blockColor: color[isSelectListId], - signerObjId: signerObjId, - placeHolder: newSignPoss, - signerPtr: { - __type: "Pointer", - className: `${contractName}`, - objectId: signerObjId - } - }; + let placeHolderPos; + if (contractName) { + placeHolderPos = { + blockColor: color[isSelectListId], + signerObjId: signerObjId, + placeHolder: newSignPoss, + signerPtr: { + __type: "Pointer", + className: `${contractName}`, + objectId: signerObjId + }, + Role: roleName, + Id: uniqueId + }; + } else { + placeHolderPos = { + blockColor: color[isSelectListId], + signerObjId: "", + placeHolder: newSignPoss, + signerPtr: {}, + Role: roleName, + Id: uniqueId + }; + } // signerPos.splice(colorIndex, 1, placeHolderPos); const newArry = [placeHolderPos]; @@ -401,19 +505,34 @@ function PlaceHolderSign() { setSignerPos(newArray); } } else { - let placeHolderPos = { - signerPtr: { - __type: "Pointer", - className: `${contractName}`, - objectId: signerObjId - }, - signerObjId: signerObjId, - blockColor: color[isSelectListId], - placeHolder: xyPosArr - }; + let placeHolderPos; + if (contractName) { + placeHolderPos = { + signerPtr: { + __type: "Pointer", + className: `${contractName}`, + objectId: signerObjId + }, + signerObjId: signerObjId, + blockColor: color[isSelectListId], + placeHolder: xyPosArr, + Role: roleName, + Id: uniqueId + }; + } else { + placeHolderPos = { + signerPtr: {}, + signerObjId: "", + blockColor: color[isSelectListId], + placeHolder: xyPosArr, + Role: roleName, + Id: uniqueId + }; + } setSignerPos((prev) => [...prev, placeHolderPos]); } + setIsMailSend(false); }; //function for get pdf page details @@ -438,17 +557,19 @@ function PlaceHolderSign() { const handleStop = (event, dragElement, signerId, key) => { if (!isResize) { const dataNewPlace = addZIndex(signerPos, key, setZIndex); - signerPos.splice(0, signerPos.length, ...dataNewPlace); + let updateSignPos = [...signerPos]; + updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace); + // signerPos.splice(0, signerPos.length, ...dataNewPlace); const containerRect = document .getElementById("container") .getBoundingClientRect(); - const signId = signerId ? signerId : signerObjId; + const signId = signerId ? signerId : uniqueId; //? signerId : signerObjId; const keyValue = key ? key : dragKey; const ybottom = containerRect.height - dragElement.y; if (keyValue >= 0) { - const filterSignerPos = signerPos.filter( - (data) => data.signerObjId === signId + const filterSignerPos = updateSignPos.filter( + (data) => data.Id === signId ); if (filterSignerPos.length > 0) { @@ -481,8 +602,8 @@ function PlaceHolderSign() { } return obj; }); - const newUpdateSigner = signerPos.map((obj, ind) => { - if (obj.signerObjId === signId) { + const newUpdateSigner = updateSignPos.map((obj, ind) => { + if (obj.Id === signId) { return { ...obj, placeHolder: newUpdateSignPos }; } return obj; @@ -496,11 +617,13 @@ function PlaceHolderSign() { }; //function for delete signature block - const handleDeleteSign = (key, signerId) => { + const handleDeleteSign = (key, Id) => { const updateData = []; - const filterSignerPos = signerPos.filter( - (data) => data.signerObjId === signerId - ); + // const filterSignerPos = signerPos.filter( + // (data) => data.signerObjId === signerId + // ); + + const filterSignerPos = signerPos.filter((data) => data.Id === Id); if (filterSignerPos.length > 0) { const getPlaceHolder = filterSignerPos[0].placeHolder; @@ -524,7 +647,7 @@ function PlaceHolderSign() { }); const newUpdateSigner = signerPos.map((obj, ind) => { - if (obj.signerObjId === signerId) { + if (obj.Id === Id) { return { ...obj, placeHolder: newUpdatePos }; } return obj; @@ -532,24 +655,20 @@ function PlaceHolderSign() { setSignerPos(newUpdateSigner); } else { - const updateFilter = signerPos.filter( - (data) => data.signerObjId !== signerId - ); + const updateFilter = signerPos.filter((data) => data.Id !== Id); const getRemainPage = filterSignerPos[0].placeHolder.filter( (data) => data.pageNumber !== pageNumber ); if (getRemainPage && getRemainPage.length > 0) { const newUpdatePos = filterSignerPos.map((obj, ind) => { - if (obj.signerObjId === signerId) { + if (obj.Id === Id) { return { ...obj, placeHolder: getRemainPage }; } return obj; }); let signerupdate = []; - signerupdate = signerPos.filter( - (data) => data.signerObjId !== signerId - ); + signerupdate = signerPos.filter((data) => data.Id !== Id); signerupdate.push(newUpdatePos[0]); setSignerPos(signerupdate); @@ -587,7 +706,7 @@ function PlaceHolderSign() { }; const alertSendEmail = async () => { - if (signerPos.length === signersdata.Signers.length) { + if (signerPos.length === signersdata.length) { const alert = { mssg: "confirm", alert: true @@ -611,15 +730,16 @@ function PlaceHolderSign() { setIsSendAlert({}); let sendMail; - const expireDate = signersdata.ExpiryDate.iso; + // console.log("pdfDetails", pdfDetails); + const expireDate = pdfDetails?.[0].ExpiryDate.iso; const newDate = new Date(expireDate); const localExpireDate = newDate.toLocaleDateString("en-US", { day: "numeric", month: "long", year: "numeric" }); - let sender = signersdata.ExtUserPtr.Email; - const signerMail = signersdata.Signers; + let sender = pdfDetails?.[0].ExtUserPtr.Email; + const signerMail = signersdata; for (let i = 0; i < signerMail.length; i++) { try { @@ -639,12 +759,12 @@ function PlaceHolderSign() { )}&${localStorage.getItem("_appName")}`; const hostUrl = window.location.origin + "/loadmf/signmicroapp"; - let signPdf = `${hostUrl}/login/${signersdata.objectId}/${signerMail[i].Email}/${objectId}/${serverParams}`; + let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}/${serverParams}`; const openSignUrl = "https://www.opensignlabs.com/"; const themeBGcolor = themeColor(); let params = { recipient: signerMail[i].Email, - subject: `${signersdata.ExtUserPtr.Name} has requested you to sign ${signersdata.Name}`, + subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, from: sender, html: @@ -653,9 +773,9 @@ function PlaceHolderSign() { " height='50' style='padding: 20px,width:170px,height:40px' />

Digital Signature Request

" + - signersdata.ExtUserPtr.Name + + pdfDetails?.[0].ExtUserPtr.Name + " has requested you to review and sign " + - signersdata.Name + + pdfDetails?.[0].Name + "

Sender " + sender + "
Organization Name __
Expire on " + @@ -675,10 +795,19 @@ function PlaceHolderSign() { } if (sendMail.data.result.status === "success") { + const signers = signersdata?.map((x) => { + return { + __type: "Pointer", + className: "contracts_Contactbook", + objectId: x.objectId + }; + }); + // console.log("signers ", signers); try { const data = { Placeholders: signerPos, - SignedUrl: pdfDetails[0].URL + SignedUrl: pdfDetails[0].URL, + Signers: signers }; await axios @@ -789,125 +918,194 @@ function PlaceHolderSign() { `${hostUrl}recipientSignPdf/${documentId}/${currentEmail[0].objectId}` ); }; + + const handleLinkUser = (id) => { + setIsAddUser({ [id]: true }); + }; + const handleAddUser = (data) => { + // console.log("hello", data); + const signerPtr = { + __type: "Pointer", + className: "contracts_Contactbook", + objectId: data.objectId + }; + const updatePlaceHolder = signerPos.map((x) => { + if (x.Id === uniqueId) { + return { ...x, signerPtr: signerPtr, signerObjId: data.objectId }; + } + return { ...x }; + }); + // console.log("updatePlaceHolder ", updatePlaceHolder); + setSignerPos(updatePlaceHolder); + + const updateSigner = signersdata.map((x) => { + if (x.Id === uniqueId) { + return { ...x, ...data }; + } + return { ...x }; + }); + // console.log("updateSigner ", updateSigner); + + setSignersData(updateSigner); + }; + + const closePopup = () => { + setIsAddUser({}); + }; + + // console.log("isAddUser", isAddUser); + // console.log("signerdata", signersdata); + // console.log("signerPos", signerPos); + return ( - - {isLoading.isLoad ? ( - - ) : handleError ? ( - - ) : noData ? ( - - ) : ( -
- {/* this component used for UI interaction and show their functionality */} - {!checkTourStatus && ( - //this tour component used in your html component where you want to put - //onRequestClose function to close tour - //steps is defined what will be your messages and style also - //isOpen is takes boolean value to open - + + {isLoading.isLoad ? ( + + ) : handleError ? ( + + ) : noData ? ( + + ) : ( +
+ {/* this component used for UI interaction and show their functionality */} + {!checkTourStatus && ( + //this tour component used in your html component where you want to put + //onRequestClose function to close tour + //steps is defined what will be your messages and style also + //isOpen is takes boolean value to open + + )} + {/* this component used to render all pdf pages in left side */} + - )} - {/* 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 alert set placeholder for all signers before send mail */} + {/* pdf render view */} +
500 && "20px", + marginRight: !isMobile && pdfOriginalWidth > 500 && "20px" + }} + > + {/* this modal is used show alert set placeholder for all signers before send mail */} - - - {isSendAlert.mssg === "sure" ? ( - Fields required - ) : ( - isSendAlert.mssg === "confirm" && ( - Send Mail - ) - )} - - - {/* signature modal */} - - {isSendAlert.mssg === "sure" ? ( -

Please Add field for all recipients.

- ) : ( - isSendAlert.mssg === "confirm" && ( -

- Are you sure you want to send out this document for - signatures? -

- ) - )} -
- - - - {isSendAlert.mssg === "confirm" && ( + {isSendAlert.mssg === "sure" ? ( + Fields required + ) : ( + isSendAlert.mssg === "confirm" && ( + Send Mail + ) + )} + + + {/* signature modal */} + + {isSendAlert.mssg === "sure" ? ( +

Please Add field for all recipients.

+ ) : ( + isSendAlert.mssg === "confirm" && ( +

+ Are you sure you want to send out this document for + signatures? +

+ ) + )} +
+ + - )} - -
- {/* this modal is used show send mail message and after send mail success message */} - - - Mails Sent - + {isSendAlert.mssg === "confirm" && ( + + )} + + + {/* this modal is used show send mail message and after send mail success message */} + + + Mails Sent + - {/* signature modal */} - -

You have successfully sent mails to all recipients!

- {currentEmail.length > 0 && ( -

Do you want to sign documents right now ?

- )} -
+ {/* signature modal */} + +

You have successfully sent mails to all recipients!

+ {currentEmail?.length > 0 && ( +

Do you want to sign documents right now ?

+ )} +
- - {currentEmail.length > 0 ? ( - <> + + {currentEmail?.length > 0 ? ( + <> + + + + + ) : ( - - - - ) : ( - - )} - -
- {/* */} - - {/* pdf header which contain funish back button */} -
-
- {containerWH && ( - - )} -
-
- - {/* signature button */} - {isMobile ? ( -
- + + {/* */} + + {/* pdf header which contain funish back button */} +
+
+ {containerWH && ( + + )} +
- ) : ( -
-
- + -
- + ) : ( +
+
+ +
+ +
-
- )} -
- )} - + )} +
+ )} + +
+ + + Add/choose user + closePopup()} + > + X + + + + {isAddUser && isAddUser[uniqueId] && ( + <> + + + + )} + + +
+ ); } diff --git a/microfrontends/SignDocuments/src/css/AddUser.css b/microfrontends/SignDocuments/src/css/AddUser.css new file mode 100644 index 000000000..712df7668 --- /dev/null +++ b/microfrontends/SignDocuments/src/css/AddUser.css @@ -0,0 +1,72 @@ +.addusercontainer { + height: 100%; + padding: 20px; +} + +.loaderdiv { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.3); + +} + +.form-wrapper { + width: 100%; + margin-left: auto; + margin-right: auto; + padding: 8px; +} + +.form-section { + margin-bottom: 0.75rem; +} + +.checkbox-label { + margin-left: 0.5rem; + color: #4b5563; +} + +.addUserInput { + padding: 0.5rem 0.75rem; + width: 100%; + border-width: 1px; + border-color: #d1d5db; + border-radius: 0.375rem; + outline: none; + font-size: 0.75rem; +} + + +.buttoncontainer { + margin-top: 1rem; + display: flex; + justify-content: flex-start; +} + +.submitbutton { + background-color: #1ab6ce; + font-size: 0.875rem; + color: white; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.2); + outline: none; +} + +/* For classes: bg-[#188ae2] text-sm text-white px-4 py-2 rounded ml-2 shadow focus:outline-none */ +.resetbutton { + background-color: #188ae2; + font-size: 0.875rem; + color: white; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.2); + margin-left: 0.5rem; + outline: none; +} \ No newline at end of file diff --git a/microfrontends/SignDocuments/src/css/signature.css b/microfrontends/SignDocuments/src/css/signature.css index b4aed0610..7fc117746 100644 --- a/microfrontends/SignDocuments/src/css/signature.css +++ b/microfrontends/SignDocuments/src/css/signature.css @@ -174,6 +174,28 @@ padding: 0px 5.1px 1px 5px; } +.signCloseBtn{ + position: absolute; + right: -1px; + top: -9px; + border-radius: 100%; + font-size: 14px; + cursor: pointer; + padding: 0px 5.1px 1px 5px; + z-index: 2; +} + +.signCopy { + position: absolute; + right: 24px; + top: -9px; + font-size: 13px; + cursor: pointer; + z-index: 2; + +} + + .placeholderBlock { padding: 0px; position: absolute; @@ -185,6 +207,16 @@ justify-content: center; border-width: 0.2px; +} +.signWidgetblock { + padding: 0px; + border-style: dashed; + display: flex !important; + text-align: center !important; + justify-content: center !important; + align-items: center !important; + border-width: 0.2px; + } .finishBtn { diff --git a/microfrontends/SignDocuments/src/utils/Utils.js b/microfrontends/SignDocuments/src/utils/Utils.js index 5deab7dee..1dbd6047a 100644 --- a/microfrontends/SignDocuments/src/utils/Utils.js +++ b/microfrontends/SignDocuments/src/utils/Utils.js @@ -1004,19 +1004,26 @@ export const signPdfFun = async ( export const randomId = () => Math.floor(1000 + Math.random() * 9000); -export const createDocument = async (template) => { +export const createDocument = async (template, placeholders, signerData) => { if (template && template.length > 0) { const Doc = template[0]; - let signers; - console.log("Doc.Placholders ", Doc) - if (Doc.Signers && Doc.Signers.length > 0) { - signers = Doc.Signers.map((x) => ({ - __type: "Pointer", - className: "contracts_Contactbook", - objectId: x.objectId - })); - } else { - signers = []; + + let placeholdersArr = [] + if(placeholders?.length > 0 ){ + placeholdersArr= placeholders + } + let signers = [] + if(signerData?.length > 0){ + signerData.forEach((x) => { + if(x.objectId){ + const obj = { + __type: "Pointer", + className: "contracts_Contactbook", + objectId: x.objectId + }; + signers.push(obj) + } + }); } const data = { Name: Doc.Name, @@ -1024,7 +1031,7 @@ export const createDocument = async (template) => { SignedUrl: Doc.SignedUrl, Description: Doc.Description, Note: Doc.Note, - Placeholders: Doc.Placeholders, + Placeholders: placeholdersArr, ExtUserPtr: { __type: "Pointer", className: "contracts_Users",