mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-05 01:07:39 +02:00
Compare commits
321
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2afe37942 | ||
|
|
41c3b4746d | ||
|
|
f52d013b06 | ||
|
|
0045603cb0 | ||
|
|
4235bc077d | ||
|
|
58b3cc6ba2 | ||
|
|
97f5d09306 | ||
|
|
fa98972b27 | ||
|
|
76848b7e09 | ||
|
|
c3faaa65b9 | ||
|
|
e819513650 | ||
|
|
dd0e2f0e58 | ||
|
|
fa08efeac6 | ||
|
|
f3ba02496c | ||
|
|
5cbbb00f66 | ||
|
|
7050df8b4c | ||
|
|
4fb27f4896 | ||
|
|
145aa5da97 | ||
|
|
1a455415f1 | ||
|
|
44ef1fe825 | ||
|
|
cb07e376d5 | ||
|
|
9b472a6b8b | ||
|
|
9840fe9412 | ||
|
|
d1a99d5211 | ||
|
|
5f7736882b | ||
|
|
d8095e077a | ||
|
|
c8fae00ce5 | ||
|
|
7c6a03a2d2 | ||
|
|
40c21321dd | ||
|
|
476dbb555d | ||
|
|
19b4bfb9ef | ||
|
|
e9a85162e7 | ||
|
|
960c297995 | ||
|
|
50e525f448 | ||
|
|
c86f048498 | ||
|
|
39fd2f697f | ||
|
|
3f2cf3ddf4 | ||
|
|
5a53a70dcf | ||
|
|
66323f9347 | ||
|
|
c65f17a216 | ||
|
|
9bf93fb231 | ||
|
|
f418e02270 | ||
|
|
403254a5c6 | ||
|
|
c893d96ad3 | ||
|
|
3971118af8 | ||
|
|
4db0d93f41 | ||
|
|
affbfc5061 | ||
|
|
886ede2007 | ||
|
|
a3936c66aa | ||
|
|
d98453ffc2 | ||
|
|
7424912455 | ||
|
|
e095495081 | ||
|
|
eb4ce5544f | ||
|
|
8eef17834d | ||
|
|
40ed5e2353 | ||
|
|
2aa4c8c361 | ||
|
|
e5b120fa36 | ||
|
|
1e026f8ebd | ||
|
|
e5c7da0847 | ||
|
|
2e67002768 | ||
|
|
9c03649d48 | ||
|
|
df436b3b20 | ||
|
|
34acf4170e | ||
|
|
f9a13c880a | ||
|
|
df7cd45be6 | ||
|
|
b22d70c833 | ||
|
|
1ef8e8aa6a | ||
|
|
2aa58b7eb3 | ||
|
|
9fb61509c4 | ||
|
|
b99dc875ed | ||
|
|
7da31f00c3 | ||
|
|
894ccd1244 | ||
|
|
8d90e6e808 | ||
|
|
79771f725e | ||
|
|
786f56941a | ||
|
|
8fae910d46 | ||
|
|
8b5920bba3 | ||
|
|
03f1451e64 | ||
|
|
1d2a975b5f | ||
|
|
3db32979dc | ||
|
|
110431dae2 | ||
|
|
ade228f756 | ||
|
|
9b18a66f22 | ||
|
|
c88de90a24 | ||
|
|
737d66d97d | ||
|
|
b77b57d3fd | ||
|
|
240c7766c1 | ||
|
|
508b2e43d3 | ||
|
|
d6129e21e9 | ||
|
|
a11a2444f1 | ||
|
|
db1fb1c0e1 | ||
|
|
7f326b19aa | ||
|
|
2a1d7d2502 | ||
|
|
01edfce6e7 | ||
|
|
9176b8f99c | ||
|
|
0ff2e57424 | ||
|
|
567966866c | ||
|
|
e03f07a8ef | ||
|
|
9915a700bb | ||
|
|
f0a406a397 | ||
|
|
851ea24be4 | ||
|
|
50c4eff790 | ||
|
|
e69e6998c9 | ||
|
|
c87873cfb6 | ||
|
|
b09becf3eb | ||
|
|
0673242f41 | ||
|
|
1776931df5 | ||
|
|
124fbfd798 | ||
|
|
893e433805 | ||
|
|
a2c0921345 | ||
|
|
ad0a974c14 | ||
|
|
2d4a7d336c | ||
|
|
8d2df87de3 | ||
|
|
873e7e2068 | ||
|
|
3fcb1d0138 | ||
|
|
ce41f9a0ce | ||
|
|
34d8ed19bf | ||
|
|
ea9f34f0b3 | ||
|
|
4e9cbd23f2 | ||
|
|
bbd65c01e9 | ||
|
|
5dc30b7702 | ||
|
|
eb3b31bd59 | ||
|
|
57597dfef0 | ||
|
|
8cb7a610c7 | ||
|
|
2c464978b4 | ||
|
|
8d0bf6abe8 | ||
|
|
82c724a768 | ||
|
|
6146fe5f86 | ||
|
|
24ce6eae3b | ||
|
|
8db934a2c2 | ||
|
|
dc90d412ca | ||
|
|
b8415c8995 | ||
|
|
0d86f39ba3 | ||
|
|
0bab033673 | ||
|
|
72a0ce3f51 | ||
|
|
c3a14b82b3 | ||
|
|
b3252e276b | ||
|
|
10c63a66f6 | ||
|
|
f44205b90d | ||
|
|
cd087d410f | ||
|
|
c5812ba938 | ||
|
|
2e4c7f7690 | ||
|
|
a7389efb00 | ||
|
|
532062687c | ||
|
|
d3a603d115 | ||
|
|
26fece78c5 | ||
|
|
b8fb626591 | ||
|
|
732786067f | ||
|
|
45c0cd48c7 | ||
|
|
50d7982dd5 | ||
|
|
ff085b1284 | ||
|
|
c3564b1f8f | ||
|
|
32eba21e7a | ||
|
|
9952afcc38 | ||
|
|
b3feccab0d | ||
|
|
86ebd4903b | ||
|
|
0533bb9c30 | ||
|
|
185e90494c | ||
|
|
3f77b497ce | ||
|
|
87a8333cdf | ||
|
|
3d12261aa7 | ||
|
|
19c6cbbcd3 | ||
|
|
39c191db7c | ||
|
|
58c36266e0 | ||
|
|
0ebdfffdeb | ||
|
|
ed840f3048 | ||
|
|
1e13b509df | ||
|
|
d76a9a4628 | ||
|
|
f70e20498e | ||
|
|
1715b39629 | ||
|
|
3c63db8c9c | ||
|
|
7af78c95dd | ||
|
|
1c4a377641 | ||
|
|
bf56937585 | ||
|
|
e97442b0c8 | ||
|
|
d029ce5380 | ||
|
|
20049921ad | ||
|
|
05a0db75db | ||
|
|
a7b8100a18 | ||
|
|
112369b283 | ||
|
|
f9b915b728 | ||
|
|
8acdbc928e | ||
|
|
9665e14e6d | ||
|
|
b45e05cc9e | ||
|
|
116f4d94ea | ||
|
|
f18b5b49c5 | ||
|
|
09a4db7c03 | ||
|
|
2616a5776b | ||
|
|
36cfc4a867 | ||
|
|
631f118afb | ||
|
|
b43e3a61e6 | ||
|
|
04100adece | ||
|
|
a103f93925 | ||
|
|
8467340fb5 | ||
|
|
3a8e41de27 | ||
|
|
97c2f183ca | ||
|
|
f1ab35e71e | ||
|
|
240d892b94 | ||
|
|
364d96e7f6 | ||
|
|
03dfd58ac5 | ||
|
|
716023b534 | ||
|
|
67b3417ac9 | ||
|
|
f3667f6aaf | ||
|
|
7b35e71f3d | ||
|
|
51031878eb | ||
|
|
19d96230cd | ||
|
|
dbee7e2894 | ||
|
|
656241da54 | ||
|
|
2a3947ea1d | ||
|
|
9c1b4261dc | ||
|
|
7c37d8128e | ||
|
|
404785bf29 | ||
|
|
dc7fd34b07 | ||
|
|
86a2975b3c | ||
|
|
f824fc7c81 | ||
|
|
244cc30eb6 | ||
|
|
a833ed8060 | ||
|
|
1e869d2d2b | ||
|
|
64df5cfff3 | ||
|
|
d8b2a80e90 | ||
|
|
10061c061e | ||
|
|
6a4124fdf0 | ||
|
|
faaa915163 | ||
|
|
3fb911298d | ||
|
|
761f81d27c | ||
|
|
d4b7c8ae97 | ||
|
|
23679e58e1 | ||
|
|
f3e39f18ef | ||
|
|
55a4cda351 | ||
|
|
f0f270b44d | ||
|
|
529de2bd90 | ||
|
|
51dd83df09 | ||
|
|
9abe4ffd8e | ||
|
|
cdd92f6990 | ||
|
|
b08fa9bf60 | ||
|
|
f0bcc3c3e7 | ||
|
|
b9c45f24f5 | ||
|
|
d5f3967558 | ||
|
|
d3fccc9b87 | ||
|
|
7e6c03faf5 | ||
|
|
02b2a52280 | ||
|
|
6eb708b155 | ||
|
|
83e6444ddc | ||
|
|
168fe4d680 | ||
|
|
0a10c9a7c9 | ||
|
|
204c530712 | ||
|
|
5e55f0debf | ||
|
|
f8bd5a6c86 | ||
|
|
101e7a9a49 | ||
|
|
271e79d6a2 | ||
|
|
2ca8f8aff8 | ||
|
|
bc6891e746 | ||
|
|
26aaeccf11 | ||
|
|
91b512b693 | ||
|
|
88d7917a84 | ||
|
|
7ae0964dd1 | ||
|
|
edb0c305dd | ||
|
|
0321f35869 | ||
|
|
1870f8e90e | ||
|
|
6e112b904f | ||
|
|
dca8d2533e | ||
|
|
c57957b56d | ||
|
|
1f5ab87653 | ||
|
|
d5513e90bd | ||
|
|
00fcd17285 | ||
|
|
356ab4e7cb | ||
|
|
572cb55bf8 | ||
|
|
08b83469e3 | ||
|
|
6939150d2b | ||
|
|
cf9a4d8a26 | ||
|
|
a5f8e4fc58 | ||
|
|
775e325503 | ||
|
|
0c472ba22c | ||
|
|
4c0d15d6ef | ||
|
|
28cea81f61 | ||
|
|
d975dae88f | ||
|
|
30297584d5 | ||
|
|
1105f8e608 | ||
|
|
eeae097a54 | ||
|
|
8199e5a253 | ||
|
|
08c7f4b491 | ||
|
|
634744c22d | ||
|
|
45f4bdd1c5 | ||
|
|
c8f5c80d5b | ||
|
|
5556fafa94 | ||
|
|
20c21cb964 | ||
|
|
d2de889995 | ||
|
|
05cf3ef7fe | ||
|
|
6bd8a8fea8 | ||
|
|
4cba1a2fd2 | ||
|
|
86f0622c4a | ||
|
|
85ad7ca187 | ||
|
|
879279a382 | ||
|
|
74df84e449 | ||
|
|
2862ae3302 | ||
|
|
7d0dfe480c | ||
|
|
c47748ed4d | ||
|
|
396504138c | ||
|
|
6e067a160c | ||
|
|
66a56757d1 | ||
|
|
088ec5580a | ||
|
|
63b2693fe0 | ||
|
|
76a69d8f3b | ||
|
|
5cd0f55cb2 | ||
|
|
db640b04a6 | ||
|
|
0665bcf30a | ||
|
|
7e8ed42f46 | ||
|
|
8d7b1a5b9b | ||
|
|
c6829a7d5e | ||
|
|
bef8fbf183 | ||
|
|
fca95f09cc | ||
|
|
4d6cdf8823 | ||
|
|
e34f52dcc5 | ||
|
|
91cc4e6f3d | ||
|
|
429b7dcb0e | ||
|
|
5ffa681a80 | ||
|
|
91364db608 | ||
|
|
2433c68f27 | ||
|
|
6ea254d9ac | ||
|
|
a4d1df8324 | ||
|
|
ba15611903 |
@@ -232,6 +232,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "1024mb",
|
||||||
|
"name": "1024mb",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/9301204?v=4",
|
||||||
|
"profile": "https://github.com/1024mb",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -77,6 +77,6 @@ Engage with the community on our [Gitter Channel](https://gitter.im/OpenSignLabs
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
By contributing, you agree that your contributions will be licensed under its [MIT License](LICENSE).
|
By contributing, you agree that your contributions will be licensed under its [AGPL-V3 License](LICENSE).
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
* All content that resides under the "apps/OpenSignServer/cloud/customRoute" directory of this repository, if that directory exists, is licensed under the license defined in "apps/OpenSignServer/cloud/customRoute".
|
||||||
|
* All third party components incorporated into the OpenSign Software are licensed under the original license provided by the owner of the applicable component.
|
||||||
|
* Content outside of the above mentioned directories or restrictions above is available under the "GNU AFFERO GENERAL PUBLIC LICENSE" as defined below -
|
||||||
|
|
||||||
|
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 19 November 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,8 @@ We would like to thank all our contributors and users for their support and feed
|
|||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VikramNagwal"><img src="https://avatars.githubusercontent.com/u/123088024?v=4?s=100" width="100px;" alt="Vikram"/><br /><sub><b>Vikram</b></sub></a><br /><a href="#code-VikramNagwal" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VikramNagwal"><img src="https://avatars.githubusercontent.com/u/123088024?v=4?s=100" width="100px;" alt="Vikram"/><br /><sub><b>Vikram</b></sub></a><br /><a href="#code-VikramNagwal" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ugoconsonni"><img src="https://avatars.githubusercontent.com/u/13661702?v=4?s=100" width="100px;" alt="ugoconsonni"/><br /><sub><b>ugoconsonni</b></sub></a><br /><a href="#code-ugoconsonni" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ugoconsonni"><img src="https://avatars.githubusercontent.com/u/13661702?v=4?s=100" width="100px;" alt="ugoconsonni"/><br /><sub><b>ugoconsonni</b></sub></a><br /><a href="#code-ugoconsonni" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-mutwiri"><img src="https://avatars.githubusercontent.com/u/8936960?v=4?s=100" width="100px;" alt="Daniel Mutwiri"/><br /><sub><b>Daniel Mutwiri</b></sub></a><br /><a href="#code-daniel-mutwiri" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-mutwiri"><img src="https://avatars.githubusercontent.com/u/8936960?v=4?s=100" width="100px;" alt="Daniel Mutwiri"/><br /><sub><b>Daniel Mutwiri</b></sub></a><br /><a href="#code-daniel-mutwiri" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a><a href="#security-Zathiel" title="Security">🛡️</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1024mb"><img src="https://avatars.githubusercontent.com/u/9301204?v=4?s=100" width="100px;" alt="1024mb"/><br /><sub><b>1024mb</b></sub></a><br /><a href="#translation-1024mb" title="Translation">🌍</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
Generated
+1738
-967
File diff suppressed because it is too large
Load Diff
+30
-27
@@ -4,16 +4,16 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/auto-animate": "^0.8.2",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@lottiefiles/dotlottie-react": "^0.9.0",
|
"@lottiefiles/dotlottie-react": "^0.9.3",
|
||||||
"@pdf-lib/fontkit": "^1.1.1",
|
"@pdf-lib/fontkit": "^1.1.1",
|
||||||
"@radix-ui/themes": "^3.1.3",
|
"@radix-ui/themes": "^3.1.6",
|
||||||
"@react-pdf/renderer": "^4.0.0",
|
"@react-pdf/renderer": "^4.0.0",
|
||||||
"@reduxjs/toolkit": "^2.2.7",
|
"@reduxjs/toolkit": "^2.3.0",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"i18next": "^23.15.1",
|
"i18next": "^23.16.5",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"i18next-http-backend": "^2.6.1",
|
"i18next-http-backend": "^2.6.2",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
@@ -23,10 +23,10 @@
|
|||||||
"print-js": "^1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"radix-ui": "^1.0.1",
|
"radix-ui": "^1.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.4",
|
"react-bootstrap": "^2.10.5",
|
||||||
"react-confetti": "^6.1.0",
|
"react-confetti": "^6.1.0",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.2",
|
||||||
"react-datepicker": "^7.4.0",
|
"react-datepicker": "^7.5.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",
|
||||||
@@ -34,27 +34,27 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-gtm-module": "^2.0.11",
|
"react-gtm-module": "^2.0.11",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-i18next": "^15.0.2",
|
"react-i18next": "^15.1.1",
|
||||||
"react-konva": "^18.2.10",
|
"react-konva": "^18.2.10",
|
||||||
"react-pdf": "^9.1.1",
|
"react-pdf": "^9.1.1",
|
||||||
"react-quill-new": "^3.3.2",
|
"react-quill-new": "^3.3.3",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
"react-rnd": "^10.4.13",
|
"react-rnd": "^10.4.13",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.28.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-scrollbars-custom": "^4.1.1",
|
"react-scrollbars-custom": "^4.1.1",
|
||||||
"react-select": "^5.8.1",
|
"react-select": "^5.8.3",
|
||||||
"react-signature-canvas": "^1.0.6",
|
"react-signature-canvas": "^1.0.6",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.6.1",
|
||||||
"react-tooltip": "^5.28.0",
|
"react-tooltip": "^5.28.0",
|
||||||
"react-web-share": "^2.0.2",
|
"react-web-share": "^2.0.2",
|
||||||
"reactour": "^1.19.4",
|
"reactour": "^1.19.4",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-thunk": "^3.1.0",
|
"redux-thunk": "^3.1.0",
|
||||||
"regex-parser": "^2.3.0",
|
"regex-parser": "^2.3.0",
|
||||||
"serve": "^14.2.3",
|
"serve": "^14.2.4",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"web-vitals": "^4.2.3",
|
"web-vitals": "^4.2.4",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -95,33 +95,36 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.26.0",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.26.0",
|
||||||
"@babel/preset-react": "^7.24.7",
|
"@babel/preset-react": "^7.25.9",
|
||||||
"@babel/runtime-corejs2": "^7.25.6",
|
"@babel/runtime-corejs2": "^7.26.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"babel-loader": "^9.2.1",
|
"babel-loader": "^9.2.1",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.1",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.1.0",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"daisyui": "^4.12.10",
|
"daisyui": "^4.12.14",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"dotenv-webpack": "^8.1.0",
|
"dotenv-webpack": "^8.1.0",
|
||||||
"eslint": "^9.11.1",
|
"eslint": "^9.14.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.36.1",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"lint-staged": "^15.2.10",
|
"lint-staged": "^15.2.10",
|
||||||
"mini-css-extract-plugin": "^2.9.1",
|
"mini-css-extract-plugin": "^2.9.2",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.49",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"pretty-quick": "^4.0.0",
|
"pretty-quick": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.13",
|
"tailwindcss": "^3.4.14",
|
||||||
"terser-webpack-plugin": "^5.3.10",
|
"terser-webpack-plugin": "^5.3.10",
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^5.1.4"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"nth-check": "$nth-check",
|
"nth-check": "$nth-check",
|
||||||
"ws": "$ws"
|
"ws": "$ws"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "18 || 20 || 22"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"header-news": "New feature: Public profiles are now live! Easily create and share public templates",
|
"header-news": "New feature: Teams plan users can now integrate their own AWS S3 buckets for file storage",
|
||||||
"header-news-btn": "Setup Now",
|
"header-news-btn": "Setup Now",
|
||||||
"create-account": "Create Account",
|
"create-account": "Create Account",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
"My Signature": "My Signature",
|
"My Signature": "My Signature",
|
||||||
"API Token": "API Token",
|
"API Token": "API Token",
|
||||||
"Webhook": "Webhook",
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Preferences",
|
||||||
"Teams": "Teams",
|
"Teams": "Teams",
|
||||||
"Team-update-successfully": "Team Updated successfully.",
|
"Team-update-successfully": "Team Updated successfully.",
|
||||||
"Users": "Users"
|
"Users": "Users"
|
||||||
@@ -132,7 +133,9 @@
|
|||||||
"View": "View",
|
"View": "View",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Embed",
|
"Embed": "Embed",
|
||||||
"Copy TemplateId":"Copy TemplateId"
|
"Copy TemplateId":"Copy TemplateId",
|
||||||
|
"Copy Public URL":"Copy Public URL",
|
||||||
|
"extend-expiry-date": "Extend expiry date"
|
||||||
},
|
},
|
||||||
"report-heading": {
|
"report-heading": {
|
||||||
"Sr.No": "Sr.No",
|
"Sr.No": "Sr.No",
|
||||||
@@ -153,7 +156,8 @@
|
|||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"created-date": "Created Date",
|
"created-date": "Created Date",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Logs": "Logs"
|
"Logs": "Logs",
|
||||||
|
"Expiry-date": "Expiry Date"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||||
@@ -264,10 +268,11 @@
|
|||||||
"make-template-public-alert": "Are you sure you want to make this template public?",
|
"make-template-public-alert": "Are you sure you want to make this template public?",
|
||||||
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
||||||
"public-role": "Public role",
|
"public-role": "Public role",
|
||||||
"public-url": "Public URL",
|
"public-url": "Public profile",
|
||||||
|
"embed-template": "Embed Template",
|
||||||
"public-url-copy": "Here’s your public URL: ",
|
"public-url-copy": "Here’s your public URL: ",
|
||||||
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||||
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
"add-public-url-alert": "Please complete your OpenSign public profile setup. Once done, you’ll be able to make templates public. This process only needs to be completed once.",
|
||||||
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
||||||
"share-with": "Share with",
|
"share-with": "Share with",
|
||||||
"team-not-found": "Team not found",
|
"team-not-found": "Team not found",
|
||||||
@@ -290,7 +295,7 @@
|
|||||||
"subject": "Subject",
|
"subject": "Subject",
|
||||||
"body": "Body",
|
"body": "Body",
|
||||||
"add-contact": "Add Contact",
|
"add-contact": "Add Contact",
|
||||||
"add-signer-alert": "Contact already exist!",
|
"add-signer-alert": "Contact already exist! Please select it from ‘Signers’ dropdown",
|
||||||
"record-delete-alert": "Record deleted successfully!",
|
"record-delete-alert": "Record deleted successfully!",
|
||||||
"record-revoke-alert": "Record revoked successfully!",
|
"record-revoke-alert": "Record revoked successfully!",
|
||||||
"mail-sent-alert": "Mail sent successfully.",
|
"mail-sent-alert": "Mail sent successfully.",
|
||||||
@@ -444,7 +449,8 @@
|
|||||||
"cutomize-email": "Cutomize Email",
|
"cutomize-email": "Cutomize Email",
|
||||||
"upgrade-to-customize-email": "Upgrade to customize Email",
|
"upgrade-to-customize-email": "Upgrade to customize Email",
|
||||||
"sign-url": "Sign url",
|
"sign-url": "Sign url",
|
||||||
"Mails Sent": "Mails Sent",
|
"mails-sent": "Mails sent",
|
||||||
|
"mail-not-delivered": "Mail not delivered",
|
||||||
"document-alert": "Document Alert",
|
"document-alert": "Document Alert",
|
||||||
"owner-subscription-expired": "Owner's subscription has expired.",
|
"owner-subscription-expired": "Owner's subscription has expired.",
|
||||||
"subscription-expired": "Subscription Expired",
|
"subscription-expired": "Subscription Expired",
|
||||||
@@ -509,7 +515,7 @@
|
|||||||
"error": "Error",
|
"error": "Error",
|
||||||
"invalid-document": "Error: invalid document!",
|
"invalid-document": "Error: invalid document!",
|
||||||
"document-not-found": "Document not Found!",
|
"document-not-found": "Document not Found!",
|
||||||
"document-signed-alert-1": "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers.",
|
"document-signed-alert-1": "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document & completion certificate will be sent to the owner & all signers over email once it is signed by all signers.",
|
||||||
"encrypted-pdf-not-support": "Currently encrypted pdf files are not supported.",
|
"encrypted-pdf-not-support": "Currently encrypted pdf files are not supported.",
|
||||||
"document-signed-alert-4": " Congratulations! 🎉 This document has been successfully signed by all participants!",
|
"document-signed-alert-4": " Congratulations! 🎉 This document has been successfully signed by all participants!",
|
||||||
"document-signed-alert-5": "This document has been signed by all Signers.",
|
"document-signed-alert-5": "This document has been signed by all Signers.",
|
||||||
@@ -639,7 +645,7 @@
|
|||||||
"public-template-mssg-3" :"Need more details or examples?",
|
"public-template-mssg-3" :"Need more details or examples?",
|
||||||
"public-template-mssg-4": "Visit the",
|
"public-template-mssg-4": "Visit the",
|
||||||
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||||
"public-template-mssg-6" :"You need to set this template as public before you can utilize this code snippet.",
|
"public-template-mssg-6" :"Before you can use this code snippet, you must make this template public.",
|
||||||
"copy-code":"COPY",
|
"copy-code":"COPY",
|
||||||
"copied-code":"COPIED",
|
"copied-code":"COPIED",
|
||||||
"Installation":"Installation",
|
"Installation":"Installation",
|
||||||
@@ -649,6 +655,7 @@
|
|||||||
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
||||||
"quota-mail-info-head":"Monthly request signatures email limit",
|
"quota-mail-info-head":"Monthly request signatures email limit",
|
||||||
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
||||||
|
"quota-mail-reset": "Your signature request email credits will be reset on",
|
||||||
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
||||||
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
||||||
"quota-mail-head":"Quota Reached",
|
"quota-mail-head":"Quota Reached",
|
||||||
@@ -668,6 +675,43 @@
|
|||||||
"download-files":"Download files",
|
"download-files":"Download files",
|
||||||
"download-pdf":"Download Pdf",
|
"download-pdf":"Download Pdf",
|
||||||
"pdf-certificate":"Download Pdf + Certificate",
|
"pdf-certificate":"Download Pdf + Certificate",
|
||||||
"document-logs":"Document logs"
|
"document-logs":"Document logs",
|
||||||
|
"server-down": "Unable to connect to the OpenSign server. If you are self-hosting OpenSign, please ensure that all the steps in the documentation have been followed correctly. If you're running OpenSign locally, you might be accessing it through an incorrect port number.",
|
||||||
|
"admin-exists": "Admin already exists. Please login to the application using admin credentials in order to manage users.",
|
||||||
|
"enable-tour":"Enable Tour",
|
||||||
|
"istourenabled-help":{
|
||||||
|
"p1":"This will enable a guided tour for signers, providing instructions during the signing process.",
|
||||||
|
"p2":"This will disable the guided tour, ensuring a faster, uninterrupted signing experience.",
|
||||||
|
"p3":"Tip: If your signers are familiar with OpenSign and frequently use it, you may want to disable the guided tour for a more seamless experience. Choose the option that best fits your document signing needs."
|
||||||
|
},
|
||||||
|
"form-title-1":"Document Flow Setting",
|
||||||
|
"form-title-2":"Security Settings",
|
||||||
|
"public-tour-message":"The template needs to be public before you can generate a shareable link.",
|
||||||
|
"add-user-template": "You need to add a role before you can add fields for it.",
|
||||||
|
"pdf-uncompatible": "This pdf is not compatible with opensign, please contact <support@opensignlabs.com>",
|
||||||
|
"text-field-tour":"Fields of type 'Text' must be filled in advance before the document is sent. If you need the signers to provide input, use the 'Text Input' field instead.",
|
||||||
|
"attach-signer-tour":"You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour.",
|
||||||
|
"allowed-signature-types": "Allowed signature types",
|
||||||
|
"at-least-one-signature-type": "At least one signature type should be enabled.",
|
||||||
|
"expect-default-one-more-signature-type": "Please enable one additional signature type apart from the default.",
|
||||||
|
"add-signer-note": "Note - This contact will be added to your contact list",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "This signature preference controls which signing options are available to your signers. Only the signature types you select will appear in the signature widget when a document is signed. For example, if you choose only the 'Draw' option in preferences, your signer will see only the 'Draw' option in the signature widget, while the other three options will not be available.",
|
||||||
|
"l1": "Create a handwritten signature directly on the screen using your finger or a stylus.",
|
||||||
|
"l2": "Enter your name and choose from various font styles to create a signature.",
|
||||||
|
"l3": "Upload an existing digital version of your signature.",
|
||||||
|
"l4": "Use a pre-set signature style saved under 'My Signature' in your settings."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notify on signatures",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "The document creator will receive an email notification whenever a signer signs the document.",
|
||||||
|
"note": "Note: Notification email will not be sent for the last signer, as the document creator will receive a completion email instead."
|
||||||
|
},
|
||||||
|
"expiry-date": "Expiry Date",
|
||||||
|
"expiry-date-updated": "The expiry date has been successfully extended to {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Please provide a new expiry date that is later than the current one",
|
||||||
|
"delete-page":"Delete page",
|
||||||
|
"delete-alert":"Can not delete single page",
|
||||||
|
"delete-alert-2":"Are you sure want to delete this page ?",
|
||||||
|
"delete-note":"Note - once delete this page you can not undo"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,717 @@
|
|||||||
|
{
|
||||||
|
"header-news": "Nueva característica: los usuarios del plan Teams ahora pueden integrar sus propios depósitos de AWS S3 para el almacenamiento de archivos",
|
||||||
|
"header-news-btn": "Configurar ahora",
|
||||||
|
"create-account": "Crear cuenta",
|
||||||
|
"login": "Iniciar sesión",
|
||||||
|
"language": "Idioma",
|
||||||
|
"name": "Nombre",
|
||||||
|
"phone": "Teléfono",
|
||||||
|
"phone-optional": "opcional",
|
||||||
|
"email": "Correo",
|
||||||
|
"company": "Compañía",
|
||||||
|
"job-title": "Título del puesto",
|
||||||
|
"profile": "Perfil",
|
||||||
|
"log-out": "Cerrar sesión",
|
||||||
|
"is-email-verified": "El correo está verificado",
|
||||||
|
"public-profile": "Perfil público",
|
||||||
|
"tagline": "Eslogan ",
|
||||||
|
"has-requested-you-to-sign": "ha solicitado que firmes",
|
||||||
|
"has-requested-you-to-review-and-sign": " ha solicitado que revises y firmes",
|
||||||
|
"input-required": "Por favor, rellena este campo.",
|
||||||
|
"sort-order": {
|
||||||
|
"Ascending": "Ascendente",
|
||||||
|
"Descending": "Descendente",
|
||||||
|
"Name": "Nombre",
|
||||||
|
"Date": "Fecha"
|
||||||
|
},
|
||||||
|
"context-menu": {
|
||||||
|
"Download": "Descargar",
|
||||||
|
"Rename": "Renombrar",
|
||||||
|
"Move": "Mover",
|
||||||
|
"Delete": "Eliminar"
|
||||||
|
},
|
||||||
|
"action": "Acción",
|
||||||
|
"add": "Agregar",
|
||||||
|
"add-new-folder": "Agregar nueva carpeta",
|
||||||
|
"disable-documentId": "Desactivar ID de documento",
|
||||||
|
"edit": "Editar",
|
||||||
|
"change-password": "Cambiar contraseña",
|
||||||
|
"save": "Guardar",
|
||||||
|
"cancel": "Cancelar",
|
||||||
|
"upgrade-now": "Mejorar ahora",
|
||||||
|
"upgrade-to": "Mejorar a",
|
||||||
|
"plan": "Plan",
|
||||||
|
"subscribe-card-teamplan": "¡Libera todo el poder de la colaboración! Crea organizaciones, equipos y jerarquías ilimitadas. Comparte plantillas sin problemas entre equipos y asigna funciones de usuario personalizadas. ¡Mejora tu flujo de trabajo hoy mismo!",
|
||||||
|
"subscribe-card-plan": "Desbloquea funciones premium desde solo {{premiumPrice}}/mes. Disfruta de un rendimiento mejorado y solo {{addonPrice}} por crédito adicional después de tus créditos premium incluidos.",
|
||||||
|
"user-name-limit-char": "Para tener un nombre de usuario menor a 8 caracteres por favor suscríbete",
|
||||||
|
"tour-content": "No mostrar esto otra vez",
|
||||||
|
"pro": "PRO",
|
||||||
|
"team": "EQUIPO",
|
||||||
|
"user": "Usuario",
|
||||||
|
"docs": "Documentación",
|
||||||
|
"session-expired": "Tu sesión ha expirado.",
|
||||||
|
"public-profile-help": "Esta es tu URL pública. Cópiala o compártela con el firmante, y podrás ver todas tus plantillas públicas.",
|
||||||
|
"tagline-help": "Este eslogan aparecerá en tu perfil público de OpenSign, por ejem. https://opensign.me/alex",
|
||||||
|
"welcome": "¡Bienvenido de nuevo!",
|
||||||
|
"Login-to-your-account": "Ingresa a tu cuenta",
|
||||||
|
"password": "Contraseña",
|
||||||
|
"forgot-password": "¿Olvidaste la contraseña?",
|
||||||
|
"loading": "Cargando...",
|
||||||
|
"of": "de",
|
||||||
|
"sign-SSO": "Ingresar con SSO",
|
||||||
|
"login-page": "Página de inicio de sesión",
|
||||||
|
"or": "O",
|
||||||
|
"signup-page": "Página de registro",
|
||||||
|
"password-length": "La contraseña debe tener 8 caracteres",
|
||||||
|
"password-case": "La contraseña debe incluir mayúsculas, minúsculas y números",
|
||||||
|
"password-special-char": " La contraseña debe incluir caracteres especiales",
|
||||||
|
"agreee": "Estoy de acuerdo con los",
|
||||||
|
"term": "Términos de Servicio",
|
||||||
|
"subscribe-to-opensign": "Suscribirse al boletín de OpenSign",
|
||||||
|
"register": "Registrarse",
|
||||||
|
"sidebar": {
|
||||||
|
"Dashboard": "Panel",
|
||||||
|
"Sign yourself": "Firma tu mismo",
|
||||||
|
"Request signatures": "Solicitar firmas",
|
||||||
|
"Templates": "Plantillas",
|
||||||
|
"Templates-Children": {
|
||||||
|
"Create template": "Crear plantilla",
|
||||||
|
"Manage templates": "Administrar plantillas"
|
||||||
|
},
|
||||||
|
"OpenSign™ Drive": "OpenSign™ Drive",
|
||||||
|
"Reports": "Reportes",
|
||||||
|
"Reports-Children": {
|
||||||
|
"Need your sign": "Necesitan tu firma",
|
||||||
|
"In Progress": "En progreso",
|
||||||
|
"Completed": "Completado",
|
||||||
|
"Drafts": "Borradores",
|
||||||
|
"Declined": "Rechazados",
|
||||||
|
"Expired": "Expirados",
|
||||||
|
"Contactbook": "Agenda de contactos"
|
||||||
|
},
|
||||||
|
"Settings": "Ajustes",
|
||||||
|
"Settings-Children": {
|
||||||
|
"My Signature": "Mi firma",
|
||||||
|
"API Token": "Token API",
|
||||||
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Preferencias",
|
||||||
|
"Teams": "Equipos",
|
||||||
|
"Team-update-successfully": "Equipo actualizado correctamente.",
|
||||||
|
"Users": "Usuarios"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dashboard-card": {
|
||||||
|
"Need your Signature": "Necesitan tu firma",
|
||||||
|
"Out for signatures": "En espera de ser firmados"
|
||||||
|
},
|
||||||
|
"report-name": {
|
||||||
|
"Draft Documents": "Documentos borradores",
|
||||||
|
"Need your sign": "Necesitan tu firma",
|
||||||
|
"In-progress documents": "Documentos en progreso",
|
||||||
|
"Completed Documents": "Documentos completados",
|
||||||
|
"Declined Documents": "Documentos rechazados",
|
||||||
|
"Expired Documents": "Documentos expirados",
|
||||||
|
"Recently sent for signatures": "Recientemente enviados para ser firmados",
|
||||||
|
"Recent signature requests": "Solicitudes de firma recientes",
|
||||||
|
"Drafts": "Borradores",
|
||||||
|
"Contactbook": "Agenda de contactos",
|
||||||
|
"Templates": "Plantillas",
|
||||||
|
"Teams": "Equipos",
|
||||||
|
"Users": "Usuarios"
|
||||||
|
},
|
||||||
|
"btnLabel": {
|
||||||
|
"sign": "firmar",
|
||||||
|
"Sign": "FIRMAR",
|
||||||
|
"Resend": "Reenviar",
|
||||||
|
"Revoke": "Revocar",
|
||||||
|
"Delete": "Eliminar",
|
||||||
|
"Use": "Usar",
|
||||||
|
"Quick send": "Envío rápido",
|
||||||
|
"Edit": "Editar",
|
||||||
|
"Share with team": "Compartir con el equipo",
|
||||||
|
"Share": "Compartir",
|
||||||
|
"View": "Ver",
|
||||||
|
"option": "Opción",
|
||||||
|
"Embed": "Incrustar",
|
||||||
|
"Copy TemplateId": "Copiar ID de plantilla",
|
||||||
|
"Copy Public URL": "Copiar URL pública",
|
||||||
|
"extend-expiry-date": "Ampliar fecha de caducidad"
|
||||||
|
},
|
||||||
|
"report-heading": {
|
||||||
|
"Sr.No": "Nº",
|
||||||
|
"Title": "Título",
|
||||||
|
"Email": "Correo",
|
||||||
|
"Phone": "Teléfono",
|
||||||
|
"File": "Archivo",
|
||||||
|
"Owner": "Propietario",
|
||||||
|
"Signers": "Firmantes",
|
||||||
|
"Note": "Nota",
|
||||||
|
"Folder": "Carpeta",
|
||||||
|
"Reason": "Razón",
|
||||||
|
"Parent Team": "Equipo padre",
|
||||||
|
"Active": "Activo",
|
||||||
|
"Role": "Rol",
|
||||||
|
"Team": "Equipo",
|
||||||
|
"Name": "Nombre",
|
||||||
|
"Status": "Estado",
|
||||||
|
"created-date": "Fecha de creación",
|
||||||
|
"Type": "Tipo",
|
||||||
|
"Logs": "Registros",
|
||||||
|
"Expiry-date": "Date d'expiration"
|
||||||
|
},
|
||||||
|
"report-help": {
|
||||||
|
"Draft Documents": "Estos son documentos que has iniciado pero no has finalizado para su envío.",
|
||||||
|
"Need your sign": "Esta es una lista de documentos que esperan tu firma.",
|
||||||
|
"In-progress documents": "Esta es una lista de documentos que has enviado a otras partes para su firma.",
|
||||||
|
"Completed Documents": "Esta es una lista de documentos en los que todas las partes han firmado.",
|
||||||
|
"Declined Documents": "Esta es una lista de documentos que han sido rechazados por uno de los firmantes.",
|
||||||
|
"Expired Documents": "Esta es una lista de documentos que han alcanzado su fecha de caducidad.",
|
||||||
|
"Contactbook": "Esta es una lista de contactos/firmantes añadidos por ti. Aparecerán como sugerencias cuando intentes añadir firmantes a un nuevo documento.",
|
||||||
|
"Templates": "Esta es una lista de plantillas que están a tu disposición para crear documentos. Puedes hacer clic en el botón «usar» para crear un nuevo documento utilizando una plantilla, modifica el documento y añade firmantes en el siguiente paso."
|
||||||
|
},
|
||||||
|
"form-name": {
|
||||||
|
"Sign Yourself": "Firmar",
|
||||||
|
"Request Signatures": "Solicitar firmas",
|
||||||
|
"New Template": "Nueva plantilla"
|
||||||
|
},
|
||||||
|
"file-type": "pdf, png, jpg, jpeg",
|
||||||
|
"docx": "docx",
|
||||||
|
"file-selected": "archivo seleccionado",
|
||||||
|
"template-title": "Título de la plantilla",
|
||||||
|
"document-title": "Título del documento",
|
||||||
|
"description": "Descripción",
|
||||||
|
"time-to-complete": "Plazo de finalización (días)",
|
||||||
|
"send-in-order": "Enviar en orden",
|
||||||
|
"send-in-order-help": {
|
||||||
|
"p1": "Elige cómo quieres que se envíen las solicitudes de firma a los firmantes del documento:",
|
||||||
|
"p2": "Seleccionando esta opción se enviará inicialmente la solicitud de firma al primer firmante. Una vez que el primer firmante complete su parte, el siguiente firmante en la secuencia recibirá la solicitud. Este proceso continúa hasta que todos los firmantes hayan firmado el documento. Este método garantiza que el documento se firme en un orden específico.",
|
||||||
|
"p3": "Seleccionando esta opción se enviarán los enlaces para la firma a todos los firmantes simultáneamente. Cada firmante puede firmar el documento cuando le convenga, independientemente de si otros firmantes han completado sus firmas. Este método es más rápido, pero no impone ningún orden de firma entre los participantes.",
|
||||||
|
"p4": "Selecciona la opción que mejor se adapte a las necesidades de tu tramitación de documentos."
|
||||||
|
},
|
||||||
|
"no": "No",
|
||||||
|
"auto-reminder": "Recordatorio automático",
|
||||||
|
"remind-once": " Recordar una vez cada (Días)",
|
||||||
|
"next": "Siguiente",
|
||||||
|
"select-folder": "Seleccionar carpeta",
|
||||||
|
"OpenSign-drive": "OpenSign™ Drive",
|
||||||
|
"drive-document-status": {
|
||||||
|
"Completed": "Completado",
|
||||||
|
"Declined": "Rechazado",
|
||||||
|
"Draft": "Borrador",
|
||||||
|
"Expired": "Expirado",
|
||||||
|
"In Progress": "En progreso"
|
||||||
|
},
|
||||||
|
"select-folder-help": "Si no seleccionas una carpeta, tu documento firmado se guardará en la carpeta principal de OpenSign Drive.",
|
||||||
|
"no-data": "No se encontraron datos",
|
||||||
|
"save-here": "Guardar aquí",
|
||||||
|
"back": "Atrás",
|
||||||
|
"add-folder": "Añadir carpeta",
|
||||||
|
"create-folder": "Crear carpeta",
|
||||||
|
"parent-folder": "Carpeta superior",
|
||||||
|
"create": "Crear",
|
||||||
|
"signers": "Firmantes",
|
||||||
|
"signers-help": "Empieza a escribir el nombre de un contacto para ver los firmantes sugeridos entre tus contactos guardados o añade otros nuevos. Organiza el orden de firma añadiendo firmantes en la secuencia deseada. Utiliza el botón «+» para añadir nuevos firmantes y la «X» para quitar todos. Cada firmante recibirá una solicitud por correo electrónico para que firme el documento según el orden indicado.",
|
||||||
|
"add-signer": "Añadir firmante",
|
||||||
|
"contact-not-found": "Contacto no encontrado",
|
||||||
|
"add-yourself": "Añadirte a ti mismo",
|
||||||
|
"submit": "Enviar",
|
||||||
|
"reset": "Volver a empezar",
|
||||||
|
"my-signature": "Mi firma",
|
||||||
|
"signature": "Firma",
|
||||||
|
"upload-image": " Subir imagen",
|
||||||
|
"clear": "Limpiar",
|
||||||
|
"upload-signature/Image": "Por favor, sube la firma/imagen",
|
||||||
|
"initials": "Iniciales",
|
||||||
|
"API": "API",
|
||||||
|
"api-token": "Token API",
|
||||||
|
"regenerate-token": "Regenerar token activo",
|
||||||
|
"generate-token": "Generar token activo",
|
||||||
|
"view-docs": "Ver documentación",
|
||||||
|
"generate-token-alert": "¿En definitiva quieres regenerar el token? Esto expirará el token antiguo.",
|
||||||
|
"yes": "Sí",
|
||||||
|
"copied": "Copiado",
|
||||||
|
"something-went-wrong-mssg": "Algo salió mal, por favor, intenta de nuevo más tarde.",
|
||||||
|
"token-generated": "Token generado exitosamente.",
|
||||||
|
"webhook": "Webhook",
|
||||||
|
"update-webhook": "Actualizar webhook",
|
||||||
|
"add-webhook": "Agregar webhook",
|
||||||
|
"webhook-added": "Webhook agregado exitosamente.",
|
||||||
|
"team-disabled": "Equipo deshabilitado",
|
||||||
|
"Team enabled": "Equipo habilitado",
|
||||||
|
"are-you-sure": "¿En definitiva quieres ",
|
||||||
|
"disable": "deshabilitar",
|
||||||
|
"enable": "habilitar",
|
||||||
|
"this-team": " este equipo?",
|
||||||
|
"edit-team": "Editar equipo",
|
||||||
|
"name-of-team": "Nombre del equipo",
|
||||||
|
"prev": "Anterior",
|
||||||
|
"no-data-avaliable": "No hay datos disponibles",
|
||||||
|
"add-team": "Agregar equipo",
|
||||||
|
"page-not-found": "Página no encontrada",
|
||||||
|
"users-from-teams": "usuarios de equipos",
|
||||||
|
"user-status": "Estado del usuario",
|
||||||
|
"activate": "activar",
|
||||||
|
"deactivate": "desactivar",
|
||||||
|
"this-user": " este usuario",
|
||||||
|
"delete-user": "Eliminar usuario",
|
||||||
|
"delete": "eliminar",
|
||||||
|
"add-user": "Agregar usuario",
|
||||||
|
"password-generateed": "La contraseña solo será generada una vez; asegúrate de copiarla.",
|
||||||
|
"Team status": "Estado del equipo",
|
||||||
|
"user-deactivated": "Usuario desactivado.",
|
||||||
|
"user-activated": "Usuario activado.",
|
||||||
|
"public": "Público",
|
||||||
|
"download": "Descargar",
|
||||||
|
"view": "Ver",
|
||||||
|
"make-template-public": "Convertir la plantilla en pública",
|
||||||
|
"make-template-private": "Convertir la plantilla en privada",
|
||||||
|
"make-template-public-alert": "¿En definitiva quieres convertir esta plantilla en pública?",
|
||||||
|
"make-template-private-alert": "¿En definitiva quieres convertir esta plantilla en privada? Esto lo removerá de tu perfil público.",
|
||||||
|
"public-role": "Rol público",
|
||||||
|
"public-url": "Perfil publico",
|
||||||
|
"embed-template": "Insertar plantilla",
|
||||||
|
"public-url-copy": "Aquí está tu URL pública: ",
|
||||||
|
"public-url-copy-mssg": "Cópiala o compártela con el firmante y podrás ver todas tus plantillas públicas.",
|
||||||
|
"add-public-url-alert": "Por favor, completa la configuración de tu perfil público OpenSign. Una vez terminado, podrás crear plantillas públicas. Este proceso solo necesita ser completado una vez.",
|
||||||
|
"share-with-alert": "No puedes compartir una plantilla si alguno de los roles ya tiene contactos asignados. Elimina todas las asignaciones de contactos de los roles antes de compartir la plantilla.",
|
||||||
|
"share-with": "Compartir con",
|
||||||
|
"team-not-found": "Equipo no encontrado",
|
||||||
|
"roles": "Roles",
|
||||||
|
"delete-document": "Eliminar documento",
|
||||||
|
"delete-document-alert": "¿En definitiva quieres eliminar este documento?",
|
||||||
|
"quick-send": "Envío rápido",
|
||||||
|
"add-new": "Agregar nuevo",
|
||||||
|
"send": "Enviar",
|
||||||
|
"quick-send-alert-1": "Todos los roles de este documento están actualmente vinculados a contactos. Para enviar rápidamente copias de esta plantilla a varios firmantes, por favor, asegúrate de que al menos un rol no esté vinculado a ningún contacto.",
|
||||||
|
"quick-send-alert-2": "Por favor, asegúrate de que hay al menos un widget de firma añadido para cada destinatario.",
|
||||||
|
"quick-send-alert-3": "Por favor, añade al menos un rol a esta plantilla para poder hacer un «envío rápido» de copias a varios firmantes.",
|
||||||
|
"quick-send-alert-4": "El envío rápido ha alcanzado el límite.",
|
||||||
|
"copy-link": "Copiar enlace",
|
||||||
|
"copy": "Copiar",
|
||||||
|
"revoke-document": "Revocar documento",
|
||||||
|
"revoke-document-alert": "¿En definitiva quieres revocar este documento?",
|
||||||
|
"resend-mail": "Reenviar correo",
|
||||||
|
"resend-mail-help": "Puedes usar las siguientes variables que serán reemplazadas por sus valores reales:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
|
||||||
|
"subject": "Asunto",
|
||||||
|
"body": "Cuerpo",
|
||||||
|
"add-contact": "Agregar contacto",
|
||||||
|
"add-signer-alert": "¡El contacto ya existe! Selecciónelo en el menú desplegable 'Firmantes'",
|
||||||
|
"record-delete-alert": "¡Entrada eliminada exitosamente!",
|
||||||
|
"record-revoke-alert": "¡Entrada revocada exitosamente!",
|
||||||
|
"mail-sent-alert": "Correo enviado exitosamente.",
|
||||||
|
"document-sent-alert": "¡Documento enviado exitosamente!",
|
||||||
|
"template-share-alert": "Plantilla compartida exitosamente.",
|
||||||
|
"template-public-alert-1": "Has convertido exitosamente la plantilla en pública.",
|
||||||
|
"template-public-alert-2": "Has convertido exitosamente la plantilla en privada.",
|
||||||
|
"template-public-alert-3": "Tienes que seleccionar un rol para los firmantes públicos.",
|
||||||
|
"template-public-alert-4": "Por favor, asegúrate de que has añadido al menos un widget de firma para cada firmante.",
|
||||||
|
"template-public-alert-5": "Dado que esta plantilla tiene «enviar en orden» habilitado, el rol público debe estar posicionado arriba al inicio.",
|
||||||
|
"template-public-alert-6": "Por favor, enlaza firmantes a todos los roles excepto al usuario de rol público.",
|
||||||
|
"template-public-alert-7": "Por favor, asigna al menos un rol público para convertir está plantilla en pública.",
|
||||||
|
"loader": " Esto podría llevar algún tiempo",
|
||||||
|
"pages": "Páginas",
|
||||||
|
"document-signed": "Documento firmado",
|
||||||
|
"close": "Cerrar",
|
||||||
|
"validation-alert": "Alerta de validación",
|
||||||
|
"validate-alert-mssg": " Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
|
||||||
|
"otp-verification": "Verificación OTP",
|
||||||
|
"enter-otp": "Ingresar OTP",
|
||||||
|
"verify": "Verificar",
|
||||||
|
"verify-email-1": "Verificar correo",
|
||||||
|
"resend": "Reenviar",
|
||||||
|
"contact-details": "Detalles del contacto",
|
||||||
|
"verify-email": "¡Por favor, verifica tu correo!",
|
||||||
|
"send-otp": " Enviar OTP",
|
||||||
|
"otp-placeholder": "Ingresa el código de verificación enviado por correo",
|
||||||
|
"loading-doc": "Cargando documento...",
|
||||||
|
"widgets-name": {
|
||||||
|
"signature": "firma",
|
||||||
|
"stamp": "sello",
|
||||||
|
"initials": "iniciales",
|
||||||
|
"name": "nombre",
|
||||||
|
"job title": "título del puesto",
|
||||||
|
"company": "compañía",
|
||||||
|
"date": "fecha",
|
||||||
|
"text": "texto",
|
||||||
|
"text input": "entrada de texto",
|
||||||
|
"checkbox": "casilla",
|
||||||
|
"dropdown": "desplegable",
|
||||||
|
"radio button": "botón de radio",
|
||||||
|
"image": "imagen",
|
||||||
|
"email": "correo"
|
||||||
|
},
|
||||||
|
"fields": "Campos",
|
||||||
|
"recipients": "Destinatarios",
|
||||||
|
"please-add": "Por favor, agrega un",
|
||||||
|
"signed-by": "Firmado por",
|
||||||
|
"more": "más",
|
||||||
|
"sent": "enviado",
|
||||||
|
"print": "Imprimir",
|
||||||
|
"certificate": "Certificado",
|
||||||
|
"decline": "Rechazar",
|
||||||
|
"finish": "Finalizar",
|
||||||
|
"mail": "Correo",
|
||||||
|
"sign-now": "Firmar ahora",
|
||||||
|
"successfully-signed": "¡Firmado exitosamente!",
|
||||||
|
"email-mssg": " Los destinatarios agregados aquí recibirán una copia del documento firmado.",
|
||||||
|
"email-error-1": " por favor, proporciona una dirección de correo correcta",
|
||||||
|
"email-error-2": "Solo puedes enviar hasta a 10 destinatarios a la vez.",
|
||||||
|
"Email-verified-alert-1": "El correo está verificado.",
|
||||||
|
"Email-verified-alert-2": "El correo ya ha sido verificado.",
|
||||||
|
"upload-stamp-image": "Subir imagen del sello",
|
||||||
|
"draw": "Dibujar",
|
||||||
|
"type": "Escribir",
|
||||||
|
"color-type": {
|
||||||
|
"red": "rojo",
|
||||||
|
"blue": "azul",
|
||||||
|
"black": "negro",
|
||||||
|
"yellow": "amarillo"
|
||||||
|
},
|
||||||
|
"my-initials": "Mis iniciales",
|
||||||
|
"upload": "Subir",
|
||||||
|
"initial-teb": "Iniciales",
|
||||||
|
"signature-tab": "Firma",
|
||||||
|
"your-signature": "Tu firma",
|
||||||
|
"copy-title": "Copiar widget a",
|
||||||
|
"contact-delete-alert": "¿En definitiva quieres eliminar este contacto?",
|
||||||
|
"reset-password-alert-1": "El enlace para restablecer la contraseña ha sido enviado a tu correo electrónico",
|
||||||
|
"reset-password-alert-2": "Por favor, configura un adaptador de correo ",
|
||||||
|
"reset-password-alert-3": "Restablece tu contraseña",
|
||||||
|
"faild-animation": "Error al cargar la animación",
|
||||||
|
"apply": "Aplicar",
|
||||||
|
"copy-type": {
|
||||||
|
"All pages": "Todas las páginas",
|
||||||
|
"All pages but last": "Todas las páginas menos la última",
|
||||||
|
"All pages but first": "Todas las páginas menos la primera",
|
||||||
|
"Next to current widget": "Junto al widget actual"
|
||||||
|
},
|
||||||
|
"options": "Opciones",
|
||||||
|
"minimun-check": "Chequeo mínimo",
|
||||||
|
"maximum-check": "Chequeo máximo",
|
||||||
|
"default-value": "Valor por defecto",
|
||||||
|
"select": "Seleccionar",
|
||||||
|
"read-only": "Es de solo lectura",
|
||||||
|
"hide-labels": "Esconder etiquetas",
|
||||||
|
"checkbox": "Casilla",
|
||||||
|
"alert": "Alerta",
|
||||||
|
"zoom-in": "Acercar",
|
||||||
|
"zoom-out": "Alejar",
|
||||||
|
"document-signed-alert": "¡Felicitaciones! 🎉 ¡Este documento ha sido firmado por ti exitosamente!",
|
||||||
|
"otp-sent-alert": "OTP enviado a tu correo",
|
||||||
|
"fields-required": "Campos requeridos",
|
||||||
|
"signature-widget-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma agregado",
|
||||||
|
"signature-widget-alert-2": "Por favor, asegúrate de que todos los campos están correctamente rellenados y de que cumplen todos los requisitos.",
|
||||||
|
"encrypted-pdf-alert": "Actualmente los archivos PDF encriptados no están soportados.",
|
||||||
|
"encrypted-pdf-alert-1": "La contraseña del archivo PFX es inválida.",
|
||||||
|
"user-not-exist": "El usuario no existe",
|
||||||
|
"template-signature-field": "Por favor, agrega al menos un campo de firma para todos los roles.",
|
||||||
|
"template-role-alert": "Por favor, primero agrega roles",
|
||||||
|
"create-document": "Crear documento",
|
||||||
|
"template-created-alert": "¿Quieres crear un documento usando la plantilla que acabas de crear?",
|
||||||
|
"signers-alert": "alerta de firmantes",
|
||||||
|
"template-creation-alert-1": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
|
||||||
|
"ok": "OK",
|
||||||
|
"radio-group": "Grupo de radio",
|
||||||
|
"dropdown-options": "Opciones del desplegable",
|
||||||
|
"add-role": "Agregar rol",
|
||||||
|
"role-ex": " por ejem.: Cliente, RRHH, Director, Administrador, Estudiante, etc.",
|
||||||
|
"add/choose-signer": "Agregar/Elegir firmante",
|
||||||
|
"choose-from-contacts": "Elegir desde los contactos",
|
||||||
|
"select-signer": " Por favor, selecciona el firmante",
|
||||||
|
"edit-template": "Editar plantilla",
|
||||||
|
"widget-info": "Información del widget",
|
||||||
|
"validation": "Validación",
|
||||||
|
"invalid-default-value": "valor por defecto inválido",
|
||||||
|
"hint": "Pista",
|
||||||
|
"color": "color",
|
||||||
|
"role-help": {
|
||||||
|
"p1": "¿Qué son los roles de una plantilla?",
|
||||||
|
"p2": "Empieza por especificar cada uno de los roles necesarios para completar el documento. Piensa en las partes implicadas en el proceso de firma y cuáles son sus responsabilidades. Los roles más habituales son RRHH para los documentos internos, Cliente para los contratos o Proveedor para los convenios comerciales.",
|
||||||
|
"p3": "¿Por qué preasignar usuarios a algunos roles?",
|
||||||
|
"p4": "Para los roles que consistentemente involucran al mismo individuo (por ejem., la firma del Gerente en las ofertas de empleo), puedes preasignar un usuario a un rol dentro de una plantilla. Este paso es opcional pero recomendado para la eficiencia y consistencia entre documentos",
|
||||||
|
"p5": "¿Cuando especifico el usuario asignado a cada rol?",
|
||||||
|
"p6": "Cuando crees un documento usando tu plantilla, se te pedirá que asignes usuarios a cada rol definido. Si un rol ya tiene un usuario asignado, este será rellenado con anticipación, pero puedes modificarlo según lo necesites antes de enviar el documento."
|
||||||
|
},
|
||||||
|
"add-recipients": "Agregar destinatarios",
|
||||||
|
"loading-mssg": "Esto podría llevar algún tiempo",
|
||||||
|
"send-mail": "Enviar correo",
|
||||||
|
"placeholder-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma para cada destinatario.",
|
||||||
|
"placeholder-alert-2": "Por favor, confirma que hayas rellenado el campo de texto.",
|
||||||
|
"placeholder-alert-3": " ¿En definitiva quieres enviar este documento para ser firmado?",
|
||||||
|
"placeholder-alert-4": "¡Has enviado exitosamente correos a todos los destinatarios!",
|
||||||
|
"placeholder-alert-5": "¿Quieres firmar documentos ahora mismo?",
|
||||||
|
"placeholder-alert-6": "¡Por favor, configura el adaptador de correo para enviar correos!",
|
||||||
|
"placeholder-alert-7": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
|
||||||
|
"email-subject": "asunto del correo",
|
||||||
|
"email-body": "cuerpo del correo",
|
||||||
|
"email-placeholder": "agregar cuerpo del correo",
|
||||||
|
"reset-to-default": "Restablecer a por defecto",
|
||||||
|
"cutomize-email": "Personalizar correo",
|
||||||
|
"upgrade-to-customize-email": "Mejora para personalizar el correo",
|
||||||
|
"sign-url": "URL de firma",
|
||||||
|
"mails-sent": "Correos enviados",
|
||||||
|
"mail-not-delivered": "correo no entregado",
|
||||||
|
"document-alert": "Alerta de documento",
|
||||||
|
"owner-subscription-expired": "La suscripción del propietario ha expirado.",
|
||||||
|
"subscription-expired": "Suscripción expirada",
|
||||||
|
"alert-message": "Mensaje de alerta",
|
||||||
|
"document-decline": "Rechazar documento",
|
||||||
|
"decline-alert-1": "¿En definitiva quieres rechazar este documento?",
|
||||||
|
"decline-alert-2": "¡Has rechazado este documento!",
|
||||||
|
"decline-alert-3": "No puedes firmar este documento ya que ha sido rechazado/revocado.",
|
||||||
|
"sign here": "Firma aquí",
|
||||||
|
"guest-email-alert": "el código de verificación ha sido enviado a tu correo",
|
||||||
|
"get-otp-alert": "recibirás un código de verificación por correo",
|
||||||
|
"user-already-exist": "El usuario ya existe.",
|
||||||
|
"server-error": "¡Error interno del servidor!",
|
||||||
|
"fill-required-details!": "¡Por favor, rellena los detalles requeridos!",
|
||||||
|
"sign-up-form": "Formulario de registro",
|
||||||
|
"sign-up": "Registrarse",
|
||||||
|
"folder-already-exist!": "¡la carpeta ya existe!",
|
||||||
|
"please-select-position!": "¡por favor, selecciona una posición!",
|
||||||
|
"default-sign-alert": "¿En definitiva quieres firmar automáticamente en todos los lugares solicitados?",
|
||||||
|
"Your-Signature": "Tu firma",
|
||||||
|
"auto-sign-all": "Firmar todo automáticamente",
|
||||||
|
"generating-certificate": "Generando certificado",
|
||||||
|
"pdf-download": "Descargar PDF",
|
||||||
|
"generate-certificate-alert": " Tu certificado de finalización se está generando. Por favor, espera un momento. Si la descarga no inicia pronto, presiona el botón otra vez.",
|
||||||
|
"folder-already-exist": "¡La carpeta ya existe!",
|
||||||
|
"folder-created-successfully": "¡Carpeta creada exitosamente!",
|
||||||
|
"fill-folder-name": "Por favor, rellena el nombre de la carpeta",
|
||||||
|
"already-exists-this-username": "¡Un usuario con este nombre de usuario ya existe!",
|
||||||
|
"verification-code-sent": "¡El correo de verificación ha sido enviado a tu correo!",
|
||||||
|
"registered-user-successfully": "Usuario registrado exitosamente.",
|
||||||
|
"role-not-found": "Rol no encontrado.",
|
||||||
|
"do-not-access": "No tienes acceso, por favor, contacta al administrador.",
|
||||||
|
"add-admin": "Agregar administrador",
|
||||||
|
"opensign-setup": "Instalación de OpenSign",
|
||||||
|
"join-discord": "Únete a nuestro servidor de Discord",
|
||||||
|
"admin-already-exist": "El administrador ya existe.",
|
||||||
|
"password-update-alert-1": "Contraseña actualizada exitosamente.",
|
||||||
|
"password-update-alert-2": "Tu contraseña actual es incorrecta o falta.",
|
||||||
|
"password-update-alert-3": "Tu contraseña actual es incorrecta o falta.",
|
||||||
|
"password-update-alert-4": "Tu contraseña y su confirmación no son iguales.",
|
||||||
|
"current-password": "Contraseña actual",
|
||||||
|
"new-password": "Contraseña nueva",
|
||||||
|
"confirm-password": "Confirmar contraseña",
|
||||||
|
"file-alert-1": "El tamaño del archivo seleccionado es muy grande. Por favor, selecciona un archivo con un tamaño menor a",
|
||||||
|
"file-alert-2": "Por favor, selecciona un archivo.",
|
||||||
|
"file-alert-3": "Por favor, espera mientras se sube el documento.",
|
||||||
|
"enter-pdf-password": "Ingresa la contraseña del PDF",
|
||||||
|
"correct-password": "Por favor, proporciona la contraseña correcta",
|
||||||
|
"decrypting-pdf": " Desencriptando PDF, por favor, espera...",
|
||||||
|
"invalid-otp": "OTP inválido",
|
||||||
|
"user-not-found": "¡Usuario no encontrado!",
|
||||||
|
"enter-otp-alert": "¡Por favor, ingresa el OTP!",
|
||||||
|
"get-verification-code": "Obtener código de verificación",
|
||||||
|
"get-verification-code-2": "Obtendrás un código de verificación por correo",
|
||||||
|
"enter-verification-code": "Ingresar código de verificación",
|
||||||
|
"provide-your-details": "Proporciona tus detalles",
|
||||||
|
"provide-email": "Por favor, proporciona un correo.",
|
||||||
|
"additional-info": "Información adicional",
|
||||||
|
"signature-saved-alert": "Firma guardada exitosamente.",
|
||||||
|
"fill-field": "Por favor, rellena este campo",
|
||||||
|
"error-template": "Error: ¡Plantilla no encontrada!",
|
||||||
|
"error": "Error",
|
||||||
|
"invalid-document": "Error: ¡Documento inválido!",
|
||||||
|
"document-not-found": "¡Documento no encontrado!",
|
||||||
|
"document-signed-alert-1": "Ha firmado exitosamente el documento. Puede descargar o imprimir una copia del documento parcialmente firmado. Se enviará una copia del documento firmado digitalmente y del certificado de finalización al propietario y a todos los firmantes por correo electrónico una vez que todos los firmantes lo hayan firmado.",
|
||||||
|
"encrypted-pdf-not-support": "Los archivos PDF encriptados no están soportados actualmente.",
|
||||||
|
"document-signed-alert-4": " ¡Felicitaciones! 🎉 ¡Este documento ha sido firmado exitosamente por todos los participantes!",
|
||||||
|
"document-signed-alert-5": "Este documento ha sido firmado por todos los firmantes.",
|
||||||
|
"document-signed-alert-6": "Este documento ha sido rechazado por uno o más destinatarios.",
|
||||||
|
"document-signed-alert-7": "Este documento ya no está disponible.",
|
||||||
|
"document-signed-alert-8": "Este documento ya ha sido enviado para ser firmado.",
|
||||||
|
"yet-to-sign": "Todavía por firmar",
|
||||||
|
"validation-alert-1": "Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
|
||||||
|
"account-already-exists": "¡La cuenta ya existe!",
|
||||||
|
"choose-password": "Elegir contraseña",
|
||||||
|
"enter-password": "Ingresar contraseña",
|
||||||
|
"sure": "claro",
|
||||||
|
"subscribed-alert": "¡Ya te has suscrito al plan!",
|
||||||
|
"monthly": "Mensual",
|
||||||
|
"yearly-upto": "Anual (hasta 66% de descuento)",
|
||||||
|
"billed-yearly": "Facturado anualmente",
|
||||||
|
"billed-monthly": "Facturado mensualmente",
|
||||||
|
"plansubscription-1": "Alójalo por tu cuenta gratuitamente",
|
||||||
|
"visit-github": "Visitar GitHub",
|
||||||
|
"user-already-exist-name": "¡Un usuario con este nombre de usuario ya existe!",
|
||||||
|
"do-not-access-contact-admin": "No tienes acceso, por favor, contacta a un administrador.",
|
||||||
|
"filed-required-correctly": "Por favor, rellena correctamente los detalles requeridos.",
|
||||||
|
"admin-created": "Administrador creado",
|
||||||
|
"invalid-masterkey": "Llave maestra inválida",
|
||||||
|
"opensign-Setup": "Instalación de OpenSign",
|
||||||
|
"master-key": " Llave maestra",
|
||||||
|
"profile-update-alert": "Perfil actualizado exitosamente.",
|
||||||
|
"date": "Fecha",
|
||||||
|
"report-not-found": "Reporte no encontrado",
|
||||||
|
"please-wait": "por favor, espera",
|
||||||
|
"select-foler": "Seleccionar carpeta",
|
||||||
|
"generated-on": "Generado el",
|
||||||
|
"text-field": "Campo de texto",
|
||||||
|
"font-size": "Tamaño de la fuente",
|
||||||
|
"widget-status": {
|
||||||
|
"Required": "Requerido",
|
||||||
|
"Optional": "Opcional"
|
||||||
|
},
|
||||||
|
"all-right": "Todos los derechos reservados",
|
||||||
|
"version": "versión",
|
||||||
|
"social-media": {
|
||||||
|
"github": "GitHub",
|
||||||
|
"linked-in": "LinkedIn",
|
||||||
|
"twitter": "Twitter",
|
||||||
|
"discord": "Discord"
|
||||||
|
},
|
||||||
|
"tour-mssg": {
|
||||||
|
"home-layout-1": "¡Has iniciado sesión exitosamente! Echemos un vistazo.",
|
||||||
|
"home-layout-2": "Para subir documentos para firmar tú mismo o para solicitar la firma de otros, simplemente selecciona los botones correspondientes.",
|
||||||
|
"home-layout-3": "¡Ya puedes empezar a utilizar OpenSign! Si necesitas soporte siéntete libre de contactarnos.",
|
||||||
|
"generate-token": "Mejora ahora para generar un token API de producción.",
|
||||||
|
"opensign-drive-1": "Haz clic en los enlaces para navegar fácilmente por la estructura jerárquica de carpetas y ver los documentos de cada carpeta.",
|
||||||
|
"opensign-drive-2": "Haz clic en el botón «Agregar» para crear una nueva carpeta o documento.",
|
||||||
|
"opensign-drive-3": "Ordena tus documentos por «Fecha» o «Nombre» usando este menú.",
|
||||||
|
"opensign-drive-4": "Haz clic en este menú para mostrar los documentos en vista de lista.",
|
||||||
|
"opensign-drive-5": "La lista de documentos es mostrada de acuerdo a la opción de ordenamiento seleccionada. Los íconos situados junto a cada documento indican su estado actual.",
|
||||||
|
"opensign-drive-6": "Haz clic con el botón derecho en un documento para ver opciones como «Descargar», «Renombrar», «Mover» y «Eliminar». Haz clic en el documento para abrirlo.",
|
||||||
|
"opensign-drive-7": "Haz clic con el botón derecho en cualquier carpeta para ver las opciones. Elige «Renombrar» para cambiar el nombre de la carpeta o haz clic en ella para navegar por su contenido.",
|
||||||
|
"pdf-request-file-1": "Lista de firmantes que todavía tienen que firmar este documento.",
|
||||||
|
"pdf-request-file-2": "Haz clic en cualquiera de los marcadores de posición que aparecen en el documento para firmar. A continuación, verás opciones para dibujar tu firma, escribirla o subir una imagen .",
|
||||||
|
"pdf-request-file-3": "Haz clic en los botones «Atrás», «Rechazar» o «Finalizar» para navegar por el documento. Utiliza el menú de tres puntos para ver otras opciones, como el botón «Descargar».",
|
||||||
|
"pdf-request-file-4": "Lista de firmantes que ya han firmado el documento.",
|
||||||
|
"pdf-request-file-5": "Puedes hacer clic en «Firmar todo automáticamente» para firmar de manera automática en todos los lugares que deban ser firmados por ti. Asegúrate de revisar correctamente el documento antes de hacer clic en ese botón.",
|
||||||
|
"placeholder-sign-1": "Selecciona un destinatario de esta lista para agregar un marcador de posición dónde este destinatario tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del destinatario una vez lo sueltes en el documento.",
|
||||||
|
"placeholder-sign-2": "Hacer clic en el botón «Agregar destinatarios» te permitirá añadir más firmantes.",
|
||||||
|
"placeholder-sign-3": "Haz clic en este botón para agregar más destinatarios/firmantes al documento.",
|
||||||
|
"placeholder-sign-4": "Arrastra o haz clic en un capo para agregarlo al documento.",
|
||||||
|
"placeholder-sign-5": "El área de contenido del PDF ya muestra los marcadores de posición existentes en la plantilla. Para tu comodidad, estos marcadores de posición coincidirán con el color del nombre del destinatario, haciéndolos fácilmente identificables.",
|
||||||
|
"placeholder-sign-6": "Hacer clic en «Enviar» guardará el documento. En el siguiente paso podrás personalizar los correos que serán enviados a los destinatarios o copiar los enlaces para firmar y compartirlos con los destinatarios por tu cuenta.",
|
||||||
|
"report-1": "Haz clic en el botón «Agregar» para crear una nueva plantilla. Las plantillas son documentos reusables diseñados para generar rápidamente nuevos documentos con la misma estructura pero diferentes firmantes. Por ejemplo, una plantilla de RR.HH. para el proceso de incorporación podría tener roles predefinidos como «Director de RR.HH.» y «Nuevo empleado». Cada vez que utilices la plantilla, puedes asignar el rol de «Nuevo empleado» a los distintos miembros del personal que se incorporen, mientras que el rol de « Director de RR.HH.» permanece constante, lo que facilita un proceso de incorporación fluido para cada persona contratada.",
|
||||||
|
"redirect": "Haz clic en el botón «Usar» para crear un nuevo documento desde una plantilla existente.",
|
||||||
|
"bulksend": "Para crear y enviar rápidamente múltiples documentos usando una plantilla existente, haz clic en el botón «Envío rápido».",
|
||||||
|
"option": "Este menú revela más opciones como «Editar» y «Eliminar». Usa el botón «Editar» para agregar roles, modificar campos y actualizar tu plantilla. Los cambios aplicarán para todos los documentos futuros que sean creados usando esta plantilla pero no afectarán a los documentos ya existentes. Con el botón «Eliminar» puedes eliminar la plantilla.",
|
||||||
|
"signyour-self-1": "Para personalizar el documento antes de que sea firmado, selecciona y arrastra al documento los widgets que prefieras. Escoge el espacio perfecto para cada modificación para adaptar el documento a tus necesidades.",
|
||||||
|
"signyour-self-2": "Arrastra y suelta en cualquier lugar de esta área. Después podrás cambiar el tamaño y moverlo.",
|
||||||
|
"template-placeholder-1": "Hacer clic en el botón «Agregar rol» te permitirá agregar varios roles de firmantes. Puedes asociar usuarios a cada rol en los siguientes pasos.",
|
||||||
|
"template-placeholder-2": "Una vez que los roles hayan sido agregados, selecciona un rol de la lista para agregar un marcador de posición donde éste tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del rol una vez lo sueltes en el documento.",
|
||||||
|
"template-placeholder-3": "Arrastra o haz clic en un capo para agregarlo al documento.",
|
||||||
|
"template-placeholder-4": "Arrastra el marcador de posición para un rol a cualquier lugar del documento. Recuerda, aparecerá con el mismo color que el nombre del rol para poder referenciarlo fácilmente.",
|
||||||
|
"template-placeholder-5": "Hacer clic en «Siguiente» guardará la plantilla actual. Luego de guardar, se te consultará si deseas crear un nuevo documento usando esta plantilla.",
|
||||||
|
"webhook-1": "Mejora ahora para configurar un webhook",
|
||||||
|
"Need your Signature": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan por tu revisión.",
|
||||||
|
"Out for signatures": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan tu firma.",
|
||||||
|
"Recent signature requests": "Esta es una lista de documentos que esperan por tu firma.",
|
||||||
|
"Recently sent for signatures": "Esta es una lista de documentos que has enviado a otras partes para que sea firmado.",
|
||||||
|
"Drafts": "Estos son documentos que has empezado pero que todavía no finalizas para su envío.",
|
||||||
|
"public-template": "Este video muestra cómo puedes configurar tu perfil público personalizado, como «https://opensign.me/tu-nombre-de-usuario». También aprenderás cómo personalizar tu eslogan y cómo hacer tus plantillas disponibles para su firmado público."
|
||||||
|
},
|
||||||
|
"enter-email-plaholder": "Agrega una dirección de correo y presiona «Enter»",
|
||||||
|
"success-email-alert": "¡Correo enviado exitosamente!",
|
||||||
|
"expired-doc-title": "Documento expirado",
|
||||||
|
"expired-on-mssg": "Este documento expiro el {{expiredDate}} y ya no está disponible para ser firmado.",
|
||||||
|
"signature-validate-alert": "Por favor, confirma que has seleccionado al menos {{minRequiredCount}} casillas.",
|
||||||
|
"signature-validate-alert-2": "Asegúrate de que este campo esté correctamente rellenado y que cumpla con todos los requisitos.",
|
||||||
|
"remaing-users": "Usuarios restantes",
|
||||||
|
"Role": "Rol",
|
||||||
|
"additional-users": "Por favor, compra el complemento Usuarios.",
|
||||||
|
"Quantity-of-users": "Cantidad de usuarios",
|
||||||
|
"Price": "Precio",
|
||||||
|
"Total-price-for-next-time": "Precio total para la próxima vez",
|
||||||
|
"Proceed": "Proceder",
|
||||||
|
"Select": "Seleccionar",
|
||||||
|
"Add-seats": "Agregar plazas",
|
||||||
|
"user-name-exist": "el nombre de usuario ya existe",
|
||||||
|
"format": "formato",
|
||||||
|
"select-date-format": "Selecciona un formato de fecha",
|
||||||
|
"quantity-of-credits": "Cantidad de créditos premium",
|
||||||
|
"remaining-credits": "Créditos premium disponibles:",
|
||||||
|
"remaining-credits-help": "Usa créditos premium para la API para la firma de documentos, envío en masa, o para incorporar la integración de OpenSign en tu página web. Te quedan {{allowedcredits}} créditos incluidos y {{addoncredits}} créditos comprados adicionalmente.",
|
||||||
|
"additional-credits": "Por favor, compra créditos premium",
|
||||||
|
"quota-err-quicksend": "Cuota alcanzada, no tienes créditos suficientes.",
|
||||||
|
"buy-credits": "Comprar créditos premium",
|
||||||
|
"rotate-right": "Rotar a la derecha",
|
||||||
|
"rotate-left": "Rotar a la izquierda",
|
||||||
|
"rotate-alert-mssg": "Todos los widgets de esta página se perderán. ¿En definitiva quieres proceder?",
|
||||||
|
"templateid": "ID de plantilla",
|
||||||
|
"bulk-send-subcription-alert": "Por favor, mejora al plan a Professional o Team para usar envío en masa.",
|
||||||
|
"generate-test-token": "Generar token de prueba",
|
||||||
|
"regenerate-test-token": "Regenerar token de prueba",
|
||||||
|
"help-test-token": "Este token puede ser usado para probar las API en el punto de acceso «https://sandbox.opensignlabs.com/api/v1», permitiéndote realizar firmas de documentos ilimitadas. Por favor, ten en cuenta que el API de pruebas firmará tus documentos con certificados autofirmados, que podrían no ser reconocidos por Adobe como válidos. Una vez hayas completado tus pruebas, puedes mejorar a uno de nuestros planes de pago para generar un token de producción.",
|
||||||
|
"help-api-token": "Este token puede ser usado para acceder a las API de producción en el punto de acceso «{{origin}}/api/v1». Solo puede ser generado con uno de nuestros planes de pago.",
|
||||||
|
"reason": "Razón",
|
||||||
|
"decline-by": "Rechazado/revocado por",
|
||||||
|
"document-declined": "Documento rechazado",
|
||||||
|
"public-template-mssg-1": "Para integrar OpenSign a tu proyecto React o Next.js, simplemente ejecuta los siguientes comandos:",
|
||||||
|
"public-template-mssg-2": "Asegúrate de tener «npm» o «yarn» configurado en tu proyecto. Si estás usando «yarn», puedes reemplazar «npm install» con «yarn add @opensign/react».",
|
||||||
|
"public-template-mssg-3": "¿Necesitas más detalles o ejemplos?",
|
||||||
|
"public-template-mssg-4": "Visita la",
|
||||||
|
"public-template-mssg-5": " «npm» para las últimas actualizaciones, documentación detallada e historial de versiones.",
|
||||||
|
"public-template-mssg-6": "Antes de que puedas usar este fragmento de código, debes convertir esta plantilla en pública.",
|
||||||
|
"copy-code": "COPIAR",
|
||||||
|
"copied-code": "COPIADO",
|
||||||
|
"Installation": "Instalación",
|
||||||
|
"Usage": "Uso",
|
||||||
|
"insufficient-credits": "Créditos de firma insuficientes",
|
||||||
|
"insufficient-credits-mssg": "El propietario de este documento actualmente carece de los créditos OpenSign necesarios para que puedas firmarlo. Por favor, contacta al propietario si necesitas más detalles.",
|
||||||
|
"angular-npm-mssg-1": "Para integrar OpenSign a tu proyecto Angular, simplemente ejecuta los siguientes comandos:",
|
||||||
|
"quota-mail-info-head": "Límite mensual de solicitudes de firma por correo",
|
||||||
|
"quota-mail-info": "Puedes enviar hasta 15 solicitudes de firma por correo cada mes. Mejora ahora para enviar solicitudes de firma sin límite.",
|
||||||
|
"quota-mail-reset": "Los créditos de tu correo electrónico de solicitud de firma se restablecerán el",
|
||||||
|
"quota-mail": "Has alcanzado tu límite de 15 solicitudes de firma por correo para este mes. Mejora ahora para continuar enviando correos.",
|
||||||
|
"quota-mail-tip": "Consejo: Todavía puedes solciitar la firma de <1>documentos ilimitados</1> compartiendo manualmente los enlaces de solicitud de firma.",
|
||||||
|
"quota-mail-head": "Cuota alcanzada",
|
||||||
|
"unauthorized-modal": "No tienes permisos para realizar esta acción, por favor, contacta a {{adminEmail}}.",
|
||||||
|
"sent-this-month": "Enviados este mes",
|
||||||
|
"available-seats": "Plazas disponibles",
|
||||||
|
"buy-users": "Comprar más usuarios",
|
||||||
|
"isenable-otp": "Habilitar verificación con OTP",
|
||||||
|
"isenable-otp-help": {
|
||||||
|
"p1": "¿Te gustaría habilitar el proceso de verificación usando una contraseña de un solo uso (OTP)?",
|
||||||
|
"p2": "Seleccionar esta opción habilitará la verificación con OTP. Los usuarios recibirán un código de verificación por correo, la cual tendrán que ingresar para poder firmar el documento.",
|
||||||
|
"p3": "Seleccionar esta opción deshabilitará la verificación con OTP, lo cual permitirá a los usuarios firmar el documento directamente sin pasos adicionales.",
|
||||||
|
"p4": "Por favor, selecciona la opción que mejor se adapte a tus requisitos para la firma de documentos."
|
||||||
|
},
|
||||||
|
"advanced-options": "Opciones avanzadas",
|
||||||
|
"hide-advanced-options": "Ocultar las opciones avanzadas",
|
||||||
|
"download-files": "Descargar archivos",
|
||||||
|
"download-pdf": "Descargar PDF",
|
||||||
|
"pdf-certificate": "Descargar PDF + Certificado",
|
||||||
|
"document-logs": "Registros de documentos",
|
||||||
|
"server-down": "No se pudo conectar al servidor de OpenSign. Si estás alojando OpenSign por tu cuenta, por favor, asegúrate de que todos los pasos de la documentación han sido seguidos correctamente. Si estás ejecutando OpenSign localmente, puedes estar accediendo a OpenSign por un número de puerto incorrecto.",
|
||||||
|
"admin-exists": "El administrador ya existe. Por favor, inicia sesión en la aplicación usando las credenciales de administrador para poder administrar los usuarios.",
|
||||||
|
"public-tour-message": "Por favor, convierte la plantilla en pública para copiar la URL pública",
|
||||||
|
"add-user-template": "Es necesario agregar un rol antes de poder agregarle campos.",
|
||||||
|
"pdf-uncompatible": "Este pdf no es compatible con opensign, comuníquese con <support@opensignlabs.com>",
|
||||||
|
"enable-tour": "Habilitar recorrido",
|
||||||
|
"istourenabled-help":{
|
||||||
|
"p1": "Esto permitirá realizar una visita guiada para los firmantes, brindando instrucciones durante el proceso de firma.",
|
||||||
|
"p2": "Esto desactivará la visita guiada, lo que garantizará una experiencia de firma más rápida e ininterrumpida.",
|
||||||
|
"p3": "Consejo: si sus firmantes están familiarizados con OpenSign y lo utilizan con frecuencia, es posible que desee desactivar la visita guiada para disfrutar de una experiencia más fluida. Elija la opción que mejor se adapte a sus necesidades de firma de documentos"
|
||||||
|
},
|
||||||
|
"form-title-1": "Configuración del flujo de documentos",
|
||||||
|
"form-title-2": "Configuración de seguridad",
|
||||||
|
"text-field-tour":"Los campos de tipo 'Texto' deben completarse con anticipación antes de enviar el documento. Si necesita que los firmantes proporcionen información, utilice el campo 'Entrada de texto'",
|
||||||
|
"attach-signer-tour" :"Debe adjuntar un firmante a cada función. Puede hacerlo haciendo clic en este icono. Una vez que seleccione un Firmante, se adjuntará a todos los campos asociados con ese rol que aparecen en el mismo color.",
|
||||||
|
"allowed-signature-types": "Tipos de firma permitidos",
|
||||||
|
"at-least-one-signature-type": "Se debe habilitar al menos un tipo de firma.",
|
||||||
|
"expect-default-one-signature-type": "Habilite un tipo de firma adicional aparte del predeterminado.",
|
||||||
|
"add-signer-note": "Nota - Este contacto se agregará a su lista de contactos",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "Esta preferencia de firma controla qué opciones de firma están disponibles para sus firmantes. Solo los tipos de firma que seleccione aparecerán en el widget de firma cuando se firme un documento. Por ejemplo, si elige sólo la opción 'Draw' en las preferencias, su firmante verá sólo la opción 'Draw' en el widget de firma, mientras que las otras tres opciones no estarán disponibles.",
|
||||||
|
"l1": "Cree una firma manuscrita directamente en la pantalla usando su dedo o un lápiz.",
|
||||||
|
"l2": "Ingrese su nombre y elija entre varios estilos de fuente para crear una firma.",
|
||||||
|
"l3": "Cargue una versión digital existente de su firma.",
|
||||||
|
"l4": "Utilice un estilo de firma preestablecido guardado en 'Mi firma' en su configuración."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notificar sobre firmas",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "El creador del documento recibirá una notificación por correo electrónico cada vez que un firmante firme el documento.",
|
||||||
|
"note": "Nota: No se enviará un correo electrónico de notificación al último firmante, ya que el creador del documento recibirá un correo electrónico de finalización."
|
||||||
|
},
|
||||||
|
"expiry-date": "Date d'expiration",
|
||||||
|
"expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Proporcione una nueva fecha de vencimiento que sea posterior a la actual",
|
||||||
|
"delete-page": "eliminar página",
|
||||||
|
"delete-alert": "No se puede eliminar una sola página",
|
||||||
|
"delete-alert-2": "¿Está seguro de que desea eliminar esta página?",
|
||||||
|
"delete-note": "Nota: una vez que elimines esta página, no podrás deshacerla"
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"header-news": "Nouvelle fonctionnalité : les profils publics sont désormais en ligne ! Créez et partagez facilement des modèles publics",
|
"header-news": "Nouvelle fonctionnalité : les utilisateurs du forfait Teams peuvent désormais intégrer leurs propres compartiments AWS S3 pour le stockage de fichiers",
|
||||||
"header-news-btn": "Configurer maintenant",
|
"header-news-btn": "Configurer maintenant",
|
||||||
"create-account": "Créer un compte",
|
"create-account": "Créer un compte",
|
||||||
"login": "Se Connecter",
|
"login": "Se Connecter",
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
"My Signature": "Ma signature",
|
"My Signature": "Ma signature",
|
||||||
"API Token": "Jeton API",
|
"API Token": "Jeton API",
|
||||||
"Webhook": "Webhook",
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Préférences",
|
||||||
"Teams": "Équipe",
|
"Teams": "Équipe",
|
||||||
"Team-update-successfully": "Équipe mise à jour avec succès.",
|
"Team-update-successfully": "Équipe mise à jour avec succès.",
|
||||||
"Users": "Utilisateurs"
|
"Users": "Utilisateurs"
|
||||||
@@ -137,7 +138,8 @@
|
|||||||
"Status": "Statut",
|
"Status": "Statut",
|
||||||
"created-date": "Date de création",
|
"created-date": "Date de création",
|
||||||
"Type": "Saisir",
|
"Type": "Saisir",
|
||||||
"Logs": "Journaux"
|
"Logs": "Journaux",
|
||||||
|
"Expiry-date": "Fecha de caducidad"
|
||||||
},
|
},
|
||||||
"btnLabel": {
|
"btnLabel": {
|
||||||
"sign": "Signer",
|
"sign": "Signer",
|
||||||
@@ -152,7 +154,9 @@
|
|||||||
"View": "Voir",
|
"View": "Voir",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Intégrer",
|
"Embed": "Intégrer",
|
||||||
"Copy TemplateId": "Copier l'ID du modèle"
|
"Copy TemplateId": "Copier l'ID du modèle",
|
||||||
|
"Copy Public URL":"Copier l'URL publique",
|
||||||
|
"extend-expiry-date": "Prolonger la date d'expiration"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
@@ -263,10 +267,11 @@
|
|||||||
"make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?",
|
"make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?",
|
||||||
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
||||||
"public-role": "Rôle public",
|
"public-role": "Rôle public",
|
||||||
"public-url": "URL publique",
|
"public-url": "Profil public",
|
||||||
|
"embed-template": "Intégrer le modèle",
|
||||||
"public-url-copy": "Voici votre URL publique : ",
|
"public-url-copy": "Voici votre URL publique : ",
|
||||||
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
||||||
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
"add-public-url-alert": "Veuillez terminer la configuration de votre profil public OpenSign. Une fois cela fait, vous pourrez rendre les modèles publics. Ce processus ne doit être effectué qu’une seule fois.",
|
||||||
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
||||||
"share-with": "Partager avec",
|
"share-with": "Partager avec",
|
||||||
"team-not-found": "Équipe introuvable",
|
"team-not-found": "Équipe introuvable",
|
||||||
@@ -289,7 +294,7 @@
|
|||||||
"subject": "Sujet",
|
"subject": "Sujet",
|
||||||
"body": "Corps",
|
"body": "Corps",
|
||||||
"add-contact": "Ajouter le contact",
|
"add-contact": "Ajouter le contact",
|
||||||
"add-signer-alert": "Le contact existe déjà !",
|
"add-signer-alert": "Le contact existe déjà ! Veuillez le sélectionner dans la liste déroulante 'Signataires'",
|
||||||
"record-delete-alert": "Enregistrement supprimé avec succès !",
|
"record-delete-alert": "Enregistrement supprimé avec succès !",
|
||||||
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
|
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
|
||||||
"mail-sent-alert": "Courriel envoyé avec succès.",
|
"mail-sent-alert": "Courriel envoyé avec succès.",
|
||||||
@@ -443,7 +448,8 @@
|
|||||||
"cutomize-email": "Personnaliser l'e-mail",
|
"cutomize-email": "Personnaliser l'e-mail",
|
||||||
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
|
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
|
||||||
"sign-url": "Signer l'URL",
|
"sign-url": "Signer l'URL",
|
||||||
"Mails Sent": "Mails envoyés avec succès !",
|
"mails-sent": "Mails envoyés avec succès !",
|
||||||
|
"mail-not-delivered": "Courrier non distribué",
|
||||||
"document-alert": "Alerte document",
|
"document-alert": "Alerte document",
|
||||||
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
|
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
|
||||||
"subscription-expired": "Abonnement expiré",
|
"subscription-expired": "Abonnement expiré",
|
||||||
@@ -508,7 +514,7 @@
|
|||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
"invalid-document": "Erreur : document invalide !",
|
"invalid-document": "Erreur : document invalide !",
|
||||||
"document-not-found": "Document introuvable !",
|
"document-not-found": "Document introuvable !",
|
||||||
"document-signed-alert-1": "Vous avez signé le document avec succès. Vous pouvez télécharger ou imprimer une copie du document partiellement signé. Une copie du document signé numériquement sera envoyée au propriétaire par e-mail une fois qu'il sera signé par tous les signataires.",
|
"document-signed-alert-1": "Vous avez signé le document avec succès. Vous pouvez télécharger ou imprimer une copie du document partiellement signé. Une copie du document signé numériquement et du certificat d'achèvement sera envoyée au propriétaire et à tous les signataires par e-mail une fois qu'il aura été signé par tous les signataires.",
|
||||||
"encrypted-pdf-not-support": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge. ",
|
"encrypted-pdf-not-support": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge. ",
|
||||||
"document-signed-alert-4": "Toutes nos félicitations! 🎉 Ce document a été signé avec succès par tous les participants !",
|
"document-signed-alert-4": "Toutes nos félicitations! 🎉 Ce document a été signé avec succès par tous les participants !",
|
||||||
"document-signed-alert-5": "Ce document a été signé par tous les signataires.",
|
"document-signed-alert-5": "Ce document a été signé par tous les signataires.",
|
||||||
@@ -638,7 +644,7 @@
|
|||||||
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
|
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
|
||||||
"public-template-mssg-4": "Visitez le",
|
"public-template-mssg-4": "Visitez le",
|
||||||
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
||||||
"public-template-mssg-6":"Vous devez définir ce modèle comme public avant de pouvoir utiliser cet extrait de code.",
|
"public-template-mssg-6":"Avant de pouvoir utiliser cet extrait de code, vous devez rendre ce modèle public.",
|
||||||
"copy-code":"COPIE",
|
"copy-code":"COPIE",
|
||||||
"copied-code":"COPIÉ",
|
"copied-code":"COPIÉ",
|
||||||
"Installation":"Installation",
|
"Installation":"Installation",
|
||||||
@@ -648,6 +654,7 @@
|
|||||||
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
||||||
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
||||||
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
||||||
|
"quota-mail-reset": "Les crédits de votre email de demande de signature seront réinitialisés le",
|
||||||
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
||||||
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
||||||
"quota-mail-head":"Quota atteint",
|
"quota-mail-head":"Quota atteint",
|
||||||
@@ -667,6 +674,43 @@
|
|||||||
"download-files" :"Télécharger des fichiers",
|
"download-files" :"Télécharger des fichiers",
|
||||||
"download-pdf" :"Télécharger le PDF",
|
"download-pdf" :"Télécharger le PDF",
|
||||||
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
||||||
"document-logs":"Journaux de documents"
|
"document-logs":"Journaux de documents",
|
||||||
|
"server-down": "Impossible de se connecter au serveur OpenSign. Si vous hébergez vous-même OpenSign, veuillez vous assurer que toutes les étapes de la documentation ont été correctement suivies. Si vous exécutez OpenSign localement, vous y accédez peut-être via un numéro de port incorrect.",
|
||||||
|
"admin-exists": "L'administrateur existe déjà. Veuillez vous connecter à l'application en utilisant les informations d'identification de l'administrateur afin de gérer les utilisateurs.",
|
||||||
|
"enable-tour": "Activer la visite",
|
||||||
|
"istourenabled-otp-help":{
|
||||||
|
"p1": "Cela permettra une visite guidée pour les signataires, fournissant des instructions pendant le processus de signature.",
|
||||||
|
"p2": "Cela désactivera la visite guidée, garantissant ainsi une expérience de signature plus rapide et ininterrompue.",
|
||||||
|
"p3": "Conseil : si vos signataires connaissent OpenSign et l'utilisent fréquemment, vous souhaiterez peut-être désactiver la visite guidée pour une expérience plus fluide. Choisissez l'option qui correspond le mieux à vos besoins en matière de signature de documents."
|
||||||
|
},
|
||||||
|
"form-title-1": "Paramètre du flux de documents",
|
||||||
|
"form-title-2": "Paramètre de sécurité",
|
||||||
|
"public-tour-message": "Le modèle doit être public avant que vous puissiez générer un lien partageable.",
|
||||||
|
"add-user-template":"Vous devez ajouter un rôle avant de pouvoir lui ajouter des champs. ",
|
||||||
|
"pdf-uncompatible":"Ce pdf n'est pas compatible avec opensign, veuillez contacter <support@opensignlabs.com>",
|
||||||
|
"text-field-tour" :"Les champs de type 'Texte' doivent être remplis à l'avance avant l'envoi du document. Si vous avez besoin que les signataires fournissent des informations, utilisez plutôt le champ 'Saisie de texte'.",
|
||||||
|
"attach-signer-tour" :"Vous devez associer un signataire à chaque rôle. Vous pouvez le faire en cliquant sur cette icône. Une fois que vous avez sélectionné un signataire, il sera attaché à tous les champs associés à ce rôle qui apparaissent dans la même couleur.",
|
||||||
|
"allowed-signature-types": "Types de signature autorisés",
|
||||||
|
"at-least-one-signature-type": "Au moins un type de signature doit être activé.",
|
||||||
|
"expect-default-one-signature-type": "Veuillez activer un type de signature supplémentaire en plus de celui par défaut.",
|
||||||
|
"add-signer-note": "Remarque - Ce contact sera ajouté à votre liste de contacts",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "Cette préférence de signature contrôle les options de signature disponibles pour vos signataires. Seuls les types de signature que vous sélectionnez apparaîtront dans le widget de signature lorsqu'un document est signé. Par exemple, si vous choisissez uniquement l'option 'Draw' dans les préférences, votre signataire ne verra que l'option 'Draw' dans le widget de signature, tandis que les trois autres options ne seront pas disponibles.",
|
||||||
|
"l1": "Créez une signature manuscrite directement sur l'écran à l'aide de votre doigt ou d'un stylet.",
|
||||||
|
"l2": "Entrez votre nom et choisissez parmi différents styles de police pour créer une signature.",
|
||||||
|
"l3": "Téléchargez une version numérique existante de votre signature.",
|
||||||
|
"l4": "Utilisez un style de signature prédéfini enregistré sous 'Ma signature' dans vos paramètres."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notifier les signatures",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "Le créateur du document recevra une notification par e-mail chaque fois qu'un signataire signera le document.",
|
||||||
|
"note": "Remarque : L'e-mail de notification ne sera pas envoyé pour le dernier signataire, car le créateur du document recevra à la place un e-mail de fin."
|
||||||
|
},
|
||||||
|
"expiry-date": "Fecha de caducidad",
|
||||||
|
"expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Veuillez fournir une nouvelle date d'expiration postérieure à la date actuelle",
|
||||||
|
"delete-page": "supprimer la page",
|
||||||
|
"delete-alert": "Impossible de supprimer une seule page",
|
||||||
|
"delete-alert-2": "Etes-vous sûr de vouloir supprimer cette page ?",
|
||||||
|
"delete-note": "Remarque : une fois cette page supprimée, vous ne pouvez plus l'annuler"
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -35,6 +35,7 @@ const GenerateToken = lazy(() => import("./pages/GenerateToken"));
|
|||||||
const Webhook = lazy(() => import("./pages/Webhook"));
|
const Webhook = lazy(() => import("./pages/Webhook"));
|
||||||
const AddAdmin = lazy(() => import("./pages/AddAdmin"));
|
const AddAdmin = lazy(() => import("./pages/AddAdmin"));
|
||||||
const UpdateExistUserAdmin = lazy(() => import("./pages/UpdateExistUserAdmin"));
|
const UpdateExistUserAdmin = lazy(() => import("./pages/UpdateExistUserAdmin"));
|
||||||
|
const Preferences = lazy(() => import("./pages/Preferences"));
|
||||||
|
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
|
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
|
||||||
const AppLoader = () => {
|
const AppLoader = () => {
|
||||||
@@ -198,6 +199,10 @@ function App() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Route path="/users" element={<UserList />} />
|
<Route path="/users" element={<UserList />} />
|
||||||
|
<Route
|
||||||
|
path="/preferences"
|
||||||
|
element={<LazyPage Page={Preferences} />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/sso" element={<SSOVerify />} />
|
<Route path="/sso" element={<SSOVerify />} />
|
||||||
<Route path="*" element={<PageNotFound />} />
|
<Route path="*" element={<PageNotFound />} />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { emailRegex } from "../constant/const";
|
||||||
|
|
||||||
const AddSigner = (props) => {
|
const AddSigner = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -47,6 +48,9 @@ const AddSigner = (props) => {
|
|||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
if (localStorage.getItem("TenantId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
try {
|
try {
|
||||||
@@ -181,6 +185,7 @@ const AddSigner = (props) => {
|
|||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert(t("something-went-wrong-mssg"));
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define a function to handle the "add yourself" checkbox
|
// Define a function to handle the "add yourself" checkbox
|
||||||
@@ -206,6 +211,7 @@ const AddSigner = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="w-full mx-auto p-2 text-base-content">
|
<div className="w-full mx-auto p-2 text-base-content">
|
||||||
|
<p className="mb-3">{t("add-signer-note")}</p>
|
||||||
{isUserExist && (
|
{isUserExist && (
|
||||||
<div className="mb-3 flex items-center">
|
<div className="mb-3 flex items-center">
|
||||||
<input
|
<input
|
||||||
@@ -268,6 +274,7 @@ const AddSigner = (props) => {
|
|||||||
onChange={(e) => setPhone(e.target.value)}
|
onChange={(e) => setPhone(e.target.value)}
|
||||||
disabled={addYourself}
|
disabled={addYourself}
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
placeholder={t("phone-optional")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex gap-x-2 justify-start">
|
<div className="mt-4 flex gap-x-2 justify-start">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Parse from "parse";
|
|||||||
import Title from "./Title";
|
import Title from "./Title";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { copytoData, fetchSubscriptionInfo } from "../constant/Utils";
|
import { copytoData, fetchSubscriptionInfo } from "../constant/Utils";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
function generatePassword(length) {
|
function generatePassword(length) {
|
||||||
const characters =
|
const characters =
|
||||||
@@ -115,6 +115,9 @@ const AddUser = (props) => {
|
|||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
if (!emailRegex.test(formdata.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
setIsFormLoader(true);
|
setIsFormLoader(true);
|
||||||
const res = await checkUserExist();
|
const res = await checkUserExist();
|
||||||
@@ -196,7 +199,9 @@ const AddUser = (props) => {
|
|||||||
}
|
}
|
||||||
if (props.handleUserData) {
|
if (props.handleUserData) {
|
||||||
if (formdata?.team) {
|
if (formdata?.team) {
|
||||||
const team = teamList.find((x) => x.objectId === formdata.team);
|
const team = teamList.find(
|
||||||
|
(x) => x.objectId === formdata.team
|
||||||
|
);
|
||||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||||
y.objectId === team.objectId ? team : y
|
y.objectId === team.objectId ? team : y
|
||||||
);
|
);
|
||||||
@@ -205,7 +210,13 @@ const AddUser = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsFormLoader(false);
|
setIsFormLoader(false);
|
||||||
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
|
setFormdata({
|
||||||
|
name: "",
|
||||||
|
email: "",
|
||||||
|
phone: "",
|
||||||
|
team: "",
|
||||||
|
role: ""
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
@@ -238,7 +249,9 @@ const AddUser = (props) => {
|
|||||||
}
|
}
|
||||||
if (props.handleUserData) {
|
if (props.handleUserData) {
|
||||||
if (formdata?.team) {
|
if (formdata?.team) {
|
||||||
const team = teamList.find((x) => x.objectId === formdata.team);
|
const team = teamList.find(
|
||||||
|
(x) => x.objectId === formdata.team
|
||||||
|
);
|
||||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||||
y.objectId === team.objectId ? team : y
|
y.objectId === team.objectId ? team : y
|
||||||
);
|
);
|
||||||
@@ -246,7 +259,13 @@ const AddUser = (props) => {
|
|||||||
props.handleUserData(parseData);
|
props.handleUserData(parseData);
|
||||||
}
|
}
|
||||||
setIsFormLoader(false);
|
setIsFormLoader(false);
|
||||||
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
|
setFormdata({
|
||||||
|
name: "",
|
||||||
|
email: "",
|
||||||
|
phone: "",
|
||||||
|
team: "",
|
||||||
|
role: ""
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -257,7 +276,11 @@ const AddUser = (props) => {
|
|||||||
msg: t("something-went-wrong-mssg")
|
msg: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500);
|
setTimeout(
|
||||||
|
() => props.setIsAlert({ type: "success", msg: "" }),
|
||||||
|
1500
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -408,13 +431,13 @@ const AddUser = (props) => {
|
|||||||
{t("phone")}
|
{t("phone")}
|
||||||
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
||||||
</label>
|
</label>
|
||||||
|
{/* added hint for phone number being optional */}
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="phone"
|
name="phone"
|
||||||
placeholder="optional"
|
placeholder={t("phone-optional")}
|
||||||
value={formdata.phone}
|
value={formdata.phone}
|
||||||
onChange={(e) => handleChange(e)}
|
onChange={(e) => handleChange(e)}
|
||||||
// required
|
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Loader from "../primitives/Loader";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import { fetchSubscription } from "../constant/Utils";
|
import { fetchSubscription } from "../constant/Utils";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
const BulkSendUi = (props) => {
|
const BulkSendUi = (props) => {
|
||||||
@@ -69,7 +69,21 @@ const BulkSendUi = (props) => {
|
|||||||
if (subscription?.plan === "freeplan") {
|
if (subscription?.plan === "freeplan") {
|
||||||
setIsFreePlan(true);
|
setIsFreePlan(true);
|
||||||
}
|
}
|
||||||
const resCredits = await Parse.Cloud.run("allowedcredits");
|
const token = props.jwttoken
|
||||||
|
? { jwttoken: props.jwttoken }
|
||||||
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
|
const axiosres = await axios.post(
|
||||||
|
`${localStorage.getItem("baseUrl")}functions/allowedcredits`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
...token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const resCredits = axiosres.data && axiosres.data.result;
|
||||||
if (resCredits) {
|
if (resCredits) {
|
||||||
const allowedcredits = resCredits?.allowedcredits || 0;
|
const allowedcredits = resCredits?.allowedcredits || 0;
|
||||||
const addoncredits = resCredits?.addoncredits || 0;
|
const addoncredits = resCredits?.addoncredits || 0;
|
||||||
@@ -81,7 +95,7 @@ const BulkSendUi = (props) => {
|
|||||||
}
|
}
|
||||||
setAmount((obj) => ({ ...obj, totalcredits: totalcredits }));
|
setAmount((obj) => ({ ...obj, totalcredits: totalcredits }));
|
||||||
}
|
}
|
||||||
const getPlaceholder = props.item?.Placeholders;
|
const getPlaceholder = props?.Placeholders;
|
||||||
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
||||||
placeholderObj?.placeHolder?.some((holder) =>
|
placeholderObj?.placeHolder?.some((holder) =>
|
||||||
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
||||||
@@ -97,7 +111,7 @@ const BulkSendUi = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setIsBulkAvailable(true);
|
setIsBulkAvailable(true);
|
||||||
setAdmin((obj) => ({ ...obj, isAdmin: true }));
|
setAdmin((obj) => ({ ...obj, isAdmin: true }));
|
||||||
const getPlaceholder = props.item?.Placeholders;
|
const getPlaceholder = props?.Placeholders;
|
||||||
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
||||||
placeholderObj?.placeHolder?.some((holder) =>
|
placeholderObj?.placeHolder?.some((holder) =>
|
||||||
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
||||||
@@ -188,13 +202,26 @@ const BulkSendUi = (props) => {
|
|||||||
const updatedForms = forms.filter((_, i) => i !== index);
|
const updatedForms = forms.filter((_, i) => i !== index);
|
||||||
setForms(updatedForms);
|
setForms(updatedForms);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function validateEmails(data) {
|
||||||
|
for (const item of data) {
|
||||||
|
for (const field of item.fields) {
|
||||||
|
if (!emailRegex.test(field.email)) {
|
||||||
|
alert(`Invalid email found: ${field.email}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsSubmit(true);
|
setIsSubmit(true);
|
||||||
|
if (validateEmails(forms)) {
|
||||||
// Create a copy of Placeholders array from props.item
|
// Create a copy of Placeholders array from props.item
|
||||||
let Placeholders = [...props.item.Placeholders];
|
let Placeholders = [...props.Placeholders];
|
||||||
// Initialize an empty array to store updated documents
|
// Initialize an empty array to store updated documents
|
||||||
let Documents = [];
|
let Documents = [];
|
||||||
// Loop through each form
|
// Loop through each form
|
||||||
@@ -244,19 +271,30 @@ const BulkSendUi = (props) => {
|
|||||||
: [...existSigner]
|
: [...existSigner]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Documents.push({ ...props.item, Placeholders: updatedPlaceholders });
|
Documents.push({
|
||||||
|
...props.item,
|
||||||
|
Placeholders: updatedPlaceholders,
|
||||||
|
SignatureType: props.signatureType
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await batchQuery(Documents);
|
await batchQuery(Documents);
|
||||||
|
} else {
|
||||||
|
setIsSubmit(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const batchQuery = async (Documents) => {
|
const batchQuery = async (Documents) => {
|
||||||
const serverUrl = localStorage.getItem("baseUrl");
|
const token = props.jwttoken
|
||||||
const functionsUrl = `${serverUrl}functions/batchdocuments`;
|
? { jwttoken: props.jwttoken }
|
||||||
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
|
const functionsUrl = `${localStorage.getItem(
|
||||||
|
"baseUrl"
|
||||||
|
)}functions/batchdocuments`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
...token
|
||||||
};
|
};
|
||||||
const params = { Documents: JSON.stringify(Documents) };
|
const params = { Documents: JSON.stringify(Documents) };
|
||||||
try {
|
try {
|
||||||
@@ -362,6 +400,7 @@ const BulkSendUi = (props) => {
|
|||||||
fieldIndex
|
fieldIndex
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
jwttoken={props?.jwttoken}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Parse from "parse";
|
|||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import {
|
import {
|
||||||
checkIsSubscribed,
|
checkIsSubscribed,
|
||||||
|
formatDate,
|
||||||
getAppLogo,
|
getAppLogo,
|
||||||
openInNewTab,
|
openInNewTab,
|
||||||
saveLanguageInLocal
|
saveLanguageInLocal
|
||||||
@@ -16,7 +17,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import QuotaCard from "../primitives/QuotaCard";
|
import QuotaCard from "../primitives/QuotaCard";
|
||||||
|
|
||||||
const Header = ({ showSidebar }) => {
|
const Header = ({ showSidebar, setIsMenu }) => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
@@ -33,6 +34,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
);
|
);
|
||||||
const [emailUsed, setEmailUsed] = useState(0);
|
const [emailUsed, setEmailUsed] = useState(0);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [emailResetDate, setEmailResetDate] = useState("");
|
||||||
const [showNotification, setShowNotification] = useState(
|
const [showNotification, setShowNotification] = useState(
|
||||||
(!dismissedVersion || dismissedVersion !== current_notification_version) &&
|
(!dismissedVersion || dismissedVersion !== current_notification_version) &&
|
||||||
true
|
true
|
||||||
@@ -40,7 +42,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
if (width <= 768) {
|
if (width <= 768) {
|
||||||
showSidebar();
|
setIsMenu(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -64,6 +66,14 @@ const Header = ({ showSidebar }) => {
|
|||||||
const extUser = await Parse.Cloud.run("getUserDetails");
|
const extUser = await Parse.Cloud.run("getUserDetails");
|
||||||
const MonthlyFreeEmails = extUser?.get("MonthlyFreeEmails") || 0;
|
const MonthlyFreeEmails = extUser?.get("MonthlyFreeEmails") || 0;
|
||||||
setEmailUsed(MonthlyFreeEmails);
|
setEmailUsed(MonthlyFreeEmails);
|
||||||
|
if (extUser) {
|
||||||
|
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||||
|
if (_extUser?.LastEmailCountReset?.iso) {
|
||||||
|
const resetDate = formatDate(_extUser?.LastEmailCountReset?.iso);
|
||||||
|
setEmailResetDate(resetDate);
|
||||||
|
}
|
||||||
|
localStorage.setItem("Extand_Class", JSON.stringify([_extUser]));
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in while fetching monthlyfreeEmails", err);
|
console.log("err in while fetching monthlyfreeEmails", err);
|
||||||
}
|
}
|
||||||
@@ -140,6 +150,13 @@ const Header = ({ showSidebar }) => {
|
|||||||
);
|
);
|
||||||
setShowNotification(false);
|
setShowNotification(false);
|
||||||
};
|
};
|
||||||
|
const handleSetupNowNavigation = () => {
|
||||||
|
const url = isStaging
|
||||||
|
? "https://staging-console.opensignlabs.com/fileadapter"
|
||||||
|
: "https://console.opensignlabs.com/fileadapter";
|
||||||
|
|
||||||
|
openInNewTab(url);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isEnableSubscription && showNotification && (
|
{isEnableSubscription && showNotification && (
|
||||||
@@ -148,7 +165,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
{t("header-news")} —
|
{t("header-news")} —
|
||||||
<span
|
<span
|
||||||
className="cursor-pointer font-medium underline text-blue-800"
|
className="cursor-pointer font-medium underline text-blue-800"
|
||||||
onClick={() => navigate("/profile")}
|
onClick={() => handleSetupNowNavigation()}
|
||||||
>
|
>
|
||||||
{" " + t("header-news-btn") + "."}
|
{" " + t("header-news-btn") + "."}
|
||||||
</span>
|
</span>
|
||||||
@@ -291,7 +308,11 @@ const Header = ({ showSidebar }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi isOpen={isModal}>
|
<ModalUi isOpen={isModal}>
|
||||||
<QuotaCard isPaidInfo={true} handlClose={handleMailUsed} />
|
<QuotaCard
|
||||||
|
isPaidInfo={true}
|
||||||
|
handlClose={handleMailUsed}
|
||||||
|
emailResetDate={emailResetDate}
|
||||||
|
/>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ function RotateAlert(props) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={props.isRotate}
|
isOpen={props.showRotateAlert}
|
||||||
title={t("Rotation-alert")}
|
title={t("Rotation-alert")}
|
||||||
handleClose={() => props.setIsRotate({ status: false, degree: 0 })}
|
handleClose={() => props.setShowRotateAlert({ status: false, degree: 0 })}
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
<div className="p-[20px] h-full">
|
<div className="p-[20px] h-full">
|
||||||
@@ -16,7 +16,9 @@ function RotateAlert(props) {
|
|||||||
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => props.setIsRotate({ status: false, degree: 0 })}
|
onClick={() =>
|
||||||
|
props.setShowRotateAlert({ status: false, degree: 0 })
|
||||||
|
}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost shadow-md"
|
className="op-btn op-btn-ghost shadow-md"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React, { useState, useEffect, useRef } from "react";
|
|||||||
import "../../styles/opensigndrive.css";
|
import "../../styles/opensigndrive.css";
|
||||||
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 { 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";
|
||||||
@@ -264,12 +263,6 @@ function DriveBody(props) {
|
|||||||
setIsOpenMoveModal(false);
|
setIsOpenMoveModal(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sanitizeFileName = (pdfName) => {
|
|
||||||
// Replace spaces with underscore
|
|
||||||
return pdfName.replace(/ /g, "_");
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEnterPress = (e, data) => {
|
const handleEnterPress = (e, data) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
handledRenameDoc(data);
|
handledRenameDoc(data);
|
||||||
|
|||||||
@@ -1,11 +1,24 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
function BorderResize({ right, top }) {
|
function BorderResize(props) {
|
||||||
|
const getHeight = () => {
|
||||||
|
const height = props.posHeight(props.pos, props.isSignYourself);
|
||||||
|
if (height > 14) {
|
||||||
|
return "14px";
|
||||||
|
} else {
|
||||||
|
return `${height}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${right ? `-right-[12px]` : "-right-[1px]"} ${
|
style={{
|
||||||
top ? `-bottom-[11px]` : "-bottom-[1px]"
|
width: getHeight() || "14px",
|
||||||
} absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize border-r-[3px] border-b-[3px] border-[#188ae2]`}
|
height: getHeight() || "14px"
|
||||||
|
}}
|
||||||
|
className={`${props.right ? `-right-[12px]` : "-right-[2px]"} ${
|
||||||
|
props.top ? `-bottom-[12px]` : "-bottom-[2px] "
|
||||||
|
} absolute inline-block hover:cursor-sw-resize border-r-[3px] border-b-[3px] border-[#188ae2]`}
|
||||||
></div>
|
></div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
function DefaultSignature(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const confirmToaddDefaultSign = () => {
|
const confirmToaddDefaultSign = () => {
|
||||||
if (xyPostion.length > 0) {
|
if (props?.xyPostion.length > 0) {
|
||||||
setDefaultSignAlert({
|
props?.setDefaultSignAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: t("default-sign-alert")
|
alertMessage: t("default-sign-alert")
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setDefaultSignAlert({
|
props?.setDefaultSignAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: t("please-select-position!")
|
alertMessage: t("please-select-position!")
|
||||||
});
|
});
|
||||||
@@ -22,22 +22,30 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
|||||||
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
||||||
{t("signature")}
|
{t("signature")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center mt-[10px] font-semibold">
|
<div className="flex flex-col items-center mt-[10px] font-semibold relative">
|
||||||
<p className="text-base-content">{t("Your-Signature")}</p>
|
<p className="text-base-content">{t("Your-Signature")}</p>
|
||||||
<div className="op-card shadow-md h-[111px] w-[90%] p-2">
|
<div className="op-card shadow-md h-[111px] w-[90%] p-2">
|
||||||
<img
|
<img
|
||||||
alt="signature"
|
alt="signature"
|
||||||
className="w-full h-full object-contain"
|
className="w-full h-full object-contain"
|
||||||
src={defaultSignImg}
|
src={props?.defaultSignImg}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm mt-[10px]"
|
className="op-btn op-btn-primary op-btn-sm mt-[10px]"
|
||||||
onClick={() => confirmToaddDefaultSign()}
|
onClick={() => confirmToaddDefaultSign()}
|
||||||
|
disabled={!props?.isDefault}
|
||||||
>
|
>
|
||||||
{t("auto-sign-all")}
|
{t("auto-sign-all")}
|
||||||
</button>
|
</button>
|
||||||
|
{!props.isDefault && (
|
||||||
|
<div className="absolute bg-black/70 text-white w-full h-full flex items-center justify-center text-[11px] cursor-default">
|
||||||
|
<span className="-rotate-45">
|
||||||
|
Document creator has disabled this option
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -339,9 +339,9 @@ function DropdownWidgetOption(props) {
|
|||||||
value={
|
value={
|
||||||
props.fontSize ||
|
props.fontSize ||
|
||||||
props.currWidgetsDetails?.options?.fontSize ||
|
props.currWidgetsDetails?.options?.fontSize ||
|
||||||
"12"
|
12
|
||||||
}
|
}
|
||||||
onChange={(e) => props.setFontSize(e.target.value)}
|
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
|
||||||
>
|
>
|
||||||
{fontsizeArr.map((size, ind) => {
|
{fontsizeArr.map((size, ind) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ import { isEnableSubscription } from "../../constant/const";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Tooltip } from "react-tooltip";
|
import { Tooltip } from "react-tooltip";
|
||||||
|
|
||||||
// import SelectFolder from "../../premitives/SelectFolder";
|
const EditTemplate = ({ template, onSuccess, jwttoken }) => {
|
||||||
|
|
||||||
const EditTemplate = ({ template, onSuccess }) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
Name: template?.Name || "",
|
Name: template?.Name || "",
|
||||||
Note: template?.Note || "",
|
Note: template?.Note || "",
|
||||||
@@ -17,7 +14,14 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
|
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
|
||||||
AutomaticReminders: template?.AutomaticReminders || false,
|
AutomaticReminders: template?.AutomaticReminders || false,
|
||||||
RemindOnceInEvery: template?.RemindOnceInEvery || 5,
|
RemindOnceInEvery: template?.RemindOnceInEvery || 5,
|
||||||
IsEnableOTP: template?.IsEnableOTP ? `${template?.IsEnableOTP}` : "false"
|
IsEnableOTP: template?.IsEnableOTP ? `${template?.IsEnableOTP}` : "false",
|
||||||
|
IsTourEnabled: template?.IsTourEnabled
|
||||||
|
? `${template?.IsTourEnabled}`
|
||||||
|
: "false",
|
||||||
|
NotifyOnSignatures:
|
||||||
|
template?.NotifyOnSignatures !== undefined
|
||||||
|
? template?.NotifyOnSignatures
|
||||||
|
: false
|
||||||
});
|
});
|
||||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -26,23 +30,20 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
const fetchSubscription = async () => {
|
const fetchSubscription = async () => {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const subscribe = await checkIsSubscribed();
|
const subscribe = await checkIsSubscribed(jwttoken);
|
||||||
setIsSubscribe(subscribe.isValid);
|
setIsSubscribe(subscribe.isValid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleStrInput = (e) => {
|
const handleStrInput = (e) => {
|
||||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
// const handleFolder = (data) => {
|
|
||||||
// console.log("handleFolder ", data)
|
|
||||||
// setFolder(data);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 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();
|
e.stopPropagation();
|
||||||
const isChecked = formData.SendinOrder === "true" ? true : false;
|
const isChecked = formData.SendinOrder === "true" ? true : false;
|
||||||
|
const isTourEnabled = formData?.IsTourEnabled === "false" ? false : true;
|
||||||
const AutoReminder = formData?.AutomaticReminders || false;
|
const AutoReminder = formData?.AutomaticReminders || false;
|
||||||
const IsEnableOTP = formData.IsEnableOTP === "true" ? true : false;
|
const IsEnableOTP = formData.IsEnableOTP === "true" ? true : false;
|
||||||
let reminderDate = {};
|
let reminderDate = {};
|
||||||
@@ -56,6 +57,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
...formData,
|
...formData,
|
||||||
SendinOrder: isChecked,
|
SendinOrder: isChecked,
|
||||||
IsEnableOTP: IsEnableOTP,
|
IsEnableOTP: IsEnableOTP,
|
||||||
|
IsTourEnabled: isTourEnabled,
|
||||||
...reminderDate
|
...reminderDate
|
||||||
};
|
};
|
||||||
onSuccess(data);
|
onSuccess(data);
|
||||||
@@ -66,6 +68,11 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
AutomaticReminders: !formData.AutomaticReminders
|
AutomaticReminders: !formData.AutomaticReminders
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleNotifySignChange` is trigger when user change radio of notify on signatures
|
||||||
|
const handleNotifySignChange = (value) => {
|
||||||
|
setFormData((obj) => ({ ...obj, NotifyOnSignatures: value }));
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="max-h-[300px] md:max-h-[400px] overflow-y-scroll p-[10px]">
|
<div className="max-h-[300px] md:max-h-[400px] overflow-y-scroll p-[10px]">
|
||||||
<div className="text-base-content">
|
<div className="text-base-content">
|
||||||
@@ -80,7 +87,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label htmlFor="name" className="text-[13px]">
|
<label htmlFor="name" className="text-[13px]">
|
||||||
{t("name")}
|
{t("Title")}
|
||||||
<span className="text-[13px] text-[red]"> *</span>
|
<span className="text-[13px] text-[red]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -122,6 +129,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label className="text-[13px]">{t("send-in-order")}</label>
|
<label className="text-[13px]">{t("send-in-order")}</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
|
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -145,6 +153,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
<div className="text-[12px]">{t("no")}</div>
|
<div className="text-[12px]">{t("no")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<span
|
<span
|
||||||
@@ -153,13 +162,12 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("auto-reminder")}
|
{t("auto-reminder")}
|
||||||
{" "}
|
|
||||||
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
</span>
|
</span>
|
||||||
<label
|
<label
|
||||||
className={`${
|
className={`${
|
||||||
isSubscribe
|
isSubscribe
|
||||||
? "cursor-pointer "
|
? "cursor-pointer"
|
||||||
: "pointer-events-none opacity-50"
|
: "pointer-events-none opacity-50"
|
||||||
} relative block items-center mb-0`}
|
} relative block items-center mb-0`}
|
||||||
>
|
>
|
||||||
@@ -224,10 +232,11 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
isSubscribe ? "" : "pointer-events-none opacity-50"
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
} flex items-center gap-2 ml-2 mb-1 `}
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -255,7 +264,116 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
<div className="text-center">{t("no")}</div>
|
<div className="text-center">{t("no")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
<span>
|
||||||
|
{t("enable-tour")}
|
||||||
|
<a data-tooltip-id="istourenabled-tooltip" className="ml-1">
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>{" "}
|
||||||
|
</span>
|
||||||
|
<Tooltip id="istourenabled-tooltip" className="z-50">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
|
<p className="font-bold">{t("enable-tour")}</p>
|
||||||
|
<p className="p-[5px]">
|
||||||
|
<ol className="list-disc">
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">{t("yes")}: </span>
|
||||||
|
<span>{t("istourenabled-help.p1")}</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">{t("no")}: </span>
|
||||||
|
<span>{t("istourenabled-help.p2")}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<p>{t("istourenabled-help.p3")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
name="IsTourEnabled"
|
||||||
|
checked={formData.IsTourEnabled === "true"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("yes")}</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="IsTourEnabled"
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
checked={formData.IsTourEnabled === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs mt-3">
|
||||||
|
<label
|
||||||
|
className={`${
|
||||||
|
isSubscribe || !isEnableSubscription ? "" : "text-gray-300"
|
||||||
|
} block`}
|
||||||
|
>
|
||||||
|
{t("notify-on-signatures")}
|
||||||
|
<a data-tooltip-id="nos-tooltip" className="ml-1">
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
<Tooltip id="nos-tooltip" className="z-[999]">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||||
|
<p className="font-bold">{t("notify-on-signatures")}</p>
|
||||||
|
<p>{t("notify-on-signatures-help.p1")}</p>
|
||||||
|
<p>{t("notify-on-signatures-help.note")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? ""
|
||||||
|
: "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(true)}
|
||||||
|
checked={formData.NotifyOnSignatures === true}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("yes")}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? ""
|
||||||
|
: "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(false)}
|
||||||
|
checked={formData.NotifyOnSignatures === false}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mt-[1rem] flex justify-start">
|
<div className="mt-[1rem] flex justify-start">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
{t("submit")}
|
{t("submit")}
|
||||||
|
|||||||
@@ -30,16 +30,15 @@ function EmailComponent({
|
|||||||
const pdfName = pdfDetails[0]?.Name;
|
const pdfName = pdfDetails[0]?.Name;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let sendMail;
|
let sendMail;
|
||||||
|
const docId = pdfDetails?.[0]?.objectId || "";
|
||||||
const docId = !pdfDetails?.[0]?.IsEnableOTP
|
const FileAdapterId = pdfDetails?.[0]?.FileAdapterId
|
||||||
? pdfDetails?.[0]?.objectId
|
? pdfDetails?.[0]?.FileAdapterId
|
||||||
: "";
|
: "";
|
||||||
let presignedUrl = pdfUrl;
|
let presignedUrl = pdfUrl;
|
||||||
try {
|
try {
|
||||||
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
|
|
||||||
const axiosRes = await axios.post(
|
const axiosRes = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
{ url: pdfUrl, docId: docId },
|
{ url: pdfUrl, docId: docId, fileAdapterId: FileAdapterId },
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "Application/json",
|
"content-type": "Application/json",
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ function EmbedTab(props) {
|
|||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
title: "Installation",
|
title: "Installation",
|
||||||
codeString: `
|
codeString: `npm install @opensign/react`
|
||||||
npm install @opensign/react`
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -28,19 +27,18 @@ npm install @opensign/react`
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Opensign from "@opensign/react";
|
import Opensign from "@opensign/react";
|
||||||
|
|
||||||
export function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<Opensign
|
<Opensign
|
||||||
onLoad={() => console.log("success")}
|
onLoad={() => console.log("success")}
|
||||||
onLoadError={(error) => console.log(error)}
|
onLoadError={(error) => console.log(error)}
|
||||||
templateId= {"${props.templateId}"}
|
templateId= "${props.templateId}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -49,36 +47,33 @@ export function App() {
|
|||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
title: "Installation",
|
title: "Installation",
|
||||||
codeString: `
|
codeString: `npm install @opensign/angular`
|
||||||
npm install @opensign/angular`
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "Usage",
|
title: "Usage",
|
||||||
codeString: `
|
codeString: `
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {OpensignComponent} from "@opensign/angular"
|
import { OpensignComponent } from "@opensign/angular"
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector:'app-root',
|
selector:'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [OpensignComponent],
|
imports: [OpensignComponent],
|
||||||
template: '<opensign templateId={"${props.templateId}"}
|
template:\`<opensign templateId="${props.templateId}"
|
||||||
(onLoad)="handleLoad()"
|
(onLoad)="handleLoad()"
|
||||||
(onLoadError)="handleError($event)"
|
(onLoadError)="handleError($event)"
|
||||||
></opensign>',
|
></opensign>\`,
|
||||||
})
|
})
|
||||||
export class AppComponent{
|
export class AppComponent {
|
||||||
handleLoad() {
|
handleLoad() {
|
||||||
console.log("success");
|
console.log("success");
|
||||||
}
|
}
|
||||||
handleError(error: string) {
|
handleError(error: string) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -98,6 +93,9 @@ export class AppComponent{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 border-t-[1px]">
|
<div className="mt-4 border-t-[1px]">
|
||||||
|
<h3 className="text-base-content font-bold text-lg pt-[15px] pb-[5px]">
|
||||||
|
{t("embed-template")}
|
||||||
|
</h3>
|
||||||
<div className="flex justify-center items-center mt-2">
|
<div className="flex justify-center items-center mt-2">
|
||||||
<div role="tablist" className="op-tabs op-tabs-bordered">
|
<div role="tablist" className="op-tabs op-tabs-bordered">
|
||||||
{tabName.map((tabData, ind) => (
|
{tabName.map((tabData, ind) => (
|
||||||
@@ -107,7 +105,7 @@ export class AppComponent{
|
|||||||
role="tab"
|
role="tab"
|
||||||
className={`${
|
className={`${
|
||||||
activeTab === ind ? "op-tab-active" : ""
|
activeTab === ind ? "op-tab-active" : ""
|
||||||
} op-tab flex items-center`}
|
} op-tab flex items-center pb-10 md:pb-0`}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className={`${tabData.icon}`}
|
className={`${tabData.icon}`}
|
||||||
@@ -129,9 +127,11 @@ export class AppComponent{
|
|||||||
<p className="font-medium text-[18px]">
|
<p className="font-medium text-[18px]">
|
||||||
{t(`${data.title}`)}
|
{t(`${data.title}`)}
|
||||||
</p>
|
</p>
|
||||||
|
{ind === 0 && (
|
||||||
<p className="text-[13px] mt-2">
|
<p className="text-[13px] mt-2">
|
||||||
{t("public-template-mssg-1")}
|
{t("public-template-mssg-1")}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
<div className="relative p-1">
|
<div className="relative p-1">
|
||||||
<div
|
<div
|
||||||
onClick={() => handleCopy(data.codeString, ind)}
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
@@ -210,11 +210,11 @@ export class AppComponent{
|
|||||||
<p className="font-medium text-[18px]">
|
<p className="font-medium text-[18px]">
|
||||||
{t(`${data.title}`)}
|
{t(`${data.title}`)}
|
||||||
</p>
|
</p>
|
||||||
|
{ind === 0 && (
|
||||||
<p className="text-[13px] mt-2">
|
<p className="text-[13px] mt-2">
|
||||||
{t("angular-npm-mssg-1")}
|
{t("angular-npm-mssg-1")}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
<div className="relative p-1">
|
<div className="relative p-1">
|
||||||
<div
|
<div
|
||||||
onClick={() => handleCopy(data.codeString, ind)}
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import PrevNext from "./PrevNext";
|
import PrevNext from "./PrevNext";
|
||||||
import {
|
import {
|
||||||
|
deletePdfPage,
|
||||||
handleDownloadCertificate,
|
handleDownloadCertificate,
|
||||||
handleDownloadPdf,
|
handleDownloadPdf,
|
||||||
|
handleRemoveWidgets,
|
||||||
handleToPrint
|
handleToPrint
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
import "../../styles/signature.css";
|
import "../../styles/signature.css";
|
||||||
@@ -40,7 +42,14 @@ function Header({
|
|||||||
handleRotationFun,
|
handleRotationFun,
|
||||||
isDisableRotate,
|
isDisableRotate,
|
||||||
templateId,
|
templateId,
|
||||||
setIsDownloadModal
|
setIsDownloadModal,
|
||||||
|
disabledBackBtn,
|
||||||
|
setPdfArrayBuffer,
|
||||||
|
setPdfBase64Url,
|
||||||
|
pdfArrayBuffer,
|
||||||
|
setIsUploadPdf,
|
||||||
|
setSignerPos,
|
||||||
|
userId
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const filterPrefill =
|
const filterPrefill =
|
||||||
@@ -48,12 +57,26 @@ function Header({
|
|||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const [isDownloading, setIsDownloading] = useState("");
|
const [isDownloading, setIsDownloading] = useState("");
|
||||||
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
||||||
|
const [isDeletePage, setIsDeletePage] = useState(false);
|
||||||
|
const enabledBackBtn = disabledBackBtn === true ? false : true;
|
||||||
|
|
||||||
//function for show decline alert
|
//function for show decline alert
|
||||||
const handleDeclinePdfAlert = async () => {
|
const handleDeclinePdfAlert = async () => {
|
||||||
const currentDecline = { currnt: "Sure", isDeclined: true };
|
const currentDecline = { currnt: "Sure", isDeclined: true };
|
||||||
setIsDecline(currentDecline);
|
setIsDecline(currentDecline);
|
||||||
};
|
};
|
||||||
|
const handleDetelePage = async () => {
|
||||||
|
setIsUploadPdf(true);
|
||||||
|
const pdfupdatedData = await deletePdfPage(pdfArrayBuffer, pageNumber);
|
||||||
|
if (pdfupdatedData?.totalPages === 1) {
|
||||||
|
alert(t("delete-alert"));
|
||||||
|
} else {
|
||||||
|
setPdfBase64Url(pdfupdatedData.base64);
|
||||||
|
setPdfArrayBuffer(pdfupdatedData.arrayBuffer);
|
||||||
|
setIsDeletePage(false);
|
||||||
|
handleRemoveWidgets(setSignerPos, signerPos, pageNumber, userId);
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="flex py-[5px]">
|
<div className="flex py-[5px]">
|
||||||
{isMobile && isShowHeader ? (
|
{isMobile && isShowHeader ? (
|
||||||
@@ -253,6 +276,17 @@ function Header({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => setIsDeletePage(true)}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<i className="fa-light fa-trash text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("delete-page")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -332,6 +366,7 @@ function Header({
|
|||||||
<i className="fa-light fa-gear fa-lg"></i>
|
<i className="fa-light fa-gear fa-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
{enabledBackBtn && (
|
||||||
<button
|
<button
|
||||||
onClick={() => window.history.go(-2)}
|
onClick={() => window.history.go(-2)}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -339,6 +374,7 @@ function Header({
|
|||||||
>
|
>
|
||||||
{t("back")}
|
{t("back")}
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
disabled={isMailSend && true}
|
disabled={isMailSend && true}
|
||||||
data-tut="headerArea"
|
data-tut="headerArea"
|
||||||
@@ -418,11 +454,7 @@ function Header({
|
|||||||
{templateId && (
|
{templateId && (
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleDownloadPdf(
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
pdfDetails,
|
|
||||||
pdfUrl,
|
|
||||||
setIsDownloading
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
|
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
|
||||||
@@ -553,6 +585,32 @@ function Header({
|
|||||||
<p>{t("generate-certificate-alert")}</p>
|
<p>{t("generate-certificate-alert")}</p>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isDeletePage}
|
||||||
|
title={t("validation-alert")}
|
||||||
|
handleClose={() => setIsDeletePage(false)}
|
||||||
|
>
|
||||||
|
<div className="h-[100%] p-[20px]">
|
||||||
|
<p>{t("delete-alert-2")}</p>
|
||||||
|
<p className="pt-3 font-medium">{t("delete-note")}</p>
|
||||||
|
{/* <p>{t("deletepage-alert")}</p> */}
|
||||||
|
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||||
|
<button
|
||||||
|
onClick={() => handleDetelePage()}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("yes")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsDeletePage(false)}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-ghost"
|
||||||
|
>
|
||||||
|
{t("no")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,38 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { deletePdfPage, handleRemoveWidgets } from "../../constant/Utils";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
|
||||||
function PdfZoom(props) {
|
function PdfZoom(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [isDeletePage, setIsDeletePage] = useState(false);
|
||||||
|
const handleDetelePage = async () => {
|
||||||
|
props.setIsUploadPdf(true);
|
||||||
|
try {
|
||||||
|
const pdfupdatedData = await deletePdfPage(
|
||||||
|
props.pdfArrayBuffer,
|
||||||
|
props.pageNumber
|
||||||
|
);
|
||||||
|
if (pdfupdatedData?.totalPages === 1) {
|
||||||
|
alert(t("delete-alert"));
|
||||||
|
} else {
|
||||||
|
props.setPdfBase64Url(pdfupdatedData.base64);
|
||||||
|
props.setPdfArrayBuffer(pdfupdatedData.arrayBuffer);
|
||||||
|
setIsDeletePage(false);
|
||||||
|
handleRemoveWidgets(
|
||||||
|
props.setSignerPos,
|
||||||
|
props.signerPos,
|
||||||
|
props.pageNumber,
|
||||||
|
props.userId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error in delete pdf page", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<span className="hidden md:flex flex-col gap-1 text-center md:w-[5%] mt-[43px] 2xl:mt-[63px]">
|
<span className="hidden md:flex flex-col gap-1 text-center md:w-[5%] mt-[43px] 2xl:mt-[63px]">
|
||||||
<span
|
<span
|
||||||
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
||||||
@@ -13,6 +41,16 @@ function PdfZoom(props) {
|
|||||||
>
|
>
|
||||||
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px]"></i>
|
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px]"></i>
|
||||||
</span>
|
</span>
|
||||||
|
{!props.isDisableDelete && (
|
||||||
|
<span
|
||||||
|
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
||||||
|
onClick={() => setIsDeletePage(true)}
|
||||||
|
title={t("delete-page")}
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-trash text-gray-500 2xl:text-[30px]"></i>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
{!props?.isDisableRotate && (
|
{!props?.isDisableRotate && (
|
||||||
<>
|
<>
|
||||||
<span
|
<span
|
||||||
@@ -42,6 +80,36 @@ function PdfZoom(props) {
|
|||||||
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px]"></i>
|
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px]"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isDeletePage}
|
||||||
|
title={t("validation-alert")}
|
||||||
|
handleClose={() => setIsDeletePage(false)}
|
||||||
|
>
|
||||||
|
<div className="h-[100%] p-[20px]">
|
||||||
|
<p>Are you sure want to delete this page ?</p>
|
||||||
|
<p className="pt-3 font-medium">
|
||||||
|
Note - once delete this page you can not undo
|
||||||
|
</p>
|
||||||
|
{/* <p>{t("deletepage-alert")}</p> */}
|
||||||
|
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||||
|
<button
|
||||||
|
onClick={() => handleDetelePage()}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("yes")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsDeletePage(false)}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-ghost"
|
||||||
|
>
|
||||||
|
{t("no")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -331,10 +331,9 @@ function Placeholder(props) {
|
|||||||
//condition for only placeholder and template flow
|
//condition for only placeholder and template flow
|
||||||
if (props.data && props?.pos?.type !== textWidget) {
|
if (props.data && props?.pos?.type !== textWidget) {
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
const checkIndex = props.xyPostion
|
||||||
(data) => data.Id === props.data.Id
|
.filter((data) => data.Role !== "prefill")
|
||||||
);
|
.findIndex((data) => data.Id === props.data.Id);
|
||||||
|
|
||||||
props.setIsSelectId(checkIndex || 0);
|
props.setIsSelectId(checkIndex || 0);
|
||||||
}
|
}
|
||||||
//condition to handle in placeholder and template flow for text widget signerId for text widgets i have to set uniqueId in tempSignerId because
|
//condition to handle in placeholder and template flow for text widget signerId for text widgets i have to set uniqueId in tempSignerId because
|
||||||
@@ -342,10 +341,6 @@ function Placeholder(props) {
|
|||||||
else if (props.data && props.pos.type === textWidget) {
|
else if (props.data && props.pos.type === textWidget) {
|
||||||
props.setTempSignerId(props.uniqueId);
|
props.setTempSignerId(props.uniqueId);
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
|
||||||
(data) => data.Id === props.data.Id
|
|
||||||
);
|
|
||||||
props.setIsSelectId(checkIndex || 0);
|
|
||||||
}
|
}
|
||||||
props.setSignKey(props.pos.key);
|
props.setSignKey(props.pos.key);
|
||||||
props.setWidgetType(props.pos.type);
|
props.setWidgetType(props.pos.type);
|
||||||
@@ -361,18 +356,13 @@ function Placeholder(props) {
|
|||||||
|
|
||||||
if (props.data && props?.pos?.type !== textWidget) {
|
if (props.data && props?.pos?.type !== textWidget) {
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
const checkIndex = props.xyPostion
|
||||||
(data) => data.Id === props.data.Id
|
.filter((data) => data.Role !== "prefill")
|
||||||
);
|
.findIndex((data) => data.Id === props.data.Id);
|
||||||
|
|
||||||
props.setIsSelectId(checkIndex || 0);
|
props.setIsSelectId(checkIndex || 0);
|
||||||
} else if (props.data && props.pos.type === textWidget) {
|
} else if (props.data && props.pos.type === textWidget) {
|
||||||
props.setTempSignerId(props.uniqueId);
|
props.setTempSignerId(props.uniqueId);
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
|
||||||
(data) => data.Id === props.data.Id
|
|
||||||
);
|
|
||||||
props.setIsSelectId(checkIndex || 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//checking widget's type and open widget copy modal for required widgets
|
//checking widget's type and open widget copy modal for required widgets
|
||||||
@@ -422,7 +412,7 @@ function Placeholder(props) {
|
|||||||
data?.format,
|
data?.format,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
props.fontSize || props.pos?.options?.fontSize || "12",
|
props.fontSize || props.pos?.options?.fontSize || 12,
|
||||||
props.fontColor || props.pos?.options?.fontColor || "black"
|
props.fontColor || props.pos?.options?.fontColor || "black"
|
||||||
);
|
);
|
||||||
setSelectDate({ date: date, format: data?.format });
|
setSelectDate({ date: date, format: data?.format });
|
||||||
@@ -455,17 +445,13 @@ function Placeholder(props) {
|
|||||||
handleOnClickSettingIcon();
|
handleOnClickSettingIcon();
|
||||||
}}
|
}}
|
||||||
className="fa-light fa-gear icon"
|
className="fa-light fa-gear icon"
|
||||||
style={{
|
style={{ color: "#188ae2", right: "29px", top: "-19px" }}
|
||||||
color: "#188ae2",
|
|
||||||
right: "29px",
|
|
||||||
top: "-19px"
|
|
||||||
}}
|
|
||||||
></i>
|
></i>
|
||||||
) : (
|
) : (
|
||||||
/* condition to add setting icon for placeholder & template flow for all widgets except signature and date */
|
/* condition to add setting icon for placeholder & template flow for all widgets except signature and date */
|
||||||
((!props?.pos?.type && props.pos.isStamp) ||
|
((!props?.pos?.type && props.pos.isStamp) ||
|
||||||
(props?.pos?.type &&
|
(props?.pos?.type &&
|
||||||
!["date", "signature"].includes(props.pos.type) &&
|
!["date"].includes(props.pos.type) &&
|
||||||
!props.isSignYourself)) && (
|
!props.isSignYourself)) && (
|
||||||
<i
|
<i
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@@ -479,7 +465,7 @@ function Placeholder(props) {
|
|||||||
className="fa-light fa-gear icon"
|
className="fa-light fa-gear icon"
|
||||||
style={{
|
style={{
|
||||||
color: "#188ae2",
|
color: "#188ae2",
|
||||||
right: props?.pos?.type === textWidget ? "32px" : "47px",
|
right: props?.pos?.type === textWidget ? "32px" : "51px",
|
||||||
top: "-19px"
|
top: "-19px"
|
||||||
}}
|
}}
|
||||||
></i>
|
></i>
|
||||||
@@ -651,6 +637,21 @@ function Placeholder(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
//function to calculate font size
|
||||||
|
const calculateFont = (size, isMinHeight) => {
|
||||||
|
const containerScale = getContainerScale(
|
||||||
|
props.pdfOriginalWH,
|
||||||
|
props.pageNumber,
|
||||||
|
props.containerWH
|
||||||
|
);
|
||||||
|
const fontSize = (size || 12) * containerScale * props.scale;
|
||||||
|
//isMinHeight to set text box minimum height
|
||||||
|
if (isMinHeight) {
|
||||||
|
return fontSize * 1.2 + "px";
|
||||||
|
} else {
|
||||||
|
return fontSize + "px";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getCursor = () => {
|
const getCursor = () => {
|
||||||
if (props.data && props.isNeedSign) {
|
if (props.data && props.isNeedSign) {
|
||||||
@@ -725,7 +726,9 @@ function Placeholder(props) {
|
|||||||
: props?.pos?.zIndex
|
: props?.pos?.zIndex
|
||||||
? props.pos.zIndex
|
? props.pos.zIndex
|
||||||
: "5",
|
: "5",
|
||||||
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
|
background: props.data
|
||||||
|
? props.data?.blockColor + "b0"
|
||||||
|
: "rgba(203, 233, 237, 0.69)"
|
||||||
}}
|
}}
|
||||||
onDrag={() => {
|
onDrag={() => {
|
||||||
setDraggingEnabled(true);
|
setDraggingEnabled(true);
|
||||||
@@ -743,12 +746,16 @@ function Placeholder(props) {
|
|||||||
? "auto"
|
? "auto"
|
||||||
: props.posHeight(props.pos, props.isSignYourself)
|
: props.posHeight(props.pos, props.isSignYourself)
|
||||||
}}
|
}}
|
||||||
|
minHeight={calculateFont(props.pos.options?.fontSize, true)}
|
||||||
|
maxHeight="auto"
|
||||||
onResizeStart={() => {
|
onResizeStart={() => {
|
||||||
setDraggingEnabled(true);
|
setDraggingEnabled(true);
|
||||||
props.setIsResize && props.setIsResize(true);
|
props.setIsResize && props.setIsResize(true);
|
||||||
}}
|
}}
|
||||||
onResizeStop={(e, direction, ref) => {
|
onResizeStop={(e, direction, ref) => {
|
||||||
|
setTimeout(() => {
|
||||||
props.setIsResize && props.setIsResize(false);
|
props.setIsResize && props.setIsResize(false);
|
||||||
|
}, 50);
|
||||||
props.handleSignYourselfImageResize &&
|
props.handleSignYourselfImageResize &&
|
||||||
props.handleSignYourselfImageResize(
|
props.handleSignYourselfImageResize(
|
||||||
ref,
|
ref,
|
||||||
@@ -783,18 +790,28 @@ function Placeholder(props) {
|
|||||||
h: ref.offsetHeight / (props.scale * containerScale)
|
h: ref.offsetHeight / (props.scale * containerScale)
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onClick={() => handleOnClickPlaceholder()}
|
onClick={() => !props.isResize && handleOnClickPlaceholder()}
|
||||||
>
|
>
|
||||||
{props.isShowBorder &&
|
{props.isShowBorder &&
|
||||||
props.pos.type !== radioButtonWidget &&
|
props.pos.type !== radioButtonWidget &&
|
||||||
props.pos.type !== "checkbox" &&
|
props.pos.type !== "checkbox" &&
|
||||||
props.pos.key === props.selectWidgetId ? (
|
props.pos.key === props.selectWidgetId ? (
|
||||||
<BorderResize right={-12} top={-11} />
|
<BorderResize
|
||||||
|
right={-12}
|
||||||
|
top={-11}
|
||||||
|
pos={props.pos}
|
||||||
|
posHeight={props.posHeight}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
/>
|
||||||
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
||||||
props.data?.signerObjId === props.signerObjId &&
|
props.data?.signerObjId === props.signerObjId &&
|
||||||
props.pos.type !== radioButtonWidget &&
|
props.pos.type !== radioButtonWidget &&
|
||||||
props.pos.type !== "checkbox" ? (
|
props.pos.type !== "checkbox" ? (
|
||||||
<BorderResize />
|
<BorderResize
|
||||||
|
posHeight={props.posHeight}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
pos={props.pos}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)
|
)
|
||||||
@@ -817,7 +834,7 @@ function Placeholder(props) {
|
|||||||
)}
|
)}
|
||||||
{isTabAndMobile ? (
|
{isTabAndMobile ? (
|
||||||
<div
|
<div
|
||||||
className="flex items-stretch"
|
className="flex items-stretch justify-center"
|
||||||
style={{
|
style={{
|
||||||
left: xPos(props.pos, props.isSignYourself),
|
left: xPos(props.pos, props.isSignYourself),
|
||||||
top: yPos(props.pos, props.isSignYourself),
|
top: yPos(props.pos, props.isSignYourself),
|
||||||
@@ -860,6 +877,7 @@ function Placeholder(props) {
|
|||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
handleSaveDate={handleSaveDate}
|
handleSaveDate={handleSaveDate}
|
||||||
xPos={props.xPos}
|
xPos={props.xPos}
|
||||||
|
calculateFont={calculateFont}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -887,6 +905,7 @@ function Placeholder(props) {
|
|||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
handleSaveDate={handleSaveDate}
|
handleSaveDate={handleSaveDate}
|
||||||
xPos={props.xPos}
|
xPos={props.xPos}
|
||||||
|
calculateFont={calculateFont}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -925,8 +944,8 @@ function Placeholder(props) {
|
|||||||
<span>{t("font-size")} :</span>
|
<span>{t("font-size")} :</span>
|
||||||
<select
|
<select
|
||||||
className="ml-[3px] md:ml:[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
className="ml-[3px] md:ml:[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
value={props.fontSize || clickonWidget.options?.fontSize || "12"}
|
value={props.fontSize || clickonWidget.options?.fontSize || 12}
|
||||||
onChange={(e) => props.setFontSize(e.target.value)}
|
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
|
||||||
>
|
>
|
||||||
{fontsizeArr.map((size, ind) => {
|
{fontsizeArr.map((size, ind) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function PlaceholderType(props) {
|
|||||||
const [textValue, setTextValue] = useState();
|
const [textValue, setTextValue] = useState();
|
||||||
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
|
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
|
||||||
const years = range(1990, getYear(new Date()) + 16, 1);
|
const years = range(1990, getYear(new Date()) + 16, 1);
|
||||||
const fontSize = (props.pos.options?.fontSize || "12") + "px";
|
const fontSize = props.calculateFont(props.pos.options?.fontSize);
|
||||||
const fontColor = props.pos.options?.fontColor || "black";
|
const fontColor = props.pos.options?.fontColor || "black";
|
||||||
const months = [
|
const months = [
|
||||||
"January",
|
"January",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function RenderAllPdfPage({
|
|||||||
signerPos,
|
signerPos,
|
||||||
signerObjectId,
|
signerObjectId,
|
||||||
containerWH,
|
containerWH,
|
||||||
pdfRotateBase64
|
pdfBase64Url
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [signPageNumber, setSignPageNumber] = useState([]);
|
const [signPageNumber, setSignPageNumber] = useState([]);
|
||||||
@@ -67,7 +67,7 @@ function RenderAllPdfPage({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
|
const pdfDataBase64 = `data:application/pdf;base64,${pdfBase64Url}`;
|
||||||
return (
|
return (
|
||||||
<div ref={pageContainer} className="hidden w-[20%] bg-base-100 md:block">
|
<div ref={pageContainer} className="hidden w-[20%] bg-base-100 md:block">
|
||||||
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
||||||
@@ -80,7 +80,7 @@ function RenderAllPdfPage({
|
|||||||
<Document
|
<Document
|
||||||
loading={t("loading-doc")}
|
loading={t("loading-doc")}
|
||||||
onLoadSuccess={onDocumentLoad}
|
onLoadSuccess={onDocumentLoad}
|
||||||
file={(pdfRotateBase64 && pdfDataBase64) || signPdfUrl}
|
file={(pdfBase64Url && pdfDataBase64) || signPdfUrl}
|
||||||
>
|
>
|
||||||
{Array.from(new Array(allPages), (el, index) => (
|
{Array.from(new Array(allPages), (el, index) => (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -61,11 +61,12 @@ function RenderPdf({
|
|||||||
setIsSelectId,
|
setIsSelectId,
|
||||||
ispublicTemplate,
|
ispublicTemplate,
|
||||||
handleUserDetails,
|
handleUserDetails,
|
||||||
pdfRotateBase64,
|
pdfBase64Url,
|
||||||
fontSize,
|
fontSize,
|
||||||
setFontSize,
|
setFontSize,
|
||||||
fontColor,
|
fontColor,
|
||||||
setFontColor
|
setFontColor,
|
||||||
|
isResize
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
@@ -104,6 +105,7 @@ function RenderPdf({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const posHeight = (pos, signYourself) => {
|
const posHeight = (pos, signYourself) => {
|
||||||
const containerScale = getContainerScale(
|
const containerScale = getContainerScale(
|
||||||
pdfOriginalWH,
|
pdfOriginalWH,
|
||||||
@@ -207,6 +209,7 @@ function RenderPdf({
|
|||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
ispublicTemplate={ispublicTemplate}
|
ispublicTemplate={ispublicTemplate}
|
||||||
handleUserDetails={handleUserDetails}
|
handleUserDetails={handleUserDetails}
|
||||||
|
isResize={isResize}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
@@ -253,8 +256,7 @@ function RenderPdf({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
|
const pdfDataBase64 = `data:application/pdf;base64,${pdfBase64Url}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{successEmail && (
|
{successEmail && (
|
||||||
@@ -357,6 +359,8 @@ function RenderPdf({
|
|||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
unSignedWidgetId={unSignedWidgetId}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
@@ -372,10 +376,11 @@ function RenderPdf({
|
|||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
{data.pageNumber === pageNumber &&
|
{data.pageNumber === pageNumber &&
|
||||||
data.pos.map((pos) => {
|
data.pos.map((pos, id) => {
|
||||||
return (
|
return (
|
||||||
pos && (
|
pos && (
|
||||||
<Placeholder
|
<Placeholder
|
||||||
|
key={id}
|
||||||
pos={pos}
|
pos={pos}
|
||||||
setIsPageCopy={setIsPageCopy}
|
setIsPageCopy={setIsPageCopy}
|
||||||
setSignKey={setSignKey}
|
setSignKey={setSignKey}
|
||||||
@@ -417,6 +422,8 @@ function RenderPdf({
|
|||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
setIsResize={setIsResize}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -436,7 +443,7 @@ function RenderPdf({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
file={
|
file={
|
||||||
(pdfRotateBase64 && pdfDataBase64) ||
|
(pdfBase64Url && pdfDataBase64) ||
|
||||||
pdfDetails[0]?.SignedUrl ||
|
pdfDetails[0]?.SignedUrl ||
|
||||||
pdfDetails[0].URL
|
pdfDetails[0].URL
|
||||||
}
|
}
|
||||||
@@ -548,6 +555,8 @@ function RenderPdf({
|
|||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
unSignedWidgetId={unSignedWidgetId}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
@@ -611,6 +620,8 @@ function RenderPdf({
|
|||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
setIsResize={setIsResize}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
@@ -629,9 +640,8 @@ function RenderPdf({
|
|||||||
setSelectWidgetId("");
|
setSelectWidgetId("");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
// ref={pdfRef}
|
|
||||||
file={
|
file={
|
||||||
(pdfRotateBase64 && pdfDataBase64) ||
|
(pdfBase64Url && pdfDataBase64) ||
|
||||||
pdfDetails[0]?.SignedUrl ||
|
pdfDetails[0]?.SignedUrl ||
|
||||||
pdfDetails[0].URL
|
pdfDetails[0].URL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,16 @@ function SelectLanguage(props) {
|
|||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const languages = [
|
const languages = [
|
||||||
{ value: "en", text: "English" },
|
{ value: "en", text: "English" },
|
||||||
|
{ value: "es", text: "Española" },
|
||||||
{ value: "fr", text: "Français" }
|
{ value: "fr", text: "Français" }
|
||||||
];
|
];
|
||||||
const [lang, setLang] = useState(i18next.language || "en");
|
const defaultLanguage = i18next.language || "en";
|
||||||
|
const [lang, setLang] = useState(defaultLanguage);
|
||||||
// This function put query that helps to change the language
|
// This function put query that helps to change the language
|
||||||
const handleChangeLang = (e) => {
|
const handleChangeLang = (e) => {
|
||||||
setLang(e.target.value);
|
setLang(e.target.value);
|
||||||
i18n.changeLanguage(e.target.value);
|
i18n.changeLanguage(e.target.value);
|
||||||
props?.updateExtUser &&
|
props?.updateExtUser && props.updateExtUser({ language: e.target.value });
|
||||||
props.updateExtUser({
|
|
||||||
language: e.target.value
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -31,9 +30,7 @@ function SelectLanguage(props) {
|
|||||||
!props.isProfile ? " md:w-[15%] w-[50%]" : "w-[180px]"
|
!props.isProfile ? " md:w-[15%] w-[50%]" : "w-[180px]"
|
||||||
} op-select op-select-bordered bg-white op-select-sm `}
|
} op-select op-select-bordered bg-white op-select-sm `}
|
||||||
>
|
>
|
||||||
<option disabled selected>
|
<option disabled>select</option>
|
||||||
select
|
|
||||||
</option>
|
|
||||||
{languages.map((item) => {
|
{languages.map((item) => {
|
||||||
return (
|
return (
|
||||||
<option key={item.value} value={item.value}>
|
<option key={item.value} value={item.value}>
|
||||||
|
|||||||
@@ -1,39 +1,20 @@
|
|||||||
import React, { useRef, useState, useEffect } from "react";
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
function SignPad({
|
|
||||||
isSignPad,
|
function SignPad(props) {
|
||||||
isStamp,
|
|
||||||
setIsImageSelect,
|
|
||||||
onSaveSign,
|
|
||||||
setIsSignPad,
|
|
||||||
setImage,
|
|
||||||
isImageSelect,
|
|
||||||
imageRef,
|
|
||||||
onImageChange,
|
|
||||||
onSaveImage,
|
|
||||||
image,
|
|
||||||
defaultSign,
|
|
||||||
setSignature,
|
|
||||||
myInitial,
|
|
||||||
isInitial,
|
|
||||||
setIsInitial,
|
|
||||||
setIsStamp,
|
|
||||||
widgetType,
|
|
||||||
currWidgetsDetails,
|
|
||||||
setCurrWidgetsDetails
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
const allColor = ["blue", "red", "black"];
|
const allColor = ["blue", "red", "black"];
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
const [isDefaultSign, setIsDefaultSign] = useState(false);
|
const [isDefaultSign, setIsDefaultSign] = useState(false);
|
||||||
const [isTab, setIsTab] = useState("draw");
|
const [isTab, setIsTab] = useState("");
|
||||||
const [isSignImg, setIsSignImg] = useState("");
|
const [isSignImg, setIsSignImg] = useState("");
|
||||||
const [signValue, setSignValue] = useState("");
|
const [signValue, setSignValue] = useState("");
|
||||||
const [textWidth, setTextWidth] = useState(0);
|
const [textWidth, setTextWidth] = useState(0);
|
||||||
const [textHeight, setTextHeight] = useState(0);
|
const [textHeight, setTextHeight] = useState(0);
|
||||||
const [signatureType, setSignatureType] = useState("draw");
|
const [signatureType, setSignatureType] = useState("");
|
||||||
|
const [isSignTypes, setIsSignTypes] = useState(true);
|
||||||
const fontOptions = [
|
const fontOptions = [
|
||||||
{ value: "Fasthand" },
|
{ value: "Fasthand" },
|
||||||
{ value: "Dancing Script" },
|
{ value: "Dancing Script" },
|
||||||
@@ -53,24 +34,58 @@ function SignPad({
|
|||||||
const jsonSender = JSON.parse(senderUser);
|
const jsonSender = JSON.parse(senderUser);
|
||||||
const currentUserName = jsonSender && jsonSender?.name;
|
const currentUserName = jsonSender && jsonSender?.name;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleTab();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.signatureTypes]);
|
||||||
|
|
||||||
|
function handleTab() {
|
||||||
|
const signtypes = props?.signatureTypes || [];
|
||||||
|
const index = signtypes?.findIndex((x) => x.enabled === true);
|
||||||
|
if (index !== -1) {
|
||||||
|
setIsSignTypes(true);
|
||||||
|
const tab = props?.signatureTypes[index].name;
|
||||||
|
if (tab === "draw") {
|
||||||
|
setIsTab("draw");
|
||||||
|
setSignatureType("draw");
|
||||||
|
} else if (tab === "upload") {
|
||||||
|
props?.setIsImageSelect(true);
|
||||||
|
setIsTab("uploadImage");
|
||||||
|
} else if (tab === "typed") {
|
||||||
|
setIsTab("type");
|
||||||
|
} else if (tab === "default") {
|
||||||
|
setIsTab("mysignature");
|
||||||
|
} else {
|
||||||
|
setIsTab(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsSignTypes(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isTabEnabled(tabName) {
|
||||||
|
const isEnabled = props?.signatureTypes.find(
|
||||||
|
(x) => x.name === tabName
|
||||||
|
)?.enabled;
|
||||||
|
return isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
//function for clear signature image
|
//function for clear signature image
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setCurrWidgetsDetails({});
|
props?.setCurrWidgetsDetails({});
|
||||||
if (isTab === "draw") {
|
if (isTab === "draw") {
|
||||||
if (canvasRef.current) {
|
if (canvasRef.current) {
|
||||||
canvasRef.current.clear();
|
canvasRef.current.clear();
|
||||||
} else if (isStamp) {
|
} else if (props?.isStamp) {
|
||||||
setImage("");
|
props?.setImage("");
|
||||||
}
|
}
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
} else if (isTab === "uploadImage") {
|
} else if (isTab === "uploadImage") {
|
||||||
setImage("");
|
props?.setImage("");
|
||||||
}
|
}
|
||||||
// setIsInitial(false);
|
|
||||||
};
|
};
|
||||||
//function for set signature url
|
//function for set signature url
|
||||||
const handleSignatureChange = (data) => {
|
const handleSignatureChange = (data) => {
|
||||||
setSignature(data);
|
props?.setSignature(data);
|
||||||
setIsSignImg(data);
|
setIsSignImg(data);
|
||||||
};
|
};
|
||||||
//save button component
|
//save button component
|
||||||
@@ -88,58 +103,57 @@ function SignPad({
|
|||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrWidgetsDetails({});
|
props?.setCurrWidgetsDetails({});
|
||||||
if (!image) {
|
if (!props?.image) {
|
||||||
if (isTab === "mysignature") {
|
if (isTab === "mysignature") {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
if (isInitial) {
|
if (props?.isInitial) {
|
||||||
onSaveSign(signatureType, "initials");
|
props?.onSaveSign(signatureType, "initials");
|
||||||
} else {
|
} else {
|
||||||
onSaveSign(null, "default");
|
props?.onSaveSign(null, "default");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isTab === "type") {
|
if (isTab === "type") {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveSign(
|
props?.onSaveSign(
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
!isInitial && textWidth > 150 ? 150 : textWidth,
|
!props?.isInitial && textWidth > 150 ? 150 : textWidth,
|
||||||
!isInitial && textHeight > 35 ? 35 : textHeight
|
!props?.isInitial && textHeight > 35 ? 35 : textHeight
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
canvasRef.current.clear();
|
canvasRef.current.clear();
|
||||||
onSaveSign(signatureType);
|
props?.onSaveSign(signatureType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPenColor("blue");
|
setPenColor("blue");
|
||||||
} else {
|
} else {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveImage(signatureType);
|
props?.onSaveImage(signatureType);
|
||||||
}
|
}
|
||||||
setIsSignPad(false);
|
props?.setIsSignPad(false);
|
||||||
setIsInitial(false);
|
props?.setIsInitial(false);
|
||||||
setIsImageSelect(false);
|
props?.setIsImageSelect(false);
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setImage();
|
props?.setImage();
|
||||||
setIsTab("draw");
|
handleTab();
|
||||||
setSignValue("");
|
setSignValue("");
|
||||||
setIsStamp(false);
|
props?.setIsStamp(false);
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className={`${
|
className={`${
|
||||||
isSignImg || image || isDefaultSign || textWidth
|
isSignImg || props?.image || isDefaultSign || textWidth
|
||||||
? ""
|
? ""
|
||||||
: "pointer-events-none"
|
: "pointer-events-none"
|
||||||
} op-btn op-btn-primary shadow-lg`}
|
} op-btn op-btn-primary shadow-lg`}
|
||||||
disabled={
|
disabled={
|
||||||
(isTab === "draw" && isSignImg) ||
|
(isTab === "draw" && isSignImg) ||
|
||||||
(isTab === "image" && image) ||
|
(isTab === "image" && props?.image) ||
|
||||||
(isTab === "mysignature" && isDefaultSign) ||
|
(isTab === "mysignature" && isDefaultSign) ||
|
||||||
(isTab === "type" && signValue)
|
(isTab === "type" && signValue)
|
||||||
? false
|
? false
|
||||||
: image
|
: props?.image
|
||||||
? false
|
? false
|
||||||
: true
|
: true
|
||||||
}
|
}
|
||||||
@@ -151,12 +165,12 @@ function SignPad({
|
|||||||
};
|
};
|
||||||
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
|
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currWidgetsDetails && canvasRef.current) {
|
if (props?.currWidgetsDetails && canvasRef.current) {
|
||||||
const isWidgetType = currWidgetsDetails?.type;
|
const isWidgetType = props?.currWidgetsDetails?.type;
|
||||||
const signatureType = currWidgetsDetails?.signatureType;
|
const signatureType = props?.currWidgetsDetails?.signatureType;
|
||||||
const url = currWidgetsDetails?.SignUrl;
|
const url = props?.currWidgetsDetails?.SignUrl;
|
||||||
//checking widget type and draw type signature url
|
//checking widget type and draw type signature url
|
||||||
if (isInitial) {
|
if (props?.isInitial) {
|
||||||
if (isWidgetType === "initials" && signatureType === "draw" && url) {
|
if (isWidgetType === "initials" && signatureType === "draw" && url) {
|
||||||
canvasRef.current.fromDataURL(url);
|
canvasRef.current.fromDataURL(url);
|
||||||
}
|
}
|
||||||
@@ -171,12 +185,12 @@ function SignPad({
|
|||||||
|
|
||||||
const trimmedName = currentUserName && currentUserName?.trim();
|
const trimmedName = currentUserName && currentUserName?.trim();
|
||||||
const firstCharacter = trimmedName?.charAt(0);
|
const firstCharacter = trimmedName?.charAt(0);
|
||||||
const userName = isInitial ? firstCharacter : currentUserName;
|
const userName = props?.isInitial ? firstCharacter : currentUserName;
|
||||||
setSignValue(userName || "");
|
setSignValue(userName || "");
|
||||||
setFontSelect("Fasthand");
|
setFontSelect("Fasthand");
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isSignPad]);
|
}, [props.isSignPad]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadFont = async () => {
|
const loadFont = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -204,7 +218,7 @@ function SignPad({
|
|||||||
? signValue?.trim()
|
? signValue?.trim()
|
||||||
: currentUserName?.trim();
|
: currentUserName?.trim();
|
||||||
const firstCharacter = trimmedName?.charAt(0);
|
const firstCharacter = trimmedName?.charAt(0);
|
||||||
const userName = isInitial ? firstCharacter : signValue;
|
const userName = props?.isInitial ? firstCharacter : signValue;
|
||||||
setSignValue(userName);
|
setSignValue(userName);
|
||||||
convertToImg(fontSelect, userName);
|
convertToImg(fontSelect, userName);
|
||||||
}
|
}
|
||||||
@@ -233,7 +247,7 @@ function SignPad({
|
|||||||
// Draw the text content on the canvas
|
// Draw the text content on the canvas
|
||||||
const ctx = canvasElement.getContext("2d");
|
const ctx = canvasElement.getContext("2d");
|
||||||
const pixelRatio = window.devicePixelRatio || 1;
|
const pixelRatio = window.devicePixelRatio || 1;
|
||||||
const addExtraWidth = isInitial ? 10 : 50;
|
const addExtraWidth = props?.isInitial ? 10 : 50;
|
||||||
const width = span.offsetWidth + addExtraWidth;
|
const width = span.offsetWidth + addExtraWidth;
|
||||||
const height = span.offsetHeight;
|
const height = span.offsetHeight;
|
||||||
setTextWidth(width);
|
setTextWidth(width);
|
||||||
@@ -255,7 +269,7 @@ function SignPad({
|
|||||||
document.body.removeChild(span);
|
document.body.removeChild(span);
|
||||||
// Convert the canvas to image data
|
// Convert the canvas to image data
|
||||||
const dataUrl = canvasElement.toDataURL("image/png");
|
const dataUrl = canvasElement.toDataURL("image/png");
|
||||||
setSignature(dataUrl);
|
props?.setSignature(dataUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
const PenColorComponent = (props) => {
|
const PenColorComponent = (props) => {
|
||||||
@@ -297,33 +311,49 @@ function SignPad({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleCancelBtn` function trigger when user click on cross button
|
||||||
|
const handleCancelBtn = () => {
|
||||||
|
setPenColor("blue");
|
||||||
|
props?.setIsSignPad(false);
|
||||||
|
props?.setIsInitial(false);
|
||||||
|
props?.setIsImageSelect(false);
|
||||||
|
setIsDefaultSign(false);
|
||||||
|
props?.setImage();
|
||||||
|
handleTab();
|
||||||
|
setSignValue("");
|
||||||
|
props?.setIsStamp(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isSignPad && (
|
{props?.isSignPad && (
|
||||||
<div className="op-modal op-modal-open">
|
<div className="op-modal op-modal-open">
|
||||||
<div className="op-modal-box px-[13px] pt-2 pb-0">
|
<div className="op-modal-box px-[13px] pt-2 pb-0">
|
||||||
|
{isSignTypes ? (
|
||||||
|
<>
|
||||||
<div className="flex justify-between text-base-content items-center">
|
<div className="flex justify-between text-base-content items-center">
|
||||||
<div className="text-[1.2rem]">
|
<div className="text-[1.2rem]">
|
||||||
<div className="flex flex-row justify-between mt-[3px]">
|
<div className="flex flex-row justify-between mt-[3px]">
|
||||||
<div className="flex flex-row justify-between gap-[5px] md:gap-[8px] text-[11px] md:text-base">
|
<div className="flex flex-row justify-between gap-[5px] md:gap-[8px] text-[11px] md:text-base">
|
||||||
{isStamp ? (
|
{props?.isStamp ? (
|
||||||
<span className="text-base-content font-bold text-lg">
|
<span className="text-base-content font-bold text-lg">
|
||||||
{widgetType === "image" ||
|
{props?.widgetType === "image" ||
|
||||||
currWidgetsDetails?.type === "image"
|
props?.currWidgetsDetails?.type === "image"
|
||||||
? t("upload-image")
|
? t("upload-image")
|
||||||
: t("upload-stamp-image")}
|
: t("upload-stamp-image")}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
{isTabEnabled("draw") && (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(false);
|
props?.setIsImageSelect(false);
|
||||||
setIsTab("draw");
|
setIsTab("draw");
|
||||||
setImage();
|
props?.setImage();
|
||||||
if (isSignImg) {
|
if (isSignImg) {
|
||||||
setSignature(isSignImg);
|
props?.setSignature(isSignImg);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -335,11 +365,13 @@ function SignPad({
|
|||||||
{t("draw")}
|
{t("draw")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{isTabEnabled("upload") && (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(true);
|
props?.setIsImageSelect(true);
|
||||||
setIsTab("uploadImage");
|
setIsTab("uploadImage");
|
||||||
setSignatureType("");
|
setSignatureType("");
|
||||||
}}
|
}}
|
||||||
@@ -352,14 +384,16 @@ function SignPad({
|
|||||||
{t("upload-image")}
|
{t("upload-image")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{isTabEnabled("typed") && (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(false);
|
props?.setIsImageSelect(false);
|
||||||
setIsTab("type");
|
setIsTab("type");
|
||||||
setSignatureType("");
|
setSignatureType("");
|
||||||
setImage();
|
props?.setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
isTab === "type"
|
isTab === "type"
|
||||||
@@ -370,15 +404,18 @@ function SignPad({
|
|||||||
{t("type")}
|
{t("type")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{!isInitial && defaultSign ? (
|
)}
|
||||||
|
{!props?.isInitial &&
|
||||||
|
props?.defaultSign &&
|
||||||
|
isTabEnabled("default") ? (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(true);
|
setIsDefaultSign(true);
|
||||||
setIsImageSelect(true);
|
props?.setIsImageSelect(true);
|
||||||
setIsTab("mysignature");
|
setIsTab("mysignature");
|
||||||
setSignatureType("");
|
setSignatureType("");
|
||||||
setImage();
|
props?.setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
isTab === "mysignature"
|
isTab === "mysignature"
|
||||||
@@ -390,16 +427,17 @@ function SignPad({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
isInitial &&
|
props?.isInitial &&
|
||||||
myInitial && (
|
props?.myInitial &&
|
||||||
|
isTabEnabled("default") && (
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDefaultSign(true);
|
setIsDefaultSign(true);
|
||||||
setIsImageSelect(true);
|
props?.setIsImageSelect(true);
|
||||||
setIsTab("mysignature");
|
setIsTab("mysignature");
|
||||||
setSignatureType("");
|
setSignatureType("");
|
||||||
setImage();
|
props?.setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
isTab === "mysignature"
|
isTab === "mysignature"
|
||||||
@@ -419,18 +457,7 @@ function SignPad({
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="text-[1.5rem] cursor-pointer"
|
className="text-[1.5rem] cursor-pointer"
|
||||||
onClick={() => {
|
onClick={handleCancelBtn}
|
||||||
setPenColor("blue");
|
|
||||||
setIsSignPad(false);
|
|
||||||
setIsInitial(false);
|
|
||||||
setIsImageSelect(false);
|
|
||||||
setIsDefaultSign(false);
|
|
||||||
setImage();
|
|
||||||
setIsTab("draw");
|
|
||||||
setSignatureType("draw");
|
|
||||||
setSignValue("");
|
|
||||||
setIsStamp(false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
×
|
×
|
||||||
</div>
|
</div>
|
||||||
@@ -451,14 +478,20 @@ function SignPad({
|
|||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
props?.isInitial
|
||||||
|
? "intialSignatureCanvas"
|
||||||
|
: "signatureCanvas"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="stamp img"
|
alt="stamp img"
|
||||||
className="w-full h-full object-contain bg-white"
|
className="w-full h-full object-contain bg-white"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
src={isInitial ? myInitial : defaultSign}
|
src={
|
||||||
|
props?.isInitial
|
||||||
|
? props?.myInitial
|
||||||
|
: props?.defaultSign
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -466,8 +499,8 @@ function SignPad({
|
|||||||
<SaveBtn />
|
<SaveBtn />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : isImageSelect || isStamp ? (
|
) : props?.isImageSelect || props?.isStamp ? (
|
||||||
!image ? (
|
!props?.image ? (
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -481,16 +514,18 @@ function SignPad({
|
|||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
|
props?.isInitial
|
||||||
|
? "intialSignatureCanvas"
|
||||||
|
: "signatureCanvas"
|
||||||
}
|
}
|
||||||
onClick={() => imageRef.current.click()}
|
onClick={() => props?.imageRef.current.click()}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
onChange={onImageChange}
|
onChange={props?.onImageChange}
|
||||||
className="filetype"
|
className="filetype"
|
||||||
accept="image/png,image/jpeg"
|
accept="image/png,image/jpeg"
|
||||||
ref={imageRef}
|
ref={props?.imageRef}
|
||||||
hidden
|
hidden
|
||||||
/>
|
/>
|
||||||
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
|
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
|
||||||
@@ -508,15 +543,15 @@ function SignPad({
|
|||||||
overflow: "hidden"
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
isInitial
|
props?.isInitial
|
||||||
? "intialSignatureCanvas"
|
? "intialSignatureCanvas"
|
||||||
: "signatureCanvas"
|
: "signatureCanvas"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="print img"
|
alt="print img"
|
||||||
ref={imageRef}
|
ref={props?.imageRef}
|
||||||
src={image.src}
|
src={props?.image.src}
|
||||||
draggable="false"
|
draggable="false"
|
||||||
className=" object-contain h-full w-full"
|
className=" object-contain h-full w-full"
|
||||||
/>
|
/>
|
||||||
@@ -531,10 +566,13 @@ function SignPad({
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="mr-[5px] text-[12px]">
|
<span className="mr-[5px] text-[12px]">
|
||||||
{isInitial ? t("initial-teb") : t("signature-tab")}:
|
{props?.isInitial
|
||||||
|
? t("initial-teb")
|
||||||
|
: t("signature-tab")}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
maxLength={isInitial ? 3 : 30}
|
maxLength={props?.isInitial ? 3 : 30}
|
||||||
style={{ fontFamily: fontSelect, color: penColor }}
|
style={{ fontFamily: fontSelect, color: penColor }}
|
||||||
type="text"
|
type="text"
|
||||||
className="ml-1 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-[20px]"
|
className="ml-1 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-[20px]"
|
||||||
@@ -555,7 +593,8 @@ function SignPad({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
fontFamily: font.value,
|
fontFamily: font.value,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
fontSelect === font.value && "rgb(206 225 247)"
|
fontSelect === font.value &&
|
||||||
|
"rgb(206 225 247)"
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFontSelect(font.value);
|
setFontSelect(font.value);
|
||||||
@@ -588,7 +627,7 @@ function SignPad({
|
|||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
penColor={penColor}
|
penColor={penColor}
|
||||||
canvasProps={{
|
canvasProps={{
|
||||||
className: isInitial
|
className: props?.isInitial
|
||||||
? "intialSignatureCanvas"
|
? "intialSignatureCanvas"
|
||||||
: "signatureCanvas",
|
: "signatureCanvas",
|
||||||
style: {
|
style: {
|
||||||
@@ -596,9 +635,11 @@ function SignPad({
|
|||||||
borderRadius: "2px"
|
borderRadius: "2px"
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
// backgroundColor="rgb(255, 255, 255)"
|
||||||
onEnd={() =>
|
onEnd={() =>
|
||||||
handleSignatureChange(canvasRef.current?.toDataURL())
|
handleSignatureChange(
|
||||||
|
canvasRef.current?.toDataURL()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
dotSize={1}
|
dotSize={1}
|
||||||
/>
|
/>
|
||||||
@@ -610,6 +651,25 @@ function SignPad({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="">
|
||||||
|
<div className="relative flex flex-row items-center justify-between">
|
||||||
|
<div className="text-base-content font-bold text-lg">
|
||||||
|
Signature
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="text-[1.5rem] cursor-pointer"
|
||||||
|
onClick={handleCancelBtn}
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mx-3 mb-6 mt-3">
|
||||||
|
<p>{t("at-least-one-signature-type")}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -21,9 +21,11 @@ function TextFontSetting(props) {
|
|||||||
value={
|
value={
|
||||||
props.fontSize ||
|
props.fontSize ||
|
||||||
props.currWidgetsDetails?.options?.fontSize ||
|
props.currWidgetsDetails?.options?.fontSize ||
|
||||||
"12"
|
12
|
||||||
}
|
}
|
||||||
onChange={(e) => props.setFontSize(e.target.value)}
|
onChange={(e) => {
|
||||||
|
props.setFontSize(parseInt(e.target.value));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{fontsizeArr.map((size, ind) => {
|
{fontsizeArr.map((size, ind) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import RecipientList from "./RecipientList";
|
|||||||
import { useDrag } from "react-dnd";
|
import { useDrag } from "react-dnd";
|
||||||
import WidgetList from "./WidgetList";
|
import WidgetList from "./WidgetList";
|
||||||
import {
|
import {
|
||||||
|
color,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
@@ -43,163 +44,69 @@ function WidgetComponent({
|
|||||||
const [isSignersModal, setIsSignersModal] = useState(false);
|
const [isSignersModal, setIsSignersModal] = useState(false);
|
||||||
const [, dropdown] = useDrag({
|
const [, dropdown] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 5, text: "dropdown" },
|
||||||
type: "BOX",
|
|
||||||
id: 5,
|
|
||||||
text: "dropdown"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({
|
||||||
isDragDropdown: !!monitor.isDragging()
|
isDragDropdown: !!monitor.isDragging()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
const [, checkbox] = useDrag({
|
const [, checkbox] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 6, text: "checkbox" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragCheck: !!monitor.isDragging() })
|
||||||
id: 6,
|
|
||||||
text: "checkbox"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragCheck: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, textInput] = useDrag({
|
const [, textInput] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 7, text: textInputWidget },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragTextInput: !!monitor.isDragging() })
|
||||||
id: 7,
|
|
||||||
text: textInputWidget
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragTextInput: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, initials] = useDrag({
|
const [, initials] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 8, text: "initials" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragInitial: !!monitor.isDragging() })
|
||||||
id: 8,
|
|
||||||
text: "initials"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragInitial: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, name] = useDrag({
|
const [, name] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 9, text: "name" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragName: !!monitor.isDragging() })
|
||||||
id: 9,
|
|
||||||
text: "name"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragName: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, company] = useDrag({
|
const [, company] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 10, text: "company" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragCompany: !!monitor.isDragging() })
|
||||||
id: 10,
|
|
||||||
text: "company"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragCompany: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, jobTitle] = useDrag({
|
const [, jobTitle] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 11, text: "job title" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragJobtitle: !!monitor.isDragging() })
|
||||||
id: 11,
|
|
||||||
text: "job title"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragJobtitle: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, date] = useDrag({
|
const [, date] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 12, text: "date" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragDate: !!monitor.isDragging() })
|
||||||
id: 12,
|
|
||||||
text: "date"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragDate: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, image] = useDrag({
|
const [, image] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 13, text: "image" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragImage: !!monitor.isDragging() })
|
||||||
id: 13,
|
|
||||||
text: "image"
|
|
||||||
},
|
|
||||||
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragImage: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, email] = useDrag({
|
const [, email] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 14, text: "email" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragEmail: !!monitor.isDragging() })
|
||||||
id: 14,
|
|
||||||
text: "email"
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragEmail: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, radioButton] = useDrag({
|
const [, radioButton] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
|
item: { type: "BOX", id: 15, text: radioButtonWidget },
|
||||||
item: {
|
collect: (monitor) => ({ isDragRadiotton: !!monitor.isDragging() })
|
||||||
type: "BOX",
|
|
||||||
id: 15,
|
|
||||||
text: radioButtonWidget
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragRadiotton: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [, text] = useDrag({
|
const [, text] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
|
item: { type: "BOX", id: 16, text: textWidget },
|
||||||
item: {
|
collect: (monitor) => ({ isDragText: !!monitor.isDragging() })
|
||||||
type: "BOX",
|
|
||||||
id: 16,
|
|
||||||
text: textWidget
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragText: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const scrollContainerRef = useRef(null);
|
const scrollContainerRef = useRef(null);
|
||||||
const [widget, setWidget] = useState([]);
|
const [widget, setWidget] = useState([]);
|
||||||
const color = [
|
|
||||||
"#93a3db",
|
|
||||||
"#e6c3db",
|
|
||||||
"#c0e3bc",
|
|
||||||
"#bce3db",
|
|
||||||
"#b8ccdb",
|
|
||||||
"#ceb8db",
|
|
||||||
"#ffccff",
|
|
||||||
"#99ffcc",
|
|
||||||
"#cc99ff",
|
|
||||||
"#ffcc99",
|
|
||||||
"#66ccff",
|
|
||||||
"#ffffcc"
|
|
||||||
];
|
|
||||||
const handleModal = () => {
|
const handleModal = () => {
|
||||||
setIsSignersModal(!isSignersModal);
|
setIsSignersModal(!isSignersModal);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import React, { useEffect, useState } from "react";
|
|||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import "../../styles/AddUser.css";
|
import "../../styles/AddUser.css";
|
||||||
import RegexParser from "regex-parser";
|
import RegexParser from "regex-parser";
|
||||||
import { textInputWidget, textWidget } from "../../constant/Utils";
|
import {
|
||||||
|
signatureTypes,
|
||||||
|
textInputWidget,
|
||||||
|
textWidget
|
||||||
|
} from "../../constant/Utils";
|
||||||
import Upgrade from "../../primitives/Upgrade";
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
import { isEnableSubscription } from "../../constant/const";
|
import { isEnableSubscription } from "../../constant/const";
|
||||||
import Tooltip from "../../primitives/Tooltip";
|
import Tooltip from "../../primitives/Tooltip";
|
||||||
@@ -11,6 +15,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
|
|
||||||
const WidgetNameModal = (props) => {
|
const WidgetNameModal = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const signTypes = props?.signatureType || signatureTypes;
|
||||||
const [formdata, setFormdata] = useState({
|
const [formdata, setFormdata] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
@@ -21,6 +26,7 @@ const WidgetNameModal = (props) => {
|
|||||||
const [isValid, setIsValid] = useState(true);
|
const [isValid, setIsValid] = useState(true);
|
||||||
const statusArr = ["Required", "Optional"];
|
const statusArr = ["Required", "Optional"];
|
||||||
const inputOpt = ["text", "email", "number"];
|
const inputOpt = ["text", "email", "number"];
|
||||||
|
const [signatureType, setSignatureType] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.defaultdata) {
|
if (props.defaultdata) {
|
||||||
@@ -40,12 +46,32 @@ const WidgetNameModal = (props) => {
|
|||||||
name: props.defaultdata?.options?.name || ""
|
name: props.defaultdata?.options?.name || ""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signTypes.length > 0) {
|
||||||
|
const defaultSignatureType = signTypes || [];
|
||||||
|
setSignatureType(defaultSignatureType);
|
||||||
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [props.defaultdata]);
|
}, [props.defaultdata]);
|
||||||
const handleSubmit = (e) => {
|
const handleSubmit = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (props.handleData) {
|
if (props.handleData) {
|
||||||
|
if (["signature", "initials"].includes(props.defaultdata?.type)) {
|
||||||
|
const enabledSignTypes = signatureType?.filter((x) => x.enabled);
|
||||||
|
const isDefaultSignTypeOnly =
|
||||||
|
enabledSignTypes?.length === 1 &&
|
||||||
|
enabledSignTypes[0]?.name === "default";
|
||||||
|
if (enabledSignTypes.length === 0) {
|
||||||
|
alert(t("at-least-one-signature-type"));
|
||||||
|
} else if (isDefaultSignTypeOnly) {
|
||||||
|
alert(t("expect-default-one-more-signature-type"));
|
||||||
|
} else {
|
||||||
|
const data = { ...formdata, signatureType };
|
||||||
|
props.handleData(data, props.defaultdata?.type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
props.handleData(formdata);
|
props.handleData(formdata);
|
||||||
|
}
|
||||||
setFormdata({
|
setFormdata({
|
||||||
name: "",
|
name: "",
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
@@ -53,6 +79,7 @@ const WidgetNameModal = (props) => {
|
|||||||
hint: "",
|
hint: "",
|
||||||
textvalidate: ""
|
textvalidate: ""
|
||||||
});
|
});
|
||||||
|
setSignatureType(signTypes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
@@ -102,6 +129,15 @@ const WidgetNameModal = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCheckboxChange = (index) => {
|
||||||
|
// Create a copy of the signatureType array
|
||||||
|
const updatedSignatureType = [...signatureType];
|
||||||
|
// Toggle the enabled value for the clicked item
|
||||||
|
updatedSignatureType[index].enabled = !updatedSignatureType[index].enabled;
|
||||||
|
// Update the state with the modified array
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={props.isOpen}
|
isOpen={props.isOpen}
|
||||||
@@ -111,9 +147,14 @@ const WidgetNameModal = (props) => {
|
|||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className={`${
|
className={`${
|
||||||
props.defaultdata?.type === textInputWidget ? "pt-0" : ""
|
props.defaultdata?.type === textInputWidget
|
||||||
|
? "pt-0"
|
||||||
|
: ["signature", "initials"].includes(props.defaultdata?.type)
|
||||||
|
? "pt-2"
|
||||||
|
: ""
|
||||||
} p-[20px] text-base-content`}
|
} p-[20px] text-base-content`}
|
||||||
>
|
>
|
||||||
|
{!["signature", "initials"].includes(props.defaultdata?.type) && (
|
||||||
<div className="mb-[0.75rem] text-[13px]">
|
<div className="mb-[0.75rem] text-[13px]">
|
||||||
<label htmlFor="name">
|
<label htmlFor="name">
|
||||||
{t("name")}
|
{t("name")}
|
||||||
@@ -129,6 +170,7 @@ const WidgetNameModal = (props) => {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
{props.defaultdata?.type === textInputWidget && (
|
{props.defaultdata?.type === textInputWidget && (
|
||||||
<>
|
<>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && (
|
||||||
@@ -226,11 +268,15 @@ const WidgetNameModal = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{!["signature", "initials"].includes(props.defaultdata?.type) && (
|
||||||
<div className="mb-[0.75rem]">
|
<div className="mb-[0.75rem]">
|
||||||
<div className="flex flex-row gap-[10px] mb-[0.5rem]">
|
<div className="flex flex-row gap-[10px] mb-[0.5rem]">
|
||||||
{statusArr.map((data, ind) => {
|
{statusArr.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<div key={ind} className="flex flex-row gap-[5px] items-center">
|
<div
|
||||||
|
key={ind}
|
||||||
|
className="flex flex-row gap-[5px] items-center"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
className="mr-[2px] op-radio op-radio-xs"
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -250,6 +296,35 @@ const WidgetNameModal = (props) => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{["signature", "initials"].includes(props.defaultdata?.type) && (
|
||||||
|
<div className="mb-[0.75rem]">
|
||||||
|
<label htmlFor="signaturetype" className="text-[14px] mb-[0.7rem]">
|
||||||
|
{t("allowed-signature-types")}
|
||||||
|
</label>
|
||||||
|
<div className=" ml-[7px] flex flex-col md:flex-row gap-[10px] mb-[0.7rem]">
|
||||||
|
{signatureType.map((type, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i} className="flex flex-row gap-[5px] items-center">
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-checkbox op-checkbox-xs"
|
||||||
|
type="checkbox"
|
||||||
|
name="signaturetype"
|
||||||
|
onChange={() => handleCheckboxChange(i)}
|
||||||
|
checked={type.enabled}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="text-[13px] font-medium hover:underline underline-offset-2 cursor-default capitalize"
|
||||||
|
title={`Enabling this allow signers to ${type.name} signature`}
|
||||||
|
>
|
||||||
|
{type.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{props.defaultdata?.type === textInputWidget && (
|
{props.defaultdata?.type === textInputWidget && (
|
||||||
<div className="mb-[0.75rem]">
|
<div className="mb-[0.75rem]">
|
||||||
<label htmlFor="hint" className="text-[13px]">
|
<label htmlFor="hint" className="text-[13px]">
|
||||||
@@ -276,9 +351,9 @@ const WidgetNameModal = (props) => {
|
|||||||
<select
|
<select
|
||||||
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
value={
|
value={
|
||||||
props.fontSize || props.defaultdata?.options?.fontSize || "12"
|
props.fontSize || props.defaultdata?.options?.fontSize || 12
|
||||||
}
|
}
|
||||||
onChange={(e) => props.setFontSize(e.target.value)}
|
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
|
||||||
>
|
>
|
||||||
{fontsizeArr.map((size, ind) => {
|
{fontsizeArr.map((size, ind) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ const DROPBOX_SCRIPT_ID = "dropboxjs";
|
|||||||
|
|
||||||
export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
||||||
useDropScript(DROPBOX_SDK_URL, {
|
useDropScript(DROPBOX_SDK_URL, {
|
||||||
attrs: {
|
attrs: { id: DROPBOX_SCRIPT_ID, "data-app-key": DROPBOX_APP_KEY }
|
||||||
id: DROPBOX_SCRIPT_ID,
|
|
||||||
"data-app-key": DROPBOX_APP_KEY
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Parse from "parse";
|
|
||||||
import AsyncSelect from "react-select/async";
|
import AsyncSelect from "react-select/async";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
const SelectSigners = (props) => {
|
const SelectSigners = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -31,17 +31,19 @@ const SelectSigners = (props) => {
|
|||||||
|
|
||||||
const loadOptions = async (inputValue) => {
|
const loadOptions = async (inputValue) => {
|
||||||
try {
|
try {
|
||||||
const currentUser = Parse.User.current();
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
const contactbook = new Parse.Query("contracts_Contactbook");
|
const url = `${baseURL}functions/getsigners`;
|
||||||
contactbook.equalTo(
|
const token = props.jwttoken
|
||||||
"CreatedBy",
|
? { jwttoken: props.jwttoken }
|
||||||
Parse.User.createWithoutData(currentUser.id)
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
);
|
const headers = {
|
||||||
if (inputValue.length > 1) {
|
"Content-Type": "application/json",
|
||||||
contactbook.matches("Name", new RegExp(inputValue, "i"));
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
}
|
...token
|
||||||
contactbook.notEqualTo("IsDeleted", true);
|
};
|
||||||
const contactRes = await contactbook.find();
|
const searchEmail = inputValue ? inputValue : "";
|
||||||
|
const axiosRes = await axios.post(url, { searchEmail }, { headers });
|
||||||
|
const contactRes = axiosRes?.data?.result || [];
|
||||||
if (contactRes) {
|
if (contactRes) {
|
||||||
const res = JSON.parse(JSON.stringify(contactRes));
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
|
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
|
||||||
@@ -52,11 +54,9 @@ const SelectSigners = (props) => {
|
|||||||
!signerObj.find((item2) => item2.objectId === item1.objectId)
|
!signerObj.find((item2) => item2.objectId === item1.objectId)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
//get update signer's List if signersdata is present
|
//get update signer's List if signersdata is present
|
||||||
const updateSignersList =
|
const updateSignersList =
|
||||||
props?.signersData && compareArrays(res, props?.signersData);
|
props?.signersData && compareArrays(res, props?.signersData);
|
||||||
|
|
||||||
const result = updateSignersList ? updateSignersList : res;
|
const result = updateSignersList ? updateSignersList : res;
|
||||||
setUserList(result);
|
setUserList(result);
|
||||||
return await result.map((item) => ({
|
return await result.map((item) => ({
|
||||||
@@ -68,7 +68,6 @@ const SelectSigners = (props) => {
|
|||||||
console.log("err", error);
|
console.log("err", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full px-[20px] py-[10px] text-base-content">
|
<div className="h-full px-[20px] py-[10px] text-base-content">
|
||||||
<div className="w-full mx-auto p-[8px]">
|
<div className="w-full mx-auto p-[8px]">
|
||||||
@@ -85,6 +84,7 @@ const SelectSigners = (props) => {
|
|||||||
loadOptions={loadOptions}
|
loadOptions={loadOptions}
|
||||||
onChange={handleOptions}
|
onChange={handleOptions}
|
||||||
unstyled
|
unstyled
|
||||||
|
onFocus={() => loadOptions()}
|
||||||
classNames={{
|
classNames={{
|
||||||
control: () =>
|
control: () =>
|
||||||
"op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full h-full text-[11px]",
|
"op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full h-full text-[11px]",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const SuggestionInput = (props) => {
|
|||||||
if (timer) clearTimeout(timer);
|
if (timer) clearTimeout(timer);
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await findContact(inputValue);
|
const res = await findContact(inputValue, props.jwttoken);
|
||||||
if (res?.length > 0) {
|
if (res?.length > 0) {
|
||||||
setSuggestions(res);
|
setSuggestions(res);
|
||||||
setShowSuggestions(true);
|
setShowSuggestions(true);
|
||||||
@@ -37,13 +37,14 @@ const SuggestionInput = (props) => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [inputValue]);
|
}, [inputValue]);
|
||||||
|
|
||||||
const handleInputChange = async (e) => {
|
const handleInputChange = async (e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setInputValue(value?.toLowerCase());
|
setInputValue(value?.toLowerCase()?.replace(/\s/g, ""));
|
||||||
if (props.onChange) {
|
if (props.onChange) {
|
||||||
props.onChange(value);
|
props.onChange(value?.toLowerCase()?.replace(/\s/g, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.trim() === "") {
|
if (value.trim() === "") {
|
||||||
|
|||||||
+256
-143
@@ -34,7 +34,8 @@ export async function fetchSubscription(
|
|||||||
extUserId,
|
extUserId,
|
||||||
contactObjId,
|
contactObjId,
|
||||||
isGuestSign = false,
|
isGuestSign = false,
|
||||||
isPublic = false
|
isPublic = false,
|
||||||
|
jwtToken
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const Extand_Class = localStorage.getItem("Extand_Class");
|
const Extand_Class = localStorage.getItem("Extand_Class");
|
||||||
@@ -48,10 +49,13 @@ export async function fetchSubscription(
|
|||||||
}
|
}
|
||||||
const baseURL = localStorage.getItem("baseUrl");
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
const url = `${baseURL}functions/getsubscriptions`;
|
const url = `${baseURL}functions/getsubscriptions`;
|
||||||
|
const token = jwtToken
|
||||||
|
? { jwttoken: jwtToken }
|
||||||
|
: { sessionToken: localStorage.getItem("accesstoken") };
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
...token
|
||||||
};
|
};
|
||||||
const params = isGuestSign
|
const params = isGuestSign
|
||||||
? { contactId: contactObjId }
|
? { contactId: contactObjId }
|
||||||
@@ -122,9 +126,9 @@ export async function fetchSubscriptionInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//function to get subcripition details from subscription class
|
//function to get subcripition details from subscription class
|
||||||
export async function checkIsSubscribed() {
|
export async function checkIsSubscribed(jwttoken) {
|
||||||
try {
|
try {
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription("", "", false, false, jwttoken);
|
||||||
if (res.plan === "freeplan") {
|
if (res.plan === "freeplan") {
|
||||||
return { plan: res.plan, isValid: false, adminId: res?.adminId };
|
return { plan: res.plan, isValid: false, adminId: res?.adminId };
|
||||||
} else if (res.billingDate) {
|
} else if (res.billingDate) {
|
||||||
@@ -226,12 +230,25 @@ export const pdfNewWidthFun = (divRef) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//`contractUsers` function is used to get contract_User details
|
//`contractUsers` function is used to get contract_User details
|
||||||
export const contractUsers = async () => {
|
export const contractUsers = async (jwttoken) => {
|
||||||
try {
|
try {
|
||||||
const userDetails = await Parse.Cloud.run("getUserDetails");
|
const url = `${localStorage.getItem("baseUrl")}functions/getUserDetails`;
|
||||||
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
|
const accesstoken = localStorage.getItem("accesstoken");
|
||||||
|
const token = jwttoken
|
||||||
|
? { jwttoken: jwttoken }
|
||||||
|
: { "X-Parse-Session-Token": accesstoken };
|
||||||
|
const headers = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
...token
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const userDetails = await axios.post(url, {}, headers);
|
||||||
let data = [];
|
let data = [];
|
||||||
if (userDetails) {
|
if (userDetails?.data?.result) {
|
||||||
const json = JSON.parse(JSON.stringify(userDetails));
|
const json = JSON.parse(JSON.stringify(userDetails.data.result));
|
||||||
data.push(json);
|
data.push(json);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
@@ -446,29 +463,29 @@ export const defaultWidthHeight = (type) => {
|
|||||||
case "stamp":
|
case "stamp":
|
||||||
return { width: 150, height: 60 };
|
return { width: 150, height: 60 };
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
return { width: 15, height: 15 };
|
return { width: 15, height: 19 };
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
return { width: 150, height: 25 };
|
return { width: 150, height: 19 };
|
||||||
case "dropdown":
|
case "dropdown":
|
||||||
return { width: 120, height: 22 };
|
return { width: 120, height: 22 };
|
||||||
case "initials":
|
case "initials":
|
||||||
return { width: 50, height: 50 };
|
return { width: 50, height: 50 };
|
||||||
case "name":
|
case "name":
|
||||||
return { width: 150, height: 25 };
|
return { width: 150, height: 19 };
|
||||||
case "company":
|
case "company":
|
||||||
return { width: 150, height: 25 };
|
return { width: 150, height: 19 };
|
||||||
case "job title":
|
case "job title":
|
||||||
return { width: 150, height: 25 };
|
return { width: 150, height: 19 };
|
||||||
case "date":
|
case "date":
|
||||||
return { width: 100, height: 20 };
|
return { width: 100, height: 20 };
|
||||||
case "image":
|
case "image":
|
||||||
return { width: 70, height: 70 };
|
return { width: 70, height: 70 };
|
||||||
case "email":
|
case "email":
|
||||||
return { width: 150, height: 20 };
|
return { width: 150, height: 19 };
|
||||||
case radioButtonWidget:
|
case radioButtonWidget:
|
||||||
return { width: 5, height: 10 };
|
return { width: 5, height: 10 };
|
||||||
case textWidget:
|
case textWidget:
|
||||||
return { width: 150, height: 25 };
|
return { width: 150, height: 19 };
|
||||||
default:
|
default:
|
||||||
return { width: 150, height: 60 };
|
return { width: 150, height: 60 };
|
||||||
}
|
}
|
||||||
@@ -620,10 +637,10 @@ export const signPdfFun = async (
|
|||||||
return { status: "error", message: "something went wrong." };
|
return { status: "error", message: "something went wrong." };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//change image width and height to 100/40 in png base64
|
//change image width and height to 300/120 in png base64
|
||||||
const getNewse64 = await changeImageWH(base64Sign);
|
const imagebase64 = await changeImageWH(base64Sign);
|
||||||
//remove suffiix of base64
|
//remove suffiix of base64 (without type)
|
||||||
const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
|
const suffixbase64 = imagebase64 && imagebase64.split(",").pop();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
mailProvider: activeMailAdapter,
|
mailProvider: activeMailAdapter,
|
||||||
@@ -645,9 +662,7 @@ export const signPdfFun = async (
|
|||||||
status: "error",
|
status: "error",
|
||||||
message: "Currently encrypted pdf files are not supported."
|
message: "Currently encrypted pdf files are not supported."
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (e?.message?.includes("password")) {
|
||||||
e.message === "PKCS#12 MAC could not be verified. Invalid password?"
|
|
||||||
) {
|
|
||||||
return { status: "error", message: "PFX file password is invalid." };
|
return { status: "error", message: "PFX file password is invalid." };
|
||||||
} else {
|
} else {
|
||||||
return { status: "error", message: "something went wrong." };
|
return { status: "error", message: "something went wrong." };
|
||||||
@@ -670,7 +685,6 @@ export const createDocument = async (
|
|||||||
) => {
|
) => {
|
||||||
if (template && template.length > 0) {
|
if (template && template.length > 0) {
|
||||||
const Doc = template[0];
|
const Doc = template[0];
|
||||||
|
|
||||||
let placeholdersArr = [];
|
let placeholdersArr = [];
|
||||||
if (placeholders?.length > 0) {
|
if (placeholders?.length > 0) {
|
||||||
placeholdersArr = placeholders;
|
placeholdersArr = placeholders;
|
||||||
@@ -688,6 +702,12 @@ export const createDocument = async (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const SignatureType = Doc?.SignatureType
|
||||||
|
? { SignatureType: Doc?.SignatureType }
|
||||||
|
: {};
|
||||||
|
const NotifyOnSignatures = Doc?.NotifyOnSignatures
|
||||||
|
? { NotifyOnSignatures: Doc?.NotifyOnSignatures }
|
||||||
|
: {};
|
||||||
const data = {
|
const data = {
|
||||||
Name: Doc.Name,
|
Name: Doc.Name,
|
||||||
URL: pdfUrl,
|
URL: pdfUrl,
|
||||||
@@ -710,7 +730,11 @@ export const createDocument = async (
|
|||||||
SendinOrder: Doc?.SendinOrder || false,
|
SendinOrder: Doc?.SendinOrder || false,
|
||||||
AutomaticReminders: Doc?.AutomaticReminders || false,
|
AutomaticReminders: Doc?.AutomaticReminders || false,
|
||||||
RemindOnceInEvery: parseInt(Doc?.RemindOnceInEvery || 5),
|
RemindOnceInEvery: parseInt(Doc?.RemindOnceInEvery || 5),
|
||||||
IsEnableOTP: Doc?.IsEnableOTP || false
|
IsEnableOTP: Doc?.IsEnableOTP || false,
|
||||||
|
IsTourEnabled: Doc?.IsTourEnabled || false,
|
||||||
|
FileAdapterId: Doc?.FileAdapterId || "",
|
||||||
|
...SignatureType,
|
||||||
|
...NotifyOnSignatures
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -996,7 +1020,7 @@ export const calculateInitialWidthHeight = (widgetData) => {
|
|||||||
const intialText = widgetData;
|
const intialText = widgetData;
|
||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.textContent = intialText;
|
span.textContent = intialText;
|
||||||
span.style.font = `14px`; // here put your text size and font family
|
span.style.font = `12px`; // here put your text size and font family
|
||||||
span.style.display = "hidden";
|
span.style.display = "hidden";
|
||||||
document.body.appendChild(span);
|
document.body.appendChild(span);
|
||||||
const width = span.offsetWidth;
|
const width = span.offsetWidth;
|
||||||
@@ -1086,6 +1110,7 @@ export const embedDocId = async (pdfDoc, documentId, allPages) => {
|
|||||||
const textContent = documentId && `OpenSign™ DocumentId: ${documentId} `;
|
const textContent = documentId && `OpenSign™ DocumentId: ${documentId} `;
|
||||||
const pages = pdfDoc.getPages();
|
const pages = pdfDoc.getPages();
|
||||||
const page = pages[i];
|
const page = pages[i];
|
||||||
|
try {
|
||||||
const getObj = compensateRotation(
|
const getObj = compensateRotation(
|
||||||
page.getRotation().angle,
|
page.getRotation().angle,
|
||||||
10,
|
10,
|
||||||
@@ -1098,6 +1123,9 @@ export const embedDocId = async (pdfDoc, documentId, allPages) => {
|
|||||||
page
|
page
|
||||||
);
|
);
|
||||||
page.drawText(textContent, getObj);
|
page.drawText(textContent, getObj);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in embed docId on page", i + 1, err?.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1145,10 +1173,7 @@ export function onSaveSign(
|
|||||||
Height: posHeight,
|
Height: posHeight,
|
||||||
SignUrl: signatureImg,
|
SignUrl: signatureImg,
|
||||||
signatureType: type && type,
|
signatureType: type && type,
|
||||||
options: {
|
options: { ...position.options, response: signatureImg }
|
||||||
...position.options,
|
|
||||||
response: signatureImg
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
@@ -1282,16 +1307,6 @@ export const changeImageWH = async (base64Image) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
//function to calculate font size of text area widgets
|
|
||||||
const calculateFontSize = (position, containerScale, signyourself) => {
|
|
||||||
const font = position?.options?.fontSize || 12;
|
|
||||||
if (!signyourself && position?.isMobile && position?.scale) {
|
|
||||||
return font / position?.scale / containerScale;
|
|
||||||
} else {
|
|
||||||
return font / containerScale;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getWidgetsFontColor = (type) => {
|
const getWidgetsFontColor = (type) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "red":
|
case "red":
|
||||||
@@ -1307,26 +1322,16 @@ const getWidgetsFontColor = (type) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
//function for embed multiple signature using pdf-lib
|
//function for embed multiple signature using pdf-lib
|
||||||
export const multiSignEmbed = async (
|
export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||||
widgets,
|
|
||||||
pdfDoc,
|
|
||||||
signyourself,
|
|
||||||
scale,
|
|
||||||
pdfOriginalWH,
|
|
||||||
containerWH
|
|
||||||
) => {
|
|
||||||
// `fontBytes` is used to embed custom font in pdf
|
// `fontBytes` is used to embed custom font in pdf
|
||||||
const fontBytes = await fileasbytes(
|
const fontBytes = await fileasbytes(
|
||||||
"https://cdn.opensignlabs.com/webfonts/times.ttf"
|
"https://cdn.opensignlabs.com/webfonts/times.ttf"
|
||||||
);
|
);
|
||||||
pdfDoc.registerFontkit(fontkit);
|
pdfDoc.registerFontkit(fontkit);
|
||||||
const font = await pdfDoc.embedFont(fontBytes, { subset: true });
|
const font = await pdfDoc.embedFont(fontBytes, { subset: true });
|
||||||
|
let hasError = false;
|
||||||
for (let item of widgets) {
|
for (let item of widgets) {
|
||||||
const containerScale = getContainerScale(
|
if (hasError) break; // Stop the outer loop if an error occurred
|
||||||
pdfOriginalWH,
|
|
||||||
item?.pageNumber,
|
|
||||||
containerWH
|
|
||||||
);
|
|
||||||
const typeExist = item.pos.some((data) => data?.type);
|
const typeExist = item.pos.some((data) => data?.type);
|
||||||
let updateItem;
|
let updateItem;
|
||||||
|
|
||||||
@@ -1334,8 +1339,17 @@ export const multiSignEmbed = async (
|
|||||||
if (signyourself) {
|
if (signyourself) {
|
||||||
updateItem = item.pos;
|
updateItem = item.pos;
|
||||||
} else {
|
} else {
|
||||||
|
// Checking required and optional widget types
|
||||||
|
// For both required and optional widgets, handle signurl, defaultValue, and response as the widget's data
|
||||||
|
// If the widget type is checkbox or radio (whether required or optional), we don't need to validate its value.
|
||||||
|
// Instead, add an empty checkbox/radio, or if a value exists, mark the checkbox/radio as checked.
|
||||||
updateItem = item.pos.filter(
|
updateItem = item.pos.filter(
|
||||||
(data) => data?.options?.status === "required"
|
(data) =>
|
||||||
|
data?.options?.SignUrl ||
|
||||||
|
data?.options?.defaultValue ||
|
||||||
|
data?.options?.response ||
|
||||||
|
data?.type === "checkbox" ||
|
||||||
|
data?.type === radioButtonWidget
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1347,39 +1361,37 @@ export const multiSignEmbed = async (
|
|||||||
const form = pdfDoc.getForm();
|
const form = pdfDoc.getForm();
|
||||||
const page = pages[pageNo - 1];
|
const page = pages[pageNo - 1];
|
||||||
const images = await Promise.all(
|
const images = await Promise.all(
|
||||||
widgetsPositionArr.map(async (url) => {
|
widgetsPositionArr.map(async (widget) => {
|
||||||
let signUrl = url.SignUrl && url.SignUrl;
|
// `SignUrl` this is wrong nomenclature and maintain for older code in this options we save base64 of signature image from sign pad
|
||||||
if (signUrl) {
|
let signbase64 = widget.SignUrl && widget.SignUrl;
|
||||||
if (url.ImageType === "image/png") {
|
if (signbase64) {
|
||||||
//function for convert signature png base64 url to jpeg base64
|
let arr = signbase64.split(","),
|
||||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
mime = arr[0].match(/:(.*?);/)[1];
|
||||||
signUrl = newUrl;
|
const res = await fetch(signbase64);
|
||||||
}
|
const arrayBuffer = await res.arrayBuffer();
|
||||||
const res = await fetch(signUrl);
|
const obj = { mimetype: mime, arrayBuffer: arrayBuffer };
|
||||||
return res.arrayBuffer();
|
return obj;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
for (let [id, position] of widgetsPositionArr.entries()) {
|
||||||
widgetsPositionArr.forEach(async (position, id) => {
|
if (hasError) break; // Stop the inner loop if an error occurred
|
||||||
|
try {
|
||||||
let img;
|
let img;
|
||||||
if (["signature", "stamp", "initials", "image"].includes(position.type)) {
|
|
||||||
if (
|
if (
|
||||||
(position.ImageType && position.ImageType === "image/png") ||
|
["signature", "stamp", "initials", "image"].includes(position.type)
|
||||||
position.ImageType === "image/jpeg"
|
|
||||||
) {
|
) {
|
||||||
img = await pdfDoc.embedJpg(images[id]);
|
if (images[id].mimetype === "image/png") {
|
||||||
|
img = await pdfDoc.embedPng(images[id].arrayBuffer);
|
||||||
} else {
|
} else {
|
||||||
img = await pdfDoc.embedPng(images[id]);
|
img = await pdfDoc.embedJpg(images[id].arrayBuffer);
|
||||||
}
|
}
|
||||||
} else if (!position.type) {
|
} else if (!position.type) {
|
||||||
if (
|
// to handle old widget when only stamp and signature are exists
|
||||||
(position.ImageType && position.ImageType === "image/png") ||
|
if (images[id].mimetype === "image/png") {
|
||||||
position.ImageType === "image/jpeg"
|
img = await pdfDoc.embedPng(images[id].arrayBuffer);
|
||||||
) {
|
|
||||||
img = await pdfDoc.embedJpg(images[id]);
|
|
||||||
} else {
|
} else {
|
||||||
img = await pdfDoc.embedPng(images[id]);
|
img = await pdfDoc.embedJpg(images[id].arrayBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let widgetWidth, widgetHeight;
|
let widgetWidth, widgetHeight;
|
||||||
@@ -1411,12 +1423,22 @@ export const multiSignEmbed = async (
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return resizePos;
|
const WidgetsTypeTextExist = [
|
||||||
|
textWidget,
|
||||||
|
textInputWidget,
|
||||||
|
"name",
|
||||||
|
"company",
|
||||||
|
"job title",
|
||||||
|
"date",
|
||||||
|
"email"
|
||||||
|
].includes(position.type);
|
||||||
|
const yPosition = WidgetsTypeTextExist ? resizePos + 6 : resizePos;
|
||||||
|
return yPosition;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const color = position?.options?.fontColor;
|
const color = position?.options?.fontColor;
|
||||||
const updateColorInRgb = getWidgetsFontColor(color);
|
const updateColorInRgb = getWidgetsFontColor(color);
|
||||||
const fontSize = parseInt(position?.options?.fontSize || 13);
|
const fontSize = parseInt(position?.options?.fontSize || 12);
|
||||||
const widgetTypeExist = [
|
const widgetTypeExist = [
|
||||||
textWidget,
|
textWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
@@ -1435,7 +1457,6 @@ export const multiSignEmbed = async (
|
|||||||
if (position?.options?.values.length > 0) {
|
if (position?.options?.values.length > 0) {
|
||||||
position?.options?.values.forEach((item, ind) => {
|
position?.options?.values.forEach((item, ind) => {
|
||||||
const checkboxRandomId = "checkbox" + randomId();
|
const checkboxRandomId = "checkbox" + randomId();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
position?.options?.response &&
|
position?.options?.response &&
|
||||||
position?.options?.response?.length > 0
|
position?.options?.response?.length > 0
|
||||||
@@ -1487,12 +1508,6 @@ export const multiSignEmbed = async (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (widgetTypeExist) {
|
} else if (widgetTypeExist) {
|
||||||
const fontSize = calculateFontSize(
|
|
||||||
position,
|
|
||||||
containerScale,
|
|
||||||
signyourself
|
|
||||||
);
|
|
||||||
parseInt(fontSize);
|
|
||||||
let textContent;
|
let textContent;
|
||||||
if (position?.options?.response) {
|
if (position?.options?.response) {
|
||||||
textContent = position.options?.response;
|
textContent = position.options?.response;
|
||||||
@@ -1524,11 +1539,9 @@ export const multiSignEmbed = async (
|
|||||||
lines.push(currentLine.trim());
|
lines.push(currentLine.trim());
|
||||||
return lines;
|
return lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to break text into lines based on when user go next line on press enter button
|
// Function to break text into lines based on when user go next line on press enter button
|
||||||
const breakTextIntoLines = (textContent, width) => {
|
const breakTextIntoLines = (textContent, width) => {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
|
|
||||||
for (const word of textContent.split("\n")) {
|
for (const word of textContent.split("\n")) {
|
||||||
const lineWidth = font.widthOfTextAtSize(`${word}`, fontSize);
|
const lineWidth = font.widthOfTextAtSize(`${word}`, fontSize);
|
||||||
//checking string length to container width
|
//checking string length to container width
|
||||||
@@ -1545,7 +1558,6 @@ export const multiSignEmbed = async (
|
|||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
//check if text content have `\n` string it means user press enter to go next line and handle condition
|
//check if text content have `\n` string it means user press enter to go next line and handle condition
|
||||||
//else auto adjust text content according to container width
|
//else auto adjust text content according to container width
|
||||||
const lines = isNewOnEnterLineExist
|
const lines = isNewOnEnterLineExist
|
||||||
@@ -1571,8 +1583,6 @@ export const multiSignEmbed = async (
|
|||||||
y += 18; // Adjust the line height as needed
|
y += 18; // Adjust the line height as needed
|
||||||
}
|
}
|
||||||
} else if (position.type === "dropdown") {
|
} else if (position.type === "dropdown") {
|
||||||
const fontsize = parseInt(position?.options?.fontSize) || 12;
|
|
||||||
|
|
||||||
const dropdownRandomId = "dropdown" + randomId();
|
const dropdownRandomId = "dropdown" + randomId();
|
||||||
const dropdown = form.createDropdown(dropdownRandomId);
|
const dropdown = form.createDropdown(dropdownRandomId);
|
||||||
dropdown.addOptions(position?.options?.values);
|
dropdown.addOptions(position?.options?.values);
|
||||||
@@ -1587,10 +1597,10 @@ export const multiSignEmbed = async (
|
|||||||
// - `FontSize` is the size you want to set (e.g., 12)
|
// - `FontSize` is the size you want to set (e.g., 12)
|
||||||
// - `Tf` specifies the font and size
|
// - `Tf` specifies the font and size
|
||||||
// - `0 g` sets the text color to black
|
// - `0 g` sets the text color to black
|
||||||
const defaultAppearance = `/Helv ${fontsize} Tf 0 g`;
|
const defaultAppearance = `/Helv ${fontSize} Tf 0 g`;
|
||||||
// Set the default appearance for the dropdown field
|
// Set the default appearance for the dropdown field
|
||||||
dropdown.acroField.setDefaultAppearance(defaultAppearance);
|
dropdown.acroField.setDefaultAppearance(defaultAppearance);
|
||||||
dropdown.setFontSize(fontsize);
|
dropdown.setFontSize(fontSize);
|
||||||
const dropdownObj = {
|
const dropdownObj = {
|
||||||
x: xPos(position),
|
x: xPos(position),
|
||||||
y: yPos(position),
|
y: yPos(position),
|
||||||
@@ -1662,11 +1672,22 @@ export const multiSignEmbed = async (
|
|||||||
const imageOptions = getWidgetPosition(page, signature, 1);
|
const imageOptions = getWidgetPosition(page, signature, 1);
|
||||||
page.drawImage(img, imageOptions);
|
page.drawImage(img, imageOptions);
|
||||||
}
|
}
|
||||||
});
|
} catch (err) {
|
||||||
|
console.log("Err in embed widget on page ", pageNo, err?.message);
|
||||||
|
hasError = true; // Set the flag to stop both loops
|
||||||
|
break; // Exit inner loop
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasError) {
|
||||||
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
||||||
//console.log("pdf", pdfBytes);
|
|
||||||
return pdfBytes;
|
return pdfBytes;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
error:
|
||||||
|
"This pdf is not compatible with opensign please contact <support@opensignlabs.com>"
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// function for validating URLs
|
// function for validating URLs
|
||||||
@@ -1742,14 +1763,17 @@ export const contactBook = async (objectId) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//function for getting document details from contract_Documents class
|
//function for getting document details from contract_Documents class
|
||||||
export const contractDocument = async (documentId) => {
|
export const contractDocument = async (documentId, JwtToken) => {
|
||||||
const data = { docId: documentId };
|
const data = { docId: documentId };
|
||||||
|
const token = JwtToken
|
||||||
|
? { jwtToken: JwtToken }
|
||||||
|
: { sessionToken: localStorage.getItem("accesstoken") };
|
||||||
const documentDeatils = await axios
|
const documentDeatils = await axios
|
||||||
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
|
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
...token
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((Listdata) => {
|
.then((Listdata) => {
|
||||||
@@ -1865,12 +1889,16 @@ export const handleCopyNextToWidget = (
|
|||||||
//get position of previous widget and create new widget next to that widget on same data except
|
//get position of previous widget and create new widget next to that widget on same data except
|
||||||
// xPosition and key
|
// xPosition and key
|
||||||
let newposition = position;
|
let newposition = position;
|
||||||
const calculateXPosition =
|
const calculateXPosition = parseInt(position.xPosition) + 10;
|
||||||
parseInt(position.xPosition) +
|
const calculateYPosition = parseInt(position.yPosition) + 10;
|
||||||
defaultWidthHeight(widgetType).width +
|
|
||||||
resizeBorderExtraWidth();
|
|
||||||
const newId = randomId();
|
const newId = randomId();
|
||||||
newposition = { ...newposition, xPosition: calculateXPosition, key: newId };
|
newposition = {
|
||||||
|
...newposition,
|
||||||
|
xPosition: calculateXPosition,
|
||||||
|
yPosition: calculateYPosition,
|
||||||
|
key: newId
|
||||||
|
};
|
||||||
//if condition to create widget in request-sign flow
|
//if condition to create widget in request-sign flow
|
||||||
if (userId) {
|
if (userId) {
|
||||||
filterSignerPos = xyPostion.filter((data) => data.Id === userId);
|
filterSignerPos = xyPostion.filter((data) => data.Id === userId);
|
||||||
@@ -1936,25 +1964,37 @@ export const getAppLogo = async () => {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in getlogo ", err);
|
console.log("err in getlogo ", err);
|
||||||
|
if (err?.message?.includes("valid JSON")) {
|
||||||
|
return { logo: appInfo.applogo, user: "exist", error: "invalid_json" };
|
||||||
|
} else {
|
||||||
return { logo: appInfo.applogo, user: "exist" };
|
return { logo: appInfo.applogo, user: "exist" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTenantDetails = async (objectId) => {
|
export const getTenantDetails = async (objectId, jwttoken, contactId) => {
|
||||||
try {
|
try {
|
||||||
const tenantCreditsQuery = new Parse.Query("partners_Tenant");
|
const url = `${localStorage.getItem("baseUrl")}functions/gettenant`;
|
||||||
tenantCreditsQuery.equalTo("UserId", {
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
__type: "Pointer",
|
const accesstoken = localStorage.getItem("accesstoken");
|
||||||
className: "_User",
|
const token = jwttoken
|
||||||
objectId: objectId
|
? { jwttoken: jwttoken }
|
||||||
|
: { "X-Parse-Session-Token": accesstoken };
|
||||||
|
const data = jwttoken ? {} : { userId: objectId, contactId: contactId };
|
||||||
|
const res = await axios.post(url, data, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": parseAppId,
|
||||||
|
...token
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const res = await tenantCreditsQuery.first();
|
|
||||||
if (res) {
|
if (res) {
|
||||||
const updateRes = JSON.parse(JSON.stringify(res));
|
const updateRes = JSON.parse(JSON.stringify(res.data.result));
|
||||||
return updateRes;
|
return updateRes;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (err) {
|
||||||
|
console.log("err in gettenant", err);
|
||||||
return "user does not exist!";
|
return "user does not exist!";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2039,11 +2079,21 @@ export const fetchUrl = async (url, pdfName) => {
|
|||||||
console.error("Error downloading the file:", error);
|
console.error("Error downloading the file:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const getSignedUrl = async (pdfUrl, docId) => {
|
export const getSignedUrl = async (
|
||||||
|
pdfUrl,
|
||||||
|
docId,
|
||||||
|
fileAdapterId,
|
||||||
|
templateId
|
||||||
|
) => {
|
||||||
//use only axios here due to public template sign
|
//use only axios here due to public template sign
|
||||||
const axiosRes = await axios.post(
|
const axiosRes = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
{ url: pdfUrl, docId: docId || "" },
|
{
|
||||||
|
url: pdfUrl,
|
||||||
|
docId: docId || "",
|
||||||
|
fileAdapterId: fileAdapterId,
|
||||||
|
templateId: templateId || ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "Application/json",
|
"content-type": "Application/json",
|
||||||
@@ -2060,9 +2110,12 @@ export const handleDownloadPdf = async (pdfDetails, setIsDownloading) => {
|
|||||||
const pdfName = pdfDetails[0] && pdfDetails[0]?.Name;
|
const pdfName = pdfDetails[0] && pdfDetails[0]?.Name;
|
||||||
const pdfUrl = pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL;
|
const pdfUrl = pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL;
|
||||||
setIsDownloading && setIsDownloading("pdf");
|
setIsDownloading && setIsDownloading("pdf");
|
||||||
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
|
const docId = pdfDetails?.[0]?.objectId || "";
|
||||||
|
const fileAdapterId = pdfDetails?.[0]?.FileAdapterId
|
||||||
|
? pdfDetails?.[0]?.FileAdapterId
|
||||||
|
: "";
|
||||||
try {
|
try {
|
||||||
const url = await getSignedUrl(pdfUrl, docId);
|
const url = await getSignedUrl(pdfUrl, docId, fileAdapterId);
|
||||||
await fetchUrl(url, pdfName);
|
await fetchUrl(url, pdfName);
|
||||||
setIsDownloading && setIsDownloading("");
|
setIsDownloading && setIsDownloading("");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -2085,14 +2138,17 @@ export const handleToPrint = async (
|
|||||||
) => {
|
) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setIsDownloading("pdf");
|
setIsDownloading("pdf");
|
||||||
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
|
const docId = pdfDetails?.[0]?.objectId || "";
|
||||||
|
const FileAdapterId = pdfDetails?.[0]?.FileAdapterId
|
||||||
|
? pdfDetails?.[0]?.FileAdapterId
|
||||||
|
: "";
|
||||||
try {
|
try {
|
||||||
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
|
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
|
||||||
//`localStorage.getItem("baseUrl")` is also use in public-profile flow for public-sign
|
//`localStorage.getItem("baseUrl")` is also use in public-profile flow for public-sign
|
||||||
//if we give this `appInfo.baseUrl` as a base url then in public-profile it will create base url of it's window.location.origin ex- opensign.me which is not base url
|
//if we give this `appInfo.baseUrl` as a base url then in public-profile it will create base url of it's window.location.origin ex- opensign.me which is not base url
|
||||||
const axiosRes = await axios.post(
|
const axiosRes = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
{ url: pdfUrl, docId: docId },
|
{ url: pdfUrl, docId: docId, fileAdapterId: FileAdapterId },
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "Application/json",
|
"content-type": "Application/json",
|
||||||
@@ -2187,18 +2243,21 @@ export const handleDownloadCertificate = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export async function findContact(value) {
|
export async function findContact(value, jwttoken) {
|
||||||
try {
|
try {
|
||||||
const currentUser = Parse.User.current();
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
const contactbook = new Parse.Query("contracts_Contactbook");
|
const url = `${baseURL}functions/getsigners`;
|
||||||
contactbook.equalTo(
|
const token = jwttoken
|
||||||
"CreatedBy",
|
? { jwttoken: jwttoken }
|
||||||
Parse.User.createWithoutData(currentUser.id)
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
);
|
const headers = {
|
||||||
contactbook.notEqualTo("IsDeleted", true);
|
"Content-Type": "application/json",
|
||||||
contactbook.matches("Email", new RegExp(value, "i"));
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
...token
|
||||||
const contactRes = await contactbook.find();
|
};
|
||||||
|
const searchEmail = value;
|
||||||
|
const axiosRes = await axios.post(url, { searchEmail }, { headers });
|
||||||
|
const contactRes = axiosRes?.data?.result || [];
|
||||||
if (contactRes) {
|
if (contactRes) {
|
||||||
const res = JSON.parse(JSON.stringify(contactRes));
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
return res;
|
return res;
|
||||||
@@ -2366,23 +2425,9 @@ export const getDefaultSignature = async (objectId) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//function to rotate pdf page
|
//function to rotate pdf page
|
||||||
export async function rotatePdfPage(
|
export async function rotatePdfPage(rotateDegree, pageNumber, pdfArrayBuffer) {
|
||||||
url,
|
|
||||||
rotateDegree,
|
|
||||||
pageNumber,
|
|
||||||
pdfRotateBase64
|
|
||||||
) {
|
|
||||||
let file;
|
|
||||||
|
|
||||||
//condition to handle pdf base64 in arrayBuffer format
|
|
||||||
if (pdfRotateBase64) {
|
|
||||||
file = base64ToArrayBuffer(pdfRotateBase64);
|
|
||||||
} else {
|
|
||||||
//condition to handle pdf url in arrayBuffer format
|
|
||||||
file = await convertPdfArrayBuffer(url);
|
|
||||||
}
|
|
||||||
// Load the existing PDF
|
// Load the existing PDF
|
||||||
const pdfDoc = await PDFDocument.load(file);
|
const pdfDoc = await PDFDocument.load(pdfArrayBuffer);
|
||||||
// Get the page according to page number
|
// Get the page according to page number
|
||||||
const page = pdfDoc.getPage(pageNumber);
|
const page = pdfDoc.getPage(pageNumber);
|
||||||
//get current page rotation angle
|
//get current page rotation angle
|
||||||
@@ -2448,21 +2493,35 @@ export const handleRemoveWidgets = (
|
|||||||
setSignerPos,
|
setSignerPos,
|
||||||
signerPos,
|
signerPos,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
|
userId,
|
||||||
setIsRotate
|
setIsRotate
|
||||||
) => {
|
) => {
|
||||||
|
const isSigners = signerPos.some((data) => data.signerPtr);
|
||||||
|
if (isSigners) {
|
||||||
const updatedSignerPos = signerPos.map((placeholderObj) => {
|
const updatedSignerPos = signerPos.map((placeholderObj) => {
|
||||||
|
if (placeholderObj.Id === userId) {
|
||||||
return {
|
return {
|
||||||
...placeholderObj,
|
...placeholderObj,
|
||||||
placeHolder: placeholderObj?.placeHolder?.filter(
|
placeHolder: placeholderObj?.placeHolder?.filter(
|
||||||
(data) => data?.pageNumber !== pageNumber
|
(data) => data?.pageNumber !== pageNumber
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return placeholderObj;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
setSignerPos(updatedSignerPos);
|
setSignerPos(updatedSignerPos);
|
||||||
|
setIsRotate &&
|
||||||
setIsRotate({
|
setIsRotate({
|
||||||
status: false,
|
status: false,
|
||||||
degree: 0
|
degree: 0
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const updatedSignerPos = signerPos.filter(
|
||||||
|
(data) => data?.pageNumber !== pageNumber
|
||||||
|
);
|
||||||
|
setSignerPos(updatedSignerPos);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//function to show warning when user rotate page and there are some already widgets on that page
|
//function to show warning when user rotate page and there are some already widgets on that page
|
||||||
export const handleRotateWarning = (signerPos, pageNumber) => {
|
export const handleRotateWarning = (signerPos, pageNumber) => {
|
||||||
@@ -2517,3 +2576,57 @@ export function generateTitleFromFilename(filename) {
|
|||||||
return "Untitled Document";
|
return "Untitled Document";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const signatureTypes = [
|
||||||
|
{ name: "draw", enabled: true },
|
||||||
|
{ name: "typed", enabled: true },
|
||||||
|
{ name: "upload", enabled: true },
|
||||||
|
{ name: "default", enabled: true }
|
||||||
|
];
|
||||||
|
|
||||||
|
// `handleSignatureType` is used to return update signature types as per tenant or user
|
||||||
|
export async function handleSignatureType(tenantSignTypes, signatureType) {
|
||||||
|
const docSignTypes = signatureType || signatureTypes;
|
||||||
|
let updatedSignatureType = signatureType || signatureTypes;
|
||||||
|
if (tenantSignTypes?.length > 0) {
|
||||||
|
updatedSignatureType = tenantSignTypes?.map((item) => {
|
||||||
|
const match = docSignTypes.find((data) => data.name === item.name);
|
||||||
|
return match ? { ...item, enabled: match.enabled } : item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return updatedSignatureType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `formatDate` is used to format date to dd-mmm-yyy
|
||||||
|
export const formatDate = (date) => {
|
||||||
|
// Create a Date object
|
||||||
|
const newDate = new Date(date);
|
||||||
|
// Format the date
|
||||||
|
const formattedDate = newDate.toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "short",
|
||||||
|
year: "numeric"
|
||||||
|
});
|
||||||
|
const format = formattedDate.replaceAll(/ /g, "-");
|
||||||
|
return format;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deletePdfPage = async (pdfArrayBuffer, pageNumber) => {
|
||||||
|
// Load the existing PDF
|
||||||
|
const pdfDoc = await PDFDocument.load(pdfArrayBuffer);
|
||||||
|
// Get the total number of pages
|
||||||
|
const totalPages = pdfDoc.getPageCount();
|
||||||
|
// Ensure the page index is valid
|
||||||
|
if (totalPages > 1) {
|
||||||
|
//Remove the specified page
|
||||||
|
pdfDoc.removePage(pageNumber - 1);
|
||||||
|
// Save the modified PDF
|
||||||
|
const modifiedPdfBytes = await pdfDoc.saveAsBase64({
|
||||||
|
useObjectStreams: false
|
||||||
|
});
|
||||||
|
const arrayBuffer = base64ToArrayBuffer(modifiedPdfBytes);
|
||||||
|
return { arrayBuffer: arrayBuffer, base64: modifiedPdfBytes };
|
||||||
|
} else {
|
||||||
|
return { totalPages: 1 };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ i18n
|
|||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false // Not needed for react as it escapes by default
|
escapeValue: false // Not needed for react as it escapes by default
|
||||||
},
|
},
|
||||||
whitelist: ["en", "fr"] // List of allowed languages
|
whitelist: ["en", "es", "fr"] // List of allowed languages
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
|||||||
@@ -2,43 +2,34 @@ import { isEnableSubscription } from "../constant/const";
|
|||||||
|
|
||||||
export default function reportJson(id) {
|
export default function reportJson(id) {
|
||||||
// console.log("json ", json);
|
// console.log("json ", json);
|
||||||
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
const head = ["Title", "Note", "Folder", "File", "Owner", "Signers"];
|
||||||
const declineHead = [
|
const declineHead = ["Title", "Reason", "Folder", "File", "Owner", "Signers"];
|
||||||
"Sr.No",
|
const iphead = ["Title", "Note", "Folder", "File", "Signers"];
|
||||||
"Title",
|
const contactbook = ["Name", "Email", "Phone"];
|
||||||
"Reason",
|
|
||||||
"Folder",
|
|
||||||
"File",
|
|
||||||
"Owner",
|
|
||||||
"Signers"
|
|
||||||
];
|
|
||||||
const iphead = [
|
|
||||||
"Sr.No",
|
|
||||||
"Title",
|
|
||||||
"Note",
|
|
||||||
"Folder",
|
|
||||||
"File",
|
|
||||||
"Status",
|
|
||||||
"Signers"
|
|
||||||
];
|
|
||||||
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
|
||||||
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
||||||
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
|
const templateReport = ["Title", "File", "Owner", "Signers"];
|
||||||
const templateSubAction = isEnableSubscription
|
const templateSubAction = isEnableSubscription
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
btnId: "2434",
|
btnId: "2435",
|
||||||
btnLabel: "Embed",
|
btnLabel: "Embed",
|
||||||
hoverLabel: "Embed",
|
hoverLabel: "Embed",
|
||||||
btnIcon: "fa-light fa-code",
|
btnIcon: "fa-light fa-code",
|
||||||
action: "Embed"
|
action: "Embed"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
btnId: "2434",
|
btnId: "2436",
|
||||||
btnLabel: "Copy TemplateId",
|
btnLabel: "Copy TemplateId",
|
||||||
hoverLabel: "Copy TemplateId",
|
hoverLabel: "Copy TemplateId",
|
||||||
btnIcon: "fa-light fa-copy",
|
btnIcon: "fa-light fa-copy",
|
||||||
action: "CopyTemplateId"
|
action: "CopyTemplateId"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2437",
|
||||||
|
btnLabel: "Copy Public URL",
|
||||||
|
hoverLabel: "Copy Public URL",
|
||||||
|
btnIcon: "fa-light fa-copy",
|
||||||
|
action: "CopyPublicURL"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
@@ -221,6 +212,25 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-light fa-trash",
|
btnIcon: "fa-light fa-trash",
|
||||||
redirectUrl: "",
|
redirectUrl: "",
|
||||||
action: "delete"
|
action: "delete"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "3234",
|
||||||
|
hoverLabel: "option",
|
||||||
|
btnColor: "",
|
||||||
|
textColor: "black",
|
||||||
|
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
|
||||||
|
action: "option",
|
||||||
|
subaction: [
|
||||||
|
{
|
||||||
|
btnId: "2199",
|
||||||
|
btnLabel: "extend-expiry-date",
|
||||||
|
hoverLabel: "Extend expiry date",
|
||||||
|
btnColor: "op-btn-primary",
|
||||||
|
btnIcon: "fa-light fa-hourglass-end",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "extendexpiry"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg:
|
helpMsg:
|
||||||
@@ -405,18 +415,15 @@ export default function reportJson(id) {
|
|||||||
if (item.action === "option") {
|
if (item.action === "option") {
|
||||||
// Make a shallow copy of the item
|
// Make a shallow copy of the item
|
||||||
const newItem = { ...item };
|
const newItem = { ...item };
|
||||||
newItem.subaction = [
|
//splice method used to add `Share with team` option on second index of list
|
||||||
{
|
newItem.subaction.splice(1, 0, {
|
||||||
btnId: "1873",
|
btnId: "1873",
|
||||||
btnLabel: "Share with team",
|
btnLabel: "Share with team",
|
||||||
hoverLabel: "Share with team",
|
hoverLabel: "Share with team",
|
||||||
btnIcon: "fa-light fa-share-nodes",
|
btnIcon: "fa-light fa-share-nodes",
|
||||||
redirectUrl: "",
|
redirectUrl: "",
|
||||||
action: "sharewith"
|
action: "sharewith"
|
||||||
},
|
});
|
||||||
...newItem.subaction
|
|
||||||
];
|
|
||||||
|
|
||||||
return newItem;
|
return newItem;
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
|
|||||||
@@ -154,6 +154,14 @@ const sidebarList = [
|
|||||||
pageType: "",
|
pageType: "",
|
||||||
description: "",
|
description: "",
|
||||||
objectId: "webhook"
|
objectId: "webhook"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "fa-light fa-sliders",
|
||||||
|
title: "Preferences",
|
||||||
|
target: "_self",
|
||||||
|
pageType: "",
|
||||||
|
description: "",
|
||||||
|
objectId: "preferences"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,18 @@ const plans = [
|
|||||||
"Unlimited digital signatures",
|
"Unlimited digital signatures",
|
||||||
"Sign documents yourself",
|
"Sign documents yourself",
|
||||||
"Request signatures from others",
|
"Request signatures from others",
|
||||||
|
"Unlimited templates",
|
||||||
"14 field types",
|
"14 field types",
|
||||||
"Automatic e-signatures",
|
"Automatic e-signatures",
|
||||||
"Completion certificates",
|
"Completion certificates",
|
||||||
"Send in order",
|
"Send in order",
|
||||||
|
"Organize docs in OpenSign™ Drive",
|
||||||
"Document templates",
|
"Document templates",
|
||||||
"Import from Dropbox",
|
"Import from Dropbox",
|
||||||
"Contact book",
|
"Contact book",
|
||||||
"Document expiry support",
|
"Document expiry support",
|
||||||
"Decline document support",
|
"Decline document support",
|
||||||
"Email notifications",
|
"Email notifications",
|
||||||
"Recipient authentication using OTP",
|
|
||||||
"Public profiles",
|
"Public profiles",
|
||||||
"And much more"
|
"And much more"
|
||||||
],
|
],
|
||||||
@@ -34,17 +35,18 @@ const plans = [
|
|||||||
"Unlimited digital signatures",
|
"Unlimited digital signatures",
|
||||||
"Sign documents yourself",
|
"Sign documents yourself",
|
||||||
"Request signatures from others",
|
"Request signatures from others",
|
||||||
|
"Unlimited templates",
|
||||||
"14 field types",
|
"14 field types",
|
||||||
"Automatic e-signatures",
|
"Automatic e-signatures",
|
||||||
"Completion certificates",
|
"Completion certificates",
|
||||||
"Send in order",
|
"Send in order",
|
||||||
|
"Organize docs in OpenSign™ Drive",
|
||||||
"Document templates",
|
"Document templates",
|
||||||
"Import from Dropbox",
|
"Import from Dropbox",
|
||||||
"Contact book",
|
"Contact book",
|
||||||
"Document expiry support",
|
"Document expiry support",
|
||||||
"Decline document support",
|
"Decline document support",
|
||||||
"Email notifications",
|
"Email notifications",
|
||||||
"Recipient authentication using OTP",
|
|
||||||
"Public profiles",
|
"Public profiles",
|
||||||
"And much more"
|
"And much more"
|
||||||
]
|
]
|
||||||
@@ -61,10 +63,10 @@ const plans = [
|
|||||||
subtitle: "Exclusive Access to advanced features.",
|
subtitle: "Exclusive Access to advanced features.",
|
||||||
btn: { text: "Subscribe", color: "op-btn-primary" },
|
btn: { text: "Subscribe", color: "op-btn-primary" },
|
||||||
url: isStaging
|
url: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328dd84ecda20eeae13878ce581d60240f206/pro-weekly"
|
? "https://billing.zohosecure.in/subscribe/9627f62a09df1c8ce500f2f4dc8328dd84ecda20eeae13878ce581d60240f206/pro-weekly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
|
||||||
yearlyUrl: isStaging
|
yearlyUrl: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328ddc184411129224f1f29ed84f6cef3b862/pro-yearly"
|
? "https://billing.zohosecure.in/subscribe/9627f62a09df1c8ce500f2f4dc8328ddc184411129224f1f29ed84f6cef3b862/pro-yearly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
|
||||||
target: "_self",
|
target: "_self",
|
||||||
benefits: [
|
benefits: [
|
||||||
@@ -77,10 +79,12 @@ const plans = [
|
|||||||
"API Access",
|
"API Access",
|
||||||
"upto 100 API signatures",
|
"upto 100 API signatures",
|
||||||
"Custom email templates",
|
"Custom email templates",
|
||||||
|
"Connect your own Gmail or SMTP account for sending emails",
|
||||||
"Auto reminders",
|
"Auto reminders",
|
||||||
"Bulk send (upto 100 docs)",
|
"Bulk send (upto 100 docs)",
|
||||||
"Premium Public profile usernames",
|
"Premium Public profile usernames",
|
||||||
"Embedding (coming soon)"
|
"Enforce email-based verification to confirm signer identity",
|
||||||
|
"Embedded signing"
|
||||||
],
|
],
|
||||||
yearlyBenefits: [
|
yearlyBenefits: [
|
||||||
"Everything in OpenSign™ free",
|
"Everything in OpenSign™ free",
|
||||||
@@ -92,10 +96,12 @@ const plans = [
|
|||||||
"API Access",
|
"API Access",
|
||||||
"upto 240 API signatures",
|
"upto 240 API signatures",
|
||||||
"Custom email templates",
|
"Custom email templates",
|
||||||
|
"Connect your own Gmail or SMTP account for sending emails",
|
||||||
"Auto reminders",
|
"Auto reminders",
|
||||||
"Bulk send (upto 240 docs)",
|
"Bulk send (upto 240 docs)",
|
||||||
"Premium Public profile usernames",
|
"Premium Public profile usernames",
|
||||||
"Embedding (coming soon)"
|
"Enforce email-based verification to confirm signer identity",
|
||||||
|
"Embedded signing"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -108,10 +114,10 @@ const plans = [
|
|||||||
subtitle: "Exclusive Access to advanced features.",
|
subtitle: "Exclusive Access to advanced features.",
|
||||||
btn: { text: "Subscribe", color: "op-btn-accent" },
|
btn: { text: "Subscribe", color: "op-btn-accent" },
|
||||||
url: isStaging
|
url: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
||||||
yearlyUrl: isStaging
|
yearlyUrl: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly",
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly",
|
||||||
target: "_self",
|
target: "_self",
|
||||||
benefits: [
|
benefits: [
|
||||||
@@ -120,6 +126,7 @@ const plans = [
|
|||||||
"Teams and Organizations",
|
"Teams and Organizations",
|
||||||
"Share Templates with teams",
|
"Share Templates with teams",
|
||||||
"Share Templates with individuals",
|
"Share Templates with individuals",
|
||||||
|
"BYOC - Store your documents in your own cloud storage",
|
||||||
"DocumentId removal from signed docs",
|
"DocumentId removal from signed docs",
|
||||||
"Bulk send (upto 100 docs)",
|
"Bulk send (upto 100 docs)",
|
||||||
"Request Payments (coming soon)",
|
"Request Payments (coming soon)",
|
||||||
@@ -131,6 +138,7 @@ const plans = [
|
|||||||
"Teams and Organizations",
|
"Teams and Organizations",
|
||||||
"Share Templates with teams",
|
"Share Templates with teams",
|
||||||
"Share Templates with individuals",
|
"Share Templates with individuals",
|
||||||
|
"BYOC - Store your documents in your own cloud storage",
|
||||||
"DocumentId removal from signed docs",
|
"DocumentId removal from signed docs",
|
||||||
"Bulk send (upto 500 docs)",
|
"Bulk send (upto 500 docs)",
|
||||||
"Request Payments (coming soon)",
|
"Request Payments (coming soon)",
|
||||||
@@ -231,10 +239,10 @@ export const paidUrl = (plan) => {
|
|||||||
}
|
}
|
||||||
const url = {
|
const url = {
|
||||||
monthly: isStaging
|
monthly: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
||||||
yearly: isStaging
|
yearly: isStaging
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly"
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -224,23 +224,13 @@ const HomeLayout = () => {
|
|||||||
|
|
||||||
async function checkTourStatus() {
|
async function checkTourStatus() {
|
||||||
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
||||||
const res = { data: cloudRes.toJSON() };
|
if (cloudRes) {
|
||||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
const extUser = JSON.parse(JSON.stringify(cloudRes));
|
||||||
const tourStatus = res.data.TourStatus;
|
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
|
||||||
// console.log("res ", res.data.TourStatus);
|
const tourStatus = extUser?.TourStatus || [];
|
||||||
setTourStatusArr(tourStatus);
|
setTourStatusArr(tourStatus);
|
||||||
const filteredtourStatus = tourStatus.filter((obj) => obj["loginTour"]);
|
const loginTour = tourStatus.find((obj) => obj.loginTour)?.loginTour;
|
||||||
if (filteredtourStatus.length > 0) {
|
setIsTour(!loginTour);
|
||||||
const loginTour = filteredtourStatus[0]["loginTour"];
|
|
||||||
// console.log("loginTour", loginTour);
|
|
||||||
if (loginTour) {
|
|
||||||
setIsTour(false);
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setIsTour(true);
|
setIsTour(true);
|
||||||
}
|
}
|
||||||
@@ -265,7 +255,9 @@ const HomeLayout = () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="sticky top-0 z-[501]">
|
<div className="sticky top-0 z-[501]">
|
||||||
{!isLoader && <Header showSidebar={showSidebar} />}
|
{!isLoader && (
|
||||||
|
<Header showSidebar={showSidebar} setIsMenu={setIsOpen} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isUserValid ? (
|
{isUserValid ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { showTenant } from "../redux/reducers/ShowTenant";
|
|||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { emailRegex } from "../constant/const";
|
||||||
|
|
||||||
const AddAdmin = () => {
|
const AddAdmin = () => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
@@ -45,8 +46,10 @@ const AddAdmin = () => {
|
|||||||
setState((prev) => ({ ...prev, loading: true }));
|
setState((prev) => ({ ...prev, loading: true }));
|
||||||
try {
|
try {
|
||||||
const app = await getAppLogo();
|
const app = await getAppLogo();
|
||||||
if (app?.user === "exist") {
|
if (app?.error === "invalid_json") {
|
||||||
setErrMsg(t("admin-already-exist"));
|
setErrMsg(t("server-down"));
|
||||||
|
} else if (app?.user === "exist") {
|
||||||
|
setErrMsg(t("admin-exists"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrMsg(t("something-went-wrong-mssg"));
|
setErrMsg(t("something-went-wrong-mssg"));
|
||||||
@@ -82,6 +85,9 @@ const AddAdmin = () => {
|
|||||||
|
|
||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||||
clearStorage();
|
clearStorage();
|
||||||
setState({ loading: true });
|
setState({ loading: true });
|
||||||
@@ -156,6 +162,7 @@ const AddAdmin = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const handleNavigation = async (sessionToken) => {
|
const handleNavigation = async (sessionToken) => {
|
||||||
const res = await Parse.User.become(sessionToken);
|
const res = await Parse.User.become(sessionToken);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Alert from "../primitives/Alert";
|
|||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import { getAppLogo } from "../constant/Utils";
|
import { getAppLogo } from "../constant/Utils";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
@@ -36,6 +36,9 @@ function ForgotPassword() {
|
|||||||
|
|
||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (!emailRegex.test(state.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
localStorage.setItem("appLogo", appInfo.applogo);
|
localStorage.setItem("appLogo", appInfo.applogo);
|
||||||
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
|
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
|
||||||
if (state.email) {
|
if (state.email) {
|
||||||
@@ -50,6 +53,7 @@ function ForgotPassword() {
|
|||||||
setTimeout(() => setSentStatus(""), 1000);
|
setTimeout(() => setSentStatus(""), 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
+570
-95
@@ -67,15 +67,16 @@ const Forms = (props) => {
|
|||||||
file: "",
|
file: "",
|
||||||
remindOnceInEvery: 5,
|
remindOnceInEvery: 5,
|
||||||
autoreminder: false,
|
autoreminder: false,
|
||||||
IsEnableOTP: "false"
|
IsEnableOTP: "false",
|
||||||
|
IsTourEnabled: "false",
|
||||||
|
NotifyOnSignatures: ""
|
||||||
});
|
});
|
||||||
const [fileupload, setFileUpload] = useState("");
|
const [fileupload, setFileUpload] = useState("");
|
||||||
const [fileload, setfileload] = useState(false);
|
const [fileload, setfileload] = useState(false);
|
||||||
const [percentage, setpercentage] = useState(0);
|
const [percentage, setpercentage] = useState(0);
|
||||||
const [isReset, setIsReset] = useState(false);
|
const [isReset, setIsReset] = useState(false);
|
||||||
const [isAlert, setIsAlert] = useState(false);
|
const [isAlert, setIsAlert] = useState({ type: "success", message: "" });
|
||||||
const [isSubmit, setIsSubmit] = useState(false);
|
const [isSubmit, setIsSubmit] = useState(false);
|
||||||
const [isErr, setIsErr] = useState("");
|
|
||||||
const [isPassword, setIsPassword] = useState(false);
|
const [isPassword, setIsPassword] = useState(false);
|
||||||
const [isDecrypting, setIsDecrypting] = useState(false);
|
const [isDecrypting, setIsDecrypting] = useState(false);
|
||||||
const [isCorrectPass, setIsCorrectPass] = useState(true);
|
const [isCorrectPass, setIsCorrectPass] = useState(true);
|
||||||
@@ -85,6 +86,9 @@ const Forms = (props) => {
|
|||||||
setIsCorrectPass(true);
|
setIsCorrectPass(true);
|
||||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
|
const extUserData =
|
||||||
|
localStorage.getItem("Extand_Class") &&
|
||||||
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleReset();
|
handleReset();
|
||||||
return () => abortController.abort();
|
return () => abortController.abort();
|
||||||
@@ -99,21 +103,25 @@ const Forms = (props) => {
|
|||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const subscribe = await checkIsSubscribed();
|
const subscribe = await checkIsSubscribed();
|
||||||
setIsSubscribe(subscribe.isValid);
|
setIsSubscribe(subscribe.isValid);
|
||||||
|
if (subscribe.isValid && extUserData.NotifyOnSignatures !== undefined) {
|
||||||
|
setFormData((obj) => ({
|
||||||
|
...obj,
|
||||||
|
NotifyOnSignatures: extUserData.NotifyOnSignatures
|
||||||
|
}));
|
||||||
|
} else if (subscribe.isValid) {
|
||||||
|
setFormData((obj) => ({ ...obj, NotifyOnSignatures: true }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsSubscribe(true);
|
||||||
|
setFormData((obj) => ({ ...obj, NotifyOnSignatures: true }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFileAsArrayBuffer(file) {
|
function getFileAsArrayBuffer(file) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => resolve(e.target.result);
|
||||||
reader.onload = (e) => {
|
reader.onerror = (e) => reject(e.target.error);
|
||||||
resolve(e.target.result);
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.onerror = (e) => {
|
|
||||||
reject(e.target.error);
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.readAsArrayBuffer(file);
|
reader.readAsArrayBuffer(file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -153,10 +161,7 @@ const Forms = (props) => {
|
|||||||
formData.append("file", files[0]);
|
formData.append("file", files[0]);
|
||||||
formData.append("password", "");
|
formData.append("password", "");
|
||||||
const config = {
|
const config = {
|
||||||
headers: {
|
headers: { "content-type": "multipart/form-data" },
|
||||||
"content-type": "multipart/form-data"
|
|
||||||
// sessiontoken: Parse.User.current().getSessionToken()
|
|
||||||
},
|
|
||||||
responseType: "blob"
|
responseType: "blob"
|
||||||
};
|
};
|
||||||
const response = await axios.post(url, formData, config);
|
const response = await axios.post(url, formData, config);
|
||||||
@@ -168,7 +173,33 @@ const Forms = (props) => {
|
|||||||
});
|
});
|
||||||
setIsDecrypting(false);
|
setIsDecrypting(false);
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
|
const fileAdapterId =
|
||||||
|
extUserData?.TenantId?.ActiveFileAdapter || "";
|
||||||
|
if (fileAdapterId) {
|
||||||
|
const base64 = await toDataUrl(pdfFile);
|
||||||
|
const fileBase64 = base64.split(",").pop();
|
||||||
|
const ext = files?.[0]?.name?.split(".").pop();
|
||||||
|
const fileRes = await saveToCustomFile(
|
||||||
|
fileBase64,
|
||||||
|
`${name}.${ext}`,
|
||||||
|
fileAdapterId
|
||||||
|
);
|
||||||
|
if (fileRes.url) {
|
||||||
|
setFileUpload(fileRes.url);
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, fileRes.url, tenantId);
|
||||||
|
return fileRes.url;
|
||||||
|
} else {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
setFileUpload("");
|
||||||
|
e.target.value = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Upload the file to Parse Server
|
// Upload the file to Parse Server
|
||||||
const parseFile = new Parse.File(
|
const parseFile = new Parse.File(
|
||||||
name,
|
name,
|
||||||
@@ -193,11 +224,11 @@ const Forms = (props) => {
|
|||||||
setfileload(false);
|
setfileload(false);
|
||||||
const title = generateTitleFromFilename(files?.[0]?.name);
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
setFormData((obj) => ({ ...obj, Name: title }));
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
SaveFileSize(size, response.url(), tenantId);
|
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
SaveFileSize(size, parseFile.url(), tenantId);
|
SaveFileSize(size, parseFile.url(), tenantId);
|
||||||
return parseFile.url();
|
return parseFile.url();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
@@ -237,12 +268,41 @@ const Forms = (props) => {
|
|||||||
width: imageWidth,
|
width: imageWidth,
|
||||||
height: imageHeight
|
height: imageHeight
|
||||||
});
|
});
|
||||||
|
const size = files?.[0]?.size;
|
||||||
|
const name = generatePdfName(16);
|
||||||
|
const fileAdapterId =
|
||||||
|
extUserData?.TenantId?.ActiveFileAdapter || "";
|
||||||
|
if (fileAdapterId) {
|
||||||
|
const base64 = await pdfDoc.saveAsBase64({
|
||||||
|
useObjectStreams: false
|
||||||
|
});
|
||||||
|
setfileload(true);
|
||||||
|
const fileBase64 = base64.split(",").pop();
|
||||||
|
const ext = files?.[0]?.name?.split(".").pop();
|
||||||
|
const fileRes = await saveToCustomFile(
|
||||||
|
fileBase64,
|
||||||
|
`${name}.${ext}`,
|
||||||
|
fileAdapterId
|
||||||
|
);
|
||||||
|
if (fileRes.url) {
|
||||||
|
setFileUpload(fileRes.url);
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, fileRes.url, tenantId);
|
||||||
|
return fileRes.url;
|
||||||
|
} else {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
e.target.value = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const getFile = await pdfDoc.save({
|
const getFile = await pdfDoc.save({
|
||||||
useObjectStreams: false
|
useObjectStreams: false
|
||||||
});
|
});
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const size = files[0].size;
|
|
||||||
const name = generatePdfName(16);
|
|
||||||
const pdfName = `${name?.split(".")[0]}.pdf`;
|
const pdfName = `${name?.split(".")[0]}.pdf`;
|
||||||
const parseFile = new Parse.File(
|
const parseFile = new Parse.File(
|
||||||
pdfName,
|
pdfName,
|
||||||
@@ -278,6 +338,7 @@ const Forms = (props) => {
|
|||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
console.error("Error uploading file:", error);
|
console.error("Error uploading file:", error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
try {
|
try {
|
||||||
@@ -322,13 +383,50 @@ const Forms = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveToCustomFile = async (base64, filename, fileAdapterId) => {
|
||||||
|
try {
|
||||||
|
const savetos3 = await Parse.Cloud.run("savetofileadapter", {
|
||||||
|
fileBase64: base64,
|
||||||
|
fileName: filename,
|
||||||
|
id: fileAdapterId
|
||||||
|
});
|
||||||
|
return { url: savetos3.url };
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in save to customfile", err);
|
||||||
|
alert(err?.message);
|
||||||
|
if (inputFileRef.current) {
|
||||||
|
inputFileRef.current.value = ""; // Set file input value to empty string
|
||||||
|
}
|
||||||
|
return { url: "" };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleFileUpload = async (file) => {
|
const handleFileUpload = async (file) => {
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const size = file.size;
|
const size = file.size;
|
||||||
const name = generatePdfName(16);
|
const name = generatePdfName(16);
|
||||||
const pdfFile = file;
|
const pdfFile = file;
|
||||||
|
const fileAdapterId = extUserData?.TenantId?.ActiveFileAdapter || "";
|
||||||
|
if (fileAdapterId) {
|
||||||
|
const base64 = await toDataUrl(file);
|
||||||
|
const fileBase64 = base64.split(",").pop();
|
||||||
|
const ext = file?.name?.split(".").pop();
|
||||||
|
const fileRes = await saveToCustomFile(
|
||||||
|
fileBase64,
|
||||||
|
`${name}.${ext}`,
|
||||||
|
fileAdapterId
|
||||||
|
);
|
||||||
|
if (fileRes.url) {
|
||||||
|
setFileUpload(fileRes?.url);
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
const title = generateTitleFromFilename(file.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
SaveFileSize(size, fileRes.url, tenantId);
|
||||||
|
}
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
} else {
|
||||||
const parseFile = new Parse.File(name, pdfFile);
|
const parseFile = new Parse.File(name, pdfFile);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await parseFile.save({
|
const response = await parseFile.save({
|
||||||
progress: (progressValue, loaded, total, { type }) => {
|
progress: (progressValue, loaded, total, { type }) => {
|
||||||
@@ -355,8 +453,18 @@ const Forms = (props) => {
|
|||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
console.error("Error uploading file:", error);
|
console.error("Error uploading file:", error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
async function uriToBase64(uri) {
|
||||||
|
const response = await fetch(uri);
|
||||||
|
const blob = await response.blob();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => resolve(reader.result);
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(blob); // Convert to Base64
|
||||||
|
});
|
||||||
|
}
|
||||||
const dropboxSuccess = async (files) => {
|
const dropboxSuccess = async (files) => {
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
@@ -371,8 +479,31 @@ const Forms = (props) => {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const name = generatePdfName(16);
|
const name = generatePdfName(16);
|
||||||
|
const fileAdapterId = extUserData?.TenantId?.ActiveFileAdapter || "";
|
||||||
|
if (fileAdapterId) {
|
||||||
|
const base64 = await uriToBase64(url);
|
||||||
|
const fileBase64 = base64.split(",").pop();
|
||||||
|
const ext = file?.name?.split(".").pop();
|
||||||
|
const fileRes = await saveToCustomFile(
|
||||||
|
fileBase64,
|
||||||
|
`${name}.${ext}`,
|
||||||
|
fileAdapterId
|
||||||
|
);
|
||||||
|
if (fileRes.url) {
|
||||||
|
setFileUpload(fileRes.url);
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, fileRes.url, tenantId);
|
||||||
|
return fileRes.url;
|
||||||
|
} else {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const parseFile = new Parse.File(name, { uri: url });
|
const parseFile = new Parse.File(name, { uri: url });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await parseFile.save({
|
const response = await parseFile.save({
|
||||||
progress: (progressValue, loaded, total, { type }) => {
|
progress: (progressValue, loaded, total, { type }) => {
|
||||||
@@ -397,8 +528,8 @@ const Forms = (props) => {
|
|||||||
console.error("Error uploading file:", error);
|
console.error("Error uploading file:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const dropboxCancel = async () => {};
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -418,15 +549,24 @@ const Forms = (props) => {
|
|||||||
}
|
}
|
||||||
if (props.title !== "Sign Yourself") {
|
if (props.title !== "Sign Yourself") {
|
||||||
const isChecked = formData.SendinOrder === "false" ? false : true;
|
const isChecked = formData.SendinOrder === "false" ? false : true;
|
||||||
|
const isTourEnabled =
|
||||||
|
formData?.IsTourEnabled === "false" ? false : true;
|
||||||
object.set("SendinOrder", isChecked);
|
object.set("SendinOrder", isChecked);
|
||||||
object.set("AutomaticReminders", formData.autoreminder);
|
object.set("AutomaticReminders", formData.autoreminder);
|
||||||
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
|
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
|
||||||
|
object.set("IsTourEnabled", isTourEnabled);
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const IsEnableOTP =
|
const IsEnableOTP =
|
||||||
formData?.IsEnableOTP === "false" ? false : true;
|
formData?.IsEnableOTP === "false" ? false : true;
|
||||||
object.set("IsEnableOTP", IsEnableOTP);
|
object.set("IsEnableOTP", IsEnableOTP);
|
||||||
|
if (isSubscribe && formData.NotifyOnSignatures !== undefined) {
|
||||||
|
object.set("NotifyOnSignatures", formData.NotifyOnSignatures);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
object.set("IsEnableOTP", false);
|
object.set("IsEnableOTP", false);
|
||||||
|
if (formData.NotifyOnSignatures !== undefined) {
|
||||||
|
object.set("NotifyOnSignatures", formData.NotifyOnSignatures);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object.set("URL", fileupload);
|
object.set("URL", fileupload);
|
||||||
@@ -447,6 +587,9 @@ const Forms = (props) => {
|
|||||||
className: "contracts_Users",
|
className: "contracts_Users",
|
||||||
objectId: ExtCls[0].objectId
|
objectId: ExtCls[0].objectId
|
||||||
});
|
});
|
||||||
|
if (extUserData?.TenantId?.ActiveFileAdapter) {
|
||||||
|
object.set("FileAdapterId", extUserData?.TenantId?.ActiveFileAdapter);
|
||||||
|
}
|
||||||
const res = await object.save();
|
const res = await object.save();
|
||||||
if (res) {
|
if (res) {
|
||||||
setSigners([]);
|
setSigners([]);
|
||||||
@@ -464,18 +607,23 @@ const Forms = (props) => {
|
|||||||
file: "",
|
file: "",
|
||||||
remindOnceInEvery: 5,
|
remindOnceInEvery: 5,
|
||||||
autoreminder: false,
|
autoreminder: false,
|
||||||
IsEnableOTP: "false"
|
IsEnableOTP: "false",
|
||||||
|
IsTourEnabled: "true"
|
||||||
});
|
});
|
||||||
setFileUpload("");
|
setFileUpload("");
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
navigate(`/${props?.redirectRoute}/${res.id}`);
|
navigate(`/${props?.redirectRoute}/${res.id}`);
|
||||||
|
setIsAlert((obj) => ({
|
||||||
|
...obj,
|
||||||
|
type: "success",
|
||||||
|
message: `${props.msgVar} created successfully!`
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
setIsErr(true);
|
setIsAlert({ type: "danger", message: t("something-went-wrong-mssg") });
|
||||||
} finally {
|
} finally {
|
||||||
setIsAlert(true);
|
setTimeout(() => setIsAlert({ type: "success", message: "" }), 1000);
|
||||||
setTimeout(() => setIsAlert(false), 1000);
|
|
||||||
setIsSubmit(false);
|
setIsSubmit(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -501,7 +649,7 @@ const Forms = (props) => {
|
|||||||
setIsReset(true);
|
setIsReset(true);
|
||||||
setSigners([]);
|
setSigners([]);
|
||||||
setFolder({ ObjectId: "", Name: "" });
|
setFolder({ ObjectId: "", Name: "" });
|
||||||
setFormData({
|
let obj = {
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "",
|
Description: "",
|
||||||
Note:
|
Note:
|
||||||
@@ -514,8 +662,10 @@ const Forms = (props) => {
|
|||||||
file: "",
|
file: "",
|
||||||
remindOnceInEvery: 5,
|
remindOnceInEvery: 5,
|
||||||
autoreminder: false,
|
autoreminder: false,
|
||||||
IsEnableOTP: "false"
|
IsEnableOTP: "false",
|
||||||
});
|
IsTourEnabled: "true"
|
||||||
|
};
|
||||||
|
setFormData(obj);
|
||||||
setFileUpload("");
|
setFileUpload("");
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
setTimeout(() => setIsReset(false), 50);
|
setTimeout(() => setIsReset(false), 50);
|
||||||
@@ -549,9 +699,33 @@ const Forms = (props) => {
|
|||||||
type: "application/pdf"
|
type: "application/pdf"
|
||||||
});
|
});
|
||||||
setIsDecrypting(false);
|
setIsDecrypting(false);
|
||||||
|
const fileAdapterId = extUserData?.TenantId?.ActiveFileAdapter || "";
|
||||||
// Upload the file to Parse Server
|
// Upload the file to Parse Server
|
||||||
|
if (fileAdapterId) {
|
||||||
|
const base64 = await toDataUrl(pdfFile);
|
||||||
|
const fileBase64 = base64.split(",").pop();
|
||||||
|
const ext = formData?.file?.name?.split(".").pop();
|
||||||
|
const fileRes = await saveToCustomFile(
|
||||||
|
fileBase64,
|
||||||
|
`${name}.${ext}`,
|
||||||
|
fileAdapterId
|
||||||
|
);
|
||||||
|
if (fileRes.url) {
|
||||||
|
setFormData((prev) => ({ ...prev, password: "" }));
|
||||||
|
setFileUpload(fileRes?.url);
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
const title = generateTitleFromFilename(formData?.file?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, fileRes.url, tenantId);
|
||||||
|
return fileRes.url;
|
||||||
|
} else {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const parseFile = new Parse.File(name, pdfFile, "application/pdf");
|
const parseFile = new Parse.File(name, pdfFile, "application/pdf");
|
||||||
|
|
||||||
await parseFile.save({
|
await parseFile.save({
|
||||||
progress: (progressValue, loaded, total, { type }) => {
|
progress: (progressValue, loaded, total, { type }) => {
|
||||||
if (type === "upload" && progressValue !== null) {
|
if (type === "upload" && progressValue !== null) {
|
||||||
@@ -560,17 +734,26 @@ const Forms = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieve the URL of the uploaded file
|
// Retrieve the URL of the uploaded file
|
||||||
if (parseFile.url()) {
|
if (parseFile.url()) {
|
||||||
setFormData((prev) => ({ ...prev, password: "" }));
|
setFormData((prev) => ({ ...prev, password: "" }));
|
||||||
setFileUpload(parseFile.url());
|
setFileUpload(parseFile.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
const title = generateTitleFromFilename(formData?.file?.name);
|
const title = generateTitleFromFilename(formData?.file?.name);
|
||||||
setFormData((obj) => ({ ...obj, Name: title }));
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
SaveFileSize(size, parseFile.url(), tenantId);
|
SaveFileSize(size, parseFile.url(), tenantId);
|
||||||
return parseFile.url();
|
return parseFile.url();
|
||||||
|
} else {
|
||||||
|
setfileload(false);
|
||||||
|
setpercentage(0);
|
||||||
|
setFormData((prev) => ({ ...prev, password: "" }));
|
||||||
|
setIsDecrypting(false);
|
||||||
|
if (inputFileRef.current) {
|
||||||
|
inputFileRef.current.value = ""; // Set file input value to empty string
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
@@ -600,16 +783,16 @@ const Forms = (props) => {
|
|||||||
const handleAutoReminder = () => {
|
const handleAutoReminder = () => {
|
||||||
setFormData((prev) => ({ ...prev, autoreminder: !formData.autoreminder }));
|
setFormData((prev) => ({ ...prev, autoreminder: !formData.autoreminder }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handleNotifySignChange` is trigger when user change radio of notify on signatures
|
||||||
|
const handleNotifySignChange = (value) => {
|
||||||
|
setFormData((obj) => ({ ...obj, NotifyOnSignatures: value }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="shadow-md rounded-box my-[2px] p-3 bg-base-100 text-base-content">
|
<div className="shadow-md rounded-box my-[2px] p-3 bg-base-100 text-base-content">
|
||||||
<Title title={props?.title} />
|
<Title title={props?.title} />
|
||||||
{isAlert && (
|
{isAlert?.message && <Alert type={isAlert.type}>{isAlert.message}</Alert>}
|
||||||
<Alert type={isErr ? "danger" : "success"}>
|
|
||||||
{isErr
|
|
||||||
? t("something-went-wrong-mssg")
|
|
||||||
: `${props.msgVar} created successfully!`}
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
{isSubmit ? (
|
{isSubmit ? (
|
||||||
<div className="h-[300px] flex justify-center items-center">
|
<div className="h-[300px] flex justify-center items-center">
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -699,10 +882,7 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
||||||
<DropboxChooser
|
<DropboxChooser onSuccess={dropboxSuccess} />
|
||||||
onSuccess={dropboxSuccess}
|
|
||||||
onCancel={dropboxCancel}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -724,10 +904,7 @@ const Forms = (props) => {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
{process.env.REACT_APP_DROPBOX_API_KEY && (
|
||||||
<DropboxChooser
|
<DropboxChooser onSuccess={dropboxSuccess} />
|
||||||
onSuccess={dropboxSuccess}
|
|
||||||
onCancel={dropboxCancel}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -786,34 +963,53 @@ const Forms = (props) => {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{props.title !== "New Template" && (
|
{props.title === "Sign Yourself" ? (
|
||||||
<SelectFolder
|
<SelectFolder
|
||||||
onSuccess={handleFolder}
|
onSuccess={handleFolder}
|
||||||
folderCls={props.Cls}
|
folderCls={props.Cls}
|
||||||
isReset={isReset}
|
isReset={isReset}
|
||||||
/>
|
/>
|
||||||
)}
|
) : (
|
||||||
{props.title !== "Sign Yourself" && (
|
<div className="flex flex-col md:flex-row w-full mt-4 md:mt-10 gap-3 ">
|
||||||
<div className="text-xs mt-2">
|
<div className="card bg-base-100 rounded-box flex-grow p-3 ">
|
||||||
|
{props.title !== "New Template" ? (
|
||||||
|
<SelectFolder
|
||||||
|
onSuccess={handleFolder}
|
||||||
|
folderCls={props.Cls}
|
||||||
|
isReset={isReset}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span className=" mb-2 font-[400]">
|
||||||
|
{t("form-title-1")}
|
||||||
|
</span>
|
||||||
|
<div className="text-xs mt-3">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
{t("send-in-order")}
|
{t("send-in-order")}
|
||||||
<a data-tooltip-id="sendInOrder-tooltip" className="ml-1">
|
<a
|
||||||
|
data-tooltip-id="sendInOrder-tooltip"
|
||||||
|
className="ml-1"
|
||||||
|
>
|
||||||
<sup>
|
<sup>
|
||||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
</sup>
|
</sup>
|
||||||
</a>
|
</a>
|
||||||
<Tooltip id="sendInOrder-tooltip" className="z-50">
|
<Tooltip id="sendInOrder-tooltip" className="z-[999]">
|
||||||
<div className="max-w-[200px] md:max-w-[450px]">
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
<p className="font-bold">{t("send-in-order")}</p>
|
<p className="font-bold">{t("send-in-order")}</p>
|
||||||
<p>{t("send-in-order-help.p1")}</p>
|
<p>{t("send-in-order-help.p1")}</p>
|
||||||
<p className="p-[5px]">
|
<p className="p-[5px]">
|
||||||
<ol className="list-disc">
|
<ol className="list-disc">
|
||||||
<li>
|
<li>
|
||||||
<span className="font-bold">{t("yes")}: </span>
|
<span className="font-bold">
|
||||||
|
{t("yes")}:{" "}
|
||||||
|
</span>
|
||||||
<span>{t("send-in-order-help.p2")}</span>
|
<span>{t("send-in-order-help.p2")}</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="font-bold">{t("no")}: </span>
|
<span className="font-bold">
|
||||||
|
{t("no")}:{" "}
|
||||||
|
</span>
|
||||||
<span>{t("send-in-order-help.p3")}</span>
|
<span>{t("send-in-order-help.p3")}</span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
@@ -822,6 +1018,7 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
<div className="flex items-center gap-2 ml-2 mb-1">
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -845,36 +1042,21 @@ const Forms = (props) => {
|
|||||||
<div className="text-center">{t("no")}</div>
|
<div className="text-center">{t("no")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{isAdvanceOpt && (
|
{isAdvanceOpt && (
|
||||||
<div className="overflow-y-auto z-[500] transition-all">
|
|
||||||
{props.title === "Request Signatures" && (
|
|
||||||
<div className="text-xs mt-2">
|
|
||||||
<label className="block">
|
|
||||||
{t("time-to-complete")}
|
|
||||||
<span className="text-red-500 text-[13px]">*</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="TimeToCompleteDays"
|
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
|
||||||
value={formData.TimeToCompleteDays}
|
|
||||||
onChange={(e) => handleStrInput(e)}
|
|
||||||
onInvalid={(e) =>
|
|
||||||
e.target.setCustomValidity(t("input-required"))
|
|
||||||
}
|
|
||||||
onInput={(e) => e.target.setCustomValidity("")}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{props.title !== "Sign Yourself" && (
|
|
||||||
<>
|
<>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription &&
|
||||||
<div className="text-xs mt-2">
|
props.title === "New Template" && (
|
||||||
<span className={isSubscribe ? "" : " text-gray-300"}>
|
<div className="text-xs mt-[15px]">
|
||||||
|
<span
|
||||||
|
className={isSubscribe ? "" : " text-gray-300"}
|
||||||
|
>
|
||||||
{t("auto-reminder")}{" "}
|
{t("auto-reminder")}{" "}
|
||||||
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<Upgrade />
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
<label
|
<label
|
||||||
className={`${
|
className={`${
|
||||||
@@ -892,7 +1074,173 @@ const Forms = (props) => {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{formData?.autoreminder === true && (
|
{props.title === "New Template" &&
|
||||||
|
formData?.autoreminder === true && (
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
{t("remind-once")}
|
||||||
|
<span className="text-red-500 text-[13px]">
|
||||||
|
*
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={formData.remindOnceInEvery}
|
||||||
|
name="remindOnceInEvery"
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
onChange={handleStrInput}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.title !== "New Template" && (
|
||||||
|
<>
|
||||||
|
<span className=" mt-2 font-[400]">
|
||||||
|
{t("form-title-1")}
|
||||||
|
</span>
|
||||||
|
<div className="text-xs mt-3">
|
||||||
|
<label className="block">
|
||||||
|
{t("send-in-order")}
|
||||||
|
<a
|
||||||
|
data-tooltip-id="sendInOrder-tooltip"
|
||||||
|
className="ml-1"
|
||||||
|
>
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
<Tooltip
|
||||||
|
id="sendInOrder-tooltip"
|
||||||
|
className="z-[999]"
|
||||||
|
>
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
|
<p className="font-bold">
|
||||||
|
{t("send-in-order")}
|
||||||
|
</p>
|
||||||
|
<p>{t("send-in-order-help.p1")}</p>
|
||||||
|
<p className="p-[5px]">
|
||||||
|
<ol className="list-disc">
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("yes")}:{" "}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{t("send-in-order-help.p2")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("no")}:{" "}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{t("send-in-order-help.p3")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<p>{t("send-in-order-help.p4")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
name="SendinOrder"
|
||||||
|
checked={formData.SendinOrder === "true"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("yes")}</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="SendinOrder"
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
checked={formData.SendinOrder === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="overflow-y-auto z-[500] transition-all">
|
||||||
|
{props.title === "Request Signatures" && (
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
{t("time-to-complete")}
|
||||||
|
<span className="text-red-500 text-[13px]">
|
||||||
|
*
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="TimeToCompleteDays"
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
value={formData.TimeToCompleteDays}
|
||||||
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{isAdvanceOpt && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height:
|
||||||
|
props.title === "New Template" && isEnableSubscription
|
||||||
|
? "220px"
|
||||||
|
: !isEnableSubscription &&
|
||||||
|
props.title === "New Template"
|
||||||
|
? "100px"
|
||||||
|
: "280px"
|
||||||
|
}}
|
||||||
|
className="w-[1px] bg-gray-300 m-auto hidden md:inline-block"
|
||||||
|
></div>
|
||||||
|
)}
|
||||||
|
{isAdvanceOpt && (
|
||||||
|
<div className="card bg-base-100 rounded-box p-3 flex-grow ">
|
||||||
|
{isEnableSubscription && props.title !== "New Template" && (
|
||||||
|
<div className="text-xs mt-[10px]">
|
||||||
|
<span className={isSubscribe ? "" : " text-gray-300"}>
|
||||||
|
{t("auto-reminder")}{" "}
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
</span>
|
||||||
|
<label
|
||||||
|
className={`${
|
||||||
|
isSubscribe
|
||||||
|
? "cursor-pointer"
|
||||||
|
: "pointer-events-none opacity-50"
|
||||||
|
} relative block items-center mb-0 mt-1.5`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white"
|
||||||
|
checked={formData.autoreminder}
|
||||||
|
onChange={handleAutoReminder}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{formData?.autoreminder === true &&
|
||||||
|
props.title !== "New Template" && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
{t("remind-once")}
|
{t("remind-once")}
|
||||||
@@ -912,8 +1260,9 @@ const Forms = (props) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<span className="font-[400] mt-2">{t("form-title-2")}</span>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-3">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
<span className={isSubscribe ? "" : " text-gray-300"}>
|
<span className={isSubscribe ? "" : " text-gray-300"}>
|
||||||
{t("isenable-otp")}{" "}
|
{t("isenable-otp")}{" "}
|
||||||
@@ -924,12 +1273,12 @@ const Forms = (props) => {
|
|||||||
<sup>
|
<sup>
|
||||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
</sup>
|
</sup>
|
||||||
</a>{" "}
|
</a>
|
||||||
{!isSubscribe && isEnableSubscription && (
|
{!isSubscribe && isEnableSubscription && (
|
||||||
<Upgrade />
|
<Upgrade />
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<Tooltip id="isenableotp-tooltip" className="z-50">
|
<Tooltip id="isenableotp-tooltip" className="z-[999]">
|
||||||
<div className="max-w-[200px] md:max-w-[450px]">
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
<p className="font-bold">{t("isenable-otp")}</p>
|
<p className="font-bold">{t("isenable-otp")}</p>
|
||||||
<p>{t("isenable-otp-help.p1")}</p>
|
<p>{t("isenable-otp-help.p1")}</p>
|
||||||
@@ -953,9 +1302,12 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
isSubscribe ? "" : "pointer-events-none opacity-50"
|
isSubscribe
|
||||||
|
? ""
|
||||||
|
: "pointer-events-none opacity-50"
|
||||||
} flex items-center gap-2 ml-2 mb-1 `}
|
} flex items-center gap-2 ml-2 mb-1 `}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -970,7 +1322,9 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
isSubscribe ? "" : "pointer-events-none opacity-50"
|
isSubscribe
|
||||||
|
? ""
|
||||||
|
: "pointer-events-none opacity-50"
|
||||||
} flex items-center gap-2 ml-2 mb-1 `}
|
} flex items-center gap-2 ml-2 mb-1 `}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -984,21 +1338,142 @@ const Forms = (props) => {
|
|||||||
<div className="text-center">{t("no")}</div>
|
<div className="text-center">{t("no")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
<div className="text-xs mt-3">
|
||||||
|
<label className="block">
|
||||||
|
<span>
|
||||||
|
{t("enable-tour")}
|
||||||
|
<a
|
||||||
|
data-tooltip-id="istourenabled-tooltip"
|
||||||
|
className="ml-1"
|
||||||
|
>
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
<Tooltip id="istourenabled-tooltip" className="z-[999]">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
|
<p className="font-bold">{t("enable-tour")}</p>
|
||||||
|
<p className="p-[5px]">
|
||||||
|
<ol className="list-disc">
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("yes")}:{" "}
|
||||||
|
</span>
|
||||||
|
<span>{t("istourenabled-help.p1")}</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">{t("no")}: </span>
|
||||||
|
<span>{t("istourenabled-help.p2")}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<p>{t("istourenabled-help.p3")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
name="IsTourEnabled"
|
||||||
|
checked={formData.IsTourEnabled === "true"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("yes")}</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="IsTourEnabled"
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
checked={formData.IsTourEnabled === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs mt-3">
|
||||||
|
<label
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "text-gray-300"
|
||||||
|
} block`}
|
||||||
|
>
|
||||||
|
{t("notify-on-signatures")}
|
||||||
|
<a data-tooltip-id="nos-tooltip" className="ml-1">
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
<Tooltip id="nos-tooltip" className="z-[999]">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||||
|
<p className="font-bold">
|
||||||
|
{t("notify-on-signatures")}
|
||||||
|
</p>
|
||||||
|
<p>{t("notify-on-signatures-help.p1")}</p>
|
||||||
|
<p>{t("notify-on-signatures-help.note")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(true)}
|
||||||
|
checked={formData.NotifyOnSignatures === true}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("yes")}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(false)}
|
||||||
|
checked={formData.NotifyOnSignatures === false}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{props.title !== "Sign Yourself" && (
|
|
||||||
<div
|
{isAdvanceOpt && props.title !== "Sign Yourself" ? (
|
||||||
|
<span
|
||||||
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
|
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
|
||||||
className={`mt-2.5 op-link op-link-primary text-sm`}
|
className={`mt-2.5 op-link op-link-primary text-sm`}
|
||||||
>
|
>
|
||||||
{isAdvanceOpt
|
{t("hide-advanced-options")}
|
||||||
? t("hide-advanced-options")
|
</span>
|
||||||
: t("advanced-options")}
|
) : (
|
||||||
</div>
|
props.title !== "Sign Yourself" && (
|
||||||
|
<span
|
||||||
|
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
|
||||||
|
className={`mt-2.5 op-link op-link-primary text-sm`}
|
||||||
|
>
|
||||||
|
{t("advanced-options")}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex items-center mt-3 gap-2">
|
<div className="flex items-center mt-3 gap-2">
|
||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import {
|
import {
|
||||||
contractUsers,
|
contractUsers,
|
||||||
getAppLogo,
|
getAppLogo,
|
||||||
@@ -189,10 +189,16 @@ function GuestLogin() {
|
|||||||
};
|
};
|
||||||
const handleUserData = async (e) => {
|
const handleUserData = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (!emailRegex.test(contact.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
const params = { ...contact, docId: documentId };
|
const params = { ...contact, docId: documentId };
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
|
const linkContactRes = await Parse.Cloud.run(
|
||||||
|
"linkcontacttodoc",
|
||||||
|
params
|
||||||
|
);
|
||||||
setContactId(linkContactRes.contactId);
|
setContactId(linkContactRes.contactId);
|
||||||
const IsEnableOTP = await navigateToDoc(
|
const IsEnableOTP = await navigateToDoc(
|
||||||
documentId,
|
documentId,
|
||||||
@@ -207,6 +213,7 @@ function GuestLogin() {
|
|||||||
alert(t("something-went-wrong-mssg"));
|
alert(t("something-went-wrong-mssg"));
|
||||||
console.log("Err in link ext contact", err);
|
console.log("Err in link ext contact", err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const handleInputChange = (e) => {
|
const handleInputChange = (e) => {
|
||||||
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
||||||
@@ -348,6 +355,7 @@ function GuestLogin() {
|
|||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
placeholder={t("phone-optional")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex justify-start">
|
<div className="mt-2 flex justify-start">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { NavLink, useNavigate, useLocation } from "react-router-dom";
|
|||||||
import login_img from "../assets/images/login_img.svg";
|
import login_img from "../assets/images/login_img.svg";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
@@ -51,6 +51,7 @@ function Login() {
|
|||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
const [image, setImage] = useState();
|
const [image, setImage] = useState();
|
||||||
const [isLoginSSO, setIsLoginSSO] = useState(false);
|
const [isLoginSSO, setIsLoginSSO] = useState(false);
|
||||||
|
const [errMsg, setErrMsg] = useState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkUserExt();
|
checkUserExt();
|
||||||
@@ -59,7 +60,9 @@ function Login() {
|
|||||||
|
|
||||||
const checkUserExt = async () => {
|
const checkUserExt = async () => {
|
||||||
const app = await getAppLogo();
|
const app = await getAppLogo();
|
||||||
if (!isEnableSubscription && app?.user === "not_exist") {
|
if (app?.error === "invalid_json") {
|
||||||
|
setErrMsg(t("server-down"));
|
||||||
|
} else if (!isEnableSubscription && app?.user === "not_exist") {
|
||||||
navigate("/addadmin");
|
navigate("/addadmin");
|
||||||
}
|
}
|
||||||
if (app?.logo) {
|
if (app?.logo) {
|
||||||
@@ -86,6 +89,9 @@ function Login() {
|
|||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
localStorage.removeItem("accesstoken");
|
localStorage.removeItem("accesstoken");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (!emailRegex.test(state.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
const { email, password } = state;
|
const { email, password } = state;
|
||||||
if (email && password) {
|
if (email && password) {
|
||||||
try {
|
try {
|
||||||
@@ -246,7 +252,11 @@ function Login() {
|
|||||||
});
|
});
|
||||||
console.error("Error while logging in user", error);
|
console.error("Error while logging in user", error);
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => setState((prev) => ({ ...prev, alertMsg: "" })), 2000);
|
setTimeout(
|
||||||
|
() => setState((prev) => ({ ...prev, alertMsg: "" })),
|
||||||
|
2000
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -620,7 +630,11 @@ function Login() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return errMsg ? (
|
||||||
|
<div className="h-screen flex justify-center text-center items-center p-4 text-gray-500 text-base">
|
||||||
|
{errMsg}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<Title title={"Login Page"} />
|
<Title title={"Login Page"} />
|
||||||
{state.loading && (
|
{state.loading && (
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import React, { useState, useRef, useEffect } from "react";
|
|||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
import "../styles/managesign.css";
|
import "../styles/managesign.css";
|
||||||
import "../styles/signature.css";
|
import "../styles/signature.css";
|
||||||
import { toDataUrl } from "../constant/Utils";
|
import { generateTitleFromFilename, toDataUrl } from "../constant/Utils";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { SaveFileSize } from "../constant/saveFileSize";
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||||
const ManageSign = () => {
|
const ManageSign = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
@@ -23,9 +24,11 @@ const ManageSign = () => {
|
|||||||
const [Initials, setInitials] = useState("");
|
const [Initials, setInitials] = useState("");
|
||||||
const [isInitials, setIsInitials] = useState(false);
|
const [isInitials, setIsInitials] = useState(false);
|
||||||
const [id, setId] = useState("");
|
const [id, setId] = useState("");
|
||||||
|
const [imgInitials, setImgInitials] = useState("");
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
const imageRef = useRef(null);
|
const imageRef = useRef(null);
|
||||||
const initailsRef = useRef(null);
|
const initailsRef = useRef(null);
|
||||||
|
const imgInitialsRef = useRef(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUserSign();
|
fetchUserSign();
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
@@ -46,14 +49,23 @@ const ManageSign = () => {
|
|||||||
if (signRes) {
|
if (signRes) {
|
||||||
const res = signRes.toJSON();
|
const res = signRes.toJSON();
|
||||||
setId(res.objectId);
|
setId(res.objectId);
|
||||||
setSignName(res?.SignatureName);
|
if (res?.SignatureName) {
|
||||||
setImage(res.ImageURL);
|
const sanitizename = generateTitleFromFilename(res?.SignatureName);
|
||||||
|
const replaceSpace = sanitizeFileName(sanitizename);
|
||||||
|
setSignName(replaceSpace);
|
||||||
|
}
|
||||||
|
setImage(res?.ImageURL);
|
||||||
if (res && res.Initials) {
|
if (res && res.Initials) {
|
||||||
setInitials(res.Initials);
|
// setInitials(res.Initials);
|
||||||
setIsInitials(true);
|
setIsInitials(true);
|
||||||
|
setImgInitials(res?.Initials);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSignName(User?.get("name") || "");
|
if (User?.get("name")) {
|
||||||
|
const sanitizename = generateTitleFromFilename(User?.get("name"));
|
||||||
|
const replaceSpace = sanitizeFileName(sanitizename);
|
||||||
|
setSignName(replaceSpace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -86,8 +98,14 @@ const ManageSign = () => {
|
|||||||
if (initailsRef.current) {
|
if (initailsRef.current) {
|
||||||
initailsRef.current.clear();
|
initailsRef.current.clear();
|
||||||
}
|
}
|
||||||
|
if (imgInitialsRef.current) {
|
||||||
|
imgInitialsRef.current.value = "";
|
||||||
|
}
|
||||||
|
setImgInitials("");
|
||||||
setInitials("");
|
setInitials("");
|
||||||
|
if (image) {
|
||||||
setIsValue(true);
|
setIsValue(true);
|
||||||
|
}
|
||||||
setIsInitials(false);
|
setIsInitials(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,40 +119,54 @@ const ManageSign = () => {
|
|||||||
const base64Img = await toDataUrl(file);
|
const base64Img = await toDataUrl(file);
|
||||||
setImage(base64Img);
|
setImage(base64Img);
|
||||||
setIsValue(true);
|
setIsValue(true);
|
||||||
|
} else {
|
||||||
|
setImage("");
|
||||||
|
setIsValue(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const isUrl = image.includes("https");
|
const isUrl = image?.includes("https") || image?.includes("http");
|
||||||
|
|
||||||
if (!isvalue) {
|
if (!isvalue) {
|
||||||
setWarning(true);
|
setWarning(true);
|
||||||
setTimeout(() => setWarning(false), 1000);
|
setTimeout(() => setWarning(false), 1000);
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
const replaceSpace = signName.replace(/ /g, "_");
|
const sanitizename = generateTitleFromFilename(signName);
|
||||||
|
const replaceSpace = sanitizeFileName(sanitizename);
|
||||||
let file;
|
let file;
|
||||||
if (signature) {
|
if (signature) {
|
||||||
file = base64StringtoFile(signature, `${replaceSpace}_sign.png`);
|
file = base64StringtoFile(signature, `${replaceSpace}_sign`);
|
||||||
} else {
|
} else {
|
||||||
if (!isUrl) {
|
if (image && !isUrl) {
|
||||||
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
|
file = base64StringtoFile(image, `${replaceSpace}__sign`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let imgUrl;
|
let imgUrl;
|
||||||
if (!isUrl) {
|
if (file && !isUrl) {
|
||||||
imgUrl = await uploadFile(file);
|
imgUrl = await uploadFile(file);
|
||||||
} else {
|
} else {
|
||||||
imgUrl = image;
|
imgUrl = image;
|
||||||
}
|
}
|
||||||
let initialsUrl = "";
|
const isInitialsUrl =
|
||||||
const isInitialsUrl = Initials.includes("https");
|
imgInitials?.includes("https") || imgInitials?.includes("http");
|
||||||
if (!isInitialsUrl && Initials) {
|
|
||||||
const initialsImg = base64StringtoFile(
|
let initialFile;
|
||||||
Initials,
|
if (Initials) {
|
||||||
`${replaceSpace}_initials.png`
|
initialFile = base64StringtoFile(Initials, `${replaceSpace}_sign`);
|
||||||
|
} else {
|
||||||
|
if (imgInitials && !isInitialsUrl) {
|
||||||
|
initialFile = base64StringtoFile(
|
||||||
|
imgInitials,
|
||||||
|
`${replaceSpace}__sign`
|
||||||
);
|
);
|
||||||
initialsUrl = await uploadFile(initialsImg);
|
}
|
||||||
|
}
|
||||||
|
let initialsUrl;
|
||||||
|
if (initialFile && !isInitialsUrl) {
|
||||||
|
initialsUrl = await uploadFile(initialFile);
|
||||||
|
} else {
|
||||||
|
initialsUrl = imgInitials;
|
||||||
}
|
}
|
||||||
if (imgUrl) {
|
if (imgUrl) {
|
||||||
await saveEntry({
|
await saveEntry({
|
||||||
@@ -146,15 +178,19 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
function base64StringtoFile(base64String, filename) {
|
function base64StringtoFile(base64String, filename) {
|
||||||
var arr = base64String.split(","),
|
let arr = base64String.split(","),
|
||||||
|
// type of uploaded image
|
||||||
mime = arr[0].match(/:(.*?);/)[1],
|
mime = arr[0].match(/:(.*?);/)[1],
|
||||||
|
// decode base64
|
||||||
bstr = atob(arr[1]),
|
bstr = atob(arr[1]),
|
||||||
n = bstr.length,
|
n = bstr.length,
|
||||||
u8arr = new Uint8Array(n);
|
u8arr = new Uint8Array(n);
|
||||||
while (n--) {
|
while (n--) {
|
||||||
u8arr[n] = bstr.charCodeAt(n);
|
u8arr[n] = bstr.charCodeAt(n);
|
||||||
}
|
}
|
||||||
return new File([u8arr], filename, { type: mime });
|
const ext = mime.split("/").pop();
|
||||||
|
const name = `${filename}.${ext}`;
|
||||||
|
return new File([u8arr], name, { type: mime });
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadFile = async (file) => {
|
const uploadFile = async (file) => {
|
||||||
@@ -175,31 +211,24 @@ const ManageSign = () => {
|
|||||||
|
|
||||||
const saveEntry = async (obj) => {
|
const saveEntry = async (obj) => {
|
||||||
const signCls = "contracts_Signature";
|
const signCls = "contracts_Signature";
|
||||||
const User = Parse.User.current().id;
|
const User = Parse?.User?.current()?.id;
|
||||||
const userId = { __type: "Pointer", className: "_User", objectId: User };
|
const userId = { __type: "Pointer", className: "_User", objectId: User };
|
||||||
if (id) {
|
if (id) {
|
||||||
try {
|
try {
|
||||||
const updateSign = new Parse.Object(signCls);
|
const updateSign = new Parse.Object(signCls);
|
||||||
updateSign.id = id;
|
updateSign.id = id;
|
||||||
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
|
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
|
||||||
updateSign.set("ImageURL", obj.url);
|
updateSign.set("ImageURL", obj.url ? obj.url : "");
|
||||||
updateSign.set("SignatureName", obj.name);
|
updateSign.set("SignatureName", obj.name);
|
||||||
updateSign.set("UserId", userId);
|
updateSign.set("UserId", userId);
|
||||||
const res = await updateSign.save();
|
const res = await updateSign.save();
|
||||||
setIsLoader(false);
|
setIsAlert({ type: "success", message: t("signature-saved-alert") });
|
||||||
setIsAlert({
|
|
||||||
type: "success",
|
|
||||||
message: t("signature-saved-alert")
|
|
||||||
});
|
|
||||||
setTimeout(() => setIsAlert({}), 2000);
|
|
||||||
return res;
|
return res;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
setIsAlert({ type: "danger", message: `${err.message}` });
|
||||||
|
} finally {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
setIsAlert({
|
|
||||||
type: "danger",
|
|
||||||
message: `${err.message}`
|
|
||||||
});
|
|
||||||
setTimeout(() => setIsAlert({}), 2000);
|
setTimeout(() => setIsAlert({}), 2000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -210,20 +239,13 @@ const ManageSign = () => {
|
|||||||
updateSign.set("SignatureName", obj.name);
|
updateSign.set("SignatureName", obj.name);
|
||||||
updateSign.set("UserId", userId);
|
updateSign.set("UserId", userId);
|
||||||
const res = await updateSign.save();
|
const res = await updateSign.save();
|
||||||
setIsLoader(false);
|
setIsAlert({ type: "success", message: t("signature-saved-alert") });
|
||||||
setIsAlert({
|
|
||||||
type: "success",
|
|
||||||
message: t("signature-saved-alert")
|
|
||||||
});
|
|
||||||
setTimeout(() => setIsAlert({}), 2000);
|
|
||||||
return res;
|
return res;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
setIsAlert({ type: "success", message: `${err.message}` });
|
||||||
|
} finally {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
setIsAlert({
|
|
||||||
type: "success",
|
|
||||||
message: `${err.message}`
|
|
||||||
});
|
|
||||||
setTimeout(() => setIsAlert({}), 2000);
|
setTimeout(() => setIsAlert({}), 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +256,29 @@ const ManageSign = () => {
|
|||||||
};
|
};
|
||||||
const handleInitialsChange = () => {
|
const handleInitialsChange = () => {
|
||||||
setInitials(initailsRef.current.toDataURL());
|
setInitials(initailsRef.current.toDataURL());
|
||||||
|
if (image || signature) {
|
||||||
setIsValue(true);
|
setIsValue(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleUploadInitials = () => {
|
||||||
|
imgInitialsRef.current.click();
|
||||||
|
};
|
||||||
|
const onImgInitialsChange = async (event) => {
|
||||||
|
if (initailsRef.current) {
|
||||||
|
initailsRef.current.clear();
|
||||||
|
}
|
||||||
|
setInitials("");
|
||||||
|
if (event.target.files && event.target.files[0]) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
const base64Img = await toDataUrl(file);
|
||||||
|
setImgInitials(base64Img);
|
||||||
|
if (image || signature) {
|
||||||
|
setIsValue(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setImgInitials("");
|
||||||
|
setIsValue(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto">
|
<div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto">
|
||||||
@@ -281,7 +325,7 @@ const ManageSign = () => {
|
|||||||
height: "180px",
|
height: "180px",
|
||||||
className: "signatureCanvas rounded-box"
|
className: "signatureCanvas rounded-box"
|
||||||
}}
|
}}
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
// backgroundColor="rgb(255, 255, 255)"
|
||||||
onEnd={() =>
|
onEnd={() =>
|
||||||
handleSignatureChange(canvasRef.current.toDataURL())
|
handleSignatureChange(canvasRef.current.toDataURL())
|
||||||
}
|
}
|
||||||
@@ -332,7 +376,7 @@ const ManageSign = () => {
|
|||||||
className="op-link"
|
className="op-link"
|
||||||
onClick={() => handleUploadBtn()}
|
onClick={() => handleUploadBtn()}
|
||||||
>
|
>
|
||||||
{t("upload-image")}
|
{t("upload")}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
@@ -356,17 +400,21 @@ const ManageSign = () => {
|
|||||||
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
||||||
{t("initials")}
|
{t("initials")}
|
||||||
</span>
|
</span>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={onImgInitialsChange}
|
||||||
|
className="filetype"
|
||||||
|
accept="image/*"
|
||||||
|
ref={imgInitialsRef}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
<div>
|
<div>
|
||||||
{isInitials ? (
|
{imgInitials ? (
|
||||||
<div className="intialSignature relative border-[1px] border-[#888] rounded-box overflow-hidden">
|
<div className="intialSignature relative border-[1px] border-[#888] rounded-box overflow-hidden">
|
||||||
<img
|
<img
|
||||||
alt="inititals"
|
alt="inititals"
|
||||||
src={Initials}
|
src={imgInitials}
|
||||||
style={{
|
className="w-[100%] h-[100%] object-contain"
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
objectFit: "contain"
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -376,10 +424,8 @@ const ManageSign = () => {
|
|||||||
canvasProps={{
|
canvasProps={{
|
||||||
className: "intialSignature rounded-box"
|
className: "intialSignature rounded-box"
|
||||||
}}
|
}}
|
||||||
backgroundColor="rgb(255, 255, 255)"
|
// backgroundColor="rgb(255, 255, 255)"
|
||||||
onEnd={() =>
|
onEnd={() => handleInitialsChange()}
|
||||||
handleInitialsChange(initailsRef.current.toDataURL())
|
|
||||||
}
|
|
||||||
dotSize={1}
|
dotSize={1}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -402,6 +448,7 @@ const ManageSign = () => {
|
|||||||
? "2px solid black"
|
? "2px solid black"
|
||||||
: "2px solid white"
|
: "2px solid white"
|
||||||
}}
|
}}
|
||||||
|
className="fa-light fa-pen-nib"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (key === 0) {
|
if (key === 0) {
|
||||||
setInitialPen("blue");
|
setInitialPen("blue");
|
||||||
@@ -412,7 +459,6 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={key}
|
key={key}
|
||||||
className="fa-light fa-pen-nib"
|
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
></i>
|
></i>
|
||||||
@@ -421,6 +467,14 @@ const ManageSign = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-row gap-1">
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
className="op-link text-sm md:text-base mr-1"
|
||||||
|
onClick={() => handleUploadInitials()}
|
||||||
|
>
|
||||||
|
{t("upload")}
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
@@ -434,6 +488,7 @@ const ManageSign = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="pt-3 ml-2 md:ml-0">
|
<div className="pt-3 ml-2 md:ml-0">
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
|
|||||||
@@ -499,22 +499,13 @@ function Opensigndrive() {
|
|||||||
//function to use check tour status of open sign drive
|
//function to use check tour status of open sign drive
|
||||||
async function checkTourStatus() {
|
async function checkTourStatus() {
|
||||||
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
||||||
const res = { data: cloudRes.toJSON() };
|
if (cloudRes) {
|
||||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
const extUser = JSON.parse(JSON.stringify(cloudRes));
|
||||||
const tourStatus = res.data.TourStatus;
|
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
|
||||||
|
const tourStatus = extUser?.TourStatus || [];
|
||||||
setTourStatusArr(tourStatus);
|
setTourStatusArr(tourStatus);
|
||||||
const filteredtourStatus = tourStatus.filter((obj) => obj["driveTour"]);
|
const driveTour = tourStatus.find((obj) => obj.driveTour)?.driveTour;
|
||||||
if (filteredtourStatus.length > 0) {
|
setIsTour(!driveTour);
|
||||||
const driveTour = filteredtourStatus[0]["driveTour"];
|
|
||||||
// console.log("loginTour", loginTour);
|
|
||||||
if (driveTour) {
|
|
||||||
setIsTour(false);
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setIsTour(true);
|
setIsTour(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { isEnableSubscription, isStaging, themeColor } from "../constant/const";
|
import {
|
||||||
|
emailRegex,
|
||||||
|
isEnableSubscription,
|
||||||
|
isStaging,
|
||||||
|
themeColor
|
||||||
|
} from "../constant/const";
|
||||||
import { PDFDocument } from "pdf-lib";
|
import { PDFDocument } from "pdf-lib";
|
||||||
import "../styles/signature.css";
|
import "../styles/signature.css";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
@@ -33,7 +38,11 @@ import {
|
|||||||
getDefaultSignature,
|
getDefaultSignature,
|
||||||
onClickZoomIn,
|
onClickZoomIn,
|
||||||
onClickZoomOut,
|
onClickZoomOut,
|
||||||
fetchUrl
|
fetchUrl,
|
||||||
|
signatureTypes,
|
||||||
|
handleSignatureType,
|
||||||
|
getTenantDetails,
|
||||||
|
getBase64FromUrl
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
@@ -51,6 +60,7 @@ import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|||||||
import DownloadPdfZip from "../primitives/DownloadPdfZip";
|
import DownloadPdfZip from "../primitives/DownloadPdfZip";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import PdfDeclineModal from "../primitives/PdfDeclineModal";
|
import PdfDeclineModal from "../primitives/PdfDeclineModal";
|
||||||
|
import { serverUrl_fn } from "../constant/appinfo";
|
||||||
|
|
||||||
function PdfRequestFiles(props) {
|
function PdfRequestFiles(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -73,7 +83,7 @@ function PdfRequestFiles(props) {
|
|||||||
const [selectWidgetId, setSelectWidgetId] = useState("");
|
const [selectWidgetId, setSelectWidgetId] = useState("");
|
||||||
const [otpLoader, setOtpLoader] = useState(false);
|
const [otpLoader, setOtpLoader] = useState(false);
|
||||||
const [isCelebration, setIsCelebration] = useState(false);
|
const [isCelebration, setIsCelebration] = useState(false);
|
||||||
const [requestSignTour, setRequestSignTour] = useState(false);
|
const [requestSignTour, setRequestSignTour] = useState(true);
|
||||||
const [tourStatus, setTourStatus] = useState([]);
|
const [tourStatus, setTourStatus] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
@@ -129,15 +139,15 @@ function PdfRequestFiles(props) {
|
|||||||
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
|
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
|
||||||
const [isOtp, setIsOtp] = useState(false);
|
const [isOtp, setIsOtp] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [res, setRes] = useState({});
|
const [publicRes, setPublicRes] = useState({});
|
||||||
const [documentId, setDocumentId] = useState("");
|
const [documentId, setDocumentId] = useState("");
|
||||||
const [isPublicContact, setIsPublicContact] = useState(false);
|
const [isPublicContact, setIsPublicContact] = useState(false);
|
||||||
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
|
||||||
const [plancode, setPlanCode] = useState("");
|
const [plancode, setPlanCode] = useState("");
|
||||||
const isHeader = useSelector((state) => state.showHeader);
|
const isHeader = useSelector((state) => state.showHeader);
|
||||||
const divRef = useRef(null);
|
const divRef = useRef(null);
|
||||||
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
|
const [signatureType, setSignatureType] = useState([]);
|
||||||
|
const [pdfBase64Url, setPdfBase64Url] = useState("");
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
|
|
||||||
let isGuestSignFlow = false;
|
let isGuestSignFlow = false;
|
||||||
@@ -284,6 +294,7 @@ function PdfRequestFiles(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//function for get document details for perticular signer with signer'object id
|
//function for get document details for perticular signer with signer'object id
|
||||||
|
//whenever change anything in this function check react/angular packages also in plan js
|
||||||
const getTemplateDetails = async () => {
|
const getTemplateDetails = async () => {
|
||||||
try {
|
try {
|
||||||
const params = { templateId: props.templateId, ispublic: true };
|
const params = { templateId: props.templateId, ispublic: true };
|
||||||
@@ -303,26 +314,20 @@ function PdfRequestFiles(props) {
|
|||||||
: [];
|
: [];
|
||||||
if (documentData && documentData[0]?.error) {
|
if (documentData && documentData[0]?.error) {
|
||||||
props?.setTemplateStatus &&
|
props?.setTemplateStatus &&
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus({ status: "Invalid" });
|
||||||
status: "Invalid"
|
|
||||||
});
|
|
||||||
throw new Error("error: Invalid TemplateId");
|
throw new Error("error: Invalid TemplateId");
|
||||||
} else if (documentData && documentData.length > 0) {
|
} else if (documentData && documentData.length > 0) {
|
||||||
if (documentData[0]?.IsPublic) {
|
if (documentData[0]?.IsPublic) {
|
||||||
|
//handle condition when someone use plan js then setTemplateStatus is not supporting
|
||||||
props?.setTemplateStatus &&
|
props?.setTemplateStatus &&
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus({ status: "Success" });
|
||||||
status: "Success"
|
|
||||||
});
|
|
||||||
const url =
|
const url =
|
||||||
documentData[0] &&
|
documentData[0] &&
|
||||||
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
||||||
if (url) {
|
if (url) {
|
||||||
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
const base64Pdf = await getBase64FromUrl(url);
|
||||||
const arrayBuffer = await convertPdfArrayBuffer(url);
|
if (base64Pdf) {
|
||||||
if (arrayBuffer === "Error") {
|
setPdfBase64Url(base64Pdf);
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
|
||||||
} else {
|
|
||||||
setPdfArrayBuffer(arrayBuffer);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
@@ -352,24 +357,18 @@ function PdfRequestFiles(props) {
|
|||||||
}
|
}
|
||||||
setUnSignedSigners(placeholdersOrSigners);
|
setUnSignedSigners(placeholdersOrSigners);
|
||||||
setPdfDetails(documentData);
|
setPdfDetails(documentData);
|
||||||
setIsLoading({
|
setIsLoading({ isLoad: false });
|
||||||
isLoad: false
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
props?.setTemplateStatus &&
|
props?.setTemplateStatus &&
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus({ status: "Private" });
|
||||||
status: "Private"
|
setIsLoading({ isLoad: false });
|
||||||
});
|
|
||||||
setIsLoading(false);
|
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
console.error("error: TemplateId is not public");
|
console.error("error: TemplateId is not public");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
props?.setTemplateStatus &&
|
props?.setTemplateStatus &&
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus({ status: "Invalid" });
|
||||||
status: "Invalid"
|
|
||||||
});
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
console.error("error: Invalid TemplateId");
|
console.error("error: Invalid TemplateId");
|
||||||
@@ -386,6 +385,33 @@ function PdfRequestFiles(props) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const fetchTenantDetails = async (contactId) => {
|
||||||
|
const user = JSON.parse(
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
const tenantDetails = await getTenantDetails(
|
||||||
|
user?.objectId, // userId
|
||||||
|
"", // jwttoken
|
||||||
|
contactId // contactId
|
||||||
|
);
|
||||||
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
} else if (tenantDetails) {
|
||||||
|
const signatureType = tenantDetails?.SignatureType || [];
|
||||||
|
const filterSignTypes = signatureType?.filter(
|
||||||
|
(x) => x.enabled === true
|
||||||
|
);
|
||||||
|
|
||||||
|
return filterSignTypes;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//function for get document details for perticular signer with signer'object id
|
//function for get document details for perticular signer with signer'object id
|
||||||
const getDocumentDetails = async (docId, isNextUser) => {
|
const getDocumentDetails = async (docId, isNextUser) => {
|
||||||
try {
|
try {
|
||||||
@@ -393,21 +419,34 @@ function PdfRequestFiles(props) {
|
|||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
);
|
);
|
||||||
const jsonSender = JSON.parse(senderUser);
|
const jsonSender = JSON.parse(senderUser);
|
||||||
|
const contactId = jsonSender?.objectId
|
||||||
|
? ""
|
||||||
|
: contactBookId || signerObjectId || "";
|
||||||
|
const tenantSignTypes = await fetchTenantDetails(contactId);
|
||||||
// `currUserId` will be contactId or extUserId
|
// `currUserId` will be contactId or extUserId
|
||||||
let currUserId;
|
let currUserId;
|
||||||
//getting document details
|
//getting document details
|
||||||
const documentData = await contractDocument(docId);
|
const documentData = await contractDocument(docId);
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
|
const userSignatureType =
|
||||||
|
documentData[0]?.ExtUserPtr?.SignatureType || signatureTypes;
|
||||||
|
const docSignTypes =
|
||||||
|
documentData?.[0]?.SignatureType || userSignatureType;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
docSignTypes
|
||||||
|
);
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
const updatedPdfDetails = [...documentData];
|
||||||
|
updatedPdfDetails[0].SignatureType = updatedSignatureType;
|
||||||
|
setPdfDetails(updatedPdfDetails);
|
||||||
const url =
|
const url =
|
||||||
documentData[0] &&
|
documentData[0] &&
|
||||||
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
||||||
if (url) {
|
if (url) {
|
||||||
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
const base64Pdf = await getBase64FromUrl(url);
|
||||||
const arrayBuffer = await convertPdfArrayBuffer(url);
|
if (base64Pdf) {
|
||||||
if (arrayBuffer === "Error") {
|
setPdfBase64Url(base64Pdf);
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
|
||||||
} else {
|
|
||||||
setPdfArrayBuffer(arrayBuffer);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
@@ -421,13 +460,15 @@ function PdfRequestFiles(props) {
|
|||||||
const expireUpdateDate = new Date(expireDate).getTime();
|
const expireUpdateDate = new Date(expireDate).getTime();
|
||||||
const currDate = new Date().getTime();
|
const currDate = new Date().getTime();
|
||||||
const getSigners = documentData[0].Signers;
|
const getSigners = documentData[0].Signers;
|
||||||
|
const isTourEnabled =
|
||||||
|
documentData[0]?.IsTourEnabled === true ? true : false;
|
||||||
const getCurrentSigner = getSigners?.find(
|
const getCurrentSigner = getSigners?.find(
|
||||||
(data) => data.UserId.objectId === jsonSender?.objectId
|
(data) => data.UserId.objectId === jsonSender?.objectId
|
||||||
);
|
);
|
||||||
|
|
||||||
currUserId = getCurrentSigner?.objectId
|
currUserId = getCurrentSigner?.objectId
|
||||||
? getCurrentSigner.objectId
|
? getCurrentSigner.objectId
|
||||||
: contactBookId || "";
|
: contactBookId || signerObjectId || ""; //signerObjectId is contactBookId refer from public template flow
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
await checkIsSubscribed(
|
await checkIsSubscribed(
|
||||||
documentData[0]?.ExtUserPtr?.objectId,
|
documentData[0]?.ExtUserPtr?.objectId,
|
||||||
@@ -596,7 +637,8 @@ function PdfRequestFiles(props) {
|
|||||||
checkAlreadySign ||
|
checkAlreadySign ||
|
||||||
!currUserId ||
|
!currUserId ||
|
||||||
declined ||
|
declined ||
|
||||||
currDate > expireUpdateDate
|
currDate > expireUpdateDate ||
|
||||||
|
!isTourEnabled
|
||||||
) {
|
) {
|
||||||
setRequestSignTour(true);
|
setRequestSignTour(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -624,6 +666,8 @@ function PdfRequestFiles(props) {
|
|||||||
tourData?.some((data) => data?.requestSign) || false;
|
tourData?.some((data) => data?.requestSign) || false;
|
||||||
setTourStatus(tourData);
|
setTourStatus(tourData);
|
||||||
setRequestSignTour(checkTourRequest);
|
setRequestSignTour(checkTourRequest);
|
||||||
|
} else {
|
||||||
|
setRequestSignTour(false);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err while getting tourstatus", err);
|
console.log("err while getting tourstatus", err);
|
||||||
@@ -645,6 +689,8 @@ function PdfRequestFiles(props) {
|
|||||||
);
|
);
|
||||||
setTourStatus(tourData);
|
setTourStatus(tourData);
|
||||||
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
|
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
|
||||||
|
} else {
|
||||||
|
setRequestSignTour(false);
|
||||||
}
|
}
|
||||||
} else if (res?.length === 0) {
|
} else if (res?.length === 0) {
|
||||||
const res = await contactBook(currUserId);
|
const res = await contactBook(currUserId);
|
||||||
@@ -661,6 +707,8 @@ function PdfRequestFiles(props) {
|
|||||||
);
|
);
|
||||||
setTourStatus(tourData);
|
setTourStatus(tourData);
|
||||||
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
|
setRequestSignTour(checkTourRequest[0]?.requestSign || false);
|
||||||
|
} else {
|
||||||
|
setRequestSignTour(false);
|
||||||
}
|
}
|
||||||
} else if (res.length === 0) {
|
} else if (res.length === 0) {
|
||||||
setHandleError(t("user-not-exist"));
|
setHandleError(t("user-not-exist"));
|
||||||
@@ -880,9 +928,29 @@ function PdfRequestFiles(props) {
|
|||||||
setIsUiLoading(true);
|
setIsUiLoading(true);
|
||||||
// `widgets` is Used to return widgets details with page number of current user
|
// `widgets` is Used to return widgets details with page number of current user
|
||||||
const widgets = checkUser?.[0]?.placeHolder;
|
const widgets = checkUser?.[0]?.placeHolder;
|
||||||
|
let pdfArrBuffer;
|
||||||
|
//`contractDocument` function used to get updated SignedUrl
|
||||||
|
// to resolve issue of widgets get remove automatically when more than 1 signers try to sign doc at a time
|
||||||
|
const documentData = await contractDocument(documentId);
|
||||||
|
if (documentData && documentData.length > 0) {
|
||||||
|
const url = documentData[0]?.SignedUrl || documentData[0]?.URL;
|
||||||
|
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
||||||
|
const arrayBuffer = await convertPdfArrayBuffer(url);
|
||||||
|
if (arrayBuffer === "Error") {
|
||||||
|
setHandleError("Error: invalid document!");
|
||||||
|
} else {
|
||||||
|
pdfArrBuffer = arrayBuffer;
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
documentData === "Error: Something went wrong!" ||
|
||||||
|
(documentData.result && documentData.result.error)
|
||||||
|
) {
|
||||||
|
setHandleError("Error: Something went wrong!");
|
||||||
|
} else {
|
||||||
|
setHandleError("Document not Found!");
|
||||||
|
}
|
||||||
// Load a PDFDocument from the existing PDF bytes
|
// Load a PDFDocument from the existing PDF bytes
|
||||||
const existingPdfBytes = pdfArrayBuffer;
|
const existingPdfBytes = pdfArrBuffer;
|
||||||
try {
|
try {
|
||||||
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
||||||
const isSignYourSelfFlow = false;
|
const isSignYourSelfFlow = false;
|
||||||
@@ -899,16 +967,14 @@ function PdfRequestFiles(props) {
|
|||||||
widgets,
|
widgets,
|
||||||
pdfDoc,
|
pdfDoc,
|
||||||
isSignYourSelfFlow,
|
isSignYourSelfFlow,
|
||||||
scale,
|
scale
|
||||||
pdfOriginalWH,
|
|
||||||
containerWH
|
|
||||||
);
|
);
|
||||||
// console.log("pdfte", pdfBytes);
|
// console.log("pdfte", pdfBytes);
|
||||||
//get ExistUserPtr object id of user class to get tenantDetails
|
//get ExistUserPtr object id of user class to get tenantDetails
|
||||||
|
if (!pdfBytes?.error) {
|
||||||
const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
|
const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
|
||||||
let activeMailAdapter =
|
let activeMailAdapter =
|
||||||
pdfDetails?.[0]?.ExtUserPtr?.active_mail_adapter;
|
pdfDetails?.[0]?.ExtUserPtr?.active_mail_adapter;
|
||||||
|
|
||||||
//function for call to embed signature in pdf and get digital signature pdf
|
//function for call to embed signature in pdf and get digital signature pdf
|
||||||
const resSign = await signPdfFun(
|
const resSign = await signPdfFun(
|
||||||
pdfBytes,
|
pdfBytes,
|
||||||
@@ -943,11 +1009,7 @@ function PdfRequestFiles(props) {
|
|||||||
const newDate = new Date(expireDate);
|
const newDate = new Date(expireDate);
|
||||||
const localExpireDate = newDate.toLocaleDateString(
|
const localExpireDate = newDate.toLocaleDateString(
|
||||||
"en-US",
|
"en-US",
|
||||||
{
|
{ day: "numeric", month: "long", year: "numeric" }
|
||||||
day: "numeric",
|
|
||||||
month: "long",
|
|
||||||
year: "numeric"
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
|
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
|
||||||
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
|
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
|
||||||
@@ -1011,7 +1073,7 @@ function PdfRequestFiles(props) {
|
|||||||
receiver_phone: user.Phone,
|
receiver_phone: user.Phone,
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: orgName,
|
company_name: orgName,
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||||
};
|
};
|
||||||
replaceVar = replaceMailVaribles(
|
replaceVar = replaceMailVaribles(
|
||||||
requestSubject,
|
requestSubject,
|
||||||
@@ -1045,7 +1107,7 @@ function PdfRequestFiles(props) {
|
|||||||
orgName +
|
orgName +
|
||||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||||
localExpireDate +
|
localExpireDate +
|
||||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||||
signPdf +
|
signPdf +
|
||||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
senderEmail +
|
senderEmail +
|
||||||
@@ -1061,7 +1123,19 @@ function PdfRequestFiles(props) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsUiLoading(false);
|
setIsUiLoading(false);
|
||||||
setIsAlert({ isShow: true, alertMessage: resSign.message });
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: resSign.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsUiLoading(false);
|
||||||
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("pdf-uncompatible")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsUiLoading(false);
|
setIsUiLoading(false);
|
||||||
@@ -1344,9 +1418,7 @@ function PdfRequestFiles(props) {
|
|||||||
try {
|
try {
|
||||||
await axios.post(
|
await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
|
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
|
||||||
{
|
{ contactId: signerObjectId },
|
||||||
contactId: signerObjectId
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -1487,6 +1559,9 @@ function PdfRequestFiles(props) {
|
|||||||
//`handlePublicUser` function to use create user from public role and create document from public template
|
//`handlePublicUser` function to use create user from public role and create document from public template
|
||||||
const handlePublicUser = async (e) => {
|
const handlePublicUser = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (!emailRegex.test(contact.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
@@ -1508,8 +1583,17 @@ function PdfRequestFiles(props) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (userRes?.data?.result) {
|
if (userRes?.data?.result) {
|
||||||
setRes(userRes.data.result);
|
setPublicRes(userRes.data.result);
|
||||||
|
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
|
||||||
|
if (isEnableOTP) {
|
||||||
await SendOtp();
|
await SendOtp();
|
||||||
|
} else {
|
||||||
|
setIsPublicContact(false);
|
||||||
|
setIsPublicTemplate(false);
|
||||||
|
setDocumentId(userRes.data?.result?.docId);
|
||||||
|
const contactId = userRes.data.result?.contactId;
|
||||||
|
setSignerObjectId(contactId);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("error in public-sign to create user details");
|
console.log("error in public-sign to create user details");
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
@@ -1539,6 +1623,7 @@ function PdfRequestFiles(props) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (e) => {
|
const handleInputChange = (e) => {
|
||||||
@@ -1551,7 +1636,7 @@ function PdfRequestFiles(props) {
|
|||||||
|
|
||||||
const SendOtp = async () => {
|
const SendOtp = async () => {
|
||||||
try {
|
try {
|
||||||
const params = { email: contact.email, docId: res.docId };
|
const params = { email: contact.email, docId: publicRes?.docId };
|
||||||
const Otp = await axios.post(
|
const Otp = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}/functions/SendOTPMailV1`,
|
`${localStorage.getItem("baseUrl")}/functions/SendOTPMailV1`,
|
||||||
params,
|
params,
|
||||||
@@ -1617,17 +1702,13 @@ function PdfRequestFiles(props) {
|
|||||||
JSON.stringify(contractUserDetails)
|
JSON.stringify(contractUserDetails)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("username", _user.name);
|
localStorage.setItem("username", _user.name);
|
||||||
localStorage.setItem("accesstoken", _user.sessionToken);
|
localStorage.setItem("accesstoken", _user.sessionToken);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
// navigate(`/load/recipientSignPdf/${res?.docId}/${res?.contactId}`);
|
|
||||||
// document.getElementById("my_modal").close();
|
|
||||||
setIsPublicContact(false);
|
setIsPublicContact(false);
|
||||||
setIsPublicTemplate(false);
|
setIsPublicTemplate(false);
|
||||||
setIsLoading({ isLoad: false });
|
setIsLoading({ isLoad: false });
|
||||||
setDocumentId(res?.docId);
|
setDocumentId(publicRes?.docId);
|
||||||
getDocumentDetails(res?.docId);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("err ", error);
|
console.log("err ", error);
|
||||||
@@ -1672,6 +1753,42 @@ function PdfRequestFiles(props) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleExpiry = async (expiryDate) => {
|
||||||
|
setIsUiLoading(true);
|
||||||
|
const doc = pdfDetails?.[0];
|
||||||
|
const oldExpiryDate = new Date(doc?.ExpiryDate?.iso);
|
||||||
|
const newExpiryDate = new Date(expiryDate);
|
||||||
|
if (newExpiryDate > oldExpiryDate) {
|
||||||
|
const updateExpiryDate = new Date(expiryDate).toISOString();
|
||||||
|
const expiryIsoFormat = { iso: updateExpiryDate, __type: "Date" };
|
||||||
|
try {
|
||||||
|
const serverUrl = serverUrl_fn();
|
||||||
|
const url = serverUrl + `/classes/contracts_Document/`;
|
||||||
|
const body = { ExpiryDate: expiryIsoFormat };
|
||||||
|
const res = await axios.put(url + doc.objectId, body, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (res.data && res.data.updatedAt) {
|
||||||
|
setIsExpired(false);
|
||||||
|
let doc = pdfDetails?.[0];
|
||||||
|
doc.ExpiryDate = expiryIsoFormat;
|
||||||
|
setPdfDetails([doc]);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err", err);
|
||||||
|
} finally {
|
||||||
|
setIsUiLoading(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsUiLoading(false);
|
||||||
|
alert(t("expiry-date-error"));
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
<Title title={props.templateId ? "Public Sign" : "Request Sign"} />
|
<Title title={props.templateId ? "Public Sign" : "Request Sign"} />
|
||||||
@@ -1758,10 +1875,12 @@ function PdfRequestFiles(props) {
|
|||||||
{/* this modal is used for show expired alert */}
|
{/* this modal is used for show expired alert */}
|
||||||
<PdfDeclineModal
|
<PdfDeclineModal
|
||||||
show={isExpired}
|
show={isExpired}
|
||||||
|
doc={pdfDetails?.[0]}
|
||||||
headMsg={t("expired-doc-title")}
|
headMsg={t("expired-doc-title")}
|
||||||
bodyMssg={t("expired-on-mssg", { expiredDate })}
|
bodyMssg={t("expired-on-mssg", { expiredDate })}
|
||||||
isDownloadBtn={true}
|
isDownloadBtn={true}
|
||||||
handleDownloadBtn={handleDownloadBtn}
|
handleDownloadBtn={handleDownloadBtn}
|
||||||
|
handleExpiry={handleExpiry}
|
||||||
/>
|
/>
|
||||||
{!isEmailVerified && (
|
{!isEmailVerified && (
|
||||||
<VerifyEmail
|
<VerifyEmail
|
||||||
@@ -1922,7 +2041,7 @@ function PdfRequestFiles(props) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary ml-1"
|
||||||
>
|
>
|
||||||
{t("close")}
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
@@ -1944,15 +2063,12 @@ function PdfRequestFiles(props) {
|
|||||||
<RenderAllPdfPage
|
<RenderAllPdfPage
|
||||||
signerPos={signerPos}
|
signerPos={signerPos}
|
||||||
signerObjectId={signerObjectId}
|
signerObjectId={signerObjectId}
|
||||||
signPdfUrl={
|
|
||||||
pdfDetails[0] &&
|
|
||||||
(pdfDetails[0]?.SignedUrl || pdfDetails[0]?.URL)
|
|
||||||
}
|
|
||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
setAllPages={setAllPages}
|
setAllPages={setAllPages}
|
||||||
setPageNumber={setPageNumber}
|
setPageNumber={setPageNumber}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
containerWH={containerWH}
|
containerWH={containerWH}
|
||||||
|
pdfBase64Url={pdfBase64Url}
|
||||||
/>
|
/>
|
||||||
{/* pdf render view */}
|
{/* pdf render view */}
|
||||||
<div className=" w-full md:w-[57%] flex mr-4">
|
<div className=" w-full md:w-[57%] flex mr-4">
|
||||||
@@ -1960,6 +2076,7 @@ function PdfRequestFiles(props) {
|
|||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
isDisableRotate={true}
|
isDisableRotate={true}
|
||||||
|
isDisableDelete={true}
|
||||||
/>
|
/>
|
||||||
<div className=" w-full md:w-[95%] ">
|
<div className=" w-full md:w-[95%] ">
|
||||||
{/* this modal is used show this document is already sign */}
|
{/* this modal is used show this document is already sign */}
|
||||||
@@ -2065,7 +2182,9 @@ function PdfRequestFiles(props) {
|
|||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
{/* this component is used for signature pad modal */}
|
{/* this component is used for signature pad modal */}
|
||||||
|
{documentId && (
|
||||||
<SignPad
|
<SignPad
|
||||||
|
signatureTypes={signatureType}
|
||||||
isSignPad={isSignPad}
|
isSignPad={isSignPad}
|
||||||
isStamp={isStamp}
|
isStamp={isStamp}
|
||||||
setIsImageSelect={setIsImageSelect}
|
setIsImageSelect={setIsImageSelect}
|
||||||
@@ -2086,6 +2205,7 @@ function PdfRequestFiles(props) {
|
|||||||
currWidgetsDetails={currWidgetsDetails}
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
{/* pdf header which contain funish back button */}
|
{/* pdf header which contain funish back button */}
|
||||||
<Header
|
<Header
|
||||||
isPdfRequestFiles={isPublicTemplate ? false : true}
|
isPdfRequestFiles={isPublicTemplate ? false : true}
|
||||||
@@ -2150,6 +2270,7 @@ function PdfRequestFiles(props) {
|
|||||||
uniqueId={uniqueId}
|
uniqueId={uniqueId}
|
||||||
ispublicTemplate={isPublicTemplate}
|
ispublicTemplate={isPublicTemplate}
|
||||||
handleUserDetails={handleUserDetails}
|
handleUserDetails={handleUserDetails}
|
||||||
|
pdfBase64Url={pdfBase64Url}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2214,6 +2335,10 @@ function PdfRequestFiles(props) {
|
|||||||
setIsLoading={setIsLoading}
|
setIsLoading={setIsLoading}
|
||||||
xyPostion={signerPos}
|
xyPostion={signerPos}
|
||||||
setDefaultSignAlert={setDefaultSignAlert}
|
setDefaultSignAlert={setDefaultSignAlert}
|
||||||
|
isDefault={
|
||||||
|
signatureType?.find((x) => x.name === "default")
|
||||||
|
?.enabled || false
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,7 +38,11 @@ import {
|
|||||||
onClickZoomOut,
|
onClickZoomOut,
|
||||||
rotatePdfPage,
|
rotatePdfPage,
|
||||||
handleRemoveWidgets,
|
handleRemoveWidgets,
|
||||||
handleRotateWarning
|
handleRotateWarning,
|
||||||
|
signatureTypes,
|
||||||
|
handleSignatureType,
|
||||||
|
formatDate,
|
||||||
|
getBase64FromUrl
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@@ -137,7 +141,7 @@ function PlaceHolderSign() {
|
|||||||
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
||||||
const isHeader = useSelector((state) => state.showHeader);
|
const isHeader = useSelector((state) => state.showHeader);
|
||||||
const [activeMailAdapter, setActiveMailAdapter] = useState("");
|
const [activeMailAdapter, setActiveMailAdapter] = useState("");
|
||||||
const [isRotate, setIsRotate] = useState({
|
const [showRotateAlert, setShowRotateAlert] = useState({
|
||||||
status: false,
|
status: false,
|
||||||
degree: 0
|
degree: 0
|
||||||
});
|
});
|
||||||
@@ -149,30 +153,27 @@ function PlaceHolderSign() {
|
|||||||
const [isCustomize, setIsCustomize] = useState(false);
|
const [isCustomize, setIsCustomize] = useState(false);
|
||||||
const [zoomPercent, setZoomPercent] = useState(0);
|
const [zoomPercent, setZoomPercent] = useState(0);
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
const [pdfRotateBase64, setPdfRotatese64] = useState("");
|
const [pdfBase64Url, setPdfBase64Url] = useState("");
|
||||||
const [planCode, setPlanCode] = useState("");
|
const [planCode, setPlanCode] = useState("");
|
||||||
|
const [unSignedWidgetId, setUnSignedWidgetId] = useState("");
|
||||||
|
const [signatureType, setSignatureType] = useState(signatureTypes);
|
||||||
|
const [emailResetDate, setEmailResetDate] = useState("");
|
||||||
|
const [isUploadPdf, setIsUploadPdf] = useState(false);
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
accept: "BOX",
|
accept: "BOX",
|
||||||
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({ isOver: !!monitor.isOver() })
|
||||||
isOver: !!monitor.isOver()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const [{ isDragSign }, dragSignature] = useDrag({
|
const [{ isDragSign }, dragSignature] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: { type: "BOX", id: 1, text: "signature" },
|
item: { type: "BOX", id: 1, text: "signature" },
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({ isDragSign: !!monitor.isDragging() })
|
||||||
isDragSign: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [{ isDragStamp }, dragStamp] = useDrag({
|
const [{ isDragStamp }, dragStamp] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: { type: "BOX", id: 2, text: "stamp" },
|
item: { type: "BOX", id: 2, text: "stamp" },
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({ isDragStamp: !!monitor.isDragging() })
|
||||||
isDragStamp: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const documentId = docId;
|
const documentId = docId;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -201,10 +202,15 @@ function PlaceHolderSign() {
|
|||||||
if (tenantDetails && tenantDetails === "user does not exist!") {
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
alert(t("user-not-exist"));
|
alert(t("user-not-exist"));
|
||||||
} else if (tenantDetails) {
|
} else if (tenantDetails) {
|
||||||
|
const signatureType = tenantDetails?.SignatureType || [];
|
||||||
|
const filterSignTypes = signatureType?.filter(
|
||||||
|
(x) => x.enabled === true
|
||||||
|
);
|
||||||
if (tenantDetails?.RequestBody) {
|
if (tenantDetails?.RequestBody) {
|
||||||
setRequestBody(tenantDetails?.RequestBody);
|
setRequestBody(tenantDetails?.RequestBody);
|
||||||
setRequestSubject(tenantDetails?.RequestSubject);
|
setRequestSubject(tenantDetails?.RequestSubject);
|
||||||
}
|
}
|
||||||
|
return filterSignTypes;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(t("user-not-exist"));
|
alert(t("user-not-exist"));
|
||||||
@@ -255,18 +261,26 @@ function PlaceHolderSign() {
|
|||||||
}
|
}
|
||||||
//function for get document details
|
//function for get document details
|
||||||
const getDocumentDetails = async () => {
|
const getDocumentDetails = async () => {
|
||||||
fetchTenantDetails();
|
const tenantSignTypes = await fetchTenantDetails();
|
||||||
//getting document details
|
//getting document details
|
||||||
const documentData = await contractDocument(documentId);
|
const documentData = await contractDocument(documentId);
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
const url = documentData[0] && documentData[0]?.URL;
|
const url = documentData[0] && documentData[0]?.URL;
|
||||||
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
||||||
const arrayBuffer = await convertPdfArrayBuffer(url);
|
const arrayBuffer = await convertPdfArrayBuffer(url);
|
||||||
|
const base64Pdf = await getBase64FromUrl(url);
|
||||||
if (arrayBuffer === "Error") {
|
if (arrayBuffer === "Error") {
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
} else {
|
} else {
|
||||||
|
setPdfBase64Url(base64Pdf);
|
||||||
setPdfArrayBuffer(arrayBuffer);
|
setPdfArrayBuffer(arrayBuffer);
|
||||||
}
|
}
|
||||||
|
if (documentData[0]?.ExtUserPtr?.LastEmailCountReset?.iso) {
|
||||||
|
const resetDate = formatDate(
|
||||||
|
documentData[0]?.ExtUserPtr?.LastEmailCountReset?.iso
|
||||||
|
);
|
||||||
|
setEmailResetDate(resetDate);
|
||||||
|
}
|
||||||
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
|
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
||||||
@@ -312,7 +326,18 @@ function PlaceHolderSign() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setPdfDetails(documentData);
|
const userSignatureType =
|
||||||
|
documentData[0]?.ExtUserPtr?.SignatureType || signatureTypes;
|
||||||
|
const docSignTypes =
|
||||||
|
documentData?.[0]?.SignatureType || userSignatureType;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
docSignTypes
|
||||||
|
);
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
const updatedPdfDetails = [...documentData];
|
||||||
|
updatedPdfDetails[0].SignatureType = updatedSignatureType;
|
||||||
|
setPdfDetails(updatedPdfDetails);
|
||||||
//condition when placeholder have empty array with role details and signers array have signers data
|
//condition when placeholder have empty array with role details and signers array have signers data
|
||||||
//and both array length are same
|
//and both array length are same
|
||||||
//this case happen using placeholder form in auto save funtionality to save draft type document without adding any placehlder
|
//this case happen using placeholder form in auto save funtionality to save draft type document without adding any placehlder
|
||||||
@@ -475,8 +500,10 @@ function PlaceHolderSign() {
|
|||||||
let dropData = [];
|
let dropData = [];
|
||||||
let placeHolder;
|
let placeHolder;
|
||||||
const dragTypeValue = item?.text ? item.text : monitor.type;
|
const dragTypeValue = item?.text ? item.text : monitor.type;
|
||||||
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
|
const widgetWidth =
|
||||||
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
|
defaultWidthHeight(dragTypeValue).width * containerScale;
|
||||||
|
const widgetHeight =
|
||||||
|
defaultWidthHeight(dragTypeValue).height * containerScale;
|
||||||
//adding and updating drop position in array when user drop signature button in div
|
//adding and updating drop position in array when user drop signature button in div
|
||||||
if (item === "onclick") {
|
if (item === "onclick") {
|
||||||
const divHeight = divRef.current.getBoundingClientRect().height;
|
const divHeight = divRef.current.getBoundingClientRect().height;
|
||||||
@@ -565,10 +592,21 @@ function PlaceHolderSign() {
|
|||||||
}
|
}
|
||||||
setSignerPos(updatesignerPos);
|
setSignerPos(updatesignerPos);
|
||||||
} else {
|
} else {
|
||||||
let updatesignerPos;
|
|
||||||
//if condition when widget type is prefill label text widget
|
//if condition when widget type is prefill label text widget
|
||||||
if (dragTypeValue === textWidget) {
|
if (dragTypeValue === textWidget) {
|
||||||
const prefileTextWidget = {
|
//check text widgets data (prefill) already exist then and want to add text widget on new page
|
||||||
|
//create new page entry with old data and update placeholder
|
||||||
|
if (filterSignerPos) {
|
||||||
|
const addPrefillData =
|
||||||
|
filterSignerPos && filterSignerPos?.placeHolder;
|
||||||
|
addPrefillData.push(placeHolder);
|
||||||
|
const updatePrefillPos = signerPos.map((x) =>
|
||||||
|
x.Role === "prefill" ? { ...x, placeHolder: addPrefillData } : x
|
||||||
|
);
|
||||||
|
setSignerPos(updatePrefillPos);
|
||||||
|
} //else condition if user do not have any text widget data
|
||||||
|
else {
|
||||||
|
const prefillTextWidget = {
|
||||||
signerPtr: {},
|
signerPtr: {},
|
||||||
signerObjId: "",
|
signerObjId: "",
|
||||||
blockColor: "#f58f8c",
|
blockColor: "#f58f8c",
|
||||||
@@ -576,11 +614,11 @@ function PlaceHolderSign() {
|
|||||||
Role: "prefill",
|
Role: "prefill",
|
||||||
Id: key
|
Id: key
|
||||||
};
|
};
|
||||||
signerPos.push(prefileTextWidget);
|
setSignerPos((prev) => [...prev, prefillTextWidget]);
|
||||||
setSignerPos(signerPos);
|
}
|
||||||
} else {
|
} else {
|
||||||
//else condition to add placeholder widgets on multiple page first time
|
//else condition to add placeholder widgets on multiple page first time
|
||||||
updatesignerPos = signerPos.map((x) =>
|
const updatesignerPos = signerPos.map((x) =>
|
||||||
x.Id === uniqueId && x?.placeHolder
|
x.Id === uniqueId && x?.placeHolder
|
||||||
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
|
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
|
||||||
: x.Id === uniqueId
|
: x.Id === uniqueId
|
||||||
@@ -755,8 +793,10 @@ function PlaceHolderSign() {
|
|||||||
signerupdate.push(newUpdatePos[0]);
|
signerupdate.push(newUpdatePos[0]);
|
||||||
setSignerPos(signerupdate);
|
setSignerPos(signerupdate);
|
||||||
} else {
|
} else {
|
||||||
const updatedData = signerPos.map((item) => {
|
const updatedData = signerPos
|
||||||
if (item.Id === Id) {
|
.filter((item) => !(item.Id === Id && item.Role === "prefill")) // Remove prefill object
|
||||||
|
.map((item) => {
|
||||||
|
if (item.Id === Id && item.Role !== "prefill") {
|
||||||
// Create a copy of the item object and delete the placeHolder field
|
// Create a copy of the item object and delete the placeHolder field
|
||||||
const updatedItem = { ...item };
|
const updatedItem = { ...item };
|
||||||
delete updatedItem.placeHolder;
|
delete updatedItem.placeHolder;
|
||||||
@@ -813,9 +853,7 @@ function PlaceHolderSign() {
|
|||||||
placeholder,
|
placeholder,
|
||||||
pdfDoc,
|
pdfDoc,
|
||||||
isSignYourSelfFlow,
|
isSignYourSelfFlow,
|
||||||
scale,
|
scale
|
||||||
pdfOriginalWH,
|
|
||||||
containerWH
|
|
||||||
);
|
);
|
||||||
const pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64);
|
const pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64);
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
@@ -825,15 +863,12 @@ function PlaceHolderSign() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error to convertBase64ToFile in placeholder flow", e);
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
}
|
}
|
||||||
} else if (pdfRotateBase64) {
|
} else if (pdfBase64Url) {
|
||||||
try {
|
try {
|
||||||
const pdfUrl = await convertBase64ToFile(
|
const pdfUrl = await convertBase64ToFile(
|
||||||
pdfDetails[0].Name,
|
pdfDetails[0].Name,
|
||||||
pdfRotateBase64
|
pdfBase64Url
|
||||||
);
|
);
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
|
||||||
const buffer = atob(pdfRotateBase64);
|
|
||||||
SaveFileSize(buffer.length, pdfUrl, tenantId);
|
|
||||||
return pdfUrl;
|
return pdfUrl;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error to convertBase64ToFile in placeholder flow", e);
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
@@ -844,17 +879,24 @@ function PlaceHolderSign() {
|
|||||||
};
|
};
|
||||||
const alertSendEmail = async () => {
|
const alertSendEmail = async () => {
|
||||||
const filterPrefill = signerPos?.filter((data) => data.Role !== "prefill");
|
const filterPrefill = signerPos?.filter((data) => data.Role !== "prefill");
|
||||||
const getPrefill = signerPos?.filter((data) => data.Role === "prefill");
|
const getPrefill = signerPos?.find((data) => data.Role === "prefill");
|
||||||
let isLabel = false;
|
let isLabel = false;
|
||||||
|
let unfilledTextWidgetId = "";
|
||||||
//checking all signers placeholder exist or not
|
//checking all signers placeholder exist or not
|
||||||
const isPlaceholderExist = filterPrefill.every((data) => data.placeHolder);
|
const isPlaceholderExist = filterPrefill.every((data) => data.placeHolder);
|
||||||
const prefillPlaceholder = getPrefill[0]?.placeHolder;
|
const prefillPlaceholder = getPrefill?.placeHolder;
|
||||||
//condition is used to check text widget data is empty or have response
|
//condition is used to check text widget data is empty or have response
|
||||||
if (getPrefill && getPrefill.length > 0) {
|
if (getPrefill) {
|
||||||
if (prefillPlaceholder) {
|
if (prefillPlaceholder) {
|
||||||
prefillPlaceholder.map((data) => {
|
prefillPlaceholder.map((data) => {
|
||||||
if (!isLabel) {
|
if (!isLabel) {
|
||||||
isLabel = data.pos.some((position) => !position.options.response);
|
const unfilledTextWidgets = data.pos.find(
|
||||||
|
(position) => !position.options.response
|
||||||
|
);
|
||||||
|
if (unfilledTextWidgets) {
|
||||||
|
isLabel = true;
|
||||||
|
unfilledTextWidgetId = unfilledTextWidgets.key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -882,6 +924,7 @@ function PlaceHolderSign() {
|
|||||||
}
|
}
|
||||||
if (getPrefill && isLabel) {
|
if (getPrefill && isLabel) {
|
||||||
setIsSendAlert({ mssg: textWidget, alert: true });
|
setIsSendAlert({ mssg: textWidget, alert: true });
|
||||||
|
setUnSignedWidgetId(unfilledTextWidgetId);
|
||||||
} else if (isSignatureExist) {
|
} else if (isSignatureExist) {
|
||||||
if (isPlaceholderExist) {
|
if (isPlaceholderExist) {
|
||||||
const IsSignerNotExist = filterPrefill?.filter((x) => !x.signerObjId);
|
const IsSignerNotExist = filterPrefill?.filter((x) => !x.signerObjId);
|
||||||
@@ -898,33 +941,42 @@ function PlaceHolderSign() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
if (signerPos?.length > 0) {
|
if (signerPos?.length > 0 && !pdfDetails?.[0]?.IsCompleted) {
|
||||||
autosavedetails();
|
autosavedetails();
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [signerPos, signersdata]);
|
}, [signerPos, signersdata, signatureType, pdfBase64Url]);
|
||||||
|
|
||||||
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
||||||
const autosavedetails = async () => {
|
const autosavedetails = async () => {
|
||||||
const signers = signersdata?.filter(
|
const signers = signersdata?.reduce((acc, x) => {
|
||||||
(x) =>
|
if (x.objectId) {
|
||||||
x?.Role !== "prefill" &&
|
acc.push({
|
||||||
x.objectId && {
|
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "contracts_Contactbook",
|
className: "contracts_Contactbook",
|
||||||
objectId: x.objectId
|
objectId: x.objectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
let pdfUrl;
|
||||||
|
if (isUploadPdf) {
|
||||||
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64Url);
|
||||||
}
|
}
|
||||||
);
|
|
||||||
try {
|
try {
|
||||||
const docCls = new Parse.Object("contracts_Document");
|
const docCls = new Parse.Object("contracts_Document");
|
||||||
docCls.id = documentId;
|
docCls.id = documentId;
|
||||||
docCls.set("Placeholders", signerPos);
|
docCls.set("Placeholders", signerPos);
|
||||||
docCls.set("Signers", signers);
|
docCls.set("Signers", signers);
|
||||||
|
docCls.set("SignatureType", signatureType);
|
||||||
|
if (pdfUrl) {
|
||||||
|
docCls.set("URL", pdfUrl);
|
||||||
|
}
|
||||||
|
|
||||||
await docCls.save();
|
await docCls.save();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error", e);
|
console.log("error", e);
|
||||||
@@ -964,21 +1016,15 @@ function PlaceHolderSign() {
|
|||||||
//filter label widgets after add label widgets data on pdf
|
//filter label widgets after add label widgets data on pdf
|
||||||
const filterPrefill = signerPos.filter((data) => data.Role !== "prefill");
|
const filterPrefill = signerPos.filter((data) => data.Role !== "prefill");
|
||||||
try {
|
try {
|
||||||
if (updateExpiryDate) {
|
|
||||||
data = {
|
data = {
|
||||||
Placeholders: filterPrefill,
|
Placeholders: filterPrefill,
|
||||||
SignedUrl: pdfUrl,
|
SignedUrl: pdfUrl,
|
||||||
Signers: signers,
|
Signers: signers,
|
||||||
SentToOthers: true,
|
SentToOthers: true,
|
||||||
ExpiryDate: { iso: updateExpiryDate, __type: "Date" }
|
SignatureType: pdfDetails?.[0]?.SignatureType
|
||||||
};
|
|
||||||
} else {
|
|
||||||
data = {
|
|
||||||
Placeholders: filterPrefill,
|
|
||||||
SignedUrl: pdfUrl,
|
|
||||||
Signers: signers,
|
|
||||||
SentToOthers: true
|
|
||||||
};
|
};
|
||||||
|
if (updateExpiryDate) {
|
||||||
|
data["ExpiryDate"] = { iso: updateExpiryDate, __type: "Date" };
|
||||||
}
|
}
|
||||||
await axios
|
await axios
|
||||||
.put(
|
.put(
|
||||||
@@ -1121,7 +1167,7 @@ function PlaceHolderSign() {
|
|||||||
receiver_phone: signerMail[i]?.Phone || "",
|
receiver_phone: signerMail[i]?.Phone || "",
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: orgName,
|
company_name: orgName,
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||||
};
|
};
|
||||||
replaceVar = replaceMailVaribles(
|
replaceVar = replaceMailVaribles(
|
||||||
requestSubject,
|
requestSubject,
|
||||||
@@ -1155,7 +1201,7 @@ function PlaceHolderSign() {
|
|||||||
orgName +
|
orgName +
|
||||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||||
localExpireDate +
|
localExpireDate +
|
||||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||||
signPdf +
|
signPdf +
|
||||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
senderEmail +
|
senderEmail +
|
||||||
@@ -1330,7 +1376,7 @@ function PlaceHolderSign() {
|
|||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1368,7 +1414,7 @@ function PlaceHolderSign() {
|
|||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1386,7 +1432,7 @@ function PlaceHolderSign() {
|
|||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1420,7 +1466,15 @@ function PlaceHolderSign() {
|
|||||||
setFontSize();
|
setFontSize();
|
||||||
setFontColor();
|
setFontColor();
|
||||||
};
|
};
|
||||||
const handleWidgetdefaultdata = (defaultdata) => {
|
const handleWidgetdefaultdata = (defaultdata, isSignWidget) => {
|
||||||
|
if (isSignWidget) {
|
||||||
|
const updatedPdfDetails = [...pdfDetails];
|
||||||
|
const signtypes = defaultdata.signatureType || signatureType;
|
||||||
|
updatedPdfDetails[0].SignatureType = signtypes;
|
||||||
|
// Update the SignatureType with the modified array
|
||||||
|
setPdfDetails(updatedPdfDetails);
|
||||||
|
setSignatureType(signtypes);
|
||||||
|
}
|
||||||
const options = ["email", "number", "text"];
|
const options = ["email", "number", "text"];
|
||||||
let inputype;
|
let inputype;
|
||||||
if (defaultdata.textvalidate) {
|
if (defaultdata.textvalidate) {
|
||||||
@@ -1459,7 +1513,7 @@ function PlaceHolderSign() {
|
|||||||
}
|
}
|
||||||
: {},
|
: {},
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1475,7 +1529,7 @@ function PlaceHolderSign() {
|
|||||||
status: defaultdata.status,
|
status: defaultdata.status,
|
||||||
defaultValue: defaultdata.defaultValue,
|
defaultValue: defaultdata.defaultValue,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1541,14 +1595,12 @@ function PlaceHolderSign() {
|
|||||||
} else {
|
} else {
|
||||||
updatedTourStatus = [{ placeholder: true }];
|
updatedTourStatus = [{ placeholder: true }];
|
||||||
}
|
}
|
||||||
await axios
|
try {
|
||||||
.put(
|
await axios.put(
|
||||||
`${localStorage.getItem(
|
`${localStorage.getItem(
|
||||||
"baseUrl"
|
"baseUrl"
|
||||||
)}classes/contracts_Users/${signerUserId}`,
|
)}classes/contracts_Users/${signerUserId}`,
|
||||||
{
|
{ TourStatus: updatedTourStatus },
|
||||||
TourStatus: updatedTourStatus
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -1556,14 +1608,10 @@ function PlaceHolderSign() {
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
.then(() => {
|
} catch (err) {
|
||||||
// const json = Listdata.data;
|
|
||||||
// const res = json.results;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
console.log("axois err ", err);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleRecipientSign = () => {
|
const handleRecipientSign = () => {
|
||||||
@@ -1648,8 +1696,15 @@ function PlaceHolderSign() {
|
|||||||
const signerAssignTour = [
|
const signerAssignTour = [
|
||||||
{
|
{
|
||||||
selector: '[data-tut="assignSigner"]',
|
selector: '[data-tut="assignSigner"]',
|
||||||
content:
|
content: t("attach-signer-tour"),
|
||||||
"You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour. ",
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const textFieldTour = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="IsSigned"]',
|
||||||
|
content: t("text-field-tour"),
|
||||||
position: "top",
|
position: "top",
|
||||||
style: { fontSize: "13px" }
|
style: { fontSize: "13px" }
|
||||||
}
|
}
|
||||||
@@ -1694,30 +1749,36 @@ function PlaceHolderSign() {
|
|||||||
};
|
};
|
||||||
//`handleRotationFun` function is used to roatate pdf particular page
|
//`handleRotationFun` function is used to roatate pdf particular page
|
||||||
const handleRotationFun = async (rotateDegree) => {
|
const handleRotationFun = async (rotateDegree) => {
|
||||||
const isRotate = handleRotateWarning(signerPos, pageNumber);
|
const rotatePlaceholderExist = handleRotateWarning(signerPos, pageNumber);
|
||||||
if (isRotate) {
|
//show rotation alert if widgets already exist
|
||||||
setIsRotate({ status: true, degree: rotateDegree });
|
if (rotatePlaceholderExist) {
|
||||||
|
setShowRotateAlert({ status: true, degree: rotateDegree });
|
||||||
} else {
|
} else {
|
||||||
|
setIsUploadPdf(true);
|
||||||
const urlDetails = await rotatePdfPage(
|
const urlDetails = await rotatePdfPage(
|
||||||
pdfDetails[0].URL,
|
|
||||||
rotateDegree,
|
rotateDegree,
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfBase64Url
|
||||||
);
|
);
|
||||||
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleRemovePlaceholder = async () => {
|
const handleRemovePlaceholder = async () => {
|
||||||
handleRemoveWidgets(setSignerPos, signerPos, pageNumber, setIsRotate);
|
handleRemoveWidgets(
|
||||||
|
setSignerPos,
|
||||||
|
signerPos,
|
||||||
|
pageNumber,
|
||||||
|
uniqueId,
|
||||||
|
setShowRotateAlert
|
||||||
|
);
|
||||||
const urlDetails = await rotatePdfPage(
|
const urlDetails = await rotatePdfPage(
|
||||||
pdfDetails[0].URL,
|
showRotateAlert.degree,
|
||||||
isRotate.degree,
|
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfArrayBuffer
|
||||||
);
|
);
|
||||||
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -1759,6 +1820,13 @@ function PlaceHolderSign() {
|
|||||||
rounded={5}
|
rounded={5}
|
||||||
closeWithMask={false}
|
closeWithMask={false}
|
||||||
/>
|
/>
|
||||||
|
<Tour
|
||||||
|
onRequestClose={() => setIsSendAlert({})}
|
||||||
|
steps={textFieldTour}
|
||||||
|
isOpen={isSendAlert.mssg === textWidget}
|
||||||
|
rounded={5}
|
||||||
|
closeWithMask={false}
|
||||||
|
/>
|
||||||
{/* this component used to render all pdf pages in left side */}
|
{/* this component used to render all pdf pages in left side */}
|
||||||
<RenderAllPdfPage
|
<RenderAllPdfPage
|
||||||
signPdfUrl={pdfDetails[0].URL}
|
signPdfUrl={pdfDetails[0].URL}
|
||||||
@@ -1767,7 +1835,7 @@ function PlaceHolderSign() {
|
|||||||
setPageNumber={setPageNumber}
|
setPageNumber={setPageNumber}
|
||||||
setSignBtnPosition={setSignBtnPosition}
|
setSignBtnPosition={setSignBtnPosition}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
pdfRotateBase64={pdfRotateBase64}
|
pdfBase64Url={pdfBase64Url}
|
||||||
/>
|
/>
|
||||||
{/* pdf render view */}
|
{/* pdf render view */}
|
||||||
<div className=" w-full md:w-[57%] flex mr-4">
|
<div className=" w-full md:w-[57%] flex mr-4">
|
||||||
@@ -1775,24 +1843,30 @@ function PlaceHolderSign() {
|
|||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
handleRotationFun={handleRotationFun}
|
handleRotationFun={handleRotationFun}
|
||||||
|
pdfArrayBuffer={pdfArrayBuffer}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
setPdfBase64Url={setPdfBase64Url}
|
||||||
|
setPdfArrayBuffer={setPdfArrayBuffer}
|
||||||
|
setIsUploadPdf={setIsUploadPdf}
|
||||||
|
setSignerPos={setSignerPos}
|
||||||
|
signerPos={signerPos}
|
||||||
|
userId={uniqueId}
|
||||||
/>
|
/>
|
||||||
<div className=" w-full md:w-[95%] ">
|
<div className=" w-full md:w-[95%] ">
|
||||||
{/* this modal is used show alert set placeholder for all signers before send mail */}
|
{/* this modal is used show alert set placeholder for all signers before send mail */}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isSendAlert.alert}
|
isOpen={
|
||||||
|
isSendAlert.alert && isSendAlert.mssg !== textWidget
|
||||||
|
}
|
||||||
title={
|
title={
|
||||||
isSendAlert.mssg === "sure" ||
|
isSendAlert.mssg === "sure" ||
|
||||||
isSendAlert.mssg === textWidget
|
(isSendAlert.mssg === "confirm" && t("send-mail"))
|
||||||
? t("fields-required")
|
|
||||||
: isSendAlert.mssg === "confirm" && t("send-mail")
|
|
||||||
}
|
}
|
||||||
handleClose={() => handleCloseSendmailModal()}
|
handleClose={() => handleCloseSendmailModal()}
|
||||||
>
|
>
|
||||||
<div className="max-h-96 overflow-y-scroll scroll-hide p-[20px] text-base-content">
|
<div className="max-h-96 overflow-y-scroll scroll-hide p-[20px] text-base-content">
|
||||||
{isSendAlert.mssg === "sure" ? (
|
{isSendAlert.mssg === "sure" ? (
|
||||||
<span>{t("placeholder-alert-1")}</span>
|
<span>{t("placeholder-alert-1")}</span>
|
||||||
) : isSendAlert.mssg === textWidget ? (
|
|
||||||
<p>{t("placeholder-alert-2")}</p>
|
|
||||||
) : (
|
) : (
|
||||||
isSendAlert.mssg === "confirm" && (
|
isSendAlert.mssg === "confirm" && (
|
||||||
<>
|
<>
|
||||||
@@ -1873,9 +1947,11 @@ function PlaceHolderSign() {
|
|||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isSend}
|
isOpen={isSend}
|
||||||
title={
|
title={
|
||||||
mailStatus === "quotareached"
|
mailStatus === "success"
|
||||||
|
? t("mails-sent")
|
||||||
|
: mailStatus === "quotareached"
|
||||||
? t("quota-mail-head")
|
? t("quota-mail-head")
|
||||||
: t("Mails Sent")
|
: t("mail-not-delivered")
|
||||||
}
|
}
|
||||||
handleClose={() => {
|
handleClose={() => {
|
||||||
setIsSend(false);
|
setIsSend(false);
|
||||||
@@ -1893,6 +1969,7 @@ function PlaceHolderSign() {
|
|||||||
) : mailStatus === "quotareached" ? (
|
) : mailStatus === "quotareached" ? (
|
||||||
<div className="flex flex-col gap-y-3">
|
<div className="flex flex-col gap-y-3">
|
||||||
<QuotaCard
|
<QuotaCard
|
||||||
|
emailResetDate={emailResetDate}
|
||||||
handleClose={() => {
|
handleClose={() => {
|
||||||
setIsSend(false);
|
setIsSend(false);
|
||||||
setSignerPos([]);
|
setSignerPos([]);
|
||||||
@@ -1902,7 +1979,12 @@ function PlaceHolderSign() {
|
|||||||
<div className="my-3">{handleShareList()}</div>
|
<div className="my-3">{handleShareList()}</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="mb-[10px]">
|
||||||
<p>{t("placeholder-alert-6")}</p>
|
<p>{t("placeholder-alert-6")}</p>
|
||||||
|
{isCurrUser && (
|
||||||
|
<p className="mt-1">{t("placeholder-alert-5")}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{!mailStatus && (
|
{!mailStatus && (
|
||||||
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
|
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
|
||||||
@@ -2018,6 +2100,7 @@ function PlaceHolderSign() {
|
|||||||
|
|
||||||
{/* pdf header which contain funish back button */}
|
{/* pdf header which contain funish back button */}
|
||||||
<Header
|
<Header
|
||||||
|
completeBtnTitle={t("next")}
|
||||||
isPlaceholder={true}
|
isPlaceholder={true}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
@@ -2032,6 +2115,12 @@ function PlaceHolderSign() {
|
|||||||
handleRotationFun={handleRotationFun}
|
handleRotationFun={handleRotationFun}
|
||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
|
setIsUploadPdf={setIsUploadPdf}
|
||||||
|
pdfArrayBuffer={pdfArrayBuffer}
|
||||||
|
setPdfArrayBuffer={setPdfArrayBuffer}
|
||||||
|
setPdfBase64Url={setPdfBase64Url}
|
||||||
|
setSignerPos={setSignerPos}
|
||||||
|
userId={uniqueId}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -2058,6 +2147,7 @@ function PlaceHolderSign() {
|
|||||||
setSignerPos={setSignerPos}
|
setSignerPos={setSignerPos}
|
||||||
containerWH={containerWH}
|
containerWH={containerWH}
|
||||||
setIsResize={setIsResize}
|
setIsResize={setIsResize}
|
||||||
|
isResize={isResize}
|
||||||
setZIndex={setZIndex}
|
setZIndex={setZIndex}
|
||||||
setIsPageCopy={setIsPageCopy}
|
setIsPageCopy={setIsPageCopy}
|
||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
@@ -2079,11 +2169,12 @@ function PlaceHolderSign() {
|
|||||||
setScale={setScale}
|
setScale={setScale}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
pdfRotateBase64={pdfRotateBase64}
|
pdfBase64Url={pdfBase64Url}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
unSignedWidgetId={unSignedWidgetId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2208,6 +2299,7 @@ function PlaceHolderSign() {
|
|||||||
signersData={signersdata}
|
signersData={signersdata}
|
||||||
/>
|
/>
|
||||||
<WidgetNameModal
|
<WidgetNameModal
|
||||||
|
signatureType={signatureType}
|
||||||
widgetName={widgetName}
|
widgetName={widgetName}
|
||||||
defaultdata={currWidgetsDetails}
|
defaultdata={currWidgetsDetails}
|
||||||
isOpen={isNameModal}
|
isOpen={isNameModal}
|
||||||
@@ -2222,8 +2314,8 @@ function PlaceHolderSign() {
|
|||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
/>
|
/>
|
||||||
<RotateAlert
|
<RotateAlert
|
||||||
isRotate={isRotate.status}
|
showRotateAlert={showRotateAlert.status}
|
||||||
setIsRotate={setIsRotate}
|
setShowRotateAlert={setShowRotateAlert}
|
||||||
handleRemoveWidgets={handleRemovePlaceholder}
|
handleRemoveWidgets={handleRemovePlaceholder}
|
||||||
/>
|
/>
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
|
|||||||
@@ -0,0 +1,314 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Title from "../components/Title";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import Loader from "../primitives/Loader";
|
||||||
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
import {
|
||||||
|
checkIsSubscribed,
|
||||||
|
getTenantDetails,
|
||||||
|
handleSignatureType,
|
||||||
|
signatureTypes
|
||||||
|
} from "../constant/Utils";
|
||||||
|
import Parse from "parse";
|
||||||
|
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import Upgrade from "../primitives/Upgrade";
|
||||||
|
const Preferences = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [isalert, setIsAlert] = useState({ type: "success", msg: "" });
|
||||||
|
const [isTopLoader, setIsTopLoader] = useState(false);
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
|
const [signatureType, setSignatureType] = useState([]);
|
||||||
|
const [errMsg, setErrMsg] = useState("");
|
||||||
|
const [isNotifyOnSignatures, setIsNotifyOnSignatures] = useState();
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSignType();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchSignType = async () => {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const subscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(subscribe.isValid);
|
||||||
|
} else {
|
||||||
|
setIsSubscribe(true);
|
||||||
|
}
|
||||||
|
setIsTopLoader(true);
|
||||||
|
try {
|
||||||
|
const user = JSON.parse(
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const tenantDetails = await getTenantDetails(user?.objectId);
|
||||||
|
const signatureType = tenantDetails?.SignatureType || [];
|
||||||
|
const tenantSignTypes = signatureType?.filter((x) => x.enabled === true);
|
||||||
|
const getUser = await Parse.Cloud.run("getUserDetails");
|
||||||
|
if (getUser) {
|
||||||
|
const _getUser = JSON.parse(JSON.stringify(getUser));
|
||||||
|
const notifyOnSignatures =
|
||||||
|
_getUser?.NotifyOnSignatures !== undefined
|
||||||
|
? _getUser?.NotifyOnSignatures
|
||||||
|
: "";
|
||||||
|
setIsNotifyOnSignatures(notifyOnSignatures);
|
||||||
|
if (tenantSignTypes?.length > 0) {
|
||||||
|
const signatureType = _getUser?.SignatureType || signatureTypes;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
signatureType
|
||||||
|
);
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
} else {
|
||||||
|
const SignatureType = _getUser?.SignatureType || signatureTypes;
|
||||||
|
setSignatureType(SignatureType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err while getting user details", err);
|
||||||
|
setErrMsg("Something went wrong");
|
||||||
|
} finally {
|
||||||
|
setIsTopLoader(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleCheckboxChange` is trigger when user enable/disable checkbox of respective type
|
||||||
|
const handleCheckboxChange = (index) => {
|
||||||
|
// Create a copy of the signatureType array
|
||||||
|
const updatedSignatureType = [...signatureType];
|
||||||
|
// Toggle the enabled value for the clicked item
|
||||||
|
updatedSignatureType[index].enabled = !updatedSignatureType[index].enabled;
|
||||||
|
// Update the state with the modified array
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleSave` is used save updated value signature type
|
||||||
|
const handleSave = async () => {
|
||||||
|
setIsLoader(true);
|
||||||
|
if (signatureType.length > 0 || isNotifyOnSignatures) {
|
||||||
|
let params = {};
|
||||||
|
if (signatureType.length > 0) {
|
||||||
|
const enabledSignTypes = signatureType?.filter((x) => x.enabled);
|
||||||
|
const isDefaultSignTypeOnly =
|
||||||
|
enabledSignTypes?.length === 1 &&
|
||||||
|
enabledSignTypes[0]?.name === "default";
|
||||||
|
if (enabledSignTypes.length === 0) {
|
||||||
|
setIsAlert({
|
||||||
|
type: "danger",
|
||||||
|
msg: t("at-least-one-signature-type")
|
||||||
|
});
|
||||||
|
} else if (isDefaultSignTypeOnly) {
|
||||||
|
setIsAlert({
|
||||||
|
type: "danger",
|
||||||
|
msg: t("expect-default-one-more-signature-type")
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
params = { ...params, SignatureType: signatureType };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNotifyOnSignatures) {
|
||||||
|
params = { ...params, NotifyOnSignatures: isNotifyOnSignatures };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const updateRes = await Parse.Cloud.run("updatepreferences", params);
|
||||||
|
if (updateRes) {
|
||||||
|
setIsAlert({ type: "success", msg: "Saved successfully." });
|
||||||
|
let extUser =
|
||||||
|
localStorage.getItem("Extand_Class") &&
|
||||||
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
|
if (extUser && extUser?.objectId) {
|
||||||
|
extUser.NotifyOnSignatures = isNotifyOnSignatures;
|
||||||
|
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||||
|
localStorage.setItem("Extand_Class", JSON.stringify([_extUser]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Error updating signature type", err);
|
||||||
|
setIsAlert({ type: "danger", msg: err.message });
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `handleNotifySignChange` is trigger when user change radio of notify on signatures
|
||||||
|
const handleNotifySignChange = (value) => {
|
||||||
|
setIsNotifyOnSignatures(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Title title={t("Preferences")} />
|
||||||
|
{isalert.msg && <Alert type={isalert.type}>{isalert.msg}</Alert>}
|
||||||
|
{isTopLoader ? (
|
||||||
|
<div className="flex justify-center items-center h-screen">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{errMsg ? (
|
||||||
|
<div className="flex justify-center items-center h-screen">
|
||||||
|
{errMsg}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="relative bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
|
||||||
|
{isLoader && (
|
||||||
|
<div className="flex justify-center items-center absolute w-full h-full rounded-box bg-black/30">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
||||||
|
OpenSign™ {t("Preferences")}{" "}
|
||||||
|
<span>
|
||||||
|
<Tooltip
|
||||||
|
message={`OpenSign™ ${t("Preferences")}`}
|
||||||
|
isSubscribe={true}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<div className="ml-4 mt-1 mb-2 flex flex-col">
|
||||||
|
<div className="mb-[0.75rem]">
|
||||||
|
<label
|
||||||
|
htmlFor="signaturetype"
|
||||||
|
className="text-[14px] mb-[0.7rem] font-medium"
|
||||||
|
>
|
||||||
|
{t("allowed-signature-types")}
|
||||||
|
<a data-tooltip-id="signtypes-tooltip" className="ml-1">
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
<ReactTooltip id="signtypes-tooltip" className="z-[999]">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||||
|
<p className="font-bold">
|
||||||
|
{t("allowed-signature-types")}
|
||||||
|
</p>
|
||||||
|
<p>{t("allowed-signature-types-help.p1")}</p>
|
||||||
|
<p className="p-[5px] ml-2">
|
||||||
|
<ol className="list-disc">
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">Draw: </span>
|
||||||
|
<span>
|
||||||
|
{t("allowed-signature-types-help.l1")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">Typed: </span>
|
||||||
|
<span>
|
||||||
|
{t("allowed-signature-types-help.l2")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">Upload: </span>
|
||||||
|
<span>
|
||||||
|
{t("allowed-signature-types-help.l3")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">Default: </span>
|
||||||
|
<span>
|
||||||
|
{t("allowed-signature-types-help.l4")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
</label>
|
||||||
|
<div className=" ml-[7px] flex flex-col md:flex-row gap-[10px] mb-[0.7rem]">
|
||||||
|
{signatureType.map((type, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="flex flex-row gap-[5px] items-center"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-checkbox op-checkbox-xs"
|
||||||
|
type="checkbox"
|
||||||
|
name="signaturetype"
|
||||||
|
onChange={() => handleCheckboxChange(i)}
|
||||||
|
checked={type.enabled}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="text-[13px] font-medium hover:underline underline-offset-2 cursor-default capitalize"
|
||||||
|
title={`Enabling this allow signers to ${type.name} signature`}
|
||||||
|
>
|
||||||
|
{type.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-[0.75rem]">
|
||||||
|
<label
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "text-gray-300"
|
||||||
|
} text-[14px] mb-[0.7rem] font-medium`}
|
||||||
|
>
|
||||||
|
{t("notify-on-signatures")}
|
||||||
|
<a data-tooltip-id="nos-tooltip" className="ml-1">
|
||||||
|
<sup>
|
||||||
|
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
<ReactTooltip id="nos-tooltip" className="z-[999]">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||||
|
<p className="font-bold">{t("notify-on-signatures")}</p>
|
||||||
|
<p>{t("notify-on-signatures-help.p1")}</p>
|
||||||
|
<p>{t("notify-on-signatures-help.note")}</p>
|
||||||
|
</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(true)}
|
||||||
|
checked={isNotifyOnSignatures === true}
|
||||||
|
/>
|
||||||
|
<div className="text-[13px] font-medium cursor-default capitalize">
|
||||||
|
{t("yes")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-4">
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[2px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
onChange={() => handleNotifySignChange(false)}
|
||||||
|
checked={isNotifyOnSignatures === false}
|
||||||
|
/>
|
||||||
|
<div className="text-[13px] font-medium cursor-default capitalize">
|
||||||
|
{t("no")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-[0.75rem]">
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Preferences;
|
||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import { fetchSubscription } from "../constant/Utils";
|
import { fetchSubscription } from "../constant/Utils";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
@@ -88,6 +88,9 @@ const SSOVerify = () => {
|
|||||||
// `handleSubmitbtn` is used to create a user in the extended class
|
// `handleSubmitbtn` is used to create a user in the extended class
|
||||||
const handleSubmitbtn = async (e) => {
|
const handleSubmitbtn = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (!emailRegex.test(userDetails.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
let phone;
|
let phone;
|
||||||
if (userDetails?.phone) {
|
if (userDetails?.phone) {
|
||||||
@@ -137,6 +140,7 @@ const SSOVerify = () => {
|
|||||||
alert(t("filed-required-correctly"));
|
alert(t("filed-required-correctly"));
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// `thirdpartyLoginfn` is used to save necessary parameters locally for the logged-in user
|
// `thirdpartyLoginfn` is used to save necessary parameters locally for the logged-in user
|
||||||
const thirdpartyLoginfn = async (sessionToken) => {
|
const thirdpartyLoginfn = async (sessionToken) => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { appInfo } from "../constant/appinfo";
|
|||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { emailRegex, isEnableSubscription } from "../constant/const";
|
||||||
import {
|
import {
|
||||||
getAppLogo,
|
getAppLogo,
|
||||||
openInNewTab,
|
openInNewTab,
|
||||||
@@ -83,6 +83,9 @@ const Signup = () => {
|
|||||||
};
|
};
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||||
clearStorage();
|
clearStorage();
|
||||||
setState({ loading: true });
|
setState({ loading: true });
|
||||||
@@ -171,6 +174,7 @@ const Signup = () => {
|
|||||||
console.log("err ", error);
|
console.log("err ", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigation = async (sessionToken, isFreeplan = false) => {
|
const handleNavigation = async (sessionToken, isFreeplan = false) => {
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ import {
|
|||||||
getDefaultSignature,
|
getDefaultSignature,
|
||||||
onClickZoomIn,
|
onClickZoomIn,
|
||||||
onClickZoomOut,
|
onClickZoomOut,
|
||||||
rotatePdfPage
|
rotatePdfPage,
|
||||||
|
signatureTypes,
|
||||||
|
getBase64FromUrl,
|
||||||
|
convertBase64ToFile
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
@@ -128,10 +131,12 @@ function SignYourSelf() {
|
|||||||
const [zoomPercent, setZoomPercent] = useState(0);
|
const [zoomPercent, setZoomPercent] = useState(0);
|
||||||
const isHeader = useSelector((state) => state.showHeader);
|
const isHeader = useSelector((state) => state.showHeader);
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
const [pdfRotateBase64, setPdfRotatese64] = useState("");
|
const [pdfBase64Url, setPdfBase64Url] = useState("");
|
||||||
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
|
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
|
||||||
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
|
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
|
||||||
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
|
const [isResize, setIsResize] = useState(false);
|
||||||
|
const [isUploadPdf, setIsUploadPdf] = useState(false);
|
||||||
const divRef = useRef(null);
|
const divRef = useRef(null);
|
||||||
const nodeRef = useRef(null);
|
const nodeRef = useRef(null);
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
@@ -219,13 +224,17 @@ function SignYourSelf() {
|
|||||||
? documentData[0]?.Placeholders
|
? documentData[0]?.Placeholders
|
||||||
: [];
|
: [];
|
||||||
setXyPostion(placeholders);
|
setXyPostion(placeholders);
|
||||||
const url = documentData[0] && documentData[0]?.URL;
|
const url =
|
||||||
|
documentData[0] &&
|
||||||
|
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
||||||
if (url) {
|
if (url) {
|
||||||
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
||||||
const arrayBuffer = await convertPdfArrayBuffer(url);
|
const arrayBuffer = await convertPdfArrayBuffer(url);
|
||||||
|
const base64Pdf = await getBase64FromUrl(url);
|
||||||
if (arrayBuffer === "Error") {
|
if (arrayBuffer === "Error") {
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
} else {
|
} else {
|
||||||
|
setPdfBase64Url(base64Pdf);
|
||||||
setPdfArrayBuffer(arrayBuffer);
|
setPdfArrayBuffer(arrayBuffer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -423,9 +432,7 @@ function SignYourSelf() {
|
|||||||
const getWidth = widgetTypeExist
|
const getWidth = widgetTypeExist
|
||||||
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
|
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
|
||||||
: defaultWidthHeight(dragTypeValue).width;
|
: defaultWidthHeight(dragTypeValue).width;
|
||||||
const getHeight = widgetTypeExist
|
const getHeight = defaultWidthHeight(dragTypeValue).height;
|
||||||
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
|
|
||||||
: defaultWidthHeight(dragTypeValue).height;
|
|
||||||
|
|
||||||
dropObj = {
|
dropObj = {
|
||||||
xPosition: getWidth / 2 + containerWH.width / 2,
|
xPosition: getWidth / 2 + containerWH.width / 2,
|
||||||
@@ -456,9 +463,7 @@ function SignYourSelf() {
|
|||||||
const getWidth = widgetTypeExist
|
const getWidth = widgetTypeExist
|
||||||
? calculateInitialWidthHeight(widgetValue).getWidth
|
? calculateInitialWidthHeight(widgetValue).getWidth
|
||||||
: defaultWidthHeight(dragTypeValue).width;
|
: defaultWidthHeight(dragTypeValue).width;
|
||||||
const getHeight = widgetTypeExist
|
const getHeight = defaultWidthHeight(dragTypeValue).height;
|
||||||
? calculateInitialWidthHeight(widgetValue).getHeight
|
|
||||||
: defaultWidthHeight(dragTypeValue).height;
|
|
||||||
dropObj = {
|
dropObj = {
|
||||||
xPosition: getXPosition / (containerScale * scale),
|
xPosition: getXPosition / (containerScale * scale),
|
||||||
yPosition: getYPosition / (containerScale * scale),
|
yPosition: getYPosition / (containerScale * scale),
|
||||||
@@ -558,21 +563,29 @@ function SignYourSelf() {
|
|||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
if (xyPostion?.length > 0) {
|
if (xyPostion?.length > 0 && !pdfDetails?.[0]?.IsCompleted) {
|
||||||
autosavedetails();
|
autosavedetails();
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [xyPostion]);
|
}, [xyPostion, pdfBase64Url]);
|
||||||
|
|
||||||
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
// `autosavedetails` is used to save doc details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
||||||
const autosavedetails = async () => {
|
const autosavedetails = async () => {
|
||||||
try {
|
try {
|
||||||
const docCls = new Parse.Object("contracts_Document");
|
const docCls = new Parse.Object("contracts_Document");
|
||||||
docCls.id = documentId;
|
docCls.id = documentId;
|
||||||
|
let pdfUrl;
|
||||||
|
if (isUploadPdf) {
|
||||||
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64Url);
|
||||||
|
}
|
||||||
|
console.log("isUploadPdf", isUploadPdf);
|
||||||
docCls.set("Placeholders", xyPostion);
|
docCls.set("Placeholders", xyPostion);
|
||||||
docCls.set("IsSignyourself", true);
|
docCls.set("IsSignyourself", true);
|
||||||
|
if (pdfUrl) {
|
||||||
|
docCls.set("URL", pdfUrl);
|
||||||
|
}
|
||||||
await docCls.save();
|
await docCls.save();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error", e);
|
console.log("error", e);
|
||||||
@@ -617,16 +630,12 @@ function SignYourSelf() {
|
|||||||
const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl;
|
const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl;
|
||||||
let checkDefaultSigned =
|
let checkDefaultSigned =
|
||||||
requiredWidgets[i]?.options?.defaultValue;
|
requiredWidgets[i]?.options?.defaultValue;
|
||||||
if (!checkSignUrl) {
|
if (!checkSignUrl && !checkDefaultSigned && !showAlert) {
|
||||||
if (!checkDefaultSigned) {
|
|
||||||
if (!showAlert) {
|
|
||||||
showAlert = true;
|
showAlert = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
//condition to check exist signature widget or not
|
//condition to check exist signature widget or not
|
||||||
if (!isSignatureExist) {
|
if (!isSignatureExist) {
|
||||||
isSignatureExist = xyPostion[i].pos.some(
|
isSignatureExist = xyPostion[i].pos.some(
|
||||||
@@ -649,10 +658,9 @@ function SignYourSelf() {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
setIsUiLoading(true);
|
setIsUiLoading(true);
|
||||||
const existingPdfBytes = pdfArrayBuffer;
|
|
||||||
// Load a PDFDocument from the existing PDF bytes
|
// Load a PDFDocument from the existing PDF bytes
|
||||||
try {
|
try {
|
||||||
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
const pdfDoc = await PDFDocument.load(pdfArrayBuffer);
|
||||||
const isSignYourSelfFlow = true;
|
const isSignYourSelfFlow = true;
|
||||||
const extUserPtr = pdfDetails[0].ExtUserPtr;
|
const extUserPtr = pdfDetails[0].ExtUserPtr;
|
||||||
const HeaderDocId = extUserPtr?.HeaderDocId;
|
const HeaderDocId = extUserPtr?.HeaderDocId;
|
||||||
@@ -665,14 +673,19 @@ function SignYourSelf() {
|
|||||||
xyPostion,
|
xyPostion,
|
||||||
pdfDoc,
|
pdfDoc,
|
||||||
isSignYourSelfFlow,
|
isSignYourSelfFlow,
|
||||||
scale,
|
scale
|
||||||
pdfOriginalWH,
|
|
||||||
containerWH
|
|
||||||
);
|
);
|
||||||
// console.log("pdf", pdfBytes);
|
// console.log("pdf", pdfBytes);
|
||||||
//function for call to embed signature in pdf and get digital signature pdf
|
//function for call to embed signature in pdf and get digital signature pdf
|
||||||
if (pdfBytes) {
|
if (!pdfBytes?.error) {
|
||||||
await signPdfFun(pdfBytes, documentId);
|
await signPdfFun(pdfBytes, documentId);
|
||||||
|
} else {
|
||||||
|
setIsUiLoading(false);
|
||||||
|
setIsAlert({
|
||||||
|
header: t("error"),
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("pdf-uncompatible")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsUiLoading(false);
|
setIsUiLoading(false);
|
||||||
@@ -684,10 +697,7 @@ function SignYourSelf() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log("err in signing", err.message);
|
console.log("err in signing", err.message);
|
||||||
if (
|
if (err?.message?.includes("password")) {
|
||||||
err.message ===
|
|
||||||
"PKCS#12 MAC could not be verified. Invalid password?"
|
|
||||||
) {
|
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
header: t("error"),
|
header: t("error"),
|
||||||
isShow: true,
|
isShow: true,
|
||||||
@@ -754,10 +764,10 @@ function SignYourSelf() {
|
|||||||
alert(t("something-went-wrong-mssg"));
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//change image width and height to 100/40 in png base64
|
//change image width and height to 300/120 in png base64
|
||||||
const getNewse64 = await changeImageWH(base64Sign);
|
const imagebase64 = await changeImageWH(base64Sign);
|
||||||
//remove suffiix of base64
|
//remove suffiix of base64 (without type)
|
||||||
const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
|
const suffixbase64 = imagebase64 && imagebase64.split(",").pop();
|
||||||
const params = {
|
const params = {
|
||||||
pdfFile: base64Url,
|
pdfFile: base64Url,
|
||||||
docId: documentId,
|
docId: documentId,
|
||||||
@@ -770,7 +780,7 @@ function SignYourSelf() {
|
|||||||
const signedpdf = JSON.parse(JSON.stringify(resSignPdf));
|
const signedpdf = JSON.parse(JSON.stringify(resSignPdf));
|
||||||
setPdfUrl(signedpdf);
|
setPdfUrl(signedpdf);
|
||||||
getDocumentDetails(false);
|
getDocumentDetails(false);
|
||||||
setPdfRotatese64("");
|
setPdfBase64Url("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -783,7 +793,7 @@ function SignYourSelf() {
|
|||||||
const handleStop = (event, dragElement) => {
|
const handleStop = (event, dragElement) => {
|
||||||
setFontSize();
|
setFontSize();
|
||||||
setFontColor();
|
setFontColor();
|
||||||
if (isDragging && dragElement) {
|
if (!isResize && isDragging && dragElement) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const containerScale = getContainerScale(
|
const containerScale = getContainerScale(
|
||||||
pdfOriginalWH,
|
pdfOriginalWH,
|
||||||
@@ -1028,7 +1038,6 @@ function SignYourSelf() {
|
|||||||
const getPageNumer = xyPostion.filter(
|
const getPageNumer = xyPostion.filter(
|
||||||
(data) => data.pageNumber === pageNumber
|
(data) => data.pageNumber === pageNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getPageNumer.length > 0) {
|
if (getPageNumer.length > 0) {
|
||||||
const getXYdata = getPageNumer[0].pos;
|
const getXYdata = getPageNumer[0].pos;
|
||||||
const getPosData = getXYdata;
|
const getPosData = getXYdata;
|
||||||
@@ -1058,7 +1067,7 @@ function SignYourSelf() {
|
|||||||
isReadOnly: isReadOnly,
|
isReadOnly: isReadOnly,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor || currWidgetsDetails?.options?.fontColor || "black"
|
fontColor || currWidgetsDetails?.options?.fontColor || "black"
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1101,6 @@ function SignYourSelf() {
|
|||||||
const getPageNumer = xyPostion.filter(
|
const getPageNumer = xyPostion.filter(
|
||||||
(data) => data.pageNumber === pageNumber
|
(data) => data.pageNumber === pageNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getPageNumer.length > 0) {
|
if (getPageNumer.length > 0) {
|
||||||
const getXYdata = getPageNumer[0].pos;
|
const getXYdata = getPageNumer[0].pos;
|
||||||
const getPosData = getXYdata;
|
const getPosData = getXYdata;
|
||||||
@@ -1102,8 +1110,7 @@ function SignYourSelf() {
|
|||||||
...position,
|
...position,
|
||||||
options: {
|
options: {
|
||||||
...position.options,
|
...position.options,
|
||||||
fontSize:
|
fontSize: fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor || currWidgetsDetails?.options?.fontColor || "black"
|
fontColor || currWidgetsDetails?.options?.fontColor || "black"
|
||||||
}
|
}
|
||||||
@@ -1135,14 +1142,14 @@ function SignYourSelf() {
|
|||||||
if (isPlaceholder) {
|
if (isPlaceholder) {
|
||||||
setIsRotate({ status: true, degree: rotateDegree });
|
setIsRotate({ status: true, degree: rotateDegree });
|
||||||
} else {
|
} else {
|
||||||
|
setIsUploadPdf(true);
|
||||||
const urlDetails = await rotatePdfPage(
|
const urlDetails = await rotatePdfPage(
|
||||||
pdfUrl || pdfDetails[0].URL,
|
|
||||||
rotateDegree,
|
rotateDegree,
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfBase64Url
|
||||||
);
|
);
|
||||||
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1166,10 +1173,10 @@ function SignYourSelf() {
|
|||||||
pdfUrl || pdfDetails[0].URL,
|
pdfUrl || pdfDetails[0].URL,
|
||||||
isRotate.degree,
|
isRotate.degree,
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfArrayBuffer
|
||||||
);
|
);
|
||||||
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
setPdfArrayBuffer && setPdfArrayBuffer(urlDetails.arrayBuffer);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
setXyPostion(updatePlaceholder);
|
setXyPostion(updatePlaceholder);
|
||||||
setIsRotate({ status: false, degree: 0 });
|
setIsRotate({ status: false, degree: 0 });
|
||||||
};
|
};
|
||||||
@@ -1236,13 +1243,20 @@ function SignYourSelf() {
|
|||||||
setSignBtnPosition={setSignBtnPosition}
|
setSignBtnPosition={setSignBtnPosition}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
containerWH={containerWH}
|
containerWH={containerWH}
|
||||||
pdfRotateBase64={pdfRotateBase64}
|
pdfBase64Url={pdfBase64Url}
|
||||||
/>
|
/>
|
||||||
<div className=" w-full md:w-[57%] flex mr-4">
|
<div className=" w-full md:w-[57%] flex mr-4">
|
||||||
<PdfZoom
|
<PdfZoom
|
||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
handleRotationFun={handleRotationFun}
|
handleRotationFun={handleRotationFun}
|
||||||
|
pdfArrayBuffer={pdfArrayBuffer}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
setPdfBase64Url={setPdfBase64Url}
|
||||||
|
setPdfArrayBuffer={setPdfArrayBuffer}
|
||||||
|
setIsUploadPdf={setIsUploadPdf}
|
||||||
|
setSignerPos={setXyPostion}
|
||||||
|
signerPos={xyPostion}
|
||||||
/>
|
/>
|
||||||
<div className="w-full md:w-[95%]">
|
<div className="w-full md:w-[95%]">
|
||||||
<ModalUi
|
<ModalUi
|
||||||
@@ -1302,6 +1316,7 @@ function SignYourSelf() {
|
|||||||
/>
|
/>
|
||||||
{/* this is modal of signature pad */}
|
{/* this is modal of signature pad */}
|
||||||
<SignPad
|
<SignPad
|
||||||
|
signatureTypes={signatureTypes}
|
||||||
isSignPad={isSignPad}
|
isSignPad={isSignPad}
|
||||||
isStamp={isStamp}
|
isStamp={isStamp}
|
||||||
setIsImageSelect={setIsImageSelect}
|
setIsImageSelect={setIsImageSelect}
|
||||||
@@ -1355,6 +1370,12 @@ function SignYourSelf() {
|
|||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
widgetsDetails={xyPostion}
|
widgetsDetails={xyPostion}
|
||||||
setIsDownloadModal={setIsDownloadModal}
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
|
setIsUploadPdf={setIsUploadPdf}
|
||||||
|
pdfArrayBuffer={pdfArrayBuffer}
|
||||||
|
setPdfArrayBuffer={setPdfArrayBuffer}
|
||||||
|
setPdfBase64Url={setPdfBase64Url}
|
||||||
|
setSignerPos={setXyPostion}
|
||||||
|
signerPos={xyPostion}
|
||||||
/>
|
/>
|
||||||
<div ref={divRef} data-tut="reactourSecond" className="h-full">
|
<div ref={divRef} data-tut="reactourSecond" className="h-full">
|
||||||
{containerWH?.width && containerWH?.height && (
|
{containerWH?.width && containerWH?.height && (
|
||||||
@@ -1395,11 +1416,13 @@ function SignYourSelf() {
|
|||||||
handleTextSettingModal={handleTextSettingModal}
|
handleTextSettingModal={handleTextSettingModal}
|
||||||
setScale={setScale}
|
setScale={setScale}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
pdfRotateBase64={pdfRotateBase64}
|
pdfBase64Url={pdfBase64Url}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
setIsResize={setIsResize}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,7 +29,13 @@ import {
|
|||||||
onClickZoomOut,
|
onClickZoomOut,
|
||||||
onClickZoomIn,
|
onClickZoomIn,
|
||||||
handleRemoveWidgets,
|
handleRemoveWidgets,
|
||||||
handleRotateWarning
|
handleRotateWarning,
|
||||||
|
color,
|
||||||
|
signatureTypes,
|
||||||
|
getTenantDetails,
|
||||||
|
handleSignatureType,
|
||||||
|
getBase64FromUrl,
|
||||||
|
convertPdfArrayBuffer
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import "../styles/AddUser.css";
|
import "../styles/AddUser.css";
|
||||||
@@ -68,10 +74,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const [isSendAlert, setIsSendAlert] = useState(false);
|
const [isSendAlert, setIsSendAlert] = useState(false);
|
||||||
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
||||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
const [isRotate, setIsRotate] = useState({
|
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
|
||||||
status: false,
|
|
||||||
degree: 0
|
|
||||||
});
|
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: t("loading-mssg")
|
message: t("loading-mssg")
|
||||||
@@ -101,51 +104,23 @@ const TemplatePlaceholder = () => {
|
|||||||
const [isNameModal, setIsNameModal] = useState(false);
|
const [isNameModal, setIsNameModal] = useState(false);
|
||||||
const [isTextSetting, setIsTextSetting] = useState(false);
|
const [isTextSetting, setIsTextSetting] = useState(false);
|
||||||
const [pdfLoad, setPdfLoad] = useState(false);
|
const [pdfLoad, setPdfLoad] = useState(false);
|
||||||
const [pdfRotateBase64, setPdfRotatese64] = useState("");
|
const [pdfBase64Url, setPdfBase64Url] = useState("");
|
||||||
const color = [
|
const [isUploadPdf, setIsUploadPdf] = useState(false);
|
||||||
"#93a3db",
|
|
||||||
"#e6c3db",
|
|
||||||
"#c0e3bc",
|
|
||||||
"#bce3db",
|
|
||||||
"#b8ccdb",
|
|
||||||
"#ceb8db",
|
|
||||||
"#ffccff",
|
|
||||||
"#99ffcc",
|
|
||||||
"#cc99ff",
|
|
||||||
"#ffcc99",
|
|
||||||
"#66ccff",
|
|
||||||
"#ffffcc"
|
|
||||||
];
|
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
accept: "BOX",
|
accept: "BOX",
|
||||||
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({ isOver: !!monitor.isOver() })
|
||||||
isOver: !!monitor.isOver()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [{ isDragSign }, dragSignature] = useDrag({
|
const [{ isDragSign }, dragSignature] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: {
|
item: { type: "BOX", id: 1, text: "signature" },
|
||||||
type: "BOX",
|
collect: (monitor) => ({ isDragSign: !!monitor.isDragging() })
|
||||||
id: 1,
|
|
||||||
text: "signature"
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragSign: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [{ isDragStamp }, dragStamp] = useDrag({
|
const [{ isDragStamp }, dragStamp] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
|
item: { type: "BOX", id: 2, text: "stamp" },
|
||||||
item: {
|
collect: (monitor) => ({ isDragStamp: !!monitor.isDragging() })
|
||||||
type: "BOX",
|
|
||||||
id: 2,
|
|
||||||
text: "stamp"
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isDragStamp: !!monitor.isDragging()
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
const [uniqueId, setUniqueId] = useState("");
|
const [uniqueId, setUniqueId] = useState("");
|
||||||
const [isModalRole, setIsModalRole] = useState(false);
|
const [isModalRole, setIsModalRole] = useState(false);
|
||||||
@@ -166,6 +141,8 @@ const TemplatePlaceholder = () => {
|
|||||||
const [fontColor, setFontColor] = useState();
|
const [fontColor, setFontColor] = useState();
|
||||||
const [zoomPercent, setZoomPercent] = useState(0);
|
const [zoomPercent, setZoomPercent] = useState(0);
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
|
const [signatureType, setSignatureType] = useState([]);
|
||||||
|
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplate();
|
fetchTemplate();
|
||||||
@@ -213,9 +190,38 @@ const TemplatePlaceholder = () => {
|
|||||||
handleNavigation(plan);
|
handleNavigation(plan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//function to fetch tenant Details
|
||||||
|
const fetchTenantDetails = async () => {
|
||||||
|
const user = JSON.parse(
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (user) {
|
||||||
|
try {
|
||||||
|
const tenantDetails = await getTenantDetails(user?.objectId);
|
||||||
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
} else if (tenantDetails) {
|
||||||
|
const signatureType = tenantDetails?.SignatureType || [];
|
||||||
|
const filterSignTypes = signatureType?.filter(
|
||||||
|
(x) => x.enabled === true
|
||||||
|
);
|
||||||
|
return filterSignTypes;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
||||||
const fetchTemplate = async () => {
|
const fetchTemplate = async () => {
|
||||||
try {
|
try {
|
||||||
|
const tenantSignTypes = await fetchTenantDetails();
|
||||||
const params = { templateId: templateId };
|
const params = { templateId: templateId };
|
||||||
const templateDeatils = await axios.post(
|
const templateDeatils = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
`${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
||||||
@@ -237,7 +243,29 @@ const TemplatePlaceholder = () => {
|
|||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
||||||
}
|
}
|
||||||
setPdfDetails(documentData);
|
const userSignatureType =
|
||||||
|
documentData[0]?.ExtUserPtr?.SignatureType || signatureTypes;
|
||||||
|
const docSignTypes =
|
||||||
|
documentData?.[0]?.SignatureType || userSignatureType;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
docSignTypes
|
||||||
|
);
|
||||||
|
const url = documentData[0] && documentData[0]?.URL;
|
||||||
|
if (url) {
|
||||||
|
const arrayBuffer = await convertPdfArrayBuffer(url);
|
||||||
|
const base64Pdf = await getBase64FromUrl(url);
|
||||||
|
if (arrayBuffer === "Error") {
|
||||||
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
|
} else {
|
||||||
|
setPdfBase64Url(base64Pdf);
|
||||||
|
setPdfArrayBuffer(arrayBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
|
const updatedPdfDetails = [...documentData];
|
||||||
|
updatedPdfDetails[0].SignatureType = updatedSignatureType;
|
||||||
|
setPdfDetails(updatedPdfDetails);
|
||||||
setIsSigners(true);
|
setIsSigners(true);
|
||||||
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
||||||
setIsSelectId(0);
|
setIsSelectId(0);
|
||||||
@@ -260,11 +288,7 @@ const TemplatePlaceholder = () => {
|
|||||||
blockColor: x.blockColor
|
blockColor: x.blockColor
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return { Role: x.Role, Id: x.Id, blockColor: x.blockColor };
|
||||||
Role: x.Role,
|
|
||||||
Id: x.Id,
|
|
||||||
blockColor: x.blockColor
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setSignersData(updatedSigners);
|
setSignersData(updatedSigners);
|
||||||
@@ -287,11 +311,7 @@ const TemplatePlaceholder = () => {
|
|||||||
documentData[0].Placeholders.length > 0
|
documentData[0].Placeholders.length > 0
|
||||||
) {
|
) {
|
||||||
let updatedSigners = documentData[0].Placeholders.map((x) => {
|
let updatedSigners = documentData[0].Placeholders.map((x) => {
|
||||||
return {
|
return { Role: x.Role, Id: x.Id, blockColor: x.blockColor };
|
||||||
Role: x.Role,
|
|
||||||
Id: x.Id,
|
|
||||||
blockColor: x.blockColor
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
setSignerPos(documentData[0].Placeholders);
|
setSignerPos(documentData[0].Placeholders);
|
||||||
setUniqueId(updatedSigners[0].Id);
|
setUniqueId(updatedSigners[0].Id);
|
||||||
@@ -304,25 +324,11 @@ const TemplatePlaceholder = () => {
|
|||||||
documentData === "Error: Something went wrong!" ||
|
documentData === "Error: Something went wrong!" ||
|
||||||
(documentData.result && documentData.result.error)
|
(documentData.result && documentData.result.error)
|
||||||
) {
|
) {
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
setIsLoading(loadObj);
|
setIsLoading({ isLoad: false });
|
||||||
} else {
|
} else {
|
||||||
setHandleError(t("no-data-avaliable"));
|
setHandleError(t("no-data-avaliable"));
|
||||||
const loadObj = {
|
setIsLoading({ isLoad: false });
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log("err ", err);
|
|
||||||
if (err?.response?.data?.code === 101) {
|
|
||||||
setHandleError(t("no-data-avaliable"));
|
|
||||||
} else {
|
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const res = await contractUsers();
|
const res = await contractUsers();
|
||||||
if (res[0] && res.length) {
|
if (res[0] && res.length) {
|
||||||
@@ -338,22 +344,21 @@ const TemplatePlaceholder = () => {
|
|||||||
setCheckTourStatus(checkTourRecipients[0].templateTour);
|
setCheckTourStatus(checkTourRecipients[0].templateTour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const loadObj = {
|
setIsLoading({ isLoad: false });
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
} else if (res === "Error: Something went wrong!") {
|
} else if (res === "Error: Something went wrong!") {
|
||||||
const loadObj = {
|
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
setIsLoading(loadObj);
|
setIsLoading({ isLoad: false });
|
||||||
} else if (res.length === 0) {
|
} else if (res.length === 0) {
|
||||||
setHandleError(t("no-data-avaliable"));
|
setHandleError(t("no-data-avaliable"));
|
||||||
const loadObj = {
|
setIsLoading({ isLoad: false });
|
||||||
isLoad: false
|
}
|
||||||
};
|
} catch (err) {
|
||||||
setIsLoading(loadObj);
|
console.log("err ", err);
|
||||||
|
if (err?.response?.data?.code === 101) {
|
||||||
|
setHandleError(t("no-data-avaliable"));
|
||||||
|
} else {
|
||||||
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -379,8 +384,10 @@ const TemplatePlaceholder = () => {
|
|||||||
);
|
);
|
||||||
const key = randomId();
|
const key = randomId();
|
||||||
const dragTypeValue = item?.text ? item.text : monitor.type;
|
const dragTypeValue = item?.text ? item.text : monitor.type;
|
||||||
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
|
const widgetWidth =
|
||||||
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
|
defaultWidthHeight(dragTypeValue).width * containerScale;
|
||||||
|
const widgetHeight =
|
||||||
|
defaultWidthHeight(dragTypeValue).height * containerScale;
|
||||||
let dropData = [],
|
let dropData = [],
|
||||||
currentPagePosition;
|
currentPagePosition;
|
||||||
let placeHolder;
|
let placeHolder;
|
||||||
@@ -402,10 +409,7 @@ const TemplatePlaceholder = () => {
|
|||||||
Height: widgetHeight / (containerScale * scale)
|
Height: widgetHeight / (containerScale * scale)
|
||||||
};
|
};
|
||||||
dropData.push(dropObj);
|
dropData.push(dropObj);
|
||||||
placeHolder = {
|
placeHolder = { pageNumber: pageNumber, pos: dropData };
|
||||||
pageNumber: pageNumber,
|
|
||||||
pos: dropData
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
const offset = monitor.getClientOffset();
|
const offset = monitor.getClientOffset();
|
||||||
//adding and updating drop position in array when user drop signature button in div
|
//adding and updating drop position in array when user drop signature button in div
|
||||||
@@ -436,10 +440,7 @@ const TemplatePlaceholder = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dropData.push(dropObj);
|
dropData.push(dropObj);
|
||||||
placeHolder = {
|
placeHolder = { pageNumber: pageNumber, pos: dropData };
|
||||||
pageNumber: pageNumber,
|
|
||||||
pos: dropData
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
let filterSignerPos = signerPos.find((data) => data.Id === uniqueId);
|
let filterSignerPos = signerPos.find((data) => data.Id === uniqueId);
|
||||||
const getPlaceHolder = filterSignerPos?.placeHolder;
|
const getPlaceHolder = filterSignerPos?.placeHolder;
|
||||||
@@ -456,10 +457,7 @@ const TemplatePlaceholder = () => {
|
|||||||
);
|
);
|
||||||
const getPos = currentPagePosition?.pos;
|
const getPos = currentPagePosition?.pos;
|
||||||
const newSignPos = getPos.concat(dropData);
|
const newSignPos = getPos.concat(dropData);
|
||||||
let xyPos = {
|
let xyPos = { pageNumber: pageNumber, pos: newSignPos };
|
||||||
pageNumber: pageNumber,
|
|
||||||
pos: newSignPos
|
|
||||||
};
|
|
||||||
updatePlace.push(xyPos);
|
updatePlace.push(xyPos);
|
||||||
const updatesignerPos = signerPos.map((x) =>
|
const updatesignerPos = signerPos.map((x) =>
|
||||||
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
|
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
|
||||||
@@ -495,7 +493,6 @@ const TemplatePlaceholder = () => {
|
|||||||
setWidgetType(dragTypeValue);
|
setWidgetType(dragTypeValue);
|
||||||
setSignKey(key);
|
setSignKey(key);
|
||||||
setSelectWidgetId(key);
|
setSelectWidgetId(key);
|
||||||
|
|
||||||
setIsMailSend(false);
|
setIsMailSend(false);
|
||||||
} else {
|
} else {
|
||||||
setIsReceipent(false);
|
setIsReceipent(false);
|
||||||
@@ -508,7 +505,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const tourAddRole = [
|
const tourAddRole = [
|
||||||
{
|
{
|
||||||
selector: '[data-tut="reactourAddbtn"]',
|
selector: '[data-tut="reactourAddbtn"]',
|
||||||
content: "You need to add a role before you can add fields for it. ",
|
content: t("add-user-template"),
|
||||||
position: "top",
|
position: "top",
|
||||||
style: { fontSize: "13px" }
|
style: { fontSize: "13px" }
|
||||||
}
|
}
|
||||||
@@ -594,9 +591,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setIsMailSend(false);
|
setIsMailSend(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => setIsDragging(false), 200);
|
||||||
setIsDragging(false);
|
|
||||||
}, 200);
|
|
||||||
};
|
};
|
||||||
//function for delete signature block
|
//function for delete signature block
|
||||||
const handleDeleteSign = (key, Id) => {
|
const handleDeleteSign = (key, Id) => {
|
||||||
@@ -712,7 +707,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [signerPos]);
|
}, [signerPos, signatureType]);
|
||||||
|
|
||||||
// `autosavedetails` is used to save template details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
// `autosavedetails` is used to save template details after every 2 sec when changes are happern in placeholder like drag-drop widgets, remove signers
|
||||||
const autosavedetails = async () => {
|
const autosavedetails = async () => {
|
||||||
@@ -729,11 +724,19 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let pdfUrl;
|
||||||
|
if (isUploadPdf) {
|
||||||
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64Url);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const templateCls = new Parse.Object("contracts_Template");
|
const templateCls = new Parse.Object("contracts_Template");
|
||||||
templateCls.id = templateId;
|
templateCls.id = templateId;
|
||||||
templateCls.set("Placeholders", signerPos);
|
templateCls.set("Placeholders", signerPos);
|
||||||
templateCls.set("Signers", signers);
|
templateCls.set("Signers", signers);
|
||||||
|
templateCls.set("SignatureType", signatureType);
|
||||||
|
if (pdfUrl) {
|
||||||
|
templateCls.set("URL", pdfUrl);
|
||||||
|
}
|
||||||
await templateCls.save();
|
await templateCls.save();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("error in autosave template", err);
|
console.log("error in autosave template", err);
|
||||||
@@ -742,8 +745,7 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
const handleSaveTemplate = async () => {
|
const handleSaveTemplate = async () => {
|
||||||
if (signersdata?.length) {
|
if (signersdata?.length) {
|
||||||
const loadObj = { isLoad: true, message: t("loading-mssg") };
|
setIsLoading({ isLoad: true, message: t("loading-mssg") });
|
||||||
setIsLoading(loadObj);
|
|
||||||
setIsSendAlert(false);
|
setIsSendAlert(false);
|
||||||
let signers = [];
|
let signers = [];
|
||||||
if (signersdata?.length > 0) {
|
if (signersdata?.length > 0) {
|
||||||
@@ -759,12 +761,9 @@ const TemplatePlaceholder = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
let pdfUrl = pdfDetails[0]?.URL;
|
let pdfUrl = pdfDetails[0]?.URL;
|
||||||
if (pdfRotateBase64) {
|
if (pdfBase64Url) {
|
||||||
try {
|
try {
|
||||||
pdfUrl = await convertBase64ToFile(
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64Url);
|
||||||
pdfDetails[0].Name,
|
|
||||||
pdfRotateBase64
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error to convertBase64ToFile in placeholder flow", e);
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
}
|
}
|
||||||
@@ -781,7 +780,13 @@ const TemplatePlaceholder = () => {
|
|||||||
RemindOnceInEvery: parseInt(pdfDetails[0]?.RemindOnceInEvery),
|
RemindOnceInEvery: parseInt(pdfDetails[0]?.RemindOnceInEvery),
|
||||||
NextReminderDate: pdfDetails[0]?.NextReminderDate,
|
NextReminderDate: pdfDetails[0]?.NextReminderDate,
|
||||||
IsEnableOTP: pdfDetails[0]?.IsEnableOTP === true ? true : false,
|
IsEnableOTP: pdfDetails[0]?.IsEnableOTP === true ? true : false,
|
||||||
URL: pdfUrl
|
IsTourEnabled: pdfDetails[0]?.IsTourEnabled === true ? true : false,
|
||||||
|
URL: pdfUrl,
|
||||||
|
SignatureType: signatureType,
|
||||||
|
NotifyOnSignatures:
|
||||||
|
pdfDetails[0]?.NotifyOnSignatures !== undefined
|
||||||
|
? pdfDetails[0]?.NotifyOnSignatures
|
||||||
|
: false
|
||||||
};
|
};
|
||||||
const updateTemplate = new Parse.Object("contracts_Template");
|
const updateTemplate = new Parse.Object("contracts_Template");
|
||||||
updateTemplate.id = templateId;
|
updateTemplate.id = templateId;
|
||||||
@@ -890,9 +895,7 @@ const TemplatePlaceholder = () => {
|
|||||||
`${localStorage.getItem(
|
`${localStorage.getItem(
|
||||||
"baseUrl"
|
"baseUrl"
|
||||||
)}classes/contracts_Users/${signerUserId}`,
|
)}classes/contracts_Users/${signerUserId}`,
|
||||||
{
|
{ TourStatus: updatedTourStatus },
|
||||||
TourStatus: updatedTourStatus
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -916,9 +919,9 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsCreateDocModal(false);
|
setIsCreateDocModal(false);
|
||||||
setIsCreateDoc(true);
|
setIsCreateDoc(true);
|
||||||
let pdfUrl = pdfDetails[0]?.URL;
|
let pdfUrl = pdfDetails[0]?.URL;
|
||||||
if (pdfRotateBase64) {
|
if (pdfBase64Url) {
|
||||||
try {
|
try {
|
||||||
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfRotateBase64);
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfBase64Url);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("error to convertBase64ToFile in placeholder flow", e);
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
}
|
}
|
||||||
@@ -1135,7 +1138,7 @@ const TemplatePlaceholder = () => {
|
|||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1173,7 +1176,7 @@ const TemplatePlaceholder = () => {
|
|||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1191,7 +1194,7 @@ const TemplatePlaceholder = () => {
|
|||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1226,7 +1229,15 @@ const TemplatePlaceholder = () => {
|
|||||||
setFontColor();
|
setFontColor();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleWidgetdefaultdata = (defaultdata) => {
|
const handleWidgetdefaultdata = (defaultdata, isSignWidget) => {
|
||||||
|
if (isSignWidget) {
|
||||||
|
const updatedPdfDetails = [...pdfDetails];
|
||||||
|
const signtypes = defaultdata.signatureType || signatureType;
|
||||||
|
updatedPdfDetails[0].SignatureType = signtypes;
|
||||||
|
// Update the SignatureType with the modified array
|
||||||
|
setPdfDetails(updatedPdfDetails);
|
||||||
|
setSignatureType(signtypes);
|
||||||
|
}
|
||||||
const options = ["email", "number", "text"];
|
const options = ["email", "number", "text"];
|
||||||
let inputype;
|
let inputype;
|
||||||
if (defaultdata.textvalidate) {
|
if (defaultdata.textvalidate) {
|
||||||
@@ -1266,7 +1277,7 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
: {},
|
: {},
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1282,7 +1293,7 @@ const TemplatePlaceholder = () => {
|
|||||||
status: defaultdata.status,
|
status: defaultdata.status,
|
||||||
defaultValue: defaultdata.defaultValue,
|
defaultValue: defaultdata.defaultValue,
|
||||||
fontSize:
|
fontSize:
|
||||||
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
fontColor:
|
fontColor:
|
||||||
fontColor ||
|
fontColor ||
|
||||||
currWidgetsDetails?.options?.fontColor ||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
@@ -1335,24 +1346,31 @@ const TemplatePlaceholder = () => {
|
|||||||
if (isRotate) {
|
if (isRotate) {
|
||||||
setIsRotate({ status: true, degree: rotateDegree });
|
setIsRotate({ status: true, degree: rotateDegree });
|
||||||
} else {
|
} else {
|
||||||
|
setIsUploadPdf(false);
|
||||||
const urlDetails = await rotatePdfPage(
|
const urlDetails = await rotatePdfPage(
|
||||||
pdfDetails[0].URL,
|
pdfDetails[0].URL,
|
||||||
rotateDegree,
|
rotateDegree,
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfArrayBuffer
|
||||||
);
|
);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleRemovePlaceholder = async () => {
|
const handleRemovePlaceholder = async () => {
|
||||||
handleRemoveWidgets(setSignerPos, signerPos, pageNumber, setIsRotate);
|
handleRemoveWidgets(
|
||||||
|
setSignerPos,
|
||||||
|
signerPos,
|
||||||
|
pageNumber,
|
||||||
|
uniqueId,
|
||||||
|
setIsRotate
|
||||||
|
);
|
||||||
const urlDetails = await rotatePdfPage(
|
const urlDetails = await rotatePdfPage(
|
||||||
pdfDetails[0].URL,
|
pdfDetails[0].URL,
|
||||||
isRotate.degree,
|
isRotate.degree,
|
||||||
pageNumber - 1,
|
pageNumber - 1,
|
||||||
pdfRotateBase64
|
pdfBase64Url
|
||||||
);
|
);
|
||||||
setPdfRotatese64(urlDetails.base64);
|
setPdfBase64Url(urlDetails.base64);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -1397,6 +1415,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setPageNumber={setPageNumber}
|
setPageNumber={setPageNumber}
|
||||||
setSignBtnPosition={setSignBtnPosition}
|
setSignBtnPosition={setSignBtnPosition}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
|
pdfBase64Url={pdfBase64Url}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* pdf render view */}
|
{/* pdf render view */}
|
||||||
@@ -1405,6 +1424,13 @@ const TemplatePlaceholder = () => {
|
|||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
handleRotationFun={handleRotationFun}
|
handleRotationFun={handleRotationFun}
|
||||||
|
pdfArrayBuffer={pdfArrayBuffer}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
setPdfBase64Url={setPdfBase64Url}
|
||||||
|
setPdfArrayBuffer={setPdfArrayBuffer}
|
||||||
|
setIsUploadPdf={setIsUploadPdf}
|
||||||
|
setSignerPos={setSignerPos}
|
||||||
|
signerPos={signerPos}
|
||||||
/>
|
/>
|
||||||
<div className="w-full md:w-[95%]">
|
<div className="w-full md:w-[95%]">
|
||||||
{/* this modal is used show alert set placeholder for all signers before send mail */}
|
{/* this modal is used show alert set placeholder for all signers before send mail */}
|
||||||
@@ -1550,6 +1576,7 @@ const TemplatePlaceholder = () => {
|
|||||||
handleRotationFun={handleRotationFun}
|
handleRotationFun={handleRotationFun}
|
||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
|
setSignerPos={setSignerPos}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
ref={divRef}
|
ref={divRef}
|
||||||
@@ -1594,11 +1621,12 @@ const TemplatePlaceholder = () => {
|
|||||||
setScale={setScale}
|
setScale={setScale}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
pdfRotateBase64={pdfRotateBase64}
|
pdfBase64Url={pdfBase64Url}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1721,6 +1749,7 @@ const TemplatePlaceholder = () => {
|
|||||||
/>
|
/>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
<WidgetNameModal
|
<WidgetNameModal
|
||||||
|
signatureType={signatureType}
|
||||||
widgetName={widgetName}
|
widgetName={widgetName}
|
||||||
defaultdata={currWidgetsDetails}
|
defaultdata={currWidgetsDetails}
|
||||||
isOpen={isNameModal}
|
isOpen={isNameModal}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { NavLink, useNavigate } from "react-router-dom";
|
|||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { emailRegex } from "../constant/const";
|
||||||
const UpdateExistUserAdmin = () => {
|
const UpdateExistUserAdmin = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -15,6 +16,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
const [isAlert, setIsAlert] = useState({ type: "danger", msg: "" });
|
const [isAlert, setIsAlert] = useState({ type: "danger", msg: "" });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkIsAdminExist();
|
checkIsAdminExist();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const checkIsAdminExist = async () => {
|
const checkIsAdminExist = async () => {
|
||||||
@@ -22,7 +24,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
const isAdminExist = await Parse.Cloud.run("checkadminexist");
|
const isAdminExist = await Parse.Cloud.run("checkadminexist");
|
||||||
if (isAdminExist !== "not_exist") {
|
if (isAdminExist !== "not_exist") {
|
||||||
// console.log("isAdminExist ", isAdminExist);
|
// console.log("isAdminExist ", isAdminExist);
|
||||||
setErrMsg("Admin already exists.");
|
setErrMsg(t("admin-exists"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Err in checkadminexist", err);
|
console.log("Err in checkadminexist", err);
|
||||||
@@ -34,6 +36,9 @@ const UpdateExistUserAdmin = () => {
|
|||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
if (!emailRegex.test(formdata.email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
setIsSubmitLoading(true);
|
setIsSubmitLoading(true);
|
||||||
try {
|
try {
|
||||||
const updateUserAsAdmin = await Parse.Cloud.run(
|
const updateUserAsAdmin = await Parse.Cloud.run(
|
||||||
@@ -52,7 +57,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
} else if (err.code === 101) {
|
} else if (err.code === 101) {
|
||||||
setIsAlert((prev) => ({ ...prev, msg: t("user-not-found") }));
|
setIsAlert((prev) => ({ ...prev, msg: t("user-not-found") }));
|
||||||
} else if (err.code === 137) {
|
} else if (err.code === 137) {
|
||||||
setIsAlert((prev) => ({ ...prev, msg: t("admin-already-exist") }));
|
setIsAlert((prev) => ({ ...prev, msg: t("admin-exists") }));
|
||||||
} else {
|
} else {
|
||||||
setErrMsg(t("something-went-wrong-mssg"));
|
setErrMsg(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
@@ -62,6 +67,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
setIsAlert(() => ({ type: "danger", msg: "" }));
|
setIsAlert(() => ({ type: "danger", msg: "" }));
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="h-screen flex justify-center">
|
<div className="h-screen flex justify-center">
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ function UserProfile() {
|
|||||||
<div className="flex flex-row md:items-center gap-1">
|
<div className="flex flex-row md:items-center gap-1">
|
||||||
{editmode || !extendUser?.[0]?.Tagline ? (
|
{editmode || !extendUser?.[0]?.Tagline ? (
|
||||||
<input
|
<input
|
||||||
maxLength={40}
|
maxLength={100}
|
||||||
onChange={handleOnchangeTagLine}
|
onChange={handleOnchangeTagLine}
|
||||||
value={tagLine}
|
value={tagLine}
|
||||||
disabled={!editmode}
|
disabled={!editmode}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Parse from "parse";
|
|
||||||
import Loader from "./Loader";
|
import Loader from "./Loader";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import axios from "axios";
|
||||||
|
import { getTenantDetails } from "../constant/Utils";
|
||||||
|
import { emailRegex } from "../constant/const";
|
||||||
const AddContact = (props) => {
|
const AddContact = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
@@ -12,6 +14,7 @@ const AddContact = (props) => {
|
|||||||
const [isUserExist, setIsUserExist] = useState(false);
|
const [isUserExist, setIsUserExist] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkUserExist();
|
checkUserExist();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
// Load user details from localStorage when the component mounts
|
// Load user details from localStorage when the component mounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -26,87 +29,61 @@ const AddContact = (props) => {
|
|||||||
}, [addYourself]);
|
}, [addYourself]);
|
||||||
|
|
||||||
const checkUserExist = async () => {
|
const checkUserExist = async () => {
|
||||||
const user = Parse.User.current();
|
|
||||||
try {
|
try {
|
||||||
const query = new Parse.Query("contracts_Contactbook");
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
query.equalTo("CreatedBy", user);
|
const url = `${baseURL}functions/isuserincontactbook`;
|
||||||
query.notEqualTo("IsDeleted", true);
|
const token = props?.jwttoken
|
||||||
query.equalTo("Email", user.getEmail());
|
? { jwttoken: props?.jwttoken }
|
||||||
const res = await query.first();
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
// console.log(res);
|
const headers = {
|
||||||
if (!res) {
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
...token
|
||||||
|
};
|
||||||
|
const axiosRes = await axios.post(url, {}, { headers });
|
||||||
|
const contactRes = axiosRes?.data?.result || {};
|
||||||
|
if (!contactRes?.objectId) {
|
||||||
setIsUserExist(true);
|
setIsUserExist(true);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err", err);
|
console.log("err ", err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 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();
|
e.stopPropagation();
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert("Please enter a valid email address.");
|
||||||
|
} else {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
if (localStorage.getItem("TenantId")) {
|
const user = JSON.parse(
|
||||||
try {
|
localStorage.getItem(
|
||||||
const user = Parse.User.current();
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
const query = new Parse.Query("contracts_Contactbook");
|
)
|
||||||
query.equalTo("CreatedBy", user);
|
|
||||||
query.notEqualTo("IsDeleted", true);
|
|
||||||
query.equalTo("Email", email);
|
|
||||||
const res = await query.first();
|
|
||||||
if (!res) {
|
|
||||||
const contactQuery = new Parse.Object("contracts_Contactbook");
|
|
||||||
contactQuery.set("Name", name);
|
|
||||||
if (phone) {
|
|
||||||
contactQuery.set("Phone", phone);
|
|
||||||
}
|
|
||||||
contactQuery.set("Email", email);
|
|
||||||
contactQuery.set("UserRole", "contracts_Guest");
|
|
||||||
|
|
||||||
if (localStorage.getItem("TenantId")) {
|
|
||||||
contactQuery.set("TenantId", {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: "partners_Tenant",
|
|
||||||
objectId: localStorage.getItem("TenantId")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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("password", email);
|
|
||||||
if (phone) {
|
|
||||||
_user.set("phone", phone);
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await _user.save();
|
|
||||||
if (user) {
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
contactQuery.set(
|
|
||||||
"CreatedBy",
|
|
||||||
Parse.User.createWithoutData(currentUser.id)
|
|
||||||
);
|
);
|
||||||
|
const userId = user?.objectId || "";
|
||||||
contactQuery.set("UserId", user);
|
const tenantDetails = await getTenantDetails(userId, props.jwttoken);
|
||||||
const acl = new Parse.ACL();
|
const tenantId = tenantDetails?.objectId || "";
|
||||||
acl.setPublicReadAccess(true);
|
if (tenantId) {
|
||||||
acl.setPublicWriteAccess(true);
|
try {
|
||||||
acl.setReadAccess(currentUser.id, true);
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
acl.setWriteAccess(currentUser.id, true);
|
const url = `${baseURL}functions/savecontact`;
|
||||||
|
const token = props?.jwttoken
|
||||||
contactQuery.setACL(acl);
|
? { jwttoken: props?.jwttoken }
|
||||||
|
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||||
const res = await contactQuery.save();
|
const data = { name, email, phone, tenantId };
|
||||||
|
const headers = {
|
||||||
const parseData = JSON.parse(JSON.stringify(res));
|
"Content-Type": "application/json",
|
||||||
props.details(parseData);
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
...token
|
||||||
|
};
|
||||||
|
const axiosRes = await axios.post(url, data, { headers });
|
||||||
|
const contactRes = axiosRes?.data?.result || {};
|
||||||
|
if (contactRes?.objectId) {
|
||||||
|
props.details(contactRes);
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
|
||||||
|
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
// Reset the form fields
|
// Reset the form fields
|
||||||
setAddYourself(false);
|
setAddYourself(false);
|
||||||
@@ -114,60 +91,21 @@ const AddContact = (props) => {
|
|||||||
setPhone("");
|
setPhone("");
|
||||||
setEmail("");
|
setEmail("");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("Err", err);
|
||||||
if (err.code === 202) {
|
|
||||||
const params = { email: email };
|
|
||||||
const userRes = await Parse.Cloud.run("getUserId", params);
|
|
||||||
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(parseData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.closePopup) {
|
|
||||||
props.closePopup();
|
|
||||||
}
|
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
// Reset the form fields
|
if (err?.response?.data?.error?.includes("already exists")) {
|
||||||
setAddYourself(false);
|
|
||||||
setName("");
|
|
||||||
setPhone("");
|
|
||||||
setEmail("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert(t("add-signer-alert"));
|
alert(t("add-signer-alert"));
|
||||||
setIsLoader(false);
|
} else {
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// console.log("err", err);
|
|
||||||
setIsLoader(false);
|
|
||||||
alert(t("something-went-wrong-mssg"));
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert(t("something-went-wrong-mssg"));
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define a function to handle the "add yourself" checkbox
|
// Define a function to handle the "add yourself" checkbox
|
||||||
@@ -259,6 +197,7 @@ const AddContact = (props) => {
|
|||||||
onChange={(e) => setPhone(e.target.value)}
|
onChange={(e) => setPhone(e.target.value)}
|
||||||
disabled={addYourself}
|
disabled={addYourself}
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
placeholder={t("phone-optional")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,13 @@ function DownloadPdfZip(props) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Fetch the first PDF (Signed Document)
|
// Fetch the first PDF (Signed Document)
|
||||||
const docId =
|
const docId = pdfDetails?.[0]?.objectId || "";
|
||||||
props.isDocId && !pdfDetails?.[0]?.IsEnableOTP
|
const fileAdapterId = pdfDetails?.[0]?.FileAdapterId
|
||||||
? pdfDetails?.[0]?.objectId
|
? pdfDetails?.[0]?.FileAdapterId
|
||||||
: "";
|
: "";
|
||||||
const signedUrl = await getSignedUrl(pdfUrl, docId);
|
console.log("pdfDetails?.[0] ", pdfDetails?.[0]);
|
||||||
|
const signedUrl = await getSignedUrl(pdfUrl, docId, fileAdapterId);
|
||||||
|
console.log("signedUrl ", signedUrl);
|
||||||
const pdf1Response = await fetch(signedUrl);
|
const pdf1Response = await fetch(signedUrl);
|
||||||
if (!pdf1Response.ok) {
|
if (!pdf1Response.ok) {
|
||||||
throw new Error(`Failed to fetch PDF: ${signedUrl}`);
|
throw new Error(`Failed to fetch PDF: ${signedUrl}`);
|
||||||
|
|||||||
@@ -14,8 +14,12 @@ import {
|
|||||||
checkIsSubscribed,
|
checkIsSubscribed,
|
||||||
copytoData,
|
copytoData,
|
||||||
fetchUrl,
|
fetchUrl,
|
||||||
|
formatDate,
|
||||||
getSignedUrl,
|
getSignedUrl,
|
||||||
replaceMailVaribles
|
getTenantDetails,
|
||||||
|
handleSignatureType,
|
||||||
|
replaceMailVaribles,
|
||||||
|
signatureTypes
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import Confetti from "react-confetti";
|
import Confetti from "react-confetti";
|
||||||
import EditorToolbar, {
|
import EditorToolbar, {
|
||||||
@@ -76,6 +80,9 @@ const ReportTable = (props) => {
|
|||||||
const [reason, setReason] = useState("");
|
const [reason, setReason] = useState("");
|
||||||
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
const [isEmbed, setIsEmbed] = useState(false);
|
const [isEmbed, setIsEmbed] = useState(false);
|
||||||
|
const [isPublicTour, setIsPublicTour] = useState();
|
||||||
|
const [signatureType, setSignatureType] = useState([]);
|
||||||
|
const [expiryDate, setExpiryDate] = useState("");
|
||||||
const Extand_Class = localStorage.getItem("Extand_Class");
|
const Extand_Class = localStorage.getItem("Extand_Class");
|
||||||
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
||||||
const startIndex = (currentPage - 1) * props.docPerPage;
|
const startIndex = (currentPage - 1) * props.docPerPage;
|
||||||
@@ -194,6 +201,33 @@ const ReportTable = (props) => {
|
|||||||
}
|
}
|
||||||
}, [isMoreDocs, pageNumbers, currentPage, setIsNextRecord]);
|
}, [isMoreDocs, pageNumbers, currentPage, setIsNextRecord]);
|
||||||
|
|
||||||
|
//function to fetch tenant Details
|
||||||
|
const fetchTenantDetails = async () => {
|
||||||
|
const user = JSON.parse(
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (user) {
|
||||||
|
try {
|
||||||
|
const tenantDetails = await getTenantDetails(user?.objectId);
|
||||||
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
} else if (tenantDetails) {
|
||||||
|
const signatureType = tenantDetails?.SignatureType || [];
|
||||||
|
const filterSignTypes = signatureType?.filter(
|
||||||
|
(x) => x.enabled === true
|
||||||
|
);
|
||||||
|
return filterSignTypes;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(t("user-not-exist"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// `handleURL` is used to open microapp
|
// `handleURL` is used to open microapp
|
||||||
const handleURL = async (item, act) => {
|
const handleURL = async (item, act) => {
|
||||||
if (props.ReportName === "Templates") {
|
if (props.ReportName === "Templates") {
|
||||||
@@ -202,9 +236,7 @@ const ReportTable = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setActLoader({ [`${item.objectId}_${act.btnId}`]: true });
|
setActLoader({ [`${item.objectId}_${act.btnId}`]: true });
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = { templateId: item.objectId };
|
||||||
templateId: item.objectId
|
|
||||||
};
|
|
||||||
const templateDeatils = await axios.post(
|
const templateDeatils = await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
`${localStorage.getItem("baseUrl")}functions/getTemplate`,
|
||||||
params,
|
params,
|
||||||
@@ -248,6 +280,20 @@ const ReportTable = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const tenantSignTypes = await fetchTenantDetails();
|
||||||
|
const docSignTypes = Doc?.SignatureType || signatureTypes;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
docSignTypes
|
||||||
|
);
|
||||||
|
const SignatureType =
|
||||||
|
updatedSignatureType.length > 0
|
||||||
|
? { SignatureType: updatedSignatureType }
|
||||||
|
: {};
|
||||||
|
const NotifyOnSignatures =
|
||||||
|
Doc.NotifyOnSignatures !== undefined
|
||||||
|
? { NotifyOnSignatures: Doc.NotifyOnSignatures }
|
||||||
|
: {};
|
||||||
let placeholdersArr = [];
|
let placeholdersArr = [];
|
||||||
if (Doc.Placeholders?.length > 0) {
|
if (Doc.Placeholders?.length > 0) {
|
||||||
placeholdersArr = Doc.Placeholders;
|
placeholdersArr = Doc.Placeholders;
|
||||||
@@ -273,7 +319,10 @@ const ReportTable = (props) => {
|
|||||||
SendinOrder: Doc?.SendinOrder || false,
|
SendinOrder: Doc?.SendinOrder || false,
|
||||||
AutomaticReminders: Doc?.AutomaticReminders || false,
|
AutomaticReminders: Doc?.AutomaticReminders || false,
|
||||||
RemindOnceInEvery: Doc?.RemindOnceInEvery || 5,
|
RemindOnceInEvery: Doc?.RemindOnceInEvery || 5,
|
||||||
IsEnableOTP: Doc?.IsEnableOTP || false
|
IsEnableOTP: Doc?.IsEnableOTP || false,
|
||||||
|
FileAdapterId: Doc?.FileAdapterId || "",
|
||||||
|
...SignatureType,
|
||||||
|
...NotifyOnSignatures
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
const res = await axios.post(
|
||||||
@@ -373,6 +422,21 @@ const ReportTable = (props) => {
|
|||||||
handleEmbedFunction(item);
|
handleEmbedFunction(item);
|
||||||
} else if (act.action === "CopyTemplateId") {
|
} else if (act.action === "CopyTemplateId") {
|
||||||
copyTemplateId(item.objectId);
|
copyTemplateId(item.objectId);
|
||||||
|
} else if (act.action === "CopyPublicURL") {
|
||||||
|
const isPublic = item?.IsPublic;
|
||||||
|
if (isPublic) {
|
||||||
|
let publicUrl = "";
|
||||||
|
if (isStaging) {
|
||||||
|
publicUrl = `https://staging.opensign.me/publicsign?templateid=${item.objectId}`;
|
||||||
|
} else {
|
||||||
|
publicUrl = `https://opensign.me/publicsign?templateid=${item.objectId}`;
|
||||||
|
}
|
||||||
|
copyTemplateId(publicUrl);
|
||||||
|
} else {
|
||||||
|
setIsPublicTour({ [item.objectId]: true });
|
||||||
|
}
|
||||||
|
} else if (act.action) {
|
||||||
|
setIsModal({ [`extendexpiry_${item.objectId}`]: true });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Get current list
|
// Get current list
|
||||||
@@ -588,40 +652,27 @@ const ReportTable = (props) => {
|
|||||||
|
|
||||||
async function checkTourStatus() {
|
async function checkTourStatus() {
|
||||||
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
||||||
const res = { data: cloudRes.toJSON() };
|
if (cloudRes) {
|
||||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
const extUser = JSON.parse(JSON.stringify(cloudRes));
|
||||||
const tourStatus = res.data.TourStatus;
|
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
|
||||||
// console.log("res ", res.data.TourStatus);
|
const tourStatus = extUser?.TourStatus || [];
|
||||||
setTourStatusArr(tourStatus);
|
setTourStatusArr(tourStatus);
|
||||||
const filteredtourStatus = tourStatus.filter(
|
const templateTour = tourStatus.find(
|
||||||
(obj) => obj["templateTour"]
|
(obj) => obj.templateTour
|
||||||
);
|
)?.templateTour;
|
||||||
if (filteredtourStatus.length > 0) {
|
setIsTour(!templateTour);
|
||||||
const templateTour = filteredtourStatus[0]["templateTour"];
|
|
||||||
|
|
||||||
if (templateTour) {
|
|
||||||
setIsTour(false);
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsTour(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setIsTour(true);
|
setIsTour(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeTour = async () => {
|
const closeTour = async () => {
|
||||||
// console.log("closeTour");
|
|
||||||
setIsTour(false);
|
setIsTour(false);
|
||||||
if (props.isDontShow) {
|
if (props.isDontShow) {
|
||||||
const serverUrl = localStorage.getItem("baseUrl");
|
const serverUrl = localStorage.getItem("baseUrl");
|
||||||
const appId = localStorage.getItem("parseAppId");
|
const appId = localStorage.getItem("parseAppId");
|
||||||
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;
|
||||||
// console.log("extUserId ", extUserId)
|
|
||||||
|
|
||||||
let updatedTourStatus = [];
|
let updatedTourStatus = [];
|
||||||
if (tourStatusArr.length > 0) {
|
if (tourStatusArr.length > 0) {
|
||||||
updatedTourStatus = [...tourStatusArr];
|
updatedTourStatus = [...tourStatusArr];
|
||||||
@@ -639,14 +690,8 @@ const ReportTable = (props) => {
|
|||||||
|
|
||||||
await axios.put(
|
await axios.put(
|
||||||
serverUrl + "classes/contracts_Users/" + extUserId,
|
serverUrl + "classes/contracts_Users/" + extUserId,
|
||||||
{
|
{ TourStatus: updatedTourStatus },
|
||||||
TourStatus: updatedTourStatus
|
{ headers: { "X-Parse-Application-Id": appId } }
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"X-Parse-Application-Id": appId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -657,12 +702,21 @@ const ReportTable = (props) => {
|
|||||||
const url = item?.SignedUrl || item?.URL || "";
|
const url = item?.SignedUrl || item?.URL || "";
|
||||||
const pdfName = item?.Name || "exported_file";
|
const pdfName = item?.Name || "exported_file";
|
||||||
const isCompleted = item?.IsCompleted || false;
|
const isCompleted = item?.IsCompleted || false;
|
||||||
|
const templateId = props?.ReportName === "Templates" && item.objectId;
|
||||||
|
const docId = props?.ReportName !== "Templates" && item.objectId;
|
||||||
|
const fileAdapterId = item?.FileAdapterId ? item?.FileAdapterId : "";
|
||||||
|
|
||||||
if (url) {
|
if (url) {
|
||||||
try {
|
try {
|
||||||
if (isCompleted) {
|
if (isCompleted) {
|
||||||
setIsDownloadModal({ [item.objectId]: true });
|
setIsDownloadModal({ [item.objectId]: true });
|
||||||
} else {
|
} else {
|
||||||
const signedUrl = await getSignedUrl(url);
|
const signedUrl = await getSignedUrl(
|
||||||
|
url,
|
||||||
|
docId,
|
||||||
|
fileAdapterId,
|
||||||
|
templateId
|
||||||
|
);
|
||||||
await fetchUrl(signedUrl, pdfName);
|
await fetchUrl(signedUrl, pdfName);
|
||||||
}
|
}
|
||||||
setActLoader({});
|
setActLoader({});
|
||||||
@@ -697,7 +751,7 @@ const ReportTable = (props) => {
|
|||||||
receiver_phone: userDetails?.Phone || "",
|
receiver_phone: userDetails?.Phone || "",
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: doc.ExtUserPtr.Company,
|
company_name: doc.ExtUserPtr.Company,
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||||
};
|
};
|
||||||
const res = replaceMailVaribles(subject, "", variables);
|
const res = replaceMailVaribles(subject, "", variables);
|
||||||
|
|
||||||
@@ -726,7 +780,7 @@ const ReportTable = (props) => {
|
|||||||
receiver_phone: userDetails?.Phone || "",
|
receiver_phone: userDetails?.Phone || "",
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: doc.ExtUserPtr.Company,
|
company_name: doc.ExtUserPtr.Company,
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||||
};
|
};
|
||||||
const res = replaceMailVaribles("", body, variables);
|
const res = replaceMailVaribles("", body, variables);
|
||||||
|
|
||||||
@@ -767,7 +821,7 @@ const ReportTable = (props) => {
|
|||||||
receiver_phone: user?.signerPtr?.Phone || "",
|
receiver_phone: user?.signerPtr?.Phone || "",
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: doc?.ExtUserPtr?.Company || "",
|
company_name: doc?.ExtUserPtr?.Company || "",
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||||
};
|
};
|
||||||
|
|
||||||
const subject =
|
const subject =
|
||||||
@@ -896,6 +950,13 @@ const ReportTable = (props) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const templateRes = axiosRes.data && axiosRes.data.result;
|
const templateRes = axiosRes.data && axiosRes.data.result;
|
||||||
|
const tenantSignTypes = await fetchTenantDetails();
|
||||||
|
const docSignTypes = templateRes?.SignatureType || signatureTypes;
|
||||||
|
const updatedSignatureType = await handleSignatureType(
|
||||||
|
tenantSignTypes,
|
||||||
|
docSignTypes
|
||||||
|
);
|
||||||
|
setSignatureType(updatedSignatureType);
|
||||||
setPlaceholders(templateRes?.Placeholders);
|
setPlaceholders(templateRes?.Placeholders);
|
||||||
setTemplateDetails(templateRes);
|
setTemplateDetails(templateRes);
|
||||||
setIsLoader({});
|
setIsLoader({});
|
||||||
@@ -1133,6 +1194,140 @@ const ReportTable = (props) => {
|
|||||||
setIsPublicUserName(extendUser[0]?.UserName || "");
|
setIsPublicUserName(extendUser[0]?.UserName || "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const publicTourConfig = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="IsPublic"]',
|
||||||
|
content: t("public-tour-message"),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const closePublicTour = () => {
|
||||||
|
setIsPublicTour();
|
||||||
|
};
|
||||||
|
const handleUpdateExpiry = async (e, item) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (expiryDate) {
|
||||||
|
const oldExpiryDate = new Date(item?.ExpiryDate?.iso);
|
||||||
|
const newExpiryDate = new Date(expiryDate);
|
||||||
|
if (newExpiryDate > oldExpiryDate) {
|
||||||
|
setActLoader({ [`${item.objectId}`]: true });
|
||||||
|
const updateExpiryDate = new Date(expiryDate).toISOString();
|
||||||
|
const expiryIsoFormat = { iso: updateExpiryDate, __type: "Date" };
|
||||||
|
try {
|
||||||
|
const serverUrl = serverUrl_fn();
|
||||||
|
const cls = "contracts_Document";
|
||||||
|
const url = serverUrl + `/classes/${cls}/`;
|
||||||
|
const body = { ExpiryDate: expiryIsoFormat };
|
||||||
|
const res = await axios.put(url + item.objectId, body, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (res.data && res.data.updatedAt) {
|
||||||
|
setIsAlert(true);
|
||||||
|
setAlertMsg({
|
||||||
|
type: "success",
|
||||||
|
message: t("expiry-date-updated", {
|
||||||
|
newexpirydate: new Date(expiryDate)?.toLocaleDateString()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if (props.ReportName === "Expired Documents") {
|
||||||
|
const upldatedList = props.List.filter(
|
||||||
|
(x) => x.objectId !== item.objectId
|
||||||
|
);
|
||||||
|
props.setList(upldatedList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err", err);
|
||||||
|
setIsAlert(true);
|
||||||
|
setAlertMsg({
|
||||||
|
type: "danger",
|
||||||
|
message: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setActLoader({});
|
||||||
|
setExpiryDate();
|
||||||
|
setTimeout(() => setIsAlert(false), 2000);
|
||||||
|
setIsModal({});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsAlert(true);
|
||||||
|
setAlertMsg({ type: "danger", message: t("expiry-date-error") });
|
||||||
|
setTimeout(() => setIsAlert(false), 2000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsAlert(true);
|
||||||
|
setAlertMsg({ type: "danger", message: t("expiry-date-error") });
|
||||||
|
setTimeout(() => setIsAlert(false), 2000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// `formatStatusRow` is used to format status row
|
||||||
|
const formatStatusRow = (item) => {
|
||||||
|
const signers = item?.Placeholders?.map((x, i) => {
|
||||||
|
const matchSigner = item?.AuditTrail?.find(
|
||||||
|
(audit) => audit?.UserPtr?.objectId === x.signerObjId
|
||||||
|
);
|
||||||
|
if (matchSigner) {
|
||||||
|
return {
|
||||||
|
id: i,
|
||||||
|
Email: matchSigner.UserPtr.Email,
|
||||||
|
Activity: matchSigner?.Activity?.toUpperCase() || "-",
|
||||||
|
SignedOn: matchSigner?.SignedOn
|
||||||
|
? new Date(matchSigner?.SignedOn)?.toUTCString()
|
||||||
|
: "-",
|
||||||
|
ViewedOn: matchSigner?.ViewedOn
|
||||||
|
? new Date(matchSigner?.ViewedOn)?.toUTCString()
|
||||||
|
: "-"
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
id: i,
|
||||||
|
Email: x?.signerPtr?.Email || x?.email,
|
||||||
|
Activity: "SENT",
|
||||||
|
SignedOn: "-",
|
||||||
|
ViewedOn: "-"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return signers?.map((x, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="text-sm font-medium flex flex-row gap-2 items-center"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsModal({ [`${item.objectId}_${i}`]: true })}
|
||||||
|
className={`${
|
||||||
|
x.Activity === "SIGNED"
|
||||||
|
? "op-border-primary op-text-primary"
|
||||||
|
: x.Activity === "VIEWED"
|
||||||
|
? "border-green-400 text-green-400"
|
||||||
|
: "border-black text-black"
|
||||||
|
} focus:outline-none border-2 w-[60px] h-[30px] text-[11px] rounded-full`}
|
||||||
|
>
|
||||||
|
{x?.Activity?.toUpperCase() || "-"}
|
||||||
|
</button>
|
||||||
|
<div className="py-2 font-bold text-[12px]">{x?.Email || "-"}</div>
|
||||||
|
{isModal[`${item.objectId}_${i}`] && (
|
||||||
|
<ModalUi
|
||||||
|
isOpen
|
||||||
|
title={t("document-logs")}
|
||||||
|
handleClose={() => setIsModal({})}
|
||||||
|
>
|
||||||
|
<div className="pl-3 first:mt-2 border-t-[1px] border-gray-600 text-[12px] py-2">
|
||||||
|
<p className="font-bold"> {x?.Email}</p>
|
||||||
|
<p>Viewed on: {x?.ViewedOn}</p>
|
||||||
|
<p>Signed on: {x?.SignedOn}</p>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{Object.keys(actLoader)?.length > 0 && (
|
{Object.keys(actLoader)?.length > 0 && (
|
||||||
@@ -1140,7 +1335,7 @@ const ReportTable = (props) => {
|
|||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="p-2 w-full overflow-hidden bg-base-100 text-base-content op-card shadow-lg">
|
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
|
||||||
{isCelebration && (
|
{isCelebration && (
|
||||||
<div className="relative z-[1000]">
|
<div className="relative z-[1000]">
|
||||||
<Confetti
|
<Confetti
|
||||||
@@ -1153,6 +1348,7 @@ const ReportTable = (props) => {
|
|||||||
)}
|
)}
|
||||||
{isAlert && <Alert type={alertMsg.type}>{alertMsg.message}</Alert>}
|
{isAlert && <Alert type={alertMsg.type}>{alertMsg.message}</Alert>}
|
||||||
{props.tourData && props.ReportName === "Templates" && (
|
{props.tourData && props.ReportName === "Templates" && (
|
||||||
|
<>
|
||||||
<Tour
|
<Tour
|
||||||
onRequestClose={closeTour}
|
onRequestClose={closeTour}
|
||||||
steps={props.tourData}
|
steps={props.tourData}
|
||||||
@@ -1160,6 +1356,19 @@ const ReportTable = (props) => {
|
|||||||
// rounded={5}
|
// rounded={5}
|
||||||
closeWithMask={false}
|
closeWithMask={false}
|
||||||
/>
|
/>
|
||||||
|
{isPublicTour && (
|
||||||
|
<Tour
|
||||||
|
showNumber={false}
|
||||||
|
showNavigation={false}
|
||||||
|
showNavigationNumber={false}
|
||||||
|
onRequestClose={closePublicTour}
|
||||||
|
steps={publicTourConfig}
|
||||||
|
isOpen={true}
|
||||||
|
rounded={5}
|
||||||
|
closeWithMask={false}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
|
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
|
||||||
<div className="font-light">
|
<div className="font-light">
|
||||||
@@ -1187,23 +1396,29 @@ const ReportTable = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`overflow-auto w-full border-b ${
|
||||||
isDashboard && props.List?.length > 0 ? "min-h-[317px]" : "h-full"
|
props.List?.length > 0
|
||||||
} overflow-auto w-full`}
|
? isDashboard
|
||||||
|
? "min-h-[317px]"
|
||||||
|
: currentList?.length === props.docPerPage
|
||||||
|
? "h-fit"
|
||||||
|
: "h-screen"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<table className="op-table border-collapse w-full ">
|
<table className="op-table border-collapse w-full mb-4">
|
||||||
<thead className="text-[14px]">
|
<thead className="text-[14px] text-center">
|
||||||
<tr className="border-y-[1px]">
|
<tr className="border-y-[1px]">
|
||||||
{props.heading?.map((item, index) => (
|
{props.heading?.map((item, index) => (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
<th className="px-4 py-2">{t(`report-heading.${item}`)}</th>
|
<th className="p-2">{t(`report-heading.${item}`)}</th>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
{props.ReportName === "Templates" && isEnableSubscription && (
|
{props.ReportName === "Templates" && isEnableSubscription && (
|
||||||
<th className="px-4 py-2">{t("public")}</th>
|
<th className="p-2">{t("public")}</th>
|
||||||
)}
|
)}
|
||||||
{props.actions?.length > 0 && (
|
{props.actions?.length > 0 && (
|
||||||
<th className="px-4 py-2 text-transparent pointer-events-none">
|
<th className="p-2 text-transparent pointer-events-none">
|
||||||
{t("action")}
|
{t("action")}
|
||||||
</th>
|
</th>
|
||||||
)}
|
)}
|
||||||
@@ -1216,15 +1431,17 @@ const ReportTable = (props) => {
|
|||||||
props.ReportName === "Contactbook" ? (
|
props.ReportName === "Contactbook" ? (
|
||||||
<tr className="border-y-[1px]" key={index}>
|
<tr className="border-y-[1px]" key={index}>
|
||||||
{props.heading.includes("Sr.No") && (
|
{props.heading.includes("Sr.No") && (
|
||||||
<th className="px-4 py-2">
|
<th className="p-2">{startIndex + index + 1}</th>
|
||||||
{startIndex + index + 1}
|
|
||||||
</th>
|
|
||||||
)}
|
)}
|
||||||
<td className="px-4 py-2 font-semibold">
|
<td className="px-4 py-2 font-semibold">
|
||||||
{item?.Name}{" "}
|
{item?.Name}{" "}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2 ">{item?.Email || "-"}</td>
|
<td className="p-2 text-center">
|
||||||
<td className="px-4 py-2">{item?.Phone || "-"}</td>
|
{item?.Email || "-"}
|
||||||
|
</td>
|
||||||
|
<td className="p-2 text-center">
|
||||||
|
{item?.Phone || "-"}
|
||||||
|
</td>
|
||||||
<td className="px-3 py-2">
|
<td className="px-3 py-2">
|
||||||
<div className="text-base-content min-w-max flex flex-row gap-x-2 gap-y-1 justify-start items-center">
|
<div className="text-base-content min-w-max flex flex-row gap-x-2 gap-y-1 justify-start items-center">
|
||||||
{props.actions?.length > 0 &&
|
{props.actions?.length > 0 &&
|
||||||
@@ -1272,36 +1489,48 @@ const ReportTable = (props) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : (
|
) : (
|
||||||
<tr className="border-y-[1px]" key={index}>
|
<tr
|
||||||
|
className={`${
|
||||||
|
currentList?.length === props.docPerPage
|
||||||
|
? "last:border-none"
|
||||||
|
: ""
|
||||||
|
} border-y-[1px] `}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
{props.heading.includes("Sr.No") && (
|
{props.heading.includes("Sr.No") && (
|
||||||
<th className="px-4 py-2">
|
<th className="px-2 py-2">
|
||||||
{startIndex + index + 1}
|
{startIndex + index + 1}
|
||||||
</th>
|
</th>
|
||||||
)}
|
)}
|
||||||
<td className="px-4 py-2 font-semibold min-w-56 max-w-56">
|
<td className="p-2 min-w-56 max-w-56 flex flex-col">
|
||||||
{item?.Name}{" "}
|
<div className="font-semibold">{item?.Name}</div>
|
||||||
|
{item?.ExpiryDate?.iso && (
|
||||||
|
<div className="text-gray-500">
|
||||||
|
Expire: {formatDate(item?.ExpiryDate?.iso)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
{props?.heading?.includes("Reason") && (
|
{props?.heading?.includes("Reason") && (
|
||||||
<td className="px-4 py-2">
|
<td className="p-2 text-center">
|
||||||
{item?.DeclineReason?.length > 25
|
{item?.DeclineReason?.length > 25
|
||||||
? item?.DeclineReason?.slice(0, 25) + "..."
|
? item?.DeclineReason?.slice(0, 25) + "..."
|
||||||
: item?.DeclineReason || "-"}
|
: item?.DeclineReason || "-"}
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
{props.heading.includes("Note") && (
|
{props.heading.includes("Note") && (
|
||||||
<td className="px-4 py-2">
|
<td className="p-2 text-center">
|
||||||
{item?.Note?.length > 25
|
<p className="truncate w-[100px]">
|
||||||
? item?.Note?.slice(0, 25) + "..."
|
{item?.Note || "-"}
|
||||||
: item?.Note || "-"}
|
</p>
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
{props.heading.includes("Folder") && (
|
{props.heading.includes("Folder") && (
|
||||||
<td className="px-4 py-2">
|
<td className="p-2 text-center">
|
||||||
{item?.Folder?.Name ||
|
{item?.Folder?.Name ||
|
||||||
t("sidebar.OpenSign™ Drive")}
|
t("sidebar.OpenSign™ Drive")}
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
<td className="px-4 py-2">
|
<td className="p-2 text-center">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDownload(item)}
|
onClick={() => handleDownload(item)}
|
||||||
className="op-link op-link-primary"
|
className="op-link op-link-primary"
|
||||||
@@ -1310,56 +1539,22 @@ const ReportTable = (props) => {
|
|||||||
{item?.URL ? t("download") : "-"}
|
{item?.URL ? t("download") : "-"}
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
{props.ReportName === "In-progress documents" ? (
|
{props.heading.includes("Owner") && (
|
||||||
<td className="px-4 py-2">
|
<td className="p-2 text-center">
|
||||||
<button
|
|
||||||
onClick={() =>
|
|
||||||
item?.AuditTrail?.length > 0 &&
|
|
||||||
setIsModal({ [item?.objectId]: true })
|
|
||||||
}
|
|
||||||
className={`${
|
|
||||||
item?.AuditTrail?.length
|
|
||||||
? "border-green-400"
|
|
||||||
: "cursor-default op-border-primary"
|
|
||||||
} focus:outline-none w-[60px] border-[2px] text-[12px] rounded-full md:self-center`}
|
|
||||||
>
|
|
||||||
{item?.AuditTrail?.length ? "VIEWED" : "SENT"}
|
|
||||||
</button>
|
|
||||||
{isModal[item.objectId] && (
|
|
||||||
<ModalUi
|
|
||||||
isOpen
|
|
||||||
title={t("document-logs")}
|
|
||||||
handleClose={() => setIsModal({})}
|
|
||||||
>
|
|
||||||
{item?.AuditTrail?.map((x, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="pl-3 first:mt-2 text-sm font-medium flex flex-col md:flex-row items-start md:gap-4 border-t-[1px] border-gray-600"
|
|
||||||
>
|
|
||||||
<div className="py-2 break-all font-bold md:text-[12px] md:col-span-2 w-full md:w-[210px]">
|
|
||||||
{x?.UserPtr?.Email || "-"}
|
|
||||||
</div>
|
|
||||||
<button className="px-2 cursor-default border-[2px] text-[12px] border-green-400 rounded-full md:self-center">
|
|
||||||
{x?.Activity?.toUpperCase() || "-"}
|
|
||||||
</button>
|
|
||||||
<div className=" text-[12px] py-2">
|
|
||||||
{x?.Activity === "Signed"
|
|
||||||
? new Date(x?.SignedOn)?.toUTCString()
|
|
||||||
: new Date(
|
|
||||||
x?.ViewedOn
|
|
||||||
)?.toUTCString() || "-"}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</ModalUi>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
) : (
|
|
||||||
<td className="px-4 py-2">
|
|
||||||
{formatRow(item?.ExtUserPtr)}
|
{formatRow(item?.ExtUserPtr)}
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
<td className="px-4 py-2">
|
{props.heading.includes("Signers") &&
|
||||||
|
["In-progress documents", "Need your sign"].includes(
|
||||||
|
props.ReportName
|
||||||
|
) ? (
|
||||||
|
<td className="px-1 py-2">
|
||||||
|
{!item?.IsSignyourself && item?.Placeholders && (
|
||||||
|
<>{formatStatusRow(item)}</>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
) : (
|
||||||
|
<td className="p-2 text-center">
|
||||||
{!item?.IsSignyourself && item?.Placeholders ? (
|
{!item?.IsSignyourself && item?.Placeholders ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => handleViewSigners(item)}
|
onClick={() => handleViewSigners(item)}
|
||||||
@@ -1371,17 +1566,22 @@ const ReportTable = (props) => {
|
|||||||
"-"
|
"-"
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
)}
|
||||||
{props.ReportName === "Templates" &&
|
{props.ReportName === "Templates" &&
|
||||||
isEnableSubscription && (
|
isEnableSubscription && (
|
||||||
<td className=" pl-[20px] py-2">
|
<td className=" pl-[20px] py-2">
|
||||||
{props.ReportName === "Templates" && (
|
{props.ReportName === "Templates" && (
|
||||||
<div className="flex flex-row">
|
<div
|
||||||
|
className="flex flex-row"
|
||||||
|
data-tut="IsPublic"
|
||||||
|
>
|
||||||
<label className="cursor-pointer relative inline-flex items-center mb-0">
|
<label className="cursor-pointer relative inline-flex items-center mb-0">
|
||||||
<input
|
<input
|
||||||
checked={props.isPublic?.[item.objectId]}
|
checked={props.isPublic?.[item.objectId]}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
handlePublicChange(e, item)
|
setIsPublicTour();
|
||||||
}
|
handlePublicChange(e, item);
|
||||||
|
}}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
value=""
|
value=""
|
||||||
className="sr-only peer"
|
className="sr-only peer"
|
||||||
@@ -1436,13 +1636,13 @@ const ReportTable = (props) => {
|
|||||||
}
|
}
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
{t("submit")}
|
{t("yes")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleClose(item)}
|
onClick={() => handleClose(item)}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
{t("cancel")}
|
{t("no")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1468,14 +1668,14 @@ const ReportTable = (props) => {
|
|||||||
<span>{t("public-url-copy")}</span>
|
<span>{t("public-url-copy")}</span>
|
||||||
<div className=" flex items-center justify-between gap-3 p-[2px] ">
|
<div className=" flex items-center justify-between gap-3 p-[2px] ">
|
||||||
<div className="w-[280px] whitespace-nowrap overflow-hidden text-ellipsis">
|
<div className="w-[280px] whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
<span
|
<a
|
||||||
onClick={() =>
|
rel="noreferrer"
|
||||||
copytoProfileLink()
|
target="_blank"
|
||||||
}
|
href={publicUrl()}
|
||||||
className="ml-[2px] underline underline-offset-2 cursor-pointer text-blue-800"
|
className="ml-[2px] underline underline-offset-2 cursor-pointer text-blue-800"
|
||||||
>
|
>
|
||||||
{publicUrl()}
|
{publicUrl()}
|
||||||
</span>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<RWebShare
|
<RWebShare
|
||||||
@@ -1492,7 +1692,7 @@ const ReportTable = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
</RWebShare>
|
</RWebShare>
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm md:w-[100px]"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copytoProfileLink()
|
copytoProfileLink()
|
||||||
}
|
}
|
||||||
@@ -1518,7 +1718,7 @@ const ReportTable = (props) => {
|
|||||||
className="mt-3 op-btn op-btn-primary"
|
className="mt-3 op-btn op-btn-primary"
|
||||||
onClick={() => navigate("/profile")}
|
onClick={() => navigate("/profile")}
|
||||||
>
|
>
|
||||||
{t("add")}
|
{t("Proceed")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -1547,9 +1747,7 @@ const ReportTable = (props) => {
|
|||||||
className={
|
className={
|
||||||
act.action !== "option"
|
act.action !== "option"
|
||||||
? `${
|
? `${
|
||||||
act?.btnColor
|
act?.btnColor || ""
|
||||||
? act.btnColor
|
|
||||||
: ""
|
|
||||||
} op-btn op-btn-sm mr-1`
|
} op-btn op-btn-sm mr-1`
|
||||||
: "text-base-content focus:outline-none text-lg mr-2 relative"
|
: "text-base-content focus:outline-none text-lg mr-2 relative"
|
||||||
}
|
}
|
||||||
@@ -1566,9 +1764,10 @@ const ReportTable = (props) => {
|
|||||||
)}`}
|
)}`}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{/* template report */}
|
||||||
{isOption[item.objectId] &&
|
{isOption[item.objectId] &&
|
||||||
act.action === "option" && (
|
act.action === "option" && (
|
||||||
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow bg-base-100 text-base-content rounded-box">
|
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow-black/20 shadow bg-base-100 text-base-content rounded-box">
|
||||||
{act.subaction?.map((subact) => (
|
{act.subaction?.map((subact) => (
|
||||||
<li
|
<li
|
||||||
key={subact.btnId}
|
key={subact.btnId}
|
||||||
@@ -1622,9 +1821,10 @@ const ReportTable = (props) => {
|
|||||||
{t(`btnLabel.${act.btnLabel}`)}
|
{t(`btnLabel.${act.btnLabel}`)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{/* doc report */}
|
||||||
{isOption[item.objectId] &&
|
{isOption[item.objectId] &&
|
||||||
act.action === "option" && (
|
act.action === "option" && (
|
||||||
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow bg-base-100 text-base-content rounded-box">
|
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow-black/20 shadow bg-base-100 text-base-content rounded-box">
|
||||||
{act.subaction?.map((subact) => (
|
{act.subaction?.map((subact) => (
|
||||||
<li
|
<li
|
||||||
key={subact.btnId}
|
key={subact.btnId}
|
||||||
@@ -1655,6 +1855,41 @@ const ReportTable = (props) => {
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{isModal["extendexpiry_" + item.objectId] && (
|
||||||
|
<ModalUi
|
||||||
|
isOpen
|
||||||
|
title={t("btnLabel.extend-expiry-date")}
|
||||||
|
reduceWidth={"md:max-w-[450px]"}
|
||||||
|
handleClose={() => setIsModal({})}
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
className="px-4 py-2 flex flex-col"
|
||||||
|
onSubmit={(e) => handleUpdateExpiry(e, item)}
|
||||||
|
>
|
||||||
|
<label className="mr-2">
|
||||||
|
{t("expiry-date")} {"(dd-mm-yyyy)"}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded-full mb-2 bg-base-300 w-full px-4 py-2 text-black border-2 hover:border-spacing-2"
|
||||||
|
defaultValue={
|
||||||
|
item?.ExpiryDate?.iso?.split("T")?.[0]
|
||||||
|
}
|
||||||
|
onChange={(e) => {
|
||||||
|
setExpiryDate(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex justify-start mb-1">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("update")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
|
)}
|
||||||
{isShareWith[item.objectId] && (
|
{isShareWith[item.objectId] && (
|
||||||
<div className="op-modal op-modal-open">
|
<div className="op-modal op-modal-open">
|
||||||
<div className="max-h-90 bg-base-100 w-[95%] md:max-w-[500px] rounded-box relative">
|
<div className="max-h-90 bg-base-100 w-[95%] md:max-w-[500px] rounded-box relative">
|
||||||
@@ -1877,6 +2112,7 @@ const ReportTable = (props) => {
|
|||||||
Placeholders={placeholders}
|
Placeholders={placeholders}
|
||||||
item={templateDeatils}
|
item={templateDeatils}
|
||||||
handleClose={handleQuickSendClose}
|
handleClose={handleQuickSendClose}
|
||||||
|
signatureType={signatureType}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
@@ -2086,6 +2322,24 @@ const ReportTable = (props) => {
|
|||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{props.List?.length <= 0 && (
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isDashboard ? "h-[317px]" : ""
|
||||||
|
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
|
||||||
|
>
|
||||||
|
<div className="w-[60px] h-[60px] overflow-hidden">
|
||||||
|
<img
|
||||||
|
className="w-full h-full object-contain"
|
||||||
|
src={pad}
|
||||||
|
alt="img"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-semibold">
|
||||||
|
{t("no-data-avaliable")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="op-join flex flex-wrap items-center p-2">
|
<div className="op-join flex flex-wrap items-center p-2">
|
||||||
{props.List.length > props.docPerPage && (
|
{props.List.length > props.docPerPage && (
|
||||||
@@ -2117,24 +2371,6 @@ const ReportTable = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{props.List?.length <= 0 && (
|
|
||||||
<div
|
|
||||||
className={`${
|
|
||||||
isDashboard ? "h-[317px]" : ""
|
|
||||||
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
|
|
||||||
>
|
|
||||||
<div className="w-[60px] h-[60px] overflow-hidden">
|
|
||||||
<img
|
|
||||||
className="w-full h-full object-contain"
|
|
||||||
src={pad}
|
|
||||||
alt="img"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="text-sm font-semibold">
|
|
||||||
{t("no-data-avaliable")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={t("add-contact")}
|
title={t("add-contact")}
|
||||||
isOpen={isContactform}
|
isOpen={isContactform}
|
||||||
|
|||||||
@@ -19,11 +19,16 @@ const LinkUserModal = (props) => {
|
|||||||
details={props.handleAddUser}
|
details={props.handleAddUser}
|
||||||
closePopup={props.closePopup}
|
closePopup={props.closePopup}
|
||||||
signersData={props?.signersData}
|
signersData={props?.signersData}
|
||||||
|
jwttoken={props?.jwttoken}
|
||||||
/>
|
/>
|
||||||
<div className="op-divider text-base-content mx-[25%] my-1">
|
<div className="op-divider text-base-content mx-[25%] my-1">
|
||||||
{t("or")}
|
{t("or")}
|
||||||
</div>
|
</div>
|
||||||
<AddContact details={props.handleAddUser} closePopup={props.closePopup} />
|
<AddContact
|
||||||
|
details={props.handleAddUser}
|
||||||
|
closePopup={props.closePopup}
|
||||||
|
jwttoken={props?.jwttoken}
|
||||||
|
/>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,29 @@ import { useTranslation } from "react-i18next";
|
|||||||
function CustomModal(props) {
|
function CustomModal(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [reason, setReason] = useState("");
|
const [reason, setReason] = useState("");
|
||||||
|
const [isExtendExpiry, setIsExtendExpiry] = useState(false);
|
||||||
|
const [expiryDate, setExpiryDate] = useState("");
|
||||||
|
const localuser = localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentUser = JSON.parse(localuser);
|
||||||
|
const isCreator = props?.doc
|
||||||
|
? props?.doc?.CreatedBy?.objectId === currentUser?.objectId &&
|
||||||
|
localStorage.getItem("_user_role") !== "Guest"
|
||||||
|
: false;
|
||||||
|
const handleExtendBtn = () => setIsExtendExpiry(!isExtendExpiry);
|
||||||
|
|
||||||
|
const handleUpdateExpiry = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (expiryDate) {
|
||||||
|
props.handleExpiry && props.handleExpiry(expiryDate);
|
||||||
|
} else {
|
||||||
|
alert(t("expiry-date-error"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
props.show && (
|
props.show && (
|
||||||
<dialog className="op-modal op-modal-open absolute z-[448]">
|
<dialog className="op-modal op-modal-open absolute z-[448]">
|
||||||
@@ -12,17 +35,29 @@ function CustomModal(props) {
|
|||||||
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
|
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
|
||||||
{props?.headMsg && props?.headMsg}
|
{props?.headMsg && props?.headMsg}
|
||||||
</h3>
|
</h3>
|
||||||
|
{!isExtendExpiry && (
|
||||||
<div className="p-[10px] px-[20px]">
|
<div className="p-[10px] px-[20px]">
|
||||||
<p className="text-[15px]">{props.bodyMssg && props.bodyMssg}</p>
|
<p className="text-[15px]">{props.bodyMssg && props.bodyMssg}</p>
|
||||||
</div>
|
</div>
|
||||||
{props.isDownloadBtn && (
|
)}
|
||||||
<div className="flex justify-start w-full ml-[20px] mb-3 mt-1">
|
{!isExtendExpiry && (
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
{isCreator && (
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary "
|
className="op-btn op-btn-primary px-6 ml-[20px] mb-3 mt-1"
|
||||||
|
onClick={() => handleExtendBtn()}
|
||||||
|
>
|
||||||
|
Extend
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{props.isDownloadBtn && (
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-primary ml-[10px] mb-3 mt-1"
|
||||||
onClick={() => props.handleDownloadBtn()}
|
onClick={() => props.handleDownloadBtn()}
|
||||||
>
|
>
|
||||||
Download
|
Download
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{props.footerMessage && (
|
{props.footerMessage && (
|
||||||
@@ -60,6 +95,34 @@ function CustomModal(props) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{isExtendExpiry && (
|
||||||
|
<form className="mx-3 mb-3" onSubmit={handleUpdateExpiry}>
|
||||||
|
<label className="ml-2 mt-2">
|
||||||
|
{t("expiry-date")} {"(dd-mm-yyyy)"}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded-full bg-base-300 w-full px-4 py-2 text-black border-2 hover:border-spacing-2"
|
||||||
|
defaultValue={props?.doc?.ExpiryDate?.iso?.split("T")?.[0]}
|
||||||
|
onChange={(e) => setExpiryDate(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div className="flex flex-row items-center mt-2">
|
||||||
|
<button type="submit" className="op-btn op-btn-primary mr-2">
|
||||||
|
{t("update")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setExpiryDate("");
|
||||||
|
setIsExtendExpiry(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
const QuotaCard = ({ isPaidInfo, handlClose }) => {
|
const QuotaCard = ({ isPaidInfo, handlClose, emailResetDate }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
return isPaidInfo ? (
|
return isPaidInfo ? (
|
||||||
@@ -17,6 +17,11 @@ const QuotaCard = ({ isPaidInfo, handlClose }) => {
|
|||||||
<div className="op-card-body">
|
<div className="op-card-body">
|
||||||
<h2 className="op-card-title">{t("quota-mail-info-head")}</h2>
|
<h2 className="op-card-title">{t("quota-mail-info-head")}</h2>
|
||||||
<p>{t("quota-mail-info")}</p>
|
<p>{t("quota-mail-info")}</p>
|
||||||
|
{emailResetDate && (
|
||||||
|
<p>
|
||||||
|
{t("quota-mail-reset")} {emailResetDate}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
<p>
|
<p>
|
||||||
<Trans i18nKey={"quota-mail-tip"}>
|
<Trans i18nKey={"quota-mail-tip"}>
|
||||||
Tip: You can still sign <strong>unlimited documents</strong> by
|
Tip: You can still sign <strong>unlimited documents</strong> by
|
||||||
@@ -39,7 +44,17 @@ const QuotaCard = ({ isPaidInfo, handlClose }) => {
|
|||||||
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
|
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
|
||||||
<div className="op-card-body">
|
<div className="op-card-body">
|
||||||
<p>{t("quota-mail")}</p>
|
<p>{t("quota-mail")}</p>
|
||||||
<p>{t("quota-mail-tip")}</p>
|
{emailResetDate && (
|
||||||
|
<p>
|
||||||
|
{t("quota-mail-reset")} {emailResetDate}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<Trans i18nKey={"quota-mail-tip"}>
|
||||||
|
Tip: You can still sign <strong>unlimited documents</strong> by
|
||||||
|
manually sharing the signing request links.
|
||||||
|
</Trans>
|
||||||
|
</div>
|
||||||
<div className="op-card-actions justify-end">
|
<div className="op-card-actions justify-end">
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate("/subscription")}
|
onClick={() => navigate("/subscription")}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import i18n from "i18next";
|
|||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
import LanguageDetector from "i18next-browser-languagedetector";
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
import en from "./locales/en/translation.json";
|
import en from "./locales/en/translation.json";
|
||||||
|
import es from "./locales/es/translation.json";
|
||||||
import fr from "./locales/fr/translation.json";
|
import fr from "./locales/fr/translation.json";
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
@@ -12,6 +13,9 @@ i18n
|
|||||||
en: {
|
en: {
|
||||||
translation: en
|
translation: en
|
||||||
},
|
},
|
||||||
|
es: {
|
||||||
|
translation: es
|
||||||
|
},
|
||||||
fr: {
|
fr: {
|
||||||
translation: fr
|
translation: fr
|
||||||
}
|
}
|
||||||
@@ -27,7 +31,7 @@ i18n
|
|||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false // React already does escaping
|
escapeValue: false // React already does escaping
|
||||||
},
|
},
|
||||||
whitelist: ["en", "fr"] // List of allowed languages
|
whitelist: ["en", "es", "fr"] // List of allowed languages
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"header-news": "New feature: Public profiles are now live! Easily create and share public templates",
|
"header-news": "New feature: Teams plan users can now integrate their own AWS S3 buckets for file storage",
|
||||||
"header-news-btn": "Setup Now",
|
"header-news-btn": "Setup Now",
|
||||||
"create-account": "Create Account",
|
"create-account": "Create Account",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
"upgrade-now": "Upgrade now",
|
"upgrade-now": "Upgrade now",
|
||||||
"upgrade-to": "Upgrade to",
|
"upgrade-to": "Upgrade to",
|
||||||
"plan": "Plan",
|
"plan": "Plan",
|
||||||
"subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
|
"subscribe-card-teamplan": "Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
|
||||||
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
|
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
|
||||||
"user-name-limit-char": "To have a username less than 8 character please subscribe",
|
"user-name-limit-char": "To have a username less than 8 character please subscribe",
|
||||||
"tour-content": "Don't show this again",
|
"tour-content": "Don't show this again",
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
"My Signature": "My Signature",
|
"My Signature": "My Signature",
|
||||||
"API Token": "API Token",
|
"API Token": "API Token",
|
||||||
"Webhook": "Webhook",
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Preferences",
|
||||||
"Teams": "Teams",
|
"Teams": "Teams",
|
||||||
"Team-update-successfully": "Team Updated successfully.",
|
"Team-update-successfully": "Team Updated successfully.",
|
||||||
"Users": "Users"
|
"Users": "Users"
|
||||||
@@ -132,7 +133,9 @@
|
|||||||
"View": "View",
|
"View": "View",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Embed",
|
"Embed": "Embed",
|
||||||
"Copy TemplateId":"Copy TemplateId"
|
"Copy TemplateId": "Copy TemplateId",
|
||||||
|
"Copy Public URL": "Copy Public URL",
|
||||||
|
"extend-expiry-date": "Extend expiry date"
|
||||||
},
|
},
|
||||||
"report-heading": {
|
"report-heading": {
|
||||||
"Sr.No": "Sr.No",
|
"Sr.No": "Sr.No",
|
||||||
@@ -153,7 +156,8 @@
|
|||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"created-date": "Created Date",
|
"created-date": "Created Date",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Logs": "Logs"
|
"Logs": "Logs",
|
||||||
|
"Expiry-date": "Expiry Date"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||||
@@ -264,10 +268,11 @@
|
|||||||
"make-template-public-alert": "Are you sure you want to make this template public?",
|
"make-template-public-alert": "Are you sure you want to make this template public?",
|
||||||
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
||||||
"public-role": "Public role",
|
"public-role": "Public role",
|
||||||
"public-url": "Public URL",
|
"public-url": "Public profile",
|
||||||
|
"embed-template": "Embed Template",
|
||||||
"public-url-copy": "Here’s your public URL: ",
|
"public-url-copy": "Here’s your public URL: ",
|
||||||
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
"public-url-copy-mssg": "Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||||
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
"add-public-url-alert": "Please complete your OpenSign public profile setup. Once done, you’ll be able to make templates public. This process only needs to be completed once.",
|
||||||
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
||||||
"share-with": "Share with",
|
"share-with": "Share with",
|
||||||
"team-not-found": "Team not found",
|
"team-not-found": "Team not found",
|
||||||
@@ -290,7 +295,7 @@
|
|||||||
"subject": "Subject",
|
"subject": "Subject",
|
||||||
"body": "Body",
|
"body": "Body",
|
||||||
"add-contact": "Add Contact",
|
"add-contact": "Add Contact",
|
||||||
"add-signer-alert": "Contact already exist!",
|
"add-signer-alert": "Contact already exist! Please select it from ‘Signers’ dropdown",
|
||||||
"record-delete-alert": "Record deleted successfully!",
|
"record-delete-alert": "Record deleted successfully!",
|
||||||
"record-revoke-alert": "Record revoked successfully!",
|
"record-revoke-alert": "Record revoked successfully!",
|
||||||
"mail-sent-alert": "Mail sent successfully.",
|
"mail-sent-alert": "Mail sent successfully.",
|
||||||
@@ -444,7 +449,8 @@
|
|||||||
"cutomize-email": "Cutomize Email",
|
"cutomize-email": "Cutomize Email",
|
||||||
"upgrade-to-customize-email": "Upgrade to customize Email",
|
"upgrade-to-customize-email": "Upgrade to customize Email",
|
||||||
"sign-url": "Sign url",
|
"sign-url": "Sign url",
|
||||||
"Mails Sent": "Mails Sent",
|
"mails-sent": "Mails Sent",
|
||||||
|
"mail-not-delivered": "Mail not delivered",
|
||||||
"document-alert": "Document Alert",
|
"document-alert": "Document Alert",
|
||||||
"owner-subscription-expired": "Owner's subscription has expired.",
|
"owner-subscription-expired": "Owner's subscription has expired.",
|
||||||
"subscription-expired": "Subscription Expired",
|
"subscription-expired": "Subscription Expired",
|
||||||
@@ -509,7 +515,7 @@
|
|||||||
"error": "Error",
|
"error": "Error",
|
||||||
"invalid-document": "Error: invalid document!",
|
"invalid-document": "Error: invalid document!",
|
||||||
"document-not-found": "Document not Found!",
|
"document-not-found": "Document not Found!",
|
||||||
"document-signed-alert-1": "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers.",
|
"document-signed-alert-1": "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document & completion certificate will be sent to the owner & all signers over email once it is signed by all signers.",
|
||||||
"encrypted-pdf-not-support": "Currently encrypted pdf files are not supported.",
|
"encrypted-pdf-not-support": "Currently encrypted pdf files are not supported.",
|
||||||
"document-signed-alert-4": " Congratulations! 🎉 This document has been successfully signed by all participants!",
|
"document-signed-alert-4": " Congratulations! 🎉 This document has been successfully signed by all participants!",
|
||||||
"document-signed-alert-5": "This document has been signed by all Signers.",
|
"document-signed-alert-5": "This document has been signed by all Signers.",
|
||||||
@@ -618,44 +624,45 @@
|
|||||||
"select-date-format": "Select a date format",
|
"select-date-format": "Select a date format",
|
||||||
"quantity-of-credits": "Quantity of premium credits",
|
"quantity-of-credits": "Quantity of premium credits",
|
||||||
"remaining-credits": "Premium credits available:",
|
"remaining-credits": "Premium credits available:",
|
||||||
"remaining-credits-help":"Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
"remaining-credits-help": "Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
||||||
"additional-credits": "Please purchase premium credits",
|
"additional-credits": "Please purchase premium credits",
|
||||||
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
|
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
|
||||||
"buy-credits": "Buy Premium Credits",
|
"buy-credits": "Buy Premium Credits",
|
||||||
"rotate-right":"Rotate right",
|
"rotate-right": "Rotate right",
|
||||||
"rotate-left":"Rotate left",
|
"rotate-left": "Rotate left",
|
||||||
"rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?",
|
"rotate-alert-mssg": "All widgets on this page will be lost. Are you sure you want to proceed?",
|
||||||
"templateid":"Template-Id",
|
"templateid": "Template-Id",
|
||||||
"bulk-send-subcription-alert":"Please upgrade to Professional or Team plan to use bulk send.",
|
"bulk-send-subcription-alert": "Please upgrade to Professional or Team plan to use bulk send.",
|
||||||
"generate-test-token":"Generate Test Token",
|
"generate-test-token": "Generate Test Token",
|
||||||
"regenerate-test-token":"Regenerate Test Token",
|
"regenerate-test-token": "Regenerate Test Token",
|
||||||
"help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
|
"help-test-token": "This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
|
||||||
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
|
"help-api-token": "This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
|
||||||
"reason":"Reason",
|
"reason": "Reason",
|
||||||
"decline-by":"Declined/revoked by",
|
"decline-by": "Declined/revoked by",
|
||||||
"document-declined": "Document declined",
|
"document-declined": "Document declined",
|
||||||
"public-template-mssg-1":"To integrate OpenSign into your React or Next.js project, simply run the following command:",
|
"public-template-mssg-1": "To integrate OpenSign into your React or Next.js project, simply run the following command:",
|
||||||
"public-template-mssg-2" :"Ensure you have npm or yarn set up in your project. If you’re using Yarn, you can replace npm install with yarn add @opensign/react.",
|
"public-template-mssg-2": "Ensure you have npm or yarn set up in your project. If you’re using Yarn, you can replace npm install with yarn add @opensign/react.",
|
||||||
"public-template-mssg-3" :"Need more details or examples?",
|
"public-template-mssg-3": "Need more details or examples?",
|
||||||
"public-template-mssg-4": "Visit the",
|
"public-template-mssg-4": "Visit the",
|
||||||
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||||
"public-template-mssg-6" :"You need to set this template as public before you can utilize this code snippet.",
|
"public-template-mssg-6": "Before you can use this code snippet, you must make this template public.",
|
||||||
"copy-code":"COPY",
|
"copy-code": "COPY",
|
||||||
"copied-code":"COPIED",
|
"copied-code": "COPIED",
|
||||||
"Installation":"Installation",
|
"Installation": "Installation",
|
||||||
"Usage" :"Usage",
|
"Usage": "Usage",
|
||||||
"insufficient-credits":"Insufficient Signing Credits",
|
"insufficient-credits": "Insufficient Signing Credits",
|
||||||
"insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details.",
|
"insufficient-credits-mssg": "The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details.",
|
||||||
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
||||||
"quota-mail-info-head":"Monthly request signatures email limit",
|
"quota-mail-info-head": "Monthly request signatures email limit",
|
||||||
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
||||||
|
"quota-mail-reset": "Your signature request email credits will be reset on",
|
||||||
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
||||||
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
"quota-mail-tip": "Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
||||||
"quota-mail-head":"Quota Reached",
|
"quota-mail-head": "Quota Reached",
|
||||||
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
|
"unauthorized-modal": "You don't have permission to perform this action, please contact {{adminEmail}}.",
|
||||||
"sent-this-month":"Sent this month",
|
"sent-this-month": "Sent this month",
|
||||||
"available-seats":"Available seats",
|
"available-seats": "Available seats",
|
||||||
"buy-users":"Buy more users",
|
"buy-users": "Buy more users",
|
||||||
"isenable-otp": "Enable OTP verification",
|
"isenable-otp": "Enable OTP verification",
|
||||||
"isenable-otp-help": {
|
"isenable-otp-help": {
|
||||||
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
|
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
|
||||||
@@ -663,10 +670,48 @@
|
|||||||
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
|
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
|
||||||
"p4": "Please choose the option that best suits your document signing requirements."
|
"p4": "Please choose the option that best suits your document signing requirements."
|
||||||
},
|
},
|
||||||
"advanced-options":"Advanced options",
|
"advanced-options": "Advanced options",
|
||||||
"hide-advanced-options":"Hide Advanced options",
|
"hide-advanced-options": "Hide Advanced options",
|
||||||
"download-files":"Download files",
|
"download-files": "Download files",
|
||||||
"download-pdf":"Download Pdf",
|
"download-pdf": "Download Pdf",
|
||||||
"pdf-certificate":"Download Pdf + Certificate",
|
"pdf-certificate": "Download Pdf + Certificate",
|
||||||
"document-logs":"Document logs"
|
"document-logs": "Document logs",
|
||||||
|
"server-down": "Unable to connect to the OpenSign server. If you are self-hosting OpenSign, please ensure that all the steps in the documentation have been followed correctly. If you're running OpenSign locally, you might be accessing it through an incorrect port number.",
|
||||||
|
"admin-exists": "Admin already exists. Please login to the application using admin credentials in order to manage users.",
|
||||||
|
"enable-tour": "Enable Tour",
|
||||||
|
"istourenabled-help": {
|
||||||
|
"p1": "This will enable a guided tour for signers, providing instructions during the signing process.",
|
||||||
|
"p2": "This will disable the guided tour, ensuring a faster, uninterrupted signing experience.",
|
||||||
|
"p3": "Tip: If your signers are familiar with OpenSign and frequently use it, you may want to disable the guided tour for a more seamless experience. Choose the option that best fits your document signing needs."
|
||||||
|
},
|
||||||
|
"form-title-1": "Document Flow Setting",
|
||||||
|
"form-title-2": "Security Settings",
|
||||||
|
"public-tour-message": "The template needs to be public before you can generate a shareable link.",
|
||||||
|
"add-user-template": "You need to add a role before you can add fields for it.",
|
||||||
|
"pdf-uncompatible": "This pdf is not compatible with opensign, please contact <support@opensignlabs.com>",
|
||||||
|
"text-field-tour": "Fields of type 'Text' must be filled in advance before the document is sent. If you need the signers to provide input, use the 'Text Input' field instead.",
|
||||||
|
"attach-signer-tour": "You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour.",
|
||||||
|
"allowed-signature-types": "Allowed signature types",
|
||||||
|
"at-least-one-signature-type": "At least one signature type should be enabled.",
|
||||||
|
"expect-default-one-signature-type": "Please enable one additional signature type apart from the default.",
|
||||||
|
"add-signer-note": "Note - This contact will be added to your contact list",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "This signature preference controls which signing options are available to your signers. Only the signature types you select will appear in the signature widget when a document is signed. For example, if you choose only the 'Draw' option in preferences, your signer will see only the 'Draw' option in the signature widget, while the other three options will not be available.",
|
||||||
|
"l1": "Create a handwritten signature directly on the screen using your finger or a stylus.",
|
||||||
|
"l2": "Enter your name and choose from various font styles to create a signature.",
|
||||||
|
"l3": "Upload an existing digital version of your signature.",
|
||||||
|
"l4": "Use a pre-set signature style saved under 'My Signature' in your settings."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notify on signatures",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "The document creator will receive an email notification whenever a signer signs the document.",
|
||||||
|
"note": "Note: Notification email will not be sent for the last signer, as the document creator will receive a completion email instead."
|
||||||
|
},
|
||||||
|
"expiry-date": "Expiry date",
|
||||||
|
"expiry-date-updated": "The expiry date has been successfully extended to {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Please provide a new expiry date that is later than the current one",
|
||||||
|
"delete-page": "Delete page",
|
||||||
|
"delete-alert": "Can not delete single page",
|
||||||
|
"delete-alert-2": "Are you sure want to delete this page ?",
|
||||||
|
"delete-note": "Note - once delete this page you can not undo"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,717 @@
|
|||||||
|
{
|
||||||
|
"header-news": "Nueva característica: los usuarios del plan Teams ahora pueden integrar sus propios depósitos de AWS S3 para el almacenamiento de archivos",
|
||||||
|
"header-news-btn": "Configurar ahora",
|
||||||
|
"create-account": "Crear cuenta",
|
||||||
|
"login": "Iniciar sesión",
|
||||||
|
"language": "Idioma",
|
||||||
|
"name": "Nombre",
|
||||||
|
"phone": "Teléfono",
|
||||||
|
"phone-optional": "opcional",
|
||||||
|
"email": "Correo",
|
||||||
|
"company": "Compañía",
|
||||||
|
"job-title": "Título del puesto",
|
||||||
|
"profile": "Perfil",
|
||||||
|
"log-out": "Cerrar sesión",
|
||||||
|
"is-email-verified": "El correo está verificado",
|
||||||
|
"public-profile": "Perfil público",
|
||||||
|
"tagline": "Eslogan ",
|
||||||
|
"has-requested-you-to-sign": "ha solicitado que firmes",
|
||||||
|
"has-requested-you-to-review-and-sign": " ha solicitado que revises y firmes",
|
||||||
|
"input-required": "Por favor, rellena este campo.",
|
||||||
|
"sort-order": {
|
||||||
|
"Ascending": "Ascendente",
|
||||||
|
"Descending": "Descendente",
|
||||||
|
"Name": "Nombre",
|
||||||
|
"Date": "Fecha"
|
||||||
|
},
|
||||||
|
"context-menu": {
|
||||||
|
"Download": "Descargar",
|
||||||
|
"Rename": "Renombrar",
|
||||||
|
"Move": "Mover",
|
||||||
|
"Delete": "Eliminar"
|
||||||
|
},
|
||||||
|
"action": "Acción",
|
||||||
|
"add": "Agregar",
|
||||||
|
"add-new-folder": "Agregar nueva carpeta",
|
||||||
|
"disable-documentId": "Desactivar ID de documento",
|
||||||
|
"edit": "Editar",
|
||||||
|
"change-password": "Cambiar contraseña",
|
||||||
|
"save": "Guardar",
|
||||||
|
"cancel": "Cancelar",
|
||||||
|
"upgrade-now": "Mejorar ahora",
|
||||||
|
"upgrade-to": "Mejorar a",
|
||||||
|
"plan": "Plan",
|
||||||
|
"subscribe-card-teamplan": "¡Libera todo el poder de la colaboración! Crea organizaciones, equipos y jerarquías ilimitadas. Comparte plantillas sin problemas entre equipos y asigna funciones de usuario personalizadas. ¡Mejora tu flujo de trabajo hoy mismo!",
|
||||||
|
"subscribe-card-plan": "Desbloquea funciones premium desde solo {{premiumPrice}}/mes. Disfruta de un rendimiento mejorado y solo {{addonPrice}} por crédito adicional después de tus créditos premium incluidos.",
|
||||||
|
"user-name-limit-char": "Para tener un nombre de usuario menor a 8 caracteres por favor suscríbete",
|
||||||
|
"tour-content": "No mostrar esto otra vez",
|
||||||
|
"pro": "PRO",
|
||||||
|
"team": "EQUIPO",
|
||||||
|
"user": "Usuario",
|
||||||
|
"docs": "Documentación",
|
||||||
|
"session-expired": "Tu sesión ha expirado.",
|
||||||
|
"public-profile-help": "Esta es tu URL pública. Cópiala o compártela con el firmante, y podrás ver todas tus plantillas públicas.",
|
||||||
|
"tagline-help": "Este eslogan aparecerá en tu perfil público de OpenSign, por ejem. https://opensign.me/alex",
|
||||||
|
"welcome": "¡Bienvenido de nuevo!",
|
||||||
|
"Login-to-your-account": "Ingresa a tu cuenta",
|
||||||
|
"password": "Contraseña",
|
||||||
|
"forgot-password": "¿Olvidaste la contraseña?",
|
||||||
|
"loading": "Cargando...",
|
||||||
|
"of": "de",
|
||||||
|
"sign-SSO": "Ingresar con SSO",
|
||||||
|
"login-page": "Página de inicio de sesión",
|
||||||
|
"or": "O",
|
||||||
|
"signup-page": "Página de registro",
|
||||||
|
"password-length": "La contraseña debe tener 8 caracteres",
|
||||||
|
"password-case": "La contraseña debe incluir mayúsculas, minúsculas y números",
|
||||||
|
"password-special-char": " La contraseña debe incluir caracteres especiales",
|
||||||
|
"agreee": "Estoy de acuerdo con los",
|
||||||
|
"term": "Términos de Servicio",
|
||||||
|
"subscribe-to-opensign": "Suscribirse al boletín de OpenSign",
|
||||||
|
"register": "Registrarse",
|
||||||
|
"sidebar": {
|
||||||
|
"Dashboard": "Panel",
|
||||||
|
"Sign yourself": "Firma tu mismo",
|
||||||
|
"Request signatures": "Solicitar firmas",
|
||||||
|
"Templates": "Plantillas",
|
||||||
|
"Templates-Children": {
|
||||||
|
"Create template": "Crear plantilla",
|
||||||
|
"Manage templates": "Administrar plantillas"
|
||||||
|
},
|
||||||
|
"OpenSign™ Drive": "OpenSign™ Drive",
|
||||||
|
"Reports": "Reportes",
|
||||||
|
"Reports-Children": {
|
||||||
|
"Need your sign": "Necesitan tu firma",
|
||||||
|
"In Progress": "En progreso",
|
||||||
|
"Completed": "Completado",
|
||||||
|
"Drafts": "Borradores",
|
||||||
|
"Declined": "Rechazados",
|
||||||
|
"Expired": "Expirados",
|
||||||
|
"Contactbook": "Agenda de contactos"
|
||||||
|
},
|
||||||
|
"Settings": "Ajustes",
|
||||||
|
"Settings-Children": {
|
||||||
|
"My Signature": "Mi firma",
|
||||||
|
"API Token": "Token API",
|
||||||
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Preferencias",
|
||||||
|
"Teams": "Equipos",
|
||||||
|
"Team-update-successfully": "Equipo actualizado correctamente.",
|
||||||
|
"Users": "Usuarios"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dashboard-card": {
|
||||||
|
"Need your Signature": "Necesitan tu firma",
|
||||||
|
"Out for signatures": "En espera de ser firmados"
|
||||||
|
},
|
||||||
|
"report-name": {
|
||||||
|
"Draft Documents": "Documentos borradores",
|
||||||
|
"Need your sign": "Necesitan tu firma",
|
||||||
|
"In-progress documents": "Documentos en progreso",
|
||||||
|
"Completed Documents": "Documentos completados",
|
||||||
|
"Declined Documents": "Documentos rechazados",
|
||||||
|
"Expired Documents": "Documentos expirados",
|
||||||
|
"Recently sent for signatures": "Recientemente enviados para ser firmados",
|
||||||
|
"Recent signature requests": "Solicitudes de firma recientes",
|
||||||
|
"Drafts": "Borradores",
|
||||||
|
"Contactbook": "Agenda de contactos",
|
||||||
|
"Templates": "Plantillas",
|
||||||
|
"Teams": "Equipos",
|
||||||
|
"Users": "Usuarios"
|
||||||
|
},
|
||||||
|
"btnLabel": {
|
||||||
|
"sign": "firmar",
|
||||||
|
"Sign": "FIRMAR",
|
||||||
|
"Resend": "Reenviar",
|
||||||
|
"Revoke": "Revocar",
|
||||||
|
"Delete": "Eliminar",
|
||||||
|
"Use": "Usar",
|
||||||
|
"Quick send": "Envío rápido",
|
||||||
|
"Edit": "Editar",
|
||||||
|
"Share with team": "Compartir con el equipo",
|
||||||
|
"Share": "Compartir",
|
||||||
|
"View": "Ver",
|
||||||
|
"option": "Opción",
|
||||||
|
"Embed": "Incrustar",
|
||||||
|
"Copy TemplateId": "Copiar ID de plantilla",
|
||||||
|
"Copy Public URL": "Copiar URL pública",
|
||||||
|
"Expiry-date": "Date d'expiration"
|
||||||
|
},
|
||||||
|
"report-heading": {
|
||||||
|
"Sr.No": "Nº",
|
||||||
|
"Title": "Título",
|
||||||
|
"Email": "Correo",
|
||||||
|
"Phone": "Teléfono",
|
||||||
|
"File": "Archivo",
|
||||||
|
"Owner": "Propietario",
|
||||||
|
"Signers": "Firmantes",
|
||||||
|
"Note": "Nota",
|
||||||
|
"Folder": "Carpeta",
|
||||||
|
"Reason": "Razón",
|
||||||
|
"Parent Team": "Equipo padre",
|
||||||
|
"Active": "Activo",
|
||||||
|
"Role": "Rol",
|
||||||
|
"Team": "Equipo",
|
||||||
|
"Name": "Nombre",
|
||||||
|
"Status": "Estado",
|
||||||
|
"created-date": "Fecha de creación",
|
||||||
|
"Type": "Tipo",
|
||||||
|
"Logs": "Registros",
|
||||||
|
"Expiry-date": "Date d'expiration"
|
||||||
|
},
|
||||||
|
"report-help": {
|
||||||
|
"Draft Documents": "Estos son documentos que has iniciado pero no has finalizado para su envío.",
|
||||||
|
"Need your sign": "Esta es una lista de documentos que esperan tu firma.",
|
||||||
|
"In-progress documents": "Esta es una lista de documentos que has enviado a otras partes para su firma.",
|
||||||
|
"Completed Documents": "Esta es una lista de documentos en los que todas las partes han firmado.",
|
||||||
|
"Declined Documents": "Esta es una lista de documentos que han sido rechazados por uno de los firmantes.",
|
||||||
|
"Expired Documents": "Esta es una lista de documentos que han alcanzado su fecha de caducidad.",
|
||||||
|
"Contactbook": "Esta es una lista de contactos/firmantes añadidos por ti. Aparecerán como sugerencias cuando intentes añadir firmantes a un nuevo documento.",
|
||||||
|
"Templates": "Esta es una lista de plantillas que están a tu disposición para crear documentos. Puedes hacer clic en el botón «usar» para crear un nuevo documento utilizando una plantilla, modifica el documento y añade firmantes en el siguiente paso."
|
||||||
|
},
|
||||||
|
"form-name": {
|
||||||
|
"Sign Yourself": "Firmar",
|
||||||
|
"Request Signatures": "Solicitar firmas",
|
||||||
|
"New Template": "Nueva plantilla"
|
||||||
|
},
|
||||||
|
"file-type": "pdf, png, jpg, jpeg",
|
||||||
|
"docx": "docx",
|
||||||
|
"file-selected": "archivo seleccionado",
|
||||||
|
"template-title": "Título de la plantilla",
|
||||||
|
"document-title": "Título del documento",
|
||||||
|
"description": "Descripción",
|
||||||
|
"time-to-complete": "Plazo de finalización (días)",
|
||||||
|
"send-in-order": "Enviar en orden",
|
||||||
|
"send-in-order-help": {
|
||||||
|
"p1": "Elige cómo quieres que se envíen las solicitudes de firma a los firmantes del documento:",
|
||||||
|
"p2": "Seleccionando esta opción se enviará inicialmente la solicitud de firma al primer firmante. Una vez que el primer firmante complete su parte, el siguiente firmante en la secuencia recibirá la solicitud. Este proceso continúa hasta que todos los firmantes hayan firmado el documento. Este método garantiza que el documento se firme en un orden específico.",
|
||||||
|
"p3": "Seleccionando esta opción se enviarán los enlaces para la firma a todos los firmantes simultáneamente. Cada firmante puede firmar el documento cuando le convenga, independientemente de si otros firmantes han completado sus firmas. Este método es más rápido, pero no impone ningún orden de firma entre los participantes.",
|
||||||
|
"p4": "Selecciona la opción que mejor se adapte a las necesidades de tu tramitación de documentos."
|
||||||
|
},
|
||||||
|
"no": "No",
|
||||||
|
"auto-reminder": "Recordatorio automático",
|
||||||
|
"remind-once": " Recordar una vez cada (Días)",
|
||||||
|
"next": "Siguiente",
|
||||||
|
"select-folder": "Seleccionar carpeta",
|
||||||
|
"OpenSign-drive": "OpenSign™ Drive",
|
||||||
|
"drive-document-status": {
|
||||||
|
"Completed": "Completado",
|
||||||
|
"Declined": "Rechazado",
|
||||||
|
"Draft": "Borrador",
|
||||||
|
"Expired": "Expirado",
|
||||||
|
"In Progress": "En progreso"
|
||||||
|
},
|
||||||
|
"select-folder-help": "Si no seleccionas una carpeta, tu documento firmado se guardará en la carpeta principal de OpenSign Drive.",
|
||||||
|
"no-data": "No se encontraron datos",
|
||||||
|
"save-here": "Guardar aquí",
|
||||||
|
"back": "Atrás",
|
||||||
|
"add-folder": "Añadir carpeta",
|
||||||
|
"create-folder": "Crear carpeta",
|
||||||
|
"parent-folder": "Carpeta superior",
|
||||||
|
"create": "Crear",
|
||||||
|
"signers": "Firmantes",
|
||||||
|
"signers-help": "Empieza a escribir el nombre de un contacto para ver los firmantes sugeridos entre tus contactos guardados o añade otros nuevos. Organiza el orden de firma añadiendo firmantes en la secuencia deseada. Utiliza el botón «+» para añadir nuevos firmantes y la «X» para quitar todos. Cada firmante recibirá una solicitud por correo electrónico para que firme el documento según el orden indicado.",
|
||||||
|
"add-signer": "Añadir firmante",
|
||||||
|
"contact-not-found": "Contacto no encontrado",
|
||||||
|
"add-yourself": "Añadirte a ti mismo",
|
||||||
|
"submit": "Enviar",
|
||||||
|
"reset": "Volver a empezar",
|
||||||
|
"my-signature": "Mi firma",
|
||||||
|
"signature": "Firma",
|
||||||
|
"upload-image": " Subir imagen",
|
||||||
|
"clear": "Limpiar",
|
||||||
|
"upload-signature/Image": "Por favor, sube la firma/imagen",
|
||||||
|
"initials": "Iniciales",
|
||||||
|
"API": "API",
|
||||||
|
"api-token": "Token API",
|
||||||
|
"regenerate-token": "Regenerar token activo",
|
||||||
|
"generate-token": "Generar token activo",
|
||||||
|
"view-docs": "Ver documentación",
|
||||||
|
"generate-token-alert": "¿En definitiva quieres regenerar el token? Esto expirará el token antiguo.",
|
||||||
|
"yes": "Sí",
|
||||||
|
"copied": "Copiado",
|
||||||
|
"something-went-wrong-mssg": "Algo salió mal, por favor, intenta de nuevo más tarde.",
|
||||||
|
"token-generated": "Token generado exitosamente.",
|
||||||
|
"webhook": "Webhook",
|
||||||
|
"update-webhook": "Actualizar webhook",
|
||||||
|
"add-webhook": "Agregar webhook",
|
||||||
|
"webhook-added": "Webhook agregado exitosamente.",
|
||||||
|
"team-disabled": "Equipo deshabilitado",
|
||||||
|
"Team enabled": "Equipo habilitado",
|
||||||
|
"are-you-sure": "¿En definitiva quieres ",
|
||||||
|
"disable": "deshabilitar",
|
||||||
|
"enable": "habilitar",
|
||||||
|
"this-team": " este equipo?",
|
||||||
|
"edit-team": "Editar equipo",
|
||||||
|
"name-of-team": "Nombre del equipo",
|
||||||
|
"prev": "Anterior",
|
||||||
|
"no-data-avaliable": "No hay datos disponibles",
|
||||||
|
"add-team": "Agregar equipo",
|
||||||
|
"page-not-found": "Página no encontrada",
|
||||||
|
"users-from-teams": "usuarios de equipos",
|
||||||
|
"user-status": "Estado del usuario",
|
||||||
|
"activate": "activar",
|
||||||
|
"deactivate": "desactivar",
|
||||||
|
"this-user": " este usuario",
|
||||||
|
"delete-user": "Eliminar usuario",
|
||||||
|
"delete": "eliminar",
|
||||||
|
"add-user": "Agregar usuario",
|
||||||
|
"password-generateed": "La contraseña solo será generada una vez; asegúrate de copiarla.",
|
||||||
|
"Team status": "Estado del equipo",
|
||||||
|
"user-deactivated": "Usuario desactivado.",
|
||||||
|
"user-activated": "Usuario activado.",
|
||||||
|
"public": "Público",
|
||||||
|
"download": "Descargar",
|
||||||
|
"view": "Ver",
|
||||||
|
"make-template-public": "Convertir la plantilla en pública",
|
||||||
|
"make-template-private": "Convertir la plantilla en privada",
|
||||||
|
"make-template-public-alert": "¿En definitiva quieres convertir esta plantilla en pública?",
|
||||||
|
"make-template-private-alert": "¿En definitiva quieres convertir esta plantilla en privada? Esto lo removerá de tu perfil público.",
|
||||||
|
"public-role": "Rol público",
|
||||||
|
"public-url": "Perfil publico",
|
||||||
|
"embed-template": "Insertar plantilla",
|
||||||
|
"public-url-copy": "Aquí está tu URL pública: ",
|
||||||
|
"public-url-copy-mssg": "Cópiala o compártela con el firmante y podrás ver todas tus plantillas públicas.",
|
||||||
|
"add-public-url-alert": "Por favor, completa la configuración de tu perfil público OpenSign. Una vez terminado, podrás crear plantillas públicas. Este proceso solo necesita ser completado una vez.",
|
||||||
|
"share-with-alert": "No puedes compartir una plantilla si alguno de los roles ya tiene contactos asignados. Elimina todas las asignaciones de contactos de los roles antes de compartir la plantilla.",
|
||||||
|
"share-with": "Compartir con",
|
||||||
|
"team-not-found": "Equipo no encontrado",
|
||||||
|
"roles": "Roles",
|
||||||
|
"delete-document": "Eliminar documento",
|
||||||
|
"delete-document-alert": "¿En definitiva quieres eliminar este documento?",
|
||||||
|
"quick-send": "Envío rápido",
|
||||||
|
"add-new": "Agregar nuevo",
|
||||||
|
"send": "Enviar",
|
||||||
|
"quick-send-alert-1": "Todos los roles de este documento están actualmente vinculados a contactos. Para enviar rápidamente copias de esta plantilla a varios firmantes, por favor, asegúrate de que al menos un rol no esté vinculado a ningún contacto.",
|
||||||
|
"quick-send-alert-2": "Por favor, asegúrate de que hay al menos un widget de firma añadido para cada destinatario.",
|
||||||
|
"quick-send-alert-3": "Por favor, añade al menos un rol a esta plantilla para poder hacer un «envío rápido» de copias a varios firmantes.",
|
||||||
|
"quick-send-alert-4": "El envío rápido ha alcanzado el límite.",
|
||||||
|
"copy-link": "Copiar enlace",
|
||||||
|
"copy": "Copiar",
|
||||||
|
"revoke-document": "Revocar documento",
|
||||||
|
"revoke-document-alert": "¿En definitiva quieres revocar este documento?",
|
||||||
|
"resend-mail": "Reenviar correo",
|
||||||
|
"resend-mail-help": "Puedes usar las siguientes variables que serán reemplazadas por sus valores reales:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
|
||||||
|
"subject": "Asunto",
|
||||||
|
"body": "Cuerpo",
|
||||||
|
"add-contact": "Agregar contacto",
|
||||||
|
"add-signer-alert": "¡El contacto ya existe! Selecciónelo en el menú desplegable 'Firmantes'",
|
||||||
|
"record-delete-alert": "¡Entrada eliminada exitosamente!",
|
||||||
|
"record-revoke-alert": "¡Entrada revocada exitosamente!",
|
||||||
|
"mail-sent-alert": "Correo enviado exitosamente.",
|
||||||
|
"document-sent-alert": "¡Documento enviado exitosamente!",
|
||||||
|
"template-share-alert": "Plantilla compartida exitosamente.",
|
||||||
|
"template-public-alert-1": "Has convertido exitosamente la plantilla en pública.",
|
||||||
|
"template-public-alert-2": "Has convertido exitosamente la plantilla en privada.",
|
||||||
|
"template-public-alert-3": "Tienes que seleccionar un rol para los firmantes públicos.",
|
||||||
|
"template-public-alert-4": "Por favor, asegúrate de que has añadido al menos un widget de firma para cada firmante.",
|
||||||
|
"template-public-alert-5": "Dado que esta plantilla tiene «enviar en orden» habilitado, el rol público debe estar posicionado arriba al inicio.",
|
||||||
|
"template-public-alert-6": "Por favor, enlaza firmantes a todos los roles excepto al usuario de rol público.",
|
||||||
|
"template-public-alert-7": "Por favor, asigna al menos un rol público para convertir está plantilla en pública.",
|
||||||
|
"loader": " Esto podría llevar algún tiempo",
|
||||||
|
"pages": "Páginas",
|
||||||
|
"document-signed": "Documento firmado",
|
||||||
|
"close": "Cerrar",
|
||||||
|
"validation-alert": "Alerta de validación",
|
||||||
|
"validate-alert-mssg": " Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
|
||||||
|
"otp-verification": "Verificación OTP",
|
||||||
|
"enter-otp": "Ingresar OTP",
|
||||||
|
"verify": "Verificar",
|
||||||
|
"verify-email-1": "Verificar correo",
|
||||||
|
"resend": "Reenviar",
|
||||||
|
"contact-details": "Detalles del contacto",
|
||||||
|
"verify-email": "¡Por favor, verifica tu correo!",
|
||||||
|
"send-otp": " Enviar OTP",
|
||||||
|
"otp-placeholder": "Ingresa el código de verificación enviado por correo",
|
||||||
|
"loading-doc": "Cargando documento...",
|
||||||
|
"widgets-name": {
|
||||||
|
"signature": "firma",
|
||||||
|
"stamp": "sello",
|
||||||
|
"initials": "iniciales",
|
||||||
|
"name": "nombre",
|
||||||
|
"job title": "título del puesto",
|
||||||
|
"company": "compañía",
|
||||||
|
"date": "fecha",
|
||||||
|
"text": "texto",
|
||||||
|
"text input": "entrada de texto",
|
||||||
|
"checkbox": "casilla",
|
||||||
|
"dropdown": "desplegable",
|
||||||
|
"radio button": "botón de radio",
|
||||||
|
"image": "imagen",
|
||||||
|
"email": "correo"
|
||||||
|
},
|
||||||
|
"fields": "Campos",
|
||||||
|
"recipients": "Destinatarios",
|
||||||
|
"please-add": "Por favor, agrega un",
|
||||||
|
"signed-by": "Firmado por",
|
||||||
|
"more": "más",
|
||||||
|
"sent": "enviado",
|
||||||
|
"print": "Imprimir",
|
||||||
|
"certificate": "Certificado",
|
||||||
|
"decline": "Rechazar",
|
||||||
|
"finish": "Finalizar",
|
||||||
|
"mail": "Correo",
|
||||||
|
"sign-now": "Firmar ahora",
|
||||||
|
"successfully-signed": "¡Firmado exitosamente!",
|
||||||
|
"email-mssg": " Los destinatarios agregados aquí recibirán una copia del documento firmado.",
|
||||||
|
"email-error-1": " por favor, proporciona una dirección de correo correcta",
|
||||||
|
"email-error-2": "Solo puedes enviar hasta a 10 destinatarios a la vez.",
|
||||||
|
"Email-verified-alert-1": "El correo está verificado.",
|
||||||
|
"Email-verified-alert-2": "El correo ya ha sido verificado.",
|
||||||
|
"upload-stamp-image": "Subir imagen del sello",
|
||||||
|
"draw": "Dibujar",
|
||||||
|
"type": "Escribir",
|
||||||
|
"color-type": {
|
||||||
|
"red": "rojo",
|
||||||
|
"blue": "azul",
|
||||||
|
"black": "negro",
|
||||||
|
"yellow": "amarillo"
|
||||||
|
},
|
||||||
|
"my-initials": "Mis iniciales",
|
||||||
|
"upload": "Subir",
|
||||||
|
"initial-teb": "Iniciales",
|
||||||
|
"signature-tab": "Firma",
|
||||||
|
"your-signature": "Tu firma",
|
||||||
|
"copy-title": "Copiar widget a",
|
||||||
|
"contact-delete-alert": "¿En definitiva quieres eliminar este contacto?",
|
||||||
|
"reset-password-alert-1": "El enlace para restablecer la contraseña ha sido enviado a tu correo electrónico",
|
||||||
|
"reset-password-alert-2": "Por favor, configura un adaptador de correo ",
|
||||||
|
"reset-password-alert-3": "Restablece tu contraseña",
|
||||||
|
"faild-animation": "Error al cargar la animación",
|
||||||
|
"apply": "Aplicar",
|
||||||
|
"copy-type": {
|
||||||
|
"All pages": "Todas las páginas",
|
||||||
|
"All pages but last": "Todas las páginas menos la última",
|
||||||
|
"All pages but first": "Todas las páginas menos la primera",
|
||||||
|
"Next to current widget": "Junto al widget actual"
|
||||||
|
},
|
||||||
|
"options": "Opciones",
|
||||||
|
"minimun-check": "Chequeo mínimo",
|
||||||
|
"maximum-check": "Chequeo máximo",
|
||||||
|
"default-value": "Valor por defecto",
|
||||||
|
"select": "Seleccionar",
|
||||||
|
"read-only": "Es de solo lectura",
|
||||||
|
"hide-labels": "Esconder etiquetas",
|
||||||
|
"checkbox": "Casilla",
|
||||||
|
"alert": "Alerta",
|
||||||
|
"zoom-in": "Acercar",
|
||||||
|
"zoom-out": "Alejar",
|
||||||
|
"document-signed-alert": "¡Felicitaciones! 🎉 ¡Este documento ha sido firmado por ti exitosamente!",
|
||||||
|
"otp-sent-alert": "OTP enviado a tu correo",
|
||||||
|
"fields-required": "Campos requeridos",
|
||||||
|
"signature-widget-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma agregado",
|
||||||
|
"signature-widget-alert-2": "Por favor, asegúrate de que todos los campos están correctamente rellenados y de que cumplen todos los requisitos.",
|
||||||
|
"encrypted-pdf-alert": "Actualmente los archivos PDF encriptados no están soportados.",
|
||||||
|
"encrypted-pdf-alert-1": "La contraseña del archivo PFX es inválida.",
|
||||||
|
"user-not-exist": "El usuario no existe",
|
||||||
|
"template-signature-field": "Por favor, agrega al menos un campo de firma para todos los roles.",
|
||||||
|
"template-role-alert": "Por favor, primero agrega roles",
|
||||||
|
"create-document": "Crear documento",
|
||||||
|
"template-created-alert": "¿Quieres crear un documento usando la plantilla que acabas de crear?",
|
||||||
|
"signers-alert": "alerta de firmantes",
|
||||||
|
"template-creation-alert-1": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
|
||||||
|
"ok": "OK",
|
||||||
|
"radio-group": "Grupo de radio",
|
||||||
|
"dropdown-options": "Opciones del desplegable",
|
||||||
|
"add-role": "Agregar rol",
|
||||||
|
"role-ex": " por ejem.: Cliente, RRHH, Director, Administrador, Estudiante, etc.",
|
||||||
|
"add/choose-signer": "Agregar/Elegir firmante",
|
||||||
|
"choose-from-contacts": "Elegir desde los contactos",
|
||||||
|
"select-signer": " Por favor, selecciona el firmante",
|
||||||
|
"edit-template": "Editar plantilla",
|
||||||
|
"widget-info": "Información del widget",
|
||||||
|
"validation": "Validación",
|
||||||
|
"invalid-default-value": "valor por defecto inválido",
|
||||||
|
"hint": "Pista",
|
||||||
|
"color": "color",
|
||||||
|
"role-help": {
|
||||||
|
"p1": "¿Qué son los roles de una plantilla?",
|
||||||
|
"p2": "Empieza por especificar cada uno de los roles necesarios para completar el documento. Piensa en las partes implicadas en el proceso de firma y cuáles son sus responsabilidades. Los roles más habituales son RRHH para los documentos internos, Cliente para los contratos o Proveedor para los convenios comerciales.",
|
||||||
|
"p3": "¿Por qué preasignar usuarios a algunos roles?",
|
||||||
|
"p4": "Para los roles que consistentemente involucran al mismo individuo (por ejem., la firma del Gerente en las ofertas de empleo), puedes preasignar un usuario a un rol dentro de una plantilla. Este paso es opcional pero recomendado para la eficiencia y consistencia entre documentos",
|
||||||
|
"p5": "¿Cuando especifico el usuario asignado a cada rol?",
|
||||||
|
"p6": "Cuando crees un documento usando tu plantilla, se te pedirá que asignes usuarios a cada rol definido. Si un rol ya tiene un usuario asignado, este será rellenado con anticipación, pero puedes modificarlo según lo necesites antes de enviar el documento."
|
||||||
|
},
|
||||||
|
"add-recipients": "Agregar destinatarios",
|
||||||
|
"loading-mssg": "Esto podría llevar algún tiempo",
|
||||||
|
"send-mail": "Enviar correo",
|
||||||
|
"placeholder-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma para cada destinatario.",
|
||||||
|
"placeholder-alert-2": "Por favor, confirma que hayas rellenado el campo de texto.",
|
||||||
|
"placeholder-alert-3": " ¿En definitiva quieres enviar este documento para ser firmado?",
|
||||||
|
"placeholder-alert-4": "¡Has enviado exitosamente correos a todos los destinatarios!",
|
||||||
|
"placeholder-alert-5": "¿Quieres firmar documentos ahora mismo?",
|
||||||
|
"placeholder-alert-6": "¡Por favor, configura el adaptador de correo para enviar correos!",
|
||||||
|
"placeholder-alert-7": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
|
||||||
|
"email-subject": "asunto del correo",
|
||||||
|
"email-body": "cuerpo del correo",
|
||||||
|
"email-placeholder": "agregar cuerpo del correo",
|
||||||
|
"reset-to-default": "Restablecer a por defecto",
|
||||||
|
"cutomize-email": "Personalizar correo",
|
||||||
|
"upgrade-to-customize-email": "Mejora para personalizar el correo",
|
||||||
|
"sign-url": "URL de firma",
|
||||||
|
"mails-sent": "Correos enviados",
|
||||||
|
"mail-not-delivered": "correo no entregado",
|
||||||
|
"document-alert": "Alerta de documento",
|
||||||
|
"owner-subscription-expired": "La suscripción del propietario ha expirado.",
|
||||||
|
"subscription-expired": "Suscripción expirada",
|
||||||
|
"alert-message": "Mensaje de alerta",
|
||||||
|
"document-decline": "Rechazar documento",
|
||||||
|
"decline-alert-1": "¿En definitiva quieres rechazar este documento?",
|
||||||
|
"decline-alert-2": "¡Has rechazado este documento!",
|
||||||
|
"decline-alert-3": "No puedes firmar este documento ya que ha sido rechazado/revocado.",
|
||||||
|
"sign here": "Firma aquí",
|
||||||
|
"guest-email-alert": "el código de verificación ha sido enviado a tu correo",
|
||||||
|
"get-otp-alert": "recibirás un código de verificación por correo",
|
||||||
|
"user-already-exist": "El usuario ya existe.",
|
||||||
|
"server-error": "¡Error interno del servidor!",
|
||||||
|
"fill-required-details!": "¡Por favor, rellena los detalles requeridos!",
|
||||||
|
"sign-up-form": "Formulario de registro",
|
||||||
|
"sign-up": "Registrarse",
|
||||||
|
"folder-already-exist!": "¡la carpeta ya existe!",
|
||||||
|
"please-select-position!": "¡por favor, selecciona una posición!",
|
||||||
|
"default-sign-alert": "¿En definitiva quieres firmar automáticamente en todos los lugares solicitados?",
|
||||||
|
"Your-Signature": "Tu firma",
|
||||||
|
"auto-sign-all": "Firmar todo automáticamente",
|
||||||
|
"generating-certificate": "Generando certificado",
|
||||||
|
"pdf-download": "Descargar PDF",
|
||||||
|
"generate-certificate-alert": " Tu certificado de finalización se está generando. Por favor, espera un momento. Si la descarga no inicia pronto, presiona el botón otra vez.",
|
||||||
|
"folder-already-exist": "¡La carpeta ya existe!",
|
||||||
|
"folder-created-successfully": "¡Carpeta creada exitosamente!",
|
||||||
|
"fill-folder-name": "Por favor, rellena el nombre de la carpeta",
|
||||||
|
"already-exists-this-username": "¡Un usuario con este nombre de usuario ya existe!",
|
||||||
|
"verification-code-sent": "¡El correo de verificación ha sido enviado a tu correo!",
|
||||||
|
"registered-user-successfully": "Usuario registrado exitosamente.",
|
||||||
|
"role-not-found": "Rol no encontrado.",
|
||||||
|
"do-not-access": "No tienes acceso, por favor, contacta al administrador.",
|
||||||
|
"add-admin": "Agregar administrador",
|
||||||
|
"opensign-setup": "Instalación de OpenSign",
|
||||||
|
"join-discord": "Únete a nuestro servidor de Discord",
|
||||||
|
"admin-already-exist": "El administrador ya existe.",
|
||||||
|
"password-update-alert-1": "Contraseña actualizada exitosamente.",
|
||||||
|
"password-update-alert-2": "Tu contraseña actual es incorrecta o falta.",
|
||||||
|
"password-update-alert-3": "Tu contraseña actual es incorrecta o falta.",
|
||||||
|
"password-update-alert-4": "Tu contraseña y su confirmación no son iguales.",
|
||||||
|
"current-password": "Contraseña actual",
|
||||||
|
"new-password": "Contraseña nueva",
|
||||||
|
"confirm-password": "Confirmar contraseña",
|
||||||
|
"file-alert-1": "El tamaño del archivo seleccionado es muy grande. Por favor, selecciona un archivo con un tamaño menor a",
|
||||||
|
"file-alert-2": "Por favor, selecciona un archivo.",
|
||||||
|
"file-alert-3": "Por favor, espera mientras se sube el documento.",
|
||||||
|
"enter-pdf-password": "Ingresa la contraseña del PDF",
|
||||||
|
"correct-password": "Por favor, proporciona la contraseña correcta",
|
||||||
|
"decrypting-pdf": " Desencriptando PDF, por favor, espera...",
|
||||||
|
"invalid-otp": "OTP inválido",
|
||||||
|
"user-not-found": "¡Usuario no encontrado!",
|
||||||
|
"enter-otp-alert": "¡Por favor, ingresa el OTP!",
|
||||||
|
"get-verification-code": "Obtener código de verificación",
|
||||||
|
"get-verification-code-2": "Obtendrás un código de verificación por correo",
|
||||||
|
"enter-verification-code": "Ingresar código de verificación",
|
||||||
|
"provide-your-details": "Proporciona tus detalles",
|
||||||
|
"provide-email": "Por favor, proporciona un correo.",
|
||||||
|
"additional-info": "Información adicional",
|
||||||
|
"signature-saved-alert": "Firma guardada exitosamente.",
|
||||||
|
"fill-field": "Por favor, rellena este campo",
|
||||||
|
"error-template": "Error: ¡Plantilla no encontrada!",
|
||||||
|
"error": "Error",
|
||||||
|
"invalid-document": "Error: ¡Documento inválido!",
|
||||||
|
"document-not-found": "¡Documento no encontrado!",
|
||||||
|
"document-signed-alert-1": "Ha firmado exitosamente el documento. Puede descargar o imprimir una copia del documento parcialmente firmado. Se enviará una copia del documento firmado digitalmente y del certificado de finalización al propietario y a todos los firmantes por correo electrónico una vez que todos los firmantes lo hayan firmado.",
|
||||||
|
"encrypted-pdf-not-support": "Los archivos PDF encriptados no están soportados actualmente.",
|
||||||
|
"document-signed-alert-4": " ¡Felicitaciones! 🎉 ¡Este documento ha sido firmado exitosamente por todos los participantes!",
|
||||||
|
"document-signed-alert-5": "Este documento ha sido firmado por todos los firmantes.",
|
||||||
|
"document-signed-alert-6": "Este documento ha sido rechazado por uno o más destinatarios.",
|
||||||
|
"document-signed-alert-7": "Este documento ya no está disponible.",
|
||||||
|
"document-signed-alert-8": "Este documento ya ha sido enviado para ser firmado.",
|
||||||
|
"yet-to-sign": "Todavía por firmar",
|
||||||
|
"validation-alert-1": "Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
|
||||||
|
"account-already-exists": "¡La cuenta ya existe!",
|
||||||
|
"choose-password": "Elegir contraseña",
|
||||||
|
"enter-password": "Ingresar contraseña",
|
||||||
|
"sure": "claro",
|
||||||
|
"subscribed-alert": "¡Ya te has suscrito al plan!",
|
||||||
|
"monthly": "Mensual",
|
||||||
|
"yearly-upto": "Anual (hasta 66% de descuento)",
|
||||||
|
"billed-yearly": "Facturado anualmente",
|
||||||
|
"billed-monthly": "Facturado mensualmente",
|
||||||
|
"plansubscription-1": "Alójalo por tu cuenta gratuitamente",
|
||||||
|
"visit-github": "Visitar GitHub",
|
||||||
|
"user-already-exist-name": "¡Un usuario con este nombre de usuario ya existe!",
|
||||||
|
"do-not-access-contact-admin": "No tienes acceso, por favor, contacta a un administrador.",
|
||||||
|
"filed-required-correctly": "Por favor, rellena correctamente los detalles requeridos.",
|
||||||
|
"admin-created": "Administrador creado",
|
||||||
|
"invalid-masterkey": "Llave maestra inválida",
|
||||||
|
"opensign-Setup": "Instalación de OpenSign",
|
||||||
|
"master-key": " Llave maestra",
|
||||||
|
"profile-update-alert": "Perfil actualizado exitosamente.",
|
||||||
|
"date": "Fecha",
|
||||||
|
"report-not-found": "Reporte no encontrado",
|
||||||
|
"please-wait": "por favor, espera",
|
||||||
|
"select-foler": "Seleccionar carpeta",
|
||||||
|
"generated-on": "Generado el",
|
||||||
|
"text-field": "Campo de texto",
|
||||||
|
"font-size": "Tamaño de la fuente",
|
||||||
|
"widget-status": {
|
||||||
|
"Required": "Requerido",
|
||||||
|
"Optional": "Opcional"
|
||||||
|
},
|
||||||
|
"all-right": "Todos los derechos reservados",
|
||||||
|
"version": "versión",
|
||||||
|
"social-media": {
|
||||||
|
"github": "GitHub",
|
||||||
|
"linked-in": "LinkedIn",
|
||||||
|
"twitter": "Twitter",
|
||||||
|
"discord": "Discord"
|
||||||
|
},
|
||||||
|
"tour-mssg": {
|
||||||
|
"home-layout-1": "¡Has iniciado sesión exitosamente! Echemos un vistazo.",
|
||||||
|
"home-layout-2": "Para subir documentos para firmar tú mismo o para solicitar la firma de otros, simplemente selecciona los botones correspondientes.",
|
||||||
|
"home-layout-3": "¡Ya puedes empezar a utilizar OpenSign! Si necesitas soporte siéntete libre de contactarnos.",
|
||||||
|
"generate-token": "Mejora ahora para generar un token API de producción.",
|
||||||
|
"opensign-drive-1": "Haz clic en los enlaces para navegar fácilmente por la estructura jerárquica de carpetas y ver los documentos de cada carpeta.",
|
||||||
|
"opensign-drive-2": "Haz clic en el botón «Agregar» para crear una nueva carpeta o documento.",
|
||||||
|
"opensign-drive-3": "Ordena tus documentos por «Fecha» o «Nombre» usando este menú.",
|
||||||
|
"opensign-drive-4": "Haz clic en este menú para mostrar los documentos en vista de lista.",
|
||||||
|
"opensign-drive-5": "La lista de documentos es mostrada de acuerdo a la opción de ordenamiento seleccionada. Los íconos situados junto a cada documento indican su estado actual.",
|
||||||
|
"opensign-drive-6": "Haz clic con el botón derecho en un documento para ver opciones como «Descargar», «Renombrar», «Mover» y «Eliminar». Haz clic en el documento para abrirlo.",
|
||||||
|
"opensign-drive-7": "Haz clic con el botón derecho en cualquier carpeta para ver las opciones. Elige «Renombrar» para cambiar el nombre de la carpeta o haz clic en ella para navegar por su contenido.",
|
||||||
|
"pdf-request-file-1": "Lista de firmantes que todavía tienen que firmar este documento.",
|
||||||
|
"pdf-request-file-2": "Haz clic en cualquiera de los marcadores de posición que aparecen en el documento para firmar. A continuación, verás opciones para dibujar tu firma, escribirla o subir una imagen .",
|
||||||
|
"pdf-request-file-3": "Haz clic en los botones «Atrás», «Rechazar» o «Finalizar» para navegar por el documento. Utiliza el menú de tres puntos para ver otras opciones, como el botón «Descargar».",
|
||||||
|
"pdf-request-file-4": "Lista de firmantes que ya han firmado el documento.",
|
||||||
|
"pdf-request-file-5": "Puedes hacer clic en «Firmar todo automáticamente» para firmar de manera automática en todos los lugares que deban ser firmados por ti. Asegúrate de revisar correctamente el documento antes de hacer clic en ese botón.",
|
||||||
|
"placeholder-sign-1": "Selecciona un destinatario de esta lista para agregar un marcador de posición dónde este destinatario tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del destinatario una vez lo sueltes en el documento.",
|
||||||
|
"placeholder-sign-2": "Hacer clic en el botón «Agregar destinatarios» te permitirá añadir más firmantes.",
|
||||||
|
"placeholder-sign-3": "Haz clic en este botón para agregar más destinatarios/firmantes al documento.",
|
||||||
|
"placeholder-sign-4": "Arrastra o haz clic en un capo para agregarlo al documento.",
|
||||||
|
"placeholder-sign-5": "El área de contenido del PDF ya muestra los marcadores de posición existentes en la plantilla. Para tu comodidad, estos marcadores de posición coincidirán con el color del nombre del destinatario, haciéndolos fácilmente identificables.",
|
||||||
|
"placeholder-sign-6": "Hacer clic en «Enviar» guardará el documento. En el siguiente paso podrás personalizar los correos que serán enviados a los destinatarios o copiar los enlaces para firmar y compartirlos con los destinatarios por tu cuenta.",
|
||||||
|
"report-1": "Haz clic en el botón «Agregar» para crear una nueva plantilla. Las plantillas son documentos reusables diseñados para generar rápidamente nuevos documentos con la misma estructura pero diferentes firmantes. Por ejemplo, una plantilla de RR.HH. para el proceso de incorporación podría tener roles predefinidos como «Director de RR.HH.» y «Nuevo empleado». Cada vez que utilices la plantilla, puedes asignar el rol de «Nuevo empleado» a los distintos miembros del personal que se incorporen, mientras que el rol de « Director de RR.HH.» permanece constante, lo que facilita un proceso de incorporación fluido para cada persona contratada.",
|
||||||
|
"redirect": "Haz clic en el botón «Usar» para crear un nuevo documento desde una plantilla existente.",
|
||||||
|
"bulksend": "Para crear y enviar rápidamente múltiples documentos usando una plantilla existente, haz clic en el botón «Envío rápido».",
|
||||||
|
"option": "Este menú revela más opciones como «Editar» y «Eliminar». Usa el botón «Editar» para agregar roles, modificar campos y actualizar tu plantilla. Los cambios aplicarán para todos los documentos futuros que sean creados usando esta plantilla pero no afectarán a los documentos ya existentes. Con el botón «Eliminar» puedes eliminar la plantilla.",
|
||||||
|
"signyour-self-1": "Para personalizar el documento antes de que sea firmado, selecciona y arrastra al documento los widgets que prefieras. Escoge el espacio perfecto para cada modificación para adaptar el documento a tus necesidades.",
|
||||||
|
"signyour-self-2": "Arrastra y suelta en cualquier lugar de esta área. Después podrás cambiar el tamaño y moverlo.",
|
||||||
|
"template-placeholder-1": "Hacer clic en el botón «Agregar rol» te permitirá agregar varios roles de firmantes. Puedes asociar usuarios a cada rol en los siguientes pasos.",
|
||||||
|
"template-placeholder-2": "Una vez que los roles hayan sido agregados, selecciona un rol de la lista para agregar un marcador de posición donde éste tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del rol una vez lo sueltes en el documento.",
|
||||||
|
"template-placeholder-3": "Arrastra o haz clic en un capo para agregarlo al documento.",
|
||||||
|
"template-placeholder-4": "Arrastra el marcador de posición para un rol a cualquier lugar del documento. Recuerda, aparecerá con el mismo color que el nombre del rol para poder referenciarlo fácilmente.",
|
||||||
|
"template-placeholder-5": "Hacer clic en «Siguiente» guardará la plantilla actual. Luego de guardar, se te consultará si deseas crear un nuevo documento usando esta plantilla.",
|
||||||
|
"webhook-1": "Mejora ahora para configurar un webhook",
|
||||||
|
"Need your Signature": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan por tu revisión.",
|
||||||
|
"Out for signatures": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan tu firma.",
|
||||||
|
"Recent signature requests": "Esta es una lista de documentos que esperan por tu firma.",
|
||||||
|
"Recently sent for signatures": "Esta es una lista de documentos que has enviado a otras partes para que sea firmado.",
|
||||||
|
"Drafts": "Estos son documentos que has empezado pero que todavía no finalizas para su envío.",
|
||||||
|
"public-template": "Este video muestra cómo puedes configurar tu perfil público personalizado, como «https://opensign.me/tu-nombre-de-usuario». También aprenderás cómo personalizar tu eslogan y cómo hacer tus plantillas disponibles para su firmado público."
|
||||||
|
},
|
||||||
|
"enter-email-plaholder": "Agrega una dirección de correo y presiona «Enter»",
|
||||||
|
"success-email-alert": "¡Correo enviado exitosamente!",
|
||||||
|
"expired-doc-title": "Documento expirado",
|
||||||
|
"expired-on-mssg": "Este documento expiro el {{expiredDate}} y ya no está disponible para ser firmado.",
|
||||||
|
"signature-validate-alert": "Por favor, confirma que has seleccionado al menos {{minRequiredCount}} casillas.",
|
||||||
|
"signature-validate-alert-2": "Asegúrate de que este campo esté correctamente rellenado y que cumpla con todos los requisitos.",
|
||||||
|
"remaing-users": "Usuarios restantes",
|
||||||
|
"Role": "Rol",
|
||||||
|
"additional-users": "Por favor, compra el complemento Usuarios.",
|
||||||
|
"Quantity-of-users": "Cantidad de usuarios",
|
||||||
|
"Price": "Precio",
|
||||||
|
"Total-price-for-next-time": "Precio total para la próxima vez",
|
||||||
|
"Proceed": "Proceder",
|
||||||
|
"Select": "Seleccionar",
|
||||||
|
"Add-seats": "Agregar plazas",
|
||||||
|
"user-name-exist": "el nombre de usuario ya existe",
|
||||||
|
"format": "formato",
|
||||||
|
"select-date-format": "Selecciona un formato de fecha",
|
||||||
|
"quantity-of-credits": "Cantidad de créditos premium",
|
||||||
|
"remaining-credits": "Créditos premium disponibles:",
|
||||||
|
"remaining-credits-help": "Usa créditos premium para la API para la firma de documentos, envío en masa, o para incorporar la integración de OpenSign en tu página web. Te quedan {{allowedcredits}} créditos incluidos y {{addoncredits}} créditos comprados adicionalmente.",
|
||||||
|
"additional-credits": "Por favor, compra créditos premium",
|
||||||
|
"quota-err-quicksend": "Cuota alcanzada, no tienes créditos suficientes.",
|
||||||
|
"buy-credits": "Comprar créditos premium",
|
||||||
|
"rotate-right": "Rotar a la derecha",
|
||||||
|
"rotate-left": "Rotar a la izquierda",
|
||||||
|
"rotate-alert-mssg": "Todos los widgets de esta página se perderán. ¿En definitiva quieres proceder?",
|
||||||
|
"templateid": "ID de plantilla",
|
||||||
|
"bulk-send-subcription-alert": "Por favor, mejora al plan a Professional o Team para usar envío en masa.",
|
||||||
|
"generate-test-token": "Generar token de prueba",
|
||||||
|
"regenerate-test-token": "Regenerar token de prueba",
|
||||||
|
"help-test-token": "Este token puede ser usado para probar las API en el punto de acceso «https://sandbox.opensignlabs.com/api/v1», permitiéndote realizar firmas de documentos ilimitadas. Por favor, ten en cuenta que el API de pruebas firmará tus documentos con certificados autofirmados, que podrían no ser reconocidos por Adobe como válidos. Una vez hayas completado tus pruebas, puedes mejorar a uno de nuestros planes de pago para generar un token de producción.",
|
||||||
|
"help-api-token": "Este token puede ser usado para acceder a las API de producción en el punto de acceso «{{origin}}/api/v1». Solo puede ser generado con uno de nuestros planes de pago.",
|
||||||
|
"reason": "Razón",
|
||||||
|
"decline-by": "Rechazado/revocado por",
|
||||||
|
"document-declined": "Documento rechazado",
|
||||||
|
"public-template-mssg-1": "Para integrar OpenSign a tu proyecto React o Next.js, simplemente ejecuta los siguientes comandos:",
|
||||||
|
"public-template-mssg-2": "Asegúrate de tener «npm» o «yarn» configurado en tu proyecto. Si estás usando «yarn», puedes reemplazar «npm install» con «yarn add @opensign/react».",
|
||||||
|
"public-template-mssg-3": "¿Necesitas más detalles o ejemplos?",
|
||||||
|
"public-template-mssg-4": "Visita la",
|
||||||
|
"public-template-mssg-5": " «npm» para las últimas actualizaciones, documentación detallada e historial de versiones.",
|
||||||
|
"public-template-mssg-6": "Antes de que puedas usar este fragmento de código, debes convertir esta plantilla en pública.",
|
||||||
|
"copy-code": "COPIAR",
|
||||||
|
"copied-code": "COPIADO",
|
||||||
|
"Installation": "Instalación",
|
||||||
|
"Usage": "Uso",
|
||||||
|
"insufficient-credits": "Créditos de firma insuficientes",
|
||||||
|
"insufficient-credits-mssg": "El propietario de este documento actualmente carece de los créditos OpenSign necesarios para que puedas firmarlo. Por favor, contacta al propietario si necesitas más detalles.",
|
||||||
|
"angular-npm-mssg-1": "Para integrar OpenSign a tu proyecto Angular, simplemente ejecuta los siguientes comandos:",
|
||||||
|
"quota-mail-info-head": "Límite mensual de solicitudes de firma por correo",
|
||||||
|
"quota-mail-info": "Puedes enviar hasta 15 solicitudes de firma por correo cada mes. Mejora ahora para enviar solicitudes de firma sin límite.",
|
||||||
|
"quota-mail-reset": "Los créditos de tu correo electrónico de solicitud de firma se restablecerán el",
|
||||||
|
"quota-mail": "Has alcanzado tu límite de 15 solicitudes de firma por correo para este mes. Mejora ahora para continuar enviando correos.",
|
||||||
|
"quota-mail-tip": "Consejo: Todavía puedes solciitar la firma de <1>documentos ilimitados</1> compartiendo manualmente los enlaces de solicitud de firma.",
|
||||||
|
"quota-mail-head": "Cuota alcanzada",
|
||||||
|
"unauthorized-modal": "No tienes permisos para realizar esta acción, por favor, contacta a {{adminEmail}}.",
|
||||||
|
"sent-this-month": "Enviados este mes",
|
||||||
|
"available-seats": "Plazas disponibles",
|
||||||
|
"buy-users": "Comprar más usuarios",
|
||||||
|
"isenable-otp": "Habilitar verificación con OTP",
|
||||||
|
"isenable-otp-help": {
|
||||||
|
"p1": "¿Te gustaría habilitar el proceso de verificación usando una contraseña de un solo uso (OTP)?",
|
||||||
|
"p2": "Seleccionar esta opción habilitará la verificación con OTP. Los usuarios recibirán un código de verificación por correo, la cual tendrán que ingresar para poder firmar el documento.",
|
||||||
|
"p3": "Seleccionar esta opción deshabilitará la verificación con OTP, lo cual permitirá a los usuarios firmar el documento directamente sin pasos adicionales.",
|
||||||
|
"p4": "Por favor, selecciona la opción que mejor se adapte a tus requisitos para la firma de documentos."
|
||||||
|
},
|
||||||
|
"advanced-options": "Opciones avanzadas",
|
||||||
|
"hide-advanced-options": "Ocultar las opciones avanzadas",
|
||||||
|
"download-files": "Descargar archivos",
|
||||||
|
"download-pdf": "Descargar PDF",
|
||||||
|
"pdf-certificate": "Descargar PDF + Certificado",
|
||||||
|
"document-logs": "Registros de documentos",
|
||||||
|
"server-down": "No se pudo conectar al servidor de OpenSign. Si estás alojando OpenSign por tu cuenta, por favor, asegúrate de que todos los pasos de la documentación han sido seguidos correctamente. Si estás ejecutando OpenSign localmente, puedes estar accediendo a OpenSign por un número de puerto incorrecto.",
|
||||||
|
"admin-exists": "El administrador ya existe. Por favor, inicia sesión en la aplicación usando las credenciales de administrador para poder administrar los usuarios.",
|
||||||
|
"public-tour-message": "Por favor, convierte la plantilla en pública para copiar la URL pública",
|
||||||
|
"add-user-template": "Es necesario agregar un rol antes de poder agregarle campos.",
|
||||||
|
"pdf-uncompatible": "Este pdf no es compatible con opensign, comuníquese con <support@opensignlabs.com>",
|
||||||
|
"enable-tour": "Habilitar recorrido",
|
||||||
|
"istourenabled-help": {
|
||||||
|
"p1": "Esto permitirá realizar una visita guiada para los firmantes, brindando instrucciones durante el proceso de firma.",
|
||||||
|
"p2": "Esto desactivará la visita guiada, lo que garantizará una experiencia de firma más rápida e ininterrumpida.",
|
||||||
|
"p3": "Consejo: si sus firmantes están familiarizados con OpenSign y lo utilizan con frecuencia, es posible que desee desactivar la visita guiada para disfrutar de una experiencia más fluida. Elija la opción que mejor se adapte a sus necesidades de firma de documentos"
|
||||||
|
},
|
||||||
|
"form-title-1": "Configuración del flujo de documentos",
|
||||||
|
"form-title-2": "Configuración de seguridad",
|
||||||
|
"text-field-tour": "Los campos de tipo 'Texto' deben completarse con anticipación antes de enviar el documento. Si necesita que los firmantes proporcionen información, utilice el campo 'Entrada de texto'",
|
||||||
|
"attach-signer-tour": "Debe adjuntar un firmante a cada función. Puede hacerlo haciendo clic en este icono. Una vez que seleccione un Firmante, se adjuntará a todos los campos asociados con ese rol que aparecen en el mismo color.",
|
||||||
|
"allowed-signature-types": "Tipos de firma permitidos",
|
||||||
|
"at-least-one-signature-type": "Se debe habilitar al menos un tipo de firma.",
|
||||||
|
"expect-default-one-signature-type": "Habilite un tipo de firma adicional aparte del predeterminado.",
|
||||||
|
"add-signer-note": "Nota - Este contacto se agregará a su lista de contactos",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "Esta preferencia de firma controla qué opciones de firma están disponibles para sus firmantes. Solo los tipos de firma que seleccione aparecerán en el widget de firma cuando se firme un documento. Por ejemplo, si elige sólo la opción 'Draw' en las preferencias, su firmante verá sólo la opción 'Draw' en el widget de firma, mientras que las otras tres opciones no estarán disponibles.",
|
||||||
|
"l1": "Cree una firma manuscrita directamente en la pantalla usando su dedo o un lápiz.",
|
||||||
|
"l2": "Ingrese su nombre y elija entre varios estilos de fuente para crear una firma.",
|
||||||
|
"l3": "Cargue una versión digital existente de su firma.",
|
||||||
|
"l4": "Utilice un estilo de firma preestablecido guardado en 'Mi firma' en su configuración."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notificar sobre firmas",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "El creador del documento recibirá una notificación por correo electrónico cada vez que un firmante firme el documento.",
|
||||||
|
"note": "Nota: No se enviará un correo electrónico de notificación al último firmante, ya que el creador del documento recibirá un correo electrónico de finalización."
|
||||||
|
},
|
||||||
|
"expiry-date": "Date d'expiration",
|
||||||
|
"expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Proporcione una nueva fecha de vencimiento que sea posterior a la actual",
|
||||||
|
"delete-page": "eliminar página",
|
||||||
|
"delete-alert": "No se puede eliminar una sola página",
|
||||||
|
"delete-alert-2": "¿Está seguro de que desea eliminar esta página?",
|
||||||
|
"delete-note": "Nota: una vez que elimines esta página, no podrás deshacerla"
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"header-news": "Nouvelle fonctionnalité : les profils publics sont désormais en ligne ! Créez et partagez facilement des modèles publics",
|
"header-news": "Nouvelle fonctionnalité : les utilisateurs du forfait Teams peuvent désormais intégrer leurs propres compartiments AWS S3 pour le stockage de fichiers",
|
||||||
"header-news-btn": "Configurer maintenant",
|
"header-news-btn": "Configurer maintenant",
|
||||||
"create-account": "Créer un compte",
|
"create-account": "Créer un compte",
|
||||||
"login": "Se Connecter",
|
"login": "Se Connecter",
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
"upgrade-to": "Mettre à niveau vers",
|
"upgrade-to": "Mettre à niveau vers",
|
||||||
"pro": "PRO",
|
"pro": "PRO",
|
||||||
"plan": "Offre",
|
"plan": "Offre",
|
||||||
"subscribe-card-teamplan":"Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
|
"subscribe-card-teamplan": "Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
|
||||||
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
|
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
|
||||||
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
|
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
|
||||||
"tour-content": "Ne plus afficher",
|
"tour-content": "Ne plus afficher",
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
"My Signature": "Ma signature",
|
"My Signature": "Ma signature",
|
||||||
"API Token": "Jeton API",
|
"API Token": "Jeton API",
|
||||||
"Webhook": "Webhook",
|
"Webhook": "Webhook",
|
||||||
|
"Preferences": "Préférences",
|
||||||
"Teams": "Équipe",
|
"Teams": "Équipe",
|
||||||
"Team-update-successfully": "Équipe mise à jour avec succès.",
|
"Team-update-successfully": "Équipe mise à jour avec succès.",
|
||||||
"Users": "Utilisateurs"
|
"Users": "Utilisateurs"
|
||||||
@@ -137,7 +138,8 @@
|
|||||||
"Status": "Statut",
|
"Status": "Statut",
|
||||||
"created-date": "Date de création",
|
"created-date": "Date de création",
|
||||||
"Type": "Saisir",
|
"Type": "Saisir",
|
||||||
"Logs": "Journaux"
|
"Logs": "Journaux",
|
||||||
|
"Expiry-date": "Fecha de caducidad"
|
||||||
},
|
},
|
||||||
"btnLabel": {
|
"btnLabel": {
|
||||||
"sign": "Signer",
|
"sign": "Signer",
|
||||||
@@ -152,7 +154,9 @@
|
|||||||
"View": "Voir",
|
"View": "Voir",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Intégrer",
|
"Embed": "Intégrer",
|
||||||
"Copy TemplateId": "Copier l'ID du modèle"
|
"Copy TemplateId": "Copier l'ID du modèle",
|
||||||
|
"Copy Public URL": "Copier l'URL publique",
|
||||||
|
"extend-expiry-date": "Prolonger la date d'expiration"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
@@ -263,10 +267,11 @@
|
|||||||
"make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?",
|
"make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?",
|
||||||
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
||||||
"public-role": "Rôle public",
|
"public-role": "Rôle public",
|
||||||
"public-url": "URL publique",
|
"public-url": "Profil public",
|
||||||
|
"embed-template": "Intégrer le modèle",
|
||||||
"public-url-copy": "Voici votre URL publique : ",
|
"public-url-copy": "Voici votre URL publique : ",
|
||||||
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
||||||
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
"add-public-url-alert": "Veuillez terminer la configuration de votre profil public OpenSign. Une fois cela fait, vous pourrez rendre les modèles publics. Ce processus ne doit être effectué qu’une seule fois.",
|
||||||
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
||||||
"share-with": "Partager avec",
|
"share-with": "Partager avec",
|
||||||
"team-not-found": "Équipe introuvable",
|
"team-not-found": "Équipe introuvable",
|
||||||
@@ -289,7 +294,7 @@
|
|||||||
"subject": "Sujet",
|
"subject": "Sujet",
|
||||||
"body": "Corps",
|
"body": "Corps",
|
||||||
"add-contact": "Ajouter le contact",
|
"add-contact": "Ajouter le contact",
|
||||||
"add-signer-alert": "Le contact existe déjà !",
|
"add-signer-alert": "Le contact existe déjà ! Veuillez le sélectionner dans la liste déroulante 'Signataires'",
|
||||||
"record-delete-alert": "Enregistrement supprimé avec succès !",
|
"record-delete-alert": "Enregistrement supprimé avec succès !",
|
||||||
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
|
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
|
||||||
"mail-sent-alert": "Courriel envoyé avec succès.",
|
"mail-sent-alert": "Courriel envoyé avec succès.",
|
||||||
@@ -443,7 +448,8 @@
|
|||||||
"cutomize-email": "Personnaliser l'e-mail",
|
"cutomize-email": "Personnaliser l'e-mail",
|
||||||
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
|
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
|
||||||
"sign-url": "Signer l'URL",
|
"sign-url": "Signer l'URL",
|
||||||
"Mails Sent": "Mails envoyés avec succès !",
|
"mails-sent": "Mails envoyés avec succès !",
|
||||||
|
"mail-not-delivered": "Courrier non distribué",
|
||||||
"document-alert": "Alerte document",
|
"document-alert": "Alerte document",
|
||||||
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
|
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
|
||||||
"subscription-expired": "Abonnement expiré",
|
"subscription-expired": "Abonnement expiré",
|
||||||
@@ -508,7 +514,7 @@
|
|||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
"invalid-document": "Erreur : document invalide !",
|
"invalid-document": "Erreur : document invalide !",
|
||||||
"document-not-found": "Document introuvable !",
|
"document-not-found": "Document introuvable !",
|
||||||
"document-signed-alert-1": "Vous avez signé le document avec succès. Vous pouvez télécharger ou imprimer une copie du document partiellement signé. Une copie du document signé numériquement sera envoyée au propriétaire par e-mail une fois qu'il sera signé par tous les signataires.",
|
"document-signed-alert-1": "Vous avez signé le document avec succès. Vous pouvez télécharger ou imprimer une copie du document partiellement signé. Une copie du document signé numériquement et du certificat d'achèvement sera envoyée au propriétaire et à tous les signataires par e-mail une fois qu'il aura été signé par tous les signataires.",
|
||||||
"encrypted-pdf-not-support": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge. ",
|
"encrypted-pdf-not-support": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge. ",
|
||||||
"document-signed-alert-4": "Toutes nos félicitations! 🎉 Ce document a été signé avec succès par tous les participants !",
|
"document-signed-alert-4": "Toutes nos félicitations! 🎉 Ce document a été signé avec succès par tous les participants !",
|
||||||
"document-signed-alert-5": "Ce document a été signé par tous les signataires.",
|
"document-signed-alert-5": "Ce document a été signé par tous les signataires.",
|
||||||
@@ -615,46 +621,47 @@
|
|||||||
"Add-seats": "Ajouter des sièges",
|
"Add-seats": "Ajouter des sièges",
|
||||||
"format": "format",
|
"format": "format",
|
||||||
"select-date-format": "Sélectionnez un format de date",
|
"select-date-format": "Sélectionnez un format de date",
|
||||||
"quantity-of-credits":"Quantité de crédits de prime",
|
"quantity-of-credits": "Quantité de crédits de prime",
|
||||||
"remaining-credits":"Crédits premium disponibles :",
|
"remaining-credits": "Crédits premium disponibles :",
|
||||||
"additional-credits":"Veuillez acheter des crédits premium",
|
"additional-credits": "Veuillez acheter des crédits premium",
|
||||||
"remaining-credits-help":"Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
|
"remaining-credits-help": "Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
|
||||||
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
|
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
|
||||||
"buy-credits": "Acheter des crédits premium",
|
"buy-credits": "Acheter des crédits premium",
|
||||||
"rotate-right" :"Faire pivoter à droite",
|
"rotate-right": "Faire pivoter à droite",
|
||||||
"rotate-left" :"Faire pivoter à gauche",
|
"rotate-left": "Faire pivoter à gauche",
|
||||||
"rotate-alert-mssg" :"Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
|
"rotate-alert-mssg": "Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
|
||||||
"templateid":"ID de modèle",
|
"templateid": "ID de modèle",
|
||||||
"bulk-send-subcription-alert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
|
"bulk-send-subcription-alert": "Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
|
||||||
"generate-test-token": "Générer jeton de test",
|
"generate-test-token": "Générer jeton de test",
|
||||||
"regenerate-test-token":"Régénérer le jeton de test",
|
"regenerate-test-token": "Régénérer le jeton de test",
|
||||||
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à l’un de nos forfaits payants pour générer un jeton de production.",
|
"help-test-token": "Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à l’un de nos forfaits payants pour générer un jeton de production.",
|
||||||
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
|
"help-api-token": "Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
|
||||||
"reason" :"Raison",
|
"reason": "Raison",
|
||||||
"decline-by" :"Refusé/révoqué par",
|
"decline-by": "Refusé/révoqué par",
|
||||||
"document-declined":"document refusé",
|
"document-declined": "document refusé",
|
||||||
"public-template-mssg-1" :"Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
|
"public-template-mssg-1": "Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
|
||||||
"public-template-mssg-2" :"Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
|
"public-template-mssg-2": "Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
|
||||||
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
|
"public-template-mssg-3": "Besoin de plus de détails ou d'exemples ?",
|
||||||
"public-template-mssg-4": "Visitez le",
|
"public-template-mssg-4": "Visitez le",
|
||||||
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
||||||
"public-template-mssg-6":"Vous devez définir ce modèle comme public avant de pouvoir utiliser cet extrait de code.",
|
"public-template-mssg-6": "Avant de pouvoir utiliser cet extrait de code, vous devez rendre ce modèle public.",
|
||||||
"copy-code":"COPIE",
|
"copy-code": "COPIE",
|
||||||
"copied-code":"COPIÉ",
|
"copied-code": "COPIÉ",
|
||||||
"Installation":"Installation",
|
"Installation": "Installation",
|
||||||
"Usage" :"Usage",
|
"Usage": "Usage",
|
||||||
"insufficient-credits":"Crédits de signature insuffisants",
|
"insufficient-credits": "Crédits de signature insuffisants",
|
||||||
"insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails.",
|
"insufficient-credits-mssg": "Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails.",
|
||||||
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
"angular-npm-mssg-1": "Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
||||||
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
"quota-mail-info-head": "Limite mensuelle d'e-mails de signatures de demandes",
|
||||||
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
||||||
|
"quota-mail-reset": "Les crédits de votre email de demande de signature seront réinitialisés le",
|
||||||
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
||||||
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
"quota-mail-tip-tip": "Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
||||||
"quota-mail-head":"Quota atteint",
|
"quota-mail-head": "Quota atteint",
|
||||||
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
|
"unauthorized-modal": "Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
|
||||||
"sent-this-month":"envoyé ce mois-ci",
|
"sent-this-month": "envoyé ce mois-ci",
|
||||||
"available-seats":"Disponible sièges",
|
"available-seats": "Disponible sièges",
|
||||||
"buy-users":"Acheter plus d'utilisateurs",
|
"buy-users": "Acheter plus d'utilisateurs",
|
||||||
"isenable-otp": "Activer la vérification OTP",
|
"isenable-otp": "Activer la vérification OTP",
|
||||||
"isenable-otp-help": {
|
"isenable-otp-help": {
|
||||||
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
|
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
|
||||||
@@ -662,11 +669,48 @@
|
|||||||
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
|
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
|
||||||
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
||||||
},
|
},
|
||||||
"advanced-options":"Options avancées",
|
"advanced-options": "Options avancées",
|
||||||
"hide-advanced-options": "Masquer les options avancées",
|
"hide-advanced-options": "Masquer les options avancées",
|
||||||
"download-files" :"Télécharger des fichiers",
|
"download-files": "Télécharger des fichiers",
|
||||||
"download-pdf" :"Télécharger le PDF",
|
"download-pdf": "Télécharger le PDF",
|
||||||
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
"pdf-certificate": "Télécharger Pdf + Certificat",
|
||||||
"document-logs":"Journaux de documents"
|
"document-logs": "Journaux de documents",
|
||||||
|
"server-down": "Impossible de se connecter au serveur OpenSign. Si vous hébergez vous-même OpenSign, veuillez vous assurer que toutes les étapes de la documentation ont été correctement suivies. Si vous exécutez OpenSign localement, vous y accédez peut-être via un numéro de port incorrect.",
|
||||||
|
"admin-exists": "L'administrateur existe déjà. Veuillez vous connecter à l'application en utilisant les informations d'identification de l'administrateur afin de gérer les utilisateurs.",
|
||||||
|
"enable-tour": "Activer la visite",
|
||||||
|
"istourenabled-otp-help": {
|
||||||
|
"p1": "Cela permettra une visite guidée pour les signataires, fournissant des instructions pendant le processus de signature.",
|
||||||
|
"p2": "Cela désactivera la visite guidée, garantissant ainsi une expérience de signature plus rapide et ininterrompue.",
|
||||||
|
"p3": "Conseil : si vos signataires connaissent OpenSign et l'utilisent fréquemment, vous souhaiterez peut-être désactiver la visite guidée pour une expérience plus fluide. Choisissez l'option qui correspond le mieux à vos besoins en matière de signature de documents."
|
||||||
|
},
|
||||||
|
"form-title-1": "Paramètre du flux de documents",
|
||||||
|
"form-title-2": "Paramètre de sécurité",
|
||||||
|
"public-tour-message": "Le modèle doit être public avant que vous puissiez générer un lien partageable.",
|
||||||
|
"add-user-template": "Vous devez ajouter un rôle avant de pouvoir lui ajouter des champs. ",
|
||||||
|
"pdf-uncompatible": "Ce pdf n'est pas compatible avec opensign, veuillez contacter <support@opensignlabs.com>",
|
||||||
|
"text-field-tour": "Les champs de type 'Texte' doivent être remplis à l'avance avant l'envoi du document. Si vous avez besoin que les signataires fournissent des informations, utilisez plutôt le champ 'Saisie de texte'.",
|
||||||
|
"attach-signer-tour": "Vous devez associer un signataire à chaque rôle. Vous pouvez le faire en cliquant sur cette icône. Une fois que vous avez sélectionné un signataire, il sera attaché à tous les champs associés à ce rôle qui apparaissent dans la même couleur.",
|
||||||
|
"allowed-signature-types": "Types de signature autorisés",
|
||||||
|
"at-least-one-signature-type": "Au moins un type de signature doit être activé.",
|
||||||
|
"expect-default-one-signature-type": "Veuillez activer un type de signature supplémentaire en plus de celui par défaut.",
|
||||||
|
"add-signer-note": "Remarque - Ce contact sera ajouté à votre liste de contacts",
|
||||||
|
"allowed-signature-types-help": {
|
||||||
|
"p1": "Cette préférence de signature contrôle les options de signature disponibles pour vos signataires. Seuls les types de signature que vous sélectionnez apparaîtront dans le widget de signature lorsqu'un document est signé. Par exemple, si vous choisissez uniquement l'option 'Draw' dans les préférences, votre signataire ne verra que l'option 'Draw' dans le widget de signature, tandis que les trois autres options ne seront pas disponibles.",
|
||||||
|
"l1": "Créez une signature manuscrite directement sur l'écran à l'aide de votre doigt ou d'un stylet.",
|
||||||
|
"l2": "Entrez votre nom et choisissez parmi différents styles de police pour créer une signature.",
|
||||||
|
"l3": "Téléchargez une version numérique existante de votre signature.",
|
||||||
|
"l4": "Utilisez un style de signature prédéfini enregistré sous 'Ma signature' dans vos paramètres."
|
||||||
|
},
|
||||||
|
"notify-on-signatures": "Notifier les signatures",
|
||||||
|
"notify-on-signatures-help": {
|
||||||
|
"p1": "Le créateur du document recevra une notification par e-mail chaque fois qu'un signataire signera le document.",
|
||||||
|
"note": "Remarque : L'e-mail de notification ne sera pas envoyé pour le dernier signataire, car le créateur du document recevra à la place un e-mail de fin."
|
||||||
|
},
|
||||||
|
"expiry-date": "Fecha de caducidad",
|
||||||
|
"expiry-date-updated": "La date d'expiration a été prolongée avec succès jusqu'au {{newexpirydate}}",
|
||||||
|
"expiry-date-error": "Veuillez fournir une nouvelle date d'expiration postérieure à la date actuelle",
|
||||||
|
"delete-page": "supprimer la page",
|
||||||
|
"delete-alert": "Impossible de supprimer une seule page",
|
||||||
|
"delete-alert-2": "Etes-vous sûr de vouloir supprimer cette page ?",
|
||||||
|
"delete-note": "Remarque : une fois cette page supprimée, vous ne pouvez plus l'annuler"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
animation: inAnimation 2s ease-in-out;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,9 +127,15 @@ export const updateMailCount = async (extUserId, plan, monthchange) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function formatWidgetOptions(type, options) {
|
export function formatWidgetOptions(type, options) {
|
||||||
|
const colorsArr = ['red', 'black', 'blue', 'yellow'];
|
||||||
|
const fontSizes = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28];
|
||||||
const status = options?.required === true ? 'required' : 'optional' || 'required';
|
const status = options?.required === true ? 'required' : 'optional' || 'required';
|
||||||
const defaultValue = options?.default || '';
|
const defaultValue = options?.default || '';
|
||||||
const values = options?.values || [];
|
const values = options?.values || [];
|
||||||
|
const color = options?.color ? options.color : 'black';
|
||||||
|
const fontColor = colorsArr.includes(color) ? color : 'black';
|
||||||
|
const size = options?.fontsize ? parseInt(options.fontsize) : 12;
|
||||||
|
const fontSize = fontSizes.includes(size) ? size : 12;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'signature':
|
case 'signature':
|
||||||
return { name: 'signature', status: 'required' };
|
return { name: 'signature', status: 'required' };
|
||||||
@@ -140,13 +146,34 @@ export function formatWidgetOptions(type, options) {
|
|||||||
case 'image':
|
case 'image':
|
||||||
return { status: status, name: options.name || 'image' };
|
return { status: status, name: options.name || 'image' };
|
||||||
case 'email':
|
case 'email':
|
||||||
return { status: status, name: options.name || 'email', validation: { type: 'email' } };
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'email',
|
||||||
|
validation: { type: 'email' },
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
|
};
|
||||||
case 'name':
|
case 'name':
|
||||||
return { status: status, name: options.name || 'name' };
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'name',
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
|
};
|
||||||
case 'job title':
|
case 'job title':
|
||||||
return { status: status, name: options.name || 'job title' };
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'job title',
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
|
};
|
||||||
case 'company':
|
case 'company':
|
||||||
return { status: status, name: options.name || 'company' };
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'company',
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
|
};
|
||||||
case 'date': {
|
case 'date': {
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
let dd = String(today.getDate()).padStart(2, '0');
|
let dd = String(today.getDate()).padStart(2, '0');
|
||||||
@@ -160,6 +187,8 @@ export function formatWidgetOptions(type, options) {
|
|||||||
name: options.name || 'date',
|
name: options.name || 'date',
|
||||||
response: defaultValue || today,
|
response: defaultValue || today,
|
||||||
validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' },
|
validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' },
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'textbox':
|
case 'textbox':
|
||||||
@@ -169,6 +198,8 @@ export function formatWidgetOptions(type, options) {
|
|||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
hint: options.hint,
|
hint: options.hint,
|
||||||
validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' },
|
validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' },
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
};
|
};
|
||||||
case 'checkbox': {
|
case 'checkbox': {
|
||||||
const arr = options?.values;
|
const arr = options?.values;
|
||||||
@@ -188,6 +219,8 @@ export function formatWidgetOptions(type, options) {
|
|||||||
maxRequiredCount: options?.validation?.maxselections || 0,
|
maxRequiredCount: options?.validation?.maxselections || 0,
|
||||||
},
|
},
|
||||||
defaultValue: selectedvalues || [],
|
defaultValue: selectedvalues || [],
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'radio button': {
|
case 'radio button': {
|
||||||
@@ -198,6 +231,8 @@ export function formatWidgetOptions(type, options) {
|
|||||||
isReadOnly: options?.readonly || false,
|
isReadOnly: options?.readonly || false,
|
||||||
isHideLabel: options?.hidelabel || false,
|
isHideLabel: options?.hidelabel || false,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'dropdown':
|
case 'dropdown':
|
||||||
@@ -206,6 +241,8 @@ export function formatWidgetOptions(type, options) {
|
|||||||
name: options.name || 'dropdown',
|
name: options.name || 'dropdown',
|
||||||
values: values,
|
values: values,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontSize: fontSize,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -234,3 +271,7 @@ export const planCredits = {
|
|||||||
'teams-monthly': 100,
|
'teams-monthly': 100,
|
||||||
'teams-yearly': 500,
|
'teams-yearly': 500,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function parseJwt(token) {
|
||||||
|
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
The OpenSign Enterprise license (the “Enterprise License”)
|
||||||
|
Copyright (c) 2020-2024 Qik Innovations Private Limited.
|
||||||
|
|
||||||
|
With regard to the OpenSign Software:
|
||||||
|
|
||||||
|
This software and associated documentation files (the "Software") may only be
|
||||||
|
used in production, if you (and any entity that you represent) have agreed to,
|
||||||
|
and are in compliance with, the OpenSign Subscription Terms of Service(the “Enterprise Terms”), or other
|
||||||
|
agreement governing the use of the Software, as agreed by you and OpenSign,
|
||||||
|
and otherwise have a valid OpenSign Enterprise license for the
|
||||||
|
correct number of user seats. Subject to the foregoing sentence, you are free to
|
||||||
|
modify this Software and publish patches to the Software. You agree that OpenSign
|
||||||
|
and/or its licensors (as applicable) retain all right, title and interest in and
|
||||||
|
to all such modifications and/or patches, and all such modifications and/or
|
||||||
|
patches may only be used, copied, modified, displayed, distributed, or otherwise
|
||||||
|
exploited with a valid OpenSign Enterprise license for the correct
|
||||||
|
number of user seats. Notwithstanding the foregoing, you may copy and modify
|
||||||
|
the Software for development and testing purposes, without requiring a
|
||||||
|
subscription. You agree that OpenSign and/or its licensors (as applicable) retain
|
||||||
|
all right, title and interest in and to all such modifications. You are not
|
||||||
|
granted any other rights beyond what is expressly stated herein. Subject to the
|
||||||
|
foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
For all third party components incorporated into the OpenSign Software, those
|
||||||
|
components are licensed under the original license provided by the owner of the
|
||||||
|
applicable component.
|
||||||
@@ -53,7 +53,7 @@ async function sendMail(doc, signer) {
|
|||||||
receiver_phone: signer?.Phone || '',
|
receiver_phone: signer?.Phone || '',
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: doc?.ExtUserPtr?.Company || '',
|
company_name: doc?.ExtUserPtr?.Company || '',
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`,
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`,
|
||||||
};
|
};
|
||||||
const mail = replaceMailVaribles(subject, body, variables);
|
const mail = replaceMailVaribles(subject, body, variables);
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ export default async function autoReminder(request, response) {
|
|||||||
docQuery.exists('Signers');
|
docQuery.exists('Signers');
|
||||||
docQuery.exists('SignedUrl');
|
docQuery.exists('SignedUrl');
|
||||||
docQuery.descending('createdAt');
|
docQuery.descending('createdAt');
|
||||||
docQuery.include('Signers,AuditTrail.UserPtr,ExtUserPtr');
|
docQuery.include('Signers,AuditTrail.UserPtr,ExtUserPtr,ExtUserPtr.TenantId');
|
||||||
docQuery.notEqualTo('IsCompleted', true);
|
docQuery.notEqualTo('IsCompleted', true);
|
||||||
docQuery.notEqualTo('IsDeclined', true);
|
docQuery.notEqualTo('IsDeclined', true);
|
||||||
docQuery.notEqualTo('IsArchive', true);
|
docQuery.notEqualTo('IsArchive', true);
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import getDocument from './routes/getDocument.js';
|
|||||||
import getContact from './routes/getContact.js';
|
import getContact from './routes/getContact.js';
|
||||||
import deleteContact from './routes/deleteContact.js';
|
import deleteContact from './routes/deleteContact.js';
|
||||||
import getContactList from './routes/getContactList.js';
|
import getContactList from './routes/getContactList.js';
|
||||||
import draftDocument from './routes/draftDocument.js';
|
|
||||||
import createTemplate from './routes/createTemplate.js';
|
|
||||||
import getTemplate from './routes/getTemplate.js';
|
import getTemplate from './routes/getTemplate.js';
|
||||||
import deletedTemplate from './routes/deleteTemplate.js';
|
import deletedTemplate from './routes/deleteTemplate.js';
|
||||||
import getTemplatetList from './routes/getTemplateList.js';
|
import getTemplatetList from './routes/getTemplateList.js';
|
||||||
@@ -60,9 +58,6 @@ app.post('/createdocumentwithbinary', upload.array('file', 1), createDocumentwit
|
|||||||
// create Document with co-ordinate
|
// create Document with co-ordinate
|
||||||
app.post('/createdocument', createDocumentwithCoordinate);
|
app.post('/createdocument', createDocumentwithCoordinate);
|
||||||
|
|
||||||
// create Document with base64 without placeholder
|
|
||||||
app.post('/draftdocument', draftDocument);
|
|
||||||
|
|
||||||
// create Document with templateId
|
// create Document with templateId
|
||||||
app.post('/createdocument/:template_id', createDocumentWithTemplate);
|
app.post('/createdocument/:template_id', createDocumentWithTemplate);
|
||||||
|
|
||||||
@@ -81,9 +76,6 @@ app.get('/documentlist/:doctype', getDocumentList);
|
|||||||
// create Template with co-ordinate
|
// create Template with co-ordinate
|
||||||
app.post('/createtemplate', createTemplatewithCoordinate);
|
app.post('/createtemplate', createTemplatewithCoordinate);
|
||||||
|
|
||||||
// create Template
|
|
||||||
app.post('/drafttemplate', createTemplate);
|
|
||||||
|
|
||||||
// create Template with binary
|
// create Template with binary
|
||||||
app.post('/createtemplatewithbinary', upload.array('file', 1), createTemplatewithCoordinate);
|
app.post('/createtemplatewithbinary', upload.array('file', 1), createTemplatewithCoordinate);
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
const send_email = request.body.send_email;
|
const send_email = request.body.send_email;
|
||||||
const email_subject = request.body.email_subject;
|
const email_subject = request.body.email_subject;
|
||||||
const email_body = request.body.email_body;
|
const email_body = request.body.email_body;
|
||||||
const sendInOrder = request.body.sendInOrder || false;
|
const sendInOrder = request.body.sendInOrder || true;
|
||||||
const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
|
const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -91,6 +91,7 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
if (totalcredits > 0) {
|
if (totalcredits > 0) {
|
||||||
const templateQuery = new Parse.Query('contracts_Template');
|
const templateQuery = new Parse.Query('contracts_Template');
|
||||||
templateQuery.include('ExtUserPtr');
|
templateQuery.include('ExtUserPtr');
|
||||||
|
templateQuery.include('ExtUserPtr.TenantId');
|
||||||
const templateRes = await templateQuery.get(templateId, { useMasterKey: true });
|
const templateRes = await templateQuery.get(templateId, { useMasterKey: true });
|
||||||
if (templateRes) {
|
if (templateRes) {
|
||||||
const template = JSON.parse(JSON.stringify(templateRes));
|
const template = JSON.parse(JSON.stringify(templateRes));
|
||||||
@@ -196,8 +197,13 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
if (TimeToCompleteDays) {
|
if (TimeToCompleteDays) {
|
||||||
object.set('TimeToCompleteDays', TimeToCompleteDays);
|
object.set('TimeToCompleteDays', TimeToCompleteDays);
|
||||||
}
|
}
|
||||||
const enableOTP = request.body?.enableOTP === true ? true : false;
|
const enableOTP = request.body?.enableOTP;
|
||||||
const IsEnableOTP = enableOTP || template?.IsEnableOTP || false;
|
const IsEnableOTP =
|
||||||
|
enableOTP !== undefined ? enableOTP : template?.IsEnableOTP || false;
|
||||||
|
const enableTour = request.body?.enableTour;
|
||||||
|
const isTourEnabled =
|
||||||
|
enableTour !== undefined ? enableTour : template?.IsTourEnabled || false;
|
||||||
|
object.set('IsTourEnabled', isTourEnabled);
|
||||||
object.set('IsEnableOTP', IsEnableOTP);
|
object.set('IsEnableOTP', IsEnableOTP);
|
||||||
object.set('CreatedBy', template.CreatedBy);
|
object.set('CreatedBy', template.CreatedBy);
|
||||||
object.set('ExtUserPtr', {
|
object.set('ExtUserPtr', {
|
||||||
@@ -208,6 +214,9 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
if (folderId) {
|
if (folderId) {
|
||||||
object.set('Folder', folderPtr);
|
object.set('Folder', folderPtr);
|
||||||
}
|
}
|
||||||
|
if (template?.FileAdapterId) {
|
||||||
|
object.set('FileAdapterId', template?.FileAdapterId);
|
||||||
|
}
|
||||||
const newACL = new Parse.ACL();
|
const newACL = new Parse.ACL();
|
||||||
newACL.setPublicReadAccess(false);
|
newACL.setPublicReadAccess(false);
|
||||||
newACL.setPublicWriteAccess(false);
|
newACL.setPublicWriteAccess(false);
|
||||||
@@ -268,7 +277,7 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
orgName +
|
orgName +
|
||||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||||
localExpireDate +
|
localExpireDate +
|
||||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||||
signPdf +
|
signPdf +
|
||||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px;'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px;'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
sender +
|
sender +
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
sanitizeFileName,
|
sanitizeFileName,
|
||||||
cloudServerUrl,
|
cloudServerUrl,
|
||||||
} from '../../../../Utils.js';
|
} from '../../../../Utils.js';
|
||||||
|
import uploadFileToS3 from '../../../parsefunction/uploadFiletoS3.js';
|
||||||
|
|
||||||
// `sendDoctoWebhook` is used to send res data of document on webhook
|
// `sendDoctoWebhook` is used to send res data of document on webhook
|
||||||
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
|
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
|
||||||
@@ -61,9 +62,10 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
||||||
const email_subject = request.body.email_subject;
|
const email_subject = request.body.email_subject;
|
||||||
const email_body = request.body.email_body;
|
const email_body = request.body.email_body;
|
||||||
const sendInOrder = request.body.sendInOrder || false;
|
const sendInOrder = request.body.sendInOrder || true;
|
||||||
const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
|
const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
|
||||||
const IsEnableOTP = request.body?.enableOTP === true ? true : false;
|
const IsEnableOTP = request.body?.enableOTP === true ? true : false;
|
||||||
|
const isTourEnabled = request.body?.enableTour || false;
|
||||||
// console.log('fileData ', fileData);
|
// console.log('fileData ', fileData);
|
||||||
const protocol = customAPIurl();
|
const protocol = customAPIurl();
|
||||||
const baseUrl = new URL(process.env.PUBLIC_URL);
|
const baseUrl = new URL(process.env.PUBLIC_URL);
|
||||||
@@ -87,6 +89,7 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
};
|
};
|
||||||
const extUsers = new Parse.Query('contracts_Users');
|
const extUsers = new Parse.Query('contracts_Users');
|
||||||
extUsers.equalTo('UserId', userPtr);
|
extUsers.equalTo('UserId', userPtr);
|
||||||
|
extUsers.include('TenantId');
|
||||||
const extUser = await extUsers.first({ useMasterKey: true });
|
const extUser = await extUsers.first({ useMasterKey: true });
|
||||||
|
|
||||||
const subscription = new Parse.Query('contracts_Subscriptions');
|
const subscription = new Parse.Query('contracts_Subscriptions');
|
||||||
@@ -114,6 +117,7 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
.status(400)
|
.status(400)
|
||||||
.json({ error: 'Please add at least one signature widget for all signers' });
|
.json({ error: 'Please add at least one signature widget for all signers' });
|
||||||
}
|
}
|
||||||
|
const parseExtUser = JSON.parse(JSON.stringify(extUser));
|
||||||
let fileUrl;
|
let fileUrl;
|
||||||
if (request.files?.[0]) {
|
if (request.files?.[0]) {
|
||||||
const base64 = fileData?.toString('base64');
|
const base64 = fileData?.toString('base64');
|
||||||
@@ -126,23 +130,29 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
const filename = sanitizeFileName(`${name}.pdf`);
|
const filename = sanitizeFileName(`${name}.pdf`);
|
||||||
|
let adapter = {};
|
||||||
|
const ActiveFileAdapter = parseExtUser?.TenantId?.ActiveFileAdapter || '';
|
||||||
|
if (ActiveFileAdapter) {
|
||||||
|
adapter =
|
||||||
|
parseExtUser?.TenantId?.FileAdapters?.find(x => (x.id = ActiveFileAdapter)) || {};
|
||||||
|
}
|
||||||
|
if (adapter?.id) {
|
||||||
|
const filedata = Buffer.from(base64File, 'base64');
|
||||||
|
// `uploadFileToS3` is used to save document in user's file storage
|
||||||
|
fileUrl = await uploadFileToS3(filedata, filename, 'application/pdf', adapter);
|
||||||
|
} else {
|
||||||
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
}
|
||||||
const buffer = Buffer.from(base64File, 'base64');
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
|
||||||
const extUser = await contractsUser.first({ useMasterKey: true });
|
|
||||||
const parseExtUser = JSON.parse(JSON.stringify(extUser));
|
|
||||||
|
|
||||||
const extUserPtr = {
|
const extUserPtr = {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className: 'contracts_Users',
|
className: 'contracts_Users',
|
||||||
objectId: extUser.id,
|
objectId: extUser.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
const object = new Parse.Object('contracts_Document');
|
const object = new Parse.Object('contracts_Document');
|
||||||
object.set('Name', name);
|
object.set('Name', name);
|
||||||
|
|
||||||
@@ -164,7 +174,11 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
object.set('TimeToCompleteDays', TimeToCompleteDays);
|
object.set('TimeToCompleteDays', TimeToCompleteDays);
|
||||||
}
|
}
|
||||||
object.set('IsEnableOTP', IsEnableOTP);
|
object.set('IsEnableOTP', IsEnableOTP);
|
||||||
|
object.set('IsTourEnabled', isTourEnabled);
|
||||||
object.set('IsSendMail', send_email);
|
object.set('IsSendMail', send_email);
|
||||||
|
if (parseExtUser?.TenantId?.ActiveFileAdapter) {
|
||||||
|
object.set('FileAdapterId', parseExtUser?.TenantId?.ActiveFileAdapter);
|
||||||
|
}
|
||||||
let contact = [];
|
let contact = [];
|
||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
let parseSigners;
|
let parseSigners;
|
||||||
@@ -325,7 +339,7 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
orgName +
|
orgName +
|
||||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||||
localExpireDate +
|
localExpireDate +
|
||||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||||
signPdf +
|
signPdf +
|
||||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
sender +
|
sender +
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
import { saveFileUsage } from '../../../../Utils.js';
|
|
||||||
export default async function createTemplate(request, response) {
|
|
||||||
const name = request.body?.title;
|
|
||||||
const note = request.body?.note;
|
|
||||||
const description = request.body?.description;
|
|
||||||
const signers = request.body?.signers;
|
|
||||||
const folderId = request.body?.folderId;
|
|
||||||
const base64File = request.body.file;
|
|
||||||
const SendinOrder = request.body.sendInOrder || false;
|
|
||||||
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
|
||||||
const baseUrl = new URL(process.env.PUBLIC_URL);
|
|
||||||
const isEnableOTP = request.body?.enableOTP === true ? true : false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const reqToken = request.headers['x-api-token'];
|
|
||||||
if (!reqToken) {
|
|
||||||
return response.status(400).json({ error: 'Please Provide API Token' });
|
|
||||||
}
|
|
||||||
const tokenQuery = new Parse.Query('appToken');
|
|
||||||
tokenQuery.equalTo('token', reqToken);
|
|
||||||
tokenQuery.include('userId');
|
|
||||||
const token = await tokenQuery.first({ useMasterKey: true });
|
|
||||||
if (token !== undefined) {
|
|
||||||
// Valid Token then proceed request
|
|
||||||
const parseUser = JSON.parse(JSON.stringify(token));
|
|
||||||
const userPtr = {
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: '_User',
|
|
||||||
objectId: parseUser.userId.objectId,
|
|
||||||
};
|
|
||||||
let fileUrl;
|
|
||||||
if (base64File) {
|
|
||||||
const file = new Parse.File(`${name}.pdf`, {
|
|
||||||
base64: base64File,
|
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
|
||||||
fileUrl = file.url();
|
|
||||||
const buffer = Buffer.from(base64File, 'base64');
|
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
|
||||||
} else {
|
|
||||||
const base64 = fileData?.toString('base64');
|
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
|
||||||
base64: base64,
|
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
|
||||||
fileUrl = file.url();
|
|
||||||
const buffer = Buffer.from(base64, 'base64');
|
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
|
||||||
const extUser = await contractsUser.first({ useMasterKey: true });
|
|
||||||
const extUserPtr = { __type: 'Pointer', className: 'contracts_Users', objectId: extUser.id };
|
|
||||||
|
|
||||||
const folderPtr = { __type: 'Pointer', className: 'contracts_Template', objectId: folderId };
|
|
||||||
|
|
||||||
const object = new Parse.Object('contracts_Template');
|
|
||||||
object.set('Name', name);
|
|
||||||
if (note) {
|
|
||||||
object.set('Note', note);
|
|
||||||
}
|
|
||||||
if (description) {
|
|
||||||
object.set('Description', description);
|
|
||||||
}
|
|
||||||
object.set('URL', fileUrl);
|
|
||||||
object.set('CreatedBy', userPtr);
|
|
||||||
object.set('ExtUserPtr', extUserPtr);
|
|
||||||
object.set('IsEnableOTP', isEnableOTP);
|
|
||||||
if (SendinOrder) {
|
|
||||||
object.set('SendinOrder', SendinOrder);
|
|
||||||
}
|
|
||||||
if (signers && signers.length > 0) {
|
|
||||||
let parseSigners;
|
|
||||||
if (base64File) {
|
|
||||||
parseSigners = signers;
|
|
||||||
} else {
|
|
||||||
parseSigners = JSON.parse(signers);
|
|
||||||
}
|
|
||||||
let createContactUrl = protocol + '/v1/createcontact';
|
|
||||||
|
|
||||||
let contact = [];
|
|
||||||
for (const obj of parseSigners) {
|
|
||||||
const body = {
|
|
||||||
name: obj?.name || '',
|
|
||||||
email: obj?.email || '',
|
|
||||||
phone: obj?.phone || '',
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const res = await axios.post(createContactUrl, body, {
|
|
||||||
headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken },
|
|
||||||
});
|
|
||||||
// console.log('res ', res.data);
|
|
||||||
contact.push({
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Contactbook',
|
|
||||||
objectId: res.data?.objectId,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
// console.log('err ', err.response);
|
|
||||||
if (err?.response?.data?.objectId) {
|
|
||||||
contact.push({
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Contactbook',
|
|
||||||
objectId: err.response.data?.objectId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object.set('Signers', contact);
|
|
||||||
}
|
|
||||||
if (folderId) {
|
|
||||||
object.set('Folder', folderPtr);
|
|
||||||
}
|
|
||||||
const newACL = new Parse.ACL();
|
|
||||||
newACL.setPublicReadAccess(false);
|
|
||||||
newACL.setPublicWriteAccess(false);
|
|
||||||
newACL.setReadAccess(userPtr.objectId, true);
|
|
||||||
newACL.setWriteAccess(userPtr.objectId, true);
|
|
||||||
object.setACL(newACL);
|
|
||||||
const res = await object.save(null, { useMasterKey: true });
|
|
||||||
if (request.posthog) {
|
|
||||||
request.posthog?.capture({
|
|
||||||
distinctId: parseUser.userId.email,
|
|
||||||
event: 'api_draft_template',
|
|
||||||
properties: { response_code: 200 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return response.json({
|
|
||||||
objectId: res.id,
|
|
||||||
url: baseUrl.origin + '/template/' + res.id,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return response.status(405).json({ error: 'Invalid API Token!' });
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log('err ', err);
|
|
||||||
return response.status(400).json({ error: 'Something went wrong, please try again later!' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
formatWidgetOptions,
|
formatWidgetOptions,
|
||||||
sanitizeFileName,
|
sanitizeFileName,
|
||||||
} from '../../../../Utils.js';
|
} from '../../../../Utils.js';
|
||||||
|
import uploadFileToS3 from '../../../parsefunction/uploadFiletoS3.js';
|
||||||
|
|
||||||
const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
||||||
export default async function createTemplatewithCoordinate(request, response) {
|
export default async function createTemplatewithCoordinate(request, response) {
|
||||||
@@ -16,8 +17,9 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
const folderId = request.body.folderId;
|
const folderId = request.body.folderId;
|
||||||
const base64File = request.body.file;
|
const base64File = request.body.file;
|
||||||
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
||||||
const SendinOrder = request.body.sendInOrder || false;
|
const SendinOrder = request.body.sendInOrder || true;
|
||||||
const isEnableOTP = request.body?.enableOTP === true ? true : false;
|
const isEnableOTP = request.body?.enableOTP === true ? true : false;
|
||||||
|
const isTourEnabled = request.body?.enableTour || false;
|
||||||
|
|
||||||
// console.log('fileData ', fileData);
|
// console.log('fileData ', fileData);
|
||||||
const protocol = customAPIurl();
|
const protocol = customAPIurl();
|
||||||
@@ -40,6 +42,11 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
objectId: parseUser.userId.objectId,
|
objectId: parseUser.userId.objectId,
|
||||||
};
|
};
|
||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
|
const contractsUser = new Parse.Query('contracts_Users');
|
||||||
|
contractsUser.equalTo('UserId', userPtr);
|
||||||
|
contractsUser.include('TenantId');
|
||||||
|
const extUser = await contractsUser.first({ useMasterKey: true });
|
||||||
|
const parseExtUser = JSON.parse(JSON.stringify(extUser));
|
||||||
let fileUrl;
|
let fileUrl;
|
||||||
if (request.files?.[0]) {
|
if (request.files?.[0]) {
|
||||||
const base64 = fileData?.toString('base64');
|
const base64 = fileData?.toString('base64');
|
||||||
@@ -52,24 +59,31 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
const filename = sanitizeFileName(`${name}.pdf`);
|
const filename = sanitizeFileName(`${name}.pdf`);
|
||||||
|
let adapter = {};
|
||||||
|
const ActiveFileAdapter = parseExtUser?.TenantId?.ActiveFileAdapter || '';
|
||||||
|
if (ActiveFileAdapter) {
|
||||||
|
adapter =
|
||||||
|
parseExtUser?.TenantId?.FileAdapters?.find(x => (x.id = ActiveFileAdapter)) || {};
|
||||||
|
}
|
||||||
|
if (adapter?.id) {
|
||||||
|
const filedata = Buffer.from(base64File, 'base64');
|
||||||
|
// `uploadFileToS3` is used to save document in user's file storage
|
||||||
|
fileUrl = await uploadFileToS3(filedata, filename, 'application/pdf', adapter);
|
||||||
|
} else {
|
||||||
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
}
|
||||||
const buffer = Buffer.from(base64File, 'base64');
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
|
||||||
const extUser = await contractsUser.first({ useMasterKey: true });
|
|
||||||
const extUserPtr = {
|
const extUserPtr = {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className: 'contracts_Users',
|
className: 'contracts_Users',
|
||||||
objectId: extUser.id,
|
objectId: extUser.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
const object = new Parse.Object('contracts_Template');
|
const object = new Parse.Object('contracts_Template');
|
||||||
object.set('Name', name);
|
object.set('Name', name);
|
||||||
|
|
||||||
if (note) {
|
if (note) {
|
||||||
object.set('Note', note);
|
object.set('Note', note);
|
||||||
}
|
}
|
||||||
@@ -83,6 +97,7 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
object.set('CreatedBy', userPtr);
|
object.set('CreatedBy', userPtr);
|
||||||
object.set('ExtUserPtr', extUserPtr);
|
object.set('ExtUserPtr', extUserPtr);
|
||||||
object.set('IsEnableOTP', isEnableOTP);
|
object.set('IsEnableOTP', isEnableOTP);
|
||||||
|
object.set('IsTourEnabled', isTourEnabled);
|
||||||
let contact = [];
|
let contact = [];
|
||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
let parseSigners;
|
let parseSigners;
|
||||||
@@ -186,6 +201,9 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
objectId: folderId,
|
objectId: folderId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (parseExtUser?.TenantId?.ActiveFileAdapter) {
|
||||||
|
object.set('FileAdapterId', parseExtUser?.TenantId?.ActiveFileAdapter);
|
||||||
|
}
|
||||||
const newACL = new Parse.ACL();
|
const newACL = new Parse.ACL();
|
||||||
newACL.setPublicReadAccess(false);
|
newACL.setPublicReadAccess(false);
|
||||||
newACL.setPublicWriteAccess(false);
|
newACL.setPublicWriteAccess(false);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export default async function deleteDocument(request, response) {
|
|||||||
const Document = new Parse.Query('contracts_Document');
|
const Document = new Parse.Query('contracts_Document');
|
||||||
Document.equalTo('objectId', request.params.document_id);
|
Document.equalTo('objectId', request.params.document_id);
|
||||||
Document.equalTo('CreatedBy', userPtr);
|
Document.equalTo('CreatedBy', userPtr);
|
||||||
|
Document.include('ExtUserPtr.TenantId');
|
||||||
const res = await Document.first({ useMasterKey: true });
|
const res = await Document.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const isArchive = res.get('IsArchive');
|
const isArchive = res.get('IsArchive');
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export default async function deleteFolder(request, response) {
|
|||||||
obj.equalTo('objectId', folderId);
|
obj.equalTo('objectId', folderId);
|
||||||
obj.equalTo('IsArchive', true);
|
obj.equalTo('IsArchive', true);
|
||||||
obj.equalTo('CreatedBy', userPtr);
|
obj.equalTo('CreatedBy', userPtr);
|
||||||
|
obj.include('ExtUserPtr.TenantId');
|
||||||
const isFolderDeleted = await obj.first({ useMasterKey: true });
|
const isFolderDeleted = await obj.first({ useMasterKey: true });
|
||||||
if (!isFolderDeleted) {
|
if (!isFolderDeleted) {
|
||||||
const folder = new Parse.Query('contracts_Document');
|
const folder = new Parse.Query('contracts_Document');
|
||||||
@@ -34,6 +35,7 @@ export default async function deleteFolder(request, response) {
|
|||||||
folder.notEqualTo('IsArchive', true);
|
folder.notEqualTo('IsArchive', true);
|
||||||
folder.equalTo('CreatedBy', userPtr);
|
folder.equalTo('CreatedBy', userPtr);
|
||||||
folder.equalTo('Type', 'Folder');
|
folder.equalTo('Type', 'Folder');
|
||||||
|
folder.include('ExtUserPtr.TenantId');
|
||||||
const isSubItems = await folder.first({ useMasterKey: true });
|
const isSubItems = await folder.first({ useMasterKey: true });
|
||||||
// console.log('isSubItems ', isSubItems);
|
// console.log('isSubItems ', isSubItems);
|
||||||
if (isSubItems) {
|
if (isSubItems) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export default async function deletedTemplate(request, response) {
|
|||||||
const template = new Parse.Query('contracts_Template');
|
const template = new Parse.Query('contracts_Template');
|
||||||
template.equalTo('objectId', request.params.template_id);
|
template.equalTo('objectId', request.params.template_id);
|
||||||
template.equalTo('CreatedBy', userPtr);
|
template.equalTo('CreatedBy', userPtr);
|
||||||
|
template.include('ExtUserPtr.TenantId');
|
||||||
const res = await template.first({ useMasterKey: true });
|
const res = await template.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const isArchive = res.get('IsArchive');
|
const isArchive = res.get('IsArchive');
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
import axios from 'axios';
|
|
||||||
import { customAPIurl, saveFileUsage } from '../../../../Utils.js';
|
|
||||||
|
|
||||||
// const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
|
||||||
export default async function draftDocument(request, response) {
|
|
||||||
const name = request.body.title;
|
|
||||||
const note = request.body.note;
|
|
||||||
const description = request.body.description;
|
|
||||||
const signers = request.body.signers;
|
|
||||||
const folderId = request.body.folderId;
|
|
||||||
const base64File = request.body.file;
|
|
||||||
const send_email = request.body.send_email || true;
|
|
||||||
const fileData = request.files?.[0] ? request.files[0].buffer : null;
|
|
||||||
const SendinOrder = request.body.sendInOrder || false;
|
|
||||||
const isEnableOTP = request.body?.enableOTP === true ? true : false;
|
|
||||||
|
|
||||||
// console.log('fileData ', fileData);
|
|
||||||
const protocol = customAPIurl();
|
|
||||||
const baseUrl = new URL(process.env.PUBLIC_URL);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const reqToken = request.headers['x-api-token'];
|
|
||||||
if (!reqToken) {
|
|
||||||
return response.status(400).json({ error: 'Please Provide API Token' });
|
|
||||||
}
|
|
||||||
const tokenQuery = new Parse.Query('appToken');
|
|
||||||
tokenQuery.equalTo('token', reqToken);
|
|
||||||
tokenQuery.include('userId');
|
|
||||||
const token = await tokenQuery.first({ useMasterKey: true });
|
|
||||||
if (token !== undefined) {
|
|
||||||
const parseUser = JSON.parse(JSON.stringify(token));
|
|
||||||
const userPtr = {
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: '_User',
|
|
||||||
objectId: parseUser.userId.objectId,
|
|
||||||
};
|
|
||||||
// Valid Token then proceed request
|
|
||||||
if (signers && signers.length > 0) {
|
|
||||||
let fileUrl;
|
|
||||||
if (request.files?.[0]) {
|
|
||||||
const base64 = fileData?.toString('base64');
|
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
|
||||||
base64: base64,
|
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
|
||||||
fileUrl = file.url();
|
|
||||||
const buffer = Buffer.from(base64, 'base64');
|
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
|
||||||
} else {
|
|
||||||
const file = new Parse.File(`${name}.pdf`, {
|
|
||||||
base64: base64File,
|
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
|
||||||
fileUrl = file.url();
|
|
||||||
const buffer = Buffer.from(base64File, 'base64');
|
|
||||||
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
|
||||||
}
|
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
|
||||||
const extUser = await contractsUser.first({ useMasterKey: true });
|
|
||||||
const extUserPtr = {
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Users',
|
|
||||||
objectId: extUser.id,
|
|
||||||
};
|
|
||||||
|
|
||||||
const folderPtr = {
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Document',
|
|
||||||
objectId: folderId,
|
|
||||||
};
|
|
||||||
|
|
||||||
const object = new Parse.Object('contracts_Document');
|
|
||||||
object.set('Name', name);
|
|
||||||
if (note) {
|
|
||||||
object.set('Note', note);
|
|
||||||
}
|
|
||||||
if (description) {
|
|
||||||
object.set('Description', description);
|
|
||||||
}
|
|
||||||
if (SendinOrder) {
|
|
||||||
object.set('SendinOrder', SendinOrder);
|
|
||||||
}
|
|
||||||
object.set('URL', fileUrl);
|
|
||||||
object.set('CreatedBy', userPtr);
|
|
||||||
object.set('ExtUserPtr', extUserPtr);
|
|
||||||
object.set('IsSendMail', send_email);
|
|
||||||
object.set('IsEnableOTP', isEnableOTP);
|
|
||||||
if (signers && signers.length > 0) {
|
|
||||||
let parseSigners;
|
|
||||||
if (base64File) {
|
|
||||||
parseSigners = signers;
|
|
||||||
} else {
|
|
||||||
parseSigners = JSON.parse(signers);
|
|
||||||
}
|
|
||||||
let createContactUrl = protocol + '/v1/createcontact';
|
|
||||||
|
|
||||||
let contact = [];
|
|
||||||
for (const obj of parseSigners) {
|
|
||||||
const body = {
|
|
||||||
name: obj?.name || '',
|
|
||||||
email: obj?.email || '',
|
|
||||||
phone: obj?.phone || '',
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const res = await axios.post(createContactUrl, body, {
|
|
||||||
headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken },
|
|
||||||
});
|
|
||||||
// console.log('res ', res.data);
|
|
||||||
contact.push({
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Contactbook',
|
|
||||||
objectId: res.data?.objectId,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
// console.log('err ', err.response);
|
|
||||||
if (err?.response?.data?.objectId) {
|
|
||||||
contact.push({
|
|
||||||
__type: 'Pointer',
|
|
||||||
className: 'contracts_Contactbook',
|
|
||||||
objectId: err.response.data?.objectId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object.set('Signers', contact);
|
|
||||||
}
|
|
||||||
if (folderId) {
|
|
||||||
object.set('Folder', folderPtr);
|
|
||||||
}
|
|
||||||
const newACL = new Parse.ACL();
|
|
||||||
newACL.setPublicReadAccess(false);
|
|
||||||
newACL.setPublicWriteAccess(false);
|
|
||||||
newACL.setReadAccess(userPtr.objectId, true);
|
|
||||||
newACL.setWriteAccess(userPtr.objectId, true);
|
|
||||||
object.setACL(newACL);
|
|
||||||
const res = await object.save(null, { useMasterKey: true });
|
|
||||||
if (request.posthog) {
|
|
||||||
request.posthog?.capture({
|
|
||||||
distinctId: parseUser.userId.email,
|
|
||||||
event: 'api_draft_document',
|
|
||||||
properties: { response_code: 200 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return response.json({
|
|
||||||
objectId: res.id,
|
|
||||||
url: `${baseUrl.origin}/placeholdersign/${res.id}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (request.posthog) {
|
|
||||||
request.posthog?.capture({
|
|
||||||
distinctId: parseUser.userId.email,
|
|
||||||
event: 'api_draft_document',
|
|
||||||
properties: { response_code: 400 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return response.status(400).json({ error: 'Please provide signers!' });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return response.status(405).json({ error: 'Invalid API Token!' });
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log('err ', err);
|
|
||||||
return response.status(400).json({ error: 'Something went wrong, please try again later!' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,7 @@ export default async function getDocument(request, response) {
|
|||||||
Document.include('Folder');
|
Document.include('Folder');
|
||||||
Document.include('ExtUserPtr');
|
Document.include('ExtUserPtr');
|
||||||
Document.include('Placeholders.signerPtr');
|
Document.include('Placeholders.signerPtr');
|
||||||
|
Document.include('ExtUserPtr.TenantId');
|
||||||
const res = await Document.first({ useMasterKey: true });
|
const res = await Document.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const document = JSON.parse(JSON.stringify(res));
|
const document = JSON.parse(JSON.stringify(res));
|
||||||
@@ -65,6 +66,7 @@ export default async function getDocument(request, response) {
|
|||||||
enableOTP: document?.IsEnableOTP || false,
|
enableOTP: document?.IsEnableOTP || false,
|
||||||
createdAt: document.createdAt,
|
createdAt: document.createdAt,
|
||||||
updatedAt: document.updatedAt,
|
updatedAt: document.updatedAt,
|
||||||
|
enableTour: document?.IsTourEnabled || false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (request.posthog) {
|
if (request.posthog) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export default async function getDocumentList(request, response) {
|
|||||||
'X-Parse-Application-Id': appId,
|
'X-Parse-Application-Id': appId,
|
||||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||||
};
|
};
|
||||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys},Placeholders&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr`;
|
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys},Placeholders&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr,ExtUserPtr.TenantId`;
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(url, { headers: headers });
|
const res = await axios.get(url, { headers: headers });
|
||||||
if (res.data && res.data.results.length > 0) {
|
if (res.data && res.data.results.length > 0) {
|
||||||
@@ -103,6 +103,7 @@ export default async function getDocumentList(request, response) {
|
|||||||
enableOTP: x?.IsEnableOTP || false,
|
enableOTP: x?.IsEnableOTP || false,
|
||||||
createdAt: x.createdAt,
|
createdAt: x.createdAt,
|
||||||
updatedAt: x.updatedAt,
|
updatedAt: x.updatedAt,
|
||||||
|
enableTour: x?.IsTourEnabled || false,
|
||||||
}));
|
}));
|
||||||
return response.json({ result: updateRes });
|
return response.json({ result: updateRes });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default async function getFolder(request, response) {
|
|||||||
folderCls.notEqualTo('IsArchive', true);
|
folderCls.notEqualTo('IsArchive', true);
|
||||||
folderCls.descending('createdAt');
|
folderCls.descending('createdAt');
|
||||||
folderCls.include('Folder');
|
folderCls.include('Folder');
|
||||||
|
folderCls.include('ExtUserPtr.TenantId');
|
||||||
const res = await folderCls.first({ useMasterKey: true });
|
const res = await folderCls.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const parseRes = JSON.parse(JSON.stringify(res));
|
const parseRes = JSON.parse(JSON.stringify(res));
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export default async function getFolderList(request, response) {
|
|||||||
folderCls.doesNotExist('Folder');
|
folderCls.doesNotExist('Folder');
|
||||||
}
|
}
|
||||||
folderCls.descending('createdAt');
|
folderCls.descending('createdAt');
|
||||||
|
folderCls.include('ExtUserPtr.TenantId');
|
||||||
folderCls.limit(limit);
|
folderCls.limit(limit);
|
||||||
folderCls.skip(skip);
|
folderCls.skip(skip);
|
||||||
const res = await folderCls.find({ useMasterKey: true });
|
const res = await folderCls.find({ useMasterKey: true });
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default async function getTemplate(request, response) {
|
|||||||
Template.include('Folder');
|
Template.include('Folder');
|
||||||
Template.include('ExtUserPtr');
|
Template.include('ExtUserPtr');
|
||||||
Template.include('Placeholders.signerPtr');
|
Template.include('Placeholders.signerPtr');
|
||||||
|
Template.include('ExtUserPtr.TenantId');
|
||||||
const res = await Template.first({ useMasterKey: true });
|
const res = await Template.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const template = JSON.parse(JSON.stringify(res));
|
const template = JSON.parse(JSON.stringify(res));
|
||||||
@@ -64,6 +65,7 @@ export default async function getTemplate(request, response) {
|
|||||||
enableOTP: template?.IsEnableOTP || false,
|
enableOTP: template?.IsEnableOTP || false,
|
||||||
createdAt: template.createdAt,
|
createdAt: template.createdAt,
|
||||||
updatedAt: template.updatedAt,
|
updatedAt: template.updatedAt,
|
||||||
|
enableTour: template?.IsTourEnabled || false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (request.posthog) {
|
if (request.posthog) {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export default async function getTemplatetList(request, response) {
|
|||||||
'X-Parse-Application-Id': appId,
|
'X-Parse-Application-Id': appId,
|
||||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||||
};
|
};
|
||||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr`;
|
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr,ExtUserPtr.TenantId`;
|
||||||
const res = await axios.get(url, { headers: headers });
|
const res = await axios.get(url, { headers: headers });
|
||||||
if (res.data && res.data.results.length > 0) {
|
if (res.data && res.data.results.length > 0) {
|
||||||
if (request.posthog) {
|
if (request.posthog) {
|
||||||
@@ -91,6 +91,7 @@ export default async function getTemplatetList(request, response) {
|
|||||||
enableOTP: template?.IsEnableOTP || false,
|
enableOTP: template?.IsEnableOTP || false,
|
||||||
createdAt: template.createdAt,
|
createdAt: template.createdAt,
|
||||||
updatedAt: template.updatedAt,
|
updatedAt: template.updatedAt,
|
||||||
|
enableTour: template?.IsTourEnabled || false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return response.json({ result: updateRes });
|
return response.json({ result: updateRes });
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default async function resendMail(request, response) {
|
|||||||
docQuery.notEqualTo('IsArchive', true);
|
docQuery.notEqualTo('IsArchive', true);
|
||||||
docQuery.greaterThanOrEqualTo('ExpiryDate', new Date());
|
docQuery.greaterThanOrEqualTo('ExpiryDate', new Date());
|
||||||
docQuery.exists('SignedUrl');
|
docQuery.exists('SignedUrl');
|
||||||
|
docQuery.include('ExtUserPtr.TenantId');
|
||||||
const resDoc = await docQuery.first({ useMasterKey: true });
|
const resDoc = await docQuery.first({ useMasterKey: true });
|
||||||
// console.log("resDoc ",resDoc)
|
// console.log("resDoc ",resDoc)
|
||||||
if (resDoc) {
|
if (resDoc) {
|
||||||
@@ -86,7 +86,7 @@ export default async function resendMail(request, response) {
|
|||||||
orgName +
|
orgName +
|
||||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||||
localExpireDate +
|
localExpireDate +
|
||||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||||
signPdf +
|
signPdf +
|
||||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||||
sender +
|
sender +
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default async function updateDocument(request, response) {
|
|||||||
const token = await tokenQuery.first({ useMasterKey: true });
|
const token = await tokenQuery.first({ useMasterKey: true });
|
||||||
if (token !== undefined) {
|
if (token !== undefined) {
|
||||||
// Valid Token then proceed request
|
// Valid Token then proceed request
|
||||||
const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP'];
|
const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP', 'enableTour'];
|
||||||
const objectKeys = Object.keys(request.body);
|
const objectKeys = Object.keys(request.body);
|
||||||
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
|
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
|
||||||
const parseUser = JSON.parse(JSON.stringify(token));
|
const parseUser = JSON.parse(JSON.stringify(token));
|
||||||
@@ -23,6 +23,7 @@ export default async function updateDocument(request, response) {
|
|||||||
const document = new Parse.Query('contracts_Document');
|
const document = new Parse.Query('contracts_Document');
|
||||||
document.equalTo('objectId', request.params.document_id);
|
document.equalTo('objectId', request.params.document_id);
|
||||||
document.equalTo('CreatedBy', userPtr);
|
document.equalTo('CreatedBy', userPtr);
|
||||||
|
document.include('ExtUserPtr.TenantId');
|
||||||
const res = await document.first({ useMasterKey: true });
|
const res = await document.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const isArchive = res.get('IsArchive');
|
const isArchive = res.get('IsArchive');
|
||||||
@@ -48,10 +49,12 @@ export default async function updateDocument(request, response) {
|
|||||||
objectId: request?.body?.folderId,
|
objectId: request?.body?.folderId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (request.body?.enableOTP !== undefined) {
|
||||||
if (request.body?.enableOTP) {
|
|
||||||
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
|
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
|
||||||
}
|
}
|
||||||
|
if (request.body?.enableTour !== undefined) {
|
||||||
|
updateQuery.set('IsTourEnabled', request.body?.enableTour);
|
||||||
|
}
|
||||||
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
|
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
|
||||||
if (updatedRes) {
|
if (updatedRes) {
|
||||||
if (request.posthog) {
|
if (request.posthog) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default async function updateFolder(request, response) {
|
|||||||
folderCls.equalTo('objectId', folderId);
|
folderCls.equalTo('objectId', folderId);
|
||||||
folderCls.equalTo('Type', 'Folder');
|
folderCls.equalTo('Type', 'Folder');
|
||||||
folderCls.notEqualTo('IsArchive', true);
|
folderCls.notEqualTo('IsArchive', true);
|
||||||
|
folderCls.include('ExtUserPtr.TenantId');
|
||||||
const res = await folderCls.first({ useMasterKey: true });
|
const res = await folderCls.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const updateFolder = new Parse.Object('contracts_Document');
|
const updateFolder = new Parse.Object('contracts_Document');
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default async function updateTemplate(request, response) {
|
|||||||
const token = await tokenQuery.first({ useMasterKey: true });
|
const token = await tokenQuery.first({ useMasterKey: true });
|
||||||
if (token !== undefined) {
|
if (token !== undefined) {
|
||||||
// Valid Token then proceed request
|
// Valid Token then proceed request
|
||||||
const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP'];
|
const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP', 'enableTour'];
|
||||||
const objectKeys = Object.keys(request.body);
|
const objectKeys = Object.keys(request.body);
|
||||||
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
|
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
|
||||||
const parseUser = JSON.parse(JSON.stringify(token));
|
const parseUser = JSON.parse(JSON.stringify(token));
|
||||||
@@ -23,6 +23,7 @@ export default async function updateTemplate(request, response) {
|
|||||||
const template = new Parse.Query('contracts_Template');
|
const template = new Parse.Query('contracts_Template');
|
||||||
template.equalTo('objectId', request.params.template_id);
|
template.equalTo('objectId', request.params.template_id);
|
||||||
template.equalTo('CreatedBy', userPtr);
|
template.equalTo('CreatedBy', userPtr);
|
||||||
|
template.include('ExtUserPtr.TenantId');
|
||||||
const res = await template.first({ useMasterKey: true });
|
const res = await template.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const isArchive = res.get('IsArchive');
|
const isArchive = res.get('IsArchive');
|
||||||
@@ -48,9 +49,12 @@ export default async function updateTemplate(request, response) {
|
|||||||
objectId: request?.body?.folderId,
|
objectId: request?.body?.folderId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (request.body?.enableOTP) {
|
if (request.body?.enableOTP !== undefined) {
|
||||||
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
|
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
|
||||||
}
|
}
|
||||||
|
if (request.body?.enableTour !== undefined) {
|
||||||
|
updateQuery.set('IsTourEnabled', request.body?.enableTour);
|
||||||
|
}
|
||||||
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
|
const updatedRes = await updateQuery.save(null, { useMasterKey: true });
|
||||||
if (updatedRes) {
|
if (updatedRes) {
|
||||||
if (request.posthog) {
|
if (request.posthog) {
|
||||||
|
|||||||
@@ -70,6 +70,21 @@ import updateContactTour from './parsefunction/updateContactTour.js';
|
|||||||
import declinedocument from './parsefunction/declinedocument.js';
|
import declinedocument from './parsefunction/declinedocument.js';
|
||||||
import addcustomsmtp from './parsefunction/addcustomsmtp.js';
|
import addcustomsmtp from './parsefunction/addcustomsmtp.js';
|
||||||
import deactivateMailAdapter from './parsefunction/deactivateMailAdapter.js';
|
import deactivateMailAdapter from './parsefunction/deactivateMailAdapter.js';
|
||||||
|
import addFileAdapter from './parsefunction/addFileAdapter.js';
|
||||||
|
import saveToFileAdapter from './parsefunction/saveToFileAdapter.js';
|
||||||
|
import getFileAdapter from './parsefunction/getFileAdapter.js';
|
||||||
|
import addPfxFile from './parsefunction/addPfxFile.js';
|
||||||
|
import getPfxFile from './parsefunction/getPfxFile.js';
|
||||||
|
import getTenant from './parsefunction/getTenant.js';
|
||||||
|
import getSigners from './parsefunction/getSigners.js';
|
||||||
|
import saveFile from './parsefunction/saveFile.js';
|
||||||
|
import savecontact from './parsefunction/savecontact.js';
|
||||||
|
import isUserInContactBook from './parsefunction/isUserInContactBook.js';
|
||||||
|
import updateTourStatus from './parsefunction/updateTourStatus.js';
|
||||||
|
import saveTemplate from './parsefunction/saveTemplate.js';
|
||||||
|
import updateToPublicTemplate from './parsefunction/updateToPublicTemplate.js';
|
||||||
|
import updateSignatureType from './parsefunction/updatesignaturetype.js';
|
||||||
|
import updatePreferences from './parsefunction/updatePreferences.js';
|
||||||
|
|
||||||
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
|
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
|
||||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||||
@@ -152,3 +167,18 @@ Parse.Cloud.define('updatecontacttour', updateContactTour);
|
|||||||
Parse.Cloud.define('declinedoc', declinedocument);
|
Parse.Cloud.define('declinedoc', declinedocument);
|
||||||
Parse.Cloud.define('addsmtp', addcustomsmtp);
|
Parse.Cloud.define('addsmtp', addcustomsmtp);
|
||||||
Parse.Cloud.define('deactivatemailadapter', deactivateMailAdapter);
|
Parse.Cloud.define('deactivatemailadapter', deactivateMailAdapter);
|
||||||
|
Parse.Cloud.define('savetofileadapter', saveToFileAdapter);
|
||||||
|
Parse.Cloud.define('addfileadapter', addFileAdapter);
|
||||||
|
Parse.Cloud.define('getfileadapter', getFileAdapter);
|
||||||
|
Parse.Cloud.define('addpfx', addPfxFile);
|
||||||
|
Parse.Cloud.define('getpfx', getPfxFile);
|
||||||
|
Parse.Cloud.define('gettenant', getTenant);
|
||||||
|
Parse.Cloud.define('getsigners', getSigners);
|
||||||
|
Parse.Cloud.define('savetemplate', saveTemplate);
|
||||||
|
Parse.Cloud.define('savefile', saveFile);
|
||||||
|
Parse.Cloud.define('savecontact', savecontact);
|
||||||
|
Parse.Cloud.define('isuserincontactbook', isUserInContactBook);
|
||||||
|
Parse.Cloud.define('updatetourstatus', updateTourStatus);
|
||||||
|
Parse.Cloud.define('updatetopublictemplate', updateToPublicTemplate);
|
||||||
|
Parse.Cloud.define('updatesignaturetype', updateSignatureType);
|
||||||
|
Parse.Cloud.define('updatepreferences', updatePreferences);
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
export default async function AllowedCredits(request) {
|
import { parseJwt } from '../../Utils.js';
|
||||||
if (!request?.user) {
|
import jwt from 'jsonwebtoken';
|
||||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
async function checkCredits(userId) {
|
||||||
}
|
|
||||||
try {
|
|
||||||
const extUser = new Parse.Query('contracts_Users');
|
const extUser = new Parse.Query('contracts_Users');
|
||||||
extUser.equalTo('UserId', {
|
extUser.equalTo('UserId', {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className: '_User',
|
className: '_User',
|
||||||
objectId: request.user.id,
|
objectId: userId,
|
||||||
});
|
});
|
||||||
const resExtUser = await extUser.first({ useMasterKey: true });
|
const resExtUser = await extUser.first({ useMasterKey: true });
|
||||||
if (resExtUser) {
|
if (resExtUser) {
|
||||||
@@ -29,6 +27,39 @@ export default async function AllowedCredits(request) {
|
|||||||
} else {
|
} else {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
export default async function AllowedCredits(request) {
|
||||||
|
const jwttoken = request?.headers?.jwttoken || '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (request?.user) {
|
||||||
|
return await checkCredits(request.user.id);
|
||||||
|
} else if (jwttoken) {
|
||||||
|
const jwtDecode = parseJwt(jwttoken);
|
||||||
|
if (jwtDecode?.user_email) {
|
||||||
|
const userCls = new Parse.Query(Parse.User);
|
||||||
|
userCls.equalTo('email', jwtDecode?.user_email);
|
||||||
|
const userRes = await userCls.first({ useMasterKey: true });
|
||||||
|
const userId = userRes?.id;
|
||||||
|
const tokenQuery = new Parse.Query('appToken');
|
||||||
|
tokenQuery.equalTo('userId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: userId,
|
||||||
|
});
|
||||||
|
const appRes = await tokenQuery.first({ useMasterKey: true });
|
||||||
|
const decoded = jwt.verify(jwttoken, appRes?.get('token'));
|
||||||
|
if (decoded?.user_email) {
|
||||||
|
return await checkCredits(userId);
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid token.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid token.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('err in allowedCredits', err);
|
console.log('err in allowedCredits', err);
|
||||||
const code = err?.code || 400;
|
const code = err?.code || 400;
|
||||||
|
|||||||
@@ -2,21 +2,30 @@ import { useLocal } from '../../Utils.js';
|
|||||||
import getPresignedUrl from './getSignedUrl.js';
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
async function DocumentAfterFind(request) {
|
async function DocumentAfterFind(request) {
|
||||||
if (useLocal !== 'true') {
|
|
||||||
if (request.objects.length === 1) {
|
if (request.objects.length === 1) {
|
||||||
if (request.objects) {
|
if (request.objects) {
|
||||||
const obj = request.objects[0];
|
const obj = request.objects[0];
|
||||||
|
const FileAdapterId = obj?.get('FileAdapterId') || '';
|
||||||
|
if (FileAdapterId || useLocal !== 'true') {
|
||||||
const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl');
|
const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl');
|
||||||
const Url = obj?.get('URL') && obj?.get('URL');
|
const Url = obj?.get('URL') && obj?.get('URL');
|
||||||
const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl');
|
const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl');
|
||||||
|
let fileAdapter = {};
|
||||||
|
if (FileAdapterId) {
|
||||||
|
const tenantId = obj?.get('ExtUserPtr')?.get('TenantId');
|
||||||
|
if (tenantId) {
|
||||||
|
const _tenantId = JSON.parse(JSON.stringify(obj?.get('ExtUserPtr')?.get('TenantId')));
|
||||||
|
fileAdapter = _tenantId?.FileAdapters?.find(x => x.id === FileAdapterId) || {};
|
||||||
|
}
|
||||||
|
}
|
||||||
if (SignedUrl) {
|
if (SignedUrl) {
|
||||||
obj.set('SignedUrl', getPresignedUrl(SignedUrl));
|
obj.set('SignedUrl', getPresignedUrl(SignedUrl, fileAdapter));
|
||||||
}
|
}
|
||||||
if (Url) {
|
if (Url) {
|
||||||
obj.set('URL', getPresignedUrl(Url));
|
obj.set('URL', getPresignedUrl(Url, fileAdapter));
|
||||||
}
|
}
|
||||||
if (certificateUrl) {
|
if (certificateUrl) {
|
||||||
obj.set('CertificateUrl', getPresignedUrl(certificateUrl));
|
obj.set('CertificateUrl', getPresignedUrl(certificateUrl, fileAdapter));
|
||||||
}
|
}
|
||||||
return [obj];
|
return [obj];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ async function DocumentAftersave(request) {
|
|||||||
const ExpiryDate = new Date(createdAt);
|
const ExpiryDate = new Date(createdAt);
|
||||||
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
||||||
const documentQuery = new Parse.Query('contracts_Document');
|
const documentQuery = new Parse.Query('contracts_Document');
|
||||||
|
documentQuery.include('ExtUserPtr.TenantId');
|
||||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||||
if (!originIp) {
|
if (!originIp) {
|
||||||
@@ -30,6 +31,7 @@ async function DocumentAftersave(request) {
|
|||||||
const ExpiryDate = new Date(createdAt);
|
const ExpiryDate = new Date(createdAt);
|
||||||
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
||||||
const documentQuery = new Parse.Query('contracts_Document');
|
const documentQuery = new Parse.Query('contracts_Document');
|
||||||
|
documentQuery.include('ExtUserPtr.TenantId');
|
||||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||||
if (!originIp) {
|
if (!originIp) {
|
||||||
@@ -76,6 +78,7 @@ async function DocumentAftersave(request) {
|
|||||||
// console.log(objId)
|
// console.log(objId)
|
||||||
const Query = new Parse.Query('contracts_Document');
|
const Query = new Parse.Query('contracts_Document');
|
||||||
Query.include('Signers');
|
Query.include('Signers');
|
||||||
|
Query.include('ExtUserPtr.TenantId');
|
||||||
Query.include('CreatedBy');
|
Query.include('CreatedBy');
|
||||||
const updateACL = await Query.get(objId, { useMasterKey: true });
|
const updateACL = await Query.get(objId, { useMasterKey: true });
|
||||||
const res = JSON.parse(JSON.stringify(updateACL));
|
const res = JSON.parse(JSON.stringify(updateACL));
|
||||||
@@ -116,6 +119,7 @@ async function DocumentAftersave(request) {
|
|||||||
// console.log(objId)
|
// console.log(objId)
|
||||||
const Query = new Parse.Query('contracts_Document');
|
const Query = new Parse.Query('contracts_Document');
|
||||||
Query.include('CreatedBy');
|
Query.include('CreatedBy');
|
||||||
|
Query.include('ExtUserPtr.TenantId');
|
||||||
const updateACL = await Query.get(objId, { useMasterKey: true });
|
const updateACL = await Query.get(objId, { useMasterKey: true });
|
||||||
const res = JSON.parse(JSON.stringify(updateACL));
|
const res = JSON.parse(JSON.stringify(updateACL));
|
||||||
// console.log("res");
|
// console.log("res");
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ async function GetPublicTemplate(request) {
|
|||||||
templatQuery.descending('updatedAt');
|
templatQuery.descending('updatedAt');
|
||||||
templatQuery.equalTo('IsPublic', true);
|
templatQuery.equalTo('IsPublic', true);
|
||||||
templatQuery.notEqualTo('IsArchive', true);
|
templatQuery.notEqualTo('IsArchive', true);
|
||||||
|
templatQuery.include('ExtUserPtr.TenantId');
|
||||||
const getTemplate = await templatQuery.find({ useMasterKey: true });
|
const getTemplate = await templatQuery.find({ useMasterKey: true });
|
||||||
const extcls = new Parse.Query('contracts_Users');
|
const extcls = new Parse.Query('contracts_Users');
|
||||||
extcls.equalTo('Email', user.get('email'));
|
extcls.equalTo('Email', user.get('email'));
|
||||||
|
|||||||
@@ -1,30 +1,63 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { cloudServerUrl } from '../../Utils.js';
|
import { cloudServerUrl, parseJwt } from '../../Utils.js';
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
export default async function GetTemplate(request) {
|
export default async function GetTemplate(request) {
|
||||||
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
||||||
const templateId = request.params.templateId;
|
const templateId = request.params.templateId;
|
||||||
const ispublic = request.params.ispublic;
|
const ispublic = request.params.ispublic;
|
||||||
|
const jwttoken = request.headers?.jwttoken;
|
||||||
|
const sessiontoken = request.headers?.sessiontoken;
|
||||||
try {
|
try {
|
||||||
if (!ispublic) {
|
if (!ispublic) {
|
||||||
|
let userEmail;
|
||||||
|
if (jwttoken) {
|
||||||
|
try {
|
||||||
|
const jwtDecode = parseJwt(jwttoken);
|
||||||
|
if (jwtDecode?.user_email) {
|
||||||
|
const userCls = new Parse.Query(Parse.User);
|
||||||
|
userCls.equalTo('email', jwtDecode?.user_email);
|
||||||
|
const userRes = await userCls.first({ useMasterKey: true });
|
||||||
|
const userId = userRes?.id;
|
||||||
|
const tokenQuery = new Parse.Query('appToken');
|
||||||
|
tokenQuery.equalTo('userId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: userId,
|
||||||
|
});
|
||||||
|
const appRes = await tokenQuery.first({ useMasterKey: true });
|
||||||
|
const decoded = jwt.verify(jwttoken, appRes?.get('token'));
|
||||||
|
if (decoded?.user_email) {
|
||||||
|
userEmail = decoded?.user_email;
|
||||||
|
} else {
|
||||||
|
return { error: 'Invalid token!' };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { error: 'Invalid token!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in jwt', err);
|
||||||
|
return { error: "You don't have access of this document!" };
|
||||||
|
}
|
||||||
|
} else if (sessiontoken) {
|
||||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': process.env.APP_ID,
|
'X-Parse-Application-Id': process.env.APP_ID,
|
||||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
'X-Parse-Session-Token': sessiontoken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const userId = userRes.data && userRes.data.objectId;
|
userEmail = userRes.data && userRes.data.email;
|
||||||
if (templateId && userId) {
|
}
|
||||||
|
if (templateId && userEmail) {
|
||||||
try {
|
try {
|
||||||
let template = new Parse.Query('contracts_Template');
|
let template = new Parse.Query('contracts_Template');
|
||||||
template.equalTo('objectId', templateId);
|
template.equalTo('objectId', templateId);
|
||||||
template.include('ExtUserPtr');
|
template.include('ExtUserPtr');
|
||||||
template.include('Signers');
|
template.include('Signers');
|
||||||
template.include('CreatedBy');
|
template.include('CreatedBy');
|
||||||
|
template.include('ExtUserPtr.TenantId');
|
||||||
const extUserQuery = new Parse.Query('contracts_Users');
|
const extUserQuery = new Parse.Query('contracts_Users');
|
||||||
extUserQuery.equalTo('Email', userRes.data.email);
|
extUserQuery.equalTo('Email', userEmail);
|
||||||
extUserQuery.include('TeamIds');
|
extUserQuery.include('TeamIds');
|
||||||
const extUser = await extUserQuery.first({ useMasterKey: true });
|
const extUser = await extUserQuery.first({ useMasterKey: true });
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
@@ -48,12 +81,16 @@ export default async function GetTemplate(request) {
|
|||||||
template.include('ExtUserPtr');
|
template.include('ExtUserPtr');
|
||||||
template.include('Signers');
|
template.include('Signers');
|
||||||
template.include('CreatedBy');
|
template.include('CreatedBy');
|
||||||
|
template.include('ExtUserPtr.TenantId');
|
||||||
|
template.include('Placeholders.signerPtr');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const res = await template.first({ useMasterKey: true });
|
const res = await template.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
// console.log("res ",res)
|
const templateRes = JSON.parse(JSON.stringify(res));
|
||||||
return res;
|
delete templateRes?.ExtUserPtr?.TenantId?.FileAdapters;
|
||||||
|
delete templateRes?.ExtUserPtr?.TenantId?.PfxFile;
|
||||||
|
return templateRes;
|
||||||
} else {
|
} else {
|
||||||
return { error: "You don't have access of this document!" };
|
return { error: "You don't have access of this document!" };
|
||||||
}
|
}
|
||||||
@@ -61,6 +98,8 @@ export default async function GetTemplate(request) {
|
|||||||
console.log('err', err);
|
console.log('err', err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return { error: "You don't have access of this document!" };
|
||||||
}
|
}
|
||||||
} else if (templateId && ispublic) {
|
} else if (templateId && ispublic) {
|
||||||
try {
|
try {
|
||||||
@@ -69,10 +108,14 @@ export default async function GetTemplate(request) {
|
|||||||
template.include('ExtUserPtr');
|
template.include('ExtUserPtr');
|
||||||
template.include('Signers');
|
template.include('Signers');
|
||||||
template.include('CreatedBy');
|
template.include('CreatedBy');
|
||||||
|
template.include('ExtUserPtr.TenantId');
|
||||||
const res = await template.first({ useMasterKey: true });
|
const res = await template.first({ useMasterKey: true });
|
||||||
// console.log("res ", res)
|
// console.log("res ", res)
|
||||||
if (res) {
|
if (res) {
|
||||||
return res;
|
const templateRes = JSON.parse(JSON.stringify(res));
|
||||||
|
delete templateRes?.ExtUserPtr?.TenantId?.FileAdapters;
|
||||||
|
delete templateRes?.ExtUserPtr?.TenantId?.PfxFile;
|
||||||
|
return templateRes;
|
||||||
} else {
|
} else {
|
||||||
return { error: "You don't have access of this document!" };
|
return { error: "You don't have access of this document!" };
|
||||||
}
|
}
|
||||||
@@ -85,7 +128,7 @@ export default async function GetTemplate(request) {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('err', err);
|
console.log('err', err);
|
||||||
if (err.code == 209) {
|
if (err?.response?.data?.code === 209 || err.code == 209) {
|
||||||
return { error: 'Invalid session token' };
|
return { error: 'Invalid session token' };
|
||||||
} else {
|
} else {
|
||||||
return { error: "You don't have access of this document!" };
|
return { error: "You don't have access of this document!" };
|
||||||
|
|||||||
@@ -31,7 +31,13 @@ const saveRoleContact = async contact => {
|
|||||||
contactQuery.set('CreatedBy', contact.CreatedBy);
|
contactQuery.set('CreatedBy', contact.CreatedBy);
|
||||||
contactQuery.set('UserId', contact.UserId);
|
contactQuery.set('UserId', contact.UserId);
|
||||||
contactQuery.set('UserRole', 'contracts_Guest');
|
contactQuery.set('UserRole', 'contracts_Guest');
|
||||||
contactQuery.set('TenantId', contact.TenantId);
|
if (contact?.TenantId) {
|
||||||
|
contactQuery.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: contact.TenantId,
|
||||||
|
});
|
||||||
|
}
|
||||||
contactQuery.set('IsDeleted', false);
|
contactQuery.set('IsDeleted', false);
|
||||||
const acl = new Parse.ACL();
|
const acl = new Parse.ACL();
|
||||||
acl.setReadAccess(contact.CreatedBy.objectId, true);
|
acl.setReadAccess(contact.CreatedBy.objectId, true);
|
||||||
@@ -55,7 +61,7 @@ const createDocumentFromTemplate = async (template, existContact, index) => {
|
|||||||
object.set('Description', template?.Description);
|
object.set('Description', template?.Description);
|
||||||
object.set('Note', template?.Note);
|
object.set('Note', template?.Note);
|
||||||
object.set('TimeToCompleteDays', template?.TimeToCompleteDays || 15);
|
object.set('TimeToCompleteDays', template?.TimeToCompleteDays || 15);
|
||||||
object.set('SendinOrder', template?.SendinOrder);
|
object.set('SendinOrder', template?.SendinOrder || false);
|
||||||
object.set('AutomaticReminders', template?.AutomaticReminders || false);
|
object.set('AutomaticReminders', template?.AutomaticReminders || false);
|
||||||
object.set('RemindOnceInEvery', template?.RemindOnceInEvery || 5);
|
object.set('RemindOnceInEvery', template?.RemindOnceInEvery || 5);
|
||||||
object.set('URL', template?.URL);
|
object.set('URL', template?.URL);
|
||||||
@@ -63,6 +69,14 @@ const createDocumentFromTemplate = async (template, existContact, index) => {
|
|||||||
object.set('ExtUserPtr', template?.ExtUserPtr);
|
object.set('ExtUserPtr', template?.ExtUserPtr);
|
||||||
object.set('OriginIp', template?.OriginIp || '');
|
object.set('OriginIp', template?.OriginIp || '');
|
||||||
object.set('IsEnableOTP', template?.IsEnableOTP || false);
|
object.set('IsEnableOTP', template?.IsEnableOTP || false);
|
||||||
|
object.set('IsTourEnabled', template?.IsTourEnabled || false);
|
||||||
|
object.set('FileAdapterId', template?.FileAdapterId || '');
|
||||||
|
if (template?.SignatureType?.length > 0) {
|
||||||
|
object.set('SignatureType', template?.SignatureType);
|
||||||
|
}
|
||||||
|
if (template?.NotifyOnSignatures) {
|
||||||
|
object.set('NotifyOnSignatures', template?.NotifyOnSignatures);
|
||||||
|
}
|
||||||
let signers = template?.Signers || [];
|
let signers = template?.Signers || [];
|
||||||
const signerobj = {
|
const signerobj = {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
@@ -97,7 +111,7 @@ const sendMailToAllSigners = async docId => {
|
|||||||
try {
|
try {
|
||||||
//get document details that recenlty created from public template
|
//get document details that recenlty created from public template
|
||||||
const docQuery = new Parse.Query('contracts_Document');
|
const docQuery = new Parse.Query('contracts_Document');
|
||||||
docQuery.include('ExtUserPtr');
|
docQuery.include('ExtUserPtr,ExtUserPtr.TenantId');
|
||||||
docQuery.include('Signers');
|
docQuery.include('Signers');
|
||||||
const docRes = await docQuery.get(docId, { useMasterKey: true });
|
const docRes = await docQuery.get(docId, { useMasterKey: true });
|
||||||
const Doc = JSON.parse(JSON.stringify(docRes));
|
const Doc = JSON.parse(JSON.stringify(docRes));
|
||||||
@@ -168,7 +182,7 @@ const sendMailToAllSigners = async docId => {
|
|||||||
receiver_phone: signerMail[i]?.Phone || '',
|
receiver_phone: signerMail[i]?.Phone || '',
|
||||||
expiry_date: localExpireDate,
|
expiry_date: localExpireDate,
|
||||||
company_name: orgName,
|
company_name: orgName,
|
||||||
signing_url: `<a href=${signPdf}>Sign here</a>`,
|
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`,
|
||||||
};
|
};
|
||||||
replaceVar = replaceMailVaribles(requestSubject, htmlReqBody, variables);
|
replaceVar = replaceMailVaribles(requestSubject, htmlReqBody, variables);
|
||||||
}
|
}
|
||||||
@@ -246,6 +260,7 @@ const deductcount = async _resSub => {
|
|||||||
export default async function PublicUserLinkContactToDoc(req) {
|
export default async function PublicUserLinkContactToDoc(req) {
|
||||||
const email = req.params.email;
|
const email = req.params.email;
|
||||||
const templateid = req.params.templateid;
|
const templateid = req.params.templateid;
|
||||||
|
const signatureType = req.params.signatureType;
|
||||||
const name = req.params.name;
|
const name = req.params.name;
|
||||||
const phone = req.params.phone;
|
const phone = req.params.phone;
|
||||||
const role = req.params.role;
|
const role = req.params.role;
|
||||||
@@ -254,6 +269,7 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
// Execute the query to get the template with the specified 'templateid'
|
// Execute the query to get the template with the specified 'templateid'
|
||||||
const docQuery = new Parse.Query('contracts_Template');
|
const docQuery = new Parse.Query('contracts_Template');
|
||||||
docQuery.include('ExtUserPtr');
|
docQuery.include('ExtUserPtr');
|
||||||
|
docQuery.include('ExtUserPtr.TenantId');
|
||||||
const tempRes = await docQuery.get(templateid, { useMasterKey: true });
|
const tempRes = await docQuery.get(templateid, { useMasterKey: true });
|
||||||
// Check if the template was found; if not, throw an error indicating the template was not found
|
// Check if the template was found; if not, throw an error indicating the template was not found
|
||||||
if (!tempRes) {
|
if (!tempRes) {
|
||||||
@@ -292,8 +308,11 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
const existContact = await contactCls.first({ useMasterKey: true });
|
const existContact = await contactCls.first({ useMasterKey: true });
|
||||||
if (existContact) {
|
if (existContact) {
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
const _template_json = template_json;
|
||||||
|
_template_json.SignatureType =
|
||||||
|
signatureType?.length > 0 ? signatureType : _template_json?.SignatureType;
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
const docRes = await createDocumentFromTemplate(template_json, existContact, index);
|
const docRes = await createDocumentFromTemplate(_template_json, existContact, index);
|
||||||
if (docRes) {
|
if (docRes) {
|
||||||
await deductcount(_resSub);
|
await deductcount(_resSub);
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
@@ -315,12 +334,15 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
Email: email,
|
Email: email,
|
||||||
Phone: _extUser?.Phone ? _extUser.Phone : '',
|
Phone: _extUser?.Phone ? _extUser.Phone : '',
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
TenantId: _tempRes.ExtUserPtr?.TenantId?.objectId,
|
||||||
};
|
};
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
const _template_json = template_json;
|
||||||
|
_template_json.SignatureType =
|
||||||
|
signatureType?.length > 0 ? signatureType : _template_json?.SignatureType;
|
||||||
// if user present on platform create contact on the basis of extended user details
|
// if user present on platform create contact on the basis of extended user details
|
||||||
const contactRes = await saveRoleContact(contact);
|
const contactRes = await saveRoleContact(contact);
|
||||||
const docRes = await createDocumentFromTemplate(template_json, contactRes, index);
|
const docRes = await createDocumentFromTemplate(_template_json, contactRes, index);
|
||||||
if (docRes) {
|
if (docRes) {
|
||||||
await deductcount(_resSub);
|
await deductcount(_resSub);
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
@@ -342,14 +364,17 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
Email: email,
|
Email: email,
|
||||||
Phone: phone,
|
Phone: phone,
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
TenantId: _tempRes.ExtUserPtr?.TenantId?.objectId,
|
||||||
};
|
};
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
const _template_json = template_json;
|
||||||
|
_template_json.SignatureType =
|
||||||
|
signatureType?.length > 0 ? signatureType : _template_json?.SignatureType;
|
||||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||||
const contactRes = await saveRoleContact(contact);
|
const contactRes = await saveRoleContact(contact);
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
const docRes = await createDocumentFromTemplate(
|
const docRes = await createDocumentFromTemplate(
|
||||||
template_json,
|
_template_json,
|
||||||
contactRes,
|
contactRes,
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
@@ -379,14 +404,17 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
Email: email,
|
Email: email,
|
||||||
Phone: phone,
|
Phone: phone,
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
TenantId: _tempRes.ExtUserPtr?.TenantId?.objectId,
|
||||||
};
|
};
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
const _template_json = template_json;
|
||||||
|
_template_json.SignatureType =
|
||||||
|
signatureType?.length > 0 ? signatureType : _template_json?.SignatureType;
|
||||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||||
const contactRes = await saveRoleContact(contact);
|
const contactRes = await saveRoleContact(contact);
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
const docRes = await createDocumentFromTemplate(
|
const docRes = await createDocumentFromTemplate(
|
||||||
template_json,
|
_template_json,
|
||||||
contactRes,
|
contactRes,
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user