Merge pull request #869 from OpenSignLabs/raktima-opensignlabs-patch-10

This commit is contained in:
Amol
2024-06-21 17:12:35 +05:30
committed by GitHub
69 changed files with 31692 additions and 2369 deletions
File diff suppressed because it is too large Load Diff
+3 -36
View File
@@ -1,53 +1,20 @@
<!DOCTYPE html>
<html lang="en" data-theme="opensigncss">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<!-- <link rel="icon" type="image/png"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALlJREFUaEPtmN0NwjAMBpNxYDKYiM1Yp90g93CKStH1NbIdfz921Dker2Pc+Js1cDF7MXAxASMGYkAigBI6vh9ZwoXP53uZoAYcvhwdA3mAVbI2aSb+9zFKU4IURB6j/HoPUIEa2G3iGIAhQQDlAUIoE2diabIklISS0NoFPebo77RF6OenEF3QntOm128he0GKrwHyACFoz2MgBqSGkpAEcHs47oHtN5AFakACqMNjQEMoE8SABFCHn4HE2zGHSLeEAAAAAElFTkSuQmCC"
sizes="40x40" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="The fastest way to sign PDFs & request signatures from others" />
<!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> -->
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="manifest" href="/manifest.json" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<link rel="stylesheet" href="/css/fonts.css" />
<title>OpenSign™</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><!-- Font Awesome Pro 6.0.0-alpha2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M374.629 150.627L233.371 9.373C227.371 3.371 219.23 0 210.746 0H64C28.652 0 0 28.652 0 64V448C0 483.345 28.652 512 64 512H320C355.348 512 384 483.345 384 448V173.254C384 164.767 380.629 156.629 374.629 150.627ZM224 22.629L361.375 160H248C234.781 160 224 149.234 224 136V22.629ZM368 448C368 474.467 346.469 496 320 496H64C37.531 496 16 474.467 16 448V64C16 37.533 37.531 16 64 16H208V136C208 158.062 225.938 176 248 176H368V448ZM96 264C96 268.406 99.594 272 104 272H280C284.406 272 288 268.406 288 264S284.406 256 280 256H104C99.594 256 96 259.594 96 264ZM280 320H104C99.594 320 96 323.594 96 328S99.594 336 104 336H280C284.406 336 288 332.406 288 328S284.406 320 280 320ZM280 384H104C99.594 384 96 387.594 96 392S99.594 400 104 400H280C284.406 400 288 396.406 288 392S284.406 384 280 384Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z"/></svg>

After

Width:  |  Height:  |  Size: 406 B

+3 -3
View File
@@ -205,7 +205,7 @@ const BulkSendUi = (props) => {
onClick={() => handleRemoveForm(index)}
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
>
<i className="fa-solid fa-trash"></i>
<i className="fa-light fa-trash"></i>
</button>
)}
<div ref={formRef}></div>
@@ -217,13 +217,13 @@ const BulkSendUi = (props) => {
onClick={handleAddForm}
className="op-btn op-btn-primary focus:outline-none"
>
<i className="fa-solid fa-plus"></i> <span>Add new</span>
<i className="fa-light fa-plus"></i> <span>Add new</span>
</button>
<button
type="submit"
className="op-btn op-btn-secondary focus:outline-none"
>
<i className="fa-solid fa-paper-plane"></i>{" "}
<i className="fa-light fa-paper-plane"></i>{" "}
<span>Send</span>
</button>
</div>
+2 -2
View File
@@ -58,10 +58,10 @@ const Footer = () => {
<button
className={`${
showButton ? "block" : "hidden"
} fixed bottom-4 right-4 px-3 p-2 text-xl bg-blue-500 text-white rounded focus:outline-none`}
} fixed bottom-4 right-4 px-3 p-2 text-xl op-bg-secondary text-white rounded focus:outline-none`}
onClick={scrollToTop}
>
<i className="fa-solid fa-angle-up"></i>
<i className="fa-light fa-angle-up"></i>
</button>
</>
);
@@ -70,9 +70,9 @@ const FullScreenButton = () => {
className="text-base-content p-2 text-sm focus:outline-none"
>
{isFullScreen ? (
<i className="fa-solid fa-compress"></i>
<i className="fa-light fa-compress"></i>
) : (
<i className="fa fa-maximize"></i>
<i className="fa-light fa-maximize"></i>
)}
</button>
</div>
+13 -9
View File
@@ -96,10 +96,10 @@ const Header = ({ showSidebar }) => {
<div className="op-navbar bg-base-100 shadow">
<div className="flex-none">
<button
className="op-btn op-btn-square op-btn-ghost focus:outline-none"
className="op-btn op-btn-square op-btn-ghost focus:outline-none hover:bg-transparent op-btn-sm no-animation"
onClick={showSidebar}
>
<i className="fa-solid fa-bars text-xl text-base-content"></i>
<i className="fa-light fa-bars text-xl text-base-content"></i>
</button>
</div>
<div className="flex-1 ml-2">
@@ -151,12 +151,16 @@ const Header = ({ showSidebar }) => {
</div>
)}
<div className="op-dropdown op-dropdown-end" id="profile-menu">
<div tabIndex={0} role="button" className="op-btn op-btn-ghost">
<div
tabIndex={0}
role="button"
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
>
<i
tabIndex={0}
role="button"
onClick={toggleDropdown}
className="fa-solid fa-angle-down text-base-content"
className="fa-light fa-angle-down text-base-content"
></i>
</div>
<ul
@@ -165,7 +169,7 @@ const Header = ({ showSidebar }) => {
>
<li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
<span>
<i className="fa-solid fa-book"></i> Docs
<i className="fa-light fa-book"></i> Docs
</span>
</li>
<li
@@ -175,7 +179,7 @@ const Header = ({ showSidebar }) => {
}}
>
<span>
<i className="fa-regular fa-user"></i> Profile
<i className="fa-light fa-user"></i> Profile
</span>
</li>
<li
@@ -185,7 +189,7 @@ const Header = ({ showSidebar }) => {
}}
>
<span>
<i className="fa-solid fa-lock"></i> Change Password
<i className="fa-light fa-lock"></i> Change Password
</span>
</li>
<li
@@ -194,12 +198,12 @@ const Header = ({ showSidebar }) => {
}}
>
<span>
<i className="fa-regular fa-id-card"></i> Console
<i className="fa-light fa-id-card"></i> Console
</span>
</li>
<li onClick={closeDropdown}>
<span>
<i className="fa-solid fa-arrow-right-from-bracket"></i> Log Out
<i className="fa-light fa-arrow-right-from-bracket"></i> Log Out
</span>
</li>
</ul>
+24 -10
View File
@@ -1,6 +1,6 @@
import React from "react";
import { Document, Page } from "react-pdf";
import { Stage, Layer, Rect } from "react-konva";
import { Stage, Layer, Rect, Text } from "react-konva";
const RenderDebugPdf = (props) => {
return (
<div>
@@ -47,16 +47,30 @@ const RenderDebugPdf = (props) => {
{props.annotations
.filter((value) => value.page === props.pageNumber)
.map((value) => {
const textX = value.x + value.width / 3;
const textY = value.y + value.height / 2.5;
return (
<Rect
key={value.key}
x={value.x}
y={value.y}
width={value.width}
height={value.height}
fill="transparent"
stroke="black"
/>
<React.Fragment key={value.key}>
<Rect
x={value.x}
y={value.y}
width={value.width}
height={value.height}
fill="#cbe9ed"
stroke="black"
/>
<Text
x={textX}
y={textY}
text={
value?.key > 0 ? "box " + value.key.toString() : "box"
}
fontSize={16}
fill="black"
align="center"
verticalAlign="middle"
/>
</React.Fragment>
);
})}
</Layer>
@@ -31,13 +31,11 @@ const DashboardButton = (props) => {
<span className="rounded-full bg-base-content bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i
className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info"
props.Icon ? props.Icon : "fa-light fa-info"
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className="op-card-title text-lg ml-3 text-base-content">
{props.Label}
</div>
<div className=" text-lg ml-3 text-base-content">{props.Label}</div>
</div>
</div>
);
@@ -341,7 +341,7 @@ const DashboardCard = (props) => {
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i
className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info"
props.Icon ? props.Icon : "fa-light fa-info"
} text-[25px] lg:text-[30px]`}
></i>
</span>
@@ -7,13 +7,13 @@ const buttonList = [
label: "Sign yourself",
redirectId: "sHAnZphf69",
redirectType: "Form",
icon: "fas fa-pen-nib"
icon: "fa-light fa-pen-nib"
},
{
label: "Request signature",
redirectId: "8mZzFxbG1z",
redirectType: "Form",
icon: "fa-solid fa-paper-plane"
icon: "fa-light fa-paper-plane"
}
];
const GetDashboard = (props) => {
@@ -17,10 +17,10 @@ function DriveBody(props) {
const [selectDoc, setSelectDoc] = useState();
const [isDeleteDoc, setIsDeleteDoc] = useState(false);
const contextMenu = [
{ type: "Download", icon: "fa-solid fa-arrow-down" },
{ type: "Rename", icon: "fa-solid fa-font" },
{ type: "Move", icon: "fa-solid fa-file-export" },
{ type: "Delete", icon: "fa-solid fa-trash" }
{ type: "Download", icon: "fa-light fa-arrow-down" },
{ type: "Rename", icon: "fa-light fa-font" },
{ type: "Move", icon: "fa-light fa-file-export" },
{ type: "Delete", icon: "fa-light fa-trash" }
];
const navigate = useNavigate();
@@ -320,10 +320,13 @@ function DriveBody(props) {
data.Type === "Folder" ? (
<tr onClick={() => handleOnclikFolder(data)}>
<td className="cursor-pointer flex items-center">
<i
className="fa fa-folder mr-[8px] text-[26px] op-text-secondary"
aria-hidden="true"
></i>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="w-[26px] h-[26px] fill-current op-text-secondary"
>
<path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z" />
</svg>
<span className="text-[12px] font-medium">{data.Name}</span>
</td>
<td>_</td>
@@ -334,7 +337,13 @@ function DriveBody(props) {
) : (
<tr onClick={() => checkPdfStatus(data)}>
<td className="cursor-pointer flex items-center">
<i className="fa-solid fa-file-lines mr-[8px] text-[26px] op-text-primary"></i>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512"
className="w-[26px] h-[26px] fill-current op-text-primary"
>
<path d="M374.629 150.627L233.371 9.373C227.371 3.371 219.23 0 210.746 0H64C28.652 0 0 28.652 0 64V448C0 483.345 28.652 512 64 512H320C355.348 512 384 483.345 384 448V173.254C384 164.767 380.629 156.629 374.629 150.627ZM224 22.629L361.375 160H248C234.781 160 224 149.234 224 136V22.629ZM368 448C368 474.467 346.469 496 320 496H64C37.531 496 16 474.467 16 448V64C16 37.533 37.531 16 64 16H208V136C208 158.062 225.938 176 248 176H368V448ZM96 264C96 268.406 99.594 272 104 272H280C284.406 272 288 268.406 288 264S284.406 256 280 256H104C99.594 256 96 259.594 96 264ZM280 320H104C99.594 320 96 323.594 96 328S99.594 336 104 336H280C284.406 336 288 332.406 288 328S284.406 320 280 320ZM280 384H104C99.594 384 96 387.594 96 392S99.594 400 104 400H280C284.406 400 288 396.406 288 392S284.406 384 280 384Z" />
</svg>
<span className="text-[12px] font-medium">{data.Name}</span>
</td>
<td>{createddate}</td>
@@ -346,7 +355,7 @@ function DriveBody(props) {
e.stopPropagation();
handleMenuItemClick("Download", data);
}}
className="fa fa-download mr-[8px] op-text-primary"
className="fa-light fa-download mr-[8px] op-text-primary"
aria-hidden="true"
></i>
</td>
@@ -356,17 +365,19 @@ function DriveBody(props) {
<div key={ind} className="relative w-[100px] h-[100px] mx-2 my-3">
<ContextMenu.Root>
<ContextMenu.Trigger className="flex flex-col justify-center items-center">
<div data-tut={props.dataTutSeventh}>
{/* <img
alt="folder"
onClick={() => handleOnclikFolder(data)}
src={folder}
className="w-full h-full"
/> */}
<i
className="fa-solid fa-folder text-[100px] mx-auto op-text-secondary"
onClick={() => handleOnclikFolder(data)}
></i>
{/* folder */}
<div
data-tut={props.dataTutSeventh}
onClick={() => handleOnclikFolder(data)}
className="cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="w-[100px] h-[100px] fill-current op-text-secondary"
>
<path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z" />
</svg>
{rename === data.objectId ? (
<input
onFocus={() => {
@@ -402,7 +413,7 @@ function DriveBody(props) {
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
<i className="fa-solid fa-font mr-[8px]"></i>
<i className="fa-light fa-font mr-[8px]"></i>
<span>Rename</span>
</ContextMenu.Item>
</ContextMenu.Content>
@@ -416,61 +427,63 @@ function DriveBody(props) {
<ContextMenu.Root>
<div className="relative w-[100px] h-[100px] mx-2 my-3">
<ContextMenu.Trigger className="flex flex-col justify-center items-center">
{/* <img
alt="PDF"
className="w-full h-full"
src={pdfLogo}
onClick={() => checkPdfStatus(data)}
/> */}
<i
className="fa-solid fa-file-lines text-[100px] text-neutral"
onClick={() => checkPdfStatus(data)}
{/* pdf */}
<div
data-tut={props.dataTutSixth}
></i>
{rename === data.objectId ? (
<input
autoFocus={true}
type="text"
onFocus={() => {
inputRef.current.setSelectionRange(0, 0);
const input = inputRef.current;
if (input) {
input.select();
}
}}
onBlur={() => handledRenameDoc(data)}
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
defaultValue={renameValue}
// value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
/>
) : (
<span className="fileName">{data.Name}</span>
)}
onClick={() => checkPdfStatus(data)}
className="cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512"
className="w-[100px] h-[100px] fill-current op-text-primary"
>
<path d="M374.629 150.627L233.371 9.373C227.371 3.371 219.23 0 210.746 0H64C28.652 0 0 28.652 0 64V448C0 483.345 28.652 512 64 512H320C355.348 512 384 483.345 384 448V173.254C384 164.767 380.629 156.629 374.629 150.627ZM224 22.629L361.375 160H248C234.781 160 224 149.234 224 136V22.629ZM368 448C368 474.467 346.469 496 320 496H64C37.531 496 16 474.467 16 448V64C16 37.533 37.531 16 64 16H208V136C208 158.062 225.938 176 248 176H368V448ZM96 264C96 268.406 99.594 272 104 272H280C284.406 272 288 268.406 288 264S284.406 256 280 256H104C99.594 256 96 259.594 96 264ZM280 320H104C99.594 320 96 323.594 96 328S99.594 336 104 336H280C284.406 336 288 332.406 288 328S284.406 320 280 320ZM280 384H104C99.594 384 96 387.594 96 392S99.594 400 104 400H280C284.406 400 288 396.406 288 392S284.406 384 280 384Z" />
</svg>
{rename === data.objectId ? (
<input
autoFocus={true}
type="text"
onFocus={() => {
inputRef.current.setSelectionRange(0, 0);
const input = inputRef.current;
if (input) {
input.select();
}
}}
onBlur={() => handledRenameDoc(data)}
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
defaultValue={renameValue}
// value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
/>
) : (
<span className="fileName">{data.Name}</span>
)}
</div>
</ContextMenu.Trigger>
{status === "Completed" ? (
<div className="status-badge completed">
<i className="fas fa-check-circle"></i>
<i className="fa-light fa-check-circle"></i>
</div>
) : status === "Declined" ? (
<div className="status-badge declined">
<i className="fa fa-thumbs-down"></i>
<i className="fa-light fa-thumbs-down"></i>
</div>
) : status === "Expired" ? (
<div className="status-badge expired">
<i className="fa fa-hourglass-end"></i>
<i className="fa-light fa-hourglass-end"></i>
</div>
) : status === "Draft" ? (
<div className="status-badge draft">
<i className="fa fa-file"></i>
<i className="fa-light fa-file"></i>
</div>
) : (
status === "In Progress" && (
<div className="status-badge in-progress">
<i className="fa fa-paper-plane"></i>
<i className="fa-light fa-paper-plane"></i>
</div>
)
)}
@@ -205,14 +205,14 @@ function DropdownWidgetOption(props) {
/>
<i
className="fa-solid fa-rectangle-xmark text-[25px] ml-[10px] text-error"
className="fa-light fa-rectangle-xmark text-[25px] ml-[10px] text-accent cursor-pointer"
onClick={() => handleDeleteInput(index)}
></i>
</div>
))}
<i
onClick={handleAddInput}
className="fa-solid fa-square-plus text-[25px] ml-[10px] text-primary"
className="fa-light fa-square-plus text-[25px] ml-[10px] op-text-primary cursor-pointer"
></i>
<div>
{props.type === "checkbox" && !props.isSignYourself && (
@@ -191,7 +191,7 @@ function EmailComponent({
onClick={handleToPrint}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa fa-print" aria-hidden="true"></i>
<i className="fa-light fa-print" aria-hidden="true"></i>
Print
</button>
)}
@@ -199,7 +199,7 @@ function EmailComponent({
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
>
<i className="fa fa-download" aria-hidden="true"></i>
<i className="fa-light fa-download" aria-hidden="true"></i>
Download
</button>
</div>
@@ -230,7 +230,7 @@ function EmailComponent({
className="text-base-100 text-[13px] font-semibold ml-[7px] cursor-pointer"
onClick={() => removeChip(ind)}
>
<i className="fa-solid fa-xmark"></i>
<i className="fa-light fa-xmark"></i>
</span>
</div>
);
@@ -281,7 +281,7 @@ function EmailComponent({
}
}}
>
<i className="fa fa-plus" aria-hidden="true"></i>
<i className="fa-light fa-plus" aria-hidden="true"></i>
</button>
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
+33 -23
View File
@@ -67,7 +67,7 @@ function Header({
<div className="flex justify-between items-center py-[5px] px-[10px] ">
<div onClick={() => navigate(-1)}>
<i
className="fa fa-arrow-left text-base-content"
className="fa-light fa-arrow-left text-base-content"
aria-hidden="true"
></i>
</div>
@@ -80,7 +80,10 @@ function Header({
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<div className="op-link op-link-primary no-underline text-[16px] font-semibold pr-[3px] pl-[5px]">
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
<i
className="fa-light fa-ellipsis-v"
aria-hidden="true"
></i>
</div>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
@@ -96,7 +99,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-arrow-down mr-[2px]"
className="fa-light fa-arrow-down mr-[2px]"
aria-hidden="true"
></i>
Download
@@ -114,7 +117,7 @@ function Header({
>
<div className="border-none bg-[#fff]">
<i
className="fa-solid fa-award mr-[2px]"
className="fa-light fa-award mr-[2px]"
aria-hidden="true"
></i>
Certificate
@@ -128,7 +131,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-envelope mr-[2px]"
className="fa-light fa-envelope mr-[2px]"
aria-hidden="true"
></i>
Mail
@@ -143,7 +146,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-print mr-[2px]"
className="fa-light fa-print mr-[2px]"
aria-hidden="true"
></i>
Print
@@ -198,9 +201,9 @@ function Header({
)}
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<div className="font-[650] text-[18px] px-2 ml-[4px] op-link op-link-info no-underline">
<div className="font-[650] text-[18px] px-2 ml-[4px] text-base-content no-underline">
<i
className="fa fa-ellipsis-v"
className="fa-light fa-ellipsis-v"
aria-hidden="true"
></i>
</div>
@@ -221,7 +224,7 @@ function Header({
}
>
<i
className="fa fa-arrow-down mr-[5px]"
className="fa-light fa-arrow-down mr-[5px]"
aria-hidden="true"
></i>
<span className="font-[500]">Download</span>
@@ -269,7 +272,7 @@ function Header({
onClick={() => setIsEditTemplate(true)}
className="outline-none border-none text-center mr-[5px]"
>
<i className="fa-solid fa-gear fa-lg"></i>
<i className="fa-light fa-gear fa-lg"></i>
</button>
)}
<button
@@ -305,7 +308,7 @@ function Header({
className="op-btn op-btn-secondary op-btn-sm mr-[5px] shadow"
>
<i
className="fa-solid fa-award py-[3px]"
className="fa-light fa-award py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Certificate</span>
@@ -317,7 +320,10 @@ function Header({
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[5px] shadow"
>
<i className="fa fa-print py-[3px]" aria-hidden="true"></i>
<i
className="fa-light fa-print py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Print</span>
</button>
@@ -328,7 +334,10 @@ function Header({
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa fa-download py-[3px]" aria-hidden="true"></i>
<i
className="fa-light fa-download py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Download</span>
</button>
</div>
@@ -362,7 +371,10 @@ function Header({
role="button"
className="op-btn op-btn-info op-btn-sm shadow"
>
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
<i
className="fa-light fa-ellipsis-v"
aria-hidden="true"
></i>
</div>
<ul
tabIndex={0}
@@ -379,7 +391,7 @@ function Header({
>
<span className="font-semibold text-[12px]">
<i
className="fa fa-arrow-down"
className="fa-light fa-arrow-down"
aria-hidden="true"
></i>{" "}
Download
@@ -401,7 +413,7 @@ function Header({
}
className="op-btn op-btn-secondary op-btn-sm font-medium text-[13px] mr-[5px] shadow"
>
<i className="fa-solid fa-award" aria-hidden="true"></i>
<i className="fa-light fa-award" aria-hidden="true"></i>
<span className="hidden lg:block">Certificate</span>
</button>
)}
@@ -410,7 +422,7 @@ function Header({
type="button"
className="op-btn op-btn-neutral op-btn-sm font-medium text-[13px] mr-[5px] shadow"
>
<i className="fa fa-print" aria-hidden="true"></i>
<i className="fa-light fa-print" aria-hidden="true"></i>
<span className="hidden lg:block">Print</span>
</button>
<button
@@ -420,7 +432,7 @@ function Header({
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa fa-download" aria-hidden="true"></i>
<i className="fa-light fa-download" aria-hidden="true"></i>
<span className="hidden lg:block">Download</span>
</button>
<button
@@ -428,7 +440,7 @@ function Header({
className="op-btn op-btn-info op-btn-sm font-medium text-[13px] mr-[5px] shadow"
onClick={() => setIsEmail(true)}
>
<i className="fa fa-envelope" aria-hidden="true"></i>
<i className="fa-light fa-envelope" aria-hidden="true"></i>
<span className="hidden lg:block">Mail</span>
</button>
</div>
@@ -474,10 +486,8 @@ function Header({
{isDownloading === "certificate"}{" "}
<p>
Your completion certificate is being generated. Please wait
momentarily.
</p>
<p>
If the download doesn&apos;t start shortly, click the button again.
momentarily. If the download doesn&apos;t start shortly, click the
button again.
</p>
</div>
</ModalUi>
@@ -0,0 +1,53 @@
import React from "react";
function PdfZoom(props) {
const onClickZoomIn = () => {
props.setScale(props.scale + 0.1 * props.scale);
props.setZoomPercent(props.zoomPercent + 10);
};
const onClickZoomOut = () => {
if (props.zoomPercent > 0) {
if (props.zoomPercent === 10) {
props.setScale(1);
} else {
props.setScale(props.scale - 0.1 * props.scale);
}
props.setZoomPercent(props.zoomPercent - 10);
}
};
const handleReset = () => {
props.setScale(1);
props.setZoomPercent(0);
};
return (
// md:mt-[41px] xl:mt-[63px]mt=[]
<span className=" hidden md:flex flex-col gap-1 text-center md:w-[5%] mt-[50px] 2xl:mt-[63px]">
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
onClick={onClickZoomIn}
title="Zoom in"
>
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px]"></i>
</span>
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer "
onClick={handleReset}
title="Reset"
>
<i className="fa-light fa-arrows-rotate text-gray-500 2xl:text-[30px]"></i>
</span>
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px]"
onClick={onClickZoomOut}
style={{
cursor: props.zoomPercent > 0 ? "pointer" : "default"
}}
title="Zoom out"
>
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px]"></i>
</span>
</span>
);
}
export default PdfZoom;
+121 -34
View File
@@ -5,7 +5,7 @@ import { Rnd } from "react-rnd";
import {
defaultWidthHeight,
handleCopyNextToWidget,
isMobile,
isTabAndMobile,
onChangeInput,
radioButtonWidget,
textInputWidget,
@@ -88,6 +88,7 @@ const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
function Placeholder(props) {
const [placeholderBorder, setPlaceholderBorder] = useState({ w: 0, h: 0 });
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
const [selectDate, setSelectDate] = useState({
@@ -119,6 +120,7 @@ function Placeholder(props) {
width: null,
height: null
});
const containerScale = props.containerWH.width / props.pdfOriginalWH.width;
const dateFormatArr = [
"L",
"DD-MM-YYYY",
@@ -293,12 +295,27 @@ function Placeholder(props) {
props?.setShowDropdown(true);
} else if (props.pos.type === "checkbox") {
props?.setIsCheckbox(true);
} else if (
[
textInputWidget,
textWidget,
"name",
"company",
"job title",
"email"
].includes(props.pos.type)
) {
props.handleTextSettingModal(true);
} else {
props?.handleNameModal(true);
props?.handleNameModal && props?.handleNameModal(true);
}
if (props.isPlaceholder && props.type !== textWidget) {
props.setUniqueId(props.data.Id);
if (props.data && props?.pos?.type !== textWidget) {
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
} else if (props.data && props.pos.type === textWidget) {
props.setTempSignerId(props.uniqueId);
props.setUniqueId(props?.data?.Id);
}
props.setSignKey(props.pos.key);
props.setWidgetType(props.pos.type);
@@ -375,7 +392,15 @@ function Placeholder(props) {
<>
{(props.isPlaceholder || props.isSignYourself) && (
<>
{props.pos.type === "checkbox" && props.isSignYourself ? (
{[
"checkbox",
textInputWidget,
textWidget,
"name",
"company",
"job title",
"email"
].includes(props.pos.type) && props.isSignYourself ? (
<i
onClick={(e) => {
e.stopPropagation();
@@ -385,7 +410,7 @@ function Placeholder(props) {
e.stopPropagation();
handleOnClickSettingIcon();
}}
className="fa-solid fa-gear settingIcon"
className="fa-light fa-gear settingIcon"
style={{
color: "#188ae2",
right: "29px",
@@ -395,9 +420,7 @@ function Placeholder(props) {
) : (
((!props?.pos?.type && props.pos.isStamp) ||
(props?.pos?.type &&
!["date", textWidget, "signature"].includes(
props.pos.type
) &&
!["date", "signature"].includes(props.pos.type) &&
!props.isSignYourself)) && (
<i
onClick={(e) => {
@@ -408,8 +431,12 @@ function Placeholder(props) {
e.stopPropagation();
handleOnClickSettingIcon();
}}
className="fa-solid fa-gear settingIcon"
style={{ color: "#188ae2", right: "47px", top: "-19px" }}
className="fa-light fa-gear settingIcon"
style={{
color: "#188ae2",
right: props?.pos?.type === textWidget ? "32px" : "47px",
top: "-19px"
}}
></i>
)
)}
@@ -417,7 +444,7 @@ function Placeholder(props) {
{props.pos.type !== textWidget && !props.isSignYourself && (
<i
data-tut="assignSigner"
className="fa-regular fa-user signUserIcon"
className="fa-light fa-user signUserIcon"
onClick={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
@@ -464,7 +491,7 @@ function Placeholder(props) {
}}
>
<i
className="fa-solid fa-gear settingIcon"
className="fa-light fa-gear settingIcon"
style={{
color: "#188ae2",
fontSize: "14px"
@@ -503,13 +530,13 @@ function Placeholder(props) {
</div>
)}
<i
className="fa-regular fa-copy signCopy"
className="fa-light fa-copy signCopy"
onClick={(e) => handleCopyPlaceholder(e)}
onTouchEnd={(e) => handleCopyPlaceholder(e)}
style={{ color: "#188ae2", right: "12px", top: "-18px" }}
></i>
<i
className="fa-regular fa-circle-xmark signCloseBtn"
className="fa-light fa-circle-xmark signCloseBtn"
onClick={(e) => {
e.stopPropagation();
@@ -535,6 +562,55 @@ function Placeholder(props) {
)
);
};
const xPos = (pos, signYourself) => {
const containerScale = props.containerWH.width / props.pdfOriginalWH.width;
const resizePos = pos.xPosition;
if (signYourself) {
return resizePos * containerScale * props.scale;
} else {
//checking both condition mobile and desktop view
if (pos.isMobile && pos.scale) {
if (props.scale > 1) {
return resizePos * pos.scale * containerScale * props.scale;
} else {
return resizePos * pos.scale * containerScale;
}
} else {
// if (pos.scale === containerScale) {
// return resizePos * pos.scale * props.scale;
// } else {
return resizePos * containerScale * props.scale;
// }
}
}
};
const yPos = (pos, signYourself) => {
const containerScale = props.containerWH.width / props.pdfOriginalWH.width;
const resizePos = pos.yPosition;
if (signYourself) {
return resizePos * containerScale * props.scale;
} else {
//checking both condition mobile and desktop view
if (pos.isMobile && pos.scale) {
if (props.scale > 1) {
return resizePos * pos.scale * containerScale * props.scale;
} else {
return resizePos * pos.scale * containerScale;
}
}
// else if (pos.scale === containerScale) {
// if (props.scale > 1) {
// return resizePos * pos.scale * props.scale;
// } else {
// return resizePos * pos.scale;
// }
// }
else {
return resizePos * containerScale * props.scale;
}
}
};
return (
<Rnd
@@ -620,8 +696,20 @@ function Placeholder(props) {
setDraggingEnabled(true);
props.setIsResize && props.setIsResize(true);
}}
onResizeStop={() => {
onResizeStop={(e, direction, ref) => {
props.setIsResize && props.setIsResize(false);
props.handleSignYourselfImageResize &&
props.handleSignYourselfImageResize(
ref,
props.pos.key,
props.xyPostion,
props.setXyPostion,
props.index,
containerScale,
props.scale,
props.data && props.data.Id,
props.isResize
);
}}
disableDragging={
props.isNeedSign
@@ -634,21 +722,15 @@ function Placeholder(props) {
props.handleStop &&
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
}
default={{
x: props.xPos(props.pos, props.isSignYourself),
y: props.yPos(props.pos, props.isSignYourself)
position={{
x: xPos(props.pos, props.isSignYourself),
y: yPos(props.pos, props.isSignYourself)
}}
onResize={(e, direction, ref) => {
props.handleSignYourselfImageResize &&
props.handleSignYourselfImageResize(
ref,
props.pos.key,
props.xyPostion,
props.setXyPostion,
props.index,
props.data && props.data.Id,
false
);
setPlaceholderBorder({
w: ref.offsetWidth / (props.scale * containerScale),
h: ref.offsetHeight / (props.scale * containerScale)
});
}}
onClick={() => handleOnClickPlaceholder()}
>
@@ -677,20 +759,22 @@ function Placeholder(props) {
pos={props.pos}
isPlaceholder={props.isPlaceholder}
getCheckboxRenderWidth={getCheckboxRenderWidth}
scale={props.scale}
containerScale={containerScale}
placeholderBorder={placeholderBorder}
/>
)}
{isMobile ? (
{isTabAndMobile ? (
<div
// className="sm:inline-block md:inline-block lg:hidden "
style={{
left: props.xPos(props.pos, props.isSignYourself),
top: props.yPos(props.pos, props.isSignYourself),
left: xPos(props.pos, props.isSignYourself),
top: yPos(props.pos, props.isSignYourself),
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
// "auto", //props.posWidth(props.pos, props.isSignYourself),
// height: props.posHeight(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
@@ -699,6 +783,7 @@ function Placeholder(props) {
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
onClick={() => handleOnClickPlaceholder()}
>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
@@ -723,6 +808,7 @@ function Placeholder(props) {
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
/>
</div>
) : (
@@ -749,6 +835,7 @@ function Placeholder(props) {
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
/>
</>
)}
@@ -11,23 +11,34 @@ function PlaceholderBorder(props) {
const getResizeBorderExtraWidth = resizeBorderExtraWidth();
const defaultWidth = defaultWidthHeight(props.pos.type).width;
const defaultHeight = defaultWidthHeight(props.pos.type).height;
const width = () => {
const getWidth =
props.placeholderBorder.w || props.pos.Width || defaultWidth;
return (
getWidth * props.scale * props.containerScale + getResizeBorderExtraWidth
);
};
const height = () => {
const getHeight =
props.placeholderBorder.h || props.pos.Height || defaultHeight;
return (
getHeight * props.scale * props.containerScale + getResizeBorderExtraWidth
);
};
const handleMinWidth = () => {
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
return props.getCheckboxRenderWidth.width + getResizeBorderExtraWidth;
} else {
return props.pos.Width
? props.pos.Width + getResizeBorderExtraWidth
: defaultWidth + getResizeBorderExtraWidth;
return width();
}
};
const handleMinHeight = () => {
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
return props.getCheckboxRenderWidth.height + getResizeBorderExtraWidth;
} else {
return props.pos.Height
? props.pos.Height + getResizeBorderExtraWidth
: defaultHeight + getResizeBorderExtraWidth;
return height();
}
};
return (
@@ -5,7 +5,6 @@ import { randomId, textWidget } from "../../constant/Utils";
function PlaceholderCopy(props) {
const copyType = ["All pages", "All pages but last", "All pages but first"];
const [selectCopyType, setSelectCopyType] = useState("");
//function for get copy placeholder position
const getCopyPlaceholderPosition = (
type,
@@ -145,7 +145,7 @@ function PlaceholderType(props) {
ref={ref}
>
{value}
<i className="fa-regular fa-calendar ml-[5px]"></i>
<i className="fa-light fa-calendar ml-[5px]"></i>
</div>
));
ExampleCustomInput.displayName = "ExampleCustomInput";
@@ -309,7 +309,7 @@ function PlaceholderType(props) {
alt="signature"
draggable="false"
src={props.pos.SignUrl}
className="w-[99%] h-full object-contain"
className="w-full h-full object-contain"
/>
) : (
<div className="text-[11px] text-black justify-center">
@@ -327,7 +327,7 @@ function PlaceholderType(props) {
alt="stamp"
draggable="false"
src={props.pos.SignUrl}
className="w-[99%] h-full object-contain"
className="w-full h-full object-contain"
/>
) : (
<div className="text-[11px] text-black justify-center">
@@ -470,7 +470,7 @@ function PlaceholderType(props) {
alt="initials"
draggable="false"
src={props.pos.SignUrl}
className="w-[99%] h-full object-contain"
className="w-full h-full object-contain"
/>
) : (
<div className="text-[11px] text-black justify-center">
@@ -650,7 +650,7 @@ function PlaceholderType(props) {
alt="image"
draggable="false"
src={props.pos.SignUrl}
className="w-[99%] h-full object-contain"
className="w-full h-full object-contain"
/>
) : (
<div className="text-[11px] text-black justify-center">
@@ -704,11 +704,9 @@ function PlaceholderType(props) {
return (
<div key={ind} className="flex items-center text-center gap-0.5">
<input
className={`${ind === 0 ? "mt-0" : "mt-[5px]"} ${
props?.pos?.Width
? `w-[${props?.pos?.Width}px] h-[${props?.pos?.Width}px]`
: "w-[15px] h-[15px]"
} flex justify-center op-radio`}
className={`${
ind === 0 ? "mt-0" : "mt-[5px]"
} ${"w-[15px] h-[15px]"} flex justify-center op-radio`}
type="radio"
disabled={
props.isNeedSign &&
@@ -761,7 +759,7 @@ function PlaceholderType(props) {
alt="image"
draggable="false"
src={props.pos.SignUrl}
className="w-[99%] h-full object-contain"
className="w-full h-full object-contain"
/>
</div>
) : (
+5 -5
View File
@@ -18,11 +18,11 @@ function PrevNext({ pageNumber, allPages, changePage }) {
onClick={previousPage}
>
<span className="block lg:hidden">
<i className="fa fa-backward" aria-hidden="true"></i>
<i className="fa-light fa-backward" aria-hidden="true"></i>
</span>
<span className="lg:block hidden">Prev</span>
<span className="lg:block hidden 2xl:text-[30px]">Prev</span>
</button>
<span className="text-xs text-base-content font-medium mx-2">
<span className="text-xs text-base-content font-medium mx-2 2xl:text-[30px]">
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
</span>
<button
@@ -31,9 +31,9 @@ function PrevNext({ pageNumber, allPages, changePage }) {
onClick={nextPage}
>
<span className="block lg:hidden">
<i className="fa fa-forward" aria-hidden="true"></i>
<i className="fa-light fa-forward" aria-hidden="true"></i>
</span>
<span className="lg:block hidden">Next</span>
<span className="lg:block hidden 2xl:text-[30px]">Next</span>
</button>
</div>
);
@@ -15,7 +15,6 @@ const RecipientList = (props) => {
const [isEdit, setIsEdit] = useState(false);
//function for onhover signer name change background color
const inputRef = useRef(null);
const isWidgetExist = (Id) => {
return props.signerPos.some((x) => x.Id === Id);
};
@@ -72,7 +71,6 @@ const RecipientList = (props) => {
props.setRoleName(remainingItems[index]?.Role);
props.setBlockColor(remainingItems[index]?.blockColor);
};
return (
<>
{props.signersdata.length > 0 &&
@@ -133,7 +131,7 @@ const RecipientList = (props) => {
>
<span className="text-white uppercase font-bold text-center text-[12px]">
{isWidgetExist(obj.Id) ? (
<i className="fa-solid fa-check"></i>
<i className="fa-light fa-check"></i>
) : (
<>
{obj.Name
@@ -145,7 +143,7 @@ const RecipientList = (props) => {
</div>
<div
className={`${
obj?.Name ? "flex-col" : "flex-row"
obj.Name ? "flex-col" : "flex-row"
} flex items-center`}
>
{obj.Name ? (
@@ -175,7 +173,7 @@ const RecipientList = (props) => {
{isEdit?.[obj.Id] && props.handleRoleChange ? (
<input
ref={inputRef}
className="bg-transparent p-[3px"
className="bg-transparent p-[3px]"
value={obj.Role}
onChange={(e) => props.handleRoleChange(e, obj.Id)}
onBlur={() => {
@@ -190,7 +188,9 @@ const RecipientList = (props) => {
}}
/>
) : (
<span className="p-[3px]">{obj.Role}</span>
<span className="text-[13px] 2xl:text-[25px]">
{obj.Role}
</span>
)}
</span>
)}
@@ -251,7 +251,7 @@ const RecipientList = (props) => {
: "text-base-content"
} cursor-pointer ml-[5px]`}
>
<i className="fa-regular fa-trash-can"></i>
<i className="fa-light fa-trash-can 2xl:text-[30px]"></i>
</div>
)}
<hr />
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import RSC from "react-scrollbars-custom";
import React, { useEffect, useRef, useState } from "react";
import { Document, Page } from "react-pdf";
import { useSelector } from "react-redux";
function RenderAllPdfPage({
signPdfUrl,
@@ -33,7 +33,22 @@ function RenderAllPdfPage({
}
}
}
const pageContainer = useRef();
const isHeader = useSelector((state) => state.showHeader);
const [pageWidth, setPageWidth] = useState("");
useEffect(() => {
const updateSize = () => {
if (pageContainer.current) {
setPageWidth(pageContainer.current.offsetWidth);
}
};
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
}, [isHeader, pageContainer]);
//'function `addSignatureBookmark` is used to display the page where the user's signature is located.
const addSignatureBookmark = (index) => {
const ispageNumber = signPageNumber.includes(index + 1);
@@ -42,68 +57,58 @@ function RenderAllPdfPage({
<div className="absolute z-20 top-[1px] -right-[13px] -translate-x-1/2 -translate-y-1/2">
<i
style={{ color: bookmarkColor || "red" }}
className="fa-solid fa-bookmark"
className="fa-light fa-bookmark"
></i>
</div>
)
);
};
return (
<div>
<div className=" hidden md:flex flex-row bg-base-100 h-full">
<div className="w-[140px]">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Pages
</div>
<div>
<RSC
id="RSC-Example"
style={{
width: "135px",
height: window.innerHeight - 130 + "px"
return (
<div
ref={pageContainer}
className="hidden min-h-screen w-[20%] bg-base-100 h-full md:block"
>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Pages
</div>
<div
className={`flex h-[90%] flex-col items-center m-2
autoSignScroll hide-scrollbar max-h-[100vh] `}
>
<Document
loading={"Loading Document.."}
onLoadSuccess={onDocumentLoad}
file={signPdfUrl}
>
{Array.from(new Array(allPages), (el, index) => (
<div
key={index}
className={`${
pageNumber - 1 === index ? "border-[red]" : "border-[#878787]"
} border-2 m-[10px] flex justify-center items-center relative`}
onClick={() => {
setPageNumber(index + 1);
if (setSignBtnPosition) {
setSignBtnPosition([]);
}
}}
>
<Document
loading={"Loading Document.."}
onLoadSuccess={onDocumentLoad}
file={signPdfUrl}
>
{Array.from(new Array(allPages), (el, index) => (
<div
key={index}
className={`${
pageNumber - 1 === index
? "border-[red]"
: "border-[#878787]"
} border-2 w-[100px] m-[10px] flex justify-center items-center relative`}
onClick={() => {
setPageNumber(index + 1);
if (setSignBtnPosition) {
setSignBtnPosition([]);
}
}}
>
{signerPos && addSignatureBookmark(index)}
{signerPos && addSignatureBookmark(index)}
<div className="relative z-[1] overflow-hidden">
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
width={100}
height={100}
scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
/>
</div>
</div>
))}
</Document>
</RSC>
</div>
<hr />
</div>
<div className="relative z-[1] overflow-hidden">
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
width={pageWidth - 60}
scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
/>
</div>
</div>
))}
</Document>
</div>
</div>
);
+157 -216
View File
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import RSC from "react-scrollbars-custom";
import { Document, Page } from "react-pdf";
import {
@@ -11,8 +11,6 @@ import Alert from "../../primitives/Alert";
function RenderPdf({
pageNumber,
pdfOriginalWidth,
pdfNewWidth,
drop,
signerPos,
successEmail,
@@ -26,15 +24,12 @@ function RenderPdf({
pdfDetails,
xyPostion,
pdfUrl,
numPages,
pageDetails,
pdfRequest,
setCurrentSigner,
signerObjectId,
signedSigners,
setPdfLoadFail,
placeholder,
pdfLoadFail,
setSignerPos,
setXyPostion,
index,
@@ -57,165 +52,87 @@ function RenderPdf({
unSignedWidgetId,
setIsCheckbox,
handleNameModal,
handleTextSettingModal,
setTempSignerId,
uniqueId
uniqueId,
setPdfRenderHeight,
pdfOriginalWH,
scale
}) {
const [isLoadPdf, setIsLoadPdf] = useState(false);
const isMobile = window.innerWidth < 767;
const newWidth = containerWH.width;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
// handle signature block width and height according to screen
const posWidth = (pos, signYourself) => {
const containerScale = containerWH.width / pdfOriginalWH.width;
const defaultWidth = defaultWidthHeight(pos.type).width;
const posWidth = pos.Width ? pos.Width : defaultWidth;
let width;
if (signYourself) {
width = posWidth;
return width;
return posWidth * scale * containerScale;
} else {
if (isMobile) {
if (!pos.isMobile) {
if (pos.IsResize) {
width = posWidth ? posWidth : defaultWidth;
return width;
if (pos.isMobile && pos.scale) {
if (pos.IsResize) {
if (scale > 1) {
return posWidth * pos.scale * containerScale * scale;
} else {
width = (posWidth || defaultWidth) / scale;
return width;
return posWidth * containerScale;
}
} else {
width = posWidth;
return width;
if (scale > 1) {
return posWidth * pos.scale * containerScale * scale;
} else {
return posWidth * pos.scale * containerScale;
}
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
width = posWidth ? posWidth : defaultWidth;
return width;
} else {
width = (posWidth || defaultWidth) * pos.scale;
return width;
}
} else {
width = posWidth ? posWidth : defaultWidth;
return width;
}
return posWidth * scale * containerScale;
}
}
};
const posHeight = (pos, signYourself) => {
let height;
const posHeight = pos.Height;
const defaultHeight = defaultWidthHeight(pos.type).height;
const containerScale = containerWH.width / pdfOriginalWH.width;
const posHeight = pos.Height || defaultWidthHeight(pos.type).height;
if (signYourself) {
height = posHeight ? posHeight : defaultHeight;
return height;
return posHeight * scale * containerScale;
} else {
if (isMobile) {
if (!pos.isMobile) {
if (pos.IsResize) {
height = posHeight ? posHeight : defaultHeight;
return height;
if (pos.isMobile && pos.scale) {
if (pos.IsResize) {
if (scale > 1) {
return posHeight * pos.scale * containerScale * scale;
} else {
height = (posHeight || defaultHeight) / scale;
return height;
return posHeight * containerScale;
}
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
height = posHeight ? posHeight : defaultHeight;
return height;
if (scale > 1) {
return posHeight * pos.scale * containerScale * scale;
} else {
height = (posHeight || defaultHeight) * pos.scale;
return height;
return posHeight * pos.scale * containerScale;
}
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
}
}
};
const xPos = (pos, signYourself) => {
const resizePos = pos.xPosition;
if (signYourself) {
return resizePos;
} else {
//checking both condition mobile and desktop view
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (!pos.isMobile) {
return resizePos / scale;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return resizePos * (pos.scale / scale);
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
return pos.scale && resizePos * pos.scale;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return resizePos;
}
return posHeight * scale * containerScale;
}
}
};
const yPos = (pos, signYourself) => {
const resizePos = pos.yPosition;
if (signYourself) {
return resizePos;
} else {
//checking both condition mobile and desktop view
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (!pos.isMobile) {
return resizePos / scale;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return resizePos * (pos.scale / scale);
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
return pos.scale && resizePos * pos.scale;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return resizePos;
}
}
}
};
//function for render placeholder block over pdf document
const checkSignedSignes = (data) => {
const checkSignedSigners = (data) => {
let checkSign = [];
//condition to handle quick send flow and using normal request sign flow
checkSign = signedSigners.filter(
(sign) => sign?.Id === data?.Id || sign?.objectId === data?.signerObjId
);
if (data.signerObjId === signerObjectId) {
setCurrentSigner(true);
}
checkSign = signedSigners
? signedSigners?.filter(
(sign) =>
sign?.Id === data?.Id || sign?.objectId === data?.signerObjId
)
: [];
const handleAllUserName = (Id, Role, type) => {
return (
<React.Fragment>
<div className="text-black text-[8px] font-medium">
<div className="text-black text-[8px] font-bold">
{
pdfDetails[0].Signers?.find(
(signer) => signer.objectId === data.signerObjId
@@ -231,7 +148,6 @@ function RenderPdf({
</React.Fragment>
);
};
return (
checkSign.length === 0 &&
data.placeHolder.map((placeData, key) => {
@@ -258,8 +174,6 @@ function RenderPdf({
isShowDropdown={true}
isNeedSign={true}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
handleUserName={handleAllUserName}
@@ -271,6 +185,10 @@ function RenderPdf({
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
uniqueId={uniqueId}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
/>
</React.Fragment>
)
@@ -281,6 +199,7 @@ function RenderPdf({
})
);
};
//function for render placeholder block over pdf document
const handleUserName = (Id, Role, type) => {
if (Id) {
@@ -316,11 +235,10 @@ function RenderPdf({
);
}
};
return (
<>
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{isMobile && scale ? (
{isMobile ? (
<div
data-tut="reactourForth"
style={{
@@ -330,12 +248,14 @@ function RenderPdf({
ref={drop}
id="container"
>
{pdfLoadFail.status &&
{isLoadPdf &&
containerWH?.width &&
pdfOriginalWH?.width &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSignes(data)}
{checkSignedSigners(data)}
</React.Fragment>
);
})
@@ -374,8 +294,6 @@ function RenderPdf({
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
@@ -391,6 +309,12 @@ function RenderPdf({
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
/>
</React.Fragment>
);
@@ -422,13 +346,10 @@ function RenderPdf({
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
pdfOriginalWidth={pdfOriginalWidth}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
@@ -441,6 +362,11 @@ function RenderPdf({
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
/>
)
);
@@ -452,7 +378,9 @@ function RenderPdf({
{/* this component for render pdf document is in middle of the component */}
<div className="flex items-center justify-center">
<Document
onLoadError={() => setPdfLoadFail(true)}
onLoadError={() => {
setPdfLoadFail(true);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
// ref={pdfRef}'
@@ -469,19 +397,20 @@ function RenderPdf({
: pdfDetails[0].URL
}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={index}
pageNumber={pageNumber}
width={containerWH.width}
height={containerWH.height}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
))}
<Page
onLoadSuccess={({ height }) => {
setPdfRenderHeight && setPdfRenderHeight(height);
setIsLoadPdf(true);
}}
key={index}
pageNumber={pageNumber}
width={containerWH.width}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
</Document>
</div>
</div>
@@ -490,29 +419,31 @@ function RenderPdf({
style={{
position: "relative",
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
width:
pdfOriginalWidth > pdfNewWidth ? pdfNewWidth : pdfOriginalWidth,
height: window.innerHeight - 110 + "px"
height: window.innerHeight + "px",
zIndex: 0
}}
noScrollY={false}
noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true}
noScrollX={scale === 1 ? true : false}
>
<div
data-tut="reactourForth"
style={{ border: "0.1px solid #ebe8e8", width: pdfOriginalWidth }}
style={{
width: containerWH.width * scale
}}
ref={drop}
id="container"
>
{pdfLoadFail.status &&
(pdfRequest
? signerPos.map((data, key) => {
{isLoadPdf &&
containerWH?.width &&
pdfOriginalWH?.width &&
(pdfRequest //pdf request sign flow
? signerPos?.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSignes(data)}
{checkSignedSigners(data)}
</React.Fragment>
);
})
: placeholder
: placeholder //placeholder and template flow
? signerPos.map((data, ind) => {
return (
<React.Fragment key={ind}>
@@ -547,8 +478,6 @@ function RenderPdf({
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
@@ -564,6 +493,12 @@ function RenderPdf({
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
/>
</React.Fragment>
);
@@ -575,53 +510,54 @@ function RenderPdf({
);
})
: xyPostion.map((data, ind) => {
// signyourself flow
return (
<React.Fragment key={ind}>
{data.pageNumber === pageNumber &&
data.pos.map((pos) => {
return (
pos && (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={(event, dragElement) =>
handleStop(event, dragElement, pos.type)
}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
pdfOriginalWidth={pdfOriginalWidth}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
/>
</React.Fragment>
)
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={(event, dragElement) =>
handleStop(event, dragElement, pos.type)
}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
/>
</React.Fragment>
);
})}
</React.Fragment>
@@ -653,17 +589,22 @@ function RenderPdf({
: pdfDetails[0].URL
}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={index}
pageNumber={pageNumber}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
))}
<Page
onLoadSuccess={({ height }) => {
setPdfRenderHeight && setPdfRenderHeight(height);
setIsLoadPdf(true);
}}
key={index}
width={containerWH.width}
scale={scale || 1}
className={"-z-[1]"} // when user zoom-in in tablet widgets move backward that's why pass -z-[1]
pageNumber={pageNumber}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
</Document>
</div>
</RSC>
+2 -2
View File
@@ -271,7 +271,7 @@ function SignPad({
}
}}
key={key}
className="fa solid fa-pen-nib"
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
@@ -472,7 +472,7 @@ function SignPad({
ref={imageRef}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
</div>
</div>
+1 -1
View File
@@ -7,7 +7,7 @@ function Signedby({ pdfDetails }) {
};
return (
<div className="hidden md:block w-[180px] h-full bg-base-100">
<div className="hidden md:block w-full h-full bg-base-100">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Signed By
</div>
@@ -0,0 +1,56 @@
import React from "react";
import { darkenColor, getFirstLetter } from "../../constant/Utils";
function SignerListComponent(props) {
const checkSignerBackColor = (obj) => {
if (obj) {
let data = "";
if (obj?.Id) {
data = props.signerPos.filter((data) => data.Id === obj.Id);
} else {
data = props.signerPos.filter(
(data) => data.signerObjId === obj.objectId
);
}
return data && data.length > 0 && data[0].blockColor;
}
};
const checkUserNameColor = (obj) => {
const getBackColor = checkSignerBackColor(obj);
if (getBackColor) {
const color = darkenColor(getBackColor, 0.4);
return color;
} else {
return "#abd1d0";
}
};
return (
<div
className="rounded-xl mx-1 flex flex-row items-center py-[10px] mt-1"
style={{
background: checkSignerBackColor(props.obj)
}}
>
<div
style={{
background: checkUserNameColor(props.obj)
}}
className="flex w-[30px] h-[30px] rounded-full justify-center items-center mx-1"
>
<span className="text-[12px] text-center font-bold text-black uppercase">
{getFirstLetter(props?.obj?.Name || props?.obj?.Role)}
</span>
</div>
<div className="flex flex-col">
<span className="userName">{props.obj?.Name || props?.obj?.Role}</span>
<span className="useEmail">
{" "}
{props.obj?.Email || props.obj?.email}
</span>
</div>
</div>
);
}
export default SignerListComponent;
@@ -8,17 +8,19 @@ function SignerListPlace(props) {
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span>
{props.title ? props.title : "Recipients"}
<span className="text-xs mt-1 ml-0.5">
<span className="absolute text-xs z-[30] mt-1 ml-0.5">
{props?.title === "Roles" && (
<>
<a data-tooltip-id="my-tooltip">
<sup>
<i className="fa-solid fa-question rounded-full border-[1.5px] border-base-content text-[11px] py-[1px] px-[3px]"></i>
<i className="fa-light fa-question rounded-full border-[1.5px] border-base-content text-[11px] py-[1px] px-[3px]"></i>
</sup>
</a>
<Tooltip id="my-tooltip" className="z-[100]">
<div className="max-w-[450px]">
<p className="font-bold">What are template roles?</p>
<div className="max-w-[450px] 2xl:max-w-[500px] 2xl:text-[20px] p-[1px]">
<p className="font-bold pb-[1px]">
What are template roles?
</p>
<p>
Begin by specifying each role needed for the completion of
the document. Think about the parties involved in the
@@ -61,11 +63,11 @@ function SignerListPlace(props) {
<div
role="button"
data-tut="reactourAddbtn"
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
disabled={props?.isMailSend ? true : false}
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
onClick={() => props.handleAddSigner()}
>
<i className="fa-solid fa-plus"></i> Add role
<i className="fa-light fa-plus"></i> Add role
</div>
) : (
<div
@@ -75,7 +77,7 @@ function SignerListPlace(props) {
disabled={props?.isMailSend ? true : false}
onClick={() => props.setIsAddSigner(true)}
>
<i className="fa-solid fa-plus"></i> Add recipients
<i className="fa-light fa-plus"></i> Add recipients
</div>
)}
</div>
@@ -0,0 +1,75 @@
import React from "react";
import ModalUi from "../../primitives/ModalUi";
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
function TextFontSetting(props) {
return (
<ModalUi
headerColor={"#dc3545"}
isOpen={props.isTextSetting}
reduceWidth={"max-w-[350px]"}
title={"Text field"}
handleClose={() => {
props.setIsTextSetting(false);
}}
>
<div className="h-full p-[20px]">
<div className="flex items-center">
<span>Font size:</span>
<select
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
value={
props.fontSize || props.currWidgetsDetails?.options?.fontSize
}
onChange={(e) => props.setFontSize(e.target.value)}
>
{fontsizeArr.map((size, ind) => {
return (
<option className="text-[13px]" value={size} key={ind}>
{size}
</option>
);
})}
</select>
<div className="flex flex-row gap-1 items-center ml-4">
<span>color: </span>
<select
value={
props.fontColor || props.currWidgetsDetails?.options?.fontColor
}
onChange={(e) => props.setFontColor(e.target.value)}
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
>
{fontColorArr.map((color, ind) => {
return (
<option value={color} key={ind}>
{color}
</option>
);
})}
</select>
<span
style={{
background:
props.fontColor ||
props.currWidgetsDetails?.options?.fontColor
}}
className="w-5 h-[19px] ml-1"
></span>
</div>
</div>
<div className="h-[1px] bg-[#9f9f9f] w-full mt-[15px] mb-2"></div>
<button
onClick={() => props.handleSaveFontSize()}
type="button"
className="op-btn op-btn-primary mt-2"
>
save
</button>
</div>
</ModalUi>
);
}
export default TextFontSetting;
@@ -297,7 +297,7 @@ function WidgetComponent({
</div>
)}
<div className="ml-[6px] text-[16px]">
<i className="fa-solid fa-angle-down"></i>
<i className="fa-light fa-angle-down"></i>
</div>
</span>
</div>
@@ -310,7 +310,7 @@ function WidgetComponent({
className="op-btn op-btn-accent w-full my-[2px]"
onClick={() => handleAddSigner()}
>
<i className="fa-solid fa-plus"></i>
<i className="fa-light fa-plus"></i>
<span>Add role</span>
</div>
) : (
@@ -320,7 +320,7 @@ function WidgetComponent({
className="op-btn op-btn-accent w-full my-[2px]"
onClick={() => setIsAddSigner(true)}
>
<i className="fa-solid fa-plus"></i>
<i className="fa-light fa-plus"></i>
<span>Add recipients</span>
</div>
)
@@ -349,12 +349,13 @@ function WidgetComponent({
data-tut={dataTut}
className={`${
isMailSend ? "bg-opacity-50 pointer-events-none" : ""
} hidden md:block w-[180px] h-full bg-base-100`}
} hidden md:block h-full bg-base-100`}
>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span>Fields</span>
</div>
<div className="flex flex-col items-center my-3">
<div className="p-[15px] flex flex-col pt-4 2xl:m-5">
<WidgetList
updateWidgets={updateWidgets}
handleDivClick={handleDivClick}
@@ -4,9 +4,9 @@ import { getWidgetType } from "../../constant/Utils";
function WidgetList(props) {
return props.updateWidgets.map((item, ind) => {
return (
<div key={ind} className="mb-[5px]">
<div className="2xl:p-3 mb-[5px]" key={ind}>
<div
className="select-none"
className="select-none mx-[2px] md:mx-0 cursor-all-scroll"
onClick={() => {
props.addPositionOfSignature &&
props.addPositionOfSignature("onclick", item);
@@ -22,11 +22,10 @@ function WidgetList(props) {
}
}}
onMouseMove={props?.handleDivClick}
onMouseDown={() => {
props?.handleMouseLeave();
}}
onMouseDown={() => props?.handleMouseLeave()}
onTouchStart={props?.handleDivClick}
>
{item.ref && getWidgetType(item, props?.marginLeft)}
{item.ref && getWidgetType(item)}
</div>
</div>
);
@@ -221,7 +221,7 @@ const WidgetNameModal = (props) => {
style={{ fontSize: 12 }}
>
<i
className="fas fa-exclamation-circle text-[15px]"
className="fa-light fa-exclamation-circle text-[15px]"
style={{ color: "#fab005" }}
></i>
invalid default value
@@ -152,7 +152,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
disabled={isLoader}
className="op-btn op-btn-primary op-btn-sm mt-3"
>
<i className="fa-solid fa-plus"></i>
<i className="fa-light fa-plus"></i>
<span>Create</span>
</button>
</div>
@@ -24,11 +24,11 @@ const FolderModal = (props) => {
const FolderQuery = new Parse.Query(props.folderCls);
if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
FolderQuery.descending("Type");
FolderQuery.notEqualTo("IsArchive", true);
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
FolderQuery.descending("Type");
FolderQuery.notEqualTo("IsArchive", true);
}
@@ -143,14 +143,14 @@ const FolderModal = (props) => {
handleCreate();
};
return (
<div className="text-xs mt-2 ">
<div className="text-xs mt-2">
<ModalUi
title={"Select Folder"}
isOpen={props.isOpenModal}
handleClose={handleCancel}
>
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<div className="pt-1 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="OpenSign™ Drive"
@@ -171,27 +171,50 @@ const FolderModal = (props) => {
{" / "}
</React.Fragment>
))}
<hr />
<hr className="bg-[#8a8a8a] mt-[0.750rem]" />
</div>
<div className="mt-2 mb-3">
<div className="max-h-[210px] overflow-auto">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer "
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
{!isAdd && folderList.length > 0
? folderList.map((folder) => (
<div
key={folder.objectId}
className={`${
folder.Type === "Folder"
? "cursor-pointer"
: "cursor-default"
} border-b-[1px] border-[#8a8a8a] py-2 mb-0.5"`}
onClick={() =>
folder.Type === "Folder" && handleSelect(folder)
}
>
<div className="flex items-center gap-2">
{folder.Type === "Folder" ? (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="w-[1.4rem] h-[1.4rem] fill-current op-text-secondary"
>
<path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z" />
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512"
className="w-[1.4rem] h-[1.4rem] fill-current op-text-primary"
>
<path d="M374.629 150.627L233.371 9.373C227.371 3.371 219.23 0 210.746 0H64C28.652 0 0 28.652 0 64V448C0 483.345 28.652 512 64 512H320C355.348 512 384 483.345 384 448V173.254C384 164.767 380.629 156.629 374.629 150.627ZM224 22.629L361.375 160H248C234.781 160 224 149.234 224 136V22.629ZM368 448C368 474.467 346.469 496 320 496H64C37.531 496 16 474.467 16 448V64C16 37.533 37.531 16 64 16H208V136C208 158.062 225.938 176 248 176H368V448ZM96 264C96 268.406 99.594 272 104 272H280C284.406 272 288 268.406 288 264S284.406 256 280 256H104C99.594 256 96 259.594 96 264ZM280 320H104C99.594 320 96 323.594 96 328S99.594 336 104 336H280C284.406 336 288 332.406 288 328S284.406 320 280 320ZM280 384H104C99.594 384 96 387.594 96 392S99.594 400 104 400H280C284.406 400 288 396.406 288 392S284.406 384 280 384Z" />
</svg>
)}
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
</div>
))}
))
: !isLoader && (
<div className="text-base-content text-center my-2">
No data found
</div>
)}
</div>
{isAdd && (
<CreateFolder
@@ -201,8 +224,8 @@ const FolderModal = (props) => {
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
<div className="flex justify-center my-4">
<i className="fa-light fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
@@ -210,22 +233,28 @@ const FolderModal = (props) => {
<hr />
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="text-[30px] cursor-pointer text-[#32a3ac]"
className="op-btn op-btn-seconday op-btn-sm"
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
<>
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
<span className="text-xs">Back</span>
</>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
<>
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
<span className="">Add folder</span>
</>
)}
</div>
<div
className="text-[30px] cursor-pointer"
className="op-btn op-btn-primary op-btn-sm"
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
</div>
</div>
</ModalUi>
@@ -177,11 +177,13 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
className=" cursor-pointer rounded px-[20px] py-[20px] bg-base-100 border-[1px] border-base-200 shadow flex max-w-sm gap-8 items-center"
>
<div>
<i
className="far fa-folder-open text-[40px] text-neutral"
style={{ fontSize: "40px" }}
aria-hidden="true"
></i>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="w-[40px] h-[40px] fill-current text-neutral"
>
<path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z" />
</svg>
</div>
<div className="font-semibold ">
<div className="flex items-center gap-2">
@@ -195,7 +197,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
// onClick={() => SetIsOpen(true)}
>
<i
className="fa fa-pencil cursor-pointer"
className="fa-light fa-pencil cursor-pointer"
title="Select Folder"
aria-hidden="true"
></i>
@@ -245,33 +247,46 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
</div>
<div className="mb-2">
<div className="max-h-[210px] overflow-auto">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.objectId}
className={`${
folder.Type === "Folder"
? "cursor-pointer"
: "cursor-default"
} border-b-[1px] border-[#8a8a8a] py-2 mb-0.5"`}
onClick={() =>
folder.Type === "Folder" && handleSelect(folder)
}
>
<div className="flex items-center gap-2">
<i
className={`${
folder.Type === "Folder"
? "fa fa-folder op-text-secondary"
: "fa fa-file op-text-primary"
} text-[1.4rem]`}
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
{!isAdd && folderList.length > 0
? folderList.map((folder) => (
<div
key={folder.objectId}
className={`${
folder.Type === "Folder"
? "cursor-pointer"
: "cursor-default"
} border-b-[1px] border-[#8a8a8a] py-2 mb-0.5"`}
onClick={() =>
folder.Type === "Folder" && handleSelect(folder)
}
>
<div className="flex items-center gap-2">
{folder.Type === "Folder" ? (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="w-[1.4rem] h-[1.4rem] fill-current op-text-secondary"
>
<path d="M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z" />
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512"
className="w-[1.4rem] h-[1.4rem] fill-current op-text-primary"
>
<path d="M374.629 150.627L233.371 9.373C227.371 3.371 219.23 0 210.746 0H64C28.652 0 0 28.652 0 64V448C0 483.345 28.652 512 64 512H320C355.348 512 384 483.345 384 448V173.254C384 164.767 380.629 156.629 374.629 150.627ZM224 22.629L361.375 160H248C234.781 160 224 149.234 224 136V22.629ZM368 448C368 474.467 346.469 496 320 496H64C37.531 496 16 474.467 16 448V64C16 37.533 37.531 16 64 16H208V136C208 158.062 225.938 176 248 176H368V448ZM96 264C96 268.406 99.594 272 104 272H280C284.406 272 288 268.406 288 264S284.406 256 280 256H104C99.594 256 96 259.594 96 264ZM280 320H104C99.594 320 96 323.594 96 328S99.594 336 104 336H280C284.406 336 288 332.406 288 328S284.406 320 280 320ZM280 384H104C99.594 384 96 387.594 96 392S99.594 400 104 400H280C284.406 400 288 396.406 288 392S284.406 384 280 384Z" />
</svg>
)}
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
</div>
))}
))
: !isLoader && (
<div className="text-base-content text-center my-2">
No data found
</div>
)}
</div>
{isAdd && (
<CreateFolder
@@ -281,8 +296,8 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
<div className="flex justify-center my-4">
<i className="fa-light fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
@@ -296,12 +311,12 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
>
{isAdd ? (
<>
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
<span className="text-xs">Back</span>
</>
) : (
<>
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
<span className="">Add folder</span>
</>
)}
@@ -311,7 +326,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>Save here
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
</div>
</div>
</ModalUi>
@@ -167,7 +167,7 @@ const SignersInput = (props) => {
}}
className="cursor-pointer op-input op-input-bordered focus:outline-none hover:border-base-content max-h-[38px] min-w-[48px] flex justify-center items-center"
>
<i className="fas fa-plus"></i>
<i className="fa-light fa-plus"></i>
</div>
<AddSignerModal isOpen={modalIsOpen}>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
+31 -12
View File
@@ -1,18 +1,18 @@
import React, { useState, useEffect } from "react";
import Menu from "./Menu";
import Submenu from "./SubMenu";
import SocialMedia from "./SocialMedia";
import Parse from "parse";
import dp from "../../assets/images/dp.png";
import sidebarList from "../../json/menuJson";
const Sidebar = ({ isOpen, closeSidebar }) => {
const [menuList, setmenuList] = useState([]);
const [submenuOpen, setSubmenuOpen] = useState(false);
let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp;
const tenantname = localStorage.getItem("TenantName");
const tenantname = localStorage.getItem("Extand_Class")
? JSON.parse(localStorage.getItem("Extand_Class"))?.[0]?.Company
: "";
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
@@ -22,13 +22,32 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
const menuItem = async () => {
try {
var sideMenu = Parse.Object.extend("w_menu");
var query = new Parse.Query(sideMenu);
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
const results = await query.first();
const resultjson = results.toJSON();
let result = resultjson;
setmenuList(result.menuItems);
if (localStorage.getItem("defaultmenuid")) {
const menuId = localStorage.getItem("defaultmenuid") !== "VPh91h0ZHk";
if (menuId) {
setmenuList(sidebarList);
} else {
const addUserForm = {
icon: "fa-light fa-user",
title: "Add User",
target: "_self",
pageType: "form",
description: "",
objectId: "lM0xRnM3iE"
};
const newSidebarList = sidebarList.map((item) => {
if (item.title === "Settings") {
// Make a shallow copy of the item
const newItem = { ...item };
// Insert addUserForm at the second position
newItem.children.splice(1, 0, addUserForm);
return newItem;
}
return item;
});
setmenuList(newSidebarList);
}
}
} catch (e) {
console.error("Problem", e);
}
@@ -44,7 +63,7 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
};
return (
<aside
className={`absolute md:relative bg-base-100 h-screen overflow-y-auto transition-all z-[100] hide-scrollbar
className={`absolute lg:relative bg-base-100 h-screen overflow-y-auto transition-all z-[100] shadow-lg hide-scrollbar
${isOpen ? "w-full md:w-[300px]" : "w-0"}`}
>
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
@@ -18,8 +18,8 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
<i
className={`${
submenuOpen[item.title]
? "fa-solid fa-angle-down"
: "fa-solid fa-angle-right"
? "fa-light fa-angle-down"
: "fa-light fa-angle-right"
}`}
aria-hidden="true"
></i>
+311 -282
View File
@@ -8,7 +8,10 @@ import { appInfo } from "./appinfo";
import { saveAs } from "file-saver";
import printModule from "print-js";
export const fontsizeArr = [7, 8, 9, 10, 11, 12, 13, 14, 15, 18];
export const fontColorArr = ["red", "black", "blue", "yellow"];
export const isMobile = window.innerWidth < 767;
export const isTabAndMobile = window.innerWidth < 1023;
export const textInputWidget = "text input";
export const textWidget = "text";
export const radioButtonWidget = "radio button";
@@ -157,9 +160,7 @@ export const getDrive = async (documentId, skip = 0, limit = 100) => {
// `pdfNewWidthFun` function is used to calculate pdf width to render in middle container
export const pdfNewWidthFun = (divRef) => {
const clientWidth = divRef.current.offsetWidth;
const pdfWidth = clientWidth - 160 - 200;
//160 is width of left side, 200 is width of right side component
const pdfWidth = divRef.current.offsetWidth;
return pdfWidth;
};
@@ -199,15 +200,12 @@ export const handleImageResize = (
signerPos,
setSignerPos,
pageNumber,
containerScale,
scale,
signerId,
showResize
) => {
// const filterSignerPos = signerPos.filter(
// (data) => data.signerObjId === signerId
// );
const filterSignerPos = signerPos.filter((data) => data.Id === signerId);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
@@ -220,8 +218,8 @@ export const handleImageResize = (
if (url.key === key) {
return {
...url,
Width: ref.offsetWidth,
Height: ref.offsetHeight,
Width: ref.offsetWidth / (containerScale * scale),
Height: ref.offsetHeight / (containerScale * scale),
IsResize: showResize ? true : false
};
}
@@ -250,72 +248,72 @@ export const handleImageResize = (
export const widgets = [
{
type: "signature",
icon: "fa-solid fa-pen-nib",
icon: "fa-light fa-pen-nib",
iconSize: "20px"
},
{
type: "stamp",
icon: "fa-solid fa-stamp",
icon: "fa-light fa-stamp",
iconSize: "19px"
},
{
type: "initials",
icon: "fa-solid fa-signature",
icon: "fa-light fa-signature",
iconSize: "15px"
},
{
type: "name",
icon: "fa-solid fa-user",
icon: "fa-light fa-user",
iconSize: "21px"
},
{
type: "job title",
icon: "fa-solid fa-address-card",
icon: "fa-light fa-address-card",
iconSize: "17px"
},
{
type: "company",
icon: "fa-solid fa-building",
icon: "fa-light fa-building",
iconSize: "25px"
},
{
type: "date",
icon: "fa-solid fa-calendar-days",
icon: "fa-light fa-calendar-days",
iconSize: "20px"
},
{
type: textWidget,
icon: "fa-solid fa-text-width",
icon: "fa-light fa-text-width",
iconSize: "20px"
},
{
type: textInputWidget,
icon: "fa-solid fa-font",
icon: "fa-light fa-font",
iconSize: "21px"
},
{
type: "checkbox",
icon: "fa-solid fa-square-check",
icon: "fa-light fa-square-check",
iconSize: "22px"
},
{
type: "dropdown",
icon: "fa-solid fa-circle-chevron-down",
icon: "fa-light fa-circle-chevron-down",
iconSize: "19px"
},
{
type: radioButtonWidget,
icon: "fa-regular fa-circle-dot",
icon: "fa-light fa-circle-dot",
iconSize: "20px"
},
{
type: "image",
icon: "fa-solid fa-image",
icon: "fa-light fa-image",
iconSize: "20px"
},
{
type: "email",
icon: "fa-solid fa-envelope",
icon: "fa-light fa-envelope",
iconSize: "20px"
}
];
@@ -378,11 +376,11 @@ export const addWidgetOptions = (type) => {
};
export const getWidgetType = (item) => {
return (
<div className="op-btn op-btn-primary op-btn-outline op-btn-sm focus:outline-none outline outline-[1.5px] w-fit md:w-[150px] ml-[6px] md:ml-0 p-0 overflow-hidden">
<div className="op-btn w-fit md:w-[100%] op-btn-primary op-btn-outline op-btn-sm focus:outline-none outline outline-[1.5px] ml-[6px] md:ml-0 p-0 overflow-hidden">
<div className="w-full h-full flex md:justify-between items-center">
<div className="flex justify-start items-center text-[13px] ml-1">
{!isMobile && <i className="fa-sharp fa-solid fa-grip-vertical"></i>}
<span className="text-center text-[15px] ml-[5px] font-semibold">
<span className="md:inline-block text-center text-[15px] ml-[5px] font-semibold pr-1 md:pr-0">
{item.type}
</span>
</div>
@@ -421,7 +419,7 @@ export const defaultWidthHeight = (type) => {
case "email":
return { width: 150, height: 20 };
case radioButtonWidget:
return { width: 15, height: 30 };
return { width: 5, height: 10 };
case textWidget:
return { width: 150, height: 17 };
default:
@@ -493,7 +491,9 @@ export const handleSignYourselfImageResize = (
key,
xyPostion,
setXyPostion,
index
index,
containerScale,
scale
) => {
const getXYdata = xyPostion[index].pos;
const getPosData = getXYdata;
@@ -501,8 +501,8 @@ export const handleSignYourselfImageResize = (
if (url.key === key) {
return {
...url,
Width: ref.offsetWidth,
Height: ref.offsetHeight,
Width: ref.offsetWidth / (scale * containerScale),
Height: ref.offsetHeight / (scale * containerScale),
IsResize: true
};
}
@@ -1005,7 +1005,7 @@ export const addInitialData = (signerPos, setXyPostion, value, userId) => {
};
//calculate width and height
export const calculateInitialWidthHeight = (type, widgetData) => {
export const calculateInitialWidthHeight = (widgetData) => {
const intialText = widgetData;
const span = document.createElement("span");
span.textContent = intialText;
@@ -1178,7 +1178,6 @@ export const onImageSelect = (event, setImgWH, setImage) => {
setImage({ src: image.src, imgType: imageType });
};
};
//convert https url to base64
export const fetchImageBase64 = async (imageUrl) => {
try {
@@ -1225,15 +1224,16 @@ export const changeImageWH = async (base64Image) => {
//function for embed multiple signature using pdf-lib
export const multiSignEmbed = async (
pngUrl,
xyPositionArray,
pdfDoc,
pdfOriginalWidth,
pdfOriginalWH,
signyourself,
containerWH
scale
) => {
for (let item of pngUrl) {
for (let item of xyPositionArray) {
const typeExist = item.pos.some((data) => data?.type);
let updateItem;
if (typeExist) {
if (signyourself) {
updateItem = item.pos;
@@ -1245,15 +1245,13 @@ export const multiSignEmbed = async (
} else {
updateItem = item.pos;
}
const newWidth = containerWH.width;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const pageNo = item.pageNumber;
const imgUrlList = updateItem;
const widgetsPositionArr = updateItem;
const pages = pdfDoc.getPages();
const form = pdfDoc.getForm();
const page = pages[pageNo - 1];
const images = await Promise.all(
imgUrlList.map(async (url) => {
widgetsPositionArr.map(async (url) => {
let signUrl = url.SignUrl && url.SignUrl;
if (signUrl) {
if (url.ImageType === "image/png") {
@@ -1261,17 +1259,13 @@ export const multiSignEmbed = async (
const newUrl = await convertPNGtoJPEG(signUrl);
signUrl = newUrl;
}
// const checkUrl = urlValidator(signUrl);
// if (checkUrl) {
// signUrl = signUrl + "?get";
// }
const res = await fetch(signUrl);
return res.arrayBuffer();
}
})
);
imgUrlList.forEach(async (position, id) => {
widgetsPositionArr.forEach(async (position, id) => {
let img;
if (["signature", "stamp", "initials", "image"].includes(position.type)) {
if (
@@ -1292,110 +1286,48 @@ export const multiSignEmbed = async (
img = await pdfDoc.embedPng(images[id]);
}
}
let scaleWidth, scaleHeight;
scaleWidth = placeholderWidth(position, scale, signyourself);
scaleHeight = placeholderHeight(position, scale, signyourself);
const xPos = (pos) => {
const resizePos = pos.xPosition;
if (signyourself) {
if (isMobile) {
return resizePos * scale;
} else {
return resizePos;
}
let widgetWidth, widgetHeight;
widgetWidth = placeholderWidth(
position,
scale,
signyourself,
pdfOriginalWH,
scale
);
widgetHeight = placeholderHeight(
position,
scale,
signyourself,
pdfOriginalWH.height,
scale
);
const xPos = (position) => {
const resizePos = position.xPosition;
//first two condition handle to old data already saved from mobile view which scale point diffrent
if (isMobile && position.isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
const x = resizePos * (position.scale / scale);
return x * scale;
} else if (position.isMobile && position.scale) {
const x = resizePos * position.scale;
return x;
} else {
//checking both condition mobile and desktop view
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (pos.isMobile) {
const x = resizePos * (pos.scale / scale);
return x * scale;
} else {
const x = resizePos / scale;
return x * scale;
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
const x = resizePos * pos.scale;
return x;
} else {
return resizePos;
}
}
return resizePos;
}
};
const yPos = (position) => {
const resizePos = position.yPosition;
const yPos = (pos, ind, labelDefaultHeight) => {
const resizePos = pos.yPosition;
let newUpdateHeight = labelDefaultHeight
? labelDefaultHeight
: scaleHeight;
const widgetHeight =
position.type === radioButtonWidget
? 10
: position.type === "checkbox"
? 10
: newUpdateHeight;
const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight;
if (signyourself) {
if (isMobile) {
if (ind && ind > 0 && position.type === "checkbox") {
return page.getHeight() - resizePos * scale - newHeight;
} else if (!ind && position.type === "checkbox") {
return page.getHeight() - resizePos * scale - 10;
} else {
return page.getHeight() - resizePos * scale - newHeight;
}
// return page.getHeight() - resizePos * scale - scaleHeight;
if (position.isMobile && position.scale) {
if (position.IsResize) {
const y = resizePos * position.scale;
return y;
} else {
if (ind && ind > 0 && position.type === "checkbox") {
return page.getHeight() - resizePos - newHeight;
} else if (!ind && position.type === "checkbox") {
return page.getHeight() - resizePos - 10;
} else {
return page.getHeight() - resizePos - newHeight;
}
// return page.getHeight() - resizePos - scaleHeight;
const y = resizePos * position.scale;
return y;
}
} else {
//checking both condition mobile and desktop view
const y = resizePos / scale;
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (pos.isMobile) {
const y = resizePos * (pos.scale / scale);
return page.getHeight() - y * scale - newUpdateHeight;
} else {
if (pos.IsResize) {
return page.getHeight() - y * scale - newUpdateHeight;
} else {
return page.getHeight() - y * scale - newUpdateHeight;
}
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
if (pos.IsResize) {
const y = resizePos * pos.scale;
return page.getHeight() - y - newUpdateHeight;
} else {
const y = resizePos * pos.scale;
return page.getHeight() - y - newUpdateHeight;
}
} else {
if (ind && ind > 0 && position.type === "checkbox") {
return page.getHeight() - resizePos - newHeight;
} else if (position.type === "checkbox") {
return page.getHeight() - resizePos - 10;
} else {
return page.getHeight() - resizePos - newHeight;
}
}
}
return resizePos;
}
};
const widgetTypeExist = [
@@ -1408,14 +1340,16 @@ export const multiSignEmbed = async (
"email"
].includes(position.type);
if (position.type === "checkbox") {
let addYPosition = 0,
isCheck;
const font = await pdfDoc.embedFont("Helvetica");
let checkboxOptionGapFromTop, isCheck;
let y = yPos(position);
const optionsFontSize = 13;
const checkboxSize = 18;
const checkboxTextGapFromLeft = 22;
if (position?.options?.values.length > 0) {
position?.options?.values.forEach((item, ind) => {
const checkboxRandomId = "checkbox" + randomId();
let yPosition;
const height = 13;
if (
position?.options?.response &&
position?.options?.response?.length > 0
@@ -1426,27 +1360,38 @@ export const multiSignEmbed = async (
}
const checkbox = form.createCheckBox(checkboxRandomId);
if (ind > 0) {
yPosition = yPos(position, ind) - addYPosition;
addYPosition = addYPosition + height + 8;
y = y + checkboxOptionGapFromTop;
} else {
yPosition = yPos(position, ind);
addYPosition = height + 8;
checkboxOptionGapFromTop = 26;
}
if (!position?.options?.isHideLabel) {
// below line of code is used to embed label with radio button in pdf
page.drawText(item, {
x: xPos(position) + 17,
y: yPosition + 2,
size: height
});
const optionsPosition = compensateRotation(
page.getRotation().angle,
xPos(position) + checkboxTextGapFromLeft,
y,
1,
page.getSize(),
optionsFontSize,
rgb(0, 0, 0),
font,
page
);
page.drawText(item, optionsPosition);
}
checkbox.addToPage(page, {
let checkboxObj = {
x: xPos(position),
y: yPosition - 3,
width: height,
height: height
});
y: y,
width: checkboxSize,
height: checkboxSize
};
checkboxObj = getImagePosition(page, checkboxObj, 1);
checkbox.addToPage(page, checkboxObj);
//applied which checkbox should be checked
if (isCheck) {
checkbox.check();
} else {
@@ -1457,14 +1402,27 @@ export const multiSignEmbed = async (
}
} else if (widgetTypeExist) {
const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 12;
const fontSize = parseInt(position?.options?.fontSize) || 12;
const color = position?.options?.fontColor;
let updateColorInRgb;
if (color === "red") {
updateColorInRgb = rgb(1, 0, 0);
} else if (color === "black") {
updateColorInRgb = rgb(0, 0, 0);
} else if (color === "blue") {
updateColorInRgb = rgb(0, 0, 1);
} else if (color === "yellow") {
updateColorInRgb = rgb(0.9, 1, 0);
} else {
updateColorInRgb = rgb(0, 0, 0);
}
let textContent;
if (position?.options?.response) {
textContent = position.options?.response;
} else if (position?.options?.defaultValue) {
textContent = position?.options?.defaultValue;
}
const fixedWidth = scaleWidth; // Set your fixed width
const fixedWidth = widgetWidth; // Set your fixed width
const isNewOnEnterLineExist = textContent.includes("\n");
// Function to break text into lines based on the fixed width
@@ -1517,21 +1475,23 @@ export const multiSignEmbed = async (
? breakTextIntoLines(textContent, fixedWidth)
: NewbreakTextIntoLines(textContent, fixedWidth);
// Set initial y-coordinate for the first line
const labelDefaultHeight = defaultWidthHeight(position.type).height;
let y = yPos(position, null, labelDefaultHeight) + 10;
let x = xPos(position);
//xPos(position)
let y = yPos(position);
// Embed each line on the page
for (const line of lines) {
page.drawText(line, {
x: x,
const textPosition = compensateRotation(
page.getRotation().angle,
x,
y,
1,
page.getSize(),
fontSize,
updateColorInRgb,
font,
color: rgb(0, 0, 0),
size: fontSize
});
y -= 18; // Adjust the line height as needed
page
);
page.drawText(line, textPosition);
y += 18; // Adjust the line height as needed
}
} else if (position.type === "dropdown") {
const dropdownRandomId = "dropdown" + randomId();
@@ -1542,65 +1502,82 @@ export const multiSignEmbed = async (
} else if (position?.options?.defaultValue) {
dropdown.select(position?.options?.defaultValue);
}
dropdown.addToPage(page, {
const dropdownObj = {
x: xPos(position),
y: yPos(position),
width: scaleWidth,
height: scaleHeight,
borderWidth: 0
});
width: widgetWidth,
height: widgetHeight
};
const dropdownOption = getImagePosition(page, dropdownObj, 1);
// page.drawImage(img, imageOptions);
dropdown.addToPage(page, dropdownOption);
dropdown.enableReadOnly();
} else if (position.type === radioButtonWidget) {
const font = await pdfDoc.embedFont("Helvetica");
const radioRandomId = "radio" + randomId();
const radioGroup = form.createRadioGroup(radioRandomId);
let addYPosition = 18;
let radioOptionGapFromTop;
const optionsFontSize = 16;
const radioTextGapFromLeft = 20;
const radioSize = 18;
let y = yPos(position);
if (position?.options?.values.length > 0) {
position?.options?.values.forEach((item, ind) => {
if (ind > 0) {
y = y + radioOptionGapFromTop;
} else {
radioOptionGapFromTop = 25;
}
if (!position?.options?.isHideLabel) {
// below line of code is used to embed label with radio button in pdf
for (let i = 1; i <= position?.options?.values.length; i++) {
const data = position?.options?.values[i - 1];
let yPosition;
if (i > 1) {
yPosition = yPos(position) - addYPosition;
} else {
yPosition = yPos(position);
}
const optionsPosition = compensateRotation(
page.getRotation().angle,
xPos(position) + radioTextGapFromLeft,
y,
1,
page.getSize(),
optionsFontSize,
rgb(0, 0, 0),
font,
page
);
if (!position?.options?.isHideLabel) {
// below line of code is used to embed label with radio button in pdf
page.drawText(data, {
x: xPos(position) + 15,
y: yPosition + 2,
size: 11
});
}
radioGroup.addOptionToPage(data, page, {
x: xPos(position),
y: yPosition,
width: 11,
height: 11
page.drawText(item, optionsPosition);
}
let radioObj = {
x: xPos(position),
y: y,
width: radioSize,
height: radioSize
};
radioObj = getImagePosition(page, radioObj, 1);
radioGroup.addOptionToPage(item, page, radioObj);
});
if (i > 1) {
addYPosition = addYPosition + 18;
}
}
if (position?.options?.response) {
radioGroup.select(position.options?.response);
} else if (position?.options?.defaultValue) {
radioGroup.select(position?.options?.defaultValue);
}
radioGroup.enableReadOnly();
} else {
page.drawImage(img, {
const signature = {
x: xPos(position),
y: yPos(position),
width: scaleWidth,
height: scaleHeight
});
width: widgetWidth,
height: widgetHeight
};
const imageOptions = getImagePosition(page, signature, 1);
page.drawImage(img, imageOptions);
}
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
// console.log("pdf", pdfBytes);
return pdfBytes;
};
@@ -1613,90 +1590,38 @@ export function urlValidator(url) {
return false;
}
}
export const placeholderWidth = (pos, scale, signyourself) => {
let width;
//calculate placeholder width to embed in pdf
export const placeholderWidth = (pos) => {
const defaultWidth = defaultWidthHeight(pos.type).width;
const posWidth = pos.Width ? pos.Width : defaultWidth;
const posWidth = pos.Width || defaultWidth;
if (signyourself) {
if (isMobile) {
return posWidth * scale;
} else {
//condition to handle old data saved from mobile view to get widthh
if (pos.isMobile && pos.scale) {
if (pos.IsResize) {
return posWidth;
} else {
return posWidth * pos.scale;
}
} else {
if (isMobile) {
if (pos.isMobile) {
width = posWidth ? posWidth * scale : defaultWidth * scale;
return width;
} else {
if (pos.IsResize) {
width = posWidth ? posWidth * scale : defaultWidth * scale;
return width;
} else {
width = posWidth ? posWidth : defaultWidth;
return width;
}
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
width = posWidth ? posWidth : defaultWidth;
return width;
} else {
width = posWidth ? posWidth * pos.scale : defaultWidth * pos.scale;
return width;
}
} else {
width = posWidth ? posWidth : defaultWidth;
return width;
}
}
return posWidth;
}
};
export const placeholderHeight = (pos, scale, signyourself) => {
let height;
//calculate placeholder height to embed in pdf
export const placeholderHeight = (pos) => {
const posHeight = pos.Height;
const defaultHeight = defaultWidthHeight(pos.type).height;
if (signyourself) {
if (isMobile) {
return posHeight ? posHeight * scale : defaultHeight * scale;
const posUpdateHeight = posHeight || defaultHeight;
//condition to handle old data saved from mobile view to get height
if (pos.isMobile && pos.scale) {
if (pos.IsResize) {
return posUpdateHeight;
} else {
return posHeight ? posHeight : defaultHeight;
return posUpdateHeight * pos.scale;
}
} else {
if (isMobile) {
if (pos.isMobile) {
height = posHeight ? posHeight * scale : defaultHeight * scale;
return height;
} else {
if (pos.IsResize) {
height = posHeight ? posHeight * scale : defaultHeight * scale;
return height;
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
height = posHeight ? posHeight : defaultHeight;
return height;
} else {
height = posHeight
? posHeight * pos.scale
: defaultHeight * pos.scale;
return height;
}
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
}
return posUpdateHeight;
}
};
@@ -2001,7 +1926,6 @@ export const convertPdfArrayBuffer = async (url) => {
return "Error";
}
};
//`handleSendOTP` function is used to send otp on user's email using `SendOTPMailV1` cloud function
export const handleSendOTP = async (email) => {
try {
@@ -2163,3 +2087,108 @@ export async function findContact(value) {
console.error("Error fetching suggestions:", error);
}
}
// `compensateRotation` is used to calculate x and y position of widget on portait, landscape pdf for pdf-lib
function compensateRotation(
pageRotation,
x,
y,
scale,
dimensions,
fontSize,
updateColorInRgb,
font,
page
) {
let rotationRads = (pageRotation * Math.PI) / 180;
//These coords are now from bottom/left
let coordsFromBottomLeft = { x: x / scale };
if (pageRotation === 90 || pageRotation === 270) {
coordsFromBottomLeft.y = dimensions.width - (y + fontSize) / scale;
} else {
coordsFromBottomLeft.y = dimensions.height - (y + fontSize) / scale;
}
let drawX = null;
let drawY = null;
if (pageRotation === 90) {
drawX =
coordsFromBottomLeft.x * Math.cos(rotationRads) -
coordsFromBottomLeft.y * Math.sin(rotationRads) +
dimensions.width;
drawY =
coordsFromBottomLeft.x * Math.sin(rotationRads) +
coordsFromBottomLeft.y * Math.cos(rotationRads);
} else if (pageRotation === 180) {
drawX =
coordsFromBottomLeft.x * Math.cos(rotationRads) -
coordsFromBottomLeft.y * Math.sin(rotationRads) +
dimensions.width;
drawY =
coordsFromBottomLeft.x * Math.sin(rotationRads) +
coordsFromBottomLeft.y * Math.cos(rotationRads) +
dimensions.height;
} else if (pageRotation === 270) {
drawX =
coordsFromBottomLeft.x * Math.cos(rotationRads) -
coordsFromBottomLeft.y * Math.sin(rotationRads);
drawY =
coordsFromBottomLeft.x * Math.sin(rotationRads) +
coordsFromBottomLeft.y * Math.cos(rotationRads) +
dimensions.height;
} else {
//no rotation
drawX = coordsFromBottomLeft.x;
drawY = coordsFromBottomLeft.y;
}
if (font) {
return {
x: drawX,
y: drawY,
font,
color: updateColorInRgb,
size: fontSize,
rotate: page.getRotation()
};
} else {
return { x: drawX, y: drawY };
}
}
// `getImagePosition` is used to calulcate position of image type widget like x, y, width, height for pdf-lib
function getImagePosition(page, image, sizeRatio) {
let pageWidth;
// pageHeight;
if ([90, 270].includes(page.getRotation().angle)) {
pageWidth = page.getHeight();
} else {
pageWidth = page.getWidth();
}
// eslint-disable-next-line
if (!image?.hasOwnProperty("vpWidth")) {
image["vpWidth"] = pageWidth;
}
const pageRatio = pageWidth / (image.vpWidth * sizeRatio);
const imageWidth = image.width * sizeRatio * pageRatio;
const imageHeight = image.height * sizeRatio * pageRatio;
const imageX = image.x * sizeRatio * pageRatio;
const imageYFromTop = image.y * sizeRatio * pageRatio;
const correction = compensateRotation(
page.getRotation().angle,
imageX,
imageYFromTop,
1,
page.getSize(),
imageHeight
);
return {
width: imageWidth,
height: imageHeight,
x: correction.x,
y: correction.y,
rotate: page.getRotation()
};
}
+31 -31
View File
@@ -15,7 +15,7 @@ export default function reportJson(id) {
btnId: "1231",
hoverLabel: "Edit",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-pen",
btnIcon: "fa-light fa-pen",
redirectUrl: "draftDocument",
action: "redirect"
},
@@ -23,7 +23,7 @@ export default function reportJson(id) {
btnId: "2142",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -42,7 +42,7 @@ export default function reportJson(id) {
btnLabel: "sign",
hoverLabel: "Sign",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-signature",
btnIcon: "fa-light fa-signature",
redirectUrl: "pdfRequestFiles",
action: "redirect"
}
@@ -60,7 +60,7 @@ export default function reportJson(id) {
btnId: "8901",
hoverLabel: "Share",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-share",
btnIcon: "fa-light fa-share",
redirectUrl: "",
action: "share"
},
@@ -68,7 +68,7 @@ export default function reportJson(id) {
btnId: "1588",
hoverLabel: "View",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-eye",
btnIcon: "fa-light fa-eye",
redirectUrl: "pdfRequestFiles",
action: "redirect"
},
@@ -77,14 +77,14 @@ export default function reportJson(id) {
hoverLabel: "option",
btnColor: "",
textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
action: "option",
subaction: [
{
btnId: "1630",
btnLabel: "Resend",
hoverLabel: "Resend",
btnIcon: "fa-solid fa-envelope",
btnIcon: "fa-light fa-envelope",
redirectUrl: "",
action: "resend"
},
@@ -92,7 +92,7 @@ export default function reportJson(id) {
btnId: "1688",
btnLabel: "Revoke",
hoverLabel: "Revoke",
btnIcon: "fa-solid fa-file-circle-xmark",
btnIcon: "fa-light fa-file-circle-xmark",
redirectUrl: "",
action: "revoke"
},
@@ -100,7 +100,7 @@ export default function reportJson(id) {
btnId: "1488",
btnLabel: "Delete",
hoverLabel: "Delete",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -120,7 +120,7 @@ export default function reportJson(id) {
btnId: "1378",
hoverLabel: "Edit",
btnColor: "op-btn-primary",
btnIcon: "fa fa-eye",
btnIcon: "fa-light fa-eye",
redirectUrl: "draftDocument",
action: "redirect"
},
@@ -128,7 +128,7 @@ export default function reportJson(id) {
btnId: "1278",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -146,7 +146,7 @@ export default function reportJson(id) {
btnId: "1458",
hoverLabel: "View",
btnColor: "op-btn-primary",
btnIcon: "fa fa-eye",
btnIcon: "fa-light fa-eye",
redirectUrl: "draftDocument",
action: "redirect"
},
@@ -154,7 +154,7 @@ export default function reportJson(id) {
btnId: "1358",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -172,7 +172,7 @@ export default function reportJson(id) {
btnId: "1898",
hoverLabel: "View",
btnColor: "op-btn-primary",
btnIcon: "fa fa-eye",
btnIcon: "fa-light fa-eye",
redirectUrl: "draftDocument",
action: "redirect"
},
@@ -180,7 +180,7 @@ export default function reportJson(id) {
btnId: "1998",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -198,7 +198,7 @@ export default function reportJson(id) {
btnId: "1999",
hoverLabel: "Share",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-share",
btnIcon: "fa-light fa-share",
redirectUrl: "",
action: "share"
},
@@ -206,7 +206,7 @@ export default function reportJson(id) {
btnId: "1999",
hoverLabel: "View",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-eye",
btnIcon: "fa-light fa-eye",
redirectUrl: "pdfRequestFiles",
action: "redirect"
},
@@ -215,14 +215,14 @@ export default function reportJson(id) {
hoverLabel: "option",
btnColor: "",
textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
action: "option",
subaction: [
{
btnId: "1631",
btnLabel: "Resend",
hoverLabel: "Resend",
btnIcon: "fa-solid fa-envelope",
btnIcon: "fa-light fa-envelope",
redirectUrl: "",
action: "resend"
},
@@ -230,7 +230,7 @@ export default function reportJson(id) {
btnId: "6788",
btnLabel: "Revoke",
hoverLabel: "Revoke",
btnIcon: "fa-solid fa-file-circle-xmark",
btnIcon: "fa-light fa-file-circle-xmark",
redirectUrl: "",
action: "revoke"
},
@@ -238,7 +238,7 @@ export default function reportJson(id) {
btnId: "2000",
btnLabel: "Delete",
hoverLabel: "Delete",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -257,7 +257,7 @@ export default function reportJson(id) {
btnLabel: "sign",
hoverLabel: "Sign",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-signature",
btnIcon: "fa-light fa-signature",
redirectUrl: "pdfRequestFiles",
action: "redirect"
}
@@ -273,7 +273,7 @@ export default function reportJson(id) {
btnId: "2003",
hoverLabel: "Edit",
btnColor: "op-btn-primary",
btnIcon: "fa-solid fa-pen",
btnIcon: "fa-light fa-pen",
redirectUrl: "draftDocument",
action: "redirect"
},
@@ -281,7 +281,7 @@ export default function reportJson(id) {
btnId: "2004",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
@@ -296,8 +296,8 @@ export default function reportJson(id) {
{
btnId: "2204",
hoverLabel: "Delete",
btnColor: "op-btn-outline op-btn-error",
btnIcon: "fa-solid fa-trash",
btnColor: "op-btn-secondary",
btnIcon: "fa-light fa-trash",
action: "delete"
}
],
@@ -316,7 +316,7 @@ export default function reportJson(id) {
btnLabel: "Use",
hoverLabel: "Use",
btnColor: "op-btn-primary",
btnIcon: "fa fa-plus",
btnIcon: "fa-light fa-plus",
redirectUrl: "placeHolderSign",
action: "redirect",
selector: "reactourSecond",
@@ -328,7 +328,7 @@ export default function reportJson(id) {
btnLabel: "Quick send",
hoverLabel: "Quick send",
btnColor: "op-btn-secondary",
btnIcon: "fa-solid fa-envelope",
btnIcon: "fa-light fa-envelope",
redirectUrl: "",
action: "bulksend",
selector: "tourbulksend",
@@ -340,7 +340,7 @@ export default function reportJson(id) {
hoverLabel: "option",
btnColor: "",
textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
action: "option",
selector: "reactourThird",
message:
@@ -350,7 +350,7 @@ export default function reportJson(id) {
btnId: "2434",
btnLabel: "Edit",
hoverLabel: "Edit",
btnIcon: "fa-solid fa-pen",
btnIcon: "fa-light fa-pen",
redirectUrl: "template",
action: "redirect"
},
@@ -358,7 +358,7 @@ export default function reportJson(id) {
btnId: "1834",
btnLabel: "Delete",
hoverLabel: "Delete",
btnIcon: "fa fa-trash",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
+2 -2
View File
@@ -6,7 +6,7 @@ const dashboardJson = [
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-signature",
icon: "fa-light fa-signature",
bgColor: "bg-[#f0058e]",
label: "Need your Signature",
description: null,
@@ -29,7 +29,7 @@ const dashboardJson = [
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-sign-out-alt",
icon: "fa-light fa-sign-out-alt",
bgColor: "bg-[#2ed8b6]",
label: "Out for signatures",
description: null,
+161
View File
@@ -0,0 +1,161 @@
const sidebarList = [
{
icon: "fa-light fa-tachometer-alt",
title: "Dashboard",
target: "",
pageType: "dashboard",
description: "",
objectId: "35KBoSgoAK"
},
{
icon: "fa-light fa-pen-nib",
title: "Sign yourself",
target: "_self",
pageType: "form",
description: "",
objectId: "sHAnZphf69"
},
{
icon: "fa-light fa-paper-plane",
title: "Request signatures",
target: "_self",
pageType: "form",
description: "",
objectId: "8mZzFxbG1z"
},
{
icon: "fa-light fa-newspaper",
title: "Templates",
target: "_self",
pageType: null,
description: null,
objectId: null,
children: [
{
icon: "fa-light fa-file-signature",
title: "Create template",
target: "_self",
pageType: "form",
description: "",
objectId: "template"
},
{
icon: "fa-light fa-file-contract",
title: "Manage templates",
target: "_self",
pageType: "report",
description: "",
objectId: "6TeaPr321t"
}
]
},
{
icon: "fa-light fa-folder",
title: "OpenSign™ Drive",
target: "_self",
pageType: "",
description: "",
objectId: "opensigndrive"
},
{
icon: "fa-light fa-address-card",
title: "Reports",
target: "_self",
pageType: null,
description: "",
objectId: null,
children: [
{
icon: "fa-light fa-signature",
title: "Need your sign",
target: "_self",
pageType: "report",
description: "",
objectId: "4Hhwbp482K"
},
{
icon: "fa-light fa-tasks",
title: "In Progress",
target: "_self",
pageType: "report",
description: "",
objectId: "1MwEuxLEkF"
},
{
icon: "fa-light fa-check-circle",
title: "Completed",
target: "_self",
pageType: "report",
description: "",
objectId: "kQUoW4hUXz"
},
{
icon: "fa-light fa-edit",
title: "Drafts",
target: "_self",
pageType: "report",
description: "",
objectId: "ByHuevtCFY"
},
{
icon: "fa-light fa-times-circle",
title: "Declined",
target: "_self",
pageType: "report",
description: "",
objectId: "UPr2Fm5WY3"
},
{
icon: "fa-light fa-hourglass-end",
title: "Expired",
target: "_self",
pageType: "report",
description: "",
objectId: "zNqBHXHsYH"
},
{
icon: "fa-light fa-address-book",
title: "Contactbook",
target: "_self",
pageType: "report",
description: "",
objectId: "5KhaPr482K"
}
]
},
{
icon: "fa-light fa-cog",
title: "Settings",
target: "_self",
pageType: null,
description: "",
objectId: null,
children: [
{
icon: "fa-light fa-pen-fancy",
title: "My Signature",
target: "_self",
pageType: "",
description: "",
objectId: "managesign"
},
{
icon: "fa-light fa-key",
title: "API Token",
target: "_self",
pageType: "generatetoken",
description: "",
objectId: ""
},
{
icon: "fa-light fa-globe",
title: "Webhook",
target: "_self",
pageType: "webhook",
description: "",
objectId: ""
}
]
}
];
export default sidebarList;
+5 -2
View File
@@ -5,7 +5,7 @@ import Sidebar from "../components/sidebar/Sidebar";
import { useWindowSize } from "../hook/useWindowSize";
import Tour from "reactour";
import axios from "axios";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import Parse from "parse";
import ModalUi from "../primitives/ModalUi";
import { useNavigate, useLocation, Outlet } from "react-router-dom";
@@ -13,10 +13,12 @@ import { isEnableSubscription } from "../constant/const";
import { useCookies } from "react-cookie";
import { fetchSubscription } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { showHeader } from "../redux/reducers/showHeader";
const HomeLayout = () => {
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
const { width } = useWindowSize();
const [isOpen, setIsOpen] = useState(true);
const arr = useSelector((state) => state.TourSteps);
@@ -98,6 +100,7 @@ const HomeLayout = () => {
}
const showSidebar = () => {
setIsOpen((value) => !value);
dispatch(showHeader(!isOpen));
};
useEffect(() => {
if (width && width <= 768) {
@@ -231,7 +234,7 @@ const HomeLayout = () => {
}
const closeSidebar = () => {
if (width <= 768) {
if (width <= 1023) {
setIsOpen(false);
}
};
+5 -5
View File
@@ -56,7 +56,7 @@ const DebugPdf = () => {
const fetchPdfMetadata = async () => {
try {
const pdfDataURL = URL.createObjectURL(pdf); // Convert File to data URL
console.log("pdfDataURL ", pdfDataURL);
// console.log("pdfDataURL ", pdfDataURL);
const pdfInfo = await pdfjs.getDocument({ url: pdfDataURL }).promise;
const pdfType = await inferPdfType(pdfInfo);
setPdfDetails((prevDetails) => ({
@@ -74,7 +74,7 @@ const DebugPdf = () => {
const inferPdfType = async (pdf) => {
try {
const firstPage = await pdf.getPage(1);
const firstPage = await pdf.getPage(2);
const scale = 1;
const { width, height } = firstPage.getViewport({ scale });
setPdfDimension({ width: width, height: height });
@@ -277,7 +277,7 @@ const DebugPdf = () => {
className="op-btn op-btn-outline op-btn-primary op-btn-xs rounded-md w-[25px] h-[25px] text-[12px] m-[2px] "
onClick={() => copytoclipboard(pdfDetails?.base64)}
>
<i className="fa-solid fa-copy"></i>
<i className="fa-light fa-copy"></i>
</span>
</div>
<div className="text-[18px] font-medium py-[10px] px-[12px] border-b-[1px] border-[gray]">
@@ -310,13 +310,13 @@ const DebugPdf = () => {
)
}
>
<i className="fa-solid fa-copy"></i>
<i className="fa-light fa-copy"></i>
</span>
<span
className="op-btn op-btn-outline op-btn-error op-btn-xs rounded-md w-[23px] h-[20px] text-[12px] m-[2px] "
onClick={() => handleDelete(coord.key)}
>
<i className="fa-solid fa-trash-can"></i>
<i className="fa-light fa-trash-can"></i>
</span>
</div>
</li>
+5 -14
View File
@@ -645,15 +645,15 @@ const Forms = (props) => {
</label>
{fileupload.length > 0 ? (
<div className="flex gap-2 justify-center items-center">
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm w-full text-x text-[13px]">
<div className="break-all">
file selected : {getFileName(fileupload)}
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm w-full h-full text-x text-[13px]">
<div className="break-all ">
file selected: {getFileName(fileupload)}
</div>
<div
onClick={() => setFileUpload("")}
className="cursor-pointer px-[10px] text-[20px] font-bold text-red-500"
>
<i className="fa-solid fa-xmark"></i>
<i className="fa-light fa-xmark"></i>
</div>
</div>
{process.env.REACT_APP_DROPBOX_API_KEY && (
@@ -761,16 +761,7 @@ const Forms = (props) => {
Send In Order
<a data-tooltip-id="sendInOrder-tooltip" className="ml-1">
<sup>
<i
className="fa-solid fa-question rounded-full"
style={{
borderColor: "#33bbff",
color: "#33bbff",
fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
}}
></i>
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1.5px] py-[1.5px] px-[4px]"></i>
</sup>
</a>
<Tooltip id="sendInOrder-tooltip" className="z-50">
+1 -1
View File
@@ -146,7 +146,7 @@ function GenerateToken() {
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2"
onClick={() => copytoclipboard(apiToken)}
>
<i className="fa-solid fa-copy"></i>
<i className="fa-light fa-copy"></i>
</button>
</span>
</div>
+8 -8
View File
@@ -191,7 +191,7 @@ function GuestLogin() {
<div className="m-1 md:m-2 p-[30px] text-base-content bg-base-100 op-card shadow-md">
<div className="md:w-[250px] md:h-[66px] inline-block overflow-hidden mt-2 mb-11">
{appLogo && (
<img src={appLogo} className="object-contain h-full" alt="logo" />
<img src={appLogo} className="object-contain" alt="logo" />
)}
</div>
{contactId ? (
@@ -199,7 +199,7 @@ function GuestLogin() {
{!EnterOTP ? (
<div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
<legend className="text-[12px] text-[#878787] mt-2">
<legend className="text-[12px] text-[#878787] mt-2 mb-1">
Verification code is sent to your email
</legend>
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
@@ -207,17 +207,17 @@ function GuestLogin() {
type="email"
name="mobile"
value={email}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full disabled:text-[#5c5c5c] text-xs"
disabled
/>
</div>
<div className="mt-2">
<div className="mt-3">
<button
className="op-btn op-btn-primary"
onClick={(e) => handleSendOTPBtn(e)}
disabled={loading}
>
{loading ? "Loading..." : "Send OTP"}
{loading ? "Loading..." : "Get verification code"}
</button>
</div>
</div>
@@ -228,7 +228,7 @@ function GuestLogin() {
>
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
<legend className="text-[12px] text-[#878787] mt-2">
You will get a OTP via Email
You will get a verification code via Email
</legend>
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
<p className="text-sm">Enter Verification Code</p>
@@ -240,7 +240,7 @@ function GuestLogin() {
onChange={(e) => setOTP(e.target.value)}
/>
</div>
<div className="mt-2">
<div className="mt-2.5">
<button
className="op-btn op-btn-primary"
type="submit"
@@ -298,7 +298,7 @@ function GuestLogin() {
disabled
/>
</div>
<div className="mb-2">
<div className="mt-2.5">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
+2
View File
@@ -1103,6 +1103,7 @@ function Login() {
type="email"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="email"
autoComplete="username"
value={state.email}
onChange={handleChange}
required
@@ -1122,6 +1123,7 @@ function Login() {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="password"
value={state.password}
autoComplete="current-password"
onChange={handleChange}
required
/>
+3 -3
View File
@@ -352,7 +352,7 @@ const ManageSign = () => {
}
}}
key={key}
className="fa solid fa-pen-nib"
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
@@ -378,7 +378,7 @@ const ManageSign = () => {
style={{ fontSize: 12 }}
>
<i
className="fas fa-exclamation-circle"
className="fa-light fa-exclamation-circle"
style={{ color: "#fab005", fontSize: 15 }}
></i>{" "}
Please upload signature/Image
@@ -453,7 +453,7 @@ const ManageSign = () => {
}
}}
key={key}
className="fa solid fa-pen-nib"
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
+16 -13
View File
@@ -635,7 +635,7 @@ function Opensigndrive() {
>
<div className="sort" data-tut="reactourSecond">
<i
className="fa fa-plus-square"
className="fa-light fa-plus-square"
aria-hidden="true"
style={{ fontSize: "25px", color: `${iconColor}` }}
></i>
@@ -650,21 +650,24 @@ function Opensigndrive() {
className="dropdown-item itemColor"
onClick={() => setIsFolder(true)}
>
<i className="fa fa-plus mr-[5px]" aria-hidden="true"></i>
<i
className="fa-light fa-plus mr-[5px]"
aria-hidden="true"
></i>
Create folder
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/sHAnZphf69")}
>
<i className="fas fa-pen-nib mr-[5px"></i>
<i className="fa-light fa-pen-nib mr-[5px]"></i>
Sign Yourself
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/8mZzFxbG1z")}
>
<i className="fa fa-file-signature mr-[5px"></i>
<i className="fa-light fa-file-signature mr-[5px]"></i>
Request Signatures
</span>
</div>
@@ -681,7 +684,7 @@ function Opensigndrive() {
data-toggle="dropdown"
>
<i
className="fa fa-sort-amount-asc mr-[5px] text-[14px]"
className="fa-light fa-sort-amount-asc mr-[5px] text-[14px]"
aria-hidden="true"
style={{ color: `${iconColor}` }}
></i>
@@ -706,16 +709,16 @@ function Opensigndrive() {
}}
className="dropdown-item itemColor"
style={{
paddingLeft: selectedSort !== value && "33px"
paddingLeft: selectedSort !== value && "31px"
}}
>
{selectedSort === value && (
<i
className="fa fa-check mr-[5px"
className="fa-light fa-check"
aria-hidden="true"
></i>
)}
{value}
<span className="ml-[5px]">{value}</span>
</span>
);
})}
@@ -731,16 +734,16 @@ function Opensigndrive() {
}}
className="dropdown-item itemColor"
style={{
paddingLeft: sortingOrder !== order && "33px"
paddingLeft: sortingOrder !== order && "31px"
}}
>
{sortingOrder === order && (
<i
className="fa fa-check mr-[5px"
className="fa-light fa-check"
aria-hidden="true"
></i>
)}
{order}
<span className="ml-[5px]">{order}</span>
</span>
);
})}
@@ -752,7 +755,7 @@ function Opensigndrive() {
<div className="sort" onClick={() => setIsList(!isList)}>
<i
onClick={() => setIsList(!isList)}
className="fa fa-th-large"
className="fa-light fa-th-large"
style={{ fontSize: "24px", color: `${iconColor}` }}
aria-hidden="true"
></i>
@@ -764,7 +767,7 @@ function Opensigndrive() {
onClick={() => setIsList(!isList)}
>
<i
className="fa fa-list"
className="fa-light fa-list"
aria-hidden="true"
style={{ fontSize: "23px", color: `${iconColor}` }}
></i>
+323 -334
View File
@@ -31,8 +31,7 @@ import {
contactBook,
handleDownloadPdf,
handleToPrint,
handleDownloadCertificate,
darkenColor
handleDownloadCertificate
} from "../constant/Utils";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
@@ -42,14 +41,17 @@ import PdfDeclineModal from "../primitives/PdfDeclineModal";
import Title from "../components/Title";
import DefaultSignature from "../components/pdf/DefaultSignature";
import ModalUi from "../primitives/ModalUi";
import VerifyEmail from "../components/pdf/VerifyEmail";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import { appInfo } from "../constant/appinfo";
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";
function useQuery() {
return new URLSearchParams(useLocation().search);
}
function PdfRequestFiles() {
const { docId } = useParams();
const navigate = useNavigate();
@@ -81,11 +83,10 @@ function PdfRequestFiles() {
isLoad: true,
message: "This might take some time"
});
const [defaultSignImg, setDefaultSignImg] = useState();
const [isDocId, setIsDocId] = useState(false);
const [pdfNewWidth, setPdfNewWidth] = useState();
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [pdfOriginalWH, setPdfOriginalWH] = useState();
const [signerPos, setSignerPos] = useState([]);
const [signerObjectId, setSignerObjectId] = useState();
const [isUiLoading, setIsUiLoading] = useState(false);
@@ -94,6 +95,7 @@ function PdfRequestFiles() {
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [unSignedWidgetId, setUnSignedWidgetId] = useState("");
const [expiredDate, setExpiredDate] = useState("");
const [isResize, setIsResize] = useState(false);
const [signerUserId, setSignerUserId] = useState();
const [isDontShow, setIsDontShow] = useState(false);
const [isDownloading, setIsDownloading] = useState("");
@@ -127,6 +129,11 @@ function PdfRequestFiles() {
const [isVerifyModal, setIsVerifyModal] = useState(false);
const [otp, setOtp] = useState("");
const [contractName, setContractName] = useState("");
const [pdfRenderHeight, setPdfRenderHeight] = useState();
const [zoomPercent, setZoomPercent] = useState(0);
const [totalZoomPercent, setTotalZoomPercent] = useState();
const [scale, setScale] = useState(1);
const isHeader = useSelector((state) => state.showHeader);
const divRef = useRef(null);
const isMobile = window.innerWidth < 767;
const rowLevel =
@@ -155,17 +162,23 @@ function PdfRequestFiles() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);
const updateSize = () => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
};
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
//function to use resend otp for email verification
const handleResend = async (e) => {
e.preventDefault();
@@ -206,7 +219,6 @@ function PdfRequestFiles() {
setOtpLoader(false);
}
};
//`handleVerifyBtn` function is used to send otp on user mail
const handleVerifyBtn = async () => {
setIsVerifyModal(true);
@@ -320,6 +332,13 @@ function PdfRequestFiles() {
message:
"You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers."
});
} else {
const checkCurrentUser = documentData[0].Placeholders.find(
(data) => data.signerObjId === currUserId
);
if (checkCurrentUser) {
setCurrentSigner(true);
}
}
const isGuestSign = location.pathname.includes("/load/");
@@ -766,10 +785,11 @@ function PdfRequestFiles() {
const pdfBytes = await multiSignEmbed(
pngUrl,
pdfDoc,
pdfOriginalWidth,
pdfOriginalWH,
isSignYourSelfFlow,
containerWH
scale
);
// console.log("pdfte", pdfBytes);
//get ExistUserPtr object id of user class to get tenantDetails
const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
//get ExistUserPtr email to get userDetails
@@ -998,31 +1018,22 @@ function PdfRequestFiles() {
style: { fontSize: "13px" }
}
];
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
const firstPage = await pdf.getPage(1);
const scale = 1;
const { width, height } = firstPage.getViewport({ scale });
// console.log("width height", width, height);
setPdfOriginalWH({ width: width, height: height });
setPdfLoadFail({
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
};
//function for change page
function changePage(offset) {
setPageNumber((prevPageNumber) => prevPageNumber + offset);
}
const getFirstLetter = (name) => {
if (name) {
const firstLetter = name.charAt(0);
return firstLetter;
}
};
//function for image upload or update
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
@@ -1131,26 +1142,6 @@ function PdfRequestFiles() {
return newState;
});
};
const checkSignerBackColor = (obj) => {
let data = "";
if (obj?.Id) {
data = signerPos.filter((data) => data.Id === obj.Id);
} else {
data = signerPos.filter((data) => data.signerObjId === obj.objectId);
}
return data && data.length > 0 && data[0].blockColor;
};
const checkUserNameColor = (obj) => {
const getBackColor = checkSignerBackColor(obj);
if (getBackColor) {
const color = darkenColor(getBackColor, 0.4);
return color;
} else {
return "#abd1d0";
}
};
//function for set decline true on press decline button
const declineDoc = async () => {
setIsDecline({ isDeclined: false });
@@ -1246,6 +1237,7 @@ function PdfRequestFiles() {
const handleDontShow = (isChecked) => {
setIsDontShow(isChecked);
};
// console.log("signerpos", signerPos);
//function to close tour and save tour status
const closeRequestSignTour = async () => {
setRequestSignTour(true);
@@ -1396,7 +1388,7 @@ function PdfRequestFiles() {
{isUiLoading && (
<div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80">
<Loader />
<span className="text-[13px] font-bold">
<span style={{ fontSize: "13px", fontWeight: "bold" }}>
This might take some time
</span>
</div>
@@ -1410,7 +1402,6 @@ function PdfRequestFiles() {
</div>
)}
<div
className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300"
style={{
pointerEvents:
isExpired ||
@@ -1418,7 +1409,7 @@ function PdfRequestFiles() {
? "none"
: "auto"
}}
ref={divRef}
className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300"
>
{!requestSignTour && requestSignTourFunction()}
<ModalUi
@@ -1435,9 +1426,12 @@ function PdfRequestFiles() {
<p>{isAlert.alertMessage}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
onClick={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
type="button"
className="op-btn op-btn-primary"
>
@@ -1495,9 +1489,12 @@ function PdfRequestFiles() {
<ModalUi
isOpen={defaultSignAlert.isShow}
title={"Auto sign"}
handleClose={() =>
setDefaultSignAlert({ isShow: false, alertMessage: "" })
}
handleClose={() => {
setDefaultSignAlert({
isShow: false,
alertMessage: ""
});
}}
>
<div className="h-full p-[20px]">
<p>{defaultSignAlert.alertMessage}</p>
@@ -1512,12 +1509,12 @@ function PdfRequestFiles() {
Yes
</button>
<button
onClick={() =>
onClick={() => {
setDefaultSignAlert({
isShow: false,
alertMessage: ""
})
}
});
}}
type="button"
className="op-btn op-btn-secondary"
>
@@ -1526,9 +1523,12 @@ function PdfRequestFiles() {
</>
) : (
<button
onClick={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
onClick={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
type="button"
className="op-btn op-btn-primary"
>
@@ -1550,289 +1550,278 @@ function PdfRequestFiles() {
setPageNumber={setPageNumber}
pageNumber={pageNumber}
/>
{/* pdf render view */}
<div
style={{
marginLeft: !isMobile && pdfOriginalWidth > 500 && "20px",
marginRight: !isMobile && pdfOriginalWidth > 500 && "20px"
}}
>
{/* this modal is used show this document is already sign */}
<ModalUi
isOpen={isCompleted.isModal}
title={"Document signed"}
handleClose={() => {
setIsCompleted((prev) => ({ ...prev, isModal: false }));
}}
reduceWidth={
!isCompleted?.message &&
"md:min-w-[440px] md:max-w-[400px]"
}
>
<div className="h-full p-[20px] text-base-content">
{isCompleted?.message ? (
<p>{isCompleted?.message}</p>
) : (
<div className="px-[15px]">
<span>
Congratulations! 🎉 This document has been
successfully signed by all participants!
</span>
</div>
)}
{!isCompleted?.message && (
<div className="flex mt-4 gap-1 px-[15px]">
<button
type="button"
onClick={() =>
handleDownloadCertificate(
pdfDetails,
setIsDownloading
)
}
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-secondary"
>
<i
className="fa-solid fa-award"
aria-hidden="true"
></i>
<span className="hidden lg:block">Certificate</span>
</button>
<button
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading)
}
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-neutral"
>
<i className="fa fa-print" aria-hidden="true"></i>
<span className="hidden lg:block">Print</span>
</button>
<button
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
}
>
<i
className="fa fa-download"
aria-hidden="true"
></i>
<span className="hidden lg:block">Download</span>
</button>
</div>
)}
</div>
</ModalUi>
{isDownloading === "pdf" && (
<div className="fixed z-[1000] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<ModalUi
isOpen={isDownloading === "certificate"}
title={
isDownloading === "certificate"
? "Generating certificate"
: "PDF Download"
}
handleClose={() => setIsDownloading("")}
>
<div className="p-3 md:p-5 text-[13px] md:text-base text-center">
{isDownloading === "certificate"}{" "}
<p>
Your completion certificate is being generated. Please
wait momentarily.
</p>
<p>
If the download doesn&apos;t start shortly, click the
button again.
</p>
</div>
</ModalUi>
{/* this component is used for signature pad modal */}
<SignPad
isSignPad={isSignPad}
isStamp={isStamp}
setIsImageSelect={setIsImageSelect}
setIsSignPad={setIsSignPad}
setImage={setImage}
isImageSelect={isImageSelect}
imageRef={imageRef}
onImageChange={onImageChange}
setSignature={setSignature}
image={image}
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
<div className=" w-full md:w-[57%] flex mr-4">
<PdfZoom
setScale={setScale}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
containerWH={containerWH}
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
{/* pdf header which contain funish back button */}
<Header
isPdfRequestFiles={true}
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfDetails={pdfDetails}
signerPos={signerPos}
isSigned={isSigned}
isCompleted={isCompleted.isCertificate}
embedWidgetsData={embedWidgetsData}
isShowHeader={true}
setIsDecline={setIsDecline}
decline={true}
currentSigner={currentSigner}
pdfUrl={pdfUrl}
alreadySign={alreadySign}
/>
{containerWH && (
<RenderPdf
pageNumber={pageNumber}
pdfOriginalWidth={pdfOriginalWidth}
pdfNewWidth={pdfNewWidth}
<div className=" w-full md:w-[95%] ">
{/* this modal is used show this document is already sign */}
<ModalUi
isOpen={isCompleted.isModal}
title={"Document signed"}
handleClose={() => {
setIsCompleted((prev) => ({ ...prev, isModal: false }));
}}
reduceWidth={
!isCompleted?.message &&
"md:min-w-[440px] md:max-w-[400px]"
}
>
<div className="h-full p-[20px] text-base-content">
{isCompleted?.message ? (
<p>{isCompleted?.message}</p>
) : (
<div className="px-[15px]">
<span>
Congratulations! 🎉 This document has been
successfully signed by all participants!
</span>
</div>
)}
{!isCompleted?.message && (
<div className="flex mt-4 gap-1 px-[15px]">
<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"
aria-hidden="true"
></i>
<span className="hidden lg:block">
Certificate
</span>
</button>
<button
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading)
}
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-neutral"
>
<i
className="fa-light fa-print"
aria-hidden="true"
></i>
<span className="hidden lg:block">Print</span>
</button>
<button
type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
}
>
<i
className="fa-light fa-download"
aria-hidden="true"
></i>
<span className="hidden lg:block">Download</span>
</button>
</div>
)}
</div>
</ModalUi>
{isDownloading === "pdf" && (
<div className="fixed z-[1000] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<ModalUi
isOpen={isDownloading === "certificate"}
title={
isDownloading === "certificate"
? "Generating certificate"
: "PDF Download"
}
handleClose={() => setIsDownloading("")}
>
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
{isDownloading === "certificate"}{" "}
<p>
Your completion certificate is being generated. Please
wait momentarily. If the download doesn&apos;t start
shortly, click the button again.
</p>
</div>
</ModalUi>
{/* this component is used for signature pad modal */}
<SignPad
isSignPad={isSignPad}
isStamp={isStamp}
setIsImageSelect={setIsImageSelect}
setIsSignPad={setIsSignPad}
setIsStamp={setIsStamp}
setSignKey={setSignKey}
pdfDetails={pdfDetails}
signerPos={signerPos}
successEmail={false}
pdfUrl={pdfUrl}
numPages={numPages}
pageDetails={pageDetails}
pdfRequest={true}
signerObjectId={signerObjectId}
signedSigners={signedSigners}
setCurrentSigner={setCurrentSigner}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setImage={setImage}
isImageSelect={isImageSelect}
imageRef={imageRef}
onImageChange={onImageChange}
setSignature={setSignature}
image={image}
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setValidateAlert={setValidateAlert}
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsStamp={setIsStamp}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
)}
</div>
<div>
<div className="hidden md:block w-[180px] h-full bg-base-100">
<div
style={{ maxHeight: window.innerHeight - 70 + "px" }}
className="overflow-y-auto hide-scrollbar"
>
{signedSigners.length > 0 && (
<div data-tut="reactourSecond">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Signed by
</div>
<div className="mt-[2px]">
{signedSigners.map((obj, ind) => {
return (
<div
className="rounded-xl mx-1 flex flex-row items-center py-[10px] mt-1"
style={{
background: checkSignerBackColor(obj)
}}
key={ind}
>
<div
className="flex w-[30px] h-[30px] rounded-full justify-center items-center mx-1"
style={{
background: checkUserNameColor(obj)
}}
>
<span className="text-[12px] text-center font-bold text-white uppercase">
{getFirstLetter(obj?.Name || obj?.Role)}
</span>
</div>
<div className="flex flex-col">
<span className="userName">
{obj?.Name || obj?.Role}
</span>
<span className="useEmail">
{obj?.Email || obj?.email}
</span>
</div>
</div>
);
})}
</div>
</div>
)}
{/* pdf header which contain funish back button */}
<Header
isPdfRequestFiles={true}
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfDetails={pdfDetails}
signerPos={signerPos}
isSigned={isSigned}
isCompleted={isCompleted.isCertificate}
embedWidgetsData={embedWidgetsData}
isShowHeader={true}
setIsDecline={setIsDecline}
decline={true}
currentSigner={currentSigner}
pdfUrl={pdfUrl}
alreadySign={alreadySign}
totalZoomPercent={totalZoomPercent}
setTotalZoomPercent={setTotalZoomPercent}
setScale={setScale}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
containerWH={containerWH}
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
{unsignedSigners.length > 0 && (
<div data-tut="reactourFirst">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Yet to sign
</div>
<div className="mt-[5px]">
{unsignedSigners.map((obj, ind) => {
return (
<div
className="rounded-xl mx-1 flex flex-row items-center py-[10px] mt-1"
style={{
background: checkSignerBackColor(obj)
}}
key={ind}
>
<div
className="flex w-[30px] h-[30px] rounded-full justify-center items-center mx-1"
style={{
background: checkUserNameColor(obj)
}}
>
<span className="text-[12px] text-center font-bold text-black uppercase">
{getFirstLetter(obj?.Name || obj?.email)}
</span>
</div>
<div className="flex flex-col">
<span className="userName">
{obj?.Name || obj?.Role}
</span>
<span className="useEmail">
{obj?.Email || obj?.email}
</span>
</div>
<hr />
</div>
);
})}
</div>
</div>
)}
{defaultSignImg && !alreadySign && (
<DefaultSignature
defaultSignImg={defaultSignImg}
setDefaultSignImg={setDefaultSignImg}
userObjectId={signerObjectId}
setIsLoading={setIsLoading}
xyPostion={signerPos}
setDefaultSignAlert={setDefaultSignAlert}
<div
ref={divRef}
data-tut="reactourSecond"
className="h-[95%]"
>
{containerWH && (
<RenderPdf
pageNumber={pageNumber}
pdfOriginalWH={pdfOriginalWH}
pdfNewWidth={pdfNewWidth}
setIsSignPad={setIsSignPad}
setIsStamp={setIsStamp}
setSignKey={setSignKey}
pdfDetails={pdfDetails}
signerPos={signerPos}
successEmail={false}
pdfUrl={pdfUrl}
numPages={numPages}
pageDetails={pageDetails}
pdfRequest={true}
signerObjectId={signerObjectId}
signedSigners={signedSigners}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsInitial={setIsInitial}
setValidateAlert={setValidateAlert}
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
divRef={divRef}
setPdfRenderHeight={setPdfRenderHeight}
pdfRenderHeight={pdfRenderHeight}
setIsResize={setIsResize}
isResize={isResize}
setTotalZoomPercent={setTotalZoomPercent}
setScale={setScale}
scale={scale}
/>
)}
</div>
</div>
</div>
<div className="w-full md:w-[23%] bg-base-100 overflow-y-auto hide-scrollbar hidden md:inline-block">
<div className={`max-h-screen`}>
{signedSigners.length > 0 && (
<>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span> Signed by</span>
</div>
<div className="mt-[2px]">
{signedSigners.map((obj, ind) => {
return (
<div key={ind}>
<SignerListComponent
ind={ind}
obj={obj}
isMenu={isHeader}
signerPos={signerPos}
/>
</div>
);
})}
</div>
</>
)}
{unsignedSigners.length > 0 && (
<>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span>Yet to sign</span>
</div>
<div className="mt-[5px]">
{unsignedSigners.map((obj, ind) => {
return (
<div key={ind}>
<SignerListComponent
ind={ind}
obj={obj}
isMenu={isHeader}
signerPos={signerPos}
/>
</div>
);
})}
</div>
</>
)}
{defaultSignImg && !alreadySign && currentSigner && (
<DefaultSignature
defaultSignImg={defaultSignImg}
setDefaultSignImg={setDefaultSignImg}
userObjectId={signerObjectId}
setIsLoading={setIsLoading}
xyPostion={signerPos}
setDefaultSignAlert={setDefaultSignAlert}
/>
)}
</div>
</div>
</div>
</div>
)}
<ModalUi
isOpen={validateAlert}
title={"Validation alert"}
handleClose={() => setValidateAlert(false)}
handleClose={() => {
setValidateAlert(false);
}}
>
<div className="h-[100%] p-[20px]">
<p>
File diff suppressed because it is too large Load Diff
+352 -273
View File
@@ -17,7 +17,6 @@ import {
contractDocument,
embedDocId,
multiSignEmbed,
pdfNewWidthFun,
onImageSelect,
calculateInitialWidthHeight,
defaultWidthHeight,
@@ -31,6 +30,7 @@ import {
getTenantDetails,
checkIsSubscribed,
convertPdfArrayBuffer,
textInputWidget,
fetchImageBase64,
changeImageWH,
handleSendOTP
@@ -46,7 +46,10 @@ 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";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
@@ -68,10 +71,12 @@ function SignYourSelf() {
const signRef = useRef(null);
const dragRef = useRef(null);
const [dragKey, setDragKey] = useState();
const [fontSize, setFontSize] = useState(11);
const [fontColor, setFontColor] = useState("black");
const [signKey, setSignKey] = useState();
const [imgWH, setImgWH] = useState({});
const [pdfNewWidth, setPdfNewWidth] = useState();
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [pdfOriginalWH, setPdfOriginalWH] = useState();
const [successEmail, setSuccessEmail] = useState(false);
const imageRef = useRef(null);
const [myInitial, setMyInitial] = useState("");
@@ -97,6 +102,7 @@ function SignYourSelf() {
const [showAlreadySignDoc, setShowAlreadySignDoc] = useState({
status: false
});
const [isTextSetting, setIsTextSetting] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState({});
const [isCheckbox, setIsCheckbox] = useState(false);
const [widgetType, setWidgetType] = useState("");
@@ -114,6 +120,10 @@ function SignYourSelf() {
const [isEmailVerified, setIsEmailVerified] = useState(true);
const [isVerifyModal, setIsVerifyModal] = useState(false);
const [otp, setOtp] = useState("");
const [pdfRenderHeight, setPdfRenderHeight] = useState();
const [zoomPercent, setZoomPercent] = useState(0);
const isHeader = useSelector((state) => state.showHeader);
const [scale, setScale] = useState(1);
const divRef = useRef(null);
const nodeRef = useRef(null);
const [, drop] = useDrop({
@@ -123,10 +133,7 @@ function SignYourSelf() {
isOver: !!monitor.isOver()
})
});
const isMobile = window.innerWidth < 767;
const pdfRef = useRef();
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
@@ -154,7 +161,6 @@ function SignYourSelf() {
return object.pageNumber === pageNumber;
});
// rowlevel={JSON.parse(localStorage.getItem("rowlevel"))}
const rowLevel =
localStorage.getItem("rowlevel") &&
JSON.parse(localStorage.getItem("rowlevel"));
@@ -182,17 +188,25 @@ function SignYourSelf() {
}, []);
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);
const updateSize = () => {
if (divRef.current) {
const pdfWidth = divRef.current.offsetWidth;
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
setScale(1);
setZoomPercent(0);
}
};
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
let isCompleted;
@@ -214,7 +228,6 @@ function SignYourSelf() {
} else {
setHandleError("Error: Something went wrong!");
}
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCompleted(true);
@@ -442,61 +455,66 @@ function SignYourSelf() {
);
const dragTypeValue = item?.text ? item.text : monitor.type;
const widgetValue = getWidgetValue(dragTypeValue);
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
const widgetTypeExist = ["name", "company", "job title", "email"].includes(
dragTypeValue
);
const containerScale = containerWH?.width / pdfOriginalWH?.width || 1;
//adding and updating drop position in array when user drop signature button in div
if (item === "onclick") {
const getWidth = widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).width
: "";
const getHeight = widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).height
: "";
dropObj = {
xPosition: containerWH.width / 2 - widgetWidth / 2,
yPosition: containerWH.height / 2 - widgetHeight / 2,
isDrag: false,
xPosition: containerWH.width / 2,
yPosition: containerWH.height / 2,
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
type: dragTypeValue,
yBottom: window.innerHeight / 2 - 60,
Width: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).width
: "",
Height: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).height
: "",
scale: containerScale,
Width: getWidth / (containerScale * scale),
Height: getHeight / (containerScale * scale),
options: addWidgetOptions(dragTypeValue)
};
dropData.push(dropObj);
} else {
//This method returns the offset of the current pointer (mouse) position relative to the client viewport.
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
//`containerRect.left`, The distance from the left of the viewport to the left side of the element.
//`containerRect.top` The distance from the top of the viewport to the top of the element.
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const getXPosition = signBtnPosition[0] ? x - signBtnPosition[0].xPos : x;
const getYPosition = signBtnPosition[0] ? y - signBtnPosition[0].yPos : y;
const getWidth = widgetTypeExist
? calculateInitialWidthHeight(widgetValue).getWidth
: defaultWidthHeight(dragTypeValue).width;
const getHeight = widgetTypeExist
? calculateInitialWidthHeight(widgetValue).getHeight
: defaultWidthHeight(dragTypeValue).height;
dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
// isDrag: false,
xPosition: getXPosition / (containerScale * scale),
yPosition: getYPosition / (containerScale * scale),
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
type: dragTypeValue,
Width: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: defaultWidthHeight(dragTypeValue).width,
Height: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: defaultWidthHeight(dragTypeValue).height,
options: addWidgetOptions(dragTypeValue)
Width: getWidth / (containerScale * scale),
Height: getHeight / (containerScale * scale),
options: addWidgetOptions(dragTypeValue),
scale: containerScale
};
dropData.push(dropObj);
@@ -506,16 +524,12 @@ function SignYourSelf() {
return object.pageNumber === pageNumber;
});
const updateData = filterDropPos[0].pos;
// if (updateData.length > dropData.length) {
const newSignPos = updateData.concat(dropData);
let xyPos = {
pageNumber: pageNumber,
pos: newSignPos
};
xyPostion.splice(index, 1, xyPos);
// }
} else {
const xyPos = {
pageNumber: pageNumber,
@@ -539,6 +553,18 @@ function SignYourSelf() {
setIsInitial(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckbox(true);
} else if (
[
textInputWidget,
textWidget,
"name",
"company",
"job title",
"email"
].includes(dragTypeValue)
) {
setFontSize(12);
setFontColor("black");
}
setWidgetType(dragTypeValue);
setSelectWidgetId(key);
@@ -669,13 +695,15 @@ function SignYourSelf() {
const pdfBytes = await multiSignEmbed(
xyPostion,
pdfDoc,
pdfOriginalWidth,
pdfOriginalWH,
isSignYourSelfFlow,
containerWH
scale
);
// console.log("pdf", pdfBytes);
//function for call to embed signature in pdf and get digital signature pdf
await signPdfFun(pdfBytes, documentId);
if (pdfBytes) {
await signPdfFun(pdfBytes, documentId);
}
} catch (err) {
setIsUiLoading(false);
if (err && err.message.includes("is encrypted.")) {
@@ -782,21 +810,16 @@ function SignYourSelf() {
setIsDragging(true);
};
// console.log("xy", pdfOriginalWH);
//function for set and update x and y postion after drag and drop signature tab
const handleStop = (event, dragElement) => {
if (isDragging && dragElement) {
event.preventDefault();
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const ybottom = containerRect.height - dragElement.y;
const containerScale = containerWH.width / pdfOriginalWH.width;
if (dragKey >= 0) {
const filterDropPos = xyPostion.filter(
(data) => data.pageNumber === pageNumber
);
if (filterDropPos.length > 0) {
const getXYdata = xyPostion[index].pos;
const getPosData = getXYdata;
@@ -804,10 +827,8 @@ function SignYourSelf() {
if (url.key === dragKey) {
return {
...url,
xPosition: dragElement.x,
yPosition: dragElement.y,
isDrag: true,
yBottom: ybottom
xPosition: dragElement.x / (containerScale * scale),
yPosition: dragElement.y / (containerScale * scale)
};
}
return url;
@@ -830,17 +851,14 @@ function SignYourSelf() {
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
const firstPage = await pdf.getPage(1);
const scale = 1;
const { width, height } = firstPage.getViewport({ scale });
setPdfOriginalWH({ width: width, height: height });
setPdfLoadFail({
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
};
//function for change page numver of pdf
function changePage(offset) {
setSignBtnPosition([]);
@@ -896,18 +914,30 @@ function SignYourSelf() {
setXyPostion(getUpdatePosition);
};
//function for capture position on hover signature button
//function for capture position on hover or touch widgets button
const handleDivClick = (e) => {
const isTouchEvent = e.type.startsWith("touch");
const divRect = e.currentTarget.getBoundingClientRect();
const mouseX = e.clientX - divRect.left;
const mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
setXYSignature(xyPosition);
let mouseX, mouseY;
if (isTouchEvent) {
const touch = e.touches[0]; // Get the first touch point
mouseX = touch.clientX - divRect.left;
mouseY = touch.clientY - divRect.top;
setSignBtnPosition([
{
xPos: mouseX,
yPos: mouseY
}
]);
} else {
mouseX = e.clientX - divRect.left;
mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
setXYSignature(xyPosition);
}
};
//function for capture position of x and y on hover signature button last position
@@ -1083,11 +1113,47 @@ function SignYourSelf() {
}
}
};
const handleCloseModal = () => {
setCurrWidgetsDetails({});
setIsCheckbox(false);
};
const handleTextSettingModal = (value) => {
setIsTextSetting(value);
};
const handleSaveFontSize = () => {
const getPageNumer = xyPostion.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
return {
...position,
options: {
...position.options,
fontSize: fontSize || currWidgetsDetails?.options?.fontSize,
fontColor: fontColor || currWidgetsDetails?.options?.fontColor
}
};
}
return position;
});
const updateXYposition = xyPostion.map((obj, ind) => {
if (ind === index) {
return { ...obj, pos: addSignPos };
}
return obj;
});
setXyPostion(updateXYposition);
setFontSize();
setFontColor();
handleTextSettingModal(false);
}
};
return (
<DndProvider backend={HTML5Backend}>
<Title title={"Self Sign"} />
@@ -1100,7 +1166,7 @@ function SignYourSelf() {
{isUiLoading && (
<div className="absolute h-[100vh] w-full z-[999] flex flex-col justify-center items-center bg-[#e6f2f2] bg-opacity-80">
<Loader />
<span className="font-bold text-[13px]">
<span style={{ fontSize: "13px", fontWeight: "bold" }}>
This might take some time
</span>
</div>
@@ -1110,11 +1176,8 @@ function SignYourSelf() {
<Confetti width={window.innerWidth} height={window.innerHeight} />
</div>
)}
<div
className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300"
ref={divRef}
>
{/* <div className="min-h-screen relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300"> */}
<div className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
{!isEmailVerified && (
<VerifyEmail
isVerifyModal={isVerifyModal}
@@ -1149,195 +1212,201 @@ function SignYourSelf() {
setPageNumber={setPageNumber}
setSignBtnPosition={setSignBtnPosition}
pageNumber={pageNumber}
containerWH={containerWH}
/>
<div className=" w-full md:w-[57%] flex mr-4">
<PdfZoom
setScale={setScale}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
containerWH={containerWH}
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
<div className=" w-full md:w-[95%] ">
<ModalUi
isOpen={isAlert.isShow}
title={isAlert?.header || "Alert"}
handleClose={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
>
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
</div>
</ModalUi>
{/* pdf render view */}
<div
style={{
marginLeft: !isMobile && pdfOriginalWidth > 500 && "20px",
marginRight: !isMobile && pdfOriginalWidth > 500 && "20px"
}}
>
<ModalUi
isOpen={isAlert.isShow}
title={isAlert?.header || "Alert"}
handleClose={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
>
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
{/* this modal is used show this document is already sign */}
<ModalUi
isOpen={showAlreadySignDoc.status}
title={"Document signed"}
handleClose={() => {
setShowAlreadySignDoc({ status: false });
}}
>
<div className="p-[20px] h-full">
<p>{showAlreadySignDoc.mssg}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
className="op-btn op-btn-ghost shadow-md"
onClick={() => setShowAlreadySignDoc({ status: false })}
>
Close
</button>
</div>
</ModalUi>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
isSignYourself={true}
handleClose={handleCloseModal}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
setIsPageCopy={setIsPageCopy}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
allPages={allPages}
pageNumber={pageNumber}
signKey={signKey}
/>
{/* this is modal of signature pad */}
<SignPad
isSignPad={isSignPad}
isStamp={isStamp}
setIsImageSelect={setIsImageSelect}
setIsSignPad={setIsSignPad}
setImage={setImage}
isImageSelect={isImageSelect}
imageRef={imageRef}
onImageChange={onImageChange}
setSignature={setSignature}
image={image}
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
widgetType={widgetType}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
{/*render email component to send email after finish signature on document */}
<EmailComponent
isEmail={isEmail}
pdfUrl={pdfUrl}
setIsEmail={setIsEmail}
pdfName={pdfDetails[0] && pdfDetails[0].Name}
setSuccessEmail={setSuccessEmail}
sender={jsonSender}
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
/>
{/* pdf header which contain funish back button */}
<Header
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfUrl={pdfUrl}
embedWidgetsData={embedWidgetsData}
pdfDetails={pdfDetails}
isShowHeader={true}
currentSigner={true}
alreadySign={pdfUrl ? true : false}
isSignYourself={true}
setIsEmail={setIsEmail}
isCompleted={isCompleted}
/>
<div
ref={divRef}
data-tut="reactourSecond"
className="h-full md:h-[95%]"
>
{containerWH?.width && containerWH?.height && (
<RenderPdf
pageNumber={pageNumber}
pdfOriginalWH={pdfOriginalWH}
pdfNewWidth={pdfNewWidth}
drop={drop}
successEmail={successEmail}
nodeRef={nodeRef}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
isDragging={isDragging}
setIsSignPad={setIsSignPad}
setIsStamp={setIsStamp}
handleDeleteSign={handleDeleteSign}
setSignKey={setSignKey}
pdfDetails={pdfDetails}
setIsDragging={setIsDragging}
xyPostion={xyPostion}
pdfRef={pdfRef}
pdfUrl={pdfUrl}
numPages={numPages}
pageDetails={pageDetails}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setXyPostion={setXyPostion}
index={index}
containerWH={containerWH}
setIsPageCopy={setIsPageCopy}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setValidateAlert={setValidateAlert}
handleTextSettingModal={handleTextSettingModal}
pdfRenderHeight={pdfRenderHeight}
setPdfRenderHeight={setPdfRenderHeight}
setScale={setScale}
scale={scale}
/>
)}
</div>
</ModalUi>
{/* this modal is used show this document is already sign */}
<ModalUi
isOpen={showAlreadySignDoc.status}
title={"Document signed"}
handleClose={() => {
setShowAlreadySignDoc({ status: false });
}}
>
<div className="p-[20px] h-full">
<p>{showAlreadySignDoc.mssg}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
className="op-btn op-btn-ghost shadow-md"
onClick={() => setShowAlreadySignDoc({ status: false })}
>
Close
</button>
</div>
</ModalUi>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
isSignYourself={true}
handleClose={handleCloseModal}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
setIsPageCopy={setIsPageCopy}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
allPages={allPages}
pageNumber={pageNumber}
signKey={signKey}
/>
{/* this is modal of signature pad */}
<SignPad
isSignPad={isSignPad}
isStamp={isStamp}
setIsImageSelect={setIsImageSelect}
setIsSignPad={setIsSignPad}
setImage={setImage}
isImageSelect={isImageSelect}
imageRef={imageRef}
onImageChange={onImageChange}
setSignature={setSignature}
image={image}
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
widgetType={widgetType}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
{/*render email component to send email after finish signature on document */}
<EmailComponent
isEmail={isEmail}
pdfUrl={pdfUrl}
setIsEmail={setIsEmail}
pdfName={pdfDetails[0] && pdfDetails[0].Name}
setSuccessEmail={setSuccessEmail}
sender={jsonSender}
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
/>
{/* pdf header which contain funish back button */}
<Header
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfUrl={pdfUrl}
embedWidgetsData={embedWidgetsData}
pdfDetails={pdfDetails}
isShowHeader={true}
currentSigner={true}
alreadySign={pdfUrl ? true : false}
isSignYourself={true}
setIsEmail={setIsEmail}
isCompleted={isCompleted}
/>
<div data-tut="reactourSecond">
{containerWH && (
<RenderPdf
pageNumber={pageNumber}
pdfOriginalWidth={pdfOriginalWidth}
pdfNewWidth={pdfNewWidth}
drop={drop}
successEmail={successEmail}
nodeRef={nodeRef}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
isDragging={isDragging}
setIsSignPad={setIsSignPad}
setIsStamp={setIsStamp}
handleDeleteSign={handleDeleteSign}
setSignKey={setSignKey}
pdfDetails={pdfDetails}
setIsDragging={setIsDragging}
xyPostion={xyPostion}
pdfRef={pdfRef}
pdfUrl={pdfUrl}
numPages={numPages}
pageDetails={pageDetails}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setXyPostion={setXyPostion}
index={index}
containerWH={containerWH}
setIsPageCopy={setIsPageCopy}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setValidateAlert={setValidateAlert}
/>
)}
</div>
</div>
{/*if document is not completed then render signature and stamp button in the right side */}
{/*else document is completed then render signed by signer name in the right side */}
<div
style={{
maxHeight: window.innerHeight - 70 + "px",
backgroundColor: "white"
}}
className="overflow-y-auto hide-scrollbar"
>
{!isCompleted ? (
<div>
<WidgetComponent
dataTut="reactourFirst"
pdfUrl={pdfUrl}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
handleAllDelete={handleAllDelete}
xyPostion={xyPostion}
isSignYourself={true}
addPositionOfSignature={addPositionOfSignature}
isMailSend={false}
/>
</div>
) : (
<div>
<Signedby pdfDetails={pdfDetails[0]} />
</div>
)}
<div className="w-full md:w-[23%] bg-base-100 overflow-y-auto hide-scrollbar">
<div className={`max-h-screen`}>
{!isCompleted ? (
<div>
<WidgetComponent
dataTut="reactourFirst"
pdfUrl={pdfUrl}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
handleAllDelete={handleAllDelete}
xyPostion={xyPostion}
isSignYourself={true}
addPositionOfSignature={addPositionOfSignature}
isMailSend={false}
/>
</div>
) : (
<div>
<Signedby pdfDetails={pdfDetails[0]} />
</div>
)}
</div>
</div>
</div>
</div>
@@ -1364,6 +1433,16 @@ function SignYourSelf() {
</button>
</div>
</ModalUi>
<TextFontSetting
isTextSetting={isTextSetting}
setIsTextSetting={setIsTextSetting}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
handleSaveFontSize={handleSaveFontSize}
currWidgetsDetails={currWidgetsDetails}
/>
</DndProvider>
);
}
+465 -347
View File
@@ -37,8 +37,12 @@ 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 TextFontSetting from "../components/pdf/TextFontSetting";
import PdfZoom from "../components/pdf/PdfZoom";
const TemplatePlaceholder = () => {
const navigate = useNavigate();
const isHeader = useSelector((state) => state.showHeader);
const { templateId } = useParams();
const [pdfDetails, setPdfDetails] = useState([]);
const [isMailSend, setIsMailSend] = useState(false);
@@ -66,7 +70,7 @@ const TemplatePlaceholder = () => {
const [checkTourStatus, setCheckTourStatus] = useState(false);
const [tourStatus, setTourStatus] = useState([]);
const [signerUserId, setSignerUserId] = useState();
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [pdfOriginalWH, setPdfOriginalWH] = useState();
const [contractName, setContractName] = useState("");
const [containerWH, setContainerWH] = useState();
const signRef = useRef(null);
@@ -83,6 +87,8 @@ const TemplatePlaceholder = () => {
const [blockColor, setBlockColor] = useState("");
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isNameModal, setIsNameModal] = useState(false);
const [pdfRenderHeight, setPdfRenderHeight] = useState();
const [isTextSetting, setIsTextSetting] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -147,6 +153,10 @@ const TemplatePlaceholder = () => {
const [isCheckbox, setIsCheckbox] = useState(false);
const [widgetName, setWidgetName] = useState(false);
const [isAddRole, setIsAddRole] = useState(false);
const [fontSize, setFontSize] = useState();
const [fontColor, setFontColor] = useState();
const [zoomPercent, setZoomPercent] = useState(0);
const [scale, setScale] = useState(1);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
@@ -162,16 +172,25 @@ const TemplatePlaceholder = () => {
}, []);
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
const updateSize = () => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
setScale(1);
setZoomPercent(0);
}
};
// Use setTimeout to wait for the transition to complete
const timer = setTimeout(updateSize, 100); // match the transition duration
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);
}, [divRef.current, isHeader]);
async function checkIsSubscribed() {
const res = await fetchSubscription();
const freeplan = res.plan;
@@ -350,29 +369,33 @@ const TemplatePlaceholder = () => {
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const newWidth = containerWH.width;
const scale = pdfOriginalWidth / newWidth;
const containerScale = containerWH.width / pdfOriginalWH.width;
const key = randomId();
// let filterSignerPos = signerPos.filter(
// (data) => data.signerObjId === signerObjId
// );
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
const dragTypeValue = item?.text ? item.text : monitor.type;
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
let dropData = [];
let placeHolder;
if (item === "onclick") {
const dropObj = {
//onclick put placeholder center on pdf
xPosition: window.innerWidth / 2 - 150,
yPosition: window.innerHeight / 2 - 60,
xPosition:
(containerWH.width / 2 - widgetWidth / 2) /
(containerScale * scale),
yPosition:
(containerWH.height / 2 - widgetHeight / 2) /
(containerScale * scale),
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
scale: scale,
isMobile: isMobile,
scale: containerScale,
// isMobile: isMobile,
zIndex: posZIndex,
type: dragTypeValue,
options: addWidgetOptions(dragTypeValue)
options: addWidgetOptions(dragTypeValue),
Width: widgetWidth / (containerScale * scale),
Height: widgetHeight / (containerScale * scale)
};
dropData.push(dropObj);
placeHolder = {
@@ -387,17 +410,24 @@ const TemplatePlaceholder = () => {
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const getXPosition = signBtnPosition[0]
? x - signBtnPosition[0].xPos
: x;
const getYPosition = signBtnPosition[0]
? y - signBtnPosition[0].yPos
: y;
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
xPosition: getXPosition / (containerScale * scale),
yPosition: getYPosition / (containerScale * scale),
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
scale: scale,
isMobile: isMobile,
scale: containerScale,
zIndex: posZIndex,
type: item.text,
options: addWidgetOptions(dragTypeValue)
options: addWidgetOptions(dragTypeValue),
Width: widgetWidth / (containerScale * scale),
Height: widgetHeight / (containerScale * scale)
};
dropData.push(dropObj);
@@ -471,6 +501,13 @@ const TemplatePlaceholder = () => {
setShowDropdown(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckbox(true);
} else if (
[textInputWidget, "name", "company", "job title", "email"].includes(
dragTypeValue
)
) {
setFontSize(12);
setFontColor("black");
} else if (dragTypeValue === radioButtonWidget) {
setIsRadio(true);
}
@@ -499,13 +536,13 @@ const TemplatePlaceholder = () => {
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
const firstPage = await pdf.getPage(1);
const scale = 1;
const { width, height } = firstPage.getViewport({ scale });
// console.log("width height", width, height);
setPdfOriginalWH({ width: width, height: height });
setPdfLoadFail({
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
};
//function for save x and y position and show signature tab on that position
@@ -520,14 +557,9 @@ const TemplatePlaceholder = () => {
const dataNewPlace = addZIndex(signerPos, key, setZIndex);
let updateSignPos = [...signerPos];
updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace);
// signerPos.splice(0, signerPos.length, ...dataNewPlace);
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const signId = signerId; //? signerId : signerObjId;
const keyValue = key ? key : dragKey;
const ybottom = containerRect.height - dragElement.y;
const containerScale = containerWH.width / pdfOriginalWH.width;
if (keyValue >= 0) {
const filterSignerPos = updateSignPos.filter(
(data) => data.Id === signId
@@ -548,10 +580,8 @@ const TemplatePlaceholder = () => {
if (url.key === keyValue) {
return {
...url,
xPosition: dragElement.x,
yPosition: dragElement.y,
isDrag: true,
yBottom: ybottom
xPosition: dragElement.x / (containerScale * scale),
yPosition: dragElement.y / (containerScale * scale)
};
}
return url;
@@ -651,18 +681,30 @@ const TemplatePlaceholder = () => {
setPageNumber((prevPageNumber) => prevPageNumber + offset);
}
//function for capture position on hover signature button
//function for capture position on hover or touch widgets
const handleDivClick = (e) => {
const isTouchEvent = e.type.startsWith("touch");
const divRect = e.currentTarget.getBoundingClientRect();
const mouseX = e.clientX - divRect.left;
const mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
setXYSignature(xyPosition);
let mouseX, mouseY;
if (isTouchEvent) {
const touch = e.touches[0]; // Get the first touch point
mouseX = touch.clientX - divRect.left;
mouseY = touch.clientY - divRect.top;
setSignBtnPosition([
{
xPos: mouseX,
yPos: mouseY
}
]);
} else {
mouseX = e.clientX - divRect.left;
mouseY = e.clientY - divRect.top;
const xyPosition = {
xPos: mouseX,
yPos: mouseY
};
setXYSignature(xyPosition);
}
};
//function for capture position of x and y on hover signature button last position
@@ -1202,8 +1244,57 @@ const TemplatePlaceholder = () => {
setIsCheckbox(false);
};
const handleSaveFontSize = () => {
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
return {
...position,
options: {
...position.options,
fontSize: fontSize,
fontColor: fontColor
}
};
}
return position;
});
const newUpdateSignPos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === pageNumber) {
return { ...obj, pos: addSignPos };
}
return obj;
});
const newUpdateSigner = signerPos.map((obj) => {
if (obj.Id === uniqueId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
}
}
setFontSize();
setFontColor();
handleTextSettingModal(false);
};
const handleTextSettingModal = (value) => {
setIsTextSetting(value);
};
return (
<div>
<>
<Title title={"Template"} />
<DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? (
@@ -1211,275 +1302,291 @@ const TemplatePlaceholder = () => {
) : handleError ? (
<HandleError handleError={handleError} />
) : (
<div
className="op-card overflow-hidden flex flex-row justify-between bg-base-300 relative"
ref={divRef}
>
{/* this component used for UI interaction and show their functionality */}
{!checkTourStatus && (
//this tour component used in your html component where you want to put
//onRequestClose function to close tour
//steps is defined what will be your messages and style also
//isOpen is takes boolean value to open
<Tour
onRequestClose={closeTour}
steps={tourConfig}
isOpen={templateTour}
rounded={5}
closeWithMask={false}
<div>
<div className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
{/* this component used for UI interaction and show their functionality */}
{!checkTourStatus && (
//this tour component used in your html component where you want to put
//onRequestClose function to close tour
//steps is defined what will be your messages and style also
//isOpen is takes boolean value to open
<Tour
onRequestClose={closeTour}
steps={tourConfig}
isOpen={templateTour}
rounded={5}
closeWithMask={false}
/>
)}
{isAddRole && (
<Tour
onRequestClose={() => setIsAddRole(false)}
steps={tourAddRole}
isOpen={isAddRole}
rounded={5}
closeWithMask={false}
/>
)}
{/* this component used to render all pdf pages in left side */}
<RenderAllPdfPage
signPdfUrl={pdfDetails[0].URL}
allPages={allPages}
setAllPages={setAllPages}
setPageNumber={setPageNumber}
setSignBtnPosition={setSignBtnPosition}
pageNumber={pageNumber}
/>
)}
{isAddRole && (
<Tour
onRequestClose={() => setIsAddRole(false)}
steps={tourAddRole}
isOpen={isAddRole}
rounded={5}
closeWithMask={false}
/>
)}
{/* this component used to render all pdf pages in left side */}
<RenderAllPdfPage
signPdfUrl={pdfDetails[0].URL}
allPages={allPages}
setAllPages={setAllPages}
setPageNumber={setPageNumber}
setSignBtnPosition={setSignBtnPosition}
pageNumber={pageNumber}
/>
{/* pdf render view */}
<div
style={{
marginLeft: !isMobile && pdfOriginalWidth > 500 && "20px",
marginRight: !isMobile && pdfOriginalWidth > 500 && "20px"
}}
>
{/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi
isOpen={isSendAlert}
title={"Fields required"}
handleClose={() => setIsSendAlert(false)}
>
<div className="h-full p-[20px]">
<p>Please add at least one signature field for all roles.</p>
</div>
</ModalUi>
<ModalUi
isOpen={!IsReceipent}
title={"Roles"}
handleClose={() => setIsReceipent(true)}
>
<div className="h-full p-[20px] text-center font-medium">
<p>Please add roles first</p>
</div>
</ModalUi>
{/* this modal is used show send mail message and after send mail success message */}
<ModalUi
isOpen={isCreateDocModal}
title={"Create Document"}
handleClose={() => setIsCreateDocModal(false)}
>
<div className="h-full p-[20px]">
<p>
Do you want to create a document using the template you just
created ?
</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
{currentEmail.length > 0 && (
<>
{/* pdf render view */}
<div className=" w-full md:w-[57%] flex mr-4">
<PdfZoom
setScale={setScale}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
containerWH={containerWH}
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
<div className=" w-full md:w-[95%] ">
{/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi
isOpen={isSendAlert}
title={"Fields required"}
handleClose={() => setIsSendAlert(false)}
>
<div className="h-full p-[20px]">
<p>
Please add at least one signature field for all roles.
</p>
</div>
</ModalUi>
<ModalUi
isOpen={!IsReceipent}
title={"Roles"}
handleClose={() => setIsReceipent(true)}
>
<div className="h-full p-[20px] text-center font-medium">
<p>Please add roles first</p>
</div>
</ModalUi>
{/* this modal is used show send mail message and after send mail success message */}
<ModalUi
isOpen={isCreateDocModal}
title={"Create Document"}
handleClose={() => setIsCreateDocModal(false)}
>
<div className="h-full p-[20px]">
<p>
Do you want to create a document using the template you
just created ?
</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
{currentEmail.length > 0 && (
<>
<button
onClick={() => {
handleCreateDocModal();
}}
type="button"
className="op-btn op-btn-primary"
>
Yes
</button>
<button
onClick={() => {
setIsCreateDocModal(false);
}}
type="button"
className="op-btn op-btn-secondary ml-2"
>
No
</button>
</>
)}
</div>
</ModalUi>
{isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
<ModalUi
isOpen={isShowEmail}
title={"signers alert"}
handleClose={() => {
setIsShowEmail(false);
}}
>
<div className="h-full p-[20px]">
<p>Please select signer for add placeholder!</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() => handleCreateDocModal()}
onClick={() => {
setIsShowEmail(false);
}}
type="button"
className="op-btn op-btn-primary"
>
Yes
Ok
</button>
<button
onClick={() => {
setIsCreateDocModal(false);
}}
type="button"
className="op-btn op-btn-secondary ml-2"
>
No
</button>
</>
)}
</div>
</ModalUi>
{isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
<ModalUi
isOpen={isShowEmail}
title={"signers alert"}
handleClose={() => {
setIsShowEmail(false);
}}
>
<div className="h-full p-[20px]">
<p>Please select signer for add placeholder!</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() => setIsShowEmail(false)}
type="button"
className="op-btn op-btn-primary"
>
Ok
</button>
</div>
</ModalUi>
<DropdownWidgetOption
type={radioButtonWidget}
title="Radio group"
showDropdown={isRadio}
setShowDropdown={setIsRadio}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<DropdownWidgetOption
type="dropdown"
title="Dropdown options"
showDropdown={showDropdown}
setShowDropdown={setShowDropdown}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
setIsPageCopy={setIsPageCopy}
xyPostion={signerPos}
setXyPostion={setSignerPos}
allPages={allPages}
pageNumber={pageNumber}
signKey={signKey}
// signerObjId={signerObjId}
Id={uniqueId}
/>
{/* pdf header which contain finish, back button */}
<Header
completeBtnTitle={"Save"}
isPlaceholder={true}
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfDetails={pdfDetails}
signerPos={signerPos}
signersdata={signersdata}
isMailSend={isMailSend}
alertSendEmail={alertSendEmail}
isShowHeader={true}
currentSigner={true}
setIsEditTemplate={handleEditTemplateModal}
dataTut4="reactourFour"
/>
<div data-tut="reactourThird">
{containerWH && (
<RenderPdf
</div>
</ModalUi>
<DropdownWidgetOption
type={radioButtonWidget}
title="Radio group"
showDropdown={isRadio}
setShowDropdown={setIsRadio}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<DropdownWidgetOption
type="dropdown"
title="Dropdown options"
showDropdown={showDropdown}
setShowDropdown={setShowDropdown}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
isSubscribe={isSubscribe}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
setIsPageCopy={setIsPageCopy}
xyPostion={signerPos}
setXyPostion={setSignerPos}
allPages={allPages}
pageNumber={pageNumber}
pdfOriginalWidth={pdfOriginalWidth}
pdfNewWidth={pdfNewWidth}
signKey={signKey}
// signerObjId={signerObjId}
Id={uniqueId}
/>
{/* pdf header which contain funish back button */}
<Header
completeBtnTitle={"Save"}
isPlaceholder={true}
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
pdfDetails={pdfDetails}
signerPos={signerPos}
successEmail={false}
numPages={numPages}
pageDetails={pageDetails}
placeholder={true}
drop={drop}
handleDeleteSign={handleDeleteSign}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsResize={setIsResize}
setZIndex={setZIndex}
handleLinkUser={handleLinkUser}
setUniqueId={setUniqueId}
signersdata={signersdata}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
setSignerObjId={setSignerObjId}
isDragging={isDragging}
setShowDropdown={setShowDropdown}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
handleNameModal={setIsNameModal}
isMailSend={isMailSend}
alertSendEmail={alertSendEmail}
isShowHeader={true}
currentSigner={true}
setIsEditTemplate={handleEditTemplateModal}
dataTut4="reactourFour"
/>
)}
</div>
</div>
{/* signature button */}
{isMobile ? (
<div>
<WidgetComponent
dataTut="reactourFirst"
dataTut2="reactourSecond"
pdfUrl={isMailSend}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={false}
addPositionOfSignature={addPositionOfSignature}
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
isSigners={isSigners}
setIsShowEmail={setIsShowEmail}
isMailSend={isMailSend}
setSelectedEmail={setSelectedEmail}
selectedEmail={selectedEmail}
handleAddSigner={handleAddSigner}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
title={"Roles"}
initial={true}
isTemplateFlow={true}
sendInOrder={pdfDetails[0].SendinOrder}
setSignersData={setSignersData}
blockColor={blockColor}
setBlockColor={setBlockColor}
/>
</div>
) : (
<div>
<div className="hidden md:block w-[180px] h-full bg-base-100">
<div
style={{ maxHeight: window.innerHeight - 70 + "px" }}
className="overflow-y-auto hide-scrollbar"
ref={divRef}
data-tut="reactourThird"
className="h-[95%]"
>
{containerWH && (
<RenderPdf
pageNumber={pageNumber}
pdfNewWidth={pdfNewWidth}
pdfDetails={pdfDetails}
signerPos={signerPos}
successEmail={false}
numPages={numPages}
pageDetails={pageDetails}
placeholder={true}
drop={drop}
handleDeleteSign={handleDeleteSign}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
setPdfLoadFail={setPdfLoadFail}
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsResize={setIsResize}
setZIndex={setZIndex}
handleLinkUser={handleLinkUser}
setUniqueId={setUniqueId}
signersdata={signersdata}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
setSignerObjId={setSignerObjId}
isDragging={isDragging}
setShowDropdown={setShowDropdown}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
handleNameModal={setIsNameModal}
setPdfRenderHeight={setPdfRenderHeight}
pdfRenderHeight={pdfRenderHeight}
handleTextSettingModal={handleTextSettingModal}
pdfOriginalWH={pdfOriginalWH}
setScale={setScale}
scale={scale}
/>
)}
</div>
</div>
</div>
{/* signature button */}
{isMobile ? (
<div>
<WidgetComponent
dataTut="reactourFirst"
dataTut2="reactourSecond"
pdfUrl={isMailSend}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={false}
addPositionOfSignature={addPositionOfSignature}
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
isSigners={isSigners}
setIsShowEmail={setIsShowEmail}
isMailSend={isMailSend}
setSelectedEmail={setSelectedEmail}
selectedEmail={selectedEmail}
handleAddSigner={handleAddSigner}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
title={"Roles"}
initial={true}
isTemplateFlow={true}
sendInOrder={pdfDetails[0].SendinOrder}
setSignersData={setSignersData}
blockColor={blockColor}
setBlockColor={setBlockColor}
/>
</div>
) : (
<div
className={`w-[23%] bg-[#FFFFFF] min-h-screen overflow-y-auto hide-scrollbar`}
>
<div className={`max-h-screen`}>
<SignerListPlace
isMailSend={isMailSend}
signerPos={signerPos}
@@ -1520,49 +1627,60 @@ const TemplatePlaceholder = () => {
</div>
</div>
</div>
</div>
)}
)}
</div>
</div>
)}
<div data-tut="reactourAddbtn--observe">
<AddRoleModal
isModalRole={isModalRole}
roleName={roleName}
signersdata={signersdata}
setRoleName={setRoleName}
handleAddRole={handleAddRole}
handleCloseRoleModal={handleCloseRoleModal}
/>
</div>
<div>
<LinkUserModal
handleAddUser={handleAddUser}
isAddUser={isAddUser}
uniqueId={uniqueId}
closePopup={closePopup}
signersData={signersdata}
/>
</div>
<ModalUi
title={"Edit Template"}
isOpen={isEditTemplate}
handleClose={handleEditTemplateModal}
>
<EditTemplate
template={pdfDetails?.[0]}
onSuccess={handleEditTemplateForm}
/>
</ModalUi>
<WidgetNameModal
widgetName={widgetName}
defaultdata={currWidgetsDetails}
isOpen={isNameModal}
handleClose={handleNameModal}
handleData={handleWidgetdefaultdata}
isSubscribe={isSubscribe}
/>
<TextFontSetting
isTextSetting={isTextSetting}
setIsTextSetting={setIsTextSetting}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
handleSaveFontSize={handleSaveFontSize}
currWidgetsDetails={currWidgetsDetails}
/>
</DndProvider>
<div data-tut="reactourAddbtn--observe">
<AddRoleModal
isModalRole={isModalRole}
roleName={roleName}
signersdata={signersdata}
setRoleName={setRoleName}
handleAddRole={handleAddRole}
handleCloseRoleModal={handleCloseRoleModal}
/>
</div>
<div>
<LinkUserModal
handleAddUser={handleAddUser}
isAddUser={isAddUser}
uniqueId={uniqueId}
closePopup={closePopup}
signersData={signersdata}
/>
</div>
<ModalUi
title={"Edit Template"}
isOpen={isEditTemplate}
handleClose={handleEditTemplateModal}
>
<EditTemplate
template={pdfDetails?.[0]}
onSuccess={handleEditTemplateForm}
/>
</ModalUi>
<WidgetNameModal
widgetName={widgetName}
defaultdata={currWidgetsDetails}
isOpen={isNameModal}
handleClose={handleNameModal}
handleData={handleWidgetdefaultdata}
isSubscribe={isSubscribe}
/>
</div>
</>
);
};
@@ -951,7 +951,7 @@ const ReportTable = (props) => {
<i
data-tut="reactourFirst"
onClick={() => navigate("/form/template")}
className="fa-solid fa-square-plus text-accent text-[40px]"
className="fa-light fa-square-plus text-accent text-[40px]"
></i>
)}
{props.form && (
@@ -959,7 +959,7 @@ const ReportTable = (props) => {
className="cursor-pointer"
onClick={() => handleContactFormModal()}
>
<i className="fa-solid fa-square-plus text-accent text-[40px]"></i>
<i className="fa-light fa-square-plus text-accent text-[40px]"></i>
</div>
)}
</div>
@@ -1427,14 +1427,14 @@ const ReportTable = (props) => {
}}
>
<button className="bg-[#002864] text-white rounded w-[32px] h-[30px] focus:outline-none">
<i className="fa-solid fa-share-from-square"></i>{" "}
<i className="fa-light fa-share-from-square"></i>{" "}
</button>
</RWebShare>
<button
className="ml-2 bg-[#002864] text-white rounded w-[100px] h-[30px] focus:outline-none"
onClick={() => copytoclipboard(share)}
>
<i className="fa-solid fa-link"></i>{" "}
<i className="fa-light fa-link"></i>{" "}
{copied[share.email]
? "Copied"
: "Copy"}
@@ -1583,11 +1583,11 @@ const ReportTable = (props) => {
</tbody>
</table>
</div>
<div className="op-join flex flex-wrap items-center p-2 ">
<div className="op-join flex flex-wrap items-center p-2">
{props.List.length > props.docPerPage && (
<button
onClick={() => paginateBack()}
className="op-join-item op-btn "
className="op-join-item op-btn op-btn-sm"
>
Prev
</button>
@@ -1599,7 +1599,7 @@ const ReportTable = (props) => {
disabled={x === "..."}
className={`${
x === currentPage ? "op-btn-active" : ""
} op-join-item op-btn`}
} op-join-item op-btn op-btn-sm`}
>
{x}
</button>
@@ -1607,7 +1607,7 @@ const ReportTable = (props) => {
{props.List.length > props.docPerPage && (
<button
onClick={() => paginateFront()}
className="op-join-item op-btn"
className="op-join-item op-btn op-btn-sm"
>
Next
</button>
@@ -1616,7 +1616,7 @@ const ReportTable = (props) => {
{props.List?.length <= 0 && (
<div
className={`${
isDashboard ? "h-[330px]" : ""
isDashboard ? "h-[317px]" : ""
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
>
<div className="w-[60px] h-[60px] overflow-hidden">
+1 -1
View File
@@ -2,7 +2,7 @@ import React from "react";
const Loader = () => {
return (
<div className="op-loading op-loading-infinity w-[4rem] text-accent"></div>
<div className="op-loading op-loading-infinity w-[4rem] text-neutral"></div>
);
};
+1 -1
View File
@@ -14,7 +14,7 @@ const Modal = ({ children, Title }) => {
onClick={() => SetIsOpen()}
className="px-2 py-1 bg-gray-400 rounded cursor-pointer"
>
<i className="fa-solid fa-xmark"></i>
<i className="fa-light fa-xmark"></i>
</div>
</div>
<hr />
+2 -2
View File
@@ -6,7 +6,7 @@ const Tooltip = ({ id, message, url, iconColor }) =>
<button onClick={() => openInNewTab(url)} className={"text-center"}>
<sup>
<i
className="fa-solid fa-question rounded-full border-[1.5px] py-[1.5px] px-[4px] text-[13px]"
className="fa-light fa-question rounded-full border-[1.5px] py-[1.5px] px-[4px] text-[13px]"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff"
@@ -23,7 +23,7 @@ const Tooltip = ({ id, message, url, iconColor }) =>
>
<sup>
<i
className="fa-solid fa-question rounded-full border-[1.5px] py-[1.5px] px-[4px] text-[13px]"
className="fa-light fa-question rounded-full border-[1.5px] py-[1.5px] px-[4px] text-[13px]"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff"
+3 -1
View File
@@ -2,9 +2,11 @@ import { combineReducers } from "redux";
import infoReducer from "./infoReducer";
import ShowTenant from "./ShowTenant";
import TourStepsReducer from "./TourStepsReducer";
import showHeader from "./showHeader";
export default combineReducers({
appInfo: infoReducer,
TourSteps: TourStepsReducer,
ShowTenant
ShowTenant,
showHeader
});
@@ -0,0 +1,14 @@
import { createSlice } from "@reduxjs/toolkit";
const showHeaderSlice = createSlice({
name: "showTenant",
initialState: "",
reducers: {
showHeader: (state, action) => {
return action.payload;
}
}
});
export const { showHeader } = showHeaderSlice.actions;
export default showHeaderSlice.reducer;
+3 -1
View File
@@ -7,10 +7,12 @@ import { configureStore } from "@reduxjs/toolkit";
import infoReducer from "./reducers/infoReducer";
import ShowTenant from "./reducers/ShowTenant";
import TourStepsReducer from "./reducers/TourStepsReducer";
import showHeader from "./reducers/showHeader";
export const store = configureStore({
reducer: {
appInfo: infoReducer,
TourSteps: TourStepsReducer,
ShowTenant
ShowTenant,
showHeader
}
});
+19 -13
View File
@@ -15,7 +15,6 @@
border-width: 0.2px;
}
.react-datepicker__input-container {
position: initial !important;
}
@@ -27,7 +26,6 @@
user-select: none;
}
.radioButton {
width: 100%;
height: 100%;
@@ -39,7 +37,6 @@
border-radius: 50px;
}
.drodown-input {
padding: 5px;
width: 100%;
@@ -145,7 +142,7 @@
background: white;
transition-duration: 0.4s;
cursor: all-scroll;
width: 150px;
width: 'auto';
height: 30px;
color: black;
}
@@ -304,9 +301,12 @@
background: white;
}
.ScrollbarsCustom-Track {
.ScrollbarsCustom-TrackY {
width: 4px !important;
}
.ScrollbarsCustom-TrackX {
height: 4px !important;
}
.signYourselfBlock {
padding: 0px;
@@ -434,7 +434,11 @@
overflow: hidden !important;
text-overflow: ellipsis;
}
.user{
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
}
.disabled {
opacity: 0.5;
/* Example: reduce opacity to visually indicate disabled state */
@@ -495,16 +499,16 @@
display: flex;
flex-direction: row;
justify-content: space-between;
background-color: #ebebeb;
/* background-color: #ebebeb; */
position: "relative";
}
.signerComponent {
/* box-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px; */
width: 180px;
/* width: 180px; */
background-color: white;
height: 100%;
}
.modalBody {
@@ -513,9 +517,10 @@
}
.signLayoutContainer1 {
padding: 30px;
padding: 15px;
display: flex;
flex-direction: column;
/* flex-direction: column; */
/* justify-content: start; */
align-items: center;
}
@@ -822,9 +827,9 @@ option {
flex-direction: column;
}
.signerComponent {
/* .signerComponent {
display: none;
}
} */
.preBtn1 {
display: none;
@@ -840,6 +845,7 @@ option {
#navbar {
overflow: hidden;
z-index: 49;
}
/* Navbar links */
+1 -1
View File
@@ -49,7 +49,7 @@ module.exports = {
accent: "#E10032",
"accent-content": "#ffd8d5",
neutral: "#99c2ff",
"neutral-content": "#f1f1f1",
"neutral-content": "#31353b",
"base-100": "#ffffff",
"base-200": "#dedede",
"base-300": "#bebebe",