Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into rotatepage_document

This commit is contained in:
RaktimaNXG
2024-08-27 17:22:53 +05:30
17 changed files with 950 additions and 894 deletions
+569 -478
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -4,16 +4,16 @@
"private": true,
"dependencies": {
"@formkit/auto-animate": "^0.8.2",
"@lottiefiles/dotlottie-react": "^0.8.7",
"@lottiefiles/dotlottie-react": "^0.8.9",
"@pdf-lib/fontkit": "^1.1.1",
"@radix-ui/themes": "^3.1.3",
"@react-pdf/renderer": "^3.4.4",
"@reduxjs/toolkit": "^2.2.7",
"axios": "^1.7.4",
"file-saver": "^2.0.5",
"i18next": "^23.12.2",
"i18next": "^23.14.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.5.2",
"i18next-http-backend": "^2.6.1",
"jwt-decode": "^4.0.0",
"moment": "^2.30.1",
"nth-check": "^2.1.1",
@@ -36,10 +36,10 @@
"react-i18next": "^15.0.1",
"react-konva": "^18.2.10",
"react-pdf": "^9.1.0",
"react-quill-new": "^3.2.2",
"react-quill-new": "^3.3.0",
"react-redux": "^9.1.2",
"react-rnd": "^10.4.11",
"react-router-dom": "^6.26.0",
"react-router-dom": "^6.26.1",
"react-scripts": "5.0.1",
"react-scrollbars-custom": "^4.1.1",
"react-select": "^5.8.0",
@@ -94,9 +94,9 @@
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/preset-env": "^7.25.4",
"@babel/preset-react": "^7.24.7",
"@babel/runtime-corejs2": "^7.25.0",
"@babel/runtime-corejs2": "^7.25.4",
"autoprefixer": "^10.4.20",
"babel-loader": "^9.1.3",
"clean-webpack-plugin": "^4.0.0",
@@ -110,7 +110,7 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.8",
"mini-css-extract-plugin": "^2.9.0",
"mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.41",
"prettier": "^3.3.3",
"pretty-quick": "^4.0.0",
@@ -618,5 +618,6 @@
"rotate-right":"Rotate right",
"rotate-left":"Rotate left",
"rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?",
"templateid":"Template-Id"
"templateid":"Template-Id",
"bulksendsubcriptionalert":"Please upgrade to Professional or Team plan to use quicksend."
}
@@ -618,5 +618,6 @@
"rotate-right" :"Faire pivoter à droite",
"rotate-left" :"Faire pivoter à gauche",
"rotate-alert-mssg" :"Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
"templateid":"ID de modèle"
"templateid":"ID de modèle",
"bulksendsubcriptionalert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend."
}
+66 -39
View File
@@ -6,8 +6,11 @@ import { useTranslation } from "react-i18next";
import Parse from "parse";
import ModalUi from "../primitives/ModalUi";
import { isEnableSubscription } from "../constant/const";
import { fetchSubscription } from "../constant/Utils";
import { useNavigate } from "react-router-dom";
const BulkSendUi = (props) => {
const { t } = useTranslation();
const navigate = useNavigate();
const [forms, setForms] = useState([]);
const [formId, setFormId] = useState(2);
const formRef = useRef(null);
@@ -25,6 +28,7 @@ const BulkSendUi = (props) => {
});
const [isQuotaReached, setIsQuotaReached] = useState(false);
const [isLoader, setIsLoader] = useState(false);
const [isFreePlan, setIsFreePlan] = useState(false);
const allowedSigners = 50;
useEffect(() => {
signatureExist();
@@ -36,6 +40,10 @@ const BulkSendUi = (props) => {
if (isEnableSubscription) {
setIsLoader(true);
try {
const subscription = await fetchSubscription();
if (subscription?.plan === "freeplan") {
setIsFreePlan(true);
}
const allowedquicksend = await Parse.Cloud.run("allowedquicksend");
if (allowedquicksend > 0) {
setIsBulkAvailable(true);
@@ -273,6 +281,9 @@ const BulkSendUi = (props) => {
const handleCloseQuotaReached = () => {
setIsQuotaReached(false);
};
const handleNavigation = () => {
navigate("/subscription");
};
return (
<>
{isLoader ? (
@@ -385,46 +396,62 @@ const BulkSendUi = (props) => {
)}
</>
) : (
<form onSubmit={handleAddOnQuickSubmit} className="p-3">
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
{t("additional-quicksend")}
</p>
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("quantityofquicksend")}
<span className="text-[red] text-[13px]">*</span>
</label>
<select
value={amount.quantity}
onChange={(e) => handlePricePerQuick(e)}
name="quantity"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
required
>
{quantityList.length > 0 &&
quantityList.map((x) => (
<option key={x} value={x}>
{x}
</option>
))}
</select>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {amount.priceperbulksend})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
<>
{isFreePlan ? (
<div className="w-full h-[130px] flex flex-col justify-center items-center text-center p-4">
<p className="text-base font-medium mb-2.5">
{t("bulksendsubcriptionalert")}
</p>
<button
onClick={() => handleNavigation()}
className="op-btn op-btn-primary"
>
{t("upgrade-now")}
</button>
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full mt-2">
{t("Proceed")}
</button>
</form>
) : (
<form onSubmit={handleAddOnQuickSubmit} className="p-3">
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
{t("additional-quicksend")}
</p>
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("quantityofquicksend")}
<span className="text-[red] text-[13px]">*</span>
</label>
<select
value={amount.quantity}
onChange={(e) => handlePricePerQuick(e)}
name="quantity"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
required
>
{quantityList.length > 0 &&
quantityList.map((x) => (
<option key={x} value={x}>
{x}
</option>
))}
</select>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {amount.priceperbulksend})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full mt-2">
{t("Proceed")}
</button>
</form>
)}
</>
)}
</>
)}
@@ -54,7 +54,7 @@ function DraftDocument() {
navigate(`/recipientSignPdf/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
else if ((!signerExist && !isPlaceholder) || data?.IsSignyourself) {
navigate(`/signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
@@ -554,7 +554,7 @@ function RenderPdf({
</React.Fragment>
);
})
: xyPostion.map((data, ind) => {
: xyPostion?.map((data, ind) => {
// signyourself flow
return (
<React.Fragment key={ind}>
+31 -16
View File
@@ -9,14 +9,13 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
import { validplan } from "../json/plansArr";
import { useTranslation } from "react-i18next";
import Parse from "parse";
function GenerateToken() {
const { t } = useTranslation();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const [apiToken, SetApiToken] = useState("");
const [isLoader, setIsLoader] = useState(true);
const [isModal, setIsModal] = useState({
@@ -50,11 +49,17 @@ function GenerateToken() {
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
}
const res = await Parse.Cloud.run("getapitoken");
const url = parseBaseUrl + "functions/getapitoken";
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessiontoken: localStorage.getItem("accesstoken")
};
const res = await axios.post(url, {}, { headers: headers });
if (res) {
const allowedapis = await Parse.Cloud.run("allowedapis");
setAmount((obj) => ({ ...obj, totalapis: allowedapis }));
SetApiToken(res?.result);
SetApiToken(res?.data?.result?.result);
}
setIsLoader(false);
} catch (err) {
@@ -65,7 +70,7 @@ function GenerateToken() {
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!validplan[isSubscribe.plan] && isEnableSubscription) {
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
setIsLoader(true);
@@ -103,11 +108,19 @@ function GenerateToken() {
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
};
const handleModal = () => {
setIsModal((obj) => ({ ...obj, generateapi: !obj.generateapi }));
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal((obj) => ({ ...obj, generateapi: !obj.generateapi }));
}
};
const handleBuyAPIsModal = () => {
setIsModal((obj) => ({ ...obj, buyapis: !obj.buyapis }));
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal((obj) => ({ ...obj, buyapis: !obj.buyapis }));
}
};
const handlePricePerAPIs = (e) => {
@@ -115,7 +128,7 @@ function GenerateToken() {
const price =
quantity > 0
? (Math.round(quantity * amount.priceperapi * 100) / 100).toFixed(2)
: 500 * amount.priceperapi;
: (Math.round(500 * amount.priceperapi * 100) / 100).toFixed(2);
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
};
const handleAddOnApiSubmit = async (e) => {
@@ -131,7 +144,7 @@ function GenerateToken() {
if (_resAddon.status === "success") {
setAmount((obj) => ({
...obj,
quantity: 1,
quantity: 500,
priceperapi: 0.15,
price: (75.0).toFixed(2),
totalapis: _resAddon.addon
@@ -172,16 +185,18 @@ function GenerateToken() {
<span
id="token"
className={`${
validplan[isSubscribe.plan]
? ""
: "bg-white/20 pointer-events-none select-none"
isSubscribe?.plan === "freeplan"
? "bg-white/20 pointer-events-none select-none"
: ""
} md:text-end py-2 md:py-0`}
>
<span
className="cursor-pointer"
onClick={() => copytoclipboard(apiToken)}
>
{apiToken ? apiToken : "_____"}
{isSubscribe?.plan !== "freeplan" && apiToken
? apiToken
: "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
@@ -299,9 +314,9 @@ function GenerateToken() {
</form>
</ModalUi>
</div>
{!validplan[isSubscribe.plan] && isEnableSubscription && (
{isSubscribe?.plan === "freeplan" && isEnableSubscription && (
<div data-tut="apisubscribe">
<SubscribeCard plan_code={isSubscribe.plan} />
<SubscribeCard plan_code={isSubscribe?.plan} />
</div>
)}
</>
+30 -58
View File
@@ -34,7 +34,8 @@ import {
openInNewTab,
getDefaultSignature,
onClickZoomIn,
onClickZoomOut
onClickZoomOut,
fetchUrl
} from "../constant/Utils";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
@@ -426,16 +427,11 @@ function PdfRequestFiles(props) {
}
if (isCompleted) {
setIsSigned(true);
const data = {
isCertificate: true,
isModal: true
};
const data = { isCertificate: true, isModal: true };
setAlreadySign(true);
setIsCompleted(data);
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setTimeout(() => setIsCelebration(false), 5000);
} else if (declined) {
const currentDecline = {
currnt: "another",
@@ -451,9 +447,7 @@ function PdfRequestFiles(props) {
} // Check if the current signer is not a last signer and handle the complete message.
else if (isNextUser) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setTimeout(() => setIsCelebration(false), 5000);
setIsCompleted({
isModal: true,
message: t("document-signed-alert-1")
@@ -480,7 +474,8 @@ function PdfRequestFiles(props) {
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId && data.Activity === "Signed"
data.UserPtr?.objectId === currUserId &&
data.Activity === "Signed"
);
if (
checkAlreadySign &&
@@ -560,15 +555,15 @@ function PdfRequestFiles(props) {
for (const item of placeholdersOrSigners) {
const checkEmail = item?.email;
//if email exist then compare user signed by using email else signers objectId
const emailOrId = checkEmail ? item.email : item.objectId;
const emailOrId = checkEmail ? item.email : item?.objectId;
//`isSignedSignature` variable to handle break loop whenever it get true
let isSignedSignature = false;
//checking the signer who signed the document by using audit trail details.
//and save signedSigners and unsignedSigners details
for (const doc of audittrailData) {
const signedExist = checkEmail
? doc?.UserPtr.Email
: doc?.UserPtr.objectId;
? doc?.UserPtr?.Email
: doc?.UserPtr?.objectId;
if (emailOrId === signedExist) {
signers.push({ ...item });
@@ -646,15 +641,11 @@ function PdfRequestFiles(props) {
(documentData.result && documentData.result.error)
) {
setHandleError(t("something-went-wrong-mssg"));
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
console.log("err in getDocument cloud function ");
} else {
setHandleError(t("no-data"));
setIsUiLoading({
isLoad: false
});
setIsUiLoading({ isLoad: false });
}
//function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId);
@@ -664,15 +655,11 @@ function PdfRequestFiles(props) {
} else if (defaultSignRes?.status === "error") {
setHandleError("Error: Something went wrong!");
}
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
} catch (err) {
console.log("Error: error in getDocumentDetails", err);
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
}
};
//function for embed signature or image url in pdf
@@ -1030,9 +1017,7 @@ function PdfRequestFiles(props) {
openSignUrl +
" target=_blank>here</a>.</p> </div></div></body> </html>"
};
await axios.post(url, params, {
headers: headers
});
await axios.post(url, params, { headers: headers });
} catch (error) {
console.log("error", error);
}
@@ -1195,10 +1180,7 @@ function PdfRequestFiles(props) {
const img = new Image();
img.src = defaultSignImg;
if (img.complete) {
imgWH = {
width: img.width,
height: img.height
};
imgWH = { width: img.width, height: img.height };
}
}
//get current signer placeholder position data
@@ -1258,10 +1240,7 @@ function PdfRequestFiles(props) {
.then(async (result) => {
const res = result.data;
if (res) {
const currentDecline = {
currnt: "YouDeclined",
isDeclined: true
};
const currentDecline = { currnt: "YouDeclined", isDeclined: true };
setIsDecline(currentDecline);
setIsUiLoading(false);
const params = {
@@ -1320,10 +1299,7 @@ function PdfRequestFiles(props) {
x.signerObjId === signerObjectId ? { ...x, placeHolder: updatePlace } : x
);
setSignerPos(updatesignerPos);
setDefaultSignAlert({
isShow: false,
alertMessage: ""
});
setDefaultSignAlert({ isShow: false, alertMessage: "" });
};
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
@@ -1504,7 +1480,6 @@ function PdfRequestFiles(props) {
const SendOtp = async () => {
try {
const params = { email: contact.email, docId: res.docId };
const Otp = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/SendOTPMailV1`,
params,
@@ -1542,10 +1517,7 @@ function PdfRequestFiles(props) {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseId
};
let body = {
email: contact.email,
otp: otp
};
let body = { email: contact.email, otp: otp };
let user = await axios.post(url, body, { headers: headers });
if (user.data.result === "Invalid Otp") {
alert(t("invalid-otp"));
@@ -1577,9 +1549,7 @@ function PdfRequestFiles(props) {
// document.getElementById("my_modal").close();
setIsPublicContact(false);
setIsPublicTemplate(false);
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
setDocumentId(res?.docId);
getDocumentDetails(res?.docId);
}
@@ -1595,11 +1565,7 @@ function PdfRequestFiles(props) {
setLoading(false);
setIsOtp(false);
setOtp();
setContact({
name: "",
email: "",
phone: ""
});
setContact({ name: "", email: "", phone: "" });
};
const clickOnZoomIn = () => {
@@ -1608,6 +1574,11 @@ function PdfRequestFiles(props) {
const clickOnZoomOut = () => {
onClickZoomOut(zoomPercent, scale, setZoomPercent, setScale);
};
const handleDownloadBtn = async () => {
const url = pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL;
const name = pdfDetails?.[0]?.Name;
await fetchUrl(url, name);
};
return (
<DndProvider backend={HTML5Backend}>
<Title title={props.templateId ? "Public Sign" : "Request Sign"} />
@@ -1698,9 +1669,9 @@ function PdfRequestFiles(props) {
headMsg={t("document-decline")}
bodyMssg={
isDecline.currnt === "Sure"
? t("decline-alert-2")
? t("decline-alert-1")
: isDecline.currnt === "YouDeclined"
? t("decline-alert-1")
? t("decline-alert-2")
: isDecline.currnt === "another" && t("decline-alert-3")
}
footerMessage={isDecline.currnt === "Sure"}
@@ -1712,6 +1683,8 @@ function PdfRequestFiles(props) {
show={isExpired}
headMsg={t("expired-doc-title")}
bodyMssg={t("expired-on-mssg", { expiredDate })}
isDownloadBtn={true}
handleDownloadBtn={handleDownloadBtn}
/>
{!isEmailVerified && (
<VerifyEmail
@@ -1725,7 +1698,6 @@ function PdfRequestFiles(props) {
handleResend={handleResend}
/>
)}
<ModalUi
isOpen={isPublicContact}
title={isOtp ? t("verify-email-1") : t("contact-details")}
+66 -135
View File
@@ -77,7 +77,7 @@ function PlaceHolderSign() {
const [signBtnPosition, setSignBtnPosition] = useState([]);
const [xySignature, setXYSignature] = useState({});
const [dragKey, setDragKey] = useState();
const [signersdata, setSignersData] = useState();
const [signersdata, setSignersData] = useState([]);
const [signerObjId, setSignerObjId] = useState();
const [signerPos, setSignerPos] = useState([]);
const [isSelectListId, setIsSelectId] = useState();
@@ -165,24 +165,14 @@ function PlaceHolderSign() {
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 1,
text: "signature"
},
item: { type: "BOX", id: 1, text: "signature" },
collect: (monitor) => ({
isDragSign: !!monitor.isDragging()
})
});
const [{ isDragStamp }, dragStamp] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 2,
text: "stamp"
},
item: { type: "BOX", id: 2, text: "stamp" },
collect: (monitor) => ({
isDragStamp: !!monitor.isDragging()
})
@@ -202,7 +192,6 @@ function PlaceHolderSign() {
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
);
if (user) {
try {
const defaultRequestBody = `<p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}}&nbsp;has requested you to review and sign&nbsp;{{document_title}}.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br>`;
@@ -241,10 +230,8 @@ function PlaceHolderSign() {
setZoomPercent(0);
}
};
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
@@ -345,11 +332,13 @@ function PlaceHolderSign() {
) {
setSignerPos(documentData[0].Placeholders);
let signers = [...documentData[0].Signers];
let updatedSigners = documentData[0].Placeholders.map((x) => {
const placeholder = documentData[0]?.Placeholders.filter(
(data) => data.Role !== "prefill"
);
let updatedSigners = placeholder.map((x) => {
let matchingSigner = signers.find(
(y) => x.signerObjId && x.signerObjId === y.objectId
);
if (matchingSigner) {
return {
...matchingSigner,
@@ -358,11 +347,7 @@ function PlaceHolderSign() {
blockColor: x.blockColor
};
} else {
return {
Role: x.Role,
Id: x.Id,
blockColor: x.blockColor
};
return { Role: x.Role, Id: x.Id, blockColor: x.blockColor };
}
});
setSignersData(updatedSigners);
@@ -385,14 +370,12 @@ function PlaceHolderSign() {
documentData[0].Placeholders &&
documentData[0].Placeholders.length > 0
) {
let updatedSigners = documentData[0].Placeholders.map((x) => {
return {
Role: x.Role,
Id: x.Id,
blockColor: x.blockColor
};
const placeholder = documentData[0]?.Placeholders.filter(
(data) => data.Role !== "prefill"
);
let updatedSigners = placeholder.map((x) => {
return { Role: x.Role, Id: x.Id, blockColor: x.blockColor };
});
setSignerPos(documentData[0].Placeholders);
setSignersData(updatedSigners);
setIsSelectId(0);
@@ -404,25 +387,16 @@ function PlaceHolderSign() {
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} else {
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
}
const res = await contractUsers();
if (res === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} else if (res.length && res[0]?.objectId) {
setActiveMailAdapter(res[0]?.active_mail_adapter);
setSignerUserId(res[0].objectId);
@@ -439,16 +413,10 @@ function PlaceHolderSign() {
setCheckTourStatus(checkTourRecipients[0].placeholder);
}
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} else if (res.length === 0) {
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
}
};
@@ -495,10 +463,7 @@ function PlaceHolderSign() {
Height: widgetHeight / (containerScale * scale)
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: dropData
};
placeHolder = { pageNumber: pageNumber, pos: dropData };
} else {
const offset = monitor.getClientOffset();
//This method returns the offset of the current pointer (mouse) position relative to the client viewport.
@@ -528,12 +493,8 @@ function PlaceHolderSign() {
Width: widgetWidth / (containerScale * scale),
Height: widgetHeight / (containerScale * scale)
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: dropData
};
placeHolder = { pageNumber: pageNumber, pos: dropData };
}
setSelectWidgetId(key);
if (signer) {
@@ -554,15 +515,11 @@ function PlaceHolderSign() {
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
};
let xyPos = { pageNumber: pageNumber, pos: newSignPos };
updatePlace.push(xyPos);
let updatesignerPos;
if (dragTypeValue === textWidget) {
@@ -574,7 +531,6 @@ function PlaceHolderSign() {
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
);
}
setSignerPos(updatesignerPos);
} else {
let updatesignerPos;
@@ -706,14 +662,11 @@ function PlaceHolderSign() {
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((url) => {
if (url.key === keyValue) {
@@ -742,36 +695,28 @@ function PlaceHolderSign() {
return { ...obj, placeHolder: newUpdateSignPos };
}
}
return obj;
});
setSignerPos(newUpdateSigner);
}
}
}
}
setTimeout(() => {
setIsDragging(false);
}, 200);
setTimeout(() => setIsDragging(false), 200);
};
//function for delete signature block
const handleDeleteSign = (key, Id) => {
const updateData = [];
const filterSignerPos = signerPos.filter((data) => data.Id === Id);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos.filter(
(data) => data.key !== key
);
if (getXYdata.length > 0) {
updateData.push(getXYdata);
const newUpdatePos = getPlaceHolder.map((obj) => {
@@ -804,7 +749,6 @@ function PlaceHolderSign() {
let signerupdate = [];
signerupdate = signerPos.filter((data) => data.Id !== Id);
signerupdate.push(newUpdatePos[0]);
setSignerPos(signerupdate);
} else {
setSignerPos(updateFilter);
@@ -829,20 +773,11 @@ function PlaceHolderSign() {
const touch = e.touches[0]; // Get the first touch point
mouseX = touch.clientX - divRect.left;
mouseY = touch.clientY - divRect.top;
setSignBtnPosition([
{
xPos: mouseX,
yPos: mouseY
}
]);
setSignBtnPosition([{ xPos: mouseX, yPos: mouseY }]);
} else {
mouseX = e.clientX - divRect.left;
mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
setXYSignature(xyPosition);
setXYSignature({ xPos: mouseX, yPos: mouseY });
}
};
@@ -925,18 +860,11 @@ function PlaceHolderSign() {
}
if (!signatureExist) {
isSignatureExist = false;
setIsSendAlert({
mssg: "sure",
alert: true
});
setIsSendAlert({ mssg: "sure", alert: true });
}
}
if (getPrefill && isLabel) {
setIsSendAlert({
mssg: textWidget,
alert: true
});
setIsSendAlert({ mssg: textWidget, alert: true });
} else if (isSignatureExist) {
if (filterPrefill.length === signersdata.length) {
const IsSignerNotExist = filterPrefill?.filter((x) => !x.signerObjId);
@@ -949,13 +877,42 @@ function PlaceHolderSign() {
saveDocumentDetails();
}
} else {
setIsSendAlert({
mssg: "sure",
alert: true
});
setIsSendAlert({ mssg: "sure", alert: true });
}
}
};
useEffect(() => {
const timer = setTimeout(() => {
if (signerPos?.length > 0) {
autosavedetails();
}
}, 2000);
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [signerPos]);
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
const autosavedetails = async () => {
const signers = signersdata?.filter(
(x) =>
x?.Role !== "prefill" && {
__type: "Pointer",
className: "contracts_Contactbook",
objectId: x.objectId
}
);
try {
const docCls = new Parse.Object("contracts_Document");
docCls.id = documentId;
docCls.set("Placeholders", signerPos);
docCls.set("Signers", signers);
await docCls.save();
} catch (e) {
console.log("error", e);
alert(t("something-went-wrong-mssg"));
}
};
//function to use save placeholder details in contracts_document
const saveDocumentDetails = async () => {
setIsUiLoading(true);
@@ -995,10 +952,7 @@ function PlaceHolderSign() {
SignedUrl: pdfUrl,
Signers: signers,
SentToOthers: true,
ExpiryDate: {
iso: updateExpiryDate,
__type: "Date"
}
ExpiryDate: { iso: updateExpiryDate, __type: "Date" }
};
} else {
data = {
@@ -1024,15 +978,10 @@ function PlaceHolderSign() {
)
.then(() => {
setIsMailSend(true);
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
setIsUiLoading(false);
setSignerPos([]);
setIsSendAlert({
mssg: "confirm",
alert: true
});
setIsSendAlert({ mssg: "confirm", alert: true });
})
.catch((err) => {
console.log("axois err ", err);
@@ -1047,9 +996,7 @@ function PlaceHolderSign() {
const copytoclipboard = (text) => {
copytoData(text);
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 1500); // Reset copied state after 1.5 seconds
setTimeout(() => setCopied(false), 1500); // Reset copied state after 1.5 seconds
};
//function show signer list and share link to share signUrl
const handleShareList = () => {
@@ -1085,12 +1032,7 @@ function PlaceHolderSign() {
<i className="fa-light fa-link" aria-hidden="true"></i>
<span className=" hidden md:block ml-1 ">{t("copy-link")}</span>
</button>
<RWebShare
data={{
url: data.url,
title: t("sign-url")
}}
>
<RWebShare data={{ url: data.url, title: t("sign-url") }}>
<i className="fa-light fa-share-from-square op-link op-link-secondary no-underline"></i>
</RWebShare>
</div>
@@ -1219,9 +1161,7 @@ function PlaceHolderSign() {
SendMail: true
};
} else {
data = {
SendMail: true
};
data = { SendMail: true };
}
await axios
@@ -1339,14 +1279,11 @@ function PlaceHolderSign() {
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
@@ -1631,9 +1568,7 @@ function PlaceHolderSign() {
}
return { ...x };
});
setSignerPos(updatePlaceHolder);
const updateSigner = signersdata.map((x) => {
if (x.Id === uniqueId) {
return { ...x, ...data, className: "contracts_Contactbook" };
@@ -1687,7 +1622,7 @@ function PlaceHolderSign() {
{
selector: '[data-tut="assignSigner"]',
content:
" You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour. ",
"You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour. ",
position: "top",
style: { fontSize: "13px" }
}
@@ -1712,7 +1647,6 @@ function PlaceHolderSign() {
setIsSelectId(index);
setBlockColor(color[index]);
}
setSignerPos(updatePlaceholderUser);
setIsMailSend(false);
};
@@ -1817,7 +1751,6 @@ function PlaceHolderSign() {
/>
<div className=" w-full md:w-[95%] ">
{/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi
isOpen={isSendAlert.alert}
title={
@@ -1948,7 +1881,6 @@ function PlaceHolderSign() {
{t("yes")}
</button>
)}
<button
onClick={() => {
setIsSend(false);
@@ -2206,7 +2138,6 @@ function PlaceHolderSign() {
</div>
</div>
)}
<ModalUi
isOpen={isAlreadyPlace.status}
title={t("document-alert")}
+62 -98
View File
@@ -165,7 +165,7 @@ function SignYourSelf() {
})
});
const index = xyPostion.findIndex((object) => {
const index = xyPostion?.findIndex((object) => {
return object.pageNumber === pageNumber;
});
// rowlevel={JSON.parse(localStorage.getItem("rowlevel"))}
@@ -211,7 +211,6 @@ function SignYourSelf() {
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
@@ -226,6 +225,11 @@ function SignYourSelf() {
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const placeholders =
documentData[0]?.Placeholders?.length > 0
? documentData[0]?.Placeholders
: [];
setXyPostion(placeholders);
const url = documentData[0] && documentData[0]?.URL;
if (url) {
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
@@ -238,21 +242,17 @@ function SignYourSelf() {
} else {
setHandleError(t("something-went-wrong-mssg"));
}
isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
isCompleted = documentData?.[0]?.IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setTimeout(() => setIsCelebration(false), 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: t("document-signed-alert")
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
setShowAlreadySignDoc({
status: true,
mssg: t("document-signed-alert")
});
} else {
setIsUiLoading(false);
setIsSignPad(false);
@@ -265,17 +265,11 @@ function SignYourSelf() {
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} else {
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
}
//function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId);
@@ -284,17 +278,12 @@ function SignYourSelf() {
setMyInitial(defaultSignRes?.res?.defaultInitial);
} else if (defaultSignRes?.status === "error") {
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
});
setIsLoading({ isLoad: false });
}
const contractUsersRes = await contractUsers();
if (contractUsersRes === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} else if (contractUsersRes[0] && contractUsersRes.length > 0) {
setActiveMailAdapter(contractUsersRes[0]?.active_mail_adapter);
setContractName("_Users");
@@ -374,51 +363,32 @@ function SignYourSelf() {
const addWidgetOptions = (type) => {
switch (type) {
case "signature":
return {
name: "signature"
};
return { name: "signature" };
case "stamp":
return {
name: "stamp"
};
return { name: "stamp" };
case "checkbox":
return {
name: "checkbox"
};
return { name: "checkbox" };
case textWidget:
return {
name: "text"
};
return { name: "text" };
case "initials":
return {
name: "initials"
};
return { name: "initials" };
case "name":
return {
name: "name",
defaultValue: getWidgetValue(type),
validation: {
type: "text",
pattern: ""
}
validation: { type: "text", pattern: "" }
};
case "company":
return {
name: "company",
defaultValue: getWidgetValue(type),
validation: {
type: "text",
pattern: ""
}
validation: { type: "text", pattern: "" }
};
case "job title":
return {
name: "job title",
defaultValue: getWidgetValue(type),
validation: {
type: "text",
pattern: ""
}
validation: { type: "text", pattern: "" }
};
case "date":
return {
@@ -427,17 +397,12 @@ function SignYourSelf() {
validation: { format: "MM/dd/yyyy", type: "date-format" }
};
case "image":
return {
name: "image"
};
return { name: "image" };
case "email":
return {
name: "email",
defaultValue: getWidgetValue(type),
validation: {
type: "email",
pattern: ""
}
validation: { type: "email", pattern: "" }
};
default:
return {};
@@ -449,7 +414,7 @@ function SignYourSelf() {
const key = randomId();
let dropData = [];
let dropObj = {};
let filterDropPos = xyPostion.filter(
let filterDropPos = xyPostion?.filter(
(data) => data.pageNumber === pageNumber
);
const dragTypeValue = item?.text ? item.text : monitor.type;
@@ -486,7 +451,6 @@ function SignYourSelf() {
Height: getHeight / (containerScale * scale),
options: addWidgetOptions(dragTypeValue)
};
dropData.push(dropObj);
} else {
//This method returns the offset of the current pointer (mouse) position relative to the client viewport.
@@ -519,25 +483,18 @@ function SignYourSelf() {
options: addWidgetOptions(dragTypeValue),
scale: containerScale
};
dropData.push(dropObj);
}
if (filterDropPos.length > 0) {
const index = xyPostion.findIndex((object) => {
if (filterDropPos?.length > 0) {
const index = xyPostion?.findIndex((object) => {
return object.pageNumber === pageNumber;
});
const updateData = filterDropPos[0].pos;
const updateData = filterDropPos?.[0].pos;
const newSignPos = updateData.concat(dropData);
let xyPos = {
pageNumber: pageNumber,
pos: newSignPos
};
xyPostion.splice(index, 1, xyPos);
let xyPos = { pageNumber: pageNumber, pos: newSignPos };
xyPostion?.splice(index, 1, xyPos);
} else {
const xyPos = {
pageNumber: pageNumber,
pos: dropData
};
const xyPos = { pageNumber: pageNumber, pos: dropData };
setXyPostion((prev) => [...prev, xyPos]);
}
@@ -549,7 +506,6 @@ function SignYourSelf() {
) {
setIsSignPad(true);
}
if (dragTypeValue === "stamp" || dragTypeValue === "image") {
setIsStamp(true);
} else if (dragTypeValue === "initials") {
@@ -612,6 +568,30 @@ function SignYourSelf() {
setIsVerifyModal(true);
await handleSendOTP(Parse.User.current().getEmail());
};
useEffect(() => {
const timer = setTimeout(() => {
if (xyPostion?.length > 0) {
autosavedetails();
}
}, 2000);
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [xyPostion]);
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
const autosavedetails = async () => {
try {
const docCls = new Parse.Object("contracts_Document");
docCls.id = documentId;
docCls.set("Placeholders", xyPostion);
docCls.set("IsSignyourself", true);
const res = await docCls.save();
console.log("Res", res);
} catch (e) {
console.log("error", e);
alert(t("something-went-wrong-mssg"));
}
};
//function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url
async function embedWidgetsData() {
//check current user email is verified or not
@@ -791,7 +771,6 @@ function SignYourSelf() {
const getNewse64 = await changeImageWH(base64Sign);
//remove suffiix of base64
const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
const params = {
pdfFile: base64Url,
docId: documentId,
@@ -825,10 +804,10 @@ function SignYourSelf() {
containerWH
);
if (dragKey >= 0) {
const filterDropPos = xyPostion.filter(
const filterDropPos = xyPostion?.filter(
(data) => data.pageNumber === pageNumber
);
if (filterDropPos.length > 0) {
if (filterDropPos?.length > 0) {
const getXYdata = xyPostion[index].pos;
const getPosData = getXYdata;
const addSign = getPosData.map((url) => {
@@ -899,15 +878,11 @@ function SignYourSelf() {
setIsSignPad(false);
setIsImageSelect(false);
setImage();
if (isDefaultSign) {
const img = new Image();
img.src = defaultSignImg;
if (img.complete) {
imgWH = {
width: img.width,
height: img.height
};
imgWH = { width: img.width, height: img.height };
}
}
const getUpdatePosition = onSaveSign(
@@ -932,19 +907,11 @@ function SignYourSelf() {
const touch = e.touches[0]; // Get the first touch point
mouseX = touch.clientX - divRect.left;
mouseY = touch.clientY - divRect.top;
setSignBtnPosition([
{
xPos: mouseX,
yPos: mouseY
}
]);
setSignBtnPosition([{ xPos: mouseX, yPos: mouseY }]);
} else {
mouseX = e.clientX - divRect.left;
mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
const xyPosition = { xPos: mouseX, yPos: mouseY };
setXYSignature(xyPosition);
}
};
@@ -962,9 +929,7 @@ function SignYourSelf() {
const handleDeleteSign = (key) => {
setCurrWidgetsDetails({});
const updateResizeData = [];
let filterData = xyPostion[index].pos.filter((data) => data.key !== key);
//delete and update block position
if (filterData.length > 0) {
updateResizeData.push(filterData);
@@ -1243,7 +1208,6 @@ function SignYourSelf() {
<Confetti width={window.innerWidth} height={window.innerHeight} />
</div>
)}
<div className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
{!isEmailVerified && (
<VerifyEmail
+44 -23
View File
@@ -714,19 +714,11 @@ const TemplatePlaceholder = () => {
const touch = e.touches[0]; // Get the first touch point
mouseX = touch.clientX - divRect.left;
mouseY = touch.clientY - divRect.top;
setSignBtnPosition([
{
xPos: mouseX,
yPos: mouseY
}
]);
setSignBtnPosition([{ xPos: mouseX, yPos: mouseY }]);
} else {
mouseX = e.clientX - divRect.left;
mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
const xyPosition = { xPos: mouseX, yPos: mouseY };
setXYSignature(xyPosition);
}
};
@@ -744,12 +736,45 @@ const TemplatePlaceholder = () => {
}
};
useEffect(() => {
const timer = setTimeout(() => {
if (signerPos?.length > 0) {
autosavedetails();
}
}, 2000);
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [signerPos]);
// `autosavedetails` is used to save template details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
const autosavedetails = async () => {
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 templateCls = new Parse.Object("contracts_Template");
templateCls.id = templateId;
templateCls.set("Placeholders", signerPos);
templateCls.set("Signers", signers);
await templateCls.save();
} catch (err) {
console.log("error in autosave template", err);
}
};
const handleSaveTemplate = async () => {
if (signersdata?.length) {
const loadObj = {
isLoad: true,
message: t("loading-mssg")
};
const loadObj = { isLoad: true, message: t("loading-mssg") };
setIsLoading(loadObj);
setIsSendAlert(false);
let signers = [];
@@ -794,16 +819,10 @@ const TemplatePlaceholder = () => {
for (const key in data) {
updateTemplate.set(key, data[key]);
}
await updateTemplate.save(null, {
sessionToken: localStorage.getItem("accesstoken")
});
await updateTemplate.save();
setIsCreateDocModal(true);
setIsMailSend(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
} catch (e) {
setIsLoading(false);
alert(t("something-went-wrong-mssg"));
@@ -1005,11 +1024,12 @@ const TemplatePlaceholder = () => {
setIsMailSend(false);
};
// `handleLinkUser` is used to open Add/Choose Signer Modal when user can link existing or new User with placeholder
// `handleLinkUser` is used to open Add/Choose Signer Modal when user can link existing or new User with placeholder
// and update entry in signersList
const handleLinkUser = (id) => {
setIsAddUser({ [id]: true });
};
// `handleAddUser` is used to adduser
const handleAddUser = (data) => {
const signerPtr = {
__type: "Pointer",
@@ -1319,6 +1339,7 @@ const TemplatePlaceholder = () => {
setCurrWidgetsDetails({});
handleNameModal();
};
const handleNameModal = () => {
setIsNameModal(false);
setCurrWidgetsDetails({});
+17 -15
View File
@@ -2,27 +2,30 @@ import React, { useState } from "react";
import "../styles/signature.css";
import { useTranslation } from "react-i18next";
function CustomModal({
show,
headMsg,
bodyMssg,
footerMessage,
declineDoc,
setIsDecline
}) {
function CustomModal(props) {
const { t } = useTranslation();
const [reason, setReason] = useState("");
return (
show && (
props.show && (
<dialog className="op-modal op-modal-open absolute z-[448]">
<div className="w-[95%] md:w-[60%] lg:w-[40%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{headMsg && headMsg}
{props?.headMsg && props?.headMsg}
</h3>
<div className="p-[10px] px-[20px]">
<p className="text-[15px]">{bodyMssg && bodyMssg}</p>
<p className="text-[15px]">{props.bodyMssg && props.bodyMssg}</p>
</div>
{footerMessage && (
{props.isDownloadBtn && (
<div className="flex justify-start w-full ml-[20px] mb-3 mt-1">
<button
className="op-btn op-btn-primary "
onClick={() => props.handleDownloadBtn()}
>
Download
</button>
</div>
)}
{props.footerMessage && (
<>
<div className="mx-3">
<textarea
@@ -33,14 +36,13 @@ function CustomModal({
onChange={(e) => setReason(e.target.value)}
></textarea>
</div>
{/* <div className="h-[1px] bg-[#9f9f9f] w-full"></div> */}
<div className="m-[15px]">
<button
className="op-btn op-btn-primary mr-2 px-6"
type="button"
onClick={() => {
setReason("");
declineDoc(reason);
props.declineDoc(reason);
}}
>
{t("yes")}
@@ -50,7 +52,7 @@ function CustomModal({
className="op-btn op-btn-secondary"
onClick={() => {
setReason("");
setIsDecline({ isDeclined: false });
props.setIsDecline({ isDeclined: false });
}}
>
{t("close")}
@@ -1,7 +1,17 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function getapitoken(request) {
try {
if (request?.user) {
const userId = request?.user?.id;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': process.env.APP_ID,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (userId) {
const tokenQuery = new Parse.Query('appToken');
tokenQuery.equalTo('userId', { __type: 'Pointer', className: '_User', objectId: userId });
const res = await tokenQuery.first({ useMasterKey: true });
@@ -0,0 +1,21 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.addBoolean('IsSignyourself');
return schema.update();
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.deleteField('IsSignyourself');
return schema.update();
};
+16 -16
View File
@@ -15,7 +15,7 @@
"@signpdf/placeholder-pdf-lib": "^3.2.4",
"@signpdf/signer-p12": "^3.2.4",
"@signpdf/signpdf": "^3.2.4",
"aws-sdk": "^2.1674.0",
"aws-sdk": "^2.1681.0",
"axios": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
@@ -42,7 +42,7 @@
"@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.0",
"jasmine": "^5.2.0",
"mongodb-runner": "^5.6.4",
"mongodb-runner": "^5.6.5",
"nodemon": "^3.1.4",
"nyc": "^17.0.0",
"prettier": "^3.3.3"
@@ -2315,14 +2315,14 @@
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md"
},
"node_modules/@mongodb-js/mongodb-downloader": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.3.tgz",
"integrity": "sha512-PIu8qF6J02lQsxfq8vdcfvueb8H5mrB43UaOl1E4AQMrOhm403imAZYKH61qe+7J7WzlVFck0zGI/7brHLHcNQ==",
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.5.tgz",
"integrity": "sha512-0tNik3E/eQxx8EkJpsa9+IIK5LtMle3N7M/1wtKQKMixJjZ1vsgAjJGguYbLfCyJqfnrw9KMyD1cwgaS37tvRA==",
"dev": true,
"dependencies": {
"debug": "^4.3.4",
"decompress": "^4.2.1",
"mongodb-download-url": "^1.3.0",
"mongodb-download-url": "^1.5.1",
"node-fetch": "^2.6.11",
"tar": "^6.1.15"
}
@@ -4120,9 +4120,9 @@
}
},
"node_modules/aws-sdk": {
"version": "2.1674.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1674.0.tgz",
"integrity": "sha512-VTijN8+pKrf4sfM2t+ISXjypJ+k3AiP6OMzyLoWJ7jfMBtBfWbQc1rN07OndNb0CZRBBukOHoBhYDPuyae+/1Q==",
"version": "2.1681.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1681.0.tgz",
"integrity": "sha512-oeCr0muJraT+g7ceTMlJcidVayPMfT69EEvDIWMbeBIHqbLOJVtpsF577VZJNEh2Zkj+8DivR69kWdu+Y9JSyQ==",
"hasInstallScript": true,
"dependencies": {
"buffer": "4.9.2",
@@ -8077,9 +8077,9 @@
}
},
"node_modules/mongodb-download-url": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.0.tgz",
"integrity": "sha512-zQP7t3aEpbWabn4ZlYapu8ODm7iRA0ON7hVFqxW2fSmY1kdCoYmKTW4LK+WfaokWOPGpLt4ZPtiWL54Bv1r87g==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.1.tgz",
"integrity": "sha512-AJH2lqb7mBo7tT7RyFWK3P/ZMh7RC1qWJgOaAVrBdKeuPuCWGCESrti+ZMt6FA6mJ4eU58Lm7iG2rTkl94pBdQ==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@@ -8104,12 +8104,12 @@
}
},
"node_modules/mongodb-runner": {
"version": "5.6.4",
"resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.6.4.tgz",
"integrity": "sha512-pwWsei3btwq9omPLjNaERmSxwt72/OzQx1O468XBuUfhmlTJ+Ta+CIUYOX8vP3K0vSS6E/NUQBG/3ctEoLqOCA==",
"version": "5.6.5",
"resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.6.5.tgz",
"integrity": "sha512-joZJL5YKuwP7MNegz0CKt7rAPgAeUcWhOfJZPgifnKD+3tl4oMbRwP+HjcQjBieT1dr9lh+kI1MQuGInRtQzMw==",
"dev": true,
"dependencies": {
"@mongodb-js/mongodb-downloader": "^0.3.3",
"@mongodb-js/mongodb-downloader": "^0.3.5",
"@mongodb-js/saslprep": "^1.1.8",
"debug": "^4.3.4",
"mongodb": "^6.8.0",
+2 -2
View File
@@ -24,7 +24,7 @@
"@signpdf/placeholder-pdf-lib": "^3.2.4",
"@signpdf/signer-p12": "^3.2.4",
"@signpdf/signpdf": "^3.2.4",
"aws-sdk": "^2.1674.0",
"aws-sdk": "^2.1681.0",
"axios": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
@@ -52,7 +52,7 @@
"@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.0",
"jasmine": "^5.2.0",
"mongodb-runner": "^5.6.4",
"mongodb-runner": "^5.6.5",
"nodemon": "^3.1.4",
"nyc": "^17.0.0",
"prettier": "^3.3.3"