Merge pull request #1232 from OpenSignLabs/raktima-patch-3

This commit is contained in:
Andrew
2024-09-20 18:11:21 +05:30
committed by GitHub
17 changed files with 754 additions and 554 deletions
+70
View File
@@ -19,6 +19,7 @@
"i18next": "^23.14.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.1",
"jszip": "^3.10.1",
"jwt-decode": "^4.0.0",
"moment": "^2.30.1",
"nth-check": "^2.1.1",
@@ -12748,6 +12749,12 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
"license": "MIT"
},
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
@@ -16181,6 +16188,54 @@
"node": ">=4.0"
}
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"license": "(MIT OR GPL-3.0-or-later)",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/jszip/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/jszip/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/jszip/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/jszip/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
@@ -16286,6 +16341,15 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"license": "MIT",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lilconfig": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
@@ -22606,6 +22670,12 @@
"node": ">= 0.4"
}
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+1
View File
@@ -14,6 +14,7 @@
"i18next": "^23.14.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.1",
"jszip": "^3.10.1",
"jwt-decode": "^4.0.0",
"moment": "^2.30.1",
"nth-check": "^2.1.1",
@@ -650,6 +650,9 @@
},
"advanced-options":"Advanced options",
"hide-advanced-options":"Hide Advanced options",
"download-files":"Download files",
"download-pdf":"Download Pdf",
"pdf-certificate":"Download Pdf + Certificate",
"document-logs":"Document logs"
}
@@ -649,6 +649,9 @@
},
"advanced-options":"Options avancées",
"hide-advanced-options": "Masquer les options avancées",
"download-files" :"Télécharger des fichiers",
"download-pdf" :"Télécharger le PDF",
"pdf-certificate" :"Télécharger Pdf + Certificat",
"document-logs":"Journaux de documents"
}
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import axios from "axios";
import { handleDownloadPdf, handleToPrint } from "../../constant/Utils";
import { handleToPrint } from "../../constant/Utils";
import { themeColor, emailRegex } from "../../constant/const";
import Loader from "../../primitives/Loader";
import ModalUi from "../../primitives/ModalUi";
@@ -15,7 +15,8 @@ function EmailComponent({
sender,
setIsAlert,
extUserId,
activeMailAdapter
activeMailAdapter,
setIsDownloadModal
}) {
const { t } = useTranslation();
const [emailList, setEmailList] = useState([]);
@@ -129,6 +130,11 @@ function EmailComponent({
}
}
};
const handleClose = () => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
};
return (
<div>
{/* isEmail */}
@@ -165,9 +171,10 @@ function EmailComponent({
)}
<button
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
handleClose();
setIsDownloadModal(true);
}}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
{t("download")}
@@ -263,11 +270,7 @@ function EmailComponent({
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={() => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}}
onClick={() => handleClose()}
>
{t("close")}
</button>
+21 -20
View File
@@ -39,7 +39,8 @@ function Header({
clickOnZoomOut,
handleRotationFun,
isDisableRotate,
templateId
templateId,
setIsDownloadModal
}) {
const { t } = useTranslation();
const filterPrefill =
@@ -94,9 +95,13 @@ function Header({
>
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
if (isCompleted) {
setIsDownloadModal(true);
} else {
handleDownloadPdf(pdfDetails, setIsDownloading);
}
}}
>
<div className="flex flex-row">
<i
@@ -211,11 +216,7 @@ function Header({
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfDetails[0]?.URL,
setIsDownloading
)
handleDownloadPdf(pdfDetails, setIsDownloading)
}
>
<div className="flex flex-row">
@@ -386,9 +387,13 @@ function Header({
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
if (isCompleted) {
setIsDownloadModal(true);
} else {
handleDownloadPdf(pdfDetails, setIsDownloading);
}
}}
>
<i
className="fa-light fa-download py-[3px]"
@@ -443,11 +448,7 @@ function Header({
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
handleDownloadPdf(pdfDetails, setIsDownloading)
}
>
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
@@ -487,9 +488,9 @@ function Header({
<button
type="button"
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
setIsDownloadModal(true);
}}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">{t("download")}</span>
+34 -22
View File
@@ -2038,29 +2038,30 @@ export const fetchUrl = async (url, pdfName) => {
console.error("Error downloading the file:", error);
}
};
export const getSignedUrl = async (pdfUrl, docId) => {
//use only axios here due to public template sign
const axiosRes = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
{ url: pdfUrl, docId: docId || "" },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
return url;
};
//handle download signed pdf
export const handleDownloadPdf = async (
pdfDetails,
pdfUrl,
setIsDownloading
) => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
export const handleDownloadPdf = async (pdfDetails, setIsDownloading) => {
const pdfName = pdfDetails[0] && pdfDetails[0]?.Name;
const pdfUrl = pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL;
setIsDownloading("pdf");
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
{ url: pdfUrl, docId: docId },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
const url = await getSignedUrl(pdfUrl, docId);
await fetchUrl(url, pdfName);
setIsDownloading("");
} catch (err) {
@@ -2130,13 +2131,18 @@ export const handleToPrint = async (
//handle download signed pdf
export const handleDownloadCertificate = async (
pdfDetails,
setIsDownloading
setIsDownloading,
isZip
) => {
if (pdfDetails?.length > 0 && pdfDetails[0]?.CertificateUrl) {
try {
await fetch(pdfDetails[0] && pdfDetails[0]?.CertificateUrl);
const certificateUrl = pdfDetails[0] && pdfDetails[0]?.CertificateUrl;
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
if (isZip) {
return certificateUrl;
} else {
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
}
} catch (err) {
console.log("err in download in certificate", err);
}
@@ -2162,7 +2168,13 @@ export const handleDownloadCertificate = async (
if (doc?.CertificateUrl) {
await fetch(doc?.CertificateUrl);
const certificateUrl = doc?.CertificateUrl;
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
if (isZip) {
setIsDownloading("");
return certificateUrl;
} else {
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
}
setIsDownloading("");
} else {
setIsDownloading("certificate");
+22 -14
View File
@@ -28,7 +28,6 @@ import {
contractUsers,
handleSendOTP,
contactBook,
handleDownloadPdf,
handleToPrint,
handleDownloadCertificate,
getDefaultSignature,
@@ -36,21 +35,22 @@ import {
onClickZoomOut,
fetchUrl
} from "../constant/Utils";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
import Header from "../components/pdf/PdfHeader";
import RenderPdf from "../components/pdf/RenderPdf";
import PdfDeclineModal from "../primitives/PdfDeclineModal";
import Title from "../components/Title";
import DefaultSignature from "../components/pdf/DefaultSignature";
import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import Loader from "../primitives/Loader";
import { useSelector } from "react-redux";
import SignerListComponent from "../components/pdf/SignerListComponent";
import VerifyEmail from "../components/pdf/VerifyEmail";
import PdfZoom from "../components/pdf/PdfZoom";
import { useTranslation } from "react-i18next";
import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import HandleError from "../primitives/HandleError";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import DownloadPdfZip from "../primitives/DownloadPdfZip";
import Loader from "../primitives/Loader";
import PdfDeclineModal from "../primitives/PdfDeclineModal";
function PdfRequestFiles(props) {
const { t } = useTranslation();
@@ -136,6 +136,7 @@ function PdfRequestFiles(props) {
const [plancode, setPlanCode] = useState("");
const isHeader = useSelector((state) => state.showHeader);
const divRef = useRef(null);
const [isDownloadModal, setIsDownloadModal] = useState(false);
const isMobile = window.innerWidth < 767;
@@ -1996,13 +1997,13 @@ function PdfRequestFiles(props) {
<button
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
}
onClick={() => {
setIsCompleted((prev) => ({
...prev,
isModal: false
}));
setIsDownloadModal(true);
}}
>
<i
className="fa-light fa-download"
@@ -2082,6 +2083,7 @@ function PdfRequestFiles(props) {
clickOnZoomOut={clickOnZoomOut}
isDisableRotate={true}
templateId={props.templateId}
setIsDownloadModal={setIsDownloadModal}
/>
<div ref={divRef} data-tut="pdfArea" className="h-[95%]">
@@ -2208,6 +2210,12 @@ function PdfRequestFiles(props) {
</button>
</div>
</ModalUi>
<DownloadPdfZip
setIsDownloadModal={setIsDownloadModal}
isDownloadModal={isDownloadModal}
pdfDetails={pdfDetails}
isDocId={true}
/>
</>
)}
</DndProvider>
+9 -9
View File
@@ -11,8 +11,6 @@ import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import WidgetComponent from "../components/pdf/WidgetComponent";
import Tour from "reactour";
import { useLocation, useParams } from "react-router-dom";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
import SignerListPlace from "../components/pdf/SignerListPlace";
import Header from "../components/pdf/PdfHeader";
import { RWebShare } from "react-web-share";
@@ -45,23 +43,25 @@ import {
import RenderPdf from "../components/pdf/RenderPdf";
import { useNavigate } from "react-router-dom";
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
import LinkUserModal from "../primitives/LinkUserModal";
import Title from "../components/Title";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import ModalUi from "../primitives/ModalUi";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import WidgetNameModal from "../components/pdf/WidgetNameModal";
import { SaveFileSize } from "../constant/saveFileSize";
import { EmailBody } from "../components/pdf/EmailBody";
import Upgrade from "../primitives/Upgrade";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
import { useSelector } from "react-redux";
import PdfZoom from "../components/pdf/PdfZoom";
import LottieWithLoader from "../primitives/DotLottieReact";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import Loader from "../primitives/Loader";
import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import HandleError from "../primitives/HandleError";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import LinkUserModal from "../primitives/LinkUserModal";
import QuotaCard from "../primitives/QuotaCard";
import LottieWithLoader from "../primitives/DotLottieReact";
import Alert from "../primitives/Alert";
import Upgrade from "../primitives/Upgrade";
function PlaceHolderSign() {
const { t } = useTranslation();
+15 -5
View File
@@ -4,7 +4,6 @@ import "../styles/signature.css";
import Parse from "parse";
import Confetti from "react-confetti";
import axios from "axios";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
@@ -42,21 +41,23 @@ import {
import { useParams } from "react-router-dom";
import Tour from "reactour";
import Signedby from "../components/pdf/Signedby";
import HandleError from "../primitives/HandleError";
import Header from "../components/pdf/PdfHeader";
import RenderPdf from "../components/pdf/RenderPdf";
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import Title from "../components/Title";
import ModalUi from "../primitives/ModalUi";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import { useSelector } from "react-redux";
import TextFontSetting from "../components/pdf/TextFontSetting";
import VerifyEmail from "../components/pdf/VerifyEmail";
import PdfZoom from "../components/pdf/PdfZoom";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import DownloadPdfZip from "../primitives/DownloadPdfZip";
import Loader from "../primitives/Loader";
import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import HandleError from "../primitives/HandleError";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
const { t } = useTranslation();
@@ -130,6 +131,7 @@ function SignYourSelf() {
const [pdfRotateBase64, setPdfRotatese64] = useState("");
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
const [isDownloadModal, setIsDownloadModal] = useState(false);
const divRef = useRef(null);
const nodeRef = useRef(null);
const [, drop] = useDrop({
@@ -1332,6 +1334,7 @@ function SignYourSelf() {
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
setIsDownloadModal={setIsDownloadModal}
/>
{/* pdf header which contain funish back button */}
<Header
@@ -1351,6 +1354,7 @@ function SignYourSelf() {
clickOnZoomIn={clickOnZoomIn}
clickOnZoomOut={clickOnZoomOut}
widgetsDetails={xyPostion}
setIsDownloadModal={setIsDownloadModal}
/>
<div ref={divRef} data-tut="reactourSecond" className="h-full">
{containerWH?.width && containerWH?.height && (
@@ -1455,6 +1459,12 @@ function SignYourSelf() {
setIsRotate={setIsRotate}
handleRemoveWidgets={handleRemoveWidgets}
/>
<DownloadPdfZip
setIsDownloadModal={setIsDownloadModal}
isDownloadModal={isDownloadModal}
pdfDetails={pdfDetails}
isDocId={true}
/>
<TextFontSetting
isTextSetting={isTextSetting}
setIsTextSetting={setIsTextSetting}
@@ -9,8 +9,6 @@ import { HTML5Backend } from "react-dnd-html5-backend";
import { useDrag, useDrop } from "react-dnd";
import WidgetComponent from "../components/pdf/WidgetComponent";
import Tour from "reactour";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
import SignerListPlace from "../components/pdf/SignerListPlace";
import Header from "../components/pdf/PdfHeader";
import WidgetNameModal from "../components/pdf/WidgetNameModal";
@@ -36,18 +34,21 @@ import {
import RenderPdf from "../components/pdf/RenderPdf";
import "../styles/AddUser.css";
import Title from "../components/Title";
import LinkUserModal from "../primitives/LinkUserModal";
import EditTemplate from "../components/pdf/EditTemplate";
import ModalUi from "../primitives/ModalUi";
import AddRoleModal from "../components/pdf/AddRoleModal";
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import Parse from "parse";
import { useSelector } from "react-redux";
import PdfZoom from "../components/pdf/PdfZoom";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import HandleError from "../primitives/HandleError";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import LinkUserModal from "../primitives/LinkUserModal";
const TemplatePlaceholder = () => {
const { t } = useTranslation();
const navigate = useNavigate();
@@ -0,0 +1,136 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import ModalUi from "./ModalUi";
import {
getSignedUrl,
handleDownloadCertificate,
handleDownloadPdf,
sanitizeFileName
} from "../constant/Utils";
import Loader from "./Loader";
import JSZip from "jszip";
import { saveAs } from "file-saver";
function DownloadPdfZip(props) {
const { t } = useTranslation();
const [selectType, setSelectType] = useState(1);
const [isDownloading, setIsDownloading] = useState(false);
const downloadType = [
{ id: 1, label: t("download-pdf") },
{ id: 2, label: t("pdf-certificate") }
];
const handleDownload = async () => {
if (selectType === 1) {
await handleDownloadPdf(props.pdfDetails, setIsDownloading);
setSelectType(1);
props.setIsDownloadModal(false);
} else if (selectType === 2) {
setIsDownloading("pdf");
const zip = new JSZip();
const pdfDetails = props.pdfDetails;
const pdfName = pdfDetails?.[0]?.Name || "Document";
const pdfUrl = pdfDetails?.[0]?.SignedUrl || "";
try {
// Fetch the first PDF (Signed Document)
const docId =
props.isDocId && !pdfDetails?.[0]?.IsEnableOTP
? pdfDetails?.[0]?.objectId
: "";
const signedUrl = await getSignedUrl(pdfUrl, docId);
const pdf1Response = await fetch(signedUrl);
if (!pdf1Response.ok) {
throw new Error(`Failed to fetch PDF: ${signedUrl}`);
}
const pdf1Blob = await pdf1Response.blob();
const isZip = true;
// Fetch the Certificate (or generate its URL dynamically)
const certificateUrl = await handleDownloadCertificate(
pdfDetails,
setIsDownloading,
isZip
);
const pdf2Response = await fetch(certificateUrl);
if (!pdf2Response.ok) {
throw new Error(`Failed to fetch certificate PDF: ${certificateUrl}`);
}
const pdf2Blob = await pdf2Response.blob();
// Add files to ZIP
zip.file(
`${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`,
pdf1Blob
);
zip.file("Certificate_signed_by_OpenSign™.pdf", pdf2Blob);
// Generate the ZIP and trigger download
const zipBlob = await zip.generateAsync({ type: "blob" });
saveAs(
zipBlob,
`${sanitizeFileName(pdfName)}_signed_by_OpenSign™.zip`
);
setSelectType(1);
props.setIsDownloadModal(false);
setIsDownloading("");
} catch (error) {
console.error("Error creating ZIP file:", error);
}
}
};
return (
<ModalUi
isOpen={props.isDownloadModal}
title={t("download-files")}
handleClose={() => props.setIsDownloadModal(false)}
>
<div className="p-[20px] h-full">
{downloadType.map((data, ind) => {
return (
<label
key={ind}
className="flex items-center gap-1 mb-2 cursor-pointer"
>
<input
className="mr-[8px] op-radio op-radio-xs"
type="radio"
value={data.id}
onChange={() => setSelectType(data.id)}
checked={selectType === data.id}
/>
{data.label}
</label>
);
})}
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() => handleDownload()}
type="submit"
className="op-btn op-btn-primary"
>
{t("download")}
</button>
</div>
{isDownloading === "pdf" && (
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<ModalUi
isOpen={isDownloading === "certificate"}
title={
isDownloading === "certificate"
? t("generating-certificate")
: t("pdf-download")
}
handleClose={() => setIsDownloading("")}
>
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
{isDownloading === "certificate"}{" "}
<p>{t("generate-certificate-alert")}</p>
</div>
</ModalUi>
</ModalUi>
);
}
export default DownloadPdfZip;
@@ -14,6 +14,7 @@ import {
checkIsSubscribed,
copytoData,
fetchUrl,
getSignedUrl,
replaceMailVaribles
} from "../constant/Utils";
import Confetti from "react-confetti";
@@ -30,6 +31,7 @@ import SubscribeCard from "./SubscribeCard";
import { validplan } from "../json/plansArr";
import { serverUrl_fn } from "../constant/appinfo";
import { useTranslation } from "react-i18next";
import DownloadPdfZip from "./DownloadPdfZip";
const ReportTable = (props) => {
const { t } = useTranslation();
@@ -71,6 +73,7 @@ const ReportTable = (props) => {
const [isSubscribe, setIsSubscribe] = useState(true);
const [isModal, setIsModal] = useState({});
const [reason, setReason] = useState("");
const [isDownloadModal, setIsDownloadModal] = useState(false);
const Extand_Class = localStorage.getItem("Extand_Class");
const extClass = Extand_Class && JSON.parse(Extand_Class);
const startIndex = (currentPage - 1) * props.docPerPage;
@@ -649,10 +652,15 @@ const ReportTable = (props) => {
setActLoader({ [`${item.objectId}`]: true });
const url = item?.SignedUrl || item?.URL || "";
const pdfName = item?.Name || "exported_file";
const isCompleted = item?.IsCompleted || false;
if (url) {
try {
const signedUrl = await Parse.Cloud.run("getsignedurl", { url: url });
await fetchUrl(signedUrl, pdfName);
if (isCompleted) {
setIsDownloadModal({ [item.objectId]: true });
} else {
const signedUrl = await getSignedUrl(url);
await fetchUrl(signedUrl, pdfName);
}
setActLoader({});
} catch (err) {
console.log("err in getsignedurl", err);
@@ -2107,6 +2115,14 @@ const ReportTable = (props) => {
</div>
</ModalUi>
)}
{isDownloadModal[item.objectId] && (
<DownloadPdfZip
setIsDownloadModal={setIsDownloadModal}
isDownloadModal={isDownloadModal[item.objectId]}
pdfDetails={[item]}
isDocId={false}
/>
)}
</td>
</tr>
)
@@ -41,7 +41,7 @@
"upgrade-now": "Upgrade now",
"upgrade-to": "Upgrade to",
"plan": "Plan",
"subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
"subscribe-card-teamplan": "Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
"user-name-limit-char": "To have a username less than 8 character please subscribe",
"tour-content": "Don't show this again",
@@ -595,7 +595,7 @@
"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.",
"public-template": "This video demonstrates how to set up your personalized public profile, such as https://opensign.me/your-username. Youll also learn how to customize your tagline and make your templates available for public signing."
},
},
"enter-email-plaholder": "Add an email address and hit enter",
"success-email-alert": "Email sent successfully!",
"expired-doc-title": "Expired Document",
@@ -616,31 +616,31 @@
"select-date-format": "Select a date format",
"quantity-of-credits": "Quantity of premium credits",
"remaining-credits": "Premium credits available:",
"remaining-credits-help":"Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
"remaining-credits-help": "Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
"additional-credits": "Please purchase premium credits",
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
"buy-credits": "Buy Premium Credits",
"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",
"bulk-send-subcription-alert":"Please upgrade to Professional or Team plan to use bulk send.",
"generate-test-token":"Generate Test Token",
"regenerate-test-token":"Regenerate Test Token",
"help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once youve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
"reason":"Reason",
"decline-by":"Declined/revoked by",
"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",
"bulk-send-subcription-alert": "Please upgrade to Professional or Team plan to use bulk send.",
"generate-test-token": "Generate Test Token",
"regenerate-test-token": "Regenerate Test Token",
"help-test-token": "This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once youve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
"help-api-token": "This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
"reason": "Reason",
"decline-by": "Declined/revoked by",
"document-declined": "Document declined",
"quota-mail-info-head":"Monthly request signatures email limit",
"quota-mail-info-head": "Monthly request signatures email limit",
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
"quota-mail-head":"Quota Reached",
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
"sent-this-month":"Sent this month",
"available-seats":"Available seats",
"buy-users":"Buy more users",
"quota-mail-tip": "Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
"quota-mail-head": "Quota Reached",
"unauthorized-modal": "You don't have permission to perform this action, please contact {{adminEmail}}.",
"sent-this-month": "Sent this month",
"available-seats": "Available seats",
"buy-users": "Buy more users",
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
@@ -648,8 +648,10 @@
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
"p4": "Please choose the option that best suits your document signing requirements."
},
"advanced-options":"Advanced options",
"hide-advanced-options":"Hide Advanced options",
"document-logs":"Document logs"
"advanced-options": "Advanced options",
"hide-advanced-options": "Hide Advanced options",
"download-files": "Download files",
"download-pdf": "Download Pdf",
"pdf-certificate": "Download Pdf + Certificate",
"document-logs": "Document logs"
}
@@ -42,7 +42,7 @@
"upgrade-to": "Mettre à niveau vers",
"pro": "PRO",
"plan": "Offre",
"subscribe-card-teamplan":"Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
"subscribe-card-teamplan": "Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
"tour-content": "Ne plus afficher",
@@ -613,33 +613,33 @@
"Add-seats": "Ajouter des sièges",
"format": "format",
"select-date-format": "Sélectionnez un format de date",
"quantity-of-credits":"Quantité de crédits de prime",
"remaining-credits":"Crédits premium disponibles :",
"additional-credits":"Veuillez acheter des crédits premium",
"remaining-credits-help":"Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
"quantity-of-credits": "Quantité de crédits de prime",
"remaining-credits": "Crédits premium disponibles :",
"additional-credits": "Veuillez acheter des crédits premium",
"remaining-credits-help": "Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
"buy-credits": "Acheter des crédits premium",
"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",
"bulk-send-subcription-alert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
"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",
"bulk-send-subcription-alert": "Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
"generate-test-token": "Générer jeton de test",
"regenerate-test-token":"Régénérer le jeton de test",
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à lun de nos forfaits payants pour générer un jeton de production.",
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
"reason" :"Raison",
"decline-by" :"Refusé/révoqué par",
"document-declined":"document refusé",
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
"regenerate-test-token": "Régénérer le jeton de test",
"help-test-token": "Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à lun de nos forfaits payants pour générer un jeton de production.",
"help-api-token": "Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
"reason": "Raison",
"decline-by": "Refusé/révoqué par",
"document-declined": "document refusé",
"quota-mail-info-head": "Limite mensuelle d'e-mails de signatures de demandes",
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
"quota-mail-head":"Quota atteint",
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
"sent-this-month":"envoyé ce mois-ci",
"available-seats":"Disponible sièges",
"buy-users":"Acheter plus d'utilisateurs",
"quota-mail-tip-tip": "Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
"quota-mail-head": "Quota atteint",
"unauthorized-modal": "Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
"sent-this-month": "envoyé ce mois-ci",
"available-seats": "Disponible sièges",
"buy-users": "Acheter plus d'utilisateurs",
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
@@ -647,8 +647,10 @@
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
},
"advanced-options":"Options avancées",
"advanced-options": "Options avancées",
"hide-advanced-options": "Masquer les options avancées",
"document-logs":"Journaux de documents"
"download-files": "Télécharger des fichiers",
"download-pdf": "Télécharger le PDF",
"pdf-certificate": "Télécharger Pdf + Certificat",
"document-logs": "Journaux de documents"
}
@@ -139,6 +139,7 @@ export default function reportJson(id, userId) {
'TimeToCompleteDays',
'Placeholders',
'IsSignyourself',
'IsCompleted',
],
};
// declined documents report