Merge pull request #1024 from OpenSignLabs/raktima-opensignlabs-patch-11

fix: error in auto-sign feature unexpected issue encountered - something went wrong
This commit is contained in:
prafull-opensignlabs
2024-08-09 16:29:24 +05:30
committed by GitHub
29 changed files with 594 additions and 539 deletions
@@ -303,7 +303,9 @@
"otp-verification":"OTP verification",
"enter-otp":"Enter OTP",
"verify":"Verify",
"verify-email-1":"Verify email",
"resend":"Resend",
"contact-details":"Contact Details",
"verify-email":"Please verify your email !",
"send-otp":" Send OTP",
"otp-placeholder":"Enter OTP received over email",
@@ -567,6 +569,9 @@
"placeholder-sign-4":"The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
"placeholder-sign-5":"Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
"report-1":"Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like HR Manager and New Employee. Each time you use the template, you can assign the New Employee role to different incoming staff members, while the HR Manager role remains constant, facilitating a seamless onboarding process for each recruit. ",
"redirect":"Click the 'Use' button to create a new document from an existing template.",
"bulksend":"To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
"option": "This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but wont affect existing documents.Use the Delete button you can delete template. ",
"signyour-self-1":"Select and drag your preferred widgets onto the PDF to customize your document before signing. Choose the perfect spots for each modification to tailor the document to your needs.",
"signyour-self-2":"Drag and drop anywhere in this area. You can resize and move it later.",
"template-placeholder-1":"Clicking 'Add role' button will allow you to add various signer roles. You can attach users to each role in subsequent steps.",
@@ -580,11 +585,13 @@
"Recent signature requests": "This is a list of documents that are waiting for your signature.",
"Recently sent for signatures":"This is a list of documents you've sent to other parties for signature.",
"Drafts":"This are documents you have started but have not finalized for sending."
}
},
"enter-email-plaholder":"Add an email address and hit enter",
"success-email-alert":"Email sent successfully!",
"expired-doc-title":"Expired Document",
"expired-on-mssg" :"This document expired on {{expiredDate}} and is no longer available to sign.",
"signature-validate-alert":"Please confirm that you have selected at least {{minRequiredCount}} checkboxes.",
"signature-validate-alert-2" :"Ensure this field is accurately filled and meets all requirements."
@@ -114,7 +114,7 @@
"Users":"Utilisateurs"
},
"report-heading":{
"Sr.No":"Numéro du document",
"Sr.No":"Numéro",
"Title":"Titre",
"Email":"E-mail",
"Phone":"Téléphone",
@@ -128,7 +128,7 @@
"Active":"Actif",
"Role":"Rôle",
"Team":"Équipe",
"Name":"Nom et Prénom",
"Name":"Nom",
"Status":"Statut",
"created-date":"Date de création",
"Type":"Saisir"
@@ -302,7 +302,9 @@
"otp-verification":"Vérification OTP",
"enter-otp":"Entrez OTP",
"verify":"Vérifier",
"verify-email-1":"Vérifier l'e-mail",
"resend":"Renvoyer",
"contact-details" :"Coordonnées",
"verify-email":"Veuillez vérifier votre email!",
"send-otp":"envoyer un code à usage unique",
"otp-placeholder":"Saisissez l'OTP reçu par e-mail",
@@ -566,6 +568,9 @@
"placeholder-sign-4":"La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
"placeholder-sign-5":"Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
"report-1":"Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
"redirect":"Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
"bulksend":"Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
"option": "Ce menu révèle plus d'options telles que Modifier et Supprimer. Utilisez le bouton « Modifier » pour ajouter des rôles de signataire, modifier les champs et mettre à jour votre modèle. Les modifications s'appliqueront à tous les futurs documents créés à partir de ce modèle mais n'affecteront pas les documents existants. Utilisez le bouton Supprimer, vous pouvez supprimer le modèle ",
"signyour-self-1": "Sélectionnez et faites glisser vos widgets préférés sur le PDF pour personnaliser votre document avant de le signer. Choisissez les endroits parfaits pour chaque modification afin d'adapter le document à vos besoins.",
"signyour-self-2":"Faites glisser et déposer n'importe où dans cette zone. Vous pourrez la redimensionner et la déplacer plus tard.",
"template-placeholder-1":"Cliquer sur le bouton 'Ajouter un rôle' vous permettra d'ajouter différents rôles de signataire. Vous pourrez attacher des utilisateurs à chaque rôle dans les étapes suivantes.",
@@ -579,8 +584,13 @@
"Recent signature requests": "Voici une liste de documents qui attendent votre signature.",
"Recently sent for signatures":"Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
"Drafts":"Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi."
}
},
"enter-email-plaholder":"Ajoutez une adresse email et appuyez sur Entrée",
"success-email-alert" :"E-mail envoyé avec succès!",
"expired-doc-title" :"Document expiré",
"expired-on-mssg" :"Ce document a expiré le {{expiredDate}} et n'est plus disponible pour signature.",
"signature-validate-alert":"Veuillez confirmer que vous avez coché au moins {{minRequiredCount}} cases.",
"signature-validate-alert-2" :"Assurez-vous que ce champ est rempli avec précision et répond à toutes les exigences."
+3 -1
View File
@@ -247,7 +247,9 @@ const AddSigner = (props) => {
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
onChange={(e) =>
setEmail(e.target.value?.toLowerCase?.replace(/\s/g, ""))
}
required
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
+9 -2
View File
@@ -240,8 +240,15 @@ const AddUser = (props) => {
props.closePopup();
}
};
const handleChange = (e) => {
setFormdata((prev) => ({ ...prev, [e.target.name]: e.target.value }));
const handleChange = (event) => {
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setFormdata((prev) => ({
...prev,
[name]: value
}));
};
const copytoclipboard = (text) => {
@@ -1,9 +1,7 @@
import React, { useState } from "react";
import { saveAs } from "file-saver";
import axios from "axios";
import { getBase64FromUrl } from "../../constant/Utils";
import { handleDownloadPdf, handleToPrint } from "../../constant/Utils";
import { themeColor, emailRegex } from "../../constant/const";
import printModule from "print-js";
import Loader from "../../primitives/Loader";
import ModalUi from "../../primitives/ModalUi";
import { useTranslation } from "react-i18next";
@@ -13,7 +11,7 @@ function EmailComponent({
pdfUrl,
setIsEmail,
setSuccessEmail,
pdfName,
pdfDetails,
sender,
setIsAlert,
extUserId,
@@ -24,10 +22,12 @@ function EmailComponent({
const [emailValue, setEmailValue] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [emailErr, setEmailErr] = useState(false);
const [isDownloading, setIsDownloading] = useState("");
const isAndroid = /Android/i.test(navigator.userAgent);
//function for send email
const sendEmail = async () => {
const pdfName = pdfDetails[0]?.Name;
setIsLoading(true);
let sendMail;
for (let i = 0; i < emailList.length; i++) {
try {
@@ -113,7 +113,7 @@ function EmailComponent({
};
//function for get email value
const handleEmailValue = (e) => {
const value = e.target.value;
const value = e.target.value?.toLowerCase()?.replace(/\s/g, "");
setEmailErr(false);
setEmailValue(value);
};
@@ -140,43 +140,6 @@ function EmailComponent({
}
}
};
// function for print signed pdf
const handleToPrint = async (event) => {
event.preventDefault();
const pdf = await getBase64FromUrl(pdfUrl);
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(
atob(pdf)
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank");
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
}
};
//handle download signed pdf
const handleDownloadPdf = () => {
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
const isAndroid = /Android/i.test(navigator.userAgent);
return (
<div>
{/* isEmail */}
@@ -190,6 +153,11 @@ function EmailComponent({
</span>
</div>
)}
{isDownloading === "pdf" && (
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<div className="flex justify-between items-center py-[10px] px-[20px] border-b-[1px] border-base-content">
<span className="text-base-content font-semibold">
{t("successfully-signed")}
@@ -197,7 +165,7 @@ function EmailComponent({
<div className="flex flex-row">
{!isAndroid && (
<button
onClick={handleToPrint}
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa-light fa-print" aria-hidden="true"></i>
@@ -206,7 +174,9 @@ function EmailComponent({
)}
<button
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
{t("download")}
@@ -263,7 +233,7 @@ function EmailComponent({
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-transparent border-[1.5px] op-border-primary"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
placeholder="Add an email address and hit enter"
placeholder={t("enter-email-plaholder")}
onBlur={() => emailValue && handleEnterPress("add")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
+9 -18
View File
@@ -9,6 +9,7 @@ import {
} from "../../constant/Utils";
import Placeholder from "./Placeholder";
import Alert from "../../primitives/Alert";
import { useTranslation } from "react-i18next";
function RenderPdf({
pageNumber,
@@ -24,7 +25,6 @@ function RenderPdf({
setSignKey,
pdfDetails,
xyPostion,
pdfUrl,
pageDetails,
pdfRequest,
signerObjectId,
@@ -63,6 +63,7 @@ function RenderPdf({
ispublicTemplate,
handleUserDetails
}) {
const { t } = useTranslation();
const isMobile = window.innerWidth < 767;
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
@@ -249,7 +250,9 @@ function RenderPdf({
};
return (
<>
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{successEmail && (
<Alert type={"success"}>{t("success-email-alert")}</Alert>
)}
{isMobile ? (
<div
data-tut="reactourForth"
@@ -394,7 +397,7 @@ function RenderPdf({
onLoadError={() => {
setPdfLoad(false);
}}
loading={"Loading Document.."}
loading={t("loading-doc")}
onLoadSuccess={pageDetails}
// ref={pdfRef}'
onClick={() => {
@@ -402,13 +405,7 @@ function RenderPdf({
setSelectWidgetId("");
}
}}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
}
file={pdfDetails[0]?.SignedUrl || pdfDetails[0]?.URL}
>
<Page
key={index}
@@ -581,7 +578,7 @@ function RenderPdf({
onLoadError={() => {
setPdfLoad(false);
}}
loading={"Loading Document.."}
loading={t("loading-doc")}
onLoadSuccess={pageDetails}
onClick={() => {
if (setSelectWidgetId) {
@@ -589,13 +586,7 @@ function RenderPdf({
}
}}
// ref={pdfRef}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
}
file={pdfDetails[0]?.SignedUrl || pdfDetails[0].URL}
>
<Page
key={index}
+42 -3
View File
@@ -439,7 +439,7 @@ export const resizeBorderExtraWidth = () => {
return 20;
};
export async function getBase64FromUrl(url) {
export async function getBase64FromUrl(url, autosign) {
const data = await fetch(url);
const blob = await data.blob();
return new Promise((resolve) => {
@@ -447,8 +447,12 @@ export async function getBase64FromUrl(url) {
reader.readAsDataURL(blob);
reader.onloadend = function () {
const pdfBase = this.result;
const suffixbase64 = pdfBase.split(",").pop();
resolve(suffixbase64);
if (autosign) {
resolve(pdfBase);
} else {
const suffixbase64 = pdfBase.split(",").pop();
resolve(suffixbase64);
}
};
});
}
@@ -2230,3 +2234,38 @@ export const saveLanguageInLocal = (i18n) => {
const detectedLanguage = i18n.language || "en";
localStorage.setItem("i18nextLng", detectedLanguage);
};
//function to get default signatur eof current user from `contracts_Signature` class
export const getDefaultSignature = async (objectId) => {
try {
const query = new Parse.Query("contracts_Signature");
query.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: objectId
});
const result = await query.first();
if (result) {
const res = JSON.parse(JSON.stringify(result));
const defaultSignature = res?.ImageURL
? await getBase64FromUrl(res?.ImageURL, true)
: "";
const defaultInitial = res?.Initials
? await getBase64FromUrl(res?.Initials, true)
: "";
return {
status: "success",
res: {
defaultSignature: defaultSignature,
defaultInitial: defaultInitial
}
};
}
} catch (err) {
console.log("Error: error in fetch data in contracts_Signature", err);
return {
status: "error"
};
}
};
+4
View File
@@ -11,3 +11,7 @@ export const isEnableSubscription =
: false;
export const isStaging =
window.location.origin === "https://staging-app.opensignlabs.com";
export const isPublicProduction =
window.location.origin === "https://opensign.me";
export const isPublicStaging =
window.location.origin === "https://staging.opensign.me";
+13
View File
@@ -2,12 +2,23 @@ import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
import { isPublicProduction, isPublicStaging } from "./constant/const";
//handle path to support language on public profile
const backendPath = isPublicStaging
? "https://staging-app.opensignlabs.com/locales/{{lng}}/{{ns}}.json"
: isPublicProduction
? "https://app.opensignlabs.com/locales/{{lng}}/{{ns}}.json"
: "/locales/{{lng}}/{{ns}}.json";
i18n
.use(Backend)
.use(LanguageDetector) // Use LanguageDetector directly without creating an instance
.use(initReactI18next)
.init({
backend: {
loadPath: backendPath
},
fallbackLng: "en", // Fallback to English if no other language is detected
detection: {
// Specifies the default language to fall back to if the detected language is not available.
@@ -15,6 +26,8 @@ i18n
// Defines where the detected language should be cached.
caches: ["localStorage"]
},
ns: ["translation"], // default namespace
defaultNS: "translation", // default namespace
//Enables debug mode, which outputs detailed logs to the console about the translation process.
debug: false,
interpolation: {
+3 -9
View File
@@ -10,7 +10,7 @@ export default function reportJson(id) {
"Owner",
"Signers"
];
const contactbook = ["Sr.No", "Title", "Email", "Phone"];
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
switch (id) {
@@ -325,9 +325,7 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-plus",
redirectUrl: "placeHolderSign",
action: "redirect",
selector: "reactourSecond",
message:
"Click the 'Use' button to create a new document from an existing template. "
selector: "reactourSecond"
},
{
btnId: "1631",
@@ -337,9 +335,7 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-envelope",
redirectUrl: "",
action: "bulksend",
selector: "tourbulksend",
message:
"To quickly create and send multiple documents using an existing template, click the 'Quick Send' button."
selector: "tourbulksend"
},
{
btnId: "2234",
@@ -349,8 +345,6 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
action: "option",
selector: "reactourThird",
message:
"This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but wont affect existing documents.Use the Delete button you can delete template. ",
subaction: [
{
btnId: "2434",
+1
View File
@@ -38,6 +38,7 @@ const HomeLayout = () => {
useEffect(() => {
const language = localStorage.getItem("i18nextLng");
i18n.changeLanguage(language);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
+5 -1
View File
@@ -310,7 +310,11 @@ const AddAdmin = () => {
type="email"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={email}
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
onChange={(e) =>
setEmail(
e.target.value?.toLowerCase()?.replace(/\s/g, "")
)
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
+4 -1
View File
@@ -24,7 +24,10 @@ function ForgotPassword() {
const [image, setImage] = useState();
const handleChange = (event) => {
const { name, value } = event.target;
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setState({ ...state, [name]: value });
};
+4 -1
View File
@@ -74,7 +74,10 @@ function Login() {
dispatch(fetchAppInfo());
};
const handleChange = (event) => {
const { name, value } = event.target;
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setState({ ...state, [name]: value });
};
+283 -291
View File
@@ -30,7 +30,8 @@ import {
contactBook,
handleDownloadPdf,
handleToPrint,
handleDownloadCertificate
handleDownloadCertificate,
getDefaultSignature
} from "../constant/Utils";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
@@ -340,243 +341,232 @@ function PdfRequestFiles(props) {
};
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (docId, isNextUser) => {
const senderUser = localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
let currUserId;
//getting document details
const documentData = await contractDocument(documentId || docId);
if (documentData && documentData.length > 0) {
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
const expireDate = documentData[0].ExpiryDate.iso;
const declined = documentData[0].IsDeclined && documentData[0].IsDeclined;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const getSigners = documentData[0].Signers;
const getCurrentSigner =
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender?.objectId
);
try {
const senderUser = localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
let currUserId;
//getting document details
const documentData = await contractDocument(documentId || docId);
if (documentData && documentData.length > 0) {
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
const expireDate = documentData[0].ExpiryDate.iso;
const declined =
documentData[0].IsDeclined && documentData[0].IsDeclined;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const getSigners = documentData[0].Signers;
const getCurrentSigner =
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender?.objectId
);
currUserId = getCurrentSigner[0] ? getCurrentSigner[0].objectId : "";
if (isEnableSubscription) {
await checkIsSubscribed(
documentData[0]?.ExtUserPtr?.objectId,
currUserId
);
}
if (currUserId) {
setSignerObjectId(currUserId);
}
if (documentData[0].SignedUrl) {
setPdfUrl(documentData[0].SignedUrl);
} else {
setPdfUrl(documentData[0].URL);
}
if (isCompleted) {
setIsSigned(true);
const data = {
isCertificate: true,
isModal: true
};
setAlreadySign(true);
setIsCompleted(data);
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
const expireDateFormat = moment(new Date(expireDate)).format(
"MMM DD, YYYY"
);
setIsExpired(true);
setExpiredDate(expireDateFormat);
} // Check if the current signer is not a last signer and handle the complete message.
else if (isNextUser) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted({
isModal: true,
message: t("document-signed-alert-1")
});
} else {
currUserId = getCurrentSigner[0] ? getCurrentSigner[0].objectId : "";
if (isEnableSubscription) {
await checkIsSubscribed(
documentData[0]?.ExtUserPtr?.objectId,
currUserId
);
}
if (currUserId) {
const checkCurrentUser = documentData[0].Placeholders.find(
(data) => data?.signerObjId === currUserId
);
if (checkCurrentUser) {
setCurrentSigner(true);
}
setSignerObjectId(currUserId);
}
}
const audittrailData =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter((data) => data.Activity === "Signed");
const checkAlreadySign =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId && data.Activity === "Signed"
);
if (
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true);
} else {
const obj = documentData?.[0];
setSendInOrder(obj?.SendinOrder || false);
if (
obj &&
obj.Signers &&
obj.Signers.length > 0 &&
obj.Placeholders &&
obj.Placeholders.length > 0
) {
const params = {
event: "viewed",
contactId: currUserId,
body: {
objectId: documentData?.[0].objectId,
file: documentData?.[0]?.SignedUrl || documentData?.[0]?.URL,
name: documentData?.[0].Name,
note: documentData?.[0].Note || "",
description: documentData?.[0].Description || "",
signers: documentData?.[0].Signers?.map((x) => ({
name: x?.Name,
email: x?.Email,
phone: x?.Phone
})),
viewedBy: jsonSender.email,
viewedAt: new Date(),
createdAt: documentData?.[0].createdAt
}
};
try {
await axios.post(
`${localStorage.getItem("baseUrl")}functions/callwebhook`,
params,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
}
}
);
} catch (err) {
console.log("Err ", err);
}
}
}
let signers = [];
let unSignedSigner = [];
const placeholdersOrSigners = [];
for (const placeholder of documentData[0].Placeholders) {
//`emailExist` variable to handle condition for quick send flow and show unsigned signers list
const signerIdExist = placeholder?.signerObjId;
if (signerIdExist) {
const getSignerData = documentData[0].Signers.find(
(data) => data.objectId === placeholder?.signerObjId
);
placeholdersOrSigners.push(getSignerData);
if (documentData[0].SignedUrl) {
setPdfUrl(documentData[0].SignedUrl);
} else {
placeholdersOrSigners.push(placeholder);
setPdfUrl(documentData[0].URL);
}
}
//condition to check already signed document by someone
if (audittrailData && audittrailData.length > 0) {
setIsDocId(true);
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;
//`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;
if (emailOrId === signedExist) {
signers.push({ ...item });
isSignedSignature = true;
break;
if (isCompleted) {
setIsSigned(true);
const data = {
isCertificate: true,
isModal: true
};
setAlreadySign(true);
setIsCompleted(data);
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
const expireDateFormat = moment(new Date(expireDate)).format(
"MMM DD, YYYY"
);
setIsExpired(true);
setExpiredDate(expireDateFormat);
} // Check if the current signer is not a last signer and handle the complete message.
else if (isNextUser) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted({
isModal: true,
message: t("document-signed-alert-1")
});
} else {
if (currUserId) {
const checkCurrentUser = documentData[0].Placeholders.find(
(data) => data?.signerObjId === currUserId
);
if (checkCurrentUser) {
setCurrentSigner(true);
}
}
if (!isSignedSignature) {
unSignedSigner.push({ ...item });
}
const audittrailData =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
const checkAlreadySign =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId && data.Activity === "Signed"
);
if (
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true);
} else {
const obj = documentData?.[0];
setSendInOrder(obj?.SendinOrder || false);
if (
obj &&
obj.Signers &&
obj.Signers.length > 0 &&
obj.Placeholders &&
obj.Placeholders.length > 0
) {
const params = {
event: "viewed",
contactId: currUserId,
body: {
objectId: documentData?.[0].objectId,
file: documentData?.[0]?.SignedUrl || documentData?.[0]?.URL,
name: documentData?.[0].Name,
note: documentData?.[0].Note || "",
description: documentData?.[0].Description || "",
signers: documentData?.[0].Signers?.map((x) => ({
name: x?.Name,
email: x?.Email,
phone: x?.Phone
})),
viewedBy: jsonSender.email,
viewedAt: new Date(),
createdAt: documentData?.[0].createdAt
}
};
try {
await axios.post(
`${localStorage.getItem("baseUrl")}functions/callwebhook`,
params,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id":
localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
}
}
);
} catch (err) {
console.log("Err ", err);
}
}
}
setSignedSigners(signers);
setUnSignedSigners(unSignedSigner);
setSignerPos(documentData[0].Placeholders);
} else {
//else condition is show there are no details in audit trail then direct push all signers details
//in unsignedsigners array
setUnSignedSigners(placeholdersOrSigners);
setSignerPos(documentData[0].Placeholders);
}
setPdfDetails(documentData);
//checking if condition current user already sign or owner does not exist as a signer or document has been declined by someone or document has been expired
//then stop to display tour message
if (
(checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0) ||
!currUserId ||
declined ||
currDate > expireUpdateDate
) {
setRequestSignTour(true);
} else {
//else condition to check current user exist in contracts_Users class and check tour message status
//if not then check user exist in contracts_Contactbook class and check tour message statu
const res = await contractUsers();
if (res === "Error: Something went wrong!") {
setHandleError(t("something-went-wrong-mssg"));
} else if (res[0] && res?.length) {
setContractName("_Users");
currUserId = res[0].objectId;
setSignerUserId(currUserId);
const tourData = res[0].TourStatus && res[0].TourStatus;
if (tourData && tourData.length > 0) {
const checkTourRequest = tourData.filter(
(data) => data?.requestSign
let signers = [];
let unSignedSigner = [];
const placeholdersOrSigners = [];
for (const placeholder of documentData[0].Placeholders) {
//`emailExist` variable to handle condition for quick send flow and show unsigned signers list
const signerIdExist = placeholder?.signerObjId;
if (signerIdExist) {
const getSignerData = documentData[0].Signers.find(
(data) => data.objectId === placeholder?.signerObjId
);
setTourStatus(tourData);
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
placeholdersOrSigners.push(getSignerData);
} else {
placeholdersOrSigners.push(placeholder);
}
} else if (res?.length === 0) {
const res = await contactBook(currUserId);
}
//condition to check already signed document by someone
if (audittrailData && audittrailData.length > 0) {
setIsDocId(true);
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;
//`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;
if (emailOrId === signedExist) {
signers.push({ ...item });
isSignedSignature = true;
break;
}
}
if (!isSignedSignature) {
unSignedSigner.push({ ...item });
}
}
setSignedSigners(signers);
setUnSignedSigners(unSignedSigner);
setSignerPos(documentData[0].Placeholders);
} else {
//else condition is show there are no details in audit trail then direct push all signers details
//in unsignedsigners array
setUnSignedSigners(placeholdersOrSigners);
setSignerPos(documentData[0].Placeholders);
}
setPdfDetails(documentData);
//checking if condition current user already sign or owner does not exist as a signer or document has been declined by someone or document has been expired
//then stop to display tour message
if (
(checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0) ||
!currUserId ||
declined ||
currDate > expireUpdateDate
) {
setRequestSignTour(true);
} else {
//else condition to check current user exist in contracts_Users class and check tour message status
//if not then check user exist in contracts_Contactbook class and check tour message statu
const res = await contractUsers();
if (res === "Error: Something went wrong!") {
setHandleError(t("something-went-wrong-mssg"));
} else if (res[0] && res.length) {
setContractName("_Contactbook");
const objectId = res[0].objectId;
setSignerUserId(objectId);
} else if (res[0] && res?.length) {
setContractName("_Users");
currUserId = res[0].objectId;
setSignerUserId(currUserId);
const tourData = res[0].TourStatus && res[0].TourStatus;
if (tourData && tourData.length > 0) {
const checkTourRequest = tourData.filter(
@@ -585,64 +575,63 @@ function PdfRequestFiles(props) {
setTourStatus(tourData);
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
}
} else if (res.length === 0) {
setHandleError(t("user-not-exist"));
} else if (res?.length === 0) {
const res = await contactBook(currUserId);
if (res === "Error: Something went wrong!") {
setHandleError(t("something-went-wrong-mssg"));
} else if (res[0] && res.length) {
setContractName("_Contactbook");
const objectId = res[0].objectId;
setSignerUserId(objectId);
const tourData = res[0].TourStatus && res[0].TourStatus;
if (tourData && tourData.length > 0) {
const checkTourRequest = tourData.filter(
(data) => data?.requestSign
);
setTourStatus(tourData);
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
}
} else if (res.length === 0) {
setHandleError(t("user-not-exist"));
}
}
}
}
setIsUiLoading(false);
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
setHandleError(t("something-went-wrong-mssg"));
setIsLoading({
isLoad: false
});
console.log("err in getDocument cloud function ");
} else {
setHandleError(t("no-data"));
setIsUiLoading({
isLoad: false
});
}
await axios
.get(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
jsonSender?.objectId
}"}}`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setMyInitial(res[0]?.Initials);
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
})
.catch((err) => {
console.log("Err in contracts_Signature class", err);
setIsUiLoading(false);
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
setHandleError(t("something-went-wrong-mssg"));
setIsLoading({
isLoad: false
});
console.log("err in getDocument cloud function ");
} else {
setHandleError(t("no-data"));
setIsUiLoading({
isLoad: false
});
}
//function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId);
if (defaultSignRes?.status === "success") {
setDefaultSignImg(defaultSignRes?.res?.defaultSignature);
setMyInitial(defaultSignRes?.res?.defaultInitial);
} else if (defaultSignRes?.status === "error") {
setHandleError("Error: Something went wrong!");
}
setIsLoading({
isLoad: false
});
} catch (err) {
console.log("Error: error in getDocumentDetails", err);
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
});
}
};
//function for embed signature or image url in pdf
async function embedWidgetsData() {
//for emailVerified data checking first in localstorage
@@ -1089,8 +1078,8 @@ function PdfRequestFiles(props) {
{
selector: '[data-tut="IsSigned"]',
content: minRequiredCount
? `Please confirm that you have selected at least ${minRequiredCount} checkboxes.`
: "Ensure this field is accurately filled and meets all requirements.",
? t("signature-validate-alert", { minRequiredCount })
: t("signature-validate-alert-2"),
position: "top",
style: { fontSize: "13px" }
}
@@ -1484,7 +1473,11 @@ function PdfRequestFiles(props) {
};
const handleInputChange = (e) => {
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
let { name, value } = e.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setContact({ ...contact, [name]: value });
};
const SendOtp = async () => {
@@ -1690,8 +1683,8 @@ function PdfRequestFiles(props) {
{/* this modal is used for show expired alert */}
<PdfDeclineModal
show={isExpired}
headMsg="Document expired"
bodyMssg={`This document expired on ${expiredDate} and is no longer available to sign.`}
headMsg={t("expired-doc-title")}
bodyMssg={t("expired-on-mssg", { expiredDate })}
/>
{!isEmailVerified && (
<VerifyEmail
@@ -1708,7 +1701,7 @@ function PdfRequestFiles(props) {
<ModalUi
isOpen={isPublicContact}
title={isOtp ? "Verify email" : "Contact Details"}
title={isOtp ? t("verify-email-1") : t("contact-details")}
handleClose={() => {
handleCloseOtp();
}}
@@ -1723,7 +1716,7 @@ function PdfRequestFiles(props) {
type="number"
name="otp"
className="grow"
placeholder="Enter Verification Code"
placeholder={t("otp-placeholder")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
@@ -1743,13 +1736,13 @@ function PdfRequestFiles(props) {
handleCloseOtp();
}}
>
Cancel
{t("cancel")}
</button>
<button
className="op-btn op-btn-primary"
disabled={loading}
>
{loading ? "Loading..." : "Verify"}
{loading ? t("loading") : t("verify")}
</button>
</div>
</div>
@@ -1772,7 +1765,7 @@ function PdfRequestFiles(props) {
name="name"
value={contact.name}
onChange={handleInputChange}
placeholder="name"
placeholder={t("name")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
@@ -1792,12 +1785,12 @@ function PdfRequestFiles(props) {
<path d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z" />
</svg>
<input
type="text"
type="email"
className="grow"
name="email"
value={contact.email}
onChange={handleInputChange}
placeholder="Email"
placeholder={t("email")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
@@ -1822,7 +1815,7 @@ function PdfRequestFiles(props) {
type="text"
name="phone"
className="grow"
placeholder="phone"
placeholder={t("phone")}
disabled={loading}
/>
</label>
@@ -1835,13 +1828,13 @@ function PdfRequestFiles(props) {
handleCloseOtp();
}}
>
Close
{t("close")}
</button>
<button
className="op-btn op-btn-primary"
disabled={loading}
>
{loading ? "Loading..." : "Submit"}
{loading ? t("loading") : t("submit")}
</button>
</div>
</div>
@@ -2164,7 +2157,6 @@ function PdfRequestFiles(props) {
{defaultSignImg && !alreadySign && currentSigner && (
<DefaultSignature
defaultSignImg={defaultSignImg}
setDefaultSignImg={setDefaultSignImg}
userObjectId={signerObjectId}
setIsLoading={setIsLoading}
xyPostion={signerPos}
+10 -15
View File
@@ -190,28 +190,20 @@ function PlaceHolderSign() {
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>`;
const defaultSubject = `{{sender_name}} has requested you to sign {{document_title}}`;
setDefaultBody(defaultRequestBody);
setDefaultSubject(defaultSubject);
const tenantDetails = await getTenantDetails(user?.objectId);
if (tenantDetails && tenantDetails === "user does not exist!") {
alert(t("user-not-exist"));
} else if (tenantDetails) {
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>`;
if (tenantDetails?.RequestBody) {
setRequestBody(tenantDetails?.RequestBody);
setRequestSubject(tenantDetails?.RequestSubject);
setDefaultBody(defaultRequestBody);
setDefaultSubject(
`{{sender_name}} has requested you to sign {{document_title}}`
);
} else {
setRequestBody(defaultRequestBody);
setRequestSubject(
`{{sender_name}} has requested you to sign {{document_title}}`
);
setDefaultBody(defaultRequestBody);
setDefaultSubject(
`{{sender_name}}has requested you to sign {{document_title}}`
);
setRequestSubject(defaultSubject);
}
}
} catch (e) {
@@ -222,6 +214,7 @@ function PlaceHolderSign() {
}
};
console.log("default body", defaultBody);
useEffect(() => {
const updateSize = () => {
if (divRef.current) {
@@ -1772,8 +1765,10 @@ function PlaceHolderSign() {
<>
<EmailBody
editorRef={editorRef}
requestBody={requestBody}
requestSubject={requestSubject}
requestBody={requestBody || defaultBody}
requestSubject={
requestSubject || defaultSubject
}
handleOnchangeRequest={handleOnchangeRequest}
setRequestSubject={setRequestSubject}
/>
+1 -1
View File
@@ -100,7 +100,7 @@ const Report = () => {
selector: `[data-tut="${data?.selector}"]`,
content: () => (
<TourContentWithBtn
message={data?.message}
message={t(`tour-mssg.${data?.action}`)}
isChecked={handleDontShow}
/>
),
+3 -1
View File
@@ -365,7 +365,9 @@ const Signup = () => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={email}
onChange={(e) =>
setEmail(e.target.value?.toLowerCase())
setEmail(
e.target.value?.toLowerCase()?.replace(/\s/g, "")
)
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
+110 -119
View File
@@ -33,7 +33,8 @@ import {
fetchImageBase64,
changeImageWH,
handleSendOTP,
getContainerScale
getContainerScale,
getDefaultSignature
} from "../constant/Utils";
import { useParams } from "react-router-dom";
import Tour from "reactour";
@@ -207,131 +208,90 @@ function SignYourSelf() {
}, [divRef.current, isHeader]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
let isCompleted;
//getting document details
const documentData = await contractDocument(documentId);
try {
let isCompleted;
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
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
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
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
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
setHandleError(t("something-went-wrong-mssg"));
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError(t("something-went-wrong-mssg"));
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError(t("something-went-wrong-mssg"));
}
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: t("document-signed-alert")
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
} else {
setIsUiLoading(false);
setIsSignPad(false);
setIsEmail(true);
setXyPostion([]);
setSignBtnPosition([]);
}
}
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
} else {
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
await axios
.get(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
jsonSender.objectId
}"}}`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: t("document-signed-alert")
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
} else {
setIsUiLoading(false);
setIsSignPad(false);
setIsEmail(true);
setXyPostion([]);
setSignBtnPosition([]);
}
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setMyInitial(res[0]?.Initials);
}
})
.catch((err) => {
console.log("Err ", err);
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
});
const contractUsersRes = await contractUsers();
if (contractUsersRes === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError(t("something-went-wrong-mssg"));
setIsLoading(loadObj);
} else if (contractUsersRes[0] && contractUsersRes.length > 0) {
setActiveMailAdapter(contractUsersRes[0]?.active_mail_adapter);
setContractName("_Users");
setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss =
contractUsersRes[0].TourStatus && contractUsersRes[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
);
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook.length > 0) {
setContractName("_Contactbook");
setSignerUserId(contractContactBook[0].objectId);
//function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId);
console.log("defaultSignRes", defaultSignRes);
if (defaultSignRes?.status === "success") {
setDefaultSignImg(defaultSignRes?.res?.defaultSignature);
setMyInitial(defaultSignRes?.res?.defaultInitial);
} else if (defaultSignRes?.status === "error") {
setHandleError("Error: Something went wrong!");
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);
} else if (contractUsersRes[0] && contractUsersRes.length > 0) {
setActiveMailAdapter(contractUsersRes[0]?.active_mail_adapter);
setContractName("_Users");
setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss =
contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus;
contractUsersRes[0].TourStatus && contractUsersRes[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
@@ -343,13 +303,44 @@ function SignYourSelf() {
} else {
setCheckTourStatus(true);
}
} else {
setHandleError(t("no-data-avaliable"));
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook.length > 0) {
setContractName("_Contactbook");
setSignerUserId(contractContactBook[0].objectId);
const tourstatuss =
contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
);
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
}
} else {
setHandleError(t("no-data-avaliable"));
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const loadObj = {
} catch (err) {
console.log("Error: error in getDocumentDetails", err);
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
};
setIsLoading(loadObj);
});
}
};
const getWidgetValue = (type) => {
@@ -1313,7 +1304,7 @@ function SignYourSelf() {
isEmail={isEmail}
pdfUrl={pdfUrl}
setIsEmail={setIsEmail}
pdfName={pdfDetails[0] && pdfDetails[0].Name}
pdfDetails={pdfDetails}
setSuccessEmail={setSuccessEmail}
sender={jsonSender}
setIsAlert={setIsAlert}
+1
View File
@@ -97,6 +97,7 @@ const TeamList = () => {
const pageNumbers = getPaginationRange();
useEffect(() => {
fetchTeamList();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function fetchTeamList() {
try {
@@ -119,7 +119,9 @@ const UpdateExistUserAdmin = () => {
onChange={(e) =>
setFormdata((prev) => ({
...prev,
email: e.target.value?.toLowerCase()
email: e.target.value
?.toLowerCase()
?.replace(/\s/g, "")
}))
}
onInvalid={(e) =>
+1
View File
@@ -85,6 +85,7 @@ const UserList = () => {
const pageNumbers = getPaginationRange();
useEffect(() => {
fetchUserList();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function fetchUserList() {
try {
+5 -2
View File
@@ -7,7 +7,7 @@ import Title from "../components/Title";
import sanitizeFileName from "../primitives/sanitizeFileName";
import axios from "axios";
import Tooltip from "../primitives/Tooltip";
import { isEnableSubscription } from "../constant/const";
import { isEnableSubscription, isStaging } from "../constant/const";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
@@ -57,6 +57,7 @@ function UserProfile() {
useEffect(() => {
getUserDetail();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const getUserDetail = async () => {
@@ -475,7 +476,9 @@ function UserProfile() {
/>
</span>
<div className="flex md:flex-row flex-col md:items-center">
<span className="mb-1 md:mb-1">opensign.me/</span>
<span className="mb-1 md:mb-1">
{isStaging ? "staging.opensign.me/" : " opensign.me/"}
</span>
{editmode ? (
<input
maxLength={40}
+3 -1
View File
@@ -222,7 +222,9 @@ const AddContact = (props) => {
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
onChange={(e) =>
setEmail(e.target.value?.toLowerCase()?.replace(/\s/g, ""))
}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
@@ -4,7 +4,7 @@ import { useLocation, useNavigate } from "react-router-dom";
import axios from "axios";
import ModalUi from "./ModalUi";
import AddSigner from "../components/AddSigner";
import { isEnableSubscription } from "../constant/const";
import { isEnableSubscription, isStaging } from "../constant/const";
import Alert from "./Alert";
import Tooltip from "./Tooltip";
import { RWebShare } from "react-web-share";
@@ -990,9 +990,16 @@ const ReportTable = (props) => {
}
};
const publicUrl = () => {
const subDomain = isStaging
? `https://staging.opensign.me/`
: `https://opensign.me/`;
const url = `${subDomain}${publicUserName}`;
return url;
};
// function to copy public profile links
const copytoProfileLink = () => {
const url = `https://opensign.me/${publicUserName}`;
const url = publicUrl();
copytoData(url);
setIsAlert(true);
setAlertMsg({
@@ -1198,7 +1205,8 @@ const ReportTable = (props) => {
)}
{props.heading.includes("Folder") && (
<td className="px-4 py-2">
{item?.Folder?.Name || t("OpenSign™ Drive")}
{item?.Folder?.Name ||
t("sidebar.OpenSign™ Drive")}
</td>
)}
<td className="px-4 py-2">
@@ -1325,7 +1333,9 @@ const ReportTable = (props) => {
<span
onClick={() => copytoProfileLink()}
className="underline underline-offset-2 w-[150px] md:w-[350px] whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer"
>{`https://opensign.me/${publicUserName}`}</span>
>
{publicUrl()}
</span>
</div>
</div>
) : (
@@ -23,6 +23,7 @@ const ValidateRoute = () => {
}
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handlelogout = async () => {
let appdata = localStorage.getItem("userSettings");
+17 -9
View File
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import Parse from "parse";
import ReactDOM from "react-dom/client";
import PdfRequestFiles from "../pages/PdfRequestFiles";
@@ -6,6 +6,8 @@ import { pdfjs } from "react-pdf";
import { Provider } from "react-redux";
import { store } from "../redux/store";
import "../index.css";
import "../i18n";
import { isPublicStaging } from "../constant/const";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`;
// Wrapper component to manage props
@@ -13,15 +15,22 @@ const PublicScriptFileWrapper = ({ initialProps }) => {
const [props, setProps] = useState(initialProps);
// Make the setProps function globally accessible
window.updatePublicTemplateProps = setProps;
useEffect(() => {
window.updatePublicTemplateProps = setProps;
return () => {
window.updatePublicTemplateProps = undefined;
};
}, []);
return <PdfRequestFiles {...props} />;
};
const appId = "legadranaxn";
// "opensign";
const serverUrl = "https://app.opensignlabs.com/api/app";
// "https://staging-app.opensignlabs.com/api/app";
const appId = isPublicStaging ? "opensign" : "legadranaxn";
const serverUrl = isPublicStaging
? "https://staging-app.opensignlabs.com/api/app"
: "https://app.opensignlabs.com/api/app";
localStorage.setItem("baseUrl", `${serverUrl}/`);
localStorage.setItem("parseAppId", appId);
Parse.initialize(appId);
@@ -38,9 +47,8 @@ document.head.appendChild(link);
//add the Tailwind CSS file
const tailwindCssLink = document.createElement("link");
tailwindCssLink.href =
"https://app.opensignlabs.com/static/js/public-template.bundle.css"; // css bundle file
// "https://staging-app.opensignlabs.com/static/js/public-template.bundle.css"; // css bundle file
tailwindCssLink.rel = "stylesheet";
// "https://app.opensignlabs.com/static/js/public-template.bundle.css"; // css bundle file
tailwindCssLink.rel = "stylesheet";
document.head.appendChild(tailwindCssLink);
// Create a root and render the wrapper component with initial props
const root = ReactDOM.createRoot(document.getElementById("script-component"));
+1 -1
View File
@@ -50,7 +50,7 @@ module.exports = {
]
},
resolve: {
extensions: [".js", ".jsx"]
extensions: [".js", ".jsx", ".json"]
},
plugins: [
new Dotenv(),
@@ -21,12 +21,11 @@ async function GetPublicTemplate(request) {
templatQuery.equalTo('IsPublic', true);
templatQuery.notEqualTo('IsArchive', true);
const getTemplate = await templatQuery.find({ useMasterKey: true });
const extcls = new Parse.Query('contracts_Users');
extcls.equalTo('email', user.get('email'));
extcls.equalTo('Email', user.get('email'));
const res = await extcls.first({ useMasterKey: true });
if (res) {
const _res = JSON.parse(JSON.stringify(_res));
const _res = JSON.parse(JSON.stringify(res));
return {
template: getTemplate,
user: user,