Compare commits

..
Author SHA1 Message Date
AmolandGitHub cc398d68e4 Merge pull request #883 from OpenSignLabs/raktima-opensignlabs-patch-10
fix: unnecessary showing message faild to load on send document popup
2024-06-26 18:17:17 +05:30
RaktimaNXG cd4844863e fix: unnecessary showing message faild to load on send document popup 2024-06-26 17:53:46 +05:30
AmolandGitHub 6d4ebf7be5 Merge pull request #882 from OpenSignLabs/raktima-opensignlabs-patch-10
fix: ui design of the share button in the in-progress report and various other UI issues.
2024-06-26 16:06:45 +05:30
RaktimaNXG 18992e0334 refactor: refactor code 2024-06-26 15:51:04 +05:30
RaktimaNXG 0580a18b0d fix: remove solid share button design to outline 2024-06-26 15:33:45 +05:30
RaktimaNXG 5a4114b786 fix: ui of share button in inprogress report, declined document popup hiding the navigation menu in mobile view, add loader to load animation of send request 2024-06-26 14:36:04 +05:30
AmolandGitHub 4fdf2299f8 Merge pull request #881 from OpenSignLabs/raktima-opensignlabs-patch-10 2024-06-26 11:31:29 +05:30
RaktimaNXG f15aa39588 fix: default text selection issue with the signature pad in the sign-yourself flow 2024-06-26 11:29:18 +05:30
AmolandGitHub 694312812a Merge pull request #880 from OpenSignLabs/raktima-opensignlabs-patch-10
fix: exiting user can't receive bulk emails, input widgets's size reduced in request-sign process
2024-06-25 20:15:46 +05:30
RaktimaNXG 2606b58434 fix: change save button to next in template flow 2024-06-25 17:17:20 +05:30
RaktimaNXG 943f9a0673 fix: navigate user on in-progress report after send document to signers. 2024-06-25 16:26:46 +05:30
RaktimaNXG 77622ebea9 fix: exiting user can't receive bulk emails, input widgets's size reduced in request-sign process 2024-06-25 16:07:54 +05:30
prafull-opensignlabsandGitHub 6fb714d565 Merge pull request #879 from OpenSignLabs/raktima-opensignlabs-patch-10
fix: tour messages display issue in all flow
2024-06-24 19:15:06 +05:30
RaktimaNXG f6170e01f6 fix: tour messages display issue in all flow 2024-06-24 19:10:28 +05:30
AmolandGitHub 1e857b615f Merge pull request #878 from OpenSignLabs/raktima-opensignlabs-patch-10
style: update theme color
2024-06-24 16:33:48 +05:30
prafull-opensignlabs b982ca5218 style: update theme color 2024-06-24 16:29:00 +05:30
prafull-opensignlabsandGitHub c83817800e Merge pull request #877 from OpenSignLabs/raktima-opensignlabs-patch-10
fix: update UI design of my signature
2024-06-24 16:17:33 +05:30
prafull-opensignlabs d1992839a8 Merge branch 'raktima-opensignlabs-patch-10' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-24 16:14:37 +05:30
prafull-opensignlabs bfb7136c89 styke: make rounded corner in my signature 2024-06-24 16:14:24 +05:30
RaktimaNXG 52b2cc6af4 refactor: refactor code 2024-06-24 16:08:52 +05:30
AmolandGitHub 94d386541d Merge pull request #876 from OpenSignLabs/raktima-opensignlabs-patch-10 2024-06-24 16:08:08 +05:30
RaktimaNXG d85d76c8aa fix: text box widgets issue in mobile view, ui design of request sign flow in mobile view, signature widgets ratio, remove on mail sent celebration effect. 2024-06-24 15:49:27 +05:30
prafull-opensignlabs ade97b972f feat: add tour for webhook and apitoken, update css 2024-06-24 15:36:51 +05:30
prafull-opensignlabs 532780629b style: update send button color in send mail & size of certificate button 2024-06-24 11:32:10 +05:30
prafull-opensignlabs 1f2298f192 fix: dragging icon is not visible and css change 2024-06-24 11:02:32 +05:30
AmolandGitHub ae5d527e4f Merge pull request #870 from OpenSignLabs/raktima-opensignlabs-patch-10 2024-06-22 00:21:39 +05:30
prafull-opensignlabs e59a7e0028 Merge branch 'raktima-opensignlabs-patch-10' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-21 20:19:01 +05:30
prafull-opensignlabs 1d6655eafe style: update ui design of my signature page 2024-06-21 20:18:37 +05:30
RaktimaNXG 09b39a467b fix: widgets disappear issue in request sign flow 2024-06-21 20:18:12 +05:30
RaktimaNXG e0e7dd5298 fix: widget's position errors caused by differing page sizes in landscape orientation 2024-06-21 19:28:59 +05:30
prafull-opensignlabs 56d5091b96 fix: miscellaneous folder are visible in folder popup 2024-06-21 19:06:50 +05:30
prafull-opensignlabs 0b28e64111 refactor: removed uncessary css, files 2024-06-21 18:44:17 +05:30
AmolandGitHub 482b75c6a7 Merge pull request #869 from OpenSignLabs/raktima-opensignlabs-patch-10 2024-06-21 17:12:35 +05:30
RaktimaNXG cdff7e252d fix: pagenumber issue 2024-06-21 16:56:43 +05:30
RaktimaNXG a18aee0be1 fix: landscape mode pdf after embed widget's position 2024-06-21 16:55:59 +05:30
prafull-opensignlabs 89f67bfeeb feat: mover sidebarlist from server to local 2024-06-21 16:18:39 +05:30
prafull-opensignlabs e4f0e9cef3 Merge branch 'raktima-opensignlabs-patch-10' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-21 13:52:04 +05:30
prafull-opensignlabs 12599c1e5a style: change icon from solid to light 2024-06-21 13:51:38 +05:30
RaktimaNXG 6bb3203417 Merge branch 'raktima-opensignlabs-patch-10' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-21 13:11:30 +05:30
RaktimaNXG 0eb2c5ecc4 fix: in landscape mode pdf after embed image,all text type and dropdown widgets position issue 2024-06-21 13:10:51 +05:30
prafull-opensignlabs 01ab19b235 feat: add box number in center of box in debugpdf UI 2024-06-20 20:09:24 +05:30
prafull-opensignlabs ba6b0ce7e5 fix: position of image type widgets on landscape pdf are not correct 2024-06-20 19:34:10 +05:30
prafull-opensignlabs b99d3f643b Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-20 19:33:10 +05:30
nxglabs fea174c48d docs: update instructions to run frontend locally in dev mode 2024-06-20 15:34:13 +05:30
nxglabs 1aa1a602b3 docs: move .env.frontend_dev from root folder to apps/OpenSign folder 2024-06-20 15:31:18 +05:30
prafull-opensignlabs 37b7e50b4c fix: when zoom in tablet widget get disappeared & hide sidbar in tablet when close 2024-06-20 14:30:45 +05:30
prafull-opensignlabs e9fab26ef3 style: updated css in guest login, header, loader, reports & update profile img 2024-06-19 18:36:48 +05:30
prafull-opensignlabs 3216a1d4ae fix: handle zindex of pdf page in signyourself flow 2024-06-19 14:50:32 +05:30
RaktimaNXG eb0941f087 fix: widgets shift slightly in right side after being dropped in the template view. 2024-06-19 14:24:08 +05:30
RaktimaNXG 0a315ef9c7 fix: only add widget on first pageand it show unnecessary on all pages, unable to select widgets in tablet view 2024-06-19 12:45:15 +05:30
RaktimaNXG 134babd070 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-10 2024-06-19 11:17:57 +05:30
AmolandGitHub 954ba13f22 Merge pull request #867 from OpenSignLabs/resolve_stage 2024-06-19 10:57:37 +05:30
prafull-opensignlabs 66718fd416 build(deps): update dependecies 2024-06-19 10:52:48 +05:30
RaktimaNXG f4358c5004 fix: ui design issue in mobile view 2024-06-19 10:00:43 +05:30
prafull-opensignlabsandGitHub 63f888b3ec Merge pull request #854 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/eslint-9.5.0
build(deps-dev): bump eslint from 8.57.0 to 9.5.0 in /apps/OpenSign
2024-06-18 19:05:14 +05:30
prafull-opensignlabsandGitHub e066d1d273 Merge pull request #856 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/prettier-3.3.2
build(deps-dev): bump prettier from 3.3.0 to 3.3.2 in /apps/OpenSignServer
2024-06-18 19:04:49 +05:30
AmolandGitHub daddb10030 Merge pull request #864 from OpenSignLabs/resolve_stage 2024-06-18 19:01:00 +05:30
prafull-opensignlabs 6d9090d414 style: change email send popup UI in signrourself 2024-06-18 18:59:35 +05:30
AmolandGitHub 795e8a8ec9 Merge pull request #863 from OpenSignLabs/resolve_stage
feat: update design of signers Ui, style of some buttons and update primary, neutral color
2024-06-18 16:38:41 +05:30
prafull-opensignlabs e8b0b333a1 feat: update design of signers Ui, style of some buttons and update primary , neutral color 2024-06-18 14:41:50 +05:30
RaktimaNXG 93d9a761ca fix: widget's position issue after zoomin and zoomout 2024-06-18 14:38:44 +05:30
RaktimaNXG 3642d4f3a3 refactor: refactor code 2024-06-17 21:17:18 +05:30
RaktimaNXG 08387fc406 feat: optimize design for high-resolution monitors 2024-06-17 21:07:25 +05:30
AmolandGitHub d1d0f40b00 Merge pull request #861 from OpenSignLabs/resolve_stage 2024-06-17 18:35:53 +05:30
prafull-opensignlabs ad4a9e7141 feat: change icons from opensign drive 2024-06-17 18:34:12 +05:30
AmolandGitHub d46cb7dc10 Merge pull request #860 from OpenSignLabs/resolve_stage 2024-06-17 14:09:11 +05:30
prafull-opensignlabs 50b9717cb9 fix: stop loop of mail sent animation 2024-06-17 14:07:45 +05:30
AmolandGitHub 4e83734c5c Merge pull request #859 from OpenSignLabs/resolve_stage
fix: zindex of tooltip, decrease size of loader, remove description from signyourself and requestsign form
2024-06-17 13:47:50 +05:30
prafull-opensignlabs 6eeaea137a fix: zindex of tooltip, decrease size of loader, remove description from signyourseld and requestsign form 2024-06-17 13:42:21 +05:30
dependabot[bot]andGitHub 2c91499232 build(deps-dev): bump prettier in /apps/OpenSignServer
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.0 to 3.3.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.0...3.3.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 00:39:28 +00:00
dependabot[bot]andGitHub e6085eb2c0 build(deps-dev): bump eslint from 8.57.0 to 9.5.0 in /apps/OpenSign
Bumps [eslint](https://github.com/eslint/eslint) from 8.57.0 to 9.5.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.5.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 00:28:33 +00:00
AmolandGitHub 6fa4c4759b Merge pull request #853 from OpenSignLabs/resolve_stage 2024-06-16 15:13:39 +05:30
prafull-opensignlabs f8d6547c24 style: update css of folder component and remove unncessary css file 2024-06-16 15:12:20 +05:30
AmolandGitHub ffdd952440 Merge pull request #852 from OpenSignLabs/resolve_stage
fix: cannot open pdf in safari < 17.4
2024-06-16 13:37:26 +05:30
prafull-opensignlabs 9594e9438e fix: cannot open pdf in safari < 17.4 2024-06-16 13:36:45 +05:30
97 changed files with 33399 additions and 5501 deletions
-12
View File
@@ -1,12 +0,0 @@
# Clone the repo and rename this file to .env if you want to run the frontend react app locally for some quick contributions to the project.
# When used as it is, this env config will connect to our hosted UAT backend
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=http://localhost:3000
# Set it to true if you want to generate the Sourcemap for debugging
GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=https://staging-app.opensignlabs.com/api/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=opensign
+551 -544
View File
File diff suppressed because it is too large Load Diff
+10 -7
View File
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@formkit/auto-animate": "^0.8.2",
"@lottiefiles/dotlottie-react": "^0.6.4",
"@radix-ui/themes": "^3.0.5",
"@react-pdf/renderer": "^3.4.4",
"@reduxjs/toolkit": "^2.2.5",
@@ -46,7 +47,8 @@
"regex-parser": "^2.3.0",
"serve": "^14.2.3",
"styled-components": "^4.4.1",
"web-vitals": "^4.0.1"
"web-vitals": "^4.0.1",
"ws": "^8.17.1"
},
"scripts": {
"start": "serve -s build",
@@ -89,15 +91,16 @@
"commitizen": "^4.3.0",
"daisyui": "^4.12.2",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.34.1",
"lint-staged": "^15.2.5",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.7",
"postcss": "^8.4.38",
"prettier": "^2.8.8",
"pretty-quick": "^3.3.1",
"prettier": "^3.3.2",
"pretty-quick": "^4.0.0",
"tailwindcss": "^3.4.4"
},
"overrides": {
"nth-check": "$nth-check"
"nth-check": "$nth-check",
"ws":"$ws"
}
}
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.
-1
View File
@@ -32,7 +32,6 @@ const GenerateToken = lazy(() => import("./pages/GenerateToken"));
const Webhook = lazy(() => import("./pages/Webhook"));
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
const AppLoader = () => {
return (
<div className="flex justify-center items-center h-[100vh]">
Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

+40 -13
View File
@@ -113,9 +113,15 @@ const BulkSendUi = (props) => {
let Placeholders = [...props.item.Placeholders];
// Initialize an empty array to store updated documents
let Documents = [];
// Loop through each form
forms.forEach((form) => {
//checking if user enter email which already exist as a signer then add user in a signers array
let existSigner = [];
form.fields.map((data) => {
if (data.signer) {
existSigner.push(data.signer);
}
});
// Map through the copied Placeholders array to update email values
const updatedPlaceholders = Placeholders.map((placeholder) => {
// Find the field in the current form that matches the placeholder Id
@@ -123,23 +129,44 @@ const BulkSendUi = (props) => {
(element) => parseInt(element.fieldId) === placeholder.Id
);
// If a matching field is found, update the email value in the placeholder
const signer = field?.signer?.objectId ? field.signer : {};
const signer = field?.signer?.objectId ? field.signer : "";
if (field) {
return {
...placeholder,
email: field.email,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
if (signer) {
return {
...placeholder,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
} else {
return {
...placeholder,
email: field.email,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
}
}
// If no matching field is found, keep the placeholder as is
return placeholder;
});
// Push a new document object with updated Placeholders into the Documents array
Documents.push({ ...props.item, Placeholders: updatedPlaceholders });
if (existSigner?.length > 0) {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders,
Signers: props.item.Signers
? [...props.item.Signers, ...existSigner]
: [...existSigner]
});
} else {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders
});
}
});
// console.log("Documents ", Documents);
//console.log("Documents ", Documents);
await batchQuery(Documents);
};
@@ -205,7 +232,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 +244,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>
+14 -10
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">
@@ -115,7 +115,7 @@ const Header = ({ showSidebar }) => {
{!isSubscribe && (
<div>
<button
className="text-xs bg-[#002864] p-2 text-white rounded shadow"
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
onClick={() => navigate("/subscription")}
>
Upgrade Now
@@ -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>
+25 -15
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>
@@ -13,11 +13,7 @@ const RenderDebugPdf = (props) => {
>
<Document
onLoadError={() => {
const load = {
status: false,
type: "failed"
};
props.setPdfLoadFail(load);
props.setPdfLoadFail(false);
}}
loading={"Loading Document.."}
onLoadSuccess={props.pageDetails}
@@ -47,16 +43,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>
@@ -1,5 +1,4 @@
import React from "react";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
import { openInNewTab } from "../../constant/Utils";
@@ -32,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>
);
@@ -2,7 +2,6 @@ import React, { useState, useEffect } from "react";
import axios from "axios";
import Parse from "parse";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
import Tooltip from "../../primitives/Tooltip";
@@ -262,21 +261,14 @@ const DashboardCard = (props) => {
}
}
body = str;
await axios
.post(url, body, { headers: headers })
.then((response) => {
try {
if (response.data.result.length > 0) {
setresponse(response.data.result[0][props.FilterData.key]);
setLoading(false);
} else {
setresponse("0");
setLoading(false);
}
} catch (error) {
setLoading(false);
}
});
const response = await axios.post(url, body, { headers: headers });
if (response.data.result.length > 0) {
setresponse(response.data.result[0][props.FilterData.key]);
setLoading(false);
} else {
setresponse("0");
setLoading(false);
}
} catch (error) {
setLoading(false);
}
@@ -339,10 +331,10 @@ const DashboardCard = (props) => {
}`}
>
<div className="flex items-center justify-start gap-5 text-white">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<span className="rounded-full bg-base-300 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) => {
@@ -1,7 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
import folder from "../../assets/images/folder.png";
import "../../styles/opensigndrive.css";
import pdfLogo from "../../assets/images/pdf3.png";
import axios from "axios";
import * as ContextMenu from "@radix-ui/react-context-menu";
import { saveAs } from "file-saver";
@@ -19,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();
@@ -315,17 +313,22 @@ function DriveBody(props) {
const signerName = getSignersName.join(", ");
return (
<span className="statusSpan w-[90%] break-words">{signerName}</span>
<span className="text-[12px] font-medium w-[90%] break-words">
{signerName}
</span>
);
};
return listType === "table" ? (
data.Type === "Folder" ? (
<tr onClick={() => handleOnclikFolder(data)}>
<td className="cursor-pointer flex items-center">
<i
className="fa fa-folder mr-[8px] text-[26px] text-[#f0ad26]"
aria-hidden="true"
></i>
<td className="cursor-pointer flex items-center gap-2">
<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>
@@ -335,8 +338,14 @@ function DriveBody(props) {
</tr>
) : (
<tr onClick={() => checkPdfStatus(data)}>
<td className="cursor-pointer flex items-center">
<i className="fa fa-file-pdf mr-[8px] text-[26px] text-[#ed4d0e]"></i>
<td className="cursor-pointer flex items-center gap-2">
<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>
@@ -348,23 +357,29 @@ function DriveBody(props) {
e.stopPropagation();
handleMenuItemClick("Download", data);
}}
className="fa fa-download mr-[8px] text-[#ed280e]"
className="fa-light fa-download mr-[8px] op-text-primary"
aria-hidden="true"
></i>
</td>
</tr>
)
) : listType === "list" && data.Type === "Folder" ? (
<div key={ind} className="icon-container">
<div key={ind} className="relative w-[100px] h-[100px] mx-2 my-3">
<ContextMenu.Root>
<ContextMenu.Trigger className="ContextMenuTrigger">
<div data-tut={props.dataTutSeventh}>
<img
alt="folder"
onClick={() => handleOnclikFolder(data)}
src={folder}
className="w-full h-full"
/>
<ContextMenu.Trigger className="flex flex-col justify-center items-center">
{/* 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={() => {
@@ -385,7 +400,7 @@ function DriveBody(props) {
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
/>
) : (
<span className="foldName">{data.Name}</span>
<span className="fileName">{data.Name}</span>
)}
</div>
</ContextMenu.Trigger>
@@ -400,7 +415,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>
@@ -412,58 +427,65 @@ function DriveBody(props) {
<HoverCard.Trigger asChild>
<div>
<ContextMenu.Root>
<div className="icon-container">
<ContextMenu.Trigger className="ContextMenuTrigger">
<img
alt="PDF"
className="w-full h-full"
src={pdfLogo}
onClick={() => checkPdfStatus(data)}
<div className="relative w-[100px] h-[100px] mx-2 my-3">
<ContextMenu.Trigger className="flex flex-col justify-center items-center">
{/* pdf */}
<div
data-tut={props.dataTutSixth}
/>
{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>
)
)}
@@ -495,21 +517,17 @@ function DriveBody(props) {
<HoverCard.Portal>
<HoverCard.Content className="HoverCardContent" sideOffset={5}>
<strong className="text-[13px]">Title: </strong>
<span className="statusSpan" style={{ marginBottom: "0px" }}>
{" "}
{data.Name}
</span>
<span className="text-[12px] font-medium mb-0"> {data.Name}</span>
<br />
<strong className="text-[13px]">Status: </strong>
<span className="statusSpan"> {status}</span>
<span className="text-[12px] font-medium"> {status}</span>
<br />
<strong className="text-[13px]">Created Date: </strong>
<span className="statusSpan">{createddate}</span>
<span className="text-[12px] font-medium">{createddate}</span>
<br />
{signerExist && (
<>
<strong className="text-[13px]">Signers: </strong>
{/* <span className="statusSpan">kjefjjnejkfnkbjs bbfjkdsbjbfjkbjk kscbjkbjkb</span> */}
{signersName()}
</>
)}
@@ -3,13 +3,9 @@ import React from "react";
function BorderResize({ right, top }) {
return (
<div
className="borderResize"
style={{
right: right ? right + "px" : "-1px",
bottom: top ? top + "px" : "-1px",
borderRight: "3px solid #188ae2",
borderBottom: "3px solid #188ae2"
}}
className={`${right ? `-right-[12px]` : "-right-[1px]"} ${
top ? `-bottom-[11px]` : "-bottom-[1px]"
} absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize border-r-[3px] border-b-[3px] border-[#188ae2]`}
></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 && (
@@ -61,7 +61,7 @@ const EditTemplate = ({ template, onSuccess }) => {
<div className="max-h-[300px] md:max-h-[400px] overflow-y-scroll p-[10px]">
<div className="text-base-content">
<form onSubmit={handleSubmit}>
<div>
<div className="mb-[0.35rem]">
<label htmlFor="name" className="text-[13px]">
File
</label>
@@ -69,7 +69,7 @@ const EditTemplate = ({ template, onSuccess }) => {
{getFileName(template.URL)}
</div>
</div>
<div className="form-section">
<div className="mb-[0.35rem]">
<label htmlFor="name" className="text-[13px]">
Name
<span className="text-[13px] text-[red]"> *</span>
@@ -83,7 +83,7 @@ const EditTemplate = ({ template, onSuccess }) => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="form-section">
<div className="mb-[0.35rem]">
<label htmlFor="Note" className="text-[13px]">
Note
</label>
@@ -96,7 +96,7 @@ const EditTemplate = ({ template, onSuccess }) => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="form-section">
<div className="mb-[0.35rem]">
<label htmlFor="Description" className="text-[13px]">
Description
</label>
@@ -109,7 +109,7 @@ const EditTemplate = ({ template, onSuccess }) => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="form-section">
<div className="mb-[0.35rem]">
<label className="text-[13px]">Send In Order</label>
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
<input
@@ -138,7 +138,7 @@ const EditTemplate = ({ template, onSuccess }) => {
{!isEnableSubscription && (
<PremiumAlertHeader
message={
"Disable Auto reminder is free in beta, this feature will incur a fee later."
"Auto reminder is free in beta, this feature will incur a fee later."
}
/>
)}
+129 -139
View File
@@ -1,11 +1,11 @@
import React, { useState } from "react";
import { saveAs } from "file-saver";
import celebration from "../../assets/images/newCeleb.gif";
import axios from "axios";
import { getBase64FromUrl } from "../../constant/Utils";
import { themeColor } from "../../constant/const";
import printModule from "print-js";
import Loader from "../../primitives/Loader";
import ModalUi from "../../primitives/ModalUi";
function EmailComponent({
isEmail,
@@ -21,7 +21,6 @@ function EmailComponent({
const [emailList, setEmailList] = useState([]);
const [emailValue, setEmailValue] = useState();
const [isLoading, setIsLoading] = useState(false);
const [isEmailCelebration, setIsEmailCelebration] = useState(false);
//function for send email
const sendEmail = async () => {
setIsLoading(true);
@@ -62,10 +61,6 @@ function EmailComponent({
" target=_blank>here</a> </p></div></div></body></html>"
};
sendMail = await axios.post(url, params, { headers: headers });
setIsEmailCelebration(true);
setTimeout(() => {
setIsEmailCelebration(false);
}, 3000);
} catch (error) {
console.log("error", error);
setIsLoading(false);
@@ -170,146 +165,141 @@ function EmailComponent({
<div>
{/* isEmail */}
{isEmail && (
<div className="modaloverlay">
<div className="modalcontainer">
{isLoading && (
<div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2] bg-opacity-80">
<Loader />
<span className="text-[12px] font-bold">
This might take some time
</span>
</div>
)}
<div style={{ background: "#32a3ac" }} className="modalheader">
<span className="text-white">Successfully signed!</span>
<div className="flex flex-row">
<div></div>
{!isAndroid && (
<button
onClick={handleToPrint}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa fa-print" aria-hidden="true"></i>
Print
</button>
)}
<button
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
>
<i className="fa fa-download" aria-hidden="true"></i>
Download
</button>
</div>
<ModalUi isOpen showHeader={false}>
{isLoading && (
<div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2]/70">
<Loader />
<span className="text-[12px] text-base-content">
This might take some time
</span>
</div>
<div className="h-full p-[20px]">
{isEmailCelebration && (
<div className="absolute w-[100%] flex justify-center items-center">
<img alt="celeb" width={300} height={250} src={celebration} />
</div>
)}
<p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
Recipients added here will get a copy of the signed document.
</p>
{emailList.length > 0 ? (
<>
<div className="addEmail">
<div className="flex flex-row flex-wrap">
{emailList.map((data, ind) => {
return (
<div
className="flex flex-row items-center bg-[#47a3ad] m-[4px] rounded-md py-[5px] px-[10px]"
key={ind}
>
<span className="text-white text-[13px]">
{data}
</span>
<span
className="text-white text-[13px] font-semibold ml-[7px] cursor-pointer"
onClick={() => removeChip(ind)}
>
<i className="fa-solid fa-xmark"></i>
</span>
</div>
);
})}
</div>
{emailList.length <= 9 && (
<input
type="text"
value={emailValue}
className="p-[10px] pb-[20px] rounded w-full text-[15px] bg-white outline-none"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
onBlur={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
required
/>
)}
</div>
</>
) : (
<div>
<input
type="text"
value={emailValue}
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-white border-2 border-[#47a3ad]"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
placeholder="Add the email addresses"
onBlur={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
required
/>
</div>
)}
<div className="flex justify-between items-center py-[10px] px-[20px] border-b-[1px] border-base-content">
<span className="text-base-content font-semibold">
Successfully signed!
</span>
<div className="flex flex-row">
<div></div>
{!isAndroid && (
<button
onClick={handleToPrint}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa-light fa-print" aria-hidden="true"></i>
Print
</button>
)}
<button
className={`${
emailValue ? "cursor-pointer" : "cursor-default"
} op-btn op-btn-primary op-btn-sm m-2 shadow-md`}
onClick={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
>
<i className="fa fa-plus" aria-hidden="true"></i>
</button>
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
<span className="font-bold">Note: </span>
<span className="text-[15px]">
You can only send to ten recipients at a time.
</span>
</div>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
type="button"
className="op-btn op-btn-primary"
onClick={() => emailList.length > 0 && sendEmail()}
>
Send
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={() => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}}
>
Close
<i className="fa-light fa-download" aria-hidden="true"></i>
Download
</button>
</div>
</div>
</div>
<div className="h-full p-[20px]">
<p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
Recipients added here will get a copy of the signed document.
</p>
{emailList.length > 0 ? (
<>
<div className="p-0 border-[1.5px] op-border-primary rounded w-full text-[15px]">
<div className="flex flex-row flex-wrap">
{emailList.map((data, ind) => {
return (
<div
className="flex flex-row items-center op-bg-primary m-[4px] rounded-md py-[5px] px-[10px]"
key={ind}
>
<span className="text-base-100 text-[13px]">
{data}
</span>
<span
className="text-base-100 text-[13px] font-semibold ml-[7px] cursor-pointer"
onClick={() => removeChip(ind)}
>
<i className="fa-light fa-xmark"></i>
</span>
</div>
);
})}
</div>
{emailList.length <= 9 && (
<input
type="text"
value={emailValue}
className="p-[10px] pb-[20px] rounded w-full text-[15px] bg-transparent outline-none"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
onBlur={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
required
/>
)}
</div>
</>
) : (
<div>
<input
type="text"
value={emailValue}
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-transparent border-[1.5px] op-border-primary"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
placeholder="Add the email addresses"
onBlur={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
required
/>
</div>
)}
<button
className={`${
emailValue ? "cursor-pointer" : "cursor-default"
} op-btn op-btn-primary op-btn-sm m-2 shadow-md`}
onClick={() => {
if (emailValue) {
handleEnterPress("add");
}
}}
>
<i className="fa-light fa-plus" aria-hidden="true"></i>
</button>
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
<span className="font-bold">Note: </span>
<span className="text-[15px]">
You can only send to ten recipients at a time.
</span>
</div>
<hr className="w-full my-[15px] bg-base-content" />
<button
type="button"
className="op-btn op-btn-secondary"
onClick={() => emailList.length > 0 && sendEmail()}
>
Send
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={() => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}}
>
Close
</button>
</div>
</ModalUi>
)}
</div>
);
+56 -47
View File
@@ -29,7 +29,6 @@ function Header({
isShowHeader,
decline,
currentSigner,
dataTut4,
alreadySign,
isSignYourself,
setIsEmail,
@@ -53,7 +52,7 @@ function Header({
};
return (
<div style={{ padding: "5px 0px 5px 0px" }} className="mobileHead">
<div className="flex py-[5px]">
{isMobile && isShowHeader ? (
<div
id="navbar"
@@ -67,7 +66,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 +79,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 +98,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-arrow-down mr-[2px]"
className="fa-light fa-arrow-down mr-[3px]"
aria-hidden="true"
></i>
Download
@@ -114,7 +116,7 @@ function Header({
>
<div className="border-none bg-[#fff]">
<i
className="fa-solid fa-award mr-[2px]"
className="fa-light fa-award mr-[3px]"
aria-hidden="true"
></i>
Certificate
@@ -128,7 +130,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-envelope mr-[2px]"
className="fa-light fa-envelope mr-[3px]"
aria-hidden="true"
></i>
Mail
@@ -143,7 +145,7 @@ function Header({
>
<div className="flex flex-row">
<i
className="fa fa-print mr-[2px]"
className="fa-light fa-print mr-[3px]"
aria-hidden="true"
></i>
Print
@@ -177,7 +179,7 @@ function Header({
className={`${
isMailSend ? "" : "op-link-primary"
} op-link no-underline font-[650] text-[14px]`}
data-tut={dataTut4}
data-tut="headerArea"
>
{completeBtnTitle ? completeBtnTitle : "Send"}
</div>
@@ -198,9 +200,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 +223,7 @@ function Header({
}
>
<i
className="fa fa-arrow-down mr-[5px]"
className="fa-light fa-arrow-down mr-[3px]"
aria-hidden="true"
></i>
<span className="font-[500]">Download</span>
@@ -236,7 +238,7 @@ function Header({
</div>
</div>
) : (
<div className="flex flex-wrap justify-between items-center mt-[5px]">
<div className="flex flex-wrap justify-between items-center w-full gap-y-1 ml-1">
<PrevNext
pageNumber={pageNumber}
allPages={allPages}
@@ -267,22 +269,22 @@ function Header({
{setIsEditTemplate && (
<button
onClick={() => setIsEditTemplate(true)}
className="outline-none border-none text-center mr-[5px]"
className="outline-none border-none text-center mr-[3px]"
>
<i className="fa-solid fa-gear fa-lg"></i>
<i className="fa-light fa-gear fa-lg"></i>
</button>
)}
<button
onClick={() => navigate(-1)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
</button>
<button
disabled={isMailSend && true}
data-tut="reactourFour"
className="op-btn op-btn-primary op-btn-sm mr-[5px]"
data-tut="headerArea"
className="op-btn op-btn-primary op-btn-sm mr-[3px]"
onClick={() => alertSendEmail()}
>
{completeBtnTitle
@@ -302,10 +304,10 @@ function Header({
onClick={() =>
handleDownloadCertificate(pdfDetails, setIsDownloading)
}
className="op-btn op-btn-secondary op-btn-sm mr-[5px] shadow"
className="op-btn op-btn-secondary op-btn-sm mr-[3px] 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>
@@ -315,20 +317,26 @@ function Header({
<button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[5px] shadow"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] 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>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[5px] shadow"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
onClick={() =>
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>
@@ -337,21 +345,21 @@ function Header({
<button
onClick={() => navigate(-1)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
</button>
{currentSigner && (
<>
<button
className="op-btn op-btn-secondary op-btn-sm mr-[5px] shadow"
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
onClick={() => handleDeclinePdfAlert()}
>
Decline
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[5px] shadow"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
onClick={() => embedWidgetsData()}
>
Finish
@@ -362,7 +370,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 +390,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
@@ -399,37 +410,37 @@ function Header({
onClick={() =>
handleDownloadCertificate(pdfDetails, setIsDownloading)
}
className="op-btn op-btn-secondary op-btn-sm font-medium text-[13px] mr-[5px] shadow"
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa-solid fa-award" aria-hidden="true"></i>
<span className="hidden lg:block">Certificate</span>
<i className="fa-light fa-award" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Certificate</span>
</button>
)}
<button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
type="button"
className="op-btn op-btn-neutral op-btn-sm font-medium text-[13px] mr-[5px] shadow"
className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa fa-print" aria-hidden="true"></i>
<span className="hidden lg:block">Print</span>
<i className="fa-light fa-print" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Print</span>
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm font-medium text-[13px] mr-[5px] shadow"
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa fa-download" aria-hidden="true"></i>
<span className="hidden lg:block">Download</span>
<i className="fa-light fa-download" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Download</span>
</button>
<button
type="button"
className="op-btn op-btn-info op-btn-sm font-medium text-[13px] mr-[5px] shadow"
className="op-btn op-btn-info op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
onClick={() => setIsEmail(true)}
>
<i className="fa fa-envelope" aria-hidden="true"></i>
<span className="hidden lg:block">Mail</span>
<i className="fa-light fa-envelope" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Mail</span>
</button>
</div>
) : (
@@ -437,13 +448,13 @@ function Header({
<button
onClick={() => navigate(-1)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[5px]"
className="op-btn op-btn-primary op-btn-sm mr-[3px]"
onClick={() => {
if (!pdfUrl) {
embedWidgetsData();
@@ -474,10 +485,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-magnifying-glass-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;
+138 -41
View File
@@ -5,7 +5,7 @@ import { Rnd } from "react-rnd";
import {
defaultWidthHeight,
handleCopyNextToWidget,
isMobile,
isTabAndMobile,
onChangeInput,
radioButtonWidget,
textInputWidget,
@@ -88,8 +88,10 @@ 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 [containerScale, setContainerScale] = useState();
const [selectDate, setSelectDate] = useState({
date:
props.pos.type === "date"
@@ -119,6 +121,14 @@ function Placeholder(props) {
width: null,
height: null
});
useEffect(() => {
const getPdfPageWidth = props.pdfOriginalWH.find(
(data) => data.pageNumber === props.pageNumber
);
setContainerScale(props.containerWH.width / getPdfPageWidth.width);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.containerWH.width, props.pdfOriginalWH]);
const dateFormatArr = [
"L",
"DD-MM-YYYY",
@@ -293,12 +303,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 +400,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 +418,7 @@ function Placeholder(props) {
e.stopPropagation();
handleOnClickSettingIcon();
}}
className="fa-solid fa-gear settingIcon"
className="fa-light fa-gear icon"
style={{
color: "#188ae2",
right: "29px",
@@ -395,9 +428,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 +439,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 icon"
style={{
color: "#188ae2",
right: props?.pos?.type === textWidget ? "32px" : "47px",
top: "-19px"
}}
></i>
)
)}
@@ -417,7 +452,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 icon"
onClick={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
@@ -441,11 +476,7 @@ function Placeholder(props) {
top: "-19px",
right: props.isPlaceholder ? "60px" : "44px"
}}
className={
isShowDateFormat
? "dropdown signUserIcon show"
: "dropdown signUserIcon"
}
className={`${isShowDateFormat ? "show" : ""} dropdown icon`}
onClick={(e) => {
setIsShowDateFormat(!isShowDateFormat);
e.stopPropagation();
@@ -464,7 +495,7 @@ function Placeholder(props) {
}}
>
<i
className="fa-solid fa-gear settingIcon"
className="fa-light fa-gear icon"
style={{
color: "#188ae2",
fontSize: "14px"
@@ -492,8 +523,7 @@ function Placeholder(props) {
setSelectDate(data);
handleSaveDate(data);
}}
className="dropdown-item itemColor"
style={{ fontSize: "12px" }}
className="dropdown-item text-[13px]"
>
{data?.date ? data?.date : "nodata"}
</span>
@@ -503,13 +533,13 @@ function Placeholder(props) {
</div>
)}
<i
className="fa-regular fa-copy signCopy"
className="fa-light fa-copy icon"
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 icon"
onClick={(e) => {
e.stopPropagation();
@@ -535,6 +565,61 @@ function Placeholder(props) {
)
);
};
const xPos = (pos, signYourself) => {
const getPdfPageWidth = props.pdfOriginalWH.find(
(data) => data.pageNumber === props.pageNumber
);
const containerScale = props.containerWH.width / getPdfPageWidth?.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 getPdfPageWidth = props.pdfOriginalWH.find(
(data) => data.pageNumber === props.pageNumber
);
const containerScale = props.containerWH.width / getPdfPageWidth.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 +705,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 +731,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 +768,23 @@ 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 "
className="flex items-stretch"
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 +793,7 @@ function Placeholder(props) {
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
onClick={() => handleOnClickPlaceholder()}
>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
@@ -723,6 +818,7 @@ function Placeholder(props) {
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
/>
</div>
) : (
@@ -749,6 +845,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 (
@@ -36,7 +47,7 @@ function PlaceholderBorder(props) {
onTouchEnd={() =>
props.pos.type === textWidget && props?.setDraggingEnabled(true)
}
className="borderResize"
className="absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize"
style={{
borderColor: themeColor,
borderStyle: "dashed",
@@ -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,
@@ -2,7 +2,6 @@ import React, { useEffect, useState, forwardRef, useRef } from "react";
import {
getMonth,
getYear,
isMobile,
onChangeHeightOfTextArea,
onChangeInput,
radioButtonWidget,
@@ -14,7 +13,10 @@ import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import "../../styles/signature.css";
import RegexParser from "regex-parser";
const textWidgetCls =
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center bg-base-100 whitespace-pre-wrap";
const selectWidgetCls =
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none bg-base-100 text-base-content";
function PlaceholderType(props) {
const type = props?.pos?.type;
const [selectOption, setSelectOption] = useState("");
@@ -137,13 +139,13 @@ function PlaceholderType(props) {
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
<div
className="inputPlaceholder"
style={{ overflow: "hidden", fontSize: calculateFontSize() }}
className={`${selectWidgetCls} overflow-hidden`}
style={{ fontSize: calculateFontSize() }}
onClick={onClick}
ref={ref}
>
{value}
<i className="fa-regular fa-calendar" style={{ marginLeft: "5px" }}></i>
<i className="fa-light fa-calendar ml-[5px]"></i>
</div>
));
ExampleCustomInput.displayName = "ExampleCustomInput";
@@ -304,17 +306,13 @@ function PlaceholderType(props) {
case "signature":
return props.pos.SignUrl ? (
<img
alt="signimg"
alt="signature"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
className="w-full h-full "
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
<div className="text-[11px] w-full h-full text-black flex flex-col justify-center items-center">
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
@@ -326,17 +324,13 @@ function PlaceholderType(props) {
case "stamp":
return props.pos.SignUrl ? (
<img
alt="signimg"
alt="stamp"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
className="w-full h-full"
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
<div className="text-[11px] w-full h-full text-black flex flex-col justify-center items-center">
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
@@ -417,19 +411,20 @@ function PlaceholderType(props) {
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap", color: "initial" }}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
fontSize: "12px"
}}
>
<span>{type}</span>
@@ -438,9 +433,8 @@ function PlaceholderType(props) {
case "dropdown":
return props.data?.signerObjId === props.signerObjId ? (
<select
className="inputPlaceholder"
className={`${selectWidgetCls} text-[12px]`}
id="myDropdown"
style={{ fontSize: "12px", color: "initial" }}
value={selectOption}
onChange={(e) => {
setSelectOption(e.target.value);
@@ -460,7 +454,7 @@ function PlaceholderType(props) {
{props?.pos?.options?.name}
</option>
{props.pos?.options?.values.map((data, ind) => {
{props.pos?.options?.values?.map((data, ind) => {
return (
<option key={ind} value={data}>
{data}
@@ -470,7 +464,7 @@ function PlaceholderType(props) {
</select>
) : (
<div
className="inputPlaceholder"
className={selectWidgetCls}
style={{ fontSize: calculateFontSize() }}
>
{props.pos?.options?.name ? props.pos.options.name : type}
@@ -479,17 +473,13 @@ function PlaceholderType(props) {
case "initials":
return props.pos.SignUrl ? (
<img
alt="signimg"
alt="initials"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
className="w-full h-full"
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
<div className="text-[11px] w-full h-full text-black flex flex-col justify-center items-center">
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
@@ -520,19 +510,20 @@ function PlaceholderType(props) {
isDefault
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap", color: "initial" }}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
fontSize: "12px"
}}
>
<span>{type}</span>
@@ -559,19 +550,20 @@ function PlaceholderType(props) {
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap", color: "initial" }}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
fontSize: "12px"
}}
>
<span>{type}</span>
@@ -598,19 +590,20 @@ function PlaceholderType(props) {
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap", color: "initial" }}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
fontSize: "12px"
}}
>
<span>{type}</span>
@@ -655,8 +648,7 @@ function PlaceholderType(props) {
}
onBlur={handleInputBlur}
closeOnScroll={true}
className="inputPlaceholder"
style={{ outlineColor: "#007bff" }}
className={`${selectWidgetCls} outline-[#007bff]`}
selected={
props?.startDate
? props?.startDate
@@ -679,17 +671,13 @@ function PlaceholderType(props) {
case "image":
return props.pos.SignUrl ? (
<img
alt="signimg"
alt="image"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
className="w-full h-full"
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
<div className="text-[11px] w-full h-full text-black flex flex-col justify-center items-center">
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
@@ -720,19 +708,20 @@ function PlaceholderType(props) {
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap", color: "initial" }}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
fontSize: "12px"
}}
>
<span>{type}</span>
@@ -745,11 +734,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 &&
@@ -791,41 +778,28 @@ function PlaceholderType(props) {
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
className={textWidgetCls}
style={{
whiteSpace: "pre-wrap",
overflow: "hidden",
color: "initial"
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
}}
cols="50"
/>
);
default:
return props.pos.SignUrl ? (
<div style={{ pointerEvents: "none" }}>
<div className="pointer-events-none">
<img
alt="signimg"
alt="image"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
className="w-full h-full"
/>
</div>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
<div className="text-[11px] w-full h-full text-black flex flex-col justify-center items-center">
{props.pos.isStamp ? <div>stamp</div> : <div>signature</div>}
{props?.handleUserName &&
props?.handleUserName(props?.data?.Id, props?.data?.Role)}
+7 -7
View File
@@ -13,27 +13,27 @@ function PrevNext({ pageNumber, allPages, changePage }) {
return (
<div className="flex items-center">
<button
className="op-btn op-btn-secondary op-btn-xs md:op-btn-sm font-semibold text-xs"
className="op-btn op-btn-neutral op-btn-xs md:op-btn-sm font-semibold text-xs"
disabled={pageNumber <= 1}
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
className="op-btn op-btn-secondary op-btn-xs md:op-btn-sm font-semibold text-xs"
className="op-btn op-btn-neutral op-btn-xs md:op-btn-sm font-semibold text-xs"
disabled={pageNumber >= allPages}
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 &&
@@ -91,7 +89,7 @@ const RecipientList = (props) => {
onDrop={(e) =>
props.sendInOrder && !isMobile && handleChangeSequence(e, ind)
}
data-tut="reactourFirst"
data-tut="recipientArea"
onMouseEnter={() => setIsHover(ind)}
onMouseLeave={() => setIsHover(null)}
className={`${
@@ -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>
)}
@@ -209,7 +209,7 @@ const RecipientList = (props) => {
</div>
</div>
{isMobile && props.sendInOrder && (
<div className="flex flex-row items-center gap-[5px]">
<div className="flex flex-row items-center gap-[5px] mr-2">
<div
onClick={(e) => {
if (ind !== 0) {
@@ -249,9 +249,9 @@ const RecipientList = (props) => {
props.isSelectListId === ind
? "text-[#424242]"
: "text-base-content"
} cursor-pointer ml-[5px]`}
} cursor-pointer`}
>
<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,55 @@ 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 w-[20%] bg-base-100 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>
);
+161 -225
View File
@@ -11,8 +11,6 @@ import Alert from "../../primitives/Alert";
function RenderPdf({
pageNumber,
pdfOriginalWidth,
pdfNewWidth,
drop,
signerPos,
successEmail,
@@ -26,15 +24,13 @@ function RenderPdf({
pdfDetails,
xyPostion,
pdfUrl,
numPages,
pageDetails,
pdfRequest,
setCurrentSigner,
signerObjectId,
signedSigners,
setPdfLoadFail,
pdfLoad,
setPdfLoad,
placeholder,
pdfLoadFail,
setSignerPos,
setXyPostion,
index,
@@ -57,165 +53,90 @@ function RenderPdf({
unSignedWidgetId,
setIsCheckbox,
handleNameModal,
handleTextSettingModal,
setTempSignerId,
uniqueId
uniqueId,
pdfOriginalWH,
scale
}) {
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 getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH.width / getPdfPageWidth.width || 1;
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 getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
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 +152,6 @@ function RenderPdf({
</React.Fragment>
);
};
return (
checkSign.length === 0 &&
data.placeHolder.map((placeData, key) => {
@@ -258,8 +178,6 @@ function RenderPdf({
isShowDropdown={true}
isNeedSign={true}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
handleUserName={handleAllUserName}
@@ -271,6 +189,11 @@ function RenderPdf({
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
uniqueId={uniqueId}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
/>
</React.Fragment>
)
@@ -281,6 +204,7 @@ function RenderPdf({
})
);
};
//function for render placeholder block over pdf document
const handleUserName = (Id, Role, type) => {
if (Id) {
@@ -316,26 +240,25 @@ function RenderPdf({
);
}
};
return (
<>
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{isMobile && scale ? (
{isMobile ? (
<div
data-tut="reactourForth"
style={{
border: "0.1px solid #ebe8e8",
marginTop: isGuestSigner && "30px"
}}
className={`${
isGuestSigner ? "30px" : ""
} border-[0.1px] border-[#ebe8e8]`}
ref={drop}
id="container"
>
{pdfLoadFail.status &&
{containerWH?.width &&
pdfOriginalWH.length > 0 &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSignes(data)}
{checkSignedSigners(data)}
</React.Fragment>
);
})
@@ -374,8 +297,6 @@ function RenderPdf({
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
@@ -391,6 +312,13 @@ function RenderPdf({
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
/>
</React.Fragment>
);
@@ -422,13 +350,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 +366,12 @@ function RenderPdf({
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
/>
)
);
@@ -452,7 +383,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={() => {
setPdfLoad(false);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
// ref={pdfRef}'
@@ -469,19 +402,16 @@ 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
key={index}
pageNumber={pageNumber}
width={containerWH.width}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
</Document>
</div>
</div>
@@ -490,29 +420,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) => {
{pdfLoad &&
containerWH?.width &&
pdfOriginalWH.length > 0 &&
(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 +479,6 @@ function RenderPdf({
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
@@ -564,6 +494,13 @@ function RenderPdf({
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
/>
</React.Fragment>
);
@@ -575,53 +512,55 @@ 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}
pageNumber={pageNumber}
/>
</React.Fragment>
);
})}
</React.Fragment>
@@ -631,11 +570,7 @@ function RenderPdf({
{/* this component for render pdf document is in middle of the component */}
<Document
onLoadError={() => {
const load = {
status: false,
type: "failed"
};
setPdfLoadFail(load);
pdfLoad(false);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
@@ -653,17 +588,18 @@ 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
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>
+24 -12
View File
@@ -61,7 +61,6 @@ function SignPad({
} else if (isStamp) {
setImage("");
}
setIsSignImg("");
} else if (isTab === "uploadImage") {
setImage("");
@@ -69,11 +68,10 @@ function SignPad({
// setIsInitial(false);
};
//function for set signature url
const handleSignatureChange = () => {
setSignature(canvasRef.current.toDataURL());
setIsSignImg(canvasRef.current.toDataURL());
const handleSignatureChange = (data) => {
setSignature(data);
setIsSignImg(data);
};
//save button component
const SaveBtn = () => {
return (
@@ -103,6 +101,8 @@ function SignPad({
setIsSignImg("");
onSaveSign(null, false, textWidth, textHeight);
} else {
setIsSignImg("");
canvasRef.current.clear();
onSaveSign(signatureType);
}
}
@@ -127,6 +127,16 @@ function SignPad({
? ""
: "pointer-events-none"
} op-btn op-btn-primary shadow-lg`}
disabled={
(isTab === "draw" && isSignImg) ||
(isTab === "image" && image) ||
(isTab === "mysignature" && isDefaultSign) ||
(isTab === "type" && textWidth)
? false
: image
? false
: true
}
>
Save
</button>
@@ -193,7 +203,6 @@ function SignPad({
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isTab]);
//function for convert input text value in image
const convertToImg = async (fontStyle, text, color) => {
//get text content to convert in image
@@ -271,7 +280,7 @@ function SignPad({
}
}}
key={key}
className="fa solid fa-pen-nib"
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
@@ -304,6 +313,9 @@ function SignPad({
setIsImageSelect(false);
setIsTab("draw");
setImage();
if (isSignImg) {
setSignature(isSignImg);
}
}}
className={`${
isTab === "draw"
@@ -472,8 +484,8 @@ function SignPad({
ref={imageRef}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
<div className="text-[10px]">Upload</div>
</div>
</div>
) : (
@@ -509,7 +521,7 @@ function SignPad({
) : isTab === "type" ? (
<div>
<div className="flex justify-between items-center">
<span className="signatureText">
<span className="mr-[5px] text-[12px]">
{isInitial ? "Initials" : "Signature"}:
</span>
<input
@@ -525,7 +537,7 @@ function SignPad({
}}
/>
</div>
<div className="fontOptionContainer">
<div className="border-[1px] border-[#d6d3d3] mt-[10px] ml-[5px]">
{fontOptions.map((font, ind) => {
return (
<div
@@ -577,7 +589,7 @@ function SignPad({
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
handleSignatureChange(canvasRef.current?.toDataURL())
}
dotSize={1}
/>
+7 -3
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>
@@ -19,8 +19,12 @@ function Signedby({ pdfDetails }) {
</span>
</div>
<div className="flex flex-col">
<span className="userName">{pdfDetails.ExtUserPtr.Name}</span>
<span className="useEmail">{pdfDetails.ExtUserPtr.Email}</span>
<span className="text-[12px] font-bold text-[#424242] w-[100px] whitespace-nowrap overflow-hidden text-ellipsis">
{pdfDetails.ExtUserPtr.Name}
</span>
<span className="text-[10px] font-medium text-[#424242] w-[100px] whitespace-nowrap overflow-hidden text-ellipsis">
{pdfDetails.ExtUserPtr.Email}
</span>
</div>
</div>
</div>
@@ -0,0 +1,53 @@
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="text-[12px] font-bold text-[#424242] w-[100px] whitespace-nowrap overflow-hidden text-ellipsis">
{props.obj?.Name || props?.obj?.Role}
</span>
<span className="text-[10px] font-medium text-[#424242] w-[100px] whitespace-nowrap overflow-hidden text-ellipsis">
{props.obj?.Email || props.obj?.email}
</span>
</div>
</div>
);
}
export default SignerListComponent;
@@ -6,19 +6,21 @@ function SignerListPlace(props) {
return (
<div>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span>
<span className="relative">
{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-[1px] 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,21 +63,21 @@ 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
role="button"
data-tut="reactourAddbtn"
data-tut="addRecipient"
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
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;
@@ -250,15 +250,14 @@ function WidgetComponent({
{isMobile ? (
!isMailSend && (
<div
data-tut={dataTut}
id="navbar"
className="stickyfooter"
className="fixed z-[99] bottom-0 right-0"
style={{ width: window.innerWidth + "px" }}
>
<div className="mx-1">
{isSigners && (
<div
data-tut={dataTut}
data-tut="recipientArea"
className="py-[10px] flex justify-center items-center op-card"
style={{
background: blockColor
@@ -297,7 +296,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,23 +309,24 @@ 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>
) : (
setIsAddSigner && (
<div
data-tut="reactourAddbtn"
data-tut="addRecipient"
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>
)
)}
</div>
<div
data-tut="addWidgets"
ref={scrollContainerRef}
className="bg-base-100 border-[2px] border-t-primary"
>
@@ -349,12 +349,16 @@ 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"
data-tut="addWidgets"
>
<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
@@ -27,10 +27,12 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
FolderQuery.equalTo("CreatedBy", Parse.User.current());
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
FolderQuery.equalTo("CreatedBy", Parse.User.current());
}
const res = await FolderQuery.find();
@@ -118,13 +120,13 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<Loader />
</div>
)}
<h1 className="text-base font-semibold">Create Folder</h1>
<h1 className="text-base font-semibold mt-[0.4rem]">Create Folder</h1>
<div className="text-xs mt-2">
<label className="block">
Name<span className="text-red-500 text-[13px]">*</span>
</label>
<input
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={name}
onChange={(e) => setName(e.target.value)}
required
@@ -135,7 +137,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<select
value={selectedParent}
onChange={handleOptions}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
>
<option>select</option>
{folderList.length > 0 &&
@@ -150,9 +152,9 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<button
onClick={handleCreateFolder}
disabled={isLoader}
className="flex items-center rounded p-2 bg-[#32a3ac] text-white mt-3"
className="op-btn op-btn-primary op-btn-sm mt-3"
>
<i className="fa-solid fa-plus mr-1"></i>
<i className="fa-light fa-plus"></i>
<span>Create</span>
</button>
</div>
@@ -24,12 +24,14 @@ 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);
FolderQuery.equalTo("CreatedBy", Parse.User.current());
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
FolderQuery.descending("Type");
FolderQuery.notEqualTo("IsArchive", true);
FolderQuery.equalTo("CreatedBy", Parse.User.current());
}
const res = await FolderQuery.find();
@@ -143,14 +145,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 +173,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 +226,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 +235,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>
@@ -44,12 +44,14 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
const FolderQuery = new Parse.Query(folderCls);
if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
FolderQuery.descending("Type");
FolderQuery.equalTo("CreatedBy", Parse.User.current());
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
FolderQuery.descending("Type");
FolderQuery.equalTo("CreatedBy", Parse.User.current());
}
const res = await FolderQuery.find();
@@ -174,14 +176,16 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<div className="relative max-w-sm">
<div
onClick={() => SetIsOpen(true)}
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"
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-[#33bbff]"
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 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>
</div>
<div className="font-semibold ">
<div className="flex items-center gap-2">
@@ -190,12 +194,9 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
? selectFolder.Name
: "OpenSign™ Drive"}
</p>
<div
className="text-black text-sm"
// onClick={() => SetIsOpen(true)}
>
<div className="text-black text-sm">
<i
className="fa fa-pencil cursor-pointer"
className="fa-light fa-pencil cursor-pointer"
title="Select Folder"
aria-hidden="true"
></i>
@@ -220,7 +221,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
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"
@@ -241,27 +242,50 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
{" / "}
</React.Fragment>
))}
<hr />
<hr className="bg-[#8a8a8a] mt-[0.750rem]" />
</div>
<div className="mt-2 mb-3">
<div className="mb-2">
<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
@@ -271,8 +295,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>
@@ -280,22 +304,28 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<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>
@@ -1,6 +1,5 @@
import React, { useState } from "react";
import Parse from "parse";
import "../../../styles/AddUser.css";
import AsyncSelect from "react-select/async";
const SelectSigners = (props) => {
@@ -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-[999] 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>
+323 -305
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,15 +376,15 @@ 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">
{!isMobile && <i className="fa-light fa-grip-vertical ml-[3px]"></i>}
<span className="md:inline-block text-center text-[15px] ml-[5px] font-semibold pr-1 md:pr-0">
{item.type}
</span>
</div>
<div className="text-[20px] op-btn op-btn-primary w-[40px] h-full flex justify-center items-center">
<div className="text-[20px] op-btn op-btn-primary rounded-none w-[40px] h-full flex justify-center items-center">
<i className={item.icon}></i>
</div>
</div>
@@ -421,9 +419,9 @@ 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 };
return { width: 150, height: 25 };
default:
return { width: 150, height: 60 };
}
@@ -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
};
}
@@ -942,7 +942,23 @@ export const onChangeHeightOfTextArea = (
setXyPostion(updatePlaceholder);
}
};
//calculate width and height
export const calculateInitialWidthHeight = (widgetData) => {
const intialText = widgetData;
const span = document.createElement("span");
span.textContent = intialText;
span.style.font = `14px`; // here put your text size and font family
span.style.display = "hidden";
document.body.appendChild(span);
const width = span.offsetWidth;
const height = span.offsetHeight;
document.body.removeChild(span);
return {
getWidth: width,
getHeight: height
};
};
export const addInitialData = (signerPos, setXyPostion, value, userId) => {
function widgetDataValue(type) {
switch (type) {
@@ -991,9 +1007,13 @@ export const addInitialData = (signerPos, setXyPostion, value, userId) => {
options: {
...item.options,
defaultValue: widgetData
},
Width: calculateInitialWidthHeight(item.type, widgetData).getWidth,
Height: calculateInitialWidthHeight(item.type, widgetData).getHeight
}
// Width:
// calculateInitialWidthHeight(item.type, widgetData).getWidth ||
// item?.Width,
// Height:
// calculateInitialWidthHeight(item.type, widgetData).getHeight ||
// item?.Height
};
} else {
return {
@@ -1004,24 +1024,6 @@ export const addInitialData = (signerPos, setXyPostion, value, userId) => {
});
};
//calculate width and height
export const calculateInitialWidthHeight = (type, widgetData) => {
const intialText = widgetData;
const span = document.createElement("span");
span.textContent = intialText;
span.style.font = `14px`; // here put your text size and font family
span.style.display = "hidden";
document.body.appendChild(span);
const width = span.offsetWidth;
const height = span.offsetHeight;
document.body.removeChild(span);
return {
getWidth: width,
getHeight: height
};
};
//function for embed document id
export const embedDocId = async (pdfDoc, documentId, allPages) => {
for (let i = 0; i < allPages; i++) {
@@ -1178,7 +1180,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 +1226,15 @@ export const changeImageWH = async (base64Image) => {
//function for embed multiple signature using pdf-lib
export const multiSignEmbed = async (
pngUrl,
xyPositionArray,
pdfDoc,
pdfOriginalWidth,
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 +1246,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 +1260,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 +1287,36 @@ 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);
widgetHeight = placeholderHeight(position);
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 +1329,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 +1349,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 +1391,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 +1464,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 +1491,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 +1579,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 +1915,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 +2076,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()
};
}
+56
View File
@@ -15,3 +15,59 @@ body {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
/* below css class replace bootstrap background color with daisy */
.op-bg-primary {
@apply bg-primary;
}
.op-bg-secondary {
@apply bg-secondary;
}
.op-bg-info {
@apply bg-info;
}
.op-bg-success{
@apply bg-success;
}
.op-bg-warning {
@apply bg-warning;
}
/* below css class replace bootstrap text color with daisy */
.op-text-primary {
@apply text-primary;
}
.op-text-secondary {
@apply text-secondary;
}
.op-text-info {
@apply text-info;
}
.op-text-success{
@apply text-success;
}
.op-text-warning {
@apply text-warning;
}
.op-border-primary{
@apply border-primary
}
/* CSS for scrollbar customization */
* {
scrollbar-width: thin; /* For Firefox */
scrollbar-color: gray; /* For Firefox */
}
/* For webkit-based browsers like Chrome, Safari */
*::-webkit-scrollbar {
width: 5px;
}
*::-webkit-scrollbar-track {
background-color: transparent;
}
*::-webkit-scrollbar-thumb {
background-color: gray;
border-radius: 10px;
}
+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"
}
+4 -4
View File
@@ -6,8 +6,8 @@ const dashboardJson = [
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-signature",
bgColor: "bg-[#f0058e]",
icon: "fa-light fa-signature",
bgColor: "op-bg-primary",
label: "Need your Signature",
description: null,
data: {
@@ -29,8 +29,8 @@ const dashboardJson = [
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-sign-out-alt",
bgColor: "bg-[#2ed8b6]",
icon: "fa-light fa-sign-out-alt",
bgColor: "op-bg-secondary",
label: "Out for signatures",
description: null,
data: {
+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);
}
};
+6 -3
View File
@@ -49,8 +49,8 @@ function ChangePassword() {
return <Navigate to="/" />;
}
return (
<div className="w-full bg-base-100 text-base-content shadow rounded p-2">
<Title title={"Change Password"} />
<div className="w-full bg-base-100 text-base-content shadow rounded-box p-2">
<Title title="Change Password" />
<div className="text-xl font-bold border-b-[1px] border-gray-300">
Change Password
</div>
@@ -98,7 +98,10 @@ function ChangePassword() {
required
/>
</div>
<button type="submit" className="op-btn op-btn-primary shadow-md m-2">
<button
type="submit"
className="op-btn op-btn-primary shadow-md mt-2"
>
Change Password
</button>
</form>
-1
View File
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import "../styles/loader.css";
import GetDashboard from "../components/dashboard/GetDashboard";
import { useNavigate, useParams } from "react-router-dom";
import Title from "../components/Title";
+31 -109
View File
@@ -1,7 +1,5 @@
import React, { useEffect, useState } from "react";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import "../styles/signature.css";
import "../styles/AddUser.css";
import Title from "../components/Title";
import RenderDebugPdf from "../components/RenderDebugPdf";
import { pdfjs } from "react-pdf";
@@ -58,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) => ({
@@ -76,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 });
@@ -217,14 +215,18 @@ const DebugPdf = () => {
};
return (
<div>
{copied && <Alert type="success">Copied</Alert>}
{copied && (
<Alert type="success">
<span className="ml-3">Copied</span>
</Alert>
)}
<Title title={"Debug Pdf"} />
{width < 800 ? (
<HandleError handleError={"Debug PDF only availble for PC"} />
) : (
<>
{!isModal && (
<div className="signatureContainer">
<div className="flex flex-row justify-between">
{/* this component used to render all pdf pages in left side */}
<RenderAllPdfPage
signPdfUrl={pdf}
@@ -253,126 +255,68 @@ const DebugPdf = () => {
/>
</div>
</div>
<div style={{ backgroundColor: "white", width: 220 }}>
<div
style={{
fontSize: 18,
fontWeight: 500,
padding: "10px 12px",
borderBottom: "1px solid grey"
}}
>
<div className="w-[220px] bg-base-100">
<div className="text-[18px] font-medium py-[10px] px-[12px] border-b-[1px] border-[gray]">
PDF details
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
Name: {pdfDetails?.name}
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
Pdf type: {pdfDetails?.pdftype}
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
Total Pages: {pdfDetails?.totalPages}
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
Current Page: {pdfDetails?.currentPage}
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
Base64 : {pdfDetails?.base64.slice(0, 10)}...
<span
style={{
borderRadius: 4,
padding: "3px 5px",
border: "1px solid gray",
fontSize: 12,
margin: 2,
cursor: "pointer"
}}
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
style={{
fontSize: 18,
fontWeight: 500,
padding: "10px 12px",
borderBottom: "1px solid grey"
}}
>
<div className="text-[18px] font-medium py-[10px] px-[12px] border-b-[1px] border-[gray]">
Last click
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
x co-ordinate: {pdfDetails?.x}
</div>
<div style={{ fontSize: 14, padding: "5px 12px" }}>
<div className="text-[14px] py-[5px] px-[12px]">
y co-ordinate: {pdfDetails?.y}
</div>
<div
style={{
fontSize: 18,
fontWeight: 500,
padding: "10px 12px",
borderBottom: "1px solid grey",
borderTop: "1px solid grey"
}}
>
<div className="text-[18px] font-medium py-[10px] px-[12px] border-y-[1px] border-[gray]">
Annotation
</div>
<ul
style={{
listStyle: "none",
padding: 10,
height: 500,
overflowY: "auto",
scrollbarWidth: 5
}}
>
<ul className=" list-none p-[10px] h-[500px] overflow-y-auto">
{annotations.map((coord, index) => (
<li key={index}>
<span style={{ fontSize: 13, fontWeight: 500 }}>{`Box ${
<span className="text-[13px] font-medium">{`Box ${
index + 1
}:`}</span>
<code
style={{
fontSize: 12,
color: "black",
cursor: "pointer"
}}
>
<code className="text-[12px] text-base-content select-none">
{` ["page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`}
</code>
<div>
<span
style={{
borderRadius: 4,
padding: "3px 5px",
border: "1px solid gray",
fontSize: 12,
margin: 2,
cursor: "pointer"
}}
className="op-btn op-btn-outline op-btn-primary op-btn-xs rounded-md w-[23px] h-[20px] text-[12px] m-[2px] "
onClick={() =>
copytoclipboard(
`"page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}`
)
}
>
<i className="fa-solid fa-copy"></i>
<i className="fa-light fa-copy"></i>
</span>
<span
style={{
borderRadius: 4,
padding: "3px 5px",
border: "1px solid gray",
fontSize: 12,
margin: 2,
cursor: "pointer"
}}
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>
@@ -382,38 +326,16 @@ const DebugPdf = () => {
</div>
)}
<ModalUi title={"Select PDF"} isOpen={isModal}>
<form onSubmit={handleSubmit} style={{ margin: "10px" }}>
<form onSubmit={handleSubmit} className="m-[10px]">
<input
type="file"
onChange={(e) => handleFileChange(e.target.files)}
style={{
width: "100%",
border: "1px solid grey",
borderRadius: "4px",
padding: "5px",
fontSize: 12
}}
className="op-file-input op-file-input-bordered op-file-input-sm focus:outline-none hover:border-base-content w-full h-[40px] text-xs"
accept=".pdf"
required
/>
<div
style={{ borderTop: "1px solid grey", margin: "10px 0" }}
></div>
<button
style={{
background: "#32a3ac",
borderRadius: "2px",
boxShadow:
"0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18)",
border: "none",
textTransform: "uppercase",
fontSize: "13px",
fontWeight: "600",
padding: "0.375rem 0.75rem",
textAlign: "center",
color: "#ffffff",
outline: "none"
}}
className="op-btn op-btn-primary w-full mt-3 mb-1"
type="submit"
>
Submit
+19 -26
View File
@@ -445,7 +445,7 @@ const Forms = (props) => {
setIsSubmit(false);
}
} else {
alert("Please wait until the PDF has been uploading.");
alert("Please wait while the document is being uploaded.");
}
};
@@ -565,7 +565,7 @@ const Forms = (props) => {
setFormData((prev) => ({ ...prev, autoreminder: !formData.autoreminder }));
};
return (
<div className="shadow-md rounded my-2 p-3 bg-base-100 text-base-content md:border-[1px] md:border-gray-600/50">
<div className="shadow-md rounded-box my-[2px] p-3 bg-base-100 text-base-content">
<Title title={props?.title} />
{isAlert && (
<Alert type={isErr ? "danger" : "success"}>
@@ -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 && (
@@ -701,15 +701,17 @@ const Forms = (props) => {
required
/>
</div>
<div className="text-xs mt-2">
<label className="block">Description</label>
<input
name="Description"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.Description}
onChange={(e) => handleStrInput(e)}
/>
</div>
{props.title === "New Template" && (
<div className="text-xs mt-2">
<label className="block">Description</label>
<input
name="Description"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.Description}
onChange={(e) => handleStrInput(e)}
/>
</div>
)}
{props.signers && (
<SignersInput
onChange={handleSigners}
@@ -759,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-[1px] py-[1.5px] px-[4px]"></i>
</sup>
</a>
<Tooltip id="sendInOrder-tooltip" className="z-50">
@@ -841,7 +834,7 @@ const Forms = (props) => {
{!isEnableSubscription && (
<PremiumAlertHeader
message={
"Disable Auto reminder is free in beta, this feature will incur a fee later."
"Auto reminder is free in beta, this feature will incur a fee later."
}
/>
)}
+139 -151
View File
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from "react";
import Title from "../components/Title";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import Alert from "../primitives/Alert";
import ModalUi from "../primitives/ModalUi";
import { isEnableSubscription } from "../constant/const";
@@ -9,19 +8,24 @@ import { checkIsSubscribed, copytoData, openInNewTab } from "../constant/Utils";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
const tourSteps = [
{
selector: '[data-tut="apisubscribe"]',
content: "Upgrade now to generate API token"
}
];
function GenerateToken() {
const navigation = useNavigate();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [apiToken, SetApiToken] = useState("");
const [isLoader, setIsLoader] = useState(true);
const [copied, setCopied] = useState(false);
const [isGenerate, setIsGenerate] = useState(false);
const [isErr, setIsErr] = useState(false);
const [isModal, setIsModal] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTour, setIsTour] = useState(false);
useEffect(() => {
fetchToken();
// eslint-disable-next-line
@@ -33,7 +37,6 @@ function GenerateToken() {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
}
const url = parseBaseUrl + "functions/getapitoken";
const headers = {
"Content-Type": "application/json",
@@ -44,7 +47,6 @@ function GenerateToken() {
if (res) {
SetApiToken(res.data.result.result);
}
setIsLoader(false);
} catch (err) {
SetApiToken();
@@ -54,49 +56,43 @@ function GenerateToken() {
};
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoader(true);
setIsModal(false);
try {
const url = parseBaseUrl + "functions/generateapitoken";
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessiontoken: localStorage.getItem("accesstoken")
};
await axios.post(url, {}, { headers: headers }).then((res) => {
if (!isSubscribe && isEnableSubscription) {
setIsTour(true);
} else {
setIsLoader(true);
setIsModal(false);
try {
const url = parseBaseUrl + "functions/generateapitoken";
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessiontoken: localStorage.getItem("accesstoken")
};
const res = await axios.post(url, {}, { headers: headers });
if (res) {
SetApiToken(res.data.result.token);
// localStorage.setItem("apiToken", res.data.result.token);
setIsGenerate(true);
setTimeout(() => {
setIsGenerate(false);
}, 1500);
setIsLoader(false);
setIsAlert({ type: "success", msg: "Token generated successfully." });
} else {
console.error("Error while generating Token");
setIsLoader(false);
setIsErr(true);
setTimeout(() => {
setIsErr(false);
}, 1500);
setIsAlert({ type: "danger", msg: "Something went wrong." });
}
});
} catch (error) {
setIsLoader(false);
setIsErr(true);
setTimeout(() => {
setIsErr(false);
}, 1500);
console.log("err", error);
} catch (error) {
setIsAlert({ type: "danger", msg: "Something went wrong." });
console.log("while generating Token", error);
} finally {
setIsLoader(false);
setTimeout(() => {
setIsAlert({ type: "success", msg: "" });
}, 1500);
}
}
};
const copytoclipboard = (text) => {
copytoData(text);
setCopied(true);
setIsAlert({ type: "success", msg: "Copied" });
setTimeout(() => {
setCopied(false);
setIsAlert({ type: "success", msg: "" });
}, 1500); // Reset copied state after 1.5 seconds
};
const handleModal = () => setIsModal(!isModal);
@@ -104,132 +100,124 @@ function GenerateToken() {
return (
<React.Fragment>
<Title title={"API Token"} />
{isGenerate && (
<Alert type="success">Token generated successfully!</Alert>
{isAlert.msg && (
<Alert type={isAlert.type}>
<div className="ml-3">{isAlert.msg}</div>
</Alert>
)}
{copied && <Alert type="success">Copied</Alert>}
{isErr && <Alert type="danger">Something went wrong!</Alert>}
{isLoader ? (
<div className="flex justify-center items-center h-screen">
<Loader />
</div>
) : (
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded">
{!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign API{" "}
<Tooltip
url={
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
}
isSubscribe={true}
/>
</h1>
<ul
className={
isSubscribe || !isEnableSubscription
? "w-full flex flex-col p-2 text-sm "
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
}
>
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5 ">
<span className="">Api Token:</span>{" "}
<span id="token" className="md:text-end py-2 md:py-0">
<span
className="cursor-pointer"
onClick={() => copytoclipboard(apiToken)}
>
{apiToken ? apiToken : "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2"
onClick={() => copytoclipboard(apiToken)}
>
<i className="fa-solid fa-copy"></i>
</button>
</span>
</div>
<button
onClick={apiToken ? handleModal : handleSubmit}
className="op-btn op-btn-primary"
>
{apiToken ? "Regenerate Token" : "Generate Token"}
</button>
</li>
</ul>
<div className="flex items-center justify-center ">
<button
type="button"
onClick={() =>
openInNewTab(
<>
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
{!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign API{" "}
<Tooltip
url={
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
)
}
className="op-btn op-btn-secondary my-2"
}
isSubscribe={true}
/>
</h1>
<ul
className={"w-full flex flex-col p-2 text-sm"}
// isSubscribe || !isEnableSubscription
// ? "w-full flex flex-col p-2 text-sm "
// : "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
>
View Docs
</button>
</div>
{!isSubscribe && isEnableSubscription && (
<>
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
Upgrade to PRO Plan
</h1>
<ul className={"w-full flex flex-col p-2 text-sm "}>
<li
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
>
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
<span className="">$29.99/month:</span>{" "}
<span id="token" className=" md:text-end cursor-pointer">
Sign 100 docs using API. Only 0.15/docs after that.
</span>
</div>
{!isSubscribe && isEnableSubscription && (
<button
type="button"
onClick={() => navigation("/subscription")}
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
<span className="ml-1">API Token:</span>{" "}
<span
id="token"
className={`${
isSubscribe || !isEnableSubscription
? ""
: "bg-white/20 pointer-events-none select-none"
} md:text-end py-2 md:py-0`}
>
<span
className="cursor-pointer"
onClick={() => copytoclipboard(apiToken)}
>
Upgrade Now
{apiToken ? apiToken : "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
onClick={() => copytoclipboard(apiToken)}
>
<i className="fa-light fa-copy"></i>
</button>
)}
</li>
</ul>
</>
)}
<ModalUi
isOpen={isModal}
title={"Regenerate Token"}
handleClose={handleModal}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-base-content">
Are you sure you want to regenerate token it will expire old
token?
</div>
<hr className="bg-[#ccc] mt-4 " />
<div className="flex items-center mt-3 gap-2 text-white">
</span>
</div>
<button
onClick={handleSubmit}
className="op-btn op-btn-primary ml-[2px]"
onClick={apiToken ? handleModal : handleSubmit}
className="op-btn op-btn-primary"
>
Yes
{apiToken ? "Regenerate Token" : "Generate Token"}
</button>
<button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</li>
</ul>
<div className="flex items-center justify-center">
<button
type="button"
onClick={() =>
openInNewTab(
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
)
}
className="op-btn op-btn-secondary mt-2 mb-3 px-8"
>
View Docs
</button>
</div>
</ModalUi>
</div>
<ModalUi
isOpen={isModal}
title={apiToken ? "Regenerate Token" : "Generate Token"}
handleClose={handleModal}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-base-content">
Are you sure you want to regenerate token it will expire old
token?
</div>
<hr className="bg-[#ccc] mt-4" />
<div className="flex items-center mt-3 gap-2 text-white">
<button
onClick={handleSubmit}
className="op-btn op-btn-primary ml-[2px]"
>
Yes
</button>
<button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</div>
</ModalUi>
</div>
{!isSubscribe && isEnableSubscription && (
<div data-tut="apisubscribe">
<SubscribeCard />
</div>
)}
</>
)}
<Tour
onRequestClose={() => setIsTour(false)}
steps={tourSteps}
isOpen={isTour}
closeWithMask={false}
disableKeyboardNavigation={["esc"]}
scrollOffset={-100}
rounded={5}
/>
</React.Fragment>
);
}
+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 -1
View File
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import "../styles/loader.css";
import { useDispatch } from "react-redux";
import axios from "axios";
import Title from "../components/Title";
@@ -1104,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
@@ -1123,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
/>
+112 -160
View File
@@ -228,12 +228,7 @@ const ManageSign = () => {
}
}
};
const handleSignatureBtn = () => {
if (imageRef.current) {
imageRef.current.value = "";
}
setImage("");
};
const handleUploadBtn = () => {
imageRef.current.click();
};
@@ -242,166 +237,130 @@ const ManageSign = () => {
setIsValue(true);
};
return (
<div className="relative h-full bg-base-100 text-base-content flex shadow rounded overflow-auto">
<div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto">
{isLoader && (
<div className="absolute bg-black bg-opacity-30 z-50 w-full h-full flex justify-center items-center">
<Loader />
</div>
)}
{isAlert?.message && <Alert type={isAlert.type}>{isAlert.message}</Alert>}
<div
className="mainDiv"
style={{
width: "100%",
paddingRight: "10px"
}}
>
<div className="m-[20px]">
<div className="font-[700] text-[15px] pb-[8px]">My Signature</div>
<div className="signBlock mt-4">
<div>
<div className="relative w-full">
<div className="ml-[5px] my-[20px] md:m-[20px]">
<div className="text-[20px] font-semibold m-[10px] md:m-0 mb-2">
My Signature
</div>
<div className="flex flex-col md:flex-row gap-0 md:gap-[12px]">
<div className="relative">
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
Signature
</span>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
hidden
/>
<div className="relative">
<div className="flex flex-row justify-between w-1/2 pl-[10px]">
<div className="flex flex-row justify-around items-center gap-[10px] mb-[10px]">
<>
<span
onClick={() => handleSignatureBtn()}
className="signature"
>
Signature
</span>
</>
<span
onClick={() => handleUploadBtn()}
className="imgupload"
>
Upload Image
</span>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
hidden
/>
</div>
</div>
<div className="relative">
<div>
{image ? (
<div className="signatureCanvas relative border-[2px] border-[#888]">
<img
alt="preview image"
src={image}
className="w-full h-full object-contain"
/>
</div>
) : (
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
dotSize={1}
<div>
{image ? (
<div className="signatureCanvas relative border-[2px] border-[#888] rounded-box">
<img
alt="signature"
src={image}
className="w-full h-full object-contain"
/>
)}
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between"
</div>
) : (
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas rounded-box"
}}
className="penContainerDefault"
>
<div>
{!image && (
<div
style={{ display: "flex", flexDirection: "row" }}
>
{allColor.map((data, key) => {
return (
<i
style={{
margin: "5px",
color: data,
borderBottom:
key === 0 && penColor === "blue"
? "2px solid blue"
: key === 1 && penColor === "red"
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
setPenColor("blue");
} else if (key === 1) {
setPenColor("red");
} else if (key === 2) {
setPenColor("black");
}
}}
key={key}
className="fa solid fa-pen-nib"
width={20}
height={20}
></i>
);
})}
</div>
)}
</div>
<div>
<div
type="button"
className="clearbtn cursor-pointer"
onClick={() => handleClear()}
>
Clear
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
dotSize={1}
/>
)}
<div className="penContainerDefault flex flex-row justify-between">
<div>
{!image && (
<div className="flex flex-row">
{allColor.map((data, key) => {
return (
<i
style={{
margin: "5px",
color: data,
borderBottom:
key === 0 && penColor === "blue"
? "2px solid blue"
: key === 1 && penColor === "red"
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
setPenColor("blue");
} else if (key === 1) {
setPenColor("red");
} else if (key === 2) {
setPenColor("black");
}
}}
key={key}
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
);
})}
</div>
)}
</div>
<div className="flex flex-row gap-2 text-sm md:text-base mr-1">
<div
type="button"
className="op-link"
onClick={() => handleUploadBtn()}
>
Upload image
</div>
<div
type="button"
className="op-link"
onClick={() => handleClear()}
>
Clear
</div>
</div>
</div>
{warning && (
<div
className="warning signWarning"
style={{ fontSize: 12 }}
>
<i
className="fas fa-exclamation-circle"
style={{ color: "#fab005", fontSize: 15 }}
></i>{" "}
Please upload signature/Image
</div>
)}
</div>
{warning && (
<span className="customwarning signWarning text-[12px] w-[220px] md:w-[300px]">
<i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i>
Please upload signature/Image
</span>
)}
</div>
</div>
<div style={{ position: "relative" }}>
<div style={{ margin: "6px 5px 18px" }}>
<span className="signature">Initials</span>
</div>
<div className="relative">
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
Initials
</span>
<div>
{isInitials ? (
<div
style={{
position: "relative",
border: "2px solid #888"
}}
className="intialSignature"
>
<div className="intialSignature relative border-[1px] border-[#888] rounded-box overflow-hidden">
<img
alt="preview image"
alt="inititals"
src={Initials}
style={{
width: "100%",
@@ -415,7 +374,7 @@ const ManageSign = () => {
ref={initailsRef}
penColor={initialPen}
canvasProps={{
className: "intialSignature"
className: "intialSignature rounded-box"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
@@ -424,17 +383,10 @@ const ManageSign = () => {
dotSize={1}
/>
)}
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between"
}}
className="penContainerInitial"
>
<div className="flex flex-row justify-between w-[183px]">
<div>
{!isInitials && (
<div style={{ display: "flex", flexDirection: "row" }}>
<div className="flex flex-row">
{allColor.map((data, key) => {
return (
<i
@@ -460,7 +412,7 @@ const ManageSign = () => {
}
}}
key={key}
className="fa solid fa-pen-nib"
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
@@ -472,7 +424,7 @@ const ManageSign = () => {
<div>
<div
type="button"
className="clearbtn cursor-pointer"
className="op-link text-sm md:text-base mr-1"
onClick={() => handleClearInitials()}
>
Clear
@@ -482,7 +434,7 @@ const ManageSign = () => {
</div>
</div>
</div>
<div style={{ paddingTop: 10 }}>
<div className="pt-3 ml-2 md:ml-0">
<button
className="op-btn op-btn-primary"
onClick={(e) => handleSubmit(e)}
+27 -22
View File
@@ -522,7 +522,7 @@ function Opensigndrive() {
}
}
return (
<div className="bg-base-100 text-base-content rounded-xl w-full">
<div className="bg-base-100 text-base-content rounded-box w-full shadow-md">
<Title title={"OpenSign™ Drive"} drive={true} />
<ModalUi
isOpen={isAlert.isShow}
@@ -598,11 +598,13 @@ function Opensigndrive() {
{isLoading.isLoad ? (
<div className="flex flex-col justify-center items-center h-[100vh] w-full">
<Loader />
<span className="text-[13px] text-[gray]">{isLoading.message}</span>
<span className="text-[13px] text-base-content">
{isLoading.message}
</span>
</div>
) : handleError ? (
<div className="flex justify-center items-center h-[100vh] w-full">
<span className="text-[20px] text-[gray]">{handleError}</span>
<span className="text-[20px] text-base-content">{handleError}</span>
</div>
) : (
<>
@@ -625,7 +627,7 @@ function Opensigndrive() {
>
{handleFolderTab(folderName)}
</div>
<div className="dropMenuBD">
<div className="flex flex-row items-center">
<div
id="folder-menu"
className={
@@ -635,7 +637,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>
@@ -647,24 +649,27 @@ function Opensigndrive() {
>
<div className="flex flex-col">
<span
className="dropdown-item itemColor"
className="dropdown-item text-[10px] md:text-[13px]"
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"
className="dropdown-item text-[10px] md:text-[13px]"
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"
className="dropdown-item text-[10px] md:text-[13px]"
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 +686,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>
@@ -704,18 +709,18 @@ function Opensigndrive() {
setSelectedSort(value);
sortingData(value, null, pdfData);
}}
className="dropdown-item itemColor"
className="dropdown-item text-[10px] md:text-[13px]"
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>
);
})}
@@ -729,18 +734,18 @@ function Opensigndrive() {
setSortingOrder(order);
sortingData(null, order, pdfData);
}}
className="dropdown-item itemColor"
className="dropdown-item text-[10px] md:text-[13px]"
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 +757,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 +769,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>
+1 -1
View File
@@ -4,7 +4,7 @@ import Title from "../components/Title";
const PageNotFound = ({ prefix }) => {
return (
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded">
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box">
<Title title={"Page Not Found"} />
<div className="text-center">
<h1 className="text-[60px] lg:text-[120px] font-semibold">404</h1>
+330 -345
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("");
@@ -108,10 +110,7 @@ function PdfRequestFiles() {
});
const [myInitial, setMyInitial] = useState("");
const [isInitial, setIsInitial] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
});
const [pdfLoad, setPdfLoad] = useState(false);
const [isSigned, setIsSigned] = useState(false);
const [isExpired, setIsExpired] = useState(false);
const [alreadySign, setAlreadySign] = useState(false);
@@ -127,6 +126,10 @@ function PdfRequestFiles() {
const [isVerifyModal, setIsVerifyModal] = useState(false);
const [otp, setOtp] = useState("");
const [contractName, setContractName] = 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 +158,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();
@@ -173,7 +182,7 @@ function PdfRequestFiles() {
const localuser = localStorage.getItem(
`Parse/${appInfo.appId}/currentUser`
);
const currentUser = JSON.parse(JSON.stringify(localuser));
const currentUser = JSON.parse(localuser);
await handleSendOTP(currentUser?.email);
setOtpLoader(false);
alert("OTP sent on you email");
@@ -185,7 +194,7 @@ function PdfRequestFiles() {
const localuser = localStorage.getItem(
`Parse/${appInfo.appId}/currentUser`
);
const currentUser = JSON.parse(JSON.stringify(localuser));
const currentUser = JSON.parse(localuser);
try {
const resEmail = await Parse.Cloud.run("verifyemail", {
otp: otp,
@@ -206,14 +215,13 @@ function PdfRequestFiles() {
setOtpLoader(false);
}
};
//`handleVerifyBtn` function is used to send otp on user mail
const handleVerifyBtn = async () => {
setIsVerifyModal(true);
const localuser = localStorage.getItem(
`Parse/${appInfo.appId}/currentUser`
);
const currentUser = JSON.parse(JSON.stringify(localuser));
const currentUser = JSON.parse(localuser);
await handleSendOTP(currentUser?.email);
};
async function checkIsSubscribed(extUserId, contactId) {
@@ -320,6 +328,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/");
@@ -485,7 +500,7 @@ function PdfRequestFiles() {
const localuser = localStorage.getItem(
`Parse/${appInfo.appId}/currentUser`
);
const currentUser = JSON.parse(JSON.stringify(localuser));
const currentUser = JSON.parse(localuser);
const currentUserEmail = currentUser.email;
const res = await contractUsers(currentUserEmail);
if (res === "Error: Something went wrong!") {
@@ -766,10 +781,10 @@ function PdfRequestFiles() {
const pdfBytes = await multiSignEmbed(
pngUrl,
pdfDoc,
pdfOriginalWidth,
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 +1013,24 @@ function PdfRequestFiles() {
style: { fontSize: "13px" }
}
];
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
let pdfWHObj = [];
const totalPages = pdf.numPages; // Get the total number of pages
for (let index = 0; index < totalPages; index++) {
const getPage = await pdf.getPage(index + 1);
const scale = 1;
const { width, height } = getPage.getViewport({ scale });
pdfWHObj.push({ pageNumber: index + 1, width, height });
}
setPdfOriginalWH(pdfWHObj);
setPdfLoad(true);
};
//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 +1139,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 +1234,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);
@@ -1299,7 +1288,7 @@ function PdfRequestFiles() {
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourForth"]',
selector: '[data-tut="pdfArea"]',
content: () => (
<TourContentWithBtn
message={`Click any of the placeholders appearing on the document to sign. You will then see options to draw your signature, type it, or upload an image .`}
@@ -1396,7 +1385,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 className="text-[13px] text-base-content">
This might take some time
</span>
</div>
@@ -1410,7 +1399,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 +1406,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 +1423,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 +1486,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 +1506,12 @@ function PdfRequestFiles() {
Yes
</button>
<button
onClick={() =>
onClick={() => {
setDefaultSignAlert({
isShow: false,
alertMessage: ""
})
}
});
}}
type="button"
className="op-btn op-btn-secondary"
>
@@ -1526,9 +1520,12 @@ function PdfRequestFiles() {
</>
) : (
<button
onClick={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
onClick={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
type="button"
className="op-btn op-btn-primary"
>
@@ -1550,289 +1547,277 @@ 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}
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 mx-[3px] lg:mx-0"
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="pdfArea" 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}
setPdfLoad={setPdfLoad}
pdfLoad={pdfLoad}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsInitial={setIsInitial}
setValidateAlert={setValidateAlert}
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
divRef={divRef}
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
data-tut="reactourSecond"
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
data-tut="reactourFirst"
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>
+85 -80
View File
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import "../styles/pgsignup.css";
import Parse from "parse";
import axios from "axios";
import { useDispatch } from "react-redux";
@@ -409,95 +408,101 @@ const PgSignUp = () => {
}
};
return (
<div className="bg-white">
<div className="w-full h-screen">
<Title title={"Pgsignup page"} />
{isLoader ? (
<div className="flex justify-center items-center h-[100vh]">
<Loader />
</div>
) : (
<form id="signup" className="pgsignup-content" onSubmit={handleSubmit}>
<div className="pgsignup-container">
<h1 className="text-2xl md:text-3xl font-bold">Choose Password</h1>
<hr className="hrt" />
<label htmlFor="password">
<b className="text-[13px]">Password</b>
</label>
<input
type="password"
placeholder="Enter Password"
name="password"
className="inputt"
value={formData.password}
onChange={handlePassowordChange}
required
/>
<label htmlFor="confirmPassword">
<b className="text-[13px]">Confirm Password</b>
</label>
<input
type="password"
placeholder="Confirm Password"
name="confirmPassword"
className="confirmInputt"
style={{
border: validationMessage
? validationMessage === "Passwords match!"
? "2px solid green"
: "2px solid red"
: "2px solid transparent",
outline: "none"
}}
value={formData.confirmPassword}
onChange={handleConFirmPassowordChange}
required
/>
<div
className="icon"
style={{
margin: validationMessage ? "0 2px 0 2px" : "0 2px 22px 2px",
color:
validationMessage === "Passwords match!" ? "green" : "red",
fontSize: 11
}}
>
{validationMessage}
</div>
{formData.password.length > 0 && (
<div className="mt-1 text-[11px]">
<p
className={`${
lengthValid ? "text-green-600" : "text-red-600"
}`}
>
{lengthValid ? "✓" : "✗"} Password should be 8 characters long
</p>
<p
className={`${
caseDigitValid ? "text-green-600" : "text-red-600"
}`}
>
{caseDigitValid ? "✓" : "✗"} Password should contain uppercase
letter, lowercase letter, digit
</p>
<p
className={`${
specialCharValid ? "text-green-600" : "text-red-600"
}`}
>
{specialCharValid ? "✓" : "✗"} Password should contain special
character
</p>
<div className="py-10 lg:p-16 flex justify-center">
<form
id="signup"
className="w-[90%] md:w-[55%] bg-base-100 text-base-content op-card shadow-md"
onSubmit={handleSubmit}
>
<div className="p-[16px]">
<h1 className="text-2xl md:text-3xl font-bold">
Choose Password
</h1>
<hr className="border-[1px] border-[#cecece] mb-[5px]" />
<label htmlFor="password">
<b className="text-[13px]">Password</b>
</label>
<input
type="password"
placeholder="Enter Password"
name="password"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.password}
onChange={handlePassowordChange}
required
/>
<label htmlFor="confirmPassword">
<b className="text-[13px]">Confirm Password</b>
</label>
<input
type="password"
placeholder="Confirm Password"
name="confirmPassword"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
style={{
border: validationMessage
? validationMessage === "Passwords match!"
? "1px solid green"
: "1px solid red"
: ""
}}
value={formData.confirmPassword}
onChange={handleConFirmPassowordChange}
required
/>
<div
className={`${
validationMessage === "Passwords match!"
? "text-[green]"
: "text-[red]"
} ml-[13px] text-[11px]`}
>
{validationMessage}
</div>
)}
<div className="clearfix">
<button type="submit" className="signupbtn">
{formData.password.length > 0 && (
<div className="mt-1 text-[11px]">
<p
className={`${
lengthValid ? "text-green-600" : "text-red-600"
}`}
>
{lengthValid ? "✓" : "✗"} Password should be 8 characters
long
</p>
<p
className={`${
caseDigitValid ? "text-green-600" : "text-red-600"
}`}
>
{caseDigitValid ? "✓" : "✗"} Password should contain
uppercase letter, lowercase letter, digit
</p>
<p
className={`${
specialCharValid ? "text-green-600" : "text-red-600"
}`}
>
{specialCharValid ? "✓" : "✗"} Password should contain
special character
</p>
</div>
)}
<button
type="submit"
className="op-btn op-btn-primary w-full mt-[8px]"
>
Submit
</button>
</div>
</div>
</form>
</form>
</div>
)}
</div>
);
File diff suppressed because it is too large Load Diff
+365 -290
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,13 +102,11 @@ 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("");
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
});
const [pdfLoad, setPdfLoad] = useState(false);
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isDontShow, setIsDontShow] = useState(false);
const [extUserId, setExtUserId] = useState("");
@@ -114,6 +117,9 @@ function SignYourSelf() {
const [isEmailVerified, setIsEmailVerified] = useState(true);
const [isVerifyModal, setIsVerifyModal] = useState(false);
const [otp, setOtp] = 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 +129,7 @@ function SignYourSelf() {
isOver: !!monitor.isOver()
})
});
const isMobile = window.innerWidth < 767;
const pdfRef = useRef();
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
@@ -154,7 +157,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 +184,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,14 +224,17 @@ function SignYourSelf() {
} else {
setHandleError("Error: Something went wrong!");
}
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: "You have successfully signed the document!"
mssg: "Congratulations! 🎉 This document has been successfully signed by you!"
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
@@ -229,12 +242,8 @@ function SignYourSelf() {
setIsUiLoading(false);
setIsSignPad(false);
setIsEmail(true);
setIsCelebration(true);
setXyPostion([]);
setSignBtnPosition([]);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
}
}
} else if (
@@ -442,61 +451,69 @@ 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 getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH?.width / getPdfPageWidth?.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 +523,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 +552,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 +694,14 @@ function SignYourSelf() {
const pdfBytes = await multiSignEmbed(
xyPostion,
pdfDoc,
pdfOriginalWidth,
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.")) {
@@ -781,22 +807,18 @@ function SignYourSelf() {
setDragKey(key);
setIsDragging(true);
};
//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 getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
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 +826,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;
@@ -827,26 +847,24 @@ function SignYourSelf() {
setIsDragging(false);
}, 200);
};
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
let pdfWHObj = [];
const totalPages = pdf?.numPages;
for (let index = 0; index < totalPages; index++) {
const getPage = await pdf.getPage(index + 1);
const scale = 1;
const { width, height } = getPage.getViewport({ scale });
pdfWHObj.push({ pageNumber: index + 1, width, height });
}
setPdfOriginalWH(pdfWHObj);
setPdfLoad(true);
};
//function for change page numver of pdf
function changePage(offset) {
setSignBtnPosition([]);
setPageNumber((prevPageNumber) => prevPageNumber + offset);
}
//function for image upload or update
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
@@ -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
@@ -955,7 +985,7 @@ function SignYourSelf() {
};
const tourConfig = [
{
selector: '[data-tut="reactourFirst"]',
selector: '[data-tut="addWidgets"]',
content: () => (
<TourContentWithBtn
message={`Select and drag your preferred widgets onto the PDF to customize your document before signing. Choose the perfect spots for each modification to tailor the document to your needs.`}
@@ -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"} />
@@ -1098,23 +1164,20 @@ function SignYourSelf() {
) : (
<div>
{isUiLoading && (
<div className="absolute h-[100vh] w-full z-[999] flex flex-col justify-center items-start bg-[#e6f2f2] bg-opacity-80">
<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>
)}
{isCelebration && (
<div className="relative z-[999]">
<div className="relative z-[1000]">
<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="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
{!isEmailVerified && (
<VerifyEmail
isVerifyModal={isVerifyModal}
@@ -1128,7 +1191,7 @@ function SignYourSelf() {
/>
)}
{/* this component used for UI interaction and show their functionality */}
{pdfLoadFail && !checkTourStatus && (
{pdfLoad && !checkTourStatus && (
<Tour
onRequestClose={closeTour}
steps={tourConfig}
@@ -1149,195 +1212,197 @@ 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}
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}
pdfLoad={pdfLoad}
setPdfLoad={setPdfLoad}
setXyPostion={setXyPostion}
index={index}
containerWH={containerWH}
setIsPageCopy={setIsPageCopy}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setValidateAlert={setValidateAlert}
handleTextSettingModal={handleTextSettingModal}
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
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 +1429,16 @@ function SignYourSelf() {
</button>
</div>
</ModalUi>
<TextFontSetting
isTextSetting={isTextSetting}
setIsTextSetting={setIsTextSetting}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
handleSaveFontSize={handleSaveFontSize}
currWidgetsDetails={currWidgetsDetails}
/>
</DndProvider>
);
}
+476 -357
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,10 +87,8 @@ const TemplatePlaceholder = () => {
const [blockColor, setBlockColor] = useState("");
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isNameModal, setIsNameModal] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
});
const [isTextSetting, setIsTextSetting] = useState(false);
const [pdfLoad, setPdfLoad] = useState(false);
const color = [
"#93a3db",
"#e6c3db",
@@ -147,6 +149,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 +168,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 +365,36 @@ const TemplatePlaceholder = () => {
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const newWidth = containerWH.width;
const scale = pdfOriginalWidth / newWidth;
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
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 +409,25 @@ 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,
// isMobile: isMobile,
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,14 +536,16 @@ const TemplatePlaceholder = () => {
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
status: true
};
setPdfLoadFail(load);
pdf.getPage(1).then((pdfPage) => {
const pageWidth = pdfPage.view[2];
setPdfOriginalWidth(pageWidth);
});
let pdfWHObj = [];
const totalPages = pdf?.numPages;
for (let index = 0; index < totalPages; index++) {
const getPage = await pdf.getPage(index + 1);
const scale = 1;
const { width, height } = getPage.getViewport({ scale });
pdfWHObj.push({ pageNumber: index + 1, width, height });
}
setPdfOriginalWH(pdfWHObj);
setPdfLoad(true);
};
//function for save x and y position and show signature tab on that position
const handleTabDrag = (key) => {
@@ -520,14 +559,12 @@ 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 getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
if (keyValue >= 0) {
const filterSignerPos = updateSignPos.filter(
(data) => data.Id === signId
@@ -548,10 +585,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 +686,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
@@ -766,7 +813,7 @@ const TemplatePlaceholder = () => {
action: () => handleCloseRoleModal()
},
{
selector: '[data-tut="reactourSecond"]',
selector: '[data-tut="addWidgets"]',
content: () => (
<TourContentWithBtn
message={`Drag or click on a field to add it to the document.`}
@@ -788,10 +835,10 @@ const TemplatePlaceholder = () => {
style: { fontSize: "13px" }
},
{
selector: '[data-tut="reactourFour"]',
selector: '[data-tut="headerArea"]',
content: () => (
<TourContentWithBtn
message={`Clicking Save will store the current template. After saving, youll be prompted to create a new document from this template if you wish.`}
message={`Clicking Next will store the current template. After saving, youll be prompted to create a new document from this template if you wish.`}
isChecked={handleDontShow}
/>
),
@@ -1202,8 +1249,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 +1307,287 @@ 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}
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={"Next"}
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}
setPdfLoad={setPdfLoad}
pdfLoad={pdfLoad}
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}
handleTextSettingModal={handleTextSettingModal}
pdfOriginalWH={pdfOriginalWH}
setScale={setScale}
scale={scale}
/>
)}
</div>
</div>
</div>
{/* signature button */}
{isMobile ? (
<div>
<WidgetComponent
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}
@@ -1500,7 +1608,7 @@ const TemplatePlaceholder = () => {
blockColor={blockColor}
setBlockColor={setBlockColor}
/>
<div data-tut="reactourSecond">
<div data-tut="addWidgets">
<WidgetComponent
isMailSend={isMailSend}
dragSignature={dragSignature}
@@ -1520,49 +1628,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>
</>
);
};
+1 -1
View File
@@ -315,7 +315,7 @@ function UserProfile() {
{userNameError}
</div>
)} */}
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded-xl w-[450px]">
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box w-[450px]">
<div className="flex flex-col justify-center items-center my-4">
<div className="w-[200px] h-[200px] overflow-hidden rounded-full">
<img
+114 -138
View File
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from "react";
import Title from "../components/Title";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import Alert from "../primitives/Alert";
import ModalUi from "../primitives/ModalUi";
import { isEnableSubscription } from "../constant/const";
@@ -10,19 +9,24 @@ import Parse from "parse";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
const tourSteps = [
{
selector: '[data-tut="webhooksubscribe"]',
content: "Upgrade now to set webhook"
}
];
function Webhook() {
const navigation = useNavigate();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [webhook, setWebhook] = useState();
const [isLoader, setIsLoader] = useState(true);
const [isGenerate, setIsGenerate] = useState(false);
const [isErr, setIsErr] = useState(false);
const [isModal, setIsModal] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
const [error, setError] = useState("");
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTour, setIsTour] = useState(false);
useEffect(() => {
fetchWebhook();
// eslint-disable-next-line
@@ -60,31 +64,22 @@ function Webhook() {
"X-Parse-Application-Id": parseAppId,
sessiontoken: localStorage.getItem("accesstoken")
};
await axios.post(url, params, { headers: headers }).then((res) => {
if (res.data && res.data.result && res.data.result.Webhook) {
setWebhook(res.data.result.Webhook);
setIsGenerate(true);
setTimeout(() => {
setIsGenerate(false);
}, 1500);
setIsLoader(false);
} else {
console.error("Error while generating webhook");
setIsLoader(false);
setIsErr(true);
setTimeout(() => {
setIsErr(false);
}, 1500);
}
});
const res = await axios.post(url, params, { headers: headers });
if (res.data && res.data.result && res.data.result.Webhook) {
setWebhook(res.data.result.Webhook);
setIsAlert({ type: "success", msg: "Webhook added successfully." });
} else {
console.error("Error while generating webhook");
setIsAlert({ type: "danger", msg: "Something went wrong." });
}
} catch (error) {
setIsAlert({ type: "danger", msg: "Something went wrong." });
console.log("err while generating webhook", error);
} finally {
setIsLoader(false);
setIsErr(true);
setTimeout(() => {
setIsErr(false);
setIsAlert({ type: "success", msg: "" });
}, 1500);
console.log("err", error);
}
} else {
setError("The webhook url should always start with https://");
@@ -94,131 +89,112 @@ function Webhook() {
}
};
const handleModal = () => setIsModal(!isModal);
const handleModal = () => {
if (!isSubscribe && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal(!isModal);
}
};
return (
<React.Fragment>
<Title title={"Webhook"} />
{isGenerate && <Alert type="success">Webhook added successfully.</Alert>}
{isErr && <Alert type="danger">Something went wrong.</Alert>}
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
{isLoader ? (
<div className="h-[100vh] flex justify-center items-center">
<Loader />
</div>
) : (
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded">
{!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign Webhook{" "}
<Tooltip
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
isSubscribe={true}
/>
</h1>
<ul
className={
isSubscribe || !isEnableSubscription
? "w-full flex flex-col p-2 text-sm "
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
}
>
<li
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
>
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
<span className="">Webhook:</span>{" "}
<span id="token" className=" md:text-end cursor-pointer">
{webhook ? webhook : "_____"}
</span>
</div>
<>
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
{!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign Webhook{" "}
<Tooltip
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
isSubscribe={true}
/>
</h1>
<ul className={"w-full flex flex-col p-2 text-sm"}>
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5">
<span className="">Webhook:</span>{" "}
<span id="token" className=" md:text-end cursor-pointer">
{webhook ? webhook : "_____"}
</span>
</div>
<button
type="button"
onClick={handleModal}
className="op-btn op-btn-primary"
>
{webhook ? "Update Webhook" : "Add Webhook"}
</button>
</li>
</ul>
<div className="flex items-center justify-center">
<button
type="button"
onClick={handleModal}
className="op-btn op-btn-primary "
onClick={() =>
openInNewTab(
"https://docs.opensignlabs.com/docs/API-docs/save-update-webhook"
)
}
className="op-btn op-btn-secondary mt-2 mb-3 px-7"
>
{webhook ? "Update Webhook" : "Add Webhook"}
View Docs
</button>
</li>
</ul>
<div className="flex items-center justify-center ">
<button
type="button"
onClick={() =>
openInNewTab(
"https://docs.opensignlabs.com/docs/API-docs/save-update-webhook"
)
}
className="op-btn op-btn-secondary my-2"
>
View Docs
</button>
</div>
{!isSubscribe && isEnableSubscription && (
<>
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
Upgrade to PRO Plan
</h1>
<ul className={"w-full flex flex-col p-2 text-sm "}>
<li
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
>
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
<span className="">$29.99/month:</span>{" "}
<span id="token" className=" md:text-end cursor-pointer">
First 100 documents included, then just $0.15 per
document.
</span>
</div>
{!isSubscribe && isEnableSubscription && (
<button
type="button"
onClick={() => navigation("/subscription")}
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
>
Upgrade Now
</button>
)}
</li>
</ul>
</>
)}
<ModalUi
isOpen={isModal}
title={"Regenerate Token"}
handleClose={handleModal}
>
{error && <Alert type="danger">{error}</Alert>}
<div className="m-[20px]">
<div className="text-lg font-normal text-base-content">
<label className="text-sm ml-2">Webhook</label>
<input
value={webhook}
onChange={(e) => setWebhook(e.target.value)}
placeholder="Enter webhook url"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<hr className="bg-[#ccc] mt-3" />
<div className="flex items-center mt-3 gap-2">
<button
onClick={handleSubmit}
className="op-btn op-btn-primary ml-[2px]"
>
Yes
</button>
<button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</div>
</ModalUi>
</div>
<ModalUi
isOpen={isModal}
title={"Regenerate Token"}
handleClose={handleModal}
>
{error && <Alert type="danger">{error}</Alert>}
<div className="m-[20px]">
<div className="text-lg font-normal text-base-content">
<label className="text-sm ml-2">Webhook</label>
<input
value={webhook}
onChange={(e) => setWebhook(e.target.value)}
placeholder="Enter webhook url"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<hr className="bg-[#ccc] mt-3" />
<div className="flex items-center mt-3 gap-2">
<button
onClick={handleSubmit}
className="op-btn op-btn-primary ml-[2px]"
>
Yes
</button>
<button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</div>
</ModalUi>
</div>
{!isSubscribe && isEnableSubscription && (
<div data-tut="webhooksubscribe">
<SubscribeCard />
</div>
)}
</>
)}
<Tour
onRequestClose={() => setIsTour(false)}
steps={tourSteps}
isOpen={isTour}
closeWithMask={false}
disableKeyboardNavigation={["esc"]}
scrollOffset={-100}
rounded={5}
/>
</React.Fragment>
);
}
+1 -2
View File
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import Parse from "parse";
import axios from "axios";
import "../styles/AddUser.css";
import Loader from "./Loader";
const AddContact = (props) => {
const [name, setName] = useState("");
@@ -203,7 +202,7 @@ const AddContact = (props) => {
</div>
)}
<div className="w-full mx-auto p-[8px]">
<div className="text-[14px] font-[700]">Add User</div>
<div className="text-[14px] font-[700]">Add Contact</div>
{isUserExist && (
<div className="mb-[0.75rem] flex items-center mt-1">
<input
@@ -0,0 +1,51 @@
import React, { useState, useEffect } from "react";
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
import Loader from "./Loader";
const LottieWithLoader = () => {
const [isLoaded, setIsLoaded] = useState(false);
const [hasError, setHasError] = useState(false);
const [animationSrc, setAnimationSrc] = useState(null);
const src =
"https://lottie.host/00a72a09-f2d4-493a-9b2d-2843bf067638/Ic7jJ44wLJ.json";
useEffect(() => {
fetch(src)
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.blob();
})
.then((blob) => {
const objectURL = URL.createObjectURL(blob);
setAnimationSrc(objectURL);
setIsLoaded(true);
})
.catch((error) => {
console.error("faild to load animation of send request:", error);
setHasError(true);
});
}, [src]);
return (
<div>
{!isLoaded && !hasError && (
<div className="loader">
{" "}
<Loader />
</div>
)}
{hasError && <div className="error">Failed to load animation</div>}
{isLoaded && animationSrc && (
<DotLottieReact
src={animationSrc}
loop
autoplay
style={{ display: "block" }}
/>
)}
</div>
);
};
export default LottieWithLoader;
@@ -951,7 +951,7 @@ const ReportTable = (props) => {
<i
data-tut="reactourFirst"
onClick={() => navigate("/form/template")}
className="fa-solid fa-square-plus text-accent text-[25px]"
className="fa-light fa-square-plus text-accent text-[40px]"
></i>
)}
{props.form && (
@@ -959,13 +959,13 @@ const ReportTable = (props) => {
className="cursor-pointer"
onClick={() => handleContactFormModal()}
>
<i className="fa-solid fa-square-plus text-accent text-[25px]"></i>
<i className="fa-light fa-square-plus text-accent text-[40px]"></i>
</div>
)}
</div>
<div
className={`${
isDashboard ? "h-[317px]" : "h-full"
isDashboard && props.List?.length > 0 ? "h-[317px]" : "h-full"
} overflow-x-auto w-full`}
>
<table className="op-table border-collapse w-full">
@@ -1000,7 +1000,7 @@ const ReportTable = (props) => {
<td className="px-4 py-2 font-semibold">
{item?.Name}{" "}
</td>
<td className="px-4 py-2">{item?.Email || "-"}</td>
<td className="px-4 py-2 ">{item?.Email || "-"}</td>
<td className="px-4 py-2">{item?.Phone || "-"}</td>
<td className="px-3 py-2 text-white grid grid-cols-2">
{props.actions?.length > 0 &&
@@ -1053,7 +1053,7 @@ const ReportTable = (props) => {
{startIndex + index + 1}
</th>
)}
<td className="px-4 py-2 font-semibold min-w-56">
<td className="px-4 py-2 font-semibold min-w-56 max-w-56">
{item?.Name}{" "}
</td>
{props.heading.includes("Note") && (
@@ -1303,46 +1303,56 @@ const ReportTable = (props) => {
))}
</div>
{isViewShare[item.objectId] && (
<div className="fixed z-[999] inset-0 w-full h-full bg-black bg-opacity-[75%]">
<div className="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-sm bg-white rounded shadow-md max-h-90 min-w-[90%] md:min-w-[400px] overflow-y-auto max-h-[340px] md:max-h-[400px] hide-scrollbar">
<ModalUi
isOpen
showHeader={
props.ReportName === "Templates" && true
}
title={"Signers"}
reduceWidth={"md:max-w-[450px]"}
handleClose={() => setIsViewShare({})}
>
{props.ReportName !== "Templates" && (
<div
className="cursor-pointer absolute text-white text-[22px] font-medium rounded-full z-50 top-1 right-3"
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-1 z-40"
onClick={() => setIsViewShare({})}
>
&times;
</div>
<table className="table-auto w-full">
<thead className="text-white h-[38px] sticky top-0 bg-[#32a3ac]">
<tr>
)}
<table className="op-table w-full overflow-auto">
<thead className="h-[38px] sticky top-0 text-base-content text-sm pt-[15px] px-[20px]">
<tr>
{props.ReportName === "Templates" && (
<th className="p-2 pl-3 w-[30%]">
Roles
</th>
)}
<th className="pl-3 py-2">
{props.ReportName === "Templates"
? "Email"
: "Signers"}
</th>
</tr>
</thead>
<tbody>
{item.Placeholders.map((x, i) => (
<tr key={i} className="text-sm font-medium">
{props.ReportName === "Templates" && (
<th className="p-2 pl-3">Roles</th>
)}
<th className="p-2">Signers</th>
</tr>
</thead>
<tbody>
{item.Placeholders.map((x, i) => (
<tr
key={i}
className="text-sm font-normal text-black odd:bg-white even:bg-gray-200"
>
{props.ReportName === "Templates" && (
<td className="text-[12px] p-2 pl-3">
{x.Role && x.Role}
</td>
)}
<td className="text-[12px] p-2 break-all">
{x.email
? x.email
: x?.signerPtr?.Email || "-"}
<td className="text-[12px] p-2 pl-3 w-[30%]">
{x.Role && x.Role}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
<td className="pl-3 text-[12px] py-2 break-all">
{x.email
? x.email
: x?.signerPtr?.Email || "-"}
</td>
</tr>
))}
</tbody>
</table>
</ModalUi>
)}
{isDeleteModal[item.objectId] && (
<ModalUi
@@ -1398,6 +1408,7 @@ const ReportTable = (props) => {
handleClose={() => {
setIsShare({});
setActLoader({});
setCopied(false);
}}
>
<div className="m-[20px]">
@@ -1406,25 +1417,26 @@ const ReportTable = (props) => {
key={i}
className="text-sm font-normal text-black flex my-2 justify-between items-center"
>
<span className="text-sm font-semibold">
<span className="w-[150px] mr-[5px] md:mr-0 md:w-[300px] whitespace-nowrap overflow-hidden text-ellipsis text-sm font-semibold">
{share.email}
</span>
<div>
<div className="flex items-center gap-2">
<RWebShare
data={{
url: share.url,
title: "Sign url"
}}
>
<button className="bg-[#002864] text-white rounded w-[32px] h-[30px] focus:outline-none">
<i className="fa-solid fa-share-from-square"></i>{" "}
<button className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm ">
<i className="fa-light fa-share-from-square"></i>{" "}
Share
</button>
</RWebShare>
<button
className="ml-2 bg-[#002864] text-white rounded w-[100px] h-[30px] focus:outline-none"
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
onClick={() => copytoclipboard(share)}
>
<i className="fa-solid fa-link"></i>{" "}
<i className="fa-light fa-link"></i>{" "}
{copied[share.email]
? "Copied"
: "Copy"}
@@ -1573,11 +1585,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>
@@ -1589,7 +1601,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>
@@ -1597,14 +1609,18 @@ 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>
)}
</div>
{props.List?.length <= 0 && (
<div className="flex flex-col items-center justify-center w-full bg-base-100 text-base-content rounded-xl py-4">
<div
className={`${
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">
<img
className="w-full h-full object-contain"
+1 -1
View File
@@ -2,7 +2,7 @@ import React from "react";
const Loader = () => {
return (
<div className="op-loading op-loading-infinity w-[5rem] text-accent"></div>
<div className="op-loading op-loading-infinity w-[4rem] text-neutral"></div>
);
};
@@ -4,7 +4,6 @@ import Loader from "./Loader";
function LoaderWithMsg({ isLoading }) {
return (
<div className="flex flex-col justify-center items-center h-[100vh]">
{/* <img alt="loader" src={loader} className="w-[80px] h-[80px]" /> */}
<Loader />
<span className="text-[13px] text-base-cotent">{isLoading.message}</span>
</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 />
+3 -2
View File
@@ -12,14 +12,15 @@ const ModalUi = ({
reduceWidth,
showHeaderMessage
}) => {
const width = reduceWidth;
return (
<>
{isOpen && (
<dialog className="op-modal op-modal-open">
<div
className={`${
reduceWidth || "md:min-w-[500px]"
} op-modal-box p-0 max-h-90 min-w-[90%] overflow-y-auto hide-scrollbar text-sm`}
width || "md:min-w-[500px]"
} op-modal-box p-0 max-h-90 overflow-y-auto hide-scrollbar text-sm`}
>
{showHeader && (
<>
@@ -11,7 +11,7 @@ function CustomModal({
}) {
return (
show && (
<dialog className="op-modal op-modal-open absolute z-[1999]">
<dialog className="op-modal op-modal-open absolute z-[998]">
<div className="w-[80%] md:w-[40%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<h3 className="text-[#de4337] font-bold text-lg pt-[15px] px-[20px]">
{headMsg && headMsg}
@@ -0,0 +1,24 @@
import React from "react";
import { useNavigate } from "react-router-dom";
const SubscribeCard = () => {
const navigate = useNavigate();
return (
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
<h2 className="op-card-title">Upgrade to PRO Plan</h2>
<p>$29.99/month: Sign 100 docs using API. Only $0.15/doc after that.</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
className="op-btn op-btn-accent"
>
Upgrade Now
</button>
</div>
</div>
</div>
);
};
export default SubscribeCard;
+8 -11
View File
@@ -6,13 +6,10 @@ const Tooltip = ({ id, message, url, iconColor }) =>
<button onClick={() => openInNewTab(url)} className={"text-center"}>
<sup>
<i
className="fa-solid fa-question rounded-full"
className="fa-light fa-question rounded-full border-[1px] py-[1.5px] px-[4px] text-[13px]"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff",
fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
color: iconColor ? iconColor : "#33bbff"
}}
></i>
</sup>
@@ -26,18 +23,18 @@ const Tooltip = ({ id, message, url, iconColor }) =>
>
<sup>
<i
className="fa-solid fa-question rounded-full"
className="fa-light fa-question rounded-full border-[1px] py-[1.5px] px-[4px] text-[13px]"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff",
fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
color: iconColor ? iconColor : "#33bbff"
}}
></i>
</sup>
</a>
<ReactTooltip id={id ? id : "my-tooltip"} className="max-w-[200px]" />
<ReactTooltip
id={id ? id : "my-tooltip"}
className="max-w-[200px] z-[200]"
/>
</>
);
+1 -1
View File
@@ -9,7 +9,7 @@ function Upgrade({ message }) {
const url = window.location.origin + "/subscription";
openInNewTab(url);
}}
className="text-blue-800 text-sm cursor-pointer underline"
className="op-link op-link-accent text-sm"
>
{message ? message : "Upgrade now"}
</span>
+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
}
});
-79
View File
@@ -1,82 +1,3 @@
.addusercontainer {
height: 100%;
padding: 10px 20px 10px 20px;
}
.loaderdiv {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
}
.form-wrapper {
width: 100%;
margin-left: auto;
margin-right: auto;
padding: 8px;
}
.form-section {
margin-bottom: 0.75rem;
}
.checkbox-label {
margin-left: 0.5rem;
color: #4b5563;
}
.addUserInput {
padding: 0.5rem 0.75rem;
width: 100%;
border-width: 1px;
border-color: #d1d5db;
border-radius: 0.375rem;
outline: none;
font-size: 0.75rem;
}
.buttoncontainer {
margin-top: 1rem;
display: flex;
justify-content: flex-start;
}
.submitbutton {
background: #1ab6ce;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
border: none;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
padding: 0.375rem 0.75rem;
text-align: center;
color: #ffffff;
outline: none;
}
/* For classes: bg-[#188ae2] text-sm text-white px-4 py-2 rounded ml-2 shadow focus:outline-none */
.resetbutton {
background-color: #188ae2;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
border: none;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
padding: 0.375rem 0.75rem;
text-align: center;
color: #ffffff;
outline: none;
margin-left: 8px;
}
.validationlist {
position: absolute;
left: 0;
-66
View File
@@ -1,66 +0,0 @@
fieldset {
border: 0 !important;
margin: 0 !important;
padding: 0 !important;
}
[class*="loader-"] {
display: inline-block;
width: 1em;
height: 1em;
color: inherit;
vertical-align: middle;
pointer-events: none;
}
.loader-37 {
border-right: 0.1em solid currentcolor;
border-radius: 100%;
-webkit-animation: loader-37 800ms linear infinite;
animation: loader-37 800ms linear infinite;
}
.loader-37:before,
.loader-37:after {
content: "";
width: 0.8em;
height: 0.8em;
display: block;
position: absolute;
top: calc(50% - 0.4em);
left: calc(50% - 0.4em);
border-left: 0.08em solid currentcolor;
border-radius: 100%;
animation: loader-37 400ms linear infinite reverse;
}
.loader-37:after {
width: 0.6em;
height: 0.6em;
top: calc(50% - 0.3em);
left: calc(50% - 0.3em);
border: 0;
border-right: 0.05em solid currentcolor;
-webkit-animation: none;
animation: none;
}
@-webkit-keyframes loader-37 {
from {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
to {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes loader-37 {
from {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
to {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
+9 -146
View File
@@ -1,18 +1,8 @@
.mainDiv {
position: relative;
}
.successBtn {
background: #3ac9d6;
border: 1px solid #3ac9d6;
}
.warning {
.customwarning {
position: absolute;
padding: 8px;
border: 1px solid black;
background: white;
width: 300px;
border-radius: 5px;
animation: inAnimation 2s ease-in-out;
z-index: 1;
@@ -38,40 +28,15 @@
margin: 0 auto;
}
.successBox {
z-index: 1;
position: absolute;
top: 5%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 13px;
animation: inAnimation 2s ease-in-out;
}
@keyframes inAnimation {
0% {
opacity: 0;
visibility: hidden;
}
25% {
opacity: 1;
visibility: visible;
}
50% {
opacity: 1;
visibility: visible;
}
75% {
opacity: 1;
visibility: visible;
}
100% {
opacity: 0;
visibility: hidden;
opacity: 1;
visibility: visible;
}
}
@@ -83,117 +48,15 @@
font-size: 12px;
font-weight: 600;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.1),
0 1px 2px rgba(0, 0, 0, 0.18);
}
.signature:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.1),
0 2px 4px rgba(0, 0, 0, 0.18);
background: #13a8da;
color: white;
}
.imgupload {
color: white;
cursor: pointer;
padding: 10px 14px 10px;
background: #15b4e9;
font-size: 12px;
font-weight: 600;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
min-width: 105px;
}
.imgupload:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background: #13a8da;
color: white;
}
.loaderContainer {
position: fixed;
inset: 0%;
width: 100%;
height: 100svh;
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7));
display: flex;
align-items: center;
justify-content: center;
}
.loader {
width: 70px;
height: 70px;
border-top: 4px solid #1b8ef4;
border-left: 4px solid #1b8ef4;
border-radius: 80%;
animation: spin 0.5s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
.customBtn {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 10px 14px 10px;
color: white;
font-weight: 600;
font-size: 12px;
text-transform: uppercase;
border-radius: 2px;
margin-left: 10px;
width: 100px;
}
.clearbtn {
font-size: 15px;
}
.clearbtn:hover {
text-decoration: underline;
text-underline-offset: 2px;
color: blue;
}
.successBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background: #1ab6ce;
color: white;
}
.resetBtn {
background: #188ae2;
margin-left: 10;
border: 1px solid #188ae2;
}
.resetBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background: #177ecd;
color: white;
}
.signBlock {
display: flex;
flex-direction: row;
gap: 12px;
}
.signInputManage {
width: 50%;
}
@media (max-width: 815px) {
.signBlock {
display: flex;
flex-direction: column;
}
.signInputManage {
width: 100%;
}
}
+4 -249
View File
@@ -9,7 +9,8 @@
border-radius: 6px;
overflow: hidden;
padding: 5px;
box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35),
box-shadow:
0px 10px 38px -10px rgba(22, 23, 24, 0.35),
0px 10px 20px -15px rgba(22, 23, 24, 0.2);
z-index: 99;
}
@@ -106,110 +107,14 @@
color: var(--violet-11);
}
.itemColor {
font-size: 13px !important;
}
.folderComponent {
padding: 30px;
height: 100%;
border-radius: 5px;
}
.inputStyle {
border: 1.6px solid #ccc !important;
}
.folderComponent::-webkit-scrollbar {
display: none;
/* for Chrome, Safari, and Opera */
}
.modal {
margin-top: 50px;
}
.folderBox {
/* box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
margin: 10px ;
padding: 5px 0px 5px 40px; */
/* overflow: scroll;
display: flex;
justify-content: space-between;
width: 200px; */
margin: 10px;
/* box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px; */
}
.folderContainer {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
/* .folderBox:hover{
box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
font-weight: bold;
} */
.pdfName {
font-size: 10px;
font-weight: 600;
}
.viewbotton {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 8px 20px;
color: white;
font-weight: 600;
font-size: 14px;
border: none;
border-radius: 2px;
margin-left: 10px;
}
.viewbotton:focus {
border: none;
outline: none;
}
.folderRender {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
position: relative;
width: 100px;
height: 100px;
margin: 20px;
display: inline-block;
}
.pdfContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 20px;
align-items: center;
justify-content: space-around;
}
.pdfContainer .box:last-child {
margin-left: 0;
/* Override the margin on the last box */
margin-right: auto;
/* Align it to the start */
}
.icon-container {
position: relative;
width: 100px;
height: 100px;
margin: 10px;
display: inline-block;
cursor: pointer;
}
.hrStyle {
margin-top: 0rem !important;
@@ -218,17 +123,11 @@
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.pdf-icon {
width: 100%;
height: 100%;
}
.status-badge {
position: absolute;
top: 0;
right: 0;
background-color: #fff;
width: 24px;
height: 24px;
display: flex;
@@ -268,14 +167,6 @@
color: #fff;
}
.add {
background-color: #05bbdb;
color: #fff;
padding: 8px 15px;
text-align: center;
display: flex;
margin: 5px;
}
.sort {
padding: 8px 15px;
@@ -292,56 +183,6 @@
border-radius: 2px;
}
/* Hover effect */
.info-box {
position: absolute;
bottom: 100%;
left: 0;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
padding: 5px;
width: 180px;
display: none;
z-index: 10;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
}
.icon-container:hover .info-box {
display: block;
}
.folderRender:hover .info-box {
display: block;
}
.info-box:hover {
z-index: 999;
}
.addFolderInput {
padding: 10px;
border-radius: 4px;
/* width: 440px; */
font-size: 15px;
border: 0.5px solid rgb(198, 195, 195);
}
.tooltip-inner {
background-color: #fff;
border: 1px solid black;
font-weight: 600;
opacity: 1 !important;
color: rgb(0, 0, 0);
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
font-size: 12px;
}
.fileName {
display: inline-block;
width: 100px;
@@ -353,22 +194,6 @@
font-weight: 480;
}
.foldName {
display: inline-block;
width: 100px;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
font-size: 11px;
text-align: center;
font-weight: 480;
}
.statusSpan {
font-size: 12px;
font-weight: 500;
}
a {
all: unset;
}
@@ -378,7 +203,8 @@ a {
padding: 5px 10px;
width: 170px;
background-color: white;
box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px,
box-shadow:
hsl(206 22% 7% / 35%) 0px 10px 38px -10px,
hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
animation-duration: 400ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
@@ -455,85 +281,14 @@ a {
}
}
.dropMenuBD {
display: flex;
flex-direction: row;
align-items: center;
}
.dropMenuSS {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
display: none;
}
.folderPath {
overflow-x: auto;
white-space: nowrap;
cursor: pointer;
user-select: none;
}
.folderPath::-webkit-scrollbar {
display: none;
/* for Chrome, Safari, and Opera */
}
.docDeleteBtn {
/* box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18); */
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
padding: 7px 17px;
color: white;
font-weight: 600 !important;
font-size: 12px !important;
border: none;
border-radius: 2px;
}
.docDeleteBtn:focus {
border: none;
outline: none;
}
.docDeleteBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
color: white;
}
@media screen and (max-width: 766px) {
.itemColor {
font-size: 10px !important;
}
}
@media (min-width: 310px) and (max-width: 550px) {
.pdfContainer {
justify-content: space-around;
}
.sort {
padding: 2px;
}
.folderComponent {
margin: 10px;
}
}
@media screen and (max-width: 309px) {
.pdfContainer {
justify-content: center;
}
.sort {
padding: 2px;
}
.folderComponent {
margin: 10px;
}
}
-136
View File
@@ -1,136 +0,0 @@
/* Full-width input fields */
.inputt {
width: 100%;
padding: 8px;
margin-bottom: 10px;
/* margin: 5px 0 14px 0; */
display: inline-block;
border: none;
background: #f1f1f1;
color: black;
font-size: 12px;
}
/* Add a background color when the inputs get focus */
.inputt:focus {
background-color: #ddd;
outline: none;
}
.confirmInputt {
width: 100%;
padding: 8px;
/* margin: 5px 0 14px 0; */
display: inline-block;
background: #f1f1f1;
color: black;
font-size: 12px;
}
.inputt::placeholder,
.confirmInputt::placeholder {
color: #474e5d;
opacity: 1;
/* Firefox */
}
.inputt:-ms-input-placeholder,
.confirmInputt:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #474e5d;
}
/* Set a style for all buttons */
.signupbtn {
background-color: #15b4e9;
color: white;
padding: 12px 12px;
margin: 8px 0;
border: none;
cursor: pointer;
opacity: 0.9;
float: left;
width: 50%;
}
.signupbtn:hover {
opacity: 1;
}
/* Add padding to pgsignup-container elements */
.pgsignup-container {
padding: 16px;
}
/* The pgsignup (background) */
.pgsignup {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: #474e5d;
padding-top: 50px;
}
/* pgsignup Content/Box */
.pgsignup-content {
background-color: #fefefe;
margin: 5% auto 15% auto;
/* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 50%;
/* Could be more or less, depending on screen size */
}
/* Style the horizontal ruler */
.hrt {
border: 1px solid #f1f1f1;
margin-bottom: 25px;
}
.clearfix {
display: flex;
justify-content: center;
align-items: center;
}
/* Clear floats */
.clearfix::after {
content: "";
clear: both;
display: table;
}
/* Change styles for cancel button and signup button on extra small screens */
@media screen and (max-width: 768px) {
/* pgsignup Content/Box */
.pgsignup-content {
background-color: #fefefe;
margin: 5% auto 15% auto;
/* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 90%;
/* Could be more or less, depending on screen size */
}
.signupbtn {
width: 100%;
font-size: 16px;
}
/* Style the horizontal ruler */
.hrt {
border: 1px solid #f1f1f1;
margin-bottom: 16px;
}
}
+14 -757
View File
@@ -3,22 +3,6 @@
@import url("https://fonts.googleapis.com/css2?family=Delicious+Handrawn&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Cedarville+Cursive&display=swap");
.placeholderBlock {
padding: 0px;
position: absolute;
border-style: dashed;
width: 150px;
height: 60px;
background: #daebe0;
text-align: center;
justify-content: center;
border-width: 0.2px;
}
.dragCursor {
cursor: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAASElEQVR4nGNgwAMkJSUbpKSkOvCpIaT5PxSTbogUQjMYMwxeIIXmVFIxA8UGDDyQGg0DnIDi6JKUlCxHMqCeZAOghjSAMD5FAKfeaURdUFxCAAAAAElFTkSuQmCC"), auto;
}
.react-datepicker__input-container {
position: initial !important;
}
@@ -30,17 +14,6 @@
user-select: none;
}
.inputPlaceholder {
width: 100%;
height: 100%;
position: absolute;
left: 0px;
top: 0px;
/* font-size: 12px; */
border: 1px solid #007bff;
border-radius: 2px;
}
.radioButton {
width: 100%;
height: 100%;
@@ -52,52 +25,6 @@
border-radius: 50px;
}
.inputPlaceholder:focus {
outline: none;
border: 1px solid #188ae2;
}
.drodown-input {
padding: 5px;
width: 100%;
font-size: 0.75rem;
border: 1px solid #8ad5ce;
/* border: 1px solid #e2dddd; */
/* background-color: #e0e5f5; */
color: black;
font-family: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
font-weight: inherit;
overflow: visible;
}
.drodown-input:focus {
outline: none;
border: 1px solid #099b8d;
}
.dropdownAdd {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
color: white;
font-weight: 600;
font-size: 13px;
border: none;
margin-left: 10px;
}
.dropdownAdd:focus {
outline: none;
}
.dropdownList {
display: flex;
flex-direction: column;
justify-content: center;
width: 50%;
}
.signatureCanvas {
border: 2px solid #888;
background-color: rgb(255, 255, 255);
@@ -123,208 +50,20 @@
width: 460px;
}
.penContainerInitial {
width: 183px;
}
.borderResize {
.icon {
position: absolute;
display: inline-block;
width: 14px;
height: 14px;
}
.borderResize :hover {
cursor: sw-resize;
}
.dropdown-date-menu {
min-width: 7rem;
}
.mailBtn {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 15px !important;
background-color: rgb(79 190 241);
border: none !important;
color: white !important;
}
.mailBtn:hover {
box-shadow: 0 2px 4px rgba(154, 36, 36, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
}
.signatureBtn {
border: 1.5px solid #47a3ad;
border-radius: 3px;
display: flex;
padding: 0px;
justify-content: space-between;
background: white;
transition-duration: 0.4s;
cursor: all-scroll;
width: 150px;
height: 30px;
color: black;
}
.disableSign {
border: 1.5px solid #47a3ad;
margin-bottom: 10px;
border-radius: 3px;
display: flex;
padding: 0px;
justify-content: space-between;
background: white;
transition-duration: 0.4s;
cursor: all-scroll;
width: 150px;
height: 30px;
color: black;
border: 1px solid rgb(203, 203, 203);
cursor: text;
}
.emailInput {
padding: 10px;
border: 1.5px solid gray;
border-radius: 4px;
width: 100%;
font-size: 15px;
padding-bottom: 20px;
}
.emailInput:focus {
outline: none;
border: 1.5px solid #47a3ad;
}
.addEmail {
padding: "0px";
border: 1.5px solid #47a3ad;
border-radius: 4px;
width: 100%;
font-size: 15px;
}
.addEmail,
.emailInput {
outline: none;
}
.addEmailInput {
border: none;
outline: none;
}
.emailChip {
background-color: #47a3ad;
margin: 4px;
border-radius: 10px;
padding: 5px 10px;
}
.addEmailInput {
padding: 10px;
border-radius: 4px;
width: 100%;
font-size: 15px;
}
.addEmailInput:focus {
outline: none;
border: none;
}
.signatureInput {
width: 80%;
border-radius: 4px;
font-size: 20px;
border: 1px solid #e2dddd;
color: black;
font-family: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
font-weight: inherit;
overflow: visible;
height: 30px;
}
.signatureInput:focus {
outline: none;
border: 1px solid blue;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
}
.resizable-box-overlay {
position: absolute;
border: 2px solid #ddd;
overflow: hidden;
background-color: white;
}
.box-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.close-button {
align-self: flex-end;
margin: 8px;
cursor: pointer;
}
.placeholdCloseBtn {
position: absolute;
right: -5px;
top: -5px;
border-radius: 100%;
font-size: 10px;
cursor: pointer;
padding: 0px 5.1px 1px 5px;
}
.signCloseBtn {
position: absolute;
font-size: 14px;
cursor: pointer;
z-index: 2;
background: white;
}
.signCopy {
position: absolute;
font-size: 13px;
cursor: pointer;
z-index: 2;
background: white;
}
.signUserIcon {
position: absolute;
font-size: 13px;
cursor: pointer;
z-index: 2;
background: white;
}
.settingIcon {
position: absolute;
font-size: 13px;
cursor: pointer;
z-index: 2;
background: white;
}
.ScrollbarsCustom-Track {
.ScrollbarsCustom-TrackY {
width: 4px !important;
}
.ScrollbarsCustom-TrackX {
height: 4px !important;
}
.signYourselfBlock {
padding: 0px;
@@ -333,19 +72,10 @@
align-items: center !important;
}
.finishBtn {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 30px;
color: white;
font-weight: 500 !important;
font-size: 14px !important;
border: none;
margin-left: 10px;
border-radius: 2px;
}
.sendMail {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.1),
0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 30px;
color: white;
font-weight: 500 !important;
@@ -354,105 +84,11 @@
margin-left: 10px;
}
.finishBtn:focus {
border: none;
outline: none;
}
.finishBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
}
.saveBtn {
padding: 3px 18px !important;
}
.disabledFinish {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 30px;
color: white;
font-weight: 600;
font-size: 14px;
border: none;
margin-left: 10px;
}
.sendHover:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
color: white;
}
.defaultSignBox {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
width: 90%;
height: 111px;
padding: 8px 20px;
color: white;
font-weight: 600;
font-size: 14px;
border: none;
border-radius: 2px;
margin-left: 10px;
}
.defaultBtn {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 26px;
color: black;
font-weight: 500;
font-size: 14px;
border: 1px solid gray;
border-radius: 2px;
margin-left: 10px;
border: "none";
}
.defaultBtn:focus {
border: none;
outline: none;
}
.signerList {
overflow-y: scroll;
max-height: 180px;
}
.signerList::-webkit-scrollbar {
display: none;
}
.showScroll {
height: 100%;
overflow: scroll;
}
.showScroll::-webkit-scrollbar {
display: none;
}
.hideScroll {
height: 100%;
overflow: scroll;
}
.signedStyle {
color: white;
padding: 5px;
font-family: sans-serif;
font-size: 15px !important;
}
.userName {
font-size: 12px !important;
font-weight: bold !important;
color: #424242 !important;
width: 100px;
.user {
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
}
.disabled {
opacity: 0.5;
/* Example: reduce opacity to visually indicate disabled state */
@@ -461,26 +97,6 @@
/* background-color: #888; */
}
.useEmail {
font-size: 10px;
color: #424242;
font-weight: 500;
width: 100px;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
}
.spanTagHead {
color: white !important;
font-size: 17px;
font-weight: 500;
}
.pTagBody {
font-size: 15px !important;
}
.signTab {
cursor: pointer !important;
font-weight: 400 !important;
@@ -488,70 +104,10 @@
font-size: 15px !important;
}
.cancelBtn {
color: black;
border: 1px solid #ccc;
}
.draggable-button {
padding: 10px 20px;
background: #3498db;
color: #fff;
border: none;
cursor: grab;
transition: transform 0.2s;
}
.draggable-button.dragging {
opacity: 0.5;
/* Reduce opacity while dragging */
transform: scale(1.1);
/* Apply a scaling effect while dragging */
}
.signatureContainer {
display: flex;
flex-direction: row;
justify-content: space-between;
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 {
padding: 1rem !important;
padding-top: 2rem !important;
}
.signLayoutContainer1 {
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
}
.signLayoutContainer2 {
display: none;
}
.preBtn1 {
display: flex;
align-items: center;
}
.preBtn2 {
display: none;
}
.headerBtn2 {
display: none;
}
.uploadImgLogo {
@@ -619,7 +175,6 @@
gap: 5px;
border: none;
background-color: #887abf;
width: 100px;
white-space: nowrap;
overflow: hidden !important;
@@ -681,7 +236,8 @@ option {
overflow: hidden;
background-color: white;
border-radius: 6px;
box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35),
box-shadow:
0px 10px 38px -10px rgba(22, 23, 24, 0.35),
0px 10px 20px -15px rgba(22, 23, 24, 0.2);
}
@@ -746,11 +302,6 @@ option {
cursor: default;
}
.fontOptionContainer {
border: 1px solid #d6d3d3;
margin: 10px 0px 5px 0px;
}
.dropDownStyle {
width: auto;
}
@@ -767,16 +318,6 @@ option {
width: 76%;
}
.regxSelect {
border: 1px solid #8ad5ce;
width: 80%;
}
.regxSelect:focus {
outline: none;
border: 1px solid #8ad5ce;
}
.radioGroupInput {
width: 100%;
}
@@ -787,77 +328,18 @@ option {
justify-content: flex-start;
}
.labelWidthDesktop {
min-width: 100%;
min-height: 100%;
}
.labelWidthMobile {
width: 100%;
height: 100%;
}
.labelTextArea {
font-size: 12px;
border: 1px solid #007bff;
outline: none;
z-index: 999;
border-radius: 2px;
resize: none;
overflow: hidden;
}
.labelTextArea:focus {
outline: none;
border: 1px solid #188ae2;
}
@media screen and (max-width: 766px) {
.validateInputText {
width: 93%;
}
.regxSelect {
width: 100%;
}
.validateText {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.showPages {
display: none;
}
.dropdown-menu {
min-width: 0rem !important;
}
.signatureContainer {
display: flex;
flex-direction: column;
}
.signerComponent {
display: none;
}
.preBtn1 {
display: none;
}
.preBtn2 {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #ebebeb;
padding: 5px 10px;
}
#navbar {
overflow: hidden;
z-index: 49;
}
/* Navbar links */
@@ -891,51 +373,13 @@ option {
position: fixed;
}
.stickyfooter {
position: fixed;
z-index: 99 !important;
bottom: 0px;
right: 0rem;
}
/* Add some top padding to the page content
to prevent sudden quick movement (as the
navigation bar gets a new position at the top of the
page (position:fixed and top:0) */
.stickyHead+.content {
.stickyHead + .content {
padding-top: 60px;
}
.signLayoutContainer2 {
display: flex;
flex-direction: row;
justify-content: space-around;
margin-top: 5px;
padding: 2px 5px 10px 5px;
position: sticky;
align-items: center;
}
.headerBtn {
display: none;
}
.headerBtn2 {
display: flex;
flex-direction: column;
justify-content: space-between;
margin-top: 5px;
}
.mobileHead {
display: flex;
}
.signatureText {
margin-right: 5px;
font-size: 12px;
}
}
@media screen and (max-width: 487px) and (min-width: 351px) {
@@ -952,17 +396,8 @@ option {
font-size: 30px;
}
.hidePdf {
display: none;
}
.mobileHead {
display: flex;
}
.signTab {
font-weight: 500 !important;
font-size: 12px !important;
}
}
@@ -980,10 +415,6 @@ option {
width: 280px;
}
.hidePdf {
display: none;
}
.signTab {
font-weight: 500 !important;
@@ -993,14 +424,6 @@ option {
.uploadImgLogo {
font-size: 25px;
}
.uploadImg {
font-size: 10px !important;
}
.mobileHead {
display: flex;
}
}
@media screen and (max-width: 310px) {
@@ -1013,178 +436,12 @@ option {
width: 230px;
}
.hidePdf {
display: none;
}
.signTab {
font-weight: 500 !important;
font-size: 8px !important;
}
.uploadImgLogo {
font-size: 20px;
}
.uploadImg {
font-size: 10px !important;
}
.mobileHead {
display: flex;
}
}
.signature-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #000;
}
.signature-backdrop.fade.in {
opacity: 0.5;
}
.modaloverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.75);
justify-content: center;
align-items: center;
z-index: 900;
}
.modalcontainer {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 901;
max-height: 80%;
min-width: 500px;
overflow-y: auto;
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* Internet Explorer and Edge */
}
.dropdownModal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 901;
max-height: 80%;
min-width: 40%;
overflow-y: auto;
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* Internet Explorer and Edge */
}
/* Hide scrollbar for Webkit browsers */
.modalcontainer::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for Webkit browsers */
.dropdownModal::-webkit-scrollbar {
display: none;
}
.modalheader {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
border-bottom: 1px solid #ccc;
color: #ffffff;
}
/* Styling for the modal title */
.modaltitle {
font-size: 1.2rem;
font-weight: normal;
}
/* Styling for the close button */
.closebtn {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
}
.defaultOptions {
font-size: 12px;
margin-left: 5px;
}
.defaultOptions:focus {
outline: none;
}
@media (max-width: 767px) {
.modalcontainer {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
max-height: 80%;
min-width: 90%;
overflow-y: auto;
}
.signatureBtn {
width: max-content;
}
.dropdownModal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
max-height: 80%;
min-width: 60%;
overflow-y: auto;
}
}
@media (max-width: 464px) {
.dropdownModal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
max-height: 80%;
min-width: 78%;
overflow-y: auto;
}
}
+6 -6
View File
@@ -42,14 +42,14 @@ module.exports = {
"sunset",
{
opensigncss: {
primary: "#034687",
"primary-content": "#ccd9e8",
secondary: "#151B25",
"secondary-content": "#cacccf",
primary: "#002864",
"primary-content": "#cacccf",
secondary: "#29354a",
"secondary-content": "#c8d1e0",
accent: "#E10032",
"accent-content": "#ffd8d5",
neutral: "#F0D7D9",
"neutral-content": "#141111",
neutral: "#c1ccdb",
"neutral-content": "#111312",
"base-100": "#ffffff",
"base-200": "#dedede",
"base-300": "#bebebe",
+4 -4
View File
@@ -44,7 +44,7 @@
"mongodb-runner": "^5.6.2",
"nodemon": "^3.1.3",
"nyc": "15.1.0",
"prettier": "^3.3.0",
"prettier": "^3.3.2",
"uglify-js": "^3.17.4"
},
"engines": {
@@ -10298,9 +10298,9 @@
}
},
"node_modules/prettier": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.0.tgz",
"integrity": "sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==",
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
+1 -1
View File
@@ -54,7 +54,7 @@
"mongodb-runner": "^5.6.2",
"nodemon": "^3.1.3",
"nyc": "15.1.0",
"prettier": "^3.3.0",
"prettier": "^3.3.2",
"uglify-js": "^3.17.4"
},
"engines": {