Merge pull request #1292 from nxglabs/sync-to-public_repo-17730712175

Merge pull request #1291 from nxglabs/staging
This commit is contained in:
prafull-opensignlabs
2025-09-15 14:51:16 +00:00
parent 6cb2d69566
commit ca4ccfd889
45 changed files with 2541 additions and 2240 deletions
+1 -1
View File
@@ -51,7 +51,7 @@
"reactour": "^1.19.4",
"redux": "^5.0.1",
"regex-parser": "^2.3.1",
"serve": "^14.2.4",
"serve": "^14.2.5",
"styled-components": "^5.3.11",
"web-vitals": "^5.1.0",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
@@ -8,7 +8,7 @@
"dark-mode": "Dunkelmodus",
"name": "Name",
"phone": "Telefon",
"phone-optional": "optional",
"phone-optional": "Optional",
"email": "E-Mail",
"company": "Unternehmen",
"job-title": "Berufsbezeichnung",
@@ -1210,5 +1210,12 @@
"otp-email": "Wir haben einen Bestätigungscode gesendet",
"save-as-temp-warn": "Hinweis: Dieses Dokument enthält vorausgefüllte Widgets, die automatisch entfernt werden, da sie bereits im Basisdokument integriert sind.",
"edit-document": "Dokument bearbeiten",
"otp-email": "Wir haben einen Bestätigungscode gesendet"
"modify": "Ändern",
"merge-certificate-to-pdf": "Zertifikat mit PDF zusammenführen",
"merge-cc-to-pdf-help": {
"p1": "Dies stellt sicher, dass das Abschlusszertifikat im endgültigen PDF-Dokument enthalten ist. Bitte beachten Sie jedoch, dass das Zertifikat nach dem Zusammenführen nicht mehr vom Hauptdokument getrennt werden kann.",
"p2": "Wenn Sie sich entscheiden, nicht zusammenzuführen, wird das Abschlusszertifikat als separate PDF-Datei zusammen mit dem unterzeichneten Dokument bereitgestellt."
},
"enter-name": "Name eingeben",
"enter-email": "E-Mail eingeben"
}
@@ -8,7 +8,7 @@
"dark-mode": "Dark mode",
"name": "Name",
"phone": "Phone",
"phone-optional": "optional",
"phone-optional": "Optional",
"email": "Email",
"company": "Company",
"job-title": "Job title",
@@ -1211,5 +1211,12 @@
"otp-email":"Weve sent a verification code to",
"save-as-temp-warn":"Note: This document includes prefilled widgets, which will be automatically removed as they are already incorporated into the base document.",
"edit-document": "Edit document",
"otp-email":"We've sent a verification code to"
"modify": "Modify",
"merge-certificate-to-pdf": "Merge Certificate to PDF",
"merge-cc-to-pdf-help": {
"p1": "This will ensure that the completion certificate is included in the final PDF document. However, please note that once merged, the certificate cannot be separated from the main document.",
"p2": "If you choose not to merge, the completion certificate will be provided as a separate PDF file along with the signed document."
},
"enter-name": "Enter name",
"enter-email": "Enter email"
}
@@ -8,7 +8,7 @@
"dark-mode": "Modo oscuro",
"name": "Nombre",
"phone": "Teléfono",
"phone-optional": "opcional",
"phone-optional": "Opcional",
"email": "Correo",
"company": "Compañía",
"job-title": "Título del puesto",
@@ -1211,5 +1211,12 @@
"otp-email": "Hemos enviado un código de verificación",
"save-as-temp-warn": "Nota: Este documento incluye widgets prellenados, que se eliminarán automáticamente ya que ya están incorporados en el documento base.",
"edit-document": "Editar documento",
"otp-email": "Hemos enviado un código de verificación"
"modify": "Modificar",
"merge-certificate-to-pdf": "Combinar certificado con PDF",
"merge-cc-to-pdf-help": {
"p1": "Esto garantizará que el certificado de finalización esté incluido en el documento PDF final. Sin embargo, tenga en cuenta que una vez combinado, el certificado no se podrá separar del documento principal.",
"p2": "Si elige no combinar, el certificado de finalización se proporcionará como un archivo PDF separado junto con el documento firmado."
},
"enter-name": "Ingrese nombre",
"enter-email": "Ingrese correo electrónico"
}
@@ -8,7 +8,7 @@
"dark-mode": "Mode sombre",
"name": "Nom et Prénom",
"phone": "Téléphone",
"phone-optional": "(facultatif)",
"phone-optional": "Optionnel",
"email": "E-mail",
"company": "Organisation",
"job-title": "Votre Fonction",
@@ -1210,5 +1210,12 @@
"otp-email": "Nous avons envoyé un code de vérification",
"save-as-temp-warn": "Remarque : Ce document contient des widgets préremplis, qui seront automatiquement supprimés car ils sont déjà intégrés dans le document de base.",
"edit-document": "Modifier le document",
"otp-email": "Nous avons envoyé un code de vérification"
"modify": "Modifier",
"merge-certificate-to-pdf": "Fusionner le certificat avec le PDF",
"merge-cc-to-pdf-help": {
"p1": "Cela garantira que le certificat de finalisation est inclus dans le document PDF final. Cependant, veuillez noter qu'une fois fusionné, le certificat ne peut plus être séparé du document principal.",
"p2": "Si vous choisissez de ne pas fusionner, le certificat de finalisation sera fourni sous forme de fichier PDF distinct accompagné du document signé."
},
"enter-name": "Saisir le nom",
"enter-email": "Saisir l'e-mail"
}
@@ -1210,5 +1210,13 @@
"otp-email": "हमने एक सत्यापन कोड भेजा है",
"save-as-temp-warn": "नोट: इस दस्तावेज़ में पहले से भरे हुए विजेट शामिल हैं, जिन्हें स्वचालित रूप से हटा दिया जाएगा क्योंकि वे पहले से ही मूल दस्तावेज़ में सम्मिलित हैं।",
"edit-document": "दस्तावेज़ संपादित करें",
"otp-email": "हमने एक सत्यापन कोड भेजा है"
"modify": "संशोधित करें",
"merge-certificate-to-pdf": "प्रमाणपत्र को PDF में मिलाएँ",
"merge-cc-to-pdf-help": {
"p1": "यह सुनिश्चित करेगा कि पूर्णता प्रमाणपत्र अंतिम PDF दस्तावेज़ में शामिल हो। हालाँकि, कृपया ध्यान दें कि एक बार मिलाने के बाद, प्रमाणपत्र को मुख्य दस्तावेज़ से अलग नहीं किया जा सकता।",
"p2": "यदि आप मिलाना नहीं चुनते हैं, तो पूर्णता प्रमाणपत्र हस्ताक्षरित दस्तावेज़ के साथ एक अलग PDF फ़ाइल के रूप में प्रदान किया जाएगा।"
},
"enter-name": "नाम दर्ज करें",
"enter-email": "ईमेल दर्ज करें"
}
@@ -8,7 +8,7 @@
"dark-mode": "Modalità scura",
"name": "Nome",
"phone": "Telefono",
"phone-optional": "facoltativo",
"phone-optional": "Opzionale",
"email": "Email",
"company": "Azienda",
"job-title": "Titolo professionale",
@@ -1210,5 +1210,12 @@
"otp-email": "Abbiamo inviato un codice di verifica",
"save-as-temp-warn": "Nota: Questo documento include widget precompilati, che verranno automaticamente rimossi poiché sono già incorporati nel documento di base.",
"edit-document": "Modifica documento",
"otp-email": "Abbiamo inviato un codice di verifica"
"modify": "Modifica",
"merge-certificate-to-pdf": "Unisci certificato al PDF",
"merge-cc-to-pdf-help": {
"p1": "Questo garantirà che il certificato di completamento sia incluso nel documento PDF finale. Tuttavia, si noti che una volta unito, il certificato non può essere separato dal documento principale.",
"p2": "Se scegli di non unire, il certificato di completamento sarà fornito come file PDF separato insieme al documento firmato."
},
"enter-name": "Inserisci nome",
"enter-email": "Inserisci e-mail"
}
@@ -244,6 +244,7 @@ const AddSigner = (props) => {
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-name")}
/>
</div>
<div className="mb-3">
@@ -263,6 +264,7 @@ const AddSigner = (props) => {
onInput={(e) => e.target.setCustomValidity("")}
disabled={addYourself}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-email")}
/>
</div>
<div className="mb-3">
+2
View File
@@ -179,6 +179,7 @@ const AddUser = (props) => {
onInput={(e) => e.target.setCustomValidity("")}
required
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-name")}
/>
</div>
<div className="mb-3">
@@ -200,6 +201,7 @@ const AddUser = (props) => {
}
onInput={(e) => e.target.setCustomValidity("")}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-email")}
/>
</div>
<div className="mb-3">
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import { useState, useEffect } from "react";
import axios from "axios";
import Parse from "parse";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
@@ -168,25 +168,21 @@ const DashboardCard = (props) => {
}
}
setresponse(arr.length);
setLoading(false);
});
} else {
await axios.get(url, { headers: headers }).then((res) => {
if (res.data.results.length > 0) {
setLoading(false);
if (props.Data.key !== "count") {
setresponse(res.data.results[0][props.Data.key]);
} else {
setresponse(res.data[props.Data.key]);
}
if (res?.data?.[props.Data.key]) {
setresponse(parseInt(res.data[props.Data.key]));
} else if (res?.data?.results?.length > 0) {
setresponse(res.data.results.length);
} else {
setresponse(0);
setLoading(false);
}
});
}
} catch (e) {
console.error("Problem", e);
} finally {
setLoading(false);
}
}
@@ -52,7 +52,7 @@ const EditTemplate = ({
Bcc: template?.Bcc,
RedirectUrl: template?.RedirectUrl || "",
AllowModifications: template?.AllowModifications || false,
TimeToCompleteDays: template?.TimeToCompleteDays || 15
TimeToCompleteDays: template?.TimeToCompleteDays || 15,
});
const [isUpdate, setIsUpdate] = useState(false);
const [showConfirm, setShowConfirm] = useState(false);
@@ -244,6 +244,7 @@ const EditTemplate = ({
setShowConfirm(false);
handleClose();
};
return (
<ModalUi
isOpen
+67 -56
View File
@@ -167,7 +167,9 @@ function Header(props) {
);
};
const handleDownloadBtn = async () => {
if (props?.isCompleted) {
if (
props?.isCompleted
) {
props?.setIsDownloadModal(true);
} else {
await handleDownloadDoc();
@@ -222,25 +224,27 @@ function Header(props) {
{t("download")}
</div>
</DropdownMenu.Item>
{props?.isCompleted && (
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
>
<div className="border-none bg-[#fff]">
<i
className="fa-light fa-award mr-[3px]"
aria-hidden="true"
></i>
{t("certificate")}
</div>
</DropdownMenu.Item>
)}
{
props?.isCompleted && (
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
>
<div className="border-none bg-[#fff]">
<i
className="fa-light fa-award mr-[3px]"
aria-hidden="true"
></i>
{t("certificate")}
</div>
</DropdownMenu.Item>
)
}
{props?.isSignYourself && (
<DropdownMenu.Item
className="DropdownMenuItem"
@@ -518,24 +522,28 @@ function Header(props) {
></i>
<span className="hidden lg:block">{t("print")}</span>
</button>
{props?.isCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
>
<i
className="fa-light fa-award py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">{t("certificate")}</span>
</button>
)}
{
props?.isCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
>
<i
className="fa-light fa-award py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">
{t("certificate")}
</span>
</button>
)
}
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
@@ -592,23 +600,25 @@ function Header(props) {
)
) : props?.isCompleted ? (
<div className="flex flex-row">
{props?.isCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa-light fa-award" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">
{t("certificate")}
</span>
</button>
)}
{
props?.isCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(
props?.pdfDetails,
setIsDownloading
)
}
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa-light fa-award" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">
{t("certificate")}
</span>
</button>
)
}
<button
onClick={(e) =>
handleToPrint(e, setIsDownloading, props?.pdfDetails)
@@ -622,7 +632,8 @@ function Header(props) {
<button
type="button"
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
onClick={() => props?.setIsDownloadModal(true)}
// onClick={() => props?.setIsDownloadModal(true)}
onClick={() => handleDownloadBtn()}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">{t("download")}</span>
@@ -441,14 +441,12 @@ function PrefillWidgetModal(props) {
handleCheckboxValue(e.target.checked, ind, position);
}}
/>
{!position.options?.isHideLabel && (
<label
htmlFor={`checkbox-${position.key + ind}`}
className="text-xs mb-0 text-center ml-[3px] cursor-pointer"
>
{data}
</label>
)}
<label
htmlFor={`checkbox-${position.key + ind}`}
className="text-xs mb-0 text-center ml-[3px] cursor-pointer"
>
{data}
</label>
</div>
))}
</div>
@@ -560,14 +558,12 @@ function PrefillWidgetModal(props) {
handleWidgetDetails(position, data);
}}
/>
{!position.options?.isHideLabel && (
<label
htmlFor={`radio-${position.key + ind}`}
className="text-xs mb-0 ml-[2px] cursor-pointer"
>
{data}
</label>
)}
<label
htmlFor={`radio-${position.key + ind}`}
className="text-xs mb-0 ml-[2px] cursor-pointer"
>
{data}
</label>
</div>
))}
</div>
@@ -591,8 +587,8 @@ function PrefillWidgetModal(props) {
}
};
const handleEmbedPrefill = (item) => {
props.handleCreateDocument();
const handleEmbedPrefill = async (item) => {
await props.handleCreateDocument();
};
//`loadOptions` function to use show all list of signer in dropdown
const loadOptions = async (inputValue) => {
@@ -654,7 +650,7 @@ function PrefillWidgetModal(props) {
handleClose={props.handleClosePrefillModal}
>
<div className="relative">
{loading && (
{(props?.isSubmit || loading) && (
<div className="absolute inset-0 flex items-center justify-center bg-white/70 z-[9999]">
<Loader />
</div>
@@ -733,7 +729,7 @@ function PrefillWidgetModal(props) {
</div>
<div className="flex gap-2 mx-4 mb-3">
<button
disabled={isAnyLoaderActive}
disabled={isAnyLoaderActive || props?.isSubmit}
className="op-btn op-btn-primary op-btn-sm w-[80px]"
onClick={() => handleEmbedPrefill(props?.item)}
>
@@ -36,7 +36,8 @@ import {
setLastIndex,
setScrollTriggerId,
setPrefillImg,
setPrefillImgLoad
setPrefillImgLoad,
setTypedSignFont
} from "../../redux/reducers/widgetSlice";
import { useDispatch, useSelector } from "react-redux";
import Loader from "../../primitives/Loader";
@@ -79,6 +80,7 @@ function WidgetsValueModal(props) {
const defaultSignImg = useSelector((state) => state.widget.defaultSignImg);
const myInitial = useSelector((state) => state.widget.myInitial);
const lastWidget = useSelector((state) => state.widget.lastIndex);
const typedSignFont = useSelector((state) => state.widget.typedSignFont);
const { t } = useTranslation();
const canvasRef = useRef(null);
const imageRef = useRef(null);
@@ -278,10 +280,7 @@ function WidgetsValueModal(props) {
setIsLoader(true);
try {
dispatch(
setPrefillImg({
id: currWidgetsDetails?.key,
base64: image?.src
})
setPrefillImg({ id: currWidgetsDetails?.key, base64: image?.src })
);
const imageName = generatePdfName(16);
const imageUrl = await convertBase64ToFile(
@@ -630,11 +629,12 @@ function WidgetsValueModal(props) {
useEffect(() => {
const loadFont = async () => {
try {
await document.fonts.load(`20px ${fontSelect}`);
const selectFontSTyle = fontOptions.find(
(font) => font.value === fontSelect
const selectedFont = typedSignFont || fontSelect;
await document.fonts.load(`20px ${selectedFont}`);
const selectFontStyle = fontOptions.find(
(font) => font.value === selectedFont
);
setFontSelect(selectFontSTyle?.value || fontOptions[0].value);
setFontSelect(selectFontStyle?.value || fontOptions[0].value);
} catch (error) {
console.error("Error loading font:", error);
}
@@ -697,12 +697,13 @@ function WidgetsValueModal(props) {
const maxWidth = currWidgetsDetails?.Width;
const maxHeight = currWidgetsDetails?.Height;
const widgetDims = { Width: maxWidth, Height: maxHeight };
const fontFamily = fontStyle || fontSelect || "Fasthand";
const fontFamily = fontStyle || typedSignFont || fontSelect || "Fasthand";
const fillColor = color || penColor;
const dataUrl = convertTextToImg(fontFamily, text, fillColor, widgetDims);
setSignature(dataUrl);
setTextWidth(maxWidth);
setTextHeight(maxHeight);
dispatch(setTypedSignFont(fontFamily));
};
const PenColorComponent = () => {
return (
+5 -2
View File
@@ -823,6 +823,8 @@ export const createDocument = async (
) => {
if (template && template.length > 0) {
const Doc = template[0];
const date = new Date();
const isoDate = date.toISOString();
let extUserId = Doc.ExtUserPtr.objectId;
let creatorId = Doc.CreatedBy.objectId;
const Extand_Class = localStorage.getItem("Extand_Class");
@@ -898,6 +900,7 @@ export const createDocument = async (
IsTourEnabled: Doc?.IsTourEnabled || false,
AllowModifications: Doc?.AllowModifications || false,
TimeToCompleteDays: parseInt(Doc?.TimeToCompleteDays) || 15,
DocSentAt: { __type: "Date", iso: isoDate },
...SignatureType,
...NotifyOnSignatures,
...Bcc,
@@ -3429,10 +3432,10 @@ export const updateDateWidgetsRes = (
journey,
isRemovePrefill
) => {
const extUser = localStorage.getItem("Extand_Class");
const contactUser = documentData?.Signers.find(
const contactUser = documentData?.Signers?.find(
(data) => data.objectId === signerId
);
const extUser = JSON.stringify([contactUser]);
let placeHolders = documentData?.Placeholders;
if (isRemovePrefill) {
placeHolders = placeHolders?.filter((x) => x.Role !== "prefill");
+2 -1
View File
@@ -2,10 +2,11 @@ import { useEffect, useMemo } from "react";
export function useManifestUrl(appName, logo) {
const url = useMemo(() => {
const start_url = window.location.origin || ".";
const manifest = {
short_name: appName,
name: appName,
start_url: ".",
start_url: start_url,
display: "standalone",
theme_color: "#000000",
background_color: "#ffffff",
+1 -39
View File
@@ -11,7 +11,7 @@ export const extraCols = [
export default function reportJson(id) {
const head = ["Title", "Note", "Folder", "File", "Owner", "Signers"];
const declineHead = ["Title", "Reason", "Folder", "File", "Owner", "Signers"];
const iphead = ["Title", "Note", "Folder", "File", "Signers"];
const iphead = ["Title", "Note", "Folder", "File", "Signers", "Sent Date"];
const contactbook = ["Name", "Email", "Phone", "Company", "JobTitle"];
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
const templateReport = ["Title", "File", "Owner", "Signers"];
@@ -38,25 +38,6 @@ export default function reportJson(id) {
redirectUrl: "",
action: "delete"
}
// {
// btnId: "22534",
// hoverLabel: "option",
// btnColor: "",
// restrictBtn: true,
// textColor: "black",
// btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
// action: "option",
// subaction: [
// {
// btnId: "1630",
// btnLabel: "Save as template",
// hoverLabel: "Save as template",
// btnIcon: "fa-light fa-envelope",
// redirectUrl: "",
// action: "saveastemplate"
// }
// ]
// }
],
helpMsg:
"These are documents you have started but have not finalized for sending."
@@ -429,25 +410,6 @@ export default function reportJson(id) {
redirectUrl: "",
action: "delete"
}
// {
// btnId: "55534",
// hoverLabel: "option",
// btnColor: "",
// restrictBtn: true,
// textColor: "black",
// btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
// action: "option",
// subaction: [
// {
// btnId: "6630",
// btnLabel: "Save as template",
// hoverLabel: "Save as template",
// btnIcon: "fa-light fa-envelope",
// redirectUrl: "",
// action: "saveastemplate"
// }
// ]
// }
]
};
// contactbook report
+1 -1
View File
@@ -36,7 +36,7 @@ const dashboardJson = [
queryType: "",
class: "contracts_Document",
query:
'where={"Type":null,"Signers":{"#*exists":true},"Placeholders":{"#*exists":true},"SignedUrl":{"#*exists":true},"IsCompleted":false,"IsDeclined":false,"IsArchive":null,"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&keys=Name,ExpiryDate,SignedUrl,Signers&count=1',
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true},"Placeholders":{"#*exists":true},"SignedUrl":{"#*exists":true},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1&limit=0',
key: "count",
Redirect_type: "Report",
Redirect_id: "1MwEuxLEkF",
+24 -17
View File
@@ -41,7 +41,7 @@ const DocSuccessPage = () => {
objectId: docId,
SignedUrl: docUrl,
CertificateUrl: certificate,
IsCompleted: completed
IsCompleted: completed,
};
setPdfDetails([details]);
const base64Pdf = await getBase64FromUrl(docUrl);
@@ -52,7 +52,9 @@ const DocSuccessPage = () => {
};
const handleDownload = () => {
if (pdfDetails?.[0]?.IsCompleted) {
if (
pdfDetails?.[0]?.IsCompleted
) {
setIsDownloadModal(true);
} else {
handleDownloadPdf(pdfDetails, setIsDownloading, pdfBase64Url);
@@ -99,21 +101,26 @@ const DocSuccessPage = () => {
<span>{t("download")}</span>
</button>
{pdfDetails?.[0]?.IsCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(pdfDetails, setIsDownloading)
}
className="font-medium text-sm md:text-[13px] md:px-4 py-2 op-btn op-btn-secondary"
>
<i
className="fa-light fa-award mx-[3px] md:mx-0"
aria-hidden="true"
></i>
<span>{t("certificate")}</span>
</button>
)}
{
pdfDetails?.[0]?.IsCompleted && (
<button
type="button"
onClick={() =>
handleDownloadCertificate(
pdfDetails,
setIsDownloading
)
}
className="font-medium text-sm md:text-[13px] md:px-4 py-2 op-btn op-btn-secondary"
>
<i
className="fa-light fa-award mx-[3px] md:mx-0"
aria-hidden="true"
></i>
<span>{t("certificate")}</span>
</button>
)
}
<button
onClick={(e) =>
handleToPrint(e, setIsDownloading, pdfDetails)
+4 -4
View File
@@ -67,7 +67,7 @@ const Forms = (props) => {
NotifyOnSignatures: "",
Bcc: [],
RedirectUrl: "",
AllowModifications: false
AllowModifications: false,
});
const [fileupload, setFileUpload] = useState("");
const [selectedFiles, setSelectedFiles] = useState([]);
@@ -461,7 +461,7 @@ const Forms = (props) => {
IsEnableOTP: "false",
IsTourEnabled: istourenabled,
RedirectUrl: "",
AllowModifications: false
AllowModifications: false,
});
setFileUpload("");
setSelectedFiles([]);
@@ -541,7 +541,7 @@ const Forms = (props) => {
IsTourEnabled: istourenabled,
NotifyOnSignatures: notifySign,
RedirectUrl: "",
AllowModifications: false
AllowModifications: false,
};
setFormData(obj);
removeFile();
@@ -1047,7 +1047,7 @@ const Forms = (props) => {
></div>
)}
{isAdvanceOpt && (
<div className="card bg-base-100 rounded-box p-3 flex-grow ">
<div className="card bg-base-100 rounded-box p-3 flex-grow ">
{formData?.autoreminder === true &&
props.title !== "New Template" && (
<div className="text-xs mt-2">
+2
View File
@@ -378,6 +378,7 @@ function GuestLogin() {
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
placeholder={t("enter-name")}
required
/>
</div>
@@ -395,6 +396,7 @@ function GuestLogin() {
value={contact.email}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-email")}
required
disabled
/>
+29 -28
View File
@@ -14,8 +14,9 @@ import {
setMyInitial,
setDefaultSignImg,
resetWidgetState,
setPrefillImg
} from "../redux/reducers/widgetSlice.js";
setPrefillImg,
setTypedSignFont
} from "../redux/reducers/widgetSlice";
import {
contractDocument,
embedWidgetsToDoc,
@@ -736,6 +737,7 @@ function PdfRequestFiles(
widgets
);
if (resSign && resSign.status === "success") {
dispatch(setTypedSignFont("Fasthand"));
setPdfUrl(resSign.data);
setIsSigned(true);
setSignedSigners([]);
@@ -884,7 +886,8 @@ function PdfRequestFiles(
?.IsCompleted
? `&completed=true`
: "";
const params = `docid=${updatedDoc.updatedPdfDetails[0].objectId}&docurl=${encodeURIComponent(url)}${isCompleted}${fileAdapter}`;
const params =
`docid=${updatedDoc.updatedPdfDetails[0].objectId}&docurl=${encodeURIComponent(url)}${isCompleted}${fileAdapter}`;
window.location.href = `/success?${params}`;
}
} else {
@@ -1714,6 +1717,10 @@ function PdfRequestFiles(
}
return email;
};
const handleDownload = async () => {
setIsCompleted((prev) => ({ ...prev, isModal: false }));
setIsDownloadModal(true);
};
return (
<>
{isLoading.isLoad ? (
@@ -1925,34 +1932,28 @@ function PdfRequestFiles(
{t("print")}
</span>
</button>
<button
type="button"
onClick={() =>
handleDownloadCertificate(
pdfDetails,
setIsDownloading
)
}
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-secondary"
>
<i
className="fa-light fa-award mx-[3px] lg:mx-0"
aria-hidden="true"
></i>
<span className="hidden lg:block">
{t("certificate")}
</span>
</button>
<button
type="button"
onClick={() =>
handleDownloadCertificate(
pdfDetails,
setIsDownloading
)
}
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-secondary"
>
<i
className="fa-light fa-award mx-[3px] lg:mx-0"
aria-hidden="true"
></i>
<span className="hidden lg:block">
{t("certificate")}
</span>
</button>
<button
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
onClick={() => {
setIsCompleted((prev) => ({
...prev,
isModal: false
}));
setIsDownloadModal(true);
}}
onClick={handleDownload}
>
<i
className="fa-light fa-download"
+4 -3
View File
@@ -61,6 +61,7 @@ const Preferences = () => {
completionMail: false
});
const [fileNameFormat, setFileNameFormat] = useState("DOCNAME");
useEffect(() => {
fetchSignType();
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -194,7 +195,7 @@ const Preferences = () => {
DateFormat: dateFormat,
Is12HourTime: is12HourTime,
IsLTVEnabled: isLTVEnabled,
DownloadFilenameFormat: fileNameFormat
DownloadFilenameFormat: fileNameFormat,
};
const updateRes = await Parse.Cloud.run("updatepreferences", params);
if (updateRes) {
@@ -804,7 +805,7 @@ const Preferences = () => {
onClick={() => handleModifyMail("request")}
className="op-btn op-btn-primary shadow-lg"
>
Modify
{t("modify")}
</button>
</div>
)
@@ -880,7 +881,7 @@ const Preferences = () => {
onClick={() => handleModifyMail("completion")}
className="op-btn op-btn-primary shadow-lg"
>
Modify
{t("modify")}
</button>
</div>
)
+6 -3
View File
@@ -32,7 +32,10 @@ const Report = () => {
const [defaultColumns, setDefaultColumns] = useState([]);
const [isColumnModal, setIsColumnModal] = useState(false);
const debounceTimer = useRef(null);
const docPerPage = 20;
// Number of documents to display per page (should always be half of docLimit for proper pagination)
const docPerPage = 10;
// Number of documents to fetch per API call
const docLimit = 20;
// below useEffect is call when id param change
useEffect(() => {
@@ -48,7 +51,7 @@ const Report = () => {
setVisibleColumns([]);
setColumnLabels({});
}
getReportData(0, docPerPage, "");
getReportData(0, docLimit, "");
// Function returned from useEffect is called on unmount
return () => {
@@ -64,7 +67,7 @@ const Report = () => {
// below useEffect call when isNextRecord state is true and fetch next record
useEffect(() => {
if (isNextRecord) {
getReportData(list.length, 20, searchTerm);
getReportData(list?.length, docLimit, searchTerm);
}
// eslint-disable-next-line
}, [isNextRecord]);
+4 -2
View File
@@ -63,8 +63,9 @@ import {
setMyInitial,
setDefaultSignImg,
setIsShowModal,
resetWidgetState
} from "../redux/reducers/widgetSlice.js";
resetWidgetState,
setTypedSignFont
} from "../redux/reducers/widgetSlice";
import WidgetsValueModal from "../components/pdf/WidgetsValueModal";
import WidgetNameModal from "../components/pdf/WidgetNameModal";
import CellsSettingModal from "../components/pdf/CellsSettingModal";
@@ -745,6 +746,7 @@ function SignYourSelf() {
if (resSignPdf) {
const signedpdf = JSON.parse(JSON.stringify(resSignPdf));
setPdfUrl(signedpdf);
dispatch(setTypedSignFont("Fasthand"));
getDocumentDetails(false);
}
};
@@ -165,6 +165,7 @@ const TemplatePlaceholder = () => {
const [currUserId, setCurrUserId] = useState(false);
const [documentDetails, setDocumentDetails] = useState();
const [copied, setCopied] = useState(false);
const [isUseTemplate, setIsUseTemplate] = useState(false);
const currentUser = localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
@@ -931,6 +932,7 @@ const TemplatePlaceholder = () => {
}
};
const handleCreateDocument = async () => {
setIsUseTemplate(true);
try {
setIsUiLoading(true);
const res = await utils?.handleCheckPrefillCreateDoc(
@@ -974,6 +976,7 @@ const TemplatePlaceholder = () => {
} catch (e) {
console.log("error in create document function", e);
}
setIsUseTemplate(false);
};
const navigatePageToDoc = async () => {
try {
@@ -2138,6 +2141,7 @@ const TemplatePlaceholder = () => {
isNewContact={isNewContact}
documentFlow={"template"}
docId={pdfDetails[0]?.objectId}
isSubmit={isUseTemplate}
/>
)}
{isShowModal[currWidgetsDetails?.key] && (
@@ -174,6 +174,7 @@ const AddContact = (props) => {
required
disabled={addYourself}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-name")}
/>
</div>
<div className="mb-[0.75rem]">
@@ -193,6 +194,7 @@ const AddContact = (props) => {
required
disabled={addYourself}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs lowercase"
placeholder={t("enter-email")}
/>
</div>
{isOptionalDetails && (
@@ -96,8 +96,8 @@ function DownloadPdfZip(props) {
handleClose={() => props.setIsDownloadModal(false)}
>
<div className="p-[20px] h-full text-base-content">
{downloadType.map((data, ind) => {
return (
{downloadType
.map((data, ind) => (
<label
key={ind}
className="flex items-center gap-1 mb-2 cursor-pointer"
@@ -111,8 +111,7 @@ function DownloadPdfZip(props) {
/>
{data.label}
</label>
);
})}
))}
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() => handleDownload()}
@@ -63,7 +63,7 @@ function CustomModal(props) {
className="op-btn op-btn-secondary ml-[10px] mb-3 mt-1"
onClick={() => props.handleDownloadBtn()}
>
Download
{t("download")}
</button>
)}
</div>
@@ -138,6 +138,12 @@ export const RenderReportCell = ({
{rowData?.ExpiryDate ? formatDate(rowData?.ExpiryDate?.iso) : "-"}
</td>
);
case "Sent Date":
return (
<td key={col} className="p-2 text-center">
{rowData?.DocSentAt ? formatDate(rowData?.DocSentAt?.iso) : "-"}
</td>
);
case "Signers":
return (
<SignerCell
@@ -13,7 +13,8 @@ const initialState = {
lastIndex: "",
scrollTriggerId: "",
prefillImg: [],
prefillImgLoad: {}
prefillImgLoad: {},
typedSignFont: "Fasthand"
};
const widgetSlice = createSlice({
@@ -41,6 +42,9 @@ const widgetSlice = createSlice({
setScrollTriggerId: (state, action) => {
state.scrollTriggerId = action.payload;
},
setTypedSignFont: (state, action) => {
state.typedSignFont = action.payload;
},
setPrefillImg: (state, action) => {
const existingIndex = state.prefillImg.findIndex(
(img) => img.id === action.payload.id
@@ -73,7 +77,8 @@ export const {
setLastIndex,
setScrollTriggerId,
setPrefillImg,
setPrefillImgLoad
setPrefillImgLoad,
setTypedSignFont
} = widgetSlice.actions;
export default widgetSlice.reducer;
@@ -88,6 +88,7 @@ const EditContactForm = (props) => {
onInput={(e) => e.target.setCustomValidity("")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-name")}
required
/>
</div>
@@ -105,6 +106,7 @@ const EditContactForm = (props) => {
onInput={(e) => e.target.setCustomValidity("")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
placeholder={t("enter-email")}
required
/>
</div>
@@ -90,6 +90,7 @@ const DocumentsReport = (props) => {
const [documentId, setDocumentId] = useState("");
const [isNewContact, setIsNewContact] = useState({ status: false, id: "" });
const [isPrefillModal, setIsPrefillModal] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const [error, setError] = useState("");
const [isMailModal, setIsMailModal] = useState(false);
const [customizeMail, setCustomizeMail] = useState({ body: "", subject: "" });
@@ -495,7 +496,9 @@ const DocumentsReport = (props) => {
const docId = props?.ReportName !== "Templates" && item.objectId;
if (url) {
try {
if (isCompleted) {
if (
isCompleted
) {
setIsDownloadModal({ [item.objectId]: true });
} else {
const signedUrl = await getSignedUrl(
@@ -920,6 +923,7 @@ const DocumentsReport = (props) => {
};
//`handlePrefillWidgetCreateDoc` is used to embed prefill all widgets on document, create document, and send document
const handlePrefillWidgetCreateDoc = async () => {
setIsSubmit(true);
const scale = 1;
const key = Object.keys(isPrefillModal)[0];
setActLoader({ [key]: true });
@@ -957,6 +961,7 @@ const DocumentsReport = (props) => {
alert(t("user-not-exist"));
}
}
setIsSubmit(false);
setActLoader({});
};
const handleRecipientSign = (documentId, currentId) => {
@@ -1027,10 +1032,10 @@ const DocumentsReport = (props) => {
if (isPrefill) {
return (
<span className="flex text-sm mt-3 text-red-500">
{t("save-as-temp-warn")}
{t("save-as-temp-warn")}
</span>
);
}
}
};
return (
<div className="relative">
@@ -1367,6 +1372,7 @@ const DocumentsReport = (props) => {
setIsNewContact={setIsNewContact}
isNewContact={isNewContact}
docId={item.objectId}
isSubmit={isSubmit}
/>
)}
{isModal["extendexpiry_" + item.objectId] && (
@@ -85,6 +85,7 @@ const TemplatesReport = (props) => {
const [documentId, setDocumentId] = useState("");
const [isNewContact, setIsNewContact] = useState({ status: false, id: "" });
const [isPrefillModal, setIsPrefillModal] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const startIndex = (currentPage - 1) * props.docPerPage;
const { isMoreDocs, setIsNextRecord } = props;
const [isMailModal, setIsMailModal] = useState(false);
@@ -871,6 +872,7 @@ const TemplatesReport = (props) => {
};
//`handlePrefillWidgetCreateDoc` is used to embed prefill all widgets on document, create document, and send document
const handlePrefillWidgetCreateDoc = async () => {
setIsSubmit(true);
const scale = 1;
const res = await utils?.handleCheckPrefillCreateDoc(
xyPosition,
@@ -940,6 +942,7 @@ const TemplatesReport = (props) => {
alert(t("user-not-exist"));
}
}
setIsSubmit(false);
};
//function show signer list and share link to share signUrl
const handleShareList = () => {
@@ -1257,6 +1260,7 @@ const TemplatesReport = (props) => {
setIsNewContact={setIsNewContact}
isNewContact={isNewContact}
docId={item.objectId}
isSubmit={isSubmit}
/>
)}
{isShareWith[item.objectId] && (