Merge pull request #1396 from OpenSignLabs/validation

feat: draft template api
This commit is contained in:
Amol
2024-10-29 15:42:53 +05:30
committed by GitHub
32 changed files with 3391 additions and 557 deletions
+5
View File
@@ -35,6 +35,7 @@ const GenerateToken = lazy(() => import("./pages/GenerateToken"));
const Webhook = lazy(() => import("./pages/Webhook"));
const AddAdmin = lazy(() => import("./pages/AddAdmin"));
const UpdateExistUserAdmin = lazy(() => import("./pages/UpdateExistUserAdmin"));
const DraftTemplate = lazy(() => import("./pages/DraftTemplate"));
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
const AppLoader = () => {
@@ -200,6 +201,10 @@ function App() {
<Route path="/users" element={<UserList />} />
</Route>
<Route path="/sso" element={<SSOVerify />} />
<Route
path="/drafttemplate/:jwttoken"
element={<DraftTemplate />}
/>
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
+26 -7
View File
@@ -69,7 +69,21 @@ const BulkSendUi = (props) => {
if (subscription?.plan === "freeplan") {
setIsFreePlan(true);
}
const resCredits = await Parse.Cloud.run("allowedcredits");
const token = props.jwttoken
? { jwttoken: props.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const axiosres = await axios.post(
`${localStorage.getItem("baseUrl")}functions/allowedcredits`,
{},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
}
}
);
const resCredits = axiosres.data && axiosres.data.result;
if (resCredits) {
const allowedcredits = resCredits?.allowedcredits || 0;
const addoncredits = resCredits?.addoncredits || 0;
@@ -81,7 +95,7 @@ const BulkSendUi = (props) => {
}
setAmount((obj) => ({ ...obj, totalcredits: totalcredits }));
}
const getPlaceholder = props.item?.Placeholders;
const getPlaceholder = props?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
@@ -97,7 +111,7 @@ const BulkSendUi = (props) => {
} else {
setIsBulkAvailable(true);
setAdmin((obj) => ({ ...obj, isAdmin: true }));
const getPlaceholder = props.item?.Placeholders;
const getPlaceholder = props?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
@@ -194,7 +208,7 @@ const BulkSendUi = (props) => {
setIsSubmit(true);
// Create a copy of Placeholders array from props.item
let Placeholders = [...props.item.Placeholders];
let Placeholders = [...props.Placeholders];
// Initialize an empty array to store updated documents
let Documents = [];
// Loop through each form
@@ -251,12 +265,16 @@ const BulkSendUi = (props) => {
};
const batchQuery = async (Documents) => {
const serverUrl = localStorage.getItem("baseUrl");
const functionsUrl = `${serverUrl}functions/batchdocuments`;
const token = props.jwttoken
? { jwttoken: props.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const functionsUrl = `${localStorage.getItem(
"baseUrl"
)}functions/batchdocuments`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
...token
};
const params = { Documents: JSON.stringify(Documents) };
try {
@@ -362,6 +380,7 @@ const BulkSendUi = (props) => {
fieldIndex
)
}
jwttoken={props?.jwttoken}
/>
</div>
))}
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import Parse from "parse";
import AsyncSelect from "react-select/async";
import { useTranslation } from "react-i18next";
import axios from "axios";
const SelectSigners = (props) => {
const { t } = useTranslation();
@@ -31,17 +31,19 @@ const SelectSigners = (props) => {
const loadOptions = async (inputValue) => {
try {
const currentUser = Parse.User.current();
const contactbook = new Parse.Query("contracts_Contactbook");
contactbook.equalTo(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
if (inputValue.length > 1) {
contactbook.matches("Name", new RegExp(inputValue, "i"));
}
contactbook.notEqualTo("IsDeleted", true);
const contactRes = await contactbook.find();
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/getsigners`;
const token = props?.jwttoken
? { jwttoken: props?.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
};
const search = inputValue;
const axiosRes = await axios.post(url, { search }, { headers });
const contactRes = axiosRes?.data?.result || [];
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
@@ -25,7 +25,7 @@ const SuggestionInput = (props) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
(async () => {
const res = await findContact(inputValue);
const res = await findContact(inputValue, props.jwttoken);
if (res?.length > 0) {
setSuggestions(res);
setShowSuggestions(true);
@@ -37,6 +37,7 @@ const SuggestionInput = (props) => {
}, 1000);
}
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputValue]);
const handleInputChange = async (e) => {
+59 -28
View File
@@ -34,7 +34,8 @@ export async function fetchSubscription(
extUserId,
contactObjId,
isGuestSign = false,
isPublic = false
isPublic = false,
jwtToken
) {
try {
const Extand_Class = localStorage.getItem("Extand_Class");
@@ -48,10 +49,13 @@ export async function fetchSubscription(
}
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/getsubscriptions`;
const token = jwtToken
? { jwttoken: jwtToken }
: { sessionToken: localStorage.getItem("accesstoken") };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
...token
};
const params = isGuestSign
? { contactId: contactObjId }
@@ -226,12 +230,25 @@ export const pdfNewWidthFun = (divRef) => {
};
//`contractUsers` function is used to get contract_User details
export const contractUsers = async () => {
export const contractUsers = async (jwttoken) => {
try {
const userDetails = await Parse.Cloud.run("getUserDetails");
const url = `${localStorage.getItem("baseUrl")}functions/getUserDetails`;
const parseAppId = localStorage.getItem("parseAppId");
const accesstoken = localStorage.getItem("accesstoken");
const token = jwttoken
? { jwttoken: jwttoken }
: { "X-Parse-Session-Token": accesstoken };
const headers = {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
...token
}
};
const userDetails = await axios.post(url, {}, headers);
let data = [];
if (userDetails) {
const json = JSON.parse(JSON.stringify(userDetails));
if (userDetails?.data?.result) {
const json = JSON.parse(JSON.stringify(userDetails.data.result));
data.push(json);
}
return data;
@@ -1762,14 +1779,17 @@ export const contactBook = async (objectId) => {
};
//function for getting document details from contract_Documents class
export const contractDocument = async (documentId) => {
export const contractDocument = async (documentId, JwtToken) => {
const data = { docId: documentId };
const token = JwtToken
? { jwtToken: JwtToken }
: { sessionToken: localStorage.getItem("accesstoken") };
const documentDeatils = await axios
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
...token
}
})
.then((Listdata) => {
@@ -1969,20 +1989,28 @@ export const getAppLogo = async () => {
}
};
export const getTenantDetails = async (objectId) => {
export const getTenantDetails = async (objectId, jwttoken) => {
try {
const tenantCreditsQuery = new Parse.Query("partners_Tenant");
tenantCreditsQuery.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: objectId
const url = `${localStorage.getItem("baseUrl")}functions/gettenant`;
const parseAppId = localStorage.getItem("parseAppId");
const accesstoken = localStorage.getItem("accesstoken");
const token = jwttoken
? { jwttoken: jwttoken }
: { "X-Parse-Session-Token": accesstoken };
const data = jwttoken ? {} : { userId: objectId };
const res = await axios.post(url, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
...token
}
});
const res = await tenantCreditsQuery.first();
if (res) {
const updateRes = JSON.parse(JSON.stringify(res));
const updateRes = JSON.parse(JSON.stringify(res.data.result));
return updateRes;
}
} catch (e) {
} catch (err) {
console.log("err in gettenant", err);
return "user does not exist!";
}
};
@@ -2231,18 +2259,21 @@ export const handleDownloadCertificate = async (
}
}
};
export async function findContact(value) {
export async function findContact(value, jwttoken) {
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);
contactbook.matches("Email", new RegExp(value, "i"));
const contactRes = await contactbook.find();
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/getsigners`;
const token = jwttoken
? { jwttoken: jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
};
const searchEmail = value;
const axiosRes = await axios.post(url, { searchEmail }, { headers });
const contactRes = axiosRes?.data?.result || [];
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
return res;
File diff suppressed because it is too large Load Diff
@@ -132,12 +132,10 @@ function PdfRequestFiles(props) {
const [publicRes, setPublicRes] = useState({});
const [documentId, setDocumentId] = useState("");
const [isPublicContact, setIsPublicContact] = useState(false);
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
const [plancode, setPlanCode] = useState("");
const isHeader = useSelector((state) => state.showHeader);
const divRef = useRef(null);
const [isDownloadModal, setIsDownloadModal] = useState(false);
const isMobile = window.innerWidth < 767;
let isGuestSignFlow = false;
@@ -323,8 +321,6 @@ function PdfRequestFiles(props) {
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
setHandleError(t("something-went-wrong-mssg"));
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError(t("something-went-wrong-mssg"));
@@ -408,8 +404,6 @@ function PdfRequestFiles(props) {
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
setHandleError(t("something-went-wrong-mssg"));
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError(t("something-went-wrong-mssg"));
+57 -122
View File
@@ -1,7 +1,8 @@
import React, { useState, useEffect } from "react";
import Parse from "parse";
import Loader from "./Loader";
import { useTranslation } from "react-i18next";
import axios from "axios";
import { getTenantDetails } from "../constant/Utils";
const AddContact = (props) => {
const { t } = useTranslation();
const [name, setName] = useState("");
@@ -12,6 +13,7 @@ const AddContact = (props) => {
const [isUserExist, setIsUserExist] = useState(false);
useEffect(() => {
checkUserExist();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Load user details from localStorage when the component mounts
useEffect(() => {
@@ -26,19 +28,24 @@ const AddContact = (props) => {
}, [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) {
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/isuserincontactbook`;
const token = props?.jwttoken
? { jwttoken: props?.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
};
const axiosRes = await axios.post(url, {}, { headers });
const contactRes = axiosRes?.data?.result || {};
if (!contactRes?.objectId) {
setIsUserExist(true);
}
} catch (err) {
console.log("err", err);
console.log("err ", err);
}
};
// Define a function to handle form submission
@@ -46,123 +53,51 @@ const AddContact = (props) => {
e.preventDefault();
e.stopPropagation();
setIsLoader(true);
if (localStorage.getItem("TenantId")) {
const user = JSON.parse(
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
);
const userId = user?.objectId || "";
const tenantDetails = await getTenantDetails(userId, props.jwttoken);
console.log("tenantDetails", tenantDetails);
const tenantId = tenantDetails?.objectId || "";
if (tenantId) {
try {
const user = Parse.User.current();
const query = new Parse.Query("contracts_Contactbook");
query.equalTo("CreatedBy", user);
query.notEqualTo("IsDeleted", true);
query.equalTo("Email", email);
const res = await query.first();
if (!res) {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
if (phone) {
contactQuery.set("Phone", phone);
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/savecontact`;
const token = props?.jwttoken
? { jwttoken: props?.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const data = { name, email, phone, tenantId };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
};
const axiosRes = await axios.post(url, data, { headers });
const contactRes = axiosRes?.data?.result || {};
if (contactRes?.objectId) {
console.log("contactRes ", contactRes);
props.details(contactRes);
if (props.closePopup) {
props.closePopup();
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest");
if (localStorage.getItem("TenantId")) {
contactQuery.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
}
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("password", email);
if (phone) {
_user.set("phone", phone);
}
const user = await _user.save();
if (user) {
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 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));
if (props.details) {
props.details(parseData);
}
if (props.closePopup) {
props.closePopup();
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
}
} else {
alert(t("add-signer-alert"));
setIsLoader(false);
}
} catch (err) {
// console.log("err", err);
console.log("Err", err);
setIsLoader(false);
alert(t("something-went-wrong-mssg"));
if (err?.response?.data?.error?.includes("already exists")) {
alert(t("add-signer-alert"));
} else {
alert(t("something-went-wrong-mssg"));
}
}
} else {
setIsLoader(false);
@@ -19,11 +19,16 @@ const LinkUserModal = (props) => {
details={props.handleAddUser}
closePopup={props.closePopup}
signersData={props?.signersData}
jwttoken={props?.jwttoken}
/>
<div className="op-divider text-base-content mx-[25%] my-1">
{t("or")}
</div>
<AddContact details={props.handleAddUser} closePopup={props.closePopup} />
<AddContact
details={props.handleAddUser}
closePopup={props.closePopup}
jwttoken={props?.jwttoken}
/>
</ModalUi>
);
};