Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
03750e3145 | ||
|
|
ff4879a984 | ||
|
|
7a6a543df5 | ||
|
|
edda20940b | ||
|
|
987a4bd04c | ||
|
|
35d20bd42c | ||
|
|
97983c423f | ||
|
|
68050e3a35 | ||
|
|
4f2801d901 | ||
|
|
aaa3dfc304 | ||
|
|
7a9bebe035 | ||
|
|
ce86510d8e | ||
|
|
9d15b035c5 | ||
|
|
156a05f6ed | ||
|
|
22de053cd3 | ||
|
|
13845adbd5 | ||
|
|
ef68f2da16 | ||
|
|
9114908521 | ||
|
|
f565edc655 | ||
|
|
b0e26b8ae2 | ||
|
|
b35d8406a3 | ||
|
|
3910486b17 | ||
|
|
60ba77a06f | ||
|
|
f86ea04a02 | ||
|
|
9e185fa33c | ||
|
|
5142a8c62d | ||
|
|
db4b5f0452 | ||
|
|
042ad8465e | ||
|
|
ebfd9d3af7 | ||
|
|
c0ae0c7ffa | ||
|
|
861a065849 | ||
|
|
3884909965 | ||
|
|
6a0788c2a1 | ||
|
|
bd60f91734 | ||
|
|
b58c3fd467 | ||
|
|
9d431af0b9 | ||
|
|
cb1ebc6a72 | ||
|
|
a198bce3e2 | ||
|
|
e5c50a0dbb | ||
|
|
caa1dfaf34 | ||
|
|
eb01a0b17d | ||
|
|
1add575d26 | ||
|
|
4a52d327ce | ||
|
|
ef68fe1c85 | ||
|
|
83fa9c9ebd | ||
|
|
1a774bfcfa | ||
|
|
db9ec6bfd5 | ||
|
|
5736306f8c | ||
|
|
67cb508944 | ||
|
|
cbcfb8c063 | ||
|
|
da846dcbbb | ||
|
|
e7280bf017 | ||
|
|
9692f57663 | ||
|
|
f0655893eb | ||
|
|
f9e59905b7 | ||
|
|
c115c7c757 | ||
|
|
4edcf807ad | ||
|
|
416d8c823c | ||
|
|
bea158b8f2 | ||
|
|
39c6560a2d | ||
|
|
509b004014 | ||
|
|
f1b7e1164b | ||
|
|
3a2f626cb9 | ||
|
|
7cde6fd73c | ||
|
|
06d6eecaf0 | ||
|
|
c9ed29261d | ||
|
|
87fe5cdd6f | ||
|
|
f74819f50a | ||
|
|
98c8af5b9c | ||
|
|
ca17f1cfc9 | ||
|
|
74e2582ff9 | ||
|
|
8bbbf9b3d8 | ||
|
|
048629dd32 | ||
|
|
fe03da1d97 | ||
|
|
0a6622159f | ||
|
|
7a5cdefcfa | ||
|
|
0a3d89d0e2 | ||
|
|
882b97da5e | ||
|
|
fa405752da | ||
|
|
2d7571af5a | ||
|
|
07a57969ac | ||
|
|
01b7b1cab8 | ||
|
|
fee3d8f672 | ||
|
|
f1628e46fa | ||
|
|
17cb4479cb | ||
|
|
b52511113b | ||
|
|
95cc15ec4c | ||
|
|
1a4b4655c8 | ||
|
|
9fc69ba7e6 | ||
|
|
8ce31d3d80 | ||
|
|
d097f9a741 | ||
|
|
8686a35405 | ||
|
|
a92d90db4a | ||
|
|
bfa0e0e144 | ||
|
|
d3b2e1f24b | ||
|
|
bc90da4cf2 | ||
|
|
61afc35ac8 | ||
|
|
00e9396590 | ||
|
|
bbedb13f3e | ||
|
|
55cfbae8a7 | ||
|
|
bfa19eec0c | ||
|
|
07851ccde2 | ||
|
|
ad5776cfba | ||
|
|
a13478fa64 | ||
|
|
85a1c10d26 | ||
|
|
6918282e31 | ||
|
|
fd778c25e6 | ||
|
|
af344c8ae2 | ||
|
|
c505f8cf86 | ||
|
|
52320e0cd9 | ||
|
|
214db474c2 | ||
|
|
1bffabc94d | ||
|
|
7c8a5e02f2 | ||
|
|
a49c76c188 | ||
|
|
1f16123865 | ||
|
|
e85bbb7bd9 | ||
|
|
34fc3afb1e | ||
|
|
67479a9c1e | ||
|
|
2a8cedca58 | ||
|
|
57fc4aa06b | ||
|
|
39f3f73896 | ||
|
|
f4e907de36 | ||
|
|
72f7e1fb27 | ||
|
|
3dc109c3dd | ||
|
|
83df89c115 | ||
|
|
4070409a59 | ||
|
|
bb732d7606 | ||
|
|
70963c06b8 | ||
|
|
a1a84b6928 | ||
|
|
eefaf5fe50 | ||
|
|
9500b2d678 | ||
|
|
221a49bb4a | ||
|
|
babe17838b | ||
|
|
f5d11f9ba6 | ||
|
|
e52c7c97cf | ||
|
|
ebdc5ef566 | ||
|
|
939d917b7b | ||
|
|
2afb868edc | ||
|
|
a5fe4a345b | ||
|
|
629bf7f51f | ||
|
|
350854ab6b | ||
|
|
cc980758fd | ||
|
|
0f1ce43cc5 | ||
|
|
5e1a9cdc20 | ||
|
|
550ce10c92 | ||
|
|
6080c59bd7 | ||
|
|
273a35d42f | ||
|
|
2f195fe02e | ||
|
|
0715ca9d85 | ||
|
|
a8d564d74d | ||
|
|
89ba3e0fa4 | ||
|
|
eebcfe94d9 | ||
|
|
ea9b0370c4 | ||
|
|
e264511a6e | ||
|
|
1ec10fbcfc | ||
|
|
274620d17b | ||
|
|
06db7d2360 | ||
|
|
2b3549e4df | ||
|
|
d16478792c | ||
|
|
7ba2ef6420 | ||
|
|
b5d98796b7 | ||
|
|
97c17cfe84 | ||
|
|
4b4e200090 | ||
|
|
232d38440d | ||
|
|
341bd9bef0 | ||
|
|
2f4d04c722 | ||
|
|
148ae40e1a | ||
|
|
9cb0ced4f6 | ||
|
|
9a3b70de43 | ||
|
|
742b8f7eae | ||
|
|
abc58941e3 | ||
|
|
aac200bfd3 | ||
|
|
27d3297d61 | ||
|
|
72431b2c82 | ||
|
|
3ca48e5848 | ||
|
|
14784ec80f | ||
|
|
127741eb27 | ||
|
|
2ed987fe10 | ||
|
|
7aaa1876c8 | ||
|
|
390ffb83a2 | ||
|
|
d63e51b8cb | ||
|
|
7bd8d64649 | ||
|
|
f9e6f49ede | ||
|
|
b701d2863f | ||
|
|
cf47093227 | ||
|
|
81d0aea66c | ||
|
|
506ca35be8 | ||
|
|
1cd6718489 | ||
|
|
153c5db4b5 | ||
|
|
ac9367a715 | ||
|
|
081dae0b90 | ||
|
|
e286390aec | ||
|
|
cf88eb2124 | ||
|
|
3226e4fd85 | ||
|
|
cab94eb63d | ||
|
|
bbd5d6805e | ||
|
|
2904ba3085 | ||
|
|
ee609061ed | ||
|
|
6c98a4e899 | ||
|
|
eef9ee7f3c | ||
|
|
2cb4575db1 | ||
|
|
e7bcad80cc | ||
|
|
353839a1dc | ||
|
|
e6d30744ba | ||
|
|
b67932f448 | ||
|
|
c185c42b80 | ||
|
|
4648ace84e | ||
|
|
ccdf50dbe0 | ||
|
|
852a3dc8bb | ||
|
|
d49b7bd201 | ||
|
|
07f2ceed6e | ||
|
|
751c7b5787 | ||
|
|
e82384dff8 | ||
|
|
92d3a85147 | ||
|
|
c5762a0baf | ||
|
|
dc40b04a18 | ||
|
|
1cca5a3085 | ||
|
|
4fe4ca638c | ||
|
|
b8c7110c63 | ||
|
|
288365b74b | ||
|
|
b57e17c01c | ||
|
|
711ab6a556 | ||
|
|
7a12f54587 | ||
|
|
056f4b3e80 | ||
|
|
730a7a4e15 | ||
|
|
a4b4dc885c | ||
|
|
8562a4bb46 | ||
|
|
d3b56432e0 | ||
|
|
527c5be42c | ||
|
|
6c1d0c712a | ||
|
|
fd0ec5fd31 | ||
|
|
f5f19c9b52 | ||
|
|
642ef4f5b7 | ||
|
|
66b65e600b | ||
|
|
01a130ef8c | ||
|
|
c3bccb5412 | ||
|
|
b32e6e71f8 | ||
|
|
3b5875e283 | ||
|
|
da42fe97ae | ||
|
|
56bb7d36eb | ||
|
|
d86b7345d7 | ||
|
|
c1c17160ff | ||
|
|
d400c843e4 | ||
|
|
4e67ab50fe | ||
|
|
74c9e21d55 | ||
|
|
fefcdf6ffc | ||
|
|
0c14d71fa8 | ||
|
|
5170e4eee2 | ||
|
|
8ebfd781c3 | ||
|
|
4e8988bf57 | ||
|
|
c26734751f | ||
|
|
ca6b4e7d82 | ||
|
|
cb4a94d036 | ||
|
|
300ddb810f | ||
|
|
0b687310fd | ||
|
|
3e741ac2f9 | ||
|
|
f65b23ca26 | ||
|
|
92527e5847 | ||
|
|
db9b8d2ba1 | ||
|
|
4866447f33 | ||
|
|
2b345ff840 | ||
|
|
b47bf437a9 | ||
|
|
c44149050c | ||
|
|
0576123a77 |
@@ -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,12 +9,12 @@ 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.
|
||||||
@@ -45,14 +43,14 @@ DO_REGION=us-west
|
|||||||
USE_LOCAL=TRUE
|
USE_LOCAL=TRUE
|
||||||
|
|
||||||
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||||
MAILGUN_API_KEY=XXXXX
|
MAILGUN_API_KEY=
|
||||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||||
SMTP_ENABLE=
|
SMTP_ENABLE=
|
||||||
SMTP_HOST=
|
SMTP_HOST=smtp.yourhost.com
|
||||||
SMTP_PORT=
|
SMTP_PORT=443
|
||||||
SMTP_USER_EMAIL=
|
SMTP_USER_EMAIL=mailer@yourdomain.com
|
||||||
SMTP_PASS=
|
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 && 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:
|
||||||
|
|||||||
@@ -38,10 +38,11 @@
|
|||||||
7. [Acknowledgments](#acknowledgments)
|
7. [Acknowledgments](#acknowledgments)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
Please star ⭐ the repo to support us! 😀
|
||||||
|
|
||||||
### Introduction
|
### Introduction
|
||||||
|
|
||||||
Welcome to OpenSign, an open-source 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 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# 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 .
|
||||||
|
|
||||||
|
# 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,29 +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"]
|
|
||||||
},
|
|
||||||
"rjsf-conditionals": {
|
|
||||||
singleton: true,
|
|
||||||
requiredVersion: dependencies["rjsf-conditionals"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -3,48 +3,56 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^1.9.7",
|
"@radix-ui/themes": "^2.0.3",
|
||||||
"@rjsf/core": "^5.13.0",
|
"@react-pdf/renderer": "^3.3.8",
|
||||||
"@rjsf/utils": "^5.13.0",
|
"@reduxjs/toolkit": "^2.2.1",
|
||||||
"@rjsf/validator-ajv8": "^5.13.0",
|
"axios": "^1.6.0",
|
||||||
"axios": "^1.5.1",
|
|
||||||
"daisyui": "^3.9.2",
|
"daisyui": "^3.9.2",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"html-react-parser": "^4.2.2",
|
"html-react-parser": "^4.2.2",
|
||||||
"json-rules-engine-simplified": "^0.1.17",
|
"jwt-decode": "^4.0.0",
|
||||||
"jwt-decode": "^3.1.2",
|
|
||||||
"mf-cra": "^0.0.5",
|
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"parse": "^4.2.0",
|
"parse": "^4.3.1",
|
||||||
|
"pdf-lib": "^1.17.1",
|
||||||
|
"print-js": "^1.6.0",
|
||||||
|
"radix-ui": "^1.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.9.0",
|
"react-bootstrap": "^2.10.1",
|
||||||
|
"react-datepicker": "^6.2.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-drag-listview": "^2.0.0",
|
||||||
|
"react-draggable": "^4.4.6",
|
||||||
"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-pdf": "^7.7.1",
|
||||||
"react-redux": "^8.1.3",
|
"react-redux": "^8.1.3",
|
||||||
"react-router-dom": "^6.16.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",
|
||||||
"reactour": "^1.19.2",
|
"reactour": "^1.19.2",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
"redux-thunk": "^2.4.2",
|
"redux-thunk": "^2.4.2",
|
||||||
"rjsf-conditionals": "github:prafullnavkar-nxg/rjsf-conditionals",
|
"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",
|
||||||
@@ -74,14 +82,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/runtime-corejs2": "^7.23.2",
|
"@babel/runtime-corejs2": "^7.23.9",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.18",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.0",
|
||||||
"eslint": "^8.51.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"lint-staged": "^15.0.1",
|
"lint-staged": "^15.2.2",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.35",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
"tailwindcss": "^3.3.3"
|
"tailwindcss": "^3.3.3"
|
||||||
|
|||||||
@@ -1,21 +1,53 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, Suspense, 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 PlanSubscriptions 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 ValidateRoute from "./primitives/ValidateRoute";
|
||||||
import ForgetPassword from "./routes/ForgetPassword";
|
import Validate from "./primitives/Validate";
|
||||||
import ChangePassword from "./routes/ChangePassword";
|
import ManageSign from "./pages/Managesign";
|
||||||
import ReportMicroapp from "./components/ReportMicroapp";
|
import TemplatePlaceholder from "./pages/TemplatePlaceholder";
|
||||||
import LoadMf from "./routes/LoadMf";
|
import SignYourSelf from "./pages/SignyourselfPdf";
|
||||||
|
import DraftDocument from "./components/pdf/DraftDocument";
|
||||||
|
import PlaceHolderSign from "./pages/PlaceHolderSign";
|
||||||
|
import PdfRequestFiles from "./pages/PdfRequestFiles";
|
||||||
|
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 GenerateToken = lazy(() => import("./pages/GenerateToken"));
|
||||||
|
const Webhook = lazy(() => import("./pages/Webhook"));
|
||||||
|
const Opensigndrive = lazy(() => import("./pages/Opensigndrive"));
|
||||||
|
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(() => {
|
||||||
@@ -23,12 +55,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) {
|
||||||
@@ -39,108 +75,86 @@ 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>
|
<Suspense fallback={<Loader />}>
|
||||||
<Route exact path="/" element={<Login />} />
|
<Routes>
|
||||||
<Route exact path="/signup" element={<Signup />} />
|
<Route element={<ValidateRoute />}>
|
||||||
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
|
<Route exact path="/" element={<Login />} />
|
||||||
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
|
<Route exact path="/signup" element={<Signup />} />
|
||||||
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
|
</Route>
|
||||||
<>
|
<Route element={<Validate />}>
|
||||||
<Route exact path="/pgsignup" element={<Pgsignup />} />
|
<Route
|
||||||
|
path="/load/template/:templateId"
|
||||||
|
element={<TemplatePlaceholder />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/subscription"
|
path="/load/placeholdersign/:docId"
|
||||||
element={<PlanSubscriptions />}
|
element={<PlaceHolderSign />}
|
||||||
/>
|
/>
|
||||||
</>
|
<Route
|
||||||
)}
|
exact
|
||||||
<Route
|
path="/load/recipientSignPdf/:docId/:contactBookId"
|
||||||
exact
|
element={<PdfRequestFiles />}
|
||||||
path="/changepassword"
|
/>
|
||||||
element={
|
</Route>
|
||||||
<HomeLayout>
|
<Route
|
||||||
<ChangePassword />
|
path="/loadmf/signmicroapp/login/:id/:userMail/:contactBookId/:serverUrl"
|
||||||
</HomeLayout>
|
element={<GuestLogin />}
|
||||||
}
|
/>
|
||||||
/>
|
<Route
|
||||||
<Route
|
path="/login/:id/:userMail/:contactBookId/:serverUrl"
|
||||||
path="/mf/:remoteApp/*"
|
element={<GuestLogin />}
|
||||||
element={
|
/>
|
||||||
<HomeLayout>
|
<Route path="/debugpdf" element={<DebugPdf />} />
|
||||||
<Microapp />
|
<Route path="/forgetpassword" element={<ForgetPassword />} />
|
||||||
</HomeLayout>
|
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
|
||||||
}
|
<>
|
||||||
/>
|
<Route exact path="/pgsignup" element={<Pgsignup />} />
|
||||||
<Route
|
<Route path="/subscription" element={<Subscriptions />} />
|
||||||
path="/asmf/:remoteApp/*"
|
</>
|
||||||
element={
|
)}
|
||||||
<HomeLayout>
|
<Route element={<HomeLayout />}>
|
||||||
<Microapp />
|
<Route path="/changepassword" element={<ChangePassword />} />
|
||||||
</HomeLayout>
|
<Route path="/form/:id" element={<Form />} />
|
||||||
}
|
<Route path="/report/:id" element={<Report />} />
|
||||||
/>
|
<Route path="/dashboard/:id" element={<Dashboard />} />
|
||||||
<Route
|
<Route path="/profile" element={<UserProfile />} />
|
||||||
path="/rpmf/:remoteApp/*"
|
<Route path="/generatetoken" element={<GenerateToken />} />
|
||||||
element={
|
<Route path="/webhook" element={<Webhook />} />
|
||||||
<HomeLayout>
|
<Route path="/managesign" element={<ManageSign />} />
|
||||||
<ReportMicroapp />
|
<Route path="/opensigndrive" element={<Opensigndrive />} />
|
||||||
</HomeLayout>
|
<Route
|
||||||
}
|
path="/template/:templateId"
|
||||||
/>
|
element={<TemplatePlaceholder />}
|
||||||
<Route
|
/>
|
||||||
path="/form/:id"
|
{/* signyouself route with no rowlevel data using docId from url */}
|
||||||
element={
|
<Route path="/signaturePdf/:docId" element={<SignYourSelf />} />
|
||||||
<HomeLayout>
|
{/* draft document route to handle and navigate route page accordiing to document status */}
|
||||||
<Form />
|
<Route path="/draftDocument" element={<DraftDocument />} />
|
||||||
</HomeLayout>
|
{/* recipient placeholder set route with no rowlevel data using docId from url*/}
|
||||||
}
|
<Route
|
||||||
/>
|
path="/placeHolderSign/:docId"
|
||||||
<Route
|
element={<PlaceHolderSign />}
|
||||||
path="/report/:id"
|
/>
|
||||||
element={
|
{/* for user signature (need your sign route) with row level data */}
|
||||||
<HomeLayout>
|
<Route path="/pdfRequestFiles" element={<PdfRequestFiles />} />
|
||||||
<Report />
|
{/* for user signature (need your sign route) with no row level data */}
|
||||||
</HomeLayout>
|
<Route
|
||||||
}
|
path="/pdfRequestFiles/:docId"
|
||||||
/>
|
element={<PdfRequestFiles />}
|
||||||
<Route
|
/>
|
||||||
path="/dashboard/:id"
|
{/* recipient signature route with no rowlevel data using docId from url */}
|
||||||
element={
|
<Route
|
||||||
<HomeLayout>
|
path="/recipientSignPdf/:docId/:contactBookId"
|
||||||
<Dashboard />
|
element={<PdfRequestFiles />}
|
||||||
</HomeLayout>
|
/>
|
||||||
}
|
</Route>
|
||||||
/>
|
<Route path="*" element={<PageNotFound />} />
|
||||||
|
</Routes>
|
||||||
<Route
|
</Suspense>
|
||||||
path="/profile"
|
|
||||||
element={
|
|
||||||
<HomeLayout>
|
|
||||||
<UserProfile />
|
|
||||||
</HomeLayout>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route path="*" element={<PageNotFound />} />
|
|
||||||
{/* <Route exact path="/ForgotPassword" element={<ForgotPassword />} /> */}
|
|
||||||
</Routes>
|
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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 |
@@ -1,8 +1,9 @@
|
|||||||
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 { 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("");
|
||||||
@@ -46,9 +47,8 @@ const AppendFormInForm = (props) => {
|
|||||||
// Define a function to handle form submission
|
// Define a function to handle form submission
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
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);
|
||||||
@@ -105,13 +105,18 @@ const AppendFormInForm = (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));
|
||||||
props.details({
|
if (props.details) {
|
||||||
value: parseData[props.valueKey],
|
props.details({
|
||||||
label: parseData[props.displayKey]
|
value: parseData[props.valueKey],
|
||||||
});
|
label: parseData[props.displayKey]
|
||||||
|
});
|
||||||
|
}
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
}
|
||||||
|
if (props.handleUserData) {
|
||||||
|
props.handleUserData(parseData);
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
// Reset the form fields
|
// Reset the form fields
|
||||||
@@ -158,13 +163,18 @@ const AppendFormInForm = (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));
|
||||||
props.details({
|
if (props.details) {
|
||||||
value: parseData[props.valueKey],
|
props.details({
|
||||||
label: parseData[props.displayKey]
|
value: parseData[props.valueKey],
|
||||||
});
|
label: parseData[props.displayKey]
|
||||||
|
});
|
||||||
|
}
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
}
|
||||||
|
if (props.handleUserData) {
|
||||||
|
props.handleUserData(parseData);
|
||||||
|
}
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
// Reset the form fields
|
// Reset the form fields
|
||||||
setAddYourself(false);
|
setAddYourself(false);
|
||||||
@@ -282,14 +292,16 @@ const AppendFormInForm = (props) => {
|
|||||||
<div className="mt-4 flex justify-start">
|
<div className="mt-4 flex justify-start">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="bg-[#1ab6ce] text-sm text-white px-4 py-2 rounded shadow focus:outline-none"
|
style={{ backgroundColor: modalSubmitBtnColor }}
|
||||||
|
className="mr-2 px-[20px] py-1.5 text-white rounded shadow-md text-center focus:outline-none "
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleReset()}
|
onClick={() => handleReset()}
|
||||||
className="bg-[#188ae2] text-sm text-white px-4 py-2 rounded ml-2 shadow focus:outline-none"
|
style={{ backgroundColor: modalCancelBtnColor }}
|
||||||
|
className="px-4 py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none"
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
</button>
|
</button>
|
||||||
@@ -300,4 +312,4 @@ const AppendFormInForm = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppendFormInForm;
|
export default AddSigner;
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Parse from "parse";
|
||||||
|
import axios from "axios";
|
||||||
|
import Title from "./Title";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
|
||||||
|
const AddUser = (props) => {
|
||||||
|
const [name, setName] = useState("");
|
||||||
|
const [phone, setPhone] = useState("");
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
|
const [isUserExist, setIsUserExist] = useState(false);
|
||||||
|
const parseBaseUrl = localStorage.getItem("baseUrl");
|
||||||
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
|
const checkUserExist = async () => {
|
||||||
|
try {
|
||||||
|
const res = await Parse.Cloud.run("getUserDetails", {
|
||||||
|
email: email,
|
||||||
|
userId: Parse.User.current().id
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Define a function to handle form submission
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsLoader(true);
|
||||||
|
const res = await checkUserExist();
|
||||||
|
if (res) {
|
||||||
|
setIsUserExist(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsUserExist(false);
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const contactQuery = new Parse.Object("contracts_Users");
|
||||||
|
contactQuery.set("Name", name);
|
||||||
|
contactQuery.set("Phone", phone);
|
||||||
|
contactQuery.set("Email", email);
|
||||||
|
contactQuery.set("UserRole", "contracts_User");
|
||||||
|
|
||||||
|
if (localStorage.getItem("TenetId")) {
|
||||||
|
contactQuery.set("TenantId", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "partners_Tenant",
|
||||||
|
objectId: localStorage.getItem("TenetId")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const _users = Parse.Object.extend("User");
|
||||||
|
const _user = new _users();
|
||||||
|
_user.set("name", name);
|
||||||
|
_user.set("username", email);
|
||||||
|
_user.set("email", email);
|
||||||
|
_user.set("phone", phone);
|
||||||
|
_user.set("password", phone);
|
||||||
|
|
||||||
|
const user = await _user.save();
|
||||||
|
if (user) {
|
||||||
|
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
const body = {
|
||||||
|
appName: localStorage.getItem("_appName"),
|
||||||
|
roleName: "contracts_User",
|
||||||
|
userId: user.id
|
||||||
|
};
|
||||||
|
await axios.post(roleurl, body, { headers: headers });
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
contactQuery.set(
|
||||||
|
"CreatedBy",
|
||||||
|
Parse.User.createWithoutData(currentUser.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
contactQuery.set("UserId", user);
|
||||||
|
const acl = new Parse.ACL();
|
||||||
|
acl.setPublicReadAccess(true);
|
||||||
|
acl.setPublicWriteAccess(true);
|
||||||
|
acl.setReadAccess(currentUser.id, true);
|
||||||
|
acl.setWriteAccess(currentUser.id, true);
|
||||||
|
|
||||||
|
contactQuery.setACL(acl);
|
||||||
|
|
||||||
|
const res = await contactQuery.save();
|
||||||
|
|
||||||
|
const parseData = JSON.parse(JSON.stringify(res));
|
||||||
|
if (props.details) {
|
||||||
|
props.details({
|
||||||
|
value: parseData[props.valueKey],
|
||||||
|
label: parseData[props.displayKey]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (props.closePopup) {
|
||||||
|
props.closePopup();
|
||||||
|
}
|
||||||
|
if (props.handleUserData) {
|
||||||
|
props.handleUserData(parseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoader(false);
|
||||||
|
|
||||||
|
setName("");
|
||||||
|
setPhone("");
|
||||||
|
setEmail("");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err ", err);
|
||||||
|
if (err.code === 202) {
|
||||||
|
const params = { email: email };
|
||||||
|
const userRes = await Parse.Cloud.run("getUserId", params);
|
||||||
|
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
const body = {
|
||||||
|
appName: localStorage.getItem("_appName"),
|
||||||
|
roleName: "contracts_User",
|
||||||
|
userId: userRes.id
|
||||||
|
};
|
||||||
|
await axios.post(roleurl, body, { headers: headers });
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
contactQuery.set(
|
||||||
|
"CreatedBy",
|
||||||
|
Parse.User.createWithoutData(currentUser.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
contactQuery.set("UserId", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "_User",
|
||||||
|
objectId: userRes.id
|
||||||
|
});
|
||||||
|
const acl = new Parse.ACL();
|
||||||
|
acl.setPublicReadAccess(true);
|
||||||
|
acl.setPublicWriteAccess(true);
|
||||||
|
acl.setReadAccess(currentUser.id, true);
|
||||||
|
acl.setWriteAccess(currentUser.id, true);
|
||||||
|
|
||||||
|
contactQuery.setACL(acl);
|
||||||
|
const res = await contactQuery.save();
|
||||||
|
|
||||||
|
const parseData = JSON.parse(JSON.stringify(res));
|
||||||
|
if (props.details) {
|
||||||
|
props.details({
|
||||||
|
value: parseData[props.valueKey],
|
||||||
|
label: parseData[props.displayKey]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (props.closePopup) {
|
||||||
|
props.closePopup();
|
||||||
|
}
|
||||||
|
if (props.handleUserData) {
|
||||||
|
props.handleUserData(parseData);
|
||||||
|
}
|
||||||
|
setIsLoader(false);
|
||||||
|
setName("");
|
||||||
|
setPhone("");
|
||||||
|
setEmail("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// console.log("err", err);
|
||||||
|
setIsLoader(false);
|
||||||
|
alert("something went wrong!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define a function to handle the "add yourself" checkbox
|
||||||
|
const handleReset = () => {
|
||||||
|
setName("");
|
||||||
|
setPhone("");
|
||||||
|
setEmail("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
||||||
|
<Title title={"Add User"} />
|
||||||
|
{isUserExist && <Alert type="danger">User already exists!</Alert>}
|
||||||
|
{isLoader && (
|
||||||
|
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="w-full mx-auto">
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<h1 className="text-[20px] font-semibold mb-4">Add User</h1>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="name"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
required
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="email"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Email
|
||||||
|
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="phone"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Phone
|
||||||
|
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="phone"
|
||||||
|
value={phone}
|
||||||
|
onChange={(e) => setPhone(e.target.value)}
|
||||||
|
required
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleReset()}
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddUser;
|
||||||
@@ -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;
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Package from "../../package.json";
|
import Package from "../../package.json";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { openInNewTab } from "../constant/Utils";
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
const [showButton, setShowButton] = useState(false);
|
const [showButton, setShowButton] = useState(false);
|
||||||
const [version, setVersion] = useState("");
|
const [version, setVersion] = useState("");
|
||||||
@@ -37,12 +38,18 @@ const Footer = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const appName = "OpenSign™";
|
const appName = "OpenSign™";
|
||||||
|
const openUrl = () => {
|
||||||
|
openInNewTab(
|
||||||
|
"https://github.com/OpenSignLabs/OpenSign/releases/tag/" + version
|
||||||
|
);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
|
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
|
||||||
All Rights Reserved © {new Date().getFullYear()}
|
All Rights Reserved © {new Date().getFullYear()}
|
||||||
{appName} ( version: {version ? version : `${Package.version} `})
|
<span onClick={openUrl} className="hover:underline cursor-pointer">
|
||||||
|
{appName} ( version: {version ? version : `${Package.version} `})
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ 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";
|
||||||
const Header = ({ showSidebar }) => {
|
const Header = ({ showSidebar }) => {
|
||||||
const navigation = useNavigate();
|
const navigation = 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);
|
||||||
|
|
||||||
@@ -21,8 +20,6 @@ const Header = ({ showSidebar }) => {
|
|||||||
|
|
||||||
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");
|
||||||
@@ -31,8 +28,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();
|
||||||
|
|
||||||
@@ -43,8 +40,8 @@ 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("/");
|
navigation("/");
|
||||||
};
|
};
|
||||||
@@ -118,6 +115,12 @@ const Header = ({ showSidebar }) => {
|
|||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
className="hover:bg-gray-100 rounded-t-lg py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 rounded-t-lg py-1 px-2 cursor-pointer font-normal"
|
||||||
|
onClick={() => openInNewTab("https://docs.opensignlabs.com")}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-book"></i> Docs
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
navigation("/profile");
|
navigation("/profile");
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ const LoginFacebook = ({
|
|||||||
email: userDetails.Email,
|
email: userDetails.Email,
|
||||||
// "passsword":userDetails.Phone,
|
// "passsword":userDetails.Phone,
|
||||||
phone: userDetails.Phone,
|
phone: userDetails.Phone,
|
||||||
role: "contracts_Admin",
|
role: "contracts_User",
|
||||||
company: userDetails.Company
|
company: userDetails.Company
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
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 { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* `GoogleSignInBtn`as it's name indicates it render google sign in button
|
* `GoogleSignInBtn`as it's name indicates it render google sign in button
|
||||||
@@ -46,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");
|
||||||
@@ -61,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);
|
||||||
@@ -148,7 +150,7 @@ const GoogleSignInBtn = ({
|
|||||||
email: userDetails.Email,
|
email: userDetails.Email,
|
||||||
// "passsword":userDetails.Phone,
|
// "passsword":userDetails.Phone,
|
||||||
phone: userDetails.Phone,
|
phone: userDetails.Phone,
|
||||||
role: "contracts_Admin",
|
role: "contracts_User",
|
||||||
company: userDetails.Company,
|
company: userDetails.Company,
|
||||||
jobTitle: userDetails.Destination
|
jobTitle: userDetails.Destination
|
||||||
}
|
}
|
||||||
@@ -189,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();
|
||||||
|
|
||||||
@@ -201,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" }}>
|
||||||
@@ -231,118 +233,94 @@ const GoogleSignInBtn = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div ref={googleBtn} className="text-sm"></div>
|
<div ref={googleBtn} className="text-sm"></div>
|
||||||
|
<ModalUi showClose={false} isOpen={isModal} title="Sign up form">
|
||||||
{isModal && (
|
<form className="px-4 py-3">
|
||||||
<div
|
<div className="mb-3">
|
||||||
className="modal fade show"
|
<label
|
||||||
id="exampleModal"
|
htmlFor="Phone"
|
||||||
tabIndex="-1"
|
style={{ display: "flex" }}
|
||||||
role="dialog"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
style={{ display: "block", zIndex: 1 }}
|
>
|
||||||
>
|
Phone <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||||
<div className="modal-dialog" role="document">
|
</label>
|
||||||
<div className="modal-content">
|
<input
|
||||||
<div className="modal-header">
|
type="tel"
|
||||||
<h5 className="modal-title">Sign up form</h5>
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
<span>
|
id="Phone"
|
||||||
<span></span>
|
value={userDetails.Phone}
|
||||||
</span>
|
onChange={(e) =>
|
||||||
</div>
|
setUserDetails({
|
||||||
<div className="modal-body">
|
...userDetails,
|
||||||
<form>
|
Phone: e.target.value
|
||||||
<div className="form-group">
|
})
|
||||||
<label
|
}
|
||||||
htmlFor="Phone"
|
required
|
||||||
style={{ display: "flex" }}
|
/>
|
||||||
className="col-form-label"
|
|
||||||
>
|
|
||||||
Phone{" "}
|
|
||||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="tel"
|
|
||||||
className="form-control"
|
|
||||||
id="Phone"
|
|
||||||
value={userDetails.Phone}
|
|
||||||
onChange={(e) =>
|
|
||||||
setUserDetails({
|
|
||||||
...userDetails,
|
|
||||||
Phone: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
|
||||||
<label
|
|
||||||
htmlFor="Company"
|
|
||||||
style={{ display: "flex" }}
|
|
||||||
className="col-form-label"
|
|
||||||
>
|
|
||||||
Company{" "}
|
|
||||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
id="Company"
|
|
||||||
value={userDetails.Company}
|
|
||||||
onChange={(e) =>
|
|
||||||
setUserDetails({
|
|
||||||
...userDetails,
|
|
||||||
Company: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
|
||||||
<label
|
|
||||||
htmlFor="JobTitle"
|
|
||||||
style={{ display: "flex" }}
|
|
||||||
className="col-form-label"
|
|
||||||
>
|
|
||||||
Job Title{" "}
|
|
||||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
id="JobTitle"
|
|
||||||
value={userDetails.Destination}
|
|
||||||
onChange={(e) =>
|
|
||||||
setUserDetails({
|
|
||||||
...userDetails,
|
|
||||||
Destination: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="bg-[#17a2b8] p-2 text-white rounded"
|
|
||||||
onClick={() => handleSubmitbtn()}
|
|
||||||
style={{ marginRight: 10 }}
|
|
||||||
>
|
|
||||||
Sign up
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="bg-[#6c757d] p-2 text-white rounded"
|
|
||||||
onClick={handleCloseModal}
|
|
||||||
style={{ width: 90 }}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="mb-3">
|
||||||
)}
|
<label
|
||||||
|
htmlFor="Company"
|
||||||
|
style={{ display: "flex" }}
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Company <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
id="Company"
|
||||||
|
value={userDetails.Company}
|
||||||
|
onChange={(e) =>
|
||||||
|
setUserDetails({
|
||||||
|
...userDetails,
|
||||||
|
Company: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="JobTitle"
|
||||||
|
style={{ display: "flex" }}
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Job Title <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
id="JobTitle"
|
||||||
|
value={userDetails.Destination}
|
||||||
|
onChange={(e) =>
|
||||||
|
setUserDetails({
|
||||||
|
...userDetails,
|
||||||
|
Destination: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none "
|
||||||
|
onClick={() => handleSubmitbtn()}
|
||||||
|
style={{ marginRight: 10, backgroundColor: modalSubmitBtnColor }}
|
||||||
|
>
|
||||||
|
Sign up
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="p-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none"
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
style={{ width: 90, backgroundColor: modalCancelBtnColor }}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Document, Page } from "react-pdf";
|
||||||
|
import { Stage, Layer, Rect } from "react-konva";
|
||||||
|
const RenderDebugPdf = (props) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "sticky",
|
||||||
|
top: 0,
|
||||||
|
padding: 10,
|
||||||
|
zIndex: 1,
|
||||||
|
backgroundColor: "white",
|
||||||
|
border: "1px solid grey",
|
||||||
|
margin: "5px 0"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Co-ordinates: X - ${props.hoverCoordinates.x}, Y - ${props.hoverCoordinates.y}`}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
position: "relative",
|
||||||
|
border: "1px solid grey",
|
||||||
|
overflow: "auto"
|
||||||
|
}}
|
||||||
|
onMouseMove={props.handleMouseMoveDiv}
|
||||||
|
>
|
||||||
|
<Document
|
||||||
|
onLoadError={() => {
|
||||||
|
const load = {
|
||||||
|
status: false,
|
||||||
|
type: "failed"
|
||||||
|
};
|
||||||
|
props.setPdfLoadFail(load);
|
||||||
|
}}
|
||||||
|
loading={"Loading Document.."}
|
||||||
|
onLoadSuccess={props.pageDetails}
|
||||||
|
ref={props.pdfRef}
|
||||||
|
file={props.pdfUrl}
|
||||||
|
>
|
||||||
|
<Page
|
||||||
|
onLoadSuccess={props.handlePageLoadSuccess}
|
||||||
|
pageNumber={props.pageNumber}
|
||||||
|
renderAnnotationLayer={false}
|
||||||
|
renderTextLayer={false}
|
||||||
|
onGetAnnotationsError={(error) => {
|
||||||
|
console.log("annotation error", error);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Document>
|
||||||
|
|
||||||
|
<Stage
|
||||||
|
onMouseMove={props.handleMouseMove}
|
||||||
|
onMouseDown={props.handleMouseDown}
|
||||||
|
onMouseUp={props.handleMouseUp}
|
||||||
|
width={props.pdfDimension.width}
|
||||||
|
height={props.pdfDimension.height}
|
||||||
|
style={{ position: "absolute", top: 0, left: 0 }}
|
||||||
|
>
|
||||||
|
<Layer>
|
||||||
|
{props.annotations
|
||||||
|
.filter((value) => value.page === props.pageNumber)
|
||||||
|
.map((value) => {
|
||||||
|
return (
|
||||||
|
<Rect
|
||||||
|
key={value.key}
|
||||||
|
x={value.x}
|
||||||
|
y={value.y}
|
||||||
|
width={value.width}
|
||||||
|
height={value.height}
|
||||||
|
fill="transparent"
|
||||||
|
stroke="black"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Layer>
|
||||||
|
</Stage>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RenderDebugPdf;
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,391 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import Form from "@rjsf/core";
|
|
||||||
import validator from "@rjsf/validator-ajv8";
|
|
||||||
import Parse from "parse";
|
|
||||||
import "../styles/loader.css";
|
|
||||||
import LayoutField from "./fields/Rjsf-layout";
|
|
||||||
import TimeWidget from "./fields/TimeWidget";
|
|
||||||
import Level1Dropdown from "./fields/Level1Dropdown";
|
|
||||||
import HiddenField from "./fields/HiddenField";
|
|
||||||
import MultiSelectField from "./fields/MultiSelectField";
|
|
||||||
import TreeWidget from "../components/TreeWidget";
|
|
||||||
import { formJson } from "../json/FormJson";
|
|
||||||
const TreeEditForm = (props) => {
|
|
||||||
const widget = {
|
|
||||||
TimeWidget: TimeWidget
|
|
||||||
};
|
|
||||||
const fields = {
|
|
||||||
layout: LayoutField,
|
|
||||||
Level1Dropdown: Level1Dropdown,
|
|
||||||
HiddenField: HiddenField,
|
|
||||||
MultiSelectField: MultiSelectField,
|
|
||||||
FolderComponent: TreeWidget
|
|
||||||
};
|
|
||||||
|
|
||||||
const [schema, setschema] = useState({});
|
|
||||||
const [ui_schema, setui_schema] = useState({});
|
|
||||||
const [title, settitle] = useState("");
|
|
||||||
const [schemaState, setschemaState] = useState({});
|
|
||||||
const [formData, setformData] = useState({});
|
|
||||||
const [active, setactive] = useState(true);
|
|
||||||
const [loading, setloading] = useState(false);
|
|
||||||
const [_validate, set_validate] = useState(null);
|
|
||||||
const [noValidate, setnoValidate] = useState(false);
|
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
|
|
||||||
const getForm = async (id) => {
|
|
||||||
setloading(true);
|
|
||||||
try {
|
|
||||||
//get json form data (schema ,uischema)
|
|
||||||
const results = formJson(id);
|
|
||||||
try {
|
|
||||||
let _record = Parse.Object.extend(results.class);
|
|
||||||
var query1 = new Parse.Query(_record);
|
|
||||||
await query1.get(props.objectId).then(
|
|
||||||
(x) => {
|
|
||||||
try {
|
|
||||||
if (x) {
|
|
||||||
let result = x.toJSON();
|
|
||||||
let new_result = result;
|
|
||||||
for (let [key, value] of Object.entries(result)) {
|
|
||||||
if (value["__type"] === "Date") {
|
|
||||||
let todayTime1 = new Date(value.iso);
|
|
||||||
var month = String(todayTime1.getMonth() + 1);
|
|
||||||
var day = String(todayTime1.getDate());
|
|
||||||
var year = String(todayTime1.getFullYear());
|
|
||||||
if (month.length < 2) month = "0" + month;
|
|
||||||
if (day.length < 2) day = "0" + day;
|
|
||||||
let date1 = year + "-" + month + "-" + day;
|
|
||||||
let bindVar = date1;
|
|
||||||
if (!results.jsonSchema.properties[key].format) {
|
|
||||||
bindVar = todayTime1.toISOString();
|
|
||||||
}
|
|
||||||
new_result[key] = bindVar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setschemaState(results.jsonSchema);
|
|
||||||
setformData(new_result);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
//alert(error.message);
|
|
||||||
|
|
||||||
setloading(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
console.log("err", error);
|
|
||||||
setloading(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
setschema(results.jsonSchema);
|
|
||||||
setui_schema(results.uiSchema);
|
|
||||||
set_validate(results.validFunction);
|
|
||||||
setnoValidate(results.noValidate);
|
|
||||||
settitle(results.class);
|
|
||||||
setloading(false);
|
|
||||||
setactive(true);
|
|
||||||
} catch (error) {
|
|
||||||
setloading(false);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
setloading(false);
|
|
||||||
console.error("Problem", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrap = (s) => "{ return " + s + " };";
|
|
||||||
|
|
||||||
const dynamicValidate = (formData, errors) => {
|
|
||||||
try {
|
|
||||||
let body = atob(_validate);
|
|
||||||
let res = new Function(wrap(body))
|
|
||||||
.call(null)
|
|
||||||
.call(null, formData, errors);
|
|
||||||
return res;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async ({ formData }) => {
|
|
||||||
setactive(false);
|
|
||||||
setloading(true);
|
|
||||||
let RowData = formData;
|
|
||||||
RowData &&
|
|
||||||
Object.entries(RowData).forEach(([key, value]) => {
|
|
||||||
if (typeof value === "string") {
|
|
||||||
RowData[key] = value.trim();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let _scanData = schemaState;
|
|
||||||
if (_scanData.dependencies) {
|
|
||||||
Object.keys(_scanData.dependencies).forEach((key) => {
|
|
||||||
if (_scanData.dependencies[key].oneOf) {
|
|
||||||
_scanData.dependencies[key].oneOf.forEach((val) => {
|
|
||||||
Object.keys(val.properties).forEach((k) => {
|
|
||||||
if (typeof val.properties[k] === "object") {
|
|
||||||
if (val.properties[k].format === "date") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newdate = new Date(RowData[k]);
|
|
||||||
RowData[k] = newdate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val.properties[k].component === "HtmlEditor") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newHtml = RowData[k]
|
|
||||||
.replace(/<p[^>]*>/g, "")
|
|
||||||
.replace(/<\/p>/g, " ");
|
|
||||||
RowData[k] = newHtml;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val.properties[k].component === "DateTime") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newDate11 = new Date(RowData[k]);
|
|
||||||
RowData[k] = newDate11;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val.properties[k].component === "CurrencyInput") {
|
|
||||||
if (val.properties[k].currencyColumn) {
|
|
||||||
RowData[`${val.properties[k].currencyColumn}`] =
|
|
||||||
val.properties[k].defaultcurrency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val.properties[k].type === "string") {
|
|
||||||
if (typeof RowData[k] === "string")
|
|
||||||
RowData[k] = RowData[k].trim();
|
|
||||||
}
|
|
||||||
if (val.properties[k].data !== undefined) {
|
|
||||||
if (val.properties[k].data.isPointer) {
|
|
||||||
let pointer = undefined;
|
|
||||||
if (val.properties[k].data.class) {
|
|
||||||
if (RowData[k]) {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: val.properties[k].data.class,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (RowData[k]) {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: localStorage.getItem("extended_class"),
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RowData[k] = pointer;
|
|
||||||
}
|
|
||||||
if (val.properties[k].data.FolderTypeValue) {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let obj = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: val.properties[k].data.ClassName,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
RowData[k] = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let temp = [];
|
|
||||||
|
|
||||||
let _dd = _scanData.properties;
|
|
||||||
let allowed = [];
|
|
||||||
if (_dd) {
|
|
||||||
Object.keys(_dd).forEach(function (k) {
|
|
||||||
allowed.push(k);
|
|
||||||
if (RowData[k]) {
|
|
||||||
let pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].class,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
RowData[k] = pointer;
|
|
||||||
}
|
|
||||||
if (_dd[k].format === "date") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newdate = new Date(RowData[k]);
|
|
||||||
if (!isNaN(newdate.getTime())) {
|
|
||||||
RowData[k] = newdate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].component === "HtmlEditor") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newHtml = RowData[k]
|
|
||||||
.replace(/<p[^>]*>/g, "")
|
|
||||||
.replace(/<\/p>/g, " ");
|
|
||||||
RowData[k] = newHtml;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].component === "DateTime") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let newdate = new Date(RowData[k]);
|
|
||||||
if (!isNaN(newdate.getTime())) {
|
|
||||||
RowData[k] = newdate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].format === "date-time") {
|
|
||||||
let newdate = new Date(RowData[k]);
|
|
||||||
RowData[k] = newdate;
|
|
||||||
}
|
|
||||||
if (_dd[k].component === "CurrencyInput") {
|
|
||||||
if (_dd[k].currencyColumn) {
|
|
||||||
RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].data !== undefined) {
|
|
||||||
if (_dd[k].data.isPointer) {
|
|
||||||
let pointer = undefined;
|
|
||||||
if (typeof RowData[k] === "object") {
|
|
||||||
if (RowData[k]) {
|
|
||||||
if (RowData[k].objectId !== "Select") {
|
|
||||||
let obj = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: RowData[k].className,
|
|
||||||
objectId: RowData[k].objectId
|
|
||||||
};
|
|
||||||
pointer = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (_dd[k].data.class) {
|
|
||||||
if (RowData[k]) {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].data.class,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (RowData[k]) {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: localStorage.getItem("extended_class"),
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowData[k] = pointer;
|
|
||||||
}
|
|
||||||
if (_dd[k].data.FolderTypeValue) {
|
|
||||||
if (RowData[k]) {
|
|
||||||
let obj = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].data.ClassName,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
RowData[k] = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].type === "string") {
|
|
||||||
if (typeof RowData[k] === "string") RowData[k] = RowData[k].trim();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const filtered = Object.keys(RowData)
|
|
||||||
.filter((key) => allowed.includes(key))
|
|
||||||
.reduce((obj, key) => {
|
|
||||||
obj[key] = RowData[key];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
try {
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
if (temp.length !== 0) {
|
|
||||||
let userPointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: "_User",
|
|
||||||
objectId: currentUser.id
|
|
||||||
};
|
|
||||||
filtered[[temp[0]]] = userPointer;
|
|
||||||
}
|
|
||||||
var data = Parse.Object.extend(title);
|
|
||||||
var query = new Parse.Query(data);
|
|
||||||
query.get(props.objectId).then(async (object) => {
|
|
||||||
object.save(filtered).then(
|
|
||||||
() => {
|
|
||||||
try {
|
|
||||||
alert("Record updated successfully");
|
|
||||||
props.HideView(false);
|
|
||||||
setloading(false);
|
|
||||||
setactive(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("err", error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
console.log("err", error);
|
|
||||||
setloading(false);
|
|
||||||
setactive(true);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log("err", error);
|
|
||||||
|
|
||||||
alert(error.message);
|
|
||||||
setloading(false);
|
|
||||||
setactive(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.FormId) {
|
|
||||||
getForm(props.FormId);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [props.FormId]);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="loader-01"
|
|
||||||
style={{
|
|
||||||
marginTop: "50px",
|
|
||||||
marginLeft: "50%",
|
|
||||||
color: "rgb(0,28,28)",
|
|
||||||
fontSize: "35px"
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
schema={schema}
|
|
||||||
uiSchema={ui_schema}
|
|
||||||
formData={formData}
|
|
||||||
showErrorList={false}
|
|
||||||
widgets={widget}
|
|
||||||
fields={fields}
|
|
||||||
validate={noValidate && dynamicValidate}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
validator={validator}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{active ? (
|
|
||||||
<button className="bg-[#1ab6ce] px-3 py-2 rounded text-white text-sm" type="submit">
|
|
||||||
Update
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button className="bg-[#1ab6ce] px-3 py-2 rounded text-white text-sm" type="submit" disabled>
|
|
||||||
Update
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TreeEditForm;
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import Form from "@rjsf/core";
|
|
||||||
import validator from "@rjsf/validator-ajv8";
|
|
||||||
import LayoutField from "./fields/Rjsf-layout";
|
|
||||||
import Level1Dropdown from "./fields/Level1Dropdown";
|
|
||||||
import HiddenField from "./fields/HiddenField";
|
|
||||||
import MultiSelectField from "./fields/MultiSelectField";
|
|
||||||
import "../styles/loader.css";
|
|
||||||
import "../styles/form.css";
|
|
||||||
import FileUpload from "./fields/FileUpload";
|
|
||||||
import parse from "html-react-parser";
|
|
||||||
import TimeWidget from "./fields/TimeWidget";
|
|
||||||
import { formJson } from "../json/FormJson";
|
|
||||||
function TreeFormComponent(props) {
|
|
||||||
const widget = {
|
|
||||||
TimeWidget: TimeWidget
|
|
||||||
};
|
|
||||||
|
|
||||||
const fields = {
|
|
||||||
layout: LayoutField,
|
|
||||||
FileUpload: FileUpload,
|
|
||||||
Level1Dropdown: Level1Dropdown,
|
|
||||||
HiddenField: HiddenField,
|
|
||||||
MultiSelectField: MultiSelectField
|
|
||||||
};
|
|
||||||
|
|
||||||
const [link, setLink] = useState("");
|
|
||||||
const [help, setHelp] = useState("");
|
|
||||||
const toastDescription = "";
|
|
||||||
const toastColor = "#5cb85c";
|
|
||||||
const [loading, setLoding] = useState(true);
|
|
||||||
const [schemaState, setSchemaState] = useState({});
|
|
||||||
const [formData, setFormData] = useState({});
|
|
||||||
const [ui_schema, setUi_schema] = useState({});
|
|
||||||
const active = true;
|
|
||||||
|
|
||||||
console.log("new form", props);
|
|
||||||
|
|
||||||
const getForm = async (id) => {
|
|
||||||
setLoding(true);
|
|
||||||
try {
|
|
||||||
// get json from data(jsonschema, uischema)
|
|
||||||
const results = formJson(id);
|
|
||||||
// console.log("result", results);
|
|
||||||
if (results) {
|
|
||||||
let parentObject = {},
|
|
||||||
childObject = {};
|
|
||||||
const resultjson = results;
|
|
||||||
for (let [key, value] of Object.entries(
|
|
||||||
resultjson.jsonSchema.properties
|
|
||||||
)) {
|
|
||||||
if (key === props.ParentField) {
|
|
||||||
if (props.ParentValue[key]) {
|
|
||||||
parentObject = { [key]: props.ParentValue[key] };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (props.ParentValue && typeof props.ParentValue === "object") {
|
|
||||||
Object.entries(props.ParentValue).forEach(([k, value]) => {
|
|
||||||
if (k === key) {
|
|
||||||
let newO = { [k]: value };
|
|
||||||
parentObject = { ...parentObject, ...newO };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (props.ChildField) {
|
|
||||||
Object.entries(props.ChildField).forEach(([k, value]) => {
|
|
||||||
if (k === key) {
|
|
||||||
let newO = { [k]: value };
|
|
||||||
childObject = { ...childObject, ...newO };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value === "object") {
|
|
||||||
for (let [k, v] of Object.entries(value)) {
|
|
||||||
if (k === "format" && v === "date") {
|
|
||||||
let today = new Date();
|
|
||||||
let date =
|
|
||||||
today.getFullYear() +
|
|
||||||
"-" +
|
|
||||||
("0" + (today.getMonth() + 1)).slice(-2) +
|
|
||||||
"-" +
|
|
||||||
("0" + today.getDate()).slice(-2);
|
|
||||||
value.default = date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (props.ParentField) {
|
|
||||||
setFormData({ ...parentObject, ...childObject });
|
|
||||||
}
|
|
||||||
|
|
||||||
let txt, link;
|
|
||||||
if (resultjson.help) {
|
|
||||||
if (resultjson.help.htmlbody) {
|
|
||||||
txt = resultjson.help.htmlbody;
|
|
||||||
}
|
|
||||||
if (resultjson.help.link) {
|
|
||||||
link = resultjson.help.link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setHelp(txt);
|
|
||||||
setLink(link);
|
|
||||||
|
|
||||||
props.ClassName(resultjson.class);
|
|
||||||
props.SchemaState(resultjson.jsonSchema);
|
|
||||||
setSchemaState(resultjson.jsonSchema);
|
|
||||||
setUi_schema(resultjson.uiSchema);
|
|
||||||
setLoding(false);
|
|
||||||
} else {
|
|
||||||
alert("form not found");
|
|
||||||
setLoding(false);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Problem", e);
|
|
||||||
setLoding(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!props.IsEdit) {
|
|
||||||
getForm(props.Id);
|
|
||||||
}
|
|
||||||
// console.log("props tree", props);
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
let formView = (
|
|
||||||
<React.Fragment>
|
|
||||||
<Form
|
|
||||||
schema={schemaState}
|
|
||||||
uiSchema={ui_schema}
|
|
||||||
showErrorList={false}
|
|
||||||
widgets={widget}
|
|
||||||
fields={fields}
|
|
||||||
formData={formData}
|
|
||||||
onSubmit={props.handleSubmit}
|
|
||||||
validator={validator}
|
|
||||||
>
|
|
||||||
{active ? (
|
|
||||||
<button className="btn btn-info submiBtn" type="submit">
|
|
||||||
{props.IsEdit ? "update folder" : "create folder"}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button className="btn btn-info submiBtn " type="submit" disabled>
|
|
||||||
submitting...
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</Form>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
formView = (
|
|
||||||
<div style={{ height: "300px" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginLeft: "45%",
|
|
||||||
marginTop: "150px",
|
|
||||||
fontSize: "45px",
|
|
||||||
color: "#3dd3e0"
|
|
||||||
}}
|
|
||||||
className="loader-37"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-md-12">
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-body no-padding height-9">
|
|
||||||
{help ? (
|
|
||||||
<div className="dropdown" style={{ marginTop: "-30px" }}>
|
|
||||||
<i
|
|
||||||
className="far fa-question-circle dropdown-toggle hovereffect"
|
|
||||||
aria-hidden="true"
|
|
||||||
id="dropdownMenuButton"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded="false"
|
|
||||||
style={{
|
|
||||||
fontSize: "18px",
|
|
||||||
color: "purple",
|
|
||||||
cursor: "pointer !important",
|
|
||||||
position: "relative",
|
|
||||||
top: "40px",
|
|
||||||
left: "98%"
|
|
||||||
}}
|
|
||||||
></i>
|
|
||||||
<div
|
|
||||||
className="dropdown-menu"
|
|
||||||
aria-labelledby="dropdownMenuButton"
|
|
||||||
style={{
|
|
||||||
marginleft: "-121px",
|
|
||||||
margintop: "-14px",
|
|
||||||
position: "absolute",
|
|
||||||
padding: "10px",
|
|
||||||
width: "300px",
|
|
||||||
top: "102px!important"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{parse(`
|
|
||||||
${help}
|
|
||||||
`)}
|
|
||||||
<br />
|
|
||||||
{link ? (
|
|
||||||
<a
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
window.location.href = link;
|
|
||||||
}}
|
|
||||||
target="_blank"
|
|
||||||
className="btn btn-xs btn-primary"
|
|
||||||
>
|
|
||||||
Read more..
|
|
||||||
</a>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<div style={{ fontSize: "13px" }}>{formView}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="snackbar" style={{ backgroundColor: toastColor }}>
|
|
||||||
{toastDescription}
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TreeFormComponent;
|
|
||||||
@@ -1,895 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import LabelField from "./fields/LabelField";
|
|
||||||
import Parse from "parse";
|
|
||||||
import axios from "axios";
|
|
||||||
import "../styles/spinner.css";
|
|
||||||
import TreeFormComponent from "./TreeFormComponent";
|
|
||||||
import TreeEditForm from "./TreeEditForm";
|
|
||||||
import "../styles/modal.css";
|
|
||||||
import Modal from "react-modal";
|
|
||||||
|
|
||||||
const TreeWidget = (props) => {
|
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [isAddField, setIsAddField] = useState(false);
|
|
||||||
const [folderList, setFolderList] = useState([]);
|
|
||||||
const [tabList, setTabList] = useState([]);
|
|
||||||
const [appId, setAppId] = useState(undefined);
|
|
||||||
const [selectedFolder, setSelectedFolder] = useState(undefined);
|
|
||||||
const [loader, setLoader] = useState(false);
|
|
||||||
const [className, setClassName] = useState("");
|
|
||||||
const [schemaState, setSchemaState] = useState({});
|
|
||||||
const [TabURL, setTabURL] = useState("");
|
|
||||||
const [editable, setEditable] = useState(false);
|
|
||||||
const [editId, setEditId] = useState("");
|
|
||||||
const [defaultState, setDefaultState] = useState(false);
|
|
||||||
const [isShowModal, setIsShowModal] = useState(false);
|
|
||||||
const selectFolderHandle = async () => {
|
|
||||||
setIsShowModal(true);
|
|
||||||
setIsAddField(false);
|
|
||||||
setDefaultState(false);
|
|
||||||
setFolderList([]);
|
|
||||||
setLoader(true);
|
|
||||||
|
|
||||||
if (tabList.length > 0) {
|
|
||||||
let len = tabList.length - 1;
|
|
||||||
selectedItemList(tabList[len]);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
var test;
|
|
||||||
if (props.schema.parent) {
|
|
||||||
try {
|
|
||||||
if (props.parent[props.schema.parent]) {
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
let res;
|
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
res = data[0];
|
|
||||||
} else {
|
|
||||||
res = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = res.toJSON();
|
|
||||||
}
|
|
||||||
if (res) {
|
|
||||||
let json = res;
|
|
||||||
setAppId(json.AppId);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
let reg = /(\#.*?\#)/gi;
|
|
||||||
let str = props.schema.data.Query;
|
|
||||||
if (str.includes("#")) {
|
|
||||||
test = str.replace(reg, props.parent[props.schema.parent]);
|
|
||||||
} else {
|
|
||||||
test = str;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (props.child[props.schema.parent]) {
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
let res;
|
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
res = data[0];
|
|
||||||
} else {
|
|
||||||
res = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = res.toJSON();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
let json = res;
|
|
||||||
setAppId(json.AppId);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
let reg = /(\#.*?\#)/gi;
|
|
||||||
let str = props.schema.data.Query;
|
|
||||||
if (str.includes("#")) {
|
|
||||||
test = str.replace(reg, props.child[props.schema.parent]);
|
|
||||||
} else {
|
|
||||||
test = str;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert(`Please select ${props.schema.parent}`);
|
|
||||||
setLoader(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("error ", error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
// eslint-disable-next-line
|
|
||||||
let reg = /(\#.*?\#)/gi;
|
|
||||||
let str = props.schema.data.Query;
|
|
||||||
let res;
|
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
res = data[0];
|
|
||||||
} else {
|
|
||||||
// emp = Parse.Object.extend(localStorage.getItem("extended_class"));
|
|
||||||
// q = new Parse.Query(emp);
|
|
||||||
// q.equalTo("UserId", currentUser);
|
|
||||||
// res = await q.first();
|
|
||||||
// if (res) res = res.toJSON();
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
res = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = res.toJSON();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
let json = res;
|
|
||||||
setAppId(json.AppId);
|
|
||||||
}
|
|
||||||
if (str.includes("#")) {
|
|
||||||
if (res) {
|
|
||||||
let json = res.toJSON();
|
|
||||||
let output = str.match(reg);
|
|
||||||
if (output.length === 1) {
|
|
||||||
output = output.join();
|
|
||||||
output = output.substring(1, output.length - 1);
|
|
||||||
output = output.split(".");
|
|
||||||
if (output.length === 1) {
|
|
||||||
let out = output[0];
|
|
||||||
if (json[out]) {
|
|
||||||
if (typeof json[out] === "object") {
|
|
||||||
test = str.replace(reg, JSON.stringify(json[out]));
|
|
||||||
} else {
|
|
||||||
test = str.replace(reg, json[out]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
test = str.replace(reg, currentUser.id);
|
|
||||||
}
|
|
||||||
} else if (output.length === 2) {
|
|
||||||
let out1 = json[output[0]][output[1]];
|
|
||||||
if (out1) {
|
|
||||||
test = str.replace(reg, out1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
test = str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?${test}`;
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
await axios
|
|
||||||
.get(url, { headers: headers })
|
|
||||||
.then((res) => {
|
|
||||||
if (res) {
|
|
||||||
setFolderList(res.data.results);
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
setLoader(false);
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedItemList = async (folder) => {
|
|
||||||
setLoader(true);
|
|
||||||
setFolderList([]);
|
|
||||||
try {
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?where={"${props.schema.data.ParentFolderField}":{"__type":"Pointer","className":"${props.schema.data.ClassName}","objectId":"${folder.objectId}"}}`;
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
await axios.get(url, { headers: headers }).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
setFolderList(result.data.results);
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTabListItem = async (e, i) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setEditable(false);
|
|
||||||
setLoader(true);
|
|
||||||
setFolderList([]);
|
|
||||||
let list = tabList.filter((itm, j) => {
|
|
||||||
if (j <= i) {
|
|
||||||
return itm;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setTabList(list);
|
|
||||||
setIsAddField(false);
|
|
||||||
try {
|
|
||||||
let _len = list.length - 1;
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?where={"${props.schema.data.ParentFolderField}":{"__type":"Pointer","className":"${props.schema.data.ClassName}","objectId":"${list[_len].objectId}"}}`;
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
await axios.get(url, { headers: headers }).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
setFolderList(result.data.results);
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
setLoader(false);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteFolder = async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (folderList.length > 0) {
|
|
||||||
alert(
|
|
||||||
"Folder should not delete. To delete first delete sub items in it."
|
|
||||||
);
|
|
||||||
} else if (window.confirm(`Are you sure you want to delete this record`)) {
|
|
||||||
try {
|
|
||||||
setLoader(true);
|
|
||||||
let len = tabList.length - 1;
|
|
||||||
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
var deleted = Parse.Object.extend(props.schema.data.ClassName);
|
|
||||||
var query = new Parse.Query(deleted);
|
|
||||||
await query.get(tabList[len].objectId).then(
|
|
||||||
(del) => {
|
|
||||||
del.destroy().then(
|
|
||||||
(y) => {
|
|
||||||
if (y) {
|
|
||||||
setLoader(false);
|
|
||||||
let list = tabList.filter((itm, j) => {
|
|
||||||
if (j !== len) return itm;
|
|
||||||
});
|
|
||||||
setTabList(list);
|
|
||||||
if (list.length > 0) {
|
|
||||||
let len = list.length - 1;
|
|
||||||
selectedItemList(list[len]);
|
|
||||||
} else {
|
|
||||||
selectFolderHandle();
|
|
||||||
}
|
|
||||||
alert("Folder deleted successfully.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
alert(error.message);
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
console.log("error ", error);
|
|
||||||
// The object was not retrieved successfully.
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
setLoader(false);
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmitResult = async (e) => {
|
|
||||||
setIsShowModal(false);
|
|
||||||
e.preventDefault();
|
|
||||||
//console.log("tabList ", tabList);
|
|
||||||
if (tabList.length > 0) {
|
|
||||||
try {
|
|
||||||
let len = tabList.length - 1;
|
|
||||||
setSelectedFolder({
|
|
||||||
Topic: tabList[len][`${props.schema.data.FolderNameField}`],
|
|
||||||
description: tabList[len][`${props.schema.data.FolderDescription}`]
|
|
||||||
});
|
|
||||||
props.onChange(tabList[len]["objectId"]);
|
|
||||||
let url = "Folders";
|
|
||||||
tabList.forEach((t) => {
|
|
||||||
url = url + " / " + t[`${props.schema.data.FolderNameField}`];
|
|
||||||
});
|
|
||||||
setTabURL(url);
|
|
||||||
setIsAddField(false);
|
|
||||||
if (!props.formData) {
|
|
||||||
setTabList([]);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setIsAddField(false);
|
|
||||||
alert(error.message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsAddField(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const editFolderDisplay = async (formData) => {
|
|
||||||
try {
|
|
||||||
let objectId = formData.objectId;
|
|
||||||
let className = formData.className;
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const fldr = Parse.Object.extend(className);
|
|
||||||
let query = new Parse.Query(fldr);
|
|
||||||
query.equalTo("objectId", objectId);
|
|
||||||
const result = await query.first();
|
|
||||||
let resultJson = result.toJSON();
|
|
||||||
let CustomTabList = [];
|
|
||||||
if (resultJson) {
|
|
||||||
CustomTabList.push(resultJson);
|
|
||||||
if (resultJson[`${props.schema.data.ParentFolderField}`]) {
|
|
||||||
let tabsRes = resultJson[`${props.schema.data.ParentFolderField}`];
|
|
||||||
let looping = false;
|
|
||||||
do {
|
|
||||||
let fldttr = Parse.Object.extend(tabsRes.className);
|
|
||||||
let query2 = new Parse.Query(fldttr);
|
|
||||||
query2.equalTo("objectId", tabsRes.objectId);
|
|
||||||
let custome_res = await query2.first();
|
|
||||||
if (custome_res) {
|
|
||||||
let tabsData = custome_res.toJSON();
|
|
||||||
CustomTabList.push(tabsData);
|
|
||||||
if (tabsData[`${props.schema.data.ParentFolderField}`]) {
|
|
||||||
tabsRes = tabsData[`${props.schema.data.ParentFolderField}`];
|
|
||||||
looping = true;
|
|
||||||
} else {
|
|
||||||
looping = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (looping);
|
|
||||||
}
|
|
||||||
let url = "Folders";
|
|
||||||
CustomTabList.length > 0 &&
|
|
||||||
CustomTabList.reverse().forEach(
|
|
||||||
(t) => (url = url + " / " + t[props.schema.data.FolderNameField])
|
|
||||||
);
|
|
||||||
setTabURL(url);
|
|
||||||
setSelectedFolder({
|
|
||||||
Topic: resultJson[`${props.schema.data.FolderNameField}`],
|
|
||||||
description: resultJson[`${props.schema.data.FolderDescription}`]
|
|
||||||
});
|
|
||||||
setTabList(CustomTabList);
|
|
||||||
props.onChange(resultJson.objectId);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async ({ formData }) => {
|
|
||||||
setLoader(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
let RowData = formData;
|
|
||||||
let _scanData = schemaState;
|
|
||||||
Object.keys(_scanData).forEach(function (key) {
|
|
||||||
let _dd = _scanData[key];
|
|
||||||
Object.keys(_dd).forEach(function (k) {
|
|
||||||
if (_dd[k].component === "AutoSuggest" && _dd[k].isPointer) {
|
|
||||||
let pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].class,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
RowData[k] = pointer;
|
|
||||||
}
|
|
||||||
if (_dd[k].format === "date") {
|
|
||||||
let newdate = new Date(RowData[k]);
|
|
||||||
RowData[k] = newdate;
|
|
||||||
}
|
|
||||||
if (_dd[k].component === "DateTime") {
|
|
||||||
let newDate11;
|
|
||||||
if (!RowData[k]) {
|
|
||||||
newDate11 = new Date();
|
|
||||||
} else {
|
|
||||||
newDate11 = new Date(RowData[k]);
|
|
||||||
}
|
|
||||||
RowData[k] = newDate11;
|
|
||||||
}
|
|
||||||
if (_dd[k].component === "CurrencyInput") {
|
|
||||||
if (_dd[k].currencyColumn) {
|
|
||||||
RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].data !== undefined) {
|
|
||||||
if (_dd[k].data.isPointer) {
|
|
||||||
let pointer = {};
|
|
||||||
if (RowData[k] && RowData[k] !== "Select") {
|
|
||||||
if (_dd[k].data.class) {
|
|
||||||
if (RowData[k]) {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].data.class,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pointer = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: localStorage.getItem("extended_class"),
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RowData[k] = pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].data.FolderTypeValue) {
|
|
||||||
let obj = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _dd[k].data.ClassName,
|
|
||||||
objectId: RowData[k]
|
|
||||||
};
|
|
||||||
RowData[k] = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_dd[k].type === "string") {
|
|
||||||
let d = RowData[k];
|
|
||||||
if (typeof d === "string") {
|
|
||||||
RowData[k] = d.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
|
|
||||||
var forms = Parse.Object.extend(className);
|
|
||||||
var folder = new forms();
|
|
||||||
folder.set(
|
|
||||||
props.schema.data.FolderNameField,
|
|
||||||
formData[props.schema.data.FolderNameField]
|
|
||||||
);
|
|
||||||
if (props.schema.data.FolderDescription) {
|
|
||||||
folder.set(
|
|
||||||
props.schema.data.FolderDescription,
|
|
||||||
formData[props.schema.data.FolderDescription]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
folder.set("AppId", appId);
|
|
||||||
folder.set(
|
|
||||||
props.schema.data.FolderTypeField,
|
|
||||||
props.schema.data.FolderTypeValue
|
|
||||||
);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
folder.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
|
||||||
if (tabList.length > 0) {
|
|
||||||
let len = tabList.length - 1;
|
|
||||||
folder.set(props.schema.data.ParentFolderField, {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: props.schema.data.ClassName,
|
|
||||||
objectId: tabList[len]["objectId"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
folder.save(RowData).then(
|
|
||||||
(result) => {
|
|
||||||
RowData = {};
|
|
||||||
if (result) {
|
|
||||||
setIsAddField(false);
|
|
||||||
setLoader(false);
|
|
||||||
if (tabList.length > 0) {
|
|
||||||
let len = tabList.length - 1;
|
|
||||||
selectedItemList(tabList[len]);
|
|
||||||
} else {
|
|
||||||
selectFolderHandle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
console.log("error ", error);
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
setLoader(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.formData) {
|
|
||||||
editFolderDisplay(props.formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [props.formData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (defaultState) {
|
|
||||||
selectFolderHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [defaultState]);
|
|
||||||
const customStyles = {
|
|
||||||
content: {
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
right: "auto",
|
|
||||||
bottom: "auto",
|
|
||||||
marginRight: "-50%",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
backgroundColor: "white",
|
|
||||||
padding: 0
|
|
||||||
},
|
|
||||||
overlay: {
|
|
||||||
width: "100%",
|
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
||||||
zIndex: 50
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<LabelField
|
|
||||||
Title={props.schema.title}
|
|
||||||
Name={props.name}
|
|
||||||
Required={props.required}
|
|
||||||
HelpBody={props.schema.helpbody}
|
|
||||||
HelpLink={props.schema.helplink}
|
|
||||||
/>
|
|
||||||
<br />
|
|
||||||
<div className="block max-w-sm bg-white border border-gray-200 shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
color: "black",
|
|
||||||
fontWeight: "bold",
|
|
||||||
fontSize: "13px",
|
|
||||||
padding: "2%",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ width: "20%" }}>
|
|
||||||
<div
|
|
||||||
className="pull-left"
|
|
||||||
title="Select Folder"
|
|
||||||
style={{
|
|
||||||
color: "#33bbff",
|
|
||||||
margin: "auto",
|
|
||||||
padding: "10px 10px",
|
|
||||||
textAlign: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="far fa-folder-open"
|
|
||||||
style={{ fontSize: "40px" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style={{ margin: "0px 10px 0 20px", width: "80%" }}>
|
|
||||||
<div>
|
|
||||||
{selectedFolder && selectedFolder.Topic
|
|
||||||
? selectedFolder.Topic
|
|
||||||
: "Root"}
|
|
||||||
<i
|
|
||||||
className="fa fa-pencil"
|
|
||||||
title="Select Folder"
|
|
||||||
style={{ fontSize: 17, cursor: "pointer", marginLeft: 12 }}
|
|
||||||
onClick={selectFolderHandle}
|
|
||||||
></i>
|
|
||||||
{selectedFolder && (
|
|
||||||
<a
|
|
||||||
className="pull-right"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedFolder(undefined);
|
|
||||||
setTabURL(undefined);
|
|
||||||
props.onChange(undefined);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-times-circle-o"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ fontSize: 17 }}
|
|
||||||
></i>
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{TabURL && (
|
|
||||||
<div
|
|
||||||
style={{ fontSize: "10px", color: "gray", fontWeight: "bold" }}
|
|
||||||
>
|
|
||||||
({TabURL})
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* save document in folder and add new folder modal */}
|
|
||||||
<Modal
|
|
||||||
isOpen={isShowModal}
|
|
||||||
onRequestClose={() => setIsShowModal(false)}
|
|
||||||
shouldCloseOnOverlayClick={false}
|
|
||||||
contentLabel="Modal"
|
|
||||||
style={customStyles}
|
|
||||||
>
|
|
||||||
<div className="w-full min-w-[300px] md:min-w-[500px]">
|
|
||||||
{/* header */}
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
backgroundColor: "rgba(203, 200, 200, 0.09)"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ padding: "10px" }}>
|
|
||||||
<h4 className=" text-black">Select Folder</h4>
|
|
||||||
</div>
|
|
||||||
<div style={{ padding: "10px" }}>
|
|
||||||
<button
|
|
||||||
className="btn btn-sm pull-right"
|
|
||||||
data-dismiss="modal"
|
|
||||||
title="Select Folder"
|
|
||||||
style={{
|
|
||||||
width: "auto",
|
|
||||||
backgroundColor: "white",
|
|
||||||
border: "1px solid gray",
|
|
||||||
boxshadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px"
|
|
||||||
}}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setIsAddField(false);
|
|
||||||
setFolderList([]);
|
|
||||||
setEditable(false);
|
|
||||||
if (!props.formData) {
|
|
||||||
setTabList([]);
|
|
||||||
}
|
|
||||||
setIsShowModal(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
{/* body */}
|
|
||||||
<div className="p-3 space-y-6">
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
color: "#ac4848",
|
|
||||||
cursor: "pointer",
|
|
||||||
fontSize: "14px",
|
|
||||||
fontWeight: "500"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
setTabList([]);
|
|
||||||
setIsAddField(false);
|
|
||||||
setDefaultState(true);
|
|
||||||
setEditable(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Folders
|
|
||||||
</a>
|
|
||||||
{" / "}
|
|
||||||
|
|
||||||
{tabList &&
|
|
||||||
tabList.map((tab, i) => (
|
|
||||||
<React.Fragment key={`${tab.objectId}-${i}`}>
|
|
||||||
<a
|
|
||||||
title={tab[`${props.schema.data.FolderNameField}`]}
|
|
||||||
onClick={(e) => removeTabListItem(e, i)}
|
|
||||||
>
|
|
||||||
{tab[`${props.schema.data.FolderNameField}`]}
|
|
||||||
</a>
|
|
||||||
{" / "}
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
<hr />
|
|
||||||
</div>
|
|
||||||
{/* {editable && (
|
|
||||||
<TreeEditForm
|
|
||||||
FormId={props.schema.data.FormId}
|
|
||||||
objectId={editId}
|
|
||||||
HideView={(cl) => {
|
|
||||||
setEditable(cl);
|
|
||||||
selectFolderHandle();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)} */}
|
|
||||||
{isAddField && !loader && !editable && (
|
|
||||||
<TreeFormComponent
|
|
||||||
Id={props.schema.data.FormId}
|
|
||||||
handleSubmit={handleSubmit}
|
|
||||||
ParentField={props.schema.parent && props.schema.parent}
|
|
||||||
ParentValue={props.schema.parent && props.parent}
|
|
||||||
ChildField={props.child && props.child}
|
|
||||||
ClassName={(cls) => setClassName(cls)}
|
|
||||||
SchemaState={(cls) => setSchemaState(cls)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{loader && (
|
|
||||||
<div
|
|
||||||
className="loader-01"
|
|
||||||
style={{
|
|
||||||
marginTop: "50px",
|
|
||||||
marginLeft: "50%",
|
|
||||||
color: "rgb(0,28,28)",
|
|
||||||
fontSize: "35px"
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!isAddField && !editable && (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
maxHeight: "280px",
|
|
||||||
overflowY: "auto",
|
|
||||||
marginTop: "5px"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ul>
|
|
||||||
{folderList &&
|
|
||||||
folderList.map(
|
|
||||||
(fldr) =>
|
|
||||||
fldr[props.schema.data.FolderTypeField] ===
|
|
||||||
props.schema.data.FolderTypeValue && (
|
|
||||||
<li
|
|
||||||
key={`${fldr.objectId}`}
|
|
||||||
style={{
|
|
||||||
listStyle: "none",
|
|
||||||
padding: "10px 20px",
|
|
||||||
textTransform: "capitalize",
|
|
||||||
fontWeight: 300,
|
|
||||||
border: "1px solid gray",
|
|
||||||
borderRadius: "1px",
|
|
||||||
marginTop: "8px",
|
|
||||||
transition: "all 0.75s ease",
|
|
||||||
WebkitTransition: "all 0.5s ease",
|
|
||||||
MozTransition: "all 0.5s ease",
|
|
||||||
MsTransition: "all 0.5s ease",
|
|
||||||
OTransition: "all 0.5 ease",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className={"fa fa-folder"}
|
|
||||||
style={{
|
|
||||||
fontSize: "1.4rem",
|
|
||||||
color: "skyblue"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
<a
|
|
||||||
style={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
fontSize: "12px",
|
|
||||||
marginLeft: "4px",
|
|
||||||
cursor: "pointer"
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setTabList((tabs) => tabs.concat(fldr));
|
|
||||||
selectedItemList(fldr);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{fldr[`${props.schema.data.FolderNameField}`]}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* {fldr[props.schema.data.FolderTypeField] ===
|
|
||||||
props.schema.data.FolderTypeValue && (
|
|
||||||
<a
|
|
||||||
className="float-right"
|
|
||||||
onClick={() => {
|
|
||||||
setEditable(true);
|
|
||||||
setEditId(fldr.objectId);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className={"fa fa-pencil"}
|
|
||||||
title={"Edit Folder"}
|
|
||||||
style={{
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
color: "purple",
|
|
||||||
cursor: "pointer"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</a>
|
|
||||||
)} */}
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* footer */}
|
|
||||||
|
|
||||||
<div className="flex items-center p-3 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600 justify-between">
|
|
||||||
<button
|
|
||||||
className="btn btn-sm float-left createFolder"
|
|
||||||
title="Create New Folder"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setIsAddField(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
<i
|
|
||||||
className="fa fa-plus"
|
|
||||||
style={{ fontSize: "1.5rem" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
{!isAddField && !editable && (
|
|
||||||
<div className="flex">
|
|
||||||
{tabList.length > 0 && (
|
|
||||||
<button
|
|
||||||
className="btn btn-sm float-right deleteFolder"
|
|
||||||
title="Delete Folder"
|
|
||||||
onClick={onDeleteFolder}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
<i
|
|
||||||
className="fa fa-trash"
|
|
||||||
style={{ fontSize: "1rem" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<button
|
|
||||||
className="btn btn-sm float-right saveFolder"
|
|
||||||
title="Save Here"
|
|
||||||
onClick={onSubmitResult}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
{/* <i
|
|
||||||
className="fa fa-floppy-o"
|
|
||||||
style={{ fontSize: "2rem" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i> */}
|
|
||||||
<i
|
|
||||||
className="fas fa-save"
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ fontSize: "20px" }}
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
|
||||||
return {
|
|
||||||
parent: state.Level1_Dropdown,
|
|
||||||
child: state.Level2_Dropdown
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(TreeWidget);
|
|
||||||
@@ -24,9 +24,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 +79,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 +218,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")) {
|
||||||
|
|||||||
@@ -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,8 +1,5 @@
|
|||||||
import React, { Suspense, lazy } from "react";
|
import React, { Suspense, lazy } from "react";
|
||||||
import ErrorBoundary from "../ErrorBoundary";
|
|
||||||
|
|
||||||
const DashboardCard = lazy(() => import("./DashboardCard"));
|
const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||||
|
|
||||||
const DashboardReport = lazy(() => import("./DashboardReport"));
|
const DashboardReport = lazy(() => import("./DashboardReport"));
|
||||||
|
|
||||||
const GetDashboard = (props) => {
|
const GetDashboard = (props) => {
|
||||||
@@ -15,7 +12,21 @@ const GetDashboard = (props) => {
|
|||||||
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}
|
||||||
@@ -76,25 +87,23 @@ const GetDashboard = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<div>
|
||||||
<div>
|
{props.dashboard.map((val, key) => (
|
||||||
{props.dashboard.map((val, key) => (
|
<div key={"a" + key} className="row">
|
||||||
<div key={"a" + key} className="row">
|
{val.columns.map((col, i) =>
|
||||||
{val.columns.map((col, i) =>
|
col.widget.data && col.widget.data.tourSection ? (
|
||||||
col.widget.data && col.widget.data.tourSection ? (
|
<div key={i} className={props.classnameArray[key][i]}>
|
||||||
<div key={i} className={props.classnameArray[key][i]}>
|
{renderSwitchWithTour(col)}
|
||||||
{renderSwitchWithTour(col)}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<div key={i} className={props.classnameArray[key][i]}>
|
||||||
<div key={i} className={props.classnameArray[key][i]}>
|
{renderSwitch(col)}
|
||||||
{renderSwitch(col)}
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,308 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { SaveFileSize } from "../../constant/saveFileSize";
|
|
||||||
import Parse from "parse";
|
|
||||||
import sanitizeFileName from "../../primitives/sanitizeFileName";
|
|
||||||
import DropboxChooser from "./DropboxChoose";
|
|
||||||
const FileUpload = (props) => {
|
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [_fileupload, setFileUpload] = useState("");
|
|
||||||
const [fileload, setfileload] = useState(false);
|
|
||||||
const [Message] = useState(false);
|
|
||||||
const [percentage, setpercentage] = useState(0);
|
|
||||||
|
|
||||||
const REQUIRED_FIELD_SYMBOL = "*";
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!props.formData) {
|
|
||||||
setFileUpload([]);
|
|
||||||
props.onChange(undefined);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [props.formData]);
|
|
||||||
const onChange = (e) => {
|
|
||||||
try {
|
|
||||||
let files = e.target.files;
|
|
||||||
if (typeof files[0] !== "undefined") {
|
|
||||||
if (props.schema.filetypes && props.schema.filetypes.length > 0) {
|
|
||||||
var fileName = files[0].name;
|
|
||||||
var fileNameExt = fileName
|
|
||||||
.substr(fileName.lastIndexOf(".") + 1)
|
|
||||||
.toLowerCase();
|
|
||||||
let Extensions = props.schema.filetypes.map((x) => x.toLowerCase());
|
|
||||||
let arr = Extensions.filter((x) => x === fileNameExt);
|
|
||||||
if (arr.length > 0) {
|
|
||||||
console.log("multiple type");
|
|
||||||
} else {
|
|
||||||
alert(
|
|
||||||
"Only these file types are accepted : " + Extensions.join(", ")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (props.schema.maxfilesizeKB && props.schema.maxfilesizeKB !== "") {
|
|
||||||
// console.log(Math.round(files[0].size / 1024));
|
|
||||||
if (
|
|
||||||
Math.round(Number(files[0].size) / 1024) >=
|
|
||||||
props.schema.maxfilesizeKB
|
|
||||||
) {
|
|
||||||
alert(
|
|
||||||
`The selected file size is too large. Please select a file less than ${Math.round(
|
|
||||||
props.schema.maxfilesizeKB / 1024
|
|
||||||
)} MB`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleFileUpload(files[0]);
|
|
||||||
} else {
|
|
||||||
alert("Please select file.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
alert(error.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFileUpload = async (file) => {
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
setfileload(true);
|
|
||||||
const size = file.size;
|
|
||||||
const fileName = file.name;
|
|
||||||
const name = sanitizeFileName(fileName);
|
|
||||||
const pdfFile = file;
|
|
||||||
const parseFile = new Parse.File(name, pdfFile);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await parseFile.save({
|
|
||||||
progress: (progressValue, loaded, total, { type }) => {
|
|
||||||
if (type === "upload" && progressValue !== null) {
|
|
||||||
const percentCompleted = Math.round((loaded * 100) / total);
|
|
||||||
// console.log("percentCompleted ", percentCompleted);
|
|
||||||
setpercentage(percentCompleted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setFileUpload(response.url());
|
|
||||||
props.onChange(response.url());
|
|
||||||
setfileload(false);
|
|
||||||
// The response object will contain information about the uploaded file
|
|
||||||
// console.log("File uploaded:", response);
|
|
||||||
|
|
||||||
// You can access the URL of the uploaded file using response.url()
|
|
||||||
// console.log("File URL:", response.url());
|
|
||||||
if (response.url()) {
|
|
||||||
SaveFileSize(size, response.url());
|
|
||||||
return response.url();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setfileload(false);
|
|
||||||
setpercentage(0);
|
|
||||||
console.error("Error uploading file:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const dropboxSuccess = async (files) => {
|
|
||||||
// console.log("file ", files);
|
|
||||||
setfileload(true);
|
|
||||||
const file = files[0];
|
|
||||||
const url = file.link;
|
|
||||||
const size = file.bytes;
|
|
||||||
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
|
||||||
|
|
||||||
if (mb > 10) {
|
|
||||||
setTimeout(() => {
|
|
||||||
alert(
|
|
||||||
`The selected file size is too large. Please select a file less than 10 MB`
|
|
||||||
);
|
|
||||||
}, 500);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
const name = sanitizeFileName(file.name);
|
|
||||||
|
|
||||||
const parseFile = new Parse.File(name, { uri: url });
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await parseFile.save({
|
|
||||||
progress: (progressValue, loaded, total, { type }) => {
|
|
||||||
if (type === "upload" && progressValue !== null) {
|
|
||||||
const percentCompleted = Math.round((loaded * 100) / total);
|
|
||||||
// console.log("percentCompleted ", percentCompleted);
|
|
||||||
setpercentage(percentCompleted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// console.log("response.url() ", response.url());
|
|
||||||
setFileUpload(response.url());
|
|
||||||
props.onChange(response.url());
|
|
||||||
setfileload(false);
|
|
||||||
|
|
||||||
if (response.url()) {
|
|
||||||
SaveFileSize(size, response.url());
|
|
||||||
return response.url();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setfileload(false);
|
|
||||||
setpercentage(0);
|
|
||||||
console.error("Error uploading file:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const dropboxCancel = async () => {
|
|
||||||
console.log("cancel clicked ");
|
|
||||||
};
|
|
||||||
let fileView =
|
|
||||||
props.formData &&
|
|
||||||
props.schema.uploadtype === "s3viajw" ? null : props.formData &&
|
|
||||||
props.formData ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<a
|
|
||||||
href={props.formData}
|
|
||||||
title={props.formData}
|
|
||||||
style={{ paddingBottom: "10px", color: "blue" }}
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</a>
|
|
||||||
</React.Fragment>
|
|
||||||
) : fileload === false ? null : (
|
|
||||||
<React.Fragment>
|
|
||||||
<a
|
|
||||||
href={_fileupload}
|
|
||||||
title={_fileupload}
|
|
||||||
style={{ paddingBottom: "10px" }}
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div style={{ display: "inline-block" }}>
|
|
||||||
<label htmlFor={props.name}>
|
|
||||||
{props.schema.title}
|
|
||||||
{props.required && (
|
|
||||||
<span className="required">{REQUIRED_FIELD_SYMBOL}</span>
|
|
||||||
)}
|
|
||||||
{fileload ? (
|
|
||||||
<div className="flex items-center gap-x-2">
|
|
||||||
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
|
|
||||||
<div
|
|
||||||
className="h-2 rounded-full bg-blue-500"
|
|
||||||
style={{ width: `${percentage}%` }}
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
<span className="text-black text-sm">{percentage}%</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
Message && (
|
|
||||||
<span style={{ fontSize: "9px", marginLeft: "4px" }}>
|
|
||||||
Processing will take 5-10 mins....
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
{props.schema.helpbody ? (
|
|
||||||
<div className="dropdown pull-right">
|
|
||||||
<i
|
|
||||||
className="far fa-question-circle dropdown-toggle hovereffect"
|
|
||||||
aria-hidden="true"
|
|
||||||
id="dropdownMenuButton"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded="false"
|
|
||||||
style={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: "purple",
|
|
||||||
cursor: "pointer !important",
|
|
||||||
position: "relative",
|
|
||||||
bottom: "0px",
|
|
||||||
left: "0px",
|
|
||||||
paddingBottom: "4px",
|
|
||||||
paddingLeft: "4px"
|
|
||||||
}}
|
|
||||||
></i>
|
|
||||||
<div
|
|
||||||
className="dropdown-menu"
|
|
||||||
aria-labelledby="dropdownMenuButton"
|
|
||||||
style={{
|
|
||||||
marginleft: "-121px",
|
|
||||||
margintop: "-14px",
|
|
||||||
position: "absolute",
|
|
||||||
padding: "10px",
|
|
||||||
top: "102px!important"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<br />
|
|
||||||
{props.schema.helplink ? (
|
|
||||||
<a
|
|
||||||
href={props.schema.helplink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="btn btn-xs btn-primary"
|
|
||||||
>
|
|
||||||
Read more..
|
|
||||||
</a>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<span style={{ marginLeft: "10px" }}>{fileView}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<>
|
|
||||||
{props.formData ? (
|
|
||||||
<div className="flex gap-2 justify-center items-center">
|
|
||||||
<div className="flex justify-between items-center px-2 py-[3px] w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
|
||||||
<div className="break-all">
|
|
||||||
file selected : {props.formData.split("/")[3]}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
console.log("clicked");
|
|
||||||
setFileUpload([]);
|
|
||||||
props.onChange(undefined);
|
|
||||||
}}
|
|
||||||
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
|
||||||
>
|
|
||||||
<i className="fa-solid fa-xmark"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<DropboxChooser
|
|
||||||
onSuccess={dropboxSuccess}
|
|
||||||
onCancel={dropboxCancel}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex gap-2 justify-center items-center">
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
id="hashfile"
|
|
||||||
style={{
|
|
||||||
border: "1px solid #ccc",
|
|
||||||
color: "gray",
|
|
||||||
backgroundColor: "white",
|
|
||||||
padding: "5px 10px",
|
|
||||||
borderRadius: "4px",
|
|
||||||
fontSize: "13px",
|
|
||||||
width: "100%",
|
|
||||||
fontWeight: "bold"
|
|
||||||
}}
|
|
||||||
accept="application/pdf,application/vnd.ms-excel"
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<DropboxChooser
|
|
||||||
onSuccess={dropboxSuccess}
|
|
||||||
onCancel={dropboxCancel}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FileUpload;
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
import React, { Component } from "react";
|
|
||||||
import Parse from "parse";
|
|
||||||
// import axios from "axios";
|
|
||||||
|
|
||||||
export class HiddenField extends Component {
|
|
||||||
state = {
|
|
||||||
baseUrl: localStorage.getItem("baseUrl"),
|
|
||||||
parseAppId: localStorage.getItem("parseAppId"),
|
|
||||||
_fields: ""
|
|
||||||
};
|
|
||||||
loadData = async () => {
|
|
||||||
if (this.props.schema.default) {
|
|
||||||
this.setState({ _fields: this.props.schema.default });
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
Parse.serverURL = this.state.baseUrl;
|
|
||||||
Parse.initialize(this.state.parseAppId);
|
|
||||||
let currentUser = await Parse.User.current();
|
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
|
||||||
let _rdata = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
let custome_Filed = "";
|
|
||||||
let splitArray = this.props.schema.data.valueKey.split(".");
|
|
||||||
if (splitArray.length > 1) {
|
|
||||||
custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
|
||||||
} else {
|
|
||||||
let _Filed = _rdata[0][splitArray[0]];
|
|
||||||
if (typeof _Filed === "object") {
|
|
||||||
custome_Filed = {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: _Filed["className"],
|
|
||||||
objectId: _Filed["objectId"]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
custome_Filed = _rdata[0][splitArray[0]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setState({ _fields: custome_Filed });
|
|
||||||
} else {
|
|
||||||
if (currentUser) {
|
|
||||||
// let url = `${this.state.baseUrl}classes/${localStorage.getItem(
|
|
||||||
// "extended_class"
|
|
||||||
// )}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${
|
|
||||||
// currentUser.id
|
|
||||||
// }"}}&keys=${this.props.schema.data.valueKey}`;
|
|
||||||
// const headers = {
|
|
||||||
// "Content-Type": "application/json",
|
|
||||||
// "X-Parse-Application-Id": this.state.parseAppId
|
|
||||||
// };
|
|
||||||
// await axios.get(url, { headers: headers }).then((res) => {
|
|
||||||
// let custome_Filed = "";
|
|
||||||
// let _rdata = res.data.results;
|
|
||||||
// let splitArray = this.props.schema.data.valueKey.split(".");
|
|
||||||
// if (splitArray.length > 1) {
|
|
||||||
// custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
|
||||||
// } else {
|
|
||||||
// console.log(_rdata[0][splitArray[0]]);
|
|
||||||
// custome_Filed = _rdata[0][splitArray[0]];
|
|
||||||
// }
|
|
||||||
// this.setState({ _fields: custome_Filed });
|
|
||||||
// });
|
|
||||||
|
|
||||||
const res = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
let custome_Filed = "";
|
|
||||||
const result = res.toJSON();
|
|
||||||
let _rdata = [result];
|
|
||||||
let splitArray = this.props.schema.data.valueKey.split(".");
|
|
||||||
if (splitArray.length > 1) {
|
|
||||||
custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
|
||||||
} else {
|
|
||||||
console.log(_rdata[0][splitArray[0]]);
|
|
||||||
custome_Filed = _rdata[0][splitArray[0]];
|
|
||||||
}
|
|
||||||
this.setState({ _fields: custome_Filed });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("err", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
componentDidMount() {
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
value={this.state._fields}
|
|
||||||
onChange={this.props.onChange(this.state._fields)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HiddenField;
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import parse from "html-react-parser";
|
|
||||||
import PropTypes from "prop-types";
|
|
||||||
|
|
||||||
const LabelField = (props) => {
|
|
||||||
const { Title, Name, Required, HelpBody, HelpLink } = props;
|
|
||||||
const REQUIRED_FIELD_SYMBOL = "*";
|
|
||||||
return (
|
|
||||||
<div style={{ display: "inline-block" }}>
|
|
||||||
<label htmlFor={Name}>
|
|
||||||
{Title}
|
|
||||||
{Required && <span className="required">{REQUIRED_FIELD_SYMBOL}</span>}
|
|
||||||
{HelpBody ? (
|
|
||||||
<div className="dropdown pull-right">
|
|
||||||
<i
|
|
||||||
className="far fa-question-circle dropdown-toggle hovereffect pull-right"
|
|
||||||
aria-hidden="true"
|
|
||||||
id="dropdownMenuButton"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded="false"
|
|
||||||
style={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: "purple",
|
|
||||||
cursor: "pointer !important",
|
|
||||||
position: "relative",
|
|
||||||
bottom: "0px",
|
|
||||||
left: "0px",
|
|
||||||
paddingBottom: "4px",
|
|
||||||
paddingLeft: "4px"
|
|
||||||
}}
|
|
||||||
></i>
|
|
||||||
<div
|
|
||||||
className="dropdown-menu"
|
|
||||||
aria-labelledby="dropdownMenuButton"
|
|
||||||
style={{
|
|
||||||
marginleft: "-121px",
|
|
||||||
margintop: "-14px",
|
|
||||||
position: "absolute",
|
|
||||||
padding: "10px",
|
|
||||||
top: "102px!important"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{parse(`
|
|
||||||
${HelpBody}
|
|
||||||
`)}
|
|
||||||
<br />
|
|
||||||
{HelpLink ? (
|
|
||||||
<a
|
|
||||||
href={HelpLink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="btn btn-xs btn-primary"
|
|
||||||
>
|
|
||||||
Read more..
|
|
||||||
</a>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
LabelField.propTypes = {
|
|
||||||
Name: PropTypes.string.isRequired,
|
|
||||||
Title: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
export default LabelField;
|
|
||||||
@@ -1,482 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { onChangeLevel1Dropdown } from "../../redux/actions/index";
|
|
||||||
import axios from "axios";
|
|
||||||
import Parse from "parse";
|
|
||||||
import parse from "html-react-parser";
|
|
||||||
|
|
||||||
const Level1Dropdown = (props) => {
|
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [Level1_DD, setLevel1_DD] = useState([]);
|
|
||||||
const [toastColor] = useState("#d9534f");
|
|
||||||
const [toastDescription, setToastDescription] = useState("");
|
|
||||||
const [active, setActive] = useState(false);
|
|
||||||
|
|
||||||
const getParams = (offset) => {
|
|
||||||
const params = {
|
|
||||||
skip: offset
|
|
||||||
};
|
|
||||||
return params;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Level1DropdownData = async () => {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
props.formData &&
|
|
||||||
props.uiSchema["ui:disabled"] &&
|
|
||||||
props.formData !== "Select"
|
|
||||||
) {
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.class}/${props.formData}`;
|
|
||||||
if (typeof props.formData === "object") {
|
|
||||||
url = `${parseBaseUrl}classes/${props.schema.data.class}/${props.formData.objectId}`;
|
|
||||||
}
|
|
||||||
let headers1 = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
let data = [];
|
|
||||||
let response = [];
|
|
||||||
await axios.get(url, { headers: headers1 }).then((res) => {
|
|
||||||
if (res) {
|
|
||||||
data.push(res.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.length > 0) {
|
|
||||||
let temp = [];
|
|
||||||
data.forEach((x) => {
|
|
||||||
let opt = "";
|
|
||||||
if (Array.isArray(x[props.schema.data.valueKey])) {
|
|
||||||
x[props.schema.data.valueKey].forEach((tt) => {
|
|
||||||
if (typeof tt === "object") {
|
|
||||||
opt = {
|
|
||||||
objectId: tt[props.schema.data.displayKey],
|
|
||||||
option: tt[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: tt,
|
|
||||||
option: tt
|
|
||||||
};
|
|
||||||
}
|
|
||||||
temp.push(opt);
|
|
||||||
});
|
|
||||||
} else if (props.schema.data.isPointer) {
|
|
||||||
if (props.schema.data.valueKey.includes(".")) {
|
|
||||||
let newArr = props.schema.data.valueKey.split(".");
|
|
||||||
if (newArr.length === 2) {
|
|
||||||
opt = {
|
|
||||||
objectId: x[newArr[0]][newArr[1]],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[newArr[0]],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[props.schema.data.valueKey],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
temp.push(opt);
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[props.schema.data.valueKey],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
temp.push(opt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
response = temp;
|
|
||||||
setLevel1_DD(response);
|
|
||||||
setActive(false);
|
|
||||||
if (response.length === 1) {
|
|
||||||
props.onChangeLevel1Dropdown(response[0].objectId, props.name);
|
|
||||||
props.onChange(response[0].objectId);
|
|
||||||
} else if (response.length === 0) {
|
|
||||||
props.onChangeLevel1Dropdown("", props.name);
|
|
||||||
props.onChange("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let response = [];
|
|
||||||
setActive(true);
|
|
||||||
Parse.serverURL = parseBaseUrl;
|
|
||||||
Parse.initialize(parseAppId);
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
var reg = /(\#.*?\#)/gi;
|
|
||||||
let str = props.schema.data.query;
|
|
||||||
var test;
|
|
||||||
if (str.includes("#")) {
|
|
||||||
let res;
|
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
res = data[0];
|
|
||||||
} else {
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
res = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = res.toJSON();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
let json = res;
|
|
||||||
let output = str.match(reg);
|
|
||||||
if (output.length === 1) {
|
|
||||||
output = output.join();
|
|
||||||
output = output.substring(1, output.length - 1);
|
|
||||||
output = output.split(".");
|
|
||||||
if (output.length === 1) {
|
|
||||||
let out = output[0];
|
|
||||||
if (json[out]) {
|
|
||||||
if (typeof json[out] === "object") {
|
|
||||||
test = str.replace(reg, JSON.stringify(json[out]));
|
|
||||||
} else {
|
|
||||||
test = str.replace(reg, json[out]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
test = str.replace(reg, currentUser.id);
|
|
||||||
}
|
|
||||||
} else if (output.length === 2) {
|
|
||||||
let out1 = json[output[0]][output[1]];
|
|
||||||
if (out1) {
|
|
||||||
test = str.replace(reg, out1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (output.length === 2) {
|
|
||||||
let output1 = output[0];
|
|
||||||
output1 = output1.substring(1, output1.length - 1);
|
|
||||||
output1 = output1.split(".");
|
|
||||||
if (output1.length === 1) {
|
|
||||||
let out = output1[0];
|
|
||||||
if (json[out]) {
|
|
||||||
if (typeof json[out] === "object") {
|
|
||||||
str = str.replace(output[0], JSON.stringify(json[out]));
|
|
||||||
} else {
|
|
||||||
str = str.replace(output[0], json[out]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
str = str.replace(output[0], currentUser.id);
|
|
||||||
}
|
|
||||||
} else if (output1.length === 2) {
|
|
||||||
let out1 = json[output1[0]][output1[1]];
|
|
||||||
if (out1) {
|
|
||||||
str = str.replace(output[0], out1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let output2 = output[1];
|
|
||||||
output2 = output2.substring(1, output2.length - 1);
|
|
||||||
output2 = output2.split(".");
|
|
||||||
if (output2.length === 1) {
|
|
||||||
let out = output2[0];
|
|
||||||
if (json[out]) {
|
|
||||||
if (typeof json[out] === "object") {
|
|
||||||
str = str.replace(output[1], JSON.stringify(json[out]));
|
|
||||||
} else {
|
|
||||||
str = str.replace(output[1], json[out]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
str = str.replace(output[1], currentUser.id);
|
|
||||||
}
|
|
||||||
} else if (output2.length === 2) {
|
|
||||||
let out1 = json[output2[0]][output2[1]];
|
|
||||||
if (out1) {
|
|
||||||
str = str.replace(output[1], out1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test = str;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setToastDescription(
|
|
||||||
`User not found in ${localStorage.getItem("extended_class")}`
|
|
||||||
);
|
|
||||||
setActive(false);
|
|
||||||
var x = document.getElementById("Level_1");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
|
||||||
x.className = x.className.replace("show", "");
|
|
||||||
}, 5000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
test = str;
|
|
||||||
}
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.class}?${test}`;
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
let fetchCount = 0;
|
|
||||||
let offset = 0;
|
|
||||||
let data = [];
|
|
||||||
/* eslint-disable no-constant-condition */
|
|
||||||
while (true) {
|
|
||||||
const params = getParams(offset);
|
|
||||||
await axios
|
|
||||||
.get(url, { params: params, headers: headers })
|
|
||||||
.then((response) => {
|
|
||||||
fetchCount = response.data.results.length;
|
|
||||||
offset += response.data.results.length;
|
|
||||||
|
|
||||||
if (fetchCount > 0) {
|
|
||||||
response.data.results.forEach((x) => {
|
|
||||||
data.push(x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Problem", err.response);
|
|
||||||
setToastDescription(err.response.data.message);
|
|
||||||
setActive(false);
|
|
||||||
var x = document.getElementById("Level_1");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
|
||||||
x.className = x.className.replace("show", "");
|
|
||||||
}, 5000);
|
|
||||||
});
|
|
||||||
if (fetchCount === 0 || fetchCount < 100) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.length > 0) {
|
|
||||||
let temp = [];
|
|
||||||
data.forEach((x) => {
|
|
||||||
let opt = "";
|
|
||||||
if (Array.isArray(x[props.schema.data.valueKey])) {
|
|
||||||
x[props.schema.data.valueKey].forEach((tt) => {
|
|
||||||
if (typeof tt === "object") {
|
|
||||||
if (props.schema.data.isPointer) {
|
|
||||||
opt = {
|
|
||||||
objectId: tt["objectId"],
|
|
||||||
option: tt[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: tt[props.schema.data.displayKey],
|
|
||||||
option: tt[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: tt,
|
|
||||||
option: tt
|
|
||||||
};
|
|
||||||
}
|
|
||||||
temp.push(opt);
|
|
||||||
});
|
|
||||||
} else if (props.schema.data.isPointer) {
|
|
||||||
if (props.schema.data.valueKey.includes(".")) {
|
|
||||||
let newArr = props.schema.data.valueKey.split(".");
|
|
||||||
if (newArr.length === 2) {
|
|
||||||
let _dis = props.schema.data.displayKey.split(".");
|
|
||||||
if (_dis.length === 2) {
|
|
||||||
opt = {
|
|
||||||
objectId: x[newArr[0]][newArr[1]],
|
|
||||||
option: x[_dis[0]][_dis[1]]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[newArr[0]][newArr[1]],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[newArr[0]],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[props.schema.data.valueKey],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
temp.push(opt);
|
|
||||||
} else {
|
|
||||||
opt = {
|
|
||||||
objectId: x[props.schema.data.valueKey],
|
|
||||||
option: x[props.schema.data.displayKey]
|
|
||||||
};
|
|
||||||
temp.push(opt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
response = temp;
|
|
||||||
setLevel1_DD(response);
|
|
||||||
setActive(false);
|
|
||||||
if (!props.formData) {
|
|
||||||
props.onChangeLevel1Dropdown("", props.name);
|
|
||||||
}
|
|
||||||
if (response.length === 1) {
|
|
||||||
props.onChangeLevel1Dropdown(response[0].objectId, props.name);
|
|
||||||
props.onChange(response[0].objectId);
|
|
||||||
} else if (response.length === 0) {
|
|
||||||
props.onChangeLevel1Dropdown("", props.name);
|
|
||||||
props.onChange("");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
try {
|
|
||||||
setToastDescription(e.message);
|
|
||||||
setActive(false);
|
|
||||||
x = document.getElementById("Level_1");
|
|
||||||
x.className = "show";
|
|
||||||
setTimeout(function () {
|
|
||||||
x.className = x.className.replace("show", "");
|
|
||||||
}, 5000);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Err", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
Level1DropdownData();
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.formData && props.formData[`objectId`]) {
|
|
||||||
props.onChangeLevel1Dropdown(props.formData.objectId, props.name);
|
|
||||||
} else if (props.formData) {
|
|
||||||
props.onChangeLevel1Dropdown(props.formData, props.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [props.formData]);
|
|
||||||
|
|
||||||
const selectDefault = () => {
|
|
||||||
props.onChange(Level1_DD[0].objectId);
|
|
||||||
props.onChangeLevel1Dropdown(Level1_DD[0].objectId, props.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
const REQUIRED_FIELD_SYMBOL = "*";
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div style={{ display: "inline-block" }}>
|
|
||||||
<label htmlFor={props.name}>
|
|
||||||
{props.schema.title}
|
|
||||||
{props.required && (
|
|
||||||
<span className="required">{REQUIRED_FIELD_SYMBOL}</span>
|
|
||||||
)}
|
|
||||||
{props.schema.data.helpbody ? (
|
|
||||||
<div className="dropdown pull-right">
|
|
||||||
<i
|
|
||||||
className="far fa-question-circle dropdown-toggle hovereffect pull-right"
|
|
||||||
aria-hidden="true"
|
|
||||||
id="dropdownMenuButton"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded="false"
|
|
||||||
style={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: "purple",
|
|
||||||
cursor: "pointer !important",
|
|
||||||
position: "relative",
|
|
||||||
bottom: "0px",
|
|
||||||
left: "0px",
|
|
||||||
paddingBottom: "4px",
|
|
||||||
paddingLeft: "4px"
|
|
||||||
}}
|
|
||||||
></i>
|
|
||||||
<div
|
|
||||||
className="dropdown-menu"
|
|
||||||
aria-labelledby="dropdownMenuButton"
|
|
||||||
style={{
|
|
||||||
marginleft: "-121px",
|
|
||||||
margintop: "-14px",
|
|
||||||
position: "absolute",
|
|
||||||
padding: "10px",
|
|
||||||
top: "102px!important"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{parse(`
|
|
||||||
${props.schema.data.helpbody}
|
|
||||||
`)}
|
|
||||||
<br />
|
|
||||||
{props.schema.data.helplink ? (
|
|
||||||
<a
|
|
||||||
href={props.schema.data.helplink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="btn btn-xs btn-primary"
|
|
||||||
>
|
|
||||||
Read more..
|
|
||||||
</a>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{Level1_DD && (
|
|
||||||
<select
|
|
||||||
className="form-control"
|
|
||||||
name={props.name}
|
|
||||||
value={props.value}
|
|
||||||
required={props.required}
|
|
||||||
disabled={props.uiSchema["ui:disabled"]}
|
|
||||||
onChange={(e) => {
|
|
||||||
if (!e.target.value) {
|
|
||||||
if (props.schema.data.isPointer) {
|
|
||||||
localStorage.setItem("Level1", undefined);
|
|
||||||
props.onChangeLevel1Dropdown(undefined, props.name);
|
|
||||||
return props.onChange(undefined);
|
|
||||||
} else {
|
|
||||||
localStorage.setItem("Level1", e.target.value);
|
|
||||||
props.onChangeLevel1Dropdown(e.target.value, props.name);
|
|
||||||
return props.onChange(e.target.value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localStorage.setItem("Level1", e.target.value);
|
|
||||||
props.onChangeLevel1Dropdown(e.target.value, props.name);
|
|
||||||
return props.onChange(e.target.value);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
readOnly={props.uiSchema["ui:disabled"] ? true : false}
|
|
||||||
defaultValue={Level1_DD.length === 1 && selectDefault}
|
|
||||||
>
|
|
||||||
<option value="">{!active ? "Select" : "loading..."}</option>
|
|
||||||
{Level1_DD &&
|
|
||||||
Level1_DD.map((x, i) => (
|
|
||||||
<React.Fragment key={i}>
|
|
||||||
{props.formData && props.formData.objectId ? (
|
|
||||||
props.formData.objectId === x.objectId ? (
|
|
||||||
<option value={x.objectId} selected>
|
|
||||||
{x.option}
|
|
||||||
</option>
|
|
||||||
) : (
|
|
||||||
<option value={x.objectId}>{x.option}</option>
|
|
||||||
)
|
|
||||||
) : props.formData && props.formData === x.objectId ? (
|
|
||||||
<option value={x.objectId} selected>
|
|
||||||
{x.option}
|
|
||||||
</option>
|
|
||||||
) : (
|
|
||||||
<option value={x.objectId}>{x.option}</option>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
)}
|
|
||||||
<div id="Level_1" style={{ backgroundColor: toastColor }}>
|
|
||||||
{toastDescription}
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(null, { onChangeLevel1Dropdown })(Level1Dropdown);
|
|
||||||
@@ -1,709 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import Select from "react-select";
|
|
||||||
import axios from "axios";
|
|
||||||
import LabelField from "./LabelField";
|
|
||||||
import ReactDragListView from "react-drag-listview";
|
|
||||||
import AppendFormInForm from "../AppendFormInForm";
|
|
||||||
import Modal from "react-modal";
|
|
||||||
function arrayMove(array, from, to) {
|
|
||||||
array = array.slice();
|
|
||||||
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* react-sortable-hoc is depcreated not usable from react 18.x.x
|
|
||||||
* need to replace it with @dnd-kit
|
|
||||||
* code changes required
|
|
||||||
*/
|
|
||||||
|
|
||||||
const MultiSelectField = (props) => {
|
|
||||||
Modal.setAppElement("body");
|
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
|
||||||
const [state, setState] = useState(undefined);
|
|
||||||
// const [editFormData, setEditFormData] = useState([]);
|
|
||||||
const [selected, setSelected] = React.useState([]);
|
|
||||||
const [isModal, setIsModel] = useState(false);
|
|
||||||
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
|
||||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
||||||
|
|
||||||
const onSortEnd = ({ oldIndex, newIndex }) => {
|
|
||||||
const newValue = arrayMove(selected, oldIndex, newIndex);
|
|
||||||
setSelected(newValue);
|
|
||||||
};
|
|
||||||
// console.log("props",props)
|
|
||||||
const GetSelectListData = async () => {
|
|
||||||
try {
|
|
||||||
let response = [];
|
|
||||||
let str = props.schema.data.query;
|
|
||||||
let _query;
|
|
||||||
/* eslint-disable no-useless-escape */
|
|
||||||
let reg = /(\#.*?\#)/gi;
|
|
||||||
let extclass =
|
|
||||||
localStorage.getItem("Extand_Class") &&
|
|
||||||
JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
let extRow = extclass.length && extclass[0];
|
|
||||||
if (str.includes("#")) {
|
|
||||||
let output = str.match(reg);
|
|
||||||
output = output.join();
|
|
||||||
output = output.substring(1, output.length - 1);
|
|
||||||
output = output.split(".");
|
|
||||||
|
|
||||||
if (output.length === 2) {
|
|
||||||
let out1 = extRow[output[0]][output[1]];
|
|
||||||
_query = str.replace(reg, out1 && out1);
|
|
||||||
} else {
|
|
||||||
let out1 = extRow[output[0]];
|
|
||||||
_query = str.replace(reg, out1 && out1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_query = str;
|
|
||||||
}
|
|
||||||
let url = `${parseBaseUrl}classes/${props.schema.data.class}?${_query}`;
|
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId,
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
};
|
|
||||||
await axios.get(url, { headers: headers }).then((res) => {
|
|
||||||
let temp = [];
|
|
||||||
let formArray = [];
|
|
||||||
let _selected = [];
|
|
||||||
if (props.schema.uiLayout === "MultiDropdownList") {
|
|
||||||
if (props.formData) {
|
|
||||||
props.formData.forEach((x) => {
|
|
||||||
if (typeof x === "object") {
|
|
||||||
formArray.push(x.objectId);
|
|
||||||
} else {
|
|
||||||
formArray.push(x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
res.data.results.forEach((x) => {
|
|
||||||
let obj = {};
|
|
||||||
if (formArray.includes(x[props.schema.data.valueKey])) {
|
|
||||||
obj = {
|
|
||||||
name: x[props.schema.data.displayKey],
|
|
||||||
value: x[props.schema.data.valueKey],
|
|
||||||
isChecked: true
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
if (props.schema.selectAll) {
|
|
||||||
obj = {
|
|
||||||
name: x[props.schema.data.displayKey],
|
|
||||||
value: x[props.schema.data.valueKey],
|
|
||||||
isChecked: true
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
obj = {
|
|
||||||
name: x[props.schema.data.displayKey],
|
|
||||||
value: x[props.schema.data.valueKey],
|
|
||||||
isChecked: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
temp.push(obj);
|
|
||||||
});
|
|
||||||
response = temp;
|
|
||||||
if (props.formData) {
|
|
||||||
let checkData = [];
|
|
||||||
response.forEach((x) => {
|
|
||||||
if (x.isChecked) {
|
|
||||||
checkData.push(x.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setSelected(checkData);
|
|
||||||
}
|
|
||||||
setState({ [`${props.name}_DD`]: response });
|
|
||||||
} else {
|
|
||||||
res.data.results.forEach((x) => {
|
|
||||||
let obj = {};
|
|
||||||
if (props.formData) {
|
|
||||||
props.formData.forEach((x) => {
|
|
||||||
if (typeof x === "object") {
|
|
||||||
formArray.push(x.objectId);
|
|
||||||
} else {
|
|
||||||
formArray.push(x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
obj = {
|
|
||||||
label: x[props.schema.data.displayKey],
|
|
||||||
value: x[props.schema.data.valueKey]
|
|
||||||
};
|
|
||||||
if (formArray.includes(x[props.schema.data.valueKey])) {
|
|
||||||
_selected.push(obj);
|
|
||||||
}
|
|
||||||
if (props.schema.selectAll) {
|
|
||||||
_selected.push(obj);
|
|
||||||
}
|
|
||||||
temp.push(obj);
|
|
||||||
});
|
|
||||||
response = temp;
|
|
||||||
setState({ [`${props.name}_DD`]: response });
|
|
||||||
setSelected(_selected);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log("err", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCheckChieldElement = (event) => {
|
|
||||||
let SelectLists = state[`${props.name}_DD`];
|
|
||||||
let List = [];
|
|
||||||
SelectLists.forEach((select) => {
|
|
||||||
if (select.value === event.target.value) {
|
|
||||||
select.isChecked = event.target.checked;
|
|
||||||
}
|
|
||||||
if (select.isChecked) {
|
|
||||||
List.push(select.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setSelected(List);
|
|
||||||
setState({ [`${props.name}_DD`]: SelectLists });
|
|
||||||
};
|
|
||||||
|
|
||||||
// const Level1CheckList = async (id) => {
|
|
||||||
// try {
|
|
||||||
// let response = [];
|
|
||||||
// // eslint-disable-next-line
|
|
||||||
// let reg = /(\#.*?\#)/gi;
|
|
||||||
// let _query = props.schema.data.query;
|
|
||||||
// let output = _query.match(reg);
|
|
||||||
// if (output.length === 2) {
|
|
||||||
// let res;
|
|
||||||
// if (localStorage.getItem("Extand_Class")) {
|
|
||||||
// let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
|
||||||
// res = data[0];
|
|
||||||
// }
|
|
||||||
// output = output.filter((x) => x !== "#queryString#");
|
|
||||||
// if (output.length === 1) {
|
|
||||||
// _query = _query.replace("#queryString#", id);
|
|
||||||
// output = output.join();
|
|
||||||
// output = output.substring(1, output.length - 1);
|
|
||||||
// output = output.split(".");
|
|
||||||
// if (output.length > 0) {
|
|
||||||
// _query = _query.replace(reg, res[output[0]][output[1]]);
|
|
||||||
// } else {
|
|
||||||
// _query = _query.replace(reg, res[output[0]]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// _query = props.schema.data.query.replace(reg, id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let url = `${parseBaseUrl}classes/${props.schema.data.class}?${_query}`;
|
|
||||||
// const headers = {
|
|
||||||
// "Content-Type": "application/json",
|
|
||||||
// "X-Parse-Application-Id": parseAppId,
|
|
||||||
// "X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
// };
|
|
||||||
// await axios.get(url, { headers: headers }).then(async (res) => {
|
|
||||||
// let temp = [];
|
|
||||||
// let formArray = [];
|
|
||||||
// let _selected = [];
|
|
||||||
// if (editFormData.length > 0) {
|
|
||||||
// editFormData.forEach((x) => {
|
|
||||||
// if (typeof x === "object") {
|
|
||||||
// formArray.push(x.objectId);
|
|
||||||
// } else {
|
|
||||||
// formArray.push(x);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } else if (
|
|
||||||
// props.schema.selectedData &&
|
|
||||||
// Object.keys(props.schema.selectedData).length !== 0 &&
|
|
||||||
// props.schema.selectedData.constructor === Object
|
|
||||||
// ) {
|
|
||||||
// try {
|
|
||||||
// let selectedDataQuery = props.schema.selectedData.query.replace(
|
|
||||||
// reg,
|
|
||||||
// id
|
|
||||||
// );
|
|
||||||
// let selectedDataUrl = `${parseBaseUrl}classes/${props.schema.selectedData.class}?${selectedDataQuery}`;
|
|
||||||
|
|
||||||
// await axios.get(selectedDataUrl, { headers }).then((sltres) => {
|
|
||||||
// let sltData = sltres.data.results;
|
|
||||||
// sltData.forEach((x) => {
|
|
||||||
// if (props.schema.selectedData.valueKey.includes(".")) {
|
|
||||||
// let sltArr = props.schema.selectedData.valueKey.split(".");
|
|
||||||
|
|
||||||
// if (Array.isArray(x[sltArr[0]])) {
|
|
||||||
// x[sltArr[0]].forEach((l) => {
|
|
||||||
// formArray.push(l[sltArr[1]]);
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// formArray.push(x[sltArr[0][sltArr[1]]]);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// formArray.push(x[props.schema.selectedData.valueKey]);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// } catch (error) {}
|
|
||||||
// }
|
|
||||||
// res.data.results.forEach((x) => {
|
|
||||||
// let obj = {};
|
|
||||||
// if (props.schema.data.valueKey.includes(".")) {
|
|
||||||
// let newArr = props.schema.data.valueKey.split(".");
|
|
||||||
// if (Array.isArray(x[newArr[0]])) {
|
|
||||||
// if (props.schema.data.displayKey.includes(".")) {
|
|
||||||
// let _dis = props.schema.data.displayKey.split(".");
|
|
||||||
// x[newArr[0]].forEach((l) => {
|
|
||||||
// if (formArray.includes(l[newArr[1]])) {
|
|
||||||
// obj = {
|
|
||||||
// label: l[_dis[1]],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: l[_dis[1]],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: l[_dis[1]],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// temp.push(obj);
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// x[newArr[0]].forEach((l) => {
|
|
||||||
// if (formArray.includes(l[newArr[1]])) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: l[newArr[1]],
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// temp.push(obj);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.data.displayKey.includes(".")) {
|
|
||||||
// let disArr = props.schema.data.displayKey.split(".");
|
|
||||||
// if (formArray.includes(x[newArr[0]][newArr[1]])) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[disArr[0]][disArr[1]],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[disArr[0]][disArr[1]],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: x[disArr[0]][disArr[1]],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (formArray.includes(x[newArr[0]][newArr[1]])) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[newArr[0]][newArr[1]],
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (Array.isArray(x[props.schema.data.valueKey])) {
|
|
||||||
// x[props.schema.data.valueKey].forEach((t) => {
|
|
||||||
// if (formArray.includes(t)) {
|
|
||||||
// obj = {
|
|
||||||
// label: t,
|
|
||||||
// value: t,
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: t,
|
|
||||||
// value: t,
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: t,
|
|
||||||
// value: t,
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// temp.push(obj);
|
|
||||||
// });
|
|
||||||
// } else if (formArray.includes(x[props.schema.data.valueKey])) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[props.schema.data.valueKey],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// if (props.schema.selectAll) {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[props.schema.data.valueKey],
|
|
||||||
// isChecked: true
|
|
||||||
// };
|
|
||||||
// _selected.push(obj);
|
|
||||||
// } else {
|
|
||||||
// obj = {
|
|
||||||
// label: x[props.schema.data.displayKey],
|
|
||||||
// value: x[props.schema.data.valueKey],
|
|
||||||
// isChecked: false
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// temp.push(obj);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// response = temp;
|
|
||||||
// if (props.schema.uiLayout === "MultiDropdownList") {
|
|
||||||
// if (editFormData) {
|
|
||||||
// let checkData = [];
|
|
||||||
// response.forEach((x) => {
|
|
||||||
// if (x.isChecked) {
|
|
||||||
// checkData.push(x.value);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// setSelected(checkData);
|
|
||||||
// }
|
|
||||||
// setState({ [`${props.name}_DD`]: response });
|
|
||||||
// } else {
|
|
||||||
// setState({ [`${props.name}_DD`]: response });
|
|
||||||
// setSelected(_selected);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } catch (error) {}
|
|
||||||
// };
|
|
||||||
|
|
||||||
const dragProps = {
|
|
||||||
onDragEnd(fromIndex, toIndex) {
|
|
||||||
const data = [...state[`${props.name}_DD`]];
|
|
||||||
const item = data.splice(fromIndex, 1)[0];
|
|
||||||
data.splice(toIndex, 0, item);
|
|
||||||
let NewList = [];
|
|
||||||
data.forEach((x) => {
|
|
||||||
if (x.isChecked) {
|
|
||||||
NewList.push(x.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setState({ [`${props.name}_DD`]: data });
|
|
||||||
setSelected(NewList);
|
|
||||||
},
|
|
||||||
nodeSelector: "li",
|
|
||||||
handleSelector: "a"
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!props.schema.parent) GetSelectListData();
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.schema.uiLayout === "MultiDropdownList") {
|
|
||||||
props.onChange(selected);
|
|
||||||
} else {
|
|
||||||
if (selected && selected.length) {
|
|
||||||
let newData = [];
|
|
||||||
selected.forEach((x) => {
|
|
||||||
newData.push(x.value);
|
|
||||||
});
|
|
||||||
props.onChange(newData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [selected]);
|
|
||||||
|
|
||||||
// useState(() => {
|
|
||||||
// if (props.formData) {
|
|
||||||
// if (props.formData === "Select") {
|
|
||||||
// } else {
|
|
||||||
// setEditFormData(props.formData);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // eslint-disable-next-line
|
|
||||||
// }, [props.formData]);
|
|
||||||
|
|
||||||
const handleModalCloseClick = () => {
|
|
||||||
setIsModel(false);
|
|
||||||
setModalIsOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const openModal = () => {
|
|
||||||
setModalIsOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// `handleNewDetails` is used to set just save from quick form to selected option in dropdown
|
|
||||||
const handleNewDetails = (data) => {
|
|
||||||
setState({ [`${props.name}_DD`]: [...state[`${props.name}_DD`], data] });
|
|
||||||
if (selected.length > 0) {
|
|
||||||
setSelected([...selected, data]);
|
|
||||||
} else {
|
|
||||||
setSelected([data]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (props.schema.uiLayout === "MultiDropdownList") {
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<LabelField
|
|
||||||
Title={props.schema.title}
|
|
||||||
Name={props.name}
|
|
||||||
Required={props.required}
|
|
||||||
HelpBody={props.schema.helpbody}
|
|
||||||
HelpLink={props.schema.helplink}
|
|
||||||
/>
|
|
||||||
<ReactDragListView {...dragProps}>
|
|
||||||
<ul
|
|
||||||
style={{
|
|
||||||
listStyleType: "square",
|
|
||||||
listStylePosition: "outside",
|
|
||||||
maxHeight: "250px",
|
|
||||||
overflow: "auto",
|
|
||||||
paddingTop: "10px",
|
|
||||||
paddingBottom: "10px",
|
|
||||||
border: "0px solid #b3b3b3",
|
|
||||||
borderRadius: "5px"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{state && state[`${props.name}_DD`].length > 0 ? (
|
|
||||||
state[`${props.name}_DD`].map((x, i) => {
|
|
||||||
return (
|
|
||||||
<li key={i} className="multiSelectList">
|
|
||||||
<input
|
|
||||||
key={x.value}
|
|
||||||
onClick={handleCheckChieldElement}
|
|
||||||
type="checkbox"
|
|
||||||
checked={x.isChecked}
|
|
||||||
style={{ marginTop: "7px" }}
|
|
||||||
value={x.value}
|
|
||||||
disabled={props.disabled}
|
|
||||||
/>{" "}
|
|
||||||
<span style={{ marginTop: "7px" }}>{x.name}</span>
|
|
||||||
{props.schema.isSortable && !props.disabled && (
|
|
||||||
<a
|
|
||||||
onClick={(e) => e.preventDefault()}
|
|
||||||
className="pull-right"
|
|
||||||
title="Sort List"
|
|
||||||
style={{ textDecoration: "none" }}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-bars"
|
|
||||||
style={{
|
|
||||||
fontSize: "30px",
|
|
||||||
color: "skyblue",
|
|
||||||
paddingTop: "11px"
|
|
||||||
}}
|
|
||||||
></i>
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<li className="multiSelectList">No Record Found</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
</ReactDragListView>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<LabelField
|
|
||||||
Title={props.schema.title}
|
|
||||||
Name={props.name}
|
|
||||||
Required={props.required}
|
|
||||||
HelpBody={props.schema.helpbody}
|
|
||||||
HelpLink={props.schema.helplink}
|
|
||||||
/>
|
|
||||||
<div style={{ display: "flex", gap: 5 }}>
|
|
||||||
<div style={{ flexWrap: "wrap", width: "100%" }}>
|
|
||||||
<Select
|
|
||||||
onSortEnd={onSortEnd}
|
|
||||||
distance={4}
|
|
||||||
isMulti
|
|
||||||
options={(state && state[`${props.name}_DD`]) || []}
|
|
||||||
value={selected}
|
|
||||||
onChange={onChange}
|
|
||||||
closeMenuOnSelect={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{props.schema.data.quickAddFormId && (
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
setIsModel(true);
|
|
||||||
openModal();
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
cursor: "pointer",
|
|
||||||
borderRadius: 4,
|
|
||||||
border: "1px solid #ccc",
|
|
||||||
minHeight: 38,
|
|
||||||
minWidth: 48,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className="fas fa-plus"></i>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* {props.schema.data.quickAddFormId && (
|
|
||||||
<div
|
|
||||||
className="modal fade"
|
|
||||||
id={"multiSelectModal" + props.schema.data.quickAddFormId}
|
|
||||||
tabIndex="-1"
|
|
||||||
role="dialog"
|
|
||||||
aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<div className="modal-dialog modal-lg" role="document">
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-header">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="close"
|
|
||||||
data-dismiss="modal"
|
|
||||||
aria-label="Close"
|
|
||||||
onClick={handleModalCloseClick}
|
|
||||||
>
|
|
||||||
<i className="fa fa-times-circle" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
{isModal && (
|
|
||||||
<AppendFormInForm
|
|
||||||
id={props.schema.data.quickAddFormId}
|
|
||||||
valueKey={props.schema.data.valueKey}
|
|
||||||
displayKey={props.schema.data.displayKey}
|
|
||||||
details={handleNewDetails}
|
|
||||||
closePopup={handleModalCloseClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)} */}
|
|
||||||
<Modal
|
|
||||||
isOpen={modalIsOpen}
|
|
||||||
onRequestClose={handleModalCloseClick}
|
|
||||||
shouldCloseOnOverlayClick={false}
|
|
||||||
contentLabel="Modal"
|
|
||||||
style={{
|
|
||||||
content: {
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
right: "auto",
|
|
||||||
bottom: "auto",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
padding: 0
|
|
||||||
},
|
|
||||||
overlay: {
|
|
||||||
width: "100%",
|
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
||||||
zIndex: 50
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="min-w-full md:min-w-[500px]">
|
|
||||||
<div
|
|
||||||
type="button"
|
|
||||||
className="flex justify-between items-center p-3 border-b-[1px] border-gray-300"
|
|
||||||
>
|
|
||||||
<div className=" text-black text-xl font-semibold pl-3">
|
|
||||||
Add Signer
|
|
||||||
</div>
|
|
||||||
<button onClick={handleModalCloseClick}>
|
|
||||||
<i
|
|
||||||
style={{ fontSize: 25 }}
|
|
||||||
className="fa fa-times-circle"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{isModal && (
|
|
||||||
<AppendFormInForm
|
|
||||||
id={props.schema.data.quickAddFormId}
|
|
||||||
valueKey={props.schema.data.valueKey}
|
|
||||||
displayKey={props.schema.data.displayKey}
|
|
||||||
details={handleNewDetails}
|
|
||||||
closePopup={handleModalCloseClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
|
||||||
return {
|
|
||||||
Level1_Dropdown: state.Level1_Dropdown,
|
|
||||||
Level2_Dropdown: state.Level2_Dropdown,
|
|
||||||
Level3_Dropdown: state.Level3_Dropdown
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default connect(mapStateToProps, null)(MultiSelectField);
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import ObjectField from "@rjsf/core/lib/components/fields/ObjectField";
|
|
||||||
import validator from "@rjsf/validator-ajv8";
|
|
||||||
import { Col } from "react-bootstrap";
|
|
||||||
import { retrieveSchema } from "@rjsf/utils";
|
|
||||||
|
|
||||||
class GridField extends ObjectField {
|
|
||||||
state = {};
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
uiSchema,
|
|
||||||
errorSchema,
|
|
||||||
idSchema,
|
|
||||||
|
|
||||||
disabled,
|
|
||||||
readonly,
|
|
||||||
onBlur,
|
|
||||||
formData
|
|
||||||
} = this.props;
|
|
||||||
const { fields, rootSchema } = this.props.registry;
|
|
||||||
|
|
||||||
const { SchemaField } = fields;
|
|
||||||
const schema = retrieveSchema(validator, this.props.schema, rootSchema);
|
|
||||||
const title = schema.title === undefined ? "" : schema.title;
|
|
||||||
const description =
|
|
||||||
schema && schema.description === undefined ? "" : schema.description;
|
|
||||||
// console.log('this.props.schema ', this.props.schema)
|
|
||||||
// console.log("schema ", schema);
|
|
||||||
const layout = uiSchema["ui:layout"];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<fieldset>
|
|
||||||
{title ? <h4>{title}</h4> : null}
|
|
||||||
{description ? <h6>{description}</h6> : null}
|
|
||||||
{layout.map((row, index) => {
|
|
||||||
return (
|
|
||||||
<div className="row" key={index}>
|
|
||||||
{Object.keys(row).map((name, index) => {
|
|
||||||
const { doShow, ...rowProps } = row[name];
|
|
||||||
let style = {};
|
|
||||||
if (doShow && !doShow({ formData })) {
|
|
||||||
style = { display: "none" };
|
|
||||||
}
|
|
||||||
if (schema.properties[name]) {
|
|
||||||
return (
|
|
||||||
<Col {...rowProps} key={index} style={style}>
|
|
||||||
<SchemaField
|
|
||||||
name={name}
|
|
||||||
required={this.isRequired(name)}
|
|
||||||
schema={schema.properties[name]}
|
|
||||||
uiSchema={uiSchema[name]}
|
|
||||||
errorSchema={errorSchema[name]}
|
|
||||||
idSchema={idSchema[name]}
|
|
||||||
formData={formData[name]}
|
|
||||||
onChange={this.onPropertyChange(name)}
|
|
||||||
onBlur={onBlur}
|
|
||||||
registry={this.props.registry}
|
|
||||||
disabled={disabled}
|
|
||||||
readonly={readonly}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const { render, ...rowProps } = row[name];
|
|
||||||
let UIComponent = () => null;
|
|
||||||
|
|
||||||
if (render) {
|
|
||||||
UIComponent = render;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Col {...rowProps} key={index} style={style}>
|
|
||||||
<UIComponent
|
|
||||||
name={name}
|
|
||||||
formData={formData}
|
|
||||||
errorSchema={errorSchema}
|
|
||||||
uiSchema={uiSchema}
|
|
||||||
schema={schema}
|
|
||||||
registry={this.props.registry}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</fieldset>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default GridField;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import PropTypes from "prop-types";
|
|
||||||
|
|
||||||
function TimeWidget(props) {
|
|
||||||
const {
|
|
||||||
onChange,
|
|
||||||
registry: {
|
|
||||||
widgets: { BaseInput }
|
|
||||||
}
|
|
||||||
} = props;
|
|
||||||
return (
|
|
||||||
<BaseInput
|
|
||||||
type="time"
|
|
||||||
{...props}
|
|
||||||
onChange={(value) => onChange(value || undefined)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production") {
|
|
||||||
TimeWidget.propTypes = {
|
|
||||||
value: PropTypes.string
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TimeWidget;
|
|
||||||
@@ -1,34 +1,43 @@
|
|||||||
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 "../shared/fields/SelectFolder"; //check this one
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
function PdfFileComponent({
|
function DriveBody({
|
||||||
pdfData,
|
pdfData,
|
||||||
setFolderName,
|
setFolderName,
|
||||||
setDocId,
|
setDocId,
|
||||||
setIsLoading,
|
setIsLoading,
|
||||||
setPdfData,
|
setPdfData,
|
||||||
isList,
|
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);
|
||||||
|
const [isOpenMoveModal, setIsOpenMoveModal] = useState(false);
|
||||||
|
const [selectDoc, setSelectDoc] = useState();
|
||||||
|
const [isDeleteDoc, setIsDeleteDoc] = useState(false);
|
||||||
|
const contextMenu = [
|
||||||
|
{ type: "Download", icon: "fa-solid fa-arrow-down" },
|
||||||
|
{ type: "Rename", icon: "fa-solid fa-font" },
|
||||||
|
{ type: "Move", icon: "fa-solid fa-file-export" },
|
||||||
|
{ type: "Delete", icon: "fa-solid fa-trash" }
|
||||||
|
];
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
//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);
|
||||||
@@ -39,12 +48,12 @@ function PdfFileComponent({
|
|||||||
const handleOnclikFolder = (data) => {
|
const handleOnclikFolder = (data) => {
|
||||||
const folderData = {
|
const folderData = {
|
||||||
name: data.Name,
|
name: data.Name,
|
||||||
objectId: data.objectId,
|
objectId: data.objectId
|
||||||
};
|
};
|
||||||
setFolderName((prev) => [...prev, folderData]);
|
setFolderName((prev) => [...prev, folderData]);
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time",
|
message: "This might take some time"
|
||||||
};
|
};
|
||||||
|
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
@@ -57,7 +66,7 @@ function PdfFileComponent({
|
|||||||
|
|
||||||
if (trimmedValue.length > 0) {
|
if (trimmedValue.length > 0) {
|
||||||
const updateName = {
|
const updateName = {
|
||||||
Name: renameValue,
|
Name: renameValue
|
||||||
};
|
};
|
||||||
const docId = data.objectId;
|
const docId = data.objectId;
|
||||||
|
|
||||||
@@ -83,98 +92,207 @@ function PdfFileComponent({
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken"),
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((result) => {
|
.then(() => {
|
||||||
// const res = result.data;
|
// const res = result.data;
|
||||||
// console.log("res", res);
|
// console.log("res", res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("error updating field is decline ", err);
|
console.log("Err ", err);
|
||||||
|
setIsAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "something went wrong"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//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 expireDate = data.ExpiryDate.iso;
|
|
||||||
const expireUpdateDate = new Date(expireDate).getTime();
|
|
||||||
const currDate = new Date().getTime();
|
|
||||||
const signerExist = data.Signers && data.Signers;
|
const signerExist = data.Signers && data.Signers;
|
||||||
const signUrl = data.SignedUrl && data.SignedUrl;
|
|
||||||
const isDecline = data.IsDeclined && data.IsDeclined;
|
const isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
const isPlaceholder = data.Placeholders && data.Placeholders;
|
const isPlaceholder = data.Placeholders && data.Placeholders;
|
||||||
//checking and navigate to signyouself page
|
const signedUrl = data.SignedUrl;
|
||||||
const checkPlaceHolder = data.Placeholders;
|
//checking if document has completed and request signature flow
|
||||||
//checking if document has completed
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
if (data.IsCompleted && signerExist) {
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
}
|
||||||
|
//checking if document has completed and signyour-self flow
|
||||||
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
|
else if (!signerExist && !isPlaceholder) {
|
||||||
} else if (data.IsCompleted && !signerExist) {
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
navigate(
|
|
||||||
`${hostUrl}signaturePdf/${data.objectId}`
|
|
||||||
);
|
|
||||||
// window.location.hash = `/recipientSignPdf/${data.objectId}/${data.ExtUserPtr.Phone}`;
|
|
||||||
}
|
}
|
||||||
//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}`);
|
||||||
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
|
//checking draft type document
|
||||||
} else if (currDate > expireUpdateDate && signerExist && !isPlaceholder) {
|
|
||||||
// window.location.hash = `/placeHolderSign/${data.objectId}`;
|
|
||||||
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
|
|
||||||
} else if (
|
} else if (
|
||||||
currDate > expireUpdateDate &&
|
signerExist?.length > 0 &&
|
||||||
!signerExist &&
|
isPlaceholder?.length > 0 &&
|
||||||
!isPlaceholder &&
|
!signedUrl
|
||||||
!signUrl
|
|
||||||
) {
|
) {
|
||||||
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
// window.location.hash = `/signaturePdf/${data.objectId}`;
|
|
||||||
}
|
}
|
||||||
//checking if document has expired
|
//Inprogress document
|
||||||
else if (currDate > expireUpdateDate) {
|
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
|
} //placeholder draft document
|
||||||
} //checking if document is draft signers type and signers placeholder does not placed yet
|
|
||||||
else if (!signUrl && signerExist) {
|
|
||||||
// window.location.hash = `/placeHolderSign/${data.objectId}`;
|
|
||||||
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
|
|
||||||
}
|
|
||||||
//checking if document is request type and signers placeholder exist and does not completed yet
|
|
||||||
//then user can check progress of document and sign also
|
|
||||||
else if (
|
else if (
|
||||||
checkPlaceHolder &&
|
(signerExist?.length > 0 &&
|
||||||
checkPlaceHolder.length > 0 &&
|
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
||||||
!data.IsCompleted
|
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
||||||
) {
|
) {
|
||||||
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
|
|
||||||
}
|
}
|
||||||
//checking document is draft and signyourself type then user can sign document
|
};
|
||||||
else {
|
|
||||||
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
|
const handleMenuItemClick = (selectType, data) => {
|
||||||
// navigate(`/signaturePdf/${data.objectId}`);
|
switch (selectType) {
|
||||||
// window.location.hash = `/signaturePdf/${data.objectId}`;
|
case "Download": {
|
||||||
|
const pdfName = data && data.Name;
|
||||||
|
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
|
||||||
|
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Rename": {
|
||||||
|
setRenameValue(data.Name);
|
||||||
|
setRename(data.objectId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Delete": {
|
||||||
|
setIsDeleteDoc(true);
|
||||||
|
setSelectDoc(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Move": {
|
||||||
|
handleMoveDocument(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//function for delete document
|
||||||
|
const handleDeleteDocument = async (docData) => {
|
||||||
|
setIsDeleteDoc(false);
|
||||||
|
const docId = docData.objectId;
|
||||||
|
const data = {
|
||||||
|
IsArchive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
await axios
|
||||||
|
.put(
|
||||||
|
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
||||||
|
"_appName"
|
||||||
|
)}_Document/${docId}`,
|
||||||
|
data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((result) => {
|
||||||
|
const res = result.data;
|
||||||
|
if (res) {
|
||||||
|
const updatedData = pdfData.filter((x) => x.objectId !== docId);
|
||||||
|
setPdfData(updatedData);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Err ", err);
|
||||||
|
setIsAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "something went wrong"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleMoveDocument = async (docData) => {
|
||||||
|
setIsOpenMoveModal(true);
|
||||||
|
setSelectDoc(docData);
|
||||||
|
};
|
||||||
|
//function for move document from one folder to another folder
|
||||||
|
const handleMoveFolder = async (selectFolderData) => {
|
||||||
|
const selecFolderId = selectDoc?.Folder?.objectId;
|
||||||
|
const moveFolderId = selectFolderData?.ObjectId;
|
||||||
|
let updateDocId = selectDoc?.objectId;
|
||||||
|
let updateData;
|
||||||
|
const checkExist = moveFolderId
|
||||||
|
? selecFolderId === moveFolderId
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
: selecFolderId
|
||||||
|
? false
|
||||||
|
: true;
|
||||||
|
if (!checkExist) {
|
||||||
|
if (moveFolderId) {
|
||||||
|
updateData = {
|
||||||
|
Folder: {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: `${localStorage.getItem("_appName")}_Document`,
|
||||||
|
objectId: moveFolderId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
updateData = {
|
||||||
|
Folder: { __op: "Delete" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios
|
||||||
|
.put(
|
||||||
|
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
||||||
|
"_appName"
|
||||||
|
)}_Document/${updateDocId}`,
|
||||||
|
updateData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
.then((Listdata) => {
|
||||||
|
// console.log("Listdata ", Listdata);
|
||||||
|
const res = Listdata.data;
|
||||||
|
if (res) {
|
||||||
|
const updatedData = pdfData.filter(
|
||||||
|
(x) => x.objectId !== updateDocId
|
||||||
|
);
|
||||||
|
setPdfData(updatedData);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("err", err);
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsOpenMoveModal(false);
|
||||||
|
} else {
|
||||||
|
alert("folder already exist!");
|
||||||
|
setIsOpenMoveModal(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sanitizeFileName = (pdfName) => {
|
||||||
|
// Replace spaces with underscore
|
||||||
|
return pdfName.replace(/ /g, "_");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnterPress = (e, data) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
handledRenameDoc(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//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) => {
|
||||||
// console.log("data", data);
|
let createddate, status, isDecline, signerExist, isComplete, isPlaceholder;
|
||||||
let createddate,
|
|
||||||
status,
|
|
||||||
isDecline,
|
|
||||||
signerExist,
|
|
||||||
isExpire,
|
|
||||||
isComplete,
|
|
||||||
signUrl,
|
|
||||||
isPlaceholder;
|
|
||||||
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;
|
||||||
@@ -183,67 +301,58 @@ function PdfFileComponent({
|
|||||||
isDecline = data.IsDeclined && data.IsDeclined;
|
isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
isPlaceholder = data.Placeholders && data.Placeholders;
|
isPlaceholder = data.Placeholders && data.Placeholders;
|
||||||
signerExist = data.Signers && data.Signers;
|
signerExist = data.Signers && data.Signers;
|
||||||
signUrl = data.SignedUrl && data.SignedUrl;
|
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();
|
||||||
|
let isExpire = false;
|
||||||
if (currDate > expireUpdateDate) {
|
if (currDate > expireUpdateDate) {
|
||||||
isExpire = true;
|
isExpire = true;
|
||||||
} else {
|
|
||||||
isExpire = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComplete) {
|
if (isComplete) {
|
||||||
status = "Completed";
|
status = "Completed";
|
||||||
} else if (isDecline) {
|
} else if (isDecline) {
|
||||||
status = "Declined";
|
status = "Declined";
|
||||||
} else if (isExpire && !isPlaceholder && signerExist) {
|
} else if (!signerExist || signerExist?.length === 0) {
|
||||||
// status = "Expired";
|
|
||||||
status = "Draft";
|
status = "Draft";
|
||||||
} else if (isExpire && !isPlaceholder && !signerExist && !signUrl) {
|
} else if (
|
||||||
// status = "Expired";
|
signerExist?.length > 0 &&
|
||||||
|
(!isPlaceholder || isPlaceholder?.length === 0)
|
||||||
|
) {
|
||||||
|
status = "Draft";
|
||||||
|
} else if (
|
||||||
|
signerExist?.length > 0 &&
|
||||||
|
isPlaceholder?.length > 0 &&
|
||||||
|
!signedUrl
|
||||||
|
) {
|
||||||
status = "Draft";
|
status = "Draft";
|
||||||
} else if (isExpire) {
|
} else if (isExpire) {
|
||||||
status = "Expired";
|
status = "Expired";
|
||||||
} else if (!signUrl) {
|
|
||||||
status = "Draft";
|
|
||||||
} else {
|
} else {
|
||||||
status = "InComplete";
|
status = "In Progress";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDraftDoc = (data) => {
|
const signersName = () => {
|
||||||
window.location.hash = `/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie?${data.objectId}`;
|
const getSignersName = signerExist.map((data) => data.Name);
|
||||||
|
const signerName = getSignersName.join(",");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className="statusSpan"
|
||||||
|
style={{ width: "90%", wordWrap: "break-word" }}
|
||||||
|
>
|
||||||
|
{signerName}{" "}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuItemClick = (selectType, data) => {
|
|
||||||
// console.log("data",data)
|
|
||||||
if (selectType === "Download") {
|
|
||||||
// console.log("download")
|
|
||||||
const pdfName = data && data.Name;
|
|
||||||
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
|
|
||||||
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
|
||||||
} else if (selectType === "Rename") {
|
|
||||||
// console.log("rename")
|
|
||||||
setRenameValue(data.Name);
|
|
||||||
setRename(data.objectId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sanitizeFileName = (pdfName) => {
|
|
||||||
// Replace spaces with underscore
|
|
||||||
return pdfName.replace(/ /g, '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleEnterPress = (e, data) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
handledRenameDoc(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return listType === "table" ? (
|
return listType === "table" ? (
|
||||||
data.Type === "Folder" ? (
|
data.Type === "Folder" ? (
|
||||||
<tr onClick={() => handleOnclikFolder(data)}>
|
<tr onClick={() => handleOnclikFolder(data)}>
|
||||||
<td>
|
<td
|
||||||
|
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
|
||||||
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-folder"
|
className="fa fa-folder"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -259,26 +368,11 @@ function PdfFileComponent({
|
|||||||
<td>_</td>
|
<td>_</td>
|
||||||
<td>_</td>
|
<td>_</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : data.Type === "AIDoc" ? (
|
|
||||||
<tr onClick={() => handleDraftDoc(data)}>
|
|
||||||
<td>
|
|
||||||
<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
|
||||||
|
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
|
||||||
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-file-pdf"
|
className="fa fa-file-pdf"
|
||||||
style={{ color: "#ed4d0e", marginRight: "8px", fontSize: "26px" }}
|
style={{ color: "#ed4d0e", marginRight: "8px", fontSize: "26px" }}
|
||||||
@@ -312,7 +406,7 @@ function PdfFileComponent({
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
cursor: "pointer",
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
@@ -333,7 +427,6 @@ function PdfFileComponent({
|
|||||||
}}
|
}}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
type="text"
|
type="text"
|
||||||
// onFocus={()=>console.log("focus")}
|
|
||||||
onBlur={() => handledRenameDoc(data)}
|
onBlur={() => handledRenameDoc(data)}
|
||||||
onKeyDown={(e) => handleEnterPress(e, data)}
|
onKeyDown={(e) => handleEnterPress(e, data)}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
@@ -344,7 +437,7 @@ function PdfFileComponent({
|
|||||||
width: "100px",
|
width: "100px",
|
||||||
border: "1.5px solid black",
|
border: "1.5px solid black",
|
||||||
borderRadius: "2px",
|
borderRadius: "2px",
|
||||||
fontSize: "10px",
|
fontSize: "10px"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -359,99 +452,19 @@ function PdfFileComponent({
|
|||||||
sideOffset={5}
|
sideOffset={5}
|
||||||
align="end"
|
align="end"
|
||||||
>
|
>
|
||||||
{/* <ContextMenu.Item
|
|
||||||
onClick={() => handleMenuItemClick("Download", data)}
|
|
||||||
onSelect={(e) => console.log("event", e)}
|
|
||||||
className="ContextMenuItem"
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</ContextMenu.Item> */}
|
|
||||||
|
|
||||||
<ContextMenu.Item
|
<ContextMenu.Item
|
||||||
onClick={() => handleMenuItemClick("Rename", data)}
|
onClick={() => handleMenuItemClick("Rename", data)}
|
||||||
className="ContextMenuItem"
|
className="ContextMenuItem"
|
||||||
>
|
>
|
||||||
Rename
|
<i className="fa-solid fa-font"></i>
|
||||||
</ContextMenu.Item>
|
<span style={{ marginLeft: "8px" }}>Rename</span>
|
||||||
</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"
|
|
||||||
// onFocus={()=>console.log("focus")}
|
|
||||||
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("Download", data)}
|
|
||||||
onSelect={(e) => console.log("event", e)}
|
|
||||||
className="ContextMenuItem"
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</ContextMenu.Item> */}
|
|
||||||
|
|
||||||
<ContextMenu.Item
|
|
||||||
onClick={() => handleMenuItemClick("Rename", data)}
|
|
||||||
className="ContextMenuItem"
|
|
||||||
>
|
|
||||||
Rename
|
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
</ContextMenu.Content>
|
</ContextMenu.Content>
|
||||||
</ContextMenu.Portal>
|
</ContextMenu.Portal>
|
||||||
</ContextMenu.Root>
|
</ContextMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<HoverCard.Root>
|
<HoverCard.Root openDelay={0} closeDelay={100}>
|
||||||
<HoverCard.Trigger asChild>
|
<HoverCard.Trigger asChild>
|
||||||
<div>
|
<div>
|
||||||
<ContextMenu.Root>
|
<ContextMenu.Root>
|
||||||
@@ -484,7 +497,7 @@ function PdfFileComponent({
|
|||||||
width: "100px",
|
width: "100px",
|
||||||
border: "1.5px solid black",
|
border: "1.5px solid black",
|
||||||
borderRadius: "2px",
|
borderRadius: "2px",
|
||||||
fontSize: "10px",
|
fontSize: "10px"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -508,7 +521,7 @@ function PdfFileComponent({
|
|||||||
<i className="fa fa-file"></i>
|
<i className="fa fa-file"></i>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
status === "InComplete" && (
|
status === "In Progress" && (
|
||||||
<div className="status-badge in-progress">
|
<div className="status-badge in-progress">
|
||||||
<i className="fa fa-paper-plane"></i>
|
<i className="fa fa-paper-plane"></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -522,20 +535,18 @@ function PdfFileComponent({
|
|||||||
sideOffset={5}
|
sideOffset={5}
|
||||||
align="end"
|
align="end"
|
||||||
>
|
>
|
||||||
<ContextMenu.Item
|
{contextMenu.map((menu, ind) => {
|
||||||
onClick={() => handleMenuItemClick("Download", data)}
|
return (
|
||||||
onSelect={(e) => console.log("event", e)}
|
<ContextMenu.Item
|
||||||
className="ContextMenuItem"
|
key={ind}
|
||||||
>
|
onClick={() => handleMenuItemClick(menu.type, data)}
|
||||||
Download
|
className="ContextMenuItem"
|
||||||
</ContextMenu.Item>
|
>
|
||||||
|
<i className={menu.icon}></i>
|
||||||
<ContextMenu.Item
|
<span style={{ marginLeft: "8px" }}>{menu.type}</span>
|
||||||
onClick={() => handleMenuItemClick("Rename", data)}
|
</ContextMenu.Item>
|
||||||
className="ContextMenuItem"
|
);
|
||||||
>
|
})}
|
||||||
Rename
|
|
||||||
</ContextMenu.Item>
|
|
||||||
</ContextMenu.Content>
|
</ContextMenu.Content>
|
||||||
</ContextMenu.Portal>
|
</ContextMenu.Portal>
|
||||||
</ContextMenu.Root>
|
</ContextMenu.Root>
|
||||||
@@ -558,57 +569,111 @@ function PdfFileComponent({
|
|||||||
{signerExist && (
|
{signerExist && (
|
||||||
<>
|
<>
|
||||||
<strong style={{ fontSize: "13px" }}>Signers: </strong>
|
<strong style={{ fontSize: "13px" }}>Signers: </strong>
|
||||||
{signerExist.map((data, key) => {
|
{/* <span className="statusSpan">kjefjjnejkfnkbjs bbfjkdsbjbfjkbjk kscbjkbjkb</span> */}
|
||||||
return (
|
{signersName()}
|
||||||
<React.Fragment key={key}>
|
|
||||||
<span className="statusSpan">{data.Name}, </span>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<HoverCard.Arrow className="HoverCardArrow" />
|
<HoverCard.Arrow className="HoverCardArrow" />
|
||||||
</HoverCard.Content>
|
</HoverCard.Content>
|
||||||
</HoverCard.Portal>
|
</HoverCard.Portal>
|
||||||
</HoverCard.Root>
|
</HoverCard.Root>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
//component to handle type of document and render according to type
|
|
||||||
|
|
||||||
return isList ? (
|
//component to handle type of document and render according to type
|
||||||
<div className="container" style={{overflowX:"auto"}}>
|
return (
|
||||||
<Table striped bordered hover >
|
<>
|
||||||
<thead>
|
{isList ? (
|
||||||
<tr>
|
<div className="container" style={{ overflowX: "auto" }}>
|
||||||
<th>Name</th>
|
<Table striped bordered hover>
|
||||||
<th>Created Date</th>
|
<thead>
|
||||||
<th>Type</th>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Name</th>
|
||||||
<th>Action</th>
|
<th>Created Date</th>
|
||||||
</tr>
|
<th>Type</th>
|
||||||
</thead>
|
<th>Status</th>
|
||||||
<tbody>
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{pdfData.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{handleFolderData(data, ind, "table")}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="pdfContainer">
|
||||||
{pdfData.map((data, ind) => {
|
{pdfData.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<div className="box" key={ind}>
|
||||||
{handleFolderData(data, ind, "table")}
|
{handleFolderData(data, ind, "list")}
|
||||||
</React.Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</div>
|
||||||
</Table>
|
)}
|
||||||
</div>
|
{isOpenMoveModal && (
|
||||||
) : (
|
<SelectFolder
|
||||||
<div className="pdfContainer">
|
onSuccess={handleMoveFolder}
|
||||||
{pdfData.map((data, ind) => {
|
isOpenModal={isOpenMoveModal}
|
||||||
return (
|
folderCls={"contracts_Document"}
|
||||||
<div className="box" key={ind}>
|
setIsOpenMoveModal={setIsOpenMoveModal}
|
||||||
{handleFolderData(data, ind, "list")}
|
setPdfData={setPdfData}
|
||||||
</div>
|
/>
|
||||||
);
|
)}
|
||||||
})}
|
<ModalUi
|
||||||
</div>
|
isOpen={isDeleteDoc}
|
||||||
|
headerColor={themeColor}
|
||||||
|
title={"Delete Document"}
|
||||||
|
handleClose={() => {
|
||||||
|
setIsDeleteDoc(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
<p>Are you sure you want to delete this document?</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
handleDeleteDocument(selectDoc);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteDoc(false);
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfFileComponent;
|
export default DriveBody;
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
|
||||||
|
const AddRoleModal = (props) => {
|
||||||
|
return (
|
||||||
|
<ModalUi
|
||||||
|
title={"Add Role"}
|
||||||
|
isOpen={props.isModalRole}
|
||||||
|
handleClose={props.handleCloseRoleModal}
|
||||||
|
>
|
||||||
|
<div className="addusercontainer">
|
||||||
|
<form
|
||||||
|
style={{ display: "flex", flexDirection: "column" }}
|
||||||
|
onSubmit={props.handleAddRole}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
value={props.roleName}
|
||||||
|
onChange={(e) => props.setRoleName(e.target.value)}
|
||||||
|
placeholder={
|
||||||
|
props.signersdata.length > 0
|
||||||
|
? "User " + (props.signersdata.length + 1)
|
||||||
|
: "User 1"
|
||||||
|
}
|
||||||
|
className="addUserInput"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: "grey",
|
||||||
|
fontSize: 11,
|
||||||
|
margin: "10px 0 10px 5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
e.g: Hr, Director, Manager, New joinee, Accountant, etc...
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
style={{
|
||||||
|
background: "#00a2b7"
|
||||||
|
}}
|
||||||
|
className="finishBtn"
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={props.handleCloseRoleModal}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddRoleModal;
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
function BorderResize() {
|
function BorderResize({ right, top }) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="borderResize"
|
className="borderResize"
|
||||||
style={{
|
style={{
|
||||||
right: "-1px",
|
right: right ? right + "px" : "-1px",
|
||||||
bottom: "-1px",
|
bottom: top ? top + "px" : "-1px",
|
||||||
borderRight: "3px solid #188ae2",
|
borderRight: "3px solid #188ae2",
|
||||||
borderBottom: "3px solid #188ae2"
|
borderBottom: "3px solid #188ae2"
|
||||||
}}
|
}}
|
||||||
@@ -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 = () => {
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
||||||
|
const confirmToaddDefaultSign = () => {
|
||||||
|
if (xyPostion.length > 0) {
|
||||||
|
setDefaultSignAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage:
|
||||||
|
"Are you sure you want to auto sign at requested all locations?"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setDefaultSignAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "please select position!"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white",
|
||||||
|
padding: "5px",
|
||||||
|
fontFamily: "sans-serif",
|
||||||
|
marginTop: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Signature
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: "10px",
|
||||||
|
fontWeight: "600"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<p>Your Signature</p>
|
||||||
|
<div className="defaultSignBox">
|
||||||
|
<img
|
||||||
|
alt="default img"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
src={defaultSignImg}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white",
|
||||||
|
marginTop: "20px",
|
||||||
|
cursor: "pointer",
|
||||||
|
marginBottom: "10px"
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn finishnHover"
|
||||||
|
onClick={() => confirmToaddDefaultSign()}
|
||||||
|
>
|
||||||
|
Auto Sign All
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DefaultSignature;
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Loader from "../../primitives/LoaderWithMsg";
|
||||||
|
import { contractDocument } from "../../constant/Utils";
|
||||||
|
import HandleError from "../../primitives/HandleError";
|
||||||
|
function DraftDocument() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [isLoading, setIsLoading] = useState({
|
||||||
|
isLoader: true,
|
||||||
|
message: "This might take some time"
|
||||||
|
});
|
||||||
|
|
||||||
|
const rowLevel =
|
||||||
|
localStorage.getItem("rowlevel") &&
|
||||||
|
JSON.parse(localStorage.getItem("rowlevel"));
|
||||||
|
const docId =
|
||||||
|
rowLevel && rowLevel?.id
|
||||||
|
? rowLevel.id
|
||||||
|
: rowLevel?.objectId && rowLevel.objectId;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDocumentDetails();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
//get document details
|
||||||
|
const getDocumentDetails = async () => {
|
||||||
|
//getting document details
|
||||||
|
const documentData = await contractDocument(docId);
|
||||||
|
if (documentData && documentData.length > 0) {
|
||||||
|
handleDraftDoc(documentData);
|
||||||
|
} else if (
|
||||||
|
documentData === "Error: Something went wrong!" ||
|
||||||
|
(documentData.result && documentData.result.error)
|
||||||
|
) {
|
||||||
|
setIsLoading({
|
||||||
|
isLoader: false,
|
||||||
|
message: "Error: Something went wrong!"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setIsLoading({
|
||||||
|
isLoader: false,
|
||||||
|
message: "No data found!"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//check document type and render on signyour self and placeholder route
|
||||||
|
const handleDraftDoc = (documentData) => {
|
||||||
|
const data = documentData[0];
|
||||||
|
const signerExist = data.Signers && data.Signers;
|
||||||
|
const isDecline = data.IsDeclined && data.IsDeclined;
|
||||||
|
const isPlaceholder = data.Placeholders && data.Placeholders;
|
||||||
|
const signedUrl = data.SignedUrl;
|
||||||
|
//checking if document has completed and request signature flow
|
||||||
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
|
}
|
||||||
|
//checking if document has completed and signyour-self flow
|
||||||
|
else if (!signerExist && !isPlaceholder) {
|
||||||
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
|
}
|
||||||
|
//checking if document has declined by someone
|
||||||
|
else if (isDecline) {
|
||||||
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
|
//checking draft type document
|
||||||
|
} else if (
|
||||||
|
signerExist?.length > 0 &&
|
||||||
|
isPlaceholder?.length > 0 &&
|
||||||
|
!signedUrl
|
||||||
|
) {
|
||||||
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
|
}
|
||||||
|
//Inprogress document
|
||||||
|
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
|
||||||
|
navigate(`/pdfRequestFiles/${data.objectId}`);
|
||||||
|
} //placeholder draft document
|
||||||
|
else if (
|
||||||
|
(signerExist?.length > 0 &&
|
||||||
|
(!isPlaceholder || isPlaceholder?.length === 0)) ||
|
||||||
|
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
|
||||||
|
) {
|
||||||
|
navigate(`/placeHolderSign/${data.objectId}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{isLoading.isLoader ? (
|
||||||
|
<Loader isLoading={isLoading} />
|
||||||
|
) : (
|
||||||
|
<HandleError handleError={isLoading.message} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DraftDocument;
|
||||||
@@ -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,402 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
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 [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);
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
);
|
||||||
|
// props.setShowDropdown(false);
|
||||||
|
setDropdownOptionList(["option-1", "option-2"]);
|
||||||
|
setDropdownName(props.type);
|
||||||
|
// props.setCurrWidgetsDetails({});
|
||||||
|
setIsReadOnly(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 (
|
||||||
|
//props.showDropdown
|
||||||
|
<ModalUi
|
||||||
|
// styleClass={"dropdownModal"}
|
||||||
|
isOpen={props.showDropdown}
|
||||||
|
title={props.title}
|
||||||
|
closeOff={true}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSaveOption();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="dropdownContainer">
|
||||||
|
{["checkbox", "radio"].includes(props.type) &&
|
||||||
|
!props.isSignYourself && (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isReadOnly}
|
||||||
|
onChange={(e) => {
|
||||||
|
setIsReadOnly(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label style={{ marginLeft: "10px" }}>Is read only</label>
|
||||||
|
</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"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{props.type === "checkbox" && !props.isSignYourself && (
|
||||||
|
<>
|
||||||
|
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
||||||
|
Minimun check
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={0}
|
||||||
|
value={minCount}
|
||||||
|
onChange={(e) => {
|
||||||
|
const count = handleSetMinMax(e);
|
||||||
|
setMinCount(count);
|
||||||
|
}}
|
||||||
|
className="drodown-input"
|
||||||
|
/>
|
||||||
|
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
||||||
|
Maximum check
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={0}
|
||||||
|
value={maxCount}
|
||||||
|
onChange={(e) => {
|
||||||
|
const count = handleSetMinMax(e);
|
||||||
|
setMaxCount(count);
|
||||||
|
}}
|
||||||
|
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>
|
||||||
|
{["dropdown", "radio"].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 !== "radio" && (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
// onClick={() => handleSaveOption()}
|
||||||
|
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;
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import "../../styles/AddUser.css";
|
||||||
|
// import SelectFolder from "../../premitives/SelectFolder";
|
||||||
|
|
||||||
|
const EditTemplate = ({ template, onSuccess }) => {
|
||||||
|
// const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
Name: template?.Name || "",
|
||||||
|
Note: template?.Note || "",
|
||||||
|
Description: template?.Description || "",
|
||||||
|
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false"
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleStrInput = (e) => {
|
||||||
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
// const handleFolder = (data) => {
|
||||||
|
// console.log("handleFolder ", data)
|
||||||
|
// setFolder(data);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Define a function to handle form submission
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const isChecked = formData.SendinOrder === "true" ? true : false;
|
||||||
|
const data = { ...formData, SendinOrder: isChecked };
|
||||||
|
onSuccess(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="addusercontainer">
|
||||||
|
<div className="form-wrapper">
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||||
|
File
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "0.5rem 0.75rem",
|
||||||
|
border: "1px solid #d1d5db",
|
||||||
|
borderRadius: "0.375rem",
|
||||||
|
fontSize: "0.75rem",
|
||||||
|
fontWeight: "700"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{template.URL?.split("/")?.pop()?.split("_")[1]}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||||
|
Name
|
||||||
|
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="Name"
|
||||||
|
value={formData.Name}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
required
|
||||||
|
className="addUserInput"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="Note" style={{ fontSize: 13 }}>
|
||||||
|
Note
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="Note"
|
||||||
|
id="Note"
|
||||||
|
value={formData.Note}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
className="addUserInput"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="Description" style={{ fontSize: 13 }}>
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="Description"
|
||||||
|
id="Description"
|
||||||
|
value={formData.Description}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
className="addUserInput"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-section">
|
||||||
|
<label style={{ fontSize: 13 }}>Send In Order</label>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
marginLeft: 8,
|
||||||
|
marginBottom: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
name="SendinOrder"
|
||||||
|
checked={formData.SendinOrder === "true"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: 12 }}>Yes</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
marginLeft: 8,
|
||||||
|
marginBottom: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="SendinOrder"
|
||||||
|
checked={formData.SendinOrder === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: 12 }}>No</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <SelectFolder onSuccess={handleFolder} folderCls={"contracts_Template"} /> */}
|
||||||
|
<div className="buttoncontainer">
|
||||||
|
<button type="submit" className="submitbutton">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditTemplate;
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { saveAs } from "file-saver";
|
||||||
|
import celebration from "../../assets/images/newCeleb.gif";
|
||||||
|
import axios from "axios";
|
||||||
|
import { getBase64FromUrl } from "../../constant/Utils";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import printModule from "print-js";
|
||||||
|
import loader from "../../assets/images/loader2.gif";
|
||||||
|
|
||||||
|
function EmailComponent({
|
||||||
|
isEmail,
|
||||||
|
pdfUrl,
|
||||||
|
isCeleb,
|
||||||
|
setIsEmail,
|
||||||
|
setSuccessEmail,
|
||||||
|
pdfName,
|
||||||
|
sender,
|
||||||
|
setIsAlert
|
||||||
|
}) {
|
||||||
|
const [emailList, setEmailList] = useState([]);
|
||||||
|
const [emailValue, setEmailValue] = useState();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
//function for send email
|
||||||
|
const sendEmail = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
let sendMail;
|
||||||
|
for (let i = 0; i < emailList.length; i++) {
|
||||||
|
try {
|
||||||
|
const imgPng =
|
||||||
|
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||||
|
|
||||||
|
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
||||||
|
const themeBGcolor = themeColor;
|
||||||
|
let params = {
|
||||||
|
pdfName: pdfName,
|
||||||
|
url: pdfUrl,
|
||||||
|
recipient: emailList[i],
|
||||||
|
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
||||||
|
from: sender.email,
|
||||||
|
html:
|
||||||
|
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=" +
|
||||||
|
imgPng +
|
||||||
|
" height='50' style='padding:20px,width:170px,height:40px'/> </div><div style='padding:2px;font-family:system-ui; background-color:" +
|
||||||
|
themeBGcolor +
|
||||||
|
";'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document Copy</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document <strong>" +
|
||||||
|
pdfName +
|
||||||
|
" </strong>is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
|
sender.email +
|
||||||
|
" directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||||
|
openSignUrl +
|
||||||
|
" target=_blank>here</a> </p></div></div></body></html>"
|
||||||
|
};
|
||||||
|
sendMail = await axios.post(url, params, { headers: headers });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error", error);
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsEmail(false);
|
||||||
|
setIsAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "something went wrong"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendMail && sendMail.data.result.status === "success") {
|
||||||
|
setSuccessEmail(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setSuccessEmail(false);
|
||||||
|
setIsEmail(false);
|
||||||
|
setEmailValue("");
|
||||||
|
setEmailList([]);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
} else if (sendMail && sendMail.data.result.status === "error") {
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsEmail(false);
|
||||||
|
setIsAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "something went wrong"
|
||||||
|
});
|
||||||
|
setEmailValue("");
|
||||||
|
setEmailList([]);
|
||||||
|
} else {
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsEmail(false);
|
||||||
|
setIsAlert({
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: "something went wrong"
|
||||||
|
});
|
||||||
|
setEmailValue("");
|
||||||
|
setEmailList([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for remove email
|
||||||
|
const removeChip = (index) => {
|
||||||
|
const updateEmailCount = emailList.filter((data, key) => key !== index);
|
||||||
|
setEmailList(updateEmailCount);
|
||||||
|
};
|
||||||
|
//function for get email value
|
||||||
|
const handleEmailValue = (e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setEmailValue(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for save email in array after press enter
|
||||||
|
const handleEnterPress = (e) => {
|
||||||
|
if (e.key === "Enter" && emailValue) {
|
||||||
|
setEmailList((prev) => [...prev, emailValue]);
|
||||||
|
setEmailValue("");
|
||||||
|
} else if (e === "add" && emailValue) {
|
||||||
|
setEmailList((prev) => [...prev, emailValue]);
|
||||||
|
setEmailValue("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function for print signed pdf
|
||||||
|
const handleToPrint = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const pdf = await getBase64FromUrl(pdfUrl);
|
||||||
|
const isAndroidDevice = navigator.userAgent.match(/Android/i);
|
||||||
|
const isAppleDevice =
|
||||||
|
(/iPad|iPhone|iPod/.test(navigator.platform) ||
|
||||||
|
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
|
||||||
|
!window.MSStream;
|
||||||
|
if (isAndroidDevice || isAppleDevice) {
|
||||||
|
const byteArray = Uint8Array.from(
|
||||||
|
atob(pdf)
|
||||||
|
.split("")
|
||||||
|
.map((char) => char.charCodeAt(0))
|
||||||
|
);
|
||||||
|
const blob = new Blob([byteArray], { type: "application/pdf" });
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
window.open(blobUrl, "_blank");
|
||||||
|
} else {
|
||||||
|
printModule({ printable: pdf, type: "pdf", base64: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//handle download signed pdf
|
||||||
|
const handleDownloadPdf = () => {
|
||||||
|
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sanitizeFileName = (pdfName) => {
|
||||||
|
// Replace spaces with underscore
|
||||||
|
return pdfName.replace(/ /g, "_");
|
||||||
|
};
|
||||||
|
|
||||||
|
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* isEmail */}
|
||||||
|
{isEmail && (
|
||||||
|
<div className="modaloverlay">
|
||||||
|
<div className="modalcontainer">
|
||||||
|
{isLoading && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
zIndex: "20",
|
||||||
|
backgroundColor: "#e6f2f2",
|
||||||
|
opacity: 0.8
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="no img"
|
||||||
|
src={loader}
|
||||||
|
style={{ width: "70px", height: "70px" }}
|
||||||
|
/>
|
||||||
|
<span style={{ fontSize: "12px", fontWeight: "bold" }}>
|
||||||
|
This might take some time
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ background: "#32a3ac" }} className="modalheader">
|
||||||
|
<span style={{ color: "white" }}>Successfully signed!</span>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
<div></div>
|
||||||
|
{!isAndroid && (
|
||||||
|
<button
|
||||||
|
onClick={handleToPrint}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
className="btn btn-primary btn-sm"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-print"
|
||||||
|
style={{
|
||||||
|
fontSize: "15px",
|
||||||
|
marginRight: "3px",
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
Print
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="btn btn-danger btn-sm"
|
||||||
|
onClick={() => handleDownloadPdf()}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginLeft: "10px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-download"
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
fontSize: "15px",
|
||||||
|
marginRight: "3px"
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
Download
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
{isCeleb && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
marginLeft: "50px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="print img"
|
||||||
|
width={300}
|
||||||
|
height={250}
|
||||||
|
// style={styles.gifCeleb}
|
||||||
|
src={celebration}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontFamily: "system-ui",
|
||||||
|
verticalAlign: "baseline",
|
||||||
|
fontWeight: "500",
|
||||||
|
color: "#403f3e",
|
||||||
|
fontSize: "15px",
|
||||||
|
marginBottom: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Recipients added here will get a copy of the signed document.
|
||||||
|
</p>
|
||||||
|
{emailList.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<div className="addEmail">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
|
||||||
|
flexWrap: "wrap"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{emailList.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="emailChip"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
key={ind}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
fontSize: "13px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: 600,
|
||||||
|
marginLeft: 7,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
onClick={() => removeChip(ind)}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-xmark"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{emailList.length <= 9 && (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={emailValue}
|
||||||
|
className="addEmailInput"
|
||||||
|
onChange={handleEmailValue}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
|
onBlur={() => {
|
||||||
|
if (emailValue) {
|
||||||
|
handleEnterPress("add");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={emailValue}
|
||||||
|
className="emailInput"
|
||||||
|
onChange={handleEmailValue}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
|
placeholder="Add the email addresses"
|
||||||
|
onBlur={() => {
|
||||||
|
if (emailValue) {
|
||||||
|
handleEnterPress("add");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
cursor: emailValue && "pointer"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (emailValue) {
|
||||||
|
handleEnterPress("add");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
style={{
|
||||||
|
backgroundColor: themeColor,
|
||||||
|
padding: "5px 7px",
|
||||||
|
marginTop: "10px",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "2px"
|
||||||
|
}}
|
||||||
|
className="fa fa-plus"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "#e3e2e1",
|
||||||
|
marginTop: "10px",
|
||||||
|
padding: "5px",
|
||||||
|
borderRadius: "3px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ fontWeight: "700" }}>Note:</span>
|
||||||
|
<span style={{ fontSize: "15px" }}>
|
||||||
|
{" "}
|
||||||
|
You can only send to ten recipients at a time.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
disabled={emailList.length === 0 && true}
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className={emailList.length === 0 ? "defaultBtn" : "finishBtn"}
|
||||||
|
onClick={() => sendEmail()}
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
onClick={() => {
|
||||||
|
setIsEmail(false);
|
||||||
|
setEmailValue("");
|
||||||
|
setEmailList([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmailComponent;
|
||||||
@@ -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,
|
||||||
@@ -34,8 +34,12 @@ function Header({
|
|||||||
dataTut4,
|
dataTut4,
|
||||||
alreadySign,
|
alreadySign,
|
||||||
isSignYourself,
|
isSignYourself,
|
||||||
setIsEmail
|
setIsEmail,
|
||||||
|
completeBtnTitle,
|
||||||
|
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");
|
||||||
@@ -117,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
|
||||||
@@ -127,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,
|
||||||
@@ -151,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
|
||||||
@@ -174,59 +171,34 @@ 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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div style={{ padding: "5px 0px 5px 0px" }} className="mobileHead">
|
||||||
style={{ padding: !isGuestSigner && "5px 0px 5px 0px" }}
|
|
||||||
className="mobileHead"
|
|
||||||
>
|
|
||||||
{isMobile && isShowHeader ? (
|
{isMobile && isShowHeader ? (
|
||||||
<div
|
<div
|
||||||
id="navbar"
|
id="navbar"
|
||||||
@@ -246,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>
|
||||||
@@ -284,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",
|
||||||
@@ -345,7 +317,7 @@ function Header({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="fa fa-envelope"
|
className="fa fa-envelope"
|
||||||
style={{ marginRight: "2px" }}
|
style={{ marginRight: "2px" }}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
@@ -408,27 +380,27 @@ function Header({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
color: isMailSend ? "gray" : themeColor(),
|
color: isMailSend ? "gray" : themeColor,
|
||||||
border: "none",
|
border: "none",
|
||||||
fontWeight: "650",
|
fontWeight: "650",
|
||||||
fontSize: "16px"
|
fontSize: "16px"
|
||||||
}}
|
}}
|
||||||
data-tut={dataTut4}
|
data-tut={dataTut4}
|
||||||
>
|
>
|
||||||
Send
|
{completeBtnTitle ? completeBtnTitle : "Send"}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
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"
|
||||||
@@ -454,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
|
||||||
@@ -522,7 +494,7 @@ function Header({
|
|||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -533,17 +505,17 @@ function Header({
|
|||||||
) : isPlaceholder ? (
|
) : isPlaceholder ? (
|
||||||
<>
|
<>
|
||||||
{!isMailSend &&
|
{!isMailSend &&
|
||||||
signersdata.Signers &&
|
signersdata.length > 0 &&
|
||||||
signersdata.Signers.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 all {signersdata.Signers.length - signerPos.length}{" "}
|
Add {signersdata.length - filterPrefill.length}{" "}
|
||||||
recipients signature
|
recipients signature
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
||||||
Add {signersdata.Signers.length - signerPos.length} more
|
Add {signersdata.length - filterPrefill.length} more
|
||||||
recipients signature
|
recipients signature
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -551,6 +523,18 @@ function Header({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
{setIsEditTemplate && (
|
||||||
|
<button
|
||||||
|
onClick={() => setIsEditTemplate(true)}
|
||||||
|
style={{
|
||||||
|
border: "none",
|
||||||
|
outline: "none",
|
||||||
|
textAlign: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-gear fa-lg"></i>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
@@ -573,7 +557,7 @@ function Header({
|
|||||||
}}
|
}}
|
||||||
className={isMailSend ? "sendMail" : "sendMail sendHover"}
|
className={isMailSend ? "sendMail" : "sendMail sendHover"}
|
||||||
>
|
>
|
||||||
Send
|
{completeBtnTitle ? completeBtnTitle : "Send"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -656,7 +640,7 @@ function Header({
|
|||||||
type="button"
|
type="button"
|
||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Finish
|
Finish
|
||||||
@@ -723,7 +707,7 @@ function Header({
|
|||||||
onClick={() => setIsEmail(true)}
|
onClick={() => setIsEmail(true)}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="fa fa-envelope"
|
className="fa fa-envelope"
|
||||||
style={{
|
style={{
|
||||||
color: "white",
|
color: "white",
|
||||||
fontSize: "15px",
|
fontSize: "15px",
|
||||||
@@ -754,7 +738,7 @@ function Header({
|
|||||||
className="finishBtn sendHover"
|
className="finishBtn sendHover"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedImages();
|
embedWidgetsData();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -0,0 +1,653 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import BorderResize from "./BorderResize";
|
||||||
|
import PlaceholderBorder from "./PlaceholderBorder";
|
||||||
|
import { Rnd } from "react-rnd";
|
||||||
|
import { defaultWidthHeight, isMobile } from "../../constant/Utils";
|
||||||
|
import PlaceholderType from "./PlaceholderType";
|
||||||
|
import moment from "moment";
|
||||||
|
import "../../styles/opensigndrive.css";
|
||||||
|
|
||||||
|
function Placeholder(props) {
|
||||||
|
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
|
||||||
|
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
|
||||||
|
const [selectDate, setSelectDate] = useState();
|
||||||
|
const [dateFormat, setDateFormat] = useState([]);
|
||||||
|
const [saveDateFormat, setSaveDateFormat] = useState("");
|
||||||
|
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"
|
||||||
|
];
|
||||||
|
|
||||||
|
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 "dd/MM/yyyy";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//set default current date and default format MM/dd/yyyy
|
||||||
|
if (props.isSignYourself) {
|
||||||
|
const date = new Date();
|
||||||
|
const milliseconds = date.getTime();
|
||||||
|
const newDate = moment(milliseconds).format("MM/DD/YYYY");
|
||||||
|
const dateObj = {
|
||||||
|
date: newDate,
|
||||||
|
format: "MM/dd/YYYY"
|
||||||
|
};
|
||||||
|
setSelectDate(dateObj);
|
||||||
|
} else {
|
||||||
|
const defaultRes = props?.pos?.options?.response;
|
||||||
|
const defaultFormat = props.pos?.options?.validation?.format;
|
||||||
|
const updateDate = defaultRes
|
||||||
|
? new Date(props?.pos?.options?.response)
|
||||||
|
: new Date();
|
||||||
|
const dateFormat = defaultFormat ? defaultFormat : "MM/DD/YYYY";
|
||||||
|
const milliseconds = updateDate.getTime();
|
||||||
|
const newDate = moment(milliseconds).format(dateFormat);
|
||||||
|
const dateObj = {
|
||||||
|
date: newDate,
|
||||||
|
format: props.pos?.options?.validation?.format
|
||||||
|
? props.pos?.options?.validation?.format
|
||||||
|
: "MM/dd/YYYY"
|
||||||
|
};
|
||||||
|
setSelectDate(dateObj);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
//function for add selected date and format in selectFormat
|
||||||
|
const changeDateFormat = () => {
|
||||||
|
const updateDate = [];
|
||||||
|
dateFormatArr.map((data) => {
|
||||||
|
let date;
|
||||||
|
if (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]);
|
||||||
|
//handle to close drop down menu onclick screen
|
||||||
|
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]);
|
||||||
|
|
||||||
|
//onclick placeholder function to open signature pad
|
||||||
|
const handlePlaceholderClick = () => {
|
||||||
|
if (props.setSelectWidgetId) {
|
||||||
|
props.setSelectWidgetId(props.pos.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const widgetTypeExist = [
|
||||||
|
"text",
|
||||||
|
"checkbox",
|
||||||
|
"name",
|
||||||
|
"company",
|
||||||
|
"job title",
|
||||||
|
"date",
|
||||||
|
"email"
|
||||||
|
].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 !== "label"
|
||||||
|
) {
|
||||||
|
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 handleWidgetsOnclick = () => {
|
||||||
|
if (props.pos.type === "radio") {
|
||||||
|
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.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
props.setWidgetType(props.pos.type);
|
||||||
|
props.setCurrWidgetsDetails(props.pos);
|
||||||
|
};
|
||||||
|
const PlaceholderIcon = () => {
|
||||||
|
return (
|
||||||
|
props.isShowBorder && (
|
||||||
|
<>
|
||||||
|
{(props.isPlaceholder || props.isSignYourself) && (
|
||||||
|
<>
|
||||||
|
{props.pos.type === "checkbox" && props.isSignYourself ? (
|
||||||
|
<i
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleWidgetsOnclick();
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleWidgetsOnclick();
|
||||||
|
}}
|
||||||
|
className="fa-solid fa-gear settingIcon"
|
||||||
|
style={{
|
||||||
|
color: "#188ae2",
|
||||||
|
right: "9px",
|
||||||
|
top: "-28px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
) : (
|
||||||
|
props.pos.type !== "date" &&
|
||||||
|
props.pos.type !== "label" &&
|
||||||
|
props.pos.type !== "signature" &&
|
||||||
|
!props.isSignYourself && (
|
||||||
|
<i
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleWidgetsOnclick();
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleWidgetsOnclick();
|
||||||
|
}}
|
||||||
|
className="fa-solid fa-gear settingIcon"
|
||||||
|
style={{
|
||||||
|
color: "#188ae2",
|
||||||
|
right: ["checkbox", "radio"].includes(props.pos.type)
|
||||||
|
? "24px"
|
||||||
|
: "47px",
|
||||||
|
top: ["checkbox", "radio"].includes(props.pos.type)
|
||||||
|
? "-28px"
|
||||||
|
: "-19px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
|
||||||
|
{props.pos.type !== "label" && !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:
|
||||||
|
props.pos.type === "checkbox" ||
|
||||||
|
props.pos.type === "radio"
|
||||||
|
? "8px"
|
||||||
|
: "32px",
|
||||||
|
top:
|
||||||
|
props.pos.type === "checkbox" ||
|
||||||
|
props.pos.type === "radio"
|
||||||
|
? "-28px"
|
||||||
|
: "-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);
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setIsShowDateFormat(!isShowDateFormat);
|
||||||
|
setSelectDate(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) => {
|
||||||
|
if (props.data) {
|
||||||
|
props.setSignerObjId(props.data.signerObjId);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
e.stopPropagation();
|
||||||
|
props.setIsPageCopy(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
}}
|
||||||
|
onTouchEnd={(e) => {
|
||||||
|
if (props.data) {
|
||||||
|
props.setSignerObjId(props.data.signerObjId);
|
||||||
|
props.setUniqueId(props.data.Id);
|
||||||
|
}
|
||||||
|
e.stopPropagation();
|
||||||
|
props.setIsPageCopy(true);
|
||||||
|
props.setSignKey(props.pos.key);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color: "#188ae2",
|
||||||
|
right:
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? "-9px"
|
||||||
|
: "12px",
|
||||||
|
top:
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? "-28px"
|
||||||
|
: "-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:
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? "-27px"
|
||||||
|
: "-8px",
|
||||||
|
top:
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? "-28px"
|
||||||
|
: "-18px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Rnd
|
||||||
|
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
||||||
|
//ref={nodeRef}
|
||||||
|
key={props.pos.key}
|
||||||
|
lockAspectRatio={
|
||||||
|
props.pos.type !== "label" &&
|
||||||
|
(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 !== "radio"
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
: props.pos.type !== "radio" &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId &&
|
||||||
|
true,
|
||||||
|
bottomLeft: false,
|
||||||
|
topLeft: false
|
||||||
|
}}
|
||||||
|
bounds="parent"
|
||||||
|
className="signYourselfBlock"
|
||||||
|
style={{
|
||||||
|
border: props.pos.type !== "checkbox" && "1px solid #007bff",
|
||||||
|
borderRadius: props.pos.type !== "checkbox" && "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"
|
||||||
|
? "99"
|
||||||
|
: props?.pos?.zIndex
|
||||||
|
? props.pos.zIndex
|
||||||
|
: "5",
|
||||||
|
background: props.data
|
||||||
|
? props.data.blockColor
|
||||||
|
: props.pos.type !== "checkbox" && "rgb(203 233 237)"
|
||||||
|
}}
|
||||||
|
onDrag={() => {
|
||||||
|
setDraggingEnabled(true);
|
||||||
|
props.handleTabDrag && props.handleTabDrag(props.pos.key);
|
||||||
|
}}
|
||||||
|
size={{
|
||||||
|
width: props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
height: 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 && props.pos.type !== "date"
|
||||||
|
? 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={() => {
|
||||||
|
!props.isNeedSign && props.setWidgetType(props.pos.type);
|
||||||
|
props.isNeedSign && props.data?.signerObjId === props.signerObjId
|
||||||
|
? handlePlaceholderClick()
|
||||||
|
: props.isPlaceholder
|
||||||
|
? handlePlaceholderClick()
|
||||||
|
: props.isSignYourself && handlePlaceholderClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.isShowBorder &&
|
||||||
|
props.pos.type !== "radio" &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId ? (
|
||||||
|
<BorderResize
|
||||||
|
right={
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? -21
|
||||||
|
: -12
|
||||||
|
}
|
||||||
|
top={
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? -21
|
||||||
|
: -11
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
||||||
|
props.data?.signerObjId === props.signerObjId &&
|
||||||
|
props.pos.type !== "radio" &&
|
||||||
|
props.pos.type !== "checkbox" ? (
|
||||||
|
<BorderResize />
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
props.pos.type !== "radio" &&
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isMobile ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
left: props.xPos(props.pos, props.isSignYourself),
|
||||||
|
top: props.yPos(props.pos, props.isSignYourself),
|
||||||
|
width: props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
// height: props.posHeight(props.pos, props.isSignYourself),
|
||||||
|
zIndex: "10"
|
||||||
|
}}
|
||||||
|
onTouchEnd={() => {
|
||||||
|
!props.isNeedSign && props.setWidgetType(props.pos.type);
|
||||||
|
props.isNeedSign && props.data?.signerObjId === props.signerObjId
|
||||||
|
? handlePlaceholderClick()
|
||||||
|
: props.isPlaceholder
|
||||||
|
? handlePlaceholderClick()
|
||||||
|
: props.isSignYourself && handlePlaceholderClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{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}
|
||||||
|
setSaveDateFormat={setSaveDateFormat}
|
||||||
|
saveDateFormat={saveDateFormat}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
/>
|
||||||
|
</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}
|
||||||
|
setSaveDateFormat={setSaveDateFormat}
|
||||||
|
saveDateFormat={saveDateFormat}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Rnd>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Placeholder;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import {
|
||||||
|
defaultWidthHeight,
|
||||||
|
resizeBorderExtraWidth
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
function PlaceholderBorder(props) {
|
||||||
|
const getResizeBorderExtraWidth =
|
||||||
|
props.pos.type === "checkbox" || props.pos.type === "radio"
|
||||||
|
? 38
|
||||||
|
: resizeBorderExtraWidth();
|
||||||
|
const defaultWidth = defaultWidthHeight(props.pos.type).width;
|
||||||
|
const defaultHeight = defaultWidthHeight(props.pos.type).height;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onMouseEnter={props?.setDraggingEnabled(true)}
|
||||||
|
className="borderResize"
|
||||||
|
style={{
|
||||||
|
borderColor: themeColor,
|
||||||
|
borderStyle: "dashed",
|
||||||
|
|
||||||
|
width: props.pos.Width
|
||||||
|
? props.pos.Width + getResizeBorderExtraWidth
|
||||||
|
: defaultWidth + getResizeBorderExtraWidth,
|
||||||
|
height: props.pos.Height
|
||||||
|
? props.pos.Height + getResizeBorderExtraWidth
|
||||||
|
: defaultHeight + getResizeBorderExtraWidth,
|
||||||
|
borderWidth: "0.2px",
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaceholderBorder;
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { randomId } from "../../constant/Utils";
|
||||||
|
|
||||||
|
function PlaceholderCopy(props) {
|
||||||
|
const copyType = ["All pages", "All pages but last", "All pages but first"];
|
||||||
|
const [selectCopyType, setSelectCopyType] = useState("");
|
||||||
|
|
||||||
|
//function for get copy placeholder position
|
||||||
|
const getCopyPlaceholderPosition = (
|
||||||
|
type,
|
||||||
|
currentPlaceholder,
|
||||||
|
newPageNumber,
|
||||||
|
existPlaceholderPosition
|
||||||
|
) => {
|
||||||
|
const filterPosition =
|
||||||
|
existPlaceholderPosition &&
|
||||||
|
existPlaceholderPosition.filter(
|
||||||
|
(data) => data.xPosition !== currentPlaceholder.xPosition
|
||||||
|
);
|
||||||
|
//copy all page placeholder at requested position except first page
|
||||||
|
if (newPageNumber === 1 && type === "first") {
|
||||||
|
if (filterPosition && filterPosition.length > 0) {
|
||||||
|
return {
|
||||||
|
pageNumber: newPageNumber,
|
||||||
|
pos: [...filterPosition]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//copy all page placeholder at requested position except last page
|
||||||
|
else if (newPageNumber === props.allPages && type === "last") {
|
||||||
|
if (existPlaceholderPosition) {
|
||||||
|
return {
|
||||||
|
pageNumber: newPageNumber,
|
||||||
|
pos: [...filterPosition]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//copy all page placeholder at requested position with existing placeholder position
|
||||||
|
else if (existPlaceholderPosition) {
|
||||||
|
return {
|
||||||
|
pageNumber: newPageNumber,
|
||||||
|
pos: [...filterPosition, currentPlaceholder]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//copy all page placeholder at requested position
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
pageNumber: newPageNumber,
|
||||||
|
pos: [currentPlaceholder]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for copy placeholder as per select copy type
|
||||||
|
const copyPlaceholder = (type) => {
|
||||||
|
let newPlaceholderPosition = [];
|
||||||
|
let newPageNumber = 1;
|
||||||
|
const signerPosition = props.xyPostion;
|
||||||
|
const signerId = props.signerObjId ? props.signerObjId : props.Id;
|
||||||
|
|
||||||
|
//handle placeholder array and copy for multiple signers placeholder at requested location
|
||||||
|
if (signerId) {
|
||||||
|
//get current signers data
|
||||||
|
let filterSignerPosition;
|
||||||
|
if (props?.signerObjId) {
|
||||||
|
filterSignerPosition = signerPosition.filter(
|
||||||
|
(data) => data.signerObjId === signerId
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
filterSignerPosition = signerPosition.filter(
|
||||||
|
(item) => item.Id === signerId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//get current pagenumber's all placeholder position data
|
||||||
|
const placeholderPosition = filterSignerPosition[0].placeHolder.filter(
|
||||||
|
(data) => data.pageNumber === props.pageNumber
|
||||||
|
);
|
||||||
|
//get current placeholder position data which user want to copy
|
||||||
|
const currentPlaceholder = placeholderPosition[0].pos.find(
|
||||||
|
(position) => position.key === props.signKey
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let i = 0; i < props.allPages; i++) {
|
||||||
|
const newId = randomId();
|
||||||
|
currentPlaceholder.key = newId;
|
||||||
|
//get exist placeholder position for particular page
|
||||||
|
const existPlaceholder = filterSignerPosition[0].placeHolder.filter(
|
||||||
|
(data) => data.pageNumber === newPageNumber
|
||||||
|
);
|
||||||
|
const existPlaceholderPosition =
|
||||||
|
existPlaceholder[0] && existPlaceholder[0].pos;
|
||||||
|
|
||||||
|
//function for get copy to requested location of placeholder position
|
||||||
|
const getPlaceholderObj = getCopyPlaceholderPosition(
|
||||||
|
type,
|
||||||
|
currentPlaceholder,
|
||||||
|
newPageNumber,
|
||||||
|
existPlaceholderPosition
|
||||||
|
);
|
||||||
|
if (getPlaceholderObj) {
|
||||||
|
newPlaceholderPosition.push(getPlaceholderObj);
|
||||||
|
}
|
||||||
|
newPageNumber++;
|
||||||
|
}
|
||||||
|
let updatedSignerPlaceholder;
|
||||||
|
if (props?.signerObjId) {
|
||||||
|
updatedSignerPlaceholder = signerPosition.map((signersData) => {
|
||||||
|
if (signersData.signerObjId === props.signerObjId) {
|
||||||
|
return {
|
||||||
|
...signersData,
|
||||||
|
placeHolder: newPlaceholderPosition
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return signersData;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
updatedSignerPlaceholder = signerPosition.map((signersData) => {
|
||||||
|
if (signersData.Id === props.Id) {
|
||||||
|
return {
|
||||||
|
...signersData,
|
||||||
|
placeHolder: newPlaceholderPosition
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return signersData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const signersData = signerPosition;
|
||||||
|
signersData.splice(0, signerPosition.length, ...updatedSignerPlaceholder);
|
||||||
|
props.setXyPostion(signersData);
|
||||||
|
}
|
||||||
|
//handle signyourself array and copy for single signers placeholder at requested location
|
||||||
|
else {
|
||||||
|
const xyPostion = props.xyPostion;
|
||||||
|
|
||||||
|
const placeholderPosition = xyPostion.filter(
|
||||||
|
(data) => data.pageNumber === props.pageNumber
|
||||||
|
);
|
||||||
|
//get current placeholder position data which user want to copy
|
||||||
|
const currentPlaceholder = placeholderPosition[0].pos.find(
|
||||||
|
(pos) => pos.key === props.signKey
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let i = 0; i < props.allPages; i++) {
|
||||||
|
//get exist placeholder position for particular page
|
||||||
|
const existPlaceholder = xyPostion.filter(
|
||||||
|
(data) => data.pageNumber === newPageNumber
|
||||||
|
);
|
||||||
|
const existPlaceholderPosition =
|
||||||
|
existPlaceholder[0] && existPlaceholder[0].pos;
|
||||||
|
|
||||||
|
const newId = randomId();
|
||||||
|
currentPlaceholder.key = newId;
|
||||||
|
//function for get copy to requested location of placeholder position
|
||||||
|
const getPlaceholderObj = getCopyPlaceholderPosition(
|
||||||
|
type,
|
||||||
|
currentPlaceholder,
|
||||||
|
newPageNumber,
|
||||||
|
existPlaceholderPosition
|
||||||
|
);
|
||||||
|
if (getPlaceholderObj) {
|
||||||
|
newPlaceholderPosition.push(getPlaceholderObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
newPageNumber++;
|
||||||
|
}
|
||||||
|
props.setXyPostion(newPlaceholderPosition);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for getting selected type placeholder copy
|
||||||
|
const handleApplyCopy = () => {
|
||||||
|
if (selectCopyType === "All pages") {
|
||||||
|
copyPlaceholder("all");
|
||||||
|
} else if (selectCopyType === "All pages but last") {
|
||||||
|
copyPlaceholder("last");
|
||||||
|
} else if (selectCopyType === "All pages but first") {
|
||||||
|
copyPlaceholder("first");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalUi
|
||||||
|
isOpen={props.isPageCopy}
|
||||||
|
title={"Copy to all pages"}
|
||||||
|
handleClose={() => {
|
||||||
|
props.setIsPageCopy(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
{copyType.map((data, key) => {
|
||||||
|
return (
|
||||||
|
<div key={key} style={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<label key={key} style={{ fontSize: "16px", fontWeight: "500" }}>
|
||||||
|
<input
|
||||||
|
style={{ accentColor: "red", marginRight: "10px" }}
|
||||||
|
type="radio"
|
||||||
|
value={data}
|
||||||
|
onChange={() => setSelectCopyType(data)}
|
||||||
|
checked={selectCopyType === data}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{data}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
handleApplyCopy();
|
||||||
|
props.setIsPageCopy(false);
|
||||||
|
}}
|
||||||
|
style={{ background: themeColor }}
|
||||||
|
type="button"
|
||||||
|
disabled={!selectCopyType}
|
||||||
|
className="finishBtn"
|
||||||
|
>
|
||||||
|
Apply
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
onClick={() => props.setIsPageCopy(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaceholderCopy;
|
||||||
@@ -0,0 +1,805 @@
|
|||||||
|
import React, { useEffect, useState, forwardRef, useRef } from "react";
|
||||||
|
import { getMonth, getYear, onChangeInput, range } 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(
|
||||||
|
props.pos?.options?.defaultValue ? props.pos?.options?.defaultValue : ""
|
||||||
|
);
|
||||||
|
const [startDate, setStartDate] = useState(new Date());
|
||||||
|
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 "text":
|
||||||
|
setValidatePlaceholder("enter text");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setValidatePlaceholder("enter text");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isNeedSign && type === "date") {
|
||||||
|
const updateDate = new Date();
|
||||||
|
setStartDate(updateDate);
|
||||||
|
} else 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?.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?.options?.defaultValue]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type && type === "date") {
|
||||||
|
if (props.selectDate) {
|
||||||
|
let updateDate;
|
||||||
|
if (props.selectDate.format === "dd-MM-yyyy") {
|
||||||
|
const [day, month, year] = props.saveDateFormat.split("-");
|
||||||
|
updateDate = new Date(`${year}-${month}-${day}`);
|
||||||
|
} else {
|
||||||
|
if (props?.saveDateFormat) {
|
||||||
|
updateDate = new Date(props.saveDateFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const updateDate = new Date(props.saveDateFormat);
|
||||||
|
setStartDate(updateDate);
|
||||||
|
const dateObj = {
|
||||||
|
date: props.saveDateFormat,
|
||||||
|
format: props.selectDate
|
||||||
|
? props.selectDate?.format
|
||||||
|
: props.pos?.options?.validation?.format
|
||||||
|
? props.pos?.options?.validation?.format
|
||||||
|
: "MM/dd/YYYY"
|
||||||
|
};
|
||||||
|
props.setSelectDate(dateObj);
|
||||||
|
onChangeInput(
|
||||||
|
props.saveDateFormat,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data.Id,
|
||||||
|
false,
|
||||||
|
props.selectDate?.format
|
||||||
|
? props.selectDate.format
|
||||||
|
: props.pos?.options?.validation?.format
|
||||||
|
? props.pos?.options?.validation?.format
|
||||||
|
: "MM/dd/YYYY"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.saveDateFormat]);
|
||||||
|
|
||||||
|
const dateValue = (value) => {
|
||||||
|
props.setSaveDateFormat(value);
|
||||||
|
return <span>{value}</span>;
|
||||||
|
};
|
||||||
|
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
||||||
|
<div
|
||||||
|
className="inputPlaceholder"
|
||||||
|
style={{ overflow: "hidden", fontSize: calculateFontSize() }}
|
||||||
|
onClick={onClick}
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
{dateValue(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
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "signature":
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
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"
|
||||||
|
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 (
|
||||||
|
<input
|
||||||
|
key={ind}
|
||||||
|
style={{
|
||||||
|
width: props.pos.Width,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginBottom: "6px",
|
||||||
|
marginTop: "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);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "text":
|
||||||
|
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"
|
||||||
|
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.isNeedSign && props.data?.signerObjId !== props.signerObjId
|
||||||
|
}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
closeOnScroll={true}
|
||||||
|
className="inputPlaceholder"
|
||||||
|
style={{ outlineColor: "#007bff" }}
|
||||||
|
selected={
|
||||||
|
startDate
|
||||||
|
? startDate
|
||||||
|
: props.pos.options?.response &&
|
||||||
|
new Date(props.pos.options.response)
|
||||||
|
}
|
||||||
|
onChange={(date) => {
|
||||||
|
setStartDate(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"
|
||||||
|
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 "radio":
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{props.pos.options?.values.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
key={ind}
|
||||||
|
style={{
|
||||||
|
width: props.pos.Width,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginBottom: "6px",
|
||||||
|
marginTop: "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);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "label":
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
placeholder="Enter label"
|
||||||
|
rows={1}
|
||||||
|
onChange={(e) => {
|
||||||
|
onChangeInput(
|
||||||
|
e.target.value,
|
||||||
|
props.pos.key,
|
||||||
|
props.xyPostion,
|
||||||
|
props.index,
|
||||||
|
props.setXyPostion,
|
||||||
|
props.data && props.data?.Id,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
className="labelTextArea"
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return props.pos.SignUrl ? (
|
||||||
|
<div style={{ pointerEvents: "none" }}>
|
||||||
|
<img
|
||||||
|
alt="signimg"
|
||||||
|
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,207 @@
|
|||||||
|
import React, { useRef, useState } from "react";
|
||||||
|
import { darkenColor, getFirstLetter } from "../../constant/Utils";
|
||||||
|
|
||||||
|
const RecipientList = (props) => {
|
||||||
|
const color = [
|
||||||
|
"#93a3db",
|
||||||
|
"#e6c3db",
|
||||||
|
"#c0e3bc",
|
||||||
|
"#bce3db",
|
||||||
|
"#b8ccdb",
|
||||||
|
"#ceb8db",
|
||||||
|
"#ffccff",
|
||||||
|
"#99ffcc",
|
||||||
|
"#cc99ff",
|
||||||
|
"#ffcc99",
|
||||||
|
"#66ccff",
|
||||||
|
"#ffffcc"
|
||||||
|
];
|
||||||
|
|
||||||
|
const nameColor = [
|
||||||
|
"#304fbf",
|
||||||
|
"#7d5270",
|
||||||
|
"#5f825b",
|
||||||
|
"#578077",
|
||||||
|
"#576e80",
|
||||||
|
"#6d527d",
|
||||||
|
"#cc00cc",
|
||||||
|
"#006666",
|
||||||
|
"#cc00ff",
|
||||||
|
"#ff9900",
|
||||||
|
"#336699",
|
||||||
|
"#cc9900"
|
||||||
|
];
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.signersdata.length > 0 &&
|
||||||
|
props.signersdata.map((obj, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-tut="reactourFirst"
|
||||||
|
onMouseEnter={() => setIsHover(ind)}
|
||||||
|
onMouseLeave={() => setIsHover(null)}
|
||||||
|
key={ind}
|
||||||
|
style={
|
||||||
|
isHover === ind || props.isSelectListId === ind
|
||||||
|
? onHoverStyle(ind, obj.blockColor)
|
||||||
|
: nonHoverStyle(ind)
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
props.setSignerObjId(obj?.objectId || "");
|
||||||
|
props.setIsSelectId(ind);
|
||||||
|
props.setContractName(obj?.className || "");
|
||||||
|
props.setUniqueId(obj.Id);
|
||||||
|
props.setRoleName(obj.Role);
|
||||||
|
if (props.handleModal) {
|
||||||
|
props.handleModal();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="signerStyle"
|
||||||
|
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
|
||||||
|
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" style={{ cursor: "default" }}>
|
||||||
|
{obj.Name}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className="userName"
|
||||||
|
onClick={() => {
|
||||||
|
setIsEdit({ [obj.Id]: true });
|
||||||
|
props.setRoleName(obj.Role);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isEdit?.[obj.Id] && props.handleRoleChange ? (
|
||||||
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
style={{
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
width: "inherit"
|
||||||
|
}}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
obj.Role
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{obj.Name && (
|
||||||
|
<span className="useEmail" style={{ cursor: "default" }}>
|
||||||
|
{obj.Role}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{props.handleDeleteUser && (
|
||||||
|
<div
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.handleDeleteUser(obj.Id);
|
||||||
|
}}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<i className="fa-regular fa-trash-can"></i>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RecipientList;
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import React from "react";
|
||||||
|
import RSC from "react-scrollbars-custom";
|
||||||
|
import { Document, Page } from "react-pdf";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
|
function RenderAllPdfPage({
|
||||||
|
pdfUrl,
|
||||||
|
signPdfUrl,
|
||||||
|
allPages,
|
||||||
|
setAllPages,
|
||||||
|
setPageNumber,
|
||||||
|
setSignBtnPosition,
|
||||||
|
pageNumber
|
||||||
|
}) {
|
||||||
|
//set all number of pages after load pdf
|
||||||
|
function onDocumentLoad({ numPages }) {
|
||||||
|
setAllPages(numPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="showPages">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
||||||
|
backgroundColor: "white",
|
||||||
|
height: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: "140px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor
|
||||||
|
// color:"white"
|
||||||
|
}}
|
||||||
|
className="signedStyle"
|
||||||
|
>
|
||||||
|
Pages
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<RSC
|
||||||
|
id="RSC-Example"
|
||||||
|
style={{
|
||||||
|
width: "135px",
|
||||||
|
height: window.innerHeight - 130 + "px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Document
|
||||||
|
loading={"Loading Document.."}
|
||||||
|
onLoadSuccess={onDocumentLoad}
|
||||||
|
file={pdfUrl ? pdfUrl : signPdfUrl}
|
||||||
|
// file="https://api.printnode.com/static/test/pdf/multipage.pdf"
|
||||||
|
>
|
||||||
|
{Array.from(new Array(allPages), (el, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
width: "100px",
|
||||||
|
border:
|
||||||
|
pageNumber - 1 === index
|
||||||
|
? "2px solid red"
|
||||||
|
: "2px solid #878787",
|
||||||
|
// padding: "5px",
|
||||||
|
margin: "10px",
|
||||||
|
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
contain: "content"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setPageNumber(index + 1);
|
||||||
|
if (setSignBtnPosition) {
|
||||||
|
setSignBtnPosition([]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Page
|
||||||
|
key={`page_${index + 1}`}
|
||||||
|
pageNumber={index + 1}
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
scale={1}
|
||||||
|
renderAnnotationLayer={false}
|
||||||
|
renderTextLayer={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Document>
|
||||||
|
</RSC>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RenderAllPdfPage;
|
||||||
@@ -0,0 +1,685 @@
|
|||||||
|
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
|
||||||
|
}) {
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
</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}
|
||||||
|
/>
|
||||||
|
</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}
|
||||||
|
/>
|
||||||
|
</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;
|
||||||
@@ -0,0 +1,670 @@
|
|||||||
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
|
function SignPad({
|
||||||
|
isSignPad,
|
||||||
|
isStamp,
|
||||||
|
setIsImageSelect,
|
||||||
|
onSaveSign,
|
||||||
|
setIsSignPad,
|
||||||
|
setImage,
|
||||||
|
isImageSelect,
|
||||||
|
imageRef,
|
||||||
|
onImageChange,
|
||||||
|
onSaveImage,
|
||||||
|
image,
|
||||||
|
defaultSign,
|
||||||
|
setSignature,
|
||||||
|
myInitial,
|
||||||
|
isInitial,
|
||||||
|
setIsInitial,
|
||||||
|
setIsStamp,
|
||||||
|
widgetType
|
||||||
|
}) {
|
||||||
|
const [penColor, setPenColor] = useState("blue");
|
||||||
|
const allColor = ["blue", "red", "black"];
|
||||||
|
const canvasRef = useRef(null);
|
||||||
|
const [isDefaultSign, setIsDefaultSign] = useState(false);
|
||||||
|
const [isTab, setIsTab] = useState("draw");
|
||||||
|
const [isSignImg, setIsSignImg] = useState("");
|
||||||
|
const [signValue, setSignValue] = useState("");
|
||||||
|
const [textWidth, setTextWidth] = useState(null);
|
||||||
|
const [textHeight, setTextHeight] = useState(null);
|
||||||
|
const fontOptions = [
|
||||||
|
{ value: "Fasthand" },
|
||||||
|
{ value: "Dancing Script" },
|
||||||
|
{ value: "Cedarville Cursive" },
|
||||||
|
{ value: "Delicious Handrawn" }
|
||||||
|
// Add more font options as needed
|
||||||
|
];
|
||||||
|
const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
|
||||||
|
|
||||||
|
const senderUser =
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
) &&
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
);
|
||||||
|
const jsonSender = JSON.parse(senderUser);
|
||||||
|
|
||||||
|
const currentUserName = jsonSender && jsonSender.name;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
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
|
||||||
|
}, []);
|
||||||
|
//function for clear signature image
|
||||||
|
const handleClear = () => {
|
||||||
|
if (isTab === "draw") {
|
||||||
|
if (canvasRef.current) {
|
||||||
|
canvasRef.current.clear();
|
||||||
|
} else if (isStamp) {
|
||||||
|
setImage("");
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSignImg("");
|
||||||
|
} else if (isTab === "uploadImage") {
|
||||||
|
setImage("");
|
||||||
|
}
|
||||||
|
setIsInitial(false);
|
||||||
|
};
|
||||||
|
//function for set signature url
|
||||||
|
const handleSignatureChange = () => {
|
||||||
|
// canvasRef.current.backgroundColor = 'rgb(165, 26, 26)'
|
||||||
|
setSignature(canvasRef.current.toDataURL());
|
||||||
|
setIsSignImg(canvasRef.current.toDataURL());
|
||||||
|
};
|
||||||
|
|
||||||
|
//save button component
|
||||||
|
const SaveBtn = () => {
|
||||||
|
return (
|
||||||
|
<div style={{ marginTop: "2px" }}>
|
||||||
|
{(isTab === "draw" || isTab === "uploadImage") && (
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
border: "1px solid #ccc"
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn saveBtn"
|
||||||
|
onClick={() => handleClear()}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
if (!image) {
|
||||||
|
if (isTab === "mysignature") {
|
||||||
|
setIsSignImg("");
|
||||||
|
if (isInitial) {
|
||||||
|
onSaveSign("initials");
|
||||||
|
} else {
|
||||||
|
onSaveSign("default");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isTab === "type") {
|
||||||
|
setIsSignImg("");
|
||||||
|
onSaveSign(false, textWidth, textHeight);
|
||||||
|
} else {
|
||||||
|
setIsSignImg("");
|
||||||
|
onSaveSign();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setPenColor("blue");
|
||||||
|
} else {
|
||||||
|
setIsSignImg("");
|
||||||
|
onSaveImage();
|
||||||
|
}
|
||||||
|
setIsSignPad(false);
|
||||||
|
setIsInitial(false);
|
||||||
|
setIsImageSelect(false);
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
setImage();
|
||||||
|
setIsTab("draw");
|
||||||
|
setSignValue("");
|
||||||
|
setIsStamp(false);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
disabled={
|
||||||
|
isSignImg || image || isDefaultSign || textWidth ? false : true
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
className={
|
||||||
|
isSignImg || image || isDefaultSign || textWidth
|
||||||
|
? "finishBtn saveBtn"
|
||||||
|
: "disabledFinish saveBtn"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadFont = async () => {
|
||||||
|
try {
|
||||||
|
await document.fonts.load(`20px ${fontSelect}`);
|
||||||
|
const selectFontSTyle = fontOptions.find(
|
||||||
|
(font) => font.value === fontSelect
|
||||||
|
);
|
||||||
|
setFontSelect(selectFontSTyle?.value || fontOptions[0].value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading font:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadFont();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [fontSelect]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Load the default signature after the component mounts
|
||||||
|
if (canvasRef.current) {
|
||||||
|
canvasRef.current.fromDataURL(isSignImg);
|
||||||
|
}
|
||||||
|
if (isTab === "type") {
|
||||||
|
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]);
|
||||||
|
|
||||||
|
//function for convert input text value in image
|
||||||
|
const convertToImg = async (fontStyle, text) => {
|
||||||
|
//get text content to convert in image
|
||||||
|
const textContent = text;
|
||||||
|
const fontfamily = fontStyle
|
||||||
|
? fontStyle
|
||||||
|
: fontSelect
|
||||||
|
? fontSelect
|
||||||
|
: "Fasthand";
|
||||||
|
|
||||||
|
//creating span for getting text content width
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.textContent = textContent;
|
||||||
|
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
|
||||||
|
span.style.display = "hidden";
|
||||||
|
document.body.appendChild(span); // Replace 'container' with the ID of the container element
|
||||||
|
|
||||||
|
//create canvas to render text in canvas and convert in image
|
||||||
|
const canvasElement = document.createElement("canvas");
|
||||||
|
// Draw the text content on the canvas
|
||||||
|
const ctx = canvasElement.getContext("2d");
|
||||||
|
const pixelRatio = window.devicePixelRatio || 1;
|
||||||
|
const width = span.offsetWidth;
|
||||||
|
const height = span.offsetHeight;
|
||||||
|
setTextWidth(width);
|
||||||
|
setTextHeight(height);
|
||||||
|
const font = span.style["font"];
|
||||||
|
// Set the canvas dimensions to match the span
|
||||||
|
canvasElement.width = width * 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
|
||||||
|
ctx.font = font;
|
||||||
|
ctx.fillStyle = "black"; // Set the text color
|
||||||
|
ctx.textAlign = "center";
|
||||||
|
ctx.textBaseline = "middle";
|
||||||
|
ctx.scale(pixelRatio, pixelRatio);
|
||||||
|
// Draw the content of the span onto the canvas
|
||||||
|
ctx.fillText(span.textContent, width / 2, height / 2); // Adjust the x,y-coordinate as needed
|
||||||
|
//remove span tag
|
||||||
|
document.body.removeChild(span);
|
||||||
|
// Convert the canvas to image data
|
||||||
|
const dataUrl = canvasElement.toDataURL("image/png");
|
||||||
|
setSignature(dataUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{isSignPad && (
|
||||||
|
<div className="modaloverlay">
|
||||||
|
<div className="modalcontainer">
|
||||||
|
<div
|
||||||
|
className="modalheader"
|
||||||
|
style={{ padding: "0 13px", marginTop: "5px" }}
|
||||||
|
>
|
||||||
|
<div className="modaltitle">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
background: "white",
|
||||||
|
marginTop: "3px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-around",
|
||||||
|
alignItems: "end",
|
||||||
|
gap: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isStamp ? (
|
||||||
|
<span style={{ color: themeColor }} className="signTab">
|
||||||
|
{widgetType === "image"
|
||||||
|
? "Upload image"
|
||||||
|
: "Upload stamp image"}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
setIsImageSelect(false);
|
||||||
|
setIsTab("draw");
|
||||||
|
setImage();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color: isTab === "draw" ? themeColor : "#515252",
|
||||||
|
marginLeft: "2px"
|
||||||
|
}}
|
||||||
|
className="signTab"
|
||||||
|
>
|
||||||
|
Draw
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border:
|
||||||
|
isTab === "draw"
|
||||||
|
? "1.5px solid #108783"
|
||||||
|
: "1.5px solid #ffffff"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
setIsImageSelect(true);
|
||||||
|
setIsTab("uploadImage");
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
isTab === "uploadImage" ? themeColor : "#515252"
|
||||||
|
}}
|
||||||
|
className="signTab"
|
||||||
|
>
|
||||||
|
Upload Image
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border:
|
||||||
|
isTab === "uploadImage"
|
||||||
|
? "1.5px solid #108783"
|
||||||
|
: "1.5px solid #ffffff"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
setIsImageSelect(false);
|
||||||
|
setIsTab("type");
|
||||||
|
setImage();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color: isTab === "type" ? themeColor : "#515252",
|
||||||
|
marginLeft: "2px"
|
||||||
|
}}
|
||||||
|
className="signTab"
|
||||||
|
>
|
||||||
|
Type
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border:
|
||||||
|
isTab === "type"
|
||||||
|
? "1.5px solid #108783"
|
||||||
|
: "1.5px solid #ffffff"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
{!isInitial && defaultSign ? (
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(true);
|
||||||
|
setIsImageSelect(true);
|
||||||
|
setIsTab("mysignature");
|
||||||
|
setImage();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
color:
|
||||||
|
isTab === "mysignature"
|
||||||
|
? themeColor
|
||||||
|
: "#515252"
|
||||||
|
}}
|
||||||
|
className="signTab"
|
||||||
|
>
|
||||||
|
My Signature
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border:
|
||||||
|
isTab === "mysignature"
|
||||||
|
? "1.5px solid #108783"
|
||||||
|
: "1.5px solid #ffffff"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
isInitial &&
|
||||||
|
myInitial && (
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
setIsDefaultSign(true);
|
||||||
|
setIsImageSelect(true);
|
||||||
|
setIsTab("mysignature");
|
||||||
|
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>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="closebtn"
|
||||||
|
style={{ color: "black" }}
|
||||||
|
onClick={() => {
|
||||||
|
setPenColor("blue");
|
||||||
|
setIsSignPad(false);
|
||||||
|
setIsInitial(false);
|
||||||
|
setIsImageSelect(false);
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
setImage();
|
||||||
|
setIsTab("draw");
|
||||||
|
setSignValue("");
|
||||||
|
setIsStamp(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
|
{isDefaultSign ? (
|
||||||
|
<>
|
||||||
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: "1.3px solid #007bff",
|
||||||
|
borderRadius: "2px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 6,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="stamp img"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
background: "rgb(255, 255, 255)",
|
||||||
|
objectFit: "contain"
|
||||||
|
}}
|
||||||
|
src={isInitial ? myInitial : defaultSign}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||||
|
<SaveBtn />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : isImageSelect || isStamp ? (
|
||||||
|
!image ? (
|
||||||
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: "1.3px solid #007bff",
|
||||||
|
borderRadius: "2px",
|
||||||
|
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 6,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
||||||
|
}
|
||||||
|
onClick={() => imageRef.current.click()}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={onImageChange}
|
||||||
|
className="filetype"
|
||||||
|
accept="image/*"
|
||||||
|
ref={imageRef}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
|
||||||
|
<div className="uploadImg">Upload</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
border: "1.3px solid #007bff",
|
||||||
|
borderRadius: "2px",
|
||||||
|
marginBottom: 6,
|
||||||
|
overflow: "hidden"
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
isInitial
|
||||||
|
? "intialSignatureCanvas"
|
||||||
|
: "signatureCanvas"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="print img"
|
||||||
|
ref={imageRef}
|
||||||
|
src={image.src}
|
||||||
|
style={{
|
||||||
|
objectFit: "contain",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{ display: "flex", justifyContent: "flex-end" }}
|
||||||
|
>
|
||||||
|
<SaveBtn />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
) : isTab === "type" ? (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="signatureText">
|
||||||
|
{isInitial ? "Initials" : "Signature"}:
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<input
|
||||||
|
maxLength={isInitial ? 3 : 30}
|
||||||
|
style={{ fontFamily: fontSelect }}
|
||||||
|
type="text"
|
||||||
|
className="signatureInput"
|
||||||
|
placeholder="Your signature"
|
||||||
|
value={signValue}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSignValue(e.target.value);
|
||||||
|
convertToImg(fontSelect, e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="fontOptionContainer">
|
||||||
|
{fontOptions.map((font, ind) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={ind}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
fontFamily: font.value,
|
||||||
|
backgroundColor:
|
||||||
|
fontSelect === font.value && "rgb(206 225 247)"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setFontSelect(font.value);
|
||||||
|
convertToImg(font.value, signValue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "5px 10px 5px 10px",
|
||||||
|
fontSize: "20px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{signValue ? signValue : "Your signature"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||||
|
<SaveBtn />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||||
|
<SignatureCanvas
|
||||||
|
ref={canvasRef}
|
||||||
|
penColor={penColor}
|
||||||
|
canvasProps={{
|
||||||
|
className: isInitial
|
||||||
|
? "intialSignatureCanvas"
|
||||||
|
: "signatureCanvas",
|
||||||
|
style: {
|
||||||
|
border: "1.6px solid #007bff",
|
||||||
|
borderRadius: "2px"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
backgroundColor="rgb(255, 255, 255)"
|
||||||
|
onEnd={() =>
|
||||||
|
handleSignatureChange(canvasRef.current.toDataURL())
|
||||||
|
}
|
||||||
|
dotSize={1}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginTop: "10px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
{allColor.map((data, key) => {
|
||||||
|
return (
|
||||||
|
<i
|
||||||
|
style={{
|
||||||
|
margin: "5px",
|
||||||
|
color: data,
|
||||||
|
borderBottom:
|
||||||
|
key === 0 && penColor === "blue"
|
||||||
|
? "2px solid blue"
|
||||||
|
: key === 1 && penColor === "red"
|
||||||
|
? "2px solid red"
|
||||||
|
: key === 2 && penColor === "black"
|
||||||
|
? "2px solid black"
|
||||||
|
: "2px solid white"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (key === 0) {
|
||||||
|
setPenColor("blue");
|
||||||
|
} else if (key === 1) {
|
||||||
|
setPenColor("red");
|
||||||
|
} else if (key === 2) {
|
||||||
|
setPenColor("black");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
key={key}
|
||||||
|
className="fa solid fa-pen-nib"
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
></i>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<SaveBtn />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SignPad;
|
||||||
@@ -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,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
import RecipientList from "./RecipientList";
|
||||||
|
|
||||||
|
function SignerListPlace(props) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: themeColor,
|
||||||
|
padding: "5px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="signedStyle">
|
||||||
|
{props.title ? props.title : "Recipients"}
|
||||||
|
</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()}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus"></i>
|
||||||
|
<span style={{ marginLeft: 2 }}>Add role</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SignerListPlace;
|
||||||
@@ -0,0 +1,419 @@
|
|||||||
|
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 { 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,
|
||||||
|
|
||||||
|
isTemplateFlow
|
||||||
|
}) {
|
||||||
|
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 [, text] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 7,
|
||||||
|
text: "text"
|
||||||
|
},
|
||||||
|
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragText: !!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 [, radio] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 15,
|
||||||
|
text: "radio"
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragRadio: !!monitor.isDragging()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const [, label] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
|
||||||
|
item: {
|
||||||
|
type: "BOX",
|
||||||
|
id: 16,
|
||||||
|
text: "label"
|
||||||
|
},
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragLabel: !!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,
|
||||||
|
label,
|
||||||
|
text,
|
||||||
|
checkbox,
|
||||||
|
dropdown,
|
||||||
|
radio,
|
||||||
|
image,
|
||||||
|
date,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
company,
|
||||||
|
jobTitle
|
||||||
|
];
|
||||||
|
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 !== "radio" && data.type !== "label"
|
||||||
|
);
|
||||||
|
const labelWidget = widget.filter((data) => data.type !== "label");
|
||||||
|
const updateWidgets = isSignYourself
|
||||||
|
? filterWidgets
|
||||||
|
: isTemplateFlow
|
||||||
|
? labelWidget
|
||||||
|
: widget;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isMobile ? (
|
||||||
|
!isMailSend && (
|
||||||
|
<div
|
||||||
|
data-tut={dataTut}
|
||||||
|
id="navbar"
|
||||||
|
className="stickyfooter"
|
||||||
|
style={{ width: window.innerWidth + "px" }}
|
||||||
|
>
|
||||||
|
{isSigners && (
|
||||||
|
<div
|
||||||
|
data-tut={dataTut}
|
||||||
|
style={{
|
||||||
|
background: isSelectListId
|
||||||
|
? color[isSelectListId % color.length]
|
||||||
|
: color[0],
|
||||||
|
padding: "10px 20px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
// if (signersdata?.length) {
|
||||||
|
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"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<WidgetList
|
||||||
|
updateWidgets={updateWidgets}
|
||||||
|
handleDivClick={handleDivClick}
|
||||||
|
handleMouseLeave={handleMouseLeave}
|
||||||
|
signRef={signRef}
|
||||||
|
marginLeft={5}
|
||||||
|
addPositionOfSignature={addPositionOfSignature}
|
||||||
|
isMobile={isMobile}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div data-tut={dataTut} className="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 ? (
|
||||||
|
<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}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<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: "10px" }}>
|
||||||
|
<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,284 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import "../../styles/AddUser.css";
|
||||||
|
import RegexParser from "regex-parser";
|
||||||
|
|
||||||
|
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 = ["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"}
|
||||||
|
>
|
||||||
|
<form onSubmit={handleSubmit} style={{ padding: 20 }}>
|
||||||
|
<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 === "text" ||
|
||||||
|
props.widgetName === "text") && (
|
||||||
|
<>
|
||||||
|
<div className="form-section">
|
||||||
|
<label htmlFor="textvalidate" style={{ fontSize: 13 }}>
|
||||||
|
Validation
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
marginBottom: "0.5rem"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: "100%", position: "relative" }}>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
padding: "0.5rem 0.75rem",
|
||||||
|
width: "92%",
|
||||||
|
borderWidth: "1px",
|
||||||
|
borderColor: "#d1d5db",
|
||||||
|
borderTopLeftRadius: "0.375rem",
|
||||||
|
borderBottomLeftRadius: "0.375rem",
|
||||||
|
outline: "none",
|
||||||
|
fontSize: "0.75rem",
|
||||||
|
position: "relative",
|
||||||
|
zIndex: 2
|
||||||
|
}}
|
||||||
|
name="textvalidate"
|
||||||
|
placeholder="Enter custom expression"
|
||||||
|
value={formdata.textvalidate}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
// onBlur={() => handleBlurRegex()}
|
||||||
|
/>
|
||||||
|
<select
|
||||||
|
style={{ position: "absolute", left: 0, zIndex: 1 }}
|
||||||
|
className="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)}
|
||||||
|
onBlur={() =>
|
||||||
|
isValid === false &&
|
||||||
|
setFormdata({ ...formdata, defaultValue: "" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{isValid === false ? (
|
||||||
|
<p style={{ color: "Red", fontSize: 8 }}>
|
||||||
|
invalid default value
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: "transparent",
|
||||||
|
fontSize: 10,
|
||||||
|
margin: "3px 8px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</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 === "text" ||
|
||||||
|
props?.widgetName === "text") && (
|
||||||
|
<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;
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Parse from "parse";
|
||||||
|
import Alert from "../../../primitives/Alert";
|
||||||
|
|
||||||
|
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
||||||
|
const folderPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: folderCls,
|
||||||
|
objectId: parentFolderId
|
||||||
|
};
|
||||||
|
const [name, setName] = useState("");
|
||||||
|
const [folderList, setFolderList] = useState([]);
|
||||||
|
const [isAlert, setIsAlert] = useState(false);
|
||||||
|
const [selectedParent, setSelectedParent] = useState();
|
||||||
|
const [alert, setAlert] = useState({ type: "info", message: "" });
|
||||||
|
useEffect(() => {
|
||||||
|
fetchFolder();
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchFolder = async () => {
|
||||||
|
try {
|
||||||
|
const FolderQuery = new Parse.Query(folderCls);
|
||||||
|
if (parentFolderId) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Err ", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCreateFolder = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (name) {
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
const exsitQuery = new Parse.Query(folderCls);
|
||||||
|
exsitQuery.equalTo("Name", name);
|
||||||
|
exsitQuery.equalTo("Type", "Folder");
|
||||||
|
if (parentFolderId) {
|
||||||
|
exsitQuery.equalTo("Folder", folderPtr);
|
||||||
|
}
|
||||||
|
const templExist = await exsitQuery.first();
|
||||||
|
if (templExist) {
|
||||||
|
setAlert({ type: "dange", message: "Folder already exist!" });
|
||||||
|
setIsAlert(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsAlert(false);
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
const template = new Parse.Object(folderCls);
|
||||||
|
template.set("Name", name);
|
||||||
|
template.set("Type", "Folder");
|
||||||
|
|
||||||
|
if (selectedParent) {
|
||||||
|
template.set("Folder", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: folderCls,
|
||||||
|
objectId: selectedParent
|
||||||
|
});
|
||||||
|
} else if (parentFolderId) {
|
||||||
|
template.set("Folder", folderPtr);
|
||||||
|
}
|
||||||
|
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||||
|
const res = await template.save();
|
||||||
|
if (res) {
|
||||||
|
setAlert({
|
||||||
|
type: "success",
|
||||||
|
message: "Folder created successfully!"
|
||||||
|
});
|
||||||
|
setIsAlert(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsAlert(false);
|
||||||
|
}, 1000);
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setAlert({ type: "info", message: "Please fill folder name" });
|
||||||
|
setIsAlert(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsAlert(false);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleOptions = (e) => {
|
||||||
|
setSelectedParent(e.target.value);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
|
||||||
|
<div id="createFolder">
|
||||||
|
<h1 className="text-base font-semibold">Create Folder</h1>
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
Name<span className="text-red-500 text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">Parent Folder</label>
|
||||||
|
<select
|
||||||
|
value={selectedParent}
|
||||||
|
onChange={handleOptions}
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
>
|
||||||
|
<option>select</option>
|
||||||
|
{folderList.length > 0 &&
|
||||||
|
folderList.map((x) => (
|
||||||
|
<option key={x.objectId} value={x.objectId}>
|
||||||
|
{x.Name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={handleCreateFolder}
|
||||||
|
className="flex items-center rounded p-2 bg-[#32a3ac] text-white mt-3"
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus mr-1"></i>
|
||||||
|
<span>Create</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateFolder;
|
||||||
@@ -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,11 +41,15 @@ export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
|||||||
[onSuccess, onCancel]
|
[onSuccess, onCancel]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChoose = useCallback(() => {
|
const handleChoose = useCallback(
|
||||||
if (window.Dropbox) {
|
(e) => {
|
||||||
window.Dropbox.choose(options);
|
e.preventDefault();
|
||||||
}
|
if (window.Dropbox) {
|
||||||
}, [options]);
|
window.Dropbox.choose(options);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[options]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={handleChoose}>
|
<div onClick={handleChoose}>
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Parse from "parse";
|
||||||
|
import CreateFolder from "./CreateFolder";
|
||||||
|
import ModalUi from "../../../primitives/ModalUi";
|
||||||
|
|
||||||
|
const SelectFolder = ({ required, onSuccess, folderCls }) => {
|
||||||
|
const [isOpen, SetIsOpen] = useState(false);
|
||||||
|
const [clickFolder, setClickFolder] = useState("");
|
||||||
|
const [selectFolder, setSelectedFolder] = useState({});
|
||||||
|
const [folderList, setFolderList] = useState([]);
|
||||||
|
const [tabList, setTabList] = useState([]);
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
|
const [folderPath, setFolderPath] = useState("");
|
||||||
|
const [isAdd, setIsAdd] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
setIsAdd(false);
|
||||||
|
setClickFolder({});
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
fetchFolder();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [isOpen]);
|
||||||
|
const fetchFolder = async (folderPtr) => {
|
||||||
|
setIsLoader(true);
|
||||||
|
try {
|
||||||
|
const FolderQuery = new Parse.Query(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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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: folderCls,
|
||||||
|
objectId: item.objectId
|
||||||
|
};
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTabList((tabs) => [...tabs, item]);
|
||||||
|
const folderPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: folderCls,
|
||||||
|
objectId: item.objectId
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
let url = "Root";
|
||||||
|
tabList.forEach((t) => {
|
||||||
|
url = url + " / " + t.Name;
|
||||||
|
});
|
||||||
|
setFolderPath(url);
|
||||||
|
setSelectedFolder(clickFolder);
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(clickFolder);
|
||||||
|
}
|
||||||
|
SetIsOpen(false);
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
SetIsOpen(false);
|
||||||
|
setClickFolder({});
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
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: folderCls,
|
||||||
|
objectId: list[_len].objectId
|
||||||
|
};
|
||||||
|
setTabList(list);
|
||||||
|
} else {
|
||||||
|
setClickFolder({});
|
||||||
|
setSelectedFolder({});
|
||||||
|
setFolderList([]);
|
||||||
|
setTabList([]);
|
||||||
|
}
|
||||||
|
fetchFolder(folderPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCreate = () => {
|
||||||
|
setIsAdd(!isAdd);
|
||||||
|
};
|
||||||
|
const handleAddFolder = () => {
|
||||||
|
setFolderList([]);
|
||||||
|
if (clickFolder && clickFolder.ObjectId) {
|
||||||
|
fetchFolder({
|
||||||
|
__type: "Pointer",
|
||||||
|
className: folderCls,
|
||||||
|
objectId: clickFolder.ObjectId
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fetchFolder();
|
||||||
|
}
|
||||||
|
handleCreate();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="text-xs mt-2 ">
|
||||||
|
<div>
|
||||||
|
<label className="block">
|
||||||
|
Select Folder
|
||||||
|
{required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
|
||||||
|
<div>
|
||||||
|
<i
|
||||||
|
className="far fa-folder-open text-[40px] text-[#33bbff]"
|
||||||
|
style={{ fontSize: "40px" }}
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
<div className="font-semibold ">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<p>
|
||||||
|
{selectFolder && selectFolder.Name ? selectFolder.Name : "Root"}
|
||||||
|
</p>
|
||||||
|
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
|
||||||
|
<i
|
||||||
|
className="fa fa-pencil"
|
||||||
|
title="Select Folder"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-[10px] text-gray-400">
|
||||||
|
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ModalUi
|
||||||
|
title={"Select Folder"}
|
||||||
|
isOpen={isOpen}
|
||||||
|
handleClose={handleCancel}
|
||||||
|
>
|
||||||
|
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
|
||||||
|
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
|
||||||
|
<span
|
||||||
|
className="cursor-pointer"
|
||||||
|
title="Root"
|
||||||
|
onClick={(e) => removeTabListItem(e)}
|
||||||
|
>
|
||||||
|
Root /{" "}
|
||||||
|
</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">
|
||||||
|
{!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>
|
||||||
|
))}
|
||||||
|
{isAdd && (
|
||||||
|
<CreateFolder
|
||||||
|
parentFolderId={clickFolder && clickFolder.ObjectId}
|
||||||
|
folderCls={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 SelectFolder;
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Parse from "parse";
|
||||||
|
import "../../../styles/AddUser.css";
|
||||||
|
import AsyncSelect from "react-select/async";
|
||||||
|
|
||||||
|
const customStyles = {
|
||||||
|
control: (provided) => ({
|
||||||
|
...provided,
|
||||||
|
fontSize: "13px" // Font size for the control
|
||||||
|
}),
|
||||||
|
option: (provided) => ({
|
||||||
|
...provided,
|
||||||
|
fontSize: "13px" // Font size for the options
|
||||||
|
})
|
||||||
|
};
|
||||||
|
const SelectSigners = (props) => {
|
||||||
|
const [userList, setUserList] = useState([]);
|
||||||
|
const [selected, setSelected] = useState();
|
||||||
|
const [userData, setUserData] = useState({});
|
||||||
|
const [isError, setIsError] = useState(false);
|
||||||
|
// `handleOptions` is used to set just save from quick form to selected option in dropdown
|
||||||
|
const handleOptions = (item) => {
|
||||||
|
setSelected(item);
|
||||||
|
const userData = userList.find((x) => x.objectId === item.value);
|
||||||
|
if (userData) {
|
||||||
|
setUserData(userData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleAdd = () => {
|
||||||
|
if (userData && userData.objectId) {
|
||||||
|
props.details(userData);
|
||||||
|
if (props.closePopup) {
|
||||||
|
props.closePopup();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsError(true);
|
||||||
|
setTimeout(() => setIsError(false), 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadOptions = async (inputValue) => {
|
||||||
|
try {
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
const contactbook = new Parse.Query("contracts_Contactbook");
|
||||||
|
contactbook.equalTo(
|
||||||
|
"CreatedBy",
|
||||||
|
Parse.User.createWithoutData(currentUser.id)
|
||||||
|
);
|
||||||
|
if (inputValue.length > 1) {
|
||||||
|
contactbook.matches("Name", new RegExp(inputValue, "i"));
|
||||||
|
}
|
||||||
|
contactbook.notEqualTo("IsDeleted", true);
|
||||||
|
const contactRes = await contactbook.find();
|
||||||
|
if (contactRes) {
|
||||||
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
|
// console.log("userList ", res);
|
||||||
|
setUserList(res);
|
||||||
|
return await res.map((item) => ({
|
||||||
|
label: item.Email,
|
||||||
|
value: item.objectId
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="addusercontainer">
|
||||||
|
<div className="form-wrapper">
|
||||||
|
<div className="form-section" style={{ marginBottom: 0 }}>
|
||||||
|
<label style={{ fontSize: 14, fontWeight: "700" }}>Choose User</label>
|
||||||
|
<AsyncSelect
|
||||||
|
cacheOptions
|
||||||
|
defaultOptions
|
||||||
|
value={selected}
|
||||||
|
loadingMessage={() => "Loading..."}
|
||||||
|
noOptionsMessage={() => "User not Found"}
|
||||||
|
loadOptions={loadOptions}
|
||||||
|
onChange={handleOptions}
|
||||||
|
styles={customStyles}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{isError ? (
|
||||||
|
<p style={{ color: "red", fontSize: "12px", margin: "5px" }}>
|
||||||
|
Please select signer
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p style={{ color: "transparent", fontSize: "12px", margin: "5px" }}>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<button className="submitbutton" onClick={() => handleAdd()}>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectSigners;
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Select from "react-select";
|
||||||
|
import AddSigner from "../../AddSigner";
|
||||||
|
import Modal from "react-modal";
|
||||||
|
import Parse from "parse";
|
||||||
|
function arrayMove(array, from, to) {
|
||||||
|
array = array.slice();
|
||||||
|
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* react-sortable-hoc is depcreated not usable from react 18.x.x
|
||||||
|
* need to replace it with @dnd-kit
|
||||||
|
* code changes required
|
||||||
|
*/
|
||||||
|
|
||||||
|
const SignersInput = (props) => {
|
||||||
|
Modal.setAppElement("body");
|
||||||
|
const [state, setState] = useState(undefined);
|
||||||
|
// const [editFormData, setEditFormData] = useState([]);
|
||||||
|
const [selected, setSelected] = React.useState([]);
|
||||||
|
const [isModal, setIsModel] = useState(false);
|
||||||
|
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
||||||
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const onSortEnd = ({ oldIndex, newIndex }) => {
|
||||||
|
const newValue = arrayMove(selected, oldIndex, newIndex);
|
||||||
|
setSelected(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GetSelectListData = async () => {
|
||||||
|
try {
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
const contactbook = new Parse.Query("contracts_Contactbook");
|
||||||
|
contactbook.equalTo(
|
||||||
|
"CreatedBy",
|
||||||
|
Parse.User.createWithoutData(currentUser.id)
|
||||||
|
);
|
||||||
|
contactbook.notEqualTo("IsDeleted", true);
|
||||||
|
const contactRes = await contactbook.find();
|
||||||
|
if (contactRes) {
|
||||||
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
|
let list = [];
|
||||||
|
|
||||||
|
// let _selected = [];
|
||||||
|
res.forEach((x) => {
|
||||||
|
let obj = {
|
||||||
|
label: x.Name,
|
||||||
|
value: x.objectId,
|
||||||
|
isChecked: true
|
||||||
|
};
|
||||||
|
|
||||||
|
list.push(obj);
|
||||||
|
});
|
||||||
|
setState(list);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
GetSelectListData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selected && selected.length) {
|
||||||
|
let newData = [];
|
||||||
|
selected.forEach((x) => {
|
||||||
|
newData.push(x.value);
|
||||||
|
});
|
||||||
|
if (props.onChange) {
|
||||||
|
props.onChange(newData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [selected]);
|
||||||
|
|
||||||
|
const handleModalCloseClick = () => {
|
||||||
|
setIsModel(false);
|
||||||
|
setModalIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openModal = () => {
|
||||||
|
setModalIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleNewDetails` is used to set just save from quick form to selected option in dropdown
|
||||||
|
const handleNewDetails = (data) => {
|
||||||
|
setState([...state, data]);
|
||||||
|
if (selected.length > 0) {
|
||||||
|
setSelected([...selected, data]);
|
||||||
|
} else {
|
||||||
|
setSelected([data]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="text-xs mt-2 ">
|
||||||
|
<label className="block">
|
||||||
|
Signers
|
||||||
|
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
|
</label>
|
||||||
|
<div style={{ display: "flex", gap: 5 }}>
|
||||||
|
<div style={{ flexWrap: "wrap", width: "100%" }}>
|
||||||
|
<Select
|
||||||
|
onSortEnd={onSortEnd}
|
||||||
|
distance={4}
|
||||||
|
isMulti
|
||||||
|
options={state || []}
|
||||||
|
value={selected}
|
||||||
|
onChange={onChange}
|
||||||
|
closeMenuOnSelect={false}
|
||||||
|
required={props.required}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
setIsModel(true);
|
||||||
|
openModal();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: 4,
|
||||||
|
border: "1px solid #ccc",
|
||||||
|
minHeight: 38,
|
||||||
|
minWidth: 48,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fas fa-plus"></i>
|
||||||
|
</div>
|
||||||
|
<Modal
|
||||||
|
isOpen={modalIsOpen}
|
||||||
|
onRequestClose={handleModalCloseClick}
|
||||||
|
shouldCloseOnOverlayClick={false}
|
||||||
|
id="modal1"
|
||||||
|
contentLabel="Modal"
|
||||||
|
style={{
|
||||||
|
content: {
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
right: "auto",
|
||||||
|
bottom: "auto",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
border: "1px transparent",
|
||||||
|
padding: 0
|
||||||
|
},
|
||||||
|
overlay: {
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
||||||
|
zIndex: 50
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="min-w-full md:min-w-[500px]">
|
||||||
|
<div
|
||||||
|
className="flex justify-between rounded-t items-center py-[10px] px-[20px] text-white"
|
||||||
|
style={{ background: "#32a3ac" }}
|
||||||
|
>
|
||||||
|
<div className="text-[1.2rem] font-normal">Add Signer</div>
|
||||||
|
<button
|
||||||
|
onClick={handleModalCloseClick}
|
||||||
|
className="text-[1.5rem] cursor-pointer focus:outline-none"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isModal && (
|
||||||
|
<AddSigner
|
||||||
|
valueKey={"objectId"}
|
||||||
|
displayKey={"Name"}
|
||||||
|
details={handleNewDetails}
|
||||||
|
closePopup={handleModalCloseClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignersInput;
|
||||||
@@ -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"
|
||||||
<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">
|
||||||
|
|||||||
@@ -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 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}`
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export const contactCls = "contracts_Contactbook";
|
||||||
|
export const templateCls = "contracts_Template";
|
||||||
|
export const documentCls = "contracts_Document";
|
||||||
|
export const rejectBtn =
|
||||||
|
"bg-[#ffffff] rounded-sm shadow-md text-[12px] font-semibold uppercase text-black py-1.5 px-4 focus:outline-none text-center border-[1px] border-[#b4b4b4]";
|
||||||
|
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";
|
||||||
|
export const modalSubmitBtnColor = "#17a2b8";
|
||||||
|
export const modalCancelBtnColor = "white";
|
||||||
|
export const themeColor = "#47a3ad";
|
||||||
|
export const iconColor = "#686968";
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
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) => {
|
||||||
//checking server url and save file's size
|
//checking server url and save file's size
|
||||||
|
|||||||
@@ -4,4 +4,15 @@
|
|||||||
|
|
||||||
body{
|
body{
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Custom CSS to hide scrollbar */
|
||||||
|
.hide-scrollbar::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-scrollbar {
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,584 +1,26 @@
|
|||||||
import Parse from "parse";
|
import { documentCls, templateCls } from "../constant/const";
|
||||||
export const formJson = (id) => {
|
export const formJson = {
|
||||||
let formData;
|
|
||||||
//json form for signYourself
|
//json form for signYourself
|
||||||
if (id === "sHAnZphf69") {
|
sHAnZphf69: {
|
||||||
formData = {
|
title: "Sign Yourself",
|
||||||
jsonSchema: {
|
redirectRoute: "signaturePdf",
|
||||||
title: "Sign Yourself",
|
msgVar: "Document",
|
||||||
description: "",
|
Cls: documentCls
|
||||||
type: "object",
|
},
|
||||||
required: ["URL", "Name"],
|
|
||||||
properties: {
|
|
||||||
URL: {
|
|
||||||
type: "string",
|
|
||||||
title: "Select Document",
|
|
||||||
filetypes: [],
|
|
||||||
maxfilesizeKB: "10000",
|
|
||||||
uploadtype: "regular",
|
|
||||||
helpbody: "",
|
|
||||||
helplink: ""
|
|
||||||
},
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Title",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Description: {
|
|
||||||
type: "string",
|
|
||||||
title: "Description",
|
|
||||||
maxLength: 500
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
title: "Folder",
|
|
||||||
parent: null,
|
|
||||||
data: {
|
|
||||||
ClassName: "contracts_Document",
|
|
||||||
FolderNameField: "Name",
|
|
||||||
FolderTypeField: "Type",
|
|
||||||
FolderTypeValue: "Folder",
|
|
||||||
FolderDescription: "Description",
|
|
||||||
ParentFolderField: "Folder",
|
|
||||||
FormId: "YjIB7W7Xs6",
|
|
||||||
Query: 'where={"Folder":{"$exists":false},"Type":"Folder"}'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExtUserPtr: {
|
|
||||||
data: {
|
|
||||||
valueKey: "objectId",
|
|
||||||
isPointer: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
URL: {
|
|
||||||
"ui:field": "FileUpload"
|
|
||||||
},
|
|
||||||
Description: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
"ui:options": {
|
|
||||||
rows: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Note: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
"ui:options": {
|
|
||||||
rows: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
"ui:field": "FolderComponent"
|
|
||||||
},
|
|
||||||
ExtUserPtr: {
|
|
||||||
"ui:field": "HiddenField"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {},
|
|
||||||
rules: null,
|
|
||||||
noValidate: false,
|
|
||||||
liveValidate: false,
|
|
||||||
isRegisterForm: false,
|
|
||||||
help: { htmlbody: "" },
|
|
||||||
description: "",
|
|
||||||
class: "contracts_Document",
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
resetText: "Reset",
|
|
||||||
submitText: "Submit"
|
|
||||||
},
|
|
||||||
edit: { submitText: "Update", cancelText: "Cancel" }
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"#currentUser#": { read: true, write: true },
|
|
||||||
"*": { read: true, write: true }
|
|
||||||
},
|
|
||||||
redirect_id:
|
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/signaturePdf",
|
|
||||||
success_message: "Success!",
|
|
||||||
success_redirect: "Microapp",
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
|
|
||||||
return formData;
|
//json form for request signatures
|
||||||
}
|
"8mZzFxbG1z": {
|
||||||
//json form for request signature
|
title: "Request Signatures",
|
||||||
else if (id === "8mZzFxbG1z") {
|
msgVar: "Document",
|
||||||
const user = Parse.User.current();
|
redirectRoute: "placeHolderSign",
|
||||||
const userPtr = JSON.stringify({
|
Cls: documentCls,
|
||||||
__type: "Pointer",
|
signers: true
|
||||||
className: "_User",
|
},
|
||||||
objectId: user.id
|
//json form for template
|
||||||
});
|
template: {
|
||||||
formData = {
|
title: "New Template",
|
||||||
jsonSchema: {
|
redirectRoute: "template",
|
||||||
title: "New Document",
|
msgVar: "Template",
|
||||||
description: "",
|
Cls: templateCls
|
||||||
type: "object",
|
|
||||||
required: ["URL", "Name", "Note", "TimeToCompleteDays", "Signers"],
|
|
||||||
properties: {
|
|
||||||
URL: {
|
|
||||||
type: "string",
|
|
||||||
title: "Select Document",
|
|
||||||
filetypes: [],
|
|
||||||
maxfilesizeKB: "5000",
|
|
||||||
uploadtype: "regular",
|
|
||||||
helpbody: "",
|
|
||||||
helplink: ""
|
|
||||||
},
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Title",
|
|
||||||
maxLength: 100
|
|
||||||
},
|
|
||||||
Description: {
|
|
||||||
type: "string",
|
|
||||||
title: "Description",
|
|
||||||
maxLength: 500
|
|
||||||
},
|
|
||||||
Signers: {
|
|
||||||
type: "array",
|
|
||||||
title: "Signers",
|
|
||||||
isSortable: false,
|
|
||||||
selectAll: false,
|
|
||||||
selectedData: null,
|
|
||||||
data: {
|
|
||||||
class: "contracts_Contactbook",
|
|
||||||
displayKey: "Name",
|
|
||||||
valueKey: "objectId",
|
|
||||||
query: `where={"CreatedBy":${userPtr},"IsDeleted":{"$ne":true}}&keys=Name`,
|
|
||||||
isPointer: true,
|
|
||||||
helpbody: "",
|
|
||||||
helplink: "",
|
|
||||||
quickAddFormId: "qUGywSWd8e"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Note: {
|
|
||||||
type: "string",
|
|
||||||
title: "Note",
|
|
||||||
default: "Please review and sign this document",
|
|
||||||
maxLength: 500
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
title: "Folder",
|
|
||||||
data: {
|
|
||||||
ClassName: "contracts_Document",
|
|
||||||
FolderNameField: "Name",
|
|
||||||
FolderTypeField: "Type",
|
|
||||||
FolderTypeValue: "Folder",
|
|
||||||
FolderDescription: "Description",
|
|
||||||
ParentFolderField: "Folder",
|
|
||||||
FormId: "YjIB7W7Xs6",
|
|
||||||
Query: 'where={"Folder":{"$exists":false},"Type":"Folder"}'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TimeToCompleteDays: {
|
|
||||||
type: "number",
|
|
||||||
title: "Time To Complete (Days)",
|
|
||||||
default: 15,
|
|
||||||
maxLength: 5000
|
|
||||||
},
|
|
||||||
ExtUserPtr: {
|
|
||||||
data: {
|
|
||||||
valueKey: "objectId",
|
|
||||||
isPointer: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
URL: {
|
|
||||||
"ui:field": "FileUpload"
|
|
||||||
},
|
|
||||||
Description: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
"ui:options": {
|
|
||||||
rows: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Note: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
"ui:options": {
|
|
||||||
rows: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Signers: {
|
|
||||||
"ui:field": "MultiSelectField"
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
"ui:field": "FolderComponent"
|
|
||||||
},
|
|
||||||
TimeToCompleteDays: {
|
|
||||||
"ui:placeholder": "No. of days",
|
|
||||||
"ui:widget": "updown"
|
|
||||||
},
|
|
||||||
ExtUserPtr: {
|
|
||||||
"ui:field": "HiddenField"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {},
|
|
||||||
rules: null,
|
|
||||||
noValidate: false,
|
|
||||||
liveValidate: false,
|
|
||||||
isRegisterForm: false,
|
|
||||||
help: { htmlbody: "" },
|
|
||||||
description: "",
|
|
||||||
class: "contracts_Document",
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
resetText: "Reset",
|
|
||||||
submitText: "Submit"
|
|
||||||
},
|
|
||||||
edit: { submitText: "Update", cancelText: "Cancel" }
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"#currentUser#": { read: true, write: true },
|
|
||||||
"*": { read: true, write: true }
|
|
||||||
},
|
|
||||||
redirect_id:
|
|
||||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/placeHolderSign",
|
|
||||||
success_message: "Success!",
|
|
||||||
success_redirect: "Microapp",
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
//json form for create new folder
|
|
||||||
else if (id === "YjIB7W7Xs6") {
|
|
||||||
formData = {
|
|
||||||
jsonSchema: {
|
|
||||||
title: "New Folder",
|
|
||||||
description: "",
|
|
||||||
type: "object",
|
|
||||||
required: ["Name"],
|
|
||||||
properties: {
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Name",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Type: {
|
|
||||||
type: "string",
|
|
||||||
data: {
|
|
||||||
valueKey: "Type",
|
|
||||||
isPointer: false
|
|
||||||
},
|
|
||||||
default: "Folder"
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
title: "Parent Folder",
|
|
||||||
data: {
|
|
||||||
class: "contracts_Document",
|
|
||||||
displayKey: "Name",
|
|
||||||
valueKey: "objectId",
|
|
||||||
query: 'where={"Type":"Folder"}&keys=Name',
|
|
||||||
isPointer: true,
|
|
||||||
savePointerClass: "",
|
|
||||||
helpbody: "",
|
|
||||||
helplink: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
Type: {
|
|
||||||
"ui:field": "HiddenField"
|
|
||||||
},
|
|
||||||
Folder: {
|
|
||||||
"ui:field": "Level1Dropdown"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {},
|
|
||||||
rules: null,
|
|
||||||
noValidate: false,
|
|
||||||
liveValidate: false,
|
|
||||||
isRegisterForm: false,
|
|
||||||
help: { htmlbody: "" },
|
|
||||||
description: "",
|
|
||||||
class: "contracts_Document",
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
resetText: "Reset",
|
|
||||||
submitText: "Submit"
|
|
||||||
},
|
|
||||||
edit: { submitText: "Update", cancelText: "Cancel" }
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"#currentUser#": { read: true, write: true },
|
|
||||||
"*": { read: true, write: true }
|
|
||||||
},
|
|
||||||
redirect_id: "",
|
|
||||||
success_message: "Success!",
|
|
||||||
success_redirect: "",
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
//json form for add signers
|
|
||||||
else if (id === "fICciRuUcB") {
|
|
||||||
formData = {
|
|
||||||
jsonSchema: {
|
|
||||||
title: "Add Signer",
|
|
||||||
description: "",
|
|
||||||
type: "object",
|
|
||||||
required: ["Name", "Email", "Phone", "Company"],
|
|
||||||
properties: {
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Name",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Email: {
|
|
||||||
type: "string",
|
|
||||||
title: "Email",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Phone: {
|
|
||||||
type: "string",
|
|
||||||
title: "Phone",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Company: {
|
|
||||||
type: "string",
|
|
||||||
title: "Company",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
JobTitle: {
|
|
||||||
type: "string",
|
|
||||||
title: "JobTitle",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
IsContactEntry: {
|
|
||||||
type: "boolean",
|
|
||||||
data: {
|
|
||||||
valueKey: "IsContactEntry",
|
|
||||||
isPointer: false
|
|
||||||
},
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
Email: {
|
|
||||||
"ui:widget": "email"
|
|
||||||
},
|
|
||||||
IsContactEntry: {
|
|
||||||
"ui:field": "HiddenField"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {
|
|
||||||
email: "$Email",
|
|
||||||
name: "$Name",
|
|
||||||
password: "$Phone",
|
|
||||||
phone: "$Phone",
|
|
||||||
role: "contracts_User",
|
|
||||||
username: "$Email"
|
|
||||||
},
|
|
||||||
rules: null,
|
|
||||||
noValidate: false,
|
|
||||||
liveValidate: false,
|
|
||||||
isRegisterForm: true,
|
|
||||||
help: {},
|
|
||||||
description: "",
|
|
||||||
class: "contracts_Users",
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
resetText: "Reset",
|
|
||||||
submitText: "Submit"
|
|
||||||
},
|
|
||||||
edit: { submitText: "Update", cancelText: "Cancel" }
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"#currentUser#": { read: true, write: true },
|
|
||||||
"*": { read: true, write: true }
|
|
||||||
},
|
|
||||||
redirect_id: "",
|
|
||||||
success_message: "Success!",
|
|
||||||
success_redirect: "",
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
//json form for add users
|
|
||||||
else if (id === "lM0xRnM3iE") {
|
|
||||||
formData = {
|
|
||||||
jsonSchema: {
|
|
||||||
title: "Add User",
|
|
||||||
description: "",
|
|
||||||
type: "object",
|
|
||||||
required: ["Name", "Email", "Phone", "JobTitle"],
|
|
||||||
properties: {
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Name",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Email: {
|
|
||||||
type: "string",
|
|
||||||
title: "Email",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Phone: {
|
|
||||||
type: "string",
|
|
||||||
title: "Phone",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
JobTitle: {
|
|
||||||
type: "string",
|
|
||||||
title: "Job Title",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Company: {
|
|
||||||
type: "string",
|
|
||||||
title: "Company",
|
|
||||||
maxLength: 50
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
Email: {
|
|
||||||
"ui:widget": "email"
|
|
||||||
},
|
|
||||||
Phone: {
|
|
||||||
"ui:options": {
|
|
||||||
inputType: "tel"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {
|
|
||||||
email: "$Email",
|
|
||||||
name: "$Name",
|
|
||||||
password: "$Phone",
|
|
||||||
phone: "$Phone",
|
|
||||||
role: "contracts_User",
|
|
||||||
username: "$Email"
|
|
||||||
},
|
|
||||||
rules: null,
|
|
||||||
noValidate: false,
|
|
||||||
liveValidate: false,
|
|
||||||
isRegisterForm: true,
|
|
||||||
help: {},
|
|
||||||
description: "",
|
|
||||||
class: "contracts_Users",
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
resetText: "Reset",
|
|
||||||
submitText: "Submit"
|
|
||||||
},
|
|
||||||
edit: { submitText: "Update", cancelText: "Cancel" }
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"#currentUser#": { read: true, write: true },
|
|
||||||
"*": { read: true, write: true }
|
|
||||||
},
|
|
||||||
redirect_id: "",
|
|
||||||
success_message: "Success!",
|
|
||||||
success_redirect: "",
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
return formData;
|
|
||||||
} else if (id === "qUGywSWd8e") {
|
|
||||||
formData = {
|
|
||||||
jsonSchema: {
|
|
||||||
title: "Add Contact",
|
|
||||||
description: "",
|
|
||||||
type: "object",
|
|
||||||
required: ["Name", "Email", "Phone"],
|
|
||||||
properties: {
|
|
||||||
Name: {
|
|
||||||
type: "string",
|
|
||||||
title: "Name",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Email: {
|
|
||||||
type: "string",
|
|
||||||
title: "Email",
|
|
||||||
maxLength: 50
|
|
||||||
},
|
|
||||||
Phone: {
|
|
||||||
type: "string",
|
|
||||||
title: "Phone",
|
|
||||||
maxLength: 50
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uiSchema: {
|
|
||||||
Email: {
|
|
||||||
"ui:widget": "email"
|
|
||||||
},
|
|
||||||
Phone: {
|
|
||||||
"ui:options": {
|
|
||||||
inputType: "tel"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userSchema: {
|
|
||||||
name: "$Name",
|
|
||||||
username: "$Email",
|
|
||||||
email: "$Email",
|
|
||||||
password: "$Phone",
|
|
||||||
phone: "$Phone",
|
|
||||||
role: "contracts_Guest"
|
|
||||||
},
|
|
||||||
restrict_form_entry: {
|
|
||||||
enable_captcha: false,
|
|
||||||
allow_one_entry_per_ip_address: false,
|
|
||||||
allow_one_entry_per_user: false,
|
|
||||||
enable_geo_fence: false
|
|
||||||
},
|
|
||||||
restrict_form_access: {
|
|
||||||
entryCount: ""
|
|
||||||
},
|
|
||||||
help: {},
|
|
||||||
email_template: {
|
|
||||||
from: "",
|
|
||||||
to: "",
|
|
||||||
subject: "",
|
|
||||||
message: ""
|
|
||||||
},
|
|
||||||
buttons: {
|
|
||||||
add: {
|
|
||||||
submitText: "Submit",
|
|
||||||
resetText: "Reset"
|
|
||||||
},
|
|
||||||
edit: {
|
|
||||||
submitText: "Update",
|
|
||||||
cancelText: "Cancel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
appId: {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: "w_appinfo",
|
|
||||||
objectId: "aIPmIvMzGM"
|
|
||||||
},
|
|
||||||
formACL: {
|
|
||||||
"*": {
|
|
||||||
read: true,
|
|
||||||
write: true
|
|
||||||
},
|
|
||||||
"#currentUser#": {
|
|
||||||
read: true,
|
|
||||||
write: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
class: "contracts_Contactbook",
|
|
||||||
description: "",
|
|
||||||
success_message: "Success!",
|
|
||||||
form_permission: "private",
|
|
||||||
success_redirect: "",
|
|
||||||
redirect_id: "",
|
|
||||||
isRegisterForm: true,
|
|
||||||
liveValidate: false,
|
|
||||||
noValidate: false,
|
|
||||||
validFunction:
|
|
||||||
"ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ=="
|
|
||||||
};
|
|
||||||
return formData;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
export default function reportJson(id) {
|
export default function reportJson(id) {
|
||||||
// console.log("json ", json);
|
// console.log("json ", json);
|
||||||
const head = ["Sr.No", "Name", "Note", "Folder", "File", "Owner", "Signers"];
|
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
||||||
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
const contactbook = ["Sr.No", "Title", "Email", "Phone"];
|
||||||
|
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
// draft documents report
|
// draft documents report
|
||||||
case "ByHuevtCFY":
|
case "ByHuevtCFY":
|
||||||
@@ -14,8 +16,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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -30,8 +31,7 @@ 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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -46,8 +46,7 @@ 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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -62,8 +61,7 @@ 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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -78,8 +76,7 @@ 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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -94,8 +91,7 @@ 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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -103,15 +99,14 @@ export default function reportJson(id) {
|
|||||||
case "d9k3UfYHBc":
|
case "d9k3UfYHBc":
|
||||||
return {
|
return {
|
||||||
reportName: "Recently sent for signatures",
|
reportName: "Recently sent for signatures",
|
||||||
heading: head,
|
heading: dashboardReportHead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnLabel: "View",
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -119,15 +114,14 @@ export default function reportJson(id) {
|
|||||||
case "5Go51Q7T8r":
|
case "5Go51Q7T8r":
|
||||||
return {
|
return {
|
||||||
reportName: "Recent signature requests",
|
reportName: "Recent signature requests",
|
||||||
heading: head,
|
heading: dashboardReportHead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "Sign",
|
btnLabel: "Sign",
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -135,15 +129,14 @@ export default function reportJson(id) {
|
|||||||
case "kC5mfynCi4":
|
case "kC5mfynCi4":
|
||||||
return {
|
return {
|
||||||
reportName: "Drafts",
|
reportName: "Drafts",
|
||||||
heading: head,
|
heading: ["Title", "Note", "Folder", "File", "Owner", "Signers"],
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "sign",
|
btnLabel: "sign",
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -159,6 +152,29 @@ export default function reportJson(id) {
|
|||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa-solid fa-trash"
|
btnIcon: "fa-solid fa-trash"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
form: "ContactBook"
|
||||||
|
};
|
||||||
|
// template report
|
||||||
|
case "6TeaPr321t":
|
||||||
|
return {
|
||||||
|
reportName: "Templates",
|
||||||
|
heading: head,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
btnLabel: "Use",
|
||||||
|
btnColor: "#4bd396",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-plus",
|
||||||
|
redirectUrl: "placeHolderSign"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnLabel: "Edit",
|
||||||
|
btnColor: "#00c9d5",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-plus",
|
||||||
|
redirectUrl: "template"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -27,13 +27,13 @@
|
|||||||
"planName": "THANKS PLAN",
|
"planName": "THANKS PLAN",
|
||||||
"currency": "$",
|
"currency": "$",
|
||||||
"price": "29.99",
|
"price": "29.99",
|
||||||
"subtitle": "Use code 'FREEBETA' to get this for free(First 1000 users)",
|
"subtitle": "Use code <span style='background-color: yellow;'>'FREEBETA'</span> to get this for free(First 1000 users)",
|
||||||
"btnText": "Subscribe",
|
"btnText": "Subscribe",
|
||||||
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
|
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
|
||||||
"target": "_self",
|
"target": "_self",
|
||||||
"benefits": [
|
"benefits": [
|
||||||
"Sign Unlimited Documents",
|
"Sign Unlimited Documents",
|
||||||
"Unlimited Secure Doc Storage with OpenSignDrive",
|
"Unlimited Secure Doc Storage with OpenSign™ Drive",
|
||||||
"Unlimited Guest Signers",
|
"Unlimited Guest Signers",
|
||||||
"Unlimited completion certificates",
|
"Unlimited completion certificates",
|
||||||
"Unique Code(OTP) verification for guest signers",
|
"Unique Code(OTP) verification for guest signers",
|
||||||
|
|||||||
@@ -7,10 +7,37 @@ import Tour from "reactour";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
const HomeLayout = ({ children }) => {
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import { useNavigate, useLocation, Outlet } from "react-router-dom";
|
||||||
|
|
||||||
|
const HomeLayout = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
const arr = useSelector((state) => state.TourSteps);
|
const arr = useSelector((state) => state.TourSteps);
|
||||||
|
const [isUserValid, setIsUserValid] = useState(true);
|
||||||
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
// Use the session token to validate the user
|
||||||
|
const userQuery = new Parse.Query(Parse.User);
|
||||||
|
const user = await userQuery.get(Parse.User.current().id, {
|
||||||
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
|
});
|
||||||
|
if (user) {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else {
|
||||||
|
setIsUserValid(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Session token is invalid or there was an error
|
||||||
|
setIsUserValid(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// reactour state
|
// reactour state
|
||||||
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
||||||
@@ -19,7 +46,7 @@ const HomeLayout = ({ children }) => {
|
|||||||
const [tourConfigs, setTourConfigs] = useState([]);
|
const [tourConfigs, setTourConfigs] = useState([]);
|
||||||
|
|
||||||
const showSidebar = () => {
|
const showSidebar = () => {
|
||||||
setIsOpen(value => !value);
|
setIsOpen((value) => !value);
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (width && width <= 768) {
|
if (width && width <= 768) {
|
||||||
@@ -28,9 +55,7 @@ const HomeLayout = ({ children }) => {
|
|||||||
}, [width]);
|
}, [width]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem("domain") === "sign" && arr && arr.length > 0) {
|
if (
|
||||||
handleDynamicSteps();
|
|
||||||
} else if (
|
|
||||||
localStorage.getItem("domain") === "contracts" &&
|
localStorage.getItem("domain") === "contracts" &&
|
||||||
arr &&
|
arr &&
|
||||||
arr.length > 0
|
arr.length > 0
|
||||||
@@ -85,7 +110,7 @@ const HomeLayout = ({ children }) => {
|
|||||||
// 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;
|
||||||
@@ -153,32 +178,80 @@ const HomeLayout = ({ children }) => {
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLoginBtn = () => {
|
||||||
|
try {
|
||||||
|
Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err ", err);
|
||||||
|
} finally {
|
||||||
|
localStorage.removeItem("accesstoken");
|
||||||
|
navigate("/", { replace: true, state: { from: location } });
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="sticky top-0 z-50">
|
<div className="sticky top-0 z-50">
|
||||||
<Header showSidebar={showSidebar} />
|
<Header showSidebar={showSidebar} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex md:flex-row flex-col z-50">
|
{isUserValid ? (
|
||||||
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
<>
|
||||||
|
{isLoader ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100vh",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="flex md:flex-row flex-col z-50">
|
||||||
|
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
||||||
|
|
||||||
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
|
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
|
||||||
<div className="bg-[#eef1f5] p-3">{children}</div>
|
<div className="bg-[#eef1f5] p-3">{<Outlet />}</div>
|
||||||
<div className="z-30">
|
<div className="z-30">
|
||||||
<Footer />
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Tour
|
||||||
|
onRequestClose={closeTour}
|
||||||
|
steps={tourConfigs}
|
||||||
|
isOpen={isTour}
|
||||||
|
closeWithMask={false}
|
||||||
|
disableKeyboardNavigation={["esc"]}
|
||||||
|
// disableInteraction={true}
|
||||||
|
scrollOffset={-100}
|
||||||
|
rounded={5}
|
||||||
|
showCloseButton={isCloseBtn}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<ModalUi title={"Session Expired"} isOpen={true} showClose={false}>
|
||||||
|
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
||||||
|
<p className="text-xl font-normal">Your session has expired.</p>
|
||||||
|
<button
|
||||||
|
onClick={handleLoginBtn}
|
||||||
|
className="text-base px-3 py-1.5 rounded shadow-md text-white bg-[#1ab6ce]"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ModalUi>
|
||||||
</div>
|
)}
|
||||||
<Tour
|
|
||||||
onRequestClose={closeTour}
|
|
||||||
steps={tourConfigs}
|
|
||||||
isOpen={isTour}
|
|
||||||
closeWithMask={false}
|
|
||||||
disableKeyboardNavigation={["esc"]}
|
|
||||||
// disableInteraction={true}
|
|
||||||
scrollOffset={-100}
|
|
||||||
rounded={5}
|
|
||||||
showCloseButton={isCloseBtn}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -12,8 +12,6 @@ const Dashboard = (props) => {
|
|||||||
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(() => {
|
||||||
@@ -24,7 +22,7 @@ const Dashboard = (props) => {
|
|||||||
getDashboard(localStorage.getItem("PageLanding"));
|
getDashboard(localStorage.getItem("PageLanding"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate("/", { replace: true });
|
navigate("/", { replace: true, state: { from: location } });
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [id]);
|
}, [id]);
|
||||||
@@ -32,8 +30,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);
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
||||||
|
import "../styles/signature.css";
|
||||||
|
import "../styles/AddUser.css";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import RenderDebugPdf from "../components/RenderDebugPdf";
|
||||||
|
import { pdfjs } from "react-pdf";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
|
|
||||||
|
function processDimensions(x, y, width, height) {
|
||||||
|
if (width < 0) {
|
||||||
|
x -= Math.abs(width);
|
||||||
|
width = Math.abs(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height < 0) {
|
||||||
|
y -= Math.abs(height);
|
||||||
|
height = Math.abs(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: Math.floor(x),
|
||||||
|
y: Math.floor(y),
|
||||||
|
width: Math.floor(width),
|
||||||
|
height: Math.floor(height)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const DebugPdf = () => {
|
||||||
|
const { width } = useWindowSize();
|
||||||
|
const [pdf, setPdf] = useState("");
|
||||||
|
const [isModal, setIsModal] = useState(true);
|
||||||
|
const [allPages, setAllPages] = useState(null);
|
||||||
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
const [pdfLoadFail, setPdfLoadFail] = useState({
|
||||||
|
status: false,
|
||||||
|
type: "load"
|
||||||
|
});
|
||||||
|
const [pdfDetails, setPdfDetails] = useState({
|
||||||
|
name: "",
|
||||||
|
pdftype: "",
|
||||||
|
totalPages: "",
|
||||||
|
currentPage: 1,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
base64: ""
|
||||||
|
});
|
||||||
|
const [hoverCoordinates, setHoverCoordinates] = useState({ x: 0, y: 0 });
|
||||||
|
const [pdfDimension, setPdfDimension] = useState({ width: 0, height: 0 });
|
||||||
|
const [annotations, setAnnotations] = useState([]);
|
||||||
|
const [newAnnotation, setNewAnnotation] = useState([]);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (pdf && pdf.name) {
|
||||||
|
const fetchPdfMetadata = async () => {
|
||||||
|
try {
|
||||||
|
const pdfDataURL = URL.createObjectURL(pdf); // Convert File to data URL
|
||||||
|
console.log("pdfDataURL ", pdfDataURL);
|
||||||
|
const pdfInfo = await pdfjs.getDocument({ url: pdfDataURL }).promise;
|
||||||
|
const pdfType = await inferPdfType(pdfInfo);
|
||||||
|
setPdfDetails((prevDetails) => ({
|
||||||
|
...prevDetails,
|
||||||
|
pdftype: pdfType
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching PDF metadata:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchPdfMetadata();
|
||||||
|
}
|
||||||
|
}, [pdf]);
|
||||||
|
|
||||||
|
const inferPdfType = async (pdf) => {
|
||||||
|
try {
|
||||||
|
const firstPage = await pdf.getPage(1);
|
||||||
|
const scale = 1;
|
||||||
|
const { width, height } = firstPage.getViewport({ scale });
|
||||||
|
setPdfDimension({ width: width, height: height });
|
||||||
|
|
||||||
|
// Assuming a standard DPI of 72, you can adjust this value if needed
|
||||||
|
const dpi = 72;
|
||||||
|
|
||||||
|
const widthInInches = width / dpi;
|
||||||
|
const heightInInches = height / dpi;
|
||||||
|
|
||||||
|
const isA1 = widthInInches > 23.39 && heightInInches > 16.54;
|
||||||
|
const isA2 = widthInInches > 16.54 && heightInInches > 11.69;
|
||||||
|
const isA3 = widthInInches > 11.69 && heightInInches > 8.27;
|
||||||
|
const isA4 = widthInInches > 8.27 && heightInInches > 5.83;
|
||||||
|
const isLegal = widthInInches > 8.5 && heightInInches > 14;
|
||||||
|
const isLetter = widthInInches > 8.5 && heightInInches > 11;
|
||||||
|
const isLedger = widthInInches > 11 && heightInInches > 17;
|
||||||
|
|
||||||
|
if (isA1) return "A1";
|
||||||
|
if (isA2) return "A2";
|
||||||
|
if (isA3) return "A3";
|
||||||
|
if (isA4) return "A4";
|
||||||
|
if (isLegal) return "Legal";
|
||||||
|
if (isLetter) return "Letter";
|
||||||
|
if (isLedger) return "Ledger";
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error getting page dimensions:", error);
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsModal(false);
|
||||||
|
setPdfDetails((prevData) => ({ ...prevData, name: pdf?.name }));
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for get pdf page details
|
||||||
|
const pageDetails = async ({ numPages }) => {
|
||||||
|
const load = {
|
||||||
|
status: true
|
||||||
|
};
|
||||||
|
setPdfDetails((prevDetails) => ({ ...prevDetails, totalPages: numPages }));
|
||||||
|
setPdfLoadFail(load);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseMoveDiv = (event) => {
|
||||||
|
setHoverCoordinates({
|
||||||
|
x: event.nativeEvent.offsetX,
|
||||||
|
y: event.nativeEvent.offsetY
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleMouseDown = (event) => {
|
||||||
|
if (newAnnotation.length === 0) {
|
||||||
|
const { x, y } = event.target.getStage().getPointerPosition();
|
||||||
|
setNewAnnotation([
|
||||||
|
{ x, y, width: 0, height: 0, key: "0", page: pageNumber }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseUp = (event) => {
|
||||||
|
if (newAnnotation.length === 1) {
|
||||||
|
const sx = newAnnotation[0].x;
|
||||||
|
const sy = newAnnotation[0].y;
|
||||||
|
const { x, y } = event.target.getStage().getPointerPosition();
|
||||||
|
const result = processDimensions(sx, sy, x - sx, y - sy);
|
||||||
|
const annotationToAdd = {
|
||||||
|
...result,
|
||||||
|
key: annotations.length + 1,
|
||||||
|
page: pageNumber
|
||||||
|
};
|
||||||
|
annotations.push(annotationToAdd);
|
||||||
|
setNewAnnotation([]);
|
||||||
|
setAnnotations(annotations);
|
||||||
|
setPdfDetails((prevDetails) => ({
|
||||||
|
...prevDetails,
|
||||||
|
x: result.x,
|
||||||
|
y: result.y
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseMove = (event) => {
|
||||||
|
if (newAnnotation.length === 1) {
|
||||||
|
const sx = newAnnotation[0].x;
|
||||||
|
const sy = newAnnotation[0].y;
|
||||||
|
const { x, y } = event.target.getStage().getPointerPosition();
|
||||||
|
setNewAnnotation([
|
||||||
|
{
|
||||||
|
x: sx,
|
||||||
|
y: sy,
|
||||||
|
width: x - sx,
|
||||||
|
height: y - sy,
|
||||||
|
page: pageNumber,
|
||||||
|
key: "0"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const annotationsToDraw = [...annotations, ...newAnnotation];
|
||||||
|
|
||||||
|
const handlePageLoadSuccess = (page) => {
|
||||||
|
setPdfDetails((prevDetails) => ({
|
||||||
|
...prevDetails,
|
||||||
|
currentPage: page.pageNumber
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const copytoclipboard = (text) => {
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setCopied(false);
|
||||||
|
}, 1500); // Reset copied state after 1.5 seconds
|
||||||
|
};
|
||||||
|
const handleFileChange = (files) => {
|
||||||
|
const file = files[0];
|
||||||
|
setPdf(file);
|
||||||
|
|
||||||
|
if (file && file.type === "application/pdf") {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onloadend = () => {
|
||||||
|
const base64String = reader.result.split(",")[1];
|
||||||
|
setPdfDetails((prevdata) => ({ ...prevdata, base64: base64String }));
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleDelete = (key) => {
|
||||||
|
const updateAnnotations = annotations.filter((x) => x.key !== key);
|
||||||
|
setAnnotations(updateAnnotations);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{copied && <Alert type="success">Copied</Alert>}
|
||||||
|
<Title title={"Debug Pdf"} />
|
||||||
|
{width < 800 ? (
|
||||||
|
<HandleError handleError={"Debug PDF only availble for PC"} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{!isModal && (
|
||||||
|
<div className="signatureContainer">
|
||||||
|
{/* this component used to render all pdf pages in left side */}
|
||||||
|
<RenderAllPdfPage
|
||||||
|
signPdfUrl={pdf}
|
||||||
|
allPages={allPages}
|
||||||
|
setAllPages={setAllPages}
|
||||||
|
setPageNumber={setPageNumber}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
/>
|
||||||
|
{/* pdf render view */}
|
||||||
|
<div>
|
||||||
|
<div data-tut="reactourThird">
|
||||||
|
<RenderDebugPdf
|
||||||
|
pdfUrl={pdf}
|
||||||
|
pageDetails={pageDetails}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
setPdfLoadFail={setPdfLoadFail}
|
||||||
|
pdfLoadFail={pdfLoadFail}
|
||||||
|
handlePageLoadSuccess={handlePageLoadSuccess}
|
||||||
|
handleMouseMove={handleMouseMove}
|
||||||
|
handleMouseUp={handleMouseUp}
|
||||||
|
handleMouseDown={handleMouseDown}
|
||||||
|
hoverCoordinates={hoverCoordinates}
|
||||||
|
annotations={annotationsToDraw}
|
||||||
|
pdfDimension={pdfDimension}
|
||||||
|
handleMouseMoveDiv={handleMouseMoveDiv}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ backgroundColor: "white", width: 220 }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: "10px 12px",
|
||||||
|
borderBottom: "1px solid grey"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
PDF details
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
Name: {pdfDetails?.name}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
Pdf type: {pdfDetails?.pdftype}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
Total Pages: {pdfDetails?.totalPages}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
Current Page: {pdfDetails?.currentPage}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
Base64 : {pdfDetails?.base64.slice(0, 10)}...
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
borderRadius: 4,
|
||||||
|
padding: "3px 5px",
|
||||||
|
border: "1px solid gray",
|
||||||
|
fontSize: 12,
|
||||||
|
margin: 2,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
onClick={() => copytoclipboard(pdfDetails?.base64)}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-copy"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: "10px 12px",
|
||||||
|
borderBottom: "1px solid grey"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Last click
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
x co-ordinate: {pdfDetails?.x}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 14, padding: "5px 12px" }}>
|
||||||
|
y co-ordinate: {pdfDetails?.y}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: "10px 12px",
|
||||||
|
borderBottom: "1px solid grey",
|
||||||
|
borderTop: "1px solid grey"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Annotation
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
listStyle: "none",
|
||||||
|
padding: 10,
|
||||||
|
height: 500,
|
||||||
|
overflowY: "auto",
|
||||||
|
scrollbarWidth: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{annotations.map((coord, index) => (
|
||||||
|
<li key={index}>
|
||||||
|
<span style={{ fontSize: 13, fontWeight: 500 }}>{`Box ${
|
||||||
|
index + 1
|
||||||
|
}:`}</span>
|
||||||
|
<code
|
||||||
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
|
color: "black",
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{` ["page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`}
|
||||||
|
</code>
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
borderRadius: 4,
|
||||||
|
padding: "3px 5px",
|
||||||
|
border: "1px solid gray",
|
||||||
|
fontSize: 12,
|
||||||
|
margin: 2,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
copytoclipboard(
|
||||||
|
`"page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-copy"></i>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
borderRadius: 4,
|
||||||
|
padding: "3px 5px",
|
||||||
|
border: "1px solid gray",
|
||||||
|
fontSize: 12,
|
||||||
|
margin: 2,
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
onClick={() => handleDelete(coord.key)}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-trash-can"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<ModalUi title={"Select PDF"} isOpen={isModal}>
|
||||||
|
<form onSubmit={handleSubmit} style={{ margin: "10px" }}>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={(e) => handleFileChange(e.target.files)}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
border: "1px solid grey",
|
||||||
|
borderRadius: "4px",
|
||||||
|
padding: "5px",
|
||||||
|
fontSize: 12
|
||||||
|
}}
|
||||||
|
accept=".pdf"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{ borderTop: "1px solid grey", margin: "10px 0" }}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
background: "#32a3ac",
|
||||||
|
borderRadius: "2px",
|
||||||
|
boxShadow:
|
||||||
|
"0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18)",
|
||||||
|
border: "none",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: "600",
|
||||||
|
padding: "0.375rem 0.75rem",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "#ffffff",
|
||||||
|
outline: "none"
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DebugPdf;
|
||||||
@@ -4,13 +4,15 @@ 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";
|
||||||
function ForgotPassword(props) {
|
function ForgotPassword(props) {
|
||||||
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,7 +25,7 @@ function ForgotPassword(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
localStorage.setItem("appLogo", props.appInfo.applogo);
|
localStorage.setItem("appLogo", props.appInfo.applogo);
|
||||||
localStorage.setItem("appName", props.appInfo.appname);
|
localStorage.setItem("appName", props.appInfo.appname);
|
||||||
@@ -33,14 +35,22 @@ function ForgotPassword(props) {
|
|||||||
"userSettings",
|
"userSettings",
|
||||||
JSON.stringify(props.appInfo.settings)
|
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"));
|
props.fetchAppInfo();
|
||||||
resize();
|
resize();
|
||||||
window.addEventListener("resize", resize);
|
window.addEventListener("resize", resize);
|
||||||
return () => window.removeEventListener("resize", resize);
|
return () => window.removeEventListener("resize", resize);
|
||||||
@@ -51,6 +61,14 @@ function ForgotPassword(props) {
|
|||||||
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">
|
||||||
@@ -0,0 +1,416 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { formJson } from "../json/FormJson";
|
||||||
|
import AddUser from "../components/AddUser";
|
||||||
|
import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||||
|
import Parse from "parse";
|
||||||
|
import DropboxChooser from "../components/shared/fields/DropboxChoose";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import SelectFolder from "../components/shared/fields/SelectFolder";
|
||||||
|
import SignersInput from "../components/shared/fields/SignersInput";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import PageNotFound from "./PageNotFound";
|
||||||
|
|
||||||
|
function Form() {
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
if (id === "lM0xRnM3iE") {
|
||||||
|
return <AddUser />;
|
||||||
|
} else {
|
||||||
|
const config = formJson[id];
|
||||||
|
if (config) {
|
||||||
|
return <Forms {...config} />;
|
||||||
|
} else {
|
||||||
|
return <PageNotFound prefix={"Form"} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Forms = (props) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [signers, setSigners] = useState([]);
|
||||||
|
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
Name: "",
|
||||||
|
Description: "",
|
||||||
|
Note: "Please review and sign this document",
|
||||||
|
TimeToCompleteDays: 15,
|
||||||
|
SendinOrder: "false"
|
||||||
|
});
|
||||||
|
const [fileupload, setFileUpload] = useState([]);
|
||||||
|
const [fileload, setfileload] = useState(false);
|
||||||
|
const [percentage, setpercentage] = useState(0);
|
||||||
|
const [isAlert, setIsAlert] = useState(false);
|
||||||
|
const [isSubmit, setIsSubmit] = useState(false);
|
||||||
|
const [isErr, setIsErr] = useState("");
|
||||||
|
const handleStrInput = (e) => {
|
||||||
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileInput = (e) => {
|
||||||
|
setpercentage(0);
|
||||||
|
try {
|
||||||
|
let files = e.target.files;
|
||||||
|
if (typeof files[0] !== "undefined") {
|
||||||
|
const mb = Math.round(files[0].bytes / Math.pow(1024, 2));
|
||||||
|
if (mb > 10) {
|
||||||
|
alert(
|
||||||
|
`The selected file size is too large. Please select a file less than ${Math.round(
|
||||||
|
10
|
||||||
|
)} MB`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFileUpload(files[0]);
|
||||||
|
} else {
|
||||||
|
alert("Please select file.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert(error.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileUpload = async (file) => {
|
||||||
|
setfileload(true);
|
||||||
|
const fileName = file.name;
|
||||||
|
const name = sanitizeFileName(fileName);
|
||||||
|
const pdfFile = file;
|
||||||
|
const parseFile = new Parse.File(name, pdfFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await parseFile.save({
|
||||||
|
progress: (progressValue, loaded, total, { type }) => {
|
||||||
|
if (type === "upload" && progressValue !== null) {
|
||||||
|
const percentCompleted = Math.round((loaded * 100) / total);
|
||||||
|
setpercentage(percentCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The response object will contain information about the uploaded file
|
||||||
|
// You can access the URL of the uploaded file using response.url()
|
||||||
|
setFileUpload(response.url());
|
||||||
|
setfileload(false);
|
||||||
|
if (response.url()) {
|
||||||
|
return response.url();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
console.error("Error uploading file:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dropboxSuccess = async (files) => {
|
||||||
|
setfileload(true);
|
||||||
|
const file = files[0];
|
||||||
|
const url = file.link;
|
||||||
|
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
||||||
|
|
||||||
|
if (mb > 10) {
|
||||||
|
setTimeout(() => {
|
||||||
|
alert(
|
||||||
|
`The selected file size is too large. Please select a file less than 10 MB`
|
||||||
|
);
|
||||||
|
}, 500);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const name = sanitizeFileName(file.name);
|
||||||
|
|
||||||
|
const parseFile = new Parse.File(name, { uri: url });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await parseFile.save({
|
||||||
|
progress: (progressValue, loaded, total, { type }) => {
|
||||||
|
if (type === "upload" && progressValue !== null) {
|
||||||
|
const percentCompleted = Math.round((loaded * 100) / total);
|
||||||
|
setpercentage(percentCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setFileUpload(response.url());
|
||||||
|
setfileload(false);
|
||||||
|
|
||||||
|
if (response.url()) {
|
||||||
|
return response.url();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
console.error("Error uploading file:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const dropboxCancel = async () => {};
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsSubmit(true);
|
||||||
|
try {
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
const object = new Parse.Object(props.Cls);
|
||||||
|
object.set("Name", formData?.Name);
|
||||||
|
object.set("Description", formData?.Description);
|
||||||
|
object.set("Note", formData?.Note);
|
||||||
|
if (props.title === "Request Signatures") {
|
||||||
|
object.set(
|
||||||
|
"TimeToCompleteDays",
|
||||||
|
parseInt(formData?.TimeToCompleteDays)
|
||||||
|
);
|
||||||
|
const isChecked = formData.SendinOrder === "true" ? true : false;
|
||||||
|
object.set("SendinOrder", isChecked);
|
||||||
|
}
|
||||||
|
object.set("URL", fileupload);
|
||||||
|
object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||||
|
if (folder && folder.ObjectId) {
|
||||||
|
object.set("Folder", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: props.Cls,
|
||||||
|
objectId: folder.ObjectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (signers && signers.length > 0) {
|
||||||
|
object.set("Signers", signers);
|
||||||
|
}
|
||||||
|
const ExtCls = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
|
object.set("ExtUserPtr", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "contracts_Users",
|
||||||
|
objectId: ExtCls[0].objectId
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await object.save();
|
||||||
|
if (res) {
|
||||||
|
setSigners([]);
|
||||||
|
setFolder({ ObjectId: "", Name: "" });
|
||||||
|
setFormData({
|
||||||
|
Name: "",
|
||||||
|
Description: "",
|
||||||
|
Note: ""
|
||||||
|
});
|
||||||
|
setFileUpload([]);
|
||||||
|
setpercentage(0);
|
||||||
|
navigate(`/${props?.redirectRoute}/${res.id}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err ", err);
|
||||||
|
setIsErr(true);
|
||||||
|
} finally {
|
||||||
|
setIsAlert(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsAlert(false);
|
||||||
|
}, 1000);
|
||||||
|
setIsSubmit(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFolder = (data) => {
|
||||||
|
setFolder(data);
|
||||||
|
};
|
||||||
|
const handleSigners = (data) => {
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
const updateSigners = data.map((x) => ({
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "contracts_Contactbook",
|
||||||
|
objectId: x
|
||||||
|
}));
|
||||||
|
setSigners(updateSigners);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
setSigners([]);
|
||||||
|
setFolder({ ObjectId: "", Name: "" });
|
||||||
|
setFormData({
|
||||||
|
Name: "",
|
||||||
|
Description: "",
|
||||||
|
Note: ""
|
||||||
|
});
|
||||||
|
setFileUpload([]);
|
||||||
|
setpercentage(0);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
||||||
|
<Title title={props?.title} />
|
||||||
|
{isAlert && (
|
||||||
|
<Alert type={isErr ? "danger" : "success"}>
|
||||||
|
{isErr
|
||||||
|
? "Something went wrong please try again!"
|
||||||
|
: `${props.msgVar} created successfully!`}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
{isSubmit ? (
|
||||||
|
<div style={{ height: "300px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "45%",
|
||||||
|
marginTop: "150px",
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<h1 className="text-[20px] font-semibold mb-4">{props?.title}</h1>
|
||||||
|
{fileload && (
|
||||||
|
<div className="flex items-center gap-x-2">
|
||||||
|
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
|
||||||
|
<div
|
||||||
|
className="h-2 rounded-full bg-blue-500"
|
||||||
|
style={{ width: `${percentage}%` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<span className="text-black text-sm">{percentage}%</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="text-xs">
|
||||||
|
<label className="block">
|
||||||
|
File<span className="text-red-500 text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
{fileupload.length > 0 ? (
|
||||||
|
<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="break-all">
|
||||||
|
file selected :{" "}
|
||||||
|
{fileupload?.split("/")?.pop()?.split("_")[1]}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
setFileUpload([]);
|
||||||
|
}}
|
||||||
|
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-xmark"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
||||||
|
<DropboxChooser
|
||||||
|
onSuccess={dropboxSuccess}
|
||||||
|
onCancel={dropboxCancel}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex gap-2 justify-center items-center">
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
onChange={(e) => handleFileInput(e)}
|
||||||
|
accept="application/pdf"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
||||||
|
<DropboxChooser
|
||||||
|
onSuccess={dropboxSuccess}
|
||||||
|
onCancel={dropboxCancel}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
Title<span className="text-red-500 text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="Name"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
value={formData.Name}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">Description</label>
|
||||||
|
<input
|
||||||
|
name="Description"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
value={formData.Description}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{props.signers && <SignersInput onChange={handleSigners} required />}
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
Note<span className="text-red-500 text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="Note"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
value={formData.Note}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<SelectFolder onSuccess={handleFolder} folderCls={props.Cls} />
|
||||||
|
|
||||||
|
{props.title === "Request Signatures" && (
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
Time To Complete (Days)
|
||||||
|
<span className="text-red-500 text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="TimeToCompleteDays"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
value={formData.TimeToCompleteDays}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.title !== "Sign Yourself" && (
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">Send In Order</label>
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
name="SendinOrder"
|
||||||
|
checked={formData.SendinOrder === "true"}
|
||||||
|
className=""
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">Yes</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="SendinOrder"
|
||||||
|
checked={formData.SendinOrder === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">No</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
|
<button
|
||||||
|
className={`${
|
||||||
|
isSubmit && "cursor-progress"
|
||||||
|
} bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none`}
|
||||||
|
type="submit"
|
||||||
|
disabled={isSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<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"
|
||||||
|
onClick={() => handleReset()}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Form;
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import axios from "axios";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import { rejectBtn, submitBtn } from "../constant/const";
|
||||||
|
import { openInNewTab } from "../constant/Utils";
|
||||||
|
|
||||||
|
function GenerateToken() {
|
||||||
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
|
const [apiToken, SetApiToken] = useState("");
|
||||||
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
const [isGenerate, setIsGenerate] = useState(false);
|
||||||
|
const [isErr, setIsErr] = useState(false);
|
||||||
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchToken();
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchToken = async () => {
|
||||||
|
try {
|
||||||
|
const url = parseBaseUrl + "functions/getapitoken";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
const res = await axios.post(url, {}, { headers: headers });
|
||||||
|
if (res) {
|
||||||
|
SetApiToken(res.data.result.result);
|
||||||
|
}
|
||||||
|
setIsLoader(false);
|
||||||
|
} catch (err) {
|
||||||
|
SetApiToken();
|
||||||
|
setIsLoader(false);
|
||||||
|
console.log("Err", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsLoader(true);
|
||||||
|
setIsModal(false);
|
||||||
|
try {
|
||||||
|
const url = parseBaseUrl + "functions/generateapitoken";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
await axios.post(url, {}, { headers: headers }).then((res) => {
|
||||||
|
if (res) {
|
||||||
|
SetApiToken(res.data.result.token);
|
||||||
|
// localStorage.setItem("apiToken", res.data.result.token);
|
||||||
|
setIsGenerate(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsGenerate(false);
|
||||||
|
}, 1500);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else {
|
||||||
|
console.error("Error while generating Token");
|
||||||
|
setIsLoader(false);
|
||||||
|
setIsErr(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsErr(false);
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoader(false);
|
||||||
|
setIsErr(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsErr(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const copytoclipboard = (text) => {
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setCopied(false);
|
||||||
|
}, 1500); // Reset copied state after 1.5 seconds
|
||||||
|
};
|
||||||
|
const handleModal = () => setIsModal(!isModal);
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Title title={"API Token"} />
|
||||||
|
{isGenerate && (
|
||||||
|
<Alert type="success">Token generated successfully!</Alert>
|
||||||
|
)}
|
||||||
|
{copied && <Alert type="success">Copied</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">
|
||||||
|
<h1 className="ml-4 mt-3 mb-2 font-semibold">API Token</h1>
|
||||||
|
<ul className="w-full flex flex-col p-2 text-sm">
|
||||||
|
<li
|
||||||
|
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<span className="w-[40%]">Api Token:</span>{" "}
|
||||||
|
<span
|
||||||
|
id="token"
|
||||||
|
className="w-[60%] md:text-end cursor-pointer"
|
||||||
|
onClick={() => copytoclipboard(apiToken)}
|
||||||
|
>
|
||||||
|
{apiToken && apiToken}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
||||||
|
<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 ? "Regenerate Token" : "Generate Token"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
openInNewTab(
|
||||||
|
"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"
|
||||||
|
>
|
||||||
|
View Docs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isModal}
|
||||||
|
title={"Regenerate Token"}
|
||||||
|
handleClose={handleModal}
|
||||||
|
>
|
||||||
|
<div className="m-[20px]">
|
||||||
|
<div className="text-lg font-normal text-black">
|
||||||
|
Are you sure you want to regenerate token it will expire old
|
||||||
|
token?
|
||||||
|
</div>
|
||||||
|
<hr className="bg-[#ccc] mt-4 " />
|
||||||
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
|
<button
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className={submitBtn + "ml-[2px]"}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button onClick={handleModal} className={rejectBtn}>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GenerateToken;
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
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 { 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 +16,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
|
||||||
@@ -103,24 +102,29 @@ function Login() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
} else {
|
} else {
|
||||||
let _user = user.data.result;
|
let _user = user.data.result;
|
||||||
|
const parseId = localStorage.getItem("parseAppId");
|
||||||
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
||||||
|
localStorage.setItem(
|
||||||
|
`Parse/${parseId}/currentUser`,
|
||||||
|
JSON.stringify(_user)
|
||||||
|
);
|
||||||
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={{
|
||||||
@@ -184,7 +188,7 @@ function Login() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
@@ -201,7 +205,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"
|
||||||
}}
|
}}
|
||||||
@@ -237,7 +241,7 @@ function Login() {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
background: themeColor(),
|
background: themeColor,
|
||||||
color: "white"
|
color: "white"
|
||||||
}}
|
}}
|
||||||
className="verifyBtn"
|
className="verifyBtn"
|
||||||
@@ -256,7 +260,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"
|
||||||
@@ -274,4 +278,4 @@ function Login() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Login;
|
export default GuestLogin;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
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 { connect } from "react-redux";
|
||||||
import { fetchAppInfo, showTenantName } from "../redux/actions";
|
import { fetchAppInfo, showTenantName } from "../redux/actions";
|
||||||
@@ -8,17 +7,21 @@ import axios from "axios";
|
|||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import GoogleSignInBtn from "../components/LoginGoogle";
|
import GoogleSignInBtn from "../components/LoginGoogle";
|
||||||
// import LoginFacebook from "../components/LoginFacebook";
|
// import LoginFacebook from "../components/LoginFacebook";
|
||||||
import { NavLink, useNavigate } from "react-router-dom";
|
import { NavLink, useNavigate, 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 { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
|
||||||
function Login(props) {
|
function Login(props) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
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: "",
|
||||||
@@ -41,11 +44,7 @@ function Login(props) {
|
|||||||
setState({ ...state, loading: true });
|
setState({ ...state, loading: true });
|
||||||
GetLoginData();
|
GetLoginData();
|
||||||
}
|
}
|
||||||
props.fetchAppInfo(
|
props.fetchAppInfo();
|
||||||
localStorage.getItem("domain"),
|
|
||||||
localStorage.getItem("BaseUrl12"),
|
|
||||||
localStorage.getItem("AppID12")
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
@@ -64,8 +63,6 @@ function Login(props) {
|
|||||||
let parseAppId = localStorage.getItem("parseAppId");
|
let parseAppId = localStorage.getItem("parseAppId");
|
||||||
localStorage.setItem("appLogo", props.appInfo.applogo);
|
localStorage.setItem("appLogo", props.appInfo.applogo);
|
||||||
localStorage.setItem("appName", props.appInfo.appname);
|
localStorage.setItem("appName", props.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) => {
|
||||||
@@ -132,6 +129,9 @@ function Login(props) {
|
|||||||
`${localStorage.getItem("_appName")}_appeditor`
|
`${localStorage.getItem("_appName")}_appeditor`
|
||||||
) {
|
) {
|
||||||
userSettings.forEach(async (element) => {
|
userSettings.forEach(async (element) => {
|
||||||
|
const redirectUrl =
|
||||||
|
location?.state?.from ||
|
||||||
|
`/${element.pageType}/${element.pageId}`;
|
||||||
if (element.role === _currentRole) {
|
if (element.role === _currentRole) {
|
||||||
let _role = _currentRole.replace(
|
let _role = _currentRole.replace(
|
||||||
`${localStorage.getItem("_appName")}_`,
|
`${localStorage.getItem("_appName")}_`,
|
||||||
@@ -143,11 +143,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")
|
||||||
@@ -260,9 +255,8 @@ function Login(props) {
|
|||||||
localStorage.removeItem(
|
localStorage.removeItem(
|
||||||
"userDetails"
|
"userDetails"
|
||||||
);
|
);
|
||||||
navigate(
|
// Redirect to the appropriate URL after successful login
|
||||||
`/${element.pageType}/${element.pageId}`
|
navigate(redirectUrl);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, {
|
navigate(`/subscription`, {
|
||||||
replace: true
|
replace: true
|
||||||
@@ -274,9 +268,8 @@ function Login(props) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
// Redirect to the appropriate URL after successful login
|
||||||
`/${element.pageType}/${element.pageId}`
|
navigate(redirectUrl);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -313,9 +306,8 @@ function Login(props) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
// Redirect to the appropriate URL after successful login
|
||||||
`/${element.pageType}/${element.pageId}`
|
navigate(redirectUrl);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -351,13 +343,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);
|
||||||
}
|
}
|
||||||
@@ -367,13 +362,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);
|
||||||
});
|
});
|
||||||
@@ -388,8 +386,8 @@ function Login(props) {
|
|||||||
setState({ ...state, thirdpartyLoader: value });
|
setState({ ...state, thirdpartyLoader: value });
|
||||||
};
|
};
|
||||||
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,
|
||||||
@@ -462,6 +460,9 @@ function Login(props) {
|
|||||||
`${localStorage.getItem("_appName")}_appeditor`
|
`${localStorage.getItem("_appName")}_appeditor`
|
||||||
) {
|
) {
|
||||||
userSettings.forEach(async (element) => {
|
userSettings.forEach(async (element) => {
|
||||||
|
const redirectUrl =
|
||||||
|
location?.state?.from ||
|
||||||
|
`/${element.pageType}/${element.pageId}`;
|
||||||
if (element.role === _currentRole) {
|
if (element.role === _currentRole) {
|
||||||
let _role = _currentRole.replace(
|
let _role = _currentRole.replace(
|
||||||
`${localStorage.getItem("_appName")}_`,
|
`${localStorage.getItem("_appName")}_`,
|
||||||
@@ -474,7 +475,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")
|
||||||
@@ -569,9 +569,7 @@ function Login(props) {
|
|||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(
|
navigate(redirectUrl);
|
||||||
`/${element.pageType}/${element.pageId}`
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, {
|
navigate(`/subscription`, {
|
||||||
replace: true
|
replace: true
|
||||||
@@ -581,9 +579,7 @@ function Login(props) {
|
|||||||
navigate(`/subscription`, { replace: true });
|
navigate(`/subscription`, { replace: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
navigate(redirectUrl);
|
||||||
`/${element.pageType}/${element.pageId}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -599,9 +595,8 @@ function Login(props) {
|
|||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(
|
// Redirect to the appropriate URL after successful login
|
||||||
`/${element.pageType}/${element.pageId}`
|
navigate(redirectUrl);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
navigate(`/subscription`, { replace: true });
|
||||||
}
|
}
|
||||||
@@ -609,9 +604,7 @@ function Login(props) {
|
|||||||
navigate(`/subscription`, { replace: true });
|
navigate(`/subscription`, { replace: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
navigate(redirectUrl);
|
||||||
`/${element.pageType}/${element.pageId}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -648,13 +641,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);
|
||||||
}
|
}
|
||||||
@@ -664,8 +660,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));
|
||||||
@@ -718,13 +712,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];
|
||||||
@@ -803,14 +801,16 @@ function Login(props) {
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
toastColor: "#d9534f",
|
alertType: "danger",
|
||||||
toastDescription:
|
alertMsg: "You don`t have access to this application!"
|
||||||
"You don`t have access to 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);
|
||||||
localStorage.setItem("accesstoken", null);
|
localStorage.setItem("accesstoken", null);
|
||||||
console.error("Error while fetching Follow", error);
|
console.error("Error while fetching Follow", error);
|
||||||
@@ -896,8 +896,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();
|
||||||
|
|
||||||
@@ -908,8 +908,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">
|
||||||
@@ -1125,109 +1125,78 @@ 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>
|
||||||
{isModal && (
|
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
|
||||||
<div
|
<form className="px-4 py-3">
|
||||||
className="modal fade show"
|
<div className="mb-3">
|
||||||
id="exampleModal"
|
<label
|
||||||
tabIndex="-1"
|
htmlFor="Company"
|
||||||
role="dialog"
|
style={{ display: "flex" }}
|
||||||
style={{
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
display: "block",
|
>
|
||||||
zIndex: 1,
|
Company <span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||||
backgroundColor: "rgba(0,0,0,0.5)"
|
</label>
|
||||||
}}
|
<input
|
||||||
>
|
type="text"
|
||||||
<div className="modal-dialog" role="document">
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
<div className="modal-content">
|
id="Company"
|
||||||
<div className="modal-header">
|
value={userDetails.Company}
|
||||||
<h5 className="modal-title font-semibold">
|
onChange={(e) =>
|
||||||
Additional Info
|
setUserDetails({
|
||||||
</h5>
|
...userDetails,
|
||||||
<span>
|
Company: e.target.value
|
||||||
<span></span>
|
})
|
||||||
</span>
|
}
|
||||||
</div>
|
required
|
||||||
<div className="modal-body">
|
/>
|
||||||
<form className="text-sm">
|
|
||||||
<div className="form-group">
|
|
||||||
<label
|
|
||||||
htmlFor="Company"
|
|
||||||
style={{ display: "flex" }}
|
|
||||||
className="col-form-label"
|
|
||||||
>
|
|
||||||
Company{" "}
|
|
||||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
id="Company"
|
|
||||||
value={userDetails.Company}
|
|
||||||
onChange={(e) =>
|
|
||||||
setUserDetails({
|
|
||||||
...userDetails,
|
|
||||||
Company: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
|
||||||
<label
|
|
||||||
htmlFor="JobTitle"
|
|
||||||
style={{ display: "flex" }}
|
|
||||||
className="col-form-label"
|
|
||||||
>
|
|
||||||
Job Title
|
|
||||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
id="JobTitle"
|
|
||||||
value={userDetails.Destination}
|
|
||||||
onChange={(e) =>
|
|
||||||
setUserDetails({
|
|
||||||
...userDetails,
|
|
||||||
Destination: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="bg-[#17a2b8] text-sm p-2 text-white rounded uppercase"
|
|
||||||
onClick={(e) => handleSubmitbtn(e)}
|
|
||||||
style={{ marginRight: 10 }}
|
|
||||||
>
|
|
||||||
Login
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="bg-[#6c757d] text-sm p-2 text-white rounded uppercase"
|
|
||||||
onClick={handleCloseModal}
|
|
||||||
style={{ width: 90 }}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="mb-3">
|
||||||
)}
|
<label
|
||||||
|
htmlFor="JobTitle"
|
||||||
|
style={{ display: "flex" }}
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
Job Title
|
||||||
|
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
id="JobTitle"
|
||||||
|
value={userDetails.Destination}
|
||||||
|
onChange={(e) =>
|
||||||
|
setUserDetails({
|
||||||
|
...userDetails,
|
||||||
|
Destination: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none "
|
||||||
|
onClick={(e) => handleSubmitbtn(e)}
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
backgroundColor: modalSubmitBtnColor
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none"
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
style={{ width: 75, backgroundColor: modalCancelBtnColor }}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
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 { 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();
|
||||||
@@ -19,7 +15,7 @@ const ManageSign = () => {
|
|||||||
const [warning, setWarning] = useState(false);
|
const [warning, setWarning] = useState(false);
|
||||||
const [nameWarning, setNameWarning] = 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();
|
||||||
@@ -142,7 +107,6 @@ const ManageSign = () => {
|
|||||||
|
|
||||||
if (!signName) {
|
if (!signName) {
|
||||||
setNameWarning(true);
|
setNameWarning(true);
|
||||||
|
|
||||||
} else if (!isvalue) {
|
} else if (!isvalue) {
|
||||||
setWarning(true);
|
setWarning(true);
|
||||||
setTimeout(() => setWarning(false), 1000);
|
setTimeout(() => setWarning(false), 1000);
|
||||||
@@ -151,29 +115,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 +158,54 @@ 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();
|
return response?.url();
|
||||||
formData.append("file", file);
|
} catch (err) {
|
||||||
const config = {
|
console.log("sign upload err", err);
|
||||||
headers: {
|
setIsLoader(false);
|
||||||
"content-type": "multipart/form-data",
|
alert(`${err.message}`);
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
}
|
||||||
},
|
|
||||||
onUploadProgress: function (progressEvent) {
|
|
||||||
let percentCompleted = Math.round(
|
|
||||||
(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 = () => {
|
||||||
@@ -319,10 +224,26 @@ const ManageSign = () => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
backgroundColor: "white",
|
||||||
maxHeight: "500px",
|
maxHeight: "500px",
|
||||||
overflow: "auto",
|
overflow: "auto"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{isLoader && (
|
||||||
|
<div className="absolute bg-black bg-opacity-75 inset-0 z-50 flex justify-center items-center">
|
||||||
|
<div style={{ height: "300px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "45%",
|
||||||
|
marginTop: "150px",
|
||||||
|
fontSize: "45px",
|
||||||
|
color: "#3dd3e0"
|
||||||
|
}}
|
||||||
|
className="loader-37"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
<div
|
<div
|
||||||
className="alert alert-success successBox"
|
className="alert alert-success successBox"
|
||||||
@@ -332,12 +253,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,7 +266,7 @@ const ManageSign = () => {
|
|||||||
fontWeight: "700",
|
fontWeight: "700",
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: "#000",
|
color: "#000",
|
||||||
paddingBottom: 8,
|
paddingBottom: 8
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Manage Signature
|
Manage Signature
|
||||||
@@ -357,10 +277,10 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
position: "relative",
|
position: "relative",
|
||||||
paddingBottom: 5,
|
paddingBottom: 5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Signer's Name
|
Signer's Name
|
||||||
{nameWarning && (
|
{nameWarning && (
|
||||||
<div
|
<div
|
||||||
className="warning nameWarning"
|
className="warning nameWarning"
|
||||||
@@ -386,7 +306,7 @@ const ManageSign = () => {
|
|||||||
height: 35,
|
height: 35,
|
||||||
padding: "6px 12px",
|
padding: "6px 12px",
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
fontSize: 12,
|
fontSize: 12
|
||||||
}}
|
}}
|
||||||
required
|
required
|
||||||
onFocus={() => setNameWarning(false)}
|
onFocus={() => setNameWarning(false)}
|
||||||
@@ -397,7 +317,7 @@ const ManageSign = () => {
|
|||||||
htmlFor="imgoverview"
|
htmlFor="imgoverview"
|
||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
paddingBottom: 5,
|
paddingBottom: 5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Signature/Image
|
Signature/Image
|
||||||
@@ -412,7 +332,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 +342,7 @@ const ManageSign = () => {
|
|||||||
justifyContent: "space-around",
|
justifyContent: "space-around",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 10,
|
gap: 10,
|
||||||
marginBottom: 10,
|
marginBottom: 10
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
@@ -456,9 +376,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 +386,7 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
objectFit: "contain",
|
objectFit: "contain"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -479,7 +397,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 +410,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,19 +421,18 @@ 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"
|
||||||
: key === 1 && penColor === "red"
|
: key === 1 && penColor === "red"
|
||||||
? "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 +444,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 +456,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 +481,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 +498,7 @@ const ManageSign = () => {
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
objectFit: "contain",
|
objectFit: "contain"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -598,9 +507,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,29 +520,27 @@ 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"
|
||||||
: key === 1 && initialPen === "red"
|
: key === 1 && initialPen === "red"
|
||||||
? "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 +552,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 +564,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 +592,6 @@ const ManageSign = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isLoader && (
|
|
||||||
<div className="loaderContainer">
|
|
||||||
<div className="loader"></div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
import axios from "axios";
|
import "../styles/opensigndrive.css";
|
||||||
import "./LegaDrive.css";
|
import loader from "../assets/images/loader2.gif";
|
||||||
import loader from "../../assests/loader2.gif";
|
import DriveBody from "../components/opensigndrive/DriveBody";
|
||||||
import PdfFileComponent from "./FolderDrive/legaDriveComponent";
|
import { themeColor, iconColor } from "../constant/const";
|
||||||
import Modal from "react-bootstrap/Modal";
|
import { getDrive } from "../constant/Utils";
|
||||||
import ModalHeader from "react-bootstrap/esm/ModalHeader";
|
|
||||||
import { themeColor, iconColor } from "../../utils/ThemeColor/backColor";
|
|
||||||
import { getDrive } from "../../utils/Utils";
|
|
||||||
import AlertComponent from "../component/alertComponent";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import Parse from "parse";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
|
||||||
function PdfFile() {
|
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);
|
||||||
@@ -27,7 +26,7 @@ function PdfFile() {
|
|||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
});
|
});
|
||||||
const [docId, setDocId] = useState();
|
const [docId, setDocId] = useState();
|
||||||
const [handleError, setHandleError] = useState();
|
const [handleError, setHandleError] = useState("");
|
||||||
const [folderName, setFolderName] = useState([]);
|
const [folderName, setFolderName] = useState([]);
|
||||||
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
||||||
const [isNewFol, setIsNewFol] = useState(false);
|
const [isNewFol, setIsNewFol] = useState(false);
|
||||||
@@ -46,6 +45,7 @@ function PdfFile() {
|
|||||||
} else {
|
} else {
|
||||||
getPdfDocumentList();
|
getPdfDocumentList();
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
}, [docId]);
|
}, [docId]);
|
||||||
|
|
||||||
//function for get all pdf document list
|
//function for get all pdf document list
|
||||||
@@ -54,29 +54,38 @@ function PdfFile() {
|
|||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
};
|
};
|
||||||
|
let driveDetails;
|
||||||
setIsLoading(load);
|
setIsLoading(load);
|
||||||
const driveDetails = await getDrive();
|
try {
|
||||||
if (driveDetails) {
|
driveDetails = await getDrive();
|
||||||
if (driveDetails.length > 0) {
|
if (driveDetails) {
|
||||||
setPdfData(driveDetails);
|
if (driveDetails.length > 0) {
|
||||||
}
|
setPdfData(driveDetails);
|
||||||
const data = [
|
sortApps(null, null, driveDetails);
|
||||||
{
|
|
||||||
name: "OpenSignDrive™",
|
|
||||||
objectId: ""
|
|
||||||
}
|
}
|
||||||
];
|
const data = [
|
||||||
setFolderName(data);
|
{
|
||||||
const loadObj = {
|
name: "OpenSign™ Drive",
|
||||||
isLoad: false
|
objectId: ""
|
||||||
};
|
}
|
||||||
setIsLoading(loadObj);
|
];
|
||||||
} else if (driveDetails === "Error: Something went wrong!") {
|
setFolderName(data);
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
setHandleError("Error: Something went wrong!");
|
setIsLoading(loadObj);
|
||||||
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 parent folder document list
|
//function for get parent folder document list
|
||||||
@@ -86,23 +95,33 @@ function PdfFile() {
|
|||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
};
|
};
|
||||||
setIsLoading(load);
|
setIsLoading(load);
|
||||||
const driveDetails = await getDrive(docId);
|
let driveDetails;
|
||||||
if (driveDetails) {
|
try {
|
||||||
if (driveDetails.length > 0) {
|
driveDetails = await getDrive(docId);
|
||||||
setPdfData(driveDetails);
|
|
||||||
} else {
|
if (driveDetails) {
|
||||||
setPdfData([]);
|
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);
|
||||||
}
|
}
|
||||||
const loadObj = {
|
} catch (e) {
|
||||||
isLoad: false
|
setIsAlert({
|
||||||
};
|
isShow: true,
|
||||||
setIsLoading(loadObj);
|
alertMessage: "something went wrong!"
|
||||||
} else if (driveDetails === "Error: Something went wrong!") {
|
});
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setHandleError("Error: Something went wrong!");
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,43 +130,16 @@ function PdfFile() {
|
|||||||
setIsFolder(true);
|
setIsFolder(true);
|
||||||
};
|
};
|
||||||
//function for handle folder name path
|
//function for handle folder name path
|
||||||
const handleRoute = (data) => {
|
const handleRoute = (index) => {
|
||||||
let loadObj = {
|
const updateFolderName = folderName.filter((x, i) => {
|
||||||
isLoad: true,
|
if (i <= index) {
|
||||||
message: "This might take some time"
|
return x;
|
||||||
};
|
|
||||||
if (data.name === "LegaDrive™") {
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
if (docId) {
|
|
||||||
setDocId();
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
} else if (data.name === folderName[folderName.length - 1].name) {
|
});
|
||||||
setIsLoading(loadObj);
|
|
||||||
setTimeout(() => {
|
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
const findIndex = folderName.findIndex(
|
|
||||||
(fold) => fold.objectId === data.objectId
|
|
||||||
);
|
|
||||||
const newFolder = folderName.slice(0, findIndex + 1);
|
|
||||||
|
|
||||||
setFolderName(newFolder);
|
setFolderName(updateFolderName);
|
||||||
const getLastId = newFolder[newFolder.length - 1];
|
const getLastId = updateFolderName[updateFolderName.length - 1];
|
||||||
|
setDocId(getLastId.objectId);
|
||||||
setDocId(getLastId.objectId);
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for add new folder name
|
//function for add new folder name
|
||||||
@@ -156,78 +148,60 @@ function PdfFile() {
|
|||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setNewFolderName(value);
|
setNewFolderName(value);
|
||||||
};
|
};
|
||||||
//function for add folder
|
//function for create folder
|
||||||
const handleAddFolder = async () => {
|
const handleAddFolder = async () => {
|
||||||
if (newFolderName) {
|
if (newFolderName) {
|
||||||
setIsFolderLoader(true);
|
setIsFolderLoader(true);
|
||||||
|
|
||||||
const getParentObjId = folderName[folderName.length - 1];
|
const getParentObjId = folderName[folderName.length - 1];
|
||||||
const parentId = getParentObjId && getParentObjId.objectId;
|
const parentId = getParentObjId && getParentObjId.objectId;
|
||||||
let data;
|
const foldercls = `${localStorage.getItem("_appName")}_Document`;
|
||||||
if (parentId) {
|
const folderPtr = {
|
||||||
data = {
|
__type: "Pointer",
|
||||||
Name: newFolderName,
|
className: foldercls,
|
||||||
Type: "Folder",
|
objectId: parentId
|
||||||
Folder: {
|
};
|
||||||
__type: "Pointer",
|
const CreatedBy = {
|
||||||
className: `${localStorage.getItem("_appName")}_Document`,
|
__type: "Pointer",
|
||||||
objectId: parentId
|
className: "_User",
|
||||||
},
|
objectId: jsonCurrentUser.objectId
|
||||||
CreatedBy: {
|
};
|
||||||
__type: "Pointer",
|
|
||||||
className: "_User",
|
|
||||||
objectId: jsonCurrentUser.objectId
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
data = {
|
|
||||||
Name: newFolderName,
|
|
||||||
Type: "Folder",
|
|
||||||
CreatedBy: {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: "_User",
|
|
||||||
objectId: jsonCurrentUser.objectId
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await axios
|
try {
|
||||||
.post(
|
const exsitQuery = new Parse.Query(foldercls);
|
||||||
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
exsitQuery.equalTo("Name", newFolderName);
|
||||||
"_appName"
|
exsitQuery.equalTo("Type", "Folder");
|
||||||
)}_Document`,
|
if (parentId) {
|
||||||
data,
|
exsitQuery.equalTo("Folder", folderPtr);
|
||||||
{
|
}
|
||||||
headers: {
|
const templExist = await exsitQuery.first();
|
||||||
"Content-Type": "application/json",
|
if (templExist) {
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
setError("Folder already exist!");
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
setIsFolderLoader(false);
|
||||||
}
|
} else {
|
||||||
}
|
const template = new Parse.Object(foldercls);
|
||||||
)
|
template.set("Name", newFolderName);
|
||||||
|
template.set("Type", "Folder");
|
||||||
|
|
||||||
.then((Listdata) => {
|
if (parentId) {
|
||||||
// console.log("Listdata ", Listdata);
|
template.set("Folder", folderPtr);
|
||||||
const json = Listdata.data;
|
}
|
||||||
// console.log("json ", json);
|
template.set("CreatedBy", CreatedBy);
|
||||||
if (json) {
|
const res = await template.save();
|
||||||
|
if (res) {
|
||||||
|
const result = JSON.parse(JSON.stringify(res));
|
||||||
|
|
||||||
|
setPdfData((prev) => [...prev, result]);
|
||||||
setNewFolderName();
|
setNewFolderName();
|
||||||
|
|
||||||
setIsFolderLoader(false);
|
setIsFolderLoader(false);
|
||||||
setIsFolder(false);
|
setIsFolder(false);
|
||||||
if (docId) {
|
|
||||||
getPdfFolderDocumentList();
|
|
||||||
} else {
|
|
||||||
getPdfDocumentList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.catch((err) => {
|
} catch (e) {
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: "something went wrong!"
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setError("Please fill out this field");
|
setError("Please fill out this field");
|
||||||
}
|
}
|
||||||
@@ -249,11 +223,11 @@ function PdfFile() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortApps = () => {
|
const sortApps = (type, order, driveDetails) => {
|
||||||
const selectedSortType = selectedSort;
|
const selectedSortType = type ? type : selectedSort ? selectedSort : "Date";
|
||||||
const sortOrder = sortingOrder;
|
const sortOrder = order ? order : sortingOrder ? sortingOrder : "Decending";
|
||||||
|
|
||||||
let sortingData = pdfData;
|
let sortingData = driveDetails;
|
||||||
if (selectedSortType === "Name") {
|
if (selectedSortType === "Name") {
|
||||||
sortingApp(sortingData, "Name", sortOrder);
|
sortingApp(sortingData, "Name", sortOrder);
|
||||||
} else if (selectedSortType === "Date") {
|
} else if (selectedSortType === "Date") {
|
||||||
@@ -315,9 +289,9 @@ function PdfFile() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const closeMenuOnOutsideClick = (e) => {
|
const closeMenuOnOutsideClick = (e) => {
|
||||||
if (isShowSort && !e.target.closest("#menu-container")) {
|
if (isShowSort && !e.target.closest("#menu-container")) {
|
||||||
setIsShowSort(false);
|
setIsShowSort(!isShowSort);
|
||||||
} else if (isNewFol && !e.target.closest("#folder-menu")) {
|
} else if (isNewFol && !e.target.closest("#folder-menu")) {
|
||||||
setIsNewFol(false);
|
setIsNewFol(!isNewFol);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -327,33 +301,88 @@ 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]);
|
}, [isShowSort, isNewFol]);
|
||||||
|
|
||||||
|
const handleFolderTab = (folderData) => {
|
||||||
|
return folderData.map((data, id) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={id}>
|
||||||
|
<span
|
||||||
|
onClick={() => handleRoute(id)}
|
||||||
|
style={{
|
||||||
|
color: "#a64b4e",
|
||||||
|
fontWeight: "400",
|
||||||
|
cursor: "pointer"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.name}
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: "#a64b4e",
|
||||||
|
fontWeight: "200",
|
||||||
|
cursor: "pointer",
|
||||||
|
margin: "0 4px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const oncloseFolder = () => {
|
||||||
|
setIsFolder(false);
|
||||||
|
setNewFolderName("");
|
||||||
|
setError("");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="folderComponent ">
|
<div style={{ backgroundColor: "white" }} className="folderComponent">
|
||||||
|
<Title title={"OpenSign™ Drive"} drive={true} />
|
||||||
<div>
|
<div>
|
||||||
<AlertComponent
|
<ModalUi
|
||||||
isShow={isAlert.isShow}
|
headerColor={"#dc3545"}
|
||||||
alertMessage={isAlert.alertMessage}
|
isOpen={isAlert.isShow}
|
||||||
setIsAlert={setIsAlert}
|
title={"Alert"}
|
||||||
/>
|
handleClose={() => {
|
||||||
<Modal show={isFolder}>
|
setIsAlert({
|
||||||
<ModalHeader style={{ background: themeColor() }}>
|
isShow: false,
|
||||||
<span style={{ color: "white" }}>Add New Folder</span>
|
alertMessage: ""
|
||||||
{!folderLoader && (
|
});
|
||||||
<span
|
}}
|
||||||
style={{ cursor: "pointer" }}
|
>
|
||||||
onClick={() => {
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
setNewFolderName("");
|
<p>{isAlert.alertMessage}</p>
|
||||||
setIsFolder(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
X
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</ModalHeader>
|
|
||||||
|
|
||||||
<Modal.Body>
|
<div
|
||||||
|
style={{
|
||||||
|
height: "1px",
|
||||||
|
backgroundColor: "#9f9f9f",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginBottom: "15px"
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setIsAlert({
|
||||||
|
isShow: false,
|
||||||
|
alertMessage: ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isFolder}
|
||||||
|
title={"Add New Folder"}
|
||||||
|
handleClose={oncloseFolder}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
{folderLoader ? (
|
{folderLoader ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -374,7 +403,13 @@ function PdfFile() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<form style={{ display: "flex", flexDirection: "column" }}>
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleAddFolder();
|
||||||
|
}}
|
||||||
|
style={{ display: "flex", flexDirection: "column" }}
|
||||||
|
>
|
||||||
<label
|
<label
|
||||||
style={{
|
style={{
|
||||||
margin: "10px 0px 10px 0px",
|
margin: "10px 0px 10px 0px",
|
||||||
@@ -382,57 +417,52 @@ function PdfFile() {
|
|||||||
fontWeight: "400"
|
fontWeight: "400"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Name*
|
Name
|
||||||
|
<span style={{ color: "red" }}>*</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
required
|
required
|
||||||
className="form-control"
|
className="form-control inputStyle"
|
||||||
type="text"
|
type="text"
|
||||||
value={newFolderName}
|
value={newFolderName}
|
||||||
onChange={(e) => handleFolderName(e)}
|
onChange={(e) => handleFolderName(e)}
|
||||||
// className="addFolderInput"
|
// className="addFolderInput"
|
||||||
/>
|
/>
|
||||||
<span style={{ color: "red", fontSize: "12px" }}>{error}</span>
|
<span
|
||||||
|
style={{ color: "red", fontSize: "12px", marginTop: "6px" }}
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
margin: "20px 10px 10px 10px ",
|
height: "1px",
|
||||||
display: "flex",
|
backgroundColor: "#9f9f9f",
|
||||||
alignItems: "flex-end",
|
width: "100%",
|
||||||
justifyContent: "flex-end",
|
marginTop: "15px",
|
||||||
alignContent: "flex-end"
|
marginBottom: "15px"
|
||||||
}}
|
}}
|
||||||
>
|
></div>
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
<button
|
<button
|
||||||
|
style={{ background: themeColor }}
|
||||||
type="submit"
|
type="submit"
|
||||||
style={{
|
|
||||||
borderRadius: "0px",
|
|
||||||
border: "1.5px solid #e3e2e1",
|
|
||||||
fontWeight: "600",
|
|
||||||
color: "black"
|
|
||||||
}}
|
|
||||||
className="finishBtn"
|
|
||||||
onClick={() => setIsFolder(false)}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => handleAddFolder()}
|
|
||||||
style={{
|
|
||||||
background: themeColor()
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
className="finishBtn"
|
className="finishBtn"
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="finishBtn cancelBtn"
|
||||||
|
onClick={oncloseFolder}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
</Modal.Body>
|
</div>
|
||||||
</Modal>
|
</ModalUi>
|
||||||
|
|
||||||
{isLoading.isLoad ? (
|
{isLoading.isLoad ? (
|
||||||
<div
|
<div
|
||||||
@@ -479,31 +509,7 @@ function PdfFile() {
|
|||||||
}}
|
}}
|
||||||
className="folderPath"
|
className="folderPath"
|
||||||
>
|
>
|
||||||
{folderName.map((data, id) => {
|
{handleFolderTab(folderName)}
|
||||||
return (
|
|
||||||
<span
|
|
||||||
key={id}
|
|
||||||
onClick={() => handleRoute(data)}
|
|
||||||
style={{
|
|
||||||
color: "#a64b4e",
|
|
||||||
fontWeight: "400",
|
|
||||||
cursor: "pointer"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{data.name}
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
color: "#a64b4e",
|
|
||||||
fontWeight: "200",
|
|
||||||
cursor: "pointer",
|
|
||||||
margin: "0 4px"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="dropMenuBD">
|
<div className="dropMenuBD">
|
||||||
<div
|
<div
|
||||||
@@ -517,7 +523,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
|
||||||
@@ -581,13 +587,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}
|
||||||
@@ -603,7 +609,7 @@ function PdfFile() {
|
|||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedSort("Name");
|
setSelectedSort("Name");
|
||||||
sortApps();
|
sortApps("Name", null, pdfData);
|
||||||
}}
|
}}
|
||||||
className="dropdown-item itemColor"
|
className="dropdown-item itemColor"
|
||||||
>
|
>
|
||||||
@@ -625,7 +631,7 @@ function PdfFile() {
|
|||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedSort("Date");
|
setSelectedSort("Date");
|
||||||
sortApps();
|
sortApps("Date", null, pdfData);
|
||||||
}}
|
}}
|
||||||
className="dropdown-item itemColor"
|
className="dropdown-item itemColor"
|
||||||
>
|
>
|
||||||
@@ -648,7 +654,7 @@ function PdfFile() {
|
|||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSortingOrder("Accending");
|
setSortingOrder("Accending");
|
||||||
sortApps();
|
sortApps(null, "Accending", pdfData);
|
||||||
}}
|
}}
|
||||||
className="dropdown-item itemColor"
|
className="dropdown-item itemColor"
|
||||||
>
|
>
|
||||||
@@ -670,7 +676,7 @@ function PdfFile() {
|
|||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSortingOrder("Decending");
|
setSortingOrder("Decending");
|
||||||
sortApps();
|
sortApps(null, "Decending", pdfData);
|
||||||
}}
|
}}
|
||||||
className="dropdown-item itemColor"
|
className="dropdown-item itemColor"
|
||||||
>
|
>
|
||||||
@@ -698,7 +704,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>
|
||||||
@@ -707,7 +713,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>
|
||||||
)}
|
)}
|
||||||
@@ -728,7 +734,7 @@ function PdfFile() {
|
|||||||
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<PdfFileComponent
|
<DriveBody
|
||||||
pdfData={pdfData}
|
pdfData={pdfData}
|
||||||
setFolderName={setFolderName}
|
setFolderName={setFolderName}
|
||||||
setIsLoading={setIsLoading}
|
setIsLoading={setIsLoading}
|
||||||
@@ -738,6 +744,7 @@ function PdfFile() {
|
|||||||
isDocId={docId}
|
isDocId={docId}
|
||||||
setPdfData={setPdfData}
|
setPdfData={setPdfData}
|
||||||
isList={isList}
|
isList={isList}
|
||||||
|
setIsAlert={setIsAlert}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@@ -747,4 +754,4 @@ function PdfFile() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfFile;
|
export default Opensigndrive;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
|
|
||||||
const PageNotFound = () => {
|
const PageNotFound = ({ prefix }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
|
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
|
||||||
<Title title={"Page Not Found"} />
|
<Title title={"Page Not Found"} />
|
||||||
@@ -10,7 +10,9 @@ const PageNotFound = () => {
|
|||||||
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black">
|
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black">
|
||||||
404
|
404
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-[30px] lg:text-[50px] text-black">Page Not Found</p>
|
<p className="text-[30px] lg:text-[50px] text-black">
|
||||||
|
{prefix ? prefix : "Page"} Not Found
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||