mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-17 21:25:54 +02:00
add template feature
This commit is contained in:
@@ -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
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs mt-2">
|
||||
@@ -292,7 +293,7 @@ const TemplateForm = () => {
|
||||
onChange={(e) => handleStrInput(e)}
|
||||
/>
|
||||
</div>
|
||||
<SignersInput onChange={handleSigners} />
|
||||
{/* <SignersInput onChange={handleSigners} /> */}
|
||||
<SelectFolder onSuccess={handleFolder} folderCls={templateCls}/>
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button
|
||||
|
||||
@@ -27,6 +27,9 @@ import {
|
||||
} from "../utils/Utils";
|
||||
import RenderPdf from "./component/renderPdf";
|
||||
import ModalComponent from "./component/modalComponent";
|
||||
import SelectSigners from "./component/SelectSigners";
|
||||
import AddUser from "./component/AddUser";
|
||||
import "../css/AddUser.css";
|
||||
const TemplatePlaceholder = () => {
|
||||
const navigate = useNavigate();
|
||||
const { templateId } = useParams();
|
||||
@@ -148,6 +151,8 @@ const TemplatePlaceholder = () => {
|
||||
const [uniqueId, setUniqueId] = useState("");
|
||||
const [isModalRole, setIsModalRole] = useState(false);
|
||||
const [roleName, setRoleName] = useState("");
|
||||
const [isAddUser, setIsAddUser] = useState({});
|
||||
|
||||
const senderUser =
|
||||
localStorage.getItem(
|
||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||
@@ -172,10 +177,29 @@ const TemplatePlaceholder = () => {
|
||||
}
|
||||
}, [divRef.current]);
|
||||
const fetchTemplate = async () => {
|
||||
// const params = { templateId: templateId };
|
||||
// const templateDeatils = await axios.post(
|
||||
// `${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
||||
// params,
|
||||
// {
|
||||
// headers: {
|
||||
// "Content-Type": "application/json",
|
||||
// "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||
// "X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// // console.log("templateDeatils.data ", templateDeatils.data);
|
||||
// const documentData =
|
||||
// templateDeatils.data && templateDeatils.data.result
|
||||
// ? [templateDeatils.data.result]
|
||||
// : [];
|
||||
|
||||
const params = { templateId: templateId };
|
||||
const templateDeatils = await axios.post(
|
||||
`${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
||||
params,
|
||||
const templateDeatils = await axios.get(
|
||||
`${localStorage.getItem("baseUrl")}classes/contracts_Template/` +
|
||||
templateId +
|
||||
"?include=ExtUserPte,Signers,CreatedBy",
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -186,8 +210,8 @@ const TemplatePlaceholder = () => {
|
||||
);
|
||||
// console.log("templateDeatils.data ", templateDeatils.data);
|
||||
const documentData =
|
||||
templateDeatils.data && templateDeatils.data.result
|
||||
? [templateDeatils.data.result]
|
||||
templateDeatils.data && templateDeatils.data
|
||||
? [templateDeatils.data]
|
||||
: [];
|
||||
// console.log("documentData ", documentData)
|
||||
if (documentData && documentData.length > 0) {
|
||||
@@ -213,20 +237,30 @@ const TemplatePlaceholder = () => {
|
||||
) {
|
||||
setSignerPos(documentData[0].Placeholders);
|
||||
|
||||
const arr = documentData[0].Placeholders.filter(
|
||||
(x) => !x.signerObjId
|
||||
);
|
||||
console.log("arr ", arr);
|
||||
let updateArr = [...updateSigners];
|
||||
arr.forEach((x) => {
|
||||
const obj = {
|
||||
Role: x.Role,
|
||||
Id: randomId()
|
||||
};
|
||||
updateArr.push(obj);
|
||||
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
|
||||
};
|
||||
}
|
||||
});
|
||||
console.log("res ", updateArr);
|
||||
setSignersData(updateArr);
|
||||
|
||||
// console.log("res ", updateArr);
|
||||
console.log("updateArray ", arr);
|
||||
setSignersData(arr);
|
||||
} else {
|
||||
setSignersData(updateSigners);
|
||||
}
|
||||
@@ -694,10 +728,25 @@ const TemplatePlaceholder = () => {
|
||||
setIsLoading(loadObj);
|
||||
setIsSendAlert(false);
|
||||
console.log("signerPos ", signerPos);
|
||||
|
||||
let signers = [];
|
||||
if (signersdata?.length > 0) {
|
||||
signersdata.forEach((x) => {
|
||||
if (x.objectId) {
|
||||
const obj = {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Contactbook",
|
||||
objectId: x.objectId
|
||||
};
|
||||
signers.push(obj);
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
const data = {
|
||||
Placeholders: signerPos,
|
||||
SignedUrl: pdfDetails[0].URL
|
||||
SignedUrl: pdfDetails[0].URL,
|
||||
Signers: signers
|
||||
};
|
||||
|
||||
await axios
|
||||
@@ -805,7 +854,7 @@ const TemplatePlaceholder = () => {
|
||||
const hostUrl = getHostUrl();
|
||||
// handle create document
|
||||
console.log("template ", pdfDetails);
|
||||
const res = await createDocument(pdfDetails);
|
||||
const res = await createDocument(pdfDetails, signerPos, signersdata);
|
||||
if (res.status === "success") {
|
||||
navigate(`${hostUrl}placeHolderSign/${res.id}`);
|
||||
} else {
|
||||
@@ -872,6 +921,55 @@ const TemplatePlaceholder = () => {
|
||||
setIsModalRole(false);
|
||||
setRoleName("");
|
||||
};
|
||||
const handleDeleteUser = (Id) => {
|
||||
const removeUser = signersdata.filter((x) => x.Id !== Id);
|
||||
setSignersData(removeUser);
|
||||
const removePlaceholderUser = signerPos.filter((x) => x.Id !== Id);
|
||||
setSignerPos(removePlaceholderUser);
|
||||
};
|
||||
|
||||
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({});
|
||||
};
|
||||
const handleRoleChange = (event, roleId) => {
|
||||
// console.log("event ", event.target.textContent)
|
||||
// Update the role when the content changes
|
||||
const updatedRoles = signersdata.map((role) =>
|
||||
role.Id === roleId ? { ...role, Role: event.target.textContent } : role
|
||||
);
|
||||
setSignersData(updatedRoles);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
@@ -1019,6 +1117,8 @@ const TemplatePlaceholder = () => {
|
||||
containerWH={containerWH}
|
||||
setIsResize={setIsResize}
|
||||
setZIndex={setZIndex}
|
||||
handleLinkUser={handleLinkUser}
|
||||
setUniqueId={setUniqueId}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -1073,6 +1173,8 @@ const TemplatePlaceholder = () => {
|
||||
setContractName={setContractName}
|
||||
handleAddSigner={handleAddSigner}
|
||||
setUniqueId={setUniqueId}
|
||||
handleDeleteUser={handleDeleteUser}
|
||||
handleRoleChange={handleRoleChange}
|
||||
/>
|
||||
<div data-tut="reactourSecond">
|
||||
<FieldsComponent
|
||||
@@ -1111,15 +1213,23 @@ const TemplatePlaceholder = () => {
|
||||
<input
|
||||
value={roleName}
|
||||
onChange={(e) => setRoleName(e.target.value)}
|
||||
style={{ borderRadiu: 20 }}
|
||||
placeholder={
|
||||
signersdata.length > 0
|
||||
? "User " + (signersdata.length + 1)
|
||||
: "User 1"
|
||||
}
|
||||
className="addUserInput"
|
||||
/>
|
||||
<div>
|
||||
<hr />
|
||||
<div
|
||||
style={{
|
||||
height: "1px",
|
||||
backgroundColor: "#9f9f9f",
|
||||
width: "100%",
|
||||
marginTop: "15px",
|
||||
marginBottom: "15px"
|
||||
}}
|
||||
></div>
|
||||
<button
|
||||
type="submit"
|
||||
style={{
|
||||
@@ -1144,6 +1254,39 @@ const TemplatePlaceholder = () => {
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Modal show={isAddUser[uniqueId]}>
|
||||
<Modal.Header
|
||||
className={"bg-info"}
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<span style={{ color: "white" }}>Add/choose user</span>
|
||||
<span
|
||||
style={{ color: "white", cursor: "pointer" }}
|
||||
onClick={() => closePopup()}
|
||||
>
|
||||
X
|
||||
</span>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{isAddUser && isAddUser[uniqueId] && (
|
||||
<>
|
||||
<SelectSigners
|
||||
details={handleAddUser}
|
||||
closePopup={closePopup}
|
||||
/>
|
||||
<AddUser details={handleAddUser} closePopup={closePopup} />
|
||||
</>
|
||||
)}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 (
|
||||
<div className="addusercontainer">
|
||||
{isLoader && (
|
||||
<div className="loaderdiv">
|
||||
<div
|
||||
style={{
|
||||
fontSize: "45px",
|
||||
color: "#3dd3e0"
|
||||
}}
|
||||
className="loader-37"
|
||||
></div>
|
||||
</div>
|
||||
)}
|
||||
<div className="form-wrapper">
|
||||
<div style={{ fontSize: 14 }}>Add User</div>
|
||||
|
||||
{isUserExist && (
|
||||
<div className="form-section">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="addYourself"
|
||||
checked={addYourself}
|
||||
onChange={handleAddYourselfChange}
|
||||
className="form-checkbox"
|
||||
/>
|
||||
<label htmlFor="addYourself" className="checkbox-label ">
|
||||
Add Yourself
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="form-section">
|
||||
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||
Name
|
||||
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
disabled={addYourself}
|
||||
className="addUserInput"
|
||||
/>
|
||||
</div>
|
||||
<div className="form-section">
|
||||
<label htmlFor="email" style={{ fontSize: 13 }}>
|
||||
Email
|
||||
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
disabled={addYourself}
|
||||
className="addUserInput"
|
||||
/>
|
||||
</div>
|
||||
<div className="form-section">
|
||||
<label htmlFor="phone" style={{ fontSize: 13 }}>
|
||||
Phone
|
||||
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="phone"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
required
|
||||
disabled={addYourself}
|
||||
className="addUserInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="buttoncontainer">
|
||||
<button type="submit" className="submitbutton">
|
||||
Submit
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleReset()}
|
||||
className="resetbutton"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddUser;
|
||||
@@ -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 (
|
||||
<div className="addusercontainer">
|
||||
<div className="form-wrapper">
|
||||
<div className="form-section">
|
||||
<label style={{ fontSize: 14 }}>Choose User</label>
|
||||
<select
|
||||
value={selected}
|
||||
onChange={handleOptions}
|
||||
className="addUserInput"
|
||||
>
|
||||
<option>select</option>
|
||||
{userList.length > 0 &&
|
||||
userList.map((x) => (
|
||||
<option key={x.objectId} value={x.objectId}>
|
||||
{x.Name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="buttoncontainer">
|
||||
<button className="submitbutton" onClick={() => handleAdd()}>
|
||||
Add Signer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectSigners;
|
||||
@@ -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({
|
||||
>
|
||||
<BorderResize />
|
||||
<div
|
||||
onClick={(e) => {
|
||||
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
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
color: "black",
|
||||
fontWeight: "600",
|
||||
<i
|
||||
|
||||
className="fa-regular fa-user signCopy"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleLinkUser(data.Id)
|
||||
setUniqueId(data.Id)
|
||||
}}
|
||||
style={{
|
||||
color: "#188ae2",
|
||||
right: 45
|
||||
|
||||
marginTop: "0px"
|
||||
}}
|
||||
>
|
||||
{pos.isStamp
|
||||
? "stamp"
|
||||
: "signature"}
|
||||
}}
|
||||
></i>
|
||||
<i
|
||||
className="fa-regular fa-copy signCopy"
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation();
|
||||
// setIsPageCopy(true);
|
||||
// setSignKey(pos.key);
|
||||
// }}
|
||||
style={{
|
||||
color: "#188ae2"
|
||||
}}
|
||||
></i>
|
||||
<i
|
||||
className="fa-regular fa-circle-xmark signCloseBtn"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDeleteSign(
|
||||
pos.key,
|
||||
data.Id
|
||||
);
|
||||
// data.signerObjId
|
||||
}}
|
||||
style={{
|
||||
color: "#188ae2"
|
||||
}}
|
||||
></i>
|
||||
|
||||
<div
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
color: themeColor(),
|
||||
justifyContent: "center"
|
||||
}}
|
||||
>
|
||||
{pos.isStamp
|
||||
? "stamp"
|
||||
: "signature"}
|
||||
</div>
|
||||
</div>
|
||||
</Rnd>
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@@ -155,13 +156,36 @@ function SignerListPlace({
|
||||
{obj.Name ? (
|
||||
<span className="userName">{obj.Name}</span>
|
||||
) : (
|
||||
<span className="userName">{obj.Role}</span>
|
||||
<>
|
||||
{handleRoleChange ? (
|
||||
<span
|
||||
className="userName"
|
||||
contentEditable
|
||||
onBlur={(e) => handleRoleChange(e, obj.Id)}
|
||||
>
|
||||
{obj.Role}
|
||||
</span>
|
||||
) : (
|
||||
<span className="userName">{obj.Role}</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{obj.Email && (
|
||||
<span className="useEmail">{obj.Email}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{handleDeleteUser && (
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDeleteUser(obj.Id);
|
||||
}}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<i className="fa-regular fa-trash-can"></i>
|
||||
</div>
|
||||
)}
|
||||
{signerPos.map((data, key) => {
|
||||
return (
|
||||
data.Id === obj.Id && (
|
||||
@@ -182,12 +206,12 @@ function SignerListPlace({
|
||||
})}
|
||||
</>
|
||||
</div>
|
||||
{handleAddSigner && (
|
||||
<div className="addSignerBtn" onClick={() => handleAddSigner()}>
|
||||
<i className="fa-solid fa-plus"></i>
|
||||
<span style={{ marginLeft: 2 }}>Add</span>
|
||||
</div>
|
||||
)}
|
||||
{handleAddSigner && (
|
||||
<div className="addSignerBtn" onClick={() => handleAddSigner()}>
|
||||
<i className="fa-solid fa-plus"></i>
|
||||
<span style={{ marginLeft: 2 }}>Add</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user