Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97bd375de3 | ||
|
|
e2d450f9aa | ||
|
|
add01cb02a | ||
|
|
cea1653805 | ||
|
|
79e3762b36 | ||
|
|
aa04a957ed | ||
|
|
d31910aefa | ||
|
|
96a4a2e7fa | ||
|
|
e8aaab99f9 | ||
|
|
0ee85f53da | ||
|
|
748e2196da | ||
|
|
58199a934a | ||
|
|
7eec822a65 | ||
|
|
6c21028523 | ||
|
|
099a3cc46d | ||
|
|
5adaffc684 | ||
|
|
d588caf6d4 | ||
|
|
5930fd940d | ||
|
|
741f66b019 | ||
|
|
0bf07c2703 | ||
|
|
de26c2d719 | ||
|
|
881ac12b03 | ||
|
|
1932dda6d6 | ||
|
|
46159b7214 | ||
|
|
c57c15a4cb | ||
|
|
724fa7c27e | ||
|
|
2762c3e170 | ||
|
|
10a0c60056 | ||
|
|
036c9b8d4a | ||
|
|
1f50368259 | ||
|
|
6d5e07dac7 | ||
|
|
3656175f11 | ||
|
|
febb50c3cd | ||
|
|
f8ba0d357b | ||
|
|
74bfd39abc | ||
|
|
5a25b2d874 | ||
|
|
3115ff3e2a | ||
|
|
d1e7b9a2ab | ||
|
|
adbf1fe1e0 | ||
|
|
60140885e0 | ||
|
|
fe2f3c5f7c | ||
|
|
a06723ff3f | ||
|
|
12a6a84450 | ||
|
|
1f350fc459 | ||
|
|
d9fd2a5531 | ||
|
|
cd4fd6e3de | ||
|
|
49cd30de96 | ||
|
|
a24ebe25a8 | ||
|
|
3e664bf677 | ||
|
|
6161e975fb | ||
|
|
c2a45c230b | ||
|
|
a629aa0bff | ||
|
|
899678d98a | ||
|
|
076a0f54c5 | ||
|
|
a94e67cd7c | ||
|
|
e78a3991f0 | ||
|
|
593a8499f4 | ||
|
|
70d643a5e2 | ||
|
|
f2b1a54695 | ||
|
|
4353a4f732 | ||
|
|
34c99edf1a | ||
|
|
91f3bdb299 | ||
|
|
276fc974fa | ||
|
|
081e11f9af | ||
|
|
4f056cc9d3 | ||
|
|
d9da25e908 | ||
|
|
99b3436c8c | ||
|
|
452d4d7a1d | ||
|
|
ed613c3424 | ||
|
|
bf70fa0b11 | ||
|
|
8684197d49 | ||
|
|
648d1224b3 | ||
|
|
126b6ad355 | ||
|
|
0512f27e2e | ||
|
|
2c61630017 | ||
|
|
72c2b2dde6 | ||
|
|
29eb78c960 | ||
|
|
aa9ba05dde | ||
|
|
365b074f62 | ||
|
|
af6cb4c17d | ||
|
|
6bcad91b0f | ||
|
|
1aa2b003b2 | ||
|
|
1a27e9addf | ||
|
|
c2891a0858 | ||
|
|
c1b226db96 | ||
|
|
8a01efee4c | ||
|
|
eafb26d462 | ||
|
|
62e1a1bd9b | ||
|
|
58eb71c52d | ||
|
|
c1e6f2b5ab | ||
|
|
ba0c18b591 | ||
|
|
c3a902dcc7 | ||
|
|
5ece3c0694 | ||
|
|
1053540410 | ||
|
|
24773759c2 | ||
|
|
7a6de70169 | ||
|
|
04b2c7c4da | ||
|
|
d11171e91c | ||
|
|
a4a78cb96c | ||
|
|
dfdcde8fcc | ||
|
|
5e1b84d2e6 | ||
|
|
e643d96797 | ||
|
|
1ff4160ca4 | ||
|
|
62f66bf524 | ||
|
|
de3bc37fa5 | ||
|
|
ea660384c3 | ||
|
|
210cb5e754 | ||
|
|
ed45bfef84 | ||
|
|
a8e77e93f7 | ||
|
|
969071bb28 | ||
|
|
76491a77f1 | ||
|
|
9a51eed2bc | ||
|
|
a675a3c8fd | ||
|
|
fea30930eb | ||
|
|
7373b086e4 | ||
|
|
2fc1eda761 | ||
|
|
2c100ad399 | ||
|
|
1cefe01aee | ||
|
|
f1cf395761 | ||
|
|
4af3d8f78b | ||
|
|
cf21ac7405 | ||
|
|
5f11e92c0c | ||
|
|
c3ffda4dd2 | ||
|
|
c929b6b7a9 | ||
|
|
eb2abd3e6d | ||
|
|
1c4c2e87b4 | ||
|
|
4fda5b4531 | ||
|
|
df61e143af | ||
|
|
3a55c35445 | ||
|
|
08476ba3d6 | ||
|
|
db9ae71d67 | ||
|
|
39806e3ad6 | ||
|
|
7882c61b81 | ||
|
|
b8f886902f | ||
|
|
17660dae21 | ||
|
|
7584667643 | ||
|
|
b47d1cff07 | ||
|
|
b99d8e6d6e | ||
|
|
8b15bceac8 | ||
|
|
86b0e90948 | ||
|
|
3bc57a999c | ||
|
|
27730c89e8 | ||
|
|
82eeffa6e4 | ||
|
|
53147caebc | ||
|
|
6004522d5c | ||
|
|
266c2463c9 | ||
|
|
1b215f53e7 | ||
|
|
73b2ba6abd | ||
|
|
c04fd80a38 | ||
|
|
61b123cb61 | ||
|
|
08e805569f | ||
|
|
375aa0b7e7 | ||
|
|
b94e0fa052 | ||
|
|
b6752549ed | ||
|
|
51505af6d8 | ||
|
|
0e5cffa1fa | ||
|
|
885b5287b4 | ||
|
|
5348c6620a | ||
|
|
73c219fa4d | ||
|
|
f4090c0c61 | ||
|
|
cd2be94d29 | ||
|
|
878dca3cd6 | ||
|
|
90cba26904 | ||
|
|
c5c001f030 | ||
|
|
a3ba4e26c3 | ||
|
|
dd95862d5a | ||
|
|
5d3de41e63 | ||
|
|
5cad0a96cd | ||
|
|
e74fd79efc | ||
|
|
6f49fc9126 | ||
|
|
bbf3cc2f44 | ||
|
|
7bf196ef75 | ||
|
|
4b5b3aff49 | ||
|
|
15b0cb132c | ||
|
|
e67f91ea90 | ||
|
|
59350f02fb | ||
|
|
32cde66d64 | ||
|
|
7ba111a275 | ||
|
|
8d3fa6cef8 | ||
|
|
ef7aede146 | ||
|
|
11ae58aad3 | ||
|
|
05e30a5d19 | ||
|
|
64773cafec | ||
|
|
c6be39ffc3 | ||
|
|
376d4293c2 | ||
|
|
67b3752297 | ||
|
|
f463ffc8ed | ||
|
|
6e2aac51b4 | ||
|
|
a9a3c25dfd | ||
|
|
645898ab14 | ||
|
|
3ad1c46455 | ||
|
|
d3d33c85d9 | ||
|
|
c2796f66fb | ||
|
|
f57fcd25c9 | ||
|
|
9bda7dee7f | ||
|
|
7e1f21b02b | ||
|
|
a83acabf1a | ||
|
|
fb99c76b0c | ||
|
|
cc0ff1f5e7 | ||
|
|
afbfd9ed43 | ||
|
|
fcad04461f | ||
|
|
ca98b5a210 | ||
|
|
bd72ef84ed | ||
|
|
cb3c62fb6c | ||
|
|
2976220e4d | ||
|
|
192371c07b | ||
|
|
708a3f4ad9 | ||
|
|
fbcdfa97cf | ||
|
|
4e39762b46 | ||
|
|
4239e8d5fb | ||
|
|
c8ee455865 | ||
|
|
d5be7b8c57 | ||
|
|
bc2f4f1ef3 | ||
|
|
e72baf3c1f | ||
|
|
b2b52b6af7 | ||
|
|
4f417ccf0f | ||
|
|
780c3f5f6d | ||
|
|
f9eff12f94 | ||
|
|
e912a8d4e0 | ||
|
|
224af292d6 | ||
|
|
e07a4457ec | ||
|
|
58cd0495e6 | ||
|
|
6b9b2afbef | ||
|
|
c55a8d09a2 | ||
|
|
71b06f92ec | ||
|
|
692ec8ecbf | ||
|
|
523ea7f314 | ||
|
|
f48444f21d | ||
|
|
b4c5b3cbe6 | ||
|
|
ed88ae013d | ||
|
|
0fe7937808 | ||
|
|
564f57b879 | ||
|
|
a47dc8e767 | ||
|
|
41e192acb0 | ||
|
|
ff4fb191b8 | ||
|
|
2feee80168 | ||
|
|
59fed8a9cc | ||
|
|
7cfca0a650 | ||
|
|
6f1a5fd3a9 | ||
|
|
cd6869778a | ||
|
|
2e8d84430e | ||
|
|
b8f32a6d8d | ||
|
|
11ab37baf1 | ||
|
|
9dbde43a44 | ||
|
|
2a24d71ee3 | ||
|
|
134444c20a | ||
|
|
44b87f178e | ||
|
|
666636d554 | ||
|
|
5ec9d59382 | ||
|
|
addc7622ab | ||
|
|
1c7c3a4777 | ||
|
|
2a46b02487 | ||
|
|
5974515362 | ||
|
|
3fab1d9c6f | ||
|
|
a283f2ee5d | ||
|
|
934823fad4 | ||
|
|
351ed795ca | ||
|
|
a335d02156 | ||
|
|
3e0747164a | ||
|
|
8ad396d3ba | ||
|
|
26b54f0c00 | ||
|
|
de5b58fff6 | ||
|
|
b9b329dde4 | ||
|
|
2581500307 | ||
|
|
ef5c20a9f2 | ||
|
|
01aee7c028 | ||
|
|
569c7f4b48 | ||
|
|
bb849f175c | ||
|
|
ede0eea944 | ||
|
|
47150cca41 | ||
|
|
86df98a6a4 | ||
|
|
8dd5e90f8b | ||
|
|
f31023e2ed | ||
|
|
740d2e5a6c | ||
|
|
20d37e1ac9 | ||
|
|
f3f79ed499 | ||
|
|
c581222022 | ||
|
|
a3fd738b46 | ||
|
|
3f16e973eb | ||
|
|
cb1013762f | ||
|
|
74e275c5d0 | ||
|
|
dbeb513f65 | ||
|
|
6f4561a38f | ||
|
|
12507190d8 | ||
|
|
85dac65030 | ||
|
|
4f1708619e | ||
|
|
84b545c37d | ||
|
|
b24086e679 | ||
|
|
8308376f53 | ||
|
|
137f371528 | ||
|
|
5707039002 | ||
|
|
d4fabf0fe9 | ||
|
|
a4a0630102 | ||
|
|
439ac7eac6 | ||
|
|
ef1b82f426 | ||
|
|
e7b9f3f121 | ||
|
|
14b4d10be3 | ||
|
|
987a4bd04c | ||
|
|
ce86510d8e | ||
|
|
156a05f6ed | ||
|
|
b35d8406a3 | ||
|
|
3910486b17 | ||
|
|
60ba77a06f | ||
|
|
f86ea04a02 | ||
|
|
db4b5f0452 | ||
|
|
c0ae0c7ffa | ||
|
|
6a0788c2a1 | ||
|
|
4a52d327ce | ||
|
|
ef68fe1c85 | ||
|
|
83fa9c9ebd | ||
|
|
5736306f8c | ||
|
|
67cb508944 | ||
|
|
87fe5cdd6f | ||
|
|
ca17f1cfc9 | ||
|
|
048629dd32 | ||
|
|
fe03da1d97 | ||
|
|
0a3d89d0e2 | ||
|
|
882b97da5e | ||
|
|
07a57969ac | ||
|
|
bc90da4cf2 | ||
|
|
ad5776cfba | ||
|
|
1f16123865 | ||
|
|
e85bbb7bd9 | ||
|
|
f4e907de36 | ||
|
|
72f7e1fb27 | ||
|
|
bb732d7606 | ||
|
|
221a49bb4a | ||
|
|
babe17838b | ||
|
|
f5d11f9ba6 | ||
|
|
939d917b7b | ||
|
|
288365b74b | ||
|
|
b57e17c01c | ||
|
|
92527e5847 |
@@ -1,6 +1,5 @@
|
|||||||
# Frontend config ************************************************************************************************************************************************************************************************
|
# Frontend config ************************************************************************************************************************************************************************************************
|
||||||
# Set CI to false while running the app locally
|
|
||||||
CI=false
|
|
||||||
# Set it to the URL form where the app home page will be accessed
|
# Set it to the URL form where the app home page will be accessed
|
||||||
PUBLIC_URL=https://app.opensignlabs.com/
|
PUBLIC_URL=https://app.opensignlabs.com/
|
||||||
# Set it to true if you want to generate the Sourcemap for debugging
|
# Set it to true if you want to generate the Sourcemap for debugging
|
||||||
@@ -8,13 +7,13 @@ GENERATE_SOURCEMAP=false
|
|||||||
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||||
REACT_APP_SERVERURL=https://app.opensignlabs.com/api/app
|
REACT_APP_SERVERURL=https://app.opensignlabs.com/api/app
|
||||||
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
# 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=aDsADsqweqwe
|
REACT_APP_APPID=opensign
|
||||||
# Google tag manager container id for configuring GTM on all pages of the app
|
# Google tag manager container id for configuring GTM on all pages of the app
|
||||||
REACT_APP_GTM=GTM-123N7LD
|
REACT_APP_GTM=GTM-123N7LD
|
||||||
|
|
||||||
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
||||||
# 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.
|
# 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=aDsADsqweqwe
|
APP_ID=opensign
|
||||||
# Name of the app. It will be visible in the verification emails sent out.
|
# Name of the app. It will be visible in the verification emails sent out.
|
||||||
appName=open_sign_server
|
appName=open_sign_server
|
||||||
# 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.
|
# 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.
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
# When used as it is, this env config will connect to our hosted UAT backend
|
# When used as it is, this env config will connect to our hosted UAT backend
|
||||||
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
||||||
|
|
||||||
# Set CI to false while running the app locally
|
|
||||||
CI=false
|
|
||||||
# Set it to the URL form where the app home page will be accessed
|
# Set it to the URL form where the app home page will be accessed
|
||||||
PUBLIC_URL=http://localhost:3000
|
PUBLIC_URL=http://localhost:3000
|
||||||
# Set it to true if you want to generate the Sourcemap for debugging
|
# Set it to true if you want to generate the Sourcemap for debugging
|
||||||
@@ -11,4 +9,4 @@ GENERATE_SOURCEMAP=false
|
|||||||
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||||
REACT_APP_SERVERURL=https://staging-app.opensignlabs.com/api/app
|
REACT_APP_SERVERURL=https://staging-app.opensignlabs.com/api/app
|
||||||
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
# 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=opensignstgn
|
REACT_APP_APPID=opensign
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
# When used as it is, this env config will connect to our hosted UAT backend
|
# When used as it is, this env config will connect to our hosted UAT backend
|
||||||
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
||||||
|
|
||||||
# Set CI to false while running the app locally
|
|
||||||
CI=false
|
|
||||||
# Set it to the URL form where the app home page will be accessed
|
# Set it to the URL form where the app home page will be accessed
|
||||||
PUBLIC_URL=http://localhost:3000
|
PUBLIC_URL=http://localhost:3000
|
||||||
# Set it to true if you want to generate the Sourcemap for debugging
|
# Set it to true if you want to generate the Sourcemap for debugging
|
||||||
@@ -11,18 +9,18 @@ GENERATE_SOURCEMAP=false
|
|||||||
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# 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
|
REACT_APP_SERVERURL=http://localhost:8080/app
|
||||||
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
# 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=opensignstgn
|
REACT_APP_APPID=opensign
|
||||||
|
|
||||||
|
|
||||||
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
||||||
# 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.
|
# 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
|
APP_ID=opensign
|
||||||
# Name of the app. It will be visible in the verification emails sent out.
|
# Name of the app. It will be visible in the verification emails sent out.
|
||||||
appName=open_sign_server
|
appName=open_sign_server
|
||||||
# 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.
|
# 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
|
MASTER_KEY=XnAadwKxxByMr
|
||||||
# Mongodb URI to connect to
|
# Mongodb URI to connect to
|
||||||
MONGODB_URI=mongodb://host.docker.internal:27017/OpenSignDB
|
MONGODB_URI=mongodb://mongo:27017/OpenSignDB
|
||||||
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
|
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
|
||||||
PARSE_MOUNT=/app
|
PARSE_MOUNT=/app
|
||||||
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||||
@@ -52,7 +50,7 @@ SMTP_ENABLE=
|
|||||||
SMTP_HOST=smtp.yourhost.com
|
SMTP_HOST=smtp.yourhost.com
|
||||||
SMTP_PORT=443
|
SMTP_PORT=443
|
||||||
SMTP_USER_EMAIL=mailer@yourdomain.com
|
SMTP_USER_EMAIL=mailer@yourdomain.com
|
||||||
SMTP_PASS=password
|
SMTP_PASS=password # if your password includes spaces then write password in single quotes ('asdf pasd asdf bgds').
|
||||||
|
|
||||||
|
|
||||||
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: ci
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- 'staging'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
@@ -11,9 +11,9 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- image: amolshejole/OpenSign
|
- image: amolshejole/OpenSign
|
||||||
dockerfile: apps/OpenSign/Dockerfile
|
dockerfile: apps/OpenSign/Dockerhubfile
|
||||||
- image: amolshejole/OpenSignServer
|
- image: amolshejole/OpenSignServer
|
||||||
dockerfile: apps/OpenSignServer/Dockerfile
|
dockerfile: apps/OpenSignServer/Dockerhubfile
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
@@ -31,8 +31,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
images: ${{ matrix.image }}
|
images: ${{ matrix.image }}
|
||||||
-
|
-
|
||||||
name: Debug - List files
|
name: Debug - List files opensign
|
||||||
run: ls -R apps/OpenSign/ # Adjust the path as needed
|
run: ls -R apps/OpenSign/ # Adjust the path as needed
|
||||||
|
-
|
||||||
|
name: Debug - List files opensignserver
|
||||||
|
run: ls -R apps/OpenSignServer/ # Adjust the path as needed
|
||||||
-
|
-
|
||||||
name: Build and push
|
name: Build and push
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
|
|||||||
@@ -1,149 +1,29 @@
|
|||||||
|
|
||||||
# INSTALLATON INSTRUCTIONS
|
# INSTALLATON INSTRUCTIONS HAS A NEW HOME
|
||||||
|
|
||||||
You can use our app as a cloud version from [OpenSignLabs](https://www.opensignlabs.com)
|
We've updated our installation instructions and moved them to our dedicated documentation portal to provide you with a better experience and updated guidance. Whether you're looking to self-host OpenSign™ or contribute to its development, you can find detailed instructions tailored to your needs at [docs.opensignlabs.com](https://docs.opensignlabs.com).
|
||||||
|
|
||||||
or follow below instructions to install it on your own infrastructure.
|
## Self Hosting
|
||||||
|
|
||||||
- Localhost(Frontend only)
|
If you're interested in self-hosting OpenSign™, our new documentation portal provides comprehensive, step-by-step instructions to help you set up OpenSign™ in your own environment. This section is designed for system administrators and those looking to deploy OpenSign™ within their organization or for personal use.
|
||||||
- Digital Ocean
|
|
||||||
- Localhost(Docker)
|
|
||||||
|
|
||||||
## Localhost(Frontend only)
|
- **Access Self Hosting Instructions:** [Self Hosting Guide](https://docs.opensignlabs.com/docs/category/docker)
|
||||||
|
|
||||||
This is the easiest way to run the frontend application for development or testing purpose without the hassle of installing backend & DB. All the features including document upload, signing, email notifications will work seamlessly from staging backend.
|
## Contributors
|
||||||
|
|
||||||
**Warning:** All data, including user accounts and documents, is stored in the staging backend. This data will be erased every time there is a merge to the main branch. As a result, you may need to recreate user accounts repeatedly. If you find that login attempts are failing, it is likely because the data has been cleared due to a recent merge.
|
For developers and contributors who are looking to build upon or contribute to OpenSign™, we've prepared a separate section that covers the setup, development environment configuration, and guidelines for contributing to the OpenSign™ project.
|
||||||
|
|
||||||
Below are the steps to follow -
|
- **Access Contributor Instructions:** [Contributors Guide](https://docs.opensignlabs.com/docs/contribute/INSTALLATION)
|
||||||
- [Clone the repository](https://help.github.com/articles/cloning-a-repository/) to your local machine using below command -
|
|
||||||
```
|
|
||||||
git clone https://github.com/OpenSignLabs/OpenSign.git
|
|
||||||
```
|
|
||||||
- Copy the .env.frontend_dev file to apps/OpenSign/.env using below command(on mac & linux). For windows use COPY command instead.
|
|
||||||
```
|
|
||||||
cp .env.frontend_dev apps/OpenSign/.env
|
|
||||||
```
|
|
||||||
- CD to /apps/OpenSign directory
|
|
||||||
- Install NPM packages using
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
- Run the project locally using
|
|
||||||
```
|
|
||||||
npm run start
|
|
||||||
```
|
|
||||||
You should be able to access the application from http://localhost:3000 after this.
|
|
||||||
Create an account by signing-up and start contributing.
|
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
## Digital Ocean
|
Should you need further assistance or have any questions, please feel free to reach out to us through our support channels:
|
||||||
|
|
||||||
OpenSign application consistes of 3 components -
|
- **Twitter:** [OpenSignHQ on Twitter](https://twitter.com/OpenSignHQ)
|
||||||
- ReactJS frontend
|
- **Facebook:** [OpenSign on Facebook](https://www.facebook.com/profile.php?id=61551030403669)
|
||||||
- NodeJS API
|
- **LinkedIn:** [OpenSign™ on LinkedIn](https://www.linkedin.com/company/opensign%E2%84%A2/)
|
||||||
- MongoDB database
|
- **Discord:** [Join our Discord Community](https://discord.com/invite/opensign)
|
||||||
|
- **YouTube:** [OpenSignHQ on YouTube](https://www.youtube.com/@opensignhq)
|
||||||
|
|
||||||
You can install all 3 components on digital ocean using the button below -
|
We are committed to providing you with the support you need to successfully install and use OpenSign™. Visit our website at [www.opensignlabs.com](https://www.opensignlabs.com) for more information about our project and its features.
|
||||||
|
|
||||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/OpenSignLabs/Deploy-OpenSign-to-Digital-Ocean/tree/main&refcode=30db1c901ab0)
|
|
||||||
|
|
||||||
## You will need to create an AWS S3 bucket or digital ocean space in order to store your uploaded documents
|
|
||||||
|
|
||||||
### AWS S3 -
|
|
||||||
- Step 1 : Create a S3 bucket
|
|
||||||
- Login to AWS console
|
|
||||||
- Navigate to S3 under services
|
|
||||||
- Hit "Create Bucket" button on upper right corner
|
|
||||||
- Remove the check from "block all public access" checkbox(we need this in order to provide access to not-logged in users after OTP verification)
|
|
||||||
- Set bucket versioning and tags as per your requirements
|
|
||||||
- Hit "Create bucket" button
|
|
||||||
- Step 2 : Create IAM user and provide access to AWS bucket
|
|
||||||
- Search for "IAM" on the search bar in AWS console
|
|
||||||
- On IAM dashboard, click the number of users(count) under IAM resources table
|
|
||||||
- Hit "create user" button on the upper right corner of the page
|
|
||||||
- Enter the user name & click next
|
|
||||||
- Click create policy, search for S3 and provide the Read, Write & list permissions
|
|
||||||
- Click next and click "Create user"
|
|
||||||
- Step 3 : Generate Credentials
|
|
||||||
- Go to IAM/Users in AWS console
|
|
||||||
- Hit the hyperlink for the user created in the previous step
|
|
||||||
- Click the "Security credentials" tab
|
|
||||||
- Scroll down to "Access keys" and hit "Create access key"
|
|
||||||
- In the next step select "Application running outside AWS"
|
|
||||||
- Add a description tag if needed & hit "Create access key"
|
|
||||||
- In the next step you will see "Access key" and "Secret Access key". Copy both the values.
|
|
||||||
- Set the value of "Access key" to "DO_ACCESS_KEY_ID" environment variable
|
|
||||||
- Set the value of "Secret Access key" to "DO_SECRET_ACCESS_KEY" environment variable
|
|
||||||
- Step 3 : Copy bucket credentials
|
|
||||||
- Visit "Amazon S3 -> Buckets" in aws console
|
|
||||||
- Click the bucket created in previous steps & visit the properties tab
|
|
||||||
- Under "Bucket overview" you will find the value of AWS region(for ex. ap-south-1). Set that value to env variable "DO_REGION"
|
|
||||||
- You can create the value for "DO_ENDPOINT" env variable by appending the region value to amazonaws.com (for ex. s3.ap-south-1.amazonaws.com)
|
|
||||||
- You can create the value for "DO_BASEURL" by adding the bucketname in front of the endpoint value(for ex. https://bucketname.s3.ap-south-1.amazonaws.com)
|
|
||||||
|
|
||||||
Visit below link if you face any issues while following the above instructions -
|
|
||||||
- https://repost.aws/knowledge-center/create-access-key
|
|
||||||
|
|
||||||
|
|
||||||
## Localhost(Docker)
|
|
||||||
|
|
||||||
For local Setup we need to need following prerequisite:
|
|
||||||
|
|
||||||
Environment Varaibles:
|
|
||||||
|
|
||||||
| Environment Varibale | Value | Description |
|
|
||||||
| ------------- | ------------- | ------------- |
|
|
||||||
| CI | false | Set CI to false while running the app locally |
|
|
||||||
| 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 |
|
|
||||||
| 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. |
|
|
||||||
| 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. |
|
|
||||||
| 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. |
|
|
||||||
| MONGODB_URI | mongodb://host.docker.internal:27017/OpenSignDB | Mongodb URI to connect to |
|
|
||||||
| PARSE_MOUNT |/app | Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions. |
|
|
||||||
| SERVER_URL | http://127.0.0.1:8080/app | Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead) |
|
|
||||||
| DO_SPACE | DOSPACENAME | Digital ocean space name or AWS S3 bucket name for uploading documents |
|
|
||||||
| DO_ENDPOINT | ams3.digitaloceanspaces.com | Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents |
|
|
||||||
| DO_BASEURL |https://DOSPACENAME.ams3.digitaloceanspaces.com | Digital ocean baseurl or AWS S3 base URL |
|
|
||||||
| DO_ACCESS_KEY_ID | YOUR_S3_ACCESS_ID | Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs |
|
|
||||||
| DO_SECRET_ACCESS_KEY | YOUR_S3_ACCESS_KEY | Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs |
|
|
||||||
| DO_REGION | YOUR_S3_REGION | Digital ocean spaces region or AWS s3 region |
|
|
||||||
| USE_LOCAL | FALSE | To use local file storage to save file |
|
|
||||||
| MAILGUN_API_KEY | YOUR_MAILGUNAPI_KEY | Mailgun API Key |
|
|
||||||
| MAILGUN_DOMAIN | YOUR_MAILGUNAPI_DOMAIN | Mailgun API Domain |
|
|
||||||
| MAILGUN_SENDER | - | Mailgun Sender Mail ID |
|
|
||||||
| PFX_BASE64 | - | Base64 encoded PFX or p12 document signing certificate file. You can generate base64 encoded self sign certificate using the passphrase `emudhra` |
|
|
||||||
|
|
||||||
# Steps to Generate Self Sign Certificate
|
|
||||||
```
|
|
||||||
# execute below command and use passphrase emudhra
|
|
||||||
openssl genrsa -des3 -out ./cert/local_dev.key 2048
|
|
||||||
openssl req -key ./cert/local_dev.key -new -x509 -days 365 -out ./cert/local_dev.crt
|
|
||||||
openssl pkcs12 -inkey ./cert/local_dev.key -in ./cert/local_dev.crt -export -out ./cert/local_dev.pfx
|
|
||||||
openssl base64 -in ./cert/local_dev.pfx -out ./cert/base64_pfx
|
|
||||||
```
|
|
||||||
|
|
||||||
# CORS Configuration
|
|
||||||
|
|
||||||
As document storage is delegated to S3-compatible services that reside in a different host than the OpenSign one, document operations (loading, storing, deleting) are subject to [Cross-Origin Resource Sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) restriction policies; as a consequence, OpenSign app may fail with (browser console) errors like the following:
|
|
||||||
```
|
|
||||||
Access to fetch at 'https://foo.nyc3.digitaloceanspaces.com/exported_file_4627_0000-00-00T00%3A45%3A43.344Z.pdf'
|
|
||||||
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
|
|
||||||
is present on the requested resource. If an opaque response serves your needs, set the request's mode to
|
|
||||||
'no-cors' to fetch the resource with CORS disabled.
|
|
||||||
```
|
|
||||||
|
|
||||||
In order to address this, your document storage system must be instructed to accept requests from other hosts; below the relevant documentation links:
|
|
||||||
- [How to Configure CORS on DigitalOcean Spaces](https://docs.digitalocean.com/products/spaces/how-to/configure-cors/)
|
|
||||||
- [Configuring cross-origin resource sharing on AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)
|
|
||||||
|
|
||||||
# Build Local Environment
|
|
||||||
|
|
||||||
Command to build project -
|
|
||||||
- Execute `make build`
|
|
||||||
|
|
||||||
Command to run project -
|
|
||||||
- Execute `make run`
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
build:
|
build:
|
||||||
cp .env.local_dev .env
|
cp .env.local_dev .env
|
||||||
rm -rf apps/OpenSign/public/mfbuild
|
cd apps/OpenSign && cp ../../.env.local_dev .env && npm install && npm run build
|
||||||
cd microfrontends/SignDocuments && npm install && npm run build
|
|
||||||
docker compose up --build --force-recreate
|
docker compose up --build --force-recreate
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
|||||||
@@ -42,24 +42,24 @@ Please star ⭐ the repo to support us! 😀
|
|||||||
|
|
||||||
### Introduction
|
### Introduction
|
||||||
|
|
||||||
Welcome to OpenSign, the premier open-source docusign alternative - document e-signing solution designed to provide a secure, reliable, and free alternative to commercial platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Developed under the OpenSignLabs organization, our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
|
Welcome to OpenSign, the premier open source docusign alternative - document e-signing solution designed to provide a secure, reliable and free alternative to commercial esign platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- **Secure PDF E-Signing:** With the help of Robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
|
- **Secure PDF E-Signing:** With the help of robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
|
||||||
- **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.
|
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that allows hand drawn signatures, uploaded images, typed signatures & saved signatures for the simplest signing experience ever.
|
||||||
- **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.
|
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "Templates", "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-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.
|
- **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 in e-signature space.
|
||||||
- **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.
|
- **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.
|
||||||
- **"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.
|
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign. Not just this, OpenSign™ also allows signers to reject signing a document.
|
||||||
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates.
|
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates.
|
||||||
- **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.
|
- **PDF Template Creation:** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time & collect e-signatures seamlessly.
|
||||||
- **OpenSign™ Drive:** It is a centralised secure vault for your signed documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
|
- **OpenSign™ Drive:** It is a centralised secure vault for your digital 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.
|
- **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.
|
- **API Support:** OpenSign™ API allows seamless integration into existing systems and software. You can generate an API key from the app and refer the [docs](https://docs.opensignlabs.com) to start integrating it in your existing applications.
|
||||||
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is coming soon.
|
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is available. We also have a Zapier integration that allows you to integrate it with virtually any application.
|
||||||
|
|
||||||
<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'>
|
||||||
@@ -76,7 +76,7 @@ Please refer to the [Installation Guide](INSTALLATION.md) for detailed instructi
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
For comprehensive guidelines on how to use OpenSign, please consult our [User Manual](USAGE.md).
|
For comprehensive guidelines on how to use OpenSign™, please consult our [User Manual](USAGE.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Use an official Node runtime as the base image
|
# Use an official Node runtime as the base image
|
||||||
FROM node:16
|
FROM node:18
|
||||||
|
|
||||||
# Set the working directory inside the container
|
# Set the working directory inside the container
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
@@ -21,5 +21,5 @@ EXPOSE 3000
|
|||||||
# ENV NODE_ENV production
|
# ENV NODE_ENV production
|
||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
ENTRYPOINT npm run start-dev
|
ENTRYPOINT npm run start
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Use an official Node runtime as the base image
|
||||||
|
FROM node:18
|
||||||
|
|
||||||
|
# Set the working directory inside the container
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy package.json and package-lock.json first to leverage Docker cache
|
||||||
|
COPY apps/OpenSign/package*.json ./
|
||||||
|
|
||||||
|
# Install application dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy the current directory contents into the container
|
||||||
|
COPY apps/OpenSign/ .
|
||||||
|
COPY apps/OpenSign/.husky .
|
||||||
|
|
||||||
|
# build
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Make port 3000 available to the world outside this container
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Define environment variables if needed
|
||||||
|
# ENV NODE_ENV production
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
CMD ["npm", "start"]
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
const { dependencies } = require("./package.json");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: "shell_app", // change me
|
|
||||||
filename: "remoteEntry.js",
|
|
||||||
exposes: {},
|
|
||||||
remotes: {},
|
|
||||||
shared: {
|
|
||||||
...dependencies,
|
|
||||||
react: {
|
|
||||||
singleton: true,
|
|
||||||
import: "react", // fallback is also react
|
|
||||||
shareScope: "default",
|
|
||||||
requiredVersion: dependencies.react
|
|
||||||
},
|
|
||||||
"react-dom": {
|
|
||||||
singleton: true,
|
|
||||||
requiredVersion: dependencies["react-dom"]
|
|
||||||
},
|
|
||||||
"react-router-dom": {
|
|
||||||
singleton: true,
|
|
||||||
requiredVersion: dependencies["react-router-dom"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -3,44 +3,54 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^1.9.7",
|
"@formkit/auto-animate": "^0.8.1",
|
||||||
"axios": "^1.5.1",
|
"@radix-ui/themes": "^2.0.3",
|
||||||
"daisyui": "^3.9.2",
|
"@react-pdf/renderer": "^3.4.0",
|
||||||
|
"@reduxjs/toolkit": "^2.2.1",
|
||||||
|
"axios": "^1.6.8",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"html-react-parser": "^4.2.2",
|
"jwt-decode": "^4.0.0",
|
||||||
"json-rules-engine-simplified": "^0.1.17",
|
"moment": "^2.30.1",
|
||||||
"jwt-decode": "^3.1.2",
|
"parse": "^4.3.1",
|
||||||
"mf-cra": "^0.0.5",
|
"pdf-lib": "^1.17.1",
|
||||||
"moment": "^2.29.4",
|
"print-js": "^1.6.0",
|
||||||
"parse": "^4.2.0",
|
"radix-ui": "^1.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.9.0",
|
"react-bootstrap": "^2.10.2",
|
||||||
|
"react-datepicker": "^6.4.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dnd-multi-backend": "^8.0.3",
|
"react-dnd-multi-backend": "^8.0.3",
|
||||||
"react-dnd-touch-backend": "^16.0.1",
|
"react-dnd-touch-backend": "^16.0.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-drag-listview": "^2.0.0",
|
|
||||||
"react-gtm-module": "^2.0.11",
|
"react-gtm-module": "^2.0.11",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
|
"react-konva": "^18.2.10",
|
||||||
"react-modal": "^3.16.1",
|
"react-modal": "^3.16.1",
|
||||||
"react-redux": "^8.1.3",
|
"react-pdf": "^7.7.1",
|
||||||
"react-router-dom": "^6.16.0",
|
"react-redux": "^9.1.0",
|
||||||
|
"react-rnd": "^10.4.1",
|
||||||
|
"react-router-dom": "^6.22.3",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-select": "^5.7.7",
|
"react-scrollbars-custom": "^4.1.1",
|
||||||
|
"react-select": "^5.8.0",
|
||||||
|
"react-signature-canvas": "^1.0.6",
|
||||||
|
"react-tooltip": "^5.26.3",
|
||||||
"reactour": "^1.19.2",
|
"reactour": "^1.19.2",
|
||||||
"redux": "^4.2.1",
|
"redux": "^5.0.1",
|
||||||
"redux-thunk": "^2.4.2",
|
"redux-thunk": "^3.1.0",
|
||||||
|
"regex-parser": "^2.3.0",
|
||||||
"serve": "^14.2.1",
|
"serve": "^14.2.1",
|
||||||
"styled-components": "^4.4.1",
|
"styled-components": "^4.4.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "serve -s build",
|
"start": "serve -s build",
|
||||||
"start-dev": "mf-cra start",
|
"start-dev": "react-scripts start",
|
||||||
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
||||||
"build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
|
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
|
||||||
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
|
"build": "npm run version && react-scripts build",
|
||||||
|
"build-win": "npm run version-win && react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject",
|
||||||
"release": "standard-version",
|
"release": "standard-version",
|
||||||
@@ -70,16 +80,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/runtime-corejs2": "^7.23.2",
|
"@babel/runtime-corejs2": "^7.24.1",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.18",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.0",
|
||||||
"eslint": "^8.51.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"lint-staged": "^15.0.1",
|
"lint-staged": "^15.2.2",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.37",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.8",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.3.1",
|
||||||
"tailwindcss": "^3.3.3"
|
"tailwindcss": "^3.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,55 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, lazy } from "react";
|
||||||
import { Routes, Route, BrowserRouter } from "react-router-dom";
|
import { Routes, Route, BrowserRouter } from "react-router-dom";
|
||||||
import Pgsignup from "./routes/Pgsignup";
|
import { pdfjs } from "react-pdf";
|
||||||
import Login from "./routes/Login";
|
import Login from "./pages/Login";
|
||||||
import Microapp from "./routes/RemoteApp";
|
import Form from "./pages/Form";
|
||||||
import Signup from "./routes/Signup";
|
import Report from "./pages/Report";
|
||||||
import Form from "./routes/Form";
|
import Dashboard from "./pages/Dashboard";
|
||||||
import Report from "./routes/Report";
|
|
||||||
import Dashboard from "./routes/Dashboard";
|
|
||||||
import Subscriptions from "./routes/PlanSubscriptions";
|
|
||||||
import HomeLayout from "./layout/HomeLayout";
|
import HomeLayout from "./layout/HomeLayout";
|
||||||
import UserProfile from "./routes/UserProfile";
|
import PageNotFound from "./pages/PageNotFound";
|
||||||
import PageNotFound from "./routes/PageNotFound";
|
|
||||||
import ForgetPassword from "./routes/ForgetPassword";
|
|
||||||
import ChangePassword from "./routes/ChangePassword";
|
|
||||||
import ReportMicroapp from "./components/ReportMicroapp";
|
|
||||||
import LoadMf from "./routes/LoadMf";
|
|
||||||
import GenerateToken from "./routes/GenerateToken";
|
|
||||||
import ValidateRoute from "./primitives/ValidateRoute";
|
import ValidateRoute from "./primitives/ValidateRoute";
|
||||||
import Webhook from "./routes/Webhook";
|
|
||||||
import Validate from "./primitives/Validate";
|
import Validate from "./primitives/Validate";
|
||||||
|
import TemplatePlaceholder from "./pages/TemplatePlaceholder";
|
||||||
|
import SignYourSelf from "./pages/SignyourselfPdf";
|
||||||
|
import DraftDocument from "./components/pdf/DraftDocument";
|
||||||
|
import PlaceHolderSign from "./pages/PlaceHolderSign";
|
||||||
|
import PdfRequestFiles from "./pages/PdfRequestFiles";
|
||||||
|
import LazyPage from "./primitives/LazyPage";
|
||||||
|
import { isEnableSubscription } from "./constant/const";
|
||||||
|
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
||||||
|
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
||||||
|
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
||||||
|
const Pgsignup = lazy(() => import("./pages/Pgsignup"));
|
||||||
|
const Subscriptions = lazy(() => import("./pages/PlanSubscriptions"));
|
||||||
|
const ChangePassword = lazy(() => import("./pages/ChangePassword"));
|
||||||
|
const UserProfile = lazy(() => import("./pages/UserProfile"));
|
||||||
|
const Signup = lazy(() => import("./pages/Signup"));
|
||||||
|
const Opensigndrive = lazy(() => import("./pages/Opensigndrive"));
|
||||||
|
const ManageSign = lazy(() => import("./pages/Managesign"));
|
||||||
|
const GenerateToken = lazy(() => import("./pages/GenerateToken"));
|
||||||
|
const Webhook = lazy(() => import("./pages/Webhook"));
|
||||||
|
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
||||||
|
|
||||||
|
const Loader = () => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
function App() {
|
function App() {
|
||||||
const [isloading, setIsLoading] = useState(true);
|
const [isloading, setIsLoading] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -27,12 +57,16 @@ function App() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCredentials = () => {
|
const handleCredentials = () => {
|
||||||
const appId = process.env.REACT_APP_APPID;
|
const appId = process.env.REACT_APP_APPID
|
||||||
const baseurl = process.env.REACT_APP_SERVERURL;
|
? process.env.REACT_APP_APPID
|
||||||
|
: "opensign";
|
||||||
|
const baseurl = process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/api/app";
|
||||||
const appName = "contracts";
|
const appName = "contracts";
|
||||||
try {
|
try {
|
||||||
localStorage.setItem("BaseUrl12", `${baseurl}/`);
|
localStorage.setItem("baseUrl", `${baseurl}/`);
|
||||||
localStorage.setItem("AppID12", appId);
|
localStorage.setItem("parseAppId", appId);
|
||||||
localStorage.setItem("domain", appName);
|
localStorage.setItem("domain", appName);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -43,51 +77,105 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div className="bg-[#eef1f5]">
|
<div className="bg-[#eef1f5]">
|
||||||
{isloading ? (
|
{isloading ? (
|
||||||
<div
|
<Loader />
|
||||||
style={{
|
|
||||||
height: "100vh",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
fontSize: "45px",
|
|
||||||
color: "#3dd3e0"
|
|
||||||
}}
|
|
||||||
className="loader-37"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<ValidateRoute />}>
|
<Route element={<ValidateRoute />}>
|
||||||
<Route exact path="/" element={<Login />} />
|
<Route exact path="/" element={<Login />} />
|
||||||
<Route exact path="/signup" element={<Signup />} />
|
<Route path="/signup" element={<LazyPage Page={Signup} />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route element={<Validate />}>
|
<Route element={<Validate />}>
|
||||||
<Route exact path="/load/:remoteApp/*" element={<LoadMf />} />
|
<Route
|
||||||
|
path="/load/template/:templateId"
|
||||||
|
element={<TemplatePlaceholder />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/load/placeholdersign/:docId"
|
||||||
|
element={<PlaceHolderSign />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/load/recipientSignPdf/:docId/:contactBookId"
|
||||||
|
element={<PdfRequestFiles />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
|
<Route
|
||||||
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
|
path="/loadmf/signmicroapp/login/:id/:userMail/:contactBookId/:serverUrl"
|
||||||
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
|
element={<LazyPage Page={GuestLogin} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/login/:id/:userMail/:contactBookId/:serverUrl"
|
||||||
|
element={<LazyPage Page={GuestLogin} />}
|
||||||
|
/>
|
||||||
|
<Route path="/debugpdf" element={<LazyPage Page={DebugPdf} />} />
|
||||||
|
<Route
|
||||||
|
path="/forgetpassword"
|
||||||
|
element={<LazyPage Page={ForgetPassword} />}
|
||||||
|
/>
|
||||||
|
{isEnableSubscription && (
|
||||||
<>
|
<>
|
||||||
<Route exact path="/pgsignup" element={<Pgsignup />} />
|
<Route
|
||||||
<Route exact path="/subscription" element={<Subscriptions />} />
|
path="/pgsignup"
|
||||||
|
element={<LazyPage Page={Pgsignup} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/subscription"
|
||||||
|
element={<LazyPage Page={Subscriptions} />}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Route element={<HomeLayout />}>
|
<Route element={<HomeLayout />}>
|
||||||
<Route path="/changepassword" element={<ChangePassword />} />
|
<Route
|
||||||
<Route path="/mf/:remoteApp/*" element={<Microapp />} />
|
path="/changepassword"
|
||||||
<Route path="/asmf/:remoteApp/*" element={<Microapp />} />
|
element={<LazyPage Page={ChangePassword} />}
|
||||||
<Route path="/rpmf/:remoteApp/*" element={<ReportMicroapp />} />
|
/>
|
||||||
<Route path="/form/:id" element={<Form />} />
|
<Route path="/form/:id" element={<Form />} />
|
||||||
<Route path="/report/:id" element={<Report />} />
|
<Route path="/report/:id" element={<Report />} />
|
||||||
<Route path="/dashboard/:id" element={<Dashboard />} />
|
<Route path="/dashboard/:id" element={<Dashboard />} />
|
||||||
<Route path="/profile" element={<UserProfile />} />
|
<Route
|
||||||
<Route path="/generatetoken" element={<GenerateToken />} />
|
path="/profile"
|
||||||
<Route path="/webhook" element={<Webhook />} />
|
element={<LazyPage Page={UserProfile} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/opensigndrive"
|
||||||
|
element={<LazyPage Page={Opensigndrive} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/managesign"
|
||||||
|
element={<LazyPage Page={ManageSign} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/generatetoken"
|
||||||
|
element={<LazyPage Page={GenerateToken} />}
|
||||||
|
/>
|
||||||
|
<Route path="/webhook" element={<LazyPage Page={Webhook} />} />
|
||||||
|
<Route
|
||||||
|
path="/template/:templateId"
|
||||||
|
element={<TemplatePlaceholder />}
|
||||||
|
/>
|
||||||
|
{/* signyouself route with no rowlevel data using docId from url */}
|
||||||
|
<Route path="/signaturePdf/:docId" element={<SignYourSelf />} />
|
||||||
|
{/* draft document route to handle and navigate route page accordiing to document status */}
|
||||||
|
<Route path="/draftDocument" element={<DraftDocument />} />
|
||||||
|
{/* recipient placeholder set route with no rowlevel data using docId from url*/}
|
||||||
|
<Route
|
||||||
|
path="/placeHolderSign/:docId"
|
||||||
|
element={<PlaceHolderSign />}
|
||||||
|
/>
|
||||||
|
{/* for user signature (need your sign route) with row level data */}
|
||||||
|
<Route path="/pdfRequestFiles" element={<PdfRequestFiles />} />
|
||||||
|
{/* for user signature (need your sign route) with no row level data */}
|
||||||
|
<Route
|
||||||
|
path="/pdfRequestFiles/:docId"
|
||||||
|
element={<PdfRequestFiles />}
|
||||||
|
/>
|
||||||
|
{/* recipient signature route with no rowlevel data using docId from url */}
|
||||||
|
<Route
|
||||||
|
path="/recipientSignPdf/:docId/:contactBookId"
|
||||||
|
element={<PdfRequestFiles />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="*" element={<PageNotFound />} />
|
<Route path="*" element={<PageNotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import ReactDOM from "react-dom/client";
|
|
||||||
import "./index.css";
|
|
||||||
import App from "./App";
|
|
||||||
import { Provider } from "react-redux";
|
|
||||||
import { store } from "./redux/store";
|
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
|
||||||
import { TouchBackend } from "react-dnd-touch-backend";
|
|
||||||
import {
|
|
||||||
DndProvider,
|
|
||||||
TouchTransition,
|
|
||||||
MouseTransition,
|
|
||||||
Preview
|
|
||||||
} from "react-dnd-multi-backend";
|
|
||||||
import DragElement from "./microappComponent/DragElement";
|
|
||||||
import TagManager from "react-gtm-module";
|
|
||||||
|
|
||||||
const HTML5toTouch = {
|
|
||||||
backends: [
|
|
||||||
{
|
|
||||||
id: "html5",
|
|
||||||
backend: HTML5Backend,
|
|
||||||
transition: MouseTransition
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "touch",
|
|
||||||
backend: TouchBackend,
|
|
||||||
options: { enableMouseEvents: true },
|
|
||||||
preview: true,
|
|
||||||
transition: TouchTransition
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
const generatePreview = (props) => {
|
|
||||||
const { item, style } = props;
|
|
||||||
const newStyle = {
|
|
||||||
...style
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={newStyle}>
|
|
||||||
<DragElement {...item} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (process.env.REACT_APP_GTM) {
|
|
||||||
const tagManagerArgs = {
|
|
||||||
gtmId: process.env.REACT_APP_GTM
|
|
||||||
};
|
|
||||||
TagManager.initialize(tagManagerArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
|
||||||
root.render(
|
|
||||||
<Provider store={store}>
|
|
||||||
<DndProvider options={HTML5toTouch}>
|
|
||||||
<Preview>{generatePreview}</Preview>
|
|
||||||
<App />
|
|
||||||
</DndProvider>
|
|
||||||
</Provider>
|
|
||||||
);
|
|
||||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -3,7 +3,7 @@ import Parse from "parse";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
||||||
|
|
||||||
const AppendFormInForm = (props) => {
|
const AddSigner = (props) => {
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [phone, setPhone] = useState("");
|
const [phone, setPhone] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -49,8 +49,6 @@ const AppendFormInForm = (props) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
try {
|
try {
|
||||||
const contactQuery = new Parse.Object("contracts_Contactbook");
|
const contactQuery = new Parse.Object("contracts_Contactbook");
|
||||||
contactQuery.set("Name", name);
|
contactQuery.set("Name", name);
|
||||||
@@ -58,11 +56,11 @@ const AppendFormInForm = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_Guest");
|
contactQuery.set("UserRole", "contracts_Guest");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,4 +312,4 @@ const AppendFormInForm = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppendFormInForm;
|
export default AddSigner;
|
||||||
@@ -12,8 +12,6 @@ const AddUser = (props) => {
|
|||||||
const [isUserExist, setIsUserExist] = useState(false);
|
const [isUserExist, setIsUserExist] = useState(false);
|
||||||
const parseBaseUrl = localStorage.getItem("baseUrl");
|
const parseBaseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
|
|
||||||
const checkUserExist = async () => {
|
const checkUserExist = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -50,11 +48,11 @@ const AddUser = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_User");
|
contactQuery.set("UserRole", "contracts_User");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import React, { Component } from "react";
|
|
||||||
|
|
||||||
export class ErrorBoundary extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = { hasError: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromError() {
|
|
||||||
return {
|
|
||||||
hasError: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch(error, info) {
|
|
||||||
console.log(error);
|
|
||||||
console.log(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.hasError) {
|
|
||||||
return (
|
|
||||||
<div className="p-2">
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
height: "100vh",
|
|
||||||
display: "flex",
|
|
||||||
|
|
||||||
flexFlow: "column"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
style={{
|
|
||||||
fontSize: "2em",
|
|
||||||
fontFamily: "sans-serif",
|
|
||||||
textShadow: "0 0 20px black"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Something went wrong.
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.props.children;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ErrorBoundary;
|
|
||||||
@@ -4,26 +4,34 @@ import FullScreenButton from "./FullScreenButton";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
|
||||||
const Header = ({ showSidebar }) => {
|
const Header = ({ showSidebar }) => {
|
||||||
const navigation = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
let applogo = localStorage.getItem("appLogo") || "";
|
let applogo = localStorage.getItem("appLogo") || "";
|
||||||
let username = localStorage.getItem("username");
|
let username = localStorage.getItem("username");
|
||||||
const image = localStorage.getItem("profileImg") || dp;
|
const image = localStorage.getItem("profileImg") || dp;
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(true);
|
||||||
|
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
checkSubscription();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
async function checkSubscription() {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
}
|
||||||
const closeDropdown = () => {
|
const closeDropdown = () => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
Parse.User.logOut();
|
Parse.User.logOut();
|
||||||
let appdata = localStorage.getItem("userSettings");
|
let appdata = localStorage.getItem("userSettings");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
@@ -32,8 +40,8 @@ const Header = ({ showSidebar }) => {
|
|||||||
let PageLanding = localStorage.getItem("PageLanding");
|
let PageLanding = localStorage.getItem("PageLanding");
|
||||||
let domain = localStorage.getItem("domain");
|
let domain = localStorage.getItem("domain");
|
||||||
let _appName = localStorage.getItem("_appName");
|
let _appName = localStorage.getItem("_appName");
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("AppID12");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
@@ -44,10 +52,10 @@ const Header = ({ showSidebar }) => {
|
|||||||
localStorage.setItem("PageLanding", PageLanding);
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
localStorage.setItem("domain", domain);
|
localStorage.setItem("domain", domain);
|
||||||
localStorage.setItem("userSettings", appdata);
|
localStorage.setItem("userSettings", appdata);
|
||||||
localStorage.setItem("BaseUrl12", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("AppID12", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
|
|
||||||
navigation("/");
|
navigate("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
//handle to close profile drop down menu onclick screen
|
//handle to close profile drop down menu onclick screen
|
||||||
@@ -87,6 +95,16 @@ const Header = ({ showSidebar }) => {
|
|||||||
id="profile-menu"
|
id="profile-menu"
|
||||||
className="flex justify-between items-center gap-x-3"
|
className="flex justify-between items-center gap-x-3"
|
||||||
>
|
>
|
||||||
|
{!isSubscribe && (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="text-xs bg-[#002864] p-2 text-white rounded shadow"
|
||||||
|
onClick={() => navigate("/subscription")}
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<FullScreenButton />
|
<FullScreenButton />
|
||||||
</div>
|
</div>
|
||||||
@@ -127,7 +145,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
navigation("/profile");
|
navigate("/profile");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-regular fa-user"></i> Profile
|
<i className="fa-regular fa-user"></i> Profile
|
||||||
@@ -136,7 +154,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
navigation("/changepassword");
|
navigate("/changepassword");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-lock"></i> Change Password
|
<i className="fa-solid fa-lock"></i> Change Password
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useRef } from "react";
|
import React, { useState, useRef } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import jwtDecode from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
import { useScript } from "../hook/useScript";
|
import { useScript } from "../hook/useScript";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
||||||
@@ -48,8 +48,8 @@ const GoogleSignInBtn = ({
|
|||||||
if (Parse.User.current()) {
|
if (Parse.User.current()) {
|
||||||
await Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
}
|
}
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("AppID12");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
let domain = localStorage.getItem("domain");
|
let domain = localStorage.getItem("domain");
|
||||||
let appversion = localStorage.getItem("appVersion");
|
let appversion = localStorage.getItem("appVersion");
|
||||||
@@ -63,8 +63,8 @@ const GoogleSignInBtn = ({
|
|||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
localStorage.setItem("BaseUrl12", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("AppID12", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
localStorage.setItem("domain", domain);
|
localStorage.setItem("domain", domain);
|
||||||
localStorage.setItem("appversion", appversion);
|
localStorage.setItem("appversion", appversion);
|
||||||
@@ -191,8 +191,8 @@ const GoogleSignInBtn = ({
|
|||||||
let PageLanding = localStorage.getItem("PageLanding");
|
let PageLanding = localStorage.getItem("PageLanding");
|
||||||
let domain = localStorage.getItem("domain");
|
let domain = localStorage.getItem("domain");
|
||||||
let _appName = localStorage.getItem("_appName");
|
let _appName = localStorage.getItem("_appName");
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("AppID12");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
@@ -203,8 +203,8 @@ const GoogleSignInBtn = ({
|
|||||||
localStorage.setItem("PageLanding", PageLanding);
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
localStorage.setItem("domain", domain);
|
localStorage.setItem("domain", domain);
|
||||||
localStorage.setItem("userSettings", appdata);
|
localStorage.setItem("userSettings", appdata);
|
||||||
localStorage.setItem("BaseUrl12", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("AppID12", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Document, Page, pdfjs } from "react-pdf";
|
import { Document, Page } from "react-pdf";
|
||||||
import { Stage, Layer, Rect } from "react-konva";
|
import { Stage, Layer, Rect } from "react-konva";
|
||||||
const RenderDebugPdf = (props) => {
|
const RenderDebugPdf = (props) => {
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -29,7 +27,7 @@ const RenderDebugPdf = (props) => {
|
|||||||
onMouseMove={props.handleMouseMoveDiv}
|
onMouseMove={props.handleMouseMoveDiv}
|
||||||
>
|
>
|
||||||
<Document
|
<Document
|
||||||
onLoadError={(e) => {
|
onLoadError={() => {
|
||||||
const load = {
|
const load = {
|
||||||
status: false,
|
status: false,
|
||||||
type: "failed"
|
type: "failed"
|
||||||
@@ -66,6 +64,7 @@ const RenderDebugPdf = (props) => {
|
|||||||
.map((value) => {
|
.map((value) => {
|
||||||
return (
|
return (
|
||||||
<Rect
|
<Rect
|
||||||
|
key={value.key}
|
||||||
x={value.x}
|
x={value.x}
|
||||||
y={value.y}
|
y={value.y}
|
||||||
width={value.width}
|
width={value.width}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import useFederatedComponent from "mf-cra";
|
|
||||||
import React, { Suspense, useEffect } from "react";
|
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
|
|
||||||
const MicroappModal = () => {
|
|
||||||
const { remoteApp } = useParams();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => localStorage.removeItem("rowlevel");
|
|
||||||
}, []);
|
|
||||||
let paramString = remoteApp;
|
|
||||||
let queryString = new URLSearchParams(paramString);
|
|
||||||
let obj = {};
|
|
||||||
for (const [key, value] of queryString.entries()) {
|
|
||||||
// console.log("value ", key + ":" + value);
|
|
||||||
|
|
||||||
if (key === "remoteUrl") {
|
|
||||||
const url = window.location.origin + "/mfbuild/remoteEntry.js";
|
|
||||||
// console.log("atob(value) ", atob(value))
|
|
||||||
obj = { ...obj, [key]: url };
|
|
||||||
} else {
|
|
||||||
if (key === "moduleToLoad") {
|
|
||||||
obj = { ...obj, [key]: "./" + value };
|
|
||||||
} else {
|
|
||||||
obj = { ...obj, [key]: value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log("app ", remoteApp);
|
|
||||||
const { Component: RemoteComponent } = useFederatedComponent(obj);
|
|
||||||
// console.log("RemoteComponent ", RemoteComponent);
|
|
||||||
return (
|
|
||||||
<div className="w-full h-full flex items-center justify-center ">
|
|
||||||
<div className="w-full">
|
|
||||||
<Suspense
|
|
||||||
fallback={
|
|
||||||
<div style={{ height: "300px" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginLeft: "45%",
|
|
||||||
marginTop: "150px",
|
|
||||||
fontSize: "45px",
|
|
||||||
color: "#3dd3e0"
|
|
||||||
}}
|
|
||||||
className="loader-37"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
backgroundColor: "#ffffff",
|
|
||||||
width: "100%",
|
|
||||||
overflow: "hidden",
|
|
||||||
minHeight: "50vh"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{RemoteComponent && <RemoteComponent />}
|
|
||||||
</div>
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MicroappModal;
|
|
||||||
@@ -1,21 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
|
|
||||||
function Title(props) {
|
function Title({ title, drive }) {
|
||||||
return (
|
return (
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{`${props.title} - OpenSign™`}</title>
|
<title>{drive ? title : `${title} - OpenSign™`}</title>
|
||||||
{/* <title>
|
<meta name="description" content={`${title} - OpenSign™`} />
|
||||||
{`${localStorage.getItem("appTitle") ? localStorage.getItem("appTitle") : ""} - ${props.title}`}
|
|
||||||
</title> */}
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content={`${props.title} - OpenSign™`}
|
|
||||||
/>
|
|
||||||
{/* <meta
|
|
||||||
name="description"
|
|
||||||
content={`${localStorage.getItem("appTitle")} - ${props.title}`}
|
|
||||||
/> */}
|
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/png"
|
type="image/png"
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import React from "react";
|
||||||
|
import "../../styles/loader.css";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { openInNewTab } from "../../constant/Utils";
|
||||||
|
|
||||||
|
const DashboardButton = (props) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
function openReport() {
|
||||||
|
if (props.Data && props.Data.Redirect_type) {
|
||||||
|
const Redirect_type = props.Data.Redirect_type;
|
||||||
|
const id = props.Data.Redirect_id;
|
||||||
|
if (Redirect_type === "Form") {
|
||||||
|
navigate(`/form/${id}`);
|
||||||
|
} else if (Redirect_type === "Report") {
|
||||||
|
navigate(`/report/${id}`);
|
||||||
|
} else if (Redirect_type === "Url") {
|
||||||
|
openInNewTab(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => openReport()}
|
||||||
|
className={`${
|
||||||
|
props.Data && props.Data.Redirect_type
|
||||||
|
? "cursor-pointer"
|
||||||
|
: "cursor-default"
|
||||||
|
} w-full px-3 py-2 flex text-white rounded-md shadow overflow-hidden`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-start gap-5">
|
||||||
|
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
|
||||||
|
<i
|
||||||
|
className={`${
|
||||||
|
props.Icon ? props.Icon : "fa fa-solid fa-info"
|
||||||
|
} text-[25px] lg:text-[30px]`}
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<div className="">
|
||||||
|
<div className="text-base lg:text-lg text-black"> {props.Label}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DashboardButton;
|
||||||
@@ -4,6 +4,7 @@ import Parse from "parse";
|
|||||||
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";
|
||||||
|
import Tooltip from "../../primitives/Tooltip";
|
||||||
|
|
||||||
const DashboardCard = (props) => {
|
const DashboardCard = (props) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -24,9 +25,6 @@ const DashboardCard = (props) => {
|
|||||||
};
|
};
|
||||||
let body = {};
|
let body = {};
|
||||||
let currentUser;
|
let currentUser;
|
||||||
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
let currentUser1 = Parse.User.current();
|
let currentUser1 = Parse.User.current();
|
||||||
currentUser = currentUser1.id;
|
currentUser = currentUser1.id;
|
||||||
let res;
|
let res;
|
||||||
@@ -82,8 +80,6 @@ const DashboardCard = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
let reg1 = /(\#.*?\#)/gi; // eslint-disable-line
|
let reg1 = /(\#.*?\#)/gi; // eslint-disable-line
|
||||||
let _query = props.Data.query;
|
let _query = props.Data.query;
|
||||||
@@ -223,8 +219,6 @@ const DashboardCard = (props) => {
|
|||||||
|
|
||||||
if (restr.includes("#")) {
|
if (restr.includes("#")) {
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
let res;
|
let res;
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
if (localStorage.getItem("Extand_Class")) {
|
||||||
@@ -342,7 +336,7 @@ const DashboardCard = (props) => {
|
|||||||
props.Data && props.Data.Redirect_type
|
props.Data && props.Data.Redirect_type
|
||||||
? "cursor-pointer"
|
? "cursor-pointer"
|
||||||
: "cursor-default"
|
: "cursor-default"
|
||||||
} w-full h-[140px] px-3 pt-4 pb-10 text-white rounded-md shadow overflow-hidden`}
|
} w-full h-[140px] px-3 pt-4 pb-10 text-white rounded-md shadow overflow-hidden relative`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-start gap-5">
|
<div className="flex items-center justify-start gap-5">
|
||||||
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
|
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
|
||||||
@@ -359,6 +353,9 @@ const DashboardCard = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-xs absolute top-2 right-1">
|
||||||
|
<Tooltip id={props.Label} iconColor={"white"} message={props?.Data?.tourMessage} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,18 +45,16 @@ function DashboardReport(props) {
|
|||||||
setActions(json.actions);
|
setActions(json.actions);
|
||||||
setReportName(json.reportName);
|
setReportName(json.reportName);
|
||||||
setHeading(json.heading);
|
setHeading(json.heading);
|
||||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
|
||||||
Parse.initialize(localStorage.getItem("AppID12"));
|
|
||||||
const currentUser = Parse.User.current().id;
|
const currentUser = Parse.User.current().id;
|
||||||
|
|
||||||
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("parseAppId"),
|
||||||
sessiontoken: localStorage.getItem("accesstoken")
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
||||||
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
|
const url = `${localStorage.getItem("baseUrl")}/functions/getReport`;
|
||||||
const res = await axios.post(url, params, {
|
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
|
||||||
|
|||||||
@@ -1,21 +1,71 @@
|
|||||||
import React, { Suspense, lazy } from "react";
|
import React, { Suspense, lazy } from "react";
|
||||||
import ErrorBoundary from "../ErrorBoundary";
|
const DashboardButton = lazy(() => import("./DashboardButton"));
|
||||||
|
|
||||||
const DashboardCard = lazy(() => import("./DashboardCard"));
|
const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||||
|
|
||||||
const DashboardReport = lazy(() => import("./DashboardReport"));
|
const DashboardReport = lazy(() => import("./DashboardReport"));
|
||||||
|
const buttonList = [
|
||||||
|
{
|
||||||
|
label: "Sign yourself",
|
||||||
|
redirectId: "sHAnZphf69",
|
||||||
|
redirectType: "Form",
|
||||||
|
icon: "fas fa-pen-nib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Request signature",
|
||||||
|
redirectId: "8mZzFxbG1z",
|
||||||
|
redirectType: "Form",
|
||||||
|
icon: "fa-solid fa-paper-plane"
|
||||||
|
}
|
||||||
|
];
|
||||||
const GetDashboard = (props) => {
|
const GetDashboard = (props) => {
|
||||||
|
const Button = ({ label, redirectId, redirectType, icon }) => (
|
||||||
|
<div className={"bg-white rounded-md shadow w-full"}>
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<div style={{ height: "300px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "45%",
|
||||||
|
marginTop: "150px",
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<DashboardButton
|
||||||
|
Icon={icon}
|
||||||
|
Label={label}
|
||||||
|
Data={{ Redirect_type: redirectType, Redirect_id: redirectId }}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
const renderSwitchWithTour = (col) => {
|
const renderSwitchWithTour = (col) => {
|
||||||
switch (col.widget.type) {
|
switch (col.widget.type) {
|
||||||
case "Card":
|
case "Card":
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
|
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
|
||||||
data-tut={col.widget.data.tourSection}
|
data-tut={col.widget.data.tourSection}
|
||||||
style={{ background: col.widget.bgColor }}
|
style={{ background: col.widget.bgColor }}
|
||||||
>
|
>
|
||||||
<Suspense fallback={<div>please wait</div>}>
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<div style={{ height: "300px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "45%",
|
||||||
|
marginTop: "150px",
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<DashboardCard
|
<DashboardCard
|
||||||
Icon={col.widget.icon}
|
Icon={col.widget.icon}
|
||||||
Label={col.widget.label}
|
Label={col.widget.label}
|
||||||
@@ -31,7 +81,7 @@ const GetDashboard = (props) => {
|
|||||||
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-3 md:mb-0">
|
||||||
<DashboardReport Record={col.widget} />
|
<DashboardReport Record={col.widget} />
|
||||||
</div>
|
</div>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
@@ -47,7 +97,7 @@ const GetDashboard = (props) => {
|
|||||||
case "Card":
|
case "Card":
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
|
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
|
||||||
style={{ background: col.widget.bgColor }}
|
style={{ background: col.widget.bgColor }}
|
||||||
>
|
>
|
||||||
<Suspense fallback={<div>please wait</div>}>
|
<Suspense fallback={<div>please wait</div>}>
|
||||||
@@ -65,7 +115,7 @@ const GetDashboard = (props) => {
|
|||||||
case "report": {
|
case "report": {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<div>please wait</div>}>
|
<Suspense fallback={<div>please wait</div>}>
|
||||||
<div className="mb-4 md:mb-0">
|
<div className="mb-3 md:mb-0">
|
||||||
<DashboardReport Record={col.widget} />
|
<DashboardReport Record={col.widget} />
|
||||||
</div>
|
</div>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
@@ -76,25 +126,39 @@ const GetDashboard = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<div>
|
||||||
<div>
|
<div className="mb-3">
|
||||||
{props.dashboard.map((val, key) => (
|
<div
|
||||||
<div key={"a" + key} className="row">
|
data-tut={"tourbutton"}
|
||||||
{val.columns.map((col, i) =>
|
className="flex flex-col md:flex-row gap-6 md:gap-8"
|
||||||
col.widget.data && col.widget.data.tourSection ? (
|
>
|
||||||
<div key={i} className={props.classnameArray[key][i]}>
|
{buttonList.map((btn) => (
|
||||||
{renderSwitchWithTour(col)}
|
<Button
|
||||||
</div>
|
key={btn.label}
|
||||||
) : (
|
label={btn.label}
|
||||||
<div key={i} className={props.classnameArray[key][i]}>
|
redirectType={btn.redirectType}
|
||||||
{renderSwitch(col)}
|
redirectId={btn.redirectId}
|
||||||
</div>
|
icon={btn.icon}
|
||||||
)
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>
|
{props.dashboard.map((val, key) => (
|
||||||
|
<div key={"a" + key} className="row">
|
||||||
|
{val.columns.map((col, i) =>
|
||||||
|
col.widget.data && col.widget.data.tourSection ? (
|
||||||
|
<div key={i} className={props.classnameArray[key][i]}>
|
||||||
|
{renderSwitchWithTour(col)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div key={i} className={props.classnameArray[key][i]}>
|
||||||
|
{renderSwitch(col)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,18 @@
|
|||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import folder from "../../../assests/folder.png";
|
import folder from "../../assets/images/folder.png";
|
||||||
import "../LegaDrive.css";
|
import "../../styles/opensigndrive.css";
|
||||||
import draftDoc from "../../../assests/draftDoc1.png";
|
import pdfLogo from "../../assets/images/pdf3.png";
|
||||||
import pdfLogo from "../../../assests/pdf3.png";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import * as ContextMenu from "@radix-ui/react-context-menu";
|
import * as ContextMenu from "@radix-ui/react-context-menu";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
import { getHostUrl } from "../../../utils/Utils";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Table from "react-bootstrap/Table";
|
import Table from "react-bootstrap/Table";
|
||||||
import * as HoverCard from "@radix-ui/react-hover-card";
|
import * as HoverCard from "@radix-ui/react-hover-card";
|
||||||
import SelectFolder from "../../../premitives/SelectFolder";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import ModalUi from "../../../premitives/ModalUi";
|
import { themeColor } from "../../constant/const";
|
||||||
import { themeColor } from "../../../utils/ThemeColor/backColor";
|
import FolderModal from "../shared/fields/FolderModal";
|
||||||
|
|
||||||
function PdfFileComponent({
|
function DriveBody(props) {
|
||||||
pdfData,
|
|
||||||
setFolderName,
|
|
||||||
setDocId,
|
|
||||||
setIsLoading,
|
|
||||||
setPdfData,
|
|
||||||
isList,
|
|
||||||
setIsAlert
|
|
||||||
}) {
|
|
||||||
const [rename, setRename] = useState("");
|
const [rename, setRename] = useState("");
|
||||||
const [renameValue, setRenameValue] = useState("");
|
const [renameValue, setRenameValue] = useState("");
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
@@ -40,7 +30,6 @@ function PdfFileComponent({
|
|||||||
//to focus input box on press rename to change doc name
|
//to focus input box on press rename to change doc name
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rename && inputRef.current) {
|
if (rename && inputRef.current) {
|
||||||
// console.log("ref", inputRef.current)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
inputRef.current.focus();
|
inputRef.current.focus();
|
||||||
}, 10);
|
}, 10);
|
||||||
@@ -53,28 +42,25 @@ function PdfFileComponent({
|
|||||||
name: data.Name,
|
name: data.Name,
|
||||||
objectId: data.objectId
|
objectId: data.objectId
|
||||||
};
|
};
|
||||||
setFolderName((prev) => [...prev, folderData]);
|
props.setFolderName((prev) => [...prev, folderData]);
|
||||||
const loadObj = {
|
props.setIsLoading({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
};
|
});
|
||||||
|
props.setDocId(data.objectId);
|
||||||
setIsLoading(loadObj);
|
props.setPdfData([]);
|
||||||
setDocId(data.objectId);
|
props.setSkip(0);
|
||||||
};
|
};
|
||||||
//function for change doc name and update doc name in _document class
|
//function for change doc name and update doc name in _document class
|
||||||
const handledRenameDoc = async (data) => {
|
const handledRenameDoc = async (data) => {
|
||||||
setRename("");
|
setRename("");
|
||||||
const trimmedValue = renameValue.trim();
|
const trimmedValue = renameValue.trim();
|
||||||
|
|
||||||
if (trimmedValue.length > 0) {
|
if (trimmedValue.length > 0) {
|
||||||
const updateName = {
|
const updateName = {
|
||||||
Name: renameValue
|
Name: renameValue
|
||||||
};
|
};
|
||||||
const docId = data.objectId;
|
const docId = data.objectId;
|
||||||
|
const docData = props.pdfData;
|
||||||
const docData = pdfData;
|
|
||||||
|
|
||||||
const updatedData = docData.map((item) => {
|
const updatedData = docData.map((item) => {
|
||||||
if (item.objectId === docId) {
|
if (item.objectId === docId) {
|
||||||
// If the item's ID matches the target ID, update the name
|
// If the item's ID matches the target ID, update the name
|
||||||
@@ -83,8 +69,7 @@ function PdfFileComponent({
|
|||||||
// If the item's ID doesn't match, keep it unchanged
|
// If the item's ID doesn't match, keep it unchanged
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
props.setPdfData(updatedData);
|
||||||
setPdfData(updatedData);
|
|
||||||
await axios
|
await axios
|
||||||
.put(
|
.put(
|
||||||
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
||||||
@@ -99,12 +84,13 @@ function PdfFileComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((result) => {
|
.then(() => {
|
||||||
// const res = result.data;
|
// const res = result.data;
|
||||||
// console.log("res", res);
|
// console.log("res", res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setIsAlert({
|
console.log("Err ", err);
|
||||||
|
props.setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: "something went wrong"
|
||||||
});
|
});
|
||||||
@@ -114,57 +100,66 @@ 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 signerExist = data.Signers && data.Signers;
|
const signerExist = data.Signers && data.Signers;
|
||||||
const isDecline = data.IsDeclined && data.IsDeclined;
|
const isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
const isPlaceholder = data.Placeholders && data.Placeholders;
|
const isPlaceholder = data.Placeholders && data.Placeholders;
|
||||||
|
const signedUrl = data.SignedUrl;
|
||||||
//checking if document has completed and request signature flow
|
//checking if document has completed and request signature flow
|
||||||
if (data?.IsCompleted && signerExist?.length > 0) {
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has completed and signyour-self flow
|
//checking if document has completed and signyour-self flow
|
||||||
else if (!signerExist && !isPlaceholder) {
|
else if (!signerExist && !isPlaceholder) {
|
||||||
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has declined by someone
|
//checking if document has declined by someone
|
||||||
else if (isDecline) {
|
else if (isDecline) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
//checking draft type document
|
//checking draft type document
|
||||||
|
} else if (
|
||||||
|
signerExist?.length > 0 &&
|
||||||
|
isPlaceholder?.length > 0 &&
|
||||||
|
!signedUrl
|
||||||
|
) {
|
||||||
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//Inprogress document
|
//Inprogress document
|
||||||
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
} //placeholder draft document
|
} //placeholder draft document
|
||||||
else if (
|
else if (
|
||||||
(signerExist?.length > 0 &&
|
(signerExist?.length > 0 &&
|
||||||
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
||||||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
||||||
) {
|
) {
|
||||||
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuItemClick = (selectType, data) => {
|
const handleMenuItemClick = (selectType, data) => {
|
||||||
switch (selectType) {
|
switch (selectType) {
|
||||||
case "Download":
|
case "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, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
||||||
break;
|
break;
|
||||||
case "Rename":
|
}
|
||||||
|
case "Rename": {
|
||||||
setRenameValue(data.Name);
|
setRenameValue(data.Name);
|
||||||
setRename(data.objectId);
|
setRename(data.objectId);
|
||||||
break;
|
break;
|
||||||
case "Delete":
|
}
|
||||||
|
case "Delete": {
|
||||||
setIsDeleteDoc(true);
|
setIsDeleteDoc(true);
|
||||||
setSelectDoc(data);
|
setSelectDoc(data);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case "Move":
|
case "Move": {
|
||||||
handleMoveDocument(data);
|
handleMoveDocument(data);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//function for delete document
|
//function for delete document
|
||||||
@@ -192,12 +187,13 @@ function PdfFileComponent({
|
|||||||
.then((result) => {
|
.then((result) => {
|
||||||
const res = result.data;
|
const res = result.data;
|
||||||
if (res) {
|
if (res) {
|
||||||
const updatedData = pdfData.filter((x) => x.objectId !== docId);
|
const updatedData = props.pdfData.filter((x) => x.objectId !== docId);
|
||||||
setPdfData(updatedData);
|
props.setPdfData(updatedData);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setIsAlert({
|
console.log("Err ", err);
|
||||||
|
props.setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: "something went wrong"
|
||||||
});
|
});
|
||||||
@@ -218,8 +214,8 @@ function PdfFileComponent({
|
|||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
: selecFolderId
|
: selecFolderId
|
||||||
? false
|
? false
|
||||||
: true;
|
: true;
|
||||||
if (!checkExist) {
|
if (!checkExist) {
|
||||||
if (moveFolderId) {
|
if (moveFolderId) {
|
||||||
updateData = {
|
updateData = {
|
||||||
@@ -254,10 +250,10 @@ function PdfFileComponent({
|
|||||||
// console.log("Listdata ", Listdata);
|
// console.log("Listdata ", Listdata);
|
||||||
const res = Listdata.data;
|
const res = Listdata.data;
|
||||||
if (res) {
|
if (res) {
|
||||||
const updatedData = pdfData.filter(
|
const updatedData = props.pdfData.filter(
|
||||||
(x) => x.objectId !== updateDocId
|
(x) => x.objectId !== updateDocId
|
||||||
);
|
);
|
||||||
setPdfData(updatedData);
|
props.setPdfData(updatedData);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -282,21 +278,17 @@ function PdfFileComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDraftDoc = (data) => {
|
|
||||||
window.location.hash = `/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie?${data.objectId}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
//component to handle type of document and render according to type
|
//component to handle type of document and render according to type
|
||||||
const handleFolderData = (data, ind, listType) => {
|
const handleFolderData = (data, ind, listType) => {
|
||||||
let createddate, status, isDecline, signerExist, isComplete, isPlaceholder;
|
let createddate, status, isDecline, signerExist, isComplete;
|
||||||
if (data.Type !== "Folder") {
|
if (data.Type !== "Folder") {
|
||||||
const expireDate = data.ExpiryDate && data.ExpiryDate.iso;
|
const expireDate = data.ExpiryDate && data.ExpiryDate.iso;
|
||||||
const createdDate = data.createdAt && data.createdAt;
|
const createdDate = data.createdAt && data.createdAt;
|
||||||
createddate = new Date(createdDate).toLocaleDateString();
|
createddate = new Date(createdDate).toLocaleDateString();
|
||||||
isComplete = data.IsCompleted && data.IsCompleted ? true : false;
|
isComplete = data.IsCompleted && data.IsCompleted ? true : false;
|
||||||
isDecline = data.IsDeclined && data.IsDeclined;
|
isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
isPlaceholder = data.Placeholders && data.Placeholders;
|
|
||||||
signerExist = data.Signers && data.Signers;
|
signerExist = data.Signers && data.Signers;
|
||||||
|
const signedUrl = data.SignedUrl;
|
||||||
|
|
||||||
const expireUpdateDate = new Date(expireDate).getTime();
|
const expireUpdateDate = new Date(expireDate).getTime();
|
||||||
const currDate = new Date().getTime();
|
const currDate = new Date().getTime();
|
||||||
@@ -309,12 +301,7 @@ function PdfFileComponent({
|
|||||||
status = "Completed";
|
status = "Completed";
|
||||||
} else if (isDecline) {
|
} else if (isDecline) {
|
||||||
status = "Declined";
|
status = "Declined";
|
||||||
} else if (!signerExist || signerExist?.length === 0) {
|
} else if (!signedUrl) {
|
||||||
status = "Draft";
|
|
||||||
} else if (
|
|
||||||
signerExist?.length > 0 &&
|
|
||||||
(!isPlaceholder || isPlaceholder?.length === 0)
|
|
||||||
) {
|
|
||||||
status = "Draft";
|
status = "Draft";
|
||||||
} else if (isExpire) {
|
} else if (isExpire) {
|
||||||
status = "Expired";
|
status = "Expired";
|
||||||
@@ -357,25 +344,6 @@ function PdfFileComponent({
|
|||||||
<td>_</td>
|
<td>_</td>
|
||||||
<td>_</td>
|
<td>_</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : data.Type === "AIDoc" ? (
|
|
||||||
<tr onClick={() => handleDraftDoc(data)}>
|
|
||||||
<td
|
|
||||||
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-file-text"
|
|
||||||
style={{ color: "#0ea3ed", marginRight: "8px", fontSize: "26px" }}
|
|
||||||
></i>
|
|
||||||
|
|
||||||
<span style={{ fontSize: "12px", fontWeight: "500" }}>
|
|
||||||
{data.Name}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>{createddate}</td>
|
|
||||||
<td>LegaGenie Draft</td>
|
|
||||||
<td>_</td>
|
|
||||||
<td>_</td>
|
|
||||||
</tr>
|
|
||||||
) : (
|
) : (
|
||||||
<tr onClick={() => checkPdfStatus(data)}>
|
<tr onClick={() => checkPdfStatus(data)}>
|
||||||
<td
|
<td
|
||||||
@@ -464,72 +432,7 @@ function PdfFileComponent({
|
|||||||
onClick={() => handleMenuItemClick("Rename", data)}
|
onClick={() => handleMenuItemClick("Rename", data)}
|
||||||
className="ContextMenuItem"
|
className="ContextMenuItem"
|
||||||
>
|
>
|
||||||
<i class="fa-solid fa-font"></i>
|
<i className="fa-solid fa-font"></i>
|
||||||
<span style={{ marginLeft: "8px" }}>Rename</span>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
</ContextMenu.Content>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu.Root>
|
|
||||||
</div>
|
|
||||||
) : data.Type === "AIDoc" ? (
|
|
||||||
<div key={ind} className="folderBox">
|
|
||||||
<ContextMenu.Root>
|
|
||||||
<ContextMenu.Trigger className="ContextMenuTrigger">
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
cursor: "pointer"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="no img"
|
|
||||||
onClick={() => handleDraftDoc(data)}
|
|
||||||
src={draftDoc}
|
|
||||||
width={100}
|
|
||||||
height={103}
|
|
||||||
/>
|
|
||||||
{rename === data.objectId ? (
|
|
||||||
<input
|
|
||||||
onFocus={() => {
|
|
||||||
inputRef.current.setSelectionRange(0, 0);
|
|
||||||
const input = inputRef.current;
|
|
||||||
if (input) {
|
|
||||||
input.select();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
autoFocus={true}
|
|
||||||
type="text"
|
|
||||||
onBlur={() => handledRenameDoc(data)}
|
|
||||||
onKeyDown={(e) => handleEnterPress(e, data)}
|
|
||||||
ref={inputRef}
|
|
||||||
defaultValue={renameValue}
|
|
||||||
// value={renameValue}
|
|
||||||
onChange={(e) => setRenameValue(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: "100px",
|
|
||||||
border: "1.5px solid black",
|
|
||||||
borderRadius: "2px",
|
|
||||||
fontSize: "10px"
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="foldName">{data.Name}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.Content
|
|
||||||
className="ContextMenuContent"
|
|
||||||
sideOffset={5}
|
|
||||||
align="end"
|
|
||||||
>
|
|
||||||
<ContextMenu.Item
|
|
||||||
onClick={() => handleMenuItemClick("Rename", data)}
|
|
||||||
className="ContextMenuItem"
|
|
||||||
>
|
|
||||||
<i class="fa-solid fa-font"></i>
|
|
||||||
<span style={{ marginLeft: "8px" }}>Rename</span>
|
<span style={{ marginLeft: "8px" }}>Rename</span>
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
</ContextMenu.Content>
|
</ContextMenu.Content>
|
||||||
@@ -615,7 +518,7 @@ function PdfFileComponent({
|
|||||||
onClick={() => handleMenuItemClick(menu.type, data)}
|
onClick={() => handleMenuItemClick(menu.type, data)}
|
||||||
className="ContextMenuItem"
|
className="ContextMenuItem"
|
||||||
>
|
>
|
||||||
<i class={menu.icon}></i>
|
<i className={menu.icon}></i>
|
||||||
<span style={{ marginLeft: "8px" }}>{menu.type}</span>
|
<span style={{ marginLeft: "8px" }}>{menu.type}</span>
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
);
|
);
|
||||||
@@ -657,7 +560,7 @@ function PdfFileComponent({
|
|||||||
//component to handle type of document and render according to type
|
//component to handle type of document and render according to type
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isList ? (
|
{props.isList ? (
|
||||||
<div className="container" style={{ overflowX: "auto" }}>
|
<div className="container" style={{ overflowX: "auto" }}>
|
||||||
<Table striped bordered hover>
|
<Table striped bordered hover>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -670,7 +573,7 @@ function PdfFileComponent({
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{pdfData.map((data, ind) => {
|
{props.pdfData.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
{handleFolderData(data, ind, "table")}
|
{handleFolderData(data, ind, "table")}
|
||||||
@@ -682,7 +585,7 @@ function PdfFileComponent({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="pdfContainer">
|
<div className="pdfContainer">
|
||||||
{pdfData.map((data, ind) => {
|
{props.pdfData.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<div className="box" key={ind}>
|
<div className="box" key={ind}>
|
||||||
{handleFolderData(data, ind, "list")}
|
{handleFolderData(data, ind, "list")}
|
||||||
@@ -691,18 +594,19 @@ function PdfFileComponent({
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isOpenMoveModal && (
|
{isOpenMoveModal && (
|
||||||
<SelectFolder
|
<FolderModal
|
||||||
onSuccess={handleMoveFolder}
|
onSuccess={handleMoveFolder}
|
||||||
isOpenModal={isOpenMoveModal}
|
isOpenModal={isOpenMoveModal}
|
||||||
folderCls={"contracts_Document"}
|
folderCls={"contracts_Document"}
|
||||||
setIsOpenMoveModal={setIsOpenMoveModal}
|
setIsOpenMoveModal={setIsOpenMoveModal}
|
||||||
setPdfData={setPdfData}
|
setPdfData={props.setPdfData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isDeleteDoc}
|
isOpen={isDeleteDoc}
|
||||||
headerColor={themeColor()}
|
headerColor={themeColor}
|
||||||
title={"Delete Document"}
|
title={"Delete Document"}
|
||||||
handleClose={() => {
|
handleClose={() => {
|
||||||
setIsDeleteDoc(false);
|
setIsDeleteDoc(false);
|
||||||
@@ -726,7 +630,7 @@ function PdfFileComponent({
|
|||||||
handleDeleteDocument(selectDoc);
|
handleDeleteDocument(selectDoc);
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -749,4 +653,4 @@ function PdfFileComponent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfFileComponent;
|
export default DriveBody;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ModalUi from "../../premitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
|
||||||
const AddRoleModal = (props) => {
|
const AddRoleModal = (props) => {
|
||||||
return (
|
return (
|
||||||
@@ -30,7 +30,7 @@ const AddRoleModal = (props) => {
|
|||||||
margin: "10px 0 10px 5px"
|
margin: "10px 0 10px 5px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
e.g: Hr, Director, Manager, New joinee, Accountant, etc...
|
e.g: Customer, Hr, Director, Manager, Student, etc...
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import "./certificate.css";
|
import opensignLogo from "../../assets/images/logo.png";
|
||||||
import opensignLogo from "../../assests/open-sign-logo.png";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Page,
|
Page,
|
||||||
Text,
|
Text,
|
||||||
@@ -18,6 +16,7 @@ function Certificate({ pdfData }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleSignerData();
|
handleSignerData();
|
||||||
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSignerData = () => {
|
const handleSignerData = () => {
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
function DefaultSignature({
|
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
||||||
themeColor,
|
|
||||||
defaultSignImg,
|
|
||||||
xyPostion,
|
|
||||||
setDefaultSignAlert
|
|
||||||
}) {
|
|
||||||
const confirmToaddDefaultSign = () => {
|
const confirmToaddDefaultSign = () => {
|
||||||
if (xyPostion.length > 0) {
|
if (xyPostion.length > 0) {
|
||||||
setDefaultSignAlert({
|
setDefaultSignAlert({
|
||||||
@@ -25,7 +20,7 @@ function DefaultSignature({
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
padding: "5px",
|
padding: "5px",
|
||||||
fontFamily: "sans-serif",
|
fontFamily: "sans-serif",
|
||||||
@@ -58,7 +53,7 @@ function DefaultSignature({
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
marginTop: "20px",
|
marginTop: "20px",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Loader from "./component/loader";
|
import Loader from "../../primitives/LoaderWithMsg";
|
||||||
import { contractDocument, getHostUrl } from "../utils/Utils";
|
import { contractDocument } from "../../constant/Utils";
|
||||||
|
import HandleError from "../../primitives/HandleError";
|
||||||
function DraftDocument() {
|
function DraftDocument() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [pdfDetails, setPdfDetails] = useState([]);
|
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoader: true,
|
||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -19,68 +19,77 @@ function DraftDocument() {
|
|||||||
: rowLevel?.objectId && rowLevel.objectId;
|
: rowLevel?.objectId && rowLevel.objectId;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (docId) {
|
getDocumentDetails();
|
||||||
getDocumentDetails();
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
//get document details
|
//get document details
|
||||||
const getDocumentDetails = async () => {
|
const getDocumentDetails = async () => {
|
||||||
//getting document details
|
//getting document details
|
||||||
const documentData = await contractDocument(docId);
|
const documentData = await contractDocument(docId);
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
setPdfDetails(documentData);
|
handleDraftDoc(documentData);
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
} else if (
|
} else if (
|
||||||
documentData === "Error: Something went wrong!" ||
|
documentData === "Error: Something went wrong!" ||
|
||||||
(documentData.result && documentData.result.error)
|
(documentData.result && documentData.result.error)
|
||||||
) {
|
) {
|
||||||
alert("Error: Something went wrong!");
|
setIsLoading({
|
||||||
|
isLoader: false,
|
||||||
|
message: "Error: Something went wrong!"
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert("No data found!");
|
setIsLoading({
|
||||||
|
isLoader: false,
|
||||||
|
message: "No data found!"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//check document type and render on signyour self and placeholder route
|
//check document type and render on signyour self and placeholder route
|
||||||
const handleDraftDoc = () => {
|
const handleDraftDoc = (documentData) => {
|
||||||
const data = pdfDetails[0];
|
const data = documentData[0];
|
||||||
const hostUrl = getHostUrl();
|
|
||||||
const signerExist = data.Signers && data.Signers;
|
const signerExist = data.Signers && data.Signers;
|
||||||
const isDecline = data.IsDeclined && data.IsDeclined;
|
const isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
const isPlaceholder = data.Placeholders && data.Placeholders;
|
const isPlaceholder = data.Placeholders && data.Placeholders;
|
||||||
|
const signedUrl = data.SignedUrl;
|
||||||
//checking if document has completed and request signature flow
|
//checking if document has completed and request signature flow
|
||||||
if (data?.IsCompleted && signerExist?.length > 0) {
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has completed and signyour-self flow
|
//checking if document has completed and signyour-self flow
|
||||||
else if (!signerExist && !isPlaceholder) {
|
else if (!signerExist && !isPlaceholder) {
|
||||||
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has declined by someone
|
//checking if document has declined by someone
|
||||||
else if (isDecline) {
|
else if (isDecline) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
//checking draft type document
|
//checking draft type document
|
||||||
|
} else if (
|
||||||
|
signerExist?.length > 0 &&
|
||||||
|
isPlaceholder?.length > 0 &&
|
||||||
|
!signedUrl
|
||||||
|
) {
|
||||||
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//Inprogress document
|
//Inprogress document
|
||||||
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
} //placeholder draft document
|
} //placeholder draft document
|
||||||
else if (
|
else if (
|
||||||
(signerExist?.length > 0 &&
|
(signerExist?.length > 0 &&
|
||||||
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
||||||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
||||||
) {
|
) {
|
||||||
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isLoading.isLoad ? <Loader isLoading={isLoading} /> : handleDraftDoc()}
|
{isLoading.isLoader ? (
|
||||||
|
<Loader isLoading={isLoading} />
|
||||||
|
) : (
|
||||||
|
<HandleError handleError={isLoading.message} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { getWidgetType, widgets } from "../../constant/Utils";
|
||||||
|
|
||||||
|
function DragElement(item) {
|
||||||
|
const getWidgets = widgets;
|
||||||
|
const filterWidgetPreview = getWidgets.filter(
|
||||||
|
(data) => data.type === item?.text
|
||||||
|
);
|
||||||
|
|
||||||
|
return <div>{getWidgetType(filterWidgetPreview[0])}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DragElement;
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { isEnableSubscription, themeColor } from "../../constant/const";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { radioButtonWidget } from "../../constant/Utils";
|
||||||
|
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||||
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
|
function DropdownWidgetOption(props) {
|
||||||
|
const [dropdownOptionList, setDropdownOptionList] = useState([
|
||||||
|
"option-1",
|
||||||
|
"option-2"
|
||||||
|
]);
|
||||||
|
const [minCount, setMinCount] = useState(0);
|
||||||
|
const [maxCount, setMaxCount] = useState(0);
|
||||||
|
const [dropdownName, setDropdownName] = useState(props.type);
|
||||||
|
const [isReadOnly, setIsReadOnly] = useState(false);
|
||||||
|
const [isHideLabel, setIsHideLabel] = useState(false);
|
||||||
|
const [status, setStatus] = useState("required");
|
||||||
|
const [defaultValue, setDefaultValue] = useState("");
|
||||||
|
const statusArr = ["required", "optional"];
|
||||||
|
const [defaultCheckbox, setDefaultCheckbox] = useState([]);
|
||||||
|
|
||||||
|
const resetState = () => {
|
||||||
|
setDropdownOptionList(["option-1", "option-2"]);
|
||||||
|
setDropdownName(props.type);
|
||||||
|
setIsReadOnly(false);
|
||||||
|
setIsHideLabel(false);
|
||||||
|
setMinCount(0);
|
||||||
|
setMaxCount(0);
|
||||||
|
setDefaultCheckbox([]);
|
||||||
|
setDefaultValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
props.currWidgetsDetails?.options?.name &&
|
||||||
|
props.currWidgetsDetails?.options?.values
|
||||||
|
) {
|
||||||
|
setDropdownName(props.currWidgetsDetails?.options?.name);
|
||||||
|
setDropdownOptionList(props.currWidgetsDetails?.options?.values);
|
||||||
|
setMinCount(
|
||||||
|
props.currWidgetsDetails?.options?.validation?.minRequiredCount
|
||||||
|
);
|
||||||
|
setMaxCount(
|
||||||
|
props.currWidgetsDetails?.options?.validation?.maxRequiredCount
|
||||||
|
);
|
||||||
|
setIsReadOnly(props.currWidgetsDetails?.options?.isReadOnly);
|
||||||
|
setIsHideLabel(props.currWidgetsDetails?.options?.isHideLabel);
|
||||||
|
setStatus(props.currWidgetsDetails?.options?.status || "required");
|
||||||
|
setDefaultValue(props.currWidgetsDetails?.options?.defaultValue || "");
|
||||||
|
setDefaultCheckbox(props.currWidgetsDetails?.options?.defaultValue || []);
|
||||||
|
} else {
|
||||||
|
setStatus("required");
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.currWidgetsDetails]);
|
||||||
|
const handleInputChange = (index, value) => {
|
||||||
|
setDropdownOptionList((prevInputs) => {
|
||||||
|
const newInputs = [...prevInputs];
|
||||||
|
newInputs[index] = value;
|
||||||
|
return newInputs;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//function add add checkbox option and add width of checkbox
|
||||||
|
const handleAddInput = () => {
|
||||||
|
const deleteOption = false;
|
||||||
|
const addOption = true;
|
||||||
|
setDropdownOptionList((prevInputs) => [...prevInputs, ""]);
|
||||||
|
props.handleSaveWidgetsOptions(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
addOption,
|
||||||
|
deleteOption
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//function add add checkbox option and delete width of checkbox
|
||||||
|
const handleDeleteInput = (ind) => {
|
||||||
|
const deleteOption = true;
|
||||||
|
const addOption = false;
|
||||||
|
const getUpdatedOptions = dropdownOptionList.filter(
|
||||||
|
(data, index) => index !== ind
|
||||||
|
);
|
||||||
|
setDropdownOptionList(getUpdatedOptions);
|
||||||
|
props.handleSaveWidgetsOptions(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
addOption,
|
||||||
|
deleteOption
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveOption = () => {
|
||||||
|
const defaultData =
|
||||||
|
defaultCheckbox && defaultCheckbox.length > 0
|
||||||
|
? defaultCheckbox
|
||||||
|
: defaultValue;
|
||||||
|
|
||||||
|
props.handleSaveWidgetsOptions(
|
||||||
|
dropdownName,
|
||||||
|
dropdownOptionList,
|
||||||
|
minCount,
|
||||||
|
maxCount,
|
||||||
|
isReadOnly,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
status,
|
||||||
|
defaultData,
|
||||||
|
isHideLabel
|
||||||
|
);
|
||||||
|
// props.setShowDropdown(false);
|
||||||
|
setDropdownOptionList(["option-1", "option-2"]);
|
||||||
|
setDropdownName(props.type);
|
||||||
|
// props.setCurrWidgetsDetails({});
|
||||||
|
setIsReadOnly(false);
|
||||||
|
setIsHideLabel(false);
|
||||||
|
setMinCount(0);
|
||||||
|
setMaxCount(0);
|
||||||
|
setDefaultCheckbox([]);
|
||||||
|
setDefaultValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSetMinMax = (e) => {
|
||||||
|
const minValue = e.target.value;
|
||||||
|
if (minValue > dropdownOptionList.length) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return minValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDefaultCheck = (index) => {
|
||||||
|
const getDefaultCheck = defaultCheckbox.includes(index);
|
||||||
|
if (getDefaultCheck) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalUi isOpen={props.showDropdown} title={props.title} showClose={false}>
|
||||||
|
<div className="h-full p-[15px]">
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSaveOption();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
||||||
|
Name<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={dropdownName}
|
||||||
|
value={dropdownName}
|
||||||
|
onChange={(e) => setDropdownName(e.target.value)}
|
||||||
|
className="drodown-input"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label
|
||||||
|
style={{ fontSize: "13px", fontWeight: "600", marginTop: "5px" }}
|
||||||
|
>
|
||||||
|
Options
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{dropdownOptionList.map((option, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
marginBottom: "5px",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.type === "checkbox" && !props.isSignYourself && (
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={handleDefaultCheck(index)}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
const getDefaultCheck =
|
||||||
|
defaultCheckbox?.includes(index);
|
||||||
|
if (!getDefaultCheck) {
|
||||||
|
setDefaultCheckbox((prev) => [...prev, index]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const removeOption = defaultCheckbox.filter(
|
||||||
|
(data) => data !== index
|
||||||
|
);
|
||||||
|
setDefaultCheckbox(removeOption);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: "23px",
|
||||||
|
height: "19px",
|
||||||
|
marginRight: "5px"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
className="drodown-input"
|
||||||
|
type="text"
|
||||||
|
value={option}
|
||||||
|
onChange={(e) => handleInputChange(index, e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-rectangle-xmark"
|
||||||
|
onClick={() => handleDeleteInput(index)}
|
||||||
|
style={{
|
||||||
|
color: "red",
|
||||||
|
fontSize: "25px",
|
||||||
|
marginLeft: "10px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<i
|
||||||
|
onClick={handleAddInput}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
color: themeColor,
|
||||||
|
fontSize: "25px",
|
||||||
|
marginLeft: "10px"
|
||||||
|
}}
|
||||||
|
className="fa-solid fa-square-plus"
|
||||||
|
></i>
|
||||||
|
<div>
|
||||||
|
{props.type === "checkbox" && !props.isSignYourself && (
|
||||||
|
<>
|
||||||
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "600",
|
||||||
|
color: !props.isSubscribe && "gray"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Minimun check
|
||||||
|
</label>
|
||||||
|
{!props.isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={0}
|
||||||
|
value={minCount}
|
||||||
|
onChange={(e) => {
|
||||||
|
const count = handleSetMinMax(e);
|
||||||
|
setMinCount(count);
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
props.isSubscribe || !isEnableSubscription
|
||||||
|
? "drodown-input"
|
||||||
|
: "disabled drodown-input"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "600",
|
||||||
|
color: !props.isSubscribe && "gray"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Maximum check
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={0}
|
||||||
|
value={maxCount}
|
||||||
|
onChange={(e) => {
|
||||||
|
const count = handleSetMinMax(e);
|
||||||
|
setMaxCount(count);
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
props.isSubscribe || !isEnableSubscription
|
||||||
|
? "drodown-input"
|
||||||
|
: "disabled drodown-input"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{["dropdown", radioButtonWidget].includes(props.type) && (
|
||||||
|
<>
|
||||||
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "600",
|
||||||
|
marginTop: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Default value
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
onChange={(e) => setDefaultValue(e.target.value)}
|
||||||
|
className="drodown-input"
|
||||||
|
name="defaultvalue"
|
||||||
|
value={defaultValue}
|
||||||
|
placeholder="select default value"
|
||||||
|
>
|
||||||
|
<option value="" disabled hidden style={{ fontSize: "13px" }}>
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{dropdownOptionList.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<option
|
||||||
|
style={{ fontSize: "13px" }}
|
||||||
|
key={ind}
|
||||||
|
value={data}
|
||||||
|
>
|
||||||
|
{data}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{props.type !== "checkbox" && props.type !== radioButtonWidget && (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
marginTop: "0.5rem"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{statusArr.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={ind}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 5,
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style={{ accentColor: "red" }}
|
||||||
|
type="radio"
|
||||||
|
name="status"
|
||||||
|
onChange={() => setStatus(data.toLowerCase())}
|
||||||
|
checked={status.toLowerCase() === data.toLowerCase()}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: "13px", fontWeight: "500" }}>
|
||||||
|
{data}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{["checkbox", radioButtonWidget].includes(props.type) && (
|
||||||
|
<div className="flex flex-row gap-5 mt-2 items-center text-center">
|
||||||
|
{!props.isSignYourself && (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="isreadonly"
|
||||||
|
type="checkbox"
|
||||||
|
checked={isReadOnly}
|
||||||
|
onChange={(e) => {
|
||||||
|
setIsReadOnly(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="ml-1" htmlFor="isreadonly">
|
||||||
|
Is read only
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="ishidelabel"
|
||||||
|
type="checkbox"
|
||||||
|
checked={isHideLabel}
|
||||||
|
onChange={(e) => {
|
||||||
|
setIsHideLabel(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label className="ml-1" htmlFor="ishidelabel">
|
||||||
|
Hide labels
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{props.type === "checkbox" &&
|
||||||
|
!props.isSignYourself &&
|
||||||
|
!isEnableSubscription && (
|
||||||
|
<PremiumAlertHeader
|
||||||
|
message={
|
||||||
|
"Field validations are free in beta, this feature will incur a fee later."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
props.type === "checkbox" && !props.isSignYourself
|
||||||
|
? "mb-[15px]"
|
||||||
|
: "my-[15px]"
|
||||||
|
} w-full h-[1px] bg-[#9f9f9f]`}
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
disabled={dropdownOptionList.length === 0 && true}
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
className={"finishBtn"}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
{props.currWidgetsDetails?.options?.values?.length > 0 && (
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
onClick={() => {
|
||||||
|
props.handleClose && props.handleClose();
|
||||||
|
resetState();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DropdownWidgetOption;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import "../../css/AddUser.css";
|
import "../../styles/AddUser.css";
|
||||||
// import SelectFolder from "../../premitives/SelectFolder";
|
// import SelectFolder from "../../premitives/SelectFolder";
|
||||||
|
|
||||||
const EditTemplate = ({ template, onSuccess }) => {
|
const EditTemplate = ({ template, onSuccess }) => {
|
||||||
@@ -45,7 +45,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
fontWeight: "700"
|
fontWeight: "700"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{template.URL?.split("/")[3]?.split("_")[1]}
|
{template.URL?.split("/")?.pop()?.split("_")[1]}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
import celebration from "../../assests/newCeleb.gif";
|
import celebration from "../../assets/images/newCeleb.gif";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { getBase64FromUrl } from "../../utils/Utils";
|
import { getBase64FromUrl } from "../../constant/Utils";
|
||||||
import { themeColor } from "../../utils/ThemeColor/backColor";
|
import { themeColor } from "../../constant/const";
|
||||||
import printModule from "print-js";
|
import printModule from "print-js";
|
||||||
import loader from "../../assests/loader2.gif";
|
import loader from "../../assets/images/loader2.gif";
|
||||||
|
|
||||||
function EmailComponent({
|
function EmailComponent({
|
||||||
isEmail,
|
isEmail,
|
||||||
@@ -15,7 +15,8 @@ function EmailComponent({
|
|||||||
setSuccessEmail,
|
setSuccessEmail,
|
||||||
pdfName,
|
pdfName,
|
||||||
sender,
|
sender,
|
||||||
setIsAlert
|
setIsAlert,
|
||||||
|
extUserId
|
||||||
}) {
|
}) {
|
||||||
const [emailList, setEmailList] = useState([]);
|
const [emailList, setEmailList] = useState([]);
|
||||||
const [emailValue, setEmailValue] = useState();
|
const [emailValue, setEmailValue] = useState();
|
||||||
@@ -28,7 +29,6 @@ function EmailComponent({
|
|||||||
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";
|
|
||||||
|
|
||||||
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
|
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -37,8 +37,9 @@ function EmailComponent({
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
||||||
const themeBGcolor = themeColor();
|
const themeBGcolor = themeColor;
|
||||||
let params = {
|
let params = {
|
||||||
|
extUserId: extUserId,
|
||||||
pdfName: pdfName,
|
pdfName: pdfName,
|
||||||
url: pdfUrl,
|
url: pdfUrl,
|
||||||
recipient: emailList[i],
|
recipient: emailList[i],
|
||||||
@@ -362,7 +363,7 @@ function EmailComponent({
|
|||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: themeColor(),
|
backgroundColor: themeColor,
|
||||||
padding: "5px 7px",
|
padding: "5px 7px",
|
||||||
marginTop: "10px",
|
marginTop: "10px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -399,7 +400,7 @@ function EmailComponent({
|
|||||||
<button
|
<button
|
||||||
disabled={emailList.length === 0 && true}
|
disabled={emailList.length === 0 && true}
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import PrevNext from "./prevNext";
|
import PrevNext from "./PrevNext";
|
||||||
import { PDFDownloadLink } from "@react-pdf/renderer";
|
import { PDFDownloadLink } from "@react-pdf/renderer";
|
||||||
import Certificate from "../Certificate/Certificate";
|
import Certificate from "./Certificate";
|
||||||
import printModule from "print-js";
|
import printModule from "print-js";
|
||||||
import { getBase64FromUrl } from "../../utils/Utils";
|
import { getBase64FromUrl } from "../../constant/Utils";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
import "../../css/signature.css";
|
import "../../styles/signature.css";
|
||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { themeColor } from "../../utils/ThemeColor/backColor";
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
isPdfRequestFiles,
|
isPdfRequestFiles,
|
||||||
@@ -21,7 +21,7 @@ function Header({
|
|||||||
changePage,
|
changePage,
|
||||||
pdfUrl,
|
pdfUrl,
|
||||||
documentStatus,
|
documentStatus,
|
||||||
embedImages,
|
embedWidgetsData,
|
||||||
pdfDetails,
|
pdfDetails,
|
||||||
signerPos,
|
signerPos,
|
||||||
signersdata,
|
signersdata,
|
||||||
@@ -38,6 +38,8 @@ function Header({
|
|||||||
completeBtnTitle,
|
completeBtnTitle,
|
||||||
setIsEditTemplate
|
setIsEditTemplate
|
||||||
}) {
|
}) {
|
||||||
|
const filterPrefill =
|
||||||
|
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
||||||
@@ -119,7 +121,7 @@ function Header({
|
|||||||
style={{ textDecoration: "none", zIndex: "35" }}
|
style={{ textDecoration: "none", zIndex: "35" }}
|
||||||
document={<Certificate pdfData={pdfDetails} />}
|
document={<Certificate pdfData={pdfDetails} />}
|
||||||
>
|
>
|
||||||
{({ blob, url, loading, error }) => (
|
{({ blob, loading }) => (
|
||||||
<>
|
<>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div
|
<div
|
||||||
@@ -129,20 +131,15 @@ function Header({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-certificate"
|
className="fa-solid fa-award"
|
||||||
style={{
|
style={{ marginRight: "2px" }}
|
||||||
marginRight: "2px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Certificate
|
Certificate
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{ border: "none", backgroundColor: "#fff" }}
|
||||||
border: "none",
|
|
||||||
backgroundColor: "#fff"
|
|
||||||
}}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleDownload(
|
handleDownload(
|
||||||
blob,
|
blob,
|
||||||
@@ -153,10 +150,8 @@ function Header({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-certificate"
|
className="fa-solid fa-award"
|
||||||
style={{
|
style={{ marginRight: "2px" }}
|
||||||
marginRight: "2px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Certificate
|
Certificate
|
||||||
@@ -176,51 +171,29 @@ function Header({
|
|||||||
pdfDetails[0] && pdfDetails[0].Name
|
pdfDetails[0] && pdfDetails[0].Name
|
||||||
}.pdf`}
|
}.pdf`}
|
||||||
>
|
>
|
||||||
{({ blob, url, loading, error }) =>
|
{({ loading }) => (
|
||||||
loading ? (
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
className="defaultBtn certificateBtn"
|
||||||
className="defaultBtn certificateBtn"
|
disabled={loading}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-award"
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
color: "white",
|
||||||
flexDirection: "row",
|
fontSize: "15px",
|
||||||
alignItems: "center"
|
marginRight: "3px"
|
||||||
}}
|
}}
|
||||||
>
|
aria-hidden="true"
|
||||||
<i
|
></i>
|
||||||
className="fa fa-certificate"
|
Certificate
|
||||||
style={{
|
</button>
|
||||||
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>
|
</PDFDownloadLink>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -245,7 +218,7 @@ function Header({
|
|||||||
<i
|
<i
|
||||||
className="fa fa-arrow-left"
|
className="fa fa-arrow-left"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{ color: themeColor(), cursor: "pointer" }}
|
style={{ color: themeColor, cursor: "pointer" }}
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -283,7 +256,7 @@ function Header({
|
|||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
color: themeColor(),
|
color: themeColor,
|
||||||
border: "none",
|
border: "none",
|
||||||
fontWeight: "650",
|
fontWeight: "650",
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
@@ -407,7 +380,7 @@ function Header({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color: isMailSend ? "gray" : themeColor(),
|
color: isMailSend ? "gray" : themeColor,
|
||||||
border: "none",
|
border: "none",
|
||||||
fontWeight: "650",
|
fontWeight: "650",
|
||||||
fontSize: "16px"
|
fontSize: "16px"
|
||||||
@@ -421,13 +394,13 @@ function Header({
|
|||||||
data-tut="reactourThird"
|
data-tut="reactourThird"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
} else if (isPdfRequestFiles) {
|
} else if (isPdfRequestFiles) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color: themeColor(),
|
color: themeColor,
|
||||||
border: "none",
|
border: "none",
|
||||||
fontWeight: "650",
|
fontWeight: "650",
|
||||||
fontSize: "16px"
|
fontSize: "16px"
|
||||||
@@ -453,7 +426,7 @@ function Header({
|
|||||||
{recipient ? (
|
{recipient ? (
|
||||||
pdfUrl || isAlreadySign.mssg ? (
|
pdfUrl || isAlreadySign.mssg ? (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
{pdfDetails[0] && pdfDetails.length > 0 && (
|
{pdfDetails && pdfDetails.length > 0 && (
|
||||||
<CertificateComponent />
|
<CertificateComponent />
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
@@ -521,7 +494,7 @@ function Header({
|
|||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -533,16 +506,16 @@ function Header({
|
|||||||
<>
|
<>
|
||||||
{!isMailSend &&
|
{!isMailSend &&
|
||||||
signersdata.length > 0 &&
|
signersdata.length > 0 &&
|
||||||
signersdata.length !== signerPos.length && (
|
signersdata.length !== filterPrefill.length && (
|
||||||
<div>
|
<div>
|
||||||
{signerPos.length === 0 ? (
|
{filterPrefill.length === 0 ? (
|
||||||
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
||||||
Add {signersdata.length - signerPos.length} recipients
|
Add {signersdata.length - filterPrefill.length}{" "}
|
||||||
signature
|
recipients signature
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
||||||
Add {signersdata.length - signerPos.length} more
|
Add {signersdata.length - filterPrefill.length} more
|
||||||
recipients signature
|
recipients signature
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -667,7 +640,7 @@ function Header({
|
|||||||
type="button"
|
type="button"
|
||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Finish
|
Finish
|
||||||
@@ -765,7 +738,7 @@ function Header({
|
|||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -0,0 +1,751 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import BorderResize from "./BorderResize";
|
||||||
|
import PlaceholderBorder from "./PlaceholderBorder";
|
||||||
|
import { Rnd } from "react-rnd";
|
||||||
|
import {
|
||||||
|
defaultWidthHeight,
|
||||||
|
handleCopyNextToWidget,
|
||||||
|
isMobile,
|
||||||
|
onChangeInput,
|
||||||
|
radioButtonWidget,
|
||||||
|
textInputWidget,
|
||||||
|
textWidget
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
import PlaceholderType from "./PlaceholderType";
|
||||||
|
import moment from "moment";
|
||||||
|
import "../../styles/opensigndrive.css";
|
||||||
|
|
||||||
|
const selectFormat = (data) => {
|
||||||
|
switch (data) {
|
||||||
|
case "L":
|
||||||
|
return "MM/dd/yyyy";
|
||||||
|
case "DD-MM-YYYY":
|
||||||
|
return "dd-MM-yyyy";
|
||||||
|
case "DD/MM/YYYY":
|
||||||
|
return "dd/MM/yyyy";
|
||||||
|
case "LL":
|
||||||
|
return "MMMM dd, yyyy";
|
||||||
|
case "DD MMM, YYYY":
|
||||||
|
return "dd MMM, yyyy";
|
||||||
|
case "YYYY-MM-DD":
|
||||||
|
return "yyyy-MM-dd";
|
||||||
|
case "MM-DD-YYYY":
|
||||||
|
return "MM-dd-yyyy";
|
||||||
|
case "MM.DD.YYYY":
|
||||||
|
return "MM.dd.yyyy";
|
||||||
|
case "MMM DD, YYYY":
|
||||||
|
return "MMM dd, yyyy";
|
||||||
|
case "DD MMMM, YYYY":
|
||||||
|
return "dd MMMM, yyyy";
|
||||||
|
default:
|
||||||
|
return "MM/dd/yyyy";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeDateToMomentFormat = (format) => {
|
||||||
|
switch (format) {
|
||||||
|
case "MM/dd/yyyy":
|
||||||
|
return "L";
|
||||||
|
case "dd-MM-yyyy":
|
||||||
|
return "DD-MM-YYYY";
|
||||||
|
case "dd/MM/yyyy":
|
||||||
|
return "DD/MM/YYYY";
|
||||||
|
case "MMMM dd, yyyy":
|
||||||
|
return "LL";
|
||||||
|
case "dd MMM, yyyy":
|
||||||
|
return "DD MMM, YYYY";
|
||||||
|
case "yyyy-MM-dd":
|
||||||
|
return "YYYY-MM-DD";
|
||||||
|
case "MM-dd-yyyy":
|
||||||
|
return "MM-DD-YYYY";
|
||||||
|
case "MM.dd.yyyy":
|
||||||
|
return "MM.DD.YYYY";
|
||||||
|
case "MMM dd, yyyy":
|
||||||
|
return "MMM DD, YYYY";
|
||||||
|
case "dd MMMM, yyyy":
|
||||||
|
return "DD MMMM, YYYY";
|
||||||
|
default:
|
||||||
|
return "L";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function to get default date
|
||||||
|
const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
|
||||||
|
let date;
|
||||||
|
if (format && format === "dd-MM-yyyy") {
|
||||||
|
const newdate = selectedDate
|
||||||
|
? selectedDate
|
||||||
|
: moment(new Date()).format(changeDateToMomentFormat(format));
|
||||||
|
const [day, month, year] = newdate.split("-");
|
||||||
|
date = new Date(`${year}-${month}-${day}`);
|
||||||
|
} else {
|
||||||
|
date = new Date(selectedDate);
|
||||||
|
}
|
||||||
|
const value = date;
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
//function to get default format
|
||||||
|
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
|
||||||
|
|
||||||
|
function Placeholder(props) {
|
||||||
|
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
|
||||||
|
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
|
||||||
|
const [selectDate, setSelectDate] = useState({
|
||||||
|
date:
|
||||||
|
props.pos.type === "date"
|
||||||
|
? moment(
|
||||||
|
getDefaultdate(
|
||||||
|
props?.pos?.options?.response,
|
||||||
|
props.pos?.options?.validation?.format
|
||||||
|
).getTime()
|
||||||
|
).format(
|
||||||
|
changeDateToMomentFormat(props.pos?.options?.validation?.format)
|
||||||
|
)
|
||||||
|
: "",
|
||||||
|
format:
|
||||||
|
props.pos.type === "date"
|
||||||
|
? getDefaultFormat(props.pos?.options?.validation?.format)
|
||||||
|
: ""
|
||||||
|
});
|
||||||
|
const [dateFormat, setDateFormat] = useState([]);
|
||||||
|
const [startDate, setStartDate] = useState(
|
||||||
|
props.pos.type === "date" &&
|
||||||
|
getDefaultdate(
|
||||||
|
props?.pos?.options?.response,
|
||||||
|
props.pos?.options?.validation?.format
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const [getCheckboxRenderWidth, setGetCheckboxRenderWidth] = useState({
|
||||||
|
width: null,
|
||||||
|
height: null
|
||||||
|
});
|
||||||
|
const dateFormatArr = [
|
||||||
|
"L",
|
||||||
|
"DD-MM-YYYY",
|
||||||
|
"YYYY-MM-DD",
|
||||||
|
"MM.DD.YYYY",
|
||||||
|
"MM-DD-YYYY",
|
||||||
|
"MMM DD, YYYY",
|
||||||
|
"LL",
|
||||||
|
"DD MMM, YYYY",
|
||||||
|
"DD MMMM, YYYY"
|
||||||
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateWidth = () => {
|
||||||
|
const rndElement = document.getElementById(props.pos.key);
|
||||||
|
if (rndElement) {
|
||||||
|
const { width, height } = rndElement.getBoundingClientRect();
|
||||||
|
setGetCheckboxRenderWidth({ width: width, height: height });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delay to ensure rendering is complete
|
||||||
|
const timer = setTimeout(updateWidth, 0);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [props.pos]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const closeMenuOnOutsideClick = (e) => {
|
||||||
|
if (!isDraggingEnabled && !e.target.closest("#changeIsDragging")) {
|
||||||
|
setDraggingEnabled(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("click", closeMenuOnOutsideClick);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// Cleanup the event listener when the component unmounts
|
||||||
|
document.removeEventListener("click", closeMenuOnOutsideClick);
|
||||||
|
};
|
||||||
|
}, [isDraggingEnabled]);
|
||||||
|
//function change format array list with selected date and format
|
||||||
|
const changeDateFormat = () => {
|
||||||
|
const updateDate = [];
|
||||||
|
dateFormatArr.map((data) => {
|
||||||
|
let date;
|
||||||
|
if (selectDate && selectDate.format === "dd-MM-yyyy") {
|
||||||
|
const [day, month, year] = selectDate.date.split("-");
|
||||||
|
date = new Date(`${year}-${month}-${day}`);
|
||||||
|
} else {
|
||||||
|
date = new Date(selectDate?.date);
|
||||||
|
}
|
||||||
|
const milliseconds = date.getTime();
|
||||||
|
const newDate = moment(milliseconds).format(data);
|
||||||
|
const dateObj = {
|
||||||
|
date: newDate,
|
||||||
|
format: selectFormat(data)
|
||||||
|
};
|
||||||
|
updateDate.push(dateObj);
|
||||||
|
});
|
||||||
|
setDateFormat(updateDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isPlaceholder || props.isSignYourself) {
|
||||||
|
selectDate && changeDateFormat();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [selectDate]);
|
||||||
|
|
||||||
|
//it detect outside click of date dropdown menu
|
||||||
|
useEffect(() => {
|
||||||
|
const closeMenuOnOutsideClick = (e) => {
|
||||||
|
if (isShowDateFormat && !e.target.closest("#menu-container")) {
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("click", closeMenuOnOutsideClick);
|
||||||
|
return () => {
|
||||||
|
// Cleanup the event listener when the component unmounts
|
||||||
|
document.removeEventListener("click", closeMenuOnOutsideClick);
|
||||||
|
};
|
||||||
|
}, [isShowDateFormat]);
|
||||||
|
|
||||||
|
//`handleWidgetIdandPopup` is used to set current widget id and open relative popup
|
||||||
|
const handleWidgetIdandPopup = () => {
|
||||||
|
if (props.setSelectWidgetId) {
|
||||||
|
props.setSelectWidgetId(props.pos.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const widgetTypeExist = [
|
||||||
|
textInputWidget,
|
||||||
|
"checkbox",
|
||||||
|
"name",
|
||||||
|
"company",
|
||||||
|
"job title",
|
||||||
|
"date",
|
||||||
|
"email",
|
||||||
|
textWidget
|
||||||
|
].includes(props.pos.type);
|
||||||
|
|
||||||
|
if (widgetTypeExist) {
|
||||||
|
setDraggingEnabled(false);
|
||||||
|
}
|
||||||
|
if ((props.isNeedSign || props.isSignYourself) && !props.isDragging) {
|
||||||
|
if (props.pos.type) {
|
||||||
|
if (
|
||||||
|
props.pos.type === "signature" ||
|
||||||
|
props.pos.type === "stamp" ||
|
||||||
|
props.pos.type === "image"
|
||||||
|
) {
|
||||||
|
props.setIsSignPad(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setIsStamp(props.pos.isStamp);
|
||||||
|
} else if (props.pos.type === "initials") {
|
||||||
|
props.setIsSignPad(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setIsStamp(props.pos.isStamp);
|
||||||
|
props.setIsInitial(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
props.setIsSignPad(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setIsStamp(props.pos?.isStamp ? props.pos.isStamp : false);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
props.isPlaceholder &&
|
||||||
|
!props.isDragging &&
|
||||||
|
props.pos.type !== textWidget
|
||||||
|
) {
|
||||||
|
if (props.pos.key === props.selectWidgetId) {
|
||||||
|
props.handleLinkUser(props.data.Id);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
} else if (!props.pos.type) {
|
||||||
|
if (
|
||||||
|
!props.pos.type &&
|
||||||
|
props.isNeedSign &&
|
||||||
|
props.data.signerObjId === props.signerObjId
|
||||||
|
) {
|
||||||
|
props.setIsSignPad(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setIsStamp(props.pos.isStamp);
|
||||||
|
} else if (
|
||||||
|
(props.isNeedSign && props.pos.type === "signature") ||
|
||||||
|
props.pos.type === "stamp"
|
||||||
|
) {
|
||||||
|
props.setIsSignPad(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setIsStamp(props.pos.isStamp);
|
||||||
|
} else if (props.isNeedSign && props.pos.type === "dropdown") {
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleOnClickPlaceholder = () => {
|
||||||
|
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails(props.pos);
|
||||||
|
if (!props.isNeedSign) {
|
||||||
|
props.setWidgetType(props.pos.type);
|
||||||
|
}
|
||||||
|
if (props.isNeedSign && props.data?.signerObjId === props.signerObjId) {
|
||||||
|
handleWidgetIdandPopup();
|
||||||
|
} else if (props.isPlaceholder || props.isSignYourself) {
|
||||||
|
handleWidgetIdandPopup();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//`handleOnClickSettingIcon` is used set current widget details and open setting of it
|
||||||
|
const handleOnClickSettingIcon = () => {
|
||||||
|
if (props.pos.type === radioButtonWidget) {
|
||||||
|
props.setIsRadio(true);
|
||||||
|
} else if (props.pos.type === "dropdown") {
|
||||||
|
props?.setShowDropdown(true);
|
||||||
|
} else if (props.pos.type === "checkbox") {
|
||||||
|
props?.setIsCheckbox(true);
|
||||||
|
} else {
|
||||||
|
props?.handleNameModal(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isPlaceholder && props.type !== textWidget) {
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setWidgetType(props.pos.type);
|
||||||
|
props.setCurrWidgetsDetails(props.pos);
|
||||||
|
};
|
||||||
|
//function to set required state value onclick on widget's copy icon
|
||||||
|
const handleCopyPlaceholder = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
//condition to handle text widget signer obj id and unique id
|
||||||
|
//when user click on copy icon of text widget in that condition text widget does not have any signerObjId
|
||||||
|
//in that case i have to save in tempSignerId as a unique id of previous select signer's unique id
|
||||||
|
//and on save or cancel button of copy all page popup i have set this temp signer Id in unique id
|
||||||
|
|
||||||
|
if (props.data && props?.pos?.type !== textWidget) {
|
||||||
|
props.setSignerObjId(props?.data?.signerObjId);
|
||||||
|
props.setUniqueId(props?.data?.Id);
|
||||||
|
} else if (props.data && props.pos.type === textWidget) {
|
||||||
|
props.setTempSignerId(props.uniqueId);
|
||||||
|
props.setSignerObjId(props?.data?.signerObjId);
|
||||||
|
props.setUniqueId(props?.data?.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//checking widget's type and open widget copy modal for required widgets
|
||||||
|
if (
|
||||||
|
["signature", textWidget, "stamp", "initial"].includes(props.pos.type)
|
||||||
|
) {
|
||||||
|
props.setIsPageCopy(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
} else {
|
||||||
|
//function to create new widget next to just widget
|
||||||
|
handleCopyNextToWidget(
|
||||||
|
props.pos,
|
||||||
|
props.pos.type,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function to save date and format on local array onchange date and onclick format
|
||||||
|
const handleSaveDate = (data, isDateChange) => {
|
||||||
|
let updateDate = data.date;
|
||||||
|
//check if date change by user
|
||||||
|
if (isDateChange) {
|
||||||
|
//`changeDateToMomentFormat` is used to convert date as per required to moment package
|
||||||
|
updateDate = moment(data.date).format(
|
||||||
|
changeDateToMomentFormat(data.format)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//using moment package is used to change date as per the format provided in selectDate obj e.g. - MM/dd/yyyy -> 03/12/2024
|
||||||
|
//`getDefaultdate` is used to convert update date in new Date() format
|
||||||
|
const date = moment(
|
||||||
|
getDefaultdate(updateDate, data?.format).getTime()
|
||||||
|
).format(changeDateToMomentFormat(data?.format));
|
||||||
|
|
||||||
|
//`onChangeInput` is used to save data related to date in a placeholder field
|
||||||
|
onChangeInput(
|
||||||
|
date,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data.Id,
|
||||||
|
false,
|
||||||
|
data?.format
|
||||||
|
);
|
||||||
|
setSelectDate({ date: date, format: data?.format });
|
||||||
|
};
|
||||||
|
const PlaceholderIcon = () => {
|
||||||
|
return (
|
||||||
|
props.isShowBorder && (
|
||||||
|
<>
|
||||||
|
{(props.isPlaceholder || props.isSignYourself) && (
|
||||||
|
<>
|
||||||
|
{props.pos.type === "checkbox" && props.isSignYourself ? (
|
||||||
|
<i
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleOnClickSettingIcon();
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleOnClickSettingIcon();
|
||||||
|
}}
|
||||||
|
className="fa-solid fa-gear settingIcon"
|
||||||
|
style={{
|
||||||
|
color: "#188ae2",
|
||||||
|
right: "29px",
|
||||||
|
top: "-19px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
) : (
|
||||||
|
((!props?.pos?.type && props.pos.isStamp) ||
|
||||||
|
(props?.pos?.type &&
|
||||||
|
!["date", textWidget, "signature"].includes(
|
||||||
|
props.pos.type
|
||||||
|
) &&
|
||||||
|
!props.isSignYourself)) && (
|
||||||
|
<i
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleOnClickSettingIcon();
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleOnClickSettingIcon();
|
||||||
|
}}
|
||||||
|
className="fa-solid fa-gear settingIcon"
|
||||||
|
style={{ color: "#188ae2", right: "47px", top: "-19px" }}
|
||||||
|
></i>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
|
||||||
|
{props.pos.type !== textWidget && !props.isSignYourself && (
|
||||||
|
<i
|
||||||
|
data-tut="reactourLinkUser"
|
||||||
|
className="fa-regular fa-user signUserIcon"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.handleLinkUser(props.data.Id);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.handleLinkUser(props.data.Id);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}}
|
||||||
|
style={{ color: "#188ae2", right: "32px", top: "-18px" }}
|
||||||
|
></i>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{props.pos.type === "date" && selectDate && (
|
||||||
|
<div
|
||||||
|
id="menu-container"
|
||||||
|
style={{
|
||||||
|
zIndex: "99",
|
||||||
|
top: "-19px",
|
||||||
|
right: props.isPlaceholder ? "60px" : "44px"
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
isShowDateFormat
|
||||||
|
? "dropdown signUserIcon show"
|
||||||
|
: "dropdown signUserIcon"
|
||||||
|
}
|
||||||
|
onClick={(e) => {
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
e.stopPropagation();
|
||||||
|
if (props.data) {
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
if (props.data) {
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-gear settingIcon"
|
||||||
|
style={{
|
||||||
|
color: "#188ae2",
|
||||||
|
fontSize: "14px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
isShowDateFormat ? "dropdown-menu show" : "dropdown-menu"
|
||||||
|
}
|
||||||
|
aria-labelledby="dropdownMenuButton"
|
||||||
|
aria-expanded={isShowDateFormat ? "true" : "false"}
|
||||||
|
>
|
||||||
|
{dateFormat.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={ind}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
setSelectDate(data);
|
||||||
|
handleSaveDate(data);
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
setSelectDate(data);
|
||||||
|
handleSaveDate(data);
|
||||||
|
}}
|
||||||
|
className="dropdown-item itemColor"
|
||||||
|
style={{ fontSize: "12px" }}
|
||||||
|
>
|
||||||
|
{data?.date ? data?.date : "nodata"}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<i
|
||||||
|
className="fa-regular fa-copy signCopy"
|
||||||
|
onClick={(e) => handleCopyPlaceholder(e)}
|
||||||
|
onTouchEnd={(e) => handleCopyPlaceholder(e)}
|
||||||
|
style={{ color: "#188ae2", right: "12px", top: "-18px" }}
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
className="fa-regular fa-circle-xmark signCloseBtn"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (props.data) {
|
||||||
|
props.handleDeleteSign(props.pos.key, props.data.Id);
|
||||||
|
} else {
|
||||||
|
props.handleDeleteSign(props.pos.key);
|
||||||
|
props.setIsStamp(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (props.data) {
|
||||||
|
props.handleDeleteSign(props.pos.key, props.data?.Id);
|
||||||
|
} else {
|
||||||
|
props.handleDeleteSign(props.pos.key);
|
||||||
|
props.setIsStamp(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ color: "#188ae2", right: "-8px", top: "-18px" }}
|
||||||
|
></i>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Rnd
|
||||||
|
id={props.pos.key}
|
||||||
|
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
||||||
|
key={props.pos.key}
|
||||||
|
lockAspectRatio={
|
||||||
|
props.pos.type !== textWidget &&
|
||||||
|
(props.pos.Width
|
||||||
|
? props.pos.Width / props.pos.Height
|
||||||
|
: defaultWidthHeight(props.pos.type).width /
|
||||||
|
defaultWidthHeight(props.pos.type).height)
|
||||||
|
}
|
||||||
|
enableResizing={{
|
||||||
|
top: false,
|
||||||
|
right: false,
|
||||||
|
bottom: false,
|
||||||
|
left: false,
|
||||||
|
topRight: false,
|
||||||
|
bottomRight:
|
||||||
|
props.data && props.isNeedSign
|
||||||
|
? props.data?.signerObjId === props.signerObjId &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.type !== radioButtonWidget
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
: props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId &&
|
||||||
|
true,
|
||||||
|
bottomLeft: false,
|
||||||
|
topLeft: false
|
||||||
|
}}
|
||||||
|
bounds="parent"
|
||||||
|
className="signYourselfBlock"
|
||||||
|
style={{
|
||||||
|
border: "1px solid #007bff",
|
||||||
|
borderRadius: "2px",
|
||||||
|
textAlign:
|
||||||
|
props.pos.type !== "name" &&
|
||||||
|
props.pos.type !== "company" &&
|
||||||
|
props.pos.type !== "job title" &&
|
||||||
|
"center",
|
||||||
|
cursor:
|
||||||
|
props.data && props.isNeedSign
|
||||||
|
? props.data?.signerObjId === props.signerObjId
|
||||||
|
? "pointer"
|
||||||
|
: "not-allowed"
|
||||||
|
: "all-scroll",
|
||||||
|
zIndex:
|
||||||
|
props.pos.type === "date"
|
||||||
|
? props.pos.key === props.selectWidgetId
|
||||||
|
? 99 + 1
|
||||||
|
: 99
|
||||||
|
: props?.pos?.zIndex
|
||||||
|
? props.pos.zIndex
|
||||||
|
: "5",
|
||||||
|
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
|
||||||
|
}}
|
||||||
|
onDrag={() => {
|
||||||
|
setDraggingEnabled(true);
|
||||||
|
props.handleTabDrag && props.handleTabDrag(props.pos.key);
|
||||||
|
}}
|
||||||
|
size={{
|
||||||
|
width:
|
||||||
|
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
height:
|
||||||
|
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posHeight(props.pos, props.isSignYourself)
|
||||||
|
}}
|
||||||
|
onResizeStart={() => {
|
||||||
|
setDraggingEnabled(true);
|
||||||
|
props.setIsResize && props.setIsResize(true);
|
||||||
|
}}
|
||||||
|
onResizeStop={() => {
|
||||||
|
props.setIsResize && props.setIsResize(false);
|
||||||
|
}}
|
||||||
|
disableDragging={
|
||||||
|
props.isNeedSign
|
||||||
|
? true
|
||||||
|
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
|
||||||
|
? false
|
||||||
|
: !isDraggingEnabled
|
||||||
|
}
|
||||||
|
onDragStop={(event, dragElement) =>
|
||||||
|
props.handleStop &&
|
||||||
|
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
|
||||||
|
}
|
||||||
|
default={{
|
||||||
|
x: props.xPos(props.pos, props.isSignYourself),
|
||||||
|
y: props.yPos(props.pos, props.isSignYourself)
|
||||||
|
}}
|
||||||
|
onResize={(e, direction, ref) => {
|
||||||
|
props.handleSignYourselfImageResize &&
|
||||||
|
props.handleSignYourselfImageResize(
|
||||||
|
ref,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.index,
|
||||||
|
props.data && props.data.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onClick={() => handleOnClickPlaceholder()}
|
||||||
|
>
|
||||||
|
{props.isShowBorder &&
|
||||||
|
props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId ? (
|
||||||
|
<BorderResize right={-12} top={-11} />
|
||||||
|
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
||||||
|
props.data?.signerObjId === props.signerObjId &&
|
||||||
|
props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" ? (
|
||||||
|
<BorderResize />
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId && <BorderResize />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
|
||||||
|
<PlaceholderBorder
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pos={props.pos}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
getCheckboxRenderWidth={getCheckboxRenderWidth}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isMobile ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
left: props.xPos(props.pos, props.isSignYourself),
|
||||||
|
top: props.yPos(props.pos, props.isSignYourself),
|
||||||
|
width:
|
||||||
|
props.pos.type === radioButtonWidget ||
|
||||||
|
props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
// "auto", //props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
// height: props.posHeight(props.pos, props.isSignYourself),
|
||||||
|
height:
|
||||||
|
props.pos.type === radioButtonWidget ||
|
||||||
|
props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posHeight(props.pos, props.isSignYourself),
|
||||||
|
zIndex: "10"
|
||||||
|
}}
|
||||||
|
onTouchEnd={() => handleOnClickPlaceholder()}
|
||||||
|
>
|
||||||
|
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
||||||
|
|
||||||
|
<PlaceholderType
|
||||||
|
pos={props.pos}
|
||||||
|
xyPostion={props.xyPostion}
|
||||||
|
index={props.index}
|
||||||
|
setXyPostion={props.setXyPostion}
|
||||||
|
data={props.data}
|
||||||
|
setSignKey={props.setSignKey}
|
||||||
|
isShowDropdown={props?.isShowDropdown}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
signerObjId={props.signerObjId}
|
||||||
|
handleUserName={props.handleUserName}
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
||||||
|
isNeedSign={props.isNeedSign}
|
||||||
|
setSelectDate={setSelectDate}
|
||||||
|
selectDate={selectDate}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
setStartDate={setStartDate}
|
||||||
|
startDate={startDate}
|
||||||
|
handleSaveDate={handleSaveDate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
||||||
|
<PlaceholderType
|
||||||
|
pos={props.pos}
|
||||||
|
xyPostion={props.xyPostion}
|
||||||
|
index={props.index}
|
||||||
|
setXyPostion={props.setXyPostion}
|
||||||
|
data={props.data}
|
||||||
|
setSignKey={props.setSignKey}
|
||||||
|
isShowDropdown={props?.isShowDropdown}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
signerObjId={props.signerObjId}
|
||||||
|
handleUserName={props.handleUserName}
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
||||||
|
isNeedSign={props.isNeedSign}
|
||||||
|
setSelectDate={setSelectDate}
|
||||||
|
selectDate={selectDate}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
setStartDate={setStartDate}
|
||||||
|
startDate={startDate}
|
||||||
|
handleSaveDate={handleSaveDate}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Rnd>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Placeholder;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import {
|
||||||
|
defaultWidthHeight,
|
||||||
|
isMobile,
|
||||||
|
radioButtonWidget,
|
||||||
|
resizeBorderExtraWidth,
|
||||||
|
textWidget
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
function PlaceholderBorder(props) {
|
||||||
|
const getResizeBorderExtraWidth = resizeBorderExtraWidth();
|
||||||
|
const defaultWidth = defaultWidthHeight(props.pos.type).width;
|
||||||
|
const defaultHeight = defaultWidthHeight(props.pos.type).height;
|
||||||
|
|
||||||
|
const handleMinWidth = () => {
|
||||||
|
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
|
||||||
|
return props.getCheckboxRenderWidth.width + getResizeBorderExtraWidth;
|
||||||
|
} else {
|
||||||
|
return props.pos.Width
|
||||||
|
? props.pos.Width + getResizeBorderExtraWidth
|
||||||
|
: defaultWidth + getResizeBorderExtraWidth;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleMinHeight = () => {
|
||||||
|
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
|
||||||
|
return props.getCheckboxRenderWidth.height + getResizeBorderExtraWidth;
|
||||||
|
} else {
|
||||||
|
return props.pos.Height
|
||||||
|
? props.pos.Height + getResizeBorderExtraWidth
|
||||||
|
: defaultHeight + getResizeBorderExtraWidth;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onMouseEnter={() => !isMobile && props?.setDraggingEnabled(true)}
|
||||||
|
onTouchEnd={() =>
|
||||||
|
props.pos.type === textWidget && props?.setDraggingEnabled(true)
|
||||||
|
}
|
||||||
|
className="borderResize"
|
||||||
|
style={{
|
||||||
|
borderColor: themeColor,
|
||||||
|
borderStyle: "dashed",
|
||||||
|
minWidth: handleMinWidth(),
|
||||||
|
minHeight: handleMinHeight(),
|
||||||
|
borderWidth: "0.2px",
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaceholderBorder;
|
||||||
@@ -1,62 +1,55 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { themeColor } from "../../utils/ThemeColor/backColor";
|
import { themeColor } from "../../constant/const";
|
||||||
import ModalUi from "../../premitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { randomId, textWidget } from "../../constant/Utils";
|
||||||
|
|
||||||
function PlaceholderCopy(props) {
|
function PlaceholderCopy(props) {
|
||||||
const copyType = ["All pages", "All pages but last", "All pages but first"];
|
const copyType = ["All pages", "All pages but last", "All pages but first"];
|
||||||
const [selectCopyType, setSelectCopyType] = useState("");
|
const [selectCopyType, setSelectCopyType] = useState("");
|
||||||
|
|
||||||
//get RandomKey Id
|
|
||||||
const randomKey = () => {
|
|
||||||
const randomId = Math.floor(1000 + Math.random() * 9000);
|
|
||||||
return randomId;
|
|
||||||
};
|
|
||||||
|
|
||||||
//function for get copy placeholder position
|
//function for get copy placeholder position
|
||||||
const getCopyPlaceholderPosition = (
|
const getCopyPlaceholderPosition = (
|
||||||
type,
|
type,
|
||||||
rest,
|
currentPlaceholder,
|
||||||
newPageNumber,
|
newPageNumber,
|
||||||
existPlaceholderPosition
|
existPlaceholderPosition
|
||||||
) => {
|
) => {
|
||||||
let obj;
|
|
||||||
|
|
||||||
const filterPosition =
|
const filterPosition =
|
||||||
existPlaceholderPosition &&
|
existPlaceholderPosition &&
|
||||||
existPlaceholderPosition.filter(
|
existPlaceholderPosition.filter(
|
||||||
(data) => data.xPosition !== rest.xPosition
|
(data) => data.xPosition !== currentPlaceholder.xPosition
|
||||||
);
|
);
|
||||||
//copy all page placeholder at requested position except first page
|
//copy all page placeholder at requested position except first page
|
||||||
if (newPageNumber === 1 && type === "first") {
|
if (newPageNumber === 1 && type === "first") {
|
||||||
if (filterPosition && filterPosition.length > 0) {
|
if (filterPosition && filterPosition.length > 0) {
|
||||||
return (obj = {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
pos: [...filterPosition]
|
pos: [...filterPosition]
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//copy all page placeholder at requested position except last page
|
//copy all page placeholder at requested position except last page
|
||||||
else if (newPageNumber === props.allPages && type === "last") {
|
else if (newPageNumber === props.allPages && type === "last") {
|
||||||
if (existPlaceholderPosition) {
|
if (existPlaceholderPosition) {
|
||||||
return (obj = {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
pos: [...filterPosition]
|
pos: [...filterPosition]
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//copy all page placeholder at requested position with existing placeholder position
|
//copy all page placeholder at requested position with existing placeholder position
|
||||||
else if (existPlaceholderPosition) {
|
else if (existPlaceholderPosition) {
|
||||||
return (obj = {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
pos: [...filterPosition, rest]
|
pos: [...filterPosition, currentPlaceholder]
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
//copy all page placeholder at requested position
|
//copy all page placeholder at requested position
|
||||||
else {
|
else {
|
||||||
return (obj = {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
pos: [rest]
|
pos: [currentPlaceholder]
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +59,7 @@ function PlaceholderCopy(props) {
|
|||||||
let newPageNumber = 1;
|
let newPageNumber = 1;
|
||||||
const signerPosition = props.xyPostion;
|
const signerPosition = props.xyPostion;
|
||||||
const signerId = props.signerObjId ? props.signerObjId : props.Id;
|
const signerId = props.signerObjId ? props.signerObjId : props.Id;
|
||||||
|
|
||||||
//handle placeholder array and copy for multiple signers placeholder at requested location
|
//handle placeholder array and copy for multiple signers placeholder at requested location
|
||||||
if (signerId) {
|
if (signerId) {
|
||||||
//get current signers data
|
//get current signers data
|
||||||
@@ -84,13 +78,13 @@ function PlaceholderCopy(props) {
|
|||||||
(data) => data.pageNumber === props.pageNumber
|
(data) => data.pageNumber === props.pageNumber
|
||||||
);
|
);
|
||||||
//get current placeholder position data which user want to copy
|
//get current placeholder position data which user want to copy
|
||||||
const currentPlaceholder = placeholderPosition[0].pos.filter(
|
const currentPlaceholder = placeholderPosition[0].pos.find(
|
||||||
(position) => position.key === props.signKey
|
(position) => position.key === props.signKey
|
||||||
);
|
);
|
||||||
const { key, ...rest } = currentPlaceholder[0];
|
|
||||||
for (let i = 0; i < props.allPages; i++) {
|
for (let i = 0; i < props.allPages; i++) {
|
||||||
const newId = randomKey();
|
const newId = randomId();
|
||||||
rest.key = newId;
|
currentPlaceholder.key = newId;
|
||||||
//get exist placeholder position for particular page
|
//get exist placeholder position for particular page
|
||||||
const existPlaceholder = filterSignerPosition[0].placeHolder.filter(
|
const existPlaceholder = filterSignerPosition[0].placeHolder.filter(
|
||||||
(data) => data.pageNumber === newPageNumber
|
(data) => data.pageNumber === newPageNumber
|
||||||
@@ -101,7 +95,7 @@ function PlaceholderCopy(props) {
|
|||||||
//function for get copy to requested location of placeholder position
|
//function for get copy to requested location of placeholder position
|
||||||
const getPlaceholderObj = getCopyPlaceholderPosition(
|
const getPlaceholderObj = getCopyPlaceholderPosition(
|
||||||
type,
|
type,
|
||||||
rest,
|
currentPlaceholder,
|
||||||
newPageNumber,
|
newPageNumber,
|
||||||
existPlaceholderPosition
|
existPlaceholderPosition
|
||||||
);
|
);
|
||||||
@@ -112,7 +106,7 @@ function PlaceholderCopy(props) {
|
|||||||
}
|
}
|
||||||
let updatedSignerPlaceholder;
|
let updatedSignerPlaceholder;
|
||||||
if (props?.signerObjId) {
|
if (props?.signerObjId) {
|
||||||
updatedSignerPlaceholder = signerPosition.map((signersData, ind) => {
|
updatedSignerPlaceholder = signerPosition.map((signersData) => {
|
||||||
if (signersData.signerObjId === props.signerObjId) {
|
if (signersData.signerObjId === props.signerObjId) {
|
||||||
return {
|
return {
|
||||||
...signersData,
|
...signersData,
|
||||||
@@ -122,7 +116,7 @@ function PlaceholderCopy(props) {
|
|||||||
return signersData;
|
return signersData;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
updatedSignerPlaceholder = signerPosition.map((signersData, ind) => {
|
updatedSignerPlaceholder = signerPosition.map((signersData) => {
|
||||||
if (signersData.Id === props.Id) {
|
if (signersData.Id === props.Id) {
|
||||||
return {
|
return {
|
||||||
...signersData,
|
...signersData,
|
||||||
@@ -132,17 +126,6 @@ function PlaceholderCopy(props) {
|
|||||||
return signersData;
|
return signersData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// const updatedSignerPlaceholder = signerPosition.map(
|
|
||||||
// (signersData, ind) => {
|
|
||||||
// if (signersData.signerObjId === props.signerObjId) {
|
|
||||||
// return {
|
|
||||||
// ...signersData,
|
|
||||||
// placeHolder: newPlaceholderPosition
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// return signersData;
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
const signersData = signerPosition;
|
const signersData = signerPosition;
|
||||||
signersData.splice(0, signerPosition.length, ...updatedSignerPlaceholder);
|
signersData.splice(0, signerPosition.length, ...updatedSignerPlaceholder);
|
||||||
@@ -156,10 +139,10 @@ function PlaceholderCopy(props) {
|
|||||||
(data) => data.pageNumber === props.pageNumber
|
(data) => data.pageNumber === props.pageNumber
|
||||||
);
|
);
|
||||||
//get current placeholder position data which user want to copy
|
//get current placeholder position data which user want to copy
|
||||||
const currentPlaceholder = placeholderPosition[0].pos.filter(
|
const currentPlaceholder = placeholderPosition[0].pos.find(
|
||||||
(pos) => pos.key === props.signKey
|
(pos) => pos.key === props.signKey
|
||||||
);
|
);
|
||||||
const { key, ...rest } = currentPlaceholder[0];
|
|
||||||
for (let i = 0; i < props.allPages; i++) {
|
for (let i = 0; i < props.allPages; i++) {
|
||||||
//get exist placeholder position for particular page
|
//get exist placeholder position for particular page
|
||||||
const existPlaceholder = xyPostion.filter(
|
const existPlaceholder = xyPostion.filter(
|
||||||
@@ -168,12 +151,12 @@ function PlaceholderCopy(props) {
|
|||||||
const existPlaceholderPosition =
|
const existPlaceholderPosition =
|
||||||
existPlaceholder[0] && existPlaceholder[0].pos;
|
existPlaceholder[0] && existPlaceholder[0].pos;
|
||||||
|
|
||||||
const newId = randomKey();
|
const newId = randomId();
|
||||||
rest.key = newId;
|
currentPlaceholder.key = newId;
|
||||||
//function for get copy to requested location of placeholder position
|
//function for get copy to requested location of placeholder position
|
||||||
const getPlaceholderObj = getCopyPlaceholderPosition(
|
const getPlaceholderObj = getCopyPlaceholderPosition(
|
||||||
type,
|
type,
|
||||||
rest,
|
currentPlaceholder,
|
||||||
newPageNumber,
|
newPageNumber,
|
||||||
existPlaceholderPosition
|
existPlaceholderPosition
|
||||||
);
|
);
|
||||||
@@ -197,7 +180,13 @@ function PlaceholderCopy(props) {
|
|||||||
copyPlaceholder("first");
|
copyPlaceholder("first");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleUniqueId = () => {
|
||||||
|
if (props.widgetType === textWidget) {
|
||||||
|
props.setUniqueId(props?.tempSignerId);
|
||||||
|
props.setTempSignerId("");
|
||||||
|
}
|
||||||
|
props.setIsPageCopy(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={props.isPageCopy}
|
isOpen={props.isPageCopy}
|
||||||
@@ -237,11 +226,9 @@ function PlaceholderCopy(props) {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleApplyCopy();
|
handleApplyCopy();
|
||||||
props.setIsPageCopy(false);
|
handleUniqueId();
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
background: themeColor()
|
|
||||||
}}
|
}}
|
||||||
|
style={{ background: themeColor }}
|
||||||
type="button"
|
type="button"
|
||||||
disabled={!selectCopyType}
|
disabled={!selectCopyType}
|
||||||
className="finishBtn"
|
className="finishBtn"
|
||||||
@@ -251,7 +238,9 @@ function PlaceholderCopy(props) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="finishBtn cancelBtn"
|
className="finishBtn cancelBtn"
|
||||||
onClick={() => props.setIsPageCopy(false)}
|
onClick={() => {
|
||||||
|
handleUniqueId();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
@@ -0,0 +1,819 @@
|
|||||||
|
import React, { useEffect, useState, forwardRef, useRef } from "react";
|
||||||
|
import {
|
||||||
|
getMonth,
|
||||||
|
getYear,
|
||||||
|
isMobile,
|
||||||
|
onChangeHeightOfTextArea,
|
||||||
|
onChangeInput,
|
||||||
|
radioButtonWidget,
|
||||||
|
range,
|
||||||
|
textInputWidget,
|
||||||
|
textWidget
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
import DatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import "../../styles/signature.css";
|
||||||
|
import RegexParser from "regex-parser";
|
||||||
|
|
||||||
|
function PlaceholderType(props) {
|
||||||
|
const type = props?.pos?.type;
|
||||||
|
const [selectOption, setSelectOption] = useState("");
|
||||||
|
const [validatePlaceholder, setValidatePlaceholder] = useState("");
|
||||||
|
const inputRef = useRef(null);
|
||||||
|
const [textValue, setTextValue] = useState();
|
||||||
|
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
|
||||||
|
const years = range(1990, getYear(new Date()) + 16, 1);
|
||||||
|
const months = [
|
||||||
|
"January",
|
||||||
|
"February",
|
||||||
|
"March",
|
||||||
|
"April",
|
||||||
|
"May",
|
||||||
|
"June",
|
||||||
|
"July",
|
||||||
|
"August",
|
||||||
|
"September",
|
||||||
|
"October",
|
||||||
|
"November",
|
||||||
|
"December"
|
||||||
|
];
|
||||||
|
const validateExpression = (regexValidation) => {
|
||||||
|
let regexObject = regexValidation;
|
||||||
|
if (props.pos?.options.validation.type === "regex") {
|
||||||
|
regexObject = RegexParser(regexValidation);
|
||||||
|
}
|
||||||
|
// new RegExp(regexValidation);
|
||||||
|
let isValidate = regexObject.test(textValue);
|
||||||
|
if (!isValidate) {
|
||||||
|
props?.setValidateAlert(true);
|
||||||
|
inputRef.current.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputBlur = () => {
|
||||||
|
props.setDraggingEnabled(true);
|
||||||
|
const validateType = props.pos?.options?.validation?.type;
|
||||||
|
let regexValidation;
|
||||||
|
if (validateType) {
|
||||||
|
switch (validateType) {
|
||||||
|
case "email":
|
||||||
|
regexValidation = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||||
|
validateExpression(regexValidation);
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
regexValidation = /^\d+$/;
|
||||||
|
validateExpression(regexValidation);
|
||||||
|
break;
|
||||||
|
case "text":
|
||||||
|
regexValidation = /^[a-zA-Z\s]+$/;
|
||||||
|
validateExpression(regexValidation);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
regexValidation = props.pos?.options.validation.pattern;
|
||||||
|
validateExpression(regexValidation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTextValid = (e) => {
|
||||||
|
const textInput = e.target.value;
|
||||||
|
setTextValue(textInput);
|
||||||
|
};
|
||||||
|
function checkRegularExpress(validateType) {
|
||||||
|
switch (validateType) {
|
||||||
|
case "email":
|
||||||
|
setValidatePlaceholder("demo@gmail.com");
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
setValidatePlaceholder("12345");
|
||||||
|
break;
|
||||||
|
case textInputWidget:
|
||||||
|
setValidatePlaceholder("enter text");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setValidatePlaceholder("enter text");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type && type === "checkbox" && props.isNeedSign) {
|
||||||
|
const isDefaultValue = props.pos.options?.defaultValue;
|
||||||
|
if (isDefaultValue) {
|
||||||
|
setSelectedCheckbox(isDefaultValue);
|
||||||
|
}
|
||||||
|
} else if (props.pos?.options?.hint) {
|
||||||
|
setValidatePlaceholder(props.pos?.options.hint);
|
||||||
|
} else if (props.pos?.options?.validation?.type) {
|
||||||
|
checkRegularExpress(props.pos?.options?.validation?.type);
|
||||||
|
}
|
||||||
|
setTextValue(
|
||||||
|
props.pos?.options?.response
|
||||||
|
? props.pos?.options?.response
|
||||||
|
: props.pos?.options?.defaultValue
|
||||||
|
? props.pos?.options?.defaultValue
|
||||||
|
: ""
|
||||||
|
);
|
||||||
|
setSelectOption(
|
||||||
|
props.pos?.options?.response
|
||||||
|
? props.pos?.options?.response
|
||||||
|
: props.pos?.options?.defaultValue
|
||||||
|
? props.pos?.options?.defaultValue
|
||||||
|
: ""
|
||||||
|
);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
["name", "email", "job title", "company"].includes(props.pos?.type) &&
|
||||||
|
props.isNeedSign &&
|
||||||
|
props.data?.signerObjId === props?.signerObjId
|
||||||
|
) {
|
||||||
|
const defaultData = props.pos?.options?.defaultValue;
|
||||||
|
if (defaultData) {
|
||||||
|
setTextValue(defaultData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.pos]);
|
||||||
|
|
||||||
|
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
||||||
|
<div
|
||||||
|
className="inputPlaceholder"
|
||||||
|
style={{ overflow: "hidden", fontSize: calculateFontSize() }}
|
||||||
|
onClick={onClick}
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
<i className="fa-regular fa-calendar" style={{ marginLeft: "5px" }}></i>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
ExampleCustomInput.displayName = "ExampleCustomInput";
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
["name", "email", "job title", "company"].includes(type) &&
|
||||||
|
props.isNeedSign &&
|
||||||
|
props.data?.signerObjId === props.signerObjId
|
||||||
|
) {
|
||||||
|
const isDefault = true;
|
||||||
|
const senderUser = localStorage.getItem(`Extand_Class`);
|
||||||
|
const jsonSender = JSON.parse(senderUser);
|
||||||
|
onChangeInput(
|
||||||
|
jsonSender && jsonSender[0],
|
||||||
|
null,
|
||||||
|
props.xyPostion,
|
||||||
|
null,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data.Id,
|
||||||
|
isDefault
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
|
const calculateFontSize = () => {
|
||||||
|
const fontSize = 10 + Math.min(props.pos.Width, props.pos.Height) * 0.1;
|
||||||
|
const size = fontSize ? fontSize : 12;
|
||||||
|
return size + "px";
|
||||||
|
};
|
||||||
|
//function for show checked checkbox
|
||||||
|
const selectCheckbox = (ind) => {
|
||||||
|
const res = props.pos.options?.response;
|
||||||
|
const defaultCheck = props.pos.options?.defaultValue;
|
||||||
|
if (res && res?.length > 0) {
|
||||||
|
const isSelectIndex = res.indexOf(ind);
|
||||||
|
if (isSelectIndex > -1) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
} else if (defaultCheck) {
|
||||||
|
const isSelectIndex = defaultCheck.indexOf(ind);
|
||||||
|
if (isSelectIndex > -1) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRadioCheck = (data) => {
|
||||||
|
const defaultData = props.pos.options?.defaultValue;
|
||||||
|
if (textValue === data) {
|
||||||
|
return true;
|
||||||
|
} else if (defaultData === data) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for set checked and unchecked value of checkbox
|
||||||
|
const handleCheckboxValue = (isChecked, ind) => {
|
||||||
|
let updateSelectedCheckbox = [],
|
||||||
|
checkedList;
|
||||||
|
let isDefaultValue, isDefaultEmpty;
|
||||||
|
if (type === "checkbox") {
|
||||||
|
updateSelectedCheckbox = selectedCheckbox ? selectedCheckbox : [];
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
updateSelectedCheckbox.push(ind);
|
||||||
|
setSelectedCheckbox(updateSelectedCheckbox);
|
||||||
|
} else {
|
||||||
|
checkedList = selectedCheckbox.filter((data) => data !== ind);
|
||||||
|
setSelectedCheckbox(checkedList);
|
||||||
|
}
|
||||||
|
if (props.isNeedSign) {
|
||||||
|
isDefaultValue = props.pos.options?.defaultValue;
|
||||||
|
}
|
||||||
|
if (isDefaultValue && isDefaultValue.length > 0) {
|
||||||
|
isDefaultEmpty = true;
|
||||||
|
}
|
||||||
|
onChangeInput(
|
||||||
|
checkedList ? checkedList : updateSelectedCheckbox,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data.Id,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
isDefaultEmpty
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function to handle select radio widget and set value seletced by user
|
||||||
|
const handleCheckRadio = (isChecked, data) => {
|
||||||
|
let isDefaultValue,
|
||||||
|
isDefaultEmpty,
|
||||||
|
isRadio = true;
|
||||||
|
if (props.isNeedSign) {
|
||||||
|
isDefaultValue = props.pos.options?.defaultValue;
|
||||||
|
}
|
||||||
|
if (isDefaultValue) {
|
||||||
|
isDefaultEmpty = true;
|
||||||
|
}
|
||||||
|
if (isChecked) {
|
||||||
|
setTextValue(data);
|
||||||
|
} else {
|
||||||
|
setTextValue("");
|
||||||
|
}
|
||||||
|
onChangeInput(
|
||||||
|
data,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data.Id,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
isDefaultEmpty,
|
||||||
|
isRadio
|
||||||
|
);
|
||||||
|
};
|
||||||
|
//function to set onchange date
|
||||||
|
const handleOnDateChange = (date) => {
|
||||||
|
props.setStartDate(date);
|
||||||
|
const isDateChange = true;
|
||||||
|
const dateObj = {
|
||||||
|
date: date,
|
||||||
|
format: props.selectDate.format
|
||||||
|
};
|
||||||
|
props.handleSaveDate(dateObj, isDateChange);
|
||||||
|
};
|
||||||
|
//handle height on enter press in text area
|
||||||
|
const handleEnterPress = (e) => {
|
||||||
|
const height = 15;
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
//function to save height of text area
|
||||||
|
onChangeHeightOfTextArea(
|
||||||
|
height,
|
||||||
|
props.pos.type,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
switch (type) {
|
||||||
|
case "signature":
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
draggable="false"
|
||||||
|
src={props.pos.SignUrl}
|
||||||
|
style={{
|
||||||
|
width: "99%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
|
||||||
|
{props?.handleUserName &&
|
||||||
|
props?.handleUserName(
|
||||||
|
props?.data?.Id,
|
||||||
|
props?.data?.Role,
|
||||||
|
props?.pos?.type
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "stamp":
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
draggable="false"
|
||||||
|
src={props.pos.SignUrl}
|
||||||
|
style={{
|
||||||
|
width: "99%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
|
||||||
|
{props?.handleUserName &&
|
||||||
|
props?.handleUserName(
|
||||||
|
props?.data?.Id,
|
||||||
|
props?.data?.Role,
|
||||||
|
props?.pos?.type
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "checkbox":
|
||||||
|
return (
|
||||||
|
<div style={{ zIndex: props.isSignYourself && "99" }}>
|
||||||
|
{props.pos.options?.values?.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind} className="flex items-center text-center gap-0.5">
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
// width: props.pos.Width,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: ind === 0 ? 0 : "5px"
|
||||||
|
}}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
disabled={
|
||||||
|
props.isNeedSign &&
|
||||||
|
(props.pos.options?.isReadOnly ||
|
||||||
|
props.data?.signerObjId !== props.signerObjId)
|
||||||
|
}
|
||||||
|
type="checkbox"
|
||||||
|
checked={selectCheckbox(ind)}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
if (!props.isPlaceholder) {
|
||||||
|
const maxRequired =
|
||||||
|
props.pos.options?.validation?.maxRequiredCount;
|
||||||
|
const maxCountInt =
|
||||||
|
maxRequired && parseInt(maxRequired);
|
||||||
|
|
||||||
|
if (maxCountInt > 0) {
|
||||||
|
if (
|
||||||
|
selectedCheckbox &&
|
||||||
|
selectedCheckbox?.length <= maxCountInt - 1
|
||||||
|
) {
|
||||||
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!props.pos.options?.isHideLabel && (
|
||||||
|
<label className="text-xs mb-0 text-center">{data}</label>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case textInputWidget:
|
||||||
|
return props.isSignYourself ||
|
||||||
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
|
<input
|
||||||
|
className="inputPlaceholder"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={validatePlaceholder}
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
value={textValue}
|
||||||
|
type="text"
|
||||||
|
tabIndex="0"
|
||||||
|
disabled={
|
||||||
|
props.isNeedSign && props.data?.signerObjId !== props.signerObjId
|
||||||
|
? true
|
||||||
|
: props.isPlaceholder
|
||||||
|
}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
setTextValue(e.target.value);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontSize: calculateFontSize()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "dropdown":
|
||||||
|
return props.data?.signerObjId === props.signerObjId ? (
|
||||||
|
<select
|
||||||
|
className="inputPlaceholder"
|
||||||
|
id="myDropdown"
|
||||||
|
style={{ fontSize: "12px" }}
|
||||||
|
value={selectOption}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSelectOption(e.target.value);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Default/Title option */}
|
||||||
|
<option value="" disabled hidden>
|
||||||
|
{props?.pos?.options?.name}
|
||||||
|
</option>
|
||||||
|
|
||||||
|
{props.pos?.options?.values.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<option key={ind} value={data}>
|
||||||
|
{data}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="inputPlaceholder"
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
>
|
||||||
|
{props.pos?.options?.name ? props.pos.options.name : type}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "initials":
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
draggable="false"
|
||||||
|
src={props.pos.SignUrl}
|
||||||
|
style={{
|
||||||
|
width: "99%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
|
||||||
|
{props?.handleUserName &&
|
||||||
|
props?.handleUserName(
|
||||||
|
props?.data?.Id,
|
||||||
|
props?.data?.Role,
|
||||||
|
props?.pos?.type
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "name":
|
||||||
|
return props.isSignYourself ||
|
||||||
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
|
<input
|
||||||
|
tabIndex="0"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={"name"}
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
className="inputPlaceholder"
|
||||||
|
type="text"
|
||||||
|
value={textValue}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
const isDefault = false;
|
||||||
|
handleTextValid(e);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
isDefault
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontSize: calculateFontSize()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "company":
|
||||||
|
return props.isSignYourself ||
|
||||||
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
|
<input
|
||||||
|
className="inputPlaceholder"
|
||||||
|
type="text"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={"company"}
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
value={textValue}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
handleTextValid(e);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontSize: calculateFontSize()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "job title":
|
||||||
|
return props.isSignYourself ||
|
||||||
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
|
<input
|
||||||
|
className="inputPlaceholder"
|
||||||
|
type="text"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={"job title"}
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
value={textValue}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
handleTextValid(e);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontSize: calculateFontSize()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "date":
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<DatePicker
|
||||||
|
renderCustomHeader={({ date, changeYear, changeMonth }) => (
|
||||||
|
<div className="flex justify-start ml-2 ">
|
||||||
|
<select
|
||||||
|
className="bg-transparent outline-none"
|
||||||
|
value={months[getMonth(date)]}
|
||||||
|
onChange={({ target: { value } }) =>
|
||||||
|
changeMonth(months.indexOf(value))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{months.map((option) => (
|
||||||
|
<option key={option} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
className="bg-transparent outline-none"
|
||||||
|
value={getYear(date)}
|
||||||
|
onChange={({ target: { value } }) => changeYear(value)}
|
||||||
|
>
|
||||||
|
{years.map((option) => (
|
||||||
|
<option key={option} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
disabled={
|
||||||
|
props.isPlaceholder ||
|
||||||
|
(props.isNeedSign &&
|
||||||
|
props.data?.signerObjId !== props.signerObjId)
|
||||||
|
}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
closeOnScroll={true}
|
||||||
|
className="inputPlaceholder"
|
||||||
|
style={{ outlineColor: "#007bff" }}
|
||||||
|
selected={
|
||||||
|
props?.startDate
|
||||||
|
? props?.startDate
|
||||||
|
: props.pos.options?.response &&
|
||||||
|
new Date(props.pos.options.response)
|
||||||
|
}
|
||||||
|
onChange={(date) => handleOnDateChange(date)}
|
||||||
|
popperPlacement="top-end"
|
||||||
|
customInput={<ExampleCustomInput />}
|
||||||
|
dateFormat={
|
||||||
|
props.selectDate
|
||||||
|
? props.selectDate?.format
|
||||||
|
: props.pos?.options?.validation?.format
|
||||||
|
? props.pos?.options?.validation?.format
|
||||||
|
: "MM/dd/yyyy"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "image":
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
draggable="false"
|
||||||
|
src={props.pos.SignUrl}
|
||||||
|
style={{
|
||||||
|
width: "99%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
|
||||||
|
{props?.handleUserName &&
|
||||||
|
props?.handleUserName(
|
||||||
|
props?.data?.Id,
|
||||||
|
props?.data?.Role,
|
||||||
|
props?.pos?.type
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "email":
|
||||||
|
return props.isSignYourself ||
|
||||||
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
|
<input
|
||||||
|
className="inputPlaceholder"
|
||||||
|
type="text"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={"email"}
|
||||||
|
style={{ fontSize: calculateFontSize() }}
|
||||||
|
value={textValue}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
handleTextValid(e);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontSize: calculateFontSize()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case radioButtonWidget:
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{props.pos.options?.values.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind} className="flex items-center text-center gap-0.5">
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
width: props.pos.Width,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: ind === 0 ? 0 : "5px"
|
||||||
|
}}
|
||||||
|
type="radio"
|
||||||
|
disabled={
|
||||||
|
props.isNeedSign &&
|
||||||
|
(props.pos.options?.isReadOnly ||
|
||||||
|
props.data?.signerObjId !== props.signerObjId)
|
||||||
|
}
|
||||||
|
checked={handleRadioCheck(data)}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (!props.isPlaceholder) {
|
||||||
|
handleCheckRadio(e.target.checked, data);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!props.pos.options?.isHideLabel && (
|
||||||
|
<label className="text-xs mb-0">{data}</label>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case textWidget:
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
placeholder="Enter label"
|
||||||
|
rows={1}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
|
value={textValue}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
onChange={(e) => {
|
||||||
|
setTextValue(e.target.value);
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<div style={{ pointerEvents: "none" }}>
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
draggable="false"
|
||||||
|
src={props.pos.SignUrl}
|
||||||
|
style={{
|
||||||
|
width: "99%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "10px",
|
||||||
|
color: "black",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.pos.isStamp ? <div>stamp</div> : <div>signature</div>}
|
||||||
|
{props?.handleUserName &&
|
||||||
|
props?.handleUserName(props?.data?.Id, props?.data?.Role)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaceholderType;
|
||||||
@@ -21,7 +21,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
|
|||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
|
|
||||||
border: "0px",
|
border: "0px",
|
||||||
marginRight: "5px",
|
marginRight: "5px"
|
||||||
}}
|
}}
|
||||||
disabled={pageNumber <= 1}
|
disabled={pageNumber <= 1}
|
||||||
onClick={previousPage}
|
onClick={previousPage}
|
||||||
@@ -31,7 +31,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
|
|||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
fontSize: "13px",
|
fontSize: "13px",
|
||||||
fontWeight: "600",
|
fontWeight: "600"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
|
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
|
||||||
@@ -43,7 +43,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
|
|||||||
background: "#d3edeb",
|
background: "#d3edeb",
|
||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
marginLeft: "5px",
|
marginLeft: "5px",
|
||||||
border: "0px",
|
border: "0px"
|
||||||
}}
|
}}
|
||||||
disabled={pageNumber >= allPages}
|
disabled={pageNumber >= allPages}
|
||||||
onClick={nextPage}
|
onClick={nextPage}
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
import React, { useRef, useState } from "react";
|
||||||
|
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||||
|
import {
|
||||||
|
color,
|
||||||
|
darkenColor,
|
||||||
|
getFirstLetter,
|
||||||
|
isMobile,
|
||||||
|
nameColor
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
|
||||||
|
const RecipientList = (props) => {
|
||||||
|
const [animationParent] = useAutoAnimate();
|
||||||
|
const [isHover, setIsHover] = useState();
|
||||||
|
const [isEdit, setIsEdit] = useState(false);
|
||||||
|
//function for onhover signer name change background color
|
||||||
|
const inputRef = useRef(null);
|
||||||
|
const onHoverStyle = (ind, blockColor) => {
|
||||||
|
const style = {
|
||||||
|
background: blockColor ? blockColor : color[ind % color.length],
|
||||||
|
padding: "10px",
|
||||||
|
marginTop: "2px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottom: "1px solid #e3e1e1",
|
||||||
|
alignItems: "center"
|
||||||
|
};
|
||||||
|
return style;
|
||||||
|
};
|
||||||
|
//function for onhover signer name remove background color
|
||||||
|
const nonHoverStyle = () => {
|
||||||
|
const style = {
|
||||||
|
padding: "10px",
|
||||||
|
marginTop: "2px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottom: "1px solid #e3e1e1",
|
||||||
|
alignItems: "center"
|
||||||
|
};
|
||||||
|
return style;
|
||||||
|
};
|
||||||
|
const isWidgetExist = (Id) => {
|
||||||
|
return props.signerPos.some((x) => x.Id === Id);
|
||||||
|
};
|
||||||
|
|
||||||
|
//handle drag start
|
||||||
|
const handleDragStart = (e, id) => {
|
||||||
|
// `e.dataTransfer.setData('text/plain')`is used to set the data to be transferred during a drag operation.
|
||||||
|
// The first argument specifies the type of data being set, and the second argument is the actual data you want to transfer.
|
||||||
|
e.dataTransfer.setData("text/plain", id);
|
||||||
|
};
|
||||||
|
|
||||||
|
//handleDragOver prevents the default behavior of the dragover event, which is necessary for the drop event to be triggered.
|
||||||
|
const handleDragOver = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
//handle draggable element drop and also used in mobile view on up and down key to chnage sequence of recipient's list
|
||||||
|
const handleChangeSequence = (e, ind, isUp, isDown) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let draggedItemId;
|
||||||
|
let index = ind;
|
||||||
|
|
||||||
|
//if isUp true then set item's id and index in mobile view
|
||||||
|
if (isUp) {
|
||||||
|
draggedItemId = index;
|
||||||
|
index = index - 1;
|
||||||
|
}
|
||||||
|
//if isDown true then set item's id and index in mobile view
|
||||||
|
else if (isDown) {
|
||||||
|
draggedItemId = index;
|
||||||
|
index = index + 1;
|
||||||
|
} //else set id on drag element in desktop viiew
|
||||||
|
else {
|
||||||
|
//`e.dataTransfer.getData('text/plain')` is used to get data that you have saved.
|
||||||
|
draggedItemId = e.dataTransfer.getData("text/plain");
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert string to number
|
||||||
|
const intDragId = parseInt(draggedItemId);
|
||||||
|
//get that item to change position
|
||||||
|
const draggedItem = props.signersdata.filter((_, ind) => ind === intDragId);
|
||||||
|
const remainingItems = props.signersdata.filter(
|
||||||
|
(_, ind) => ind !== intDragId
|
||||||
|
);
|
||||||
|
//splice method is used to replace or add new value in array at specific index
|
||||||
|
remainingItems.splice(index, 0, ...draggedItem);
|
||||||
|
|
||||||
|
//set current draggable recipient details,objectId,index,contract_className ... after replace recipient list
|
||||||
|
props.setSignersData(remainingItems);
|
||||||
|
props.setSignerObjId(remainingItems[index]?.objectId || "");
|
||||||
|
props.setIsSelectId(index);
|
||||||
|
props.setContractName(remainingItems[index]?.className || "");
|
||||||
|
props.setUniqueId(remainingItems[index]?.Id);
|
||||||
|
props.setRoleName(remainingItems[index]?.Role);
|
||||||
|
props.setBlockColor(remainingItems[index]?.blockColor);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.signersdata.length > 0 &&
|
||||||
|
props.signersdata.map((obj, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={animationParent}
|
||||||
|
key={ind}
|
||||||
|
draggable={props.sendInOrder && !isMobile ? true : false}
|
||||||
|
onDragStart={(e) =>
|
||||||
|
props.sendInOrder && !isMobile && handleDragStart(e, ind)
|
||||||
|
}
|
||||||
|
onDragOver={(e) =>
|
||||||
|
props.sendInOrder && !isMobile && handleDragOver(e)
|
||||||
|
}
|
||||||
|
onDrop={(e) =>
|
||||||
|
props.sendInOrder && !isMobile && handleChangeSequence(e, ind)
|
||||||
|
}
|
||||||
|
data-tut="reactourFirst"
|
||||||
|
onMouseEnter={() => setIsHover(ind)}
|
||||||
|
onMouseLeave={() => setIsHover(null)}
|
||||||
|
className={
|
||||||
|
props.sendInOrder
|
||||||
|
? props.isMailSend
|
||||||
|
? "disabled"
|
||||||
|
: "dragCursor"
|
||||||
|
: props.isMailSend && "disabled"
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
(!isMobile && isHover === ind) || props.isSelectListId === ind
|
||||||
|
? onHoverStyle(ind, obj?.blockColor)
|
||||||
|
: nonHoverStyle(ind)
|
||||||
|
}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
props.setSignerObjId(obj?.objectId || "");
|
||||||
|
props.setIsSelectId(ind);
|
||||||
|
props.setContractName(obj?.className || "");
|
||||||
|
props.setUniqueId(obj.Id);
|
||||||
|
props.setRoleName(obj.Role);
|
||||||
|
props.setBlockColor(obj?.blockColor);
|
||||||
|
if (props.handleModal) {
|
||||||
|
props.handleModal();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: obj?.blockColor
|
||||||
|
? darkenColor(obj?.blockColor, 0.4)
|
||||||
|
: nameColor[ind % nameColor.length],
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
display: "flex",
|
||||||
|
borderRadius: 30 / 2,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginRight: "12px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={props.sendInOrder && "dragCursor"}
|
||||||
|
style={{
|
||||||
|
fontSize: "12px",
|
||||||
|
textAlign: "center",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "white",
|
||||||
|
textTransform: "uppercase"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isWidgetExist(obj.Id) ? (
|
||||||
|
<i className="fa-solid fa-check"></i>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{obj.Name
|
||||||
|
? getFirstLetter(obj.Name)
|
||||||
|
: getFirstLetter(obj.Role)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: obj.Name ? "column" : "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{obj.Name ? (
|
||||||
|
<span className={"userName"}>{obj.Name}</span>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className="userName"
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClick={() => {
|
||||||
|
setIsEdit({ [obj.Id]: true });
|
||||||
|
props.setRoleName(obj.Role);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isEdit?.[obj.Id] && props.handleRoleChange ? (
|
||||||
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
style={{
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
width: "inherit",
|
||||||
|
padding: "3px"
|
||||||
|
}}
|
||||||
|
value={obj.Role}
|
||||||
|
onChange={(e) => props.handleRoleChange(e, obj.Id)}
|
||||||
|
onBlur={() => {
|
||||||
|
setIsEdit({});
|
||||||
|
props.handleOnBlur(obj.Role, obj.Id);
|
||||||
|
}}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
inputRef.current.blur();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span style={{ padding: "3px" }}>{obj.Role}</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{obj.Name && <span className={"useEmail"}>{obj.Role}</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{isMobile && props.sendInOrder && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
onClick={(e) => {
|
||||||
|
if (ind !== 0) {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleChangeSequence(e, ind, "up");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ color: ind === 0 ? "gray" : "black" }}
|
||||||
|
>
|
||||||
|
▲
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={(e) => {
|
||||||
|
if (ind !== props.signersdata.length - 1) {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleChangeSequence(e, ind, null, "down");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
ind === props.signersdata.length - 1 ? "gray" : "black"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
▼
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.handleDeleteUser && (
|
||||||
|
<div
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.handleDeleteUser(obj.Id);
|
||||||
|
}}
|
||||||
|
style={{ cursor: "pointer", marginLeft: "5px" }}
|
||||||
|
>
|
||||||
|
<i className="fa-regular fa-trash-can"></i>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RecipientList;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import RSC from "react-scrollbars-custom";
|
import RSC from "react-scrollbars-custom";
|
||||||
import { Document, Page, pdfjs } from "react-pdf";
|
import { Document, Page } from "react-pdf";
|
||||||
import { themeColor } from "../../utils/ThemeColor/backColor";
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
function RenderAllPdfPage({
|
function RenderAllPdfPage({
|
||||||
pdfUrl,
|
pdfUrl,
|
||||||
@@ -12,8 +12,6 @@ function RenderAllPdfPage({
|
|||||||
setSignBtnPosition,
|
setSignBtnPosition,
|
||||||
pageNumber
|
pageNumber
|
||||||
}) {
|
}) {
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
|
||||||
|
|
||||||
//set all number of pages after load pdf
|
//set all number of pages after load pdf
|
||||||
function onDocumentLoad({ numPages }) {
|
function onDocumentLoad({ numPages }) {
|
||||||
setAllPages(numPages);
|
setAllPages(numPages);
|
||||||
@@ -33,7 +31,7 @@ function RenderAllPdfPage({
|
|||||||
<div style={{ width: "140px" }}>
|
<div style={{ width: "140px" }}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: themeColor()
|
background: themeColor
|
||||||
// color:"white"
|
// color:"white"
|
||||||
}}
|
}}
|
||||||
className="signedStyle"
|
className="signedStyle"
|
||||||
@@ -0,0 +1,694 @@
|
|||||||
|
import React from "react";
|
||||||
|
import RSC from "react-scrollbars-custom";
|
||||||
|
import { Document, Page } from "react-pdf";
|
||||||
|
import {
|
||||||
|
defaultWidthHeight,
|
||||||
|
handleImageResize,
|
||||||
|
handleSignYourselfImageResize
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
import Placeholder from "./Placeholder";
|
||||||
|
import Alert from "../../primitives/Alert";
|
||||||
|
|
||||||
|
function RenderPdf({
|
||||||
|
pageNumber,
|
||||||
|
pdfOriginalWidth,
|
||||||
|
pdfNewWidth,
|
||||||
|
drop,
|
||||||
|
signerPos,
|
||||||
|
successEmail,
|
||||||
|
handleTabDrag,
|
||||||
|
handleStop,
|
||||||
|
isDragging,
|
||||||
|
setIsSignPad,
|
||||||
|
setIsStamp,
|
||||||
|
handleDeleteSign,
|
||||||
|
setSignKey,
|
||||||
|
pdfDetails,
|
||||||
|
xyPostion,
|
||||||
|
pdfUrl,
|
||||||
|
numPages,
|
||||||
|
pageDetails,
|
||||||
|
pdfRequest,
|
||||||
|
setCurrentSigner,
|
||||||
|
signerObjectId,
|
||||||
|
signedSigners,
|
||||||
|
setPdfLoadFail,
|
||||||
|
placeholder,
|
||||||
|
pdfLoadFail,
|
||||||
|
setSignerPos,
|
||||||
|
setXyPostion,
|
||||||
|
index,
|
||||||
|
containerWH,
|
||||||
|
setIsResize,
|
||||||
|
handleLinkUser,
|
||||||
|
setUniqueId,
|
||||||
|
signersdata,
|
||||||
|
setIsPageCopy,
|
||||||
|
setSignerObjId,
|
||||||
|
setShowDropdown,
|
||||||
|
setIsInitial,
|
||||||
|
setIsValidate,
|
||||||
|
setWidgetType,
|
||||||
|
setValidateAlert,
|
||||||
|
setIsRadio,
|
||||||
|
setCurrWidgetsDetails,
|
||||||
|
setSelectWidgetId,
|
||||||
|
selectWidgetId,
|
||||||
|
unSignedWidgetId,
|
||||||
|
setIsCheckbox,
|
||||||
|
handleNameModal,
|
||||||
|
setTempSignerId,
|
||||||
|
uniqueId
|
||||||
|
}) {
|
||||||
|
const isMobile = window.innerWidth < 767;
|
||||||
|
const newWidth = containerWH.width;
|
||||||
|
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||||
|
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
|
||||||
|
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
||||||
|
|
||||||
|
// handle signature block width and height according to screen
|
||||||
|
const posWidth = (pos, signYourself) => {
|
||||||
|
const defaultWidth = defaultWidthHeight(pos.type).width;
|
||||||
|
const posWidth = pos.Width ? pos.Width : defaultWidth;
|
||||||
|
let width;
|
||||||
|
if (signYourself) {
|
||||||
|
width = posWidth;
|
||||||
|
return width;
|
||||||
|
} else {
|
||||||
|
if (isMobile) {
|
||||||
|
if (!pos.isMobile) {
|
||||||
|
if (pos.IsResize) {
|
||||||
|
width = posWidth ? posWidth : defaultWidth;
|
||||||
|
return width;
|
||||||
|
} else {
|
||||||
|
width = (posWidth || defaultWidth) / scale;
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = posWidth;
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos.isMobile) {
|
||||||
|
if (pos.IsResize) {
|
||||||
|
width = posWidth ? posWidth : defaultWidth;
|
||||||
|
return width;
|
||||||
|
} else {
|
||||||
|
width = (posWidth || defaultWidth) * pos.scale;
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = posWidth ? posWidth : defaultWidth;
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const posHeight = (pos, signYourself) => {
|
||||||
|
let height;
|
||||||
|
const posHeight = pos.Height;
|
||||||
|
const defaultHeight = defaultWidthHeight(pos.type).height;
|
||||||
|
|
||||||
|
if (signYourself) {
|
||||||
|
height = posHeight ? posHeight : defaultHeight;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
} else {
|
||||||
|
if (isMobile) {
|
||||||
|
if (!pos.isMobile) {
|
||||||
|
if (pos.IsResize) {
|
||||||
|
height = posHeight ? posHeight : defaultHeight;
|
||||||
|
return height;
|
||||||
|
} else {
|
||||||
|
height = (posHeight || defaultHeight) / scale;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = posHeight ? posHeight : defaultHeight;
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos.isMobile) {
|
||||||
|
if (pos.IsResize) {
|
||||||
|
height = posHeight ? posHeight : defaultHeight;
|
||||||
|
return height;
|
||||||
|
} else {
|
||||||
|
height = (posHeight || defaultHeight) * pos.scale;
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = posHeight ? posHeight : defaultHeight;
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const xPos = (pos, signYourself) => {
|
||||||
|
const resizePos = pos.xPosition;
|
||||||
|
if (signYourself) {
|
||||||
|
return resizePos;
|
||||||
|
} else {
|
||||||
|
//checking both condition mobile and desktop view
|
||||||
|
if (isMobile) {
|
||||||
|
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||||
|
if (!pos.isMobile) {
|
||||||
|
return resizePos / scale;
|
||||||
|
}
|
||||||
|
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
|
||||||
|
else {
|
||||||
|
return resizePos * (pos.scale / scale);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||||
|
|
||||||
|
if (pos.isMobile) {
|
||||||
|
return pos.scale && resizePos * pos.scale;
|
||||||
|
}
|
||||||
|
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
|
||||||
|
else {
|
||||||
|
return resizePos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const yPos = (pos, signYourself) => {
|
||||||
|
const resizePos = pos.yPosition;
|
||||||
|
if (signYourself) {
|
||||||
|
return resizePos;
|
||||||
|
} else {
|
||||||
|
//checking both condition mobile and desktop view
|
||||||
|
if (isMobile) {
|
||||||
|
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||||
|
if (!pos.isMobile) {
|
||||||
|
return resizePos / scale;
|
||||||
|
}
|
||||||
|
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
|
||||||
|
else {
|
||||||
|
return resizePos * (pos.scale / scale);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||||
|
|
||||||
|
if (pos.isMobile) {
|
||||||
|
return pos.scale && resizePos * pos.scale;
|
||||||
|
}
|
||||||
|
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
|
||||||
|
else {
|
||||||
|
return resizePos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//function for render placeholder block over pdf document
|
||||||
|
const checkSignedSignes = (data) => {
|
||||||
|
const checkSign = signedSigners.filter(
|
||||||
|
(sign) => sign.objectId === data.signerObjId
|
||||||
|
);
|
||||||
|
if (data.signerObjId === signerObjectId) {
|
||||||
|
setCurrentSigner(true);
|
||||||
|
}
|
||||||
|
const handleAllUserName = (Id, Role, type) => {
|
||||||
|
return pdfDetails[0].Signers.map((signerData, key) => {
|
||||||
|
return (
|
||||||
|
signerData.objectId === data.signerObjId && (
|
||||||
|
<React.Fragment key={key}>
|
||||||
|
{signerData?.Name && (
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{signerData.Name}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{type && (
|
||||||
|
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
||||||
|
)}
|
||||||
|
{Role && (
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{`(${Role})`}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
checkSign.length === 0 &&
|
||||||
|
data.placeHolder.map((placeData, key) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={key}>
|
||||||
|
{placeData.pageNumber === pageNumber &&
|
||||||
|
placeData.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
pos && (
|
||||||
|
<React.Fragment key={pos.key}>
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
setIsSignPad={setIsSignPad}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleSignYourselfImageResize={handleImageResize}
|
||||||
|
index={pageNumber}
|
||||||
|
xyPostion={signerPos}
|
||||||
|
setXyPostion={setSignerPos}
|
||||||
|
data={data}
|
||||||
|
setIsResize={setIsResize}
|
||||||
|
isShowBorder={false}
|
||||||
|
signerObjId={signerObjectId}
|
||||||
|
isShowDropdown={true}
|
||||||
|
isNeedSign={true}
|
||||||
|
isSignYourself={false}
|
||||||
|
xPos={xPos}
|
||||||
|
yPos={yPos}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
handleUserName={handleAllUserName}
|
||||||
|
isDragging={false}
|
||||||
|
pdfDetails={pdfDetails}
|
||||||
|
setIsInitial={setIsInitial}
|
||||||
|
setValidateAlert={setValidateAlert}
|
||||||
|
unSignedWidgetId={unSignedWidgetId}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUserName = (Id, Role, type) => {
|
||||||
|
if (Id) {
|
||||||
|
const checkSign = signersdata.find((sign) => sign.Id === Id);
|
||||||
|
if (checkSign?.Name) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{checkSign?.Name}
|
||||||
|
</div>
|
||||||
|
{type && (
|
||||||
|
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
||||||
|
)}
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{`(${Role})`}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{type && (
|
||||||
|
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
||||||
|
)}
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{Role}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{type && (
|
||||||
|
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
||||||
|
)}
|
||||||
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
|
{Role}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
|
||||||
|
{isMobile && scale ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: "0.1px solid #ebe8e8",
|
||||||
|
marginTop: isGuestSigner && "30px"
|
||||||
|
}}
|
||||||
|
ref={drop}
|
||||||
|
id="container"
|
||||||
|
>
|
||||||
|
{pdfLoadFail.status &&
|
||||||
|
(pdfRequest
|
||||||
|
? signerPos.map((data, key) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={key}>
|
||||||
|
{checkSignedSignes(data)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: placeholder // placeholder mobile
|
||||||
|
? signerPos.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{data.placeHolder.map((placeData, index) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
{placeData.pageNumber === pageNumber &&
|
||||||
|
placeData.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={pos.key}>
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setIsPageCopy={setIsPageCopy}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
handleDeleteSign={handleDeleteSign}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleTabDrag={handleTabDrag}
|
||||||
|
handleStop={handleStop}
|
||||||
|
handleSignYourselfImageResize={
|
||||||
|
handleImageResize
|
||||||
|
}
|
||||||
|
index={pageNumber}
|
||||||
|
xyPostion={signerPos}
|
||||||
|
setXyPostion={setSignerPos}
|
||||||
|
setSignerObjId={setSignerObjId}
|
||||||
|
data={data}
|
||||||
|
setIsResize={setIsResize}
|
||||||
|
setShowDropdown={setShowDropdown}
|
||||||
|
isShowBorder={true}
|
||||||
|
isPlaceholder={true}
|
||||||
|
setUniqueId={setUniqueId}
|
||||||
|
handleLinkUser={handleLinkUser}
|
||||||
|
handleUserName={handleUserName}
|
||||||
|
isSignYourself={false}
|
||||||
|
xPos={xPos}
|
||||||
|
yPos={yPos}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
isDragging={isDragging}
|
||||||
|
setIsValidate={setIsValidate}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setIsRadio={setIsRadio}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
setCurrWidgetsDetails={
|
||||||
|
setCurrWidgetsDetails
|
||||||
|
}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
handleNameModal={handleNameModal}
|
||||||
|
setTempSignerId={setTempSignerId}
|
||||||
|
uniqueId={uniqueId}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: xyPostion.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{data.pageNumber === pageNumber &&
|
||||||
|
data.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
pos && (
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setIsPageCopy={setIsPageCopy}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
handleDeleteSign={handleDeleteSign}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleTabDrag={handleTabDrag}
|
||||||
|
handleStop={handleStop}
|
||||||
|
handleSignYourselfImageResize={
|
||||||
|
handleSignYourselfImageResize
|
||||||
|
}
|
||||||
|
index={index}
|
||||||
|
xyPostion={xyPostion}
|
||||||
|
setXyPostion={setXyPostion}
|
||||||
|
pdfOriginalWidth={pdfOriginalWidth}
|
||||||
|
containerWH={containerWH}
|
||||||
|
setIsSignPad={setIsSignPad}
|
||||||
|
isShowBorder={true}
|
||||||
|
isSignYourself={true}
|
||||||
|
xPos={xPos}
|
||||||
|
yPos={yPos}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
pdfDetails={pdfDetails[0]}
|
||||||
|
isDragging={isDragging}
|
||||||
|
setIsInitial={setIsInitial}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
handleUserName={handleUserName}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
setValidateAlert={setValidateAlert}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}))}
|
||||||
|
|
||||||
|
{/* this component for render pdf document is in middle of the component */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Document
|
||||||
|
onLoadError={() => {
|
||||||
|
setPdfLoadFail(true);
|
||||||
|
}}
|
||||||
|
loading={"Loading Document.."}
|
||||||
|
onLoadSuccess={pageDetails}
|
||||||
|
// ref={pdfRef}'
|
||||||
|
onClick={() => {
|
||||||
|
if (setSelectWidgetId) {
|
||||||
|
setSelectWidgetId("");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
file={
|
||||||
|
pdfUrl
|
||||||
|
? pdfUrl
|
||||||
|
: pdfDetails[0] && pdfDetails[0].SignedUrl
|
||||||
|
? pdfDetails[0].SignedUrl
|
||||||
|
: pdfDetails[0].URL
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from(new Array(numPages), (el, index) => (
|
||||||
|
<Page
|
||||||
|
key={index}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
width={containerWH.width}
|
||||||
|
height={containerWH.height}
|
||||||
|
renderAnnotationLayer={false}
|
||||||
|
renderTextLayer={false}
|
||||||
|
onGetAnnotationsError={(error) => {
|
||||||
|
console.log("annotation error", error);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Document>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<RSC
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
||||||
|
width:
|
||||||
|
pdfOriginalWidth > pdfNewWidth ? pdfNewWidth : pdfOriginalWidth,
|
||||||
|
height: window.innerHeight - 110 + "px"
|
||||||
|
}}
|
||||||
|
noScrollY={false}
|
||||||
|
noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: "0.1px solid #ebe8e8",
|
||||||
|
width: pdfOriginalWidth
|
||||||
|
}}
|
||||||
|
ref={drop}
|
||||||
|
id="container"
|
||||||
|
>
|
||||||
|
{pdfLoadFail.status &&
|
||||||
|
(pdfRequest
|
||||||
|
? signerPos.map((data, key) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={key}>
|
||||||
|
{checkSignedSignes(data)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: placeholder
|
||||||
|
? signerPos.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{data.placeHolder.map((placeData, index) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
{placeData.pageNumber === pageNumber &&
|
||||||
|
placeData.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={pos.key}>
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setIsPageCopy={setIsPageCopy}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
handleDeleteSign={handleDeleteSign}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleTabDrag={handleTabDrag}
|
||||||
|
handleStop={handleStop}
|
||||||
|
handleSignYourselfImageResize={
|
||||||
|
handleImageResize
|
||||||
|
}
|
||||||
|
index={pageNumber}
|
||||||
|
xyPostion={signerPos}
|
||||||
|
setXyPostion={setSignerPos}
|
||||||
|
setSignerObjId={setSignerObjId}
|
||||||
|
data={data}
|
||||||
|
setIsResize={setIsResize}
|
||||||
|
setShowDropdown={setShowDropdown}
|
||||||
|
isShowBorder={true}
|
||||||
|
isPlaceholder={true}
|
||||||
|
setUniqueId={setUniqueId}
|
||||||
|
handleLinkUser={handleLinkUser}
|
||||||
|
handleUserName={handleUserName}
|
||||||
|
isSignYourself={false}
|
||||||
|
xPos={xPos}
|
||||||
|
yPos={yPos}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
isDragging={isDragging}
|
||||||
|
setIsValidate={setIsValidate}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setIsRadio={setIsRadio}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
setCurrWidgetsDetails={
|
||||||
|
setCurrWidgetsDetails
|
||||||
|
}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
handleNameModal={handleNameModal}
|
||||||
|
setTempSignerId={setTempSignerId}
|
||||||
|
uniqueId={uniqueId}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: xyPostion.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{data.pageNumber === pageNumber &&
|
||||||
|
data.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
pos && (
|
||||||
|
<React.Fragment key={pos.key}>
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setIsPageCopy={setIsPageCopy}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
handleDeleteSign={handleDeleteSign}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleTabDrag={handleTabDrag}
|
||||||
|
handleStop={(event, dragElement) =>
|
||||||
|
handleStop(event, dragElement, pos.type)
|
||||||
|
}
|
||||||
|
handleSignYourselfImageResize={
|
||||||
|
handleSignYourselfImageResize
|
||||||
|
}
|
||||||
|
index={index}
|
||||||
|
xyPostion={xyPostion}
|
||||||
|
setXyPostion={setXyPostion}
|
||||||
|
pdfOriginalWidth={pdfOriginalWidth}
|
||||||
|
containerWH={containerWH}
|
||||||
|
setIsSignPad={setIsSignPad}
|
||||||
|
isShowBorder={true}
|
||||||
|
isSignYourself={true}
|
||||||
|
xPos={xPos}
|
||||||
|
yPos={yPos}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
pdfDetails={pdfDetails[0]}
|
||||||
|
isDragging={isDragging}
|
||||||
|
setIsInitial={setIsInitial}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
handleUserName={handleUserName}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
setValidateAlert={setValidateAlert}
|
||||||
|
setCurrWidgetsDetails={
|
||||||
|
setCurrWidgetsDetails
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}))}
|
||||||
|
|
||||||
|
{/* this component for render pdf document is in middle of the component */}
|
||||||
|
<Document
|
||||||
|
onLoadError={() => {
|
||||||
|
const load = {
|
||||||
|
status: false,
|
||||||
|
type: "failed"
|
||||||
|
};
|
||||||
|
setPdfLoadFail(load);
|
||||||
|
}}
|
||||||
|
loading={"Loading Document.."}
|
||||||
|
onLoadSuccess={pageDetails}
|
||||||
|
onClick={() => {
|
||||||
|
if (setSelectWidgetId) {
|
||||||
|
setSelectWidgetId("");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
// ref={pdfRef}
|
||||||
|
file={
|
||||||
|
pdfUrl
|
||||||
|
? pdfUrl
|
||||||
|
: pdfDetails[0] && pdfDetails[0].SignedUrl
|
||||||
|
? pdfDetails[0].SignedUrl
|
||||||
|
: pdfDetails[0].URL
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Array.from(new Array(numPages), (el, index) => (
|
||||||
|
<Page
|
||||||
|
key={index}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
renderAnnotationLayer={false}
|
||||||
|
renderTextLayer={false}
|
||||||
|
onGetAnnotationsError={(error) => {
|
||||||
|
console.log("annotation error", error);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Document>
|
||||||
|
</div>
|
||||||
|
</RSC>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RenderPdf;
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
import React from "react";
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
import { useRef, useState } from "react";
|
|
||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
import redPen from "../../assests/redPen.png";
|
import { themeColor } from "../../constant/const";
|
||||||
import bluePen from "../../assests/bluePen.png";
|
|
||||||
import blackPen from "../../assests/blackPen.png";
|
|
||||||
import { themeColor } from "../../utils/ThemeColor/backColor";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
function SignPad({
|
function SignPad({
|
||||||
isSignPad,
|
isSignPad,
|
||||||
@@ -20,10 +15,17 @@ function SignPad({
|
|||||||
onSaveImage,
|
onSaveImage,
|
||||||
image,
|
image,
|
||||||
defaultSign,
|
defaultSign,
|
||||||
setSignature
|
setSignature,
|
||||||
|
myInitial,
|
||||||
|
isInitial,
|
||||||
|
setIsInitial,
|
||||||
|
setIsStamp,
|
||||||
|
widgetType,
|
||||||
|
currWidgetsDetails,
|
||||||
|
setCurrWidgetsDetails
|
||||||
}) {
|
}) {
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
const allColor = [bluePen, redPen, blackPen];
|
const allColor = ["blue", "red", "black"];
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
const [isDefaultSign, setIsDefaultSign] = useState(false);
|
const [isDefaultSign, setIsDefaultSign] = useState(false);
|
||||||
const [isTab, setIsTab] = useState("draw");
|
const [isTab, setIsTab] = useState("draw");
|
||||||
@@ -31,6 +33,7 @@ function SignPad({
|
|||||||
const [signValue, setSignValue] = useState("");
|
const [signValue, setSignValue] = useState("");
|
||||||
const [textWidth, setTextWidth] = useState(null);
|
const [textWidth, setTextWidth] = useState(null);
|
||||||
const [textHeight, setTextHeight] = useState(null);
|
const [textHeight, setTextHeight] = useState(null);
|
||||||
|
const [signatureType, setSignatureType] = useState("draw");
|
||||||
const fontOptions = [
|
const fontOptions = [
|
||||||
{ value: "Fasthand" },
|
{ value: "Fasthand" },
|
||||||
{ value: "Dancing Script" },
|
{ value: "Dancing Script" },
|
||||||
@@ -40,23 +43,19 @@ function SignPad({
|
|||||||
];
|
];
|
||||||
const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
|
const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
|
||||||
|
|
||||||
useEffect(() => {
|
const senderUser =
|
||||||
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 jsonSender = JSON.parse(senderUser);
|
||||||
const jsonSender = JSON.parse(senderUser);
|
const currentUserName = jsonSender && jsonSender.name;
|
||||||
|
|
||||||
const currentUserName = jsonSender && jsonSender.name;
|
|
||||||
//function for clear signature
|
|
||||||
setSignValue(currentUserName);
|
|
||||||
setFontSelect("Fasthand");
|
|
||||||
}, []);
|
|
||||||
//function for clear signature image
|
//function for clear signature image
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
|
setCurrWidgetsDetails({});
|
||||||
if (isTab === "draw") {
|
if (isTab === "draw") {
|
||||||
if (canvasRef.current) {
|
if (canvasRef.current) {
|
||||||
canvasRef.current.clear();
|
canvasRef.current.clear();
|
||||||
@@ -66,12 +65,12 @@ function SignPad({
|
|||||||
|
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
} else if (isTab === "uploadImage") {
|
} else if (isTab === "uploadImage") {
|
||||||
setImage("");
|
setImage("");
|
||||||
}
|
}
|
||||||
|
// setIsInitial(false);
|
||||||
};
|
};
|
||||||
//function for set signature url
|
//function for set signature url
|
||||||
const handleSignatureChange = (dataURL) => {
|
const handleSignatureChange = () => {
|
||||||
// canvasRef.current.backgroundColor = 'rgb(165, 26, 26)'
|
|
||||||
setSignature(canvasRef.current.toDataURL());
|
setSignature(canvasRef.current.toDataURL());
|
||||||
setIsSignImg(canvasRef.current.toDataURL());
|
setIsSignImg(canvasRef.current.toDataURL());
|
||||||
};
|
};
|
||||||
@@ -96,34 +95,40 @@ function SignPad({
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setCurrWidgetsDetails({});
|
||||||
if (!image) {
|
if (!image) {
|
||||||
if (isDefaultSign) {
|
if (isTab === "mysignature") {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveSign(isDefaultSign);
|
if (isInitial) {
|
||||||
|
onSaveSign(signatureType, "initials");
|
||||||
|
} else {
|
||||||
|
onSaveSign(null, "default");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isTab === "type") {
|
if (isTab === "type") {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveSign(false, textWidth, textHeight);
|
onSaveSign(null, false, textWidth, textHeight);
|
||||||
} else {
|
} else {
|
||||||
setIsSignImg("");
|
onSaveSign(signatureType);
|
||||||
onSaveSign();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPenColor("blue");
|
setPenColor("blue");
|
||||||
} else {
|
} else {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveImage();
|
onSaveImage(signatureType);
|
||||||
}
|
}
|
||||||
setIsSignPad(false);
|
setIsSignPad(false);
|
||||||
|
setIsInitial(false);
|
||||||
setIsImageSelect(false);
|
setIsImageSelect(false);
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setImage();
|
setImage();
|
||||||
setIsTab("draw");
|
setIsTab("draw");
|
||||||
|
setSignValue("");
|
||||||
|
setIsStamp(false);
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
disabled={
|
disabled={
|
||||||
@@ -141,7 +146,35 @@ function SignPad({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
|
||||||
|
useEffect(() => {
|
||||||
|
if (currWidgetsDetails && canvasRef.current) {
|
||||||
|
const isWidgetType = currWidgetsDetails?.type;
|
||||||
|
const signatureType = currWidgetsDetails?.signatureType;
|
||||||
|
const url = currWidgetsDetails?.SignUrl;
|
||||||
|
|
||||||
|
//checking widget type and draw type signature url
|
||||||
|
if (isInitial) {
|
||||||
|
if (isWidgetType === "initials" && signatureType === "draw" && url) {
|
||||||
|
canvasRef.current.fromDataURL(url);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
isWidgetType === "signature" &&
|
||||||
|
signatureType === "draw" &&
|
||||||
|
url
|
||||||
|
) {
|
||||||
|
canvasRef.current.fromDataURL(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const trimmedName = currentUserName.trim();
|
||||||
|
const firstCharacter = trimmedName.charAt(0);
|
||||||
|
const userName = isInitial ? firstCharacter : currentUserName;
|
||||||
|
setSignValue(userName);
|
||||||
|
setFontSelect("Fasthand");
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [isSignPad]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadFont = async () => {
|
const loadFont = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -156,6 +189,7 @@ function SignPad({
|
|||||||
};
|
};
|
||||||
|
|
||||||
loadFont();
|
loadFont();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [fontSelect]);
|
}, [fontSelect]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -164,11 +198,17 @@ function SignPad({
|
|||||||
canvasRef.current.fromDataURL(isSignImg);
|
canvasRef.current.fromDataURL(isSignImg);
|
||||||
}
|
}
|
||||||
if (isTab === "type") {
|
if (isTab === "type") {
|
||||||
convertToImg(fontSelect, signValue);
|
const trimmedName = signValue ? signValue.trim() : currentUserName.trim();
|
||||||
|
const firstCharacter = trimmedName.charAt(0);
|
||||||
|
const userName = isInitial ? firstCharacter : signValue;
|
||||||
|
setSignValue(userName);
|
||||||
|
convertToImg(fontSelect, userName);
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isTab]);
|
}, [isTab]);
|
||||||
|
|
||||||
//function for convert input text value in image
|
//function for convert input text value in image
|
||||||
const convertToImg = async (fontStyle, text) => {
|
const convertToImg = async (fontStyle, text, color) => {
|
||||||
//get text content to convert in image
|
//get text content to convert in image
|
||||||
const textContent = text;
|
const textContent = text;
|
||||||
const fontfamily = fontStyle
|
const fontfamily = fontStyle
|
||||||
@@ -181,6 +221,7 @@ function SignPad({
|
|||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.textContent = textContent;
|
span.textContent = textContent;
|
||||||
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
|
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
|
||||||
|
span.style.color = color ? color : penColor;
|
||||||
span.style.display = "hidden";
|
span.style.display = "hidden";
|
||||||
document.body.appendChild(span); // Replace 'container' with the ID of the container element
|
document.body.appendChild(span); // Replace 'container' with the ID of the container element
|
||||||
|
|
||||||
@@ -198,13 +239,9 @@ function SignPad({
|
|||||||
canvasElement.width = width * pixelRatio;
|
canvasElement.width = width * pixelRatio;
|
||||||
canvasElement.height = height * pixelRatio;
|
canvasElement.height = height * pixelRatio;
|
||||||
|
|
||||||
// Render the content of the span onto the canvas
|
|
||||||
// ctx.fillStyle = "white"; // Set the background color of the canvas
|
|
||||||
// ctx.fillRect(0, 0, width*pixelRatio, height*pixelRatio);
|
|
||||||
|
|
||||||
// You can customize text styles if needed
|
// You can customize text styles if needed
|
||||||
ctx.font = font;
|
ctx.font = font;
|
||||||
ctx.fillStyle = "black"; // Set the text color
|
ctx.fillStyle = color ? color : penColor; // Set the text color
|
||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
ctx.scale(pixelRatio, pixelRatio);
|
ctx.scale(pixelRatio, pixelRatio);
|
||||||
@@ -217,6 +254,45 @@ function SignPad({
|
|||||||
setSignature(dataUrl);
|
setSignature(dataUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PenColorComponent = (props) => {
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
{allColor.map((data, key) => {
|
||||||
|
return (
|
||||||
|
<i
|
||||||
|
style={{
|
||||||
|
margin: "5px",
|
||||||
|
color: data,
|
||||||
|
borderBottom:
|
||||||
|
key === 0 && penColor === "blue"
|
||||||
|
? "2px solid blue"
|
||||||
|
: key === 1 && penColor === "red"
|
||||||
|
? "2px solid red"
|
||||||
|
: key === 2 && penColor === "black"
|
||||||
|
? "2px solid black"
|
||||||
|
: "2px solid white"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
props?.convertToImg &&
|
||||||
|
props?.convertToImg(fontSelect, signValue, data);
|
||||||
|
if (key === 0) {
|
||||||
|
setPenColor("blue");
|
||||||
|
} else if (key === 1) {
|
||||||
|
setPenColor("red");
|
||||||
|
} else if (key === 2) {
|
||||||
|
setPenColor("black");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
key={key}
|
||||||
|
className="fa solid fa-pen-nib"
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
></i>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isSignPad && (
|
{isSignPad && (
|
||||||
@@ -246,8 +322,10 @@ function SignPad({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isStamp ? (
|
{isStamp ? (
|
||||||
<span style={{ color: themeColor() }} className="signTab">
|
<span style={{ color: themeColor }} className="signTab">
|
||||||
Upload stamp image
|
{widgetType === "image"
|
||||||
|
? "Upload image"
|
||||||
|
: "Upload stamp image"}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -260,9 +338,7 @@ function SignPad({
|
|||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color:
|
color: isTab === "draw" ? themeColor : "#515252",
|
||||||
isTab === "draw" ? themeColor() : "#515252",
|
|
||||||
|
|
||||||
marginLeft: "2px"
|
marginLeft: "2px"
|
||||||
}}
|
}}
|
||||||
className="signTab"
|
className="signTab"
|
||||||
@@ -285,12 +361,11 @@ function SignPad({
|
|||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("uploadImage");
|
setIsTab("uploadImage");
|
||||||
|
setSignatureType("");
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color:
|
color:
|
||||||
isTab === "uploadImage"
|
isTab === "uploadImage" ? themeColor : "#515252"
|
||||||
? themeColor()
|
|
||||||
: "#515252"
|
|
||||||
}}
|
}}
|
||||||
className="signTab"
|
className="signTab"
|
||||||
>
|
>
|
||||||
@@ -311,12 +386,11 @@ function SignPad({
|
|||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(false);
|
setIsImageSelect(false);
|
||||||
setIsTab("type");
|
setIsTab("type");
|
||||||
|
setSignatureType("");
|
||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color:
|
color: isTab === "type" ? themeColor : "#515252",
|
||||||
isTab === "type" ? themeColor() : "#515252",
|
|
||||||
|
|
||||||
marginLeft: "2px"
|
marginLeft: "2px"
|
||||||
}}
|
}}
|
||||||
className="signTab"
|
className="signTab"
|
||||||
@@ -333,19 +407,20 @@ function SignPad({
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
{defaultSign && (
|
{!isInitial && defaultSign ? (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(true);
|
setIsDefaultSign(true);
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("mysignature");
|
setIsTab("mysignature");
|
||||||
|
setSignatureType("");
|
||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color:
|
color:
|
||||||
isTab === "mysignature"
|
isTab === "mysignature"
|
||||||
? themeColor()
|
? themeColor
|
||||||
: "#515252"
|
: "#515252"
|
||||||
}}
|
}}
|
||||||
className="signTab"
|
className="signTab"
|
||||||
@@ -361,6 +436,38 @@ function SignPad({
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
isInitial &&
|
||||||
|
myInitial && (
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(true);
|
||||||
|
setIsImageSelect(true);
|
||||||
|
setIsTab("mysignature");
|
||||||
|
setSignatureType("");
|
||||||
|
setImage();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
isTab === "mysignature"
|
||||||
|
? themeColor
|
||||||
|
: "#515252"
|
||||||
|
}}
|
||||||
|
className="signTab"
|
||||||
|
>
|
||||||
|
My Initials
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border:
|
||||||
|
isTab === "mysignature"
|
||||||
|
? "1.5px solid #108783"
|
||||||
|
: "1.5px solid #ffffff"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -373,11 +480,14 @@ function SignPad({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPenColor("blue");
|
setPenColor("blue");
|
||||||
setIsSignPad(false);
|
setIsSignPad(false);
|
||||||
|
setIsInitial(false);
|
||||||
setIsImageSelect(false);
|
setIsImageSelect(false);
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setImage();
|
setImage();
|
||||||
setIsTab("draw");
|
setIsTab("draw");
|
||||||
|
setSignatureType("draw");
|
||||||
|
setSignValue("");
|
||||||
|
setIsStamp(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
×
|
×
|
||||||
@@ -386,28 +496,34 @@ function SignPad({
|
|||||||
<div style={{ height: "100%", padding: 20 }}>
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
{isDefaultSign ? (
|
{isDefaultSign ? (
|
||||||
<>
|
<>
|
||||||
<div
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
style={{
|
<div
|
||||||
border: "1px solid black",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
marginBottom: 6,
|
|
||||||
cursor: "pointer"
|
|
||||||
}}
|
|
||||||
className="signatureCanvas"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="stamp img"
|
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
border: "1.3px solid #007bff",
|
||||||
height: "100%",
|
borderRadius: "2px",
|
||||||
background: "rgb(255, 255, 255)",
|
display: "flex",
|
||||||
objectFit: "contain"
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 6,
|
||||||
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
src={defaultSign}
|
className={
|
||||||
/>
|
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="stamp img"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
background: "rgb(255, 255, 255)",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
draggable="false"
|
||||||
|
src={isInitial ? myInitial : defaultSign}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||||
<SaveBtn />
|
<SaveBtn />
|
||||||
@@ -415,52 +531,64 @@ function SignPad({
|
|||||||
</>
|
</>
|
||||||
) : isImageSelect || isStamp ? (
|
) : isImageSelect || isStamp ? (
|
||||||
!image ? (
|
!image ? (
|
||||||
<div
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
style={{
|
<div
|
||||||
border: "1px solid black",
|
style={{
|
||||||
|
border: "1.3px solid #007bff",
|
||||||
|
borderRadius: "2px",
|
||||||
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginBottom: 6,
|
marginBottom: 6,
|
||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
className="signatureCanvas"
|
className={
|
||||||
onClick={() => imageRef.current.click()}
|
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
||||||
>
|
}
|
||||||
<input
|
onClick={() => imageRef.current.click()}
|
||||||
type="file"
|
>
|
||||||
onChange={onImageChange}
|
<input
|
||||||
className="filetype"
|
type="file"
|
||||||
accept="image/*"
|
onChange={onImageChange}
|
||||||
ref={imageRef}
|
className="filetype"
|
||||||
hidden
|
accept="image/*"
|
||||||
/>
|
ref={imageRef}
|
||||||
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
|
hidden
|
||||||
<div className="uploadImg">Upload</div>
|
/>
|
||||||
|
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
|
||||||
|
<div className="uploadImg">Upload</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
style={{
|
<div
|
||||||
border: "1px solid black",
|
|
||||||
marginBottom: 6,
|
|
||||||
|
|
||||||
overflow: "hidden"
|
|
||||||
}}
|
|
||||||
className="signatureCanvas"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="print img"
|
|
||||||
ref={imageRef}
|
|
||||||
src={image.src}
|
|
||||||
style={{
|
style={{
|
||||||
objectFit: "contain",
|
border: "1.3px solid #007bff",
|
||||||
height: "100%",
|
borderRadius: "2px",
|
||||||
width: "100%"
|
marginBottom: 6,
|
||||||
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
/>
|
className={
|
||||||
|
isInitial
|
||||||
|
? "intialSignatureCanvas"
|
||||||
|
: "signatureCanvas"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="print img"
|
||||||
|
ref={imageRef}
|
||||||
|
src={image.src}
|
||||||
|
draggable="false"
|
||||||
|
style={{
|
||||||
|
objectFit: "contain",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{ display: "flex", justifyContent: "flex-end" }}
|
style={{ display: "flex", justifyContent: "flex-end" }}
|
||||||
@@ -478,11 +606,13 @@ function SignPad({
|
|||||||
alignItems: "center"
|
alignItems: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="signatureText">Signature:</span>
|
<span className="signatureText">
|
||||||
|
{isInitial ? "Initials" : "Signature"}:
|
||||||
|
</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
maxLength={30}
|
maxLength={isInitial ? 3 : 30}
|
||||||
style={{ fontFamily: fontSelect }}
|
style={{ fontFamily: fontSelect, color: penColor }}
|
||||||
type="text"
|
type="text"
|
||||||
className="signatureInput"
|
className="signatureInput"
|
||||||
placeholder="Your signature"
|
placeholder="Your signature"
|
||||||
@@ -513,7 +643,8 @@ function SignPad({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: "5px 10px 5px 10px",
|
padding: "5px 10px 5px 10px",
|
||||||
fontSize: "20px"
|
fontSize: "20px",
|
||||||
|
color: penColor
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{signValue ? signValue : "Your signature"}
|
{signValue ? signValue : "Your signature"}
|
||||||
@@ -523,25 +654,6 @@ function SignPad({
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
|
||||||
<SaveBtn />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<SignatureCanvas
|
|
||||||
ref={canvasRef}
|
|
||||||
penColor={penColor}
|
|
||||||
canvasProps={{
|
|
||||||
className: "signatureCanvas"
|
|
||||||
}}
|
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
|
||||||
onEnd={() =>
|
|
||||||
handleSignatureChange(canvasRef.current.toDataURL())
|
|
||||||
}
|
|
||||||
dotSize={1}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -550,41 +662,41 @@ function SignPad({
|
|||||||
marginTop: "10px"
|
marginTop: "10px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<PenColorComponent convertToImg={convertToImg} />
|
||||||
{allColor.map((data, key) => {
|
<SaveBtn />
|
||||||
return (
|
</div>
|
||||||
<img
|
</div>
|
||||||
key={key}
|
) : (
|
||||||
alt="pen img"
|
<>
|
||||||
style={{
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
border: "none",
|
<SignatureCanvas
|
||||||
margin: "5px",
|
ref={canvasRef}
|
||||||
borderBottom:
|
penColor={penColor}
|
||||||
key === 0 && penColor === "blue"
|
canvasProps={{
|
||||||
? "2px solid blue"
|
className: isInitial
|
||||||
: key === 1 && penColor === "red"
|
? "intialSignatureCanvas"
|
||||||
? "2px solid red"
|
: "signatureCanvas",
|
||||||
: key === 2 && penColor === "black"
|
style: {
|
||||||
? "2px solid black"
|
border: "1.6px solid #007bff",
|
||||||
: "2px solid white"
|
borderRadius: "2px"
|
||||||
}}
|
}
|
||||||
onClick={() => {
|
}}
|
||||||
if (key === 0) {
|
backgroundColor="rgb(255, 255, 255)"
|
||||||
setPenColor("blue");
|
onEnd={() =>
|
||||||
} else if (key === 1) {
|
handleSignatureChange(canvasRef.current.toDataURL())
|
||||||
setPenColor("red");
|
}
|
||||||
} else if (key === 2) {
|
dotSize={1}
|
||||||
setPenColor("black");
|
/>
|
||||||
}
|
</div>
|
||||||
}}
|
<div
|
||||||
src={data}
|
style={{
|
||||||
width={20}
|
display: "flex",
|
||||||
height={20}
|
flexDirection: "row",
|
||||||
/>
|
justifyContent: "space-between",
|
||||||
);
|
marginTop: "10px"
|
||||||
})}
|
}}
|
||||||
</div>
|
>
|
||||||
|
<PenColorComponent />
|
||||||
<SaveBtn />
|
<SaveBtn />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import "../../styles/signature.css";
|
||||||
|
function Signedby({ pdfDetails }) {
|
||||||
|
const getFirstLetter = (name) => {
|
||||||
|
const firstLetter = name.charAt(0);
|
||||||
|
return firstLetter;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="signerComponent">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
className="signedStyle"
|
||||||
|
>
|
||||||
|
Signed By
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: "2px", background: "white" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
padding: "10px",
|
||||||
|
background: "#93a3db"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="signerStyle"
|
||||||
|
style={{
|
||||||
|
background: "#abd1d0",
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
display: "flex",
|
||||||
|
borderRadius: 30 / 2,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginRight: "20px",
|
||||||
|
marginTop: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: "8px",
|
||||||
|
textAlign: "center",
|
||||||
|
fontWeight: "bold"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getFirstLetter(pdfDetails.ExtUserPtr.Name)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<span className="userName">{pdfDetails.ExtUserPtr.Name}</span>
|
||||||
|
<span className="useEmail">{pdfDetails.ExtUserPtr.Email}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Signedby;
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import RecipientList from "./RecipientList";
|
||||||
|
import { Tooltip } from "react-tooltip";
|
||||||
|
|
||||||
|
function SignerListPlace(props) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
padding: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="signedStyle">
|
||||||
|
{props.title ? props.title : "Recipients"}
|
||||||
|
<span className="absolute text-xs z-[30] mt-1 ml-0.5">
|
||||||
|
{props?.title === "Roles" && (
|
||||||
|
<>
|
||||||
|
<a data-tooltip-id="my-tooltip">
|
||||||
|
<sup>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-question rounded-full"
|
||||||
|
style={{
|
||||||
|
borderColor: "white",
|
||||||
|
color: "white",
|
||||||
|
fontSize: 11,
|
||||||
|
borderWidth: 1.5,
|
||||||
|
padding: "1px 3px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
<Tooltip id="my-tooltip">
|
||||||
|
<div className="max-w-[450px]">
|
||||||
|
<p className="font-bold">What are template roles?</p>
|
||||||
|
<p>
|
||||||
|
Begin by specifying each role needed for the completion of
|
||||||
|
the document. Think about the parties involved in the
|
||||||
|
signing process and what their responsibilities are.
|
||||||
|
Common roles include HR for internal documents, Customer
|
||||||
|
for agreements or Vendor for business agreements.{" "}
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">
|
||||||
|
Why pre-attach users to some roles?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For roles that consistently involve the same individual
|
||||||
|
(e.g., the CEO's signature on employee offer
|
||||||
|
letters), you can pre-attach a user to a role within the
|
||||||
|
template. This step is optional but recommended for
|
||||||
|
efficiency and consistency across documents.
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">
|
||||||
|
When do i specify the user attached to each role?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When you create a document from your template, you'll
|
||||||
|
be prompted to attach users to each defined role. If a
|
||||||
|
role already has a user attached, this will be pre-filled,
|
||||||
|
but you can modify it as needed before sending out the
|
||||||
|
document.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="signerList">
|
||||||
|
<RecipientList {...props} />
|
||||||
|
</div>
|
||||||
|
{props.handleAddSigner && (
|
||||||
|
<div
|
||||||
|
data-tut="reactourAddbtn"
|
||||||
|
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
||||||
|
onClick={() => props.handleAddSigner()}
|
||||||
|
style={{
|
||||||
|
opacity: props.isMailSend && "0.5",
|
||||||
|
pointerEvents: props.isMailSend && "none"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus"></i>
|
||||||
|
<span style={{ marginLeft: 2 }}>Add role</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SignerListPlace;
|
||||||
@@ -0,0 +1,436 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import RecipientList from "./RecipientList";
|
||||||
|
import { useDrag } from "react-dnd";
|
||||||
|
import WidgetList from "./WidgetList";
|
||||||
|
import {
|
||||||
|
radioButtonWidget,
|
||||||
|
textInputWidget,
|
||||||
|
textWidget,
|
||||||
|
widgets
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
function WidgetComponent({
|
||||||
|
dragSignature,
|
||||||
|
signRef,
|
||||||
|
handleDivClick,
|
||||||
|
handleMouseLeave,
|
||||||
|
dragStamp,
|
||||||
|
isSignYourself,
|
||||||
|
addPositionOfSignature,
|
||||||
|
signersdata,
|
||||||
|
isSelectListId,
|
||||||
|
setSignerObjId,
|
||||||
|
setIsSelectId,
|
||||||
|
setContractName,
|
||||||
|
isSigners,
|
||||||
|
dataTut,
|
||||||
|
isMailSend,
|
||||||
|
handleAddSigner,
|
||||||
|
setUniqueId,
|
||||||
|
setRoleName,
|
||||||
|
handleDeleteUser,
|
||||||
|
signerPos,
|
||||||
|
handleRoleChange,
|
||||||
|
handleOnBlur,
|
||||||
|
title,
|
||||||
|
setSignersData,
|
||||||
|
sendInOrder,
|
||||||
|
isTemplateFlow,
|
||||||
|
setBlockColor,
|
||||||
|
blockColor
|
||||||
|
}) {
|
||||||
|
const [isSignersModal, setIsSignersModal] = useState(false);
|
||||||
|
|
||||||
|
const [, dropdown] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 5,
|
||||||
|
text: "dropdown"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragDropdown: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, checkbox] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 6,
|
||||||
|
text: "checkbox"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragCheck: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, textInput] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 7,
|
||||||
|
text: textInputWidget
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragTextInput: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, initials] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 8,
|
||||||
|
text: "initials"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragInitial: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, name] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 9,
|
||||||
|
text: "name"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragName: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, company] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 10,
|
||||||
|
text: "company"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragCompany: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, jobTitle] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 11,
|
||||||
|
text: "job title"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragJobtitle: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, date] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 12,
|
||||||
|
text: "date"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragDate: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, image] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 13,
|
||||||
|
text: "image"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragImage: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, email] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 14,
|
||||||
|
text: "email"
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragEmail: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, radioButton] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 15,
|
||||||
|
text: radioButtonWidget
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragRadiotton: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, text] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 16,
|
||||||
|
text: textWidget
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragText: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const isMobile = window.innerWidth < 767;
|
||||||
|
const scrollContainerRef = useRef(null);
|
||||||
|
const [widget, setWidget] = useState([]);
|
||||||
|
|
||||||
|
const color = [
|
||||||
|
"#93a3db",
|
||||||
|
"#e6c3db",
|
||||||
|
"#c0e3bc",
|
||||||
|
"#bce3db",
|
||||||
|
"#b8ccdb",
|
||||||
|
"#ceb8db",
|
||||||
|
"#ffccff",
|
||||||
|
"#99ffcc",
|
||||||
|
"#cc99ff",
|
||||||
|
"#ffcc99",
|
||||||
|
"#66ccff",
|
||||||
|
"#ffffcc"
|
||||||
|
];
|
||||||
|
const handleModal = () => {
|
||||||
|
setIsSignersModal(!isSignersModal);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const widgetRef = [
|
||||||
|
dragSignature,
|
||||||
|
dragStamp,
|
||||||
|
initials,
|
||||||
|
name,
|
||||||
|
jobTitle,
|
||||||
|
company,
|
||||||
|
date,
|
||||||
|
text,
|
||||||
|
textInput,
|
||||||
|
checkbox,
|
||||||
|
dropdown,
|
||||||
|
radioButton,
|
||||||
|
image,
|
||||||
|
email
|
||||||
|
];
|
||||||
|
const getWidgetArray = widgets;
|
||||||
|
const newUpdateSigner = getWidgetArray.map((obj, ind) => {
|
||||||
|
return { ...obj, ref: widgetRef[ind] };
|
||||||
|
});
|
||||||
|
|
||||||
|
setWidget(newUpdateSigner);
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const filterWidgets = widget.filter(
|
||||||
|
(data) =>
|
||||||
|
data.type !== "dropdown" &&
|
||||||
|
data.type !== radioButtonWidget &&
|
||||||
|
data.type !== textInputWidget
|
||||||
|
);
|
||||||
|
const textWidgetData = widget.filter((data) => data.type !== textWidget);
|
||||||
|
const updateWidgets = isSignYourself
|
||||||
|
? filterWidgets
|
||||||
|
: isTemplateFlow
|
||||||
|
? textWidgetData
|
||||||
|
: widget;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isMobile ? (
|
||||||
|
!isMailSend && (
|
||||||
|
<div
|
||||||
|
data-tut={dataTut}
|
||||||
|
id="navbar"
|
||||||
|
className="stickyfooter"
|
||||||
|
style={{ width: window.innerWidth + "px" }}
|
||||||
|
>
|
||||||
|
{isSigners && (
|
||||||
|
<div
|
||||||
|
data-tut={dataTut}
|
||||||
|
style={{
|
||||||
|
background: blockColor
|
||||||
|
? blockColor
|
||||||
|
: isSelectListId
|
||||||
|
? color[isSelectListId % color.length]
|
||||||
|
: color[0],
|
||||||
|
padding: "10px 20px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
onClick={() => handleModal()}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "700",
|
||||||
|
textAlign: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title ? title : "Recipient"}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "700",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{signersdata[isSelectListId]?.Role && (
|
||||||
|
<div>
|
||||||
|
{signersdata[isSelectListId]?.Name ? (
|
||||||
|
<>
|
||||||
|
:{" "}
|
||||||
|
{signersdata[isSelectListId]?.Name?.length > 12
|
||||||
|
? `${signersdata[isSelectListId].Name.slice(
|
||||||
|
0,
|
||||||
|
12
|
||||||
|
)}...`
|
||||||
|
: signersdata[isSelectListId]?.Name}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
:{" "}
|
||||||
|
{signersdata[isSelectListId]?.Role?.length > 12
|
||||||
|
? `${signersdata[isSelectListId].Role.slice(
|
||||||
|
0,
|
||||||
|
12
|
||||||
|
)}...`
|
||||||
|
: signersdata[isSelectListId]?.Role}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ marginLeft: 6, fontSize: 16 }}>
|
||||||
|
<i className="fa-solid fa-angle-down"></i>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{handleAddSigner && (
|
||||||
|
<div
|
||||||
|
data-tut="reactourAddbtn"
|
||||||
|
style={{
|
||||||
|
margin: "5px 0 5px 0",
|
||||||
|
backgroundColor: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
||||||
|
onClick={() => handleAddSigner()}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus"></i>
|
||||||
|
<span style={{ marginLeft: 2 }}>Add role</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
ref={scrollContainerRef}
|
||||||
|
style={{
|
||||||
|
background: "white",
|
||||||
|
borderTop: `2px solid ${themeColor}`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
overflowX: "scroll",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
padding: "10px 5px 10px 1px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<WidgetList
|
||||||
|
updateWidgets={updateWidgets}
|
||||||
|
handleDivClick={handleDivClick}
|
||||||
|
handleMouseLeave={handleMouseLeave}
|
||||||
|
signRef={signRef}
|
||||||
|
marginLeft={5}
|
||||||
|
addPositionOfSignature={addPositionOfSignature}
|
||||||
|
isMobile={isMobile}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
data-tut={dataTut}
|
||||||
|
className={
|
||||||
|
isMailSend ? "disabled signerComponent " : "signerComponent"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
padding: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="signedStyle">Fields</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="signLayoutContainer1">
|
||||||
|
<WidgetList
|
||||||
|
updateWidgets={updateWidgets}
|
||||||
|
handleDivClick={handleDivClick}
|
||||||
|
handleMouseLeave={handleMouseLeave}
|
||||||
|
signRef={signRef}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isSignersModal && (
|
||||||
|
<ModalUi
|
||||||
|
title={"Roles"}
|
||||||
|
isOpen={isSignersModal}
|
||||||
|
handleClose={handleModal}
|
||||||
|
>
|
||||||
|
{signersdata.length > 0 ? (
|
||||||
|
<div style={{ maxHeight: "600px", overflow: "auto" }}>
|
||||||
|
<RecipientList
|
||||||
|
signerPos={signerPos}
|
||||||
|
signersdata={signersdata}
|
||||||
|
isSelectListId={isSelectListId}
|
||||||
|
setSignerObjId={setSignerObjId}
|
||||||
|
setIsSelectId={setIsSelectId}
|
||||||
|
setContractName={setContractName}
|
||||||
|
setUniqueId={setUniqueId}
|
||||||
|
setRoleName={setRoleName}
|
||||||
|
handleDeleteUser={handleDeleteUser}
|
||||||
|
handleRoleChange={handleRoleChange}
|
||||||
|
handleOnBlur={handleOnBlur}
|
||||||
|
handleModal={handleModal}
|
||||||
|
sendInOrder={sendInOrder}
|
||||||
|
setSignersData={setSignersData}
|
||||||
|
setBlockColor={setBlockColor}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 20,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: "500",
|
||||||
|
textAlign: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Please add a role
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ModalUi>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WidgetComponent;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { getWidgetType } from "../../constant/Utils";
|
||||||
|
|
||||||
|
function WidgetList(props) {
|
||||||
|
return props.updateWidgets.map((item, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind} style={{ marginBottom: "5px" }}>
|
||||||
|
<div
|
||||||
|
className="widgets"
|
||||||
|
onClick={() => {
|
||||||
|
props.addPositionOfSignature &&
|
||||||
|
props.addPositionOfSignature("onclick", item);
|
||||||
|
}}
|
||||||
|
ref={(element) => {
|
||||||
|
if (!props.isMobile) {
|
||||||
|
item.ref(element);
|
||||||
|
if (element) {
|
||||||
|
if (props?.signRef) {
|
||||||
|
props.signRef.current = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMouseMove={props?.handleDivClick}
|
||||||
|
onMouseDown={() => {
|
||||||
|
props?.handleMouseLeave();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.ref && getWidgetType(item, props?.marginLeft)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WidgetList;
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import "../../styles/AddUser.css";
|
||||||
|
import RegexParser from "regex-parser";
|
||||||
|
import { textInputWidget } from "../../constant/Utils";
|
||||||
|
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||||
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
|
import { isEnableSubscription } from "../../constant/const";
|
||||||
|
|
||||||
|
const WidgetNameModal = (props) => {
|
||||||
|
const [formdata, setFormdata] = useState({
|
||||||
|
name: "",
|
||||||
|
defaultValue: "",
|
||||||
|
status: "required",
|
||||||
|
hint: "",
|
||||||
|
textvalidate: "text"
|
||||||
|
});
|
||||||
|
const [isValid, setIsValid] = useState(true);
|
||||||
|
const statusArr = ["Required", "Optional"];
|
||||||
|
const inputOpt = ["text", "email", "number"];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.defaultdata) {
|
||||||
|
setFormdata({
|
||||||
|
name: props.defaultdata?.options?.name || props?.widgetName || "",
|
||||||
|
defaultValue: props.defaultdata?.options?.defaultValue || "",
|
||||||
|
status: props.defaultdata?.options?.status || "required",
|
||||||
|
hint: props.defaultdata?.options?.hint || "",
|
||||||
|
textvalidate:
|
||||||
|
props.defaultdata?.options?.validation?.type === "regex"
|
||||||
|
? props.defaultdata?.options?.validation?.pattern
|
||||||
|
: props.defaultdata?.options?.validation?.type || ""
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setFormdata({
|
||||||
|
...formdata,
|
||||||
|
name: props.defaultdata?.options?.name || props?.widgetName || ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [props.defaultdata, props.widgetName]);
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (props.handleData) {
|
||||||
|
props.handleData(formdata);
|
||||||
|
setFormdata({
|
||||||
|
name: "",
|
||||||
|
defaultValue: "",
|
||||||
|
status: "required",
|
||||||
|
hint: "",
|
||||||
|
textvalidate: "text"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleChange = (e) => {
|
||||||
|
setFormdata({ ...formdata, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handledefaultChange = (e) => {
|
||||||
|
if (formdata.textvalidate) {
|
||||||
|
const regexObject = RegexParser(handleValidation(formdata.textvalidate));
|
||||||
|
const isValidate = regexObject?.test(e.target.value);
|
||||||
|
setIsValid(isValidate);
|
||||||
|
} else {
|
||||||
|
setIsValid(true);
|
||||||
|
}
|
||||||
|
setFormdata({ ...formdata, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleValidation(type) {
|
||||||
|
switch (type) {
|
||||||
|
case "email":
|
||||||
|
return "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/";
|
||||||
|
case "number":
|
||||||
|
return "/^\\d+$/";
|
||||||
|
case "text":
|
||||||
|
return "/^[a-zA-Zs]+$/";
|
||||||
|
default:
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBlurRegex() {
|
||||||
|
if (!formdata.textvalidate) {
|
||||||
|
setFormdata({ ...formdata, textvalidate: "text" });
|
||||||
|
} else {
|
||||||
|
if (formdata.defaultValue) {
|
||||||
|
const regexObject = RegexParser(
|
||||||
|
handleValidation(formdata.textvalidate)
|
||||||
|
);
|
||||||
|
const isValidate = regexObject?.test(formdata.defaultValue);
|
||||||
|
if (isValidate === false) {
|
||||||
|
setFormdata({ ...formdata, defaultValue: "" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ModalUi
|
||||||
|
isOpen={props.isOpen}
|
||||||
|
handleClose={props.handleClose && props.handleClose}
|
||||||
|
title={"Widget info"}
|
||||||
|
>
|
||||||
|
{(props.defaultdata?.type === textInputWidget ||
|
||||||
|
props.widgetName === textInputWidget) &&
|
||||||
|
!isEnableSubscription && (
|
||||||
|
<PremiumAlertHeader
|
||||||
|
message={
|
||||||
|
"Field validations are free in beta, this feature will incur a fee later."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className={`${
|
||||||
|
props.defaultdata?.type === textInputWidget ||
|
||||||
|
props.widgetName === textInputWidget
|
||||||
|
? "pt-0"
|
||||||
|
: ""
|
||||||
|
} p-[20px]`}
|
||||||
|
>
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||||
|
Name
|
||||||
|
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="addUserInput"
|
||||||
|
name="name"
|
||||||
|
value={formdata.name}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{(props.defaultdata?.type === textInputWidget ||
|
||||||
|
props.widgetName === textInputWidget) && (
|
||||||
|
<>
|
||||||
|
<div className="form-section">
|
||||||
|
<label
|
||||||
|
htmlFor="textvalidate"
|
||||||
|
className={
|
||||||
|
!props.isSubscribe && isEnableSubscription && "disabled"
|
||||||
|
}
|
||||||
|
style={{ fontSize: 13 }}
|
||||||
|
>
|
||||||
|
Validation
|
||||||
|
</label>
|
||||||
|
{!props.isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
!props.isSubscribe && isEnableSubscription && "disabled"
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
marginBottom: "0.5rem"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: "100%", position: "relative" }}>
|
||||||
|
<input
|
||||||
|
className="relative z-20 w-[87%] md:w-[92%] p-2.5 border-[1px] border-[#d1d5db] rounded-l-md outline-none text-xs"
|
||||||
|
name="textvalidate"
|
||||||
|
placeholder="Enter custom expression"
|
||||||
|
value={formdata.textvalidate}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
// onBlur={() => handleBlurRegex()}
|
||||||
|
/>
|
||||||
|
<select
|
||||||
|
className="validationlist addUserInput"
|
||||||
|
name="textvalidate"
|
||||||
|
value={formdata.textvalidate}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
onBlur={() => handleBlurRegex()}
|
||||||
|
>
|
||||||
|
<option disabled style={{ fontSize: "13px" }}>
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{inputOpt.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<option
|
||||||
|
style={{ fontSize: "13px" }}
|
||||||
|
key={ind}
|
||||||
|
value={data}
|
||||||
|
>
|
||||||
|
{data}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||||
|
Default value
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="addUserInput"
|
||||||
|
name="defaultValue"
|
||||||
|
value={formdata.defaultValue}
|
||||||
|
onChange={(e) => handledefaultChange(e)}
|
||||||
|
autoComplete="off"
|
||||||
|
onBlur={() => {
|
||||||
|
if (isValid === false) {
|
||||||
|
setFormdata({ ...formdata, defaultValue: "" });
|
||||||
|
setIsValid(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isValid === false && (
|
||||||
|
<div
|
||||||
|
className="warning defaultvalueWarning"
|
||||||
|
style={{ fontSize: 12 }}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fas fa-exclamation-circle"
|
||||||
|
style={{ color: "#fab005", fontSize: 15 }}
|
||||||
|
></i>{" "}
|
||||||
|
invalid default value
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="form-section">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
marginBottom: "0.5rem"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{statusArr.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={ind}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 5,
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style={{ accentColor: "red", marginRight: "10px" }}
|
||||||
|
type="radio"
|
||||||
|
name="status"
|
||||||
|
onChange={() =>
|
||||||
|
setFormdata({ ...formdata, status: data.toLowerCase() })
|
||||||
|
}
|
||||||
|
checked={
|
||||||
|
formdata.status.toLowerCase() === data.toLowerCase()
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: "13px", fontWeight: "500" }}>
|
||||||
|
{data}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{(props.defaultdata?.type === textInputWidget ||
|
||||||
|
props?.widgetName === textInputWidget) && (
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="hint" style={{ fontSize: 13 }}>
|
||||||
|
Hint
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="addUserInput"
|
||||||
|
name="hint"
|
||||||
|
value={formdata.hint}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: "#b7b3b3",
|
||||||
|
width: "100%",
|
||||||
|
marginBottom: "16px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
padding: "5px 20px",
|
||||||
|
backgroundColor: "#32a3ac"
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
className="finishBtn"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WidgetNameModal;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Alert from "../../primitives/Alert";
|
import Alert from "../../../primitives/Alert";
|
||||||
|
|
||||||
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
||||||
const folderPtr = {
|
const folderPtr = {
|
||||||
@@ -11,6 +11,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [folderList, setFolderList] = useState([]);
|
const [folderList, setFolderList] = useState([]);
|
||||||
const [isAlert, setIsAlert] = useState(false);
|
const [isAlert, setIsAlert] = useState(false);
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
const [selectedParent, setSelectedParent] = useState();
|
const [selectedParent, setSelectedParent] = useState();
|
||||||
const [alert, setAlert] = useState({ type: "info", message: "" });
|
const [alert, setAlert] = useState({ type: "info", message: "" });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -42,6 +43,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
};
|
};
|
||||||
const handleCreateFolder = async (event) => {
|
const handleCreateFolder = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
handleLoader(true);
|
||||||
if (name) {
|
if (name) {
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
const exsitQuery = new Parse.Query(folderCls);
|
const exsitQuery = new Parse.Query(folderCls);
|
||||||
@@ -52,7 +54,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
const templExist = await exsitQuery.first();
|
const templExist = await exsitQuery.first();
|
||||||
if (templExist) {
|
if (templExist) {
|
||||||
setAlert({ type: "dange", message: "Folder already exist!" });
|
setAlert({ type: "danger", message: "Folder already exist!" });
|
||||||
setIsAlert(true);
|
setIsAlert(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsAlert(false);
|
setIsAlert(false);
|
||||||
@@ -74,6 +76,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||||
const res = await template.save();
|
const res = await template.save();
|
||||||
if (res) {
|
if (res) {
|
||||||
|
handleLoader(false);
|
||||||
setAlert({
|
setAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
message: "Folder created successfully!"
|
message: "Folder created successfully!"
|
||||||
@@ -88,6 +91,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
handleLoader(false);
|
||||||
setAlert({ type: "info", message: "Please fill folder name" });
|
setAlert({ type: "info", message: "Please fill folder name" });
|
||||||
setIsAlert(true);
|
setIsAlert(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -98,10 +102,21 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
const handleOptions = (e) => {
|
const handleOptions = (e) => {
|
||||||
setSelectedParent(e.target.value);
|
setSelectedParent(e.target.value);
|
||||||
};
|
};
|
||||||
|
const handleLoader = (status) => {
|
||||||
|
setIsLoader(status);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
|
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
|
||||||
<div id="createFolder">
|
<div id="createFolder" className="relative">
|
||||||
|
{isLoader && (
|
||||||
|
<div className="absolute h-full w-full flex justify-center items-center ">
|
||||||
|
<div
|
||||||
|
style={{ fontSize: "45px", color: "#3dd3e0" }}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<h1 className="text-base font-semibold">Create Folder</h1>
|
<h1 className="text-base font-semibold">Create Folder</h1>
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
@@ -133,6 +148,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
onClick={handleCreateFolder}
|
onClick={handleCreateFolder}
|
||||||
|
disabled={isLoader}
|
||||||
className="flex items-center rounded p-2 bg-[#32a3ac] text-white mt-3"
|
className="flex items-center rounded p-2 bg-[#32a3ac] text-white mt-3"
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-plus mr-1"></i>
|
<i className="fa-solid fa-plus mr-1"></i>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useMemo } from "react";
|
import React, { useCallback, useMemo } from "react";
|
||||||
import { useDropScript } from "../../hook/useScript";
|
import { useDropScript } from "../../../hook/useScript";
|
||||||
|
|
||||||
const DROPBOX_APP_KEY = process.env.REACT_APP_DROPBOX_API_KEY; // App key
|
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_SDK_URL = "https://www.dropbox.com/static/api/2/dropins.js";
|
||||||
@@ -41,12 +41,15 @@ export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
|||||||
[onSuccess, onCancel]
|
[onSuccess, onCancel]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChoose = useCallback((e) => {
|
const handleChoose = useCallback(
|
||||||
e.preventDefault()
|
(e) => {
|
||||||
if (window.Dropbox) {
|
e.preventDefault();
|
||||||
window.Dropbox.choose(options);
|
if (window.Dropbox) {
|
||||||
}
|
window.Dropbox.choose(options);
|
||||||
}, [options]);
|
}
|
||||||
|
},
|
||||||
|
[options]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={handleChoose}>
|
<div onClick={handleChoose}>
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Parse from "parse";
|
||||||
|
import CreateFolder from "./CreateFolder";
|
||||||
|
import ModalUi from "../../../primitives/ModalUi";
|
||||||
|
|
||||||
|
const FolderModal = (props) => {
|
||||||
|
const [clickFolder, setClickFolder] = useState("");
|
||||||
|
const [folderList, setFolderList] = useState([]);
|
||||||
|
const [tabList, setTabList] = useState([]);
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
|
const [isAdd, setIsAdd] = useState(false);
|
||||||
|
// below useEffect is called when user open popup
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isOpenModal) {
|
||||||
|
fetchFolder();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [props.isOpenModal]);
|
||||||
|
|
||||||
|
// `fetchFolder` is used to fetch of folder list created by user on basis of folderPtr or without folderPtr
|
||||||
|
const fetchFolder = async (folderPtr) => {
|
||||||
|
setIsLoader(true);
|
||||||
|
try {
|
||||||
|
const FolderQuery = new Parse.Query(props.folderCls);
|
||||||
|
if (folderPtr) {
|
||||||
|
FolderQuery.equalTo("Folder", folderPtr);
|
||||||
|
FolderQuery.equalTo("Type", "Folder");
|
||||||
|
} else {
|
||||||
|
FolderQuery.doesNotExist("Folder");
|
||||||
|
FolderQuery.equalTo("Type", "Folder");
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await FolderQuery.find();
|
||||||
|
if (res) {
|
||||||
|
const result = JSON.parse(JSON.stringify(res));
|
||||||
|
if (result) {
|
||||||
|
setFolderList(result);
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleSelect` is used to save pointer of folder selected by user and it's path in state
|
||||||
|
const handleSelect = (item) => {
|
||||||
|
setFolderList([]);
|
||||||
|
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
|
||||||
|
if (tabList.length > 0) {
|
||||||
|
const tab = tabList.some((x) => x.objectId === item.objectId);
|
||||||
|
if (!tab) {
|
||||||
|
setTabList((tabs) => [...tabs, item]);
|
||||||
|
const folderPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: props.folderCls,
|
||||||
|
objectId: item.objectId
|
||||||
|
};
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTabList((tabs) => [...tabs, item]);
|
||||||
|
const folderPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: props.folderCls,
|
||||||
|
objectId: item.objectId
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleSubmit` is used to pass folderPtr to parent component
|
||||||
|
const handleSubmit = () => {
|
||||||
|
let url = "OpenSign™ Drive";
|
||||||
|
tabList.forEach((t) => {
|
||||||
|
url = url + " / " + t.Name;
|
||||||
|
});
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess(clickFolder);
|
||||||
|
}
|
||||||
|
// SetIsOpen(false);
|
||||||
|
props.setIsOpenMoveModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleCancel` is used to clear list of folder, close popup and folderUrl
|
||||||
|
const handleCancel = () => {
|
||||||
|
// SetIsOpen(false);
|
||||||
|
props.setIsOpenMoveModal(false);
|
||||||
|
setClickFolder({});
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleCancel` is call when user click on folder name from path/tab in popup
|
||||||
|
const removeTabListItem = async (e, i) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// setEditable(false);
|
||||||
|
if (!isAdd) {
|
||||||
|
setIsLoader(true);
|
||||||
|
let folderPtr;
|
||||||
|
if (i) {
|
||||||
|
setFolderList([]);
|
||||||
|
let list = tabList.filter((itm, j) => {
|
||||||
|
if (j <= i) {
|
||||||
|
return itm;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let _len = list.length - 1;
|
||||||
|
folderPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: props.folderCls,
|
||||||
|
objectId: list[_len].objectId
|
||||||
|
};
|
||||||
|
setTabList(list);
|
||||||
|
} else {
|
||||||
|
setClickFolder({});
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
}
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// `handleCreate` is used to open folder creation form in popup
|
||||||
|
const handleCreate = () => {
|
||||||
|
setIsAdd(!isAdd);
|
||||||
|
};
|
||||||
|
// `handleAddFolder` is call when user folder created successfully and it fetch folder list on the basis of folderPtr or without folderPtr
|
||||||
|
const handleAddFolder = (newFolder) => {
|
||||||
|
props.setPdfData((prev) => [...prev, newFolder?.toJSON()]);
|
||||||
|
if (clickFolder && clickFolder.ObjectId) {
|
||||||
|
fetchFolder({
|
||||||
|
__type: "Pointer",
|
||||||
|
className: props.folderCls,
|
||||||
|
objectId: clickFolder.ObjectId
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fetchFolder();
|
||||||
|
}
|
||||||
|
handleCreate();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="text-xs mt-2 ">
|
||||||
|
<ModalUi
|
||||||
|
title={"Select Folder"}
|
||||||
|
isOpen={props.isOpenModal}
|
||||||
|
handleClose={handleCancel}
|
||||||
|
>
|
||||||
|
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
|
||||||
|
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
|
||||||
|
<span
|
||||||
|
className="cursor-pointer"
|
||||||
|
title="OpenSign™ Drive"
|
||||||
|
onClick={(e) => removeTabListItem(e)}
|
||||||
|
>
|
||||||
|
OpenSign™ Drive /{" "}
|
||||||
|
</span>
|
||||||
|
{tabList &&
|
||||||
|
tabList.map((tab, i) => (
|
||||||
|
<React.Fragment key={`${tab.objectId}-${i}`}>
|
||||||
|
<span
|
||||||
|
className="cursor-pointer"
|
||||||
|
title={tab.Name}
|
||||||
|
onClick={(e) => removeTabListItem(e, i)}
|
||||||
|
>
|
||||||
|
{tab.Name}
|
||||||
|
</span>
|
||||||
|
{" / "}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 mb-3">
|
||||||
|
<div className="max-h-[210px] overflow-auto">
|
||||||
|
{!isAdd &&
|
||||||
|
folderList.length > 0 &&
|
||||||
|
folderList.map((folder) => (
|
||||||
|
<div
|
||||||
|
key={folder.Name}
|
||||||
|
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer "
|
||||||
|
onClick={() => handleSelect(folder)}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<i
|
||||||
|
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span className="font-semibold">{folder.Name}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{isAdd && (
|
||||||
|
<CreateFolder
|
||||||
|
parentFolderId={clickFolder && clickFolder.ObjectId}
|
||||||
|
folderCls={props.folderCls}
|
||||||
|
onSuccess={handleAddFolder}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isLoader && (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
||||||
|
<div
|
||||||
|
className="text-[30px] cursor-pointer text-[#32a3ac]"
|
||||||
|
title="Save Here"
|
||||||
|
onClick={handleCreate}
|
||||||
|
>
|
||||||
|
{isAdd ? (
|
||||||
|
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
|
||||||
|
) : (
|
||||||
|
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="text-[30px] cursor-pointer"
|
||||||
|
title="Save Here"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
<i className="fas fa-save" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FolderModal;
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import CreateFolder from "./CreateFolder";
|
import CreateFolder from "./CreateFolder";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../../primitives/ModalUi";
|
||||||
|
import Tooltip from "../../../primitives/Tooltip";
|
||||||
|
|
||||||
const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||||
const [isOpen, SetIsOpen] = useState(false);
|
const [isOpen, SetIsOpen] = useState(false);
|
||||||
const [clickFolder, setClickFolder] = useState("");
|
const [clickFolder, setClickFolder] = useState("");
|
||||||
const [selectFolder, setSelectedFolder] = useState({});
|
const [selectFolder, setSelectedFolder] = useState({});
|
||||||
@@ -22,6 +23,21 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
// below useEffect is used to reset folder selection if user pass isReset = true from parent component
|
||||||
|
useEffect(() => {
|
||||||
|
if (isReset == true) {
|
||||||
|
handleReset();
|
||||||
|
}
|
||||||
|
}, [isReset]);
|
||||||
|
const handleReset = () => {
|
||||||
|
setFolderPath({});
|
||||||
|
setSelectedFolder("");
|
||||||
|
setClickFolder("");
|
||||||
|
setIsAdd(false);
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
};
|
||||||
|
// `fetchFolder` is used to fetch of folder list created by user on basis of folderPtr or without folderPtr
|
||||||
const fetchFolder = async (folderPtr) => {
|
const fetchFolder = async (folderPtr) => {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
try {
|
try {
|
||||||
@@ -47,6 +63,8 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleSelect` is used to save pointer of folder selected by user and it's path in state
|
||||||
const handleSelect = (item) => {
|
const handleSelect = (item) => {
|
||||||
setFolderList([]);
|
setFolderList([]);
|
||||||
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
|
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
|
||||||
@@ -73,8 +91,9 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleSubmit` is used to pass folderPtr to parent component
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
let url = "Root";
|
let url = "OpenSign™ Drive";
|
||||||
tabList.forEach((t) => {
|
tabList.forEach((t) => {
|
||||||
url = url + " / " + t.Name;
|
url = url + " / " + t.Name;
|
||||||
});
|
});
|
||||||
@@ -85,6 +104,8 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
SetIsOpen(false);
|
SetIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleCancel` is used to clear list of folder, close popup and folderUrl
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
SetIsOpen(false);
|
SetIsOpen(false);
|
||||||
setClickFolder({});
|
setClickFolder({});
|
||||||
@@ -92,6 +113,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
setTabList([]);
|
setTabList([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleCancel` is call when user click on folder name from path/tab in popup
|
||||||
const removeTabListItem = async (e, i) => {
|
const removeTabListItem = async (e, i) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// setEditable(false);
|
// setEditable(false);
|
||||||
@@ -121,9 +143,11 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
fetchFolder(folderPtr);
|
fetchFolder(folderPtr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// `handleCreate` is used to open folder creation form in popup
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
setIsAdd(!isAdd);
|
setIsAdd(!isAdd);
|
||||||
};
|
};
|
||||||
|
// `handleAddFolder` is call when user folder created successfully and it fetch folder list on the basis of folderPtr or without folderPtr
|
||||||
const handleAddFolder = () => {
|
const handleAddFolder = () => {
|
||||||
setFolderList([]);
|
setFolderList([]);
|
||||||
if (clickFolder && clickFolder.ObjectId) {
|
if (clickFolder && clickFolder.ObjectId) {
|
||||||
@@ -145,7 +169,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
{required && <span className="text-red-500 text-[13px]">*</span>}
|
{required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
|
<div className="relative rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
|
||||||
<div>
|
<div>
|
||||||
<i
|
<i
|
||||||
className="far fa-folder-open text-[40px] text-[#33bbff]"
|
className="far fa-folder-open text-[40px] text-[#33bbff]"
|
||||||
@@ -156,7 +180,9 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
<div className="font-semibold ">
|
<div className="font-semibold ">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<p>
|
<p>
|
||||||
{selectFolder && selectFolder.Name ? selectFolder.Name : "Root"}
|
{selectFolder && selectFolder.Name
|
||||||
|
? selectFolder.Name
|
||||||
|
: "OpenSign™ Drive"}
|
||||||
</p>
|
</p>
|
||||||
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
|
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
|
||||||
<i
|
<i
|
||||||
@@ -170,20 +196,27 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
|
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="absolute top-2 right-1 cursor-pointer">
|
||||||
|
<Tooltip
|
||||||
|
message={
|
||||||
|
"If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Select Folder"}
|
title={"Select Folder"}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
handleClose={handleCancel}
|
handleClose={handleCancel}
|
||||||
>
|
>
|
||||||
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
|
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
|
||||||
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
|
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
|
||||||
<span
|
<span
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
title="Root"
|
title="OpenSign™ Drive"
|
||||||
onClick={(e) => removeTabListItem(e)}
|
onClick={(e) => removeTabListItem(e)}
|
||||||
>
|
>
|
||||||
Root /{" "}
|
OpenSign™ Drive /{" "}
|
||||||
</span>
|
</span>
|
||||||
{tabList &&
|
{tabList &&
|
||||||
tabList.map((tab, i) => (
|
tabList.map((tab, i) => (
|
||||||
@@ -201,23 +234,25 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 mb-3">
|
<div className="mt-2 mb-3">
|
||||||
{!isAdd &&
|
<div className="max-h-[210px] overflow-auto">
|
||||||
folderList.length > 0 &&
|
{!isAdd &&
|
||||||
folderList.map((folder) => (
|
folderList.length > 0 &&
|
||||||
<div
|
folderList.map((folder) => (
|
||||||
key={folder.Name}
|
<div
|
||||||
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer"
|
key={folder.Name}
|
||||||
onClick={() => handleSelect(folder)}
|
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer "
|
||||||
>
|
onClick={() => handleSelect(folder)}
|
||||||
<div className="flex items-center gap-2">
|
>
|
||||||
<i
|
<div className="flex items-center gap-2">
|
||||||
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
|
<i
|
||||||
aria-hidden="true"
|
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
|
||||||
></i>
|
aria-hidden="true"
|
||||||
<span className="font-semibold">{folder.Name}</span>
|
></i>
|
||||||
|
<span className="font-semibold">{folder.Name}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
{isAdd && (
|
{isAdd && (
|
||||||
<CreateFolder
|
<CreateFolder
|
||||||
parentFolderId={clickFolder && clickFolder.ObjectId}
|
parentFolderId={clickFolder && clickFolder.ObjectId}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import "../css/AddUser.css";
|
import "../../../styles/AddUser.css";
|
||||||
import AsyncSelect from "react-select/async";
|
import AsyncSelect from "react-select/async";
|
||||||
|
|
||||||
const customStyles = {
|
const customStyles = {
|
||||||
@@ -17,12 +17,7 @@ const SelectSigners = (props) => {
|
|||||||
const [userList, setUserList] = useState([]);
|
const [userList, setUserList] = useState([]);
|
||||||
const [selected, setSelected] = useState();
|
const [selected, setSelected] = useState();
|
||||||
const [userData, setUserData] = useState({});
|
const [userData, setUserData] = useState({});
|
||||||
const [isError, setIsError]= useState(false)
|
const [isError, setIsError] = useState(false);
|
||||||
const parseBaseUrl = localStorage.getItem("baseUrl");
|
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
|
|
||||||
// `handleOptions` is used to set just save from quick form to selected option in dropdown
|
// `handleOptions` is used to set just save from quick form to selected option in dropdown
|
||||||
const handleOptions = (item) => {
|
const handleOptions = (item) => {
|
||||||
setSelected(item);
|
setSelected(item);
|
||||||
@@ -32,14 +27,14 @@ const SelectSigners = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
if(userData && userData.objectId){
|
if (userData && userData.objectId) {
|
||||||
props.details(userData);
|
props.details(userData);
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
setIsError(true)
|
setIsError(true);
|
||||||
setTimeout(()=> setIsError(false), 1000)
|
setTimeout(() => setIsError(false), 1000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,8 +68,8 @@ const SelectSigners = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="addusercontainer">
|
<div className="addusercontainer">
|
||||||
<div className="form-wrapper">
|
<div className="form-wrapper">
|
||||||
<div className="form-section" style={{marginBottom: 0}}>
|
<div className="form-section" style={{ marginBottom: 0 }}>
|
||||||
<label style={{ fontSize: 14 , fontWeight: "700"}}>Choose User</label>
|
<label style={{ fontSize: 14, fontWeight: "700" }}>Choose User</label>
|
||||||
<AsyncSelect
|
<AsyncSelect
|
||||||
cacheOptions
|
cacheOptions
|
||||||
defaultOptions
|
defaultOptions
|
||||||
@@ -86,7 +81,15 @@ const SelectSigners = (props) => {
|
|||||||
styles={customStyles}
|
styles={customStyles}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isError ? <p style={{color:'red', fontSize: "12px", margin:"5px"}}>Please select signer</p>: <p style={{color:'transparent', fontSize: "12px", margin:"5px"}}>.</p>}
|
{isError ? (
|
||||||
|
<p style={{ color: "red", fontSize: "12px", margin: "5px" }}>
|
||||||
|
Please select signer
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p style={{ color: "transparent", fontSize: "12px", margin: "5px" }}>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<button className="submitbutton" onClick={() => handleAdd()}>
|
<button className="submitbutton" onClick={() => handleAdd()}>
|
||||||
Submit
|
Submit
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Select from "react-select";
|
import Select from "react-select";
|
||||||
import AppendFormInForm from "../AppendFormInForm";
|
import AddSigner from "../../AddSigner";
|
||||||
import Modal from "react-modal";
|
import Modal from "react-modal";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
|
import Tooltip from "../../../primitives/Tooltip";
|
||||||
function arrayMove(array, from, to) {
|
function arrayMove(array, from, to) {
|
||||||
array = array.slice();
|
array = array.slice();
|
||||||
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
||||||
@@ -19,7 +20,7 @@ const SignersInput = (props) => {
|
|||||||
Modal.setAppElement("body");
|
Modal.setAppElement("body");
|
||||||
const [state, setState] = useState(undefined);
|
const [state, setState] = useState(undefined);
|
||||||
// const [editFormData, setEditFormData] = useState([]);
|
// const [editFormData, setEditFormData] = useState([]);
|
||||||
const [selected, setSelected] = React.useState([]);
|
const [selected, setSelected] = useState([]);
|
||||||
const [isModal, setIsModel] = useState(false);
|
const [isModal, setIsModel] = useState(false);
|
||||||
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
||||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
@@ -63,6 +64,11 @@ const SignersInput = (props) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
GetSelectListData();
|
GetSelectListData();
|
||||||
}, []);
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isReset && props.isReset === true) {
|
||||||
|
setSelected([]);
|
||||||
|
}
|
||||||
|
}, [props.isReset]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selected && selected.length) {
|
if (selected && selected.length) {
|
||||||
@@ -99,9 +105,15 @@ const SignersInput = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-xs mt-2 ">
|
<div className="text-xs mt-2 ">
|
||||||
<label className="block">
|
<label className="block relative">
|
||||||
Signers
|
Signers
|
||||||
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
|
<span className="absolute ml-1 text-xs z-50">
|
||||||
|
<Tooltip
|
||||||
|
id={"signer-tooltip"}
|
||||||
|
message={"Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed."}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div style={{ display: "flex", gap: 5 }}>
|
<div style={{ display: "flex", gap: 5 }}>
|
||||||
<div style={{ flexWrap: "wrap", width: "100%" }}>
|
<div style={{ flexWrap: "wrap", width: "100%" }}>
|
||||||
@@ -172,7 +184,7 @@ const SignersInput = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isModal && (
|
{isModal && (
|
||||||
<AppendFormInForm
|
<AddSigner
|
||||||
valueKey={"objectId"}
|
valueKey={"objectId"}
|
||||||
displayKey={"Name"}
|
displayKey={"Name"}
|
||||||
details={handleNewDetails}
|
details={handleNewDetails}
|
||||||
@@ -2,20 +2,24 @@ import React from "react";
|
|||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
|
|
||||||
const Menu = ({ item, isOpen, closeSidebar }) => {
|
const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||||
return (
|
return (
|
||||||
<li key={item.title} role="none">
|
<li key={item.title} role="none">
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/${item.pageType}/${item.objectId}`}
|
to={
|
||||||
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4"
|
item.pageType
|
||||||
onClick={closeSidebar}
|
? `/${item.pageType}/${item.objectId}`
|
||||||
tabIndex={isOpen ? 0 : -1}
|
: `/${item.objectId}`
|
||||||
role="menuitem"
|
}
|
||||||
>
|
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer focus:text-[#0056b3] focus:bg-[#eef1f5]"
|
||||||
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
onClick={closeSidebar}
|
||||||
<span className="ml-3 lg:ml-4">{item.title}</span>
|
tabIndex={isOpen ? 0 : -1}
|
||||||
</NavLink>
|
role="menuitem"
|
||||||
</li>
|
>
|
||||||
)
|
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
||||||
}
|
<span className="ml-3 lg:ml-4">{item.title}</span>
|
||||||
|
</NavLink>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Menu;
|
export default Menu;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import Menu from './Menu';
|
import Menu from "./Menu";
|
||||||
import Submenu from "./SubMenu";
|
import Submenu from "./SubMenu";
|
||||||
import SocialMedia from './SocialMedia';
|
import SocialMedia from "./SocialMedia";
|
||||||
|
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import dp from "../../assets/images/dp.png";
|
import dp from "../../assets/images/dp.png";
|
||||||
@@ -20,16 +20,10 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const menuItem = async () => {
|
const menuItem = async () => {
|
||||||
const parseBaseUrl = localStorage.getItem("baseUrl");
|
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
var sideMenu = Parse.Object.extend("w_menu");
|
var sideMenu = Parse.Object.extend("w_menu");
|
||||||
var query = new Parse.Query(sideMenu);
|
var query = new Parse.Query(sideMenu);
|
||||||
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
|
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
|
||||||
|
|
||||||
const results = await query.first();
|
const results = await query.first();
|
||||||
const resultjson = results.toJSON();
|
const resultjson = results.toJSON();
|
||||||
let result = resultjson;
|
let result = resultjson;
|
||||||
@@ -37,7 +31,6 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Problem", e);
|
console.error("Problem", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -47,7 +40,11 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
|||||||
>
|
>
|
||||||
<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">
|
||||||
<img className="w-full h-full object-cover" src={image} alt="Profile" />
|
<img
|
||||||
|
className="w-full h-full object-cover"
|
||||||
|
src={image}
|
||||||
|
alt="Profile"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-[14px] font-bold">{username}</p>
|
<p className="text-[14px] font-bold">{username}</p>
|
||||||
@@ -57,14 +54,27 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav aria-label="OpenSign Sidebar Navigation">
|
<nav aria-label="OpenSign Sidebar Navigation">
|
||||||
<ul className="text-sm" role="menubar" aria-label="OpenSign Sidebar Navigation">
|
<ul
|
||||||
{menuList.map((item) => (
|
className="text-sm"
|
||||||
|
role="menubar"
|
||||||
|
aria-label="OpenSign Sidebar Navigation"
|
||||||
|
>
|
||||||
|
{menuList.map((item) =>
|
||||||
!item.children ? (
|
!item.children ? (
|
||||||
<Menu key={item.title} item={item} isOpen={isOpen} closeSidebar={closeSidebar} />
|
<Menu
|
||||||
|
key={item.title}
|
||||||
|
item={item}
|
||||||
|
isOpen={isOpen}
|
||||||
|
closeSidebar={closeSidebar}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Submenu key={item.title} item={item} closeSidebar={closeSidebar} />
|
<Submenu
|
||||||
|
key={item.title}
|
||||||
|
item={item}
|
||||||
|
closeSidebar={closeSidebar}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
))}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
|
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const Submenu = ({ item, closeSidebar }) => {
|
|||||||
<li role="none">
|
<li role="none">
|
||||||
<button
|
<button
|
||||||
onClick={toggleSubmenu}
|
onClick={toggleSubmenu}
|
||||||
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:ring-2 focus:ring-blue-600"
|
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:outline-none focus:text-[#0056b3] focus:bg-[#eef1f5]"
|
||||||
aria-expanded={submenuOpen}
|
aria-expanded={submenuOpen}
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-controls={`submenu-${title}`}
|
aria-controls={`submenu-${title}`}
|
||||||
@@ -22,8 +22,9 @@ const Submenu = ({ item, closeSidebar }) => {
|
|||||||
<div className="flex justify-between items-center w-full">
|
<div className="flex justify-between items-center w-full">
|
||||||
<span className="ml-3 lg:ml-4">{title}</span>
|
<span className="ml-3 lg:ml-4">{title}</span>
|
||||||
<i
|
<i
|
||||||
className={`${submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
|
className={`${
|
||||||
}`}
|
submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
|
||||||
|
}`}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,13 +34,20 @@ const Submenu = ({ item, closeSidebar }) => {
|
|||||||
{children.map((childItem) => (
|
{children.map((childItem) => (
|
||||||
<li key={childItem.title} role="none">
|
<li key={childItem.title} role="none">
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/${childItem.pageType}/${childItem.objectId}`}
|
to={
|
||||||
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white"
|
childItem.pageType
|
||||||
|
? `/${childItem.pageType}/${childItem.objectId}`
|
||||||
|
: `/${childItem.objectId}`
|
||||||
|
}
|
||||||
|
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white focus:text-[#0056b3] focus:bg-[#eef1f5] cursor-pointer"
|
||||||
onClick={closeSidebar}
|
onClick={closeSidebar}
|
||||||
role="menuitem"
|
role="menuitem"
|
||||||
tabIndex={submenuOpen ? 0 : -1}
|
tabIndex={submenuOpen ? 0 : -1}
|
||||||
>
|
>
|
||||||
<i className={`${childItem.icon} text-[18px]`} aria-hidden="true"></i>
|
<i
|
||||||
|
className={`${childItem.icon} text-[18px]`}
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
<span className="ml-3 lg:ml-4">{childItem.title}</span>
|
<span className="ml-3 lg:ml-4">{childItem.title}</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ export const appInfo = {
|
|||||||
appTitle: "contracts",
|
appTitle: "contracts",
|
||||||
applogo: logo,
|
applogo: logo,
|
||||||
appname: "contracts",
|
appname: "contracts",
|
||||||
baseurl: process.env.REACT_APP_SERVERURL,
|
appId: process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID : "opensign",
|
||||||
|
baseUrl: process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/api/app",
|
||||||
defaultRole: "contracts_User",
|
defaultRole: "contracts_User",
|
||||||
fbAppId: process.env.REACT_APP_FBAPPID
|
fbAppId: process.env.REACT_APP_FBAPPID
|
||||||
? `${process.env.REACT_APP_FBAPPID}`
|
? `${process.env.REACT_APP_FBAPPID}`
|
||||||
|
|||||||
@@ -7,3 +7,6 @@ export const submitBtn =
|
|||||||
"bg-[#32a3ac] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-4 focus:outline-none text-center";
|
"bg-[#32a3ac] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-4 focus:outline-none text-center";
|
||||||
export const modalSubmitBtnColor = "#17a2b8";
|
export const modalSubmitBtnColor = "#17a2b8";
|
||||||
export const modalCancelBtnColor = "white";
|
export const modalCancelBtnColor = "white";
|
||||||
|
export const themeColor = "#47a3ad";
|
||||||
|
export const iconColor = "#686968";
|
||||||
|
export const isEnableSubscription = process.env.REACT_APP_ENABLE_SUBSCRIPTION;
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Parse from "parse";
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const parseAppId = localStorage.getItem("AppID12");
|
const serverUrl = localStorage.getItem("baseUrl");
|
||||||
const serverUrl = localStorage.getItem("BaseUrl12");
|
|
||||||
Parse.serverURL = serverUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
|
|
||||||
export const SaveFileSize = async (size, imageUrl) => {
|
export const SaveFileSize = async (size, imageUrl, tenantId) => {
|
||||||
//checking server url and save file's size
|
//checking server url and save file's size
|
||||||
|
const tenantPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "partners_Tenant",
|
||||||
|
objectId: tenantId
|
||||||
|
};
|
||||||
|
const _tenantPtr = JSON.stringify(tenantPtr);
|
||||||
try {
|
try {
|
||||||
const response = await axios
|
const res = await axios.get(
|
||||||
.get(`${serverUrl}classes/partners_TenantCredits`, {
|
`${serverUrl}classes/partners_TenantCredits?where={"PartnersTenant":${_tenantPtr}}`,
|
||||||
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.then((result) => {
|
);
|
||||||
const res = result.data;
|
const response = res.data.results;
|
||||||
// console.log("res", res);
|
|
||||||
|
|
||||||
return res.results;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
|
||||||
let data;
|
let data;
|
||||||
// console.log("response", response);
|
// console.log("response", response);
|
||||||
if (response && response.length > 0) {
|
if (response && response.length > 0) {
|
||||||
@@ -33,69 +29,49 @@ export const SaveFileSize = async (size, imageUrl) => {
|
|||||||
? response[0].usedStorage + size
|
? response[0].usedStorage + size
|
||||||
: size
|
: size
|
||||||
};
|
};
|
||||||
await axios
|
await axios.put(
|
||||||
.put(
|
`${serverUrl}classes/partners_TenantCredits/${response[0].objectId}`,
|
||||||
`${serverUrl}classes/partners_TenantCredits/${response[0].objectId}`,
|
data,
|
||||||
data,
|
{
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
// const res = result.data;
|
|
||||||
// console.log("save res", res);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
data = {
|
|
||||||
usedStorage: size
|
|
||||||
};
|
|
||||||
await axios
|
|
||||||
.post(`${serverUrl}classes/partners_TenantCredits`, data, {
|
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.then(() => {
|
);
|
||||||
// const res = result.data;
|
} else {
|
||||||
// console.log("res", res);
|
data = { usedStorage: size, PartnersTenant: tenantPtr };
|
||||||
})
|
await axios.post(`${serverUrl}classes/partners_TenantCredits`, data, {
|
||||||
.catch((err) => {
|
headers: {
|
||||||
console.log("axois err ", err);
|
"Content-Type": "application/json",
|
||||||
});
|
"X-Parse-Application-Id": parseAppId
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (err) {
|
||||||
console.log("org app error", e);
|
console.log("err in save usage", err);
|
||||||
}
|
}
|
||||||
saveDataFile(size, imageUrl);
|
saveDataFile(size, imageUrl, tenantPtr);
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for save fileUrl and file size in particular client db class partners_DataFiles
|
//function for save fileUrl and file size in particular client db class partners_DataFiles
|
||||||
const saveDataFile = async (size, imageUrl) => {
|
const saveDataFile = async (size, imageUrl, tenantPtr) => {
|
||||||
const data = {
|
const data = {
|
||||||
FileUrl: imageUrl,
|
FileUrl: imageUrl,
|
||||||
FileSize: size
|
FileSize: size,
|
||||||
|
TenantPtr: tenantPtr
|
||||||
};
|
};
|
||||||
|
|
||||||
// console.log("data save",file, data)
|
// console.log("data save",file, data)
|
||||||
await axios
|
try {
|
||||||
.post(`${serverUrl}classes/partners_DataFiles`, data, {
|
await axios.post(`${serverUrl}classes/partners_DataFiles`, data, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// const res = result.data;
|
|
||||||
// console.log("res", res);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in save usage ", err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1 +1,71 @@
|
|||||||
import("./Bootstrap");
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import "./index.css";
|
||||||
|
import App from "./App";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
import { store } from "./redux/store";
|
||||||
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
|
import { TouchBackend } from "react-dnd-touch-backend";
|
||||||
|
import {
|
||||||
|
DndProvider,
|
||||||
|
TouchTransition,
|
||||||
|
MouseTransition,
|
||||||
|
Preview
|
||||||
|
} from "react-dnd-multi-backend";
|
||||||
|
import DragElement from "./components/pdf/DragElement";
|
||||||
|
import TagManager from "react-gtm-module";
|
||||||
|
import Parse from "parse";
|
||||||
|
const appId = process.env.REACT_APP_APPID
|
||||||
|
? process.env.REACT_APP_APPID
|
||||||
|
: "opensign";
|
||||||
|
const serverUrl = process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/api/app";
|
||||||
|
Parse.initialize(appId);
|
||||||
|
Parse.serverURL = serverUrl;
|
||||||
|
|
||||||
|
const HTML5toTouch = {
|
||||||
|
backends: [
|
||||||
|
{
|
||||||
|
id: "html5",
|
||||||
|
backend: HTML5Backend,
|
||||||
|
transition: MouseTransition
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "touch",
|
||||||
|
backend: TouchBackend,
|
||||||
|
options: { enableMouseEvents: true },
|
||||||
|
preview: true,
|
||||||
|
transition: TouchTransition
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const generatePreview = (props) => {
|
||||||
|
const { item, style } = props;
|
||||||
|
const newStyle = {
|
||||||
|
...style
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={newStyle}>
|
||||||
|
<DragElement {...item} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.REACT_APP_GTM) {
|
||||||
|
const tagManagerArgs = {
|
||||||
|
gtmId: process.env.REACT_APP_GTM
|
||||||
|
};
|
||||||
|
TagManager.initialize(tagManagerArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||||
|
root.render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<DndProvider options={HTML5toTouch}>
|
||||||
|
<Preview>{generatePreview}</Preview>
|
||||||
|
<App />
|
||||||
|
</DndProvider>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa fa-plus",
|
||||||
redirectUrl:
|
redirectUrl: "draftDocument"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg: "These are documents you have started but have not finalized for sending."
|
||||||
};
|
};
|
||||||
// Need your sign report
|
// Need your sign report
|
||||||
case "4Hhwbp482K":
|
case "4Hhwbp482K":
|
||||||
@@ -32,10 +32,11 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#3ac9d6",
|
btnColor: "#3ac9d6",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "pdfRequestFiles"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg:
|
||||||
|
"This is a list of documents that are waiting for your signature"
|
||||||
};
|
};
|
||||||
// In progess report
|
// In progess report
|
||||||
case "1MwEuxLEkF":
|
case "1MwEuxLEkF":
|
||||||
@@ -48,10 +49,11 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#3ac9d6",
|
btnColor: "#3ac9d6",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "pdfRequestFiles"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg:
|
||||||
|
"This is a list of documents you've sent to other parties for signature."
|
||||||
};
|
};
|
||||||
// completed documents report
|
// completed documents report
|
||||||
case "kQUoW4hUXz":
|
case "kQUoW4hUXz":
|
||||||
@@ -64,10 +66,10 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "draftDocument"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg: "This is a list of documents that have been signed by all parties."
|
||||||
};
|
};
|
||||||
// declined documents report
|
// declined documents report
|
||||||
case "UPr2Fm5WY3":
|
case "UPr2Fm5WY3":
|
||||||
@@ -80,10 +82,10 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "draftDocument"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg: "This is a list of documents that have been declined by one of the signers."
|
||||||
};
|
};
|
||||||
// Expired Documents report
|
// Expired Documents report
|
||||||
case "zNqBHXHsYH":
|
case "zNqBHXHsYH":
|
||||||
@@ -96,10 +98,10 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "draftDocument"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg: "This is a list of documents that have reached their expiration date."
|
||||||
};
|
};
|
||||||
// Recently sent for signatures report show on dashboard
|
// Recently sent for signatures report show on dashboard
|
||||||
case "d9k3UfYHBc":
|
case "d9k3UfYHBc":
|
||||||
@@ -112,8 +114,7 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "pdfRequestFiles"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -128,8 +129,7 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl:
|
redirectUrl: "pdfRequestFiles"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -144,8 +144,7 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa fa-plus",
|
||||||
redirectUrl:
|
redirectUrl: "draftDocument"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -162,7 +161,8 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-solid fa-trash"
|
btnIcon: "fa-solid fa-trash"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
form: "ContactBook"
|
form: "ContactBook",
|
||||||
|
helpMsg: "This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document."
|
||||||
};
|
};
|
||||||
// template report
|
// template report
|
||||||
case "6TeaPr321t":
|
case "6TeaPr321t":
|
||||||
@@ -175,18 +175,18 @@ export default function reportJson(id) {
|
|||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa fa-plus",
|
||||||
redirectUrl:
|
redirectUrl: "placeHolderSign"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/placeHolderSign"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
btnLabel: "Edit",
|
btnLabel: "Edit",
|
||||||
btnColor: "#00c9d5",
|
btnColor: "#00c9d5",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa fa-plus",
|
||||||
redirectUrl:
|
redirectUrl: "template"
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/template"
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
helpMsg:
|
||||||
|
"This is a list of templates that are available to you for creating documents. You can click the 'use' button to create a new document using a template, modify the document & add signers in the next step."
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,65 +1,70 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"planName": "SELF HOSTED",
|
"planName": "OPENSIGN™ FREE",
|
||||||
"currency": "",
|
"currency": "",
|
||||||
"price": "Free",
|
"monthlyPrice": "Free",
|
||||||
"subtitle": "Free for life One click install.",
|
"yearlyPrice": "Free",
|
||||||
"btnText": "Visit github",
|
"subtitle": "Free Unlimited E-signatures, Forever.",
|
||||||
"url": "https://github.com/opensignlabs/opensign",
|
"btnText": "Subscribe",
|
||||||
"target": "_blank",
|
"url": "",
|
||||||
"benefits": [
|
"target": "_blank",
|
||||||
"Sign Unlimited Documents",
|
"benefits": [
|
||||||
"S3 Doc Storage",
|
"Unlimited envelopes",
|
||||||
"Unlimited Guest Signers",
|
"Sign documents yourself",
|
||||||
"Unlimited completion certificates",
|
"Request signatures from others",
|
||||||
"Unique Code(OTP) verification for guest signers",
|
"14 field types",
|
||||||
"Expiring docs & reject signature support",
|
"Automatic e-signatures",
|
||||||
"PDF Template Creation(coming soon)",
|
"Completion certificates",
|
||||||
"Audit Trails",
|
"Send in order",
|
||||||
"API support",
|
"Document templates",
|
||||||
"Add-ons support(coming soon)",
|
"Import from Dropbox",
|
||||||
"Self hosted cloud infrastructure",
|
"Contact book",
|
||||||
"Free for lifetime",
|
"Document expiry support",
|
||||||
"Community support"
|
"Decline document support",
|
||||||
]
|
"Email notifications",
|
||||||
},
|
"Recipient authentication using OTP",
|
||||||
{
|
"And much more"
|
||||||
"planName": "THANKS PLAN",
|
]
|
||||||
"currency": "$",
|
},
|
||||||
"price": "29.99",
|
{
|
||||||
"subtitle": "Use code <span style='background-color: yellow;'>'FREEBETA'</span> to get this for free(First 1000 users)",
|
"planName": "OPENSIGN™ PROFESSIONAL",
|
||||||
"btnText": "Subscribe",
|
"currency": "$",
|
||||||
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
|
"monthlyPrice": "29.99",
|
||||||
"target": "_self",
|
"yearlyPrice": "329.99",
|
||||||
"benefits": [
|
"subtitle": "Exclusive Access to advanced features.",
|
||||||
"Sign Unlimited Documents",
|
"btnText": "Subscribe",
|
||||||
"Unlimited Secure Doc Storage with OpenSign™ Drive",
|
"url": "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
|
||||||
"Unlimited Guest Signers",
|
"yearlyUrl": "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
|
||||||
"Unlimited completion certificates",
|
"target": "_self",
|
||||||
"Unique Code(OTP) verification for guest signers",
|
"benefits": [
|
||||||
"Expiring docs & reject signature support",
|
"Everything in OpenSign™ professional",
|
||||||
"PDF Template Creation(coming soon)",
|
"Field validations",
|
||||||
"Audit Trails",
|
"Regular expression validations",
|
||||||
"API support",
|
"Organize docs in OpenSign™ Drive",
|
||||||
"Add-ons support(coming soon)",
|
"Webhooks",
|
||||||
"Self hosted cloud infrastructure"
|
"Zapier integration",
|
||||||
]
|
"API Access",
|
||||||
},
|
"100 API signatures included",
|
||||||
{
|
"DocumentId removal from signed docs",
|
||||||
"planName": "ENTERPRISE",
|
"Custom email templates(coming soon)"
|
||||||
"currency": "",
|
]
|
||||||
"price": "Request Price",
|
},
|
||||||
"subtitle": "Customization available Priority support.",
|
{
|
||||||
"btnText": "Contact us",
|
"planName": "OPENSIGN™ ENTERPRISE",
|
||||||
"url": "https://www.opensignlabs.com/contact-us",
|
"currency": "",
|
||||||
"target": "_blank",
|
"monthlyPrice": "Request Price",
|
||||||
"benefits": [
|
"yearlyPrice": "Request Price",
|
||||||
"All features",
|
"subtitle": "Scalable Features with priority support.",
|
||||||
"Custom domain",
|
"btnText": "Contact us",
|
||||||
"Whitelabeling",
|
"url": "https://www.opensignlabs.com/contact-us",
|
||||||
"Uptime SLA",
|
"target": "_blank",
|
||||||
"SSO support",
|
"benefits": [
|
||||||
"24/7 support"
|
"All features",
|
||||||
]
|
"Custom domain",
|
||||||
}
|
"Custom branding",
|
||||||
]
|
"Uptime SLA",
|
||||||
|
"SSO support",
|
||||||
|
"Priority support"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useSelector } from "react-redux";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { useNavigate, useLocation, Outlet } from "react-router-dom";
|
import { useNavigate, useLocation, Outlet } from "react-router-dom";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
|
||||||
const HomeLayout = () => {
|
const HomeLayout = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -18,6 +19,12 @@ const HomeLayout = () => {
|
|||||||
const arr = useSelector((state) => state.TourSteps);
|
const arr = useSelector((state) => state.TourSteps);
|
||||||
const [isUserValid, setIsUserValid] = useState(true);
|
const [isUserValid, setIsUserValid] = useState(true);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
// reactour state
|
||||||
|
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
||||||
|
const [isTour, setIsTour] = useState(false);
|
||||||
|
const [tourStatusArr, setTourStatusArr] = useState([]);
|
||||||
|
const [tourConfigs, setTourConfigs] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -27,8 +34,7 @@ const HomeLayout = () => {
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
});
|
});
|
||||||
if (user) {
|
if (user) {
|
||||||
setIsUserValid(true);
|
checkIsSubscribed();
|
||||||
setIsLoader(false);
|
|
||||||
} else {
|
} else {
|
||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
}
|
}
|
||||||
@@ -37,14 +43,36 @@ const HomeLayout = () => {
|
|||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// reactour state
|
async function checkIsSubscribed() {
|
||||||
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
const currentUser = Parse.User.current();
|
||||||
const [isTour, setIsTour] = useState(false);
|
const user = await Parse.Cloud.run("getUserDetails", {
|
||||||
const [tourStatusArr, setTourStatusArr] = useState([]);
|
email: currentUser.get("email")
|
||||||
const [tourConfigs, setTourConfigs] = useState([]);
|
});
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const freeplan = user?.get("Plan") && user?.get("Plan").plan_code;
|
||||||
|
const billingDate =
|
||||||
|
user?.get("Next_billing_date") && user?.get("Next_billing_date");
|
||||||
|
if (freeplan === "freeplan") {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (billingDate > new Date()) {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
const showSidebar = () => {
|
const showSidebar = () => {
|
||||||
setIsOpen((value) => !value);
|
setIsOpen((value) => !value);
|
||||||
};
|
};
|
||||||
@@ -94,10 +122,16 @@ const HomeLayout = () => {
|
|||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="tourbutton"]',
|
||||||
|
content: `To upload documents for self-signing or to request others’ signatures, simply select the respective buttons.`,
|
||||||
|
position: "top"
|
||||||
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
|
},
|
||||||
...resArr,
|
...resArr,
|
||||||
{
|
{
|
||||||
selector: '[data-tut="reactourLast"]',
|
selector: '[data-tut="reactourLast"]',
|
||||||
content: `You are good to go`,
|
content: `You are ready to start using OpenSign! If you need support feel free to contact us.`,
|
||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
}
|
}
|
||||||
@@ -110,7 +144,7 @@ const HomeLayout = () => {
|
|||||||
// console.log("closeTour");
|
// console.log("closeTour");
|
||||||
setIsTour(false);
|
setIsTour(false);
|
||||||
const serverUrl = localStorage.getItem("baseUrl");
|
const serverUrl = localStorage.getItem("baseUrl");
|
||||||
const appId = localStorage.getItem("AppID12");
|
const appId = localStorage.getItem("parseAppId");
|
||||||
const extUserClass = localStorage.getItem("extended_class");
|
const extUserClass = localStorage.getItem("extended_class");
|
||||||
const json = JSON.parse(localStorage.getItem("Extand_Class"));
|
const json = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
const extUserId = json && json.length > 0 && json[0].objectId;
|
const extUserId = json && json.length > 0 && json[0].objectId;
|
||||||
@@ -192,7 +226,7 @@ const HomeLayout = () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="sticky top-0 z-50">
|
<div className="sticky top-0 z-50">
|
||||||
<Header showSidebar={showSidebar} />
|
{!isLoader && <Header showSidebar={showSidebar} />}
|
||||||
</div>
|
</div>
|
||||||
{isUserValid ? (
|
{isUserValid ? (
|
||||||
<>
|
<>
|
||||||
@@ -217,8 +251,10 @@ const HomeLayout = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="flex md:flex-row flex-col z-50">
|
<div className="flex md:flex-row flex-col z-50">
|
||||||
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
||||||
|
<div
|
||||||
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
|
id="renderList"
|
||||||
|
className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"
|
||||||
|
>
|
||||||
<div className="bg-[#eef1f5] p-3">{<Outlet />}</div>
|
<div className="bg-[#eef1f5] p-3">{<Outlet />}</div>
|
||||||
<div className="z-30">
|
<div className="z-30">
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import stamp from "./stamp2.png";
|
|
||||||
import sign from "./sign3.png";
|
|
||||||
import { themeColor } from "./IconColor.js";
|
|
||||||
|
|
||||||
function DragElement({ id }) {
|
|
||||||
const selectedId = id;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{selectedId === 3 ? (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
userSelect: "none"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="sign img"
|
|
||||||
style={{
|
|
||||||
width: "25px",
|
|
||||||
height: "23px",
|
|
||||||
background: themeColor()
|
|
||||||
}}
|
|
||||||
src={sign}
|
|
||||||
/>
|
|
||||||
<span style={{ color: themeColor(), fontSize: "12px" }}>
|
|
||||||
Signature
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
userSelect: "none"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="stamp img"
|
|
||||||
style={{
|
|
||||||
width: "25px",
|
|
||||||
height: "23px",
|
|
||||||
background: themeColor()
|
|
||||||
}}
|
|
||||||
src={stamp}
|
|
||||||
/>
|
|
||||||
<span style={{ color: themeColor(), fontSize: "12px" }}>Stamp</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DragElement;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export const themeColor = () => {
|
|
||||||
return "#47a3ad";
|
|
||||||
};
|
|
||||||
|
Before Width: | Height: | Size: 804 B |
|
Before Width: | Height: | Size: 561 B |
@@ -11,8 +11,6 @@ function ChangePassword() {
|
|||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
try {
|
try {
|
||||||
if (newpassword === confirmpassword) {
|
if (newpassword === confirmpassword) {
|
||||||
Parse.serverURL = localStorage.getItem("baseUrl");
|
|
||||||
Parse.initialize(localStorage.getItem("parseAppId"));
|
|
||||||
Parse.User.logIn(localStorage.getItem("userEmail"), currentpassword)
|
Parse.User.logIn(localStorage.getItem("userEmail"), currentpassword)
|
||||||
.then(async (user) => {
|
.then(async (user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -4,16 +4,15 @@ import "../styles/loader.css";
|
|||||||
import GetDashboard from "../components/dashboard/GetDashboard";
|
import GetDashboard from "../components/dashboard/GetDashboard";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { save_tourSteps } from "../redux/actions";
|
import { useDispatch } from "react-redux";
|
||||||
import { connect } from "react-redux";
|
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
||||||
const Dashboard = (props) => {
|
const Dashboard = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [dashboard, setdashboard] = useState([]);
|
const [dashboard, setdashboard] = useState([]);
|
||||||
const [classnameArray, setclassnameArray] = useState([]);
|
const [classnameArray, setclassnameArray] = useState([]);
|
||||||
const [loading, setloading] = useState(false);
|
const [loading, setloading] = useState(false);
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [defaultQuery, setDefaultQuery] = useState("");
|
const [defaultQuery, setDefaultQuery] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -32,8 +31,6 @@ const Dashboard = (props) => {
|
|||||||
const getDashboard = async (id) => {
|
const getDashboard = async (id) => {
|
||||||
setloading(true);
|
setloading(true);
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
var forms = Parse.Object.extend("w_dashboard");
|
var forms = Parse.Object.extend("w_dashboard");
|
||||||
var query = new Parse.Query(forms);
|
var query = new Parse.Query(forms);
|
||||||
query.equalTo("objectId", id);
|
query.equalTo("objectId", id);
|
||||||
@@ -92,7 +89,7 @@ const Dashboard = (props) => {
|
|||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
props.save_tourSteps(arr);
|
dispatch(saveTourSteps(arr));
|
||||||
// console.log("arr ", arr);
|
// console.log("arr ", arr);
|
||||||
setclassnameArray(classArray);
|
setclassnameArray(classArray);
|
||||||
if (localStorage.getItem("DashboardDefaultFilter")) {
|
if (localStorage.getItem("DashboardDefaultFilter")) {
|
||||||
@@ -137,6 +134,4 @@ const Dashboard = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, {
|
export default Dashboard;
|
||||||
save_tourSteps
|
|
||||||
})(Dashboard);
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import RenderAllPdfPage from "./component/renderAllPdfPage";
|
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
||||||
import "../css/./signature.css";
|
import "../styles/signature.css";
|
||||||
import "../css/AddUser.css";
|
import "../styles/AddUser.css";
|
||||||
import Title from "./component/Title";
|
import Title from "../components/Title";
|
||||||
import ModalUi from "../premitives/ModalUi";
|
import RenderDebugPdf from "../components/RenderDebugPdf";
|
||||||
import RenderDebugPdf from "./component/RenderDebugPdf";
|
|
||||||
import { pdfjs } from "react-pdf";
|
import { pdfjs } from "react-pdf";
|
||||||
import Alert from "../premitives/Alert";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import HandleError from "./component/HandleError";
|
import Alert from "../primitives/Alert";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
|
|
||||||
function processDimensions(x, y, width, height) {
|
function processDimensions(x, y, width, height) {
|
||||||
@@ -28,7 +28,7 @@ function processDimensions(x, y, width, height) {
|
|||||||
height: Math.floor(height)
|
height: Math.floor(height)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const DebugUi = () => {
|
const DebugPdf = () => {
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const [pdf, setPdf] = useState("");
|
const [pdf, setPdf] = useState("");
|
||||||
const [isModal, setIsModal] = useState(true);
|
const [isModal, setIsModal] = useState(true);
|
||||||
@@ -426,4 +426,4 @@ const DebugUi = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DebugUi;
|
export default DebugPdf;
|
||||||
@@ -1,16 +1,21 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { fetchAppInfo, forgetPassword } from "../redux/actions";
|
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
import login_img from "../assets/images/login_img.svg";
|
import login_img from "../assets/images/login_img.svg";
|
||||||
|
import Parse from "parse";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import { appInfo } from "../constant/appinfo";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
|
|
||||||
function ForgotPassword(props) {
|
function ForgotPassword() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
hideNav: ""
|
hideNav: ""
|
||||||
});
|
});
|
||||||
|
const [sentStatus, setSentStatus] = useState("");
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
setState({ ...state, [name]: value });
|
setState({ ...state, [name]: value });
|
||||||
@@ -23,34 +28,47 @@ function ForgotPassword(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
localStorage.setItem("appLogo", props.appInfo.applogo);
|
localStorage.setItem("appLogo", appInfo.applogo);
|
||||||
localStorage.setItem("appName", props.appInfo.appname);
|
localStorage.setItem("appName", appInfo.appname);
|
||||||
localStorage.setItem("defaultmenuid", props.appInfo.defaultmenuid);
|
// localStorage.setItem("defaultmenuid", props.appInfo.defaultmenuid);
|
||||||
localStorage.setItem("PageLanding", props.appInfo.LandingPageId);
|
// localStorage.setItem("PageLanding", props.appInfo.LandingPageId);
|
||||||
localStorage.setItem(
|
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
|
||||||
"userSettings",
|
|
||||||
JSON.stringify(props.appInfo.settings)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (state.email) {
|
if (state.email) {
|
||||||
props.forgetPassword(state.email);
|
const username = state.email;
|
||||||
|
try {
|
||||||
|
await Parse.User.requestPasswordReset(username);
|
||||||
|
setSentStatus("success");
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err ", err.code);
|
||||||
|
setSentStatus("failed");
|
||||||
|
} finally {
|
||||||
|
setTimeout(() => setSentStatus(""), 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
props.fetchAppInfo(localStorage.getItem("domain"));
|
dispatch(fetchAppInfo());
|
||||||
resize();
|
resize();
|
||||||
window.addEventListener("resize", resize);
|
window.addEventListener("resize", resize);
|
||||||
return () => window.removeEventListener("resize", resize);
|
return () => window.removeEventListener("resize", resize);
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
let image = props.appInfo.applogo;
|
let image = appInfo.applogo;
|
||||||
return (
|
return (
|
||||||
<div className="bg-white">
|
<div className="bg-white">
|
||||||
<Title title="Forgot password page" />
|
<Title title="Forgot password page" />
|
||||||
|
{sentStatus === "success" && (
|
||||||
|
<Alert type="success">
|
||||||
|
Reset password link has been sent to your email id
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
{sentStatus === "failed" && (
|
||||||
|
<Alert type={"danger"}>Please setup email adapter </Alert>
|
||||||
|
)}
|
||||||
<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">
|
||||||
@@ -111,10 +129,4 @@ function ForgotPassword(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
export default ForgotPassword;
|
||||||
return { appInfo: state.appInfo, forgotPassword: state.forgotPassword };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, { fetchAppInfo, forgetPassword })(
|
|
||||||
ForgotPassword
|
|
||||||
);
|
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { formJson } from "../json/FormJson";
|
import { formJson } from "../json/FormJson";
|
||||||
import AddUser from "../components/AddUser";
|
import AddUser from "../components/AddUser";
|
||||||
import sanitizeFileName from "../primitives/sanitizeFileName";
|
import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import DropboxChooser from "../components/fields/DropboxChoose";
|
import DropboxChooser from "../components/shared/fields/DropboxChoose";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import SelectFolder from "../components/fields/SelectFolder";
|
import SelectFolder from "../components/shared/fields/SelectFolder";
|
||||||
import SignersInput from "../components/fields/SignersInput";
|
import SignersInput from "../components/shared/fields/SignersInput";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
|
|
||||||
|
// `Form` render all type of Form on this basis of their provided in path
|
||||||
function Form() {
|
function Form() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
@@ -27,42 +29,47 @@ function Form() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Forms = (props) => {
|
const Forms = (props) => {
|
||||||
|
const maxFileSize = 20;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [signers, setSigners] = useState([]);
|
const [signers, setSigners] = useState([]);
|
||||||
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "",
|
Description: "",
|
||||||
Note: "Please review and sign this document",
|
Note: "",
|
||||||
TimeToCompleteDays: 15,
|
TimeToCompleteDays: 15,
|
||||||
SendinOrder: "false"
|
SendinOrder: "false"
|
||||||
});
|
});
|
||||||
const [fileupload, setFileUpload] = useState([]);
|
const [fileupload, setFileUpload] = useState([]);
|
||||||
const [fileload, setfileload] = useState(false);
|
const [fileload, setfileload] = useState(false);
|
||||||
const [percentage, setpercentage] = useState(0);
|
const [percentage, setpercentage] = useState(0);
|
||||||
|
const [isReset, setIsReset] = useState(false);
|
||||||
const [isAlert, setIsAlert] = useState(false);
|
const [isAlert, setIsAlert] = useState(false);
|
||||||
const [isSubmit, setIsSubmit] = useState(false);
|
const [isSubmit, setIsSubmit] = useState(false);
|
||||||
const [isErr, setIsErr] = useState("");
|
const [isErr, setIsErr] = useState("");
|
||||||
const handleStrInput = (e) => {
|
const handleStrInput = (e) => {
|
||||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
handleReset();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.title]);
|
||||||
const handleFileInput = (e) => {
|
const handleFileInput = (e) => {
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
try {
|
try {
|
||||||
let files = e.target.files;
|
let files = e.target.files;
|
||||||
if (typeof files[0] !== "undefined") {
|
if (typeof files[0] !== "undefined") {
|
||||||
const mb = Math.round(files[0].bytes / Math.pow(1024, 2));
|
const mb = Math.round(files[0].size / Math.pow(1024, 2));
|
||||||
if (mb > 10) {
|
if (mb > maxFileSize) {
|
||||||
alert(
|
alert(
|
||||||
`The selected file size is too large. Please select a file less than ${Math.round(
|
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
|
||||||
10
|
|
||||||
)} MB`
|
|
||||||
);
|
);
|
||||||
|
setFileUpload([]);
|
||||||
|
e.target.value = "";
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
handleFileUpload(files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFileUpload(files[0]);
|
|
||||||
} else {
|
} else {
|
||||||
alert("Please select file.");
|
alert("Please select file.");
|
||||||
return false;
|
return false;
|
||||||
@@ -74,10 +81,9 @@ const Forms = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleFileUpload = async (file) => {
|
const handleFileUpload = async (file) => {
|
||||||
Parse.serverURL = process.env.REACT_APP_SERVERURL;
|
|
||||||
Parse.initialize(process.env.REACT_APP_APPID);
|
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const fileName = file.name;
|
const fileName = file.name;
|
||||||
|
const size = file.size;
|
||||||
const name = sanitizeFileName(fileName);
|
const name = sanitizeFileName(fileName);
|
||||||
const pdfFile = file;
|
const pdfFile = file;
|
||||||
const parseFile = new Parse.File(name, pdfFile);
|
const parseFile = new Parse.File(name, pdfFile);
|
||||||
@@ -97,6 +103,8 @@ const Forms = (props) => {
|
|||||||
setFileUpload(response.url());
|
setFileUpload(response.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -109,13 +117,14 @@ const Forms = (props) => {
|
|||||||
const dropboxSuccess = async (files) => {
|
const dropboxSuccess = async (files) => {
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
|
const size = file.bytes;
|
||||||
const url = file.link;
|
const url = file.link;
|
||||||
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
||||||
|
|
||||||
if (mb > 10) {
|
if (mb > maxFileSize) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
alert(
|
alert(
|
||||||
`The selected file size is too large. Please select a file less than 10 MB`
|
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
|
||||||
);
|
);
|
||||||
}, 500);
|
}, 500);
|
||||||
return;
|
return;
|
||||||
@@ -137,6 +146,8 @@ const Forms = (props) => {
|
|||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -162,7 +173,9 @@ const Forms = (props) => {
|
|||||||
"TimeToCompleteDays",
|
"TimeToCompleteDays",
|
||||||
parseInt(formData?.TimeToCompleteDays)
|
parseInt(formData?.TimeToCompleteDays)
|
||||||
);
|
);
|
||||||
const isChecked = formData.SendinOrder === "true" ? true : false;
|
}
|
||||||
|
if (props.title !== "Sign Yourself") {
|
||||||
|
const isChecked = formData.SendinOrder === "false" ? false : true;
|
||||||
object.set("SendinOrder", isChecked);
|
object.set("SendinOrder", isChecked);
|
||||||
}
|
}
|
||||||
object.set("URL", fileupload);
|
object.set("URL", fileupload);
|
||||||
@@ -195,9 +208,7 @@ const Forms = (props) => {
|
|||||||
});
|
});
|
||||||
setFileUpload([]);
|
setFileUpload([]);
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
navigate(
|
navigate(`/${props?.redirectRoute}/${res.id}`);
|
||||||
`/asmf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/${props?.redirectRoute}/${res.id}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
@@ -226,15 +237,22 @@ const Forms = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
setIsReset(true);
|
||||||
setSigners([]);
|
setSigners([]);
|
||||||
setFolder({ ObjectId: "", Name: "" });
|
setFolder({ ObjectId: "", Name: "" });
|
||||||
setFormData({
|
setFormData({
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "",
|
Description: "",
|
||||||
Note: ""
|
Note:
|
||||||
|
props.title === "Sign Yourself"
|
||||||
|
? "Note to myself"
|
||||||
|
: "Please review and sign this document",
|
||||||
|
TimeToCompleteDays: 15,
|
||||||
|
SendinOrder: "true"
|
||||||
});
|
});
|
||||||
setFileUpload([]);
|
setFileUpload([]);
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
|
setTimeout(() => setIsReset(false), 50);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
||||||
@@ -280,7 +298,8 @@ const Forms = (props) => {
|
|||||||
<div className="flex gap-2 justify-center items-center">
|
<div className="flex gap-2 justify-center items-center">
|
||||||
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
||||||
<div className="break-all">
|
<div className="break-all">
|
||||||
file selected : {fileupload?.split("/")[3]?.split("_")[1]}
|
file selected :{" "}
|
||||||
|
{fileupload?.split("/")?.pop()?.split("_")[1]}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -318,7 +337,10 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
Title<span className="text-red-500 text-[13px]">*</span>
|
{props.title === "New Template"
|
||||||
|
? "Template Title"
|
||||||
|
: "Document Title"}
|
||||||
|
<span className="text-red-500 text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
name="Name"
|
name="Name"
|
||||||
@@ -337,7 +359,9 @@ const Forms = (props) => {
|
|||||||
onChange={(e) => handleStrInput(e)}
|
onChange={(e) => handleStrInput(e)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{props.signers && <SignersInput onChange={handleSigners} required />}
|
{props.signers && (
|
||||||
|
<SignersInput onChange={handleSigners} isReset={isReset} required />
|
||||||
|
)}
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
Note<span className="text-red-500 text-[13px]">*</span>
|
Note<span className="text-red-500 text-[13px]">*</span>
|
||||||
@@ -350,7 +374,11 @@ const Forms = (props) => {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SelectFolder onSuccess={handleFolder} folderCls={props.Cls} />
|
<SelectFolder
|
||||||
|
onSuccess={handleFolder}
|
||||||
|
folderCls={props.Cls}
|
||||||
|
isReset={isReset}
|
||||||
|
/>
|
||||||
|
|
||||||
{props.title === "Request Signatures" && (
|
{props.title === "Request Signatures" && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
@@ -402,10 +430,10 @@ const Forms = (props) => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmit}
|
disabled={isSubmit}
|
||||||
>
|
>
|
||||||
Submit
|
Next
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
className="bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none"
|
className="cursor-pointer bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none"
|
||||||
onClick={() => handleReset()}
|
onClick={() => handleReset()}
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { rejectBtn, submitBtn } from "../constant/const";
|
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||||
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
|
||||||
function GenerateToken() {
|
function GenerateToken() {
|
||||||
|
const navigation = useNavigate();
|
||||||
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 [apiToken, SetApiToken] = useState("");
|
const [apiToken, SetApiToken] = useState("");
|
||||||
@@ -15,6 +19,7 @@ function GenerateToken() {
|
|||||||
const [isGenerate, setIsGenerate] = useState(false);
|
const [isGenerate, setIsGenerate] = useState(false);
|
||||||
const [isErr, setIsErr] = useState(false);
|
const [isErr, setIsErr] = useState(false);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchToken();
|
fetchToken();
|
||||||
@@ -23,6 +28,11 @@ function GenerateToken() {
|
|||||||
|
|
||||||
const fetchToken = async () => {
|
const fetchToken = async () => {
|
||||||
try {
|
try {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
|
||||||
const url = parseBaseUrl + "functions/getapitoken";
|
const url = parseBaseUrl + "functions/getapitoken";
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -33,6 +43,7 @@ function GenerateToken() {
|
|||||||
if (res) {
|
if (res) {
|
||||||
SetApiToken(res.data.result.result);
|
SetApiToken(res.data.result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
SetApiToken();
|
SetApiToken();
|
||||||
@@ -88,6 +99,7 @@ function GenerateToken() {
|
|||||||
}, 1500); // Reset copied state after 1.5 seconds
|
}, 1500); // Reset copied state after 1.5 seconds
|
||||||
};
|
};
|
||||||
const handleModal = () => setIsModal(!isModal);
|
const handleModal = () => setIsModal(!isModal);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Title title={"API Token"} />
|
<Title title={"API Token"} />
|
||||||
@@ -115,29 +127,47 @@ function GenerateToken() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">API Token</h1>
|
{!isEnableSubscription && <PremiumAlertHeader />}
|
||||||
<ul className="w-full flex flex-col p-2 text-sm">
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
OpenSign™ API{" "}
|
||||||
|
<Tooltip
|
||||||
|
url={
|
||||||
|
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
|
}
|
||||||
|
isSubscribe={true}
|
||||||
|
/>
|
||||||
|
</h1>
|
||||||
|
<ul
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "w-full flex flex-col p-2 text-sm "
|
||||||
|
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
<li
|
<li
|
||||||
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
>
|
>
|
||||||
<span className="w-[40%]">Api Token:</span>{" "}
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
|
||||||
<span
|
<span className="">Api Token:</span>{" "}
|
||||||
id="token"
|
<span
|
||||||
className="w-[60%] md:text-end cursor-pointer"
|
id="token"
|
||||||
onClick={() => copytoclipboard(apiToken)}
|
className=" md:text-end cursor-pointer"
|
||||||
|
onClick={() => copytoclipboard(apiToken)}
|
||||||
|
>
|
||||||
|
{apiToken ? apiToken : "_____"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={apiToken ? handleModal : handleSubmit}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
||||||
>
|
>
|
||||||
{apiToken && apiToken}
|
{apiToken ? "Regenerate Token" : "Generate Token"}
|
||||||
</span>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
|
||||||
<button
|
<div className="flex items-center justify-center ">
|
||||||
type="button"
|
|
||||||
onClick={apiToken ? handleModal : handleSubmit}
|
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
|
||||||
>
|
|
||||||
{apiToken ? "Regenerate Token" : "Generate Token"}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -145,12 +175,41 @@ function GenerateToken() {
|
|||||||
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
className="rounded hover:bg-[#15b4e9] border-[1px] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
>
|
>
|
||||||
View Docs
|
View Docs
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<>
|
||||||
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
Upgrade to PRO Plan
|
||||||
|
</h1>
|
||||||
|
<ul className={"w-full flex flex-col p-2 text-sm "}>
|
||||||
|
<li
|
||||||
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
|
||||||
|
<span className="">$29.99/month:</span>{" "}
|
||||||
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
|
Sign 100 docs using API. Only 0.15/docs after that.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigation("/subscription")}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isModal}
|
isOpen={isModal}
|
||||||
title={"Regenerate Token"}
|
title={"Regenerate Token"}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import "../css/LoginPage.css";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import loader from "../assests/loader2.gif";
|
import "../styles/loginPage.css";
|
||||||
|
import loader from "../assets/images/loader2.gif";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useParams } from "react-router-dom";
|
import { themeColor } from "../constant/const";
|
||||||
import { themeColor } from "../utils/ThemeColor/backColor";
|
import { contractUsers } from "../constant/Utils";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
function Login() {
|
function GuestLogin() {
|
||||||
const { id, userMail, contactBookId, serverUrl } = useParams();
|
const { id, userMail, contactBookId, serverUrl } = useParams();
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const [email, setEmail] = useState(userMail);
|
const [email, setEmail] = useState(userMail);
|
||||||
@@ -18,6 +17,7 @@ function Login() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleServerUrl();
|
handleServerUrl();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
//function generate serverUrl and parseAppId from url and save it in local storage
|
//function generate serverUrl and parseAppId from url and save it in local storage
|
||||||
@@ -59,7 +59,8 @@ function Login() {
|
|||||||
"X-Parse-Application-Id": parseId
|
"X-Parse-Application-Id": parseId
|
||||||
};
|
};
|
||||||
let body = {
|
let body = {
|
||||||
email: email.toString()
|
email: email.toString(),
|
||||||
|
docId: id
|
||||||
};
|
};
|
||||||
let Otp = await axios.post(url, body, { headers: headers });
|
let Otp = await axios.post(url, body, { headers: headers });
|
||||||
|
|
||||||
@@ -104,28 +105,36 @@ function Login() {
|
|||||||
} else {
|
} else {
|
||||||
let _user = user.data.result;
|
let _user = user.data.result;
|
||||||
const parseId = localStorage.getItem("parseAppId");
|
const parseId = localStorage.getItem("parseAppId");
|
||||||
|
const contractUserDetails = await contractUsers(_user.email);
|
||||||
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
`Parse/${parseId}/currentUser`,
|
`Parse/${parseId}/currentUser`,
|
||||||
JSON.stringify(_user)
|
JSON.stringify(_user)
|
||||||
);
|
);
|
||||||
|
if (contractUserDetails) {
|
||||||
|
localStorage.setItem(
|
||||||
|
"Extand_Class",
|
||||||
|
JSON.stringify(contractUserDetails)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
localStorage.setItem("username", _user.name);
|
localStorage.setItem("username", _user.name);
|
||||||
localStorage.setItem("accesstoken", _user.sessionToken);
|
localStorage.setItem("accesstoken", _user.sessionToken);
|
||||||
//save isGuestSigner true in local to handle login flow header in mobile view
|
//save isGuestSigner true in local to handle login flow header in mobile view
|
||||||
localStorage.setItem("isGuestSigner", true);
|
localStorage.setItem("isGuestSigner", true);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
navigate(
|
navigate(`/load/recipientSignPdf/${id}/${contactBookId}`);
|
||||||
`/loadmf/signmicroapp/recipientSignPdf/${id}/${contactBookId}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {
|
||||||
|
console.log("err ", error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please Enter OTP!");
|
alert("Please Enter OTP!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: "2rem" }}>
|
<div style={{ padding: "2rem", background: "white" }}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -189,7 +198,7 @@ function Login() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
@@ -206,7 +215,7 @@ function Login() {
|
|||||||
<button
|
<button
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
marginLeft: "0px !important"
|
marginLeft: "0px !important"
|
||||||
}}
|
}}
|
||||||
@@ -242,7 +251,7 @@ function Login() {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
@@ -261,7 +270,7 @@ function Login() {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={(e) => VerifyOTP(e)}
|
onClick={(e) => VerifyOTP(e)}
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
@@ -279,4 +288,4 @@ function Login() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Login;
|
export default GuestLogin;
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import "../styles/toast.css";
|
|
||||||
import "../styles/loader.css";
|
import "../styles/loader.css";
|
||||||
import { connect } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { fetchAppInfo, showTenantName } from "../redux/actions";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import GoogleSignInBtn from "../components/LoginGoogle";
|
import GoogleSignInBtn from "../components/LoginGoogle";
|
||||||
@@ -12,16 +10,24 @@ import { NavLink, useNavigate, useLocation } 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";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
import {
|
||||||
|
isEnableSubscription,
|
||||||
function Login(props) {
|
modalCancelBtnColor,
|
||||||
|
modalSubmitBtnColor
|
||||||
|
} from "../constant/const";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import { appInfo } from "../constant/appinfo";
|
||||||
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
|
function Login() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
email: "",
|
email: "",
|
||||||
toastColor: "#5cb85c",
|
alertType: "success",
|
||||||
toastDescription: "",
|
alertMsg: "",
|
||||||
password: "",
|
password: "",
|
||||||
passwordVisible: false,
|
passwordVisible: false,
|
||||||
mobile: "",
|
mobile: "",
|
||||||
@@ -37,18 +43,14 @@ function Login(props) {
|
|||||||
Destination: ""
|
Destination: ""
|
||||||
});
|
});
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
const image = props?.appInfo?.applogo || undefined;
|
const image = appInfo?.applogo || undefined;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem("accesstoken")) {
|
if (localStorage.getItem("accesstoken")) {
|
||||||
setState({ ...state, loading: true });
|
setState({ ...state, loading: true });
|
||||||
GetLoginData();
|
GetLoginData();
|
||||||
}
|
}
|
||||||
props.fetchAppInfo(
|
dispatch(fetchAppInfo());
|
||||||
localStorage.getItem("domain"),
|
|
||||||
localStorage.getItem("BaseUrl12"),
|
|
||||||
localStorage.getItem("AppID12")
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
@@ -65,10 +67,8 @@ function Login(props) {
|
|||||||
setState({ ...state, loading: true });
|
setState({ ...state, loading: true });
|
||||||
let baseUrl = localStorage.getItem("baseUrl");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let parseAppId = localStorage.getItem("parseAppId");
|
let parseAppId = localStorage.getItem("parseAppId");
|
||||||
localStorage.setItem("appLogo", props.appInfo.applogo);
|
localStorage.setItem("appLogo", appInfo.applogo);
|
||||||
localStorage.setItem("appName", props.appInfo.appname);
|
localStorage.setItem("appName", appInfo.appname);
|
||||||
Parse.serverURL = localStorage.getItem("baseUrl");
|
|
||||||
Parse.initialize(localStorage.getItem("parseAppId"));
|
|
||||||
// Pass the username and password to logIn function
|
// Pass the username and password to logIn function
|
||||||
await Parse.User.logIn(email, password)
|
await Parse.User.logIn(email, password)
|
||||||
.then(async (user) => {
|
.then(async (user) => {
|
||||||
@@ -87,8 +87,8 @@ function Login(props) {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
let userRoles = [];
|
let userRoles = [];
|
||||||
if (props.appInfo.settings) {
|
if (appInfo.settings) {
|
||||||
let userSettings = props.appInfo.settings;
|
let userSettings = appInfo.settings;
|
||||||
|
|
||||||
//Get Current user roles
|
//Get Current user roles
|
||||||
let url = `${baseUrl}functions/UserGroups`;
|
let url = `${baseUrl}functions/UserGroups`;
|
||||||
@@ -149,11 +149,6 @@ function Login(props) {
|
|||||||
"extended_class",
|
"extended_class",
|
||||||
element.extended_class
|
element.extended_class
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
|
||||||
"userpointer",
|
|
||||||
element.userpointer
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
@@ -183,8 +178,10 @@ function Login(props) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(
|
||||||
|
tenentInfo[0].tenentName || ""
|
||||||
|
)
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -216,15 +213,17 @@ function Login(props) {
|
|||||||
x.TenantId.TenantName || ""
|
x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(
|
||||||
|
tenentInfo[0].tenentName || ""
|
||||||
|
)
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -244,10 +243,7 @@ function Login(props) {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (
|
if (isEnableSubscription) {
|
||||||
process.env
|
|
||||||
.REACT_APP_ENABLE_SUBSCRIPTION
|
|
||||||
) {
|
|
||||||
const LocalUserDetails = {
|
const LocalUserDetails = {
|
||||||
name: results[0].get("Name"),
|
name: results[0].get("Name"),
|
||||||
email: results[0].get("Email"),
|
email: results[0].get("Email"),
|
||||||
@@ -258,10 +254,15 @@ function Login(props) {
|
|||||||
"userDetails",
|
"userDetails",
|
||||||
JSON.stringify(LocalUserDetails)
|
JSON.stringify(LocalUserDetails)
|
||||||
);
|
);
|
||||||
|
const freeplan =
|
||||||
|
results[0].get("Plan") &&
|
||||||
|
results[0].get("Plan").plan_code;
|
||||||
const billingDate =
|
const billingDate =
|
||||||
results[0].get("Next_billing_date") &&
|
results[0].get("Next_billing_date") &&
|
||||||
results[0].get("Next_billing_date");
|
results[0].get("Next_billing_date");
|
||||||
if (billingDate) {
|
if (freeplan === "freeplan") {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem(
|
localStorage.removeItem(
|
||||||
"userDetails"
|
"userDetails"
|
||||||
@@ -297,9 +298,7 @@ function Login(props) {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (
|
if (isEnableSubscription) {
|
||||||
process.env.REACT_APP_ENABLE_SUBSCRIPTION
|
|
||||||
) {
|
|
||||||
const LocalUserDetails = {
|
const LocalUserDetails = {
|
||||||
name: _user.name,
|
name: _user.name,
|
||||||
email: email,
|
email: email,
|
||||||
@@ -354,13 +353,16 @@ function Login(props) {
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: `${error.message}`
|
alertMsg: `${error.message}`
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@@ -370,13 +372,16 @@ function Login(props) {
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: "Login failed: Invalid username or password."
|
alertMsg: "Invalid username or password!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
console.error("Error while logging in user", error);
|
console.error("Error while logging in user", error);
|
||||||
});
|
});
|
||||||
@@ -390,15 +395,32 @@ function Login(props) {
|
|||||||
const setThirdpartyLoader = (value) => {
|
const setThirdpartyLoader = (value) => {
|
||||||
setState({ ...state, thirdpartyLoader: value });
|
setState({ ...state, thirdpartyLoader: value });
|
||||||
};
|
};
|
||||||
|
const handleFreePlan = async (id) => {
|
||||||
|
try {
|
||||||
|
const params = { userId: id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "error") {
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
const thirdpartyLoginfn = async (sessionToken, billingDate) => {
|
const thirdpartyLoginfn = async (sessionToken, billingDate) => {
|
||||||
const baseUrl = localStorage.getItem("BaseUrl12");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("AppID12");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const res = await axios.get(baseUrl + "users/me", {
|
const res = await axios.get(baseUrl + "users/me", {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Parse-Session-Token": sessionToken,
|
"X-Parse-Session-Token": sessionToken,
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const param = new URLSearchParams(location.search);
|
||||||
|
const isFreeplan = param?.get("subscription") === "freeplan";
|
||||||
|
if (isFreeplan) {
|
||||||
|
await handleFreePlan(res.data.objectId);
|
||||||
|
}
|
||||||
await Parse.User.become(sessionToken).then(() => {
|
await Parse.User.become(sessionToken).then(() => {
|
||||||
window.localStorage.setItem("accesstoken", sessionToken);
|
window.localStorage.setItem("accesstoken", sessionToken);
|
||||||
});
|
});
|
||||||
@@ -417,8 +439,8 @@ function Login(props) {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
let userRoles = [];
|
let userRoles = [];
|
||||||
if (props.appInfo.settings) {
|
if (appInfo.settings) {
|
||||||
let userSettings = props.appInfo.settings;
|
let userSettings = appInfo.settings;
|
||||||
|
|
||||||
//Get Current user roles
|
//Get Current user roles
|
||||||
let url = `${baseUrl}functions/UserGroups`;
|
let url = `${baseUrl}functions/UserGroups`;
|
||||||
@@ -480,7 +502,6 @@ function Login(props) {
|
|||||||
"extended_class",
|
"extended_class",
|
||||||
element.extended_class
|
element.extended_class
|
||||||
);
|
);
|
||||||
localStorage.setItem("userpointer", element.userpointer);
|
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
@@ -509,8 +530,8 @@ function Login(props) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -542,15 +563,15 @@ function Login(props) {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -571,18 +592,28 @@ function Login(props) {
|
|||||||
);
|
);
|
||||||
setThirdpartyLoader(false);
|
setThirdpartyLoader(false);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, {
|
navigate(`/subscription`, {
|
||||||
replace: true
|
replace: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
navigate(`/subscription`, { replace: true });
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
@@ -597,17 +628,29 @@ function Login(props) {
|
|||||||
localStorage.setItem("pageType", element.pageType);
|
localStorage.setItem("pageType", element.pageType);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
setThirdpartyLoader(false);
|
setThirdpartyLoader(false);
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
@@ -647,13 +690,16 @@ function Login(props) {
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: `${error.message}`
|
alertMsg: `${error.message}`
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@@ -663,8 +709,6 @@ function Login(props) {
|
|||||||
const GetLoginData = async () => {
|
const GetLoginData = async () => {
|
||||||
setState({ ...state, loading: true });
|
setState({ ...state, loading: true });
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = localStorage.getItem("baseUrl");
|
|
||||||
Parse.initialize(localStorage.getItem("parseAppId"));
|
|
||||||
const user = await Parse.User.become(localStorage.getItem("accesstoken"));
|
const user = await Parse.User.become(localStorage.getItem("accesstoken"));
|
||||||
let _usss = user.toJSON();
|
let _usss = user.toJSON();
|
||||||
localStorage.setItem("UserInformation", JSON.stringify(_usss));
|
localStorage.setItem("UserInformation", JSON.stringify(_usss));
|
||||||
@@ -717,13 +761,17 @@ function Login(props) {
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: `Does not have permissions to access this application.`
|
alertMsg:
|
||||||
|
"Does not have permissions to access this application!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
// _currentRole = userRoles[0];
|
// _currentRole = userRoles[0];
|
||||||
@@ -731,92 +779,153 @@ function Login(props) {
|
|||||||
} else {
|
} else {
|
||||||
_currentRole = userRoles[0];
|
_currentRole = userRoles[0];
|
||||||
}
|
}
|
||||||
let SettingsUser = JSON.parse(userSettings);
|
if (_currentRole && _currentRole !== "contracts_Guest") {
|
||||||
SettingsUser.forEach(async (element) => {
|
let SettingsUser = JSON.parse(userSettings);
|
||||||
if (element.role === _currentRole) {
|
SettingsUser.forEach(async (item) => {
|
||||||
let _role = _currentRole.replace(
|
if (item.role === _currentRole) {
|
||||||
`${localStorage.getItem("_appName")}_`,
|
let _role = _currentRole.replace(`${appInfo.appname}_`, "");
|
||||||
""
|
localStorage.setItem("_user_role", _role);
|
||||||
);
|
// Get TenentID from Extendend Class
|
||||||
localStorage.setItem("_user_role", _role);
|
localStorage.setItem("extended_class", item.extended_class);
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
// Get TenentID from Extendend Class
|
const userSettings = appInfo.settings;
|
||||||
localStorage.setItem(
|
const setting = userSettings.find(
|
||||||
"extended_class",
|
(x) => x.role === _currentRole
|
||||||
element.extended_class
|
);
|
||||||
);
|
const redirectUrl =
|
||||||
|
location?.state?.from ||
|
||||||
const currentUser = Parse.User.current();
|
`/${setting.pageType}/${setting.pageId}`;
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
}).then(
|
}).then(
|
||||||
(result) => {
|
(result) => {
|
||||||
let tenentInfo = [];
|
let tenentInfo = [];
|
||||||
const results = [result];
|
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);
|
||||||
if (extendedInfo.length > 1) {
|
if (extendedInfo.length > 1) {
|
||||||
extendedInfo.forEach((x) => {
|
extendedInfo.forEach((x) => {
|
||||||
if (x.TenantId) {
|
if (x.TenantId) {
|
||||||
let obj = {
|
let obj = {
|
||||||
tenentId: x.TenantId.objectId,
|
tenentId: x.TenantId.objectId,
|
||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
localStorage.setItem("showpopup", true);
|
||||||
localStorage.setItem("showpopup", true);
|
localStorage.setItem("PageLanding", item.pageId);
|
||||||
localStorage.setItem("PageLanding", element.pageId);
|
localStorage.setItem("defaultmenuid", item.menuId);
|
||||||
localStorage.setItem("defaultmenuid", element.menuId);
|
localStorage.setItem("pageType", item.pageType);
|
||||||
localStorage.setItem("pageType", element.pageType);
|
navigate("/");
|
||||||
navigate("/");
|
} else {
|
||||||
} else {
|
extendedInfo.forEach((x) => {
|
||||||
extendedInfo.forEach((x) => {
|
if (x.TenantId) {
|
||||||
if (x.TenantId) {
|
let obj = {
|
||||||
let obj = {
|
tenentId: x.TenantId.objectId,
|
||||||
tenentId: x.TenantId.objectId,
|
tenentName: x.TenantId.TenantName || ""
|
||||||
tenentName: x.TenantId.TenantName || ""
|
};
|
||||||
|
localStorage.setItem(
|
||||||
|
"TenantId",
|
||||||
|
x.TenantId.objectId
|
||||||
|
);
|
||||||
|
tenentInfo.push(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
localStorage.setItem("PageLanding", setting.pageId);
|
||||||
|
localStorage.setItem(
|
||||||
|
"defaultmenuid",
|
||||||
|
setting.menuId
|
||||||
|
);
|
||||||
|
localStorage.setItem("pageType", setting.pageType);
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const LocalUserDetails = {
|
||||||
|
name: results[0].get("Name"),
|
||||||
|
email: results[0].get("Email"),
|
||||||
|
phone: results[0].get("Phone"),
|
||||||
|
company: results[0].get("Company")
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"userDetails",
|
||||||
x.TenantId.objectId
|
JSON.stringify(LocalUserDetails)
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
const billingDate =
|
||||||
|
results[0].get("Next_billing_date") &&
|
||||||
|
results[0].get("Next_billing_date");
|
||||||
|
const freeplan =
|
||||||
|
results[0]?.get("Plan") &&
|
||||||
|
results[0]?.get("Plan").plan_code;
|
||||||
|
|
||||||
|
if (freeplan === "freeplan") {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (billingDate > new Date()) {
|
||||||
|
localStorage.removeItem("userDetails");
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
localStorage.setItem("PageLanding", element.pageId);
|
} else {
|
||||||
localStorage.setItem("defaultmenuid", element.menuId);
|
localStorage.setItem("PageLanding", setting.pageId);
|
||||||
localStorage.setItem("pageType", element.pageType);
|
localStorage.setItem("defaultmenuid", setting.menuId);
|
||||||
navigate(`/${element.pageType}/${element.pageId}`);
|
localStorage.setItem("pageType", setting.pageType);
|
||||||
|
setState({ ...state, loading: false });
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const LocalUserDetails = {
|
||||||
|
name: results[0].get("Name"),
|
||||||
|
email: results[0].get("Email"),
|
||||||
|
phone: results[0].get("Phone")
|
||||||
|
// company: results.get("Company"),
|
||||||
|
};
|
||||||
|
localStorage.setItem(
|
||||||
|
"userDetails",
|
||||||
|
JSON.stringify(LocalUserDetails)
|
||||||
|
);
|
||||||
|
const billingDate = "";
|
||||||
|
if (billingDate) {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
localStorage.setItem("PageLanding", element.pageId);
|
(error) => {
|
||||||
localStorage.setItem("defaultmenuid", element.menuId);
|
setState({
|
||||||
localStorage.setItem("pageType", element.pageType);
|
...state,
|
||||||
navigate(`/${element.pageType}/${element.pageId}`);
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: "You don`t have access to this application!"
|
||||||
|
});
|
||||||
|
setTimeout(function () {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
localStorage.setItem("accesstoken", null);
|
||||||
|
console.error("Error while fetching Follow", error);
|
||||||
}
|
}
|
||||||
},
|
);
|
||||||
(error) => {
|
}
|
||||||
setState({
|
});
|
||||||
...state,
|
} else {
|
||||||
loading: false,
|
setState({ ...state, loading: false });
|
||||||
toastColor: "#d9534f",
|
handleCloseModal();
|
||||||
toastDescription:
|
}
|
||||||
"You don`t 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("Error while fetching Follow", error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
console.log("User Role Not Found.");
|
console.log("User Role Not Found.");
|
||||||
}
|
}
|
||||||
@@ -895,8 +1004,8 @@ function Login(props) {
|
|||||||
let PageLanding = localStorage.getItem("PageLanding");
|
let PageLanding = localStorage.getItem("PageLanding");
|
||||||
let domain = localStorage.getItem("domain");
|
let domain = localStorage.getItem("domain");
|
||||||
let _appName = localStorage.getItem("_appName");
|
let _appName = localStorage.getItem("_appName");
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("AppID12");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
@@ -907,8 +1016,8 @@ function Login(props) {
|
|||||||
localStorage.setItem("PageLanding", PageLanding);
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
localStorage.setItem("domain", domain);
|
localStorage.setItem("domain", domain);
|
||||||
localStorage.setItem("userSettings", appdata);
|
localStorage.setItem("userSettings", appdata);
|
||||||
localStorage.setItem("BaseUrl12", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("AppID12", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="bg-white">
|
<div className="bg-white">
|
||||||
@@ -942,7 +1051,7 @@ function Login(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{props.isloginVisible && props.isloginVisible ? (
|
{appInfo && appInfo.appId ? (
|
||||||
<>
|
<>
|
||||||
<div aria-labelledby="loginHeading" role="region">
|
<div aria-labelledby="loginHeading" role="region">
|
||||||
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
||||||
@@ -1042,7 +1151,11 @@ function Login(props) {
|
|||||||
</button>
|
</button>
|
||||||
<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={
|
||||||
|
location.search
|
||||||
|
? "/signup" + location.search
|
||||||
|
: "/signup"
|
||||||
|
}
|
||||||
style={width < 768 ? { textAlign: "center" } : {}}
|
style={width < 768 ? { textAlign: "center" } : {}}
|
||||||
>
|
>
|
||||||
Create Account
|
Create Account
|
||||||
@@ -1050,7 +1163,7 @@ function Login(props) {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<br />
|
<br />
|
||||||
{(props.appInfo.fbAppId || props.appInfo.googleClietId) && (
|
{(appInfo.fbAppId || appInfo.googleClietId) && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -1081,9 +1194,9 @@ function Login(props) {
|
|||||||
justifyContent: "center"
|
justifyContent: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* {props.appInfo.fbAppId && props.appInfo.fbAppId !== "" ? (
|
{/* {appInfo.fbAppId && appInfo.fbAppId !== "" ? (
|
||||||
<LoginFacebook
|
<LoginFacebook
|
||||||
FBCred={props.appInfo.fbAppId}
|
FBCred={appInfo.fbAppId}
|
||||||
thirdpartyLoginfn={thirdpartyLoginfn}
|
thirdpartyLoginfn={thirdpartyLoginfn}
|
||||||
thirdpartyLoader={state.thirdpartyLoader}
|
thirdpartyLoader={state.thirdpartyLoader}
|
||||||
setThirdpartyLoader={setThirdpartyLoader}
|
setThirdpartyLoader={setThirdpartyLoader}
|
||||||
@@ -1099,10 +1212,9 @@ function Login(props) {
|
|||||||
justifyContent: "center"
|
justifyContent: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.appInfo.googleClietId &&
|
{appInfo.googleClietId && appInfo.googleClietId !== "" ? (
|
||||||
props.appInfo.googleClietId !== "" ? (
|
|
||||||
<GoogleSignInBtn
|
<GoogleSignInBtn
|
||||||
GoogleCred={props.appInfo.googleClietId}
|
GoogleCred={appInfo.googleClietId}
|
||||||
thirdpartyLoginfn={thirdpartyLoginfn}
|
thirdpartyLoginfn={thirdpartyLoginfn}
|
||||||
thirdpartyLoader={state.thirdpartyLoader}
|
thirdpartyLoader={state.thirdpartyLoader}
|
||||||
setThirdpartyLoader={setThirdpartyLoader}
|
setThirdpartyLoader={setThirdpartyLoader}
|
||||||
@@ -1124,14 +1236,7 @@ function Login(props) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
||||||
<div
|
|
||||||
id="snackbar"
|
|
||||||
role="alert"
|
|
||||||
style={{ backgroundColor: state.toastColor }}
|
|
||||||
>
|
|
||||||
{state.toastDescription}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
|
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
|
||||||
<form className="px-4 py-3">
|
<form className="px-4 py-3">
|
||||||
@@ -1219,16 +1324,4 @@ function Login(props) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default Login;
|
||||||
const mapStateToProps = (state) => {
|
|
||||||
if (Object.keys(state.appInfo).length !== 0) {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: true };
|
|
||||||
} else {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: false };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, {
|
|
||||||
fetchAppInfo,
|
|
||||||
showTenantName
|
|
||||||
})(Login);
|
|
||||||
@@ -1,25 +1,21 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
import redPen from "../assests/redPen.png";
|
import "../styles/managesign.css";
|
||||||
import bluePen from "../assests/bluePen.png";
|
import "../styles/signature.css";
|
||||||
import blackPen from "../assests/blackPen.png";
|
import { toDataUrl } from "../constant/Utils";
|
||||||
import "../css/custom.css";
|
import Parse from "parse";
|
||||||
import "../css/signature.css";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import axios from "axios";
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
import { toDataUrl } from "../utils/toDataUrl";
|
|
||||||
|
|
||||||
|
|
||||||
const ManageSign = () => {
|
const ManageSign = () => {
|
||||||
let appName;
|
const appName = appInfo.appname;
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
const [initialPen, setInitialPen] = useState("blue");
|
const [initialPen, setInitialPen] = useState("blue");
|
||||||
const [image, setImage] = useState();
|
const [image, setImage] = useState();
|
||||||
const [signName, setSignName] = useState("");
|
const [signName, setSignName] = useState("");
|
||||||
const [signature, setSignature] = useState("");
|
const [signature, setSignature] = useState("");
|
||||||
const [warning, setWarning] = useState(false);
|
const [warning, setWarning] = useState(false);
|
||||||
const [nameWarning, setNameWarning] = useState(false);
|
|
||||||
const [isvalue, setIsValue] = useState(false);
|
const [isvalue, setIsValue] = useState(false);
|
||||||
const allColor = [bluePen, redPen, blackPen];
|
const allColor = ["blue", "red", "black"];
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
const [isSuccess, setIsSuccess] = useState(false);
|
const [isSuccess, setIsSuccess] = useState(false);
|
||||||
const [Initials, setInitials] = useState("");
|
const [Initials, setInitials] = useState("");
|
||||||
@@ -29,59 +25,40 @@ const ManageSign = () => {
|
|||||||
const imageRef = useRef(null);
|
const imageRef = useRef(null);
|
||||||
const initailsRef = useRef(null);
|
const initailsRef = useRef(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getLocalStorageValue();
|
fetchUserSign();
|
||||||
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
const fetchUserSign = async () => {
|
||||||
//function for get localstorage value first and than call another function.
|
const User = Parse.User.current();
|
||||||
const getLocalStorageValue = () => {
|
|
||||||
let User = JSON.parse(
|
|
||||||
localStorage.getItem(
|
|
||||||
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
appName =
|
|
||||||
localStorage.getItem("_appName") && localStorage.getItem("_appName");
|
|
||||||
if (User) {
|
if (User) {
|
||||||
fetchUserSign(User);
|
const userId = {
|
||||||
}
|
__type: "Pointer",
|
||||||
};
|
className: "_User",
|
||||||
|
objectId: User.id
|
||||||
const fetchUserSign = async (User) => {
|
};
|
||||||
const userId = {
|
try {
|
||||||
__type: "Pointer",
|
const signCls = `${appName}_Signature`;
|
||||||
className: "_User",
|
const signQuery = new Parse.Query(signCls);
|
||||||
objectId: User.objectId,
|
signQuery.equalTo("UserId", userId);
|
||||||
};
|
const signRes = await signQuery.first();
|
||||||
const strObj = JSON.stringify(userId);
|
if (signRes) {
|
||||||
const url =
|
const res = signRes.toJSON();
|
||||||
localStorage.getItem("baseUrl") +
|
setId(res.objectId);
|
||||||
`classes/${appName}_Signature?where={"UserId":${strObj}}&limit=1`;
|
setSignName(res?.SignatureName);
|
||||||
|
setImage(res.ImageURL);
|
||||||
const headers = {
|
if (res && res.Initials) {
|
||||||
"Content-Type": "application/json",
|
setInitials(res.Initials);
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
|
||||||
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
|
|
||||||
};
|
|
||||||
const res = await axios
|
|
||||||
.get(url, { headers: headers })
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.results.length > 0) {
|
|
||||||
setId(res.data.results[0].objectId);
|
|
||||||
setSignName(res.data.results[0].SignatureName);
|
|
||||||
setImage(res.data.results[0].ImageURL);
|
|
||||||
if (res.data.results[0] && res.data.results[0].Initials) {
|
|
||||||
setInitials(res.data.results[0].Initials);
|
|
||||||
setIsInitials(true);
|
setIsInitials(true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setSignName(User?.get("name") || "");
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
return res;
|
} catch (err) {
|
||||||
})
|
console.log("Err", err);
|
||||||
.catch((error) => {
|
alert(`${err.message}`);
|
||||||
console.log(error);
|
}
|
||||||
alert(`${error.message}`);
|
}
|
||||||
});
|
|
||||||
return res;
|
|
||||||
};
|
};
|
||||||
const handleSignatureChange = () => {
|
const handleSignatureChange = () => {
|
||||||
if (imageRef.current) {
|
if (imageRef.current) {
|
||||||
@@ -112,18 +89,6 @@ const ManageSign = () => {
|
|||||||
setIsInitials(false);
|
setIsInitials(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const handleReset = () => {
|
|
||||||
// if (canvasRef.current) {
|
|
||||||
// canvasRef.current.clear();
|
|
||||||
// }
|
|
||||||
// if (imageRef.current) {
|
|
||||||
// imageRef.current.value = "";
|
|
||||||
// }
|
|
||||||
// setImage("");
|
|
||||||
// setSignature("");
|
|
||||||
// setIsValue(false);
|
|
||||||
// setSignName("");
|
|
||||||
// };
|
|
||||||
const onImageChange = async (event) => {
|
const onImageChange = async (event) => {
|
||||||
if (canvasRef.current) {
|
if (canvasRef.current) {
|
||||||
canvasRef.current.clear();
|
canvasRef.current.clear();
|
||||||
@@ -140,10 +105,7 @@ const ManageSign = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const isUrl = image.includes("https");
|
const isUrl = image.includes("https");
|
||||||
|
|
||||||
if (!signName) {
|
if (!isvalue) {
|
||||||
setNameWarning(true);
|
|
||||||
|
|
||||||
} else if (!isvalue) {
|
|
||||||
setWarning(true);
|
setWarning(true);
|
||||||
setTimeout(() => setWarning(false), 1000);
|
setTimeout(() => setWarning(false), 1000);
|
||||||
} else {
|
} else {
|
||||||
@@ -151,29 +113,32 @@ const ManageSign = () => {
|
|||||||
const replaceSpace = signName.replace(/ /g, "_");
|
const replaceSpace = signName.replace(/ /g, "_");
|
||||||
let file;
|
let file;
|
||||||
if (signature) {
|
if (signature) {
|
||||||
file = base64StringtoFile(signature, `${replaceSpace}.png`);
|
file = base64StringtoFile(signature, `${replaceSpace}_sign.png`);
|
||||||
} else {
|
} else {
|
||||||
if (!isUrl) {
|
if (!isUrl) {
|
||||||
file = base64StringtoFile(image, `${replaceSpace}.png`);
|
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log("isUrl ", isUrl);
|
|
||||||
let imgUrl;
|
let imgUrl;
|
||||||
if (!isUrl) {
|
if (!isUrl) {
|
||||||
imgUrl = await uploadFile(file);
|
imgUrl = await uploadFile(file);
|
||||||
} else {
|
} else {
|
||||||
imgUrl = { data: { imageUrl: image } };
|
imgUrl = image;
|
||||||
}
|
}
|
||||||
let initialsUrl = "";
|
let initialsUrl = "";
|
||||||
if (Initials) {
|
const isInitialsUrl = Initials.includes("https");
|
||||||
const initialsImg = base64StringtoFile(Initials, `${replaceSpace}.png`);
|
if (!isInitialsUrl && Initials) {
|
||||||
|
const initialsImg = base64StringtoFile(
|
||||||
|
Initials,
|
||||||
|
`${replaceSpace}_initials.png`
|
||||||
|
);
|
||||||
initialsUrl = await uploadFile(initialsImg);
|
initialsUrl = await uploadFile(initialsImg);
|
||||||
}
|
}
|
||||||
if (imgUrl.data && imgUrl.data.imageUrl) {
|
if (imgUrl) {
|
||||||
await saveEntry({
|
await saveEntry({
|
||||||
name: signName,
|
name: signName,
|
||||||
url: imgUrl.data.imageUrl,
|
url: imgUrl,
|
||||||
initialsUrl: initialsUrl,
|
initialsUrl: initialsUrl
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,116 +156,58 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uploadFile = async (file) => {
|
const uploadFile = async (file) => {
|
||||||
let parseBaseUrl = localStorage.getItem("baseUrl");
|
try {
|
||||||
parseBaseUrl = parseBaseUrl.slice(0, -4);
|
const parseFile = new Parse.File(file.name, file);
|
||||||
const url = parseBaseUrl + `file_upload`;
|
const response = await parseFile.save();
|
||||||
const formData = new FormData();
|
if (response?.url()) {
|
||||||
formData.append("file", file);
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
const config = {
|
SaveFileSize(file.size, response.url(), tenantId);
|
||||||
headers: {
|
return response?.url();
|
||||||
"content-type": "multipart/form-data",
|
}
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
} catch (err) {
|
||||||
},
|
console.log("sign upload err", err);
|
||||||
onUploadProgress: function (progressEvent) {
|
setIsLoader(false);
|
||||||
let percentCompleted = Math.round(
|
alert(`${err.message}`);
|
||||||
(progressEvent.loaded * 100) / progressEvent.total
|
}
|
||||||
);
|
|
||||||
// setpercentage(percentCompleted);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const response = await axios
|
|
||||||
.post(url, formData, config)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.status === "Error") {
|
|
||||||
alert(res.data.message);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
setIsLoader(false);
|
|
||||||
alert(`${error.message}`);
|
|
||||||
});
|
|
||||||
return response;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveEntry = async (obj) => {
|
const saveEntry = async (obj) => {
|
||||||
|
const signCls = `${appName}_Signature`;
|
||||||
|
const User = Parse.User.current().id;
|
||||||
|
const userId = { __type: "Pointer", className: "_User", objectId: User };
|
||||||
if (id) {
|
if (id) {
|
||||||
const User = JSON.parse(
|
try {
|
||||||
localStorage.getItem(
|
const updateSign = new Parse.Object(signCls);
|
||||||
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
|
updateSign.id = id;
|
||||||
)
|
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
|
||||||
);
|
updateSign.set("ImageURL", obj.url);
|
||||||
const url =
|
updateSign.set("SignatureName", obj.name);
|
||||||
localStorage.getItem("baseUrl") +
|
updateSign.set("UserId", userId);
|
||||||
`classes/${localStorage.getItem("_appName")}_Signature/${id}`;
|
const res = await updateSign.save();
|
||||||
const body = {
|
setIsLoader(false);
|
||||||
Initials: obj.initialsUrl ? obj.initialsUrl.data.imageUrl : "",
|
setIsSuccess(true);
|
||||||
ImageURL: obj.url,
|
return res;
|
||||||
SignatureName: obj.name,
|
} catch (err) {
|
||||||
UserId: {
|
console.log(err);
|
||||||
__type: "Pointer",
|
setIsLoader(false);
|
||||||
className: "_User",
|
alert(`${err.message}`);
|
||||||
objectId: User.objectId,
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
|
||||||
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
|
|
||||||
};
|
|
||||||
const res = await axios
|
|
||||||
.put(url, body, { headers: headers })
|
|
||||||
.then((res) => {
|
|
||||||
// handleReset();
|
|
||||||
setIsLoader(false);
|
|
||||||
setIsSuccess(true);
|
|
||||||
return res;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
setIsLoader(false);
|
|
||||||
alert(`${error.message}`);
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
} else {
|
} else {
|
||||||
const User = JSON.parse(
|
try {
|
||||||
localStorage.getItem(
|
const updateSign = new Parse.Object(signCls);
|
||||||
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
|
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
|
||||||
)
|
updateSign.set("ImageURL", obj.url);
|
||||||
);
|
updateSign.set("SignatureName", obj.name);
|
||||||
const url =
|
updateSign.set("UserId", userId);
|
||||||
localStorage.getItem("baseUrl") +
|
const res = await updateSign.save();
|
||||||
`classes/${localStorage.getItem("_appName")}_Signature`;
|
setIsLoader(false);
|
||||||
const body = {
|
setIsSuccess(true);
|
||||||
Initials: obj.initialsUrl ? obj.initialsUrl.data.imageUrl : "",
|
return res;
|
||||||
ImageURL: obj.url,
|
} catch (err) {
|
||||||
SignatureName: obj.name,
|
console.log(err);
|
||||||
UserId: {
|
setIsLoader(false);
|
||||||
__type: "Pointer",
|
alert(`${err.message}`);
|
||||||
className: "_User",
|
}
|
||||||
objectId: User.objectId,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
|
||||||
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
|
|
||||||
};
|
|
||||||
const res = await axios
|
|
||||||
.post(url, body, { headers: headers })
|
|
||||||
.then((res) => {
|
|
||||||
// handleReset();
|
|
||||||
setIsLoader(false);
|
|
||||||
setIsSuccess(true);
|
|
||||||
return res;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
setIsLoader(false);
|
|
||||||
alert(`${error.message}`);
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSignatureBtn = () => {
|
const handleSignatureBtn = () => {
|
||||||
@@ -317,12 +224,15 @@ const ManageSign = () => {
|
|||||||
setIsValue(true);
|
setIsValue(true);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="relative h-full bg-white flex shadow rounded overflow-auto">
|
||||||
style={{
|
{isLoader && (
|
||||||
maxHeight: "500px",
|
<div className="absolute bg-black bg-opacity-75 z-50 w-full h-full flex justify-center items-center">
|
||||||
overflow: "auto",
|
<div
|
||||||
}}
|
style={{ color: "#3dd3e0" }}
|
||||||
>
|
className="loader-37 text-[45px]"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
<div
|
<div
|
||||||
className="alert alert-success successBox"
|
className="alert alert-success successBox"
|
||||||
@@ -332,12 +242,11 @@ const ManageSign = () => {
|
|||||||
Signature saved successfully!
|
Signature saved successfully!
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="mainDiv"
|
className="mainDiv"
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
paddingRight: "10px",
|
paddingRight: "10px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ margin: 20 }}>
|
<div style={{ margin: 20 }}>
|
||||||
@@ -346,64 +255,12 @@ const ManageSign = () => {
|
|||||||
fontWeight: "700",
|
fontWeight: "700",
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: "#000",
|
color: "#000",
|
||||||
paddingBottom: 8,
|
paddingBottom: 8
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Manage Signature
|
My Signature
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
<div className="signBlock mt-4">
|
||||||
<label
|
|
||||||
htmlFor="signName"
|
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
position: "relative",
|
|
||||||
paddingBottom: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Signer's Name
|
|
||||||
{nameWarning && (
|
|
||||||
<div
|
|
||||||
className="warning nameWarning"
|
|
||||||
style={{ fontSize: 12 }}
|
|
||||||
onAnimationEnd={() => setNameWarning(false)}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fas fa-exclamation-circle"
|
|
||||||
style={{ color: "#fab005", fontSize: 15 }}
|
|
||||||
></i>{" "}
|
|
||||||
Please fill input field
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="signName"
|
|
||||||
className="signInputManage"
|
|
||||||
value={signName}
|
|
||||||
style={{
|
|
||||||
border: "1px solid #ccc",
|
|
||||||
borderRadius: 4,
|
|
||||||
|
|
||||||
height: 35,
|
|
||||||
padding: "6px 12px",
|
|
||||||
marginBottom: 10,
|
|
||||||
fontSize: 12,
|
|
||||||
}}
|
|
||||||
required
|
|
||||||
onFocus={() => setNameWarning(false)}
|
|
||||||
onChange={(e) => setSignName(e.target.value)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<label
|
|
||||||
htmlFor="imgoverview"
|
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
paddingBottom: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Signature/Image
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="signBlock">
|
|
||||||
<div>
|
<div>
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
<div
|
<div
|
||||||
@@ -412,7 +269,7 @@ const ManageSign = () => {
|
|||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
width: "50%",
|
width: "50%",
|
||||||
paddingLeft: 10,
|
paddingLeft: 10
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -422,7 +279,7 @@ const ManageSign = () => {
|
|||||||
justifyContent: "space-around",
|
justifyContent: "space-around",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 10,
|
gap: 10,
|
||||||
marginBottom: 10,
|
marginBottom: 10
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
@@ -456,9 +313,7 @@ const ManageSign = () => {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
border: "2px solid #888"
|
||||||
border: "2px solid #888",
|
|
||||||
marginBottom: 6,
|
|
||||||
}}
|
}}
|
||||||
className="signatureCanvas"
|
className="signatureCanvas"
|
||||||
>
|
>
|
||||||
@@ -468,7 +323,7 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
objectFit: "contain",
|
objectFit: "contain"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -479,7 +334,7 @@ const ManageSign = () => {
|
|||||||
canvasProps={{
|
canvasProps={{
|
||||||
width: "456px",
|
width: "456px",
|
||||||
height: "180px",
|
height: "180px",
|
||||||
className: "signatureCanvas",
|
className: "signatureCanvas"
|
||||||
}}
|
}}
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
backgroundColor="rgb(255, 255, 255)"
|
||||||
onEnd={() =>
|
onEnd={() =>
|
||||||
@@ -492,10 +347,9 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between"
|
||||||
// width: 460,
|
|
||||||
}}
|
}}
|
||||||
className="penContainer"
|
className="penContainerDefault"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{!image && (
|
{!image && (
|
||||||
@@ -504,11 +358,10 @@ const ManageSign = () => {
|
|||||||
>
|
>
|
||||||
{allColor.map((data, key) => {
|
{allColor.map((data, key) => {
|
||||||
return (
|
return (
|
||||||
<img
|
<i
|
||||||
alt="black img"
|
|
||||||
style={{
|
style={{
|
||||||
border: "none",
|
|
||||||
margin: "5px",
|
margin: "5px",
|
||||||
|
color: data,
|
||||||
borderBottom:
|
borderBottom:
|
||||||
key === 0 && penColor === "blue"
|
key === 0 && penColor === "blue"
|
||||||
? "2px solid blue"
|
? "2px solid blue"
|
||||||
@@ -516,7 +369,7 @@ const ManageSign = () => {
|
|||||||
? "2px solid red"
|
? "2px solid red"
|
||||||
: key === 2 && penColor === "black"
|
: key === 2 && penColor === "black"
|
||||||
? "2px solid black"
|
? "2px solid black"
|
||||||
: "2px solid white",
|
: "2px solid white"
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (key === 0) {
|
if (key === 0) {
|
||||||
@@ -528,10 +381,10 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={key}
|
key={key}
|
||||||
src={data}
|
className="fa solid fa-pen-nib"
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
></i>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -540,7 +393,7 @@ const ManageSign = () => {
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
className="clearbtn"
|
className="clearbtn cursor-pointer"
|
||||||
onClick={() => handleClear()}
|
onClick={() => handleClear()}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
@@ -565,23 +418,16 @@ const ManageSign = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
<div style={{ margin: "6px 5px 18px" }}>
|
<div style={{ margin: "6px 5px 18px" }}>
|
||||||
<span
|
<span className="signature">Initials</span>
|
||||||
// onClick={() => handleSignatureBtn()}
|
|
||||||
className="signature"
|
|
||||||
>
|
|
||||||
Initials
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{isInitials ? (
|
{isInitials ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
border: "2px solid #888"
|
||||||
border: "2px solid #888",
|
|
||||||
marginBottom: 6,
|
|
||||||
}}
|
}}
|
||||||
className="signatureCanvas"
|
className="intialSignature"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="preview image"
|
alt="preview image"
|
||||||
@@ -589,7 +435,7 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
objectFit: "contain",
|
objectFit: "contain"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -598,9 +444,7 @@ const ManageSign = () => {
|
|||||||
ref={initailsRef}
|
ref={initailsRef}
|
||||||
penColor={initialPen}
|
penColor={initialPen}
|
||||||
canvasProps={{
|
canvasProps={{
|
||||||
width: "456px",
|
className: "intialSignature"
|
||||||
height: "180px",
|
|
||||||
className: "signatureCanvas",
|
|
||||||
}}
|
}}
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
backgroundColor="rgb(255, 255, 255)"
|
||||||
onEnd={() =>
|
onEnd={() =>
|
||||||
@@ -613,21 +457,19 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between"
|
||||||
// width: 460,
|
|
||||||
}}
|
}}
|
||||||
className="penContainer"
|
className="penContainerInitial"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{!isInitials && (
|
{!isInitials && (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
{allColor.map((data, key) => {
|
{allColor.map((data, key) => {
|
||||||
return (
|
return (
|
||||||
<img
|
<i
|
||||||
alt="pen"
|
|
||||||
style={{
|
style={{
|
||||||
border: "none",
|
|
||||||
margin: "5px",
|
margin: "5px",
|
||||||
|
color: data,
|
||||||
borderBottom:
|
borderBottom:
|
||||||
key === 0 && initialPen === "blue"
|
key === 0 && initialPen === "blue"
|
||||||
? "2px solid blue"
|
? "2px solid blue"
|
||||||
@@ -635,7 +477,7 @@ const ManageSign = () => {
|
|||||||
? "2px solid red"
|
? "2px solid red"
|
||||||
: key === 2 && initialPen === "black"
|
: key === 2 && initialPen === "black"
|
||||||
? "2px solid black"
|
? "2px solid black"
|
||||||
: "2px solid white",
|
: "2px solid white"
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (key === 0) {
|
if (key === 0) {
|
||||||
@@ -647,10 +489,10 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={key}
|
key={key}
|
||||||
src={data}
|
className="fa solid fa-pen-nib"
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
></i>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -659,7 +501,7 @@ const ManageSign = () => {
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
className="clearbtn"
|
className="clearbtn cursor-pointer"
|
||||||
onClick={() => handleClearInitials()}
|
onClick={() => handleClearInitials()}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
@@ -687,11 +529,6 @@ const ManageSign = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isLoader && (
|
|
||||||
<div className="loaderContainer">
|
|
||||||
<div className="loader"></div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1,20 +1,41 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
import "./LegaDrive.css";
|
import "../styles/opensigndrive.css";
|
||||||
import loader from "../../assests/loader2.gif";
|
import loader from "../assets/images/loader2.gif";
|
||||||
import PdfFileComponent from "./FolderDrive/legaDriveComponent";
|
import { themeColor, iconColor } from "../constant/const";
|
||||||
import { themeColor, iconColor } from "../../utils/ThemeColor/backColor";
|
import { getDrive } from "../constant/Utils";
|
||||||
import { getDrive } from "../../utils/Utils";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Title from "../component/Title";
|
import Title from "../components/Title";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import ModalUi from "../../premitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
const DriveBody = React.lazy(
|
||||||
function PdfFile() {
|
() => import("../components/opensigndrive/DriveBody")
|
||||||
|
);
|
||||||
|
const Loader = () => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
function Opensigndrive() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const scrollRef = useRef(null);
|
const scrollRef = useRef(null);
|
||||||
const [isList, setIsList] = useState(false);
|
const [isList, setIsList] = useState(false);
|
||||||
const [selectedSort, setSelectedSort] = useState("Date");
|
const [selectedSort, setSelectedSort] = useState("Date");
|
||||||
const [sortingOrder, setSortingOrder] = useState("Decending");
|
const [sortingOrder, setSortingOrder] = useState("Descending");
|
||||||
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();
|
||||||
@@ -30,6 +51,17 @@ function PdfFile() {
|
|||||||
const [folderName, setFolderName] = useState([]);
|
const [folderName, setFolderName] = useState([]);
|
||||||
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
||||||
const [isNewFol, setIsNewFol] = useState(false);
|
const [isNewFol, setIsNewFol] = useState(false);
|
||||||
|
const [skip, setSkip] = useState(0);
|
||||||
|
const limit = 100;
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const sortOrder = ["Ascending", "Descending"];
|
||||||
|
const sortingValue = ["Name", "Date"];
|
||||||
|
const orderName = {
|
||||||
|
Ascending: "Ascending",
|
||||||
|
Descending: "Descending",
|
||||||
|
Name: "Name",
|
||||||
|
Date: "Date"
|
||||||
|
};
|
||||||
const currentUser =
|
const currentUser =
|
||||||
localStorage.getItem(
|
localStorage.getItem(
|
||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
@@ -40,102 +72,83 @@ function PdfFile() {
|
|||||||
const jsonCurrentUser = JSON.parse(currentUser);
|
const jsonCurrentUser = JSON.parse(currentUser);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (docId) {
|
getPdfDocumentList();
|
||||||
getPdfFolderDocumentList();
|
// eslint-disable-next-line
|
||||||
} else {
|
|
||||||
getPdfDocumentList();
|
|
||||||
}
|
|
||||||
}, [docId]);
|
}, [docId]);
|
||||||
|
|
||||||
//function for get all pdf document list
|
//function for get all pdf document list
|
||||||
const getPdfDocumentList = async () => {
|
const getPdfDocumentList = async (disbaleLoading) => {
|
||||||
const load = {
|
setLoading(true);
|
||||||
isLoad: true,
|
if (!disbaleLoading) {
|
||||||
message: "This might take some time"
|
setIsLoading({ isLoad: true, message: "This might take some time" });
|
||||||
};
|
}
|
||||||
let driveDetails;
|
|
||||||
setIsLoading(load);
|
|
||||||
try {
|
try {
|
||||||
driveDetails = await getDrive();
|
const driveDetails = await getDrive(docId, skip, limit);
|
||||||
if (driveDetails) {
|
if (driveDetails && driveDetails === "Error: Something went wrong!") {
|
||||||
if (driveDetails.length > 0) {
|
|
||||||
setPdfData(driveDetails);
|
|
||||||
sortApps(null, null, driveDetails);
|
|
||||||
}
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
name: "OpenSign™ Drive",
|
|
||||||
objectId: ""
|
|
||||||
}
|
|
||||||
];
|
|
||||||
setFolderName(data);
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
} else if (driveDetails === "Error: Something went wrong!") {
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError("Error: Something went wrong!");
|
||||||
setIsLoading(loadObj);
|
} else if (driveDetails && driveDetails.length > 0) {
|
||||||
|
setSkip((prevSkip) => prevSkip + limit);
|
||||||
|
sortingData(null, null, driveDetails, true);
|
||||||
|
}
|
||||||
|
if (!docId) {
|
||||||
|
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: "something went wrong"
|
||||||
});
|
});
|
||||||
}
|
} finally {
|
||||||
};
|
setLoading(false);
|
||||||
//function for get parent folder document list
|
setIsLoading({
|
||||||
const getPdfFolderDocumentList = async () => {
|
isLoad: false
|
||||||
const load = {
|
|
||||||
isLoad: true,
|
|
||||||
message: "This might take some time"
|
|
||||||
};
|
|
||||||
setIsLoading(load);
|
|
||||||
let driveDetails;
|
|
||||||
try {
|
|
||||||
driveDetails = await getDrive(docId);
|
|
||||||
|
|
||||||
if (driveDetails) {
|
|
||||||
if (driveDetails.length > 0) {
|
|
||||||
setPdfData(driveDetails);
|
|
||||||
sortApps(null, null, driveDetails);
|
|
||||||
} else {
|
|
||||||
setPdfData([]);
|
|
||||||
}
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
} else if (driveDetails === "Error: Something went wrong!") {
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setHandleError("Error: Something went wrong!");
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
setIsAlert({
|
|
||||||
isShow: true,
|
|
||||||
alertMessage: "something went wrong!"
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for get all pdf document list
|
//function to fetch drive details list on scroll bottom
|
||||||
const getParentFolder = async () => {
|
const handleScroll = () => {
|
||||||
setIsFolder(true);
|
//get document of render openSign-drive component using id
|
||||||
|
const documentList = document.getElementById("renderList");
|
||||||
|
//documentList.clientHeight property returns the height of an element's content area, including padding but not including borders, margins, or scrollbars.
|
||||||
|
//documentList.scrollHeight property returns the entire height of an element,including the parts that are not visible due to overflow..
|
||||||
|
// documentList.scrollTop property show height of element, how much the content has been scrolled from the top.
|
||||||
|
// When the sum of scrollTop and clientHeight is equal to scrollHeight, it means that the user has scrolled to the bottom of the div.
|
||||||
|
if (
|
||||||
|
documentList &&
|
||||||
|
documentList.scrollTop + documentList.clientHeight >=
|
||||||
|
documentList.scrollHeight
|
||||||
|
) {
|
||||||
|
//disableLoading is used disable initial loader
|
||||||
|
const disableLoading = true;
|
||||||
|
// If the fetched data length is less than the limit, it means there's no more data to fetch
|
||||||
|
|
||||||
|
if (!loading && pdfData.length % 100 === 0) {
|
||||||
|
getPdfDocumentList(disableLoading);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
//useEffect is used to call handleScroll function on scrolling event
|
||||||
|
useEffect(() => {
|
||||||
|
const documentList = document.getElementById("renderList");
|
||||||
|
if (documentList) {
|
||||||
|
documentList.addEventListener("scroll", handleScroll);
|
||||||
|
return () => {
|
||||||
|
documentList.removeEventListener("scroll", handleScroll);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [loading, sortingOrder, selectedSort]); // Add/remove scroll event listener when loading changes
|
||||||
|
|
||||||
//function for handle folder name path
|
//function for handle folder name path
|
||||||
const handleRoute = (index) => {
|
const handleRoute = (index) => {
|
||||||
|
setPdfData([]);
|
||||||
|
setSkip(0);
|
||||||
const updateFolderName = folderName.filter((x, i) => {
|
const updateFolderName = folderName.filter((x, i) => {
|
||||||
if (i <= index) {
|
if (i <= index) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setFolderName(updateFolderName);
|
setFolderName(updateFolderName);
|
||||||
const getLastId = updateFolderName[updateFolderName.length - 1];
|
const getLastId = updateFolderName[updateFolderName.length - 1];
|
||||||
setDocId(getLastId.objectId);
|
setDocId(getLastId.objectId);
|
||||||
@@ -206,34 +219,38 @@ function PdfFile() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortingApp = (appInfo, type, order) => {
|
//function to use sorting document list according to type and order
|
||||||
if (type === "Name") {
|
const sortedBy = (appInfo, type, order) => {
|
||||||
if (order === "Accending") {
|
if (type === orderName.Name) {
|
||||||
|
if (order === orderName.Ascending) {
|
||||||
return appInfo.sort((a, b) => (a.Name > b.Name ? 1 : -1));
|
return appInfo.sort((a, b) => (a.Name > b.Name ? 1 : -1));
|
||||||
} else if (order === "Decending") {
|
} else if (order === orderName.Descending) {
|
||||||
return appInfo.sort((a, b) => (a.Name > b.Name ? -1 : 1));
|
return appInfo.sort((a, b) => (a.Name > b.Name ? -1 : 1));
|
||||||
}
|
}
|
||||||
} else if (type === "Date") {
|
} else if (type === orderName.Date) {
|
||||||
if (order === "Accending") {
|
if (order === orderName.Ascending) {
|
||||||
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1));
|
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1));
|
||||||
} else if (order === "Decending") {
|
} else if (order === orderName.Descending) {
|
||||||
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortApps = (type, order, driveDetails) => {
|
//function to use get sorting type, order and document list to sort
|
||||||
const selectedSortType = type ? type : selectedSort ? selectedSort : "Date";
|
const sortingData = (type, order, driveDetails, isInitial) => {
|
||||||
const sortOrder = order ? order : sortingOrder ? sortingOrder : "Decending";
|
const selectedSortType = type ? type : selectedSort;
|
||||||
|
const sortOrder = order ? order : sortingOrder;
|
||||||
|
|
||||||
let sortingData = driveDetails;
|
//check isInitial true it means sort previous 20 and get on scrolling 20 = 40 document list
|
||||||
if (selectedSortType === "Name") {
|
const allPdfData = isInitial ? [...pdfData, ...driveDetails] : driveDetails;
|
||||||
sortingApp(sortingData, "Name", sortOrder);
|
//call sortedBy function according to selected Type and order
|
||||||
} else if (selectedSortType === "Date") {
|
if (selectedSortType === orderName.Name) {
|
||||||
sortingApp(sortingData, "Date", sortOrder);
|
sortedBy(allPdfData, orderName.Name, sortOrder);
|
||||||
|
} else if (selectedSortType === orderName.Date) {
|
||||||
|
sortedBy(allPdfData, orderName.Date, sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
setPdfData(sortingData);
|
setPdfData(allPdfData);
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for handle auto scroll on folder path
|
//function for handle auto scroll on folder path
|
||||||
@@ -300,9 +317,10 @@ function PdfFile() {
|
|||||||
// Cleanup the event listener when the component unmounts
|
// Cleanup the event listener when the component unmounts
|
||||||
document.removeEventListener("click", closeMenuOnOutsideClick);
|
document.removeEventListener("click", closeMenuOnOutsideClick);
|
||||||
};
|
};
|
||||||
}, [isShowSort || isNewFol]);
|
// eslint-disable-next-line
|
||||||
|
}, [isShowSort, isNewFol]);
|
||||||
|
|
||||||
const handleFolderTab = (folderData, isMove) => {
|
const handleFolderTab = (folderData) => {
|
||||||
return folderData.map((data, id) => {
|
return folderData.map((data, id) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={id}>
|
<React.Fragment key={id}>
|
||||||
@@ -336,7 +354,7 @@ function PdfFile() {
|
|||||||
setError("");
|
setError("");
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="folderComponent ">
|
<div style={{ backgroundColor: "white" }} className="folderComponent">
|
||||||
<Title title={"OpenSign™ Drive"} drive={true} />
|
<Title title={"OpenSign™ Drive"} drive={true} />
|
||||||
<div>
|
<div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
@@ -444,9 +462,7 @@ function PdfFile() {
|
|||||||
></div>
|
></div>
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{ background: themeColor }}
|
||||||
background: themeColor()
|
|
||||||
}}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
className="finishBtn"
|
className="finishBtn"
|
||||||
>
|
>
|
||||||
@@ -524,7 +540,7 @@ function PdfFile() {
|
|||||||
<i
|
<i
|
||||||
className="fa fa-plus-square"
|
className="fa fa-plus-square"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{ fontSize: "25px", color: `${iconColor()}` }}
|
style={{ fontSize: "25px", color: `${iconColor}` }}
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -543,7 +559,7 @@ function PdfFile() {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="dropdown-item itemColor"
|
className="dropdown-item itemColor"
|
||||||
onClick={() => getParentFolder()}
|
onClick={() => setIsFolder(true)}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
style={{ marginRight: "5px" }}
|
style={{ marginRight: "5px" }}
|
||||||
@@ -588,13 +604,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}
|
||||||
@@ -607,95 +623,56 @@ function PdfFile() {
|
|||||||
aria-labelledby="dropdownMenuButton"
|
aria-labelledby="dropdownMenuButton"
|
||||||
aria-expanded={isShowSort ? "true" : "false"}
|
aria-expanded={isShowSort ? "true" : "false"}
|
||||||
>
|
>
|
||||||
<span
|
{sortingValue.map((value, ind) => {
|
||||||
onClick={() => {
|
return (
|
||||||
setSelectedSort("Name");
|
<span
|
||||||
sortApps("Name", null, pdfData);
|
key={ind}
|
||||||
}}
|
onClick={() => {
|
||||||
className="dropdown-item itemColor"
|
setSelectedSort(value);
|
||||||
>
|
sortingData(value, null, pdfData);
|
||||||
{selectedSort !== "Name" ? (
|
}}
|
||||||
<i
|
className="dropdown-item itemColor"
|
||||||
className="fa fa-arrow-up"
|
style={{
|
||||||
aria-hidden="true"
|
paddingLeft: selectedSort !== value && "33px"
|
||||||
style={{ marginRight: "5px" }}
|
}}
|
||||||
></i>
|
>
|
||||||
) : (
|
{selectedSort === value && (
|
||||||
<i
|
<i
|
||||||
className="fa fa-check"
|
className="fa fa-check"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{ marginRight: "5px" }}
|
style={{ marginRight: "5px" }}
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
Name
|
{value}
|
||||||
</span>
|
</span>
|
||||||
<span
|
);
|
||||||
onClick={() => {
|
})}
|
||||||
setSelectedSort("Date");
|
|
||||||
sortApps("Date", null, pdfData);
|
|
||||||
}}
|
|
||||||
className="dropdown-item itemColor"
|
|
||||||
>
|
|
||||||
{selectedSort !== "Date" ? (
|
|
||||||
<i
|
|
||||||
className="fa fa-arrow-up"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ marginRight: "5px" }}
|
|
||||||
></i>
|
|
||||||
) : (
|
|
||||||
<i
|
|
||||||
className="fa fa-check"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ marginRight: "5px" }}
|
|
||||||
></i>
|
|
||||||
)}
|
|
||||||
Date
|
|
||||||
</span>
|
|
||||||
<hr className="hrStyle" />
|
<hr className="hrStyle" />
|
||||||
<span
|
{sortOrder.map((order, ind) => {
|
||||||
onClick={() => {
|
return (
|
||||||
setSortingOrder("Accending");
|
<span
|
||||||
sortApps(null, "Accending", pdfData);
|
key={ind}
|
||||||
}}
|
onClick={() => {
|
||||||
className="dropdown-item itemColor"
|
setSortingOrder(order);
|
||||||
>
|
sortingData(null, order, pdfData);
|
||||||
{sortingOrder !== "Accending" ? (
|
}}
|
||||||
<i
|
className="dropdown-item itemColor"
|
||||||
className="fa fa-arrow-up"
|
style={{
|
||||||
aria-hidden="true"
|
paddingLeft: sortingOrder !== order && "33px"
|
||||||
style={{ marginRight: "5px" }}
|
}}
|
||||||
></i>
|
>
|
||||||
) : (
|
{sortingOrder === order && (
|
||||||
<i
|
<i
|
||||||
className="fa fa-check"
|
className="fa fa-check"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{ marginRight: "5px" }}
|
style={{ marginRight: "5px" }}
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
Accending
|
{order}
|
||||||
</span>
|
</span>
|
||||||
<span
|
);
|
||||||
onClick={() => {
|
})}
|
||||||
setSortingOrder("Decending");
|
|
||||||
sortApps(null, "Decending", pdfData);
|
|
||||||
}}
|
|
||||||
className="dropdown-item itemColor"
|
|
||||||
>
|
|
||||||
{sortingOrder !== "Decending" ? (
|
|
||||||
<i
|
|
||||||
className="fa fa-arrow-up"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ marginRight: "5px" }}
|
|
||||||
></i>
|
|
||||||
) : (
|
|
||||||
<i
|
|
||||||
className="fa fa-check"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ marginRight: "5px" }}
|
|
||||||
></i>
|
|
||||||
)}
|
|
||||||
Decending
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -705,7 +682,7 @@ function PdfFile() {
|
|||||||
<i
|
<i
|
||||||
onClick={() => setIsList(!isList)}
|
onClick={() => setIsList(!isList)}
|
||||||
className="fa fa-th-large"
|
className="fa fa-th-large"
|
||||||
style={{ fontSize: "24px", color: `${iconColor()}` }}
|
style={{ fontSize: "24px", color: `${iconColor}` }}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -714,7 +691,7 @@ function PdfFile() {
|
|||||||
<i
|
<i
|
||||||
className="fa fa-list"
|
className="fa fa-list"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style={{ fontSize: "23px", color: `${iconColor()}` }}
|
style={{ fontSize: "23px", color: `${iconColor}` }}
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -735,18 +712,23 @@ function PdfFile() {
|
|||||||
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<PdfFileComponent
|
<React.Suspense fallback={<Loader />}>
|
||||||
pdfData={pdfData}
|
<DriveBody
|
||||||
setFolderName={setFolderName}
|
pdfData={pdfData}
|
||||||
setIsLoading={setIsLoading}
|
setFolderName={setFolderName}
|
||||||
setDocId={setDocId}
|
setIsLoading={setIsLoading}
|
||||||
getPdfFolderDocumentList={getPdfFolderDocumentList}
|
setDocId={setDocId}
|
||||||
getPdfDocumentList={getPdfDocumentList}
|
getPdfDocumentList={getPdfDocumentList}
|
||||||
isDocId={docId}
|
isDocId={docId}
|
||||||
setPdfData={setPdfData}
|
setPdfData={setPdfData}
|
||||||
isList={isList}
|
isList={isList}
|
||||||
setIsAlert={setIsAlert}
|
setIsAlert={setIsAlert}
|
||||||
/>
|
setSkip={setSkip}
|
||||||
|
/>
|
||||||
|
{loading && (
|
||||||
|
<div style={{ textAlign: "center" }}>Loading...</div>
|
||||||
|
)}
|
||||||
|
</React.Suspense>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -755,4 +737,4 @@ function PdfFile() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfFile;
|
export default Opensigndrive;
|
||||||
@@ -2,20 +2,19 @@ import React, { useState, useEffect } from "react";
|
|||||||
import "../styles/pgsignup.css";
|
import "../styles/pgsignup.css";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { fetchAppInfo, showTenantName } from "../redux/actions/index";
|
import { useDispatch } from "react-redux";
|
||||||
import { connect } from "react-redux";
|
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
|
import { appInfo } from "../constant/appinfo";
|
||||||
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
|
|
||||||
const appId = localStorage.getItem("AppID12");
|
const PgSignUp = () => {
|
||||||
const server = localStorage.getItem("BaseUrl12");
|
|
||||||
Parse.serverURL = server;
|
|
||||||
Parse.initialize(appId);
|
|
||||||
const PgSignUp = (props) => {
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("BaseUrl12"));
|
const dispatch = useDispatch();
|
||||||
const [parseAppId] = useState(localStorage.getItem("AppID12"));
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: ""
|
confirmPassword: ""
|
||||||
@@ -28,12 +27,7 @@ const PgSignUp = (props) => {
|
|||||||
|
|
||||||
// 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(() => {
|
||||||
// Parse.User.logOut()
|
dispatch(fetchAppInfo());
|
||||||
props.fetchAppInfo(
|
|
||||||
localStorage.getItem("domain"),
|
|
||||||
localStorage.getItem("BaseUrl12"),
|
|
||||||
localStorage.getItem("AppID12")
|
|
||||||
);
|
|
||||||
handleSignedUpUser();
|
handleSignedUpUser();
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
@@ -224,8 +218,8 @@ const PgSignUp = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigation = async (sessionToken) => {
|
const handleNavigation = async (sessionToken) => {
|
||||||
const baseUrl = localStorage.getItem("BaseUrl12");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("AppID12");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const res = await axios.get(baseUrl + "users/me", {
|
const res = await axios.get(baseUrl + "users/me", {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Parse-Session-Token": sessionToken,
|
"X-Parse-Session-Token": sessionToken,
|
||||||
@@ -251,8 +245,8 @@ const PgSignUp = (props) => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
let userRoles = [];
|
let userRoles = [];
|
||||||
if (props.appInfo.settings) {
|
if (appInfo.settings) {
|
||||||
let userSettings = props.appInfo.settings;
|
let userSettings = appInfo.settings;
|
||||||
|
|
||||||
//Get Current user roles
|
//Get Current user roles
|
||||||
let url = `${baseUrl}functions/UserGroups`;
|
let url = `${baseUrl}functions/UserGroups`;
|
||||||
@@ -299,8 +293,6 @@ const PgSignUp = (props) => {
|
|||||||
"extended_class",
|
"extended_class",
|
||||||
element.extended_class
|
element.extended_class
|
||||||
);
|
);
|
||||||
localStorage.setItem("userpointer", element.userpointer);
|
|
||||||
|
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
@@ -329,8 +321,8 @@ const PgSignUp = (props) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -361,15 +353,15 @@ const PgSignUp = (props) => {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -407,11 +399,11 @@ const PgSignUp = (props) => {
|
|||||||
localStorage.setItem("pageType", element.pageType);
|
localStorage.setItem("pageType", element.pageType);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
const redirectUrl =
|
const redirectUrl =
|
||||||
location?.state?.from ||
|
location?.state?.from ||
|
||||||
`/${element.pageType}/${element.pageId}`;
|
`/${element.pageType}/${element.pageId}`;
|
||||||
|
|
||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
@@ -547,15 +539,4 @@ const PgSignUp = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
export default PgSignUp;
|
||||||
if (Object.keys(state.appInfo).length !== 0) {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: true };
|
|
||||||
} else {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: false };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, {
|
|
||||||
fetchAppInfo,
|
|
||||||
showTenantName
|
|
||||||
})(PgSignUp);
|
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { NavLink, useNavigate } from "react-router-dom";
|
||||||
|
import checkmark from "../assets/images/checkmark.png";
|
||||||
|
import plansArr from "../json/plansArr.json";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import Parse from "parse";
|
||||||
|
const listItemStyle = {
|
||||||
|
paddingLeft: "20px", // Add padding to create space for the image
|
||||||
|
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
|
||||||
|
backgroundPosition: "left",
|
||||||
|
backgroundRepeat: "no-repeat",
|
||||||
|
backgroundSize: "16px 16px" // Adjust the size of the image
|
||||||
|
};
|
||||||
|
|
||||||
|
const PlanSubscriptions = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [yearlyVisible, setYearlyVisible] = useState(false);
|
||||||
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
|
||||||
|
const userDetails = JSON.parse(localStorage.getItem("userDetails"));
|
||||||
|
const name =
|
||||||
|
userDetails && userDetails.name ? "first_name=" + userDetails.name : "";
|
||||||
|
const email =
|
||||||
|
userDetails && userDetails.email ? "&email=" + userDetails.email : "";
|
||||||
|
const company =
|
||||||
|
userDetails && userDetails.company
|
||||||
|
? "&company_name=" + userDetails.company
|
||||||
|
: "";
|
||||||
|
const phone =
|
||||||
|
userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : "";
|
||||||
|
const details =
|
||||||
|
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
||||||
|
name +
|
||||||
|
email +
|
||||||
|
company +
|
||||||
|
phone;
|
||||||
|
useEffect(() => {
|
||||||
|
// if (localStorage.getItem("accesstoken")) {
|
||||||
|
setIsLoader(false);
|
||||||
|
// } else {
|
||||||
|
// navigate("/", { replace: true });
|
||||||
|
// }
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleFreePlan = async () => {
|
||||||
|
setIsLoader(true);
|
||||||
|
try {
|
||||||
|
const params = { userId: Parse.User.current().id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "success" && res.result === "already subscribed!") {
|
||||||
|
setIsLoader(false);
|
||||||
|
alert("You have already subscribed to plan!");
|
||||||
|
} else if (res.status === "success") {
|
||||||
|
setIsLoader(false);
|
||||||
|
navigate("/");
|
||||||
|
} else if (res.status === "error") {
|
||||||
|
setIsLoader(false);
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setIsLoader(false);
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Title title={"Subscriptions"} />
|
||||||
|
{isLoader ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
overflowY: "auto",
|
||||||
|
maxHeight: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div id="monthlyPlans" className="block my-2">
|
||||||
|
<div className="flex flex-col justify-center items-center w-full">
|
||||||
|
<div className="mb-6 mt-2 flex flex-row border-[1px] p-2 border-gray-300 rounded text-sm">
|
||||||
|
<span
|
||||||
|
onClick={() => setYearlyVisible(false)}
|
||||||
|
className={`${
|
||||||
|
!yearlyVisible
|
||||||
|
? "bg-[#002862] text-white"
|
||||||
|
: "bg-white text-black"
|
||||||
|
} px-4 py-1 rounded cursor-pointer`}
|
||||||
|
>
|
||||||
|
Monthly
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
onClick={() => setYearlyVisible(true)}
|
||||||
|
className={`${
|
||||||
|
yearlyVisible
|
||||||
|
? "bg-[#002862] text-white"
|
||||||
|
: "bg-white text-black"
|
||||||
|
} px-4 py-1 rounded cursor-pointer`}
|
||||||
|
>
|
||||||
|
Yearly (10% off)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ul className="flex flex-col md:flex-row h-full bg-white justify-center">
|
||||||
|
{plansArr.map((item) => (
|
||||||
|
<li
|
||||||
|
className="flex flex-col md:my-0 text-center border-collapse border-[1px] border-gray-300 w-[260px]"
|
||||||
|
key={item.planName}
|
||||||
|
>
|
||||||
|
<div className="p-2 flex flex-col justify-center items-center min-h-[320px]">
|
||||||
|
<h3 className="text-[#002862] uppercase">
|
||||||
|
{item.planName}
|
||||||
|
</h3>
|
||||||
|
<div className="w-[150px] h-[150px]">
|
||||||
|
<img
|
||||||
|
className="icon-basic mx-auto"
|
||||||
|
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
|
||||||
|
alt="freeimg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="">
|
||||||
|
<span className="text-3xl">
|
||||||
|
{item.currency && <small>{item.currency}</small>}
|
||||||
|
{yearlyVisible
|
||||||
|
? item?.yearlyPrice
|
||||||
|
: item.monthlyPrice}
|
||||||
|
</span>
|
||||||
|
<p className="font-semibold pt-2 text-sm">
|
||||||
|
{yearlyVisible ? "Billed Yearly" : "Billed Monthly"}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
item.subtitle.length <= 32
|
||||||
|
? "w-[150px] h-[40px] text-center"
|
||||||
|
: ""
|
||||||
|
} text-sm text-center my-2`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
|
backgroundColor: item.subtitlecolor
|
||||||
|
? item.subtitlecolor
|
||||||
|
: "white"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.subtitle.includes("<") ? (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: item.subtitle
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span>{item.subtitle}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{item.url ? (
|
||||||
|
<NavLink
|
||||||
|
to={
|
||||||
|
item.btnText === "Subscribe"
|
||||||
|
? yearlyVisible
|
||||||
|
? item.yearlyUrl + details
|
||||||
|
: item.url + details
|
||||||
|
: item.url
|
||||||
|
}
|
||||||
|
className="bg-[#002862] w-full mt-1 text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer"
|
||||||
|
target={item.target}
|
||||||
|
>
|
||||||
|
{item.btnText}
|
||||||
|
</NavLink>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
className="bg-[#002862] w-full mt-1 text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer"
|
||||||
|
onClick={() => handleFreePlan()}
|
||||||
|
>
|
||||||
|
{item.btnText}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<hr className="w-full bg-gray-300 h-[0.5px]" />
|
||||||
|
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
||||||
|
{item.benefits.map((subitem, index) => (
|
||||||
|
<li style={listItemStyle} key={index} className="m-1">
|
||||||
|
<span style={{ position: "relative" }}>
|
||||||
|
{subitem}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
className="text-sm"
|
||||||
|
>
|
||||||
|
<hr
|
||||||
|
className={"border-[1px] border-gray-300 w-[20%]"}
|
||||||
|
style={{ color: "grey" }}
|
||||||
|
/>
|
||||||
|
<span style={{ color: "grey" }} className="px-2 ">
|
||||||
|
or
|
||||||
|
</span>
|
||||||
|
<hr
|
||||||
|
className={"border-[1px] border-gray-300 w-[20%]"}
|
||||||
|
style={{ color: "grey" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center w-full items-center">
|
||||||
|
<h3 className="text-[#002862] mt-1 mb-2">
|
||||||
|
Host it yourself for free
|
||||||
|
</h3>
|
||||||
|
<NavLink
|
||||||
|
to={"https://github.com/OpenSignLabs/OpenSign"}
|
||||||
|
className="bg-[#002862] w-[200px] text-center text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer"
|
||||||
|
target={"_blank"}
|
||||||
|
>
|
||||||
|
Visit Github
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default PlanSubscriptions;
|
||||||
@@ -12,6 +12,7 @@ const Report = () => {
|
|||||||
const [List, setList] = useState([]);
|
const [List, setList] = useState([]);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
const [reportName, setReportName] = useState("");
|
const [reportName, setReportName] = useState("");
|
||||||
|
const [reporthelp, setReportHelp] = useState("");
|
||||||
const [actions, setActions] = useState([]);
|
const [actions, setActions] = useState([]);
|
||||||
const [heading, setHeading] = useState([]);
|
const [heading, setHeading] = useState([]);
|
||||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||||
@@ -53,18 +54,17 @@ const Report = () => {
|
|||||||
setHeading(json.heading);
|
setHeading(json.heading);
|
||||||
setReportName(json.reportName);
|
setReportName(json.reportName);
|
||||||
setForm(json.form);
|
setForm(json.form);
|
||||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
setReportHelp(json?.helpMsg)
|
||||||
Parse.initialize(localStorage.getItem("AppID12"));
|
|
||||||
const currentUser = Parse.User.current().id;
|
const currentUser = Parse.User.current().id;
|
||||||
|
|
||||||
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("parseAppId"),
|
||||||
sessiontoken: localStorage.getItem("accesstoken")
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
||||||
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
|
const url = `${localStorage.getItem("baseUrl")}/functions/getReport`;
|
||||||
const res = await axios.post(url, params, {
|
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
|
||||||
@@ -158,6 +158,7 @@ const Report = () => {
|
|||||||
isMoreDocs={isMoreDocs}
|
isMoreDocs={isMoreDocs}
|
||||||
docPerPage={docPerPage}
|
docPerPage={docPerPage}
|
||||||
form={form}
|
form={form}
|
||||||
|
report_help={reporthelp}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<PageNotFound prefix={"Report"} />
|
<PageNotFound prefix={"Report"} />
|
||||||
@@ -1,28 +1,31 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { connect } from "react-redux";
|
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { fetchAppInfo, showTenantName } from "../redux/actions";
|
import { useNavigate, NavLink, useLocation } 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";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
const Signup = (props) => {
|
import { appInfo } from "../constant/appinfo";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
const Signup = () => {
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [phone, setPhone] = useState("");
|
const [phone, setPhone] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [company, setCompany] = useState("");
|
const [company, setCompany] = useState("");
|
||||||
const [jobTitle, setJobTitle] = useState("");
|
const [jobTitle, setJobTitle] = useState("");
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#5cb85c",
|
alertType: "success",
|
||||||
toastDescription: ""
|
alertMsg: ""
|
||||||
});
|
});
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [lengthValid, setLengthValid] = useState(false);
|
const [lengthValid, setLengthValid] = useState(false);
|
||||||
@@ -30,14 +33,14 @@ const Signup = (props) => {
|
|||||||
const [specialCharValid, setSpecialCharValid] = useState(false);
|
const [specialCharValid, setSpecialCharValid] = useState(false);
|
||||||
|
|
||||||
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
||||||
const image = props.appInfo.applogo;
|
const image = appInfo.applogo;
|
||||||
|
|
||||||
const clearStorage = async () => {
|
const clearStorage = async () => {
|
||||||
if (Parse.User.current()) {
|
if (Parse.User.current()) {
|
||||||
await Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
}
|
}
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("AppID12");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
let domain = localStorage.getItem("domain");
|
let domain = localStorage.getItem("domain");
|
||||||
let appversion = localStorage.getItem("appVersion");
|
let appversion = localStorage.getItem("appVersion");
|
||||||
@@ -51,8 +54,8 @@ const Signup = (props) => {
|
|||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
localStorage.setItem("BaseUrl12", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("AppID12", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
localStorage.setItem("domain", domain);
|
localStorage.setItem("domain", domain);
|
||||||
localStorage.setItem("appversion", appversion);
|
localStorage.setItem("appversion", appversion);
|
||||||
@@ -66,6 +69,19 @@ const Signup = (props) => {
|
|||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFreePlan = async (id) => {
|
||||||
|
try {
|
||||||
|
const params = { userId: id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "error") {
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||||
@@ -80,8 +96,6 @@ const Signup = (props) => {
|
|||||||
};
|
};
|
||||||
localStorage.setItem("userDetails", JSON.stringify(userDetails));
|
localStorage.setItem("userDetails", JSON.stringify(userDetails));
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var user = new Parse.User();
|
var user = new Parse.User();
|
||||||
user.set("name", name);
|
user.set("name", name);
|
||||||
@@ -93,7 +107,7 @@ const Signup = (props) => {
|
|||||||
res
|
res
|
||||||
.then(async (r) => {
|
.then(async (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
let roleData = props.appInfo.settings;
|
let roleData = appInfo.settings;
|
||||||
if (roleData && roleData.length > 0) {
|
if (roleData && roleData.length > 0) {
|
||||||
const params = {
|
const params = {
|
||||||
userDetails: {
|
userDetails: {
|
||||||
@@ -102,7 +116,7 @@ const Signup = (props) => {
|
|||||||
name: name,
|
name: name,
|
||||||
email: email,
|
email: email,
|
||||||
phone: phone,
|
phone: phone,
|
||||||
role: props.appInfo.defaultRole
|
role: appInfo.defaultRole
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
@@ -111,7 +125,13 @@ const Signup = (props) => {
|
|||||||
params
|
params
|
||||||
);
|
);
|
||||||
if (usersignup) {
|
if (usersignup) {
|
||||||
handleNavigation(r.getSessionToken());
|
const param = new URLSearchParams(location.search);
|
||||||
|
const isFreeplan =
|
||||||
|
param?.get("subscription") === "freeplan";
|
||||||
|
if (isFreeplan) {
|
||||||
|
await handleFreePlan(r.id);
|
||||||
|
}
|
||||||
|
handleNavigation(r.getSessionToken(), isFreeplan);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err.message);
|
alert(err.message);
|
||||||
@@ -129,12 +149,8 @@ const Signup = (props) => {
|
|||||||
alert("User already exists with this username!");
|
alert("User already exists with this username!");
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
} else {
|
} else {
|
||||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
|
||||||
let parseAppId = localStorage.getItem("AppID12");
|
|
||||||
// console.log("state.email ", email);
|
// console.log("state.email ", email);
|
||||||
try {
|
try {
|
||||||
Parse.serverURL = baseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
await Parse.User.requestPasswordReset(email).then(
|
await Parse.User.requestPasswordReset(email).then(
|
||||||
async function (res1) {
|
async function (res1) {
|
||||||
if (res1.data === undefined) {
|
if (res1.data === undefined) {
|
||||||
@@ -160,9 +176,9 @@ const Signup = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigation = async (sessionToken) => {
|
const handleNavigation = async (sessionToken, isFreeplan = false) => {
|
||||||
const baseUrl = localStorage.getItem("BaseUrl12");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("AppID12");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const res = await axios.get(baseUrl + "users/me", {
|
const res = await axios.get(baseUrl + "users/me", {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Parse-Session-Token": sessionToken,
|
"X-Parse-Session-Token": sessionToken,
|
||||||
@@ -188,8 +204,8 @@ const Signup = (props) => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
let userRoles = [];
|
let userRoles = [];
|
||||||
if (props.appInfo.settings) {
|
if (appInfo.settings) {
|
||||||
let userSettings = props.appInfo.settings;
|
let userSettings = appInfo.settings;
|
||||||
|
|
||||||
//Get Current user roles
|
//Get Current user roles
|
||||||
let url = `${baseUrl}functions/UserGroups`;
|
let url = `${baseUrl}functions/UserGroups`;
|
||||||
@@ -236,8 +252,6 @@ const Signup = (props) => {
|
|||||||
"extended_class",
|
"extended_class",
|
||||||
element.extended_class
|
element.extended_class
|
||||||
);
|
);
|
||||||
localStorage.setItem("userpointer", element.userpointer);
|
|
||||||
|
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: email
|
email: email
|
||||||
}).then(
|
}).then(
|
||||||
@@ -265,8 +279,8 @@ const Signup = (props) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -302,15 +316,15 @@ const Signup = (props) => {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
props.showTenantName(
|
dispatch(
|
||||||
tenentInfo[0].tenentName || ""
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -330,8 +344,14 @@ const Signup = (props) => {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(
|
||||||
|
`/${element.pageType}/${element.pageId}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, { replace: true });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Registered user successfully");
|
alert("Registered user successfully");
|
||||||
navigate(
|
navigate(
|
||||||
@@ -348,8 +368,14 @@ 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 (isEnableSubscription) {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(
|
||||||
|
`/${element.pageType}/${element.pageId}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, { replace: true });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
navigate(
|
||||||
`/${element.pageType}/${element.pageId}`
|
`/${element.pageType}/${element.pageId}`
|
||||||
@@ -358,19 +384,18 @@ const Signup = (props) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
/* alert(
|
|
||||||
"You dont have access to this application."
|
|
||||||
); */
|
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription:
|
alertMsg:
|
||||||
"You dont have access to this application."
|
"You dont have access to this application!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
localStorage.setItem("accesstoken", null);
|
localStorage.setItem("accesstoken", null);
|
||||||
console.error("Error while fetching Follow", error);
|
console.error("Error while fetching Follow", error);
|
||||||
@@ -381,25 +406,29 @@ const Signup = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: "User Role Not Found."
|
alertMsg: "User Role Not Found!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: "User Role Not Found."
|
alertMsg: "User Role Not Found!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -407,13 +436,16 @@ const Signup = (props) => {
|
|||||||
console.log("err", err);
|
console.log("err", err);
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: `Does not have permissions to access this application.`
|
alertMsg:
|
||||||
|
"Does not have permissions to access this application!"
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -421,24 +453,22 @@ const Signup = (props) => {
|
|||||||
// alert(`${error.message}`);
|
// alert(`${error.message}`);
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription: `${error.message}`
|
alertMsg: `${error.message}`
|
||||||
});
|
});
|
||||||
const x = document.getElementById("snackbar");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
x.className = x.className.replace("show", "");
|
setState({
|
||||||
|
loading: false,
|
||||||
|
alertType: "danger",
|
||||||
|
alertMsg: ""
|
||||||
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
props.fetchAppInfo(
|
dispatch(fetchAppInfo());
|
||||||
localStorage.getItem("domain"),
|
|
||||||
localStorage.getItem("BaseUrl12"),
|
|
||||||
localStorage.getItem("AppID12")
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -484,7 +514,7 @@ const Signup = (props) => {
|
|||||||
|
|
||||||
<Title title={"Signup page"} />
|
<Title title={"Signup page"} />
|
||||||
|
|
||||||
{props.isloginVisible && props.isloginVisible ? (
|
{appInfo && appInfo.applogo ? (
|
||||||
<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">
|
||||||
@@ -627,7 +657,7 @@ const Signup = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
<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={location.search ? "/" + location.search : "/"}
|
||||||
style={width < 768 ? { textAlign: "center" } : {}}
|
style={width < 768 ? { textAlign: "center" } : {}}
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
@@ -644,10 +674,7 @@ const Signup = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
||||||
<div id="snackbar" style={{ backgroundColor: state.toastColor }}>
|
|
||||||
{state.toastDescription}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -665,15 +692,4 @@ const Signup = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
export default Signup;
|
||||||
if (Object.keys(state.appInfo).length !== 0) {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: true };
|
|
||||||
} else {
|
|
||||||
return { appInfo: state.appInfo, isloginVisible: false };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, {
|
|
||||||
fetchAppInfo,
|
|
||||||
showTenantName
|
|
||||||
})(Signup);
|
|
||||||
@@ -1,39 +1,41 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
import RenderAllPdfPage from "./component/renderAllPdfPage";
|
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
||||||
import { useParams, useNavigate } from "react-router-dom";
|
import { useParams, useNavigate } from "react-router-dom";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import "../css/./signature.css";
|
import "../styles/signature.css";
|
||||||
import sign from "../assests/sign3.png";
|
import { isEnableSubscription, themeColor } from "../constant/const";
|
||||||
import stamp from "../assests/stamp2.png";
|
|
||||||
import { themeColor } from "../utils/ThemeColor/backColor";
|
|
||||||
import { DndProvider } from "react-dnd";
|
import { DndProvider } from "react-dnd";
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
import { useDrag, useDrop } from "react-dnd";
|
import { useDrag, useDrop } from "react-dnd";
|
||||||
import FieldsComponent from "./component/fieldsComponent";
|
import WidgetComponent from "../components/pdf/WidgetComponent";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import Loader from "./component/loader";
|
import Loader from "../primitives/LoaderWithMsg";
|
||||||
import HandleError from "./component/HandleError";
|
import HandleError from "../primitives/HandleError";
|
||||||
import Nodata from "./component/Nodata";
|
import SignerListPlace from "../components/pdf/SignerListPlace";
|
||||||
import SignerListPlace from "./component/signerListPlace";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import Header from "./component/header";
|
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
||||||
import {
|
import {
|
||||||
pdfNewWidthFun,
|
pdfNewWidthFun,
|
||||||
contractUsers,
|
contractUsers,
|
||||||
getHostUrl,
|
|
||||||
randomId,
|
randomId,
|
||||||
addZIndex,
|
addZIndex,
|
||||||
createDocument
|
createDocument,
|
||||||
} from "../utils/Utils";
|
defaultWidthHeight,
|
||||||
import RenderPdf from "./component/renderPdf";
|
addWidgetOptions,
|
||||||
import "../css/AddUser.css";
|
textInputWidget,
|
||||||
import Title from "./component/Title";
|
radioButtonWidget
|
||||||
import LinkUserModal from "./component/LinkUserModal";
|
} from "../constant/Utils";
|
||||||
import EditTemplate from "./component/EditTemplate";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import ModalUi from "../premitives/ModalUi";
|
import "../styles/AddUser.css";
|
||||||
import AddRoleModal from "./component/AddRoleModal";
|
import Title from "../components/Title";
|
||||||
import PlaceholderCopy from "./component/PlaceholderCopy";
|
import LinkUserModal from "../primitives/LinkUserModal";
|
||||||
import ModalComponent from "./component/modalComponent";
|
import EditTemplate from "../components/pdf/EditTemplate";
|
||||||
import TourContentWithBtn from "../premitives/TourContentWithBtn";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import AddRoleModal from "../components/pdf/AddRoleModal";
|
||||||
|
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
||||||
|
import Parse from "parse";
|
||||||
const TemplatePlaceholder = () => {
|
const TemplatePlaceholder = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { templateId } = useParams();
|
const { templateId } = useParams();
|
||||||
@@ -51,6 +53,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const [isSelectListId, setIsSelectId] = useState();
|
const [isSelectListId, setIsSelectId] = useState();
|
||||||
const [isSendAlert, setIsSendAlert] = useState(false);
|
const [isSendAlert, setIsSendAlert] = useState(false);
|
||||||
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = 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"
|
||||||
@@ -62,7 +65,6 @@ const TemplatePlaceholder = () => {
|
|||||||
const [checkTourStatus, setCheckTourStatus] = useState(false);
|
const [checkTourStatus, setCheckTourStatus] = useState(false);
|
||||||
const [tourStatus, setTourStatus] = useState([]);
|
const [tourStatus, setTourStatus] = useState([]);
|
||||||
const [signerUserId, setSignerUserId] = useState();
|
const [signerUserId, setSignerUserId] = useState();
|
||||||
const [noData, setNoData] = useState(false);
|
|
||||||
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
|
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
|
||||||
const [contractName, setContractName] = useState("");
|
const [contractName, setContractName] = useState("");
|
||||||
const [containerWH, setContainerWH] = useState();
|
const [containerWH, setContainerWH] = useState();
|
||||||
@@ -74,6 +76,12 @@ const TemplatePlaceholder = () => {
|
|||||||
const [isResize, setIsResize] = useState(false);
|
const [isResize, setIsResize] = useState(false);
|
||||||
const [isSigners, setIsSigners] = useState(false);
|
const [isSigners, setIsSigners] = useState(false);
|
||||||
const [zIndex, setZIndex] = useState(1);
|
const [zIndex, setZIndex] = useState(1);
|
||||||
|
const [showDropdown, setShowDropdown] = useState(false);
|
||||||
|
const [widgetType, setWidgetType] = useState("");
|
||||||
|
const [isRadio, setIsRadio] = useState(false);
|
||||||
|
const [blockColor, setBlockColor] = useState("");
|
||||||
|
const [selectWidgetId, setSelectWidgetId] = useState("");
|
||||||
|
const [isNameModal, setIsNameModal] = useState(false);
|
||||||
const [pdfLoadFail, setPdfLoadFail] = useState({
|
const [pdfLoadFail, setPdfLoadFail] = useState({
|
||||||
status: false,
|
status: false,
|
||||||
type: "load"
|
type: "load"
|
||||||
@@ -93,7 +101,7 @@ const TemplatePlaceholder = () => {
|
|||||||
"#ffffcc"
|
"#ffffcc"
|
||||||
];
|
];
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const [{ isOver }, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
accept: "BOX",
|
accept: "BOX",
|
||||||
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({
|
||||||
@@ -105,7 +113,7 @@ const TemplatePlaceholder = () => {
|
|||||||
item: {
|
item: {
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
id: 1,
|
id: 1,
|
||||||
text: "drag me"
|
text: "signature"
|
||||||
},
|
},
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({
|
||||||
isDragSign: !!monitor.isDragging()
|
isDragSign: !!monitor.isDragging()
|
||||||
@@ -117,37 +125,12 @@ const TemplatePlaceholder = () => {
|
|||||||
item: {
|
item: {
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
id: 2,
|
id: 2,
|
||||||
text: "drag me"
|
text: "stamp"
|
||||||
},
|
},
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({
|
||||||
isDragStamp: !!monitor.isDragging()
|
isDragStamp: !!monitor.isDragging()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const [{ isDragSignatureSS }, dragSignatureSS] = useDrag({
|
|
||||||
type: "BOX",
|
|
||||||
item: {
|
|
||||||
type: "BOX",
|
|
||||||
id: 3,
|
|
||||||
text: "drag me"
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragSignatureSS: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const [{ isDragStampSS }, dragStampSS] = useDrag({
|
|
||||||
type: "BOX",
|
|
||||||
item: {
|
|
||||||
type: "BOX",
|
|
||||||
id: 4,
|
|
||||||
text: "drag me"
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragStampSS: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const [uniqueId, setUniqueId] = useState("");
|
const [uniqueId, setUniqueId] = useState("");
|
||||||
const [isModalRole, setIsModalRole] = useState(false);
|
const [isModalRole, setIsModalRole] = useState(false);
|
||||||
const [roleName, setRoleName] = useState("");
|
const [roleName, setRoleName] = useState("");
|
||||||
@@ -159,6 +142,9 @@ const TemplatePlaceholder = () => {
|
|||||||
const [IsReceipent, setIsReceipent] = useState(true);
|
const [IsReceipent, setIsReceipent] = useState(true);
|
||||||
const [isDontShow, setIsDontShow] = useState(false);
|
const [isDontShow, setIsDontShow] = useState(false);
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
|
||||||
|
const [isCheckbox, setIsCheckbox] = useState(false);
|
||||||
|
const [widgetName, setWidgetName] = useState(false);
|
||||||
const senderUser =
|
const senderUser =
|
||||||
localStorage.getItem(
|
localStorage.getItem(
|
||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
@@ -170,7 +156,7 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplate();
|
fetchTemplate();
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -182,8 +168,28 @@ const TemplatePlaceholder = () => {
|
|||||||
height: divRef.current.offsetHeight
|
height: divRef.current.offsetHeight
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [divRef.current]);
|
}, [divRef.current]);
|
||||||
|
async function checkIsSubscribed(email) {
|
||||||
|
const user = await Parse.Cloud.run("getUserDetails", {
|
||||||
|
email: email
|
||||||
|
});
|
||||||
|
const freeplan = user?.get("Plan") && user?.get("Plan").plan_code;
|
||||||
|
const billingDate =
|
||||||
|
user?.get("Next_billing_date") && user?.get("Next_billing_date");
|
||||||
|
if (freeplan === "freeplan") {
|
||||||
|
return true;
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (billingDate > new Date()) {
|
||||||
|
setIsSubscribe(true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
}
|
||||||
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
||||||
const fetchTemplate = async () => {
|
const fetchTemplate = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -205,6 +211,9 @@ const TemplatePlaceholder = () => {
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
||||||
|
}
|
||||||
setPdfDetails(documentData);
|
setPdfDetails(documentData);
|
||||||
setIsSigners(true);
|
setIsSigners(true);
|
||||||
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
||||||
@@ -239,6 +248,7 @@ const TemplatePlaceholder = () => {
|
|||||||
});
|
});
|
||||||
setSignersData(updatedSigners);
|
setSignersData(updatedSigners);
|
||||||
setUniqueId(updatedSigners[0].Id);
|
setUniqueId(updatedSigners[0].Id);
|
||||||
|
setBlockColor(updatedSigners[0].blockColor);
|
||||||
} else {
|
} else {
|
||||||
const updatedSigners = documentData[0].Signers.map((x, index) => ({
|
const updatedSigners = documentData[0].Signers.map((x, index) => ({
|
||||||
...x,
|
...x,
|
||||||
@@ -247,6 +257,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}));
|
}));
|
||||||
setSignersData(updatedSigners);
|
setSignersData(updatedSigners);
|
||||||
setUniqueId(updatedSigners[0].Id);
|
setUniqueId(updatedSigners[0].Id);
|
||||||
|
setBlockColor(updatedSigners[0].blockColor);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setRoleName("User 1");
|
setRoleName("User 1");
|
||||||
@@ -265,6 +276,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setUniqueId(updatedSigners[0].Id);
|
setUniqueId(updatedSigners[0].Id);
|
||||||
setSignersData(updatedSigners);
|
setSignersData(updatedSigners);
|
||||||
setIsSelectId(0);
|
setIsSelectId(0);
|
||||||
|
setBlockColor(updatedSigners[0].blockColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
@@ -277,8 +289,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setHandleError("Error: Something went wrong!");
|
setHandleError("Error: Something went wrong!");
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
} else {
|
} else {
|
||||||
setNoData(true);
|
setHandleError("No Data Found!");
|
||||||
|
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
@@ -317,8 +328,7 @@ const TemplatePlaceholder = () => {
|
|||||||
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);
|
setHandleError("No Data Found!");
|
||||||
|
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
@@ -328,6 +338,9 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
//function for setting position after drop signature button over pdf
|
//function for setting position after drop signature button over pdf
|
||||||
const addPositionOfSignature = (item, monitor) => {
|
const addPositionOfSignature = (item, monitor) => {
|
||||||
|
if (item && item.text) {
|
||||||
|
setWidgetName(item.text);
|
||||||
|
}
|
||||||
getSignerPos(item, monitor);
|
getSignerPos(item, monitor);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -345,26 +358,29 @@ const TemplatePlaceholder = () => {
|
|||||||
// (data) => data.signerObjId === signerObjId
|
// (data) => data.signerObjId === signerObjId
|
||||||
// );
|
// );
|
||||||
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
|
const dragTypeValue = item?.text ? item.text : monitor.type;
|
||||||
let dropData = [];
|
let dropData = [];
|
||||||
let placeHolder;
|
let placeHolder;
|
||||||
if (item === "onclick") {
|
if (item === "onclick") {
|
||||||
const dropObj = {
|
const dropObj = {
|
||||||
xPosition: window.innerWidth / 2 - 100,
|
//onclick put placeholder center on pdf
|
||||||
|
xPosition: window.innerWidth / 2 - 150,
|
||||||
yPosition: window.innerHeight / 2 - 60,
|
yPosition: window.innerHeight / 2 - 60,
|
||||||
isStamp: monitor,
|
isStamp:
|
||||||
|
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
|
||||||
key: key,
|
key: key,
|
||||||
isDrag: false,
|
|
||||||
scale: scale,
|
scale: scale,
|
||||||
isMobile: isMobile,
|
isMobile: isMobile,
|
||||||
yBottom: window.innerHeight / 2 - 60,
|
zIndex: posZIndex,
|
||||||
zIndex: posZIndex
|
type: dragTypeValue,
|
||||||
|
options: addWidgetOptions(dragTypeValue)
|
||||||
};
|
};
|
||||||
dropData.push(dropObj);
|
dropData.push(dropObj);
|
||||||
placeHolder = {
|
placeHolder = {
|
||||||
pageNumber: pageNumber,
|
pageNumber: pageNumber,
|
||||||
pos: dropData
|
pos: dropData
|
||||||
};
|
};
|
||||||
} else if (item.type === "BOX") {
|
} else {
|
||||||
const offset = monitor.getClientOffset();
|
const offset = monitor.getClientOffset();
|
||||||
//adding and updating drop position in array when user drop signature button in div
|
//adding and updating drop position in array when user drop signature button in div
|
||||||
const containerRect = document
|
const containerRect = document
|
||||||
@@ -372,20 +388,17 @@ const TemplatePlaceholder = () => {
|
|||||||
.getBoundingClientRect();
|
.getBoundingClientRect();
|
||||||
const x = offset.x - containerRect.left;
|
const x = offset.x - containerRect.left;
|
||||||
const y = offset.y - containerRect.top;
|
const y = offset.y - containerRect.top;
|
||||||
const ybottom = containerRect.bottom - offset.y;
|
|
||||||
|
|
||||||
const dropObj = {
|
const dropObj = {
|
||||||
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
|
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
|
||||||
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
|
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
|
||||||
isStamp: isDragStamp || isDragStampSS ? true : false,
|
isStamp:
|
||||||
|
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
|
||||||
key: key,
|
key: key,
|
||||||
isDrag: false,
|
|
||||||
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
|
|
||||||
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
|
|
||||||
yBottom: ybottom,
|
|
||||||
scale: scale,
|
scale: scale,
|
||||||
isMobile: isMobile,
|
isMobile: isMobile,
|
||||||
zIndex: posZIndex
|
zIndex: posZIndex,
|
||||||
|
type: item.text,
|
||||||
|
options: addWidgetOptions(dragTypeValue)
|
||||||
};
|
};
|
||||||
|
|
||||||
dropData.push(dropObj);
|
dropData.push(dropObj);
|
||||||
@@ -454,12 +467,26 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
setSignerPos((prev) => [...prev, placeHolderPos]);
|
setSignerPos((prev) => [...prev, placeHolderPos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dragTypeValue === "dropdown") {
|
||||||
|
setShowDropdown(true);
|
||||||
|
} else if (dragTypeValue === "checkbox") {
|
||||||
|
setIsCheckbox(true);
|
||||||
|
} else if (dragTypeValue === radioButtonWidget) {
|
||||||
|
setIsRadio(true);
|
||||||
|
}
|
||||||
|
setCurrWidgetsDetails({});
|
||||||
|
setWidgetType(dragTypeValue);
|
||||||
|
setSignKey(key);
|
||||||
|
setSelectWidgetId(key);
|
||||||
|
|
||||||
setIsMailSend(false);
|
setIsMailSend(false);
|
||||||
} else {
|
} else {
|
||||||
setIsReceipent(false);
|
setIsReceipent(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for get pdf page details
|
//function for get pdf page details
|
||||||
const pageDetails = async (pdf) => {
|
const pageDetails = async (pdf) => {
|
||||||
const load = {
|
const load = {
|
||||||
@@ -507,7 +534,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const getXYdata = getPageNumer[0].pos;
|
const getXYdata = getPageNumer[0].pos;
|
||||||
|
|
||||||
const getPosData = getXYdata;
|
const getPosData = getXYdata;
|
||||||
const addSignPos = getPosData.map((url, ind) => {
|
const addSignPos = getPosData.map((url) => {
|
||||||
if (url.key === keyValue) {
|
if (url.key === keyValue) {
|
||||||
return {
|
return {
|
||||||
...url,
|
...url,
|
||||||
@@ -520,13 +547,13 @@ const TemplatePlaceholder = () => {
|
|||||||
return url;
|
return url;
|
||||||
});
|
});
|
||||||
|
|
||||||
const newUpdateSignPos = getPlaceHolder.map((obj, ind) => {
|
const newUpdateSignPos = getPlaceHolder.map((obj) => {
|
||||||
if (obj.pageNumber === pageNumber) {
|
if (obj.pageNumber === pageNumber) {
|
||||||
return { ...obj, pos: addSignPos };
|
return { ...obj, pos: addSignPos };
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
const newUpdateSigner = updateSignPos.map((obj, ind) => {
|
const newUpdateSigner = updateSignPos.map((obj) => {
|
||||||
if (obj.Id === signId) {
|
if (obj.Id === signId) {
|
||||||
return { ...obj, placeHolder: newUpdateSignPos };
|
return { ...obj, placeHolder: newUpdateSignPos };
|
||||||
}
|
}
|
||||||
@@ -562,19 +589,19 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
if (getPageNumer.length > 0) {
|
if (getPageNumer.length > 0) {
|
||||||
const getXYdata = getPageNumer[0].pos.filter(
|
const getXYdata = getPageNumer[0].pos.filter(
|
||||||
(data, ind) => data.key !== key
|
(data) => data.key !== key
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getXYdata.length > 0) {
|
if (getXYdata.length > 0) {
|
||||||
updateData.push(getXYdata);
|
updateData.push(getXYdata);
|
||||||
const newUpdatePos = getPlaceHolder.map((obj, ind) => {
|
const newUpdatePos = getPlaceHolder.map((obj) => {
|
||||||
if (obj.pageNumber === pageNumber) {
|
if (obj.pageNumber === pageNumber) {
|
||||||
return { ...obj, pos: updateData[0] };
|
return { ...obj, pos: updateData[0] };
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
|
|
||||||
const newUpdateSigner = signerPos.map((obj, ind) => {
|
const newUpdateSigner = signerPos.map((obj) => {
|
||||||
if (obj.Id === Id) {
|
if (obj.Id === Id) {
|
||||||
return { ...obj, placeHolder: newUpdatePos };
|
return { ...obj, placeHolder: newUpdatePos };
|
||||||
}
|
}
|
||||||
@@ -589,7 +616,7 @@ const TemplatePlaceholder = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (getRemainPage && getRemainPage.length > 0) {
|
if (getRemainPage && getRemainPage.length > 0) {
|
||||||
const newUpdatePos = filterSignerPos.map((obj, ind) => {
|
const newUpdatePos = filterSignerPos.map((obj) => {
|
||||||
if (obj.Id === Id) {
|
if (obj.Id === Id) {
|
||||||
return { ...obj, placeHolder: getRemainPage };
|
return { ...obj, placeHolder: getRemainPage };
|
||||||
}
|
}
|
||||||
@@ -629,7 +656,7 @@ const TemplatePlaceholder = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//function for capture position of x and y on hover signature button last position
|
//function for capture position of x and y on hover signature button last position
|
||||||
const handleMouseLeave = (e) => {
|
const handleMouseLeave = () => {
|
||||||
setSignBtnPosition([xySignature]);
|
setSignBtnPosition([xySignature]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -664,7 +691,6 @@ const TemplatePlaceholder = () => {
|
|||||||
try {
|
try {
|
||||||
const data = {
|
const data = {
|
||||||
Placeholders: signerPos,
|
Placeholders: signerPos,
|
||||||
SignedUrl: pdfDetails[0].URL,
|
|
||||||
Signers: signers,
|
Signers: signers,
|
||||||
Name: pdfDetails[0]?.Name || "",
|
Name: pdfDetails[0]?.Name || "",
|
||||||
Note: pdfDetails[0]?.Note || "",
|
Note: pdfDetails[0]?.Note || "",
|
||||||
@@ -686,7 +712,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((result) => {
|
.then(() => {
|
||||||
setIsCreateDocModal(true);
|
setIsCreateDocModal(true);
|
||||||
setIsMailSend(true);
|
setIsMailSend(true);
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
@@ -727,7 +753,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourFirst"]',
|
selector: '[data-tut="reactourFirst"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Select a role from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`}
|
message={`Once roles are added, select a role from list to add a place-holder where he is supposed to sign. The placeholder will appear in the same colour as the role name once you drop it on the document.`}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -739,7 +765,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourSecond"]',
|
selector: '[data-tut="reactourSecond"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`}
|
message={`Drag a widget placeholder onto the PDF to choose your desired signing location.`}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -761,7 +787,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourFour"]',
|
selector: '[data-tut="reactourFour"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Clicking "Save" button will save the template and will ask you for creating new document.`}
|
message={`Clicking "Save" button will save the template and will ask you if you want to create a new document using this template.`}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -805,7 +831,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((Listdata) => {
|
.then(() => {
|
||||||
// const json = Listdata.data;
|
// const json = Listdata.data;
|
||||||
// const res = json.results;
|
// const res = json.results;
|
||||||
})
|
})
|
||||||
@@ -819,11 +845,10 @@ const TemplatePlaceholder = () => {
|
|||||||
const handleCreateDocModal = async () => {
|
const handleCreateDocModal = async () => {
|
||||||
setIsCreateDocModal(false);
|
setIsCreateDocModal(false);
|
||||||
setIsCreateDoc(true);
|
setIsCreateDoc(true);
|
||||||
const hostUrl = getHostUrl();
|
|
||||||
// handle create document
|
// handle create document
|
||||||
const res = await createDocument(pdfDetails, signerPos, signersdata);
|
const res = await createDocument(pdfDetails, signerPos, signersdata);
|
||||||
if (res.status === "success") {
|
if (res.status === "success") {
|
||||||
navigate(`${hostUrl}placeHolderSign/${res.id}`, {
|
navigate(`/placeHolderSign/${res.id}`, {
|
||||||
state: { title: "Use Template" }
|
state: { title: "Use Template" }
|
||||||
});
|
});
|
||||||
setIsCreateDoc(false);
|
setIsCreateDoc(false);
|
||||||
@@ -857,6 +882,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsModalRole(false);
|
setIsModalRole(false);
|
||||||
setRoleName("");
|
setRoleName("");
|
||||||
setUniqueId(Id);
|
setUniqueId(Id);
|
||||||
|
setBlockColor(color[index]);
|
||||||
setIsSelectId(index);
|
setIsSelectId(index);
|
||||||
setIsMailSend(false);
|
setIsMailSend(false);
|
||||||
};
|
};
|
||||||
@@ -873,9 +899,11 @@ const TemplatePlaceholder = () => {
|
|||||||
if (index === signersdata.length - 1) {
|
if (index === signersdata.length - 1) {
|
||||||
setUniqueId(updateSigner[updateSigner.length - 1]?.Id || "");
|
setUniqueId(updateSigner[updateSigner.length - 1]?.Id || "");
|
||||||
setIsSelectId(index - 1 || 0);
|
setIsSelectId(index - 1 || 0);
|
||||||
|
setBlockColor(color[index - 1 || 0]);
|
||||||
} else {
|
} else {
|
||||||
setUniqueId(updateSigner[index]?.Id || "");
|
setUniqueId(updateSigner[index]?.Id || "");
|
||||||
setIsSelectId(index);
|
setIsSelectId(index);
|
||||||
|
setBlockColor(color[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSignerPos(updatePlaceholderUser);
|
setSignerPos(updatePlaceholderUser);
|
||||||
@@ -964,6 +992,211 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsModalRole(false);
|
setIsModalRole(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSaveWidgetsOptions = (
|
||||||
|
dropdownName,
|
||||||
|
dropdownOptions,
|
||||||
|
minCount,
|
||||||
|
maxCount,
|
||||||
|
isReadOnly,
|
||||||
|
addOption,
|
||||||
|
deleteOption,
|
||||||
|
status,
|
||||||
|
defaultValue,
|
||||||
|
isHideLabel
|
||||||
|
) => {
|
||||||
|
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
|
if (filterSignerPos.length > 0) {
|
||||||
|
const getPlaceHolder = filterSignerPos[0].placeHolder;
|
||||||
|
|
||||||
|
const getPageNumer = getPlaceHolder.filter(
|
||||||
|
(data) => data.pageNumber === pageNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
if (getPageNumer.length > 0) {
|
||||||
|
const getXYdata = getPageNumer[0].pos;
|
||||||
|
|
||||||
|
const getPosData = getXYdata;
|
||||||
|
const addSignPos = getPosData.map((position) => {
|
||||||
|
if (position.key === signKey) {
|
||||||
|
if (widgetType === radioButtonWidget) {
|
||||||
|
if (addOption) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
Height: position.Height
|
||||||
|
? position.Height + 15
|
||||||
|
: defaultWidthHeight(widgetType).height + 15
|
||||||
|
};
|
||||||
|
} else if (deleteOption) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
Height: position.Height
|
||||||
|
? position.Height - 15
|
||||||
|
: defaultWidthHeight(widgetType).height - 15
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
options: {
|
||||||
|
...position.options,
|
||||||
|
name: dropdownName,
|
||||||
|
values: dropdownOptions,
|
||||||
|
status: status,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
isReadOnly: isReadOnly || false,
|
||||||
|
isHideLabel: isHideLabel || false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if (widgetType === "checkbox") {
|
||||||
|
if (addOption) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
Height: position.Height
|
||||||
|
? position.Height + 15
|
||||||
|
: defaultWidthHeight(widgetType).height + 15
|
||||||
|
};
|
||||||
|
} else if (deleteOption) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
Height: position.Height
|
||||||
|
? position.Height - 15
|
||||||
|
: defaultWidthHeight(widgetType).height - 15
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
options: {
|
||||||
|
...position.options,
|
||||||
|
name: dropdownName,
|
||||||
|
values: dropdownOptions,
|
||||||
|
validation: {
|
||||||
|
minRequiredCount: minCount,
|
||||||
|
maxRequiredCount: maxCount
|
||||||
|
},
|
||||||
|
isReadOnly: isReadOnly || false,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
isHideLabel: isHideLabel || false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
options: {
|
||||||
|
...position.options,
|
||||||
|
name: dropdownName,
|
||||||
|
status: status,
|
||||||
|
values: dropdownOptions,
|
||||||
|
defaultValue: defaultValue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
});
|
||||||
|
|
||||||
|
const newUpdateSignPos = getPlaceHolder.map((obj) => {
|
||||||
|
if (obj.pageNumber === pageNumber) {
|
||||||
|
return { ...obj, pos: addSignPos };
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
const newUpdateSigner = signerPos.map((obj) => {
|
||||||
|
if (obj.Id === uniqueId) {
|
||||||
|
return { ...obj, placeHolder: newUpdateSignPos };
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSignerPos(newUpdateSigner);
|
||||||
|
if (!addOption && !deleteOption) {
|
||||||
|
handleNameModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleWidgetdefaultdata = (defaultdata) => {
|
||||||
|
const options = ["email", "number", "text"];
|
||||||
|
let inputype;
|
||||||
|
if (defaultdata.textvalidate) {
|
||||||
|
inputype = options.includes(defaultdata.textvalidate)
|
||||||
|
? defaultdata.textvalidate
|
||||||
|
: "regex";
|
||||||
|
} else {
|
||||||
|
inputype = "text";
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
|
if (filterSignerPos.length > 0) {
|
||||||
|
const getPlaceHolder = filterSignerPos[0].placeHolder;
|
||||||
|
|
||||||
|
const getPageNumer = getPlaceHolder.filter(
|
||||||
|
(data) => data.pageNumber === pageNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
if (getPageNumer.length > 0) {
|
||||||
|
const getXYdata = getPageNumer[0].pos;
|
||||||
|
const getPosData = getXYdata;
|
||||||
|
const addSignPos = getPosData.map((position) => {
|
||||||
|
if (position.key === signKey) {
|
||||||
|
if (position.type === textInputWidget) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
options: {
|
||||||
|
...position.options,
|
||||||
|
name: defaultdata?.name || "text",
|
||||||
|
status: defaultdata?.status || "required",
|
||||||
|
hint: defaultdata?.hint || "",
|
||||||
|
defaultValue: defaultdata?.defaultValue || "",
|
||||||
|
validation: {
|
||||||
|
type: inputype,
|
||||||
|
pattern:
|
||||||
|
inputype === "regex" ? defaultdata.textvalidate : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
options: {
|
||||||
|
...position.options,
|
||||||
|
name: defaultdata.name,
|
||||||
|
status: defaultdata.status,
|
||||||
|
defaultValue: defaultdata.defaultValue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
});
|
||||||
|
|
||||||
|
const newUpdateSignPos = getPlaceHolder.map((obj) => {
|
||||||
|
if (obj.pageNumber === pageNumber) {
|
||||||
|
return { ...obj, pos: addSignPos };
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
const newUpdateSigner = signerPos.map((obj) => {
|
||||||
|
if (obj.Id === uniqueId) {
|
||||||
|
return { ...obj, placeHolder: newUpdateSignPos };
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
setSignerPos(newUpdateSigner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCurrWidgetsDetails({});
|
||||||
|
handleNameModal();
|
||||||
|
};
|
||||||
|
const handleNameModal = () => {
|
||||||
|
setIsNameModal(false);
|
||||||
|
setCurrWidgetsDetails({});
|
||||||
|
setShowDropdown(false);
|
||||||
|
setIsRadio(false);
|
||||||
|
setIsCheckbox(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Title title={"Template"} />
|
<Title title={"Template"} />
|
||||||
@@ -972,8 +1205,6 @@ const TemplatePlaceholder = () => {
|
|||||||
<Loader isLoading={isLoading} />
|
<Loader isLoading={isLoading} />
|
||||||
) : handleError ? (
|
) : handleError ? (
|
||||||
<HandleError handleError={handleError} />
|
<HandleError handleError={handleError} />
|
||||||
) : noData ? (
|
|
||||||
<Nodata />
|
|
||||||
) : (
|
) : (
|
||||||
<div className="signatureContainer" ref={divRef}>
|
<div className="signatureContainer" ref={divRef}>
|
||||||
{/* this component used for UI interaction and show their functionality */}
|
{/* this component used for UI interaction and show their functionality */}
|
||||||
@@ -1055,7 +1286,7 @@ const TemplatePlaceholder = () => {
|
|||||||
handleCreateDocModal();
|
handleCreateDocModal();
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -1077,10 +1308,68 @@ const TemplatePlaceholder = () => {
|
|||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
{isCreateDoc && <Loader isLoading={isLoading} />}
|
{isCreateDoc && <Loader isLoading={isLoading} />}
|
||||||
<ModalComponent
|
<ModalUi
|
||||||
isShow={isShowEmail}
|
headerColor={"#dc3545"}
|
||||||
type={"signersAlert"}
|
isOpen={isShowEmail}
|
||||||
setIsShowEmail={setIsShowEmail}
|
title={"signers alert"}
|
||||||
|
handleClose={() => {
|
||||||
|
setIsShowEmail(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
<p>Please select signer for add placeholder!</p>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setIsShowEmail(false);
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
>
|
||||||
|
Ok
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
<DropdownWidgetOption
|
||||||
|
type={radioButtonWidget}
|
||||||
|
title="Radio group"
|
||||||
|
showDropdown={isRadio}
|
||||||
|
setShowDropdown={setIsRadio}
|
||||||
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
|
/>
|
||||||
|
<DropdownWidgetOption
|
||||||
|
type="checkbox"
|
||||||
|
title="Checkbox"
|
||||||
|
showDropdown={isCheckbox}
|
||||||
|
setShowDropdown={setIsCheckbox}
|
||||||
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
|
/>
|
||||||
|
<DropdownWidgetOption
|
||||||
|
type="dropdown"
|
||||||
|
title="Dropdown options"
|
||||||
|
showDropdown={showDropdown}
|
||||||
|
setShowDropdown={setShowDropdown}
|
||||||
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
/>
|
/>
|
||||||
<PlaceholderCopy
|
<PlaceholderCopy
|
||||||
isPageCopy={isPageCopy}
|
isPageCopy={isPageCopy}
|
||||||
@@ -1139,6 +1428,14 @@ const TemplatePlaceholder = () => {
|
|||||||
setSignKey={setSignKey}
|
setSignKey={setSignKey}
|
||||||
setSignerObjId={setSignerObjId}
|
setSignerObjId={setSignerObjId}
|
||||||
isDragging={isDragging}
|
isDragging={isDragging}
|
||||||
|
setShowDropdown={setShowDropdown}
|
||||||
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setIsRadio={setIsRadio}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
handleNameModal={setIsNameModal}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1146,25 +1443,19 @@ const TemplatePlaceholder = () => {
|
|||||||
{/* signature button */}
|
{/* signature button */}
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<div>
|
<div>
|
||||||
<FieldsComponent
|
<WidgetComponent
|
||||||
dataTut="reactourFirst"
|
dataTut="reactourFirst"
|
||||||
dataTut2="reactourSecond"
|
dataTut2="reactourSecond"
|
||||||
pdfUrl={isMailSend}
|
pdfUrl={isMailSend}
|
||||||
sign={sign}
|
|
||||||
stamp={stamp}
|
|
||||||
dragSignature={dragSignature}
|
dragSignature={dragSignature}
|
||||||
signRef={signRef}
|
signRef={signRef}
|
||||||
handleDivClick={handleDivClick}
|
handleDivClick={handleDivClick}
|
||||||
handleMouseLeave={handleMouseLeave}
|
handleMouseLeave={handleMouseLeave}
|
||||||
isDragSign={isDragSign}
|
isDragSign={isDragSign}
|
||||||
themeColor={themeColor}
|
|
||||||
dragStamp={dragStamp}
|
dragStamp={dragStamp}
|
||||||
dragRef={dragRef}
|
dragRef={dragRef}
|
||||||
isDragStamp={isDragStamp}
|
isDragStamp={isDragStamp}
|
||||||
isSignYourself={true}
|
isSignYourself={false}
|
||||||
isDragSignatureSS={isDragSignatureSS}
|
|
||||||
dragSignatureSS={dragSignatureSS}
|
|
||||||
dragStampSS={dragStampSS}
|
|
||||||
addPositionOfSignature={addPositionOfSignature}
|
addPositionOfSignature={addPositionOfSignature}
|
||||||
signerPos={signerPos}
|
signerPos={signerPos}
|
||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
@@ -1184,44 +1475,59 @@ const TemplatePlaceholder = () => {
|
|||||||
handleRoleChange={handleRoleChange}
|
handleRoleChange={handleRoleChange}
|
||||||
handleOnBlur={handleOnBlur}
|
handleOnBlur={handleOnBlur}
|
||||||
title={"Roles"}
|
title={"Roles"}
|
||||||
|
initial={true}
|
||||||
|
isTemplateFlow={true}
|
||||||
|
sendInOrder={pdfDetails[0].SendinOrder}
|
||||||
|
setSignersData={setSignersData}
|
||||||
|
blockColor={blockColor}
|
||||||
|
setBlockColor={setBlockColor}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<div className="signerComponent">
|
<div className="signerComponent">
|
||||||
<SignerListPlace
|
<div
|
||||||
signerPos={signerPos}
|
style={{ maxHeight: window.innerHeight - 70 + "px" }}
|
||||||
signersdata={signersdata}
|
className="autoSignScroll"
|
||||||
isSelectListId={isSelectListId}
|
>
|
||||||
setSignerObjId={setSignerObjId}
|
<SignerListPlace
|
||||||
setRoleName={setRoleName}
|
isMailSend={isMailSend}
|
||||||
setIsSelectId={setIsSelectId}
|
signerPos={signerPos}
|
||||||
setContractName={setContractName}
|
signersdata={signersdata}
|
||||||
handleAddSigner={handleAddSigner}
|
isSelectListId={isSelectListId}
|
||||||
setUniqueId={setUniqueId}
|
setSignerObjId={setSignerObjId}
|
||||||
handleDeleteUser={handleDeleteUser}
|
setRoleName={setRoleName}
|
||||||
handleRoleChange={handleRoleChange}
|
setIsSelectId={setIsSelectId}
|
||||||
handleOnBlur={handleOnBlur}
|
setContractName={setContractName}
|
||||||
title={"Roles"}
|
handleAddSigner={handleAddSigner}
|
||||||
/>
|
setUniqueId={setUniqueId}
|
||||||
<div data-tut="reactourSecond">
|
handleDeleteUser={handleDeleteUser}
|
||||||
<FieldsComponent
|
handleRoleChange={handleRoleChange}
|
||||||
pdfUrl={isMailSend}
|
handleOnBlur={handleOnBlur}
|
||||||
sign={sign}
|
|
||||||
stamp={stamp}
|
|
||||||
dragSignature={dragSignature}
|
|
||||||
signRef={signRef}
|
|
||||||
handleDivClick={handleDivClick}
|
|
||||||
handleMouseLeave={handleMouseLeave}
|
|
||||||
isDragSign={isDragSign}
|
|
||||||
themeColor={themeColor}
|
|
||||||
dragStamp={dragStamp}
|
|
||||||
dragRef={dragRef}
|
|
||||||
isDragStamp={isDragStamp}
|
|
||||||
isSignYourself={false}
|
|
||||||
addPositionOfSignature={addPositionOfSignature}
|
|
||||||
title={"Roles"}
|
title={"Roles"}
|
||||||
|
sendInOrder={pdfDetails[0]?.SendinOrder}
|
||||||
|
setSignersData={setSignersData}
|
||||||
|
blockColor={blockColor}
|
||||||
|
setBlockColor={setBlockColor}
|
||||||
/>
|
/>
|
||||||
|
<div data-tut="reactourSecond">
|
||||||
|
<WidgetComponent
|
||||||
|
isMailSend={isMailSend}
|
||||||
|
dragSignature={dragSignature}
|
||||||
|
signRef={signRef}
|
||||||
|
handleDivClick={handleDivClick}
|
||||||
|
handleMouseLeave={handleMouseLeave}
|
||||||
|
isDragSign={isDragSign}
|
||||||
|
dragStamp={dragStamp}
|
||||||
|
dragRef={dragRef}
|
||||||
|
isDragStamp={isDragStamp}
|
||||||
|
isSignYourself={false}
|
||||||
|
addPositionOfSignature={addPositionOfSignature}
|
||||||
|
title={"Roles"}
|
||||||
|
initial={true}
|
||||||
|
isTemplateFlow={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1257,6 +1563,14 @@ const TemplatePlaceholder = () => {
|
|||||||
onSuccess={handleEditTemplateForm}
|
onSuccess={handleEditTemplateForm}
|
||||||
/>
|
/>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
<WidgetNameModal
|
||||||
|
widgetName={widgetName}
|
||||||
|
defaultdata={currWidgetsDetails}
|
||||||
|
isOpen={isNameModal}
|
||||||
|
handleClose={handleNameModal}
|
||||||
|
handleData={handleWidgetdefaultdata}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Navigate, useNavigate } from "react-router-dom";
|
import { Navigate, useNavigate } from "react-router-dom";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { SaveFileSize } from "../constant/saveFileSize";
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
@@ -6,6 +6,12 @@ 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";
|
import axios from "axios";
|
||||||
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { checkIsSubscribed } from "../constant/Utils";
|
||||||
|
import Upgrade from "../primitives/Upgrade";
|
||||||
|
|
||||||
function UserProfile() {
|
function UserProfile() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
||||||
@@ -17,9 +23,25 @@ function UserProfile() {
|
|||||||
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);
|
const [percentage, setpercentage] = useState(0);
|
||||||
|
const [isDisableDocId, setIsDisableDocId] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
useEffect(() => {
|
||||||
Parse.initialize(parseAppId);
|
getUserDetail();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getUserDetail = async () => {
|
||||||
|
const extClass = localStorage.getItem("Extand_Class");
|
||||||
|
const jsonSender = JSON.parse(extClass);
|
||||||
|
const HeaderDocId = jsonSender[0]?.HeaderDocId;
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
if (HeaderDocId) {
|
||||||
|
setIsDisableDocId(HeaderDocId);
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
@@ -33,6 +55,7 @@ function UserProfile() {
|
|||||||
object.set("name", name);
|
object.set("name", name);
|
||||||
object.set("ProfilePic", Image);
|
object.set("ProfilePic", Image);
|
||||||
object.set("phone", phn);
|
object.set("phone", phn);
|
||||||
|
|
||||||
object.save().then(
|
object.save().then(
|
||||||
async (response) => {
|
async (response) => {
|
||||||
if (response) {
|
if (response) {
|
||||||
@@ -66,8 +89,12 @@ 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("UserId ", ExtUserId);
|
|
||||||
const body = { Phone: obj.Phone, Name: obj.Name };
|
const body = {
|
||||||
|
Phone: obj.Phone,
|
||||||
|
Name: obj.Name,
|
||||||
|
HeaderDocId: isDisableDocId
|
||||||
|
};
|
||||||
await axios.put(
|
await axios.put(
|
||||||
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
|
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
|
||||||
body,
|
body,
|
||||||
@@ -122,7 +149,8 @@ function UserProfile() {
|
|||||||
setImage(response.url());
|
setImage(response.url());
|
||||||
localStorage.setItem("profileImg", response.url());
|
localStorage.setItem("profileImg", response.url());
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
SaveFileSize(size, response.url());
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -137,6 +165,9 @@ function UserProfile() {
|
|||||||
return <Navigate to={_redirect} />;
|
return <Navigate to={_redirect} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDisableDocId = () => {
|
||||||
|
setIsDisableDocId((prevChecked) => !prevChecked);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Title title={"Profile"} />
|
<Title title={"Profile"} />
|
||||||
@@ -233,7 +264,7 @@ function UserProfile() {
|
|||||||
<span className="font-semibold">Email:</span>{" "}
|
<span className="font-semibold">Email:</span>{" "}
|
||||||
<span>{UserProfile && UserProfile.email}</span>
|
<span>{UserProfile && UserProfile.email}</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex justify-between items-center border-y-[1px] border-gray-300 py-2 break-all">
|
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
|
||||||
<span className="font-semibold">Is Email verified:</span>{" "}
|
<span className="font-semibold">Is Email verified:</span>{" "}
|
||||||
<span>
|
<span>
|
||||||
{UserProfile && UserProfile.emailVerified
|
{UserProfile && UserProfile.emailVerified
|
||||||
@@ -241,6 +272,52 @@ function UserProfile() {
|
|||||||
: "Not verified"}
|
: "Not verified"}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li className="border-y-[1px] border-gray-300 break-all">
|
||||||
|
<div className="flex justify-between items-center py-2">
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "font-semibold"
|
||||||
|
: "font-semibold text-gray-300"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Disable DocumentId :{" "}
|
||||||
|
<Tooltip
|
||||||
|
url={
|
||||||
|
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
|
||||||
|
}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
|
/>{" "}
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
</span>{" "}
|
||||||
|
<label
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? `${
|
||||||
|
editmode ? "cursor-pointer" : ""
|
||||||
|
} relative inline-flex items-center mb-0`
|
||||||
|
: "relative inline-flex items-center mb-0 pointer-events-none opacity-50"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
disabled={editmode ? false : true}
|
||||||
|
checked={isDisableDocId}
|
||||||
|
onChange={handleDisableDocId}
|
||||||
|
type="checkbox"
|
||||||
|
value=""
|
||||||
|
className="sr-only peer"
|
||||||
|
/>
|
||||||
|
<div className="w-9 h-5 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-black rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-black peer-checked:bg-blue-600"></div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{!isEnableSubscription && (
|
||||||
|
<PremiumAlertHeader
|
||||||
|
message={
|
||||||
|
"Disable documentId is free in beta, this feature will incur a fee later."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
|
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
|
||||||
{editmode ? (
|
{editmode ? (
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||||
|
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||||
|
import Parse from "parse";
|
||||||
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
|
||||||
|
function Webhook() {
|
||||||
|
const navigation = useNavigate();
|
||||||
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
|
const [webhook, setWebhook] = useState();
|
||||||
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
const [isGenerate, setIsGenerate] = useState(false);
|
||||||
|
const [isErr, setIsErr] = useState(false);
|
||||||
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchWebhook();
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchWebhook = async () => {
|
||||||
|
const email = Parse.User.current().getEmail();
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
const params = { email: email };
|
||||||
|
try {
|
||||||
|
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||||
|
if (extRes) {
|
||||||
|
setWebhook(extRes.get("Webhook"));
|
||||||
|
}
|
||||||
|
setIsLoader(false);
|
||||||
|
} catch (err) {
|
||||||
|
setWebhook();
|
||||||
|
setIsLoader(false);
|
||||||
|
console.log("Err", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (webhook && webhook.startsWith("https://")) {
|
||||||
|
setIsLoader(true);
|
||||||
|
setIsModal(false);
|
||||||
|
try {
|
||||||
|
const params = { url: webhook };
|
||||||
|
const url = parseBaseUrl + "functions/savewebhook";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
await axios.post(url, params, { headers: headers }).then((res) => {
|
||||||
|
if (res.data && res.data.result && res.data.result.Webhook) {
|
||||||
|
setWebhook(res.data.result.Webhook);
|
||||||
|
setIsGenerate(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsGenerate(false);
|
||||||
|
}, 1500);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else {
|
||||||
|
console.error("Error while generating webhook");
|
||||||
|
setIsLoader(false);
|
||||||
|
setIsErr(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsErr(false);
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoader(false);
|
||||||
|
setIsErr(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsErr(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setError("The webhook url should always start with https://");
|
||||||
|
setTimeout(() => {
|
||||||
|
setError("");
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleModal = () => setIsModal(!isModal);
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Title title={"Webhook"} />
|
||||||
|
{isGenerate && <Alert type="success">Webhook added successfully!</Alert>}
|
||||||
|
{isErr && <Alert type="danger">Something went wrong!</Alert>}
|
||||||
|
|
||||||
|
{isLoader ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||||
|
{!isEnableSubscription && <PremiumAlertHeader />}
|
||||||
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
OpenSign™ Webhook{" "}
|
||||||
|
<Tooltip
|
||||||
|
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
|
||||||
|
isSubscribe={true}
|
||||||
|
/>
|
||||||
|
</h1>
|
||||||
|
<ul
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "w-full flex flex-col p-2 text-sm "
|
||||||
|
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
|
||||||
|
<span className="">Webhook:</span>{" "}
|
||||||
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
|
{webhook ? webhook : "_____"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleModal}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
{webhook ? "Update Webhook" : "Add Webhook"}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-center ">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
openInNewTab(
|
||||||
|
"https://docs.opensignlabs.com/docs/API-docs/save-update-webhook"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
View Docs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<>
|
||||||
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
Upgrade to PRO Plan
|
||||||
|
</h1>
|
||||||
|
<ul className={"w-full flex flex-col p-2 text-sm "}>
|
||||||
|
<li
|
||||||
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
|
||||||
|
<span className="">$29.99/month:</span>{" "}
|
||||||
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
|
First 100 documents included, then just $0.15 per
|
||||||
|
document.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigation("/subscription")}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isModal}
|
||||||
|
title={"Regenerate Token"}
|
||||||
|
handleClose={handleModal}
|
||||||
|
>
|
||||||
|
{error && <Alert type="danger">{error}</Alert>}
|
||||||
|
<div className="m-[20px]">
|
||||||
|
<div className="text-lg font-normal text-black">
|
||||||
|
<label className="text-sm ml-2">Webhook</label>
|
||||||
|
<input
|
||||||
|
value={webhook}
|
||||||
|
onChange={(e) => setWebhook(e.target.value)}
|
||||||
|
placeholder="Enter webhook url"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<hr className="bg-[#ccc] mt-4 " />
|
||||||
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
|
<button
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className={submitBtn + "ml-[2px]"}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button onClick={handleModal} className={rejectBtn}>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Webhook;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import "../css/AddUser.css";
|
import "../styles/AddUser.css";
|
||||||
const AddUser = (props) => {
|
const AddUser = (props) => {
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [phone, setPhone] = useState("");
|
const [phone, setPhone] = useState("");
|
||||||
@@ -11,9 +11,6 @@ const AddUser = (props) => {
|
|||||||
const [isUserExist, setIsUserExist] = useState(false);
|
const [isUserExist, setIsUserExist] = useState(false);
|
||||||
const parseBaseUrl = localStorage.getItem("baseUrl");
|
const parseBaseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkUserExist();
|
checkUserExist();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -50,8 +47,6 @@ const AddUser = (props) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
try {
|
try {
|
||||||
const contactQuery = new Parse.Object("contracts_Contactbook");
|
const contactQuery = new Parse.Object("contracts_Contactbook");
|
||||||
contactQuery.set("Name", name);
|
contactQuery.set("Name", name);
|
||||||
@@ -59,11 +54,11 @@ const AddUser = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_Guest");
|
contactQuery.set("UserRole", "contracts_Guest");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,10 +153,10 @@ const AddUser = (props) => {
|
|||||||
const res = await contactQuery.save();
|
const res = await contactQuery.save();
|
||||||
|
|
||||||
const parseData = JSON.parse(JSON.stringify(res));
|
const parseData = JSON.parse(JSON.stringify(res));
|
||||||
if(props.details){
|
if (props.details) {
|
||||||
props.details(parseData);
|
props.details(parseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ const Alert = ({ children, type }) => {
|
|||||||
<>
|
<>
|
||||||
{children && (
|
{children && (
|
||||||
<div
|
<div
|
||||||
className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] `}
|
className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] z-50`}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||