Compare commits

..
2 Commits
Author SHA1 Message Date
AmolandGitHub b4315b5e0a Merge pull request #163 from OpenSignLabs/staging
v1.0.4
2023-11-10 02:52:04 +05:30
AmolandGitHub ccecec5e59 Merge pull request #149 from OpenSignLabs/staging
v1.0.3
2023-11-08 14:28:32 +05:30
88 changed files with 3800 additions and 5706 deletions
-18
View File
@@ -178,24 +178,6 @@
"contributions": [ "contributions": [
"a11y" "a11y"
] ]
},
{
"login": "Govinda04",
"name": "Govinda Kocharekar",
"avatar_url": "https://avatars.githubusercontent.com/u/50038172?v=4",
"profile": "https://github.com/Govinda04",
"contributions": [
"code"
]
},
{
"login": "crediblebilal",
"name": "Bilal Ahmad Bhat",
"avatar_url": "https://avatars.githubusercontent.com/u/55330484?v=4",
"profile": "https://bilal.cc",
"contributions": [
"code"
]
} }
] ]
} }
+2 -9
View File
@@ -39,18 +39,11 @@ DO_ACCESS_KEY_ID=
DO_SECRET_ACCESS_KEY= DO_SECRET_ACCESS_KEY=
# Digital ocean spaces region or AWS s3 region # Digital ocean spaces region or AWS s3 region
DO_REGION=us-west DO_REGION=us-west
# Set this to true id you are using local storage instead of s3 compatible storage
# USE_LOCAL=TRUE
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) ********************************************************************************************************************* # Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
MAILGUN_API_KEY=XXXXX MAILGUN_API_KEY=
MAILGUN_DOMAIN=mail.yourdomain.com MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_SENDER=postmaster@mail.yourdomain.com MAILGUN_SENDER=postmaster@mail.yourdomain.com
SMTP_ENABLE=
SMTP_HOST=
SMTP_PORT=
SMTP_USER_EMAIL=
SMTP_PASS=
# Base64 encoded PFX or p12 document signing certificate file ********************************************************************************************************************* # Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
PFX_BASE64= PFX_BASE64=
+58 -63
View File
@@ -42,74 +42,69 @@ DO_SECRET_ACCESS_KEY=
# Digital ocean spaces region or AWS s3 region # Digital ocean spaces region or AWS s3 region
DO_REGION=us-west DO_REGION=us-west
# local storage # local storage
USE_LOCAL=TRUE USE_LOCAL=FALSE
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) ********************************************************************************************************************* # Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
MAILGUN_API_KEY=XXXXX MAILGUN_API_KEY=XXXXX
MAILGUN_DOMAIN=mail.yourdomain.com MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_SENDER=postmaster@mail.yourdomain.com MAILGUN_SENDER=postmaster@mail.yourdomain.com
SMTP_ENABLE=
SMTP_HOST=
SMTP_PORT=
SMTP_USER_EMAIL=
SMTP_PASS=
# Base64 encoded PFX or p12 document signing certificate file ********************************************************************************************************************* # Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
PFX_BASE64='MIIKCQIBAzCCCc8GCSqGSIb3DQEHAaCCCcAEggm8MIIJuDCCBG8GCSqGSIb3DQEH PFX_BASE64='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
3pXAXxZuvVvv9tsb4bdrBAhyb+KCIjp/gAICCAA=' MEEwMTANBglghkgBZQMEAgEFAAQgPlLuG+67SxPOEPbgFuEnVgewvY6LUzFmrprx
c6yryFgECIld0S5kDk7JAgIIAA=='
# Provide Pass pharse of above PFX or p12 document # Provide Pass pharse of above PFX or p12 document
PASS_PHRASE=opensign PASS_PHRASE=
-73
View File
@@ -1,73 +0,0 @@
name: "Bug Report"
labels: ["bug","up-for-grabs"]
title: "[Bug]: "
assignees:
- andrew-opensignlabs
description: Create a bug report to help us make OpenSign™ the world's best document e-signature platform
body:
- type: textarea
attributes:
label: Issue Description
description: Please provide a clear & concise description of the problem.
- type: textarea
attributes:
label: Expected Behavior
description: Describe what you expected to happen.
- type: textarea
attributes:
label: Current Behavior
description: Describe what is happening instead.
- type: textarea
attributes:
label: Steps to reproduce
description: Please provide step-by-step instructions to reproduce the issue. Include code snippets, URLs, error messages and any other relevant information.
- type: textarea
attributes:
label: Screenshots of the issue(optional)
description: Add screenshots to better explain the issue.
- type: input
attributes:
label: Operating System [e.g. MacOS Sonoma 14.1, Windows 11]
- type: dropdown
id: browsers
attributes:
label: What browsers are you seeing the problem on?
multiple: true
options:
- Chrome
- Firefox
- Safari
- Microsoft Edge
default: 0
- type: input
attributes:
label: What version of OpenSign™ are you seeing this issue on? [e.g. 1.0.6]
validations:
required: true
- type: dropdown
id: environment
attributes:
label: What environment are you seeing the problem on?
multiple: true
options:
- Production (app.opensignlabs.com)
- Staging (staging-app.opensignlabs.com)
- Hosted (app.yourdomain.com)
- Dev (localhost or vercel)
- type: checkboxes
attributes:
label: Please check the boxes that apply to this issue report.
options:
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
validations:
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
options:
- label: I agree to follow this project's Code of Conduct
required: true
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
required: true
@@ -1,70 +0,0 @@
name: Feature Request
description: Suggest an idea for OpenSign™
title: "Feature Request: [Short Description]"
labels: [feature request, needs triage]
body:
- type: markdown
attributes:
value: |
## Thanks for taking the time to fill out this feature request!
- type: input
id: title
attributes:
label: Feature Title
description: What would you call this feature?
placeholder: e.g., Advanced Signature Verification
validations:
required: true
- type: textarea
id: feature-description
attributes:
label: Feature Description
description: |
Please provide a detailed description of the feature you're proposing.
placeholder: |
e.g., I'm proposing an advanced signature verification feature that...
validations:
required: true
- type: dropdown
id: featuretype
attributes:
label: What type of feature are you requesting?
multiple: true
options:
- UI/UX Improvement
- Security / Compliance
- Performance / Optimization
- 3rd party integration
- Other
- type: dropdown
id: importance
attributes:
label: Importance
description: How important is this feature to you?
options:
- Critical
- High
- Medium
- Low
validations:
required: true
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Any other context or screenshots about the feature request here.
placeholder: Additional details, examples, or screenshots...
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
options:
- label: I agree to follow this project's Code of Conduct
required: true
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
required: true
+4 -3
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env sh #!/bin/sh
. "$(dirname -- "$0")/_/husky.sh" . "$(dirname "$0")/_/husky.sh"
npm run lint-staged-changes npx eslint '**/*.{js,jsx}'
npx pretty-quick --staged '**/*.{js,jsx}'
-3
View File
@@ -1,3 +0,0 @@
{
"*.js": "prettier --write"
}
+2 -1
View File
@@ -98,7 +98,8 @@ Environment Varaibles:
| PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed | | PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
| GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging | | GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging |
| REACT_APP_SERVERURL | http://localhost:8080/app | 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 | http://localhost:8080/app | 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_APPID | opensignstgn | 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 | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
| PUBLIC_URL | opensignstgn | 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. |
| APP_ID | opensignstgn | A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App. | | APP_ID | opensignstgn | A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App. |
| appName | open_sign_server | Name of the app. It will be visible in the verification emails sent out. | | appName | open_sign_server | Name of the app. It will be visible in the verification emails sent out. |
| MASTER_KEY | XnAadwKxxByMr | A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database. | | MASTER_KEY | XnAadwKxxByMr | A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database. |
+1 -1
View File
@@ -2,7 +2,7 @@ build:
cp .env.local_dev .env cp .env.local_dev .env
rm -rf apps/OpenSign/public/mfbuild rm -rf apps/OpenSign/public/mfbuild
cd microfrontends/SignDocuments && npm install && npm run build cd microfrontends/SignDocuments && npm install && npm run build
docker compose up --build --force-recreate docker compose up -d
run: run:
cp .env.local_dev .env cp .env.local_dev .env
+13 -18
View File
@@ -1,7 +1,8 @@
<h1 align="center"><a href='https://www.opensignlabs.com'><img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/e518cc9c-5de3-47da-950b-f93336b9f14e></a> <h1 align="center"><a href='https://www.opensignlabs.com'>OpenSign™</a></h1>
</h1><div align="center">
<div align="center">
[The free and open source alternative to DocuSign](https://www.opensignlabs.com) The free and open source alternative to DocuSign
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/opensignlabs/opensign.svg)](http://isitmaintained.com/project/opensignlabs/opensign "Average time to resolve an issue") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/opensignlabs/opensign.svg)](http://isitmaintained.com/project/opensignlabs/opensign "Average time to resolve an issue")
[![All Contributors](https://img.shields.io/github/all-contributors/opensignlabs/opensign?color=ee8449&style=flat-square)](#contributors) [![All Contributors](https://img.shields.io/github/all-contributors/opensignlabs/opensign?color=ee8449&style=flat-square)](#contributors)
@@ -22,7 +23,7 @@
<a href="https://www.linkedin.com/company/opensign%E2%84%A2/about/">LinkedIn</a> <a href="https://www.linkedin.com/company/opensign%E2%84%A2/about/">LinkedIn</a>
## The open-source document e-signing solution ## An open-source document e-signing solution
--- ---
</div> </div>
@@ -47,18 +48,14 @@ Welcome to OpenSign, an open-source document e-signing solution designed to prov
### Features ### Features
- **Secure PDF E-Signing:** With the help of Robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility. - **Secure Signing**: Utilizes state-of-the-art cryptographic algorithms to ensure the security & integrity of your documents.
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that comes with hand drawn signatures support as well as uploaded images & saved signatures for the simplest signing experience. - **User-Friendly Interface**: Designed with usability in mind, making it easy for both technical and non-technical users.
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders. - **Multi-Platform Support**: Compatible with various browsers and devices.
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players. - **Invite & collaborate users**: Bring multiple people from your team into the signing process, all within your own infrastructure.
- **Email Unique Code(OTP) verification support for guest signers:** With OpenSign™, your documents are fully secure even when being signed by guest users. Guest signers can only sign the document after entering a unique code sent to their email address.  - **Secure**: Allows for the easy, secure and seamless organization of your documents using 'OpenSigDrive'.
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign it. Not just this, OpenSign also allows signers to reject signing a document. - **Audit Trails**: Keeps a detailed log of all activities related to the document signing process including IP addresses and access timings.
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates. - **Completion Certificate**: Generate secure completion certificate as soon as a document is signed by all participants.
- **PDF Template Creation(coming soon):** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time. - **API Support**: Provides a robust API for integration into other software and services.
- **OpenSign™ Drive:** It is a centralised secure vault for your signed documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
- **Audit Trails & completion certificate:** Being a security focused solution, OpenSign™ makes it a top priority to save detailed logs for tracking document activities along with time-stamps, IP addresses, email IDs & phone numbers. A completion certificate is generated as soon as document is completed which contains all the document related logs for added safety.
- **API Support(coming soon):** OpenSign™ API allows seamless integration into existing systems and software. APIs will soon be available as a cloud hosted solution.
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is coming soon.
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/b37ff443-7099-4273-9aeb-21c46d7154cf height='200'> <img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/b37ff443-7099-4273-9aeb-21c46d7154cf height='200'>
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/86db91b7-6c2f-4885-a33c-58f4fd35ec89 height='200'> <img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/86db91b7-6c2f-4885-a33c-58f4fd35ec89 height='200'>
@@ -128,8 +125,6 @@ We would like to thank all our contributors and users for their support and feed
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rishabjasrotia"><img src="https://avatars.githubusercontent.com/u/33950743?v=4?s=100" width="100px;" alt="Rishab"/><br /><sub><b>Rishab</b></sub></a><br /><a href="#code-rishabjasrotia" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/rishabjasrotia"><img src="https://avatars.githubusercontent.com/u/33950743?v=4?s=100" width="100px;" alt="Rishab"/><br /><sub><b>Rishab</b></sub></a><br /><a href="#code-rishabjasrotia" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://session.it"><img src="https://avatars.githubusercontent.com/u/327285?v=4?s=100" width="100px;" alt="Maurizio Pillitu"/><br /><sub><b>Maurizio Pillitu</b></sub></a><br /><a href="#bug-maoo" title="Bug reports">🐛</a></td> <td align="center" valign="top" width="14.28%"><a href="https://session.it"><img src="https://avatars.githubusercontent.com/u/327285?v=4?s=100" width="100px;" alt="Maurizio Pillitu"/><br /><sub><b>Maurizio Pillitu</b></sub></a><br /><a href="#bug-maoo" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://luisparra.dev"><img src="https://avatars.githubusercontent.com/u/16653744?v=4?s=100" width="100px;" alt="Luis Parra"/><br /><sub><b>Luis Parra</b></sub></a><br /><a href="#a11y-lsprr" title="Accessibility">️♿️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://luisparra.dev"><img src="https://avatars.githubusercontent.com/u/16653744?v=4?s=100" width="100px;" alt="Luis Parra"/><br /><sub><b>Luis Parra</b></sub></a><br /><a href="#a11y-lsprr" title="Accessibility">️♿️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Govinda04"><img src="https://avatars.githubusercontent.com/u/50038172?v=4?s=100" width="100px;" alt="Govinda Kocharekar"/><br /><sub><b>Govinda Kocharekar</b></sub></a><br /><a href="#code-Govinda04" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bilal.cc"><img src="https://avatars.githubusercontent.com/u/55330484?v=4?s=100" width="100px;" alt="Bilal Ahmad Bhat"/><br /><sub><b>Bilal Ahmad Bhat</b></sub></a><br /><a href="#code-crediblebilal" title="Code">💻</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
-1
View File
@@ -10,7 +10,6 @@
# production # production
/build /build
/mfbuild
# misc # misc
.env .env
+2 -3
View File
@@ -42,8 +42,7 @@
"scripts": { "scripts": {
"start": "serve -s build", "start": "serve -s build",
"start-dev": "mf-cra start", "start-dev": "mf-cra start",
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt", "build": "rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
"build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build", "micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
@@ -86,4 +85,4 @@
"pretty-quick": "^3.1.3", "pretty-quick": "^3.1.3",
"tailwindcss": "^3.3.3" "tailwindcss": "^3.3.3"
} }
} }
+2 -2
View File
@@ -31,7 +31,7 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" <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" /> integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<title>OpenSign</title> <title>Open sign</title>
</head> </head>
<body> <body>
@@ -50,4 +50,4 @@
--> -->
</body> </body>
</html> </html>
-1
View File
@@ -1 +0,0 @@
v1.0.5-beta
@@ -32,7 +32,6 @@ const AppendFormInForm = (props) => {
try { try {
const query = new Parse.Query("contracts_Contactbook"); const query = new Parse.Query("contracts_Contactbook");
query.equalTo("CreatedBy", user); query.equalTo("CreatedBy", user);
query.notEqualTo("IsDeleted", true);
query.equalTo("Email", user.getEmail()); query.equalTo("Email", user.getEmail());
const res = await query.first(); const res = await query.first();
// console.log(res); // console.log(res);
@@ -242,24 +241,7 @@ const AppendFormInForm = (props) => {
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
/> />
</div> </div>
<div className="mb-3">
<label
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email
<span style={{ color: "red", fontSize: 13 }}> *</span>
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
/>
</div>
<div className="mb-3"> <div className="mb-3">
<label <label
htmlFor="phone" htmlFor="phone"
@@ -279,6 +261,25 @@ const AppendFormInForm = (props) => {
/> />
</div> </div>
<div className="mb-3">
<label
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email
<span style={{ color: "red", fontSize: 13 }}> *</span>
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
/>
</div>
<div className="mt-4 flex justify-start"> <div className="mt-4 flex justify-start">
<button <button
type="submit" type="submit"
+7 -15
View File
@@ -1,20 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Package from "../../package.json"; import Package from "../../package.json";
import axios from "axios";
const Footer = () => { const Footer = () => {
const [showButton, setShowButton] = useState(false); const [showButton, setShowButton] = useState(false);
const [version, setVersion] = useState("");
useEffect(() => {
axios
.get("/version.txt")
.then((response) => {
setVersion(response.data); // Set the retrieved data to the state variable
})
.catch((error) => {
console.error("Error reading the file:", error);
});
}, []);
const handleScroll = () => { const handleScroll = () => {
if (window.pageYOffset >= 50) { if (window.pageYOffset >= 50) {
setShowButton(true); setShowButton(true);
@@ -37,12 +25,16 @@ const Footer = () => {
}, []); }, []);
const appName = "OpenSign™"; const appName = "OpenSign™";
return ( return (
<> <>
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3"> <div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
All Rights Reserved &copy; {new Date().getFullYear()} &nbsp; All Rights Reserved &copy; {new Date().getFullYear()} &nbsp;
{appName} ( version: {version ? version : `${Package.version} `}) {appName}{" "}
(version:{" "}
{localStorage.getItem("appVersion") &&
`${Package.version}.${localStorage.getItem("appVersion")}`}
)
</div> </div>
<button <button
className={`${ className={`${
+12 -15
View File
@@ -27,14 +27,14 @@ const LoginFacebook = ({
setThirdpartyLoader(true); setThirdpartyLoader(true);
const details = { const details = {
Email: response.email, Email: response.email,
Name: response.name Name: response.name,
}; };
setUserDetails({ ...userDetails, ...details }); setUserDetails({ ...userDetails, ...details });
const fDetails = { const fDetails = {
Id: response.userID, Id: response.userID,
AccessToken: response.accessToken, AccessToken: response.accessToken,
Name: response.name, Name: response.name,
Email: response.email Email: response.email,
}; };
setFBDetails({ ...fBDetails, ...fDetails }); setFBDetails({ ...fBDetails, ...fDetails });
const res = await checkExtUser(fDetails); const res = await checkExtUser(fDetails);
@@ -42,11 +42,9 @@ const LoginFacebook = ({
}; };
const checkExtUser = async (details) => { const checkExtUser = async (details) => {
// const extUser = new Parse.Query("contracts_Users"); const extUser = new Parse.Query("contracts_Users");
// extUser.equalTo("Email", details.Email); extUser.equalTo("Email", details.Email);
// const extRes = await extUser.first(); const extRes = await extUser.first();
const params = { email: details.Email };
const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes); // console.log("extRes ", extRes);
if (extRes) { if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") }; const params = { ...details, Phone: extRes.get("Phone") };
@@ -211,19 +209,18 @@ const LoginFacebook = ({
<div> <div>
<button <button
type="button" type="button"
onClick={() => handleSubmitbtn()} className="btn btn-secondary"
className="btn btn-info" onClick={() => setIsModal(false)}
style={{ marginRight: 10 }} style={{ marginRight: 10, width: 90 }}
> >
Sign up Cancel
</button> </button>
<button <button
type="button" type="button"
className="btn btn-secondary" onClick={() => handleSubmitbtn()}
onClick={() => setIsModal(false)} className="btn btn-info"
style={{ width: 90 }}
> >
Cancel Sign up
</button> </button>
</div> </div>
</form> </form>
+13 -51
View File
@@ -42,42 +42,7 @@ const GoogleSignInBtn = ({
width: "187px" width: "187px"
}); });
}); });
const clearStorage = async () => {
if (Parse.User.current()) {
await Parse.User.logOut();
}
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let applogo = localStorage.getItem("appLogo");
let domain = localStorage.getItem("domain");
let appversion = localStorage.getItem("appVersion");
let appTitle = localStorage.getItem("appTitle");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let _appName = localStorage.getItem("_appName");
let _app_objectId = localStorage.getItem("_app_objectId");
let appName = localStorage.getItem("appName");
let userSettings = localStorage.getItem("userSettings");
localStorage.clear();
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("domain", domain);
localStorage.setItem("appversion", appversion);
localStorage.setItem("appTitle", appTitle);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("_appName", _appName);
localStorage.setItem("_app_objectId", _app_objectId);
localStorage.setItem("appName", appName);
localStorage.setItem("userSettings", userSettings);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
};
const responseGoogle = async (response) => { const responseGoogle = async (response) => {
clearStorage();
setThirdpartyLoader(true); setThirdpartyLoader(true);
// console.log("response ", response); // console.log("response ", response);
if (response.credential) { if (response.credential) {
@@ -101,11 +66,9 @@ const GoogleSignInBtn = ({
} }
}; };
const checkExtUser = async (details) => { const checkExtUser = async (details) => {
// const extUser = new Parse.Query("contracts_Users"); const extUser = new Parse.Query("contracts_Users");
// extUser.equalTo("Email", details.Gmail); extUser.equalTo("Email", details.Gmail);
// const extRes = await extUser.first(); const extRes = await extUser.first();
const params = { email: details.Gmail };
const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes); // console.log("extRes ", extRes);
if (extRes) { if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") }; const params = { ...details, Phone: extRes.get("Phone") };
@@ -298,17 +261,17 @@ const GoogleSignInBtn = ({
</div> </div>
<div className="form-group"> <div className="form-group">
<label <label
htmlFor="JobTitle" htmlFor="Destination"
style={{ display: "flex" }} style={{ display: "flex" }}
className="col-form-label" className="col-form-label"
> >
Job Title{" "} Destination{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span> <span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="text" type="text"
className="form-control" className="form-control"
id="JobTitle" id="Destination"
value={userDetails.Destination} value={userDetails.Destination}
onChange={(e) => onChange={(e) =>
setUserDetails({ setUserDetails({
@@ -322,19 +285,18 @@ const GoogleSignInBtn = ({
<div> <div>
<button <button
type="button" type="button"
className="bg-[#17a2b8] p-2 text-white rounded" className="bg-[#6c757d] p-2 text-white rounded"
onClick={() => handleSubmitbtn()} onClick={handleCloseModal}
style={{ marginRight: 10 }} style={{ marginRight: 10, width: 90 }}
> >
Sign up Cancel
</button> </button>
<button <button
type="button" type="button"
className="bg-[#6c757d] p-2 text-white rounded" className="bg-[#17a2b8] p-2 text-white rounded"
onClick={handleCloseModal} onClick={() => handleSubmitbtn()}
style={{ width: 90 }}
> >
Cancel Sign up
</button> </button>
</div> </div>
</form> </form>
+21 -22
View File
@@ -49,9 +49,12 @@ const TreeWidget = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
res = await Parse.Cloud.run("getUserDetails", { var emp = Parse.Object.extend(
email: currentUser.get("email") localStorage.getItem("extended_class")
}); );
var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
res = await q.first();
if (res) res = res.toJSON(); if (res) res = res.toJSON();
} }
if (res) { if (res) {
@@ -76,9 +79,12 @@ const TreeWidget = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
res = await Parse.Cloud.run("getUserDetails", { emp = Parse.Object.extend(
email: currentUser.get("email") localStorage.getItem("extended_class")
}); );
q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
res = await q.first();
if (res) res = res.toJSON(); if (res) res = res.toJSON();
} }
@@ -115,15 +121,10 @@ const TreeWidget = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
// emp = Parse.Object.extend(localStorage.getItem("extended_class")); emp = Parse.Object.extend(localStorage.getItem("extended_class"));
// q = new Parse.Query(emp); q = new Parse.Query(emp);
// q.equalTo("UserId", currentUser); q.equalTo("UserId", currentUser);
// res = await q.first(); res = await q.first();
// if (res) res = res.toJSON();
const currentUser = Parse.User.current();
res = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
if (res) res = res.toJSON(); if (res) res = res.toJSON();
} }
@@ -472,8 +473,6 @@ const TreeWidget = (props) => {
props.schema.data.FolderTypeField, props.schema.data.FolderTypeField,
props.schema.data.FolderTypeValue props.schema.data.FolderTypeValue
); );
const currentUser = Parse.User.current();
folder.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
if (tabList.length > 0) { if (tabList.length > 0) {
let len = tabList.length - 1; let len = tabList.length - 1;
folder.set(props.schema.data.ParentFolderField, { folder.set(props.schema.data.ParentFolderField, {
@@ -533,7 +532,7 @@ const TreeWidget = (props) => {
padding: 0 padding: 0
}, },
overlay: { overlay: {
width: "100%", width:"100%",
backgroundColor: "rgba(0, 0, 0, 0.75)", backgroundColor: "rgba(0, 0, 0, 0.75)",
zIndex: 50 zIndex: 50
} }
@@ -700,7 +699,7 @@ const TreeWidget = (props) => {
))} ))}
<hr /> <hr />
</div> </div>
{/* {editable && ( {editable && (
<TreeEditForm <TreeEditForm
FormId={props.schema.data.FormId} FormId={props.schema.data.FormId}
objectId={editId} objectId={editId}
@@ -709,7 +708,7 @@ const TreeWidget = (props) => {
selectFolderHandle(); selectFolderHandle();
}} }}
/> />
)} */} )}
{isAddField && !loader && !editable && ( {isAddField && !loader && !editable && (
<TreeFormComponent <TreeFormComponent
Id={props.schema.data.FormId} Id={props.schema.data.FormId}
@@ -797,7 +796,7 @@ const TreeWidget = (props) => {
</a> </a>
</div> </div>
{/* {fldr[props.schema.data.FolderTypeField] === {fldr[props.schema.data.FolderTypeField] ===
props.schema.data.FolderTypeValue && ( props.schema.data.FolderTypeValue && (
<a <a
className="float-right" className="float-right"
@@ -817,7 +816,7 @@ const TreeWidget = (props) => {
aria-hidden="true" aria-hidden="true"
></i> ></i>
</a> </a>
)} */} )}
</li> </li>
) )
)} )}
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import axios from "axios"; import axios from "axios";
import Parse from "parse"; import Parse from "parse";
import onSearchFilter from "../../constant/searchQuery";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery"; import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
import "../../styles/loader.css"; import "../../styles/loader.css";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
@@ -34,9 +35,14 @@ const DashboardCard = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
res = await Parse.Cloud.run("getUserDetails", { var emp = Parse.Object.extend(localStorage.getItem("extended_class"));
email: currentUser.get("email") var q = new Parse.Query(emp);
q.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: currentUser
}); });
res = await q.first();
if (res) res = res.toJSON(); if (res) res = res.toJSON();
} }
if (res) { if (res) {
@@ -44,7 +50,12 @@ const DashboardCard = (props) => {
var reg = /(\#.*?\#)/gi; // eslint-disable-line var reg = /(\#.*?\#)/gi; // eslint-disable-line
var str = props.Data.query; var str = props.Data.query;
var test = ""; var test = "";
if (str.includes("#filterCondition#")) {
str = str.replace(
"#filterCondition#",
onSearchFilter(props.DefaultQuery)
);
}
if (props.Data.extendkey) { if (props.Data.extendkey) {
let a = props.Data.extendkey.split("."); let a = props.Data.extendkey.split(".");
if (a.length > 0) { if (a.length > 0) {
@@ -99,10 +110,13 @@ const DashboardCard = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
resr = data[0]; resr = data[0];
} else { } else {
resr = await Parse.Cloud.run("getUserDetails", { let emp = Parse.Object.extend(
email: currentUser.get("email") localStorage.getItem("extended_class")
}); );
if (resr) resr = resr.toJSON(); let q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
let t = await q.first();
resr = t.toJSON();
} }
let json = resr; let json = resr;
@@ -136,65 +150,47 @@ const DashboardCard = (props) => {
"X-Parse-Application-Id": parseAppId, "X-Parse-Application-Id": parseAppId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken") "X-Parse-Session-Token": localStorage.getItem("accesstoken")
}; };
// handle need your sign report count await axios.get(url, { headers: headers }).then((res) => {
if (props.Data.Redirect_id === "4Hhwbp482K") { if (res.data.results.length > 0) {
const params = { setLoading(false);
reportId: props.Data.Redirect_id, if (props.Data.key !== "count") {
skip: 0, setresponse(res.data.results[0][props.Data.key]);
limit: 200 } else {
}; if (props.Label === "Need your Signature") {
const url = `${parseBaseUrl}/functions/getReport`; const listData = res.data?.results.filter(
await axios (x) => x.Signers.length > 0
.post(url, params, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessiontoken: localStorage.getItem("accesstoken")
}
})
.then((res) => {
const listData = res.data?.result.filter(
(x) => x.Signers.length > 0
);
let arr = [];
for (const obj of listData) {
const isSigner = obj.Signers.some(
(item) => item.UserId.objectId === currentUser.id
); );
if (isSigner) { let arr = [];
let isRecord; for (const obj of listData) {
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) { const isSigner = obj.Signers.some(
isRecord = obj?.AuditTrail.some( (item) => item.UserId.objectId === currentUser.id
(item) => );
item?.UserPtr?.UserId?.objectId === currentUser.id && if (isSigner) {
item.Activity === "Signed" let isRecord;
); if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
} else { isRecord = obj?.AuditTrail.some(
isRecord = false; (item) =>
} item?.UserPtr?.UserId?.objectId === currentUser.id &&
if (isRecord === false) { item.Activity === "Signed"
arr.push(obj); );
} else {
isRecord = false;
}
if (isRecord === false) {
arr.push(obj);
}
} }
} }
} setresponse(arr.length);
setresponse(arr.length);
setLoading(false);
});
} else {
await axios.get(url, { headers: headers }).then((res) => {
if (res.data.results.length > 0) {
setLoading(false);
if (props.Data.key !== "count") {
setresponse(res.data.results[0][props.Data.key]);
} else { } else {
setresponse(res.data[props.Data.key]); setresponse(res.data[props.Data.key]);
} }
} else {
setresponse(0);
setLoading(false);
} }
}); } else {
} setresponse(0);
setLoading(false);
}
});
} catch (e) { } catch (e) {
console.error("Problem", e); console.error("Problem", e);
setLoading(false); setLoading(false);
@@ -231,10 +227,13 @@ const DashboardCard = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
let resr = await Parse.Cloud.run("getUserDetails", { var emp = Parse.Object.extend(
email: currentUser.get("email") localStorage.getItem("extended_class")
}); );
if (res) res = resr.toJSON(); var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
let resr = await q.first();
res = resr.toJSON();
} }
let json = res; let json = res;
@@ -9,60 +9,39 @@ function DashboardReport(props) {
const [isLoader, setIsLoader] = useState(true); const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState(""); const [reportName, setReportName] = useState("");
const [actions, setActions] = useState([]); const [actions, setActions] = useState([]);
const [heading, setHeading] = useState([]);
const [isNextRecord, setIsNextRecord] = useState(false);
const [isMoreDocs, setIsMoreDocs] = useState(true);
const abortController = new AbortController();
const docPerPage = 5;
useEffect(() => { useEffect(() => {
setReportName(""); setReportName("");
getReportData(props.Record.reportId); getReportData(props.Record.reportId);
// Function returned from useEffect is called on unmount
return () => {
setIsLoader(true);
setList([]);
setIsNextRecord(false);
// Here it'll abort the fetch
abortController.abort();
};
// eslint-disable-next-line
}, [props.Record.reportId]); }, [props.Record.reportId]);
// below useEffect call when isNextRecord state is true and fetch next record const getReportData = async (id) => {
useEffect(() => {
if (isNextRecord) {
getReportData(props.Record.reportId, List.length, 200);
}
// eslint-disable-next-line
}, [isNextRecord]);
const getReportData = async (id, skipUserRecord = 0, limit = 200) => {
setIsLoader(true); setIsLoader(true);
const json = reportJson(id); const json = reportJson(id);
if (json) { if (json) {
setActions(json.actions); setActions(json.actions);
setReportName(json.reportName); setReportName(json.reportName);
setHeading(json.heading); const { className, params, keys, orderBy } = json;
Parse.serverURL = localStorage.getItem("BaseUrl12"); Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12")); Parse.initialize(localStorage.getItem("AppID12"));
const currentUser = Parse.User.current().id; const serverURL =
localStorage.getItem("BaseUrl12") + "classes/" + className;
const strParams = JSON.stringify(params);
const strKeys = keys.join();
const headers = { const headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"), "X-Parse-Application-Id": localStorage.getItem("AppID12"),
sessiontoken: localStorage.getItem("accesstoken") "X-Parse-Session-Token": localStorage.getItem("accesstoken")
}; };
try { try {
const params = { reportId: id, skip: skipUserRecord, limit: limit }; const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`; const res = await axios.get(url, { headers: headers });
const res = await axios.post(url, params, { // console.log("res ", res.data?.results);
headers: headers,
signal: abortController.signal // is used to cancel fetch query
});
if (id === "5Go51Q7T8r") { if (id === "5Go51Q7T8r") {
const listData = res.data?.result.filter((x) => x.Signers.length > 0); const currentUser = Parse.User.current().id;
const listData = res.data?.results.filter(
(x) => x.Signers.length > 0
);
let arr = []; let arr = [];
for (const obj of listData) { for (const obj of listData) {
const isSigner = obj.Signers.some( const isSigner = obj.Signers.some(
@@ -84,34 +63,14 @@ function DashboardReport(props) {
} }
} }
} }
if (arr.length === docPerPage) { setList(arr);
setIsMoreDocs(true);
} else {
setIsMoreDocs(false);
}
setList((prevRecord) =>
prevRecord.length > 0 ? [...prevRecord, ...arr] : arr
);
} else { } else {
if (res.data.result.length === docPerPage) { setList(res.data?.results);
setIsMoreDocs(true);
} else {
setIsMoreDocs(false);
}
setIsNextRecord(false);
setList((prevRecord) =>
prevRecord.length > 0
? [...prevRecord, ...res.data.result]
: res.data.result
);
} }
setIsLoader(false); setIsLoader(false);
} catch (err) { } catch (err) {
const isCancel = axios.isCancel(err); console.log("err ", err);
if (!isCancel) { setIsLoader(false);
console.log("err ", err);
setIsLoader(false);
}
} }
} else { } else {
setIsLoader(false); setIsLoader(false);
@@ -142,12 +101,8 @@ function DashboardReport(props) {
<ReportTable <ReportTable
ReportName={reportName} ReportName={reportName}
List={List} List={List}
setList={setList} act={"Sign"}
actions={actions} actions={actions}
heading={heading}
setIsNextRecord={setIsNextRecord}
isMoreDocs={isMoreDocs}
docPerPage={docPerPage}
/> />
) : ( ) : (
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded"> <div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
@@ -1,4 +1,5 @@
import React, { Suspense, lazy } from "react"; import React, { useState, Suspense, lazy } from "react";
import moment from "moment";
import ErrorBoundary from "../ErrorBoundary"; import ErrorBoundary from "../ErrorBoundary";
const DashboardCard = lazy(() => import("./DashboardCard")); const DashboardCard = lazy(() => import("./DashboardCard"));
@@ -6,6 +7,258 @@ const DashboardCard = lazy(() => import("./DashboardCard"));
const DashboardReport = lazy(() => import("./DashboardReport")); const DashboardReport = lazy(() => import("./DashboardReport"));
const GetDashboard = (props) => { const GetDashboard = (props) => {
const [filter, setfilter] = useState("");
const [option, setoption] = useState("");
const onSearchFilter = (e) => {
let _search = e.target.value;
localStorage.setItem("DashboardDefaultFilter", _search);
switch (_search) {
case "Today": {
let d = new Date();
let formDate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
).toISOString();
let Todate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
).toISOString();
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
setfilter(Query);
setoption(_search);
break;
}
case "Yesterday": {
let d1 = new Date();
d1.setDate(d1.getDate() - 1);
let yesFrDate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
).toISOString();
let YesTodate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
).toISOString();
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
setfilter(Query1);
setoption(_search);
break;
}
case "This week": {
let oneDay = 24 * 60 * 60 * 1000;
let curr = new Date(); // get current date
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
let firstday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
0,
0,
0
)
).setDate(first)
).toISOString();
let diffDays = Math.round(
Math.abs(
(new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
) -
new Date(firstday)) /
oneDay
)
); //Days since last week
let last = first + diffDays;
let lastday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
).setDate(last)
).toISOString();
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
setfilter(Query2);
setoption(_search);
break;
}
case "Last 7 days": {
let d7 = new Date();
let d7l = new Date();
d7.setDate(d7.getDate() - 7);
let l7t = new Date(
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
).toISOString();
let date7 = new Date(
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
).toISOString();
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
setfilter(Query7);
setoption(_search);
break;
}
case "Last 14 days": {
let d14 = new Date();
let d14l = new Date();
let l14t = new Date(
Date.UTC(
d14l.getFullYear(),
d14l.getMonth(),
d14l.getDate(),
23,
59,
59
)
).toISOString();
d14.setDate(d14.getDate() - 14);
let date14 = new Date(
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
).toISOString();
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
setfilter(Query14);
setoption(_search);
break;
}
case "Last 30 days": {
let d30 = new Date();
let d30l = new Date();
let l30t = new Date(
Date.UTC(
d30l.getFullYear(),
d30l.getMonth(),
d30l.getDate(),
23,
59,
59
)
).toISOString();
d30.setDate(d30.getDate() - 30);
let date30 = new Date(
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
).toISOString();
let Query30 = `'$gte':'${date30}','$lte':'${l30t}'`;
setfilter(Query30);
setoption(_search);
break;
}
case "Last week": {
const from_date = moment().startOf("week").subtract(7, "days");
const to_date = moment().endOf("week").subtract(7, "days");
let Queryl = `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
setfilter(Queryl);
setoption(_search);
break;
}
case "This month": {
const tdate = new Date();
let tfirstDay = new Date(
tdate.getFullYear(),
tdate.getMonth(),
1
).toISOString();
let tlastDay = new Date(
tdate.getFullYear(),
tdate.getMonth() + 1,
0
).toISOString();
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
setfilter(Querylt);
setoption(_search);
break;
}
case "Last month": {
const ldate = new Date();
var lfirstDay = new Date(
ldate.getFullYear(),
ldate.getMonth() - 1,
2
).toISOString();
var llastDay = new Date(
ldate.getFullYear(),
ldate.getMonth(),
1
).toISOString();
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
setfilter(Queryltl);
setoption(_search);
break;
}
case "All": {
let fall = new Date(
new Date().getFullYear() - 100,
0,
1,
0,
0,
0
).toISOString();
let fall_year = `'$gte':'${fall}'`;
setfilter(fall_year);
setoption(_search);
break;
}
case "This year": {
let fcy = new Date(
new Date().getFullYear(),
0,
1,
0,
0,
0
).toISOString();
let lcy = new Date(
new Date().getFullYear(),
11,
31,
23,
59,
59
).toISOString();
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
setfilter(cur_year);
setoption(_search);
break;
}
case "Last year": {
let fly = new Date(
new Date().getFullYear() - 1,
0,
1,
0,
0,
0
).toISOString();
let lly = new Date(
new Date().getFullYear() - 1,
11,
31,
23,
59,
59
).toISOString();
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
setfilter(last_year);
setoption(_search);
break;
}
default: {
setoption(_search);
break;
}
}
};
const renderSwitchWithTour = (col) => { const renderSwitchWithTour = (col) => {
switch (col.widget.type) { switch (col.widget.type) {
case "Card": case "Card":
@@ -19,6 +272,7 @@ const GetDashboard = (props) => {
<DashboardCard <DashboardCard
Icon={col.widget.icon} Icon={col.widget.icon}
Label={col.widget.label} Label={col.widget.label}
Filter={filter}
Format={col.widget.format && col.widget.format} Format={col.widget.format && col.widget.format}
Data={col.widget.data} Data={col.widget.data}
FilterData={col.widget.filter} FilterData={col.widget.filter}
@@ -27,12 +281,50 @@ const GetDashboard = (props) => {
</Suspense> </Suspense>
</div> </div>
); );
case "customeHtml":
return (
<div data-tut={col.widget.data.tourSection}>
<select
id="searchFiltr"
className="form-control"
value={
option ||
localStorage.getItem("DashboardDefaultFilter") ||
col.widget.data[0].default
}
onChange={onSearchFilter}
>
{col.widget.data[0].options.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
<br />
</div>
);
case "customeTag":
return (
<h3
data-tut={col.widget.data.tourSection}
style={{
marginBottom: "4px",
color: "currentColor",
marginLeft: "4px"
}}
>
{col.widget.label}
</h3>
);
case "report": { case "report": {
let _filter = `${col.widget.filterKey}:${filter}`;
return ( return (
<div data-tut={col.widget.data.tourSection}> <div data-tut={col.widget.data.tourSection}>
<Suspense fallback={<div>please wait</div>}> <Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0"> <div className="mb-4 md:mb-0">
<DashboardReport Record={col.widget} /> <DashboardReport Filter={_filter} Record={col.widget} />
</div> </div>
</Suspense> </Suspense>
</div> </div>
@@ -54,6 +346,7 @@ const GetDashboard = (props) => {
<DashboardCard <DashboardCard
Icon={col.widget.icon} Icon={col.widget.icon}
Label={col.widget.label} Label={col.widget.label}
Filter={filter}
Format={col.widget.format && col.widget.format} Format={col.widget.format && col.widget.format}
Data={col.widget.data} Data={col.widget.data}
FilterData={col.widget.filter} FilterData={col.widget.filter}
@@ -62,11 +355,48 @@ const GetDashboard = (props) => {
</Suspense> </Suspense>
</div> </div>
); );
case "customeHtml":
return (
<div>
<select
id="searchFiltr"
className="form-control"
value={
option ||
localStorage.getItem("DashboardDefaultFilter") ||
col.widget.data[0].default
}
onChange={onSearchFilter}
>
{col.widget.data[0].options.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
<br />
</div>
);
case "customeTag":
return (
<h3
style={{
marginBottom: "4px",
color: "currentColor",
marginLeft: "4px"
}}
>
{col.widget.label}
</h3>
);
case "report": { case "report": {
let _filter = `${col.widget.filterKey}:${filter}`;
return ( return (
<Suspense fallback={<div>please wait</div>}> <Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0"> <div className="mb-4 md:mb-0">
<DashboardReport Record={col.widget} /> <DashboardReport Filter={_filter} Record={col.widget} />
</div> </div>
</Suspense> </Suspense>
); );
@@ -1,59 +0,0 @@
import React, { useCallback, useMemo } from "react";
import { useDropScript } from "../../hook/useScript";
const DROPBOX_APP_KEY = process.env.REACT_APP_DROPBOX_API_KEY; // App key
const DROPBOX_SDK_URL = "https://www.dropbox.com/static/api/2/dropins.js";
const DROPBOX_SCRIPT_ID = "dropboxjs";
export default function DropboxChooser({ children, onSuccess, onCancel }) {
useDropScript(DROPBOX_SDK_URL, {
attrs: {
id: DROPBOX_SCRIPT_ID,
"data-app-key": DROPBOX_APP_KEY
}
});
const options = useMemo(
() => ({
// Required. Called when a user selects an item in the Chooser.
success: (files) => {
// console.log("success", files);
onSuccess && onSuccess(files);
},
// Optional. Called when the user closes the dialog without selecting a file
// and does not include any parameters.
cancel: () => {
console.log("cancel");
onCancel && onCancel();
},
// Optional. "preview" (default) is a preview link to the document for sharing,
// "direct" is an expiring link to download the contents of the file. For more
linkType: "direct", // or "preview"
multiselect: false, // 是否支持多选
extensions: [".pdf"],
// Optional. A value of false (default) limits selection to files,
// while true allows the user to select both folders and files.
// You cannot specify `linkType: "direct"` when using `folderselect: true`.
folderselect: false // or true
}),
[onSuccess, onCancel]
);
const handleChoose = useCallback(() => {
if (window.Dropbox) {
window.Dropbox.choose(options);
}
}, [options]);
return (
<div onClick={handleChoose}>
{children || (
<button className="px-2 py-[2px] text-2xl rounded border-[1px] text-blue-400 border-gray-300 w-full">
<i className="fa-brands fa-dropbox"></i>
</button>
)}
</div>
);
}
@@ -2,12 +2,14 @@ import React, { useState, useEffect } from "react";
import { SaveFileSize } from "../../constant/saveFileSize"; import { SaveFileSize } from "../../constant/saveFileSize";
import Parse from "parse"; import Parse from "parse";
import sanitizeFileName from "../../primitives/sanitizeFileName"; import sanitizeFileName from "../../primitives/sanitizeFileName";
import DropboxChooser from "./DropboxChoose";
const FileUpload = (props) => { const FileUpload = (props) => {
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId")); const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [_fileupload, setFileUpload] = useState(""); const [_fileupload, setFileUpload] = useState("");
const [fileload, setfileload] = useState(false); const [fileload, setfileload] = useState(false);
const [localValue, setLocalValue] = useState("");
const [Message] = useState(false); const [Message] = useState(false);
const [percentage, setpercentage] = useState(0); const [percentage, setpercentage] = useState(0);
@@ -23,6 +25,7 @@ const FileUpload = (props) => {
const onChange = (e) => { const onChange = (e) => {
try { try {
let files = e.target.files; let files = e.target.files;
setLocalValue(e.target.files);
if (typeof files[0] !== "undefined") { if (typeof files[0] !== "undefined") {
if (props.schema.filetypes && props.schema.filetypes.length > 0) { if (props.schema.filetypes && props.schema.filetypes.length > 0) {
var fileName = files[0].name; var fileName = files[0].name;
@@ -103,56 +106,6 @@ const FileUpload = (props) => {
console.error("Error uploading file:", error); console.error("Error uploading file:", error);
} }
}; };
const dropboxSuccess = async (files) => {
// console.log("file ", files);
setfileload(true);
const file = files[0];
const url = file.link;
const size = file.bytes;
const mb = Math.round(file.bytes / Math.pow(1024, 2));
if (mb > 10) {
setTimeout(() => {
alert(
`The selected file size is too large. Please select a file less than 10 MB`
);
}, 500);
return;
} else {
const name = sanitizeFileName(file.name);
const parseFile = new Parse.File(name, { uri: url });
try {
const response = await parseFile.save({
progress: (progressValue, loaded, total, { type }) => {
if (type === "upload" && progressValue !== null) {
const percentCompleted = Math.round((loaded * 100) / total);
// console.log("percentCompleted ", percentCompleted);
setpercentage(percentCompleted);
}
}
});
// console.log("response.url() ", response.url());
setFileUpload(response.url());
props.onChange(response.url());
setfileload(false);
if (response.url()) {
SaveFileSize(size, response.url());
return response.url();
}
} catch (error) {
setfileload(false);
setpercentage(0);
console.error("Error uploading file:", error);
}
}
};
const dropboxCancel = async () => {
console.log("cancel clicked ");
};
let fileView = let fileView =
props.formData && props.formData &&
props.schema.uploadtype === "s3viajw" ? null : props.formData && props.schema.uploadtype === "s3viajw" ? null : props.formData &&
@@ -254,51 +207,55 @@ const FileUpload = (props) => {
</div> </div>
<> <>
{props.formData ? ( {localValue ? (
<div className="flex gap-2 justify-center items-center"> <input
<div className="flex justify-between items-center px-2 py-[3px] w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]"> type="file"
<div className="break-all"> id="hashfile"
file selected : {props.formData.split("/")[3]} style={{
</div> border: "1px solid #ccc",
<div color: "gray",
onClick={() => { backgroundColor: "white",
console.log("clicked"); padding: "5px 10px",
setFileUpload([]); borderRadius: "4px",
props.onChange(undefined); fontSize: "13px",
}} width: "100%",
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" fontWeight: "bold"
> }}
<i className="fa-solid fa-xmark"></i> accept="application/pdf,application/vnd.ms-excel"
</div> onChange={onChange}
</div> />
<DropboxChooser ) : props.formData ? (
onSuccess={dropboxSuccess} <div
onCancel={dropboxCancel} style={{
/> border: "1px solid #ccc",
color: "gray",
backgroundColor: "white",
padding: "5px 10px",
borderRadius: "4px",
fontSize: "13px",
width: "100%",
fontWeight: "bold"
}}
>
file selected : {props.formData.split("/")[3]}
</div> </div>
) : ( ) : (
<div className="flex gap-2 justify-center items-center"> <input
<input type="file"
type="file" id="hashfile"
id="hashfile" style={{
style={{ border: "1px solid #ccc",
border: "1px solid #ccc", color: "gray",
color: "gray", backgroundColor: "white",
backgroundColor: "white", padding: "5px 10px",
padding: "5px 10px", borderRadius: "4px",
borderRadius: "4px", fontSize: "13px",
fontSize: "13px", width: "100%",
width: "100%", fontWeight: "bold"
fontWeight: "bold" }}
}} accept="application/pdf,application/vnd.ms-excel"
accept="application/pdf,application/vnd.ms-excel" onChange={onChange}
onChange={onChange} />
/>
<DropboxChooser
onSuccess={dropboxSuccess}
onCancel={dropboxCancel}
/>
</div>
)} )}
</> </>
</React.Fragment> </React.Fragment>
@@ -1,6 +1,6 @@
import React, { Component } from "react"; import React, { Component } from "react";
import Parse from "parse"; import Parse from "parse";
// import axios from "axios"; import axios from "axios";
export class HiddenField extends Component { export class HiddenField extends Component {
state = { state = {
@@ -37,46 +37,31 @@ export class HiddenField extends Component {
this.setState({ _fields: custome_Filed }); this.setState({ _fields: custome_Filed });
} else { } else {
if (currentUser) { if (currentUser) {
// let url = `${this.state.baseUrl}classes/${localStorage.getItem( let url = `${this.state.baseUrl}classes/${localStorage.getItem(
// "extended_class" "extended_class"
// )}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${ )}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${
// currentUser.id currentUser.id
// }"}}&keys=${this.props.schema.data.valueKey}`; }"}}&keys=${this.props.schema.data.valueKey}`;
// const headers = { const headers = {
// "Content-Type": "application/json", "Content-Type": "application/json",
// "X-Parse-Application-Id": this.state.parseAppId "X-Parse-Application-Id": this.state.parseAppId
// }; };
// await axios.get(url, { headers: headers }).then((res) => { await axios.get(url, { headers: headers }).then((res) => {
// let custome_Filed = ""; let custome_Filed = "";
// let _rdata = res.data.results; let _rdata = res.data.results;
// let splitArray = this.props.schema.data.valueKey.split("."); let splitArray = this.props.schema.data.valueKey.split(".");
// if (splitArray.length > 1) { if (splitArray.length > 1) {
// custome_Filed = _rdata[0][splitArray[0]][splitArray[1]]; custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
// } else { } else {
// console.log(_rdata[0][splitArray[0]]); console.log(_rdata[0][splitArray[0]]);
// custome_Filed = _rdata[0][splitArray[0]]; custome_Filed = _rdata[0][splitArray[0]];
// } }
// this.setState({ _fields: custome_Filed }); this.setState({ _fields: custome_Filed });
// });
const res = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
}); });
let custome_Filed = "";
const result = res.toJSON();
let _rdata = [result];
let splitArray = this.props.schema.data.valueKey.split(".");
if (splitArray.length > 1) {
custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
} else {
console.log(_rdata[0][splitArray[0]]);
custome_Filed = _rdata[0][splitArray[0]];
}
this.setState({ _fields: custome_Filed });
} }
} }
} catch (error) { } catch (error) {
console.log("err", error); console.log('err', error)
} }
} }
}; };
@@ -120,10 +120,12 @@ const Level1Dropdown = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class")); let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0]; res = data[0];
} else { } else {
const currentUser = Parse.User.current(); var emp = Parse.Object.extend(
res = await Parse.Cloud.run("getUserDetails", { localStorage.getItem("extended_class")
email: currentUser.get("email") );
}); var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
res = await q.first();
if (res) res = res.toJSON(); if (res) res = res.toJSON();
} }
@@ -337,7 +339,7 @@ const Level1Dropdown = (props) => {
x.className = x.className.replace("show", ""); x.className = x.className.replace("show", "");
}, 5000); }, 5000);
} catch (error) { } catch (error) {
console.log("Err", error); console.log("Err", error)
} }
} }
}; };
@@ -42,8 +42,9 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
return ( return (
<aside <aside
className={`bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 md:translate-x-0 className={`${isOpen ? "block" : "hidden"
${isOpen ? "translate-x-0 block" : "-translate-x-full hidden"}`} } bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 ${isOpen ? "translate-x-0" : "-translate-x-full"
}`}
> >
<div className="flex px-2 py-3 gap-2 items-center shadow-md"> <div className="flex px-2 py-3 gap-2 items-center shadow-md">
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden"> <div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
+210
View File
@@ -0,0 +1,210 @@
import moment from "moment";
export default function onSearchFilter(_search) {
switch (_search) {
case "Today": {
let d = new Date();
let formDate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
).toISOString();
let Todate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
).toISOString();
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
return Query;
}
case "Yesterday": {
let d1 = new Date();
d1.setDate(d1.getDate() - 1);
let yesFrDate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
).toISOString();
let YesTodate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
).toISOString();
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
return Query1;
}
case "This week": {
let oneDay = 24 * 60 * 60 * 1000;
let curr = new Date(); // get current date
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
let firstday = new Date(
new Date(
Date.UTC(curr.getFullYear(), curr.getMonth(), curr.getDate(), 0, 0, 0)
).setDate(first)
).toISOString();
let diffDays = Math.round(
Math.abs(
(new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
) -
new Date(firstday)) /
oneDay
)
); //Days since last week
let last = first + diffDays;
let lastday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
).setDate(last)
).toISOString();
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
return Query2;
}
case "Last 7 days": {
let d7 = new Date();
let d7l = new Date();
d7.setDate(d7.getDate() - 7);
let l7t = new Date(
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
).toISOString();
let date7 = new Date(
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
).toISOString();
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
return Query7;
}
case "Last 14 days": {
let d14 = new Date();
let d14l = new Date();
let l14t = new Date(
Date.UTC(
d14l.getFullYear(),
d14l.getMonth(),
d14l.getDate(),
23,
59,
59
)
).toISOString();
d14.setDate(d14.getDate() - 14);
let date14 = new Date(
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
).toISOString();
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
return Query14;
}
case "Last 30 days": {
let d30 = new Date();
let d30l = new Date();
let l30t = new Date(
Date.UTC(
d30l.getFullYear(),
d30l.getMonth(),
d30l.getDate(),
23,
59,
59
)
).toISOString();
d30.setDate(d30.getDate() - 30);
let date30 = new Date(
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
).toISOString();
return `'$gte':'${date30}','$lte':'${l30t}'`;
}
case "Last week": {
const from_date = moment().startOf("week").subtract(7, "days");
const to_date = moment().endOf("week").subtract(7, "days");
return `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
}
case "This month": {
var tdate = new Date();
var tfirstDay = new Date(
tdate.getFullYear(),
tdate.getMonth(),
1
).toISOString();
var tlastDay = new Date(
tdate.getFullYear(),
tdate.getMonth() + 1,
0
).toISOString();
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
return Querylt;
}
case "Last month": {
var ldate = new Date();
var lfirstDay = new Date(
ldate.getFullYear(),
ldate.getMonth() - 1,
2
).toISOString();
var llastDay = new Date(
ldate.getFullYear(),
ldate.getMonth(),
1
).toISOString();
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
return Queryltl;
}
case "All": {
let fall = new Date(
new Date().getFullYear() - 100,
0,
1,
0,
0,
0
).toISOString();
let fall_year = `'$gte':'${fall}'`;
return fall_year;
}
case "This year": {
let fcy = new Date(new Date().getFullYear(), 0, 1, 0, 0, 0).toISOString();
let lcy = new Date(
new Date().getFullYear(),
11,
31,
23,
59,
59
).toISOString();
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
return cur_year;
}
case "Last year": {
let fly = new Date(
new Date().getFullYear() - 1,
0,
1,
0,
0,
0
).toISOString();
let lly = new Date(
new Date().getFullYear() - 1,
11,
31,
23,
59,
59
).toISOString();
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
return last_year;
}
default:
return "";
}
}
-17
View File
@@ -15,20 +15,3 @@ export const useScript = (url, onload) => {
}; };
}, [url, onload]); }, [url, onload]);
}; };
/**`useScript` hook is generated scripte for google sign in button */
export const useDropScript = (url, onload) => {
useEffect(() => {
const script = document.createElement("script");
//add url parameter to the script src, for load and it will remove after load in return
script.src = url;
script.async = true;
script.defer = true;
script.id = "dropboxjs";
script.setAttribute("data-app-key", "8k0thg9r1t7asqg");
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, [url, onload]);
};
+3 -2
View File
@@ -14,7 +14,7 @@ export const formJson = (id) => {
type: "string", type: "string",
title: "Select Document", title: "Select Document",
filetypes: [], filetypes: [],
maxfilesizeKB: "10000", maxfilesizeKB: "5000",
uploadtype: "regular", uploadtype: "regular",
helpbody: "", helpbody: "",
helplink: "" helplink: ""
@@ -147,7 +147,7 @@ export const formJson = (id) => {
class: "contracts_Contactbook", class: "contracts_Contactbook",
displayKey: "Name", displayKey: "Name",
valueKey: "objectId", valueKey: "objectId",
query: `where={"CreatedBy":${userPtr},"IsDeleted":{"$ne":true}}&keys=Name`, query: `where={"CreatedBy":${userPtr}}&keys=Name`,
isPointer: true, isPointer: true,
helpbody: "", helpbody: "",
helplink: "", helplink: "",
@@ -582,3 +582,4 @@ export const formJson = (id) => {
return formData; return formData;
} }
}; };
+246 -25
View File
@@ -1,13 +1,35 @@
import Parse from "parse";
export default function reportJson(id) { export default function reportJson(id) {
const currentUserId = Parse.User.current().id;
// console.log("json ", json); // console.log("json ", json);
const head = ["Sr.No", "Name", "Note", "Folder", "File", "Owner", "Signers"];
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
switch (id) { switch (id) {
// draft documents report // draft documents report
case "ByHuevtCFY": case "ByHuevtCFY":
return { return {
reportName: "Draft Documents", reportName: "Draft Documents",
heading: head, className: "contracts_Document",
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "sign", btnLabel: "sign",
@@ -23,7 +45,27 @@ export default function reportJson(id) {
case "4Hhwbp482K": case "4Hhwbp482K":
return { return {
reportName: "Need your sign", reportName: "Need your sign",
heading: head, className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
},
Placeholders: { $ne: null }
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name",
"Signers.UserId",
"AuditTrail"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "sign", btnLabel: "sign",
@@ -39,7 +81,31 @@ export default function reportJson(id) {
case "1MwEuxLEkF": case "1MwEuxLEkF":
return { return {
reportName: "In-progress documents", reportName: "In-progress documents",
heading: head, className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "View", btnLabel: "View",
@@ -55,7 +121,27 @@ export default function reportJson(id) {
case "kQUoW4hUXz": case "kQUoW4hUXz":
return { return {
reportName: "Completed Documents", reportName: "Completed Documents",
heading: head, className: "contracts_Document",
params: {
Type: null,
IsCompleted: true,
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
IsDeclined: { $ne: true }
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name",
"TimeToCompleteDays"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "View", btnLabel: "View",
@@ -67,11 +153,63 @@ export default function reportJson(id) {
} }
] ]
}; };
// OpenSignDrive™ documents Drafts
case "VRFDmUmw5B":
return {
reportName: "OpenSignDrive™ Drafts",
className: "contracts_Document",
params: {
Type: "AIDoc",
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "edit",
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie"
}
]
};
// declined documents report // declined documents report
case "UPr2Fm5WY3": case "UPr2Fm5WY3":
return { return {
reportName: "Declined Documents", reportName: "Declined Documents",
heading: head, className: "contracts_Document",
params: { Type: null, IsDeclined: true },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "View", btnLabel: "View",
@@ -87,7 +225,39 @@ export default function reportJson(id) {
case "zNqBHXHsYH": case "zNqBHXHsYH":
return { return {
reportName: "Expired Documents", reportName: "Expired Documents",
heading: head, className: "contracts_Document",
params: {
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
Type: { $ne: "Folder" },
$and: [
{
$or: [
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
{ Placeholders: { $ne: null } }
]
},
{
ExpiryDate: {
$lt: { __type: "Date", iso: new Date().toISOString() }
}
}
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "View", btnLabel: "View",
@@ -103,7 +273,31 @@ export default function reportJson(id) {
case "d9k3UfYHBc": case "d9k3UfYHBc":
return { return {
reportName: "Recently sent for signatures", reportName: "Recently sent for signatures",
heading: head, className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "View", btnLabel: "View",
@@ -119,7 +313,27 @@ export default function reportJson(id) {
case "5Go51Q7T8r": case "5Go51Q7T8r":
return { return {
reportName: "Recent signature requests", reportName: "Recent signature requests",
heading: head, className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
},
Placeholders: { $ne: null }
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name",
"Signers.UserId",
"AuditTrail"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "Sign", btnLabel: "Sign",
@@ -135,7 +349,28 @@ export default function reportJson(id) {
case "kC5mfynCi4": case "kC5mfynCi4":
return { return {
reportName: "Drafts", reportName: "Drafts",
heading: head, className: "contracts_Document",
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [ actions: [
{ {
btnLabel: "sign", btnLabel: "sign",
@@ -147,20 +382,6 @@ export default function reportJson(id) {
} }
] ]
}; };
// contactbook report
case "5KhaPr482K":
return {
reportName: "Contactbook",
heading: contactbook,
actions: [
{
btnLabel: "",
btnColor: "#f55a42",
textColor: "white",
btnIcon: "fa-solid fa-trash"
}
]
};
default: default:
return null; return null;
} }
+1 -4
View File
@@ -6,7 +6,6 @@
"subtitle": "Free for life One click install.", "subtitle": "Free for life One click install.",
"btnText": "Visit github", "btnText": "Visit github",
"url": "https://github.com/opensignlabs/opensign", "url": "https://github.com/opensignlabs/opensign",
"target": "_blank",
"benefits": [ "benefits": [
"Sign Unlimited Documents", "Sign Unlimited Documents",
"S3 Doc Storage", "S3 Doc Storage",
@@ -27,10 +26,9 @@
"planName": "THANKS PLAN", "planName": "THANKS PLAN",
"currency": "$", "currency": "$",
"price": "29.99", "price": "29.99",
"subtitle": "Use code 'FREEBETA' to get this for free(First 1000 users)", "subtitle": "Use code 'FREEBETA' to get this for free(First 100 users)",
"btnText": "Subscribe", "btnText": "Subscribe",
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks", "url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
"target": "_self",
"benefits": [ "benefits": [
"Sign Unlimited Documents", "Sign Unlimited Documents",
"Unlimited Secure Doc Storage with OpenSignDrive", "Unlimited Secure Doc Storage with OpenSignDrive",
@@ -52,7 +50,6 @@
"subtitle": "Customization available Priority support.", "subtitle": "Customization available Priority support.",
"btnText": "Contact us", "btnText": "Contact us",
"url": "https://www.opensignlabs.com/contact-us", "url": "https://www.opensignlabs.com/contact-us",
"target": "_blank",
"benefits": [ "benefits": [
"All features", "All features",
"Custom domain", "Custom domain",
+19 -8
View File
@@ -6,10 +6,10 @@ import { useWindowSize } from "../hook/useWindowSize";
import Tour from "reactour"; import Tour from "reactour";
import axios from "axios"; import axios from "axios";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Parse from "parse";
const HomeLayout = ({ children }) => { const HomeLayout = ({ children }) => {
const { width } = useWindowSize(); const { width } = useWindowSize();
const [isOpen, setIsOpen] = useState(true); const [isOpen, setIsOpen] = useState(false);
const arr = useSelector((state) => state.TourSteps); const arr = useSelector((state) => state.TourSteps);
// reactour state // reactour state
@@ -19,11 +19,13 @@ const HomeLayout = ({ children }) => {
const [tourConfigs, setTourConfigs] = useState([]); const [tourConfigs, setTourConfigs] = useState([]);
const showSidebar = () => { const showSidebar = () => {
setIsOpen(value => !value); setIsOpen(!isOpen);
}; };
useEffect(() => { useEffect(() => {
if (width && width <= 768) { if (width && width <= 768) {
setIsOpen(false); setIsOpen(false);
} else {
setIsOpen(true);
} }
}, [width]); }, [width]);
@@ -122,11 +124,20 @@ const HomeLayout = ({ children }) => {
}; };
async function checkTourStatus() { async function checkTourStatus() {
const currentUser = Parse.User.current(); const serverUrl = localStorage.getItem("baseUrl");
const cloudRes = await Parse.Cloud.run("getUserDetails", { const appId = localStorage.getItem("AppID12");
email: currentUser.get("email") const extUserClass = localStorage.getItem("extended_class");
}); const json = JSON.parse(localStorage.getItem("Extand_Class"));
const res = { data: cloudRes.toJSON() }; const extUserId = json && json.length > 0 && json[0].objectId;
// console.log("extUserId ", extUserId);
const res = await axios.get(
serverUrl + "classes/" + extUserClass + "/" + extUserId,
{
headers: {
"X-Parse-Application-Id": appId
}
}
);
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) { if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus; const tourStatus = res.data.TourStatus;
// console.log("res ", res.data.TourStatus); // console.log("res ", res.data.TourStatus);
+71 -165
View File
@@ -1,23 +1,19 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo } from "react";
import pad from "../assets/images/pad.svg"; import pad from "../assets/images/pad.svg";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import axios from "axios";
import "../styles/report.css";
const ReportTable = ({ const ReportTable = ({
ReportName, ReportName,
List, List,
setList,
actions, actions,
heading,
setIsNextRecord, setIsNextRecord,
isMoreDocs, isMoreDocs
docPerPage
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [actLoader, setActLoader] = useState({}); const docPerPage = 10;
const [isAlert, setIsAlert] = useState(false); // const pageNumbers = [];
const [isErr, setIsErr] = useState(false);
// For loop is used to calculate page numbers visible below table // For loop is used to calculate page numbers visible below table
// Initialize pageNumbers using useMemo to avoid unnecessary re-creation // Initialize pageNumbers using useMemo to avoid unnecessary re-creation
const pageNumbers = useMemo(() => { const pageNumbers = useMemo(() => {
@@ -26,7 +22,7 @@ const ReportTable = ({
calculatedPageNumbers.push(i); calculatedPageNumbers.push(i);
} }
return calculatedPageNumbers; return calculatedPageNumbers;
}, [List, docPerPage]); }, [List]);
// below useEffect reset currenpage to 1 if user change route // below useEffect reset currenpage to 1 if user change route
useEffect(() => { useEffect(() => {
return () => setCurrentPage(1); return () => setCurrentPage(1);
@@ -61,34 +57,8 @@ const ReportTable = ({
localStorage.setItem("rowlevel", JSON.stringify(item)); localStorage.setItem("rowlevel", JSON.stringify(item));
// localStorage.setItem("rowlevelMicro"); // localStorage.setItem("rowlevelMicro");
}; };
const handlebtn = async (item) => { const handlebtn = () => {
if (ReportName === "Contactbook") { console.log("clicked");
setActLoader({ [item.objectId]: true });
try {
const url =
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
const body = { IsDeleted: true };
const res = await axios.put(url + item.objectId, body, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
});
// console.log("Res ", res.data);
if (res.data && res.data.updatedAt) {
setActLoader({});
setIsAlert(true);
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
setList(upldatedList);
}
} catch (err) {
console.log("err", err);
setIsAlert(true);
setIsErr(true);
setActLoader({});
}
}
}; };
// Get current list // Get current list
@@ -103,27 +73,17 @@ const ReportTable = ({
return ( return (
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md"> <div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
{isAlert && (
<div
className={`alert alert-${isErr ? "danger" : "success"} alertBox`}
role="alert"
onAnimationEnd={() => setIsAlert(false)}
>
{isErr
? "Something went wrong, Please try again later!"
: "Record deleted successfully!"}
</div>
)}
<h2 className="text-[23px] font-light my-2">{ReportName}</h2> <h2 className="text-[23px] font-light my-2">{ReportName}</h2>
<table className="table-auto w-full border-collapse"> <table className="table-auto w-full border-collapse">
<thead className="text-[14px]"> <thead className="text-[14px]">
<tr className="border-y-[1px]"> <tr className="border-y-[1px]">
{heading?.map((item, index) => ( <th className="px-4 py-2 font-thin">Sr.No</th>
<React.Fragment key={index}> <th className="px-4 py-2 font-thin">Name</th>
<th className="px-4 py-2 font-thin">{item}</th> <th className="px-4 py-2 font-thin">Note</th>
</React.Fragment> <th className="px-4 py-2 font-thin">Folder</th>
))} <th className="px-4 py-2 font-thin">File</th>
<th className="px-4 py-2 font-thin">Owner</th>
<th className="px-4 py-2 font-thin">Signers</th>
{actions?.length > 0 && ( {actions?.length > 0 && (
<th className="px-4 py-2 font-thin">Action</th> <th className="px-4 py-2 font-thin">Action</th>
)} )}
@@ -132,115 +92,61 @@ const ReportTable = ({
<tbody className="text-[12px]"> <tbody className="text-[12px]">
{List?.length > 0 ? ( {List?.length > 0 ? (
<> <>
{currentLists.map((item, index) => {currentLists.map((item, index) => (
ReportName === "Contactbook" ? ( <tr className="border-y-[1px]" key={index}>
<tr className="border-y-[1px]" key={index}> <td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2">{index + 1}</td> <td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2 font-semibold">{item?.Name} </td> <td className="px-4 py-2">{item?.Note || "-"}</td>
<td className="px-4 py-2">{item?.Email || "-"}</td> <td className="px-4 py-2">
<td className="px-4 py-2">{item?.Phone || "-"}</td> {item?.Folder?.Name || "OpenSignDrive"}
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white"> </td>
{actions?.length > 0 && <td className="px-4 py-2">
actions.map((act, index) => ( <a
<button target="_blank"
key={index} rel="noopener noreferrer"
onClick={() => title={item?.URL}
act?.redirectUrl href={item?.URL}
? handlemicroapp(item, act.redirectUrl) download={item?.URL}
: handlebtn(item) className="text-[blue] hover:text-[blue] hover:underline"
} >
className={`flex justify-center items-center gap-1 px-2 py-1 rounded shadow`} {item?.URL ? "Download" : "-"}
style={{ </a>
backgroundColor: act.btnColor </td>
? act.btnColor
: "#3ac9d6",
color: act?.textColor ? act?.textColor : "white"
}}
>
<span>
{act?.btnIcon && (
<i
className={
actLoader[item.objectId]
? "fa-solid fa-spinner fa-spin-pulse"
: act.btnIcon
}
></i>
)}
</span>
{act?.btnLabel && (
<span className="uppercase">
{act?.btnLabel ? act.btnLabel : "View"}
</span>
)}
</button>
))}
</td>
</tr>
) : (
<tr className="border-y-[1px]" key={index}>
<td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2">{item?.Note || "-"}</td>
<td className="px-4 py-2">
{item?.Folder?.Name || "OpenSignDrive"}
</td>
<td className="px-4 py-2">
<a
target="_blank"
rel="noopener noreferrer"
title={item?.URL}
href={item?.URL}
download={item?.URL}
className="text-[blue] hover:text-[blue] hover:underline"
>
{item?.URL ? "Download" : "-"}
</a>
</td>
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td> <td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
<td className="px-4 py-2"> <td className="px-4 py-2">
{item?.Signers ? formatRow(item?.Signers) : "-"} {item?.Signers ? formatRow(item?.Signers) : "-"}
</td> </td>
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white"> <td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
{actions?.length > 0 && {actions?.length > 0 &&
actions.map((act, index) => ( actions.map((act, index) => (
<button <button
key={index} key={index}
onClick={() => onClick={() =>
act?.redirectUrl act?.redirectUrl
? handlemicroapp(item, act.redirectUrl) ? handlemicroapp(item, act.redirectUrl)
: handlebtn(item) : handlebtn(item)
} }
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`} className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
style={{ style={{
backgroundColor: act.btnColor backgroundColor: act.btnColor
? act.btnColor ? act.btnColor
: "#3ac9d6", : "#3ac9d6",
color: act?.textColor ? act?.textColor : "white" color: act?.textColor ? act?.textColor : "white"
}} }}
> >
<span> <span>
{act?.btnIcon && ( {act?.btnIcon && <i className={act.btnIcon}></i>}
<i </span>
className={ <span className="uppercase">
actLoader[item.objectId] {act?.btnLabel ? act.btnLabel : "view"}
? "fa-solid fa-spinner fa-spin-pulse" </span>
: act.btnIcon </button>
} // )
></i> ))}
)} </td>
</span> </tr>
<span className="uppercase"> ))}
{act?.btnLabel ? act.btnLabel : "view"}
</span>
</button>
// )
))}
</td>
</tr>
)
)}
</> </>
) : ( ) : (
<></> <></>
@@ -248,7 +154,7 @@ const ReportTable = ({
</tbody> </tbody>
</table> </table>
<div className="flex flex-wrap items-center gap-2 p-2 "> <div className="flex flex-wrap items-center gap-2 p-2 ">
{List.length > docPerPage && ( {List.length > 10 && (
<> <>
{currentPage > 1 && ( {currentPage > 1 && (
<button <button
@@ -272,7 +178,7 @@ const ReportTable = ({
{isMoreDocs && ( {isMoreDocs && (
<button className="text-black rounded px-1 py-2">...</button> <button className="text-black rounded px-1 py-2">...</button>
)} )}
{List.length > docPerPage && ( {List.length > 10 && (
<> <>
{pageNumbers.includes(currentPage + 1) && ( {pageNumbers.includes(currentPage + 1) && (
<button <button
+12 -8
View File
@@ -11,8 +11,7 @@ export const fetchAppInfo = (str, burl, app_id) => async (dispatch) => {
let _base = ""; // Define _base here and initialize it to an empty string let _base = ""; // Define _base here and initialize it to an empty string
if (response && response.baseurl) { if (response && response.baseurl) {
_base = response.baseurl.charAt(response.baseurl.length - 1); _base = response.baseurl.charAt(response.baseurl.length - 1);
} } localStorage.removeItem("baseUrl");
localStorage.removeItem("baseUrl");
localStorage.setItem("_appName", response.appname); localStorage.setItem("_appName", response.appname);
localStorage.setItem("_app_objectId", response.objectId); localStorage.setItem("_app_objectId", response.objectId);
if (_base === "/") { if (_base === "/") {
@@ -121,11 +120,16 @@ export const login = (username, password) => async (dispatch) => {
localStorage.setItem("_user_role", _role); localStorage.setItem("_user_role", _role);
} }
try { try {
const currentUser = Parse.User.current(); const tour = Parse.Object.extend(
await Parse.Cloud.run("getUserDetails", { localStorage.getItem("extended_class")
email: currentUser.get("email") );
}) let _tour = new Parse.Query(tour);
.then( _tour.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: resultjson.objectId
});
await _tour.first().then(
(results) => { (results) => {
let userinfo = results.toJSON(); let userinfo = results.toJSON();
if (userinfo.TenantId) { if (userinfo.TenantId) {
@@ -138,7 +142,7 @@ export const login = (username, password) => async (dispatch) => {
} }
); );
} catch (error) { } catch (error) {
console.log("err ", error); console.log("err ", error)
} }
} }
}); });
+15 -15
View File
@@ -2,12 +2,11 @@ import React, { useState, useEffect } from "react";
import Parse from "parse"; import Parse from "parse";
import "../styles/loader.css"; import "../styles/loader.css";
import GetDashboard from "../components/dashboard/GetDashboard"; import GetDashboard from "../components/dashboard/GetDashboard";
import { useNavigate, useParams } from "react-router-dom"; import { Navigate, useParams } from "react-router-dom";
import Title from "../components/Title"; import Title from "../components/Title";
import { save_tourSteps } from "../redux/actions"; import { save_tourSteps } from "../redux/actions";
import { connect } from "react-redux"; import { connect } from "react-redux";
const Dashboard = (props) => { const Dashboard = (props) => {
const navigate = useNavigate();
const { id } = useParams(); const { id } = useParams();
const [dashboard, setdashboard] = useState([]); const [dashboard, setdashboard] = useState([]);
const [classnameArray, setclassnameArray] = useState([]); const [classnameArray, setclassnameArray] = useState([]);
@@ -16,19 +15,6 @@ const Dashboard = (props) => {
const [parseAppId] = useState(localStorage.getItem("parseAppId")); const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [defaultQuery, setDefaultQuery] = useState(""); const [defaultQuery, setDefaultQuery] = useState("");
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
if (id !== undefined) {
getDashboard(id);
} else {
getDashboard(localStorage.getItem("PageLanding"));
}
} else {
navigate("/", { replace: true });
}
// eslint-disable-next-line
}, [id]);
const getDashboard = async (id) => { const getDashboard = async (id) => {
setloading(true); setloading(true);
try { try {
@@ -107,6 +93,20 @@ const Dashboard = (props) => {
} }
}; };
useEffect(() => {
if (id !== undefined) {
getDashboard(id);
} else {
getDashboard(localStorage.getItem("PageLanding"));
}
// eslint-disable-next-line
}, [id]);
if (localStorage.getItem("accesstoken") === "" || null) {
return <Navigate to="/" />;
}
let _dash = ( let _dash = (
<GetDashboard <GetDashboard
dashboard={dashboard} dashboard={dashboard}
+98 -79
View File
@@ -10,11 +10,9 @@ import GoogleSignInBtn from "../components/LoginGoogle";
// import LoginFacebook from "../components/LoginFacebook"; // import LoginFacebook from "../components/LoginFacebook";
import { NavLink, useNavigate } from "react-router-dom"; import { NavLink, useNavigate } from "react-router-dom";
import login_img from "../assets/images/login_img.svg"; import login_img from "../assets/images/login_img.svg";
import { useWindowSize } from "../hook/useWindowSize";
function Login(props) { function Login(props) {
const navigate = useNavigate(); const navigate = useNavigate();
const { width } = useWindowSize();
const [state, setState] = useState({ const [state, setState] = useState({
email: "", email: "",
toastColor: "#5cb85c", toastColor: "#5cb85c",
@@ -23,6 +21,7 @@ function Login(props) {
passwordVisible: false, passwordVisible: false,
mobile: "", mobile: "",
phone: "", phone: "",
hideNav: "",
scanResult: "", scanResult: "",
baseUrl: localStorage.getItem("baseUrl"), baseUrl: localStorage.getItem("baseUrl"),
parseAppId: localStorage.getItem("parseAppId"), parseAppId: localStorage.getItem("parseAppId"),
@@ -48,11 +47,26 @@ function Login(props) {
); );
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, []);
useEffect(() => {
resize();
window.addEventListener("resize", resize());
return () => {
window.removeEventListener("resize", resize());
};
// eslint-disable-next-line
}, []);
const handleChange = (event) => { const handleChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
setState({ ...state, [name]: value }); setState({ ...state, [name]: value });
}; };
const resize = () => {
let currentHideNav = window.innerWidth <= 760;
if (currentHideNav !== state.hideNav) {
setState({ ...state, hideNav: currentHideNav });
}
};
const handleSubmit = async (event) => { const handleSubmit = async (event) => {
localStorage.removeItem("accesstoken"); localStorage.removeItem("accesstoken");
event.preventDefault(); event.preventDefault();
@@ -115,7 +129,7 @@ function Login(props) {
); );
if (rolesfiltered.length > 0) { if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0]; _currentRole = rolesfiltered[0];
} }
} else { } else {
const rolesfiltered = userRoles.filter( const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x) (x) => !valuesToExclude.includes(x)
@@ -148,13 +162,15 @@ function Login(props) {
element.userpointer element.userpointer
); );
const currentUser = Parse.User.current(); const extendedClass = Parse.Object.extend(
await Parse.Cloud.run("getUserDetails", { element.extended_class
email: currentUser.get("email") );
}).then( let query = new Parse.Query(extendedClass);
(result) => { query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = []; let tenentInfo = [];
const results = [result];
if (results) { if (results) {
let extendedInfo_stringify = let extendedInfo_stringify =
JSON.stringify(results); JSON.stringify(results);
@@ -264,14 +280,10 @@ function Login(props) {
`/${element.pageType}/${element.pageId}` `/${element.pageType}/${element.pageId}`
); );
} else { } else {
navigate(`/subscription`, { navigate(`/subscription`);
replace: true
});
} }
} else { } else {
navigate(`/subscription`, { navigate(`/subscription`);
replace: true
});
} }
} else { } else {
navigate( navigate(
@@ -308,9 +320,7 @@ function Login(props) {
); );
const billingDate = ""; const billingDate = "";
if (billingDate) { if (billingDate) {
navigate(`/subscription`, { navigate(`/subscription`);
replace: true
});
} }
} else { } else {
navigate( navigate(
@@ -324,6 +334,23 @@ function Login(props) {
sessionToken: user.getSessionToken() sessionToken: user.getSessionToken()
}; };
handleSubmitbtn(payload); handleSubmitbtn(payload);
// setState({
// ...state,
// loading: false,
// toastColor: "#d9534f",
// toastDescription:
// "You dont have access to this application."
// });
// const x = document.getElementById("snackbar");
// x.className = "show";
// setTimeout(function () {
// x.className = x.className.replace(
// "show",
// ""
// );
// }, 2000);
// localStorage.setItem("accesstoken", null);
console.error( console.error(
"Error while fetching Follow", "Error while fetching Follow",
error error
@@ -445,7 +472,7 @@ function Login(props) {
); );
if (rolesfiltered.length > 0) { if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0]; _currentRole = rolesfiltered[0];
} }
} else { } else {
const rolesfiltered = userRoles.filter( const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x) (x) => !valuesToExclude.includes(x)
@@ -475,13 +502,16 @@ function Login(props) {
element.extended_class element.extended_class
); );
localStorage.setItem("userpointer", element.userpointer); localStorage.setItem("userpointer", element.userpointer);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", { const extendedClass = Parse.Object.extend(
email: currentUser.get("email") element.extended_class
}).then( );
(result) => { let query = new Parse.Query(extendedClass);
query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = []; let tenentInfo = [];
const results = [result];
if (results) { if (results) {
let extendedInfo_stringify = let extendedInfo_stringify =
JSON.stringify(results); JSON.stringify(results);
@@ -566,26 +596,20 @@ function Login(props) {
setThirdpartyLoader(false); setThirdpartyLoader(false);
setState({ ...state, loading: false }); setState({ ...state, loading: false });
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) { if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
if (billingDate) { if (billingDate) {
if (billingDate > new Date()) { if (billingDate > new Date()) {
localStorage.removeItem("userDetails"); localStorage.removeItem("userDetails");
navigate( navigate(
`/${element.pageType}/${element.pageId}` `/${element.pageType}/${element.pageId}`
); );
} else {
navigate(`/subscription`, {
replace: true
});
}
} else { } else {
navigate(`/subscription`, { replace: true }); navigate(`/subscription`);
} }
} else { } else {
navigate( navigate(`/subscription`);
`/${element.pageType}/${element.pageId}`
);
} }
} }
}
} else { } else {
localStorage.setItem("PageLanding", element.pageId); localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem( localStorage.setItem(
@@ -596,25 +620,21 @@ function Login(props) {
setState({ ...state, loading: false }); setState({ ...state, loading: false });
setThirdpartyLoader(false); setThirdpartyLoader(false);
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) { if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
if (billingDate) { if (billingDate) {
if (billingDate > new Date()) { if (billingDate > new Date()) {
localStorage.removeItem("userDetails"); localStorage.removeItem("userDetails");
navigate( navigate(
`/${element.pageType}/${element.pageId}` `/${element.pageType}/${element.pageId}`
); );
} else {
navigate(`/subscription`, { replace: true });
}
} else { } else {
navigate(`/subscription`, { replace: true }); navigate(`/subscription`);
} }
} else { } else {
navigate( navigate(`/subscription`);
`/${element.pageType}/${element.pageId}`
);
} }
} }
}, }
},
(error) => { (error) => {
const payload = { const payload = {
sessionToken: sessionToken sessionToken: sessionToken
@@ -635,6 +655,7 @@ function Login(props) {
} else { } else {
setThirdpartyLoader(false); setThirdpartyLoader(false);
setState({ ...state, loading: false }); setState({ ...state, loading: false });
} }
}) })
.catch((err) => { .catch((err) => {
@@ -696,10 +717,9 @@ function Login(props) {
await axios await axios
.post(url, JSON.stringify(body), { headers: headers1 }) .post(url, JSON.stringify(body), { headers: headers1 })
.then((axiosres) => { .then((roles) => {
const roles = axiosres.data.result;
if (roles) { if (roles) {
userRoles = roles; userRoles = roles.data.result;
let _currentRole = ""; let _currentRole = "";
if (userRoles.length > 1) { if (userRoles.length > 1) {
if ( if (
@@ -747,13 +767,15 @@ function Login(props) {
element.extended_class element.extended_class
); );
const currentUser = Parse.User.current(); const extendedClass = Parse.Object.extend(
await Parse.Cloud.run("getUserDetails", { element.extended_class
email: currentUser.get("email") );
}).then( let query = new Parse.Query(extendedClass);
(result) => { query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = []; let tenentInfo = [];
const results = [result];
if (results) { if (results) {
let extendedInfo_stringify = JSON.stringify(results); let extendedInfo_stringify = JSON.stringify(results);
let extendedInfo = JSON.parse(extendedInfo_stringify); let extendedInfo = JSON.parse(extendedInfo_stringify);
@@ -1044,7 +1066,7 @@ function Login(props) {
<NavLink <NavLink
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase" className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
to="/signup" to="/signup"
style={width < 768 ? { textAlign: "center" } : {}} style={state.hideNav ? { textAlign: "center" } : {}}
> >
Create Account Create Account
</NavLink> </NavLink>
@@ -1112,7 +1134,7 @@ function Login(props) {
</div> </div>
</div> </div>
</div> </div>
{width >= 768 && ( {!state.hideNav && (
<div className="self-center"> <div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]"> <div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img <img
@@ -1149,9 +1171,7 @@ function Login(props) {
<div className="modal-dialog" role="document"> <div className="modal-dialog" role="document">
<div className="modal-content"> <div className="modal-content">
<div className="modal-header"> <div className="modal-header">
<h5 className="modal-title font-semibold"> <h5 className="modal-title">Login form</h5>
Additional Info
</h5>
<span> <span>
<span></span> <span></span>
</span> </span>
@@ -1183,17 +1203,17 @@ function Login(props) {
</div> </div>
<div className="form-group"> <div className="form-group">
<label <label
htmlFor="JobTitle" htmlFor="Destination"
style={{ display: "flex" }} style={{ display: "flex" }}
className="col-form-label" className="col-form-label"
> >
Job Title Destination{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span> <span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="text" type="text"
className="form-control" className="form-control"
id="JobTitle" id="Destination"
value={userDetails.Destination} value={userDetails.Destination}
onChange={(e) => onChange={(e) =>
setUserDetails({ setUserDetails({
@@ -1207,19 +1227,18 @@ function Login(props) {
<div className="mt-4"> <div className="mt-4">
<button <button
type="button" type="button"
className="bg-[#17a2b8] text-sm p-2 text-white rounded uppercase" className="bg-[#6c757d] text-sm p-2 text-white rounded uppercase"
onClick={(e) => handleSubmitbtn(e)} onClick={handleCloseModal}
style={{ marginRight: 10 }} style={{ marginRight: 10, width: 90 }}
> >
Login Cancel
</button> </button>
<button <button
type="button" type="button"
className="bg-[#6c757d] text-sm p-2 text-white rounded uppercase" className="bg-[#17a2b8] text-sm p-2 text-white rounded uppercase"
onClick={handleCloseModal} onClick={(e) => handleSubmitbtn(e)}
style={{ width: 90 }}
> >
Cancel Login
</button> </button>
</div> </div>
</form> </form>
+35 -67
View File
@@ -21,9 +21,6 @@ const PgSignUp = (props) => {
}); });
const [validationMessage, setValidationMessage] = useState(""); const [validationMessage, setValidationMessage] = useState("");
const [isLoader, setIsLoader] = useState(true); const [isLoader, setIsLoader] = useState(true);
const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false);
// below useEffect is used to fetch App data and save to redux state // below useEffect is used to fetch App data and save to redux state
useEffect(() => { useEffect(() => {
@@ -70,8 +67,9 @@ const PgSignUp = (props) => {
const userSettings = JSON.parse(localStorage.getItem("userSettings")); const userSettings = JSON.parse(localStorage.getItem("userSettings"));
const extClass = userSettings[0].extended_class; const extClass = userSettings[0].extended_class;
// console.log("extClass ", extClass); // console.log("extClass ", extClass);
const params = { email: userDetails.email }; const checkUser = new Parse.Query(extClass);
const res = await Parse.Cloud.run("getUserDetails", params); checkUser.equalTo("Email", userDetails.email);
const res = await checkUser.first();
// console.log("res", res); // console.log("res", res);
if (res) { if (res) {
const checkUser = new Parse.Query(extClass); const checkUser = new Parse.Query(extClass);
@@ -107,23 +105,21 @@ const PgSignUp = (props) => {
// "handleSubmit" is used to save user details signup him/her who come from plan-pricing page // "handleSubmit" is used to save user details signup him/her who come from plan-pricing page
const handleSubmit = (e) => { const handleSubmit = (e) => {
e.preventDefault(); e.preventDefault();
if (lengthValid && caseDigitValid && specialCharValid) { setIsLoader(true);
setIsLoader(true); if (formData.password === formData.confirmPassword) {
if (formData.password === formData.confirmPassword) { const url = window.location.href;
const url = window.location.href; let paramString = url.split("?")[1];
let paramString = url.split("?")[1]; let queryString = new URLSearchParams(paramString);
let queryString = new URLSearchParams(paramString); // console.log("url ", queryString);
// console.log("url ", queryString);
let obj = { ...formData }; let obj = { ...formData };
for (let pair of queryString.entries()) { for (let pair of queryString.entries()) {
// console.log("Key is: " + pair[0]); // console.log("Key is: " + pair[0]);
// console.log("Value is: " + pair[1]); // console.log("Value is: " + pair[1]);
obj = { ...obj, [pair[0]]: pair[1] }; obj = { ...obj, [pair[0]]: pair[1] };
}
saveUser(obj);
// console.log("obj ", obj);}
} }
saveUser(obj);
// console.log("obj ", obj);}
} }
}; };
const saveUser = async (obj) => { const saveUser = async (obj) => {
@@ -156,7 +152,6 @@ const PgSignUp = (props) => {
if (res) { if (res) {
const params = { const params = {
userDetails: { userDetails: {
jobTitle: zohoRes.data.result.jobTitle,
company: zohoRes.data.result.company, company: zohoRes.data.result.company,
name: zohoRes.data.result.name, name: zohoRes.data.result.name,
email: zohoRes.data.result.email, email: zohoRes.data.result.email,
@@ -199,15 +194,6 @@ const PgSignUp = (props) => {
const newPassword = e.target.value; const newPassword = e.target.value;
setFormData({ ...formData, [e.target.name]: e.target.value }); setFormData({ ...formData, [e.target.name]: e.target.value });
validatePasswords(newPassword, formData.confirmPassword); validatePasswords(newPassword, formData.confirmPassword);
// Check conditions separately
setLengthValid(newPassword.length >= 8);
setCaseDigitValid(
/[a-z]/.test(newPassword) &&
/[A-Z]/.test(newPassword) &&
/\d/.test(newPassword)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
}; };
const handleConFirmPassowordChange = (e) => { const handleConFirmPassowordChange = (e) => {
const newConfirmPassword = e.target.value; const newConfirmPassword = e.target.value;
@@ -293,6 +279,13 @@ const PgSignUp = (props) => {
"" ""
); );
localStorage.setItem("_user_role", _role); localStorage.setItem("_user_role", _role);
if (element.enableCart) {
localStorage.setItem("EnableCart", element.enableCart);
props.setEnableCart(element.enableCart);
} else {
localStorage.removeItem("EnableCart");
}
// Get TenentID from Extendend Class // Get TenentID from Extendend Class
localStorage.setItem( localStorage.setItem(
"extended_class", "extended_class",
@@ -300,12 +293,14 @@ const PgSignUp = (props) => {
); );
localStorage.setItem("userpointer", element.userpointer); localStorage.setItem("userpointer", element.userpointer);
const currentUser = Parse.User.current(); const extendedClass = Parse.Object.extend(
await Parse.Cloud.run("getUserDetails", { element.extended_class
email: currentUser.get("email") );
}).then( let query = new Parse.Query(extendedClass);
(result) => { query.equalTo("UserId", Parse.User.current());
const results = [result]; query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = []; let tenentInfo = [];
if (results) { if (results) {
let extendedInfo_stringify = let extendedInfo_stringify =
@@ -420,7 +415,7 @@ const PgSignUp = (props) => {
} }
}) })
.catch((err) => { .catch((err) => {
console.log("err", err); console.log('err', err)
setIsLoader(false); setIsLoader(false);
}); });
} }
@@ -453,10 +448,10 @@ const PgSignUp = (props) => {
) : ( ) : (
<form id="signup" className="pgsignup-content" onSubmit={handleSubmit}> <form id="signup" className="pgsignup-content" onSubmit={handleSubmit}>
<div className="pgsignup-container"> <div className="pgsignup-container">
<h1 className="text-2xl md:text-3xl font-bold">Choose Password</h1> <h1 className="text-4xl font-bold">Choose Password</h1>
<hr className="hrt" /> <hr className="hrt" />
<label htmlFor="password"> <label htmlFor="password">
<b className="text-[13px]">Password</b> <b>Password</b>
</label> </label>
<input <input
type="password" type="password"
@@ -469,7 +464,7 @@ const PgSignUp = (props) => {
/> />
<label htmlFor="confirmPassword"> <label htmlFor="confirmPassword">
<b className="text-[13px]">Confirm Password</b> <b>Confirm Password</b>
</label> </label>
<input <input
type="password" type="password"
@@ -499,33 +494,6 @@ const PgSignUp = (props) => {
> >
{validationMessage} {validationMessage}
</div> </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>
)}
<div className="clearfix"> <div className="clearfix">
<button type="submit" className="signupbtn"> <button type="submit" className="signupbtn">
Submit Submit
+16 -24
View File
@@ -2,14 +2,14 @@ import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
import checkmark from "../assets/images/checkmark.png"; import checkmark from "../assets/images/checkmark.png";
import plansArr from "../json/plansArr.json"; import plansArr from '../json/plansArr.json'
import Title from "../components/Title"; import Title from "../components/Title";
const listItemStyle = { const listItemStyle = {
paddingLeft: "20px", // Add padding to create space for the image paddingLeft: '20px', // Add padding to create space for the image
backgroundImage: `url(${checkmark})`, // Set your image as the list style image backgroundImage: `url(${checkmark})`, // Set your image as the list style image
backgroundPosition: "left", backgroundPosition: 'left',
backgroundRepeat: "no-repeat", backgroundRepeat: 'no-repeat',
backgroundSize: "16px 16px" // Adjust the size of the image backgroundSize: '16px 16px', // Adjust the size of the image
}; };
const PlanSubscriptions = () => { const PlanSubscriptions = () => {
@@ -28,12 +28,7 @@ const PlanSubscriptions = () => {
: ""; : "";
const phone = const phone =
userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : ""; userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : "";
const details = const details = "?" + name + email + company + phone;
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
name +
email +
company +
phone;
useEffect(() => { useEffect(() => {
if (localStorage.getItem("accesstoken")) { if (localStorage.getItem("accesstoken")) {
setIsLoader(false); setIsLoader(false);
@@ -46,7 +41,7 @@ const PlanSubscriptions = () => {
return ( return (
<> <>
<Title title={"Subscriptions"} /> <Title title={"Subscriptions"} />
{isLoader ? ( {isLoader ? (
<div <div
style={{ style={{
@@ -136,18 +131,15 @@ const PlanSubscriptions = () => {
<p>{item.subtitle}</p> <p>{item.subtitle}</p>
</div> </div>
</div> </div>
<div className="bg-[#002862] w-full text-white py-2 rounded">
<NavLink <NavLink
to={ to={item.url + details}
item.btnText === "Subscribe" className="rounded uppercase hover:no-underline hover:text-white"
? item.url + details target="_self"
: item.url >
} {item.btnText}
className="bg-[#002862] w-full text-white py-2 rounded uppercase hover:no-underline hover:text-white" </NavLink>
target={item.target} </div>
>
{item.btnText}
</NavLink>
</div> </div>
<hr className="w-full bg-gray-300 p-[.5px]" /> <hr className="w-full bg-gray-300 p-[.5px]" />
<ul className="mx-1 p-3 text-left break-words text-sm list-none"> <ul className="mx-1 p-3 text-left break-words text-sm list-none">
+16 -15
View File
@@ -12,11 +12,9 @@ const Report = () => {
const [isLoader, setIsLoader] = useState(true); const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState(""); const [reportName, setReportName] = useState("");
const [actions, setActions] = useState([]); const [actions, setActions] = useState([]);
const [heading, setHeading] = useState([]);
const [isNextRecord, setIsNextRecord] = useState(false); const [isNextRecord, setIsNextRecord] = useState(false);
const [isMoreDocs, setIsMoreDocs] = useState(true); const [isMoreDocs, setIsMoreDocs] = useState(true);
const abortController = new AbortController(); const abortController = new AbortController();
const docPerPage = 10;
// below useEffect is call when id param change // below useEffect is call when id param change
useEffect(() => { useEffect(() => {
@@ -48,26 +46,31 @@ const Report = () => {
const json = reportJson(id); const json = reportJson(id);
if (json) { if (json) {
setActions(json.actions); setActions(json.actions);
setHeading(json.heading);
setReportName(json.reportName); setReportName(json.reportName);
const { className, params, keys, orderBy } = json;
Parse.serverURL = localStorage.getItem("BaseUrl12"); Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12")); Parse.initialize(localStorage.getItem("AppID12"));
const currentUser = Parse.User.current().id; const currentUser = Parse.User.current().id;
const serverURL =
localStorage.getItem("BaseUrl12") + "classes/" + className;
const strParams = JSON.stringify(params);
const strKeys = keys.join();
const headers = { const headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"), "X-Parse-Application-Id": localStorage.getItem("AppID12"),
sessiontoken: localStorage.getItem("accesstoken") "X-Parse-Session-Token": localStorage.getItem("accesstoken")
}; };
try { try {
const params = { reportId: id, skip: skipUserRecord, limit: limit }; const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skipUserRecord}&limit=${limit}&include=AuditTrail.UserPtr`;
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`; const res = await axios.get(url, {
const res = await axios.post(url, params, {
headers: headers, headers: headers,
signal: abortController.signal // is used to cancel fetch query signal: abortController.signal // is used to cancel fetch query
}); });
if (id === "4Hhwbp482K") { if (id === "4Hhwbp482K") {
const listData = res.data?.result.filter((x) => x.Signers.length > 0); const listData = res.data?.results.filter(
(x) => x.Signers.length > 0
);
let arr = []; let arr = [];
for (const obj of listData) { for (const obj of listData) {
const isSigner = obj.Signers.some( const isSigner = obj.Signers.some(
@@ -89,7 +92,7 @@ const Report = () => {
} }
} }
} }
if (arr.length === docPerPage) { if (arr.length === 10) {
setIsMoreDocs(true); setIsMoreDocs(true);
} else { } else {
setIsMoreDocs(false); setIsMoreDocs(false);
@@ -98,16 +101,17 @@ const Report = () => {
prevRecord.length > 0 ? [...prevRecord, ...arr] : arr prevRecord.length > 0 ? [...prevRecord, ...arr] : arr
); );
} else { } else {
if (res.data.result.length === docPerPage) { if (res.data.results.length === 10) {
setIsMoreDocs(true); setIsMoreDocs(true);
console.log("here");
} else { } else {
setIsMoreDocs(false); setIsMoreDocs(false);
} }
setIsNextRecord(false); setIsNextRecord(false);
setList((prevRecord) => setList((prevRecord) =>
prevRecord.length > 0 prevRecord.length > 0
? [...prevRecord, ...res.data.result] ? [...prevRecord, ...res.data.results]
: res.data.result : res.data.results
); );
} }
setIsLoader(false); setIsLoader(false);
@@ -148,12 +152,9 @@ const Report = () => {
<ReportTable <ReportTable
ReportName={reportName} ReportName={reportName}
List={List} List={List}
setList={setList}
actions={actions} actions={actions}
heading={heading}
setIsNextRecord={setIsNextRecord} setIsNextRecord={setIsNextRecord}
isMoreDocs={isMoreDocs} isMoreDocs={isMoreDocs}
docPerPage={docPerPage}
/> />
) : ( ) : (
<div className="flex items-center justify-center h-screen w-full bg-white rounded"> <div className="flex items-center justify-center h-screen w-full bg-white rounded">
+136 -180
View File
@@ -6,10 +6,8 @@ import Title from "../components/Title";
import { fetchAppInfo, showTenantName } from "../redux/actions"; import { fetchAppInfo, showTenantName } from "../redux/actions";
import { useNavigate, NavLink } from "react-router-dom"; import { useNavigate, NavLink } from "react-router-dom";
import login_img from "../assets/images/login_img.svg"; import login_img from "../assets/images/login_img.svg";
import { useWindowSize } from "../hook/useWindowSize";
const Signup = (props) => { const Signup = (props) => {
const { width } = useWindowSize();
const navigate = useNavigate(); const navigate = useNavigate();
const [name, setName] = useState(""); const [name, setName] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
@@ -20,143 +18,122 @@ const Signup = (props) => {
const [company, setCompany] = useState(""); const [company, setCompany] = useState("");
const [jobTitle, setJobTitle] = useState(""); const [jobTitle, setJobTitle] = useState("");
const [state, setState] = useState({ const [state, setState] = useState({
hideNav: "",
loading: false, loading: false,
toastColor: "#5cb85c", toastColor: "#5cb85c",
toastDescription: "" toastDescription: ""
}); });
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false);
const togglePasswordVisibility = () => setShowPassword(!showPassword); const togglePasswordVisibility = () => setShowPassword(!showPassword);
const image = props.appInfo.applogo; const image = props.appInfo.applogo;
const clearStorage = async () => {
if (Parse.User.current()) {
await Parse.User.logOut();
}
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let applogo = localStorage.getItem("appLogo");
let domain = localStorage.getItem("domain");
let appversion = localStorage.getItem("appVersion");
let appTitle = localStorage.getItem("appTitle");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let _appName = localStorage.getItem("_appName");
let _app_objectId = localStorage.getItem("_app_objectId");
let appName = localStorage.getItem("appName");
let userSettings = localStorage.getItem("userSettings");
localStorage.clear();
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("domain", domain);
localStorage.setItem("appversion", appversion);
localStorage.setItem("appTitle", appTitle);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("_appName", _appName);
localStorage.setItem("_app_objectId", _app_objectId);
localStorage.setItem("appName", appName);
localStorage.setItem("userSettings", userSettings);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
};
const handleSubmit = (event) => { const handleSubmit = (event) => {
event.preventDefault(); setState({ loading: true });
if (lengthValid && caseDigitValid && specialCharValid) { const userDetails = {
clearStorage(); name: name,
setState({ loading: true }); email: email,
const userDetails = { phone: phone,
name: name, company: company,
email: email, jobTitle: jobTitle
phone: phone, };
company: company, localStorage.setItem("userDetails", JSON.stringify(userDetails));
jobTitle: jobTitle try {
}; event.preventDefault();
localStorage.setItem("userDetails", JSON.stringify(userDetails)); Parse.serverURL = parseBaseUrl;
try { Parse.initialize(parseAppId);
Parse.serverURL = parseBaseUrl; event.preventDefault();
Parse.initialize(parseAppId); var user = new Parse.User();
event.preventDefault(); user.set("name", name);
var user = new Parse.User(); user.set("email", email);
user.set("name", name); user.set("password", password);
user.set("email", email); user.set("phone", phone);
user.set("password", password); user.set("username", email);
user.set("phone", phone); let res = user.save();
user.set("username", email); res
let res = user.save(); .then(async (r) => {
res if (r) {
.then(async (r) => { let roleurl = `${parseBaseUrl}functions/AddUserToRole`;
if (r) { const headers = {
let roleData = props.appInfo.settings; "Content-Type": "application/json",
if (roleData && roleData.length > 0) { "X-Parse-Application-Id": parseAppId,
const params = { sessionToken:
userDetails: { r.getSessionToken() || localStorage.getItem("accesstoken")
jobTitle: jobTitle, };
company: company, let body = {
name: name, appName: props.appInfo.appname,
email: email, roleName: props.appInfo.defaultRole,
phone: phone, userId: r.id
role: props.appInfo.defaultRole };
} await axios.post(roleurl, body, { headers: headers });
};
try { let roleData = props.appInfo.settings;
const usersignup = await Parse.Cloud.run( if (roleData && roleData.length > 0) {
"usersignup", roleData.forEach((rld) => {
params if (rld.role === props.appInfo.defaultRole) {
); const extCls = Parse.Object.extend(rld.extended_class);
if (usersignup) { const newObj = new extCls();
handleNavigation(r.getSessionToken()); newObj.set("UserId", {
} __type: "Pointer",
} catch (err) { className: "_User",
alert(err.message); objectId: r.id
setState({ loading: false }); });
} newObj.set("UserRole", props.appInfo.defaultRole);
} newObj.set("Email", email);
} newObj.set("Name", name);
}) newObj.set("Phone", phone);
.catch(async (err) => { newObj.set("Company", company);
if (err.code === 202) { newObj.set("JobTitle", jobTitle);
const params = { email: email }; newObj
const res = await Parse.Cloud.run("getUserDetails", params); .save()
// console.log("Res ", res); .then((ex) => {
if (res) { if (ex) {
alert("User already exists with this username!"); handleNavigation(r.getSessionToken());
setState({ loading: false });
} else {
let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
// console.log("state.email ", email);
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
alert(
"Verification mail has been sent to your E-mail!"
);
} }
} })
); .catch((err) => {
} catch (err) { alert(err.message);
console.log(err); setState({ loading: false });
});
} }
setState({ loading: false }); });
} }
}
})
.catch(async (err) => {
if (err.code === 202) {
const userQuery = new Parse.Query("contracts_Users");
userQuery.equalTo("Email", email);
const res = await userQuery.first();
// console.log("Res ", res);
if (res) {
alert("User already exists with this username!");
setState({ loading: false });
} else { } else {
alert(err.message); let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
// console.log("state.email ", email);
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
alert("Email has been sent to your mail!");
}
}
);
} catch (err) {
console.log(err);
}
setState({ loading: false }); setState({ loading: false });
} }
}); } else {
} catch (error) { alert(err.message);
console.log("err ", error); setState({ loading: false });
} }
});
} catch (error) {
console.log("err ", error);
} }
}; };
@@ -231,6 +208,13 @@ const Signup = (props) => {
"" ""
); );
localStorage.setItem("_user_role", _role); localStorage.setItem("_user_role", _role);
if (element.enableCart) {
localStorage.setItem("EnableCart", element.enableCart);
props.setEnableCart(element.enableCart);
} else {
localStorage.removeItem("EnableCart");
}
// Get TenentID from Extendend Class // Get TenentID from Extendend Class
localStorage.setItem( localStorage.setItem(
"extended_class", "extended_class",
@@ -238,12 +222,15 @@ const Signup = (props) => {
); );
localStorage.setItem("userpointer", element.userpointer); localStorage.setItem("userpointer", element.userpointer);
await Parse.Cloud.run("getUserDetails", { const extendedClass = Parse.Object.extend(
email: email element.extended_class
}).then( );
(result) => { let query = new Parse.Query(extendedClass);
query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = []; let tenentInfo = [];
const results = [result];
if (results) { if (results) {
let extendedInfo_stringify = let extendedInfo_stringify =
JSON.stringify(results); JSON.stringify(results);
@@ -331,7 +318,7 @@ const Signup = (props) => {
); );
setState({ loading: false }); setState({ loading: false });
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) { if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
navigate(`/subscription`, { replace: true }); navigate("/subscription");
} else { } else {
alert("Registered user successfully"); alert("Registered user successfully");
navigate( navigate(
@@ -349,7 +336,7 @@ const Signup = (props) => {
localStorage.setItem("pageType", element.pageType); localStorage.setItem("pageType", element.pageType);
setState({ loading: false }); setState({ loading: false });
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) { if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
navigate(`/subscription`, { replace: true }); navigate("/subscription");
} else { } else {
navigate( navigate(
`/${element.pageType}/${element.pageId}` `/${element.pageType}/${element.pageId}`
@@ -434,26 +421,23 @@ const Signup = (props) => {
} }
}; };
useEffect(() => { useEffect(() => {
window.addEventListener("resize", resize);
props.fetchAppInfo( props.fetchAppInfo(
localStorage.getItem("domain"), localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"), localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12") localStorage.getItem("AppID12")
); );
return () => {
window.removeEventListener("resize", resize);
};
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, []);
const handlePasswordChange = (e) => { const resize = () => {
const newPassword = e.target.value; let currentHideNav = window.innerWidth <= 760;
setPassword(newPassword); if (currentHideNav !== state.hideNav) {
setState({ hideNav: currentHideNav });
// Check conditions separately }
setLengthValid(newPassword.length >= 8);
setCaseDigitValid(
/[a-z]/.test(newPassword) &&
/[A-Z]/.test(newPassword) &&
/\d/.test(newPassword)
);
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
}; };
return ( return (
<div className="bg-white"> <div className="bg-white">
@@ -488,7 +472,11 @@ const Signup = (props) => {
<div> <div>
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 "> <div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
<div className="w-[250px] h-[66px] inline-block"> <div className="w-[250px] h-[66px] inline-block">
<img src={image} width="100%" alt="" /> {state.hideNav ? (
<img src={image} width="100%" alt="" />
) : (
<img src={image} width="100%" alt="" />
)}
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2"> <div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div className=""> <div className="">
@@ -567,7 +555,7 @@ const Signup = (props) => {
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="password" name="password"
value={password} value={password}
onChange={(e) => handlePasswordChange(e)} onChange={(e) => setPassword(e.target.value)}
required required
/> />
<span <span
@@ -583,38 +571,6 @@ const Signup = (props) => {
)} )}
</span> </span>
</div> </div>
{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>
)}
</div> </div>
</div> </div>
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2"> <div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
@@ -628,14 +584,14 @@ const Signup = (props) => {
<NavLink <NavLink
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase" className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
to="/" to="/"
style={width < 768 ? { textAlign: "center" } : {}} style={state.hideNav ? { textAlign: "center" } : {}}
> >
Login Login
</NavLink> </NavLink>
</div> </div>
</form> </form>
</div> </div>
{width >= 768 && ( {!state.hideNav && (
<div className="self-center"> <div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]"> <div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img src={login_img} alt="bisec" width="100%" /> <img src={login_img} alt="bisec" width="100%" />
+34 -62
View File
@@ -5,7 +5,7 @@ import { SaveFileSize } from "../constant/saveFileSize";
import dp from "../assets/images/dp.png"; import dp from "../assets/images/dp.png";
import Title from "../components/Title"; import Title from "../components/Title";
import sanitizeFileName from "../primitives/sanitizeFileName"; import sanitizeFileName from "../primitives/sanitizeFileName";
import axios from "axios";
function UserProfile() { function UserProfile() {
const navigate = useNavigate(); const navigate = useNavigate();
let UserProfile = JSON.parse(localStorage.getItem("UserInformation")); let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
@@ -16,8 +16,6 @@ function UserProfile() {
const [Phone, SetPhone] = useState(UserProfile && UserProfile.phone); const [Phone, SetPhone] = useState(UserProfile && UserProfile.phone);
const [Image, setImage] = useState(localStorage.getItem("profileImg")); const [Image, setImage] = useState(localStorage.getItem("profileImg"));
const [isLoader, setIsLoader] = useState(false); const [isLoader, setIsLoader] = useState(false);
const [percentage, setpercentage] = useState(0);
Parse.serverURL = parseBaseUrl; Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId); Parse.initialize(parseAppId);
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
@@ -46,7 +44,7 @@ function UserProfile() {
await updateExtUser({ Name: res.name, Phone: res.phone }); await updateExtUser({ Name: res.name, Phone: res.phone });
alert("Profile updated successfully."); alert("Profile updated successfully.");
setEditMode(false); setEditMode(false);
navigate("/dashboard/35KBoSgoAK"); navigate("/");
} }
}, },
(error) => { (error) => {
@@ -66,24 +64,18 @@ function UserProfile() {
const extClass = localStorage.getItem("extended_class"); const extClass = localStorage.getItem("extended_class");
const extData = JSON.parse(localStorage.getItem("Extand_Class")); const extData = JSON.parse(localStorage.getItem("Extand_Class"));
const ExtUserId = extData[0].objectId; const ExtUserId = extData[0].objectId;
// console.log("extData ", extData);
// console.log("UserId ", ExtUserId); // console.log("UserId ", ExtUserId);
const body = { Phone: obj.Phone, Name: obj.Name };
await axios.put(
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
body,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const res = await Parse.Cloud.run("getUserDetails", {
email: extData[0].Email
});
const json = JSON.parse(JSON.stringify([res])); const extQuery = new Parse.Query(extClass);
const update = await extQuery.get(ExtUserId);
// console.log("update ", update);
update.set("Phone", obj.Phone);
update.set("Name", obj.Name);
const updateRes = await update.save();
const json = JSON.parse(JSON.stringify([updateRes]));
const extRes = JSON.stringify(json); const extRes = JSON.stringify(json);
localStorage.setItem("Extand_Class", extRes); localStorage.setItem("Extand_Class", extRes);
@@ -104,15 +96,7 @@ function UserProfile() {
const parseFile = new Parse.File(name, pdfFile); const parseFile = new Parse.File(name, pdfFile);
try { try {
const response = await parseFile.save({ const response = await parseFile.save();
progress: (progressValue, loaded, total, { type }) => {
if (type === "upload" && progressValue !== null) {
const percentCompleted = Math.round((loaded * 100) / total);
// console.log("percentCompleted ", percentCompleted);
setpercentage(percentCompleted);
}
}
});
// // The response object will contain information about the uploaded file // // The response object will contain information about the uploaded file
// console.log("File uploaded:", response); // console.log("File uploaded:", response);
@@ -121,7 +105,6 @@ function UserProfile() {
if (response.url()) { if (response.url()) {
setImage(response.url()); setImage(response.url());
localStorage.setItem("profileImg", response.url()); localStorage.setItem("profileImg", response.url());
setpercentage(0);
SaveFileSize(size, response.url()); SaveFileSize(size, response.url());
return response.url(); return response.url();
} }
@@ -171,25 +154,14 @@ function UserProfile() {
<input <input
type="file" type="file"
className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded" className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded"
accept="image/png, image/gif, image/jpeg"
onChange={(e) => { onChange={(e) => {
let files = e.target.files; let files = e.target.files;
fileUpload(files[0]); fileUpload(files[0]);
}} }}
/> />
)} )}
{percentage !== 0 && (
<div className="flex items-center gap-x-2">
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
<div
className="h-2 rounded-full bg-blue-500"
style={{ width: `${percentage}%` }}
></div>
</div>
<span className="text-black text-sm">{percentage}%</span>
</div>
)}
<div className="text-base font-semibold pt-4"> <div className="text-base font-semibold pt-4">
{" "}
{localStorage.getItem("_user_role")} {localStorage.getItem("_user_role")}
</div> </div>
</div> </div>
@@ -242,25 +214,6 @@ function UserProfile() {
</li> </li>
</ul> </ul>
<div className="flex justify-center pb-4"> <div className="flex justify-center pb-4">
{editmode ? (
<button
type="button"
onClick={handleSubmit}
className="rounded bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-2 mr-4"
>
Save
</button>
) : (
<button
type="button"
onClick={() => {
setEditMode(true);
}}
className="rounded shadow text-white bg-[#e7505a] px-4 py-2 mr-4"
>
Edit
</button>
)}
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
@@ -270,12 +223,31 @@ function UserProfile() {
navigate("/changepassword"); navigate("/changepassword");
} }
}} }}
className={`rounded shadow text-white bg-[#3598dc] ${ className={`rounded shadow text-white bg-[#3598dc] mr-4 ${
editmode ? "px-4 py-2 " : "p-2" editmode ? "px-4 py-2 " : "p-2"
}`} }`}
> >
{editmode ? "Cancel" : "Change Password"} {editmode ? "Cancel" : "Change Password"}
</button> </button>
{editmode ? (
<button
type="button"
onClick={handleSubmit}
className="rounded bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-2"
>
Save
</button>
) : (
<button
type="button"
onClick={() => {
setEditMode(true);
}}
className="rounded shadow text-white bg-[#e7505a] px-4 py-2"
>
Edit
</button>
)}
</div> </div>
</div> </div>
)} )}
+9 -29
View File
@@ -1,14 +1,12 @@
/* Full-width input fields */ /* Full-width input fields */
.inputt { .inputt {
width: 100%; width: 100%;
padding: 8px; padding: 15px;
margin-bottom: 10px; margin: 5px 0 22px 0;
/* margin: 5px 0 14px 0; */
display: inline-block; display: inline-block;
border: none; border: none;
background: #f1f1f1; background: #f1f1f1;
color: black; color: black;
font-size: 12px;
} }
/* Add a background color when the inputs get focus */ /* Add a background color when the inputs get focus */
@@ -20,12 +18,11 @@
.confirmInputt { .confirmInputt {
width: 100%; width: 100%;
padding: 8px; padding: 15px;
/* margin: 5px 0 14px 0; */ margin: 5px 0 1px 0;
display: inline-block; display: inline-block;
background: #f1f1f1; background: #f1f1f1;
color: black; color: black;
font-size: 12px;
} }
.inputt::placeholder, .inputt::placeholder,
@@ -45,10 +42,11 @@
.signupbtn { .signupbtn {
background-color: #15b4e9; background-color: #15b4e9;
color: white; color: white;
padding: 12px 12px; padding: 14px 20px;
margin: 8px 0; margin: 8px 0;
border: none; border: none;
cursor: pointer; cursor: pointer;
width: 100%;
opacity: 0.9; opacity: 0.9;
float: left; float: left;
width: 50%; width: 50%;
@@ -89,7 +87,7 @@
margin: 5% auto 15% auto; margin: 5% auto 15% auto;
/* 5% from the top, 15% from the bottom and centered */ /* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888; border: 1px solid #888;
width: 50%; width: 80%;
/* Could be more or less, depending on screen size */ /* Could be more or less, depending on screen size */
} }
@@ -113,26 +111,8 @@
} }
/* Change styles for cancel button and signup button on extra small screens */ /* Change styles for cancel button and signup button on extra small screens */
@media screen and (max-width: 768px) { @media screen and (max-width: 300px) {
/* 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 { .signupbtn {
width: 100%; width: 100%;
font-size: 16px;
} }
}
/* Style the horizontal ruler */
.hrt {
border: 1px solid #f1f1f1;
margin-bottom: 16px;
}
}
-36
View File
@@ -1,36 +0,0 @@
.alertBox {
z-index: 1;
position: absolute;
top: 10%;
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;
}
}
-8
View File
@@ -13,10 +13,6 @@ import sendMailOTPv1 from './parsefunction/SendMailOTPv1.js';
import SendMailv1 from './parsefunction/SendMailv1.js'; import SendMailv1 from './parsefunction/SendMailv1.js';
import AuthLoginAsMail from './parsefunction/AuthLoginAsMail.js'; import AuthLoginAsMail from './parsefunction/AuthLoginAsMail.js';
import getUserId from './parsefunction/getUserId.js'; import getUserId from './parsefunction/getUserId.js';
import getUserDetails from './parsefunction/getUserDetails.js';
import getDocument from './parsefunction/getDocument.js';
import getDrive from './parsefunction/getDrive.js';
import getReport from './parsefunction/getReport.js';
Parse.Cloud.define('AddUserToRole', addUserToGroups); Parse.Cloud.define('AddUserToRole', addUserToGroups);
Parse.Cloud.define('UserGroups', getUserGroups); Parse.Cloud.define('UserGroups', getUserGroups);
@@ -33,7 +29,3 @@ Parse.Cloud.define('SendOTPMailV1', sendMailOTPv1);
Parse.Cloud.define('sendmail', SendMailv1); Parse.Cloud.define('sendmail', SendMailv1);
Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail); Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail);
Parse.Cloud.define('getUserId', getUserId); Parse.Cloud.define('getUserId', getUserId);
Parse.Cloud.define('getUserDetails', getUserDetails);
Parse.Cloud.define('getDocument', getDocument);
Parse.Cloud.define('getDrive', getDrive)
Parse.Cloud.define('getReport', getReport)
@@ -16,7 +16,6 @@ async function ContactbookAftersave(request) {
acl.setWriteAccess(object.get('UserId'), true); acl.setWriteAccess(object.get('UserId'), true);
object.setACL(acl); object.setACL(acl);
object.set('IsDeleted', false)
// Continue saving the object // Continue saving the object
return object.save(null, { useMasterKey: true }); return object.save(null, { useMasterKey: true });
} }
@@ -5,7 +5,7 @@ async function SendMailv1(request) {
const recipient = request.params.email; const recipient = request.params.email;
const otp = request.params.otp; const otp = request.params.otp;
const res = await Parse.Cloud.sendEmail({ const res = await Parse.Cloud.sendEmail({
from: 'Test user' + ' <' + process.env.SMTP_ENABLE ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER + '>', from: 'Test user' + ' <' + process.env.MAILGUN_SENDER + '>',
recipient: recipient, recipient: recipient,
subject: 'Your OpenSign™ OTP', subject: 'Your OpenSign™ OTP',
text: 'This email is a test.', text: 'This email is a test.',
@@ -46,20 +46,15 @@ export default async function ZohoDetails(request) {
(userData.data.data.subscription.customer && (userData.data.data.subscription.customer &&
userData.data.data.subscription.customer.company_name) || userData.data.data.subscription.customer.company_name) ||
''; '';
const jobTitle =
(userData.data.data.subscription.customer &&
userData.data.data.subscription.customer.cd_job_title) ||
'';
const resData = { const resData = {
phone: userData.data.data.subscription.contactpersons[0].mobile, phone: userData.data.data.subscription.contactpersons[0].mobile,
name: first_name + ' ' + last_name, name: first_name + ' ' + last_name,
email: userData.data.data.subscription.contactpersons[0].email, email: userData.data.data.subscription.contactpersons[0].email,
nextBillingDate: userData.data.data.subscription.next_billing_at, nextBillingDate: userData.data.expiring_time,
company: company_name, company: company_name,
plan: userData.data.data.subscription.plan, plan: userData.data.data.subscription.plan,
customer_id: userData.data.data.subscription.customer_id, customer_id: userData.data.data.subscription.customer_id,
subscription_id: userData.data.data.subscription.subscription_id, subscription_id: userData.data.data.subscription.subscription_id,
jobTitle: jobTitle,
}; };
return resData; return resData;
} }
@@ -1,50 +0,0 @@
import axios from 'axios';
export default async function getDocument(request) {
const serverUrl = process.env.SERVER_URL;
const docId = request.params.docId;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': process.env.APP_ID,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (docId && userId) {
try {
const query = new Parse.Query('contracts_Document');
query.equalTo('objectId', docId);
query.include('ExtUserPtr');
query.include('CreatedBy');
query.include('Signers');
query.include('AuditTrail.UserPtr');
query.include('Placeholders');
const res = await query.first({ useMasterKey: true });
if (res) {
const acl = res.getACL();
if (acl && acl.getReadAccess(userId)) {
return res;
} else {
return { error: "You don't have access of this document!" };
}
} else {
return { error: "You don't have access of this document!" };
}
} catch (err) {
console.log('err', err);
return err;
}
} else {
return { error: 'Please pass required parameters!' };
}
} catch (err) {
console.log('err');
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {
return { error: "You don't have access of this document!" };
}
}
}
@@ -1,51 +0,0 @@
import axios from 'axios';
export default async function getDrive(request) {
const serverUrl = process.env.SERVER_URL;
const appId = process.env.APP_ID;
const classUrl = serverUrl + '/classes/contracts_Document';
const docId = request.params.docId;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': appId,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (userId) {
let url;
if (docId) {
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers,Folder`;
} else {
url = `${classUrl}?where={"Folder":{"$exists":false},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers`;
}
try {
const res = await axios.get(url, {
headers: {
'X-Parse-Application-Id': appId,
'X-Parse-Master-key': process.env.MASTER_KEY,
},
});
// console.log('res.data.results ', res.data.results);
if (res.data && res.data.results) {
return res.data.results;
} else {
return [];
}
} catch (err) {
console.log('err', err);
return { error: "You don't have access to drive" };
}
} else {
return { error: 'Please provide required parameter!' };
}
} catch (err) {
console.log('err', err);
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {
return { error: "You don't have access!" };
}
}
}
@@ -1,52 +0,0 @@
import reportJson from './reportsJson.js';
import axios from 'axios';
export default async function getReport(request) {
const reportId = request.params.reportId;
const limit = request.params.limit;
const skip = request.params.skip;
const serverUrl = process.env.SERVER_URL;
const appId = process.env.APP_ID;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': appId,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (userId) {
const json = reportId && reportJson(reportId, userId);
const clsName = reportId === '5KhaPr482K' ? 'contracts_Contactbook' : 'contracts_Document';
if (json) {
const { params, keys } = json;
const orderBy = '-updatedAt';
const strParams = JSON.stringify(params);
const strKeys = keys.join();
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': appId,
'X-Parse-Master-Key': process.env.MASTER_KEY,
};
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr`;
const res = await axios.get(url, { headers: headers });
if (res.data && res.data.results) {
return res.data.results;
} else {
return [];
}
} else {
return { error: 'Report is not available!' };
}
}
} catch (err) {
console.log('err', err);
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {
return { error: "You don't have access!" };
}
}
}
@@ -1,14 +0,0 @@
async function getUserDetails(request) {
try {
const userQuery = new Parse.Query('contracts_Users');
userQuery.equalTo('Email', request.params.email);
userQuery.include('TenantId');
userQuery.include('UserId')
const res = await userQuery.first({ useMasterKey: true });
return res;
} catch (err) {
console.log('Err ', err);
return err;
}
}
export default getUserDetails;
+4 -4
View File
@@ -79,7 +79,7 @@ async function sendCompletedMail(e) {
url: a, url: a,
from: 'OpenSign™', from: 'OpenSign™',
recipient: e.receiver, recipient: e.receiver,
subject: `Document ${s} has been signed by all parties`, subject: `Document ${s} has beeen signed by all parties`,
pdfName: s, pdfName: s,
html: html:
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document sign successfully</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document" + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document sign successfully</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document" +
@@ -105,7 +105,7 @@ async function PDF(s, r) {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID, 'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY, 'X-Parse-Session-Token': s.headers.sessiontoken,
}, },
}), }),
d = await axios.get(serverUrl + '/users/me', { d = await axios.get(serverUrl + '/users/me', {
@@ -132,7 +132,7 @@ async function PDF(s, r) {
: ((a = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, { : ((a = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, {
headers: { headers: {
'X-Parse-Application-Id': APPID, 'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY, 'X-Parse-Session-Token': s.headers.sessiontoken,
}, },
})), })),
'contracts_Users') 'contracts_Users')
@@ -142,7 +142,7 @@ async function PDF(s, r) {
(c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, { (c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, {
headers: { headers: {
'X-Parse-Application-Id': APPID, 'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY, 'X-Parse-Session-Token': s.headers.sessiontoken,
}, },
})).data && 0 < c.data.results.length })).data && 0 < c.data.results.length
? ((a = c), 'contracts_Users') ? ((a = c), 'contracts_Users')
@@ -1,28 +1,28 @@
import{DEFAULT_BYTE_RANGE_PLACEHOLDER,DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import PNG from"png-js";import zlib from"zlib";const specialCharacters=["á","Á","é","É","í","Í","ó","Ó","ö","Ö","ő","Ő","ú","Ú","ű","Ű"],MARKERS=[65472,65473,65474,65475,65477,65478,65479,65480,65481,65482,65483,65484,65485,65486,65487],COLOR_SPACE_MAP={1:"DeviceGray",3:"DeviceRGB",4:"DeviceCMYK"};function getImage(e,t){let n;if(255===e[0]&&216===e[1])n=getJpgImage(t,e);else{if(137!==e[0]||"PNG"!==e.toString("ascii",1,4))throw new Error("Unknown image format.");n=getPngImage(t,e)}return n}function getAnnotationApparance(e,t,n){return e.ref({CropBox:[0,10,200,60],Type:"XObject",FormType:1,BBox:[0,10,200,60],Resources:`<</XObject << import{DEFAULT_BYTE_RANGE_PLACEHOLDER,DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import PNG from"png-js";import zlib from"zlib";import fs from"node:fs";const specialCharacters=["á","Á","é","É","í","Í","ó","Ó","ö","Ö","ő","Ő","ú","Ú","ű","Ű"],MARKERS=[65472,65473,65474,65475,65477,65478,65479,65480,65481,65482,65483,65484,65485,65486,65487],COLOR_SPACE_MAP={1:"DeviceGray",3:"DeviceRGB",4:"DeviceCMYK"};function getImage(e,t){let n;if(255===e[0]&&216===e[1])n=getJpgImage(t,e);else{if(137!==e[0]||"PNG"!==e.toString("ascii",1,4))throw new Error("Unknown image format.");n=getPngImage(t,e)}return n}function getAnnotationApparance(e,t,n){return e.ref({CropBox:[0,0,197,70],Type:"XObject",FormType:1,BBox:[0,0,197,70],Resources:`<</XObject <<
/Img${t.index} ${t.index} 0 R /Img${t.index} ${t.index} 0 R
>> >>
/Font << /Font <<
/f1 ${n.index} 0 R /f1 ${n.index} 0 R
>> >>
>>`,MediaBox:[0,10,200,60],Subtype:"Form"},null,getStream(t.index))}const getStream=e=>getConvertedText(` >>`,MediaBox:[0,0,197,70],Subtype:"Form"},null,getStream(t.index))}const getStream=e=>getConvertedText(`
1.0 1.0 1.0 rg 1.0 1.0 1.0 rg
0.0 0.0 0.0 RG 0.0 0.0 0.0 RG
q q
q q
200 0 0 50 0 10 cm 200 0 0 50 0 10 cm
/Img${e} Do /Img${e} Do
Q Q
0 0 0 rg 0 0 0 rg
BT BT
0 Tr 0 Tr
/f1 10.0 Tf /f1 10.0 Tf
1.4 0 0 1 20 45.97412 Tm 1.4 0 0 1 20 45.97412 Tm
ET ET
BT BT
0 Tr 0 Tr
/f1 10.0 Tf /f1 10.0 Tf
1.4 0 0 1 20 33.56006 Tm 1.4 0 0 1 20 33.56006 Tm
ET ET
Q`),getFont=(e,t)=>e.ref({Type:"Font",BaseFont:t,Encoding:"WinAnsiEncoding",Subtype:"Type1"}),getJpgImage=(e,t)=>{if(65496!==t.readUInt16BE(0))throw"SOI not found in JPEG";let n=2,a;for(;n<t.length&&(a=t.readUInt16BE(n),n+=2,!MARKERS.includes(a));)n+=t.readUInt16BE(n);if(!MARKERS.includes(a))throw"Invalid JPEG.";n+=2;var r=t[n++],o=t.readUInt16BE(n),i=(n+=2,t.readUInt16BE(n)),l=(n+=2,t[n++]),l=COLOR_SPACE_MAP[l],r={Type:"XObject",Subtype:"Image",BitsPerComponent:r,Width:i,Height:o,ColorSpace:l,Filter:"DCTDecode"},i=("DeviceCMYK"===l&&(r.Decode=[1,0,1,0,1,0,1,0]),e.ref(r,null,t));return i},getPngImage=(e,t)=>{var t=new PNG(t),n=t.hasAlphaChannel,a={Type:"XObject",Subtype:"Image",BitsPerComponent:n?8:t.bits,Width:t.width,Height:t.height,Filter:"FlateDecode"};if(n||(r=e.ref({Predictor:15,Colors:t.colors,BitsPerComponent:t.bits,Columns:t.width}),a.DecodeParms=r),0===t.palette.length?a.ColorSpace=t.colorSpace:(r=e.ref({stream:new Buffer(t.palette)}),a.ColorSpace=["Indexed","DeviceRGB",t.palette.length/3-1,r]),null!=t.transparency.grayscale){var r=t.transparency.grayscale;a.Mask=[r,r]}else if(t.transparency.rgb){var o,r=t.transparency["rgb"],i=[];for(o of r)i.push(o,o);a.Mask=i}else t.transparency.indexed?loadIndexedAlphaChannel(t):n&&(splitAlphaChannel(t),r=getSmask(e,t),a.Mask=r);return e.ref(a,null,t.imgData)},loadIndexedAlphaChannel=e=>{const o=e.transparency.indexed;return e.decodePixels(n=>{var a=new Buffer(e.width*e.height);let r=0;for(let e=0,t=n.length;e<t;e++)a[r++]=o[n[e]];e.alphaChannel=zlib.deflateSync(a)})},splitAlphaChannel=d=>{d.decodePixels(t=>{let e,n;var a=d.colors,r=d.width*d.height,o=new Buffer(r*a),i=new Buffer(r);let l=n=e=0;for(var c=t.length,g=16===d.bits?1:0;l<c;){for(let e=0;e<a;e++)o[n++]=t[l++],l+=g;i[e++]=t[l++],l+=g}d.imgData=zlib.deflateSync(o),d.alphaChannel=zlib.deflateSync(i)})},getSmask=(e,t)=>{let n;return console.log("image.hasAlphaChannel ",t.hasAlphaChannel),t.hasAlphaChannel&&(console.log("image.alphaChannel ",t.alphaChannel),n=e.ref({Type:"XObject",Subtype:"Image",Height:t.height,Width:t.width,BitsPerComponent:8,Filter:"FlateDecode",ColorSpace:"DeviceGray",Decode:[0,1],stream:t.alphaChannel})),n},getConvertedText=e=>e.split("").map(e=>specialCharacters.includes(e)?getOctalCodeFromCharacter(e):e).join(""),getOctalCodeFromCharacter=e=>"\\"+e.charCodeAt(0).toString(8),pdfkitAddPlaceholder=({pdf:e,pdfBuffer:a,reason:r,contactInfo:t="emailfromp1289@gmail.com",name:n="Name from p12",location:o="Location from p12",signatureLength:i=DEFAULT_SIGNATURE_LENGTH,byteRangePlaceholder:l=DEFAULT_BYTE_RANGE_PLACEHOLDER,subFilter:c=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:g})=>{var d=getFont(e,"Helvetica"),s=getFont(e,"ZapfDingbats"),p=getFont(e,"Helvetica"),f=g.Base64,f=getAnnotationApparance(e,getImage(Buffer.from(f,"base64"),e),p,g),p=e.ref({Type:"Sig",Filter:"Adobe.PPKLite",SubFilter:c,ByteRange:[0,l,l,l],Contents:Buffer.from(String.fromCharCode(0).repeat(i)),Reason:new String(r),M:new Date,ContactInfo:new String(t),Name:new String(n),Location:new String(o)}),h=a.lastIndexOf("/Type /AcroForm"),c=-1!==h;let m=[],C;if(c){let e=h;var S=h-10;let t="",n=11;for(n;n<22;n+=1){var A=a.slice(h-n,S).toString();if("\n"===A[0])break;t=A,e=h-n}l=a.slice(e),i=l.slice(0,l.indexOf("endobj")).toString(),r=(C=parseInt(t),i.slice(i.indexOf("/Fields [")+9,i.indexOf("]")));m=r.split(" ").filter((e,t)=>t%3==0).map(e=>new PDFKitReferenceMock(e))}t=g.Left,n=g.Bottom,o=t+g.Width,l=n+g.Height,i=e.ref({Type:"Annot",Subtype:"Widget",FT:"Sig",Rect:[t,n,o,l],V:p,T:new String("Signature"+(m.length+1)),F:4,P:e.page.dictionary,AP:`<</N ${f.index} 0 R>>`,DA:new String("/Helvetica 0 Tf 0 g")});e.page.dictionary.data.Annots=[i];let T;return T=c?e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i],DR:`<</Font Q`),getFont=(e,t)=>e.ref({Type:"Font",BaseFont:t,Encoding:"WinAnsiEncoding",Subtype:"Type1"}),getJpgImage=(e,t)=>{if(65496!==t.readUInt16BE(0))throw"SOI not found in JPEG";let n=2,a;for(;n<t.length&&(a=t.readUInt16BE(n),n+=2,!MARKERS.includes(a));)n+=t.readUInt16BE(n);if(!MARKERS.includes(a))throw"Invalid JPEG.";n+=2;var r=t[n++],o=t.readUInt16BE(n),i=(n+=2,t.readUInt16BE(n)),l=(n+=2,t[n++]),l=COLOR_SPACE_MAP[l],r={Type:"XObject",Subtype:"Image",BitsPerComponent:r,Width:i,Height:o,ColorSpace:l,Filter:"DCTDecode"},i=("DeviceCMYK"===l&&(r.Decode=[1,0,1,0,1,0,1,0]),e.ref(r,null,t));return i},getPngImage=(e,t)=>{var t=new PNG(t),n=t.hasAlphaChannel,a={Type:"XObject",Subtype:"Image",BitsPerComponent:n?8:t.bits,Width:t.width,Height:t.height,Filter:"FlateDecode"};if(n||(r=e.ref({Predictor:15,Colors:t.colors,BitsPerComponent:t.bits,Columns:t.width}),a.DecodeParms=r),0===t.palette.length?a.ColorSpace=t.colorSpace:(r=e.ref({stream:new Buffer(t.palette)}),a.ColorSpace=["Indexed","DeviceRGB",t.palette.length/3-1,r]),null!=t.transparency.grayscale){var r=t.transparency.grayscale;a.Mask=[r,r]}else if(t.transparency.rgb){var o,r=t.transparency["rgb"],i=[];for(o of r)i.push(o,o);a.Mask=i}else t.transparency.indexed?loadIndexedAlphaChannel(t):n&&(splitAlphaChannel(t),r=getSmask(e,t),a.Mask=r);return e.ref(a,null,t.imgData)},loadIndexedAlphaChannel=e=>{const o=e.transparency.indexed;return e.decodePixels(n=>{var a=new Buffer(e.width*e.height);let r=0;for(let e=0,t=n.length;e<t;e++)a[r++]=o[n[e]];e.alphaChannel=zlib.deflateSync(a)})},splitAlphaChannel=d=>{d.decodePixels(t=>{let e,n;var a=d.colors,r=d.width*d.height,o=new Buffer(r*a),i=new Buffer(r);let l=n=e=0;for(var g=t.length,c=16===d.bits?1:0;l<g;){for(let e=0;e<a;e++)o[n++]=t[l++],l+=c;i[e++]=t[l++],l+=c}d.imgData=zlib.deflateSync(o),d.alphaChannel=zlib.deflateSync(i)})},getSmask=(e,t)=>{let n;return console.log("image.hasAlphaChannel ",t.hasAlphaChannel),t.hasAlphaChannel&&(console.log("image.alphaChannel ",t.alphaChannel),n=e.ref({Type:"XObject",Subtype:"Image",Height:t.height,Width:t.width,BitsPerComponent:8,Filter:"FlateDecode",ColorSpace:"DeviceGray",Decode:[0,1],stream:t.alphaChannel})),n},getConvertedText=e=>e.split("").map(e=>specialCharacters.includes(e)?getOctalCodeFromCharacter(e):e).join(""),getOctalCodeFromCharacter=e=>"\\"+e.charCodeAt(0).toString(8),pdfkitAddPlaceholder=({pdf:e,pdfBuffer:a,reason:r,contactInfo:t="emailfromp1289@gmail.com",name:n="Name from p12",location:o="Location from p12",signatureLength:i=DEFAULT_SIGNATURE_LENGTH,byteRangePlaceholder:l=DEFAULT_BYTE_RANGE_PLACEHOLDER,subFilter:g=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:c})=>{var d=getFont(e,"Helvetica"),s=getFont(e,"ZapfDingbats"),f=getFont(e,"Helvetica"),p=c.Base64,p=getAnnotationApparance(e,getImage(Buffer.from(p,"base64"),e),f),f=e.ref({Type:"Sig",Filter:"Adobe.PPKLite",SubFilter:g,ByteRange:[0,l,l,l],Contents:Buffer.from(String.fromCharCode(0).repeat(i)),Reason:new String(r),M:new Date,ContactInfo:new String(t),Name:new String(n),Location:new String(o)}),h=a.lastIndexOf("/Type /AcroForm"),g=-1!==h;let m=[],C;if(g){let e=h;var S=h-10;let t="",n=11;for(n;n<22;n+=1){var A=a.slice(h-n,S).toString();if("\n"===A[0])break;t=A,e=h-n}l=a.slice(e),i=l.slice(0,l.indexOf("endobj")).toString(),r=(C=parseInt(t),i.slice(i.indexOf("/Fields [")+9,i.indexOf("]")));m=r.split(" ").filter((e,t)=>t%3==0).map(e=>new PDFKitReferenceMock(e))}m.length;t=c.Left,n=c.Bottom,o=t+c.Width,l=n+c.Height,i=e.ref({Type:"Annot",Subtype:"Widget",FT:"Sig",Rect:[t,n,o,l],V:f,T:new String("Signature"+(m.length+1)),F:4,P:e.page.dictionary,AP:`<</N ${p.index} 0 R>>`,DA:new String("/Helvetica 0 Tf 0 g")});e.page.dictionary.data.Annots=[i];let T;return T=g?e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i],DR:`<</Font
<</Helvetica ${d.index} 0 R/ZapfDingbats ${s.index} 0 R>> <</Helvetica ${d.index} 0 R/ZapfDingbats ${s.index} 0 R>>
>>`},C):e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i]}),{signature:p,form:e._root.data.AcroForm=T,widget:i}};export default pdfkitAddPlaceholder; >>`},C):e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i]}),{signature:f,form:e._root.data.AcroForm=T,widget:i}};export default pdfkitAddPlaceholder;
@@ -1,218 +0,0 @@
export default function reportJson(id, userId) {
const currentUserId = userId;
switch (id) {
// draft documents report
case 'ByHuevtCFY':
return {
reportName: 'Draft Documents',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// Need your sign report
case '4Hhwbp482K':
return {
reportName: 'Need your sign',
params: {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
Placeholders: { $ne: null },
},
keys: [
'Name',
'Note',
'Folder.Name',
'URL',
'ExtUserPtr.Name',
'Signers.Name',
'Signers.UserId',
'AuditTrail',
],
};
// In progess report
case '1MwEuxLEkF':
return {
reportName: 'In-progress documents',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// completed documents report
case 'kQUoW4hUXz':
return {
reportName: 'Completed Documents',
params: {
Type: null,
IsCompleted: true,
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
IsDeclined: { $ne: true },
},
keys: [
'Name',
'Note',
'Folder.Name',
'URL',
'ExtUserPtr.Name',
'Signers.Name',
'TimeToCompleteDays',
],
};
// declined documents report
case 'UPr2Fm5WY3':
return {
reportName: 'Declined Documents',
params: {
Type: null,
IsDeclined: true,
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// Expired Documents report
case 'zNqBHXHsYH':
return {
reportName: 'Expired Documents',
params: {
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
Type: { $ne: 'Folder' },
$and: [
{
$or: [
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
{ Placeholders: { $ne: null } },
],
},
{
ExpiryDate: {
$lt: { __type: 'Date', iso: new Date().toISOString() },
},
},
],
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// Recently sent for signatures report show on dashboard
case 'd9k3UfYHBc':
return {
reportName: 'Recently sent for signatures',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// Recent signature requests report show on dashboard
case '5Go51Q7T8r':
return {
reportName: 'Recent signature requests',
params: {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
Placeholders: { $ne: null },
},
keys: [
'Name',
'Note',
'Folder.Name',
'URL',
'ExtUserPtr.Name',
'Signers.Name',
'Signers.UserId',
'AuditTrail',
],
};
// Drafts report show on dashboard
case 'kC5mfynCi4':
return {
reportName: 'Drafts',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// contact book report
case '5KhaPr482K':
return {
reportName: 'Contactbook',
params: {
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
IsDeleted: { $ne: true },
},
keys: ['Name', 'Email', 'Phone'],
};
default:
return null;
}
}
@@ -1,30 +1,14 @@
import fs from 'node:fs'; import fs from 'node:fs';
import https from 'https';
import formData from 'form-data'; import formData from 'form-data';
import Mailgun from 'mailgun.js'; import Mailgun from 'mailgun.js';
import { createTransport } from 'nodemailer'; import https from 'https';
let transporterSMTP; const mailgun = new Mailgun(formData);
let mailgunClient; const mailgunClient = mailgun.client({
let mailgunDomain; username: 'api',
if (process.env.SMTP_ENABLE) { key: process.env.MAILGUN_API_KEY,
transporterSMTP = createTransport({ });
host: process.env.SMTP_HOST, const mailgunDomain = process.env.MAILGUN_DOMAIN;
port: process.env.SMTP_PORT || 465,
secure: process.env.SMTP_SECURE || true,
auth: {
user: process.env.SMTP_USER_EMAIL,
pass: process.env.SMTP_PASS,
},
});
} else {
const mailgun = new Mailgun(formData);
mailgunClient = mailgun.client({
username: 'api',
key: process.env.MAILGUN_API_KEY,
});
mailgunDomain = process.env.MAILGUN_DOMAIN;
}
async function sendmail(req) { async function sendmail(req) {
try { try {
@@ -54,67 +38,22 @@ async function sendmail(req) {
const pdfName = req.params.pdfName && `${req.params.pdfName}.pdf`; const pdfName = req.params.pdfName && `${req.params.pdfName}.pdf`;
const file = { const file = {
filename: pdfName || 'exported.pdf', filename: pdfName || 'exported.pdf',
content: process.env.SMTP_ENABLE ? PdfBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'), data: PdfBuffer, //fs.readFileSync('./exports/exported_file_1223.pdf'),
data: process.env.SMTP_ENABLE ? undefined : PdfBuffer,
}; };
// const html = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body style='text-align: center;'> <p style='font-weight: bolder; font-size: large;'>Hello!</p> <p>This is a html checking mail</p><p><button style='background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue'>Verify email</button></p></body></html>" // const html = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body style='text-align: center;'> <p style='font-weight: bolder; font-size: large;'>Hello!</p> <p>This is a html checking mail</p><p><button style='background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue'>Verify email</button></p></body></html>"
const from = req.params.from || ''; const from = req.params.from || '';
const mailsender = process.env.SMTP_ENABLE
? process.env.SMTP_USER_EMAIL
: process.env.MAILGUN_SENDER;
const messageParams = { const messageParams = {
from: from + ' <' + mailsender + '>', from: from + ' <' + process.env.MAILGUN_SENDER + '>',
to: req.params.recipient, to: req.params.recipient,
subject: req.params.subject, subject: req.params.subject,
text: req.params.text || 'mail', text: req.params.text || 'mail',
html: req.params.html || '', html: req.params.html || '',
attachments: process.env.SMTP_ENABLE ? [file] : undefined, attachment: file,
attachment: process.env.SMTP_ENABLE ? undefined : file,
}; };
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
if (!res.err) {
return {
status: 'success',
};
}
} else {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
if (res.status === 200) {
return {
status: 'success',
};
}
}
}
} else {
const from = req.params.from || '';
const mailsender = process.env.SMTP_ENABLE
? process.env.SMTP_USER_EMAIL
: process.env.MAILGUN_SENDER;
const messageParams = {
from: from + ' <' + mailsender + '>',
to: req.params.recipient,
subject: req.params.subject,
text: req.params.text || 'mail',
html: req.params.html || '',
};
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
if (!res.err) {
return {
status: 'success',
};
}
} else {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams); const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res); console.log('Res ', res);
if (res.status === 200) { if (res.status === 200) {
@@ -123,6 +62,23 @@ async function sendmail(req) {
}; };
} }
} }
} else {
const from = req.params.from || '';
const messageParams = {
from: from + ' <' + process.env.MAILGUN_SENDER + '>',
to: req.params.recipient,
subject: req.params.subject,
text: req.params.text || 'mail',
html: req.params.html || '',
};
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
if (res.status === 200) {
return {
status: 'success',
};
}
} }
} catch (err) { } catch (err) {
console.log('err ', err); console.log('err ', err);
@@ -1,47 +0,0 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
// TODO: set className here
const className = 'contracts_Users';
const schema = new Parse.Schema(className);
// schema.addString('Name');
// schema.addString('Phone');
// schema.addString('JobTitle');
// schema.addString('Email');
// schema.addString('Company');
// schema.addString('UserRole');
// schema.addObject('Plan');
// schema.addString('Customer_id');
// schema.addString('Subscription_id');
// schema.addString('Next_billing_date');
// schema.addBoolean('IsContactEntry');
// schema.addBoolean('ShareWithTeam');
// schema.addPointer('TenantId', 'partners_Tenant');
// schema.addPointer('UserId', '_User');
// schema.addPointer('CreatedBy', '_User');
schema.setCLP({
get: {},
find: {},
count: {},
create: { '*': true },
update: { '*': true },
delete: {},
addField: {},
});
return schema.update();
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
// TODO: set className here
const className = 'contracts_Users';
const schema = new Parse.Schema(className);
return schema.purge().then(() => schema.delete());
};
@@ -1,556 +0,0 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
const className = 'w_menu';
const userMenu = new Parse.Query(className);
const updateUserMenu = await userMenu.get('H9vRfEYKhT');
updateUserMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive™',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
},
],
},
]);
const AdminMenu = new Parse.Query(className);
const updateAdminMenu = await AdminMenu.get('VPh91h0ZHk');
updateAdminMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive™',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
},
{
icon: 'far fa-user',
title: 'Add User',
target: '_self',
pageType: 'form',
description: '',
objectId: 'lM0xRnM3iE',
},
],
},
]);
// TODO: Set the schema here
// Example:
// schema.addString('name').addNumber('cash');
const batch = [updateUserMenu, updateAdminMenu];
return Parse.Object.saveAll(batch, { useMasterKey: true });
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
// TODO: set className here
const className = 'w_menu';
const userMenu = new Parse.Query(className);
const revertUserMenu = await userMenu.get('H9vRfEYKhT');
revertUserMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive™',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
},
],
},
]);
const adminMenu = new Parse.Query(className);
const revertAdminMenu = await adminMenu.get('VPh91h0ZHk');
revertAdminMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fas fa-file-signature',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive™',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
},
{
icon: 'far fa-user',
title: 'Add User',
target: '_self',
pageType: 'form',
description: '',
objectId: 'lM0xRnM3iE',
},
],
},
]);
// TODO: Set the schema here
// Example:
// schema.addString('name').addNumber('cash');
const batch = [revertUserMenu, revertAdminMenu];
return Parse.Object.saveAll(batch, { useMasterKey: true });
};
@@ -10,7 +10,7 @@
<br /> <br />
<p><a href="{{{link}}}" style="background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue">Verify email</a></p> <p><a href="{{{link}}}" style="background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue">Verify email</a></p>
<br /> <br />
<p><a href="https://www.opensignlabs.com">OpenSign™</a></p> <p>ExampleApp</p>
</body> </body>
</html> </html>
+31 -65
View File
@@ -17,12 +17,10 @@ import S3Adapter from 'parse-server-s3-adapter';
import FSFilesAdapter from 'parse-server-fs-adapter'; import FSFilesAdapter from 'parse-server-fs-adapter';
import AWS from 'aws-sdk'; import AWS from 'aws-sdk';
import { app as customRoute } from './cloud/customRoute/customApp.js'; import { app as customRoute } from './cloud/customRoute/customApp.js';
import { exec } from 'child_process';
import { createTransport } from 'nodemailer';
const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT); const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT);
// console.log("configuration ", configuration); // console.log("configuration ", configuration);
if (process.env.USE_LOCAL !== 'TRUE') { if (process.env.USE_LOCAL !== "TRUE") {
const s3Options = { const s3Options = {
bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket, bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket,
baseUrl: process.env.DO_BASEURL, baseUrl: process.env.DO_BASEURL,
@@ -38,31 +36,18 @@ if (process.env.USE_LOCAL !== 'TRUE') {
var fsAdapter = new S3Adapter(s3Options); var fsAdapter = new S3Adapter(s3Options);
} else { } else {
var fsAdapter = new FSFilesAdapter({ var fsAdapter = new FSFilesAdapter({
filesSubDirectory: 'files', // optional, defaults to ./files "filesSubDirectory": "files" // optional, defaults to ./files
}); });
} }
let transporterMail;
let mailgunClient; let mailgunClient;
let mailgunDomain; let mailgunDomain;
if (process.env.MAILGUN_API_KEY) {
if (process.env.SMTP_ENABLE) {
transporterMail = createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT || 465,
secure: process.env.SMTP_SECURE || true,
auth: {
user: process.env.SMTP_USER_EMAIL,
pass: process.env.SMTP_PASS,
},
});
} else if (process.env.MAILGUN_API_KEY) {
const mailgun = new Mailgun(formData); const mailgun = new Mailgun(formData);
mailgunClient = mailgun.client({ mailgunClient = mailgun.client({
username: 'api', username: 'api',
key: process.env.MAILGUN_API_KEY, key: process.env.MAILGUN_API_KEY,
}); });
mailgunDomain = process.env.MAILGUN_DOMAIN; mailgunDomain = process.env.MAILGUN_DOMAIN;
} }
@@ -74,46 +59,41 @@ export const config = {
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret! masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
masterKeyIps: ['0.0.0.0/0', '::1'], // '::1' masterKeyIps: ['0.0.0.0/0', '::1'], // '::1'
serverURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Don't forget to change to https if needed serverURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Don't forget to change to https if needed
verifyUserEmails: true, // verifyUserEmails: true,
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app', publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
// Your apps name. This will appear in the subject and body of the emails that are sent. // Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Open Sign', appName: 'Open Sign',
allowClientClassCreation: false, allowClientClassCreation: false,
emailAdapter: emailAdapter: process.env.MAILGUN_API_KEY
process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY ? {
? { module: 'parse-server-api-mail-adapter',
module: 'parse-server-api-mail-adapter', options: {
options: { // The email address from which emails are sent.
// The email address from which emails are sent. sender: process.env.MAILGUN_SENDER,
sender: process.env.SMTP_ENABLE // The email templates.
? process.env.SMTP_USER_EMAIL templates: {
: process.env.MAILGUN_SENDER, // The template used by Parse Server to send an email for password
// The email templates. // reset; this is a reserved template name.
templates: { passwordResetEmail: {
// The template used by Parse Server to send an email for password subjectPath: './files/password_reset_email_subject.txt',
// reset; this is a reserved template name. textPath: './files/password_reset_email.txt',
passwordResetEmail: { htmlPath: './files/password_reset_email.html',
subjectPath: './files/password_reset_email_subject.txt',
textPath: './files/password_reset_email.txt',
htmlPath: './files/password_reset_email.html',
},
// The template used by Parse Server to send an email for email
// address verification; this is a reserved template name.
verificationEmail: {
subjectPath: './files/verification_email_subject.txt',
textPath: './files/verification_email.txt',
htmlPath: './files/verification_email.html',
},
}, },
apiCallback: async ({ payload, locale }) => { // The template used by Parse Server to send an email for email
if (mailgunClient) { // address verification; this is a reserved template name.
const mailgunPayload = ApiPayloadConverter.mailgun(payload); verificationEmail: {
await mailgunClient.messages.create(mailgunDomain, mailgunPayload); subjectPath: './files/verification_email_subject.txt',
} else if (transporterMail) await transporterMail.sendMail(payload); textPath: './files/verification_email.txt',
htmlPath: './files/verification_email.html',
}, },
}, },
} apiCallback: async ({ payload, locale }) => {
: null, const mailgunPayload = ApiPayloadConverter.mailgun(payload);
await mailgunClient.messages.create(mailgunDomain, mailgunPayload);
},
},
}
: null,
filesAdapter: fsAdapter, filesAdapter: fsAdapter,
auth: { auth: {
google: { google: {
@@ -184,20 +164,6 @@ if (!process.env.TESTING) {
httpServer.headersTimeout = 100000; // in milliseconds httpServer.headersTimeout = 100000; // in milliseconds
httpServer.listen(port, function () { httpServer.listen(port, function () {
console.log('parse-server-example running on port ' + port + '.'); console.log('parse-server-example running on port ' + port + '.');
const migrate = `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=http://localhost:8080/app MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
exec(migrate, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Error: ${stderr}`);
return;
}
console.log(`Command output: ${stdout}`);
});
}); });
// This will enable the Live Query real-time server // This will enable the Live Query real-time server
await ParseServer.createLiveQueryServer(httpServer); await ParseServer.createLiveQueryServer(httpServer);
+11 -334
View File
@@ -18,19 +18,16 @@
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"mailgun.js": "^9.3.0", "mailgun.js": "^9.0.1",
"mongoose": "^7.2.1", "mongoose": "^7.2.1",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"multer-s3": "^2.10.0", "multer-s3": "^2.10.0",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"node-signpdf": "^1.5.1", "node-signpdf": "^1.5.1",
"nodemailer": "^6.9.7",
"openai": "^4.8.0", "openai": "^4.8.0",
"parse": "4.1.0", "parse": "4.1.0",
"parse-dbtool": "^1.2.0",
"parse-server": "6.3.1", "parse-server": "6.3.1",
"parse-server-api-mail-adapter": "^3.0.0", "parse-server-api-mail-adapter": "^3.0.0",
"parse-server-fs-adapter": "1.0.1",
"parse-server-s3-adapter": "^1.2.0", "parse-server-s3-adapter": "^1.2.0",
"pdf-lib": "^1.16.0", "pdf-lib": "^1.16.0",
"pdfkit": "^0.13.0", "pdfkit": "^0.13.0",
@@ -2148,6 +2145,7 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": { "dependencies": {
"fill-range": "^7.0.1" "fill-range": "^7.0.1"
}, },
@@ -2796,37 +2794,6 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"dependencies": {
"@babel/runtime": "^7.21.0"
},
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/date-fns/node_modules/@babel/runtime": {
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
"integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/date-fns/node_modules/regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -3933,32 +3900,6 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
}, },
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.4"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fast-json-stable-stringify": { "node_modules/fast-json-stable-stringify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4058,6 +3999,7 @@
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": { "dependencies": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
}, },
@@ -4393,6 +4335,7 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": { "engines": {
"node": "6.* || 8.* || >= 10.*" "node": "6.* || 8.* || >= 10.*"
} }
@@ -5148,6 +5091,7 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": { "engines": {
"node": ">=0.12.0" "node": ">=0.12.0"
} }
@@ -6072,9 +6016,9 @@
} }
}, },
"node_modules/mailgun.js": { "node_modules/mailgun.js": {
"version": "9.3.0", "version": "9.0.1",
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-9.3.0.tgz", "resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-9.0.1.tgz",
"integrity": "sha512-iRqCglCdi+Q5anFpeRKHiytT/i34E14p/WtTE57VSeq5bATK+zQ8UnpFgPRaqGGTJqyGjqcO9m5YDRRB4/qirw==", "integrity": "sha512-bVZ1zGh5UfQcChqIwIAil99hzoTeB3aHqAUbqmIBLMLcKfx+FF2qvhbc00WtwrFhe5dBQqQw6zPj0QBlqV4nXg==",
"dependencies": { "dependencies": {
"axios": "^1.3.3", "axios": "^1.3.3",
"base-64": "^1.0.0", "base-64": "^1.0.0",
@@ -6143,14 +6087,6 @@
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
}, },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"engines": {
"node": ">= 8"
}
},
"node_modules/methods": { "node_modules/methods": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -6159,18 +6095,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mime": { "node_modules/mime": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
@@ -6875,14 +6799,6 @@
"node-forge": "^1.2.1" "node-forge": "^1.2.1"
} }
}, },
"node_modules/nodemailer": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz",
"integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/nodemon": { "node_modules/nodemon": {
"version": "2.0.22", "version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
@@ -7412,234 +7328,6 @@
"crypto-js": "4.1.1" "crypto-js": "4.1.1"
} }
}, },
"node_modules/parse-dbtool": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/parse-dbtool/-/parse-dbtool-1.2.0.tgz",
"integrity": "sha512-APRMPdQ2jyJ7SBouPYZsCD4BjB0zIrSEgALgeYZsVSDrrtoqXhUHJHi42tF/0ocTA/nolteUMzlHT+msrqPvjQ==",
"dependencies": {
"chalk": "^4.1.1",
"date-fns": "^2.21.3",
"dotenv": "^10.0.0",
"fast-glob": "^3.2.5",
"parse": "^3.2.0",
"ts-dedent": "^2.1.1",
"yargs": "^17.0.1"
},
"bin": {
"parse-dbtool": "src/parse-dbtool.js"
}
},
"node_modules/parse-dbtool/node_modules/@babel/runtime": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/parse-dbtool/node_modules/@babel/runtime-corejs3": {
"version": "7.17.8",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz",
"integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==",
"dependencies": {
"core-js-pure": "^3.20.2",
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/parse-dbtool/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/parse-dbtool/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/parse-dbtool/node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/parse-dbtool/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/parse-dbtool/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/parse-dbtool/node_modules/dotenv": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
"engines": {
"node": ">=10"
}
},
"node_modules/parse-dbtool/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/parse-dbtool/node_modules/idb-keyval": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.0.3.tgz",
"integrity": "sha512-yh8V7CnE6EQMu9YDwQXhRxwZh4nv+8xm/HV4ZqK4IiYFJBWYGjJuykADJbSP+F/GDXUBwCSSNn/14IpGL81TuA==",
"dependencies": {
"safari-14-idb-fix": "^3.0.0"
}
},
"node_modules/parse-dbtool/node_modules/parse": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/parse/-/parse-3.5.1.tgz",
"integrity": "sha512-uxkLVNfbqgZ/pStg/jIQGh09tOUkPZorzDIqz9vSFjZ3iIZzgvNk6VBbjXjcMWsR8LyFPOR1ROR6/y9Dedn3/w==",
"dependencies": {
"@babel/runtime": "7.18.0",
"@babel/runtime-corejs3": "7.17.8",
"idb-keyval": "6.0.3",
"react-native-crypto-js": "1.0.0",
"uuid": "3.4.0",
"ws": "8.6.0",
"xmlhttprequest": "1.8.0"
},
"optionalDependencies": {
"crypto-js": "4.1.1"
}
},
"node_modules/parse-dbtool/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/parse-dbtool/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/parse-dbtool/node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/parse-dbtool/node_modules/ws": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/parse-dbtool/node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"engines": {
"node": ">=10"
}
},
"node_modules/parse-dbtool/node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/parse-dbtool/node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/parse-server": { "node_modules/parse-server": {
"version": "6.3.1", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/parse-server/-/parse-server-6.3.1.tgz", "resolved": "https://registry.npmjs.org/parse-server/-/parse-server-6.3.1.tgz",
@@ -7715,12 +7403,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/parse-server-fs-adapter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-server-fs-adapter/-/parse-server-fs-adapter-1.0.1.tgz",
"integrity": "sha512-5IRKAT2QkzHrYrBESY4E8jsV1sl+XVBTKGyUvBPgBR2QzsTTqiyU/lFZD8PAJavA+TH1BLyLTUMZbhZhswNVbQ==",
"deprecated": "use @parse/fs-files-adapter"
},
"node_modules/parse-server-s3-adapter": { "node_modules/parse-server-s3-adapter": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/parse-server-s3-adapter/-/parse-server-s3-adapter-1.2.0.tgz", "resolved": "https://registry.npmjs.org/parse-server-s3-adapter/-/parse-server-s3-adapter-1.2.0.tgz",
@@ -8199,6 +7881,7 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": { "engines": {
"node": ">=8.6" "node": ">=8.6"
}, },
@@ -8772,6 +8455,7 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -9537,6 +9221,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": { "dependencies": {
"is-number": "^7.0.0" "is-number": "^7.0.0"
}, },
@@ -9598,14 +9283,6 @@
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
}, },
"node_modules/ts-dedent": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
"integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
"engines": {
"node": ">=6.10"
}
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
+2 -4
View File
@@ -27,20 +27,18 @@
"express-sse": "^0.5.3", "express-sse": "^0.5.3",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"mailgun.js": "^9.3.0", "mailgun.js": "^9.0.1",
"mongoose": "^7.2.1", "mongoose": "^7.2.1",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"multer-s3": "^2.10.0", "multer-s3": "^2.10.0",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"node-signpdf": "^1.5.1", "node-signpdf": "^1.5.1",
"nodemailer": "^6.9.7",
"openai": "^4.8.0", "openai": "^4.8.0",
"parse": "4.1.0", "parse": "4.1.0",
"parse-dbtool": "^1.2.0",
"parse-server": "6.3.1", "parse-server": "6.3.1",
"parse-server-api-mail-adapter": "^3.0.0", "parse-server-api-mail-adapter": "^3.0.0",
"parse-server-fs-adapter": "1.0.1",
"parse-server-s3-adapter": "^1.2.0", "parse-server-s3-adapter": "^1.2.0",
"parse-server-fs-adapter": "1.0.1",
"pdf-lib": "^1.16.0", "pdf-lib": "^1.16.0",
"pdfkit": "^0.13.0", "pdfkit": "^0.13.0",
"razorpay": "^2.8.6", "razorpay": "^2.8.6",
-37
View File
@@ -1,37 +0,0 @@
// const { exec } = require('child_process');
import { exec } from 'child_process';
const migrate =
'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool migrate';
// `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=${process.env.SERVER_URL} MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
exec(migrate, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Error: ${stderr}`);
return;
}
console.log(`Command output: ${stdout}`);
});
// const seeder =
// 'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool seed';
// exec(seeder, (error, stdout, stderr) => {
// if (error) {
// console.error(`Error: ${error.message}`);
// return;
// }
// if (stderr) {
// console.error(`Error: ${stderr}`);
// return;
// }
// console.log(`Command output: ${stdout}`);
// });
@@ -40,7 +40,7 @@
"id": "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f", "id": "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f",
"queryType": "", "queryType": "",
"class": "contracts_Document", "class": "contracts_Document",
"query": "where={\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&include=Signers,AuditTrail.UserPtr", "query": "where={\"CreatedBy\":{\"__type\":\"Pointer\",\"className\":\"_User\",\"objectId\":\"#UserId.objectId#\"},\"IsCompleted\":{\"$ne\":true},\"IsDeclined\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&count=1",
"key": "count", "key": "count",
"Redirect_type": "Report", "Redirect_type": "Report",
"Redirect_id": "1MwEuxLEkF", "Redirect_id": "1MwEuxLEkF",
@@ -1,5 +1,4 @@
[ [{
{
"_id": "H9vRfEYKhT", "_id": "H9vRfEYKhT",
"_created_at": { "_created_at": {
"$date": "2023-09-04T14:04:00.669Z" "$date": "2023-09-04T14:04:00.669Z"
@@ -106,14 +105,6 @@
"pageType": "report", "pageType": "report",
"description": "", "description": "",
"objectId": "zNqBHXHsYH" "objectId": "zNqBHXHsYH"
},
{
"icon": "fa-solid fa-address-book",
"title": "Contactbook",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "5KhaPr482K"
} }
] ]
}, },
@@ -246,14 +237,6 @@
"pageType": "report", "pageType": "report",
"description": "", "description": "",
"objectId": "zNqBHXHsYH" "objectId": "zNqBHXHsYH"
},
{
"icon": "fa-solid fa-address-book",
"title": "Contactbook",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "5KhaPr482K"
} }
] ]
}, },
@@ -286,5 +269,4 @@
], ],
"menuTitle": "Admin Menu", "menuTitle": "Admin Menu",
"menuType": "Side Menu" "menuType": "Side Menu"
} }]
]
+55 -54
View File
@@ -1,54 +1,55 @@
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
3pXAXxZuvVvv9tsb4bdrBAhyb+KCIjp/gAICCAA= MEEwMTANBglghkgBZQMEAgEFAAQgPlLuG+67SxPOEPbgFuEnVgewvY6LUzFmrprx
c6yryFgECIld0S5kDk7JAgIIAA==
+19 -21
View File
@@ -1,23 +1,21 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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 Jg==
vIHQgwn4K5WMsZVLxoiUcU7cSqE/qhnP+pzBf8lRaYwd+zUznDvzpKKz6nFgeHok
s8BK7JAKkIsl
-----END CERTIFICATE----- -----END CERTIFICATE-----
+30 -30
View File
@@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN ENCRYPTED PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIJvntFBuTIWACAggA
DEK-Info: DES-EDE3-CBC,5932FA9F02938D1B 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 mFXB4iaMX0hGcgzpK4iNcg==
-----END RSA PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
Binary file not shown.
-20
View File
@@ -36,7 +36,6 @@
"react-scrollbars-custom": "^4.1.1", "react-scrollbars-custom": "^4.1.1",
"react-signature-canvas": "^1.0.6", "react-signature-canvas": "^1.0.6",
"reactour": "^1.19.1", "reactour": "^1.19.1",
"select-dom": "^9.0.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
} }
}, },
@@ -18703,20 +18702,6 @@
"resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz", "resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz",
"integrity": "sha512-HSdN78VMvFCSGCkh0oYX/tY4R3P1DW61f8+TeZZ4j2VLgfwvw0bpRSOv4PCVKisktIwbzHCfZsx+rLbbDBqIBA==" "integrity": "sha512-HSdN78VMvFCSGCkh0oYX/tY4R3P1DW61f8+TeZZ4j2VLgfwvw0bpRSOv4PCVKisktIwbzHCfZsx+rLbbDBqIBA=="
}, },
"node_modules/select-dom": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/select-dom/-/select-dom-9.0.0.tgz",
"integrity": "sha512-AD1NfASSwJQc1Sy713R1vT9CMmUSUo2tg0j1FtkRGIxllTphDrkuH2pYYvhRlGaoq3pS6tcKkKS/diEZLy+7BQ==",
"dependencies": {
"typed-query-selector": "^2.11.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/fregante"
}
},
"node_modules/select-hose": { "node_modules/select-hose": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -20218,11 +20203,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/typed-query-selector": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.11.0.tgz",
"integrity": "sha512-qBs4sfmnLlPOyo2oSdvHbIFHe2CPgU54/1UGfSNceb7LARpIEVxUaeRX0Doje6oKpuySS2stqy90R3YrynR8Kg=="
},
"node_modules/typedarray-to-buffer": { "node_modules/typedarray-to-buffer": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
@@ -32,7 +32,6 @@
"react-scrollbars-custom": "^4.1.1", "react-scrollbars-custom": "^4.1.1",
"react-signature-canvas": "^1.0.6", "react-signature-canvas": "^1.0.6",
"reactour": "^1.19.1", "reactour": "^1.19.1",
"select-dom": "^9.0.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
@@ -1,15 +1,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import "./certificate.css"; import "./certificate.css";
import opensignLogo from "../../assests/open-sign-logo.png";
import { import { Page, Text, View, Document, StyleSheet } from "@react-pdf/renderer";
Page,
Text,
View,
Document,
StyleSheet,
Image
} from "@react-pdf/renderer";
function Certificate({ pdfData }) { function Certificate({ pdfData }) {
const [isMultiSigners, setIsMultiSigners] = useState(); const [isMultiSigners, setIsMultiSigners] = useState();
@@ -57,34 +49,70 @@ function Certificate({ pdfData }) {
fontSize: "11px", fontSize: "11px",
marginBottom: "10px", marginBottom: "10px",
color: "gray" color: "gray"
},
image: {
width: "71px",
height: "17px"
} }
}); });
const generatedDate = () => { const generatedDate = () => {
const newDate = new Date(); const newDate = new Date();
const utcTime = newDate.toUTCString(); const localExpireDate = newDate.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric"
});
var currentOffset = newDate.getTimezoneOffset();
var ISTOffset = 330; // IST offset UTC +5:30
var ISTTime = new Date(
newDate.getTime() + (ISTOffset + currentOffset) * 60000
);
// ISTTime now represents the time in IST coordinates
var hoursIST = ISTTime.getHours();
var minutesIST = ISTTime.getMinutes();
return ( return (
<Text <Text
style={{ style={{
textAlign: "right",
color: "gray", color: "gray",
fontSize: "10px" fontSize: "10px",
marginBottom: "30px"
}} }}
> >
Generated On {utcTime} Generated On {localExpireDate} {hoursIST}:{minutesIST} IST
</Text> </Text>
); );
}; };
const changeCompletedDate = () => { const changeCompletedDate = () => {
const completedOn = pdfData[0].updatedAt; const completedOn = pdfData[0].updatedAt;
const newDate = new Date(completedOn); const newDate = new Date(completedOn);
const utcTime = newDate.toUTCString(); const localExpireDate = newDate.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric"
});
return <Text style={styles.textStyle2}>{utcTime}</Text>; var currentOffset = newDate.getTimezoneOffset();
var ISTOffset = 330; // IST offset UTC +5:30
var ISTTime = new Date(
newDate.getTime() + (ISTOffset + currentOffset) * 60000
);
// ISTTime now represents the time in IST coordinates
var hoursIST = ISTTime.getHours();
var minutesIST = ISTTime.getMinutes();
return (
<Text style={styles.textStyle2}>
{localExpireDate} {hoursIST}:{minutesIST} IST
</Text>
);
}; };
const signerName = (data) => { const signerName = (data) => {
@@ -115,19 +143,7 @@ function Certificate({ pdfData }) {
{/** Page defines a single page of content. */} {/** Page defines a single page of content. */}
<Page size="A4" style={styles.page}> <Page size="A4" style={styles.page}>
<View style={styles.section1}> <View style={styles.section1}>
<View {generatedDate()}
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "30px"
}}
>
<Image src={opensignLogo} style={styles.image} />
{generatedDate()}
</View>
<View style={{ justifyContent: "center" }}> <View style={{ justifyContent: "center" }}>
<Text <Text
style={{ style={{
@@ -166,9 +182,7 @@ function Certificate({ pdfData }) {
</Text> </Text>
<Text style={styles.textStyle}> <Text style={styles.textStyle}>
Organization : &nbsp; Organization : &nbsp;
<Text style={styles.textStyle2}> <Text style={styles.textStyle2}>__</Text>
{pdfData[0].ExtUserPtr.Company}
</Text>
</Text> </Text>
<Text style={styles.textStyle}> <Text style={styles.textStyle}>
Completed on : &nbsp;{changeCompletedDate()} Completed on : &nbsp;{changeCompletedDate()}
@@ -246,12 +260,6 @@ function Certificate({ pdfData }) {
{pdfData[0].ExtUserPtr.Name} {pdfData[0].ExtUserPtr.Name}
</Text> </Text>
</Text> </Text>
<Text style={styles.textStyle}>
Email : &nbsp;
<Text style={styles.textStyle2}>
{pdfData[0].ExtUserPtr.Email}
</Text>
</Text>
<Text style={styles.textStyle}> <Text style={styles.textStyle}>
Accessed from : &nbsp; Accessed from : &nbsp;
<Text style={styles.textStyle2}> <Text style={styles.textStyle2}>
@@ -1,47 +1,61 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Loader from "./component/loader"; import Loader from "./component/loader";
import { contractDocument, getHostUrl } from "../utils/Utils"; import { getHostUrl } from "../utils/Utils";
function DraftDocument() { function DraftDocument() {
const navigate = useNavigate(); const navigate = useNavigate();
const [pdfDetails, setPdfDetails] = useState([]); const [pdfDetails, setPdfDetails] = useState([]);
const [isLoading, setIsLoading] = useState({ const [isLoading, setIsLoading] = useState({
isLoad: true, isLoad: true,
message: "This might take some time" message: "This might take some time",
}); });
const rowLevel = const rowLevel =
localStorage.getItem("rowlevel") && localStorage.getItem("rowlevel") &&
JSON.parse(localStorage.getItem("rowlevel")); JSON.parse(localStorage.getItem("rowlevel"));
const docId = const signObjId =
rowLevel && rowLevel?.id rowLevel && rowLevel?.id
? rowLevel.id ? rowLevel.id
: rowLevel?.objectId && rowLevel.objectId; : rowLevel?.objectId && rowLevel.objectId;
useEffect(() => { useEffect(() => {
if (docId) { if (signObjId) {
getDocumentDetails(); getDocumentDetails();
} }
}, []); }, []);
//get document details //get document details
const getDocumentDetails = async () => { const getDocumentDetails = async () => {
//getting document details await axios
const documentData = await contractDocument(docId); .get(
if (documentData && documentData.length > 0) { `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
setPdfDetails(documentData); "_appName"
const loadObj = { )}_Document?where={"objectId":"${signObjId}"}&include=ExtUserPtr,Signers`,
isLoad: false {
}; headers: {
setIsLoading(loadObj); "Content-Type": "application/json",
} else if ( "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
documentData === "Error: Something went wrong!" || "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
(documentData.result && documentData.result.error) },
) { }
alert("Error: Something went wrong!"); )
} else { .then((Listdata) => {
alert("No data found!"); const json = Listdata.data;
} const res = json.results;
if (res[0] && res.length > 0) {
setPdfDetails(res);
const loadObj = {
isLoad: false,
};
setIsLoading(loadObj);
} else {
alert("No data found!");
}
})
.catch((err) => {
console.log("axois err ", err);
});
}; };
//check document type and render on signyour self and placeholder route //check document type and render on signyour self and placeholder route
@@ -49,25 +63,24 @@ function DraftDocument() {
const data = pdfDetails[0]; const data = pdfDetails[0];
const checkSignerExist = const checkSignerExist =
pdfDetails[0] && pdfDetails[0].Signers && pdfDetails[0].Signers; pdfDetails[0] && pdfDetails[0].Signers && pdfDetails[0].Signers;
const isPlaceholder = const isPlaceholder =
pdfDetails[0].Placeholders && pdfDetails[0].Placeholders; pdfDetails[0].Placeholders && pdfDetails[0].Placeholders;
const isDecline = data.IsDeclined && data.IsDeclined; const isDecline = data.IsDeclined && data.IsDeclined;
const signUrl = data.SignedUrl && data.SignedUrl; const signUrl = data.SignedUrl && data.SignedUrl;
const expireDate = const expireDate = pdfDetails[0] && pdfDetails[0].ExpiryDate.iso && pdfDetails[0].ExpiryDate.iso;
pdfDetails[0] &&
pdfDetails[0].ExpiryDate.iso &&
pdfDetails[0].ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime(); const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime(); const currDate = new Date().getTime();
const hostUrl = getHostUrl(); const hostUrl = getHostUrl();
//checking document is completed and signer exist then navigate to pdfRequestFiles file //checking document is completed and signer exist then navigate to pdfRequestFiles file
if (data.IsCompleted && checkSignerExist) { if (data.IsCompleted && checkSignerExist) {
navigate(`${hostUrl}pdfRequestFiles`); navigate(`${hostUrl}pdfRequestFiles`);
} }
//checking document is completed and signer does not exist then navigate to recipientSignPdf file //checking document is completed and signer does not exist then navigate to recipientSignPdf file
else if (data.IsCompleted && !checkSignerExist) { else if (data.IsCompleted && !checkSignerExist) {
navigate(`${hostUrl}signaturePdf`); navigate(
`${hostUrl}signaturePdf`
);
} }
//checking document is declined by someone then navigate to pdfRequestFiles file //checking document is declined by someone then navigate to pdfRequestFiles file
else if (isDecline) { else if (isDecline) {
@@ -99,7 +99,7 @@ function PdfFileComponent({
//function for navigate user to microapp-signature component //function for navigate user to microapp-signature component
const checkPdfStatus = async (data) => { const checkPdfStatus = async (data) => {
const hostUrl = getHostUrl(); const hostUrl = getHostUrl();
const expireDate = data.ExpiryDate.iso; const expireDate = data.ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime(); const expireUpdateDate = new Date(expireDate).getTime();
@@ -221,19 +221,13 @@ function PdfFileComponent({
// console.log("download") // console.log("download")
const pdfName = data && data.Name; const pdfName = data && data.Name;
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL; const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`); saveAs(pdfUrl, `${pdfName}_signed_by_OpenSign™.pdf`);
} else if (selectType === "Rename") { } else if (selectType === "Rename") {
// console.log("rename") // console.log("rename")
setRenameValue(data.Name); setRenameValue(data.Name);
setRename(data.objectId); setRename(data.objectId);
} }
}; };
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, '_');
}
const handleEnterPress = (e, data) => { const handleEnterPress = (e, data) => {
if (e.key === "Enter") { if (e.key === "Enter") {
handledRenameDoc(data); handledRenameDoc(data);
@@ -6,7 +6,6 @@ import PdfFileComponent from "./FolderDrive/legaDriveComponent";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
import ModalHeader from "react-bootstrap/esm/ModalHeader"; import ModalHeader from "react-bootstrap/esm/ModalHeader";
import { themeColor, iconColor } from "../../utils/ThemeColor/backColor"; import { themeColor, iconColor } from "../../utils/ThemeColor/backColor";
import { getDrive } from "../../utils/Utils";
function PdfFile() { function PdfFile() {
const scrollRef = useRef(null); const scrollRef = useRef(null);
@@ -16,24 +15,28 @@ function PdfFile() {
const [pdfData, setPdfData] = useState([]); const [pdfData, setPdfData] = useState([]);
const [isFolder, setIsFolder] = useState(false); const [isFolder, setIsFolder] = useState(false);
const [newFolderName, setNewFolderName] = useState(); const [newFolderName, setNewFolderName] = useState();
// const [parentFolderName, setParentFolderName] = useState();
// const [parentFolder, setParentFolder] = useState([]);
const [error, setError] = useState(); const [error, setError] = useState();
const [folderLoader, setIsFolderLoader] = useState(false); const [folderLoader, setIsFolderLoader] = useState(false);
const [isShowSort, setIsShowSort] = useState(false); const [isShowSort, setIsShowSort] = useState(false);
const [isLoading, setIsLoading] = useState({ const [isLoading, setIsLoading] = useState({
isLoad: true, isLoad: true,
message: "This might take some time" message: "This might take some time",
}); });
const [docId, setDocId] = useState(); const [docId, setDocId] = useState();
const [handleError, setHandleError] = useState(); const [handleError, setHandleError] = useState();
const [folderName, setFolderName] = useState([]); const [folderName, setFolderName] = useState([]);
const currentUser =
const senderUser =
localStorage.getItem( localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser` `Parse/${localStorage.getItem("parseAppId")}/currentUser`
) && ) &&
localStorage.getItem( localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser` `Parse/${localStorage.getItem("parseAppId")}/currentUser`
); );
const jsonCurrentUser = JSON.parse(currentUser); const jsonSender = JSON.parse(senderUser);
useEffect(() => { useEffect(() => {
if (docId) { if (docId) {
@@ -47,59 +50,104 @@ function PdfFile() {
const getPdfDocumentList = async () => { const getPdfDocumentList = async () => {
const load = { const load = {
isLoad: true, isLoad: true,
message: "This might take some time" message: "This might take some time",
}; };
setIsLoading(load); setIsLoading(load);
const driveDetails = await getDrive(); //?where={"Type":"Folder" }&include=ExtUserPtr,Signers
//?where={"$or":[{"Type":{"$exists":true}},{"Folder":{"$exists":false}}]}&include=ExtUserPtr,Signers
if (driveDetails) { // "CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${jsonSender.objectId}"}
if (driveDetails.length > 0) { // where={"Folder":{"$exists":false} }&include=ExtUserPtr,Signers`,
setPdfData(driveDetails); await axios
} .get(
const data = [ `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document?where={"Folder":{"$exists":false},"$or":[{"CreatedBy":{"$exists":false}},{"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${
jsonSender.objectId
}"}}]}&include=ExtUserPtr,Signers`,
{ {
name: "OpenSignDrive™", headers: {
objectId: "" "Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken"),
},
} }
]; )
setFolderName(data); .then((Listdata) => {
const loadObj = { const json = Listdata.data;
isLoad: false const res = json.results;
}; // console.log("result", res);
setIsLoading(loadObj); if (res[0] && res.length > 0) {
} else if (driveDetails === "Error: Something went wrong!") { setPdfData(res);
const loadObj = { }
isLoad: false
}; const data = [
setHandleError("Error: Something went wrong!"); {
setIsLoading(loadObj); name: "OpenSignDrive™",
} objectId: "",
},
];
setFolderName(data);
const loadObj = {
isLoad: false,
};
setIsLoading(loadObj);
})
.catch((err) => {
const loadObj = {
isLoad: false,
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
}; };
//function for get parent folder document list //function for get parent folder document list
const getPdfFolderDocumentList = async () => { const getPdfFolderDocumentList = async () => {
const load = { const load = {
isLoad: true, isLoad: true,
message: "This might take some time" message: "This might take some time",
}; };
setIsLoading(load); setIsLoading(load);
const driveDetails = await getDrive(docId); //{"$inQuery":{"where":{"objectId":"${docId}"},"className":"${appName}_Document"}}
if (driveDetails) { //"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${jsonSender.objectId}"}
if (driveDetails.length > 0) { await axios
setPdfData(driveDetails); .get(
} else { `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
setPdfData([]); "_appName"
} )}_Document?where={"Folder":{"__type":"Pointer","className":"${localStorage.getItem(
const loadObj = { "_appName"
isLoad: false )}_Document","objectId":"${docId}"},"$or":[{"CreatedBy":{"$exists":false}},{"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${
}; jsonSender.objectId
setIsLoading(loadObj); }"}}]}&include=ExtUserPtr,Signers,Folder`,
} else if (driveDetails === "Error: Something went wrong!") { {
const loadObj = { headers: {
isLoad: false "Content-Type": "application/json",
}; "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
setHandleError("Error: Something went wrong!"); "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
setIsLoading(loadObj); },
} }
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
setPdfData(res);
} else {
setPdfData([]);
}
const loadObj = {
isLoad: false,
};
setIsLoading(loadObj);
})
.catch((err) => {
const loadObj = {
isLoad: false,
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
}; };
//function for get all pdf document list //function for get all pdf document list
@@ -110,7 +158,7 @@ function PdfFile() {
const handleRoute = (data) => { const handleRoute = (data) => {
let loadObj = { let loadObj = {
isLoad: true, isLoad: true,
message: "This might take some time" message: "This might take some time",
}; };
if (data.name === "LegaDrive™") { if (data.name === "LegaDrive™") {
setIsLoading(loadObj); setIsLoading(loadObj);
@@ -119,7 +167,7 @@ function PdfFile() {
} else { } else {
setTimeout(() => { setTimeout(() => {
const loadObj = { const loadObj = {
isLoad: false isLoad: false,
}; };
setIsLoading(loadObj); setIsLoading(loadObj);
}, 1000); }, 1000);
@@ -128,11 +176,12 @@ function PdfFile() {
setIsLoading(loadObj); setIsLoading(loadObj);
setTimeout(() => { setTimeout(() => {
const loadObj = { const loadObj = {
isLoad: false isLoad: false,
}; };
setIsLoading(loadObj); setIsLoading(loadObj);
}, 1000); }, 1000);
} else { } else {
// console.log("go here1",data.objectId)
const findIndex = folderName.findIndex( const findIndex = folderName.findIndex(
(fold) => fold.objectId === data.objectId (fold) => fold.objectId === data.objectId
); );
@@ -158,32 +207,22 @@ function PdfFile() {
setIsFolderLoader(true); setIsFolderLoader(true);
const getParentObjId = folderName[folderName.length - 1]; const getParentObjId = folderName[folderName.length - 1];
const parentId = getParentObjId && getParentObjId.objectId; const isParentId = getParentObjId && getParentObjId.objectId;
let data; let data;
if (parentId) { if (isParentId) {
data = { data = {
Name: newFolderName, Name: newFolderName,
Type: "Folder", Type: "Folder",
Folder: { Folder: {
__type: "Pointer", __type: "Pointer",
className: `${localStorage.getItem("_appName")}_Document`, className: `${localStorage.getItem("_appName")}_Document`,
objectId: parentId objectId: isParentId,
}, },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: jsonCurrentUser.objectId
}
}; };
} else { } else {
data = { data = {
Name: newFolderName, Name: newFolderName,
Type: "Folder", Type: "Folder",
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: jsonCurrentUser.objectId
}
}; };
} }
@@ -198,8 +237,8 @@ function PdfFile() {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"), "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken") "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
} },
} }
) )
@@ -349,7 +388,7 @@ function PdfFile() {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
justifyContent: "center", justifyContent: "center",
alignItems: "center" alignItems: "center",
}} }}
> >
<img <img
@@ -367,7 +406,7 @@ function PdfFile() {
style={{ style={{
margin: "10px 0px 10px 0px", margin: "10px 0px 10px 0px",
fontSize: "15px", fontSize: "15px",
fontWeight: "400" fontWeight: "400",
}} }}
> >
Name* Name*
@@ -389,7 +428,7 @@ function PdfFile() {
display: "flex", display: "flex",
alignItems: "flex-end", alignItems: "flex-end",
justifyContent: "flex-end", justifyContent: "flex-end",
alignContent: "flex-end" alignContent: "flex-end",
}} }}
> >
<button <button
@@ -398,7 +437,7 @@ function PdfFile() {
borderRadius: "0px", borderRadius: "0px",
border: "1.5px solid #e3e2e1", border: "1.5px solid #e3e2e1",
fontWeight: "600", fontWeight: "600",
color: "black" color: "black",
}} }}
className="finishBtn" className="finishBtn"
onClick={() => setIsFolder(false)} onClick={() => setIsFolder(false)}
@@ -409,7 +448,7 @@ function PdfFile() {
<button <button
onClick={() => handleAddFolder()} onClick={() => handleAddFolder()}
style={{ style={{
background: themeColor() background: themeColor(),
}} }}
type="button" type="button"
className="finishBtn" className="finishBtn"
@@ -430,7 +469,7 @@ function PdfFile() {
alignItems: "center", alignItems: "center",
height: "100vh", height: "100vh",
width: "100%", width: "100%",
flexDirection: "column" flexDirection: "column",
}} }}
> >
<img <img
@@ -449,7 +488,7 @@ function PdfFile() {
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
height: "100vh", height: "100vh",
width: "100%" width: "100%",
}} }}
> >
<span style={{ fontSize: "20px", color: "gray" }}> <span style={{ fontSize: "20px", color: "gray" }}>
@@ -463,7 +502,7 @@ function PdfFile() {
onMouseEnter={(e) => handleMouseEnter(e)} onMouseEnter={(e) => handleMouseEnter(e)}
ref={scrollRef} ref={scrollRef}
style={{ style={{
width: "100%" width: "100%",
}} }}
className="folderPath" className="folderPath"
> >
@@ -475,7 +514,7 @@ function PdfFile() {
style={{ style={{
color: "#a64b4e", color: "#a64b4e",
fontWeight: "400", fontWeight: "400",
cursor: "pointer" cursor: "pointer",
}} }}
> >
{data.name} {data.name}
@@ -484,7 +523,7 @@ function PdfFile() {
color: "#a64b4e", color: "#a64b4e",
fontWeight: "200", fontWeight: "200",
cursor: "pointer", cursor: "pointer",
margin: "0 4px" margin: "0 4px",
}} }}
> >
&gt; &gt;
@@ -506,13 +545,13 @@ function PdfFile() {
style={{ style={{
marginRight: "5px", marginRight: "5px",
fontSize: "14px", fontSize: "14px",
color: `${iconColor()}` color: `${iconColor()}`,
}} }}
></i> ></i>
<span <span
style={{ style={{
fontSize: "15px", fontSize: "15px",
color: `${iconColor()}` color: `${iconColor()}`,
}} }}
> >
{selectedSort} {selectedSort}
@@ -655,7 +694,7 @@ function PdfFile() {
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
height: "50vh", height: "50vh",
width: "100%" width: "100%",
}} }}
> >
<span style={{ fontWeight: "bold" }}>No Data Found!</span> <span style={{ fontWeight: "bold" }}>No Data Found!</span>
@@ -1,6 +1,6 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { themeColor } from "../utils/ThemeColor/backColor"; import { themeColor } from "../utils/ThemeColor/backColor";
import { PDFDocument } from "pdf-lib"; import { PDFDocument, rgb } from "pdf-lib";
import "../css/signature.css"; import "../css/signature.css";
import axios from "axios"; import axios from "axios";
import ModalHeader from "react-bootstrap/esm/ModalHeader"; import ModalHeader from "react-bootstrap/esm/ModalHeader";
@@ -11,16 +11,7 @@ import { HTML5Backend } from "react-dnd-html5-backend";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import SignPad from "./component/signPad"; import SignPad from "./component/signPad";
import RenderAllPdfPage from "./component/renderAllPdfPage"; import RenderAllPdfPage from "./component/renderAllPdfPage";
import { import { getBase64FromIMG, getBase64FromUrl } from "../utils/Utils";
convertPNGtoJPEG,
contractDocument,
getBase64FromIMG,
getBase64FromUrl,
urlValidator,
multiSignEmbed,
embedDocId,
pdfNewWidthFun
} from "../utils/Utils";
import Loader from "./component/loader"; import Loader from "./component/loader";
import HandleError from "./component/HandleError"; import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata"; import Nodata from "./component/Nodata";
@@ -93,14 +84,19 @@ function PdfRequestFiles() {
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
useEffect(() => { useEffect(() => {
const clientWidth = window.innerWidth;
const value = docId ? 80 : 30;
const pdfWidth = clientWidth - 160 - 200 - value;
//160 is width of left side, 200 is width of right side component and 50 is space of middle compoent
//pdf from left and right component
setPdfNewWidth(pdfWidth);
if (documentId) { if (documentId) {
getDocumentDetails(); getDocumentDetails();
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
if (divRef.current) { if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({ setContainerWH({
width: divRef.current.offsetWidth, width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight height: divRef.current.offsetHeight
@@ -110,135 +106,153 @@ function PdfRequestFiles() {
//function for get document details for perticular signer with signer'object id //function for get document details for perticular signer with signer'object id
const getDocumentDetails = async () => { const getDocumentDetails = async () => {
//getting document details await axios
const documentData = await contractDocument(documentId); .get(
if (documentData && documentData.length > 0) { `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
const isCompleted = "_appName"
documentData[0].IsCompleted && documentData[0].IsCompleted; )}_Document?where={"objectId":"${documentId}"}&include=ExtUserPtr,Signers,UserPtr`,
const expireDate = documentData[0].ExpiryDate.iso; {
const declined = documentData[0].IsDeclined && documentData[0].IsDeclined; headers: {
const expireUpdateDate = new Date(expireDate).getTime(); "Content-Type": "application/json",
const currDate = new Date().getTime(); "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
const getSigners = documentData[0].Signers; "X-Parse-Session-Token": localStorage.getItem("accesstoken")
const getCurrentSigner = }
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender.objectId
);
const currUserId = getCurrentSigner[0]
? getCurrentSigner[0].objectId
: "";
setSignerObjectId(currUserId);
if (documentData[0].SignedUrl) {
setPdfUrl(documentData[0].SignedUrl);
} else {
setPdfUrl(documentData[0].URL);
}
if (isCompleted) {
setIsSigned(true);
const data = {
isCertificate: true,
isModal: true
};
setAlreadySign(true);
setIsCompleted(data);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
setIsExpired(true);
}
if (documentData.length > 0) {
const checkDocIdExist =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
const checkAlreadySign =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId && data.Activity === "Signed"
);
if (
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true);
} }
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
let signers = []; if (res[0] && res.length > 0) {
let unSignedSigner = []; const isCompleted = res[0].IsCompleted && res[0].IsCompleted;
const expireDate = res[0].ExpiryDate.iso;
const declined = res[0].IsDeclined && res[0].IsDeclined;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const getSigners = res[0].Signers;
const getCurrentSigner =
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender.objectId
);
//check document is signed or not const currUserId = getCurrentSigner[0]
if (checkDocIdExist && checkDocIdExist.length > 0) { ? getCurrentSigner[0].objectId
setIsDocId(true); : "";
const signerRes = documentData[0].Signers; setSignerObjectId(currUserId);
//comparison auditTrail user details with signers user details if (res[0].SignedUrl) {
for (let i = 0; i < signerRes.length; i++) { setPdfUrl(res[0].SignedUrl);
const signerId = signerRes[i].objectId; } else {
setPdfUrl(res[0].URL);
}
if (isCompleted) {
setIsSigned(true);
const data = {
isCertificate: true,
isModal: true
};
setAlreadySign(true);
setIsCompleted(data);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
setIsExpired(true);
}
let isSigned = false; if (res.length > 0) {
for (let j = 0; j < checkDocIdExist.length; j++) { const checkDocIdExist =
const signedExist = json.results[0].AuditTrail &&
checkDocIdExist[j] && checkDocIdExist[j].UserPtr.objectId; json.results[0].AuditTrail.length > 0 &&
//checking signerObjId and auditTrail User objId json.results[0].AuditTrail.filter(
// if match then add signed data in signer array and break loop (data) => data.Activity === "Signed"
);
if (signerId === signedExist) { const checkAlreadySign =
signers.push({ ...signerRes[i], ...signerRes[i] }); json.results[0].AuditTrail &&
isSigned = true; json.results[0].AuditTrail.length > 0 &&
break; json.results[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId &&
data.Activity === "Signed"
);
if (
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true);
}
let signers = [];
let unSignedSigner = [];
//check document is signed or not
if (checkDocIdExist && checkDocIdExist.length > 0) {
setAlreadySign(true);
setIsDocId(true);
const signerRes = res[0].Signers;
//comparison auditTrail user details with signers user details
for (let i = 0; i < signerRes.length; i++) {
const signerId = signerRes[i].objectId;
let isSigned = false;
for (let j = 0; j < checkDocIdExist.length; j++) {
const signedExist =
checkDocIdExist[j] && checkDocIdExist[j].UserPtr.objectId;
//checking signerObjId and auditTrail User objId
// if match then add signed data in signer array and break loop
if (signerId === signedExist) {
signers.push({ ...signerRes[i], ...signerRes[i] });
isSigned = true;
break;
}
// if does not match then add unsigned data in unSignedSigner array
}
if (!isSigned) {
unSignedSigner.push({ ...signerRes[i], ...signerRes[i] });
}
} }
// if does not match then add unsigned data in unSignedSigner array setSignedSigners(signers);
} setUnSignedSigners(unSignedSigner);
if (!isSigned) {
unSignedSigner.push({ ...signerRes[i], ...signerRes[i] });
}
}
setSignedSigners(signers);
setUnSignedSigners(unSignedSigner);
setSignerPos(documentData[0].Placeholders); setSignerPos(res[0].Placeholders);
} else { } else {
let unsigned = []; let unsigned = [];
for (let i = 0; i < documentData.length; i++) { for (let i = 0; i < res.length; i++) {
unsigned.push(documentData[i].Signers); unsigned.push(res[i].Signers);
}
setUnSignedSigners(unsigned[0]);
setSignerPos(res[0].Placeholders);
}
setPdfDetails(res);
setIsUiLoading(false);
} else {
alert("No data found!");
} }
setUnSignedSigners(unsigned[0]); } else {
setSignerPos(documentData[0].Placeholders); setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsUiLoading(false);
} }
setPdfDetails(documentData); })
setIsUiLoading(false); .catch((err) => {
} else { console.log("err", err);
alert("No data found!"); const loadObj = {
} isLoad: false
} else if ( };
documentData === "Error: Something went wrong!" || setHandleError("Error: Something went wrong!");
(documentData.result && documentData.result.error) setIsLoading(loadObj);
) { });
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsUiLoading(false);
}
await axios await axios
.get( .get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -280,6 +294,7 @@ function PdfRequestFiles() {
const checkUser = signerPos.filter( const checkUser = signerPos.filter(
(data) => data.signerObjId === signerObjectId (data) => data.signerObjId === signerObjectId
); );
if (checkUser && checkUser.length > 0) { if (checkUser && checkUser.length > 0) {
let checkSignUrl = []; let checkSignUrl = [];
const checkSign = checkUser[0].placeHolder.filter( const checkSign = checkUser[0].placeHolder.filter(
@@ -317,25 +332,67 @@ function PdfRequestFiles() {
if (isDocId) { if (isDocId) {
pdfBase64 = await getBase64FromUrl(url); pdfBase64 = await getBase64FromUrl(url);
} else { } else {
//embed document's object id to all pages in pdf document for (let i = 0; i < allPages; i++) {
await embedDocId(pdfDoc, documentId, allPages); const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 10;
const textContent =
documentId && `OpenSign™ DocumentId: ${documentId}`;
const pages = pdfDoc.getPages();
const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
pdfBase64 = await pdfDoc.saveAsBase64({ pdfBase64 = await pdfDoc.saveAsBase64({
useObjectStreams: false useObjectStreams: false
}); });
} }
for (let i = 0; i < pngUrl.length; i++) { for (let i = 0; i < pngUrl.length; i++) {
const imgUrlList = pngUrl[i].pos; const imgUrlList = pngUrl[i].pos;
const pageNo = pngUrl[i].pageNumber; const pageNo = pngUrl[i].pageNumber;
imgUrlList.map(async (data) => { imgUrlList.map(async (data) => {
//cheking signUrl is defau;t signature url of custom url //cheking signUrl is defau;t signature url of custom url
let ImgUrl = data.SignUrl; let ImgUrl = data.SignUrl;
const checkUrl = urlValidator(ImgUrl); const checkUrl = ImgUrl.includes("https:");
//if default signature url then convert it in base 64 //if default signature url then convert it in base 64
if (checkUrl) { if (checkUrl) {
ImgUrl = await getBase64FromIMG(ImgUrl + "?get"); ImgUrl = await getBase64FromIMG(ImgUrl + "?get");
} }
//function for called convert png signatre to jpeg in base 64 //function for called convert png signatre to jpeg in base 64
const convertPNGtoJPEG = (base64Data) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas");
const img = new Image();
img.src = base64Data;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Convert to JPEG by using the canvas.toDataURL() method
const jpegBase64Data = canvas.toDataURL("image/jpeg");
resolve(jpegBase64Data);
};
img.onerror = (error) => {
reject(error);
};
});
};
convertPNGtoJPEG(ImgUrl) convertPNGtoJPEG(ImgUrl)
.then((jpegBase64Data) => { .then((jpegBase64Data) => {
const removeBase64Fromjpeg = "data:image/jpeg;base64,"; const removeBase64Fromjpeg = "data:image/jpeg;base64,";
@@ -362,15 +419,123 @@ function PdfRequestFiles() {
} }
//else if signature is more than one then embed all sign with the use of pdf-lib //else if signature is more than one then embed all sign with the use of pdf-lib
else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) { else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) {
//embed document's object id to all pages in pdf document for (let i = 0; i < allPages; i++) {
await embedDocId(pdfDoc, documentId, allPages); const font = await pdfDoc.embedFont("Helvetica");
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed( const fontSize = 10;
pngUrl, const textContent =
pdfDoc, documentId && `OpenSign™ DocumentId: ${documentId} `;
pdfOriginalWidth,
false const pages = pdfDoc.getPages();
); const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
for (let i = 0; i < pngUrl.length; i++) {
const pageNo = pngUrl[i].pageNumber;
const imgUrlList = pngUrl[i].pos;
const pages = pdfDoc.getPages();
const page = pages[pageNo - 1];
const images = await Promise.all(
imgUrlList.map(async (url) => {
let signUrl = url.SignUrl;
const checkUrl = url.SignUrl.includes("https:");
if (checkUrl) {
signUrl = signUrl + "?get";
}
const res = await fetch(signUrl);
return res.arrayBuffer();
})
);
images.forEach(async (imgData, id) => {
let img;
if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/jpeg"
) {
img = await pdfDoc.embedJpg(imgData);
} else if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/png"
) {
img = await pdfDoc.embedPng(imgData);
} else {
img = await pdfDoc.embedPng(imgData);
}
const imgHeight = imgUrlList[id].Height
? imgUrlList[id].Height
: 60;
const imgWidth = imgUrlList[id].Width
? imgUrlList[id].Width
: 150;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const xPos = (pos) => {
//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 = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / 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 = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yPos = (pos) => {
//checking both condition mobile and desktop view
const y = pos.yPosition / 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 = pos.yPosition * (pos.scale / scale);
return page.getHeight() - y * scale - imgHeight;
} else {
return page.getHeight() - y * scale - imgHeight;
}
} 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 y = pos.yPosition * pos.scale;
return page.getHeight() - y - imgHeight;
} else {
return page.getHeight() - pos.yPosition - imgHeight;
}
}
};
page.drawImage(img, {
x: xPos(imgUrlList[id]),
y: yPos(imgUrlList[id]),
width: imgWidth,
height: imgHeight
});
});
}
const pdfBytes = await pdfDoc.saveAsBase64({
useObjectStreams: false
});
signPdfFun(pdfBytes, documentId, pngUrl); signPdfFun(pdfBytes, documentId, pngUrl);
} }
@@ -432,12 +597,12 @@ function PdfRequestFiles() {
if (isMobile) { if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale //if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (pos.isMobile) { if (pos.isMobile) {
const y = pos.yBottom * (pos.scale / scale); const y = pos.yPosition * (pos.scale / scale);
yPosition = pos.isDrag yPosition = pos.isDrag
? y * scale - height ? y * scale - height
: pos.firstYPos : pos.firstYPos
? y * scale - height + pos.firstYPos ? y * scale - height + pos.firstYPos
: y * scale - height; : y * scale - height;
return yPosition; return yPosition;
} else { } else {
const y = pos.yBottom / scale; const y = pos.yBottom / scale;
@@ -445,8 +610,8 @@ function PdfRequestFiles() {
yPosition = pos.isDrag yPosition = pos.isDrag
? y * scale - height ? y * scale - height
: pos.firstYPos : pos.firstYPos
? y * scale - height + pos.firstYPos ? y * scale - height + pos.firstYPos
: y * scale - height; : y * scale - height;
return yPosition; return yPosition;
} }
} else { } else {
@@ -457,15 +622,15 @@ function PdfRequestFiles() {
yPosition = pos.isDrag yPosition = pos.isDrag
? y - height ? y - height
: pos.firstYPos : pos.firstYPos
? y - height + pos.firstYPos ? y - height + pos.firstYPos
: y - height; : y - height;
return yPosition; return yPosition;
} else { } else {
yPosition = pos.isDrag yPosition = pos.isDrag
? pos.yBottom - height ? pos.yBottom - height
: pos.firstYPos : pos.firstYPos
? pos.yBottom - height + pos.firstYPos ? pos.yBottom - height + pos.firstYPos
: pos.yBottom - height; : pos.yBottom - height;
return yPosition; return yPosition;
} }
} }
@@ -883,7 +1048,7 @@ function PdfRequestFiles() {
<Modal.Body> <Modal.Body>
<p className="pTagBody"> <p className="pTagBody">
This document has been signed by all Signers. This document has been signed by all Sigers.
</p> </p>
</Modal.Body> </Modal.Body>
@@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { PDFDocument } from "pdf-lib"; import { PDFDocument, rgb } from "pdf-lib";
import "../css/./signature.css"; import "../css/./signature.css";
import sign from "../assests/sign3.png"; import sign from "../assests/sign3.png";
import stamp from "../assests/stamp2.png"; import stamp from "../assests/stamp2.png";
@@ -15,14 +15,7 @@ import EmailComponent from "./component/emailComponent";
import FieldsComponent from "./component/fieldsComponent"; import FieldsComponent from "./component/fieldsComponent";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
import ModalHeader from "react-bootstrap/esm/ModalHeader"; import ModalHeader from "react-bootstrap/esm/ModalHeader";
import { import { getBase64FromIMG } from "../utils/Utils";
convertPNGtoJPEG,
contractDocument,
getBase64FromIMG,
embedDocId,
multiSignEmbed,
pdfNewWidthFun
} from "../utils/Utils";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import Tour from "reactour"; import Tour from "reactour";
import { onSaveImage, onSaveSign } from "../utils/Utils"; import { onSaveImage, onSaveSign } from "../utils/Utils";
@@ -31,9 +24,7 @@ import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata"; import Nodata from "./component/Nodata";
import Header from "./component/header"; import Header from "./component/header";
import RenderPdf from "./component/renderPdf"; import RenderPdf from "./component/renderPdf";
import { contractUsers, contactBook, urlValidator } from "../utils/Utils"; import { contractUsers, contactBook } from "../utils/Utils";
import { modalAlign } from "../utils/Utils";
//For signYourself inProgress section signer can add sign and complete doc sign. //For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() { function SignYourSelf() {
const [pdfDetails, setPdfDetails] = useState([]); const [pdfDetails, setPdfDetails] = useState([]);
@@ -82,7 +73,7 @@ function SignYourSelf() {
status: false, status: false,
type: "load" type: "load"
}); });
const divRef = useRef(null);
const nodeRef = useRef(null); const nodeRef = useRef(null);
const [{ isOver }, drop] = useDrop({ const [{ isOver }, drop] = useDrop({
accept: "BOX", accept: "BOX",
@@ -169,57 +160,68 @@ function SignYourSelf() {
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
useEffect(() => { useEffect(() => {
const clientWidth = window.innerWidth;
const value = docId ? 80 : 80;
const pdfWidth = clientWidth - 160 - 200 - value;
//160 is width of left side, 200 is width of right side component and 50 is space of middle compoent
//pdf from left and right component
setPdfNewWidth(pdfWidth);
if (documentId) { if (documentId) {
getDocumentDetails(true); getDocumentDetails();
} }
}, []); }, []);
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
}
}, [divRef.current]);
//function for get document details for perticular signer with signer'object id //function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => { const getDocumentDetails = async () => {
//getting document details await axios
const documentData = await contractDocument(documentId); .get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
if (documentData && documentData.length > 0) { "_appName"
setPdfDetails(documentData); )}_Document?where={"objectId":"${documentId}"}&include=ExtUserPtr,Signers`,
const isCompleted = {
documentData[0].IsCompleted && documentData[0].IsCompleted; headers: {
if (isCompleted) { "Content-Type": "application/json",
const docStatus = { "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
isCompleted: isCompleted "X-Parse-Session-Token": localStorage.getItem("accesstoken")
}; }
setDocumentStatus(docStatus);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: "You have successfully signed the document!"
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
} }
} )
} else if ( .then((Listdata) => {
documentData === "Error: Something went wrong!" || const json = Listdata.data;
(documentData.result && documentData.result.error) const res = json.results;
) {
const loadObj = { if (res[0] && res.length > 0) {
isLoad: false setPdfDetails(res);
}; const isCompleted = res[0].IsCompleted && res[0].IsCompleted;
setHandleError("Error: Something went wrong!"); if (isCompleted) {
setIsLoading(loadObj); const docStatus = {
} else { isCompleted: isCompleted
setNoData(true); };
const loadObj = {
isLoad: false setDocumentStatus(docStatus);
}; const alreadySign = {
setIsLoading(loadObj); status: true,
} mssg: "You have successfully signed the document!"
};
setShowAlreadySignDoc(alreadySign);
setPdfUrl(res[0].SignedUrl);
}
} else {
setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
})
.catch((err) => {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
await axios await axios
.get( .get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -250,10 +252,13 @@ function SignYourSelf() {
setHandleError("Error: Something went wrong!"); setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
}); });
const contractUsersRes = await contractUsers(jsonSender.objectId);
const contractUsersRes = await contractUsers(jsonSender.email); if (
contractUsersRes !== "Error: Something went wrong!" &&
if (contractUsersRes[0] && contractUsersRes.length > 0) { contractUsersRes &&
contractUsersRes[0]
) {
setContractName("_Users"); setContractName("_Users");
setSignerUserId(contractUsersRes[0].objectId); setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss = const tourstatuss =
@@ -280,12 +285,14 @@ function SignYourSelf() {
setIsLoading(loadObj); setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) { } else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId); const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook.length > 0) { if (contractContactBook && contractContactBook[0]) {
setContractName("_Contactbook"); setContractName("_Contactbook");
setSignerUserId(contractContactBook[0].objectId); setSignerUserId(contractContactBook[0].objectId);
const tourstatuss = const tourstatuss =
contractContactBook[0].TourStatus && contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus; contractContactBook[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0) { if (tourstatuss && tourstatuss.length > 0) {
setTourStatus(tourstatuss); setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter( const checkTourRecipients = tourstatuss.filter(
@@ -295,8 +302,6 @@ function SignYourSelf() {
setCheckTourStatus(checkTourRecipients[0].signyourself); setCheckTourStatus(checkTourRecipients[0].signyourself);
} }
} }
} else {
setNoData(true);
} }
const loadObj = { const loadObj = {
isLoad: false isLoad: false
@@ -427,7 +432,24 @@ function SignYourSelf() {
//checking if signature is only one then send image url in jpeg formate to server //checking if signature is only one then send image url in jpeg formate to server
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) { if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
//embed document's object id to all pages in pdf document //embed document's object id to all pages in pdf document
await embedDocId(pdfDoc, documentId, allPages); for (let i = 0; i < allPages; i++) {
const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 10;
const textContent =
documentId && `OpenSign™ DocumentId: ${documentId}`;
const pages = pdfDoc.getPages();
const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
const pdfBase64 = await pdfDoc.saveAsBase64({ const pdfBase64 = await pdfDoc.saveAsBase64({
useObjectStreams: false useObjectStreams: false
}); });
@@ -438,13 +460,39 @@ function SignYourSelf() {
imgUrlList.map(async (data) => { imgUrlList.map(async (data) => {
let ImgUrl = data.SignUrl; let ImgUrl = data.SignUrl;
//cheking signUrl is defau;t signature url of custom url //cheking signUrl is defau;t signature url of custom url
const checkUrl = urlValidator(ImgUrl); const checkUrl = ImgUrl.includes("https:");
//if default signature url then convert it in base 64 //if default signature url then convert it in base 64
if (checkUrl) { if (checkUrl) {
ImgUrl = await getBase64FromIMG(ImgUrl + "?get"); ImgUrl = await getBase64FromIMG(ImgUrl + "?get");
} }
//function for convert signature png base64 url to jpeg base64 //function for convert signature png base64 url to jpeg base64
const convertPNGtoJPEG = (base64Data) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas");
const img = new Image();
img.src = base64Data;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Convert to JPEG by using the canvas.toDataURL() method
const jpegBase64Data = canvas.toDataURL("image/jpeg");
resolve(jpegBase64Data);
};
img.onerror = (error) => {
reject(error);
};
});
};
convertPNGtoJPEG(ImgUrl) convertPNGtoJPEG(ImgUrl)
.then((jpegBase64Data) => { .then((jpegBase64Data) => {
const removeBase64Fromjpeg = "data:image/jpeg;base64,"; const removeBase64Fromjpeg = "data:image/jpeg;base64,";
@@ -452,6 +500,7 @@ function SignYourSelf() {
removeBase64Fromjpeg, removeBase64Fromjpeg,
"" ""
); );
//function for call to embed signature in pdf and get digital signature pdf //function for call to embed signature in pdf and get digital signature pdf
signPdfFun(newImgUrl, documentId, data, pdfBase64, pageNo); signPdfFun(newImgUrl, documentId, data, pdfBase64, pageNo);
}) })
@@ -463,15 +512,91 @@ function SignYourSelf() {
} }
//else if signature is more than one then embed all sign with the use of pdf-lib //else if signature is more than one then embed all sign with the use of pdf-lib
else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) { else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) {
//embed document's object id to all pages in pdf document for (let i = 0; i < allPages; i++) {
await embedDocId(pdfDoc, documentId, allPages); const font = await pdfDoc.embedFont("Helvetica");
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed( const fontSize = 10;
pngUrl, const textContent =
pdfDoc, documentId && `OpenSign™ DocumentId: ${documentId} `;
pdfOriginalWidth,
true const pages = pdfDoc.getPages();
); const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
for (let i = 0; i < pngUrl.length; i++) {
const pageNo = pngUrl[i].pageNumber;
const imgUrlList = pngUrl[i].pos;
const pages = pdfDoc.getPages();
const page = pages[pageNo - 1];
const images = await Promise.all(
imgUrlList.map(async (url) => {
let signUrl = url.SignUrl;
const checkUrl = url.SignUrl.includes("https:");
if (checkUrl) {
signUrl = signUrl + "?get";
}
const res = await fetch(signUrl);
return res.arrayBuffer();
})
);
images.forEach(async (imgData, id) => {
let img;
if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/jpeg"
) {
img = await pdfDoc.embedJpg(imgData);
} else if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/png"
) {
img = await pdfDoc.embedPng(imgData);
} else {
img = await pdfDoc.embedPng(imgData);
}
const imgHeight = imgUrlList[id].Height
? imgUrlList[id].Height
: 60;
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const posY = () => {
if (id === 0) {
return (
page.getHeight() -
imgUrlList[id].yPosition * scale -
imgHeight
);
} else if (id > 0) {
return page.getHeight() - imgUrlList[id].yPosition * scale;
}
};
page.drawImage(img, {
x: isMobile
? imgUrlList[id].xPosition * scale + imgWidth / 2
: imgUrlList[id].xPosition,
y: posY(),
width: imgWidth,
height: imgHeight
});
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
signPdfFun(pdfBytes, documentId); signPdfFun(pdfBytes, documentId);
} }
setIsSignPad(false); setIsSignPad(false);
@@ -490,18 +615,17 @@ function SignYourSelf() {
pageNo pageNo
) => { ) => {
let singleSign; let singleSign;
const isMobile = window.innerWidth < 767; const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth - 32; const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1; const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const imgWidth = xyPosData ? xyPosData.Width : 150; const imgWidth = xyPosData.Width.Width ? xyPosData.Width.Width : 150;
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) { if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
const height = xyPosData.Height ? xyPosData.Height : 60; const height = xyPosData.Height ? xyPosData.Height : 60;
const bottomY = xyPosData.isDrag const bottomY = xyPosData.isDrag
? xyPosData.yBottom * scale - height * scale ? xyPosData.yBottom * scale - height
: xyPosData.firstYPos : xyPosData.firstYPos
? xyPosData.yBottom * scale - height * scale + xyPosData.firstYPos ? xyPosData.yBottom * scale - height + xyPosData.firstYPos
: xyPosData.yBottom * scale - height * scale; : xyPosData.yBottom * scale - height;
singleSign = { singleSign = {
pdfFile: pdfBase64Url, pdfFile: pdfBase64Url,
@@ -509,11 +633,11 @@ function SignYourSelf() {
sign: { sign: {
Base64: base64Url, Base64: base64Url,
Left: isMobile Left: isMobile
? xyPosData.xPosition * scale + 43 ? xyPosData.xPosition * scale + imgWidth / 2
: xyPosData.xPosition, : xyPosData.xPosition,
Bottom: bottomY, Bottom: bottomY,
Width: xyPosData.Width ? xyPosData.Width * scale : 150 * scale, Width: xyPosData.Width ? xyPosData.Width : 150,
Height: height * scale, Height: height,
Page: pageNo Page: pageNo
} }
}; };
@@ -537,7 +661,15 @@ function SignYourSelf() {
// console.log("json ", json); // console.log("json ", json);
setPdfUrl(json.result.data); setPdfUrl(json.result.data);
if (json.result.data) { if (json.result.data) {
getDocumentDetails(false); const docStatus = {
isCompleted: true
};
setDocumentStatus(docStatus);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} }
}) })
.catch((err) => { .catch((err) => {
@@ -877,7 +1009,7 @@ function SignYourSelf() {
) : noData ? ( ) : noData ? (
<Nodata /> <Nodata />
) : ( ) : (
<div className="signatureContainer" ref={divRef}> <div className="signatureContainer">
{/* this component used for UI interaction and show their functionality */} {/* this component used for UI interaction and show their functionality */}
{pdfLoadFail && !checkTourStatus && ( {pdfLoadFail && !checkTourStatus && (
<Tour <Tour
@@ -909,11 +1041,7 @@ function SignYourSelf() {
> >
{/* this modal is used show this document is already sign */} {/* this modal is used show this document is already sign */}
<Modal <Modal show={showAlreadySignDoc.status}>
show={showAlreadySignDoc.status}
onShow={() => modalAlign()}
backdropClassName="signature-backdrop"
>
<ModalHeader style={{ background: themeColor() }}> <ModalHeader style={{ background: themeColor() }}>
<span style={{ color: "white" }}> Sign Documents</span> <span style={{ color: "white" }}> Sign Documents</span>
</ModalHeader> </ModalHeader>
@@ -987,8 +1115,6 @@ function SignYourSelf() {
pdfDetails={pdfDetails} pdfDetails={pdfDetails}
isShowHeader={true} isShowHeader={true}
currentSigner={true} currentSigner={true}
alreadySign={pdfUrl ? true : false}
isSignYourself={true}
/> />
{/* className="hidePdf" */} {/* className="hidePdf" */}
@@ -28,7 +28,9 @@ function EmailComponent({
setIsLoading(true); setIsLoading(true);
let sendMail; let sendMail;
for (let i = 0; i < emailCount.length; i++) { for (let i = 0; i < emailCount.length; i++) {
try { try {
const imgPng = const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
// "https://qikinnovation.ams3.digitaloceanspaces.com/mailLogo_2023-08-18T12%3A51%3A31.573Z.png"; // "https://qikinnovation.ams3.digitaloceanspaces.com/mailLogo_2023-08-18T12%3A51%3A31.573Z.png";
@@ -39,7 +41,7 @@ function EmailComponent({
"X-Parse-Application-Id": localStorage.getItem("parseAppId"), "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken") sessionToken: localStorage.getItem("accesstoken")
}; };
const themeBGcolor = themeColor(); const themeBGcolor = themeColor();
let params = { let params = {
pdfName: pdfName, pdfName: pdfName,
@@ -109,36 +111,26 @@ function EmailComponent({
const pdf = await getBase64FromUrl(pdfUrl); const pdf = await getBase64FromUrl(pdfUrl);
const isAndroidDevice = navigator.userAgent.match(/Android/i); const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice = const isAppleDevice = (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) { if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from( const byteArray = Uint8Array.from(atob(pdf).split('').map(char => char.charCodeAt(0)));
atob(pdf) const blob = new Blob([byteArray], { type: 'application/pdf' });
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob); const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank"); window.open(blobUrl, '_blank');
} else { } else {
printModule({ printable: pdf, type: "pdf", base64: true }); printModule({ printable: pdf, type: "pdf", base64: true });
} }
}; };
//handle download signed pdf //handle download signed pdf
const handleDownloadPdf = () => { const handleDownloadPdf = () => {
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`); saveAs(pdfUrl, `${pdfName}_signed_by_OpenSign™.pdf`);
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
}; };
const isAndroid = /Android/i.test(navigator.userAgent); const isAndroid = /Android/i.test(navigator.userAgent);
return ( return (
<div> <div>
{/* isEmail */} {/* isEmail */}
@@ -170,7 +162,7 @@ function EmailComponent({
)} )}
<ModalHeader style={{ background: themeColor() }}> <ModalHeader style={{ background: themeColor() }}>
<span style={{ color: "white" }}>Successfully signed!</span> <span style={{ color: "white" }}>Email Documents</span>
<div style={{ display: "flex", flexDirection: "row" }}> <div style={{ display: "flex", flexDirection: "row" }}>
<div></div> <div></div>
@@ -256,25 +248,20 @@ function EmailComponent({
style={{ style={{
display: "flex", display: "flex",
flexDirection: "row", flexDirection: "row",
flexWrap: "wrap" flexWrap: "wrap"
}} }}
> >
{emailCount.map((data, ind) => { {emailCount.map((data, ind) => {
return ( return (
<div <div className="emailChip"
className="emailChip" style={{display:"flex", flexDirection:"row", alignItems:"center"}}
style={{ key={ind}>
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
key={ind}
>
<span <span
style={{ style={{
color: "white", color: "white",
fontSize: "13px" fontSize: "13px",
marginRight: "20px"
}} }}
> >
{data} {data}
@@ -286,8 +273,7 @@ function EmailComponent({
src={close} src={close}
width={10} width={10}
height={10} height={10}
style={{ fontWeight: "600", marginLeft: "7px" }} style={{ fontWeight: "600" }}
className="emailChipClose"
/> />
</div> </div>
); );
@@ -27,13 +27,13 @@ function Header({
signersdata, signersdata,
isMailSend, isMailSend,
alertSendEmail, alertSendEmail,
isSigned,
isCompleted, isCompleted,
isShowHeader, isShowHeader,
decline, decline,
currentSigner, currentSigner,
dataTut4, dataTut4,
alreadySign, alreadySign
isSignYourself
}) { }) {
const isMobile = window.innerWidth < 767; const isMobile = window.innerWidth < 767;
const navigate = useNavigate(); const navigate = useNavigate();
@@ -61,19 +61,12 @@ function Header({
const pdf = await getBase64FromUrl(pdfUrl); const pdf = await getBase64FromUrl(pdfUrl);
const isAndroidDevice = navigator.userAgent.match(/Android/i); const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice = const isAppleDevice = (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) { if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from( const byteArray = Uint8Array.from(atob(pdf).split('').map(char => char.charCodeAt(0)));
atob(pdf) const blob = new Blob([byteArray], { type: 'application/pdf' });
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob); const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank"); window.open(blobUrl, '_blank');
} else { } else {
printModule({ printable: pdf, type: "pdf", base64: true }); printModule({ printable: pdf, type: "pdf", base64: true });
} }
@@ -82,148 +75,13 @@ function Header({
//handle download signed pdf //handle download signed pdf
const handleDownloadPdf = () => { const handleDownloadPdf = () => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name; const pdfName = pdfDetails[0] && pdfDetails[0].Name;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
saveAs(pdfUrl, `${pdfName}_signed_by_OpenSign™.pdf`);
}; };
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
//certificate generate and download component in mobile view
const CertificateDropDown = () => {
//after generate download certifcate pdf
const handleDownload = (pdfBlob, fileName) => {
if (pdfBlob) {
const url = window.URL.createObjectURL(pdfBlob);
// Create a temporary anchor element
const link = document.createElement("a");
link.href = url;
link.download = fileName;
// Append the anchor to the body
document.body.appendChild(link);
// Programmatically click the anchor to trigger the download
link.click();
// Remove the anchor from the body
document.body.removeChild(link);
// Release the object URL to free up resources
window.URL.revokeObjectURL(url);
}
};
return (
<PDFDownloadLink
onClick={(e) => e.preventDefault()}
style={{ textDecoration: "none", zIndex: "35" }}
document={<Certificate pdfData={pdfDetails} />}
>
{({ blob, url, loading, error }) => (
<>
{loading ? (
<div
style={{
border: "none",
backgroundColor: "#fff"
}}
>
<i
className="fa fa-certificate"
style={{
marginRight: "2px"
}}
aria-hidden="true"
></i>
Certificate
</div>
) : (
<div
style={{
border: "none",
backgroundColor: "#fff"
}}
onClick={() =>
handleDownload(
blob,
`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`
)
}
>
<i
className="fa fa-certificate"
style={{
marginRight: "2px"
}}
aria-hidden="true"
></i>
Certificate
</div>
)}
</>
)}
</PDFDownloadLink>
);
};
const CertificateComponent = () => {
return (
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
<button
type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
) : (
<button
type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
);
};
return ( return (
<div <div
style={{ padding: !isGuestSigner && "5px 0px 5px 0px" }} style={{ padding: !isGuestSigner && "5px 0px 5px 0px" }}
className="mobileHead" className="mobileHead"
> >
{isMobile && isShowHeader ? ( {isMobile && isShowHeader ? (
@@ -231,9 +89,7 @@ function Header({
id="navbar" id="navbar"
className={isGuestSigner ? "stickySignerHead" : "stickyHead"} className={isGuestSigner ? "stickySignerHead" : "stickyHead"}
style={{ style={{
width: isGuestSigner width: isGuestSigner ? window.innerWidth : window.innerWidth - 30 + "px"
? window.innerWidth
: window.innerWidth - 30 + "px"
}} }}
> >
<div className="preBtn2"> <div className="preBtn2">
@@ -278,16 +134,16 @@ function Header({
style={{ color: "gray", cursor: "pointer" }} style={{ color: "gray", cursor: "pointer" }}
></i> ></i>
</div> </div>
{pdfUrl && alreadySign ? ( {pdfUrl ? (
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger asChild> <DropdownMenu.Trigger asChild>
<div <div
// onClick={() => handleDownloadPdf()}
style={{ style={{
color: themeColor(), color: themeColor(),
border: "none", border: "none",
fontWeight: "650", fontWeight: "650",
fontSize: "16px", fontSize: "16px"
padding: "0px 3px 0px 5px"
}} }}
> >
<i className="fa fa-ellipsis-v" aria-hidden="true"></i> <i className="fa fa-ellipsis-v" aria-hidden="true"></i>
@@ -317,41 +173,44 @@ function Header({
Download Download
</div> </div>
</DropdownMenu.Item> </DropdownMenu.Item>
{recipient && pdfDetails[0] && pdfDetails.length > 0 ? ( <DropdownMenu.Item className="DropdownMenuItem">
<DropdownMenu.Item className="DropdownMenuItem"> <PDFDownloadLink
<CertificateDropDown /> style={{ textDecoration: "none" }}
</DropdownMenu.Item> document={<Certificate pdfData={pdfDetails} />}
) : isPdfRequestFiles && fileName={`completion certificate-${
alreadySign && pdfDetails[0] && pdfDetails[0].Name
isCompleted.isCertificate ? ( }.pdf`}
<DropdownMenu.Item className="DropdownMenuItem">
<CertificateDropDown />
</DropdownMenu.Item>
) : (
isSignYourself && (
<DropdownMenu.Item className="DropdownMenuItem">
<CertificateDropDown />
</DropdownMenu.Item>
)
)}
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={handleToPrint}
>
<div
style={{
display: "flex",
flexDirection: "row"
}}
> >
{" "} {({ blob, url, loading, error }) => (
<i <>
className="fa fa-print" {console.log("error", error)}
aria-hidden="true" {loading ? (
style={{ marginRight: "2px" }} "Loading document..."
></i> ) : (
Print <button
</div> type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)}
</>
)}
</PDFDownloadLink>
</DropdownMenu.Item> </DropdownMenu.Item>
</DropdownMenu.Content> </DropdownMenu.Content>
</DropdownMenu.Portal> </DropdownMenu.Portal>
@@ -402,8 +261,6 @@ function Header({
onClick={() => { onClick={() => {
if (!pdfUrl) { if (!pdfUrl) {
embedImages(); embedImages();
} else if (isPdfRequestFiles) {
embedImages();
} }
}} }}
style={{ style={{
@@ -434,7 +291,40 @@ function Header({
pdfUrl || isAlreadySign.mssg ? ( pdfUrl || isAlreadySign.mssg ? (
<div style={{ display: "flex", flexDirection: "row" }}> <div style={{ display: "flex", flexDirection: "row" }}>
{pdfDetails[0] && pdfDetails.length > 0 && ( {pdfDetails[0] && pdfDetails.length > 0 && (
<CertificateComponent /> <PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<button
type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
)} )}
<button <button
onClick={handleToPrint} onClick={handleToPrint}
@@ -559,7 +449,42 @@ function Header({
) : isPdfRequestFiles ? ( ) : isPdfRequestFiles ? (
alreadySign ? ( alreadySign ? (
<div style={{ display: "flex", flexDirection: "row" }}> <div style={{ display: "flex", flexDirection: "row" }}>
{isCompleted.isCertificate && <CertificateComponent />} {isCompleted.isCertificate && (
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<button
type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
)}
<button <button
onClick={handleToPrint} onClick={handleToPrint}
type="button" type="button"
@@ -646,7 +571,40 @@ function Header({
) )
) : pdfUrl || (documentStatus && documentStatus.isCompleted) ? ( ) : pdfUrl || (documentStatus && documentStatus.isCompleted) ? (
<div style={{ display: "flex", flexDirection: "row" }}> <div style={{ display: "flex", flexDirection: "row" }}>
<CertificateComponent /> <PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<button
type="button"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
className="defaultBtn certificateBtn"
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
<button <button
onClick={handleToPrint} onClick={handleToPrint}
type="button" type="button"
File diff suppressed because it is too large Load Diff
@@ -17,12 +17,7 @@ import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata"; import Nodata from "./component/Nodata";
import SignerListPlace from "./component/signerListPlace"; import SignerListPlace from "./component/signerListPlace";
import Header from "./component/header"; import Header from "./component/header";
import { import { contactBook, contractUsers, getHostUrl } from "../utils/Utils";
pdfNewWidthFun,
contractDocument,
contractUsers,
getHostUrl
} from "../utils/Utils";
import RenderPdf from "./component/renderPdf"; import RenderPdf from "./component/renderPdf";
import ModalComponent from "./component/modalComponent"; import ModalComponent from "./component/modalComponent";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
@@ -36,10 +31,13 @@ function PlaceHolderSign() {
const [pageNumber, setPageNumber] = useState(1); const [pageNumber, setPageNumber] = useState(1);
const [signBtnPosition, setSignBtnPosition] = useState([]); const [signBtnPosition, setSignBtnPosition] = useState([]);
const [xySignature, setXYSignature] = useState({}); const [xySignature, setXYSignature] = useState({});
const signRef = useRef(null);
const dragRef = useRef(null);
const [dragKey, setDragKey] = useState(); const [dragKey, setDragKey] = useState();
const [signersdata, setSignersData] = useState(); const [signersdata, setSignersData] = useState();
const [signerObjId, setSignerObjId] = useState(); const [signerObjId, setSignerObjId] = useState();
const [signerPos, setSignerPos] = useState([]); const [signerPos, setSignerPos] = useState([]);
const [isSelectListId, setIsSelectId] = useState(); const [isSelectListId, setIsSelectId] = useState();
const [isSendAlert, setIsSendAlert] = useState({}); const [isSendAlert, setIsSendAlert] = useState({});
const [isSend, setIsSend] = useState(false); const [isSend, setIsSend] = useState(false);
@@ -58,9 +56,6 @@ function PlaceHolderSign() {
const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [contractName, setContractName] = useState(""); const [contractName, setContractName] = useState("");
const { docId } = useParams(); const { docId } = useParams();
const signRef = useRef(null);
const dragRef = useRef(null);
const divRef = useRef(null);
const [isShowEmail, setIsShowEmail] = useState(false); const [isShowEmail, setIsShowEmail] = useState(false);
const [selectedEmail, setSelectedEmail] = useState(false); const [selectedEmail, setSelectedEmail] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({ const [pdfLoadFail, setPdfLoadFail] = useState({
@@ -161,53 +156,69 @@ function PlaceHolderSign() {
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
useEffect(() => { useEffect(() => {
const clientWidth = window.innerWidth;
const value = docId ? 80 : 30;
const pdfWidth = clientWidth - 160 - 200 - value;
//160 is width of left side, 200 is width of right side component and 50 is space of middle compoent
//pdf from left and right component
setPdfNewWidth(pdfWidth);
if (documentId) { if (documentId) {
getDocumentDetails(); getDocumentDetails();
} }
}, []); }, []);
useEffect(() => {
if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
}
}, [divRef.current]);
//function for get document details //function for get document details
const getDocumentDetails = async () => { const getDocumentDetails = async () => {
//getting document details await axios
const documentData = await contractDocument(documentId); .get(
if (documentData && documentData.length > 0) { `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
setPdfDetails(documentData); "_appName"
)}_Document?where={"objectId":"${documentId}"}&include=ExtUserPtr,Signers`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
const currEmail = documentData[0].ExtUserPtr.Email; if (res[0] && res.length > 0) {
const filterCurrEmail = documentData[0].Signers.filter( setPdfDetails(res);
(data) => data.Email === currEmail
);
setCurrentEmail(filterCurrEmail); const currEmail = res[0].ExtUserPtr.Email;
setSignersData(documentData[0]); const filterCurrEmail = res[0].Signers.filter(
(data) => data.Email === currEmail
);
setSignerObjId(documentData[0].Signers[0].objectId); setCurrentEmail(filterCurrEmail);
setContractName(documentData[0].Signers[0].className); setSignersData(res[0]);
setIsSelectId(0);
} else if ( setSignerObjId(res[0].Signers[0].objectId);
documentData === "Error: Something went wrong!" || setContractName(res[0].Signers[0].className);
(documentData.result && documentData.result.error) setIsSelectId(0);
) { } else {
const loadObj = { setNoData(true);
isLoad: false const loadObj = {
}; isLoad: false
setHandleError("Error: Something went wrong!"); };
setIsLoading(loadObj); setIsLoading(loadObj);
} else { }
setNoData(true); })
.catch((err) => {
console.log("axois err ", err);
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
const res = await contractUsers(jsonSender.objectId);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const res = await contractUsers(jsonSender.email);
if (res[0] && res.length) { if (res[0] && res.length) {
setSignerUserId(res[0].objectId); setSignerUserId(res[0].objectId);
const tourstatus = res[0].TourStatus && res[0].TourStatus; const tourstatus = res[0].TourStatus && res[0].TourStatus;
@@ -231,12 +242,24 @@ function PlaceHolderSign() {
setHandleError("Error: Something went wrong!"); setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
} else if (res.length === 0) { } else if (res.length === 0) {
setNoData(true); const res = await contactBook(jsonSender.objectId);
if (res[0] && res.length) {
const loadObj = { setSignerUserId(res[0].objectId);
isLoad: false const tourstatus = res[0].TourStatus && res[0].TourStatus;
}; if (tourstatus && tourstatus.length > 0) {
setIsLoading(loadObj); setTourStatus(tourstatus);
const checkTourRecipients = tourstatus.filter(
(data) => data.placeholder
);
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].placeholder);
}
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
} }
}; };
@@ -833,7 +856,7 @@ function PlaceHolderSign() {
) : noData ? ( ) : noData ? (
<Nodata /> <Nodata />
) : ( ) : (
<div className="signatureContainer" ref={divRef}> <div className="signatureContainer">
{/* this component used for UI interaction and show their functionality */} {/* this component used for UI interaction and show their functionality */}
{!checkTourStatus && ( {!checkTourStatus && (
//this tour component used in your html component where you want to put //this tour component used in your html component where you want to put
@@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { PDFDocument } from "pdf-lib"; import { PDFDocument, rgb } from "pdf-lib";
import "../css/./signature.css"; import "../css/./signature.css";
import axios from "axios"; import axios from "axios";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
@@ -14,14 +14,7 @@ import DefaultSignature from "./component/defaultSignature";
import { import {
getBase64FromUrl, getBase64FromUrl,
getBase64FromIMG, getBase64FromIMG,
pdfNewWidthFun, contactBookName
convertPNGtoJPEG,
contractUsers,
contactBook,
contractDocument,
urlValidator,
multiSignEmbed,
embedDocId
} from "../utils/Utils"; } from "../utils/Utils";
import Tour from "reactour"; import Tour from "reactour";
import Signedby from "./component/signedby"; import Signedby from "./component/signedby";
@@ -32,7 +25,6 @@ import Nodata from "./component/Nodata";
import Header from "./component/header"; import Header from "./component/header";
import RenderPdf from "./component/renderPdf"; import RenderPdf from "./component/renderPdf";
import CustomModal from "./component/CustomModal"; import CustomModal from "./component/CustomModal";
import { modalAlign } from "../utils/Utils";
function EmbedPdfImage() { function EmbedPdfImage() {
const { id, contactBookId } = useParams(); const { id, contactBookId } = useParams();
const [isSignPad, setIsSignPad] = useState(false); const [isSignPad, setIsSignPad] = useState(false);
@@ -82,24 +74,18 @@ function EmbedPdfImage() {
return object.pageNumber === pageNumber; return object.pageNumber === pageNumber;
}); });
const divRef = useRef(null); const divRef = useRef(null);
const senderUser = localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
? localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
: `${localStorage.getItem("UserInformation")}` &&
`${localStorage.getItem("UserInformation")}`;
const jsonSender = JSON.parse(senderUser);
//check isGuestSigner is present in local if yes than handle login flow header in mobile view //check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner"); const isGuestSigner = localStorage.getItem("isGuestSigner");
useEffect(() => { useEffect(() => {
const clientWidth = window.innerWidth;
const pdfWidth = clientWidth - 160 - 220 - 30;
//160 is width of left side, 200 is width of right side component and 50 is space of middle compoent
//pdf from left and right component
setPdfNewWidth(pdfWidth);
getDocumentDetails(); getDocumentDetails();
}, []); }, []);
useEffect(() => { useEffect(() => {
if (divRef.current) { if (divRef.current) {
const pdfWidth = pdfNewWidthFun(divRef);
setPdfNewWidth(pdfWidth);
setContainerWH({ setContainerWH({
width: divRef.current.offsetWidth, width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight height: divRef.current.offsetHeight
@@ -110,26 +96,33 @@ function EmbedPdfImage() {
//function for get document details for perticular signer with signer'object id //function for get document details for perticular signer with signer'object id
const getDocumentDetails = async () => { const getDocumentDetails = async () => {
let currUserId, userObjectId; let currUserId, userObjectId;
//getting contracts_contactBook details const json = await contactBookName(contactBookId, "_Contactbook");
const json = await contactBook(contactBookId); if (json !== "Error: Something went wrong!" && json && json.results[0]) {
if (json && json.length > 0) {
setContractName("_Contactbook"); setContractName("_Contactbook");
if (json.results[0]) {
userObjectId = json.results[0].UserId.objectId;
setUserObjectID(userObjectId);
currUserId = json.results[0].objectId;
userObjectId = json[0].UserId.objectId; setSignerUserId(currUserId);
setUserObjectID(userObjectId); const tourstatus =
currUserId = json[0].objectId; json.results[0].TourStatus && json.results[0].TourStatus;
setSignerUserId(currUserId); if (tourstatus && tourstatus.length > 0) {
const tourstatus = json[0].TourStatus && json[0].TourStatus; setTourStatus(tourstatus);
const checkTourRecipients = tourstatus.filter(
if (tourstatus && tourstatus.length > 0) { (data) => data.recipientssign
setTourStatus(tourstatus); );
const checkTourRecipients = tourstatus.filter( if (checkTourRecipients && checkTourRecipients.length > 0) {
(data) => data.recipientssign setCheckTourStatus(checkTourRecipients[0].recipientssign);
); }
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].recipientssign);
} }
} else {
setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} }
} else if (json === "Error: Something went wrong!") { } else if (json === "Error: Something went wrong!") {
const loadObj = { const loadObj = {
@@ -138,16 +131,18 @@ function EmbedPdfImage() {
setHandleError("Error: Something went wrong!"); setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
} else { } else {
const json = await contractUsers(jsonSender.email); const json = await contactBookName(contactBookId, "_Users");
if (json && json.length > 0) {
if (json !== "Error: Something went wrong!" && json && json.results[0]) {
setContractName("_Users"); setContractName("_Users");
if (json[0]) { if (json.results[0]) {
userObjectId = json[0].UserId.objectId; userObjectId = json.results[0].UserId.objectId;
setUserObjectID(userObjectId); setUserObjectID(userObjectId);
currUserId = json[0].objectId; currUserId = json.results[0].objectId;
setSignerUserId(currUserId); setSignerUserId(currUserId);
const tourstatus = json[0].TourStatus && json[0].TourStatus; const tourstatus =
json.results[0].TourStatus && json.results[0].TourStatus;
if (tourstatus && tourstatus.length > 0) { if (tourstatus && tourstatus.length > 0) {
setTourStatus(tourstatus); setTourStatus(tourstatus);
@@ -171,170 +166,171 @@ function EmbedPdfImage() {
}; };
setHandleError("Error: Something went wrong!"); setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
} else { }
setNoData(true); }
await axios
.get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document?where={"objectId":"${docId}"}&include=ExtUserPtr,Signers,AuditTrail
,`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
const declined = res[0].IsDeclined && res[0].IsDeclined;
const isCompleted = res[0].IsCompleted && res[0].IsCompleted;
const expireDate = res[0].ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
if (isCompleted) {
//checking document is completed (signed by all requested signers) than isCompleted true
//then show alert with completed message
const alreadySign = {
status: true,
mssg: "This document has been successfully signed!"
};
setIsAlreadySign(alreadySign);
setPdfUrl(res[0].SignedUrl);
setSignedPdfData(json.results);
setCompletePdfData(res);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
setSignedPdfData(json.results);
} else if (currDate > expireUpdateDate) {
setIsExpired(true);
const checkDocIdExist =
json.results[0].AuditTrail &&
json.results[0].AuditTrail.length > 0 &&
json.results[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
//if signed by someone than go to in if condition
// and second signer could not be add documentId
//for that setIsDocId true
if (checkDocIdExist && checkDocIdExist.length > 0) {
setIsDocId(true);
const currUser =
json.results[0].Placeholders &&
json.results[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(json.results);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
//for show current requested signer's placeholder
else {
const currUser =
json.results[0].Placeholders &&
json.results[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(json.results);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
} else {
//checking document has signed by someone or not
const checkDocIdExist =
json.results[0].AuditTrail &&
json.results[0].AuditTrail.length > 0 &&
json.results[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
//if signed by someone than go to in if condition
// and second signer could not be add documentId
//for that setIsDocId true
if (checkDocIdExist && checkDocIdExist.length > 0) {
setIsDocId(true);
//condition for checking document signed by current requested user or not
const checkAlreadyBySigner = json.results[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId &&
data.Activity === "Signed"
);
// if checkAlreadyBySigner has some data that current user already sign this document
// then show alert with message
if (checkAlreadyBySigner && checkAlreadyBySigner.length > 0) {
const alreadySign = {
status: true,
mssg: "You have successfully signed the document!"
};
setIsAlreadySign(alreadySign);
setPdfUrl(res[0].SignedUrl);
setSignedPdfData(json.results);
}
//else show placeholder of current requested signer
else {
const currUser =
json.results[0].Placeholders &&
json.results[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(json.results);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
}
//for show current requested signer's placeholder
else {
const currUser =
json.results[0].Placeholders &&
json.results[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(json.results);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
}
}
})
.catch((err) => {
const loadObj = { const loadObj = {
isLoad: false isLoad: false
}; };
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
} console.log("err", err);
} });
//getting document details
const documentData = await contractDocument(docId);
if (documentData && documentData.length > 0) {
const declined = documentData[0].IsDeclined && documentData[0].IsDeclined;
const isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
const expireDate = documentData[0].ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
if (isCompleted) {
//checking document is completed (signed by all requested signers) than isCompleted true
//then show alert with completed message
const alreadySign = {
status: true,
mssg: "This document has been successfully signed!"
};
setIsAlreadySign(alreadySign);
setPdfUrl(documentData[0].SignedUrl);
setSignedPdfData(documentData);
setCompletePdfData(documentData);
} else if (declined) {
const currentDecline = {
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline);
setSignedPdfData(documentData);
} else if (currDate > expireUpdateDate) {
setIsExpired(true);
const checkDocIdExist =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
//if signed by someone than go to in if condition
// and second signer could not be add documentId
//for that setIsDocId true
if (checkDocIdExist && checkDocIdExist.length > 0) {
setIsDocId(true);
const currUser =
documentData.Placeholders &&
documentData.Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(documentData);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
//for show current requested signer's placeholder
else {
const currUser =
documentData[0].Placeholders &&
documentData[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(documentData);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
} else {
//checking document has signed by someone or not
const checkDocIdExist =
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => data.Activity === "Signed"
);
//if signed by someone than go to in if condition
// and second signer could not be add documentId
//for that setIsDocId true
if (checkDocIdExist && checkDocIdExist.length > 0) {
setIsDocId(true);
//condition for checking document signed by current requested user or not
const checkAlreadyBySigner = documentData[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId && data.Activity === "Signed"
);
// if checkAlreadyBySigner has some data that current user already sign this document
// then show alert with message
if (checkAlreadyBySigner && checkAlreadyBySigner.length > 0) {
const alreadySign = {
status: true,
mssg: "You have successfully signed the document!"
};
setIsAlreadySign(alreadySign);
setPdfUrl(documentData[0].SignedUrl);
setSignedPdfData(documentData);
}
//else show placeholder of current requested signer
else {
const currUser =
documentData[0].Placeholders &&
documentData[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(documentData);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
}
//for show current requested signer's placeholder
else {
const currUser =
documentData[0].Placeholders &&
documentData[0].Placeholders.filter(
(data) => data.signerObjId === currUserId
);
setSignedPdfData(documentData);
setXyPostion(currUser[0].placeHolder);
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
}
}
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
await axios await axios
.get( .get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -423,8 +419,23 @@ function EmbedPdfImage() {
if (isDocId) { if (isDocId) {
pdfBase64 = await getBase64FromUrl(url); pdfBase64 = await getBase64FromUrl(url);
} else { } else {
//embed document's object id to all pages in pdf document for (let i = 0; i < allPages; i++) {
await embedDocId(pdfDoc, docId, allPages); const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 10;
const textContent = docId && `OpenSign™ DocumentId: ${docId} `;
const pages = pdfDoc.getPages();
const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
pdfBase64 = await pdfDoc.saveAsBase64({ useObjectStreams: false }); pdfBase64 = await pdfDoc.saveAsBase64({ useObjectStreams: false });
} }
for (let i = 0; i < xyPostion.length; i++) { for (let i = 0; i < xyPostion.length; i++) {
@@ -433,13 +444,38 @@ function EmbedPdfImage() {
imgUrlList.map(async (data) => { imgUrlList.map(async (data) => {
//cheking signUrl is defau;t signature url of custom url //cheking signUrl is defau;t signature url of custom url
let ImgUrl = data.SignUrl; let ImgUrl = data.SignUrl;
const checkUrl = urlValidator(ImgUrl); const checkUrl = ImgUrl.includes("https:");
//if default signature url then convert it in base 64 //if default signature url then convert it in base 64
if (checkUrl) { if (checkUrl) {
ImgUrl = await getBase64FromIMG(ImgUrl + "?get"); ImgUrl = await getBase64FromIMG(ImgUrl + "?get");
} }
//function for convert signature png base64 url to jpeg base64 //function for called convert png signatre to jpeg in base 64
const convertPNGtoJPEG = (base64Data) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas");
const img = new Image();
img.src = base64Data;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Convert to JPEG by using the canvas.toDataURL() method
const jpegBase64Data = canvas.toDataURL("image/jpeg");
resolve(jpegBase64Data);
};
img.onerror = (error) => {
reject(error);
};
});
};
convertPNGtoJPEG(ImgUrl) convertPNGtoJPEG(ImgUrl)
.then((jpegBase64Data) => { .then((jpegBase64Data) => {
const removeBase64Fromjpeg = "data:image/jpeg;base64,"; const removeBase64Fromjpeg = "data:image/jpeg;base64,";
@@ -459,18 +495,123 @@ function EmbedPdfImage() {
} }
//else if signature is more than one then embed all sign with the use of pdf-lib //else if signature is more than one then embed all sign with the use of pdf-lib
else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) { else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) {
//embed document's object id to all pages in pdf document for (let i = 0; i < allPages; i++) {
await embedDocId(pdfDoc, docId, allPages); const font = await pdfDoc.embedFont("Helvetica");
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed( const fontSize = 10;
pngUrl, const textContent = docId && `OpenSign™ DocumentId: ${docId} `;
pdfDoc,
pdfOriginalWidth, const pages = pdfDoc.getPages();
false const page = pages[i];
);
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
for (let i = 0; i < pngUrl.length; i++) {
const pageNo = pngUrl[i].pageNumber;
const imgUrlList = pngUrl[i].pos;
const pages = pdfDoc.getPages();
const page = pages[pageNo - 1];
const images = await Promise.all(
imgUrlList.map(async (url) => {
let signUrl = url.SignUrl;
const checkUrl = url.SignUrl.includes("https:");
if (checkUrl) {
signUrl = signUrl + "?get";
}
const res = await fetch(signUrl);
return res.arrayBuffer();
})
);
images.forEach(async (imgData, id) => {
let img;
if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/jpeg"
) {
img = await pdfDoc.embedJpg(imgData);
} else if (
imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/png"
) {
img = await pdfDoc.embedPng(imgData);
} else {
img = await pdfDoc.embedPng(imgData);
}
const imgHeight = imgUrlList[id].Height
? imgUrlList[id].Height
: 60;
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const xPos = (pos) => {
//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 = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / 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 = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yPos = (pos) => {
//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 y = pos.yPosition * (pos.scale / scale);
return page.getHeight() - y * scale - imgHeight;
} else {
const y = pos.yPosition / scale;
return page.getHeight() - y * scale - imgHeight;
}
} 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 y = pos.yPosition * pos.scale;
return page.getHeight() - y - imgHeight;
} else {
return page.getHeight() - pos.yPosition - imgHeight;
}
}
};
page.drawImage(img, {
x: xPos(imgUrlList[id]),
y: yPos(imgUrlList[id]),
width: imgWidth,
height: imgHeight
});
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
signPdfFun(pdfBytes, docId); signPdfFun(pdfBytes, docId);
} }
setIsSignPad(false); setIsSignPad(false);
setXyPostion([]); setXyPostion([]);
} }
} }
@@ -521,8 +662,8 @@ function EmbedPdfImage() {
yPosition = pos.isDrag yPosition = pos.isDrag
? y * scale - height ? y * scale - height
: pos.firstYPos : pos.firstYPos
? y * scale - height + pos.firstYPos ? y * scale - height + pos.firstYPos
: y * scale - height; : y * scale - height;
return yPosition; return yPosition;
} else { } else {
const y = pos.yBottom / scale; const y = pos.yBottom / scale;
@@ -530,8 +671,8 @@ function EmbedPdfImage() {
yPosition = pos.isDrag yPosition = pos.isDrag
? y * scale - height ? y * scale - height
: pos.firstYPos : pos.firstYPos
? y * scale - height + pos.firstYPos ? y * scale - height + pos.firstYPos
: y * scale - height; : y * scale - height;
return yPosition; return yPosition;
} }
} else { } else {
@@ -542,15 +683,15 @@ function EmbedPdfImage() {
yPosition = pos.isDrag yPosition = pos.isDrag
? y - height ? y - height
: pos.firstYPos : pos.firstYPos
? y - height + pos.firstYPos ? y - height + pos.firstYPos
: y - height; : y - height;
return yPosition; return yPosition;
} else { } else {
yPosition = pos.isDrag yPosition = pos.isDrag
? pos.yBottom - height ? pos.yBottom - height
: pos.firstYPos : pos.firstYPos
? pos.yBottom - height + pos.firstYPos ? pos.yBottom - height + pos.firstYPos
: pos.yBottom - height; : pos.yBottom - height;
return yPosition; return yPosition;
} }
} }
@@ -875,11 +1016,7 @@ function EmbedPdfImage() {
}} }}
> >
{/* this modal is used show this document is already sign */} {/* this modal is used show this document is already sign */}
<Modal <Modal show={isAlreadySign.status}>
show={isAlreadySign.status}
onShow={() => modalAlign()}
backdropClassName="signature-backdrop"
>
<ModalHeader style={{ background: themeColor() }}> <ModalHeader style={{ background: themeColor() }}>
<span style={{ color: "white" }}> Sign Documents</span> <span style={{ color: "white" }}> Sign Documents</span>
</ModalHeader> </ModalHeader>
@@ -935,7 +1072,7 @@ function EmbedPdfImage() {
{/* pdf header which contain finish back button */} {/* pdf header which contain finish back button */}
<Header <Header
recipient={true} recipient={true}
pdfDetails={signedPdfData} pdfDetails={completePdfData}
isAlreadySign={isAlreadySign} isAlreadySign={isAlreadySign}
pageNumber={pageNumber} pageNumber={pageNumber}
allPages={allPages} allPages={allPages}
@@ -946,7 +1083,6 @@ function EmbedPdfImage() {
isShowHeader={true} isShowHeader={true}
currentSigner={true} currentSigner={true}
decline={true} decline={true}
alreadySign={pdfUrl ? true : false}
/> />
<RenderPdf <RenderPdf
@@ -991,8 +1127,9 @@ function EmbedPdfImage() {
)} )}
</div> </div>
)} )}
</DndProvider> </DndProvider>
); );
} }
export default EmbedPdfImage; export default EmbedPdfImage;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

@@ -80,10 +80,6 @@
padding: 5px 10px; padding: 5px 10px;
} }
.emailChipClose:hover {
cursor: pointer;
}
.addEmailInput { .addEmailInput {
padding: 10px; padding: 10px;
border-radius: 4px; border-radius: 4px;
@@ -378,13 +374,15 @@
font-size: 50px; font-size: 50px;
} }
.DropdownMenuContent, .DropdownMenuContent,
.DropdownMenuSubContent { .DropdownMenuSubContent {
min-width: 130px; min-width: 130px;
background-color: #fff; background-color: #887abf;
border: 1px solid rgba(0, 0, 0, .15); border: none;
border-radius: 0.25rem;
padding: 5px; padding: 5px;
animation-duration: 400ms; animation-duration: 400ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
will-change: transform, opacity; will-change: transform, opacity;
@@ -415,13 +413,13 @@
font-size: 13px; font-size: 13px;
line-height: 1; line-height: 1;
color: black; color: black;
background-color: #fff; background-color: #887abf;
display: flex; display: flex;
align-items: center; align-items: center;
height: 25px; height: 25px;
padding: 0 5px; padding: 0 5px;
position: relative; position: relative;
padding-left: 20px; padding-left: 25px;
user-select: none; user-select: none;
outline: none; outline: none;
border: none; border: none;
@@ -567,13 +565,13 @@ option {
color: var(--violet-11); color: var(--violet-11);
cursor: default; cursor: default;
} }
.fontOptionContainer{
.fontOptionContainer { border: 1px solid #d6d3d3;
border: 1px solid #d6d3d3; margin: 10px 5px 5px 5px;
margin: 10px 5px 5px 5px;
} }
@media screen and (max-width:766px) { @media screen and (max-width:766px) {
.showPages { .showPages {
@@ -630,27 +628,25 @@ option {
padding: 16px; padding: 16px;
} }
/* The sticky class is added to the navbar /* The sticky class is added to the navbar
with JS when it reaches its scroll position */ with JS when it reaches its scroll position */
.stickyHead { .stickyHead {
position: fixed;
top: 50px; top: 50px;
left: 0.9rem; left: 0.9rem;
} }
.stickySignerHead{
.stickySignerHead { position: fixed;
}
.stickyfooter {
position: fixed; position: fixed;
}
.stickyfooter {
position: fixed;
z-index: 32 !important;
bottom: 0px; bottom: 0px;
right: 0rem; right: 0rem;
} }
/* Add some top padding to the page content /* Add some top padding to the page content
to prevent sudden quick movement (as the to prevent sudden quick movement (as the
navigation bar gets a new position at the top of the navigation bar gets a new position at the top of the
page (position:fixed and top:0) */ page (position:fixed and top:0) */
.stickyHead+.content { .stickyHead+.content {
padding-top: 60px; padding-top: 60px;
@@ -780,14 +776,4 @@ option {
.mobileHead { .mobileHead {
display: flex; display: flex;
} }
} }
.signature-backdrop {
position: fixed;
top: 0; bottom: 0; left: 0; right: 0;
background-color: #000;
}
.signature-backdrop.fade.in {
opacity: 0.5;
}
+45 -271
View File
@@ -1,6 +1,5 @@
import axios from "axios"; import axios from "axios";
import { $ } from "select-dom";
import { rgb } from "pdf-lib";
export async function getBase64FromUrl(url) { export async function getBase64FromUrl(url) {
const data = await fetch(url); const data = await fetch(url);
const blob = await data.blob(); const blob = await data.blob();
@@ -29,35 +28,13 @@ export async function getBase64FromIMG(url) {
}; };
}); });
} }
//function for convert signature png base64 url to jpeg base64
export const convertPNGtoJPEG = (base64Data) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas");
const img = new Image();
img.src = base64Data;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#ffffff"; // white color
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
// Convert to JPEG by using the canvas.toDataURL() method
const jpegBase64Data = canvas.toDataURL("image/jpeg");
resolve(jpegBase64Data);
};
img.onerror = (error) => {
reject(error);
};
});
};
export function getHostUrl() { export function getHostUrl() {
const hostUrl = window.location.href; const hostUrl = window.location.href;
/// const hostUrl = "https://contracts-defaultssty.qik.ai/#/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive";
// const hostUrl = "https://contracts-defaultssty.qik.ai/#/"
// const hostUrl = "https://lionfish-app-75ly7.ondigitalocean.app/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
//const hostUrl = "https://app.opensignlabs.com/rpmf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument";
if (hostUrl) { if (hostUrl) {
const urlSplit = hostUrl.split("/"); const urlSplit = hostUrl.split("/");
@@ -80,6 +57,7 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
(data, ind) => (data, ind) =>
data.key === signKey && data.Width && data.Height && data.SignUrl data.key === signKey && data.Width && data.Height && data.SignUrl
); );
if (updateFilter.length > 0) { if (updateFilter.length > 0) {
let newWidth, newHeight; let newWidth, newHeight;
@@ -161,7 +139,7 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
...url, ...url,
Width: getPosData[0].Width ? getPosData[0].Width : newWidth, Width: getPosData[0].Width ? getPosData[0].Width : newWidth,
Height: getPosData[0].Height ? getPosData[0].Height : newHeight, Height: getPosData[0].Height ? getPosData[0].Height : newHeight,
SignUrl: image.src, SignUrl: image.src,
ImageType: image.imgType ImageType: image.imgType
}; };
} }
@@ -175,6 +153,7 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
return obj; return obj;
}); });
return newUpdateUrl; return newUpdateUrl;
// setXyPostion(newUpdateUrl);
} }
} }
@@ -204,105 +183,40 @@ export function onSaveSign(xyPostion, index, signKey, signatureImg) {
return newUpdateUrl; return newUpdateUrl;
} }
//function for getting document details from contract_Documents class
export const contractDocument = async (documentId) => {
const data = {
docId: documentId
};
const documentDeatils = await axios
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
})
.then((Listdata) => {
const json = Listdata.data;
let data = [];
if (json && json.result.error) {
return json;
} else if (json && json.result) {
data.push(json.result);
return data;
} else {
return [];
}
})
.catch((err) => {
return "Error: Something went wrong!";
});
return documentDeatils;
};
//function for getting document details for getDrive
export const getDrive = async (documentId) => {
const data = {
docId: documentId && documentId
};
const driveDeatils = await axios
.post(`${localStorage.getItem("baseUrl")}functions/getDrive`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
}
})
.then((Listdata) => {
const json = Listdata.data;
if (json && json.result.error) {
return json;
} else if (json && json.result) {
const data = json.result;
return data;
} else {
return [];
}
})
.catch((err) => {
return "Error: Something went wrong!";
});
return driveDeatils;
};
//function for getting contract_User details //function for getting contract_User details
export const contractUsers = async (email) => { export const contractUsers = async (objectId) => {
const data = { const result = await axios
email: email .get(
}; `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
const userDetails = await axios "_appName"
.post(`${localStorage.getItem("baseUrl")}functions/getUserDetails`, data, { )}_Users?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${objectId}"}}`,
headers: { {
"Content-Type": "application/json", headers: {
"X-Parse-Application-Id": localStorage.getItem("parseAppId"), "Content-Type": "application/json",
sessionToken: localStorage.getItem("accesstoken") "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
} }
}) )
.then((Listdata) => { .then((Listdata) => {
const json = Listdata.data; const json = Listdata.data;
let data = []; const res = json.results;
return res;
if (json && json.result) {
data.push(json.result);
return data;
}
}) })
.catch((err) => { .catch((err) => {
return "Error: Something went wrong!"; return "Error: Something went wrong!";
}); });
return userDetails; return result;
}; };
//function for getting contracts_contactbook details //function for getting contrscts_contactbook details
export const contactBook = async (objectId) => { export const contactBook = async (objectId) => {
const result = await axios const result = await axios
.get( .get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName" "_appName"
)}_Contactbook?where={"objectId":"${objectId}"}`, )}_Contactbook?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${objectId}"}}`,
{ {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -323,166 +237,26 @@ export const contactBook = async (objectId) => {
return result; return result;
}; };
// function for validating URLs export const contactBookName = async (objectId, className) => {
export function urlValidator(url) { const result = await axios
try { .get(
const newUrl = new URL(url); `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
return newUrl.protocol === "http:" || newUrl.protocol === "https:"; "_appName"
} catch (err) { )}${className}?where={"objectId":"${objectId}"}`,
return false; {
} headers: {
} "Content-Type": "application/json",
export function modalAlign() { "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
let modalDialog = $(".modal-dialog").getBoundingClientRect(); "X-Parse-Session-Token": localStorage.getItem("accesstoken")
let mobileHead = $(".mobileHead").getBoundingClientRect();
let modal = $(".modal-dialog");
if (modalDialog.left < mobileHead.left) {
let leftOffset = mobileHead.left - modalDialog.left;
modal.style.left = leftOffset + "px";
modal.style.top = window.innerHeight / 3 + "px";
}
}
//function for embed multiple signature using pdf-lib
export const multiSignEmbed = async (
pngUrl,
pdfDoc,
pdfOriginalWidth,
signyourself
) => {
for (let i = 0; i < pngUrl.length; i++) {
const pageNo = pngUrl[i].pageNumber;
const imgUrlList = pngUrl[i].pos;
const pages = pdfDoc.getPages();
const page = pages[pageNo - 1];
const images = await Promise.all(
imgUrlList.map(async (url) => {
let signUrl = url.SignUrl;
if (url.ImageType === "image/png") {
//function for convert signature png base64 url to jpeg base64
const newUrl = await convertPNGtoJPEG(signUrl);
signUrl = newUrl;
} }
const checkUrl = urlValidator(signUrl);
if (checkUrl) {
signUrl = signUrl + "?get";
}
const res = await fetch(signUrl);
return res.arrayBuffer();
})
);
images.forEach(async (imgData, id) => {
let img;
if (
(imgUrlList[id].ImageType &&
imgUrlList[id].ImageType === "image/png") ||
imgUrlList[id].ImageType === "image/jpeg"
) {
img = await pdfDoc.embedJpg(imgData);
} else {
img = await pdfDoc.embedPng(imgData);
} }
const imgHeight = imgUrlList[id].Height ? imgUrlList[id].Height : 60; )
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150; .then((Listdata) => {
const isMobile = window.innerWidth < 767; const json = Listdata.data;
const newWidth = window.innerWidth - 32; return json;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1; })
const xPos = (pos) => { .catch((err) => {
if (signyourself) { return "Error: Something went wrong!";
if (isMobile) {
return imgUrlList[id].xPosition * scale + 43;
} else {
return imgUrlList[id].xPosition;
}
} 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 = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / 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 = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
}
};
const yPos = (pos) => {
if (signyourself) {
if (isMobile) {
return (
page.getHeight() -
imgUrlList[id].yPosition * scale -
imgHeight * scale
);
} else {
return page.getHeight() - imgUrlList[id].yPosition - imgHeight;
}
} else {
//checking both condition mobile and desktop view
const y = pos.yPosition / 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 = pos.yPosition * (pos.scale / scale);
return page.getHeight() - y * scale - imgHeight;
} else {
return page.getHeight() - y * scale - imgHeight;
}
} 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 y = pos.yPosition * pos.scale;
return page.getHeight() - y - imgHeight;
} else {
return page.getHeight() - pos.yPosition - imgHeight;
}
}
}
};
page.drawImage(img, {
x: xPos(imgUrlList[id]),
y: yPos(imgUrlList[id]),
width: signyourself ? imgWidth * scale : imgWidth,
height: signyourself ? imgHeight * scale : imgHeight
});
}); });
} return result;
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
return pdfBytes;
};
//function for embed document id
export const embedDocId = async (pdfDoc, documentId, allPages) => {
for (let i = 0; i < allPages; i++) {
const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 10;
const textContent = documentId && `OpenSign™ DocumentId: ${documentId} `;
const pages = pdfDoc.getPages();
const page = pages[i];
page.drawText(textContent, {
x: 10,
y: page.getHeight() - 10,
size: fontSize,
font,
color: rgb(0.5, 0.5, 0.5)
});
}
};
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
return pdfWidth;
}; };
-704
View File
@@ -1,704 +0,0 @@
{
"name": "opensign",
"version": "1.0.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "opensign",
"version": "1.0.6",
"license": "AGPL-3.0",
"devDependencies": {
"husky": "^8.0.0",
"lint-staged": "^15.1.0",
"prettier": "3.1.0"
}
},
"node_modules/ansi-escapes": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz",
"integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==",
"dev": true,
"dependencies": {
"type-fest": "^1.0.2"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chalk": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/cli-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
"integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
"dev": true,
"dependencies": {
"restore-cursor": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-truncate": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
"integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==",
"dev": true,
"dependencies": {
"slice-ansi": "^5.0.0",
"string-width": "^5.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true,
"engines": {
"node": ">=16"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
},
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
"dev": true
},
"node_modules/execa": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
"integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^8.0.1",
"human-signals": "^5.0.0",
"is-stream": "^3.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^5.1.0",
"onetime": "^6.0.0",
"signal-exit": "^4.1.0",
"strip-final-newline": "^3.0.0"
},
"engines": {
"node": ">=16.17"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/get-stream": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
"dev": true,
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/human-signals": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
"dev": true,
"engines": {
"node": ">=16.17.0"
}
},
"node_modules/husky": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
"integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
"dev": true,
"bin": {
"husky": "lib/bin.js"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
"integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/lint-staged": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.1.0.tgz",
"integrity": "sha512-ZPKXWHVlL7uwVpy8OZ7YQjYDAuO5X4kMh0XgZvPNxLcCCngd0PO5jKQyy3+s4TL2EnHoIXIzP1422f/l3nZKMw==",
"dev": true,
"dependencies": {
"chalk": "5.3.0",
"commander": "11.1.0",
"debug": "4.3.4",
"execa": "8.0.1",
"lilconfig": "2.1.0",
"listr2": "7.0.2",
"micromatch": "4.0.5",
"pidtree": "0.6.0",
"string-argv": "0.3.2",
"yaml": "2.3.4"
},
"bin": {
"lint-staged": "bin/lint-staged.js"
},
"engines": {
"node": ">=18.12.0"
},
"funding": {
"url": "https://opencollective.com/lint-staged"
}
},
"node_modules/listr2": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/listr2/-/listr2-7.0.2.tgz",
"integrity": "sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==",
"dev": true,
"dependencies": {
"cli-truncate": "^3.1.0",
"colorette": "^2.0.20",
"eventemitter3": "^5.0.1",
"log-update": "^5.0.1",
"rfdc": "^1.3.0",
"wrap-ansi": "^8.1.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/log-update": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz",
"integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==",
"dev": true,
"dependencies": {
"ansi-escapes": "^5.0.0",
"cli-cursor": "^4.0.0",
"slice-ansi": "^5.0.0",
"strip-ansi": "^7.0.1",
"wrap-ansi": "^8.0.1"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"dev": true,
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"dev": true,
"dependencies": {
"path-key": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm-run-path/node_modules/path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dev": true,
"dependencies": {
"mimic-fn": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pidtree": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
"dev": true,
"bin": {
"pidtree": "bin/pidtree.js"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/prettier": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz",
"integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/restore-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
"dev": true,
"dependencies": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/restore-cursor/node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/restore-cursor/node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
"dependencies": {
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/restore-cursor/node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true
},
"node_modules/rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
"dev": true
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/slice-ansi": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
"integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.0.0",
"is-fullwidth-code-point": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/string-argv": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
"dev": true,
"engines": {
"node": ">=0.6.19"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/type-fest": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/yaml": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
"dev": true,
"engines": {
"node": ">= 14"
}
}
}
}
-30
View File
@@ -1,30 +0,0 @@
{
"name": "opensign",
"version": "1.0.6",
"description": "Free and open source alternative to DocuSign",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "husky install",
"lint-staged-changes": "lint-staged"
},
"repository": {
"type": "git",
"url": "github.com/opensignlabs/opensign"
},
"keywords": [
"digital",
"signature",
"e-signature",
"docusign",
"electronic",
"signature"
],
"author": "OpenSignLabs",
"license": "AGPL-3.0",
"devDependencies": {
"husky": "^8.0.0",
"lint-staged": "^15.1.0",
"prettier": "3.1.0"
}
}