Skip to content

Commit ff9a495

Browse files
authored
Merge pull request #656 from OpenSignLabs/staging
v1.5.8
2 parents b29c7d5 + c564b57 commit ff9a495

34 files changed

+2302
-1041
lines changed

apps/OpenSign/package-lock.json

Lines changed: 79 additions & 119 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/OpenSign/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@formkit/auto-animate": "^0.8.1",
6+
"@formkit/auto-animate": "^0.8.2",
77
"@radix-ui/themes": "^2.0.3",
8-
"@react-pdf/renderer": "^3.4.0",
8+
"@react-pdf/renderer": "^3.4.4",
99
"@reduxjs/toolkit": "^2.2.1",
1010
"axios": "^1.6.8",
1111
"file-saver": "^2.0.5",
@@ -31,15 +31,15 @@
3131
"react-pdf": "^7.7.1",
3232
"react-quill": "^2.0.0",
3333
"react-redux": "^9.1.0",
34-
"react-rnd": "^10.4.1",
34+
"react-rnd": "^10.4.10",
3535
"react-router-dom": "^6.22.3",
3636
"react-scripts": "5.0.1",
3737
"react-scrollbars-custom": "^4.1.1",
3838
"react-select": "^5.8.0",
3939
"react-signature-canvas": "^1.0.6",
4040
"react-tooltip": "^5.26.3",
4141
"react-web-share": "^2.0.2",
42-
"reactour": "^1.19.2",
42+
"reactour": "^1.19.3",
4343
"redux": "^5.0.1",
4444
"redux-thunk": "^3.1.0",
4545
"regex-parser": "^2.3.0",
@@ -83,14 +83,14 @@
8383
}
8484
},
8585
"devDependencies": {
86-
"@babel/runtime-corejs2": "^7.24.1",
87-
"autoprefixer": "^10.4.18",
86+
"@babel/runtime-corejs2": "^7.24.5",
87+
"autoprefixer": "^10.4.19",
8888
"commitizen": "^4.3.0",
8989
"eslint": "^8.57.0",
9090
"eslint-plugin-prettier": "^4.2.1",
9191
"eslint-plugin-react": "^7.34.1",
9292
"lint-staged": "^15.2.2",
93-
"postcss": "^8.4.37",
93+
"postcss": "^8.4.38",
9494
"prettier": "^2.8.8",
9595
"pretty-quick": "^3.3.1",
9696
"tailwindcss": "^3.4.1"

apps/OpenSign/src/App.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ function App() {
109109
path="/login/:id/:userMail/:contactBookId/:serverUrl"
110110
element={<LazyPage Page={GuestLogin} />}
111111
/>
112+
<Route
113+
path="/login/:base64url"
114+
element={<LazyPage Page={GuestLogin} />}
115+
/>
112116
<Route path="/debugpdf" element={<LazyPage Page={DebugPdf} />} />
113117
<Route
114118
path="/forgetpassword"

apps/OpenSign/src/components/pdf/EmailBody.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function EmailBody(props) {
2020
required
2121
value={props.requestSubject}
2222
onChange={(e) => props.setRequestSubject(e.target.value)}
23-
placeholder="${senderName} has requested you to sign ${documentName}"
23+
placeholder='${senderName} has requested you to sign "${documentName}"'
2424
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
2525
/>
2626
<label className="text-sm ml-2 mt-3">

apps/OpenSign/src/components/pdf/PdfHeader.js

Lines changed: 119 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { useState } from "react";
22
import PrevNext from "./PrevNext";
33
import printModule from "print-js";
44
import { getBase64FromUrl } from "../../constant/Utils";
@@ -7,8 +7,9 @@ import "../../styles/signature.css";
77
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
88
import { useNavigate } from "react-router-dom";
99
import { themeColor } from "../../constant/const";
10-
import Certificate from "./Certificate";
11-
import { PDFDownloadLink } from "@react-pdf/renderer";
10+
import axios from "axios";
11+
import ModalUi from "../../primitives/ModalUi";
12+
import Parse from "parse";
1213

1314
function Header({
1415
isPdfRequestFiles,
@@ -39,6 +40,7 @@ function Header({
3940
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
4041
const isMobile = window.innerWidth < 767;
4142
const navigate = useNavigate();
43+
const [isCertificate, setIsCertificate] = useState(false);
4244
const isGuestSigner = localStorage.getItem("isGuestSigner");
4345
//for go to previous page
4446
function previousPage() {
@@ -61,30 +63,43 @@ function Header({
6163
const handleToPrint = async (event) => {
6264
event.preventDefault();
6365

64-
const pdf = await getBase64FromUrl(pdfUrl);
65-
const isAndroidDevice = navigator.userAgent.match(/Android/i);
66-
const isAppleDevice =
67-
(/iPad|iPhone|iPod/.test(navigator.platform) ||
68-
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
69-
!window.MSStream;
70-
if (isAndroidDevice || isAppleDevice) {
71-
const byteArray = Uint8Array.from(
72-
atob(pdf)
73-
.split("")
74-
.map((char) => char.charCodeAt(0))
75-
);
76-
const blob = new Blob([byteArray], { type: "application/pdf" });
77-
const blobUrl = URL.createObjectURL(blob);
78-
window.open(blobUrl, "_blank");
79-
} else {
80-
printModule({ printable: pdf, type: "pdf", base64: true });
66+
try {
67+
const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
68+
const pdf = await getBase64FromUrl(url);
69+
const isAndroidDevice = navigator.userAgent.match(/Android/i);
70+
const isAppleDevice =
71+
(/iPad|iPhone|iPod/.test(navigator.platform) ||
72+
(navigator.platform === "MacIntel" &&
73+
navigator.maxTouchPoints > 1)) &&
74+
!window.MSStream;
75+
if (isAndroidDevice || isAppleDevice) {
76+
const byteArray = Uint8Array.from(
77+
atob(pdf)
78+
.split("")
79+
.map((char) => char.charCodeAt(0))
80+
);
81+
const blob = new Blob([byteArray], { type: "application/pdf" });
82+
const blobUrl = URL.createObjectURL(blob);
83+
window.open(blobUrl, "_blank");
84+
} else {
85+
printModule({ printable: pdf, type: "pdf", base64: true });
86+
}
87+
} catch (err) {
88+
console.log("err in getsignedurl", err);
89+
alert("something went wrong, please try again later.");
8190
}
8291
};
8392

8493
//handle download signed pdf
85-
const handleDownloadPdf = () => {
94+
const handleDownloadPdf = async () => {
8695
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
87-
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
96+
try {
97+
const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
98+
saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
99+
} catch (err) {
100+
console.log("err in getsignedurl", err);
101+
alert("something went wrong, please try again later.");
102+
}
88103
};
89104

90105
const sanitizeFileName = (pdfName) => {
@@ -102,55 +117,41 @@ function Header({
102117
} catch (err) {
103118
console.log("err in download in certificate", err);
104119
}
120+
} else {
121+
setIsCertificate(true);
122+
try {
123+
const data = {
124+
docId: pdfDetails[0]?.objectId
125+
};
126+
const docDetails = await axios.post(
127+
`${localStorage.getItem("baseUrl")}functions/getDocument`,
128+
data,
129+
{
130+
headers: {
131+
"Content-Type": "application/json",
132+
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
133+
sessionToken: localStorage.getItem("accesstoken")
134+
}
135+
}
136+
);
137+
if (docDetails.data && docDetails.data.result) {
138+
const doc = docDetails.data.result;
139+
if (doc?.CertificateUrl) {
140+
await fetch(doc?.CertificateUrl);
141+
const certificateUrl = doc?.CertificateUrl;
142+
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
143+
setIsCertificate(false);
144+
} else {
145+
setIsCertificate(true);
146+
}
147+
}
148+
} catch (err) {
149+
console.log("err in download in certificate", err);
150+
alert("something went wrong, please try again later.");
151+
}
105152
}
106153
};
107154

108-
const GenerateCertificate = () => {
109-
//after generate download certifcate pdf
110-
const handleDownload = (pdfBlob, fileName) => {
111-
if (pdfBlob) {
112-
const url = window.URL.createObjectURL(pdfBlob);
113-
// Create a temporary anchor element
114-
const link = document.createElement("a");
115-
link.href = url;
116-
link.download = fileName;
117-
// Append the anchor to the body
118-
document.body.appendChild(link);
119-
// Programmatically click the anchor to trigger the download
120-
link.click();
121-
// Remove the anchor from the body
122-
document.body.removeChild(link);
123-
// Release the object URL to free up resources
124-
window.URL.revokeObjectURL(url);
125-
}
126-
};
127-
128-
return (
129-
<PDFDownloadLink
130-
onClick={(e) => e.preventDefault()}
131-
style={{ textDecoration: "none", zIndex: "35" }}
132-
document={<Certificate pdfData={pdfDetails} />}
133-
>
134-
{({ blob, loading }) => (
135-
<button
136-
onClick={() =>
137-
handleDownload(
138-
blob,
139-
`completion certificate-${
140-
pdfDetails[0] && pdfDetails[0].Name
141-
}.pdf`
142-
)
143-
}
144-
disabled={loading}
145-
className=" md:bg-[#08bc66] border-none focus:outline-none flex flex-row items-center md:shadow md:rounded-[3px] py-[3px] md:px-[11px] md:text-white text-black md:font-[500] text-[13px] mr-[5px]"
146-
>
147-
<i className="fa-solid fa-award py-[3px]" aria-hidden="true"></i>
148-
<span className="md:hidden lg:block ml-1">Certificate</span>
149-
</button>
150-
)}
151-
</PDFDownloadLink>
152-
);
153-
};
154155
return (
155156
<div style={{ padding: "5px 0px 5px 0px" }} className="mobileHead">
156157
{isMobile && isShowHeader ? (
@@ -240,32 +241,24 @@ function Header({
240241
</div>
241242
</DropdownMenu.Item>
242243
{isCompleted && (
243-
<>
244-
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
245-
<DropdownMenu.Item
246-
className="DropdownMenuItem"
247-
onClick={() => handleDownloadCertificate()}
248-
>
249-
<div
250-
style={{
251-
border: "none",
252-
backgroundColor: "#fff"
253-
}}
254-
>
255-
<i
256-
className="fa-solid fa-award"
257-
style={{ marginRight: "2px" }}
258-
aria-hidden="true"
259-
></i>
260-
Certificate
261-
</div>
262-
</DropdownMenu.Item>
263-
) : (
264-
<DropdownMenu.Item className="DropdownMenuItem">
265-
<GenerateCertificate />
266-
</DropdownMenu.Item>
267-
)}
268-
</>
244+
<DropdownMenu.Item
245+
className="DropdownMenuItem"
246+
onClick={() => handleDownloadCertificate()}
247+
>
248+
<div
249+
style={{
250+
border: "none",
251+
backgroundColor: "#fff"
252+
}}
253+
>
254+
<i
255+
className="fa-solid fa-award"
256+
style={{ marginRight: "2px" }}
257+
aria-hidden="true"
258+
></i>
259+
Certificate
260+
</div>
261+
</DropdownMenu.Item>
269262
)}
270263
{isSignYourself && (
271264
<DropdownMenu.Item
@@ -442,25 +435,17 @@ function Header({
442435
alreadySign ? (
443436
<div style={{ display: "flex", flexDirection: "row" }}>
444437
{isCompleted && (
445-
<>
446-
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
447-
<button
448-
type="button"
449-
onClick={() => handleDownloadCertificate()}
450-
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
451-
>
452-
<i
453-
className="fa-solid fa-award py-[3px]"
454-
aria-hidden="true"
455-
></i>
456-
<span className="hidden lg:block ml-1">
457-
Certificate
458-
</span>
459-
</button>
460-
) : (
461-
<GenerateCertificate />
462-
)}
463-
</>
438+
<button
439+
type="button"
440+
onClick={() => handleDownloadCertificate()}
441+
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
442+
>
443+
<i
444+
className="fa-solid fa-award py-[3px]"
445+
aria-hidden="true"
446+
></i>
447+
<span className="hidden lg:block ml-1">Certificate</span>
448+
</button>
464449
)}
465450

466451
<button
@@ -520,23 +505,17 @@ function Header({
520505
) : isCompleted ? (
521506
<div style={{ display: "flex", flexDirection: "row" }}>
522507
{isCompleted && (
523-
<>
524-
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
525-
<button
526-
type="button"
527-
onClick={() => handleDownloadCertificate()}
528-
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
529-
>
530-
<i
531-
className="fa-solid fa-award py-[3px]"
532-
aria-hidden="true"
533-
></i>
534-
<span className="hidden lg:block ml-1">Certificate</span>
535-
</button>
536-
) : (
537-
<GenerateCertificate />
538-
)}
539-
</>
508+
<button
509+
type="button"
510+
onClick={() => handleDownloadCertificate()}
511+
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
512+
>
513+
<i
514+
className="fa-solid fa-award py-[3px]"
515+
aria-hidden="true"
516+
></i>
517+
<span className="hidden lg:block ml-1">Certificate</span>
518+
</button>
540519
)}
541520
<button
542521
onClick={handleToPrint}
@@ -592,6 +571,16 @@ function Header({
592571
)}
593572
</div>
594573
)}
574+
<ModalUi
575+
isOpen={isCertificate}
576+
title={"Generating certificate"}
577+
handleClose={() => setIsCertificate(false)}
578+
>
579+
<div className="p-3 md:p-5 text-[13px] md:text-base text-center">
580+
<p>Completion certificate is generating,</p>
581+
<p>please wait for some time if not download try again later</p>
582+
</div>
583+
</ModalUi>
595584
</div>
596585
);
597586
}

0 commit comments

Comments
 (0)