Merge branch 'staging' into text-input

This commit is contained in:
Raktima
2024-01-03 12:44:55 +05:30
committed by GitHub
29 changed files with 1139 additions and 953 deletions
+19 -2
View File
@@ -15,6 +15,7 @@ import ForgetPassword from "./routes/ForgetPassword";
import ChangePassword from "./routes/ChangePassword";
import ReportMicroapp from "./components/ReportMicroapp";
import LoadMf from "./routes/LoadMf";
import ValidateRoute from "./primitives/ValidateRoute";
function App() {
const [isloading, setIsLoading] = useState(true);
@@ -58,8 +59,24 @@ function App() {
) : (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Login />} />
<Route exact path="/signup" element={<Signup />} />
<Route
exact
path="/"
element={
<ValidateRoute>
<Login />
</ValidateRoute>
}
/>
<Route
exact
path="/signup"
element={
<ValidateRoute>
<Signup />
</ValidateRoute>
}
/>
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
@@ -86,7 +86,7 @@ const LoginFacebook = ({
email: userDetails.Email,
// "passsword":userDetails.Phone,
phone: userDetails.Phone,
role: "contracts_Admin",
role: "contracts_User",
company: userDetails.Company
}
};
+1 -1
View File
@@ -148,7 +148,7 @@ const GoogleSignInBtn = ({
email: userDetails.Email,
// "passsword":userDetails.Phone,
phone: userDetails.Phone,
role: "contracts_Admin",
role: "contracts_User",
company: userDetails.Company,
jobTitle: userDetails.Destination
}
@@ -74,15 +74,15 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
const res = await template.save();
if (res) {
setAlert({
type: "success",
message: "Folder created successfully!"
});
setIsAlert(true);
setTimeout(() => {
setIsAlert(false);
}, 1000);
if (onSuccess) {
setAlert({
type: "success",
message: "Folder created successfully!"
});
setIsAlert(true);
setTimeout(() => {
setIsAlert(false);
}, 1000);
onSuccess(res);
}
}
@@ -135,6 +135,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
} else {
fetchFolder();
}
handleCreate();
};
return (
<div className="text-xs mt-2 ">
@@ -253,101 +254,6 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
</div>
</div>
</ModalUi>
{/* {isOpen && (
<div
className={`fixed z-40 top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm bg-white rounded `}
>
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem] bg-[#f5f5f5]">
<div className="font-semibold text-lg text-black">
Select Folder
</div>
<div
onClick={handleCancel}
className="px-2 py-1 border-[1px] border-[#8a8a8a] bg-white rounded cursor-pointer"
>
<i className="fa-solid fa-xmark"></i>
</div>
</div>
<hr />
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="Root"
onClick={(e) => removeTabListItem(e)}
>
Root /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
<React.Fragment key={`${tab.objectId}-${i}`}>
<span
className="cursor-pointer"
title={tab.Name}
onClick={(e) => removeTabListItem(e, i)}
>
{tab.Name}
</span>
{" / "}
</React.Fragment>
))}
<hr />
</div>
<div className="mt-2 mb-3">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer"
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
))}
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
folderCls={folderCls}
onSuccess={handleAddFolder}
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
</div>
<hr />
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="text-[30px] cursor-pointer text-[#33bbff]"
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
)}
</div>
<div
className="text-[30px] cursor-pointer"
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
</div>
</div>
</div>
)} */}
</div>
);
};
+73 -23
View File
@@ -7,10 +7,35 @@ import Tour from "reactour";
import axios from "axios";
import { useSelector } from "react-redux";
import Parse from "parse";
import ModalUi from "../primitives/ModalUi";
import { useNavigate } from "react-router-dom";
const HomeLayout = ({ children }) => {
const navigate = useNavigate();
const { width } = useWindowSize();
const [isOpen, setIsOpen] = useState(true);
const arr = useSelector((state) => state.TourSteps);
const [isUserValid, setIsUserValid] = useState(true);
useEffect(() => {
(async () => {
try {
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(Parse.User.current().id, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
setIsUserValid(true);
} else {
setIsUserValid(false);
}
} catch (error) {
// Session token is invalid or there was an error
setIsUserValid(false);
}
})();
}, []);
// reactour state
const [isCloseBtn, setIsCloseBtn] = useState(true);
@@ -19,7 +44,7 @@ const HomeLayout = ({ children }) => {
const [tourConfigs, setTourConfigs] = useState([]);
const showSidebar = () => {
setIsOpen(value => !value);
setIsOpen((value) => !value);
};
useEffect(() => {
if (width && width <= 768) {
@@ -28,9 +53,7 @@ const HomeLayout = ({ children }) => {
}, [width]);
useEffect(() => {
if (localStorage.getItem("domain") === "sign" && arr && arr.length > 0) {
handleDynamicSteps();
} else if (
if (
localStorage.getItem("domain") === "contracts" &&
arr &&
arr.length > 0
@@ -153,32 +176,59 @@ const HomeLayout = ({ children }) => {
setIsOpen(false);
}
};
const handleLoginBtn = () => {
try {
Parse.User.logOut();
} catch (err) {
console.log("err ", err);
} finally {
localStorage.removeItem("accesstoken");
navigate("/", { replace: true });
}
};
return (
<div>
<div className="sticky top-0 z-50">
<Header showSidebar={showSidebar} />
</div>
<div className="flex md:flex-row flex-col z-50">
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
{isUserValid ? (
<>
<div className="flex md:flex-row flex-col z-50">
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
<div className="bg-[#eef1f5] p-3">{children}</div>
<div className="z-30">
<Footer />
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
<div className="bg-[#eef1f5] p-3">{children}</div>
<div className="z-30">
<Footer />
</div>
</div>
</div>
</div>
</div>
<Tour
onRequestClose={closeTour}
steps={tourConfigs}
isOpen={isTour}
closeWithMask={false}
disableKeyboardNavigation={["esc"]}
// disableInteraction={true}
scrollOffset={-100}
rounded={5}
showCloseButton={isCloseBtn}
/>
<Tour
onRequestClose={closeTour}
steps={tourConfigs}
isOpen={isTour}
closeWithMask={false}
disableKeyboardNavigation={["esc"]}
// disableInteraction={true}
scrollOffset={-100}
rounded={5}
showCloseButton={isCloseBtn}
/>
</>
) : (
<ModalUi title={"Session Expired"} isOpen={true} showClose={false}>
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
<p className="text-xl font-normal">Your session has expired.</p>
<button
onClick={handleLoginBtn}
className="text-base px-3 py-1.5 rounded shadow-md text-white bg-[#1ab6ce]"
>
Login
</button>
</div>
</ModalUi>
)}
</div>
);
};
+153 -79
View File
@@ -21,7 +21,11 @@ const ReportTable = ({
const [actLoader, setActLoader] = useState({});
const [isAlert, setIsAlert] = useState(false);
const [isErr, setIsErr] = useState(false);
const [isPopup, setIsPopup] = useState(false);
const [isDocErr, setIsDocErr] = useState(false);
const [isContactform, setIsContactform] = useState(false);
const [isDeleteModal, setIsDeleteModal] = useState({});
const startIndex = (currentPage - 1) * docPerPage;
// For loop is used to calculate page numbers visible below table
// Initialize pageNumbers using useMemo to avoid unnecessary re-creation
const pageNumbers = useMemo(() => {
@@ -64,7 +68,7 @@ const ReportTable = ({
if (btnLabel === "Edit") {
navigate(`/asmf/${url}/${item.objectId}`);
} else {
setActLoader({ [item.objectId]: true });
setActLoader({ [`${item.objectId}_${btnLabel}`]: true });
try {
const params = {
templateId: item.objectId
@@ -87,10 +91,6 @@ const ReportTable = ({
if (!templateData.error) {
const Doc = templateData;
let placeholdersArr = [];
if (Doc.Placeholders?.length > 0) {
placeholdersArr = Doc.Placeholders;
}
let signers = [];
if (Doc.Signers?.length > 0) {
Doc.Signers?.forEach((x) => {
@@ -104,45 +104,63 @@ const ReportTable = ({
}
});
}
const data = {
Name: Doc.Name,
URL: Doc.URL,
SignedUrl: Doc.SignedUrl,
Description: Doc.Description,
Note: Doc.Note,
Placeholders: placeholdersArr,
ExtUserPtr: {
__type: "Pointer",
className: "contracts_Users",
objectId: Doc.ExtUserPtr.objectId
},
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: Doc.CreatedBy.objectId
},
Signers: signers
};
const res = await axios.post(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
let placeholdersArr = [];
if (Doc.Placeholders?.length > 0) {
placeholdersArr = Doc.Placeholders;
const data = {
Name: Doc.Name,
URL: Doc.URL,
SignedUrl: Doc.SignedUrl,
Description: Doc.Description,
Note: Doc.Note,
Placeholders: placeholdersArr,
ExtUserPtr: {
__type: "Pointer",
className: "contracts_Users",
objectId: Doc.ExtUserPtr.objectId
},
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: Doc.CreatedBy.objectId
},
Signers: signers
};
try {
const res = await axios.post(
`${localStorage.getItem(
"baseUrl"
)}classes/${localStorage.getItem("_appName")}_Document`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id":
localStorage.getItem("parseAppId"),
"X-Parse-Session-Token":
localStorage.getItem("accesstoken")
}
}
);
// console.log("Res ", res.data);
if (res.data && res.data.objectId) {
setActLoader({});
setIsAlert(true);
navigate(`/asmf/${url}/${res.data.objectId}`, {
state: { title: "Use Template" }
});
}
} catch (err) {
console.log("Err", err);
setIsAlert(true);
setIsErr(true);
setActLoader({});
}
);
// console.log("Res ", res.data);
if (res.data && res.data.objectId) {
} else {
setIsDocErr(true);
setActLoader({});
setIsAlert(true);
navigate(`/asmf/${url}/${res.data.objectId}`);
}
} else {
setIsAlert(true);
@@ -166,31 +184,7 @@ const ReportTable = ({
};
const handlebtn = async (item) => {
if (ReportName === "Contactbook") {
setActLoader({ [item.objectId]: true });
try {
const url =
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
const body = { IsDeleted: true };
const res = await axios.put(url + item.objectId, body, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
});
// console.log("Res ", res.data);
if (res.data && res.data.updatedAt) {
setActLoader({});
setIsAlert(true);
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
setList(upldatedList);
}
} catch (err) {
console.log("err", err);
setIsAlert(true);
setIsErr(true);
setActLoader({});
}
setIsDeleteModal({ [item.objectId]: true });
}
};
@@ -204,13 +198,44 @@ const ReportTable = ({
const paginateFront = () => setCurrentPage(currentPage + 1);
const paginateBack = () => setCurrentPage(currentPage - 1);
const handlePopup = () => {
setIsPopup(!isPopup);
const handleContactFormModal = () => {
setIsContactform(!isContactform);
};
const handleUserData = (data) => {
setList((prevData) => [data, ...prevData]);
};
const handleDelete = async (item) => {
setIsDeleteModal({});
setActLoader({ [item.objectId]: true });
try {
const url =
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
const body = { IsDeleted: true };
const res = await axios.put(url + item.objectId, body, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
});
// console.log("Res ", res.data);
if (res.data && res.data.updatedAt) {
setActLoader({});
setIsAlert(true);
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
setList(upldatedList);
}
} catch (err) {
console.log("err", err);
setIsAlert(true);
setIsErr(true);
setActLoader({});
}
};
const handleCloseDeleteModal = () => setIsDeleteModal({});
return (
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
{isAlert && (
@@ -228,7 +253,10 @@ const ReportTable = ({
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
<div className="font-light">{ReportName}</div>
{form && (
<div className="cursor-pointer" onClick={() => handlePopup()}>
<div
className="cursor-pointer"
onClick={() => handleContactFormModal()}
>
<i className="fa-solid fa-square-plus text-sky-400 text-[25px]"></i>
</div>
)}
@@ -253,12 +281,12 @@ const ReportTable = ({
ReportName === "Contactbook" ? (
<tr className="border-y-[1px]" key={index}>
{heading.includes("Sr.No") && (
<td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2">{startIndex + index + 1}</td>
)}
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2">{item?.Email || "-"}</td>
<td className="px-4 py-2">{item?.Phone || "-"}</td>
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
<td className="px-3 py-2 text-white">
{actions?.length > 0 &&
actions.map((act, index) => (
<button
@@ -268,7 +296,7 @@ const ReportTable = ({
? handlemicroapp(item, act.redirectUrl)
: handlebtn(item)
}
className={`flex justify-center items-center gap-1 px-2 py-1 rounded shadow`}
className={`mb-1 flex justify-center items-center gap-1 px-2 py-1 rounded shadow`}
style={{
backgroundColor: act.btnColor
? act.btnColor
@@ -294,14 +322,44 @@ const ReportTable = ({
)}
</button>
))}
{isDeleteModal[item.objectId] && (
<ModalUi
isOpen
title={"Delete Contact"}
handleClose={handleCloseDeleteModal}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-black">
Are you sure you want to delete this contact?
</div>
<hr className="bg-[#ccc] mt-4 " />
<div className="flex items-center mt-3 gap-2 text-white">
<button
onClick={() => handleDelete(item)}
className="bg-[#1ab6ce] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-3 focus:outline-none"
>
Yes
</button>
<button
onClick={handleCloseDeleteModal}
className="bg-[#188ae2] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-3 text-center ml-[2px] focus:outline-none"
>
No
</button>
</div>
</div>
</ModalUi>
)}
</td>
</tr>
) : (
<tr className="border-y-[1px]" key={index}>
{heading.includes("Sr.No") && (
<td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2">{startIndex + index + 1}</td>
)}
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2 font-semibold w-56">
{item?.Name}{" "}
</td>
{heading.includes("Note") && (
<td className="px-4 py-2">{item?.Note || "-"}</td>
)}
@@ -327,7 +385,7 @@ const ReportTable = ({
<td className="px-4 py-2">
{item?.Signers ? formatRow(item?.Signers) : "-"}
</td>
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
<td className="px-3 py-2 text-white">
{actions?.length > 0 &&
actions.map((act, index) => (
<button
@@ -341,7 +399,7 @@ const ReportTable = ({
)
: handlebtn(item)
}
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
className={`mb-1 flex justify-center items-center gap-1 px-2 py-1 rounded shadow`}
style={{
backgroundColor: act.btnColor
? act.btnColor
@@ -353,7 +411,9 @@ const ReportTable = ({
{act?.btnIcon && (
<i
className={
actLoader[item.objectId]
actLoader[
`${item.objectId}_${act.btnLabel}`
]
? "fa-solid fa-spinner fa-spin-pulse"
: act.btnIcon
}
@@ -421,12 +481,26 @@ const ReportTable = ({
<div className="text-sm font-semibold">No Data Available</div>
</div>
)}
<ModalUi title={"Add Contact"} isOpen={isPopup} handleClose={handlePopup}>
<ModalUi
title={"Add Contact"}
isOpen={isContactform}
handleClose={handleContactFormModal}
>
<AppendFormInForm
handleUserData={handleUserData}
closePopup={handlePopup}
closePopup={handleContactFormModal}
/>
</ModalUi>
<ModalUi
headColor={"#dc3545"}
isOpen={isDocErr}
title={"Receipent required"}
handleClose={() => setIsDocErr(false)}
>
<div style={{ height: "100%", padding: 20 }}>
<p>Please add receipent in template!</p>
</div>
</ModalUi>
</div>
);
};
+24 -10
View File
@@ -1,21 +1,35 @@
import React from "react";
const ModalUi = ({ children, title, isOpen, handleClose }) => {
const ModalUi = ({
children,
title,
isOpen,
headColor,
handleClose,
showHeader = true,
showClose = true
}) => {
return (
<>
{isOpen && (
<div className="fixed z-[999] top-0 left-0 w-[100%] h-[100%] bg-black bg-opacity-[75%]">
<div className="fixed z-[1000] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-sm bg-white rounded shadow-md max-h-90 md:min-w-[500px] overflow-y-auto hide-scrollbar">
<div className="flex justify-between bg-[#32a3ac] rounded-t items-center py-[10px] px-[20px] text-white">
<div className="text-[1.2rem] font-normal">{title}</div>
<div className="fixed z-[1000] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-sm bg-white rounded shadow-md max-h-90 min-w-[90%] md:min-w-[500px] overflow-y-auto hide-scrollbar">
{showHeader && (
<div
className="text-[1.5rem] cursor-pointer"
onClick={() => handleClose && handleClose()}
className="flex justify-between rounded-t items-center py-[15px] px-[20px] text-white"
style={{ background: headColor ? headColor : "#32a3ac" }}
>
&times;
<div className="text-[1.2rem] font-normal">{title}</div>
{showClose && (
<div
className="text-[1.5rem] cursor-pointer"
onClick={() => handleClose && handleClose()}
>
&times;
</div>
)}
</div>
</div>
<div >{children}</div>
)}
<div>{children}</div>
</div>
</div>
)}
@@ -0,0 +1,34 @@
import React, { useEffect } from "react";
import Parse from "parse";
const ValidateRoute = ({ children }) => {
useEffect(() => {
(async () => {
try {
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(Parse.User.current().id, {
sessionToken: localStorage.getItem("accesstoken")
});
if (!user) {
handlelogout();
}
} catch (error) {
handlelogout();
}
})();
}, []);
const handlelogout = async () => {
try {
Parse.User.logOut();
localStorage.removeItem("accesstoken");
} catch (err) {
console.log("err ", err);
} finally {
localStorage.removeItem("accesstoken");
}
};
return <div>{children}</div>;
};
export default ValidateRoute;
+2 -2
View File
@@ -74,8 +74,8 @@ const PgSignUp = (props) => {
const res = await Parse.Cloud.run("getUserDetails", params);
// console.log("res", res);
if (res) {
const checkUser = new Parse.Query(extClass);
const updateQuery = await checkUser.get(res.id);
const updateQuery = new Parse.Object(extClass);
updateQuery.id = res.id;
updateQuery.set(
"Next_billing_date",
new Date(zohoRes.data.result.nextBillingDate)
+110 -90
View File
@@ -2,7 +2,7 @@ import SignPDF from './SignPDF.min.cjs';
import fs from 'node:fs';
import axios from 'axios';
import FormData from 'form-data';
import plainplaceholder from './customSignPdf/plainplaceholder.min.js';
// import plainplaceholder from './customSignPdf/plainplaceholder.min.js';
import { plainAddPlaceholder } from 'node-signpdf/dist/helpers/index.js';
const serverUrl = process.env.SERVER_URL,
APPID = process.env.APP_ID,
@@ -19,20 +19,20 @@ async function uploadFile(a) {
console.log('err ', e), fs.unlinkSync(a);
}
}
async function updateDoc(t, s, r, i, o, n) {
async function updateDoc(t, s, r, i, n, o) {
try {
var d = {
UserPtr: { __type: 'Pointer', className: n, objectId: r },
UserPtr: { __type: 'Pointer', className: o, objectId: r },
SignedUrl: s,
Activity: 'Signed',
ipAddress: i,
};
let e;
var l = (e = o.AuditTrail && 0 < o.AuditTrail.length ? [...o.AuditTrail, d] : [d]).filter(
var l = (e = n.AuditTrail && 0 < n.AuditTrail.length ? [...n.AuditTrail, d] : [d]).filter(
e => 'Signed' === e.Activity
);
let a = !1;
!((o.Signers && 0 < o.Signers.length && l.length !== o.Signers.length) || !(a = !0));
!((n.Signers && 0 < n.Signers.length && l.length !== n.Signers.length) || !(a = !0));
var p = { SignedUrl: s, AuditTrail: e, IsCompleted: a };
await axios.put(serverUrl + '/classes/contracts_Document/' + t, p, {
headers: {
@@ -61,7 +61,7 @@ async function sendMail(e) {
s +
' Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' +
t.Mail +
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>',
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>'
};
await axios.post(serverUrl + '/functions/sendmailv3', a, {
headers: {
@@ -86,7 +86,7 @@ async function sendCompletedMail(e) {
s +
'. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' +
t.Mail +
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>',
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>',
};
await axios.post(serverUrl + '/functions/sendmailv3', a, {
headers: {
@@ -96,115 +96,135 @@ async function sendCompletedMail(e) {
},
});
}
async function PDF(s, r) {
async function PDF(i, n) {
try {
var i = s.params.sign,
e = s.params.docId,
o = s.params.userId,
n = await axios.get(serverUrl + '/classes/contracts_Document/' + e + '?include=ExtUserPtr', {
headers: {
'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
}),
d = await axios.get(serverUrl + '/users/me', {
i.params.sign;
var e = i.params.docId,
a = i.params.userId,
o = await axios.get(
serverUrl + '/classes/contracts_Document/' + e + '?include=ExtUserPtr,Signers',
{
headers: {
'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
}
),
t = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
});
if (!d.data || !d.data.objectId) return { status: 'error', message: 'this user not allowed!' };
if (!t.data || !t.data.objectId) return { status: 'error', message: 'this user not allowed!' };
{
var l,
var d,
l,
p,
c,
m = JSON.stringify({ objectId: o });
let a, t;
t = o
? (l = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + m, {
c = JSON.stringify({ objectId: a });
let s, r;
r = a
? (d = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + c, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
})).data && 0 < l.data.results.length
? ((a = l), 'contracts_Contactbook')
: ((a = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
})).data && 0 < d.data.results.length
? ((s = d), 'contracts_Contactbook')
: ((s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + c, {
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
})),
'contracts_Users')
: ((p = JSON.stringify({
UserId: { __type: 'Pointer', className: '_User', objectId: d.data.objectId },
: ((l = JSON.stringify({
UserId: { __type: 'Pointer', className: '_User', objectId: t.data.objectId },
})),
(c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
})).data && 0 < c.data.results.length
? ((a = c), 'contracts_Users')
: ((a = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + p, {
(p = await axios.get(serverUrl + '/classes/contracts_Users?where=' + l, {
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
})).data && 0 < p.data.results.length
? ((s = p), 'contracts_Users')
: ((s = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + l, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
})),
'contracts_Contactbook'));
var g = a.data.results[0].Name,
h = a.data.results[0].Email;
if (!s.params.pdfFile) return { status: 'error', message: 'pdf file not present!' };
var m = s.data.results[0].Name,
g = s.data.results[0].Email;
if (!i.params.pdfFile) return { status: 'error', message: 'pdf file not present!' };
{
let e = Buffer.from(s.params.pdfFile, 'base64');
let e = Buffer.from(i.params.pdfFile, 'base64');
var u = process.env.PFX_BASE64,
f = Buffer.from(u, 'base64');
e = i
? plainplaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + g + ' <' + h + '>',
location: 'test location',
signatureLength: 1e4,
sign: i,
})
: plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + g + ' <' + h + '>',
location: 'test location',
signatureLength: 1e4,
});
var y = await new SignPDF(e, f).signPDF(),
v = `./exports/exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
P = (fs.writeFileSync(v, y), await uploadFile(v));
if (P && P.imageUrl) {
const r = await updateDoc(
s.params.docId,
P.imageUrl,
a.data.results[0].objectId,
s.headers['x-real-ip'],
n.data,
t
h = Buffer.from(u, 'base64'),
f = {
UserPtr: { __type: 'Pointer', className: r, objectId: s.data.results[0].objectId },
SignedUrl: '',
Activity: 'Signed',
ipAddress: i.headers['x-real-ip'],
};
let a;
var y = (a =
o.data.AuditTrail && 0 < o.data.AuditTrail.length
? [...o.data.AuditTrail, f]
: [f]).filter(e => 'Signed' === e.Activity);
let t = !1;
!(
(o.data.Signers && 0 < o.data.Signers.length && y.length !== o.data.Signers.length) ||
!(t = !0)
);
var v,
P,
x = `./exports/exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
A =
(t
? ((v = o.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
(e =
v && 0 < v.length
? plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + v?.join(', '),
location: 'location',
signatureLength: 1e4,
})
: plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + m + ' <' + g + '>',
location: 'location',
signatureLength: 1e4,
})),
(P = await new SignPDF(e, h).signPDF()),
fs.writeFileSync(x, P))
: fs.writeFileSync(x, e),
await uploadFile(x));
if (A && A.imageUrl) {
const n = await updateDoc(
i.params.docId,
A.imageUrl,
s.data.results[0].objectId,
i.headers['x-real-ip'],
o.data,
r
);
return (
sendMail({
url: P.imageUrl,
sender: { Mail: n.data.ExtUserPtr.Email, Name: n.data.ExtUserPtr.Name },
pdfName: n.data.Name,
receiver: h,
url: A.imageUrl,
sender: { Mail: o.data.ExtUserPtr.Email, Name: o.data.ExtUserPtr.Name },
pdfName: o.data.Name,
receiver: g,
}),
r &&
r.isCompleted &&
n &&
n.isCompleted &&
sendCompletedMail({
url: P.imageUrl,
sender: { Mail: n.data.ExtUserPtr.Email, Name: 'Open sign' },
pdfName: n.data.Name,
receiver: n.data.ExtUserPtr.Email,
url: A.imageUrl,
sender: { Mail: o.data.ExtUserPtr.Email, Name: 'Open sign' },
pdfName: o.data.Name,
receiver: o.data.ExtUserPtr.Email,
}),
fs.unlinkSync(v),
console.log('New Signed PDF created called: ' + v),
'success' === r.message
? { status: 'success', data: P.imageUrl }
fs.unlinkSync(x),
console.log('New Signed PDF created called: ' + x),
'success' === n.message
? { status: 'success', data: A.imageUrl }
: { status: 'error', message: 'please provide required parameters!' }
);
}
@@ -62,7 +62,7 @@ export default function reportJson(id, userId) {
reportName: 'In-progress documents',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Signers: { $exists: true, $ne: [] },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
@@ -153,7 +153,7 @@ export default function reportJson(id, userId) {
reportName: 'Recently sent for signatures',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Signers: { $exists: true, $ne: [] },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
@@ -32,7 +32,7 @@ exports.up = async Parse => {
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
@@ -50,7 +50,7 @@ exports.up = async Parse => {
],
},
{
icon: 'fas fa-file-signature',
icon: 'fa-solid fa-file-contract',
title: 'Templates',
target: '_self',
pageType: 'report',
@@ -181,23 +181,30 @@ exports.up = async Parse => {
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
{
icon: 'fas fa-file-signature',
title: 'New template',
target: '_self',
pageType: 'form',
description: '',
objectId: 'template',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive™',
icon: 'fa-solid fa-file-contract',
title: 'Templates',
target: '_self',
pageType: 'mf',
pageType: 'report',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
objectId: '6TeaPr321t',
},
{
icon: 'fas fa-address-card',
Binary file not shown.
@@ -32,6 +32,7 @@ import Header from "./component/header";
import RenderPdf from "./component/renderPdf";
import CustomModal from "./component/CustomModal";
import AlertComponent from "./component/alertComponent";
import Title from "./component/Title";
function PdfRequestFiles() {
const { docId } = useParams();
@@ -625,6 +626,7 @@ function PdfRequestFiles() {
return (
<DndProvider backend={HTML5Backend}>
<Title title={"Request Sign"}/>
{isLoading.isLoad ? (
<Loader isLoading={isLoading} />
) : handleError ? (
@@ -39,6 +39,8 @@ import { contractUsers, contactBook, urlValidator } from "../utils/Utils";
import { modalAlign } from "../utils/Utils";
import AlertComponent from "./component/alertComponent";
import PlaceholderCopy from "./component/PlaceholderCopy";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
import Title from "./component/Title";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
@@ -91,6 +93,7 @@ function SignYourSelf() {
type: "load"
});
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isDontShow, setIsDontShow] = useState(false);
const divRef = useRef(null);
const nodeRef = useRef(null);
const [{ isOver }, drop] = useDrop({
@@ -748,16 +751,31 @@ function SignYourSelf() {
setXyPostion(getXyData);
setShowAlreadySignDoc({ status: false });
};
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
};
const tourConfig = [
{
selector: '[data-tut="reactourFirst"]',
content: `Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`,
content: () => (
<TourContentWithBtn
message={`Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourSecond"]',
content: `Drag and drop anywhere in this area. You can resize and move it later.`,
content: () => (
<TourContentWithBtn
message={`Drag and drop anywhere in this area. You can resize and move it later.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
}
@@ -766,47 +784,49 @@ function SignYourSelf() {
//function for update TourStatus
const closeTour = async () => {
setSignTour(false);
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const signyourselfIndex = tourStatus.findIndex(
(obj) => obj["signyourself"] === false || obj["signyourself"] === true
);
if (signyourselfIndex !== -1) {
updatedTourStatus[signyourselfIndex] = { signyourself: true };
} else {
updatedTourStatus.push({ signyourself: true });
}
} else {
updatedTourStatus = [{ signyourself: true }];
}
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}${contractName}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
if (isDontShow) {
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const signyourselfIndex = tourStatus.findIndex(
(obj) => obj["signyourself"] === false || obj["signyourself"] === true
);
if (signyourselfIndex !== -1) {
updatedTourStatus[signyourselfIndex] = { signyourself: true };
} else {
updatedTourStatus.push({ signyourself: true });
}
)
.then((Listdata) => {
// const json = Listdata.data;
})
.catch((err) => {
console.log("axois err ", err);
});
} else {
updatedTourStatus = [{ signyourself: true }];
}
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}${contractName}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
// const json = Listdata.data;
})
.catch((err) => {
console.log("axois err ", err);
});
}
};
return (
<DndProvider backend={HTML5Backend}>
<Title title={"Self Sign"} />
{isLoading.isLoad ? (
<Loader isLoading={isLoading} />
) : handleError ? (
@@ -33,7 +33,7 @@ import ModalUi from "../premitives/ModalUi";
import AddRoleModal from "./component/AddRoleModal";
import PlaceholderCopy from "./component/PlaceholderCopy";
import ModalComponent from "./component/modalComponent";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
const TemplatePlaceholder = () => {
const navigate = useNavigate();
const { templateId } = useParams();
@@ -157,6 +157,7 @@ const TemplatePlaceholder = () => {
const [isPageCopy, setIsPageCopy] = useState(false);
const [signKey, setSignKey] = useState();
const [IsReceipent, setIsReceipent] = useState(true);
const [isDontShow, setIsDontShow] = useState(false);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
@@ -197,7 +198,6 @@ const TemplatePlaceholder = () => {
}
}
);
// console.log("templateDeatils.data ", templateDeatils.data);
const documentData =
templateDeatils.data && templateDeatils.data.result
? [templateDeatils.data.result]
@@ -327,201 +327,136 @@ const TemplatePlaceholder = () => {
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
getSignerPos(item, monitor);
getSignerPos(item, monitor);
};
// `getSignerPos` is used to get placeholder position when user place it and save it in array
const getSignerPos = (item, monitor) => {
const signer = signersdata.find((x) => x.Id === uniqueId);
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const newWidth = containerWH.width;
const scale = pdfOriginalWidth / newWidth;
const key = randomId();
// let filterSignerPos = signerPos.filter(
// (data) => data.signerObjId === signerObjId
// );
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
let dropData = [];
let xyPosArr = [];
let xyPos = {};
if (item === "onclick") {
const dropObj = {
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor,
key: key,
isDrag: false,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60,
zIndex: posZIndex
};
dropData.push(dropObj);
xyPos = {
pageNumber: pageNumber,
pos: dropData
};
xyPosArr.push(xyPos);
} else if (item.type === "BOX") {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: scale,
isMobile: isMobile,
zIndex: posZIndex
};
dropData.push(dropObj);
xyPos = {
pageNumber: pageNumber,
pos: dropData
};
xyPosArr.push(xyPos);
}
const { blockColor, Role } = signersdata.find((x) => x.Id === uniqueId);
//adding placholder in existing signer pos array (placaholder)
if (filterSignerPos.length > 0) {
// 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(
(data) => data.pageNumber !== pageNumber
);
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
//add entry of position for same signer on multiple page
if (getPageNumer.length > 0) {
const getPos = getPageNumer[0].pos;
const newSignPos = getPos.concat(dropData);
let xyPos = {
if (uniqueId) {
const signer = signersdata.find((x) => x.Id === uniqueId);
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const newWidth = containerWH.width;
const scale = pdfOriginalWidth / newWidth;
const key = randomId();
// let filterSignerPos = signerPos.filter(
// (data) => data.signerObjId === signerObjId
// );
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
let dropData = [];
let placeHolder;
if (item === "onclick") {
const dropObj = {
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor,
key: key,
isDrag: false,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60,
zIndex: posZIndex
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: newSignPos
pos: dropData
};
updatePlace.push(xyPos);
let placeHolderPos;
if (contractName) {
placeHolderPos = {
blockColor: blockColor ? blockColor : color[isSelectListId],
signerObjId: signerObjId,
placeHolder: updatePlace,
signerPtr: {
__type: "Pointer",
className: `${contractName}`,
objectId: signerObjId
},
Role: Role ? Role : roleName,
Id: uniqueId
};
} else {
placeHolderPos = {
blockColor: blockColor ? blockColor : color[isSelectListId],
signerObjId: "",
placeHolder: updatePlace,
signerPtr: {},
Role: Role ? Role : roleName,
Id: uniqueId
};
}
// signerPos.splice(colorIndex, 1, placeHolderPos);
const newArry = [placeHolderPos];
const newArray = [
...signerPos.slice(0, colorIndex),
...newArry,
...signerPos.slice(colorIndex + 1)
];
setSignerPos(newArray);
} else {
const newSignPoss = getPlaceHolder.concat(xyPosArr[0]);
let placeHolderPos;
if (contractName) {
placeHolderPos = {
blockColor: color[isSelectListId],
signerObjId: signerObjId,
placeHolder: newSignPoss,
signerPtr: {
__type: "Pointer",
className: `${contractName}`,
objectId: signerObjId
},
Role: Role ? Role : roleName,
Id: uniqueId
};
} else {
placeHolderPos = {
blockColor: color[isSelectListId],
signerObjId: "",
placeHolder: newSignPoss,
signerPtr: {},
Role: Role ? Role : roleName,
Id: uniqueId
};
}
} else if (item.type === "BOX") {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const newArry = [placeHolderPos];
const newArray = [
...signerPos.slice(0, colorIndex),
...newArry,
...signerPos.slice(colorIndex + 1)
];
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: scale,
isMobile: isMobile,
zIndex: posZIndex
};
setSignerPos(newArray);
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: dropData
};
}
const { blockColor, Role } = signer;
//adding placholder in existing signer pos array (placaholder)
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const updatePlace = getPlaceHolder.filter(
(data) => data.pageNumber !== pageNumber
);
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
//add entry of position for same signer on multiple page
if (getPageNumer.length > 0) {
const getPos = getPageNumer[0].pos;
const newSignPos = getPos.concat(dropData);
let xyPos = {
pageNumber: pageNumber,
pos: newSignPos
};
updatePlace.push(xyPos);
const updatesignerPos = signerPos.map((x) =>
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
);
setSignerPos(updatesignerPos);
} else {
const updatesignerPos = signerPos.map((x) =>
x.Id === uniqueId
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
: x
);
setSignerPos(updatesignerPos);
}
} else {
//adding new placeholder for selected signer in pos array (placeholder)
let placeHolderPos;
if (contractName) {
placeHolderPos = {
signerPtr: {
__type: "Pointer",
className: `${contractName}`,
objectId: signerObjId
},
signerObjId: signerObjId,
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: [placeHolder],
Role: Role ? Role : roleName,
Id: uniqueId
};
} else {
placeHolderPos = {
signerPtr: {},
signerObjId: "",
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: [placeHolder],
Role: Role ? Role : roleName,
Id: uniqueId
};
}
setSignerPos((prev) => [...prev, placeHolderPos]);
}
setIsMailSend(false);
} else {
//adding new placeholder for selected signer in pos array (placeholder)
let placeHolderPos;
if (contractName) {
placeHolderPos = {
signerPtr: {
__type: "Pointer",
className: `${contractName}`,
objectId: signerObjId
},
signerObjId: signerObjId,
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: xyPosArr,
Role: Role ? Role : roleName,
Id: uniqueId
};
} else {
placeHolderPos = {
signerPtr: {},
signerObjId: "",
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: xyPosArr,
Role: Role ? Role : roleName,
Id: uniqueId
};
}
setSignerPos((prev) => [...prev, placeHolderPos]);
setIsReceipent(false);
}
setIsMailSend(false);
} else {
setIsReceipent(false);
}
};
//function for get pdf page details
@@ -760,38 +695,67 @@ const TemplatePlaceholder = () => {
setIsReceipent(false);
}
};
//here you can add your messages in content and selector is key of particular steps
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
};
//here you can add your messages in content and selector is key of particular steps
const tourConfig = [
{
selector: '[data-tut="reactourAddbtn"]',
content: `Clicking "Add role" button will allow you to add various signer roles. You can attach users to each role in subsequent steps.`,
content: () => (
<TourContentWithBtn
message={`Clicking "Add role" button will allow you to add various signer roles. You can attach users to each role in subsequent steps.`}
isChecked={handleDontShow}
/>
),
position: "top",
observe: '[data-tut="reactourAddbtn--observe"]',
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourFirst"]',
content: `Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`,
content: () => (
<TourContentWithBtn
message={`Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" },
action: () => handleCloseRoleModal()
},
{
selector: '[data-tut="reactourSecond"]',
content: `Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`,
content: () => (
<TourContentWithBtn
message={`Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourThird"]',
content: `Drag the placeholder for a recipient anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`,
content: () => (
<TourContentWithBtn
message={`Drag the placeholder for a recipient anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourFour"]',
content: `Clicking "Save" button will save the template and will ask you for creating new document.`,
content: () => (
<TourContentWithBtn
message={`Clicking "Save" button will save the template and will ask you for creating new document.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
}
@@ -800,44 +764,46 @@ const TemplatePlaceholder = () => {
//function for update TourStatus
const closeTour = async () => {
setTemplateTour(false);
const extUserClass = localStorage.getItem("extended_class");
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const templatetourIndex = tourStatus.findIndex(
(obj) => obj["templatetour"] === false || obj["templatetour"] === true
);
if (templatetourIndex !== -1) {
updatedTourStatus[templatetourIndex] = { templatetour: true };
} else {
updatedTourStatus.push({ templatetour: true });
}
} else {
updatedTourStatus = [{ templatetour: true }];
}
await axios
.put(
`${localStorage.getItem(
"baseUrl"
)}classes/${extUserClass}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
if (isDontShow) {
const extUserClass = localStorage.getItem("extended_class");
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const templatetourIndex = tourStatus.findIndex(
(obj) => obj["templatetour"] === false || obj["templatetour"] === true
);
if (templatetourIndex !== -1) {
updatedTourStatus[templatetourIndex] = { templatetour: true };
} else {
updatedTourStatus.push({ templatetour: true });
}
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
})
.catch((err) => {
console.log("axois err ", err);
});
} else {
updatedTourStatus = [{ templatetour: true }];
}
await axios
.put(
`${localStorage.getItem(
"baseUrl"
)}classes/${extUserClass}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
})
.catch((err) => {
console.log("axois err ", err);
});
}
};
// `handleCreateDocModal` is used to create Document from template when user click on yes from modal
@@ -848,7 +814,9 @@ const TemplatePlaceholder = () => {
// handle create document
const res = await createDocument(pdfDetails, signerPos, signersdata);
if (res.status === "success") {
navigate(`${hostUrl}placeHolderSign/${res.id}`);
navigate(`${hostUrl}placeHolderSign/${res.id}`, {
state: { title: "Use Template" }
});
setIsCreateDoc(false);
} else {
setHandleError("Error: Something went wrong!");
@@ -866,6 +834,8 @@ const TemplatePlaceholder = () => {
// save Role in entry in signerList and user
const handleAddRole = (e) => {
e.preventDefault();
setSignerObjId('')
setContractName('')
const count = signersdata.length > 0 ? signersdata.length + 1 : 1;
const Id = randomId();
const index = signersdata.length;
@@ -884,18 +854,18 @@ const TemplatePlaceholder = () => {
// `handleDeleteUser` function is used to delete record and placeholder when user click on delete which is place next user name in recipients list
const handleDeleteUser = (Id) => {
const updateSigner = signersdata
.filter((x) => x.Id !== Id)
.map((x, i) => ({ ...x, blockColor: color[i] }));
.filter((x) => x.Id !== Id)
.map((x, i) => ({ ...x, blockColor: color[i] }));
setSignersData(updateSigner);
const updatePlaceholderUser = signerPos
.filter((x) => x.Id !== Id)
.map((x, i) => ({ ...x, blockColor: color[i] }));
const index = signersdata.findIndex((x)=> x.Id === Id)
if(index === signersdata.length - 1){
setUniqueId(updateSigner[updateSigner.length - 1]?.Id ||"");
setIsSelectId(0);
}else{
setUniqueId(updateSigner[index]?.Id ||"");
.filter((x) => x.Id !== Id)
.map((x, i) => ({ ...x, blockColor: color[i] }));
const index = signersdata.findIndex((x) => x.Id === Id);
if (index === signersdata.length - 1) {
setUniqueId(updateSigner[updateSigner.length - 1]?.Id || "");
setIsSelectId(index - 1|| 0);
} else {
setUniqueId(updateSigner[index]?.Id || "");
setIsSelectId(index);
}
@@ -924,12 +894,14 @@ const TemplatePlaceholder = () => {
const updateSigner = signersdata.map((x) => {
if (x.Id === uniqueId) {
return { ...x, ...data };
return { ...x, ...data, className: "contracts_Contactbook" };
}
return { ...x };
});
setSignersData(updateSigner);
setIsMailSend(false);
const index = signersdata.findIndex((x) => x.Id === uniqueId);
setIsSelectId(index);
};
// `closePopup` is used to close Add/Choose signer modal
@@ -1054,7 +1026,10 @@ const TemplatePlaceholder = () => {
handleClose={() => setIsCreateDocModal(false)}
>
<div style={{ height: "100%", padding: 20 }}>
<p>Do you want to create a document using the template you just created ?</p>
<p>
Do you want to create a document using the template you just
created ?
</p>
<div
style={{
height: "1px",
@@ -43,7 +43,7 @@ const EditTemplate = ({ template, onSuccess }) => {
fontWeight: "700"
}}
>
file selected : {template.URL?.split("/")[3]?.split("_")[1]}
{template.URL?.split("/")[3]?.split("_")[1]}
</div>
</div>
<div className="form-section">
@@ -10,12 +10,12 @@ const LinkUserModal = (props) => {
details={props.handleAddUser}
closePopup={props.closePopup}
/>
<div style={{ display: "flex", alignItems: "center", gap: 5, margin:"0px 25px" }}>
<div style={{ display: "flex", alignItems: "center", gap: 5, margin:"0 30%", color:"#808080" }}>
<span
style={{
height: 1,
width: "100%",
backgroundColor: "grey"
backgroundColor: "#ccc"
}}
></span>
<span>or</span>
@@ -23,7 +23,7 @@ const LinkUserModal = (props) => {
style={{
height: 1,
width: "100%",
backgroundColor: "grey"
backgroundColor: "#ccc"
}}
></span>
</div>
@@ -83,22 +83,56 @@ function FieldsComponent({
justifyContent: "center"
}}
onClick={() => {
if (signersdata?.length) {
handleModal();
}
// if (signersdata?.length) {
handleModal();
// }
}}
>
<span style={{ fontSize: "13px", fontWeight: "700" }}>
<span
style={{
fontSize: "13px",
fontWeight: "700",
textAlign: "center"
}}
>
Recipient
</span>
<span style={{ fontSize: "13px", fontWeight: "700" }}>
<span
style={{
fontSize: "13px",
fontWeight: "700",
display: "flex",
alignItems: "center"
}}
>
{signersdata[isSelectListId]?.Role && (
<div>
{signersdata[isSelectListId]?.Name
? ` : ${signersdata[isSelectListId]?.Name}`
: ` : ${signersdata[isSelectListId]?.Role}`}
{signersdata[isSelectListId]?.Name ? (
<>
:{" "}
{signersdata[isSelectListId]?.Name?.length > 12
? `${signersdata[isSelectListId].Name.slice(
0,
12
)}...`
: signersdata[isSelectListId]?.Name}
</>
) : (
<>
:{" "}
{signersdata[isSelectListId]?.Role?.length > 12
? `${signersdata[isSelectListId].Role.slice(
0,
12
)}...`
: signersdata[isSelectListId]?.Role}
</>
)}
</div>
)}
<div style={{ marginLeft: 6, fontSize: 16 }}>
<i className="fa-solid fa-angle-down"></i>
</div>
</span>
</div>
)}
@@ -333,25 +367,41 @@ function FieldsComponent({
</div>
</div>
)}
<ModalUi
title={"Recipients"}
isOpen={isSignersModal}
handleClose={handleModal}
>
<RecipientList
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
/>
</ModalUi>
{isSignersModal && (
<ModalUi
title={"Recipients"}
isOpen={isSignersModal}
handleClose={handleModal}
>
{signersdata.length > 0 ? (
<RecipientList
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
handleModal={handleModal}
/>
) : (
<div
style={{
padding: 20,
fontSize: 15,
fontWeight: "500",
textAlign: "center"
}}
>
Please add Recipient
</div>
)}
</ModalUi>
)}
</>
);
}
@@ -381,14 +381,12 @@ function RenderPdf({
};
const handleUserName = (signerId, Role) => {
if (signerId) {
const checkSign = signersdata.filter(
(sign) => sign.objectId === signerId
);
if (checkSign.length > 0) {
const checkSign = signersdata.find((sign) => sign.objectId === signerId);
if (checkSign?.Name) {
return (
<>
<div style={{ color: "black", fontSize: 11 }}>
{checkSign[0].Name}
{checkSign?.Name}
</div>
<div style={{ color: "black", fontSize: 11 }}> {`(${Role})`} </div>
</>
@@ -479,7 +477,7 @@ function RenderPdf({
onClick={() => {
setIsSignPad(true);
setSignKey(pos.key);
setIsStamp(false);
setIsStamp(pos?.isStamp ? pos.isStamp : false);
}}
>
<BorderResize />
@@ -647,6 +645,7 @@ function RenderPdf({
}}
>
<i
data-tut="reactourLinkUser"
className="fa-regular fa-user signUserIcon"
onTouchEnd={(e) => {
e.stopPropagation();
@@ -788,7 +787,6 @@ function RenderPdf({
xyPostion,
index,
setXyPostion
);
}}
>
@@ -1008,7 +1006,7 @@ function RenderPdf({
onClick={() => {
setIsSignPad(true);
setSignKey(pos.key);
setIsStamp(false);
setIsStamp(pos?.isStamp ? pos.isStamp : false);
}}
>
<div style={{ pointerEvents: "none" }}>
@@ -1173,6 +1171,7 @@ function RenderPdf({
/>
<div>
<i
data-tut="reactourLinkUser"
className="fa-regular fa-user signUserIcon"
onClick={(e) => {
e.stopPropagation();
@@ -11,7 +11,7 @@ import { useDrag, useDrop } from "react-dnd";
import RenderAllPdfPage from "./component/renderAllPdfPage";
import FieldsComponent from "./component/fieldsComponent";
import Tour from "reactour";
import { useParams } from "react-router-dom";
import { useLocation, useParams } from "react-router-dom";
import Loader from "./component/loader";
import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata";
@@ -31,9 +31,11 @@ import { useNavigate } from "react-router-dom";
import PlaceholderCopy from "./component/PlaceholderCopy";
import LinkUserModal from "./component/LinkUserModal";
import Title from "./component/Title";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
function PlaceHolderSign() {
const navigate = useNavigate();
const { state } = useLocation();
const [pdfDetails, setPdfDetails] = useState([]);
const [isMailSend, setIsMailSend] = useState(false);
const [allPages, setAllPages] = useState(null);
@@ -53,7 +55,7 @@ function PlaceHolderSign() {
message: "This might take some time"
});
const [handleError, setHandleError] = useState();
const [currentEmail, setCurrentEmail] = useState();
const [currentId, setCurrentId] = useState("");
const [pdfNewWidth, setPdfNewWidth] = useState();
const [placeholderTour, setPlaceholderTour] = useState(true);
const [checkTourStatus, setCheckTourStatus] = useState(false);
@@ -81,6 +83,7 @@ function PlaceHolderSign() {
const [roleName, setRoleName] = useState("");
const [isAddUser, setIsAddUser] = useState({});
const [signerExistModal, setSignerExistModal] = useState(false);
const [isDontShow, setIsDontShow] = useState(false);
const color = [
"#93a3db",
"#e6c3db",
@@ -202,10 +205,7 @@ function PlaceHolderSign() {
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);
setCurrentId(currEmail);
setSignerObjId(documentData[0].Signers[0].objectId);
setContractName(documentData[0].Signers[0].className);
setIsSelectId(0);
@@ -317,208 +317,136 @@ function PlaceHolderSign() {
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
if (isMobile) {
if (selectedEmail) {
getSignerPos(item, monitor);
} else {
setIsShowEmail(true);
}
} else {
getSignerPos(item, monitor);
}
getSignerPos(item, monitor);
};
const getSignerPos = (item, monitor) => {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
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.Id === uniqueId);
let dropData = [];
let xyPosArr = [];
let xyPos = {};
if (item === "onclick") {
const dropObj = {
//onclick put placeholder center on pdf
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor,
key: key,
isDrag: false,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60,
zIndex: posZIndex
};
dropData.push(dropObj);
xyPos = {
pageNumber: pageNumber,
pos: dropData
};
xyPosArr.push(xyPos);
} else if (item.type === "BOX") {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: scale,
isMobile: isMobile,
zIndex: posZIndex
};
dropData.push(dropObj);
xyPos = {
pageNumber: pageNumber,
pos: dropData
};
xyPosArr.push(xyPos);
}
//add signers objId first inseretion
if (filterSignerPos.length > 0) {
// 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(
(data) => data.pageNumber !== pageNumber
);
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
//add entry of position for same signer on multiple page
if (getPageNumer.length > 0) {
const getPos = getPageNumer[0].pos;
const newSignPos = getPos.concat(dropData);
let xyPos = {
setSignerObjId('')
setContractName('')
if (uniqueId) {
const signer = signersdata.find((x) => x.Id === uniqueId);
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const newWidth = containerWH.width;
const scale = pdfOriginalWidth / newWidth;
const key = randomId();
// let filterSignerPos = signerPos.filter(
// (data) => data.signerObjId === signerObjId
// );
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
let dropData = [];
let placeHolder;
if (item === "onclick") {
const dropObj = {
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor,
key: key,
isDrag: false,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60,
zIndex: posZIndex
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: newSignPos
pos: dropData
};
updatePlace.push(xyPos);
} else if (item.type === "BOX") {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: scale,
isMobile: isMobile,
zIndex: posZIndex
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: dropData
};
}
const { blockColor, Role } = signer;
//adding placholder in existing signer pos array (placaholder)
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const updatePlace = getPlaceHolder.filter(
(data) => data.pageNumber !== pageNumber
);
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
//add entry of position for same signer on multiple page
if (getPageNumer.length > 0) {
const getPos = getPageNumer[0].pos;
const newSignPos = getPos.concat(dropData);
let xyPos = {
pageNumber: pageNumber,
pos: newSignPos
};
updatePlace.push(xyPos);
const updatesignerPos = signerPos.map((x) =>
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
);
setSignerPos(updatesignerPos);
} else {
const updatesignerPos = signerPos.map((x) =>
x.Id === uniqueId
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
: x
);
setSignerPos(updatesignerPos);
}
} else {
//adding new placeholder for selected signer in pos array (placeholder)
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 = [
...signerPos.slice(0, colorIndex),
...newArry,
...signerPos.slice(colorIndex + 1)
];
setSignerPos(newArray);
} else {
const newSignPoss = getPlaceHolder.concat(xyPosArr[0]);
let placeHolderPos;
if (contractName) {
placeHolderPos = {
blockColor: color[isSelectListId],
signerObjId: signerObjId,
placeHolder: newSignPoss,
signerPtr: {
__type: "Pointer",
className: `${contractName}`,
objectId: signerObjId
},
Role: roleName,
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: [placeHolder],
Role: Role ? Role : roleName,
Id: uniqueId
};
} else {
placeHolderPos = {
blockColor: color[isSelectListId],
signerObjId: "",
placeHolder: newSignPoss,
signerPtr: {},
Role: roleName,
signerObjId: "",
blockColor: blockColor ? blockColor : color[isSelectListId],
placeHolder: [placeHolder],
Role: Role ? Role : roleName,
Id: uniqueId
};
}
// signerPos.splice(colorIndex, 1, placeHolderPos);
const newArry = [placeHolderPos];
const newArray = [
...signerPos.slice(0, colorIndex),
...newArry,
...signerPos.slice(colorIndex + 1)
];
setSignerPos(newArray);
setSignerPos((prev) => [...prev, placeHolderPos]);
}
} else {
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
const pageDetails = async (pdf) => {
const load = {
@@ -791,6 +719,8 @@ function PlaceHolderSign() {
objectId: x.objectId
};
});
const currentUser = signersdata.find((x) => x.Email === currentId);
setCurrentId(currentUser?.objectId);
// console.log("signers ", signers);
try {
const data = {
@@ -829,31 +759,65 @@ function PlaceHolderSign() {
}
}
};
//here you can add your messages in content and selector is key of particular steps
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
};
//here you can add your messages in content and selector is key of particular steps
const tourConfig = [
{
selector: '[data-tut="reactourFirst"]',
content: `Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`,
content: () => (
<TourContentWithBtn
message={`Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourSecond"]',
content: `Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`,
content: () => (
<TourContentWithBtn
message={`Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourThird"]',
content: `Drag the placeholder for a recipient anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`,
content: () => (
<TourContentWithBtn
message={`Drag the placeholder for a recipient anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourLinkUser"]',
content: () => (
<TourContentWithBtn
message={`Click to this icon to assign or replace signer for the placeholder.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourFour"]',
content: `Clicking "Send" button will share the document with all the recipients.It will also send out emails to everyone on the recipients list.`,
content: () => (
<TourContentWithBtn
message={`Clicking "Send" button will share the document with all the recipients.It will also send out emails to everyone on the recipients list.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
}
@@ -862,81 +826,82 @@ function PlaceHolderSign() {
//function for update TourStatus
const closeTour = async () => {
setPlaceholderTour(false);
const extUserClass = localStorage.getItem("extended_class");
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const placeholderIndex = tourStatus.findIndex(
(obj) => obj["placeholder"] === false || obj["placeholder"] === true
);
if (placeholderIndex !== -1) {
updatedTourStatus[placeholderIndex] = { placeholder: true };
} else {
updatedTourStatus.push({ placeholder: true });
}
} else {
updatedTourStatus = [{ placeholder: true }];
}
await axios
.put(
`${localStorage.getItem(
"baseUrl"
)}classes/${extUserClass}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
if (isDontShow) {
const extUserClass = localStorage.getItem("extended_class");
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const placeholderIndex = tourStatus.findIndex(
(obj) => obj["placeholder"] === false || obj["placeholder"] === true
);
if (placeholderIndex !== -1) {
updatedTourStatus[placeholderIndex] = { placeholder: true };
} else {
updatedTourStatus.push({ placeholder: true });
}
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
})
.catch((err) => {
console.log("axois err ", err);
});
} else {
updatedTourStatus = [{ placeholder: true }];
}
await axios
.put(
`${localStorage.getItem(
"baseUrl"
)}classes/${extUserClass}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
})
.catch((err) => {
console.log("axois err ", err);
});
}
};
const handleRecipientSign = () => {
const hostUrl = getHostUrl();
navigate(
`${hostUrl}recipientSignPdf/${documentId}/${currentEmail[0].objectId}`
);
navigate(`${hostUrl}recipientSignPdf/${documentId}/${currentId}`);
};
const handleLinkUser = (id) => {
setIsAddUser({ [id]: true });
};
const handleAddUser = (data) => {
if(data && data.objectId){
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);
if (data && data.objectId) {
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 updateSigner = signersdata.map((x) => {
if (x.Id === uniqueId) {
return { ...x, ...data, className: "contracts_Contactbook" };
}
return { ...x };
});
// console.log("updateSigner ", updateSigner);
setSignersData(updateSigner);
const index = signersdata.findIndex((x) => x.Id === uniqueId);
setIsSelectId(index);
}
};
const closePopup = () => {
@@ -944,7 +909,7 @@ function PlaceHolderSign() {
};
return (
<>
<Title title={"placeholder"} />
<Title title={state?.title ? state.title : "New Document"} />
<DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? (
<Loader isLoading={isLoading} />
@@ -1056,13 +1021,13 @@ function PlaceHolderSign() {
{/* signature modal */}
<Modal.Body>
<p>You have successfully sent mails to all recipients!</p>
{currentEmail?.length > 0 && (
{currentId && (
<p>Do you want to sign documents right now ?</p>
)}
</Modal.Body>
<Modal.Footer>
{currentEmail?.length > 0 ? (
{currentId ? (
<>
<button
onClick={() => {
@@ -37,6 +37,8 @@ import RenderPdf from "./component/renderPdf";
import CustomModal from "./component/CustomModal";
import { modalAlign } from "../utils/Utils";
import AlertComponent from "./component/alertComponent";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
import Title from "./component/Title";
function EmbedPdfImage() {
const { id, contactBookId } = useParams();
const [isSignPad, setIsSignPad] = useState(false);
@@ -84,6 +86,7 @@ function EmbedPdfImage() {
});
const [containerWH, setContainerWH] = useState({});
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isDontShow, setIsDontShow] = useState(false);
const docId = id && id;
const isMobile = window.innerWidth < 767;
const index = xyPostion.findIndex((object) => {
@@ -645,66 +648,86 @@ function EmbedPdfImage() {
//function for update TourStatus
const closeTour = async () => {
setSignTour(false);
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const recipientssignIndex = tourStatus.findIndex(
(obj) =>
obj["recipientssign"] === false || obj["recipientssign"] === true
);
if (recipientssignIndex !== -1) {
updatedTourStatus[recipientssignIndex] = { recipientssign: true };
} else {
updatedTourStatus.push({ recipientssign: true });
}
} else {
updatedTourStatus = [{ recipientssign: true }];
}
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}${contractName}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
if (isDontShow) {
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const recipientssignIndex = tourStatus.findIndex(
(obj) =>
obj["recipientssign"] === false || obj["recipientssign"] === true
);
if (recipientssignIndex !== -1) {
updatedTourStatus[recipientssignIndex] = { recipientssign: true };
} else {
updatedTourStatus.push({ recipientssign: true });
}
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
// console.log("res", json);
})
.catch((err) => {
console.log("axois err ", err);
});
} else {
updatedTourStatus = [{ recipientssign: true }];
}
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}${contractName}/${signerUserId}`,
{
TourStatus: updatedTourStatus
},
{
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;
// console.log("res", json);
})
.catch((err) => {
console.log("axois err ", err);
});
}
};
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
};
const tourFunction = () => {
const tourConfig = [
{
selector: '[data-tut="reactourFirst"]',
content: `You can click "Auto Sign All" to automatically sign at all the locations meant to be signed by you.Make sure that you review the document properly before you click this button.`,
content: () => (
<TourContentWithBtn
message={`You can click "Auto Sign All" to automatically sign at all the locations meant to be signed by you.Make sure that you review the document properly before you click this button.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourSecond"]',
content: `Click any of such placeholders appearing on the document to sign.You will see the options to draw sign or upload an image once you click here.`,
content: () => (
<TourContentWithBtn
message={`Click any of such placeholders appearing on the document to sign.You will see the options to draw sign or upload an image once you click here.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourThird"]',
content: `Click here to finish & download the signed document.You will also receive a copy on your email.`,
content: () => (
<TourContentWithBtn
message={`Click here to finish & download the signed document.You will also receive a copy on your email.`}
isChecked={handleDontShow}
/>
),
position: "top",
style: { fontSize: "13px" }
}
@@ -730,6 +753,7 @@ function EmbedPdfImage() {
return (
<DndProvider backend={HTML5Backend}>
<Title title={"Sign Document"} />
{isLoading.isLoad ? (
<Loader isLoading={isLoading} />
) : handleError ? (
@@ -1,6 +1,6 @@
.addusercontainer {
height: 100%;
padding: 20px;
padding: 10px 20px 10px 20px;
}
.loaderdiv {
@@ -158,10 +158,10 @@ const AddUser = (props) => {
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
if(props.details){
props.details(parseData);
}
if (props.closePopup) {
props.closePopup();
}
@@ -80,11 +80,14 @@ const RecipientList = (props) => {
: nonHoverStyle(ind)
}
onClick={() => {
props.setSignerObjId(obj?.objectId);
props.setSignerObjId(obj?.objectId || "");
props.setIsSelectId(ind);
props.setContractName(obj?.className);
props.setContractName(obj?.className || "");
props.setUniqueId(obj.Id);
props.setRoleName(obj.Role);
if(props.handleModal){
props.handleModal()
}
}}
>
<div
@@ -26,9 +26,9 @@ const SelectSigners = (props) => {
// `handleOptions` is used to set just save from quick form to selected option in dropdown
const handleOptions = (item) => {
setSelected(item);
const userData = userList.filter((x) => x.objectId === item.value);
if (userData.length > 0) {
setUserData(userData[0]);
const userData = userList.find((x) => x.objectId === item.value);
if (userData) {
setUserData(userData);
}
};
const handleAdd = () => {
@@ -87,10 +87,9 @@ const SelectSigners = (props) => {
/>
</div>
{isError ? <p style={{color:'red', fontSize: "12px", margin:"5px"}}>Please select signer</p>: <p style={{color:'transparent', fontSize: "12px", margin:"5px"}}>.</p>}
<div >
<div>
<button className="submitbutton" onClick={() => handleAdd()}>
Add Signer
Submit
</button>
</div>
</div>
@@ -0,0 +1,26 @@
import React, { useState } from "react";
export default function TourContentWithBtn({ message, isChecked }) {
const [isCheck, setIsCheck] = useState(false);
const handleCheck = () => {
setIsCheck(!isCheck);
if (isChecked) {
isChecked(!isCheck);
}
};
return (
<div>
<p>{message}</p>
<label style={{ textAlign: "center", display: "flex", "justifyContent":'center' }}>
<input
type="checkbox"
style={{ marginRight: 3 }}
checked={isCheck}
onChange={handleCheck}
/>{" "}
<span style={{color:"#787878", fontSize: 12}}>Don't show this again</span>
</label>
</div>
);
}
@@ -764,7 +764,8 @@ export const handleSignYourselfImageResize = (
key,
xyPostion,
index,
setXyPostion
setXyPostion,
) => {
// const updateFilter = xyPostion[index].pos.filter(
// (data) => data.key === key && data.Width && data.Height