mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-04 16:58:05 +02:00
Compare commits
627
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
eda6113792 | ||
|
|
4f1509c836 | ||
|
|
dfcf32ef3e | ||
|
|
4a95257ee2 | ||
|
|
ee1e13ef61 | ||
|
|
c9c099ffc5 | ||
|
|
a80f4fb3c9 | ||
|
|
941f3ac47f | ||
|
|
80d3200d57 | ||
|
|
55926e25d2 | ||
|
|
a31f3ebad7 | ||
|
|
dc9c32c6ee | ||
|
|
dac3aac2a1 | ||
|
|
40196e823c | ||
|
|
7708b7e938 | ||
|
|
8bbc5a9bc6 | ||
|
|
4dbdfb1b77 | ||
|
|
05c51edce3 | ||
|
|
379e8cd95e | ||
|
|
9fd00d4427 | ||
|
|
ca114cf124 | ||
|
|
75128784db | ||
|
|
722f0e277e | ||
|
|
7089998966 | ||
|
|
52211ddfa4 | ||
|
|
2b8b762d35 | ||
|
|
04c228cd36 | ||
|
|
915f8e7700 | ||
|
|
218cea00b5 | ||
|
|
f38f5ea670 | ||
|
|
a9c08c8a9f | ||
|
|
9406c4f718 | ||
|
|
791d8beb06 | ||
|
|
57a9f3aca0 | ||
|
|
ae8bf187c8 | ||
|
|
88f2ab1f8e | ||
|
|
76f5136073 | ||
|
|
0f84cd8949 | ||
|
|
adfdf7606f | ||
|
|
ce671d4294 | ||
|
|
2e7cf7a9df | ||
|
|
f699d93e44 | ||
|
|
531ef4d0b2 | ||
|
|
4c6dbb6690 | ||
|
|
0beb60d1b5 | ||
|
|
893c9d7c42 | ||
|
|
b7a22d94db | ||
|
|
3d854756d1 | ||
|
|
251e7058f1 | ||
|
|
368eb24217 | ||
|
|
f89ef54b82 | ||
|
|
b9d9f8772b | ||
|
|
f2ee03e850 | ||
|
|
92e59a0072 | ||
|
|
5394c0b520 | ||
|
|
e4a9c6f8c2 | ||
|
|
e559d037c3 | ||
|
|
c9909a0869 | ||
|
|
988fc1bbfd | ||
|
|
1831bbcd70 | ||
|
|
ced9bbdbd5 | ||
|
|
15d57d937b | ||
|
|
555979869d | ||
|
|
4e6477297e | ||
|
|
e9e06fc53b | ||
|
|
ecb2818589 | ||
|
|
c442689573 | ||
|
|
88919f2634 | ||
|
|
1a1bc41283 | ||
|
|
4188caed33 | ||
|
|
50557d8bc5 | ||
|
|
0f1ef0406e | ||
|
|
ffc742b460 | ||
|
|
0c04cc6ce6 | ||
|
|
4e6dfed838 | ||
|
|
fdc0524ad2 | ||
|
|
096d5962a3 | ||
|
|
9ea36f94a7 | ||
|
|
2b66df992f | ||
|
|
ff3c31975e | ||
|
|
beaa5eca69 | ||
|
|
b98040faac | ||
|
|
fbbff0df61 | ||
|
|
07d5f393c0 | ||
|
|
8220b15a29 | ||
|
|
7cf638b2be | ||
|
|
9852c87be7 | ||
|
|
30fb8f31e3 | ||
|
|
ec4d875547 | ||
|
|
1268f65516 | ||
|
|
6551b2537a | ||
|
|
43eee63df2 | ||
|
|
4caf9f598a | ||
|
|
107eaca8f0 | ||
|
|
cc11848346 | ||
|
|
b138ccf625 | ||
|
|
27ff7baa6d | ||
|
|
c8ecd34bd3 | ||
|
|
d4a4eb3248 | ||
|
|
f782733397 | ||
|
|
7720eddc47 | ||
|
|
71170a373a | ||
|
|
8f080080a7 | ||
|
|
71b2958c14 | ||
|
|
f69aafcbfa | ||
|
|
5f6a423697 | ||
|
|
5d245927c4 | ||
|
|
17c96fb849 | ||
|
|
b7c28cdf36 | ||
|
|
d05aa0d350 | ||
|
|
875dc086bf | ||
|
|
4719ebd52a | ||
|
|
c8a436a7df | ||
|
|
8d6f4dd64e | ||
|
|
63486927d6 | ||
|
|
c36a70f8d3 | ||
|
|
39472d6874 | ||
|
|
6207e99cc0 | ||
|
|
bdc163199d | ||
|
|
e7a04ede65 | ||
|
|
f6aee4148d | ||
|
|
6cb30a6597 | ||
|
|
34fcfc8f30 | ||
|
|
bc89b33468 | ||
|
|
af9af347e6 | ||
|
|
6f46279b52 | ||
|
|
8f93ed8b8e | ||
|
|
df91363ff4 | ||
|
|
e40e59714d | ||
|
|
a43d95afc3 | ||
|
|
8fa4b5ab22 | ||
|
|
68a030145f | ||
|
|
4f48657623 | ||
|
|
3fc41f4255 | ||
|
|
ff2f7f6586 | ||
|
|
93f33d73d9 | ||
|
|
402c176277 | ||
|
|
79b05b4a66 | ||
|
|
fb9e37e71c | ||
|
|
cd7a741d53 | ||
|
|
5fdc90b4f9 | ||
|
|
e775840abb | ||
|
|
d7df54dfa1 | ||
|
|
646d165d37 | ||
|
|
ba0a80cca4 | ||
|
|
9d59858542 | ||
|
|
aaff0a5697 | ||
|
|
1bb7cee238 | ||
|
|
d330e662d3 | ||
|
|
b530ff76c4 | ||
|
|
b20aa33a04 | ||
|
|
e59a166445 | ||
|
|
980e713735 | ||
|
|
7a5228bbab | ||
|
|
5a26e5c2ee | ||
|
|
a64da4cd85 | ||
|
|
c2dccf17ce | ||
|
|
181d6bf1e4 | ||
|
|
e80bcfc586 | ||
|
|
a07be3b5dc | ||
|
|
af2666c83d | ||
|
|
cad9929b56 | ||
|
|
3b79da527d | ||
|
|
3eaba55823 | ||
|
|
e2eddb6362 | ||
|
|
de5b8160a2 | ||
|
|
83df969751 | ||
|
|
d885570dd8 | ||
|
|
f3de883e39 | ||
|
|
6da22d23a8 | ||
|
|
49461a43bb | ||
|
|
d4414f99af | ||
|
|
52f37b0a37 | ||
|
|
ce949e4029 | ||
|
|
19d3465a13 | ||
|
|
a0e1425c74 | ||
|
|
a5d8379b18 | ||
|
|
9ac487ea5b | ||
|
|
9cc9a93c3d | ||
|
|
4f2b0313de | ||
|
|
806894b24b | ||
|
|
cbb737f96b | ||
|
|
5407f8156a | ||
|
|
a0c2fd09ae | ||
|
|
48b744c8ba | ||
|
|
812b946d85 | ||
|
|
27eca2b470 | ||
|
|
ab6c88bebd | ||
|
|
d547e0552a | ||
|
|
03fc0b84cb | ||
|
|
b0825634ee | ||
|
|
9675e051bd | ||
|
|
981654a2aa | ||
|
|
8c97ea0da0 | ||
|
|
6c80911c90 | ||
|
|
740b5ea719 | ||
|
|
76c958fb7a | ||
|
|
28c53fd115 | ||
|
|
6d9fc8b3df | ||
|
|
a044f4eceb | ||
|
|
1f35efcd51 | ||
|
|
c587abddae | ||
|
|
d7f4c9a329 | ||
|
|
8a3e6f5781 | ||
|
|
cfbebc4989 | ||
|
|
99ec772d64 | ||
|
|
1f60b0bbcb | ||
|
|
c8fb9a5b09 | ||
|
|
d6f117c7bf | ||
|
|
a765668354 | ||
|
|
da053658e8 | ||
|
|
cb5bcd72e4 | ||
|
|
d4d53623ef | ||
|
|
8a31b008d2 | ||
|
|
fa4541b59f | ||
|
|
aae6b32828 | ||
|
|
7158d6735b | ||
|
|
f04fd16c9e | ||
|
|
f4b896d5e6 | ||
|
|
d2f814e6f8 | ||
|
|
87cec67e60 | ||
|
|
041c46f38e | ||
|
|
54a7628f75 | ||
|
|
7cbbc16390 | ||
|
|
14532bf6db | ||
|
|
7bfe18e718 | ||
|
|
07903a07a8 | ||
|
|
14fe3b2b98 | ||
|
|
fa2756ff3f | ||
|
|
9d4841b4dc | ||
|
|
4b74b08825 | ||
|
|
6457cfc958 | ||
|
|
30081c893b | ||
|
|
e69890a47e | ||
|
|
9d31162eec | ||
|
|
0031cc7418 | ||
|
|
57132892b5 | ||
|
|
be084d1570 | ||
|
|
03d29a9ebd | ||
|
|
e9a837b534 | ||
|
|
36c601f9fa | ||
|
|
af41234484 | ||
|
|
bcaf03a770 | ||
|
|
9429b009ce | ||
|
|
3395785cbc | ||
|
|
97c048c7af | ||
|
|
726eb2ffe6 | ||
|
|
a9f22d3a10 | ||
|
|
5a6437e371 | ||
|
|
4ffc98b371 | ||
|
|
16c73d4f91 | ||
|
|
96aff5230f | ||
|
|
b298571be8 | ||
|
|
7b7b10c9a5 | ||
|
|
56beed5ad5 | ||
|
|
8c8ef0ea53 | ||
|
|
90377d98c0 | ||
|
|
d167e474d8 | ||
|
|
0cfacfe057 | ||
|
|
fbda5231d0 | ||
|
|
bd4d333d59 | ||
|
|
07878207de | ||
|
|
b2352877b9 | ||
|
|
669ba9e8cb | ||
|
|
5fa8a76219 | ||
|
|
476dcf051c | ||
|
|
db96dbba6a | ||
|
|
e9c6509970 | ||
|
|
b26c7dfa8f | ||
|
|
3f251761d6 | ||
|
|
bc9d489ee8 | ||
|
|
271563ba9f | ||
|
|
82aba20e83 | ||
|
|
12f60c9be5 | ||
|
|
1c98a354c7 | ||
|
|
9ca7aee859 | ||
|
|
937b306128 | ||
|
|
69a2ab0ce2 | ||
|
|
b720711217 | ||
|
|
bf56348c62 | ||
|
|
f993817cb6 | ||
|
|
1c2b4794f3 | ||
|
|
523d210503 | ||
|
|
39da8bd636 | ||
|
|
fbea98bbe6 | ||
|
|
5d89f724f4 | ||
|
|
0313b6f3ab | ||
|
|
fe92111dc9 | ||
|
|
9a03bfb9e7 | ||
|
|
882db6acc9 | ||
|
|
5596468b03 | ||
|
|
eb66de1220 | ||
|
|
f97896f6a6 | ||
|
|
cfb47f880e | ||
|
|
eba87776a0 | ||
|
|
dda0e6d676 | ||
|
|
8d514644c1 | ||
|
|
0870a34391 | ||
|
|
38118986a3 | ||
|
|
1b4e5247ad | ||
|
|
3ef2eeef93 | ||
|
|
4d5682e79b | ||
|
|
24100d203f | ||
|
|
86946a2c21 | ||
|
|
54f3e4cc6f | ||
|
|
d9360b2d8c | ||
|
|
abb47118c0 | ||
|
|
9e4e55bb8d | ||
|
|
498f720507 | ||
|
|
b9bc9cb75e | ||
|
|
3b65917422 | ||
|
|
862dd78cd5 | ||
|
|
d0bc48d119 | ||
|
|
37462ba282 | ||
|
|
99e7f5862a | ||
|
|
048e529bb5 | ||
|
|
5b8b06f3a1 | ||
|
|
3c7d025802 | ||
|
|
4f8b46da14 | ||
|
|
0b386a882e | ||
|
|
6329d58a67 | ||
|
|
0444e17848 | ||
|
|
c3d039fe45 | ||
|
|
1d5d713854 | ||
|
|
4336c15ca4 | ||
|
|
aac644d15c | ||
|
|
ab3dde17c7 | ||
|
|
924ec33d73 | ||
|
|
d798e02126 | ||
|
|
af0d780ac0 | ||
|
|
45c2c863ef | ||
|
|
bc08aeb5b7 | ||
|
|
c32067890c | ||
|
|
83a180e3b8 | ||
|
|
3372e16409 | ||
|
|
a04fad9c1f | ||
|
|
7500797dd0 | ||
|
|
9427f4141f | ||
|
|
1440244c4d | ||
|
|
47c8b82cfa | ||
|
|
540f23fb41 | ||
|
|
323c9f2d4f | ||
|
|
1d648b525f | ||
|
|
11c2771451 | ||
|
|
1733756b4a | ||
|
|
edf1933800 | ||
|
|
38d3165d14 | ||
|
|
5766b307c1 | ||
|
|
6497703d3b | ||
|
|
60e48580ae | ||
|
|
08b52f3618 | ||
|
|
55001cc434 | ||
|
|
b84b864396 | ||
|
|
34835b8cdf | ||
|
|
df8bdbf5b3 | ||
|
|
e775a832cb | ||
|
|
b9c4bada23 | ||
|
|
97f35f7ee6 | ||
|
|
0f90a06028 | ||
|
|
db4f2e7696 | ||
|
|
69837b0515 | ||
|
|
9811c49288 | ||
|
|
d709c99641 | ||
|
|
a92666082f | ||
|
|
cc05b28a42 | ||
|
|
a2c9953096 | ||
|
|
75ef6934b4 | ||
|
|
aa4d3c039b | ||
|
|
a8a89dc9bd | ||
|
|
a0305a745a | ||
|
|
290ff54638 | ||
|
|
dc4decffe4 | ||
|
|
f06b702360 | ||
|
|
e2eca66db0 | ||
|
|
d20913023e | ||
|
|
f4466dc325 | ||
|
|
00e6ea5b3b | ||
|
|
50b0a3ea17 | ||
|
|
0072e3e5ba | ||
|
|
6f104c4ee6 | ||
|
|
c721580516 | ||
|
|
2238f1fafc | ||
|
|
00bc5a00c1 | ||
|
|
1fe1381fe2 | ||
|
|
6bc0470c69 | ||
|
|
a9ab25e9c2 | ||
|
|
fd5bc22a70 | ||
|
|
28fe1fafd6 | ||
|
|
6695138244 | ||
|
|
3fb19cbe96 | ||
|
|
3f8a17c3ea | ||
|
|
9fa97f27f0 | ||
|
|
0e98312d55 | ||
|
|
06057a1d35 | ||
|
|
4373fddaa8 | ||
|
|
c45511d9a5 | ||
|
|
7d2b2494e5 | ||
|
|
870a25dad1 | ||
|
|
d74dc2f4ca | ||
|
|
f8c9c535a0 | ||
|
|
d22322be86 | ||
|
|
e4e5d5c6d7 | ||
|
|
7e45f23b6c | ||
|
|
719f61f612 | ||
|
|
908edda14b | ||
|
|
74792a9c21 | ||
|
|
eb345b5ca2 | ||
|
|
23c2b4b204 | ||
|
|
095e616e4c | ||
|
|
89f4626fce | ||
|
|
c759d673f0 | ||
|
|
8d1be554d4 | ||
|
|
e931d06ed4 | ||
|
|
76b90f9bc0 | ||
|
|
b4e5fedb51 | ||
|
|
6a229aabaf | ||
|
|
841c7df2f3 | ||
|
|
dd85ce7cfe | ||
|
|
4c7d771bb3 | ||
|
|
c55bdba948 | ||
|
|
4f2dce0a03 | ||
|
|
450a992b26 | ||
|
|
4284b2402b | ||
|
|
50c88f82f4 | ||
|
|
7dff3dc658 | ||
|
|
adb3864ea9 | ||
|
|
d6330060dc | ||
|
|
2dcb35a34c | ||
|
|
624ba95792 | ||
|
|
ae24a80b95 | ||
|
|
e7f1b1cc32 | ||
|
|
e71940ecdc | ||
|
|
65a800701c | ||
|
|
36dc1fb3e9 | ||
|
|
99305b4185 | ||
|
|
bd2e8be186 | ||
|
|
dc4c6ceff5 | ||
|
|
10083ac807 | ||
|
|
11023c6400 | ||
|
|
6d31314df6 | ||
|
|
d5367194ab | ||
|
|
cf179b2f9c | ||
|
|
de82188663 | ||
|
|
4aefe775f9 | ||
|
|
8c06c98917 | ||
|
|
ee9f778725 | ||
|
|
ff0883c8e6 | ||
|
|
d4e0f05cef | ||
|
|
dfcb4fe286 | ||
|
|
d546d5d0a7 | ||
|
|
375dc86f0a | ||
|
|
d2f187f6c0 | ||
|
|
5393ee9ba9 | ||
|
|
d4d2948455 | ||
|
|
37617c04ad | ||
|
|
10e0153018 | ||
|
|
42cbe94af8 | ||
|
|
8f95e53d9d | ||
|
|
0dae21dcf1 | ||
|
|
912efeb5fd | ||
|
|
3d9307f96d | ||
|
|
873f4b080a | ||
|
|
e337a79e2e | ||
|
|
980ce62bf6 | ||
|
|
dccf757f56 | ||
|
|
c6e93cd3c8 | ||
|
|
4a6b88328e | ||
|
|
779a84cf0b | ||
|
|
aff409ba63 | ||
|
|
275167c0c4 | ||
|
|
19b2af7f57 | ||
|
|
779d5df264 | ||
|
|
5050b9ee97 | ||
|
|
23da4be6b1 | ||
|
|
299648b8e0 | ||
|
|
86fa0c87ae | ||
|
|
77cd52ca04 | ||
|
|
bed2a77232 | ||
|
|
9619eec40f | ||
|
|
886161d65f | ||
|
|
d5d646e6e0 | ||
|
|
494103163c | ||
|
|
72e9e4848b | ||
|
|
1181ba6f90 | ||
|
|
b8d6ec5fe0 | ||
|
|
7335d7df0a | ||
|
|
44754095fb | ||
|
|
0f515bae01 | ||
|
|
76a11f6ee6 | ||
|
|
5fb28feb65 | ||
|
|
e5f1524b10 | ||
|
|
8a875691fb | ||
|
|
0b2710b97d | ||
|
|
57552a32b0 | ||
|
|
572ec3658e | ||
|
|
6d5c791f61 | ||
|
|
168e479c0c | ||
|
|
927e1b7ef9 | ||
|
|
76dccf804e | ||
|
|
4262e0e6eb | ||
|
|
7d487420aa | ||
|
|
c422b11e3a |
@@ -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"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -3,11 +3,11 @@
|
|||||||
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
||||||
|
|
||||||
# Set it to the URL form where the app home page will be accessed
|
# Set it to the URL form where the app home page will be accessed
|
||||||
PUBLIC_URL=http://localhost:3000
|
PUBLIC_URL=https://localhost:3001
|
||||||
# Set it to true if you want to generate the Sourcemap for debugging
|
# Set it to true if you want to generate the Sourcemap for debugging
|
||||||
GENERATE_SOURCEMAP=false
|
GENERATE_SOURCEMAP=false
|
||||||
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||||
REACT_APP_SERVERURL=http://localhost:8080/app
|
# REACT_APP_SERVERURL=http://localhost:8080/app
|
||||||
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
||||||
REACT_APP_APPID=opensign
|
REACT_APP_APPID=opensign
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ appName=open_sign_server
|
|||||||
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
|
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
|
||||||
MASTER_KEY=XnAadwKxxByMr
|
MASTER_KEY=XnAadwKxxByMr
|
||||||
# Mongodb URI to connect to
|
# Mongodb URI to connect to
|
||||||
MONGODB_URI=mongodb://mongo:27017/OpenSignDB
|
MONGODB_URI=mongodb://mongo-container:27017/OpenSignDB
|
||||||
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
|
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
|
||||||
PARSE_MOUNT=/app
|
PARSE_MOUNT=/app
|
||||||
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
|
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||||
@@ -46,7 +46,7 @@ USE_LOCAL=true
|
|||||||
MAILGUN_API_KEY=
|
MAILGUN_API_KEY=
|
||||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||||
SMTP_ENABLE=
|
SMTP_ENABLE=true
|
||||||
SMTP_HOST=smtp.yourhost.com
|
SMTP_HOST=smtp.yourhost.com
|
||||||
SMTP_PORT=443
|
SMTP_PORT=443
|
||||||
SMTP_USER_EMAIL=mailer@yourdomain.com
|
SMTP_USER_EMAIL=mailer@yourdomain.com
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: ci
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'staging'
|
- 'main'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{$HOST_URL} {
|
||||||
|
reverse_proxy client:3000
|
||||||
|
handle_path /app/* {
|
||||||
|
reverse_proxy server:8080
|
||||||
|
rewrite * /app{uri}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
build:
|
build:
|
||||||
|
@echo "Building with HOST_URL=${HOST_URL}"
|
||||||
cp .env.local_dev .env
|
cp .env.local_dev .env
|
||||||
cd apps/OpenSign && cp ../../.env.local_dev .env && npm install && npm run build
|
cd apps/OpenSign && cp ../../.env.local_dev .env && npm install && npm run build
|
||||||
docker compose up --build --force-recreate
|
HOST_URL=${HOST_URL} docker compose up --build --force-recreate
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
@echo "Building with HOST_URL=${HOST_URL}"
|
||||||
cp .env.local_dev .env
|
cp .env.local_dev .env
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|||||||
@@ -75,7 +75,13 @@ Welcome to OpenSign, the premier open source docusign alternative - document e-s
|
|||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
Please refer to the [Installation Guide](INSTALLATION.md) for detailed instructions on how to install OpenSign on your system.
|
The simplest way to install OpenSign on your own server is using official docker images by running the following command -
|
||||||
|
```
|
||||||
|
export HOST_URL=https://opensign.yourdomain.com && curl --remote-name-all https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/docker-compose.yml https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/Caddyfile https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/.env.local_dev && mv .env.local_dev .env.prod && docker compose up --force-recreate
|
||||||
|
```
|
||||||
|
Make sure that you have `Docker` and `git` installed before you run this command -
|
||||||
|
|
||||||
|
Please refer to the [Installation Guide](https://docs.opensignlabs.com/docs/self-host/docker/run-locally/) for detailed instructions on how to install OpenSign on your system.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -141,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
+3362
-6703
File diff suppressed because it is too large
Load Diff
+43
-33
@@ -4,12 +4,17 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/auto-animate": "^0.8.2",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@lottiefiles/dotlottie-react": "^0.7.2",
|
"@lottiefiles/dotlottie-react": "^0.9.1",
|
||||||
"@radix-ui/themes": "^3.1.1",
|
"@pdf-lib/fontkit": "^1.1.1",
|
||||||
"@react-pdf/renderer": "^3.4.4",
|
"@radix-ui/themes": "^3.1.4",
|
||||||
"@reduxjs/toolkit": "^2.2.6",
|
"@react-pdf/renderer": "^4.0.0",
|
||||||
"axios": "^1.7.2",
|
"@reduxjs/toolkit": "^2.2.8",
|
||||||
|
"axios": "^1.7.7",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
|
"i18next": "^23.16.0",
|
||||||
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
|
"i18next-http-backend": "^2.6.2",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nth-check": "^2.1.1",
|
"nth-check": "^2.1.1",
|
||||||
@@ -18,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.1.4",
|
"react-cookie": "^7.2.1",
|
||||||
"react-datepicker": "^7.2.0",
|
"react-datepicker": "^7.4.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dnd-multi-backend": "^8.0.3",
|
"react-dnd-multi-backend": "^8.0.3",
|
||||||
@@ -29,32 +34,34 @@
|
|||||||
"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.3",
|
||||||
"react-konva": "^18.2.10",
|
"react-konva": "^18.2.10",
|
||||||
"react-pdf": "^9.1.0",
|
"react-pdf": "^9.1.1",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill-new": "^3.3.3",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
"react-rnd": "^10.4.11",
|
"react-rnd": "^10.4.13",
|
||||||
"react-router-dom": "^6.25.1",
|
"react-router-dom": "^6.27.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.0",
|
"react-select": "^5.8.1",
|
||||||
"react-signature-canvas": "^1.0.6",
|
"react-signature-canvas": "^1.0.6",
|
||||||
"react-tooltip": "^5.27.1",
|
"react-syntax-highlighter": "^15.5.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.3",
|
||||||
"styled-components": "^4.4.1",
|
"styled-components": "^5.3.0",
|
||||||
"web-vitals": "^4.2.2",
|
"web-vitals": "^4.2.3",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-webpack": "webpack --config webpack.config.js",
|
"build-webpack": "webpack --config webpack.config.js",
|
||||||
"build": "npm run version && npm run build-webpack && react-scripts build",
|
"build": "npm run version && npm run build-webpack && react-scripts build",
|
||||||
"build-watch": "webpack --config webpack.config.js --watch",
|
"build-watch": "webpack --config webpack.config.js --watch",
|
||||||
"start-dev": "concurrently \"npm run build-watch\" \"react-scripts start\"",
|
"start-dev": "react-scripts start",
|
||||||
"start": "serve -s build",
|
"start": "serve -s build",
|
||||||
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
||||||
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
|
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
|
||||||
@@ -88,33 +95,36 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.6",
|
"@babel/core": "^7.25.8",
|
||||||
"@babel/preset-env": "^7.24.6",
|
"@babel/preset-env": "^7.25.8",
|
||||||
"@babel/preset-react": "^7.24.6",
|
"@babel/preset-react": "^7.25.7",
|
||||||
"@babel/runtime-corejs2": "^7.24.7",
|
"@babel/runtime-corejs2": "^7.25.7",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.20",
|
||||||
"babel-loader": "^9.1.3",
|
"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": "^8.2.2",
|
"concurrently": "^9.0.1",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"daisyui": "^4.12.10",
|
"daisyui": "^4.12.13",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"dotenv-webpack": "^8.1.0",
|
"dotenv-webpack": "^8.1.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.12.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.34.3",
|
"eslint-plugin-react": "^7.37.1",
|
||||||
"lint-staged": "^15.2.7",
|
"lint-staged": "^15.2.10",
|
||||||
"mini-css-extract-plugin": "^2.9.0",
|
"mini-css-extract-plugin": "^2.9.1",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.47",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"pretty-quick": "^4.0.0",
|
"pretty-quick": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.6",
|
"tailwindcss": "^3.4.13",
|
||||||
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,687 @@
|
|||||||
|
{
|
||||||
|
"header-news": "New feature: Public profiles are now live! Easily create and share public templates",
|
||||||
|
"header-news-btn": "Setup Now",
|
||||||
|
"create-account": "Create Account",
|
||||||
|
"login": "Login",
|
||||||
|
"language": "Language",
|
||||||
|
"name": "Name",
|
||||||
|
"phone": "Phone",
|
||||||
|
"phone-optional": "optional",
|
||||||
|
"email": "Email",
|
||||||
|
"company": "Company",
|
||||||
|
"job-title": "Job title",
|
||||||
|
"profile": "Profile",
|
||||||
|
"log-out": "Log Out",
|
||||||
|
"is-email-verified": "Is Email verified",
|
||||||
|
"public-profile": "Public profile",
|
||||||
|
"tagline": "Tagline ",
|
||||||
|
"has-requested-you-to-sign": "has requested you to sign",
|
||||||
|
"has-requested-you-to-review-and-sign": " has requested you to review and sign",
|
||||||
|
"input-required": "Please fill out this field.",
|
||||||
|
"sort-order": {
|
||||||
|
"Ascending": "Ascending",
|
||||||
|
"Descending": "Descending",
|
||||||
|
"Name": "Name",
|
||||||
|
"Date": "Date"
|
||||||
|
},
|
||||||
|
"context-menu": {
|
||||||
|
"Download": "Download",
|
||||||
|
"Rename": "Rename",
|
||||||
|
"Move": "Move",
|
||||||
|
"Delete": "Delete"
|
||||||
|
},
|
||||||
|
"action": "Action",
|
||||||
|
"add": "Add",
|
||||||
|
"add-new-folder": "Add a new folder",
|
||||||
|
"disable-documentId": "Disable DocumentId",
|
||||||
|
"edit": "Edit",
|
||||||
|
"change-password": "Change Password",
|
||||||
|
"save": "Save",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"upgrade-now": "Upgrade now",
|
||||||
|
"upgrade-to": "Upgrade to",
|
||||||
|
"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-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",
|
||||||
|
"tour-content": "Don't show this again",
|
||||||
|
"pro": "PRO",
|
||||||
|
"team": "TEAM",
|
||||||
|
"user": "User",
|
||||||
|
"docs": "Docs",
|
||||||
|
"session-expired": "Your session has expired.",
|
||||||
|
"public-profile-help": "This is your public URL. Copy or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||||
|
"tagline-help": "This Tagline will appear on your OpenSign public profile for ex. https://opensign.me/alex",
|
||||||
|
"welcome": "Welcome Back!",
|
||||||
|
"Login-to-your-account": "Login to your account",
|
||||||
|
"password": "Password",
|
||||||
|
"forgot-password": "Forgot Password?",
|
||||||
|
"loading": "Loading...",
|
||||||
|
"of": "of",
|
||||||
|
"sign-SSO": "Sign in with SSO",
|
||||||
|
"login-page": "Login Page",
|
||||||
|
"or": "OR",
|
||||||
|
"signup-page": "Signup page",
|
||||||
|
"password-length": "Password should be 8 characters long",
|
||||||
|
"password-case": "Password should contain uppercase letter, lowercase letter, digit",
|
||||||
|
"password-special-char": " Password should contain special character",
|
||||||
|
"agreee": "I agree to the",
|
||||||
|
"term": "Terms of Service",
|
||||||
|
"subscribe-to-opensign": "Subscribe to OpenSign newsletter",
|
||||||
|
"register": "Register",
|
||||||
|
"sidebar": {
|
||||||
|
"Dashboard": "Dashboard",
|
||||||
|
"Sign yourself": "Sign yourself",
|
||||||
|
"Request signatures": "Request signatures",
|
||||||
|
"Templates": "Templates",
|
||||||
|
"Templates-Children": {
|
||||||
|
"Create template": "Create template",
|
||||||
|
"Manage templates": "Manage templates"
|
||||||
|
},
|
||||||
|
"OpenSign™ Drive": "OpenSign™ Drive",
|
||||||
|
"Reports": "Reports",
|
||||||
|
"Reports-Children": {
|
||||||
|
"Need your sign": "Need your sign",
|
||||||
|
"In Progress": "In Progress",
|
||||||
|
"Completed": "Completed",
|
||||||
|
"Drafts": "Drafts",
|
||||||
|
"Declined": "Declined",
|
||||||
|
"Expired": "Expired",
|
||||||
|
"Contactbook": "Contactbook"
|
||||||
|
},
|
||||||
|
"Settings": "Settings",
|
||||||
|
"Settings-Children": {
|
||||||
|
"My Signature": "My Signature",
|
||||||
|
"API Token": "API Token",
|
||||||
|
"Webhook": "Webhook",
|
||||||
|
"Teams": "Teams",
|
||||||
|
"Team-update-successfully": "Team Updated successfully.",
|
||||||
|
"Users": "Users"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dashboard-card": {
|
||||||
|
"Need your Signature": "Need your Signature",
|
||||||
|
"Out for signatures": "Out for Signatures"
|
||||||
|
},
|
||||||
|
"report-name": {
|
||||||
|
"Draft Documents": "Draft Documents",
|
||||||
|
"Need your sign": "Need your sign",
|
||||||
|
"In-progress documents": "In-progress documents",
|
||||||
|
"Completed Documents": "Completed Documents",
|
||||||
|
"Declined Documents": "Declined Documents",
|
||||||
|
"Expired Documents": "Expired Documents",
|
||||||
|
"Recently sent for signatures": "Recently sent for signatures",
|
||||||
|
"Recent signature requests": "Recent signature requests",
|
||||||
|
"Drafts": "Drafts",
|
||||||
|
"Contactbook": "Contactbook",
|
||||||
|
"Templates": "Templates",
|
||||||
|
"Teams": "Teams",
|
||||||
|
"Users": "Users"
|
||||||
|
},
|
||||||
|
"btnLabel": {
|
||||||
|
"sign": "sign",
|
||||||
|
"Sign": "SIGN",
|
||||||
|
"Resend": "Resend",
|
||||||
|
"Revoke": "Revoke",
|
||||||
|
"Delete": "Delete",
|
||||||
|
"Use": "Use",
|
||||||
|
"Quick send": "Quick send",
|
||||||
|
"Edit": "Edit",
|
||||||
|
"Share with team": "Share with team",
|
||||||
|
"Share": "Share",
|
||||||
|
"View": "View",
|
||||||
|
"option": "Option",
|
||||||
|
"Embed": "Embed",
|
||||||
|
"Copy TemplateId":"Copy TemplateId",
|
||||||
|
"Copy Public URL":"Copy Public URL"
|
||||||
|
},
|
||||||
|
"report-heading": {
|
||||||
|
"Sr.No": "Sr.No",
|
||||||
|
"Title": "Title",
|
||||||
|
"Email": "Email",
|
||||||
|
"Phone": "Phone",
|
||||||
|
"File": "File",
|
||||||
|
"Owner": "Owner",
|
||||||
|
"Signers": "Signers",
|
||||||
|
"Note": "Note",
|
||||||
|
"Folder": "Folder",
|
||||||
|
"Reason": "Reason",
|
||||||
|
"Parent Team": "Parent Team",
|
||||||
|
"Active": "Active",
|
||||||
|
"Role": "Role",
|
||||||
|
"Team": "Team",
|
||||||
|
"Name": "Name",
|
||||||
|
"Status": "Status",
|
||||||
|
"created-date": "Created Date",
|
||||||
|
"Type": "Type",
|
||||||
|
"Logs": "Logs"
|
||||||
|
},
|
||||||
|
"report-help": {
|
||||||
|
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||||
|
"Need your sign": "This is a list of documents that are waiting for your signature",
|
||||||
|
"In-progress documents": "This is a list of documents you've sent to other parties for signature.",
|
||||||
|
"Completed Documents": "This is a list of documents that have been signed by all parties.",
|
||||||
|
"Declined Documents": "This is a list of documents that have been declined by one of the signers.",
|
||||||
|
"Expired Documents": "This is a list of documents that have reached their expiration date.",
|
||||||
|
"Contactbook": "This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document.",
|
||||||
|
"Templates": "This is a list of templates that are available to you for creating documents. You can click the 'use' button to create a new document using a template, modify the document & add signers in the next step."
|
||||||
|
},
|
||||||
|
"form-name": {
|
||||||
|
"Sign Yourself": "Sign Yourself",
|
||||||
|
"Request Signatures": "Request Signatures",
|
||||||
|
"New Template": "New Template"
|
||||||
|
},
|
||||||
|
"file-type": "pdf, png, jpg, jpeg",
|
||||||
|
"docx": "docx",
|
||||||
|
"file-selected": "file selected",
|
||||||
|
"template-title": "Template Title",
|
||||||
|
"document-title": "Document Title",
|
||||||
|
"description": "Description",
|
||||||
|
"time-to-complete": "Time To Complete (Days)",
|
||||||
|
"send-in-order": "Send In Order",
|
||||||
|
"send-in-order-help": {
|
||||||
|
"p1": "Choose how you want the signing requests to be sent to the document signers:",
|
||||||
|
"p2": "Selecting this option will send the signing request to the first signer initially. Once the first signer completes their part, the next signer in the sequence will receive the request. This process continues until all signers have signed the document. This method ensures that the document is signed in a specific order.",
|
||||||
|
"p3": "Selecting this option will send the signing links to all signers simultaneously. Every signer can sign the document at their convenience, regardless of whether other signers have completed their signatures. This method is faster but does not enforce any signing order among the participants.",
|
||||||
|
"p4": "Select the option that best suits the needs of your document processing."
|
||||||
|
},
|
||||||
|
"no": "No",
|
||||||
|
"auto-reminder": "Auto reminder",
|
||||||
|
"remind-once": " Remind once in every (Days)",
|
||||||
|
"next": "Next",
|
||||||
|
"select-folder": "Select Folder",
|
||||||
|
"OpenSign-drive": "OpenSign™ Drive",
|
||||||
|
"drive-document-status": {
|
||||||
|
"Completed": "Completed",
|
||||||
|
"Declined": "Declined",
|
||||||
|
"Draft": "Draft",
|
||||||
|
"Expired": "Expired",
|
||||||
|
"In Progress": "In Progress"
|
||||||
|
},
|
||||||
|
"select-folder-help": "If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder.",
|
||||||
|
"no-data": "No data found",
|
||||||
|
"save-here": "Save Here",
|
||||||
|
"back": "Back",
|
||||||
|
"add-folder": "Add folder",
|
||||||
|
"create-folder": "Create Folder",
|
||||||
|
"parent-folder": "Parent Folder",
|
||||||
|
"create": "Create",
|
||||||
|
"signers": "Signers",
|
||||||
|
"signers-help": "Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed.",
|
||||||
|
"add-signer": "Add Signer",
|
||||||
|
"contact-not-found": "Contact not found",
|
||||||
|
"add-yourself": "Add Yourself",
|
||||||
|
"submit": "Submit",
|
||||||
|
"reset": "Reset",
|
||||||
|
"my-signature": "My Signature",
|
||||||
|
"signature": "Signature",
|
||||||
|
"upload-image": " Upload image",
|
||||||
|
"clear": "Clear",
|
||||||
|
"upload-signature/Image": "Please upload signature/Image",
|
||||||
|
"initials": "Initials",
|
||||||
|
"API": "API",
|
||||||
|
"api-token": "API Token",
|
||||||
|
"regenerate-token": "Regenerate Live Token",
|
||||||
|
"generate-token": "Generate Live Token",
|
||||||
|
"view-docs": "View Docs",
|
||||||
|
"generate-token-alert": "Are you sure you want to regenerate token it will expire old token?",
|
||||||
|
"yes": "Yes",
|
||||||
|
"copied": "Copied",
|
||||||
|
"something-went-wrong-mssg": "Something went wrong, please try again later.",
|
||||||
|
"token-generated": "Token generated successfully.",
|
||||||
|
"webhook": "Webhook",
|
||||||
|
"update-webhook": "Update Webhook",
|
||||||
|
"add-webhook": "Add Webhook",
|
||||||
|
"webhook-added": "Webhook added successfully.",
|
||||||
|
"team-disabled": "Team disabled",
|
||||||
|
"Team enabled": "Team enabled",
|
||||||
|
"are-you-sure": "Are you sure you want to",
|
||||||
|
"disable": "disable",
|
||||||
|
"enable": "enable",
|
||||||
|
"this-team": " this team?",
|
||||||
|
"edit-team": "Edit Team",
|
||||||
|
"name-of-team": "Name of Team",
|
||||||
|
"prev": "Prev",
|
||||||
|
"no-data-avaliable": "No Data Available",
|
||||||
|
"add-team": "Add Team",
|
||||||
|
"page-not-found": "Page Not Found",
|
||||||
|
"users-from-teams": "users from Teams",
|
||||||
|
"user-status": "User status",
|
||||||
|
"activate": "activate",
|
||||||
|
"deactivate": "deactivate",
|
||||||
|
"this-user": " this user",
|
||||||
|
"delete-user": "Delete User",
|
||||||
|
"delete": "delete",
|
||||||
|
"add-user": "Add User",
|
||||||
|
"password-generateed": "Password will only be generated once; make sure to copy it.",
|
||||||
|
"Team status": "Team status",
|
||||||
|
"user-deactivated": "User deactivated.",
|
||||||
|
"user-activated": "User activated.",
|
||||||
|
"public": "Public",
|
||||||
|
"download": "Download",
|
||||||
|
"view": "View",
|
||||||
|
"make-template-public": "Make template public",
|
||||||
|
"make-template-private": "Make template private",
|
||||||
|
"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.",
|
||||||
|
"public-role": "Public role",
|
||||||
|
"public-url": "Public profile needed",
|
||||||
|
"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.",
|
||||||
|
"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": "Share with",
|
||||||
|
"team-not-found": "Team not found",
|
||||||
|
"roles": "Roles",
|
||||||
|
"delete-document": "Delete Document",
|
||||||
|
"delete-document-alert": "Are you sure you want to delete this document?",
|
||||||
|
"quick-send": "Quick send",
|
||||||
|
"add-new": "Add new",
|
||||||
|
"send": "Send",
|
||||||
|
"quick-send-alert-1": "All roles in this document are currently linked to contacts. To quick send copies of this template to multiple signers, please ensure that at least one role is not linked to any contact.",
|
||||||
|
"quick-send-alert-2": "Please ensure there's at least one signature widget added for all recipients.",
|
||||||
|
"quick-send-alert-3": "Please add at least one role to this template in order to 'quick send' copies of it to multiple signers.",
|
||||||
|
"quick-send-alert-4": "Quick send reached limit.",
|
||||||
|
"copy-link": "Copy link",
|
||||||
|
"copy": "Copy",
|
||||||
|
"revoke-document": "Revoke document",
|
||||||
|
"revoke-document-alert": "Are you sure you want to revoke this document?",
|
||||||
|
"resend-mail": "Resend Mail",
|
||||||
|
"resend-mail-help": "You can use following variables which will get replaced with their actual values:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
|
||||||
|
"subject": "Subject",
|
||||||
|
"body": "Body",
|
||||||
|
"add-contact": "Add Contact",
|
||||||
|
"add-signer-alert": "Contact already exist!",
|
||||||
|
"record-delete-alert": "Record deleted successfully!",
|
||||||
|
"record-revoke-alert": "Record revoked successfully!",
|
||||||
|
"mail-sent-alert": "Mail sent successfully.",
|
||||||
|
"document-sent-alert": "Document sent successfully!",
|
||||||
|
"template-share-alert": "Template Shared successfully.",
|
||||||
|
"template-public-alert-1": "You have successfully made the template public.",
|
||||||
|
"template-public-alert-2": "You have successfully made the template private.",
|
||||||
|
"template-public-alert-3": "You need to select a role for the public signers.",
|
||||||
|
"template-public-alert-4": "Please ensure there's at least one signature widget added for all signers.",
|
||||||
|
"template-public-alert-5": "Since this template has send-in-order enabled, the public role must be positioned at the top.",
|
||||||
|
"template-public-alert-6": "Please attach signers to all roles except for the public role user.",
|
||||||
|
"template-public-alert-7": "Please assign at least one public role to make this template public.",
|
||||||
|
"loader": " This might take some time",
|
||||||
|
"pages": "Pages",
|
||||||
|
"document-signed": "Document signed",
|
||||||
|
"close": "Close",
|
||||||
|
"validation-alert": "Validation alert",
|
||||||
|
"validate-alert-mssg": " The input does not meet the criteria set by the regular expression.",
|
||||||
|
"otp-verification": "OTP verification",
|
||||||
|
"enter-otp": "Enter OTP",
|
||||||
|
"verify": "Verify",
|
||||||
|
"verify-email-1": "Verify email",
|
||||||
|
"resend": "Resend",
|
||||||
|
"contact-details": "Contact Details",
|
||||||
|
"verify-email": "Please verify your email !",
|
||||||
|
"send-otp": " Send OTP",
|
||||||
|
"otp-placeholder": "Enter verification code received over email",
|
||||||
|
"loading-doc": "Loading Document..",
|
||||||
|
"widgets-name": {
|
||||||
|
"signature": "signature",
|
||||||
|
"stamp": "stamp",
|
||||||
|
"initials": "initials",
|
||||||
|
"name": "name",
|
||||||
|
"job title": "job title",
|
||||||
|
"company": "company",
|
||||||
|
"date": "date",
|
||||||
|
"text": "text",
|
||||||
|
"text input": "text input",
|
||||||
|
"checkbox": "checkbox",
|
||||||
|
"dropdown": "dropdown",
|
||||||
|
"radio button": "radio button",
|
||||||
|
"image": "image",
|
||||||
|
"email": "email"
|
||||||
|
},
|
||||||
|
"fields": "Fields",
|
||||||
|
"recipients": "Recipients",
|
||||||
|
"please-add": "Please add a",
|
||||||
|
"signed-by": "Signed By",
|
||||||
|
"more": "more",
|
||||||
|
"sent": "sent",
|
||||||
|
"print": "Print",
|
||||||
|
"certificate": "Certificate",
|
||||||
|
"decline": "Decline",
|
||||||
|
"finish": "Finish",
|
||||||
|
"mail": "Mail",
|
||||||
|
"sign-now": "Sign Now",
|
||||||
|
"successfully-signed": "Successfully signed!",
|
||||||
|
"email-mssg": " Recipients added here will get a copy of the signed document.",
|
||||||
|
"email-error-1": " please provide correct email address",
|
||||||
|
"email-error-2": "You can only send to ten recipients at a time.",
|
||||||
|
"Email-verified-alert-1": "Email is verified.",
|
||||||
|
"Email-verified-alert-2": "Email is already verified.",
|
||||||
|
"upload-stamp-image": "Upload stamp image",
|
||||||
|
"draw": "Draw",
|
||||||
|
"type": "Type",
|
||||||
|
"color-type": {
|
||||||
|
"red": "red",
|
||||||
|
"blue": "blue",
|
||||||
|
"black": "black",
|
||||||
|
"yellow": "yellow"
|
||||||
|
},
|
||||||
|
"my-initials": "My Initials",
|
||||||
|
"upload": "Upload",
|
||||||
|
"initial-teb": "Initials",
|
||||||
|
"signature-tab": "Signature",
|
||||||
|
"your-signature": "Your signature",
|
||||||
|
"copy-title": "Copy widget to",
|
||||||
|
"contact-delete-alert": "Are you sure you want to delete this contact?",
|
||||||
|
"reset-password-alert-1": "Reset password link has been sent to your email id",
|
||||||
|
"reset-password-alert-2": "Please setup email adapter ",
|
||||||
|
"reset-password-alert-3": "Reset Your Password",
|
||||||
|
"faild-animation": "Failed to load animation",
|
||||||
|
"apply": "Apply",
|
||||||
|
"copy-type": {
|
||||||
|
"All pages": "All pages",
|
||||||
|
"All pages but last": "All pages but last",
|
||||||
|
"All pages but first": "All pages but first",
|
||||||
|
"Next to current widget": "Next to current widget"
|
||||||
|
},
|
||||||
|
"options": "Options",
|
||||||
|
"minimun-check": "Minimun check",
|
||||||
|
"maximum-check": "Maximum check",
|
||||||
|
"default-value": "Default value",
|
||||||
|
"select": "Select",
|
||||||
|
"read-only": "Is read only",
|
||||||
|
"hide-labels": "Hide labels",
|
||||||
|
"checkbox": "Checkbox",
|
||||||
|
"alert": "Alert",
|
||||||
|
"zoom-in": "Zoom in",
|
||||||
|
"zoom-out": "Zoom out",
|
||||||
|
"document-signed-alert": "Congratulations! 🎉 This document has been successfully signed by you!",
|
||||||
|
"otp-sent-alert": "OTP sent on your email",
|
||||||
|
"fields-required": "Fields required",
|
||||||
|
"signature-widget-alert-1": "Please ensure there's at least one signature widget added",
|
||||||
|
"signature-widget-alert-2": "Please ensure all field is accurately filled and meets all requirements.",
|
||||||
|
"encrypted-pdf-alert": "Currently encrypted pdf files are not supported.",
|
||||||
|
"encrypted-pdf-alert-1": "PFX file password is invalid.",
|
||||||
|
"user-not-exist": "User does not exist",
|
||||||
|
"template-signature-field": "Please add at least one signature field for all roles.",
|
||||||
|
"template-role-alert": "Please add roles first",
|
||||||
|
"create-document": "Create Document",
|
||||||
|
"template-created-alert": "Do you want to create a document using the template you just created ?",
|
||||||
|
"signers-alert": "signers alert",
|
||||||
|
"template-creation-alert-1": "Please select signer for add placeholder!",
|
||||||
|
"ok": "Ok",
|
||||||
|
"radio-group": "Radio group",
|
||||||
|
"dropdown-options": "Dropdown options",
|
||||||
|
"add-role": "Add Role",
|
||||||
|
"role-ex": " e.g: Customer, Hr, Director, Manager, Student, etc",
|
||||||
|
"add/choose-signer": "Add/Choose Signer",
|
||||||
|
"choose-from-contacts": "Choose from contacts",
|
||||||
|
"select-signer": " Please select signer",
|
||||||
|
"edit-template": "Edit Template",
|
||||||
|
"widget-info": "Widget info",
|
||||||
|
"validation": "Validation",
|
||||||
|
"invalid-default-value": "invalid default value",
|
||||||
|
"hint": "Hint",
|
||||||
|
"color": "color",
|
||||||
|
"role-help": {
|
||||||
|
"p1": "What are template roles?",
|
||||||
|
"p2": "Begin by specifying each role needed for the completion of the document. Think about the parties involved in the signing process and what their responsibilities are. Common roles include HR for internal documents, Customer for agreements or Vendor for business agreements.",
|
||||||
|
"p3": "Why pre-attach users to some roles?",
|
||||||
|
"p4": "For roles that consistently involve the same individual (e.g., the CEO's signature on employee offer letters), you can pre-attach a user to a role within the template. This step is optional but recommended for efficiency and consistency across documents.",
|
||||||
|
"p5": "When do i specify the user attached to each role?",
|
||||||
|
"p6": "When you create a document from your template, you'll be prompted to attach users to each defined role. If a role already has a user attached, this will be pre-filled, but you can modify it as needed before sending out the document."
|
||||||
|
},
|
||||||
|
"add-recipients": "Add recipients",
|
||||||
|
"loading-mssg": "This might take some time",
|
||||||
|
"send-mail": "Send Mail",
|
||||||
|
"placeholder-alert-1": "Please ensure there's at least one signature widget added for all recipients.",
|
||||||
|
"placeholder-alert-2": "Please confirm that you have filled the text field.",
|
||||||
|
"placeholder-alert-3": " Are you sure you want to send out this document for signatures?",
|
||||||
|
"placeholder-alert-4": "You have successfully sent mails to all recipients!",
|
||||||
|
"placeholder-alert-5": "Do you want to sign documents right now ?",
|
||||||
|
"placeholder-alert-6": "Please setup mail adapter to send mail!",
|
||||||
|
"placeholder-alert-7": "Please select signer for add placeholder!",
|
||||||
|
"email-subject": "email subject",
|
||||||
|
"email-body": "email body",
|
||||||
|
"email-placeholder": "add body of email",
|
||||||
|
"reset-to-default": "Reset to default",
|
||||||
|
"cutomize-email": "Cutomize Email",
|
||||||
|
"upgrade-to-customize-email": "Upgrade to customize Email",
|
||||||
|
"sign-url": "Sign url",
|
||||||
|
"Mails Sent": "Mails Sent",
|
||||||
|
"document-alert": "Document Alert",
|
||||||
|
"owner-subscription-expired": "Owner's subscription has expired.",
|
||||||
|
"subscription-expired": "Subscription Expired",
|
||||||
|
"alert-message": "Alert message",
|
||||||
|
"document-decline": "Document decline",
|
||||||
|
"decline-alert-1": "Are you sure want to decline this document ?",
|
||||||
|
"decline-alert-2": "You have declined this document!",
|
||||||
|
"decline-alert-3": "You can not sign this document as it has been declined/revoked.",
|
||||||
|
"sign here": "Sign here",
|
||||||
|
"guest-email-alert": "verification code is sent to your email",
|
||||||
|
"get-otp-alert": "you will get a verification code via Email",
|
||||||
|
"user-already-exist": "User already exist.",
|
||||||
|
"server-error": "Internal server error !",
|
||||||
|
"fill-required-details!": "Please fill required details!",
|
||||||
|
"sign-up-form": "Sign up form",
|
||||||
|
"sign-up": "Sign up",
|
||||||
|
"folder-already-exist!": "folder already exist!",
|
||||||
|
"please-select-position!": "please select position!",
|
||||||
|
"default-sign-alert": "Are you sure you want to auto sign at requested all locations?",
|
||||||
|
"Your-Signature": "Your Signature",
|
||||||
|
"auto-sign-all": "Auto Sign All",
|
||||||
|
"generating-certificate": "Generating certificate",
|
||||||
|
"pdf-download": "PDF Download",
|
||||||
|
"generate-certificate-alert": " Your completion certificate is being generated. Please wait momentarily. If the download doesn't start shortly, click the button again.",
|
||||||
|
"folder-already-exist": "Folder already exist!",
|
||||||
|
"folder-created-successfully": "Folder created successfully!",
|
||||||
|
"fill-folder-name": "Please fill folder name",
|
||||||
|
"already-exists-this-username": "User already exists with this username!",
|
||||||
|
"verification-code-sent": "Verification mail has been sent to your E-mail!",
|
||||||
|
"registered-user-successfully": "Registered user successfully.",
|
||||||
|
"role-not-found": "Role not found.",
|
||||||
|
"do-not-access": "You don't have access, please contact the admin.",
|
||||||
|
"add-admin": "Add admin",
|
||||||
|
"opensign-setup": "OpenSign Setup",
|
||||||
|
"join-discord": "Join our discord server",
|
||||||
|
"admin-already-exist": "Admin already exist.",
|
||||||
|
"password-update-alert-1": "Password updated successfully.",
|
||||||
|
"password-update-alert-2": "Your current password is missing or incorrect.",
|
||||||
|
"password-update-alert-3": "Your current password is missing or incorrect.",
|
||||||
|
"password-update-alert-4": "Your password and confirmation password do not match.",
|
||||||
|
"current-password": "Current Password",
|
||||||
|
"new-password": "New Password",
|
||||||
|
"confirm-password": "Confirm Password",
|
||||||
|
"file-alert-1": "The selected file size is too large. Please select a file less than",
|
||||||
|
"file-alert-2": "Please select file.",
|
||||||
|
"file-alert-3": "Please wait while the document is being uploaded.",
|
||||||
|
"enter-pdf-password": "Enter Pdf Password",
|
||||||
|
"correct-password": "Please provide correct password",
|
||||||
|
"decrypting-pdf": " Decrypting pdf please wait...",
|
||||||
|
"invalid-otp": "Invalid Otp",
|
||||||
|
"user-not-found": "User not found!",
|
||||||
|
"enter-otp-alert": "Please Enter OTP!",
|
||||||
|
"get-verification-code": "Get verification code",
|
||||||
|
"get-verification-code-2": "You will get a verification code via Email",
|
||||||
|
"enter-verification-code": "Enter Verification Code",
|
||||||
|
"provide-your-details": "Provide your details",
|
||||||
|
"provide-email": "Please provide email.",
|
||||||
|
"additional-info": "Additional Info",
|
||||||
|
"signature-saved-alert": "Signature saved successfully.",
|
||||||
|
"fill-field": "Please fill out this field",
|
||||||
|
"error-template": "Error: Template not found!",
|
||||||
|
"error": "Error",
|
||||||
|
"invalid-document": "Error: invalid document!",
|
||||||
|
"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.",
|
||||||
|
"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-5": "This document has been signed by all Signers.",
|
||||||
|
"document-signed-alert-6": "This document has been declined by one or more recipient(s).",
|
||||||
|
"document-signed-alert-7": "This Document is no longer available.",
|
||||||
|
"document-signed-alert-8": "The document has already been dispatched for signing.",
|
||||||
|
"yet-to-sign": "Yet to sign",
|
||||||
|
"validation-alert-1": "The input does not meet the criteria set by the regular expression.",
|
||||||
|
"account-already-exists": "Account already exists!",
|
||||||
|
"choose-password": "Choose Password",
|
||||||
|
"enter-password": "Enter Password",
|
||||||
|
"sure": "sure",
|
||||||
|
"subscribed-alert": "You have already subscribed to plan!",
|
||||||
|
"monthly": "Monthly",
|
||||||
|
"yearly-upto": "Yearly (upto 66% off)",
|
||||||
|
"billed-yearly": "Billed Yearly",
|
||||||
|
"billed-monthly": "Billed Monthly",
|
||||||
|
"plansubscription-1": "Host it yourself for free",
|
||||||
|
"visit-github": "Visit Github",
|
||||||
|
"user-already-exist-name": "User already exists with this username!",
|
||||||
|
"do-not-access-contact-admin": "You don't have access, please contact the admin.",
|
||||||
|
"filed-required-correctly": "Please fill required details correctly.",
|
||||||
|
"admin-created": "Admin created",
|
||||||
|
"invalid-masterkey": "Invalid masterkey",
|
||||||
|
"opensign-Setup": "OpenSign Setup",
|
||||||
|
"master-key": " Master key",
|
||||||
|
"profile-update-alert": "Profile updated successfully.",
|
||||||
|
"date": "Date",
|
||||||
|
"report-not-found": "Report Not Found",
|
||||||
|
"please-wait": "please wait",
|
||||||
|
"select-foler": "Select Folder",
|
||||||
|
"generated-on": "Generated On",
|
||||||
|
"text-field": "Text field",
|
||||||
|
"font-size": "Font size",
|
||||||
|
"widget-status": {
|
||||||
|
"Required": "Required",
|
||||||
|
"Optional": "Optional"
|
||||||
|
},
|
||||||
|
"all-right": "All Rights Reserved",
|
||||||
|
"version": "version",
|
||||||
|
"social-media": {
|
||||||
|
"github": "Github",
|
||||||
|
"linked-in": "LinkedIn",
|
||||||
|
"twitter": "Twitter",
|
||||||
|
"discord": "Discord"
|
||||||
|
},
|
||||||
|
"tour-mssg": {
|
||||||
|
"home-layout-1": "You have logged in successfully! Let's take a look.",
|
||||||
|
"home-layout-2": "To upload documents for self-signing or to request others’ signatures, simply select the respective buttons.",
|
||||||
|
"home-layout-3": "You are ready to start using OpenSign! If you need support feel free to contact us.",
|
||||||
|
"generate-token": "Upgrade now to generate production API token.",
|
||||||
|
"opensign-drive-1": "Click on the breadcrumb links to easily navigate through the folder hierarchy and view the documents within each folder.",
|
||||||
|
"opensign-drive-2": "Click the add button to create a new folder or document.",
|
||||||
|
"opensign-drive-3": "Sort your documents by Date or Name using this menu.",
|
||||||
|
"opensign-drive-4": "Click on this menu to display the documents in list view.",
|
||||||
|
"opensign-drive-5": "The document list is displayed according to the selected sorting option. Icons next to each document indicate its current status.",
|
||||||
|
"opensign-drive-6": "Right-click on a document to see options such as Download, Rename, Move, and Delete. Click on the document to open it.",
|
||||||
|
"opensign-drive-7": "Right-click on any folder to see options. Choose ‘Rename’ to change the folder’s name or click on the folder to navigate through its contents.",
|
||||||
|
"pdf-request-file-1": "List of signers who still need to sign the document .",
|
||||||
|
"pdf-request-file-2": "Click any of the placeholders appearing on the document to sign. You will then see options to draw your signature, type it, or upload an image .",
|
||||||
|
"pdf-request-file-3": "Click the Back, Decline, or Finish buttons to navigate your document. Use the ellipsis menu for additional options, including the Download button .",
|
||||||
|
"pdf-request-file-4": "List of signers who have already signed the document .",
|
||||||
|
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
|
||||||
|
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
|
||||||
|
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
|
||||||
|
"placeholder-sign-3": "Click this button to add more recipients/signers to the document.",
|
||||||
|
"placeholder-sign-4": "Drag or click on a field to add it to the document.",
|
||||||
|
"placeholder-sign-5": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
|
||||||
|
"placeholder-sign-6": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
|
||||||
|
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. ",
|
||||||
|
"redirect": "Click the 'Use' button to create a new document from an existing template.",
|
||||||
|
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
|
||||||
|
"option": "This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but won’t affect existing documents.Use the Delete button you can delete template. ",
|
||||||
|
"signyour-self-1": "Select and drag your preferred widgets onto the PDF to customize your document before signing. Choose the perfect spots for each modification to tailor the document to your needs.",
|
||||||
|
"signyour-self-2": "Drag and drop anywhere in this area. You can resize and move it later.",
|
||||||
|
"template-placeholder-1": "Clicking 'Add role' button will allow you to add various signer roles. You can attach users to each role in subsequent steps.",
|
||||||
|
"template-placeholder-2": "Once roles are added, select a role from list to add a place-holder where he is supposed to sign. The placeholder will appear in the same colour as the role name once you drop it on the document.",
|
||||||
|
"template-placeholder-3": "Drag or click on a field to add it to the document.",
|
||||||
|
"template-placeholder-4": "Drag the placeholder for a role anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.",
|
||||||
|
"template-placeholder-5": "Clicking 'Next' will store the current template. After saving, you’ll be prompted to create a new document from this template if you wish.",
|
||||||
|
"webhook-1": "Upgrade now to set webhook",
|
||||||
|
"Need your Signature": "Clicking on this card will take you to the list of documents awaiting your review.",
|
||||||
|
"Out for signatures": "Clicking on this card will take you to a list of documents awaiting signature.",
|
||||||
|
"Recent signature requests": "This is a list of documents that are waiting for your signature.",
|
||||||
|
"Recently sent for signatures": "This is a list of documents you've sent to other parties for signature.",
|
||||||
|
"Drafts": "This are documents you have started but have not finalized for sending.",
|
||||||
|
"public-template": "This video demonstrates how to set up your personalized public profile, such as ‘https://opensign.me/your-username’. You’ll also learn how to customize your tagline and make your templates available for public signing."
|
||||||
|
},
|
||||||
|
"enter-email-plaholder": "Add an email address and hit enter",
|
||||||
|
"success-email-alert": "Email sent successfully!",
|
||||||
|
"expired-doc-title": "Expired Document",
|
||||||
|
"expired-on-mssg": "This document expired on {{expiredDate}} and is no longer available to sign.",
|
||||||
|
"signature-validate-alert": "Please confirm that you have selected at least {{minRequiredCount}} checkboxes.",
|
||||||
|
"signature-validate-alert-2": "Ensure this field is accurately filled and meets all requirements.",
|
||||||
|
"remaing-users": "Remaining users",
|
||||||
|
"Role": "Role",
|
||||||
|
"additional-users": "Please purchase add-on users.",
|
||||||
|
"Quantity-of-users": "Quantity of users",
|
||||||
|
"Price": "Price",
|
||||||
|
"Total-price-for-next-time": "Total price for next time",
|
||||||
|
"Proceed": "Proceed",
|
||||||
|
"Select": "Select",
|
||||||
|
"Add-seats": "Add Seats",
|
||||||
|
"user-name-exist": "user name already exist",
|
||||||
|
"format": "format",
|
||||||
|
"select-date-format": "Select a date format",
|
||||||
|
"quantity-of-credits": "Quantity of premium credits",
|
||||||
|
"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.",
|
||||||
|
"additional-credits": "Please purchase premium credits",
|
||||||
|
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
|
||||||
|
"buy-credits": "Buy Premium Credits",
|
||||||
|
"rotate-right":"Rotate right",
|
||||||
|
"rotate-left":"Rotate left",
|
||||||
|
"rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?",
|
||||||
|
"templateid":"Template-Id",
|
||||||
|
"bulk-send-subcription-alert":"Please upgrade to Professional or Team plan to use bulk send.",
|
||||||
|
"generate-test-token":"Generate 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-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",
|
||||||
|
"decline-by":"Declined/revoked by",
|
||||||
|
"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-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-4": "Visit the",
|
||||||
|
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||||
|
"public-template-mssg-6" :"Before you can use this code snippet, you must make this template public.",
|
||||||
|
"copy-code":"COPY",
|
||||||
|
"copied-code":"COPIED",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"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.",
|
||||||
|
"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": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests 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-head":"Quota Reached",
|
||||||
|
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
|
||||||
|
"sent-this-month":"Sent this month",
|
||||||
|
"available-seats":"Available seats",
|
||||||
|
"buy-users":"Buy more users",
|
||||||
|
"isenable-otp": "Enable OTP verification",
|
||||||
|
"isenable-otp-help": {
|
||||||
|
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
|
||||||
|
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
|
||||||
|
"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."
|
||||||
|
},
|
||||||
|
"advanced-options":"Advanced options",
|
||||||
|
"hide-advanced-options":"Hide Advanced options",
|
||||||
|
"download-files":"Download files",
|
||||||
|
"download-pdf":"Download Pdf",
|
||||||
|
"pdf-certificate":"Download Pdf + Certificate",
|
||||||
|
"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 Setting",
|
||||||
|
"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>"
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,687 @@
|
|||||||
|
{
|
||||||
|
"header-news": "Nueva funcionalidad: ¡Los perfiles públicos ahora están disponibles! Crea y comparte plantillas públicas fácilmente",
|
||||||
|
"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",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"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": "Se requiere perfil público",
|
||||||
|
"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!",
|
||||||
|
"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",
|
||||||
|
"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": "Has firmado el documento exitosamente. Puedes descargar o imprimir una copia del documento parcialmente firmado. Una copia del documento firmado digitalmente será enviada al propietario mediante correo electrónico una vez haya sido firmado por todos los firmantes.",
|
||||||
|
"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": "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"
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,687 @@
|
|||||||
|
{
|
||||||
|
"header-news": "Nouvelle fonctionnalité : les profils publics sont désormais en ligne ! Créez et partagez facilement des modèles publics",
|
||||||
|
"header-news-btn": "Configurer maintenant",
|
||||||
|
"create-account": "Créer un compte",
|
||||||
|
"login": "Se Connecter",
|
||||||
|
"language": "Langue",
|
||||||
|
"name": "Nom et Prénom",
|
||||||
|
"phone": "Téléphone",
|
||||||
|
"phone-optional": "(facultatif)",
|
||||||
|
"email": "E-mail",
|
||||||
|
"company": "Organisation",
|
||||||
|
"job-title": "Votre Fonction",
|
||||||
|
"profile": "Profil",
|
||||||
|
"is-email-verified": "L'e-mail est-il vérifié",
|
||||||
|
"log-out": "Déconnexion",
|
||||||
|
"public-profile": "Profil public",
|
||||||
|
"tagline": "Slogan",
|
||||||
|
"has-requested-you-to-sign": " vous a demandé de signer",
|
||||||
|
"has-requested-you-to-review-and-sign": "vous a demandé de consulter et de signer",
|
||||||
|
"input-required": "Veuillez remplir ce champ.",
|
||||||
|
"sort-order": {
|
||||||
|
"Ascending": "Ascendant",
|
||||||
|
"Descending": "Descendant",
|
||||||
|
"Name": "Nom et Prénom",
|
||||||
|
"Date": "Date"
|
||||||
|
},
|
||||||
|
"context-menu": {
|
||||||
|
"Download": "Télécharger",
|
||||||
|
"Rename": "Renommer",
|
||||||
|
"Move": "Se déplacer",
|
||||||
|
"Delete": "Supprimer"
|
||||||
|
},
|
||||||
|
"action": "Action",
|
||||||
|
"add": "Ajouter",
|
||||||
|
"add-new-folder": "Ajouter un nouveau dossier",
|
||||||
|
"disable-documentId": "Désactiver l'ID du document",
|
||||||
|
"edit": "Modifier",
|
||||||
|
"change-password": "Changer votre mot de passe",
|
||||||
|
"save": "Sauvegarder",
|
||||||
|
"cancel": "Annuler",
|
||||||
|
"upgrade-now": "Mettre à jour maintenant",
|
||||||
|
"upgrade-to": "Mettre à niveau vers",
|
||||||
|
"pro": "PRO",
|
||||||
|
"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-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",
|
||||||
|
"tour-content": "Ne plus afficher",
|
||||||
|
"team": "Équipe",
|
||||||
|
"docs": "Documents",
|
||||||
|
"session-expired": "Votre session a expiré.",
|
||||||
|
"user": "Utilisateur",
|
||||||
|
"public-profile-help": "Il s'agit de votre URL publique. Copiez-le ou partagez-le avec le signataire et vous pourrez voir tous vos modèles définis publiquement.",
|
||||||
|
"tagline-help": "Ce surnom apparaîtra sur votre profil public OpenSign par exemple. https://opensign.me/alex",
|
||||||
|
"welcome": "Content de te revoir!",
|
||||||
|
"Login-to-your-account": "Se connecter à son compte",
|
||||||
|
"password": "Mot de passe",
|
||||||
|
"forgot-password": "Mot de passe oublié?",
|
||||||
|
"loading": "Chargement...",
|
||||||
|
"of": "de",
|
||||||
|
"sign-SSO": "Connectez-vous avec SSO",
|
||||||
|
"login-page": "Page de connexion",
|
||||||
|
"or": "OU",
|
||||||
|
"signup-page": "Page d'inscription",
|
||||||
|
"password-length": "Le mot de passe doit être de plus de 8 caractères",
|
||||||
|
"password-case": "Le mot de passe doit contenir une lettre majuscule, minuscule et un chiffre ",
|
||||||
|
"password-special-char": "Le mot de passe doit contenir un caractère spécial",
|
||||||
|
"agreee": "Je suis d'accord avec le",
|
||||||
|
"term": "Conditions d'utilisation",
|
||||||
|
"subscribe-to-opensign": "Abonnez-vous à la newsletter OpenSign",
|
||||||
|
"register": "S'enregistrer ",
|
||||||
|
"sidebar": {
|
||||||
|
"Dashboard": "Tableau de bord",
|
||||||
|
"Sign yourself": "signez vous-même",
|
||||||
|
"Request signatures": "Demander des signatures",
|
||||||
|
"Templates": "Modèles",
|
||||||
|
"Templates-Children": {
|
||||||
|
"Create template": "Créer un modèle",
|
||||||
|
"Manage templates": "Gérer les modèles"
|
||||||
|
},
|
||||||
|
"OpenSign™ Drive": "Lecteur OpenSign™",
|
||||||
|
"Reports": "Rapports",
|
||||||
|
"Reports-Children": {
|
||||||
|
"Need your sign": "Besoin de votre signature",
|
||||||
|
"In Progress": "En cours",
|
||||||
|
"Completed": "Complété",
|
||||||
|
"Drafts": "Brouillons",
|
||||||
|
"Declined": "Signature refusé",
|
||||||
|
"Expired": "Expiré",
|
||||||
|
"Contactbook": "Carnet de contacts"
|
||||||
|
},
|
||||||
|
"Settings": "Paramètres",
|
||||||
|
"Settings-Children": {
|
||||||
|
"My Signature": "Ma signature",
|
||||||
|
"API Token": "Jeton API",
|
||||||
|
"Webhook": "Webhook",
|
||||||
|
"Teams": "Équipe",
|
||||||
|
"Team-update-successfully": "Équipe mise à jour avec succès.",
|
||||||
|
"Users": "Utilisateurs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dashboard-card": {
|
||||||
|
"Need your Signature": "Besoin de votre signature",
|
||||||
|
"Out for signatures": "En attente de Signature"
|
||||||
|
},
|
||||||
|
"report-name": {
|
||||||
|
"Draft Documents": "Brouillons",
|
||||||
|
"Need your sign": "Besoin de votre signature",
|
||||||
|
"In-progress documents": "Documents en cours",
|
||||||
|
"Completed Documents": "Documents complétés",
|
||||||
|
"Declined Documents": "Documents refusés",
|
||||||
|
"Expired Documents": "Documents expirés",
|
||||||
|
"Recently sent for signatures": "Récemment envoyé pour signature",
|
||||||
|
"Recent signature requests": "Demandes de signature récentes",
|
||||||
|
"Drafts": "Brouillons",
|
||||||
|
"Contactbook": "Carnet de contacts",
|
||||||
|
"Templates": "Modèles",
|
||||||
|
"Teams": "Équipe",
|
||||||
|
"Users": "Utilisateurs"
|
||||||
|
},
|
||||||
|
"report-heading": {
|
||||||
|
"Sr.No": "Numéro",
|
||||||
|
"Title": "Titre",
|
||||||
|
"Email": "E-mail",
|
||||||
|
"Phone": "Téléphone",
|
||||||
|
"File": "Fichier",
|
||||||
|
"Owner": "Propriétaire",
|
||||||
|
"Signers": "Signataires",
|
||||||
|
"Note": "Note",
|
||||||
|
"Folder": "Dossier",
|
||||||
|
"Reason": "Raison",
|
||||||
|
"Parent Team": "Équipe de parents",
|
||||||
|
"Active": "Actif",
|
||||||
|
"Role": "Rôle",
|
||||||
|
"Team": "Équipe",
|
||||||
|
"Name": "Nom",
|
||||||
|
"Status": "Statut",
|
||||||
|
"created-date": "Date de création",
|
||||||
|
"Type": "Saisir",
|
||||||
|
"Logs": "Journaux"
|
||||||
|
},
|
||||||
|
"btnLabel": {
|
||||||
|
"sign": "Signer",
|
||||||
|
"Resend": "Relancer",
|
||||||
|
"Revoke": "Révoquer",
|
||||||
|
"Delete": "Supprimer",
|
||||||
|
"Use": "Utiliser",
|
||||||
|
"Quick send": "Envoi rapide",
|
||||||
|
"Edit": "Modifier",
|
||||||
|
"Share with team": "Partager avec l'équipe",
|
||||||
|
"Share": "Partager",
|
||||||
|
"View": "Voir",
|
||||||
|
"option": "Option",
|
||||||
|
"Embed": "Intégrer",
|
||||||
|
"Copy TemplateId": "Copier l'ID du modèle",
|
||||||
|
"Copy Public URL":"Copier l'URL publique"
|
||||||
|
},
|
||||||
|
"report-help": {
|
||||||
|
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
|
"Need your sign": "Voici une liste de documents ou votre signature est requise",
|
||||||
|
"In-progress documents": "Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
|
||||||
|
"Completed Documents": "Il s'agit d'une liste de documents signés par toutes les parties.",
|
||||||
|
"Declined Documents": "Il s'agit d'une liste de documents qui ont été refusés par l'un des signataires.",
|
||||||
|
"Expired Documents": "Il s'agit d'une liste de documents qui ont atteint leur date d'expiration.",
|
||||||
|
"Contactbook": "Il s'agit d'une liste de contacts/signataires que vous avez ajoutés. Ceux-ci apparaîtront sous forme de suggestions lorsque vous tenterez d'ajouter des signataires à un nouveau document.",
|
||||||
|
"Templates": "Il s'agit d'une liste de modèles à votre disposition pour créer des documents. Vous pouvez cliquer sur le bouton 'Utiliser' pour créer un nouveau document à l'aide d'un modèle, modifier le document et ajouter des signataires à l'étape suivante."
|
||||||
|
},
|
||||||
|
"form-name": {
|
||||||
|
"Sign Yourself": "signez vous-même",
|
||||||
|
"Request Signatures": "Demander des signatures",
|
||||||
|
"New Template": "Nouveau modèle"
|
||||||
|
},
|
||||||
|
"file-type": "pdf, png, jpg, jpeg",
|
||||||
|
"docx": "docx",
|
||||||
|
"file-selected": "fichier sélectionné",
|
||||||
|
"template-title": "Titre du modèle",
|
||||||
|
"document-title": "Titre du document",
|
||||||
|
"description": "Description",
|
||||||
|
"time-to-complete": "Temps de réalisation (jours)",
|
||||||
|
"send-in-order": "Envoyer dans l'ordre ?",
|
||||||
|
"send-in-order-help": {
|
||||||
|
"p1": "Choisissez la manière dont vous souhaitez que les demandes de signature soient envoyées aux signataires du document :",
|
||||||
|
"p2": "La sélection de cette option enverra initialement la demande de signature au premier signataire. Une fois que le premier signataire a terminé sa partie, le prochain signataire de la séquence recevra la demande. Ce processus se poursuit jusqu'à ce que tous les signataires aient signé le document. Cette méthode garantit que le document est signé dans un ordre spécifique.",
|
||||||
|
"p3": "La sélection de cette option enverra les liens de signature à tous les signataires simultanément. Chaque signataire peut signer le document à sa convenance, que d'autres signataires aient ou non complété leur signature. Cette méthode est plus rapide mais n’impose aucun ordre de signature entre les participants.",
|
||||||
|
"p4": "Sélectionnez l'option qui correspond le mieux aux besoins de votre traitement de documents."
|
||||||
|
},
|
||||||
|
"no": "Non",
|
||||||
|
"auto-reminder": "Rappel automatique",
|
||||||
|
"remind-once": "Rappeler une fois tous les (jours)",
|
||||||
|
"next": "Suivant",
|
||||||
|
"select-folder": "Sélectionner le dossier",
|
||||||
|
"OpenSign-drive": "Lecteur OpenSign™",
|
||||||
|
"drive-document-status": {
|
||||||
|
"Completed": "Complété",
|
||||||
|
"Declined": "Refuser",
|
||||||
|
"Draft": "Brouillon",
|
||||||
|
"Expired": "Expiré",
|
||||||
|
"In Progress": "En cours"
|
||||||
|
},
|
||||||
|
"select-folder-help": "Si vous ne sélectionnez pas de dossier, votre document signé sera enregistré dans le dossier du lecteur principal OpenSign.",
|
||||||
|
"no-data": "Aucune données disponible",
|
||||||
|
"save-here": "Enregistrer ici",
|
||||||
|
"back": "Retour",
|
||||||
|
"add-folder": "Ajouter le dossier",
|
||||||
|
"create-folder": "Créer le dossier",
|
||||||
|
"parent-folder": "Dossier Parent",
|
||||||
|
"create": "Créer",
|
||||||
|
"signers": "Signataires",
|
||||||
|
"signers-help": "Commencez à saisir le nom d'un contact pour voir les signataires suggérés par vos contacts enregistrés ou en ajouter de nouveaux. Organisez l'ordre de signature en ajoutant des signataires dans l'ordre souhaité. Utilisez le bouton « + » pour inclure les signataires et le « x » pour les supprimer. Chaque signataire recevra un e-mail invité à signer le document dans l'ordre indiqué.",
|
||||||
|
"add-signer": "Ajouter un signataire",
|
||||||
|
"contact-not-found": "Contact introuvable",
|
||||||
|
"add-yourself": "Ajoutez-vous",
|
||||||
|
"submit": "Soumettre",
|
||||||
|
"reset": "Réinitialiser",
|
||||||
|
"my-signature": "Ma signature",
|
||||||
|
"signature": "Signature",
|
||||||
|
"upload-image": "Télécharger une image",
|
||||||
|
"clear": "Vider",
|
||||||
|
"upload-signature/Image": "télécharger-signature/Image",
|
||||||
|
"initials": "Initiales",
|
||||||
|
"API": "API",
|
||||||
|
"api-token": "Jeton API",
|
||||||
|
"regenerate-token": "Régénérer en direct jeton",
|
||||||
|
"generate-token": "Générer en direct jeton",
|
||||||
|
"view-docs": "Afficher les documents",
|
||||||
|
"generate-token-alert": "Êtes-vous sûr de vouloir régénérer le jeton, votre ancien jeton sera supprimer?",
|
||||||
|
"yes": "Oui",
|
||||||
|
"copied": "Copié",
|
||||||
|
"wrong-mssg": "Quelque chose c'est mal passé. Merci d'essayer plus tard.",
|
||||||
|
"token-generated": "Jeton généré avec succès.",
|
||||||
|
"webhook": "Webhook",
|
||||||
|
"update-webhook": "Mettre à jour le webhook",
|
||||||
|
"add-webhook": "Ajouter un webhook",
|
||||||
|
"webhook-added": "Webhook ajouté avec succès.",
|
||||||
|
"team-disabled": "Équipe: Désactivée",
|
||||||
|
"team-enabled": "Équipe activée",
|
||||||
|
"are-you-sure": "Êtes-vous sûr de vouloir",
|
||||||
|
"disable": "désactiver",
|
||||||
|
"enable": "activer",
|
||||||
|
"this-team": "cette équipe?",
|
||||||
|
"edit-team": "Modifier l'équipe",
|
||||||
|
"name-of-team": "Nom de l'équipe",
|
||||||
|
"prev": "précédent",
|
||||||
|
"no-data-avaliable": "pas de données disponibles",
|
||||||
|
"add-team": "Ajouter une équipe",
|
||||||
|
"page-not-found": "Page non trouvée",
|
||||||
|
"users-from-teams": "utilisateurs de votre Équipe",
|
||||||
|
"user-status": "Statut de l'utilisateur",
|
||||||
|
"activate": "Activer",
|
||||||
|
"deactivate": "désactiver",
|
||||||
|
"this-user": "cet utilisateur ",
|
||||||
|
"delete-user": "Supprimer l'utilisateur",
|
||||||
|
"delete": "supprimer",
|
||||||
|
"add-user": "Ajouter un utilisateur",
|
||||||
|
"password-generateed": "Le mot de passe ne sera généré qu'une seule fois ; assurez-vous de le copier.",
|
||||||
|
"Team status": "Statut de l'équipe",
|
||||||
|
"user-deactivated": "Utilisateur désactivé.",
|
||||||
|
"user-activated": "Activé par l'utilisateur.",
|
||||||
|
"public": "Public",
|
||||||
|
"download": "Téléchargement",
|
||||||
|
"view": "voir",
|
||||||
|
"make-template-public": "Rendre le modèle public",
|
||||||
|
"make-template-private": "Rendre le modèle privé",
|
||||||
|
"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.",
|
||||||
|
"public-role": "Rôle public",
|
||||||
|
"public-url": "Profil public requis",
|
||||||
|
"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.",
|
||||||
|
"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": "Partager avec",
|
||||||
|
"team-not-found": "Équipe introuvable",
|
||||||
|
"roles": "Les rôles",
|
||||||
|
"delete-document": "Supprimer un document",
|
||||||
|
"delete-document-alert": "Êtes-vous sûr de vouloir supprimer ce document ?",
|
||||||
|
"quick-send": "Envoi rapide",
|
||||||
|
"add-new": "Ajouter un nouveau",
|
||||||
|
"send": "envoyer",
|
||||||
|
"quick-send-alert-1": "Tous les rôles dans ce document sont actuellement liés à des contacts. Pour envoyer rapidement des copies de ce modèle à plusieurs signataires, veuillez vous assurer qu'au moins un rôle n'est lié à aucun contact.",
|
||||||
|
"quick-send-alert-2": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les destinataires.",
|
||||||
|
"quick-send-alert-3": "Veuillez ajouter au moins un rôle à ce modèle afin d'en « envoyer rapidement » des copies à plusieurs signataires.",
|
||||||
|
"quick-send-alert-4": "L'envoi rapide a atteint la limite.",
|
||||||
|
"copy-link": "Copier le lien",
|
||||||
|
"copy": "Copier",
|
||||||
|
"revoke-document": "Révoquer le document",
|
||||||
|
"revoke-document-alert": "Êtes-vous sûr de vouloir révoquer ce document ?",
|
||||||
|
"resend-mail": "Renvoyer le courrier",
|
||||||
|
"resend-mail-help": "Vous pouvez utiliser les variables suivantes qui seront remplacées par leurs valeurs réelles : - {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email} }, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
|
||||||
|
"subject": "Sujet",
|
||||||
|
"body": "Corps",
|
||||||
|
"add-contact": "Ajouter le contact",
|
||||||
|
"add-signer-alert": "Le contact existe déjà !",
|
||||||
|
"record-delete-alert": "Enregistrement supprimé avec succès !",
|
||||||
|
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
|
||||||
|
"mail-sent-alert": "Courriel envoyé avec succès.",
|
||||||
|
"document-sent-alert": "Document envoyé avec succès !",
|
||||||
|
"template-share-alert": "Modèle partagé avec succès.",
|
||||||
|
"template-public-alert-1": "Vous avez rendu le modèle public avec succès.",
|
||||||
|
"template-public-alert-2": "Vous avez réussi à rendre le modèle privé.",
|
||||||
|
"template-public-alert-3": "Vous devez sélectionner un rôle pour les signataires publics.",
|
||||||
|
"template-public-alert-4": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les signataires.",
|
||||||
|
"template-public-alert-5": "Étant donné que l'envoi dans l'ordre est activé sur ce modèle, le rôle public doit être positionné en haut.",
|
||||||
|
"template-public-alert-6": "Veuillez associer des signataires à tous les rôles, à l'exception du rôle d'utilisateur public.",
|
||||||
|
"template-public-alert-7": "Veuillez attribuer au moins un rôle public pour rendre ce modèle public.",
|
||||||
|
"loader": "Cela pourrait prendre un certain temps",
|
||||||
|
"pages": "Pages",
|
||||||
|
"document-signed": "Document signé",
|
||||||
|
"close": "Fermer",
|
||||||
|
"validation-alert": "Alerte de validation",
|
||||||
|
"validate-alert-mssg": "L'entrée ne répond pas aux critères définis par l'expression régulière.",
|
||||||
|
"otp-verification": "Vérification OTP",
|
||||||
|
"enter-otp": "Entrez OTP",
|
||||||
|
"verify": "Vérifier",
|
||||||
|
"verify-email-1": "Vérifier l'e-mail",
|
||||||
|
"resend": "Renvoyer",
|
||||||
|
"contact-details": "Coordonnées",
|
||||||
|
"verify-email": "Veuillez vérifier votre email!",
|
||||||
|
"send-otp": "envoyer un code à usage unique",
|
||||||
|
"otp-placeholder": "Entrez le code de vérification reçu par e-mail",
|
||||||
|
"loading-doc": "Chargement du document..",
|
||||||
|
"widgets-name": {
|
||||||
|
"signature": "signature",
|
||||||
|
"stamp": "tampon",
|
||||||
|
"initials": "initiales",
|
||||||
|
"name": "nom et Prénom",
|
||||||
|
"job title": "votre fonction",
|
||||||
|
"company": "organisation",
|
||||||
|
"date": "date",
|
||||||
|
"text": "texte",
|
||||||
|
"text input": "saisie de texte",
|
||||||
|
"checkbox": "case à cocher",
|
||||||
|
"dropdown": "dérouler",
|
||||||
|
"radio button": "bouton radio",
|
||||||
|
"image": "image",
|
||||||
|
"email": "e-mail"
|
||||||
|
},
|
||||||
|
"fields": "Des champs",
|
||||||
|
"recipients": "Destinataires",
|
||||||
|
"please-add": "Veuillez ajouter un",
|
||||||
|
"signed-by": "Signé par",
|
||||||
|
"more": "plus",
|
||||||
|
"sent": "Envoyé",
|
||||||
|
"print": "imprimer",
|
||||||
|
"certificate": "Certificat",
|
||||||
|
"decline": "refusé",
|
||||||
|
"finish": "terminé",
|
||||||
|
"mail": "Mail",
|
||||||
|
"sign-now": "Signez maintenant",
|
||||||
|
"successfully-signed": "Signé avec succès !",
|
||||||
|
"email-mssg": "Les destinataires ajoutés ici recevront une copie du document signé.",
|
||||||
|
"email-error-1": "veuillez fournir une adresse e-mail correcte",
|
||||||
|
"email-error-2": "Vous ne pouvez envoyer qu'à dix destinataires à la fois.",
|
||||||
|
"Email-verified-alert-1": "L'e-mail est vérifié.",
|
||||||
|
"Email-verified-alert-2": "L'e-mail est déjà vérifié.",
|
||||||
|
"upload-stamp-image": "Télécharger l'image du tampon",
|
||||||
|
"draw": "Dessiner",
|
||||||
|
"type": "Taper",
|
||||||
|
"color-type": {
|
||||||
|
"red": "rouge",
|
||||||
|
"blue": "bleu",
|
||||||
|
"black": "noir",
|
||||||
|
"yellow": "jaune"
|
||||||
|
},
|
||||||
|
"my-initials": "Mes initiales",
|
||||||
|
"upload": "Télécharger",
|
||||||
|
"initial-teb": "Initiales",
|
||||||
|
"signature-tab": "Signature",
|
||||||
|
"your-signature": "Votre signature",
|
||||||
|
"copy-title": "Copier le widget vers",
|
||||||
|
"contact-delete-alert": "Êtes-vous sûr de vouloir supprimer ce contact ?",
|
||||||
|
"reset-password": "Le lien de réinitialisation du mot de passe a été envoyé à votre identifiant de messagerie",
|
||||||
|
"reset-password-alert-2": "Veuillez configurer l'adaptateur de messagerie",
|
||||||
|
"reset-password-alert-3": "Réinitialisez votre mot de passe",
|
||||||
|
"faild-animation": "Échec du chargement de l'animation",
|
||||||
|
"apply": "Appliquer",
|
||||||
|
"copy-type": {
|
||||||
|
"All pages": "Toutes les pages",
|
||||||
|
"All pages but last": "Toutes les pages sauf la dernière",
|
||||||
|
"All pages but first": "Toutes les pages sauf la première",
|
||||||
|
"Next to current widget": "À côté du widget actuel"
|
||||||
|
},
|
||||||
|
"options": "Possibilités",
|
||||||
|
"minimun-check": "Vérification minimale",
|
||||||
|
"maximum-check": "Contrôle maximum",
|
||||||
|
"default-value": "Valeur par défaut",
|
||||||
|
"select": "Sélectionner",
|
||||||
|
"read-only": "Est en lecture seule",
|
||||||
|
"hide-labels": "Masquer les étiquettes",
|
||||||
|
"checkbox": "Case à cocher",
|
||||||
|
"alert": "Alerte",
|
||||||
|
"zoom-in": "Agrandir",
|
||||||
|
"zoom-out": "Dézoomer",
|
||||||
|
"document-signed-alert": "Félicitations ! 🎉 Votre document à bien été signer!",
|
||||||
|
"otp-sent-alert": "Le code OTP a bien été envoyer sur votre adresse Email",
|
||||||
|
"fields-required": "Champs obligatoires",
|
||||||
|
"signature-widget-alert-1": "Veuillez vous assurer qu'au moins un widget de signature a été ajouté",
|
||||||
|
"signature-widget-alert-2": "Veuillez vous assurer que tous les champs sont remplis avec précision et répondent à toutes les exigences.",
|
||||||
|
"encrypted-pdf-alert": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge.",
|
||||||
|
"encrypted-pdf-alert-1": "Le mot de passe du fichier PFX n'est pas valide.",
|
||||||
|
"user-not-exist": "L'utilisateur n'existe pas",
|
||||||
|
"template-signature-field": "Veuillez ajouter au moins un champ de signature pour tous les rôles.",
|
||||||
|
"template-role-alert": "Veuillez d'abord ajouter des rôles",
|
||||||
|
"create-document": "Créer un document",
|
||||||
|
"template-created-alert": "Voulez-vous créer un document en utilisant le modèle que vous vient de créer ?",
|
||||||
|
"signers-alert": "alerte des signataires",
|
||||||
|
"template-creation-alert-1": "Veuillez sélectionner le signataire pour ajouter un espace réservé !",
|
||||||
|
"ok": "D'accord",
|
||||||
|
"radio-group": "Groupe de radio",
|
||||||
|
"dropdown-options": "Options déroulantes",
|
||||||
|
"add-role": "Ajouter un rôle",
|
||||||
|
"role-ex": "Ex : Client, RH, Directeur, Manager, Étudiant, etc.",
|
||||||
|
"add/choose-signer": "Ajouter/Choisir un signataire",
|
||||||
|
"choose-from-contacts": "Choisissez parmis les contacts",
|
||||||
|
"select-signer": "Veuillez sélectionner le signataire",
|
||||||
|
"edit-template": "Modifier le modèle",
|
||||||
|
"widget-info": "Informations sur les widgets",
|
||||||
|
"validation": "Validation",
|
||||||
|
"invalid-default-value": "valeur par défaut invalide",
|
||||||
|
"hint": "Indice",
|
||||||
|
"color": "couleur",
|
||||||
|
"role-help": {
|
||||||
|
"p1": "Que sont les rôles modèles ?",
|
||||||
|
"p2": "Commencez par spécifier chaque rôle nécessaire à la finalisation du document. Pensez aux parties impliquées dans le processus de signature et à leurs responsabilités. Les rôles courants incluent les RH pour les documents internes, le Client pour les accords ou le Fournisseur pour les accords commerciaux.",
|
||||||
|
"p3": "Pourquoi pré-attacher les utilisateurs à certains rôles ?",
|
||||||
|
"p4": "Pour les rôles qui impliquent systématiquement la même personne (par exemple, la signature du PDG sur les lettres d'offre des employés), vous pouvez pré-attacher un utilisateur à un rôle dans le modèle. Cette étape est facultative mais recommandée pour des raisons d'efficacité et de cohérence entre les documents.",
|
||||||
|
"p5": "Quand dois-je spécifier l'utilisateur attaché à chaque rôle ?",
|
||||||
|
"p6": "Lorsque vous créez un document à partir de votre modèle, vous serez invité à attacher des utilisateurs à chaque rôle défini. Si un rôle est déjà associé à un utilisateur, celui-ci sera pré-rempli, mais vous pourrez le modifier si nécessaire avant d'envoyer le document."
|
||||||
|
},
|
||||||
|
"add-recipients": "Ajouter des destinataires",
|
||||||
|
"loading-mssg": "Cela pourrait prendre du temps",
|
||||||
|
"send-mail": "Envoyer un mail",
|
||||||
|
"placeholder-alert-1": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les destinataires.",
|
||||||
|
"placeholder-alert-2": "Veuillez confirmer que vous avez rempli le champ de texte.",
|
||||||
|
"placeholder-alert-3": "Etes-vous sûr de vouloir envoyer ce document pour signature ? ",
|
||||||
|
"placeholder-alert-4": "Vous avez envoyé avec succès des mails à tous les",
|
||||||
|
"placeholder-alert-5": "Voulez-vous signer des documents maintenant ?",
|
||||||
|
"placeholder-alert-6": "Veuillez configurer l'adaptateur de messagerie pour envoyer du courrier !",
|
||||||
|
"placeholder-alert-7": "Veuillez sélectionner le signataire pour ajouter un espace réservé !",
|
||||||
|
"email-subject": "Sujet du courriel",
|
||||||
|
"email-body": "corps de l'e-mail",
|
||||||
|
"email-placeholder": "Ajouter le corps de l'e-mail",
|
||||||
|
"reset-to-default": "Réinitialiser aux valeurs par défaut",
|
||||||
|
"cutomize-email": "Personnaliser l'e-mail",
|
||||||
|
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
|
||||||
|
"sign-url": "Signer l'URL",
|
||||||
|
"Mails Sent": "Mails envoyés avec succès !",
|
||||||
|
"document-alert": "Alerte document",
|
||||||
|
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
|
||||||
|
"subscription-expired": "Abonnement expiré",
|
||||||
|
"alert-message": "Message d'alerte",
|
||||||
|
"document-decline": "Document-refusé",
|
||||||
|
"decline-alert-1": "Etes-vous sûr de vouloir refuser ce document ?",
|
||||||
|
"decline-alert-2": "Vous avez refusé ce document !",
|
||||||
|
"decline-alert-3": "Vous ne pouvez pas signer ce document car il a été refusé/révoqué.",
|
||||||
|
"sign here": "Signer ici",
|
||||||
|
"guest-email-alert": "le code de vérification a été envoyé sur votre e-mail",
|
||||||
|
"get-otp-alert": "vous recevrez un code de vérification par e-mail",
|
||||||
|
"user-already-exist": "L'utilisateur existe déjà.",
|
||||||
|
"server-error": "Erreur interne du serveur !",
|
||||||
|
"fill-required-details!": "Veuillez remplir les informations requises !",
|
||||||
|
"sign-up-form": "Formulaire d'inscription",
|
||||||
|
"sign-up": "S'inscrire",
|
||||||
|
"folder-already-exist!": "le dossier existe déjà !",
|
||||||
|
"please-select-position!": "Veuillez sélectionner un poste !",
|
||||||
|
"default-sign-alert": "Êtes-vous sûr de vouloir vous connecter automatiquement à tous les emplacements demandés ? ",
|
||||||
|
"Your-Signature": "Votre signature",
|
||||||
|
"auto-sign-all": "Tout signer automatiquement",
|
||||||
|
"generating-certificate": "Génération du certificat",
|
||||||
|
"pdf-download": "Téléchargement PDF",
|
||||||
|
"generate-certificate-alert": " Votre certificat d'achèvement est en cours de génération. Veuillez patienter quelques instants. Si le téléchargement ne démarre pas sous peu, cliquez à nouveau sur le bouton. ",
|
||||||
|
"folder-already-exist": "Le dossier existe déjà !",
|
||||||
|
"folder-created-successfully": "Dossier créé avec succès !",
|
||||||
|
"fill-folder-name": "Veuillez indiquer le nom du dossier",
|
||||||
|
"already-exists-this-username": "Un utilisateur existe déjà avec ce nom d'utilisateur !",
|
||||||
|
"verification-code-sent": "Un e-mail de vérification a été envoyé à votre adresse e-mail !",
|
||||||
|
"registered-user-successfully": "Utilisateur enregistré avec succès.",
|
||||||
|
"role-not-found": "Rôle introuvable.",
|
||||||
|
"do-not-access": "Vous n'y avez pas accès, veuillez contacter l'administrateur.",
|
||||||
|
"add-admin": "Ajouter un administrateur",
|
||||||
|
"opensign-setup": "Configuration d'OpenSign",
|
||||||
|
"join-discord": "Rejoignez notre serveur Discord",
|
||||||
|
"admin-already-exist": "L'administrateur existe déjà.",
|
||||||
|
"password-update-alert-1": "Mot de passe mis à jour avec succès.",
|
||||||
|
"password-update-alert-2": "Votre mot de passe actuel est manquant ou incorrect.",
|
||||||
|
"password-update-alert-3": "Votre mot de passe actuel est manquant ou incorrect.",
|
||||||
|
"password-update-alert-4": "Votre mot de passe et votre mot de passe de confirmation ne correspondent pas.",
|
||||||
|
"current-password": "mot de passe actuel",
|
||||||
|
"new-password": "nouveau mot de passe",
|
||||||
|
"confirm-password": "Confirmez le mot de passe",
|
||||||
|
"file-alert-1": "La taille du fichier sélectionné est trop grande. Veuillez sélectionner un fichier inférieur à",
|
||||||
|
"file-alert-2": "Veuillez sélectionner un fichier.",
|
||||||
|
"file-alert-3": "Veuillez patienter pendant le téléchargement du document.",
|
||||||
|
"enter-pdf-password": "Entrez le mot de passe PDF",
|
||||||
|
"correct-password": "Veuillez fournir un mot de passe correct",
|
||||||
|
"decrypting-pdf": "Décryptage du pdf, veuillez patienter...",
|
||||||
|
"invalid-otp": "OTP invalide",
|
||||||
|
"user-not-found": "Utilisateur non trouvé!",
|
||||||
|
"enter-otp-alert": "Veuillez saisir OTP !",
|
||||||
|
"get-verification-code": "Obtenir le code de vérification",
|
||||||
|
"get-verification-code-2": "Vous recevrez un code de vérification par e-mail",
|
||||||
|
"enter-verification-code": "Entrez le code de vérification",
|
||||||
|
"provide-your-details": "Fournissez vos coordonnées",
|
||||||
|
"provide-email": "Veuillez fournir un e-mail.",
|
||||||
|
"additional-info": "Information additionnelle",
|
||||||
|
"signature-saved-alert": "Signature enregistrée avec succès.",
|
||||||
|
"fill-field": "Veuillez remplir ce champ",
|
||||||
|
"error-template": "Erreur : modèle introuvable ! ",
|
||||||
|
"error": "Erreur",
|
||||||
|
"invalid-document": "Erreur : document invalide !",
|
||||||
|
"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.",
|
||||||
|
"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-5": "Ce document a été signé par tous les signataires.",
|
||||||
|
"document-signed-alert-6": "Ce document a été refusé par un ou plusieurs destinataire(s).",
|
||||||
|
"document-signed-alert-7": "Ce document n'est plus disponible.",
|
||||||
|
"document-signed-alert-8": "Le document a déjà été envoyé pour signature.",
|
||||||
|
"yet-to-sign": "Reste à signer",
|
||||||
|
"validation-alert-1": "L'entrée ne répond pas aux critères définis par l'expression régulière.",
|
||||||
|
"account-already-exists": "Le compte existe déjà!",
|
||||||
|
"choose-password": "Choisissez un mot de passe",
|
||||||
|
"enter-password": "Entrer le mot de passe",
|
||||||
|
"sure": "bien sûr",
|
||||||
|
"subscribed-alert": "Vous êtes déjà abonné au forfait !",
|
||||||
|
"monthly": "Mensuel",
|
||||||
|
"yearly-upto": "Annuel (jusqu'à 66 % de réduction)",
|
||||||
|
"billed-yearly": "Facturé annuellement",
|
||||||
|
"billed-monthly": "Facturé mensuellement",
|
||||||
|
"plansubscription-1": "Hébergez-le vous-même gratuitement",
|
||||||
|
"visit-github": "Visitez Github",
|
||||||
|
"user-already-exist-name": "Un utilisateur existe déjà avec ce nom d'utilisateur !",
|
||||||
|
"do-not-access-contact-admin": "Vous n'y avez pas accès, veuillez contacter l'administrateur.",
|
||||||
|
"filed-required-correctly": "Veuillez remplir correctement les informations requises.",
|
||||||
|
"admin-created": "Administrateur créé",
|
||||||
|
"invalid-masterkey": "Clé principale invalide",
|
||||||
|
"opensign-Setup": "Configuration d'OpenSign",
|
||||||
|
"master-key": "La clef maitresse",
|
||||||
|
"profile-update-alert": "Mise à jour du profil réussie.",
|
||||||
|
"date": "Date",
|
||||||
|
"report-not-found": "Rapport introuvable",
|
||||||
|
"please-wait": "S'il vous plaît, attendez",
|
||||||
|
"select-foler": "Sélectionner le dossier",
|
||||||
|
"generated-on": "Généré le",
|
||||||
|
"text-field": "Champ de texte",
|
||||||
|
"font-size": "Taille de police",
|
||||||
|
"widget-status": {
|
||||||
|
"Required": "Requis",
|
||||||
|
"Optional": "Facultative"
|
||||||
|
},
|
||||||
|
"all-right": "Tous droits réservés",
|
||||||
|
"version": "version",
|
||||||
|
"social-media": {
|
||||||
|
"github": "Github",
|
||||||
|
"linked-in": "LinkedIn",
|
||||||
|
"twitter": "Twitter",
|
||||||
|
"discord": "Discorde"
|
||||||
|
},
|
||||||
|
"tour-mssg": {
|
||||||
|
"home-layout-1": "Vous vous êtes connecté avec succès ! Jetons un coup d'oeil.",
|
||||||
|
"home-layout-2": "Pour télécharger des documents à auto-signature ou pour demander la signature d'autres personnes, sélectionnez simplement les boutons correspondants.",
|
||||||
|
"home-layout-3": "Vous êtes prêt à commencer à utiliser OpenSign ! Si vous avez besoin d'aide, n'hésitez pas à nous contacter.",
|
||||||
|
"generate-token": "Effectuez la mise à niveau maintenant pour générer un jeton API de production.",
|
||||||
|
"opensign-drive-1": "Cliquez sur les liens du fil d'Ariane pour naviguer facilement dans la hiérarchie des dossiers et afficher les documents dans chaque dossier.",
|
||||||
|
"opensign-drive-2": "Cliquez sur le bouton Ajouter pour créer un nouveau dossier ou document.",
|
||||||
|
"opensign-drive-3": "Triez vos documents par date ou par nom à l'aide de ce menu.",
|
||||||
|
"opensign-drive-4": "Cliquez sur ce menu pour afficher les documents sous forme de liste.",
|
||||||
|
"opensign-drive-5": "La liste des documents s'affiche selon l'option de tri sélectionnée. Les icônes à côté de chaque document indiquent son état actuel.",
|
||||||
|
"opensign-drive-6": "Faites un clic droit sur un document pour voir les options telles que Télécharger, Renommer, Déplacer et Supprimer. Cliquez sur le document pour l'ouvrir.",
|
||||||
|
"opensign-drive-7": "Faites un clic droit sur n'importe quel dossier pour voir les options. Choisissez 'Renommer' pour changer le nom du dossier ou cliquez sur le dossier pour naviguer dans son contenu.",
|
||||||
|
"pdf-request-file-1": "Liste des signataires qui doivent encore signer le document.",
|
||||||
|
"pdf-request-file-2": "Cliquez sur l'un des espaces réservés apparaissant sur le document pour signer. Vous verrez alors des options pour dessiner votre signature, la saisir ou télécharger une image.",
|
||||||
|
"pdf-request-file-3": "Cliquez sur les boutons Précédent, Refuser ou Terminer pour parcourir votre document. Utilisez le menu points de suspension pour des options supplémentaires, notamment le bouton Télécharger.",
|
||||||
|
"pdf-request-file-4": "Liste des signataires ayant déjà signé le document.",
|
||||||
|
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
|
||||||
|
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
|
||||||
|
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
|
||||||
|
"placeholder-sign-3": "Cliquez sur ce bouton pour ajouter plus de destinataires/signataires au document",
|
||||||
|
"placeholder-sign-4": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
||||||
|
"placeholder-sign-5": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
|
||||||
|
"placeholder-sign-6": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
|
||||||
|
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
|
||||||
|
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
|
||||||
|
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
|
||||||
|
"option": "Ce menu révèle plus d'options telles que Modifier et Supprimer. Utilisez le bouton « Modifier » pour ajouter des rôles de signataire, modifier les champs et mettre à jour votre modèle. Les modifications s'appliqueront à tous les futurs documents créés à partir de ce modèle mais n'affecteront pas les documents existants. Utilisez le bouton Supprimer, vous pouvez supprimer le modèle ",
|
||||||
|
"signyour-self-1": "Sélectionnez et faites glisser vos widgets préférés sur le PDF pour personnaliser votre document avant de le signer. Choisissez les endroits parfaits pour chaque modification afin d'adapter le document à vos besoins.",
|
||||||
|
"signyour-self-2": "Faites glisser et déposer n'importe où dans cette zone. Vous pourrez la redimensionner et la déplacer plus tard.",
|
||||||
|
"template-placeholder-1": "Cliquer sur le bouton 'Ajouter un rôle' vous permettra d'ajouter différents rôles de signataire. Vous pourrez attacher des utilisateurs à chaque rôle dans les étapes suivantes.",
|
||||||
|
"template-placeholder-2": "Une fois les rôles ajoutés, sélectionnez un rôle dans la liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra dans la même couleur que le nom du rôle une fois que vous l'aurez déposé sur le document.",
|
||||||
|
"template-placeholder-3": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
||||||
|
"template-placeholder-4": "Faites glisser l'espace réservé pour un rôle n'importe où sur le document. N'oubliez pas qu'il apparaîtra dans la même couleur que le nom du destinataire pour une référence facile.",
|
||||||
|
"template-placeholder-5": "Cliquer sur 'Suivant' stockera le modèle actuel. Après l'enregistrement, vous serez invité à créer un nouveau document à partir de ce modèle si vous le souhaitez.",
|
||||||
|
"webhook-1": "Mettez à niveau maintenant pour définir le webhook",
|
||||||
|
"Need your Signature": "En cliquant sur cette carte, vous accéderez à la liste des documents en attente de révision.",
|
||||||
|
"Out for signatures": "En cliquant sur cette carte, vous accéderez à une liste de documents en attente de signature.",
|
||||||
|
"Recent signature requests": "Voici une liste de documents qui attendent votre signature.",
|
||||||
|
"Recently sent for signatures": "Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
|
||||||
|
"Drafts": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
|
"public-template": "Cette vidéo montre comment configurer votre profil public personnalisé, tel que 'https://opensign.me/your-username'. Vous apprendrez également comment personnaliser votre slogan et rendre vos modèles disponibles pour la signature publique."
|
||||||
|
},
|
||||||
|
"enter-email-plaholder": "Ajoutez une adresse email et appuyez sur Entrée",
|
||||||
|
"success-email-alert": "E-mail envoyé avec succès!",
|
||||||
|
"expired-doc-title": "Document expiré",
|
||||||
|
"expired-on-mssg": "Ce document a expiré le {{expiredDate}} et n'est plus disponible pour signature.",
|
||||||
|
"signature-validate-alert": "Veuillez confirmer que vous avez coché au moins {{minRequiredCount}} cases.",
|
||||||
|
"signature-validate-alert-2": "Assurez-vous que ce champ est rempli avec précision et répond à toutes les exigences.",
|
||||||
|
"user-name-exist": "le nom d'utilisateur existe déjà",
|
||||||
|
"remaing-users": "Utilisateurs restants",
|
||||||
|
"Role": "Rôle",
|
||||||
|
"additional-users": "Veuillez acheter des utilisateurs supplémentaires.",
|
||||||
|
"Quantity-of-users": "Quantité d'utilisateurs",
|
||||||
|
"Price": "Prix",
|
||||||
|
"Total-price-for-next-time": "Prix total pour la prochaine fois",
|
||||||
|
"Proceed": "Procéder",
|
||||||
|
"Select": "sélectionner",
|
||||||
|
"Add-seats": "Ajouter des sièges",
|
||||||
|
"format": "format",
|
||||||
|
"select-date-format": "Sélectionnez un format de date",
|
||||||
|
"quantity-of-credits":"Quantité de crédits de prime",
|
||||||
|
"remaining-credits":"Crédits premium disponibles :",
|
||||||
|
"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.",
|
||||||
|
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
|
||||||
|
"buy-credits": "Acheter des crédits premium",
|
||||||
|
"rotate-right" :"Faire pivoter à droite",
|
||||||
|
"rotate-left" :"Faire pivoter à gauche",
|
||||||
|
"rotate-alert-mssg" :"Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
|
||||||
|
"templateid":"ID de modèle",
|
||||||
|
"bulk-send-subcription-alert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
|
||||||
|
"generate-test-token": "Générer 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-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",
|
||||||
|
"decline-by" :"Refusé/révoqué par",
|
||||||
|
"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-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-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-6":"Avant de pouvoir utiliser cet extrait de code, vous devez rendre ce modèle public.",
|
||||||
|
"copy-code":"COPIE",
|
||||||
|
"copied-code":"COPIÉ",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"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.",
|
||||||
|
"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": "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": "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-head":"Quota atteint",
|
||||||
|
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
|
||||||
|
"sent-this-month":"envoyé ce mois-ci",
|
||||||
|
"available-seats":"Disponible sièges",
|
||||||
|
"buy-users":"Acheter plus d'utilisateurs",
|
||||||
|
"isenable-otp": "Activer la vérification OTP",
|
||||||
|
"isenable-otp-help": {
|
||||||
|
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
|
||||||
|
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
|
||||||
|
"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."
|
||||||
|
},
|
||||||
|
"advanced-options":"Options avancées",
|
||||||
|
"hide-advanced-options": "Masquer les options avancées",
|
||||||
|
"download-files" :"Télécharger des fichiers",
|
||||||
|
"download-pdf" :"Télécharger le PDF",
|
||||||
|
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
||||||
|
"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>"
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -20,6 +20,7 @@ import SSOVerify from "./pages/SSOVerify";
|
|||||||
import Loader from "./primitives/Loader";
|
import Loader from "./primitives/Loader";
|
||||||
import TeamList from "./pages/TeamList";
|
import TeamList from "./pages/TeamList";
|
||||||
import UserList from "./pages/UserList";
|
import UserList from "./pages/UserList";
|
||||||
|
import { serverUrl_fn } from "./constant/appinfo";
|
||||||
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
||||||
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
||||||
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
||||||
@@ -53,9 +54,7 @@ function App() {
|
|||||||
const appId = process.env.REACT_APP_APPID
|
const appId = process.env.REACT_APP_APPID
|
||||||
? process.env.REACT_APP_APPID
|
? process.env.REACT_APP_APPID
|
||||||
: "opensign";
|
: "opensign";
|
||||||
const baseurl = process.env.REACT_APP_SERVERURL
|
const baseurl = serverUrl_fn();
|
||||||
? process.env.REACT_APP_SERVERURL
|
|
||||||
: window.location.origin + "/api/app";
|
|
||||||
try {
|
try {
|
||||||
localStorage.setItem("baseUrl", `${baseurl}/`);
|
localStorage.setItem("baseUrl", `${baseurl}/`);
|
||||||
localStorage.setItem("parseAppId", appId);
|
localStorage.setItem("parseAppId", appId);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
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";
|
||||||
|
|
||||||
const AddSigner = (props) => {
|
const AddSigner = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [phone, setPhone] = useState("");
|
const [phone, setPhone] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -167,17 +169,17 @@ const AddSigner = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Contact already exist!");
|
alert(t("add-signer-alert"));
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in fetch contact", err);
|
console.log("err in fetch contact", err);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert("something went wrong, please try again later");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert("something went wrong, please try again later");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -214,14 +216,14 @@ const AddSigner = (props) => {
|
|||||||
className="op-checkbox op-checkbox-sm"
|
className="op-checkbox op-checkbox-sm"
|
||||||
/>
|
/>
|
||||||
<label htmlFor="addYourself" className="ml-2 mb-0">
|
<label htmlFor="addYourself" className="ml-2 mb-0">
|
||||||
Add Yourself
|
{t("add-yourself")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="name" className="block text-xs font-semibold">
|
<label htmlFor="name" className="block text-xs font-semibold">
|
||||||
Name
|
{t("name")}
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -231,27 +233,33 @@ const AddSigner = (props) => {
|
|||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
required
|
required
|
||||||
disabled={addYourself}
|
disabled={addYourself}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
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>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="email" className="block text-xs font-semibold">
|
<label htmlFor="email" className="block text-xs font-semibold">
|
||||||
Email
|
{t("email")}
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
id="email"
|
id="email"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
|
onChange={(e) =>
|
||||||
|
setEmail(e.target.value?.toLowerCase()?.replace(/\s/g, ""))
|
||||||
|
}
|
||||||
required
|
required
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
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"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="phone" className="block text-xs font-semibold">
|
<label htmlFor="phone" className="block text-xs font-semibold">
|
||||||
Phone
|
{t("phone")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -264,14 +272,14 @@ const AddSigner = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex gap-x-2 justify-start">
|
<div className="mt-4 flex gap-x-2 justify-start">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleReset()}
|
onClick={() => handleReset()}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
Reset
|
{t("reset")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Title from "./Title";
|
import Title from "./Title";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const AddTeam = (props) => {
|
const AddTeam = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [formdata, setFormdata] = useState({
|
const [formdata, setFormdata] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
team: ""
|
team: ""
|
||||||
@@ -17,7 +19,7 @@ const AddTeam = (props) => {
|
|||||||
const getTeamList = async () => {
|
const getTeamList = async () => {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
try {
|
try {
|
||||||
const teams = await Parse.Cloud.run("getteams");
|
const teams = await Parse.Cloud.run("getteams", { active: true });
|
||||||
const teamRes = JSON.parse(JSON.stringify(teams));
|
const teamRes = JSON.parse(JSON.stringify(teams));
|
||||||
if (teamRes.length > 0) {
|
if (teamRes.length > 0) {
|
||||||
const _teamRes = JSON.parse(JSON.stringify(teamRes));
|
const _teamRes = JSON.parse(JSON.stringify(teamRes));
|
||||||
@@ -125,10 +127,10 @@ const AddTeam = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
|
<div className="shadow-md rounded-box my-[1px] p-3 bg-base-100 relative">
|
||||||
<Title title="Add Team" />
|
<Title title="Add Team" />
|
||||||
{isLoader && (
|
{isLoader && (
|
||||||
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50 rounded-box">
|
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
|
||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -140,7 +142,7 @@ const AddTeam = (props) => {
|
|||||||
htmlFor="name"
|
htmlFor="name"
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
>
|
>
|
||||||
Name
|
{t("name")}
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -148,6 +150,8 @@ const AddTeam = (props) => {
|
|||||||
name="name"
|
name="name"
|
||||||
value={formdata.name}
|
value={formdata.name}
|
||||||
onChange={(e) => handleChange(e)}
|
onChange={(e) => handleChange(e)}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
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"
|
||||||
/>
|
/>
|
||||||
@@ -157,7 +161,7 @@ const AddTeam = (props) => {
|
|||||||
htmlFor="phone"
|
htmlFor="phone"
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
>
|
>
|
||||||
Parent Team
|
{t("report-heading.Parent Team")}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={formdata.team}
|
value={formdata.team}
|
||||||
@@ -175,14 +179,14 @@ const AddTeam = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center mt-3 gap-2 text-white">
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleReset()}
|
onClick={() => handleReset()}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
Reset
|
{t("reset")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Title from "./Title";
|
import Title from "./Title";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { copytoData } from "../constant/Utils";
|
import { copytoData, fetchSubscriptionInfo } from "../constant/Utils";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function generatePassword(length) {
|
function generatePassword(length) {
|
||||||
const characters =
|
const characters =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
@@ -17,6 +18,7 @@ function generatePassword(length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AddUser = (props) => {
|
const AddUser = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [formdata, setFormdata] = useState({
|
const [formdata, setFormdata] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
phone: "",
|
phone: "",
|
||||||
@@ -25,25 +27,66 @@ const AddUser = (props) => {
|
|||||||
password: "",
|
password: "",
|
||||||
role: ""
|
role: ""
|
||||||
});
|
});
|
||||||
|
const [amount, setAmount] = useState({ quantity: 1, price: 0 });
|
||||||
|
const [planInfo, setPlanInfo] = useState({
|
||||||
|
priceperUser: 0,
|
||||||
|
price: 0,
|
||||||
|
totalAllowedUser: 0,
|
||||||
|
adminId: ""
|
||||||
|
});
|
||||||
|
const [isFormLoader, setIsFormLoader] = useState(false);
|
||||||
const [isLoader, setIsLoader] = useState(false);
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
const [teamList, setTeamList] = useState([]);
|
const [teamList, setTeamList] = useState([]);
|
||||||
|
const [allowedUser, setAllowedUser] = useState(0);
|
||||||
|
const [err, setErr] = useState("");
|
||||||
const role = ["OrgAdmin", "Editor", "User"];
|
const role = ["OrgAdmin", "Editor", "User"];
|
||||||
|
const extUser =
|
||||||
|
localStorage.getItem("Extand_Class") &&
|
||||||
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getTeamList();
|
getTeamList();
|
||||||
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getTeamList = async () => {
|
const getTeamList = async () => {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
try {
|
||||||
|
setIsLoader(true);
|
||||||
|
const resSub = await fetchSubscriptionInfo();
|
||||||
|
if (!resSub.error) {
|
||||||
|
setPlanInfo((prev) => ({
|
||||||
|
...prev,
|
||||||
|
priceperUser: resSub.price,
|
||||||
|
totalAllowedUser: resSub.totalAllowedUser,
|
||||||
|
adminId: resSub.adminId
|
||||||
|
}));
|
||||||
|
setAmount((prev) => ({ ...prev, price: resSub.price }));
|
||||||
|
const res = await Parse.Cloud.run("allowedusers");
|
||||||
|
if (props.setFormHeader) {
|
||||||
|
if (res > 0) {
|
||||||
|
props.setFormHeader(t("add-user"));
|
||||||
|
} else {
|
||||||
|
props.setFormHeader(
|
||||||
|
resSub.adminId !== extUser?.objectId
|
||||||
|
? "Unauthorized"
|
||||||
|
: t("Add-seats")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAllowedUser(res);
|
||||||
|
} else {
|
||||||
|
setAllowedUser(0);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setAllowedUser(0);
|
||||||
|
console.log("Err in alloweduser", err);
|
||||||
|
setErr(err.message);
|
||||||
|
} finally {
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
setFormdata((prev) => ({ ...prev, password: generatePassword(12) }));
|
setFormdata((prev) => ({ ...prev, password: generatePassword(12) }));
|
||||||
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
const teamRes = await Parse.Cloud.run("getteams", { active: true });
|
||||||
const team = new Parse.Query("contracts_Teams");
|
|
||||||
team.equalTo("OrganizationId", {
|
|
||||||
__type: "Pointer",
|
|
||||||
className: "contracts_Organizations",
|
|
||||||
objectId: extUser.OrganizationId.objectId
|
|
||||||
});
|
|
||||||
team.notEqualTo("IsActive", false);
|
|
||||||
const teamRes = await team.find();
|
|
||||||
if (teamRes.length > 0) {
|
if (teamRes.length > 0) {
|
||||||
const _teamRes = JSON.parse(JSON.stringify(teamRes));
|
const _teamRes = JSON.parse(JSON.stringify(teamRes));
|
||||||
setTeamList(_teamRes);
|
setTeamList(_teamRes);
|
||||||
@@ -73,14 +116,12 @@ const AddUser = (props) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
setIsLoader(true);
|
setIsFormLoader(true);
|
||||||
const res = await checkUserExist();
|
const res = await checkUserExist();
|
||||||
if (res) {
|
if (res) {
|
||||||
props.setIsAlert({ type: "danger", msg: "User already exist." });
|
props.setIsAlert({ type: "danger", msg: t("user-already-exist") });
|
||||||
setIsLoader(false);
|
setIsFormLoader(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1000);
|
||||||
props.setIsAlert({ type: "success", msg: "" });
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const extUser = new Parse.Object("contracts_Users");
|
const extUser = new Parse.Object("contracts_Users");
|
||||||
@@ -163,14 +204,8 @@ const AddUser = (props) => {
|
|||||||
props.handleUserData(parseData);
|
props.handleUserData(parseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoader(false);
|
setIsFormLoader(false);
|
||||||
setFormdata({
|
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
|
||||||
name: "",
|
|
||||||
email: "",
|
|
||||||
phone: "",
|
|
||||||
team: "",
|
|
||||||
role: ""
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
@@ -210,20 +245,17 @@ const AddUser = (props) => {
|
|||||||
}
|
}
|
||||||
props.handleUserData(parseData);
|
props.handleUserData(parseData);
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
setIsFormLoader(false);
|
||||||
setFormdata({
|
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
|
||||||
name: "",
|
|
||||||
email: "",
|
|
||||||
phone: "",
|
|
||||||
team: "",
|
|
||||||
role: ""
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err", err);
|
console.log("err", err);
|
||||||
setIsLoader(false);
|
setIsFormLoader(false);
|
||||||
props.setIsAlert({ type: "danger", msg: "something went wrong." });
|
props.setIsAlert({
|
||||||
|
type: "danger",
|
||||||
|
msg: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500);
|
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500);
|
||||||
}
|
}
|
||||||
@@ -232,173 +264,289 @@ const AddUser = (props) => {
|
|||||||
|
|
||||||
// Define a function to handle the "add yourself" checkbox
|
// Define a function to handle the "add yourself" checkbox
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setFormdata({
|
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
|
||||||
name: "",
|
|
||||||
email: "",
|
|
||||||
phone: "",
|
|
||||||
team: "",
|
|
||||||
role: ""
|
|
||||||
});
|
|
||||||
if (props.closePopup) {
|
if (props.closePopup) {
|
||||||
props.closePopup();
|
props.closePopup();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleChange = (e) => {
|
const handleChange = (event) => {
|
||||||
setFormdata((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
let { name, value } = event.target;
|
||||||
|
if (name === "email") {
|
||||||
|
value = value?.toLowerCase()?.replace(/\s/g, "");
|
||||||
|
}
|
||||||
|
setFormdata((prev) => ({ ...prev, [name]: value }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const copytoclipboard = (text) => {
|
const copytoclipboard = (text) => {
|
||||||
copytoData(text);
|
copytoData(text);
|
||||||
props.setIsAlert({ type: "success", msg: "Copied" });
|
props.setIsAlert({ type: "success", msg: t("copied") });
|
||||||
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
|
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
|
||||||
};
|
};
|
||||||
|
const handlePricePerUser = (e) => {
|
||||||
|
const quantity = e.target.value;
|
||||||
|
const price = e.target?.value > 0 ? planInfo.priceperUser * quantity : 0;
|
||||||
|
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
|
||||||
|
};
|
||||||
|
const handleAddOnSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsFormLoader(true);
|
||||||
|
try {
|
||||||
|
const resAddon = await Parse.Cloud.run("buyaddonusers", {
|
||||||
|
users: amount.quantity
|
||||||
|
});
|
||||||
|
if (resAddon) {
|
||||||
|
const _resAddon = JSON.parse(JSON.stringify(resAddon));
|
||||||
|
if (_resAddon.status === "success") {
|
||||||
|
setAllowedUser(amount.quantity);
|
||||||
|
setPlanInfo((obj) => ({ ...obj, totalAllowedUser: _resAddon.addon }));
|
||||||
|
}
|
||||||
|
if (props.handleBuyUsers) {
|
||||||
|
props.handleBuyUsers(amount.quantity, _resAddon.addon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in buy addon", err);
|
||||||
|
props.setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
|
} finally {
|
||||||
|
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 2000);
|
||||||
|
setIsFormLoader(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
|
<div className="shadow-md rounded-box my-[1px] p-3 bg-base-100 relative">
|
||||||
<Title title={"Add User"} />
|
<Title title={t("add-user")} />
|
||||||
{isLoader && (
|
{isFormLoader && (
|
||||||
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50 rounded-box">
|
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
|
||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="w-full mx-auto">
|
{!isLoader ? (
|
||||||
<form onSubmit={handleSubmit}>
|
<>
|
||||||
{/* <h1 className="text-[20px] font-semibold mb-4">Add User</h1> */}
|
{err ? (
|
||||||
<div className="mb-3">
|
<div className="flex justify-center items-center h-[70px] text-[18px]">
|
||||||
<label
|
{err}
|
||||||
htmlFor="name"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Name
|
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
value={formdata.name}
|
|
||||||
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"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<label
|
|
||||||
htmlFor="email"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Email
|
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
name="email"
|
|
||||||
value={formdata.email}
|
|
||||||
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"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<label
|
|
||||||
htmlFor="email"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Password
|
|
||||||
</label>
|
|
||||||
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm text-base-content w-full h-full text-[13px]">
|
|
||||||
<div className="break-all">{formdata?.password}</div>
|
|
||||||
<i
|
|
||||||
onClick={() => copytoclipboard(formdata?.password)}
|
|
||||||
className="fa-light fa-copy rounded-full hover:bg-base-300 p-[8px] cursor-pointer "
|
|
||||||
></i>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[12px] ml-2 mb-0 text-[red] select-none">
|
) : (
|
||||||
Password will only be generated once; make sure to copy it.
|
<div className="w-full mx-auto">
|
||||||
</div>
|
{!isEnableSubscription || allowedUser > 0 ? (
|
||||||
</div>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="mb-3">
|
{isEnableSubscription && (
|
||||||
<label
|
<p className="flex justify-center mb-1">
|
||||||
htmlFor="phone"
|
{t("remaing-users")}{" "}
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
<span
|
||||||
>
|
className={`${
|
||||||
Phone
|
allowedUser < 2 ? "op-text-accent" : "op-text-primary"
|
||||||
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
} font-medium ml-1`}
|
||||||
</label>
|
>
|
||||||
<input
|
{allowedUser} {t("of")} {planInfo.totalAllowedUser}
|
||||||
type="text"
|
</span>
|
||||||
name="phone"
|
</p>
|
||||||
placeholder="optional"
|
)}
|
||||||
value={formdata.phone}
|
<div className="mb-3">
|
||||||
onChange={(e) => handleChange(e)}
|
<label
|
||||||
// required
|
htmlFor="name"
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
/>
|
>
|
||||||
</div>
|
{t("name")}
|
||||||
{isEnableSubscription && (
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
<div className="mb-3">
|
</label>
|
||||||
<label
|
<input
|
||||||
htmlFor="phone"
|
type="text"
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
name="name"
|
||||||
>
|
value={formdata.name}
|
||||||
Team<span className="text-[red] text-[13px]"> *</span>
|
onChange={(e) => handleChange(e)}
|
||||||
</label>
|
onInvalid={(e) =>
|
||||||
<select
|
e.target.setCustomValidity(t("input-required"))
|
||||||
value={formdata.team}
|
}
|
||||||
onChange={(e) => handleChange(e)}
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
name="team"
|
required
|
||||||
className="op-select op-select-bordered op-select-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"
|
||||||
required
|
/>
|
||||||
>
|
</div>
|
||||||
<option defaultValue={""} value={""}>
|
<div className="mb-3">
|
||||||
select
|
<label
|
||||||
</option>
|
htmlFor="email"
|
||||||
{teamList.length > 0 &&
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
teamList.map((x) => (
|
>
|
||||||
<option key={x.objectId} value={x.objectId}>
|
{t("email")}
|
||||||
{x.Name}
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</option>
|
</label>
|
||||||
))}
|
<input
|
||||||
</select>
|
type="email"
|
||||||
|
name="email"
|
||||||
|
value={formdata.email}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
required
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="block text-xs text-gray-700 font-semibold">
|
||||||
|
{t("password")}
|
||||||
|
</label>
|
||||||
|
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm text-base-content w-full h-full text-[13px]">
|
||||||
|
<div className="break-all">{formdata?.password}</div>
|
||||||
|
<i
|
||||||
|
onClick={() => copytoclipboard(formdata?.password)}
|
||||||
|
className="fa-light fa-copy rounded-full hover:bg-base-300 p-[8px] cursor-pointer "
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
<div className="text-[12px] ml-2 mb-0 text-[red] select-none">
|
||||||
|
{t("password-generateed")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="phone"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("phone")}
|
||||||
|
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="phone"
|
||||||
|
placeholder="optional"
|
||||||
|
value={formdata.phone}
|
||||||
|
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"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{isEnableSubscription && (
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="phone"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("team")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
name="team"
|
||||||
|
value={formdata.team}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option defaultValue={""} value={""}>
|
||||||
|
{t("Select")}
|
||||||
|
</option>
|
||||||
|
{teamList.length > 0 &&
|
||||||
|
teamList.map((x) => (
|
||||||
|
<option key={x.objectId} value={x.objectId}>
|
||||||
|
{x.Name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="mb-3">
|
||||||
|
<label
|
||||||
|
htmlFor="phone"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("Role")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
value={formdata.role}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
name="role"
|
||||||
|
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option defaultValue={""} value={""}>
|
||||||
|
{t("Select")}
|
||||||
|
</option>
|
||||||
|
{role.length > 0 &&
|
||||||
|
role.map((x) => (
|
||||||
|
<option key={x} value={x}>
|
||||||
|
{x}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
|
{t("submit")}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleReset()}
|
||||||
|
className="op-btn op-btn-secondary"
|
||||||
|
>
|
||||||
|
{t("cancel")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{planInfo.adminId !== extUser?.objectId ? (
|
||||||
|
<div className="mb-3 mt-1 flex justify-center text-center items-center font-medium break-all">
|
||||||
|
{t("unauthorized-modal", {
|
||||||
|
adminEmail: extUser?.TenantId?.EmailAddress
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<form onSubmit={handleAddOnSubmit}>
|
||||||
|
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
|
||||||
|
{t("additional-users")}
|
||||||
|
</p>
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label
|
||||||
|
htmlFor="quantity"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("Quantity-of-users")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="quantity"
|
||||||
|
value={amount.quantity}
|
||||||
|
onChange={(e) => handlePricePerUser(e)}
|
||||||
|
className="w-1/4 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label className="block text-xs text-gray-700 font-semibold">
|
||||||
|
{t("Price")} (1 * {planInfo.priceperUser})
|
||||||
|
</label>
|
||||||
|
<div className="w-1/4 flex justify-center items-center text-sm">
|
||||||
|
USD {amount.price}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr className="text-base-content mb-3" />
|
||||||
|
<button className="op-btn op-btn-primary w-full">
|
||||||
|
{t("Proceed")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="mb-3">
|
</>
|
||||||
<label
|
) : (
|
||||||
htmlFor="phone"
|
<div className="w-full h-[200px] inset-0 flex justify-center items-center z-50">
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
<Loader />
|
||||||
>
|
</div>
|
||||||
Role<span className="text-[red] text-[13px]"> *</span>
|
)}
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
value={formdata.role}
|
|
||||||
onChange={(e) => handleChange(e)}
|
|
||||||
name="role"
|
|
||||||
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<option defaultValue={""} value={""}>
|
|
||||||
select
|
|
||||||
</option>
|
|
||||||
{role.length > 0 &&
|
|
||||||
role.map((x) => (
|
|
||||||
<option key={x} value={x}>
|
|
||||||
{x}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center mt-3 gap-2 text-white">
|
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleReset()}
|
|
||||||
className="op-btn op-btn-secondary"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,8 +2,15 @@ import React, { useState, useEffect, useRef } from "react";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import SuggestionInput from "./shared/fields/SuggestionInput";
|
import SuggestionInput from "./shared/fields/SuggestionInput";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import Parse from "parse";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { fetchSubscription } from "../constant/Utils";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
const BulkSendUi = (props) => {
|
const BulkSendUi = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
const [forms, setForms] = useState([]);
|
const [forms, setForms] = useState([]);
|
||||||
const [formId, setFormId] = useState(2);
|
const [formId, setFormId] = useState(2);
|
||||||
const formRef = useRef(null);
|
const formRef = useRef(null);
|
||||||
@@ -11,6 +18,22 @@ const BulkSendUi = (props) => {
|
|||||||
const [isSubmit, setIsSubmit] = useState(false);
|
const [isSubmit, setIsSubmit] = useState(false);
|
||||||
const [allowedForm, setAllowedForm] = useState(0);
|
const [allowedForm, setAllowedForm] = useState(0);
|
||||||
const [isSignatureExist, setIsSignatureExist] = useState();
|
const [isSignatureExist, setIsSignatureExist] = useState();
|
||||||
|
const [isBulkAvailable, setIsBulkAvailable] = useState(false);
|
||||||
|
const quantityList = [500, 1000, 5000, 50000];
|
||||||
|
const [amount, setAmount] = useState({
|
||||||
|
price: (75.0).toFixed(2),
|
||||||
|
quantity: 500,
|
||||||
|
priceperbulksend: 0.15,
|
||||||
|
totalcredits: 0
|
||||||
|
});
|
||||||
|
const [isQuotaReached, setIsQuotaReached] = useState(false);
|
||||||
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
|
const [isFreePlan, setIsFreePlan] = useState(false);
|
||||||
|
const [admin, setAdmin] = useState({
|
||||||
|
objectId: "",
|
||||||
|
email: "",
|
||||||
|
isAdmin: true
|
||||||
|
});
|
||||||
const allowedSigners = 50;
|
const allowedSigners = 50;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
signatureExist();
|
signatureExist();
|
||||||
@@ -18,14 +41,71 @@ const BulkSendUi = (props) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
//function to check atleast one signature field exist
|
//function to check atleast one signature field exist
|
||||||
const signatureExist = () => {
|
const signatureExist = async () => {
|
||||||
const getPlaceholder = props.item?.Placeholders;
|
if (isEnableSubscription) {
|
||||||
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
setIsLoader(true);
|
||||||
placeholderObj?.placeHolder?.some((holder) =>
|
try {
|
||||||
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
const subscription = await fetchSubscription();
|
||||||
)
|
const extUser =
|
||||||
);
|
localStorage.getItem("Extand_Class") &&
|
||||||
setIsSignatureExist(checkIsSignatureExistt);
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
|
if (
|
||||||
|
subscription?.adminId &&
|
||||||
|
extUser?.objectId === subscription?.adminId
|
||||||
|
) {
|
||||||
|
setAdmin((obj) => ({
|
||||||
|
...obj,
|
||||||
|
objectId: subscription?.adminId,
|
||||||
|
isAdmin: true
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
setAdmin((obj) => ({
|
||||||
|
...obj,
|
||||||
|
isAdmin: false,
|
||||||
|
email: extUser?.TenantId?.EmailAddress
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
setAdmin((obj) => ({ ...obj, objectId: subscription?.adminId }));
|
||||||
|
if (subscription?.plan === "freeplan") {
|
||||||
|
setIsFreePlan(true);
|
||||||
|
}
|
||||||
|
const resCredits = await Parse.Cloud.run("allowedcredits");
|
||||||
|
if (resCredits) {
|
||||||
|
const allowedcredits = resCredits?.allowedcredits || 0;
|
||||||
|
const addoncredits = resCredits?.addoncredits || 0;
|
||||||
|
const totalcredits = allowedcredits + addoncredits;
|
||||||
|
if (totalcredits > 0) {
|
||||||
|
if (subscription?.plan !== "freeplan") {
|
||||||
|
setIsBulkAvailable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAmount((obj) => ({ ...obj, totalcredits: totalcredits }));
|
||||||
|
}
|
||||||
|
const getPlaceholder = props.item?.Placeholders;
|
||||||
|
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
||||||
|
placeholderObj?.placeHolder?.some((holder) =>
|
||||||
|
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setIsSignatureExist(checkIsSignatureExistt);
|
||||||
|
setIsLoader(false);
|
||||||
|
} catch (err) {
|
||||||
|
setIsLoader(false);
|
||||||
|
alert(t("something-went-wrong-mssg"));
|
||||||
|
console.log("Err", err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsBulkAvailable(true);
|
||||||
|
setAdmin((obj) => ({ ...obj, isAdmin: true }));
|
||||||
|
const getPlaceholder = props.item?.Placeholders;
|
||||||
|
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
|
||||||
|
placeholderObj?.placeHolder?.some((holder) =>
|
||||||
|
holder?.pos?.some((posItem) => posItem?.type === "signature")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setIsSignatureExist(checkIsSignatureExistt);
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (scrollOnNextUpdate && formRef.current) {
|
if (scrollOnNextUpdate && formRef.current) {
|
||||||
@@ -74,29 +154,33 @@ const BulkSendUi = (props) => {
|
|||||||
const handleAddForm = (e) => {
|
const handleAddForm = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// Check if the quick send limit has been reached
|
// Check if the quick send limit has been reached
|
||||||
if (forms?.length < allowedForm) {
|
if (isEnableSubscription && forms.length >= amount.totalcredits) {
|
||||||
if (props?.Placeholders.length > 0) {
|
setIsQuotaReached(true);
|
||||||
let newForm = [];
|
|
||||||
props?.Placeholders?.forEach((element) => {
|
|
||||||
if (!element.signerObjId) {
|
|
||||||
newForm = [
|
|
||||||
...newForm,
|
|
||||||
{
|
|
||||||
fieldId: element.Id,
|
|
||||||
email: "",
|
|
||||||
label: element.Role,
|
|
||||||
signer: {}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setForms([...forms, { Id: formId, fields: newForm }]);
|
|
||||||
}
|
|
||||||
setFormId(formId + 1);
|
|
||||||
setScrollOnNextUpdate(true);
|
|
||||||
} else {
|
} else {
|
||||||
// If the limit has been reached, throw an error with the appropriate message
|
if (forms?.length < allowedForm) {
|
||||||
alert("Quick send reached limit.");
|
if (props?.Placeholders.length > 0) {
|
||||||
|
let newForm = [];
|
||||||
|
props?.Placeholders?.forEach((element) => {
|
||||||
|
if (!element.signerObjId) {
|
||||||
|
newForm = [
|
||||||
|
...newForm,
|
||||||
|
{
|
||||||
|
fieldId: element.Id,
|
||||||
|
email: "",
|
||||||
|
label: element.Role,
|
||||||
|
signer: {}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setForms([...forms, { Id: formId, fields: newForm }]);
|
||||||
|
}
|
||||||
|
setFormId(formId + 1);
|
||||||
|
setScrollOnNextUpdate(true);
|
||||||
|
} else {
|
||||||
|
// If the limit has been reached, throw an error with the appropriate message
|
||||||
|
alert(t("quick-send-alert-4"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,13 +244,9 @@ const BulkSendUi = (props) => {
|
|||||||
: [...existSigner]
|
: [...existSigner]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Documents.push({
|
Documents.push({ ...props.item, Placeholders: updatedPlaceholders });
|
||||||
...props.item,
|
|
||||||
Placeholders: updatedPlaceholders
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//console.log("Documents ", Documents);
|
|
||||||
await batchQuery(Documents);
|
await batchQuery(Documents);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,9 +258,7 @@ const BulkSendUi = (props) => {
|
|||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
const params = {
|
const params = { Documents: JSON.stringify(Documents) };
|
||||||
Documents: JSON.stringify(Documents)
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(functionsUrl, params, { headers: headers });
|
const res = await axios.post(functionsUrl, params, { headers: headers });
|
||||||
// console.log("res ", res);
|
// console.log("res ", res);
|
||||||
@@ -194,87 +272,231 @@ const BulkSendUi = (props) => {
|
|||||||
setIsSubmit(false);
|
setIsSubmit(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleAddOnQuickSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsSubmit(true);
|
||||||
|
try {
|
||||||
|
const resAddon = await Parse.Cloud.run("buycredits", {
|
||||||
|
credits: amount.quantity
|
||||||
|
});
|
||||||
|
if (resAddon) {
|
||||||
|
const _resAddon = JSON.parse(JSON.stringify(resAddon));
|
||||||
|
if (_resAddon.status === "success") {
|
||||||
|
setIsBulkAvailable(true);
|
||||||
|
handleCloseQuotaReached();
|
||||||
|
setAmount((obj) => ({
|
||||||
|
...obj,
|
||||||
|
quantity: 500,
|
||||||
|
priceperbulksend: 0.15,
|
||||||
|
price: (75.0).toFixed(2),
|
||||||
|
totalcredits: obj?.totalcredits + _resAddon.addon
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in buy addon", err);
|
||||||
|
alert(t("something-went-wrong-mssg"));
|
||||||
|
} finally {
|
||||||
|
setIsSubmit(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePricePerQuick = async (e) => {
|
||||||
|
const quantity = e.target?.value;
|
||||||
|
const price =
|
||||||
|
quantity > 0
|
||||||
|
? (Math.round(quantity * amount.priceperbulksend * 100) / 100).toFixed(
|
||||||
|
2
|
||||||
|
)
|
||||||
|
: 500 * amount.priceperbulksend;
|
||||||
|
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
|
||||||
|
};
|
||||||
|
const handleCloseQuotaReached = () => {
|
||||||
|
setIsQuotaReached(false);
|
||||||
|
};
|
||||||
|
const handleNavigation = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isSubmit && (
|
{isLoader ? (
|
||||||
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
|
<div className="w-full h-[100px] flex justify-center items-center z-[999]">
|
||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
{props.Placeholders?.length > 0 ? (
|
|
||||||
isSignatureExist ? (
|
|
||||||
<>
|
|
||||||
{props.Placeholders?.some((x) => !x.signerObjId) ? (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<div className="min-h-max max-h-[250px] overflow-y-auto">
|
|
||||||
{forms?.map((form, index) => (
|
|
||||||
<div
|
|
||||||
key={form.Id}
|
|
||||||
className="p-3 op-card border-[1px] border-gray-400 mt-3 mx-4 mb-4 bg-base-200 text-base-content grid grid-cols-1 md:grid-cols-2 gap-2 relative"
|
|
||||||
>
|
|
||||||
{form?.fields?.map((field, fieldIndex) => (
|
|
||||||
<div className="flex flex-col" key={field.fieldId}>
|
|
||||||
<label>{field.label}</label>
|
|
||||||
<SuggestionInput
|
|
||||||
required
|
|
||||||
type="email"
|
|
||||||
value={field.value}
|
|
||||||
index={fieldIndex}
|
|
||||||
onChange={(signer) =>
|
|
||||||
handleInputChange(index, signer, fieldIndex)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{forms?.length > 1 && (
|
|
||||||
<button
|
|
||||||
onClick={() => handleRemoveForm(index)}
|
|
||||||
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
|
|
||||||
>
|
|
||||||
<i className="fa-light fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<div ref={formRef}></div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col mx-4 mb-4 gap-3">
|
|
||||||
<button
|
|
||||||
onClick={handleAddForm}
|
|
||||||
className="op-btn op-btn-primary focus:outline-none"
|
|
||||||
>
|
|
||||||
<i className="fa-light fa-plus"></i> <span>Add new</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="op-btn op-btn-secondary focus:outline-none"
|
|
||||||
>
|
|
||||||
<i className="fa-light fa-paper-plane"></i>{" "}
|
|
||||||
<span>Send</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
) : (
|
|
||||||
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
|
||||||
All roles in this document are currently linked to contacts. To
|
|
||||||
'quick send' copies of this template to multiple
|
|
||||||
signers, please ensure that at least one role is not linked to
|
|
||||||
any contact.
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
|
||||||
Please ensure there's at least one signature widget added for
|
|
||||||
all recipients.
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
<>
|
||||||
Please add at least one role to this template in order to 'quick
|
{isSubmit && (
|
||||||
send' copies of it to multiple signers.
|
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
|
||||||
</div>
|
<Loader />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isBulkAvailable ? (
|
||||||
|
<>
|
||||||
|
{props.Placeholders?.length > 0 ? (
|
||||||
|
isSignatureExist ? (
|
||||||
|
<>
|
||||||
|
{props.Placeholders?.some((x) => !x.signerObjId) ? (
|
||||||
|
<div>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="min-h-max max-h-[250px] overflow-y-auto">
|
||||||
|
{forms?.map((form, index) => (
|
||||||
|
<div
|
||||||
|
key={form.Id}
|
||||||
|
className="p-3 op-card border-[1px] border-gray-400 mt-3 mx-4 mb-4 bg-base-200 text-base-content grid grid-cols-1 md:grid-cols-2 gap-2 relative"
|
||||||
|
>
|
||||||
|
{form?.fields?.map((field, fieldIndex) => (
|
||||||
|
<div
|
||||||
|
className="flex flex-col"
|
||||||
|
key={field.fieldId}
|
||||||
|
>
|
||||||
|
<label>{field.label}</label>
|
||||||
|
<SuggestionInput
|
||||||
|
required
|
||||||
|
type="email"
|
||||||
|
value={field.value}
|
||||||
|
index={fieldIndex}
|
||||||
|
onChange={(signer) =>
|
||||||
|
handleInputChange(
|
||||||
|
index,
|
||||||
|
signer,
|
||||||
|
fieldIndex
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{forms?.length > 1 && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleRemoveForm(index)}
|
||||||
|
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<div ref={formRef}></div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col mx-4 mb-4 gap-3">
|
||||||
|
{isEnableSubscription && (
|
||||||
|
<button
|
||||||
|
onClick={handleAddForm}
|
||||||
|
className="op-btn op-btn-primary focus:outline-none"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-plus"></i>{" "}
|
||||||
|
<span>{t("add-new")}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="op-btn op-btn-accent focus:outline-none"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-paper-plane"></i>{" "}
|
||||||
|
<span>{t("send")}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isQuotaReached}
|
||||||
|
handleClose={() => handleCloseQuotaReached()}
|
||||||
|
>
|
||||||
|
<div className="p-4 flex justify-center items-center flex-col gap-y-3">
|
||||||
|
<p className="text-center text-base-content">
|
||||||
|
{t("quota-err-quicksend")}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsBulkAvailable(false)}
|
||||||
|
className=" op-btn op-btn-primary w-[200px]"
|
||||||
|
>
|
||||||
|
{t("buy-credits")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
||||||
|
{t("quick-send-alert-1")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
||||||
|
{t("quick-send-alert-2")}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
|
||||||
|
{t("quick-send-alert-3")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{isFreePlan ? (
|
||||||
|
<div className="w-full h-[130px] flex flex-col justify-center items-center text-center p-4">
|
||||||
|
<p className="text-base font-medium mb-2.5">
|
||||||
|
{t("bulk-send-subcription-alert")}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => handleNavigation()}
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("upgrade-now")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{admin?.isAdmin ? (
|
||||||
|
<form onSubmit={handleAddOnQuickSubmit} className="p-3">
|
||||||
|
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
|
||||||
|
{t("additional-credits")}
|
||||||
|
</p>
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label
|
||||||
|
htmlFor="quantity"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("quantity-of-credits")}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
value={amount.quantity}
|
||||||
|
onChange={(e) => handlePricePerQuick(e)}
|
||||||
|
name="quantity"
|
||||||
|
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
{quantityList.length > 0 &&
|
||||||
|
quantityList.map((x) => (
|
||||||
|
<option key={x} value={x}>
|
||||||
|
{x}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label className="block text-xs text-gray-700 font-semibold">
|
||||||
|
{t("Price")} (1 * {amount.priceperbulksend})
|
||||||
|
</label>
|
||||||
|
<div className="w-1/4 flex justify-center items-center text-sm">
|
||||||
|
USD {amount.price}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr className="text-base-content mb-3" />
|
||||||
|
<button className="op-btn op-btn-primary w-full mt-2">
|
||||||
|
{t("Proceed")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<div className="mx-8 mt-4 mb-8 flex justify-center text-center items-center font-medium break-all">
|
||||||
|
{t("unauthorized-modal", { adminEmail: admin?.email })}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Package from "../../package.json";
|
import Package from "../../package.json";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { openInNewTab } from "../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [showButton, setShowButton] = useState(false);
|
const [showButton, setShowButton] = useState(false);
|
||||||
const [version, setVersion] = useState("");
|
const [version, setVersion] = useState("");
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -48,9 +50,10 @@ const Footer = () => {
|
|||||||
<footer className="op-footer op-footer-center py-3 bg-base-300 text-base-content text-center text-[13px]">
|
<footer className="op-footer op-footer-center py-3 bg-base-300 text-base-content text-center text-[13px]">
|
||||||
<aside>
|
<aside>
|
||||||
<p>
|
<p>
|
||||||
All Rights Reserved © {new Date().getFullYear()}
|
{t("all-right")} © {new Date().getFullYear()}
|
||||||
<span onClick={openUrl} className="hover:underline cursor-pointer">
|
<span onClick={openUrl} className="hover:underline cursor-pointer">
|
||||||
{appName} ( version: {version ? version : `${Package.version} `})
|
{appName} ( {t("version")}:{" "}
|
||||||
|
{version ? version : `${Package.version} `})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -4,23 +4,44 @@ import FullScreenButton from "./FullScreenButton";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import { checkIsSubscribed, getAppLogo, openInNewTab } from "../constant/Utils";
|
import {
|
||||||
|
checkIsSubscribed,
|
||||||
|
getAppLogo,
|
||||||
|
openInNewTab,
|
||||||
|
saveLanguageInLocal
|
||||||
|
} from "../constant/Utils";
|
||||||
import { isEnableSubscription, isStaging } from "../constant/const";
|
import { isEnableSubscription, isStaging } from "../constant/const";
|
||||||
|
import { validplan } from "../json/plansArr";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import QuotaCard from "../primitives/QuotaCard";
|
||||||
|
|
||||||
const Header = ({ showSidebar }) => {
|
const Header = ({ showSidebar }) => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
let username = localStorage.getItem("username");
|
const current_notification_version = "1"; // Update this with each new feature release
|
||||||
|
// Get the dismissed version from local storage
|
||||||
|
const dismissedVersion = localStorage.getItem("notificationDismissedVersion");
|
||||||
|
const username = localStorage.getItem("username") || "";
|
||||||
const image = localStorage.getItem("profileImg") || dp;
|
const image = localStorage.getItem("profileImg") || dp;
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [isSubscribe, setIsSubscribe] = useState(true);
|
const [isSubscribe, setIsSubscribe] = useState(true);
|
||||||
const [isPro, setIsPro] = useState(false);
|
const [isTeam, setIsTeam] = useState({ plan: "", isValid: false });
|
||||||
const [applogo, setAppLogo] = useState(
|
const [applogo, setAppLogo] = useState(
|
||||||
localStorage.getItem("appLogo") || " "
|
localStorage.getItem("appLogo") || " "
|
||||||
);
|
);
|
||||||
|
const [emailUsed, setEmailUsed] = useState(0);
|
||||||
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [showNotification, setShowNotification] = useState(
|
||||||
|
(!dismissedVersion || dismissedVersion !== current_notification_version) &&
|
||||||
|
true
|
||||||
|
);
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
|
if (width <= 768) {
|
||||||
|
showSidebar();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkSubscription();
|
checkSubscription();
|
||||||
@@ -28,8 +49,8 @@ const Header = ({ showSidebar }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
async function checkSubscription() {
|
async function checkSubscription() {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const getIsSubscribe = await checkIsSubscribed();
|
const subscribe = await checkIsSubscribed();
|
||||||
if (getIsSubscribe) {
|
if (subscribe.isValid) {
|
||||||
const applogo = await getAppLogo();
|
const applogo = await getAppLogo();
|
||||||
if (applogo?.logo) {
|
if (applogo?.logo) {
|
||||||
setAppLogo(applogo?.logo);
|
setAppLogo(applogo?.logo);
|
||||||
@@ -37,19 +58,31 @@ const Header = ({ showSidebar }) => {
|
|||||||
setAppLogo(localStorage.getItem("appLogo") || "");
|
setAppLogo(localStorage.getItem("appLogo") || "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setIsPro(getIsSubscribe);
|
setIsTeam(subscribe);
|
||||||
setIsSubscribe(getIsSubscribe);
|
setIsSubscribe(subscribe.isValid);
|
||||||
|
try {
|
||||||
|
const extUser = await Parse.Cloud.run("getUserDetails");
|
||||||
|
const MonthlyFreeEmails = extUser?.get("MonthlyFreeEmails") || 0;
|
||||||
|
setEmailUsed(MonthlyFreeEmails);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in while fetching monthlyfreeEmails", err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const applogo = await getAppLogo();
|
||||||
|
if (applogo?.logo) {
|
||||||
|
setAppLogo(applogo?.logo);
|
||||||
|
} else {
|
||||||
|
setAppLogo(localStorage.getItem("appLogo") || "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeDropdown = () => {
|
const closeDropdown = async () => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
if (Parse?.User?.current()) {
|
try {
|
||||||
try {
|
await Parse.User.logOut();
|
||||||
Parse.User.logOut();
|
} catch (err) {
|
||||||
} catch (err) {
|
console.log("Err while logging out", err);
|
||||||
console.log("Err", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let appdata = localStorage.getItem("userSettings");
|
let appdata = localStorage.getItem("userSettings");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
@@ -59,7 +92,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
let appid = localStorage.getItem("parseAppId");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||||
localStorage.setItem("PageLanding", PageLanding);
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
@@ -92,123 +125,174 @@ const Header = ({ showSidebar }) => {
|
|||||||
window.open("https://console.opensignlabs.com/");
|
window.open("https://console.opensignlabs.com/");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleNavigation = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
|
const handleMailUsed = () => {
|
||||||
|
setIsModal(!isModal);
|
||||||
|
};
|
||||||
|
// Handle dismissing the notification
|
||||||
|
const dismissNotification = () => {
|
||||||
|
// Store the current version as dismissed in local storage
|
||||||
|
localStorage.setItem(
|
||||||
|
"notificationDismissedVersion",
|
||||||
|
current_notification_version
|
||||||
|
);
|
||||||
|
setShowNotification(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="op-navbar bg-base-100 shadow">
|
<div>
|
||||||
<div className="flex-none">
|
{isEnableSubscription && showNotification && (
|
||||||
<button
|
<div className="flex justify-between items-center shadow py-1 bg-[#CAE4FA] p-1">
|
||||||
className="op-btn op-btn-square op-btn-ghost focus:outline-none hover:bg-transparent op-btn-sm no-animation"
|
<div className="text-center text-[14px] ml-auto">
|
||||||
onClick={showSidebar}
|
{t("header-news")} —
|
||||||
>
|
<span
|
||||||
<i className="fa-light fa-bars text-xl text-base-content"></i>
|
className="cursor-pointer font-medium underline text-blue-800"
|
||||||
</button>
|
onClick={() => navigate("/profile")}
|
||||||
</div>
|
|
||||||
<div className="flex-1 ml-2">
|
|
||||||
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
|
|
||||||
<img
|
|
||||||
className="object-contain h-full w-auto"
|
|
||||||
src={applogo}
|
|
||||||
alt="img"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="profile-menu" className="flex-none gap-2">
|
|
||||||
{!isSubscribe && (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
|
|
||||||
onClick={() => navigate("/subscription")}
|
|
||||||
>
|
>
|
||||||
Upgrade Now
|
{" " + t("header-news-btn") + "."}
|
||||||
</button>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
{isPro && (
|
|
||||||
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
|
|
||||||
PRO
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div>
|
|
||||||
<FullScreenButton />
|
|
||||||
</div>
|
|
||||||
{width >= 768 && (
|
|
||||||
<div
|
<div
|
||||||
onClick={toggleDropdown}
|
className="ml-auto mr-1 cursor-pointer"
|
||||||
className="cursor-pointer w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-gray-400 overflow-hidden"
|
onClick={() => dismissNotification()}
|
||||||
>
|
>
|
||||||
|
<i className="fa-light fa-xmark"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="op-navbar bg-base-100 shadow">
|
||||||
|
<div className="flex-none">
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-square op-btn-ghost focus:outline-none hover:bg-transparent op-btn-sm no-animation"
|
||||||
|
onClick={showSidebar}
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-bars text-xl text-base-content"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 ml-2">
|
||||||
|
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
|
||||||
<img
|
<img
|
||||||
className="w-[35px] h-[35px] object-contain"
|
className="object-contain h-full w-auto"
|
||||||
src={image}
|
src={applogo}
|
||||||
alt="img"
|
alt="img"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
{width >= 768 && (
|
<div id="profile-menu" className="flex-none gap-2">
|
||||||
<div
|
{!isSubscribe && (
|
||||||
onClick={toggleDropdown}
|
<div>
|
||||||
className="cursor-pointer text-base-content text-sm"
|
<button
|
||||||
>
|
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
|
||||||
{username && username}
|
onClick={() => handleNavigation()}
|
||||||
|
>
|
||||||
|
{t("upgrade-now")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isTeam.isValid && !validplan[isTeam.plan] && (
|
||||||
|
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
|
||||||
|
{t("pro")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{validplan[isTeam.plan] && (
|
||||||
|
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] text-[13px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
|
||||||
|
{t("team")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<FullScreenButton />
|
||||||
</div>
|
</div>
|
||||||
)}
|
{width >= 768 && (
|
||||||
<div className="op-dropdown op-dropdown-end" id="profile-menu">
|
<div
|
||||||
<div
|
onClick={toggleDropdown}
|
||||||
tabIndex={0}
|
className="cursor-pointer w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-gray-400 overflow-hidden"
|
||||||
role="button"
|
>
|
||||||
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
|
<img
|
||||||
>
|
className="w-[35px] h-[35px] object-contain"
|
||||||
<i
|
src={image}
|
||||||
|
alt="img"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{width >= 768 && (
|
||||||
|
<div
|
||||||
|
onClick={toggleDropdown}
|
||||||
|
className="cursor-pointer text-base-content text-sm"
|
||||||
|
>
|
||||||
|
{username && username}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="op-dropdown op-dropdown-end" id="profile-menu">
|
||||||
|
<div
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
onClick={toggleDropdown}
|
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
|
||||||
className="fa-light fa-angle-down text-base-content"
|
>
|
||||||
></i>
|
<i
|
||||||
|
tabIndex={0}
|
||||||
|
role="button"
|
||||||
|
onClick={toggleDropdown}
|
||||||
|
className="fa-light fa-angle-down text-base-content"
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
tabIndex={0}
|
||||||
|
className="mt-3 z-[1] p-2 shadow op-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52"
|
||||||
|
>
|
||||||
|
<li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-book"></i> {t("docs")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
onClick={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
navigate("/profile");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-user"></i> {t("profile")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
onClick={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
navigate("/changepassword");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-lock"></i> {t("change-password")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{isEnableSubscription && (
|
||||||
|
<li onClick={() => handleConsoleRedirect()}>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-id-card"></i> Console
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{isEnableSubscription && isTeam?.plan === "freeplan" && (
|
||||||
|
<li className="cursor-pointer" onClick={handleMailUsed}>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-envelope"></i>
|
||||||
|
{emailUsed}/15 {t("sent-this-month")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
<li onClick={closeDropdown}>
|
||||||
|
<span>
|
||||||
|
<i className="fa-light fa-arrow-right-from-bracket"></i>{" "}
|
||||||
|
{t("log-out")}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<ul
|
|
||||||
tabIndex={0}
|
|
||||||
className="mt-3 z-[1] p-2 shadow op-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52"
|
|
||||||
>
|
|
||||||
<li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
|
|
||||||
<span>
|
|
||||||
<i className="fa-light fa-book"></i> Docs
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
onClick={() => {
|
|
||||||
setIsOpen(false);
|
|
||||||
navigate("/profile");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<i className="fa-light fa-user"></i> Profile
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
onClick={() => {
|
|
||||||
setIsOpen(false);
|
|
||||||
navigate("/changepassword");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<i className="fa-light fa-lock"></i> Change Password
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
onClick={() => {
|
|
||||||
handleConsoleRedirect();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<i className="fa-light fa-id-card"></i> Console
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li onClick={closeDropdown}>
|
|
||||||
<span>
|
|
||||||
<i className="fa-light fa-arrow-right-from-bracket"></i> Log Out
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ModalUi isOpen={isModal}>
|
||||||
|
<QuotaCard isPaidInfo={true} handlClose={handleMailUsed} />
|
||||||
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } 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 FacebookLogin from "react-facebook-login";
|
// import FacebookLogin from "react-facebook-login";
|
||||||
|
|
||||||
const LoginFacebook = ({
|
const LoginFacebook = ({
|
||||||
@@ -9,6 +10,7 @@ const LoginFacebook = ({
|
|||||||
thirdpartyLoader,
|
thirdpartyLoader,
|
||||||
setThirdpartyLoader
|
setThirdpartyLoader
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
const [userDetails, setUserDetails] = useState({
|
const [userDetails, setUserDetails] = useState({
|
||||||
Phone: "",
|
Phone: "",
|
||||||
@@ -106,10 +108,10 @@ const LoginFacebook = ({
|
|||||||
alert(userSignUp.message);
|
alert(userSignUp.message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Internal server error !");
|
alert(t("server-error"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please fill required details!");
|
alert(t("fill-required-details!"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@@ -136,7 +138,7 @@ const LoginFacebook = ({
|
|||||||
<div className="modal-dialog" role="document">
|
<div className="modal-dialog" role="document">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal-header">
|
<div className="modal-header">
|
||||||
<h5 className="modal-title">Sign up form</h5>
|
<h5 className="modal-title">{t("sign-up-form")}</h5>
|
||||||
<span>
|
<span>
|
||||||
<span></span>
|
<span></span>
|
||||||
</span>
|
</span>
|
||||||
@@ -145,7 +147,8 @@ const LoginFacebook = ({
|
|||||||
<form>
|
<form>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="Phone" className="col-form-label">
|
<label htmlFor="Phone" className="col-form-label">
|
||||||
Phone <span className="text-[red] text-[13px]">*</span>
|
{t("phone")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
@@ -158,12 +161,17 @@ const LoginFacebook = ({
|
|||||||
Phone: e.target.value
|
Phone: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="Company" className="col-form-label">
|
<label htmlFor="Company" className="col-form-label">
|
||||||
Company <span className="text-[red] text-[13px]">*</span>
|
{t("company")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -176,6 +184,10 @@ const LoginFacebook = ({
|
|||||||
Company: e.target.value
|
Company: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,14 +197,14 @@ const LoginFacebook = ({
|
|||||||
onClick={() => handleSubmitbtn()}
|
onClick={() => handleSubmitbtn()}
|
||||||
className="btn btn-info mr-[10px]"
|
className="btn btn-info mr-[10px]"
|
||||||
>
|
>
|
||||||
Sign up
|
{t("sign-up")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary w-[90px]"
|
className="btn btn-secondary w-[90px]"
|
||||||
onClick={() => setIsModal(false)}
|
onClick={() => setIsModal(false)}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { jwtDecode } from "jwt-decode";
|
|||||||
import { useScript } from "../hook/useScript";
|
import { useScript } from "../hook/useScript";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { saveLanguageInLocal } from "../constant/Utils";
|
||||||
/*
|
/*
|
||||||
* `GoogleSignInBtn`as it's name indicates it render google sign in button
|
* `GoogleSignInBtn`as it's name indicates it render google sign in button
|
||||||
* and in this `useScript` in which we have created for generate google sign button
|
* and in this `useScript` in which we have created for generate google sign button
|
||||||
@@ -17,6 +18,7 @@ const GoogleSignInBtn = ({
|
|||||||
thirdpartyLoader,
|
thirdpartyLoader,
|
||||||
setThirdpartyLoader
|
setThirdpartyLoader
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
const googleBtn = useRef();
|
const googleBtn = useRef();
|
||||||
const [userDetails, setUserDetails] = useState({
|
const [userDetails, setUserDetails] = useState({
|
||||||
@@ -45,8 +47,10 @@ const GoogleSignInBtn = ({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
const clearStorage = async () => {
|
const clearStorage = async () => {
|
||||||
if (Parse.User.current()) {
|
try {
|
||||||
await Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
}
|
}
|
||||||
let baseUrl = localStorage.getItem("baseUrl");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("parseAppId");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
@@ -56,6 +60,7 @@ const GoogleSignInBtn = ({
|
|||||||
let userSettings = localStorage.getItem("userSettings");
|
let userSettings = localStorage.getItem("userSettings");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
|
|
||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
@@ -74,10 +79,7 @@ const GoogleSignInBtn = ({
|
|||||||
const data = jwtDecode(response.credential);
|
const data = jwtDecode(response.credential);
|
||||||
// console.log("data ", data);
|
// console.log("data ", data);
|
||||||
if (data.sub && data.email) {
|
if (data.sub && data.email) {
|
||||||
const details = {
|
const details = { Email: data.email, Name: data.name };
|
||||||
Email: data.email,
|
|
||||||
Name: data.name
|
|
||||||
};
|
|
||||||
setUserDetails({ ...userDetails, ...details });
|
setUserDetails({ ...userDetails, ...details });
|
||||||
const Gdetails = {
|
const Gdetails = {
|
||||||
Id: data.sub,
|
Id: data.sub,
|
||||||
@@ -91,26 +93,18 @@ const GoogleSignInBtn = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const checkExtUser = async (details) => {
|
const checkExtUser = async (details) => {
|
||||||
// const extUser = new Parse.Query("contracts_Users");
|
|
||||||
// extUser.equalTo("Email", details.Gmail);
|
|
||||||
// const extRes = await extUser.first();
|
|
||||||
const params = { email: details.Gmail };
|
const params = { email: details.Gmail };
|
||||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||||
// console.log("extRes ", extRes);
|
|
||||||
if (extRes) {
|
if (extRes) {
|
||||||
const params = { ...details, Phone: extRes?.get("Phone") || "" };
|
// const params = { ...details, Phone: extRes?.get("Phone") || "" };
|
||||||
|
const params = { ...details, extUserId: extRes.objectId };
|
||||||
const payload = await Parse.Cloud.run("googlesign", params);
|
const payload = await Parse.Cloud.run("googlesign", params);
|
||||||
// console.log("payload ", payload);
|
|
||||||
if (payload && payload.sessiontoken) {
|
if (payload && payload.sessiontoken) {
|
||||||
// setThirdpartyLoader(true);
|
|
||||||
// const billingDate =
|
|
||||||
// extRes.get("Next_billing_date") && extRes.get("Next_billing_date");
|
|
||||||
// console.log("billingDate expired", billingDate > new Date());
|
|
||||||
const LocalUserDetails = {
|
const LocalUserDetails = {
|
||||||
name: details.Name,
|
name: details.Name,
|
||||||
email: details.Gmail,
|
email: details.Gmail,
|
||||||
phone: extRes?.get("Phone") || "",
|
phone: payload?.phone || "",
|
||||||
company: extRes.get("Company")
|
company: payload.company
|
||||||
};
|
};
|
||||||
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
|
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
|
||||||
thirdpartyLoginfn(payload.sessiontoken);
|
thirdpartyLoginfn(payload.sessiontoken);
|
||||||
@@ -162,16 +156,19 @@ const GoogleSignInBtn = ({
|
|||||||
payload &&
|
payload &&
|
||||||
payload.message.replace(/ /g, "_") === "Internal_server_err"
|
payload.message.replace(/ /g, "_") === "Internal_server_err"
|
||||||
) {
|
) {
|
||||||
alert("Internal server error !");
|
alert(t("server-error"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please fill required details!");
|
alert(t("fill-required-details!"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = async () => {
|
||||||
setIsModal(false);
|
setIsModal(false);
|
||||||
Parse.User.logOut();
|
try {
|
||||||
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
|
}
|
||||||
let appdata = localStorage.getItem("userSettings");
|
let appdata = localStorage.getItem("userSettings");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
||||||
@@ -180,7 +177,7 @@ const GoogleSignInBtn = ({
|
|||||||
let appid = localStorage.getItem("parseAppId");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||||
localStorage.setItem("PageLanding", PageLanding);
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
@@ -196,11 +193,11 @@ const GoogleSignInBtn = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div ref={googleBtn} className="text-sm"></div>
|
<div ref={googleBtn} className="text-sm"></div>
|
||||||
<ModalUi showClose={false} isOpen={isModal} title="Sign up form">
|
<ModalUi showClose={false} isOpen={isModal} title={t("sign-up-form")}>
|
||||||
<form className="px-4 py-3 text-base-content">
|
<form className="px-4 py-3 text-base-content">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="Phone" className="block text-xs font-semibold">
|
<label htmlFor="Phone" className="block text-xs font-semibold">
|
||||||
Phone <span className="text-[13px] text-[red]">*</span>
|
{t("phone")} <span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
@@ -213,12 +210,14 @@ const GoogleSignInBtn = ({
|
|||||||
Phone: e.target.value
|
Phone: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="Company" className="block text-xs font-semibold">
|
<label htmlFor="Company" className="block text-xs font-semibold">
|
||||||
Company <span className="text-[13px] text-[red]">*</span>
|
{t("company")} <span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -231,12 +230,14 @@ const GoogleSignInBtn = ({
|
|||||||
Company: e.target.value
|
Company: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="JobTitle" className="block text-xs font-semibold">
|
<label htmlFor="JobTitle" className="block text-xs font-semibold">
|
||||||
Job Title <span className="text-[13px] text-[red]">*</span>
|
{t("job-title")} <span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -249,6 +250,8 @@ const GoogleSignInBtn = ({
|
|||||||
Destination: e.target.value
|
Destination: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -258,14 +261,14 @@ const GoogleSignInBtn = ({
|
|||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
onClick={() => handleSubmitbtn()}
|
onClick={() => handleSubmitbtn()}
|
||||||
>
|
>
|
||||||
Sign up
|
{t("sign-up")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost"
|
className="op-btn op-btn-ghost"
|
||||||
onClick={handleCloseModal}
|
onClick={handleCloseModal}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function RotateAlert(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<ModalUi
|
||||||
|
isOpen={props.isRotate}
|
||||||
|
title={t("Rotation-alert")}
|
||||||
|
handleClose={() => props.setIsRotate({ status: false, degree: 0 })}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<div className="p-[20px] h-full">
|
||||||
|
<p>{t("rotate-alert-mssg")}</p>
|
||||||
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
|
<div className="flex gap-1">
|
||||||
|
<button
|
||||||
|
onClick={() => props.setIsRotate({ status: false, degree: 0 })}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-ghost shadow-md"
|
||||||
|
>
|
||||||
|
{t("no")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => props.handleRemoveWidgets()}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("yes")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RotateAlert;
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { openInNewTab } from "../../constant/Utils";
|
import { openInNewTab } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const DashboardButton = (props) => {
|
const DashboardButton = (props) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
function openReport() {
|
function openReport() {
|
||||||
if (props.Data && props.Data.Redirect_type) {
|
if (props.Data && props.Data.Redirect_type) {
|
||||||
@@ -35,7 +37,9 @@ const DashboardButton = (props) => {
|
|||||||
} text-[25px] lg:text-[30px]`}
|
} text-[25px] lg:text-[30px]`}
|
||||||
></i>
|
></i>
|
||||||
</span>
|
</span>
|
||||||
<div className=" text-lg ml-3 text-base-content">{props.Label}</div>
|
<div className=" text-lg ml-3 text-base-content">
|
||||||
|
{t(`sidebar.${props.Label}`)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import Parse from "parse";
|
|||||||
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
|
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Tooltip from "../../primitives/Tooltip";
|
import Tooltip from "../../primitives/Tooltip";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const DashboardCard = (props) => {
|
const DashboardCard = (props) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
const [response, setresponse] = useState("");
|
const [response, setresponse] = useState("");
|
||||||
@@ -23,17 +25,12 @@ const DashboardCard = (props) => {
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
let body = {};
|
let body = {};
|
||||||
let currentUser;
|
|
||||||
let currentUser1 = Parse.User.current();
|
|
||||||
currentUser = currentUser1.id;
|
|
||||||
let res;
|
let res;
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
if (localStorage.getItem("Extand_Class")) {
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
res = data[0];
|
res = data[0];
|
||||||
} else {
|
} else {
|
||||||
res = await Parse.Cloud.run("getUserDetails", {
|
res = await Parse.Cloud.run("getUserDetails");
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = res.toJSON();
|
if (res) res = res.toJSON();
|
||||||
}
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
@@ -94,9 +91,7 @@ const DashboardCard = (props) => {
|
|||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
resr = data[0];
|
resr = data[0];
|
||||||
} else {
|
} else {
|
||||||
resr = await Parse.Cloud.run("getUserDetails", {
|
resr = await Parse.Cloud.run("getUserDetails");
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (resr) resr = resr.toJSON();
|
if (resr) resr = resr.toJSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,15 +213,12 @@ const DashboardCard = (props) => {
|
|||||||
|
|
||||||
if (restr.includes("#")) {
|
if (restr.includes("#")) {
|
||||||
try {
|
try {
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
let res;
|
let res;
|
||||||
if (localStorage.getItem("Extand_Class")) {
|
if (localStorage.getItem("Extand_Class")) {
|
||||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
res = data[0];
|
res = data[0];
|
||||||
} else {
|
} else {
|
||||||
let resr = await Parse.Cloud.run("getUserDetails", {
|
let resr = await Parse.Cloud.run("getUserDetails");
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (res) res = resr.toJSON();
|
if (res) res = resr.toJSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,6 +313,7 @@ const DashboardCard = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={() => openReport()}
|
onClick={() => openReport()}
|
||||||
@@ -338,8 +331,11 @@ const DashboardCard = (props) => {
|
|||||||
} text-[25px] lg:text-[30px]`}
|
} text-[25px] lg:text-[30px]`}
|
||||||
></i>
|
></i>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="font-medium">
|
<div className="font-medium">
|
||||||
<div className="text-base lg:text-lg"> {props.Label}</div>
|
<div className="text-base lg:text-lg">
|
||||||
|
{t(`dashboard-card.${props.Label}`)}
|
||||||
|
</div>
|
||||||
<div className="text-2xl font-light">
|
<div className="text-2xl font-light">
|
||||||
{loading ? <div className="loader-01"></div> : setFormat(response)}
|
{loading ? <div className="loader-01"></div> : setFormat(response)}
|
||||||
</div>
|
</div>
|
||||||
@@ -349,7 +345,8 @@ const DashboardCard = (props) => {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
id={props.Label}
|
id={props.Label}
|
||||||
iconColor={"white"}
|
iconColor={"white"}
|
||||||
message={props?.Data?.tourMessage}
|
message={t(`tour-mssg.${props.Label}`)}
|
||||||
|
// {props?.Data?.tourMessage}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import ReportTable from "../../primitives/GetReportDisplay";
|
|||||||
import reportJson from "../../json/ReportJson";
|
import reportJson from "../../json/ReportJson";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Loader from "../../primitives/Loader";
|
import Loader from "../../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function DashboardReport(props) {
|
function DashboardReport(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
// console.log("props ", props)
|
// console.log("props ", props)
|
||||||
const [List, setList] = useState([]);
|
const [List, setList] = useState([]);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
@@ -141,7 +143,7 @@ function DashboardReport(props) {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
|
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="text-xl text-black">Report Not Found</p>
|
<p className="text-xl text-black">{t("report-not-found")}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { Suspense, lazy } from "react";
|
import React, { Suspense, lazy } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
const DashboardButton = lazy(() => import("./DashboardButton"));
|
const DashboardButton = lazy(() => import("./DashboardButton"));
|
||||||
const DashboardCard = lazy(() => import("./DashboardCard"));
|
const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||||
const DashboardReport = lazy(() => import("./DashboardReport"));
|
const DashboardReport = lazy(() => import("./DashboardReport"));
|
||||||
@@ -10,13 +11,14 @@ const buttonList = [
|
|||||||
icon: "fa-light fa-pen-nib"
|
icon: "fa-light fa-pen-nib"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Request signature",
|
label: "Request signatures",
|
||||||
redirectId: "8mZzFxbG1z",
|
redirectId: "8mZzFxbG1z",
|
||||||
redirectType: "Form",
|
redirectType: "Form",
|
||||||
icon: "fa-light fa-paper-plane"
|
icon: "fa-light fa-paper-plane"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const GetDashboard = (props) => {
|
const GetDashboard = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const Button = ({ label, redirectId, redirectType, icon }) => (
|
const Button = ({ label, redirectId, redirectType, icon }) => (
|
||||||
<DashboardButton
|
<DashboardButton
|
||||||
Icon={icon}
|
Icon={icon}
|
||||||
@@ -37,7 +39,7 @@ const GetDashboard = (props) => {
|
|||||||
<Suspense
|
<Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<div className="h-[150px] w-full flex justify-center items-center">
|
<div className="h-[150px] w-full flex justify-center items-center">
|
||||||
loading...
|
{t("loading")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ 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";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import FolderModal from "../shared/fields/FolderModal";
|
import FolderModal from "../shared/fields/FolderModal";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { handleDownloadPdf } from "../../constant/Utils";
|
||||||
|
|
||||||
function DriveBody(props) {
|
function DriveBody(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [rename, setRename] = useState("");
|
const [rename, setRename] = useState("");
|
||||||
const [renameValue, setRenameValue] = useState("");
|
const [renameValue, setRenameValue] = useState("");
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
@@ -42,7 +44,7 @@ function DriveBody(props) {
|
|||||||
props.setFolderName((prev) => [...prev, folderData]);
|
props.setFolderName((prev) => [...prev, folderData]);
|
||||||
props.setIsLoading({
|
props.setIsLoading({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: t("loading-mssg")
|
||||||
});
|
});
|
||||||
props.setDocId(data.objectId);
|
props.setDocId(data.objectId);
|
||||||
props.setPdfData([]);
|
props.setPdfData([]);
|
||||||
@@ -90,7 +92,7 @@ function DriveBody(props) {
|
|||||||
console.log("Err ", err);
|
console.log("Err ", err);
|
||||||
props.setIsAlert({
|
props.setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,16 +100,17 @@ function DriveBody(props) {
|
|||||||
|
|
||||||
//function for navigate user to microapp-signature component
|
//function for navigate user to microapp-signature component
|
||||||
const checkPdfStatus = async (data) => {
|
const checkPdfStatus = async (data) => {
|
||||||
const signerExist = data.Signers && data.Signers;
|
const signerExist = data?.Signers;
|
||||||
const isDecline = data.IsDeclined && data.IsDeclined;
|
const isDecline = data?.IsDeclined;
|
||||||
const isPlaceholder = data.Placeholders && data.Placeholders;
|
const isPlaceholder = data?.Placeholders;
|
||||||
const signedUrl = data.SignedUrl;
|
const signedUrl = data?.SignedUrl;
|
||||||
|
const isSignYourself = data?.IsSignyourself;
|
||||||
//checking if document has completed and request signature flow
|
//checking if document has completed and request signature flow
|
||||||
if (data?.IsCompleted && signerExist?.length > 0) {
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
navigate(`/recipientSignPdf/${data.objectId}`);
|
navigate(`/recipientSignPdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has completed and signyour-self flow
|
//checking if document has completed and signyour-self flow
|
||||||
else if (!signerExist && !isPlaceholder) {
|
else if ((!signerExist && !isPlaceholder) || isSignYourself) {
|
||||||
navigate(`/signaturePdf/${data.objectId}`);
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has declined by someone
|
//checking if document has declined by someone
|
||||||
@@ -134,12 +137,10 @@ function DriveBody(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuItemClick = (selectType, data) => {
|
const handleMenuItemClick = async (selectType, data) => {
|
||||||
switch (selectType) {
|
switch (selectType) {
|
||||||
case "Download": {
|
case "Download": {
|
||||||
const pdfName = data && data.Name;
|
await handleDownloadPdf([data]);
|
||||||
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
|
|
||||||
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Rename": {
|
case "Rename": {
|
||||||
@@ -191,7 +192,7 @@ function DriveBody(props) {
|
|||||||
console.log("Err ", err);
|
console.log("Err ", err);
|
||||||
props.setIsAlert({
|
props.setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -258,16 +259,10 @@ function DriveBody(props) {
|
|||||||
|
|
||||||
setIsOpenMoveModal(false);
|
setIsOpenMoveModal(false);
|
||||||
} else {
|
} else {
|
||||||
alert("folder already exist!");
|
alert(t("folder-already-exist!"));
|
||||||
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);
|
||||||
@@ -348,14 +343,14 @@ function DriveBody(props) {
|
|||||||
</td>
|
</td>
|
||||||
<td>{createddate}</td>
|
<td>{createddate}</td>
|
||||||
<td>Pdf</td>
|
<td>Pdf</td>
|
||||||
<td>{status}</td>
|
<td>{t(`drive-document-status.${status}`)}</td>
|
||||||
<td>
|
<td>
|
||||||
<i
|
<i
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleMenuItemClick("Download", data);
|
handleMenuItemClick("Download", data);
|
||||||
}}
|
}}
|
||||||
className="fa-light fa-download mr-[8px] op-text-primary"
|
className="fa-light fa-download mr-[8px] op-text-primary cursor-pointer"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
</td>
|
</td>
|
||||||
@@ -368,7 +363,11 @@ function DriveBody(props) {
|
|||||||
{/* folder */}
|
{/* folder */}
|
||||||
<div
|
<div
|
||||||
data-tut={props.dataTutSeventh}
|
data-tut={props.dataTutSeventh}
|
||||||
onClick={() => handleOnclikFolder(data)}
|
onClick={() => {
|
||||||
|
if (!rename) {
|
||||||
|
handleOnclikFolder(data);
|
||||||
|
}
|
||||||
|
}}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -381,7 +380,6 @@ function DriveBody(props) {
|
|||||||
{rename === data.objectId ? (
|
{rename === data.objectId ? (
|
||||||
<input
|
<input
|
||||||
onFocus={() => {
|
onFocus={() => {
|
||||||
inputRef.current.setSelectionRange(0, 0);
|
|
||||||
const input = inputRef.current;
|
const input = inputRef.current;
|
||||||
if (input) {
|
if (input) {
|
||||||
input.select();
|
input.select();
|
||||||
@@ -393,9 +391,8 @@ function DriveBody(props) {
|
|||||||
onKeyDown={(e) => handleEnterPress(e, data)}
|
onKeyDown={(e) => handleEnterPress(e, data)}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
defaultValue={renameValue}
|
defaultValue={renameValue}
|
||||||
// value={renameValue}
|
|
||||||
onChange={(e) => setRenameValue(e.target.value)}
|
onChange={(e) => setRenameValue(e.target.value)}
|
||||||
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
|
className="op-input op-input-bordered op-input-xs w-[100px] focus:outline-none hover:border-base-content text-[10px]"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className="fileName">{data.Name}</span>
|
<span className="fileName">{data.Name}</span>
|
||||||
@@ -421,7 +418,11 @@ function DriveBody(props) {
|
|||||||
</ContextMenu.Root>
|
</ContextMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<HoverCard.Root openDelay={0} closeDelay={100}>
|
<HoverCard.Root
|
||||||
|
open={rename ? false : undefined}
|
||||||
|
openDelay={0}
|
||||||
|
closeDelay={100}
|
||||||
|
>
|
||||||
<HoverCard.Trigger asChild>
|
<HoverCard.Trigger asChild>
|
||||||
<div>
|
<div>
|
||||||
<ContextMenu.Root>
|
<ContextMenu.Root>
|
||||||
@@ -430,7 +431,11 @@ function DriveBody(props) {
|
|||||||
{/* pdf */}
|
{/* pdf */}
|
||||||
<div
|
<div
|
||||||
data-tut={props.dataTutSixth}
|
data-tut={props.dataTutSixth}
|
||||||
onClick={() => checkPdfStatus(data)}
|
onClick={() => {
|
||||||
|
if (!rename) {
|
||||||
|
checkPdfStatus(data);
|
||||||
|
}
|
||||||
|
}}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -445,7 +450,6 @@ function DriveBody(props) {
|
|||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
type="text"
|
type="text"
|
||||||
onFocus={() => {
|
onFocus={() => {
|
||||||
inputRef.current.setSelectionRange(0, 0);
|
|
||||||
const input = inputRef.current;
|
const input = inputRef.current;
|
||||||
if (input) {
|
if (input) {
|
||||||
input.select();
|
input.select();
|
||||||
@@ -455,9 +459,8 @@ function DriveBody(props) {
|
|||||||
onKeyDown={(e) => handleEnterPress(e, data)}
|
onKeyDown={(e) => handleEnterPress(e, data)}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
defaultValue={renameValue}
|
defaultValue={renameValue}
|
||||||
// value={renameValue}
|
|
||||||
onChange={(e) => setRenameValue(e.target.value)}
|
onChange={(e) => setRenameValue(e.target.value)}
|
||||||
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
|
className="op-input op-input-bordered op-input-xs w-[100px] focus:outline-none hover:border-base-content text-[10px]"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span className="fileName">{data.Name}</span>
|
<span className="fileName">{data.Name}</span>
|
||||||
@@ -503,7 +506,9 @@ function DriveBody(props) {
|
|||||||
className="ContextMenuItem"
|
className="ContextMenuItem"
|
||||||
>
|
>
|
||||||
<i className={menu.icon}></i>
|
<i className={menu.icon}></i>
|
||||||
<span className="ml-[8px]">{menu.type}</span>
|
<span className="ml-[8px]">
|
||||||
|
{t(`context-menu.${menu.type}`)}
|
||||||
|
</span>
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -514,18 +519,28 @@ function DriveBody(props) {
|
|||||||
</HoverCard.Trigger>
|
</HoverCard.Trigger>
|
||||||
<HoverCard.Portal>
|
<HoverCard.Portal>
|
||||||
<HoverCard.Content className="HoverCardContent" sideOffset={5}>
|
<HoverCard.Content className="HoverCardContent" sideOffset={5}>
|
||||||
<strong className="text-[13px]">Title: </strong>
|
<strong className="text-[13px]">
|
||||||
|
{t("report-heading.Title")}:{" "}
|
||||||
|
</strong>
|
||||||
<span className="text-[12px] font-medium mb-0"> {data.Name}</span>
|
<span className="text-[12px] font-medium mb-0"> {data.Name}</span>
|
||||||
<br />
|
<br />
|
||||||
<strong className="text-[13px]">Status: </strong>
|
<strong className="text-[13px]">
|
||||||
<span className="text-[12px] font-medium"> {status}</span>
|
{t("report-heading.Status")}:{" "}
|
||||||
|
</strong>
|
||||||
|
<span className="text-[12px] font-medium">
|
||||||
|
{t(`drive-document-status.${status}`)}
|
||||||
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<strong className="text-[13px]">Created Date: </strong>
|
<strong className="text-[13px]">
|
||||||
|
{t("report-heading.created-date")}:{" "}
|
||||||
|
</strong>
|
||||||
<span className="text-[12px] font-medium">{createddate}</span>
|
<span className="text-[12px] font-medium">{createddate}</span>
|
||||||
<br />
|
<br />
|
||||||
{signerExist && (
|
{signerExist && (
|
||||||
<>
|
<>
|
||||||
<strong className="text-[13px]">Signers: </strong>
|
<strong className="text-[13px]">
|
||||||
|
{t("report-heading.Signers")}:{" "}
|
||||||
|
</strong>
|
||||||
{signersName()}
|
{signersName()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -545,11 +560,11 @@ function DriveBody(props) {
|
|||||||
<Table striped bordered hover>
|
<Table striped bordered hover>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>{t("report-heading.Name")}</th>
|
||||||
<th>Created Date</th>
|
<th>{t("report-heading.created-date")}</th>
|
||||||
<th>Type</th>
|
<th>{t("report-heading.Type")}</th>
|
||||||
<th>Status</th>
|
<th>{t("report-heading.Status")}</th>
|
||||||
<th>Action</th>
|
<th>{t("action")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -582,25 +597,25 @@ function DriveBody(props) {
|
|||||||
)}
|
)}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isDeleteDoc}
|
isOpen={isDeleteDoc}
|
||||||
title={"Delete Document"}
|
title={t("delete-document")}
|
||||||
handleClose={() => setIsDeleteDoc(false)}
|
handleClose={() => setIsDeleteDoc(false)}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px] text-base-content">
|
<div className="h-full p-[20px] text-base-content">
|
||||||
<p>Are you sure you want to delete this document?</p>
|
<p>{t("delete-document-alert")}</p>
|
||||||
<div className="h-[1px] w-full bg-[#9f9f9f] my-[15px]"></div>
|
<div className="h-[1px] w-full bg-[#9f9f9f] my-[15px]"></div>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDeleteDocument(selectDoc)}
|
onClick={() => handleDeleteDocument(selectDoc)}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary mr-2"
|
className="op-btn op-btn-primary mr-2"
|
||||||
>
|
>
|
||||||
Yes
|
{t("yes")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsDeleteDoc(false)}
|
onClick={() => setIsDeleteDoc(false)}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-neutral"
|
className="op-btn op-btn-neutral"
|
||||||
>
|
>
|
||||||
No
|
{t("no")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const AddRoleModal = (props) => {
|
const AddRoleModal = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Add Role"}
|
title={t("add-role")}
|
||||||
isOpen={props.isModalRole}
|
isOpen={props.isModalRole}
|
||||||
handleClose={props.handleCloseRoleModal}
|
handleClose={props.handleCloseRoleModal}
|
||||||
>
|
>
|
||||||
@@ -21,19 +23,19 @@ const AddRoleModal = (props) => {
|
|||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs mt-1"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs mt-1"
|
||||||
/>
|
/>
|
||||||
<p className="text-[gray] text-[11px] mt-[5px] mb-[10px] ml-[10px]">
|
<p className="text-[gray] text-[11px] mt-[5px] mb-[10px] ml-[10px]">
|
||||||
e.g: Customer, Hr, Director, Manager, Student, etc...
|
{t("role-ex")}..
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<div className="h-[1px] w-full bg-[#9f9f9f] mb-[10px]"></div>
|
<div className="h-[1px] w-full bg-[#9f9f9f] mb-[10px]"></div>
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Add
|
{t("add")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={props.handleCloseRoleModal}
|
onClick={props.handleCloseRoleModal}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost ml-2"
|
className="op-btn op-btn-ghost ml-2"
|
||||||
>
|
>
|
||||||
Close
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -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,18 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const confirmToaddDefaultSign = () => {
|
const confirmToaddDefaultSign = () => {
|
||||||
if (xyPostion.length > 0) {
|
if (xyPostion.length > 0) {
|
||||||
setDefaultSignAlert({
|
setDefaultSignAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage:
|
alertMessage: t("default-sign-alert")
|
||||||
"Are you sure you want to auto sign at requested all locations?"
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setDefaultSignAlert({
|
setDefaultSignAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "please select position!"
|
alertMessage: t("please-select-position!")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -18,10 +20,10 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
|||||||
return (
|
return (
|
||||||
<div data-tut="reactourThird">
|
<div data-tut="reactourThird">
|
||||||
<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">
|
||||||
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">
|
||||||
<p className="text-base-content">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"
|
||||||
@@ -34,7 +36,7 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
|
|||||||
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()}
|
||||||
>
|
>
|
||||||
Auto Sign All
|
{t("auto-sign-all")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,16 +3,18 @@ import LoaderWithMsg from "../../primitives/LoaderWithMsg";
|
|||||||
import { contractDocument } from "../../constant/Utils";
|
import { contractDocument } from "../../constant/Utils";
|
||||||
import HandleError from "../../primitives/HandleError";
|
import HandleError from "../../primitives/HandleError";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function useQuery() {
|
function useQuery() {
|
||||||
return new URLSearchParams(useLocation().search);
|
return new URLSearchParams(useLocation().search);
|
||||||
}
|
}
|
||||||
function DraftDocument() {
|
function DraftDocument() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const query = useQuery();
|
const query = useQuery();
|
||||||
const docId = query.get("docId");
|
const docId = query.get("docId");
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoader: true,
|
isLoader: true,
|
||||||
message: "This might take some time"
|
message: t("loading-mssg")
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDocumentDetails();
|
getDocumentDetails();
|
||||||
@@ -52,7 +54,7 @@ function DraftDocument() {
|
|||||||
navigate(`/recipientSignPdf/${data.objectId}`);
|
navigate(`/recipientSignPdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has completed and signyour-self flow
|
//checking if document has completed and signyour-self flow
|
||||||
else if (!signerExist && !isPlaceholder) {
|
else if ((!signerExist && !isPlaceholder) || data?.IsSignyourself) {
|
||||||
navigate(`/signaturePdf/${data.objectId}`);
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has declined by someone
|
//checking if document has declined by someone
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import { isEnableSubscription } from "../../constant/const";
|
|||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import { radioButtonWidget } from "../../constant/Utils";
|
import { radioButtonWidget } from "../../constant/Utils";
|
||||||
import Upgrade from "../../primitives/Upgrade";
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
||||||
|
|
||||||
function DropdownWidgetOption(props) {
|
function DropdownWidgetOption(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [dropdownOptionList, setDropdownOptionList] = useState([
|
const [dropdownOptionList, setDropdownOptionList] = useState([
|
||||||
"option-1",
|
"option-1",
|
||||||
"option-2"
|
"option-2"
|
||||||
@@ -155,9 +159,12 @@ function DropdownWidgetOption(props) {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-[13px] font-semibold">
|
<label className="text-[13px] font-semibold">
|
||||||
Name<span className="text-[red] text-[13px]"> *</span>
|
{t("name")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
defaultValue={dropdownName}
|
defaultValue={dropdownName}
|
||||||
value={dropdownName}
|
value={dropdownName}
|
||||||
@@ -166,7 +173,7 @@ function DropdownWidgetOption(props) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<label className="text-[13px] font-semibold mt-[5px]">
|
<label className="text-[13px] font-semibold mt-[5px]">
|
||||||
Options
|
{t("options")}
|
||||||
</label>
|
</label>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{dropdownOptionList.map((option, index) => (
|
{dropdownOptionList.map((option, index) => (
|
||||||
@@ -196,6 +203,10 @@ function DropdownWidgetOption(props) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
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"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -222,12 +233,16 @@ function DropdownWidgetOption(props) {
|
|||||||
!props.isSubscribe ? "text-[gray]" : ""
|
!props.isSubscribe ? "text-[gray]" : ""
|
||||||
} text-[13px] font-semibold`}
|
} text-[13px] font-semibold`}
|
||||||
>
|
>
|
||||||
Minimun check
|
{t("minimun-check")}
|
||||||
</label>
|
</label>
|
||||||
{!props.isSubscribe && isEnableSubscription && (
|
{!props.isSubscribe && isEnableSubscription && (
|
||||||
<Upgrade />
|
<Upgrade />
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
defaultValue={0}
|
defaultValue={0}
|
||||||
value={minCount}
|
value={minCount}
|
||||||
@@ -245,9 +260,13 @@ function DropdownWidgetOption(props) {
|
|||||||
!props.isSubscribe ? "text-[gray]" : ""
|
!props.isSubscribe ? "text-[gray]" : ""
|
||||||
} text-[13px] font-semibold`}
|
} text-[13px] font-semibold`}
|
||||||
>
|
>
|
||||||
Maximum check
|
{t("maximum-check")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
defaultValue={0}
|
defaultValue={0}
|
||||||
value={maxCount}
|
value={maxCount}
|
||||||
@@ -268,7 +287,7 @@ function DropdownWidgetOption(props) {
|
|||||||
{["dropdown", radioButtonWidget].includes(props.type) && (
|
{["dropdown", radioButtonWidget].includes(props.type) && (
|
||||||
<>
|
<>
|
||||||
<label className="text-[13px] font-semibold mt-[5px]">
|
<label className="text-[13px] font-semibold mt-[5px]">
|
||||||
Default value
|
{t("default-value")}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
onChange={(e) => setDefaultValue(e.target.value)}
|
onChange={(e) => setDefaultValue(e.target.value)}
|
||||||
@@ -278,7 +297,7 @@ function DropdownWidgetOption(props) {
|
|||||||
placeholder="select default value"
|
placeholder="select default value"
|
||||||
>
|
>
|
||||||
<option value="" disabled hidden className="text-[13px]">
|
<option value="" disabled hidden className="text-[13px]">
|
||||||
Select...
|
{t("select")}...
|
||||||
</option>
|
</option>
|
||||||
{dropdownOptionList.map((data, ind) => {
|
{dropdownOptionList.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
@@ -313,6 +332,55 @@ function DropdownWidgetOption(props) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<div className="flex items-center mt-3 mb-3">
|
||||||
|
<span>{t("font-size")} :</span>
|
||||||
|
<select
|
||||||
|
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
|
value={
|
||||||
|
props.fontSize ||
|
||||||
|
props.currWidgetsDetails?.options?.fontSize ||
|
||||||
|
"12"
|
||||||
|
}
|
||||||
|
onChange={(e) => props.setFontSize(e.target.value)}
|
||||||
|
>
|
||||||
|
{fontsizeArr.map((size, ind) => {
|
||||||
|
return (
|
||||||
|
<option className="text-[13px]" value={size} key={ind}>
|
||||||
|
{size}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<div className="flex flex-row gap-1 items-center ml-4 ">
|
||||||
|
<span>{t("color")} : </span>
|
||||||
|
<select
|
||||||
|
value={
|
||||||
|
props.fontColor ||
|
||||||
|
props.currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black"
|
||||||
|
}
|
||||||
|
onChange={(e) => props.setFontColor(e.target.value)}
|
||||||
|
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
|
>
|
||||||
|
{fontColorArr.map((color, ind) => {
|
||||||
|
return (
|
||||||
|
<option value={color} key={ind}>
|
||||||
|
{t(`color-type.${color}`)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
props.fontColor ||
|
||||||
|
props.currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black"
|
||||||
|
}}
|
||||||
|
className="w-5 h-[19px] ml-1"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{["checkbox", radioButtonWidget].includes(props.type) && (
|
{["checkbox", radioButtonWidget].includes(props.type) && (
|
||||||
<div className="flex flex-row gap-5 my-2 items-center text-center">
|
<div className="flex flex-row gap-5 my-2 items-center text-center">
|
||||||
{!props.isSignYourself && (
|
{!props.isSignYourself && (
|
||||||
@@ -325,7 +393,7 @@ function DropdownWidgetOption(props) {
|
|||||||
onChange={(e) => setIsReadOnly(e.target.checked)}
|
onChange={(e) => setIsReadOnly(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label className="ml-1 mb-0" htmlFor="isreadonly">
|
<label className="ml-1 mb-0" htmlFor="isreadonly">
|
||||||
Is read only
|
{t("read-only")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -339,12 +407,13 @@ function DropdownWidgetOption(props) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<label className="ml-1 mb-0" htmlFor="ishidelabel">
|
<label className="ml-1 mb-0" htmlFor="ishidelabel">
|
||||||
Hide labels
|
{t("hide-labels")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
props.type === "checkbox" && !props.isSignYourself
|
props.type === "checkbox" && !props.isSignYourself
|
||||||
@@ -358,7 +427,7 @@ function DropdownWidgetOption(props) {
|
|||||||
type="submit"
|
type="submit"
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
Save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
{props.currWidgetsDetails?.options?.values?.length > 0 && (
|
{props.currWidgetsDetails?.options?.values?.length > 0 && (
|
||||||
<button
|
<button
|
||||||
@@ -369,7 +438,7 @@ function DropdownWidgetOption(props) {
|
|||||||
resetState();
|
resetState();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ import React, { useState, useEffect } from "react";
|
|||||||
import { checkIsSubscribed, getFileName } from "../../constant/Utils";
|
import { checkIsSubscribed, getFileName } from "../../constant/Utils";
|
||||||
import Upgrade from "../../primitives/Upgrade";
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
import { isEnableSubscription } from "../../constant/const";
|
import { isEnableSubscription } from "../../constant/const";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Tooltip } from "react-tooltip";
|
||||||
|
|
||||||
// import SelectFolder from "../../premitives/SelectFolder";
|
// import SelectFolder from "../../premitives/SelectFolder";
|
||||||
|
|
||||||
const EditTemplate = ({ template, onSuccess }) => {
|
const EditTemplate = ({ template, onSuccess }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
// const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
// const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
Name: template?.Name || "",
|
Name: template?.Name || "",
|
||||||
@@ -12,7 +16,11 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
Description: template?.Description || "",
|
Description: template?.Description || "",
|
||||||
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",
|
||||||
|
IsTourEnabled: template?.IsTourEnabled
|
||||||
|
? `${template?.IsTourEnabled}`
|
||||||
|
: "false"
|
||||||
});
|
});
|
||||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -21,8 +29,8 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
const fetchSubscription = async () => {
|
const fetchSubscription = async () => {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const getIsSubscribe = await checkIsSubscribed();
|
const subscribe = await checkIsSubscribed();
|
||||||
setIsSubscribe(getIsSubscribe);
|
setIsSubscribe(subscribe.isValid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleStrInput = (e) => {
|
const handleStrInput = (e) => {
|
||||||
@@ -38,8 +46,9 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
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;
|
||||||
let reminderDate = {};
|
let reminderDate = {};
|
||||||
if (AutoReminder) {
|
if (AutoReminder) {
|
||||||
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
|
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
|
||||||
@@ -47,7 +56,13 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
||||||
reminderDate = { NextReminderDate: ReminderDate };
|
reminderDate = { NextReminderDate: ReminderDate };
|
||||||
}
|
}
|
||||||
const data = { ...formData, SendinOrder: isChecked, ...reminderDate };
|
const data = {
|
||||||
|
...formData,
|
||||||
|
SendinOrder: isChecked,
|
||||||
|
IsEnableOTP: IsEnableOTP,
|
||||||
|
IsTourEnabled: isTourEnabled,
|
||||||
|
...reminderDate
|
||||||
|
};
|
||||||
onSuccess(data);
|
onSuccess(data);
|
||||||
};
|
};
|
||||||
const handleAutoReminder = () => {
|
const handleAutoReminder = () => {
|
||||||
@@ -62,7 +77,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label htmlFor="name" className="text-[13px]">
|
<label htmlFor="name" className="text-[13px]">
|
||||||
File
|
{t("report-heading.File")}
|
||||||
</label>
|
</label>
|
||||||
<div className="op-input op-input-bordered op-input-sm focus:outline-none py-2 font-semibold w-full text-xs">
|
<div className="op-input op-input-bordered op-input-sm focus:outline-none py-2 font-semibold w-full text-xs">
|
||||||
{getFileName(template.URL)}
|
{getFileName(template.URL)}
|
||||||
@@ -70,7 +85,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]">
|
||||||
Name
|
{t("name")}
|
||||||
<span className="text-[13px] text-[red]"> *</span>
|
<span className="text-[13px] text-[red]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -78,13 +93,15 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
name="Name"
|
name="Name"
|
||||||
value={formData.Name}
|
value={formData.Name}
|
||||||
onChange={(e) => handleStrInput(e)}
|
onChange={(e) => handleStrInput(e)}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
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>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label htmlFor="Note" className="text-[13px]">
|
<label htmlFor="Note" className="text-[13px]">
|
||||||
Note
|
{t("report-heading.Note")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -97,7 +114,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label htmlFor="Description" className="text-[13px]">
|
<label htmlFor="Description" className="text-[13px]">
|
||||||
Description
|
{t("description")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -109,7 +126,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-[0.35rem]">
|
<div className="mb-[0.35rem]">
|
||||||
<label className="text-[13px]">Send In Order</label>
|
<label className="text-[13px]">{t("send-in-order")}</label>
|
||||||
<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"
|
||||||
@@ -119,7 +136,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
checked={formData.SendinOrder === "true"}
|
checked={formData.SendinOrder === "true"}
|
||||||
onChange={handleStrInput}
|
onChange={handleStrInput}
|
||||||
/>
|
/>
|
||||||
<div className="text-[12px]">Yes</div>
|
<div className="text-[12px]">{t("yes")}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
|
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
|
||||||
<input
|
<input
|
||||||
@@ -130,7 +147,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
checked={formData.SendinOrder === "false"}
|
checked={formData.SendinOrder === "false"}
|
||||||
onChange={handleStrInput}
|
onChange={handleStrInput}
|
||||||
/>
|
/>
|
||||||
<div className="text-[12px]">No</div>
|
<div className="text-[12px]">{t("no")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && (
|
||||||
@@ -140,7 +157,8 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
isSubscribe ? "font-semibold" : "font-semibold text-gray-300"
|
isSubscribe ? "font-semibold" : "font-semibold text-gray-300"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Auto reminder{" "}
|
{t("auto-reminder")}
|
||||||
|
{" "}
|
||||||
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
</span>
|
</span>
|
||||||
<label
|
<label
|
||||||
@@ -162,7 +180,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
{isSubscribe && formData?.AutomaticReminders === true && (
|
{isSubscribe && formData?.AutomaticReminders === true && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
Remind once in every (Days)
|
{t("remind-once")}
|
||||||
<span className="text-red-500 text-[13px]">*</span>
|
<span className="text-red-500 text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -171,13 +189,134 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
name="RemindOnceInEvery"
|
name="RemindOnceInEvery"
|
||||||
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"
|
||||||
onChange={handleStrInput}
|
onChange={handleStrInput}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isEnableSubscription && (
|
||||||
|
<div className="text-xs mt-2">
|
||||||
|
<label className="block">
|
||||||
|
<span className={isSubscribe ? "" : " text-gray-300"}>
|
||||||
|
{t("isenable-otp")}{" "}
|
||||||
|
<a data-tooltip-id="isenableotp-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 />}
|
||||||
|
</span>
|
||||||
|
<Tooltip id="isenableotp-tooltip" className="z-50">
|
||||||
|
<div className="max-w-[200px] md:max-w-[450px]">
|
||||||
|
<p className="font-bold">{t("isenable-otp")}</p>
|
||||||
|
<p>{t("isenable-otp-help.p1")}</p>
|
||||||
|
<p className="p-[5px]">
|
||||||
|
<ol className="list-disc">
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">{t("yes")}: </span>
|
||||||
|
<span>{t("isenable-otp-help.p2")}</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="font-bold">{t("no")}: </span>
|
||||||
|
<span>{t("isenable-otp-help.p3")}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<p>{t("isenable-otp-help.p4")}</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isSubscribe ? "" : "pointer-events-none opacity-50"
|
||||||
|
} flex items-center gap-2 ml-2 mb-1 `}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={"true"}
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
name="IsEnableOTP"
|
||||||
|
checked={formData.IsEnableOTP === "true"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<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
|
||||||
|
type="radio"
|
||||||
|
value={"false"}
|
||||||
|
name="IsEnableOTP"
|
||||||
|
className="op-radio op-radio-xs"
|
||||||
|
checked={formData.IsEnableOTP === "false"}
|
||||||
|
onChange={handleStrInput}
|
||||||
|
/>
|
||||||
|
<div className="text-center">{t("no")}</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 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 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">
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Quill } from "react-quill";
|
import { Quill } from "react-quill-new";
|
||||||
|
|
||||||
// Custom Undo button icon component for Quill editor. You can import it directly
|
// Custom Undo button icon component for Quill editor. You can import it directly
|
||||||
// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
|
// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
|
||||||
@@ -79,7 +79,6 @@ export const formats = [
|
|||||||
"blockquote",
|
"blockquote",
|
||||||
"background",
|
"background",
|
||||||
"list",
|
"list",
|
||||||
"bullet",
|
|
||||||
"indent",
|
"indent",
|
||||||
"link",
|
"link",
|
||||||
"image",
|
"image",
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Tooltip from "../../primitives/Tooltip";
|
import Tooltip from "../../primitives/Tooltip";
|
||||||
import ReactQuill from "react-quill";
|
import ReactQuill from "react-quill-new";
|
||||||
import "react-quill/dist/quill.snow.css";
|
import "../../styles/quill.css";
|
||||||
import EditorToolbar, { module1, formats } from "./EditorToolbar";
|
import EditorToolbar, { module1, formats } from "./EditorToolbar";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export function EmailBody(props) {
|
export function EmailBody(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<form className="flex flex-col text-base-content text-lg font-normal">
|
<form className="flex flex-col text-base-content text-lg font-normal">
|
||||||
<div className="m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md">
|
<div className="m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md">
|
||||||
<label className="text-sm ml-2">
|
<label className="text-sm ml-2">
|
||||||
Subject <Tooltip message={"email subject"} />
|
{t("subject")} <Tooltip message={t("email-subject")} />
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
required
|
required
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
value={props.requestSubject}
|
value={props.requestSubject}
|
||||||
onChange={(e) => props.setRequestSubject(e.target.value)}
|
onChange={(e) => props.setRequestSubject(e.target.value)}
|
||||||
placeholder='${senderName} has requested you to sign "${documentName}"'
|
placeholder='${senderName} has requested you to sign "${documentName}"'
|
||||||
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"
|
||||||
/>
|
/>
|
||||||
<label className="text-sm ml-2 mt-3">
|
<label className="text-sm ml-2 mt-3">
|
||||||
Body <Tooltip message={"email body"} />
|
{t("body")} <Tooltip message={t("email-body")} />
|
||||||
</label>
|
</label>
|
||||||
<div className="px-3 py-2 w-full focus:outline-none text-xs">
|
<div className="px-1 py-2 w-full focus:outline-none text-xs">
|
||||||
<EditorToolbar containerId="toolbar1" />
|
<EditorToolbar containerId="toolbar1" />
|
||||||
<ReactQuill
|
<ReactQuill
|
||||||
theme="snow"
|
theme="snow"
|
||||||
value={props.requestBody}
|
value={props.requestBody}
|
||||||
// value={typedText}
|
placeholder={t("email-placeholder")}
|
||||||
placeholder="add body of email "
|
|
||||||
// readOnly={loading}
|
|
||||||
// onChangeSelection={handleTextSelection} // Listen for text selection
|
|
||||||
ref={props.editorRef}
|
ref={props.editorRef}
|
||||||
modules={module1}
|
modules={module1}
|
||||||
formats={formats}
|
formats={formats}
|
||||||
|
|||||||
@@ -1,38 +1,62 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { saveAs } from "file-saver";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { getBase64FromUrl } from "../../constant/Utils";
|
import { handleToPrint } from "../../constant/Utils";
|
||||||
import { themeColor, emailRegex } from "../../constant/const";
|
import { themeColor, emailRegex } from "../../constant/const";
|
||||||
import printModule from "print-js";
|
|
||||||
import Loader from "../../primitives/Loader";
|
import Loader from "../../primitives/Loader";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function EmailComponent({
|
function EmailComponent({
|
||||||
isEmail,
|
isEmail,
|
||||||
pdfUrl,
|
pdfUrl,
|
||||||
setIsEmail,
|
setIsEmail,
|
||||||
setSuccessEmail,
|
setSuccessEmail,
|
||||||
pdfName,
|
pdfDetails,
|
||||||
sender,
|
sender,
|
||||||
setIsAlert,
|
setIsAlert,
|
||||||
extUserId,
|
extUserId,
|
||||||
activeMailAdapter
|
activeMailAdapter,
|
||||||
|
setIsDownloadModal
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [emailList, setEmailList] = useState([]);
|
const [emailList, setEmailList] = useState([]);
|
||||||
const [emailValue, setEmailValue] = useState("");
|
const [emailValue, setEmailValue] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [emailErr, setEmailErr] = useState(false);
|
const [emailErr, setEmailErr] = useState(false);
|
||||||
|
const [isDownloading, setIsDownloading] = useState("");
|
||||||
|
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||||
//function for send email
|
//function for send email
|
||||||
const sendEmail = async () => {
|
const sendEmail = async () => {
|
||||||
|
const pdfName = pdfDetails[0]?.Name;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
let sendMail;
|
let sendMail;
|
||||||
|
const docId = pdfDetails?.[0]?.objectId || "";
|
||||||
|
const FileAdapterId = pdfDetails?.[0]?.FileAdapterId
|
||||||
|
? pdfDetails?.[0]?.FileAdapterId
|
||||||
|
: "";
|
||||||
|
let presignedUrl = pdfUrl;
|
||||||
|
try {
|
||||||
|
const axiosRes = await axios.post(
|
||||||
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
|
{ url: pdfUrl, docId: docId, fileAdapterId: FileAdapterId },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"content-type": "Application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
presignedUrl = axiosRes.data.result;
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in getsignedurl", err);
|
||||||
|
}
|
||||||
for (let i = 0; i < emailList.length; i++) {
|
for (let i = 0; i < emailList.length; i++) {
|
||||||
try {
|
try {
|
||||||
const imgPng =
|
const imgPng =
|
||||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||||
|
|
||||||
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
|
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
|
||||||
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"),
|
||||||
@@ -44,7 +68,7 @@ function EmailComponent({
|
|||||||
mailProvider: activeMailAdapter,
|
mailProvider: activeMailAdapter,
|
||||||
extUserId: extUserId,
|
extUserId: extUserId,
|
||||||
pdfName: pdfName,
|
pdfName: pdfName,
|
||||||
url: pdfUrl,
|
url: presignedUrl,
|
||||||
recipient: emailList[i],
|
recipient: emailList[i],
|
||||||
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
||||||
from: sender.email,
|
from: sender.email,
|
||||||
@@ -68,36 +92,25 @@ function EmailComponent({
|
|||||||
setIsEmail(false);
|
setIsEmail(false);
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sendMail?.data?.result?.status === "success") {
|
||||||
if (sendMail && sendMail.data.result.status === "success") {
|
|
||||||
setSuccessEmail(true);
|
setSuccessEmail(true);
|
||||||
|
setIsEmail(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSuccessEmail(false);
|
setSuccessEmail(false);
|
||||||
setIsEmail(false);
|
|
||||||
setEmailValue("");
|
setEmailValue("");
|
||||||
setEmailList([]);
|
setEmailList([]);
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} else if (sendMail && sendMail.data.result.status === "error") {
|
|
||||||
setIsLoading(false);
|
|
||||||
setIsEmail(false);
|
|
||||||
setIsAlert({
|
|
||||||
isShow: true,
|
|
||||||
alertMessage: "something went wrong"
|
|
||||||
});
|
|
||||||
setEmailValue("");
|
|
||||||
setEmailList([]);
|
|
||||||
} else {
|
} else {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsEmail(false);
|
setIsEmail(false);
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
setEmailValue("");
|
setEmailValue("");
|
||||||
setEmailList([]);
|
setEmailList([]);
|
||||||
@@ -111,7 +124,7 @@ function EmailComponent({
|
|||||||
};
|
};
|
||||||
//function for get email value
|
//function for get email value
|
||||||
const handleEmailValue = (e) => {
|
const handleEmailValue = (e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value?.toLowerCase()?.replace(/\s/g, "");
|
||||||
setEmailErr(false);
|
setEmailErr(false);
|
||||||
setEmailValue(value);
|
setEmailValue(value);
|
||||||
};
|
};
|
||||||
@@ -138,43 +151,11 @@ function EmailComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleClose = () => {
|
||||||
// function for print signed pdf
|
setIsEmail(false);
|
||||||
const handleToPrint = async (event) => {
|
setEmailValue("");
|
||||||
event.preventDefault();
|
setEmailList([]);
|
||||||
|
|
||||||
const pdf = await getBase64FromUrl(pdfUrl);
|
|
||||||
const isAndroidDevice = navigator.userAgent.match(/Android/i);
|
|
||||||
const isAppleDevice =
|
|
||||||
(/iPad|iPhone|iPod/.test(navigator.platform) ||
|
|
||||||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
|
|
||||||
!window.MSStream;
|
|
||||||
if (isAndroidDevice || isAppleDevice) {
|
|
||||||
const byteArray = Uint8Array.from(
|
|
||||||
atob(pdf)
|
|
||||||
.split("")
|
|
||||||
.map((char) => char.charCodeAt(0))
|
|
||||||
);
|
|
||||||
const blob = new Blob([byteArray], { type: "application/pdf" });
|
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
|
||||||
window.open(blobUrl, "_blank");
|
|
||||||
} else {
|
|
||||||
printModule({ printable: pdf, type: "pdf", base64: true });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//handle download signed pdf
|
|
||||||
const handleDownloadPdf = () => {
|
|
||||||
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sanitizeFileName = (pdfName) => {
|
|
||||||
// Replace spaces with underscore
|
|
||||||
return pdfName.replace(/ /g, "_");
|
|
||||||
};
|
|
||||||
|
|
||||||
const isAndroid = /Android/i.test(navigator.userAgent);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* isEmail */}
|
{/* isEmail */}
|
||||||
@@ -184,36 +165,46 @@ function EmailComponent({
|
|||||||
<div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2]/70">
|
<div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2]/70">
|
||||||
<Loader />
|
<Loader />
|
||||||
<span className="text-[12px] text-base-content">
|
<span className="text-[12px] text-base-content">
|
||||||
This might take some time
|
{t("loader")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isDownloading === "pdf" && (
|
||||||
|
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="flex justify-between items-center py-[10px] px-[20px] border-b-[1px] border-base-content">
|
<div className="flex justify-between items-center py-[10px] px-[20px] border-b-[1px] border-base-content">
|
||||||
<span className="text-base-content font-semibold">
|
<span className="text-base-content font-semibold">
|
||||||
Successfully signed!
|
{t("successfully-signed")}
|
||||||
</span>
|
</span>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
{!isAndroid && (
|
{!isAndroid && (
|
||||||
<button
|
<button
|
||||||
onClick={handleToPrint}
|
onClick={(e) =>
|
||||||
|
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
|
||||||
|
}
|
||||||
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
|
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-print" aria-hidden="true"></i>
|
<i className="fa-light fa-print" aria-hidden="true"></i>
|
||||||
Print
|
{t("print")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
|
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
|
||||||
onClick={() => handleDownloadPdf()}
|
onClick={() => {
|
||||||
|
handleClose();
|
||||||
|
setIsDownloadModal(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-download" aria-hidden="true"></i>
|
<i className="fa-light fa-download" aria-hidden="true"></i>
|
||||||
Download
|
{t("download")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full p-[20px]">
|
<div className="h-full p-[20px]">
|
||||||
<p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
|
<p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
|
||||||
Recipients added here will get a copy of the signed document.
|
{t("email-mssg")}
|
||||||
</p>
|
</p>
|
||||||
{emailList.length > 0 ? (
|
{emailList.length > 0 ? (
|
||||||
<div className="p-0 border-[1.5px] op-border-primary rounded w-full text-[15px]">
|
<div className="p-0 border-[1.5px] op-border-primary rounded w-full text-[15px]">
|
||||||
@@ -245,6 +236,10 @@ function EmailComponent({
|
|||||||
onChange={handleEmailValue}
|
onChange={handleEmailValue}
|
||||||
onKeyDown={handleEnterPress}
|
onKeyDown={handleEnterPress}
|
||||||
onBlur={() => emailValue && handleEnterPress("add")}
|
onBlur={() => emailValue && handleEnterPress("add")}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -257,15 +252,19 @@ function EmailComponent({
|
|||||||
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-transparent border-[1.5px] op-border-primary"
|
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-transparent border-[1.5px] op-border-primary"
|
||||||
onChange={handleEmailValue}
|
onChange={handleEmailValue}
|
||||||
onKeyDown={handleEnterPress}
|
onKeyDown={handleEnterPress}
|
||||||
placeholder="Add an email address and hit enter"
|
placeholder={t("enter-email-plaholder")}
|
||||||
onBlur={() => emailValue && handleEnterPress("add")}
|
onBlur={() => emailValue && handleEnterPress("add")}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{emailErr && (
|
{emailErr && (
|
||||||
<p className="text-xs text-[red] ml-1.5 mt-0.5">
|
<p className="text-xs text-[red] ml-1.5 mt-0.5">
|
||||||
please provide correct email address
|
{t("email-error-1")}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
@@ -278,10 +277,8 @@ function EmailComponent({
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
|
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
|
||||||
<span className="font-bold">Note: </span>
|
<span className="font-bold">{t("report-heading.Note")}: </span>
|
||||||
<span className="text-[15px]">
|
<span className="text-[15px]">{t("email-error-2")}</span>
|
||||||
You can only send to ten recipients at a time.
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<hr className="w-full my-[15px] bg-base-content" />
|
<hr className="w-full my-[15px] bg-base-content" />
|
||||||
<button
|
<button
|
||||||
@@ -289,18 +286,14 @@ function EmailComponent({
|
|||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
onClick={() => emailList.length > 0 && sendEmail()}
|
onClick={() => emailList.length > 0 && sendEmail()}
|
||||||
>
|
>
|
||||||
Send
|
{t("send")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost ml-2"
|
className="op-btn op-btn-ghost ml-2"
|
||||||
onClick={() => {
|
onClick={() => handleClose()}
|
||||||
setIsEmail(false);
|
|
||||||
setEmailValue("");
|
|
||||||
setEmailList([]);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Close
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -0,0 +1,269 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
|
import { tomorrow } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||||
|
import { copytoData } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function EmbedTab(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const tabName = [
|
||||||
|
{ title: "React/Next.js", icon: "fa-brands fa-react", color: "#61dafb" },
|
||||||
|
{ title: "JavaScript", icon: "fa-brands fa-js", color: "#ffd43b" },
|
||||||
|
{ title: "Angular", icon: "fa-brands fa-angular", color: "#ff5733" }
|
||||||
|
];
|
||||||
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
// State to track if the code has been copied
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
const reactCode = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "Installation",
|
||||||
|
codeString: `
|
||||||
|
npm install @opensign/react`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Usage",
|
||||||
|
codeString: `
|
||||||
|
import React from "react";
|
||||||
|
import Opensign from "@opensign/react";
|
||||||
|
|
||||||
|
export function App() {
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<Opensign
|
||||||
|
onLoad={() => console.log("success")}
|
||||||
|
onLoadError={(error) => console.log(error)}
|
||||||
|
templateId= "${props.templateId}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const angularCode = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "Installation",
|
||||||
|
codeString: `
|
||||||
|
npm install @opensign/angular`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Usage",
|
||||||
|
codeString: `
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {OpensignComponent} from "@opensign/angular"
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector:'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [OpensignComponent],
|
||||||
|
template:\`<opensign templateId="${props.templateId}"
|
||||||
|
(onLoad)="handleLoad()"
|
||||||
|
(onLoadError)="handleError($event)"
|
||||||
|
></opensign>\`,
|
||||||
|
})
|
||||||
|
export class AppComponent{
|
||||||
|
handleLoad() {
|
||||||
|
console.log("success");
|
||||||
|
}
|
||||||
|
handleError(error: string) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const jsCodeString = `
|
||||||
|
<script
|
||||||
|
src= "https://app.opensignlabs.com/static/js/public-template.bundle.js"
|
||||||
|
id="opensign-script"
|
||||||
|
templateId=${props.templateId}
|
||||||
|
></script>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const handleCopy = (code, ind) => {
|
||||||
|
copytoData(code);
|
||||||
|
setIsCopied({ ...isCopied, [ind]: true });
|
||||||
|
setTimeout(() => setIsCopied(false), 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4 border-t-[1px]">
|
||||||
|
<div className="flex justify-center items-center mt-2">
|
||||||
|
<div role="tablist" className="op-tabs op-tabs-bordered">
|
||||||
|
{tabName.map((tabData, ind) => (
|
||||||
|
<div
|
||||||
|
onClick={() => setActiveTab(ind)}
|
||||||
|
key={ind}
|
||||||
|
role="tab"
|
||||||
|
className={`${
|
||||||
|
activeTab === ind ? "op-tab-active" : ""
|
||||||
|
} op-tab flex items-center`}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className={`${tabData.icon}`}
|
||||||
|
style={{ color: tabData.color }}
|
||||||
|
></i>
|
||||||
|
<span className="ml-1 text-[10px] font-medium md:font-normal md:text-[15px]">
|
||||||
|
{tabData.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{activeTab === 0 ? (
|
||||||
|
<div className="mt-4">
|
||||||
|
{reactCode.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind}>
|
||||||
|
<p className="font-medium text-[18px]">
|
||||||
|
{t(`${data.title}`)}
|
||||||
|
</p>
|
||||||
|
{ind === 0 && (
|
||||||
|
<p className="text-[13px] mt-2">
|
||||||
|
{t("public-template-mssg-1")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[ind] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{data.codeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<p className="font-medium text-[15px]">
|
||||||
|
{t("public-template-mssg-3")}
|
||||||
|
</p>
|
||||||
|
<p className="my-[6px]">
|
||||||
|
{" "}
|
||||||
|
{t("public-template-mssg-4")}
|
||||||
|
<a
|
||||||
|
href="https://www.npmjs.com/package/@opensign/react"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="cursor-pointer text-blue-700 "
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
OpenSign React package{" "}
|
||||||
|
</a>
|
||||||
|
{t("public-template-mssg-5")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : activeTab === 1 ? (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div>
|
||||||
|
{/* <p className="font-medium text-[18px]">{t(`${data.title}`)}</p> */}
|
||||||
|
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(jsCodeString, 0)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[0] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{jsCodeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
activeTab === 2 && (
|
||||||
|
<div className="mt-4">
|
||||||
|
{angularCode.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind}>
|
||||||
|
<p className="font-medium text-[18px]">
|
||||||
|
{t(`${data.title}`)}
|
||||||
|
</p>
|
||||||
|
{ind === 0 && (
|
||||||
|
<p className="text-[13px] mt-2">
|
||||||
|
{t("angular-npm-mssg-1")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[ind] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{data.codeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<p className="font-medium text-[15px]">
|
||||||
|
{t("public-template-mssg-3")}
|
||||||
|
</p>
|
||||||
|
<p className="my-[6px]">
|
||||||
|
{" "}
|
||||||
|
{t("public-template-mssg-4")}
|
||||||
|
<a
|
||||||
|
href="https://www.npmjs.com/package/@opensign/angular"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="cursor-pointer text-blue-700 "
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
OpenSign Angular package{" "}
|
||||||
|
</a>
|
||||||
|
{t("public-template-mssg-5")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmbedTab;
|
||||||
@@ -9,6 +9,7 @@ import "../../styles/signature.css";
|
|||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import Loader from "../../primitives/Loader";
|
import Loader from "../../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
isPdfRequestFiles,
|
isPdfRequestFiles,
|
||||||
@@ -33,8 +34,15 @@ function Header({
|
|||||||
setIsEmail,
|
setIsEmail,
|
||||||
completeBtnTitle,
|
completeBtnTitle,
|
||||||
setIsEditTemplate,
|
setIsEditTemplate,
|
||||||
isPublicTemplate
|
isPublicTemplate,
|
||||||
|
clickOnZoomIn,
|
||||||
|
clickOnZoomOut,
|
||||||
|
handleRotationFun,
|
||||||
|
isDisableRotate,
|
||||||
|
templateId,
|
||||||
|
setIsDownloadModal
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const filterPrefill =
|
const filterPrefill =
|
||||||
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
|
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
@@ -46,7 +54,6 @@ function Header({
|
|||||||
const currentDecline = { currnt: "Sure", isDeclined: true };
|
const currentDecline = { currnt: "Sure", isDeclined: true };
|
||||||
setIsDecline(currentDecline);
|
setIsDecline(currentDecline);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex py-[5px]">
|
<div className="flex py-[5px]">
|
||||||
{isMobile && isShowHeader ? (
|
{isMobile && isShowHeader ? (
|
||||||
@@ -71,7 +78,7 @@ function Header({
|
|||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
changePage={changePage}
|
changePage={changePage}
|
||||||
/>
|
/>
|
||||||
{pdfUrl && alreadySign ? (
|
{isCompleted || alreadySign ? (
|
||||||
<DropdownMenu.Root>
|
<DropdownMenu.Root>
|
||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
<div className="op-link op-link-primary no-underline text-[16px] font-semibold pr-[3px] pl-[5px]">
|
<div className="op-link op-link-primary no-underline text-[16px] font-semibold pr-[3px] pl-[5px]">
|
||||||
@@ -88,16 +95,20 @@ function Header({
|
|||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="DropdownMenuItem"
|
className="DropdownMenuItem"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
if (isCompleted) {
|
||||||
}
|
setIsDownloadModal(true);
|
||||||
|
} else {
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<i
|
<i
|
||||||
className="fa-light fa-arrow-down mr-[3px]"
|
className="fa-light fa-arrow-down mr-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Download
|
{t("download")}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{isCompleted && (
|
{isCompleted && (
|
||||||
@@ -115,7 +126,7 @@ function Header({
|
|||||||
className="fa-light fa-award mr-[3px]"
|
className="fa-light fa-award mr-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Certificate
|
{t("certificate")}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
)}
|
)}
|
||||||
@@ -129,14 +140,14 @@ function Header({
|
|||||||
className="fa-light fa-envelope mr-[3px]"
|
className="fa-light fa-envelope mr-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Mail
|
{t("mail")}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
)}
|
)}
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="DropdownMenuItem"
|
className="DropdownMenuItem"
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
handleToPrint(e, pdfUrl, setIsDownloading)
|
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
@@ -144,7 +155,7 @@ function Header({
|
|||||||
className="fa-light fa-print mr-[3px]"
|
className="fa-light fa-print mr-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Print
|
{t("print")}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
@@ -162,7 +173,7 @@ function Header({
|
|||||||
onClick={() => handleDeclinePdfAlert()}
|
onClick={() => handleDeclinePdfAlert()}
|
||||||
className="text-[red] border-none font-[650] text-[14px] mr-2"
|
className="text-[red] border-none font-[650] text-[14px] mr-2"
|
||||||
>
|
>
|
||||||
Decline
|
{t("decline")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isPlaceholder ? (
|
{isPlaceholder ? (
|
||||||
@@ -177,21 +188,15 @@ function Header({
|
|||||||
} op-link no-underline font-[650] text-[14px]`}
|
} op-link no-underline font-[650] text-[14px]`}
|
||||||
data-tut="headerArea"
|
data-tut="headerArea"
|
||||||
>
|
>
|
||||||
{completeBtnTitle ? completeBtnTitle : "Send"}
|
{completeBtnTitle ? completeBtnTitle : t("send")}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
data-tut="reactourThird"
|
data-tut="reactourThird"
|
||||||
onClick={() => {
|
onClick={() => embedWidgetsData()}
|
||||||
if (!pdfUrl) {
|
|
||||||
embedWidgetsData();
|
|
||||||
} else if (isPdfRequestFiles) {
|
|
||||||
embedWidgetsData();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
|
className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
|
||||||
>
|
>
|
||||||
Finish
|
{t("finish")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<DropdownMenu.Root>
|
<DropdownMenu.Root>
|
||||||
@@ -205,30 +210,86 @@ function Header({
|
|||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content
|
<DropdownMenu.Content
|
||||||
className="bg-white shadow-md rounded-full px-3 py-2"
|
className="bg-white shadow-md rounded-md px-3 py-2"
|
||||||
sideOffset={5}
|
sideOffset={5}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleDownloadPdf(
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
pdfDetails,
|
|
||||||
pdfUrl,
|
|
||||||
setIsDownloading
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i
|
<div className="flex flex-row">
|
||||||
className="fa-light fa-arrow-down mr-[3px]"
|
<i
|
||||||
aria-hidden="true"
|
className="fa-light fa-arrow-down mr-[3px]"
|
||||||
></i>
|
aria-hidden="true"
|
||||||
<span className="font-[500]">Download</span>
|
></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("download")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
{!isDisableRotate && (
|
||||||
|
<>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => handleRotationFun(90)}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("rotate-right")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => handleRotationFun(-90)}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("rotate-left")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => clickOnZoomIn()}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">{t("zoom-in")}</span>
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => clickOnZoomOut()}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("zoom-out")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isPublicTemplate && (
|
||||||
|
<div
|
||||||
|
data-tut="reactourThird"
|
||||||
|
onClick={() => embedWidgetsData()}
|
||||||
|
className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
|
||||||
|
>
|
||||||
|
{t("sign-now")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -249,13 +310,14 @@ function Header({
|
|||||||
<div>
|
<div>
|
||||||
{filterPrefill.length === 0 ? (
|
{filterPrefill.length === 0 ? (
|
||||||
<span className="text-[13px] text-[#f5405e]">
|
<span className="text-[13px] text-[#f5405e]">
|
||||||
Add {signersdata.length - filterPrefill.length}{" "}
|
{t("add")} {signersdata.length - filterPrefill.length}{" "}
|
||||||
recipients signature
|
{t("recipients")} {t("widgets-name.signature")}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-[13px] text-[#f5405e]">
|
<span className="text-[13px] text-[#f5405e]">
|
||||||
Add {signersdata.length - filterPrefill.length} more
|
{t("add")} {signersdata.length - filterPrefill.length}{" "}
|
||||||
recipients signature
|
{t("more")}
|
||||||
|
{t("recipients")} {t("widgets-name.signature")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -275,7 +337,7 @@ function Header({
|
|||||||
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]"
|
||||||
>
|
>
|
||||||
Back
|
{t("back")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
disabled={isMailSend && true}
|
disabled={isMailSend && true}
|
||||||
@@ -286,8 +348,8 @@ function Header({
|
|||||||
{completeBtnTitle
|
{completeBtnTitle
|
||||||
? completeBtnTitle
|
? completeBtnTitle
|
||||||
: isMailSend
|
: isMailSend
|
||||||
? "Sent"
|
? t("sent")
|
||||||
: "Send"}
|
: t("send")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -295,7 +357,9 @@ function Header({
|
|||||||
alreadySign ? (
|
alreadySign ? (
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<button
|
<button
|
||||||
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
|
onClick={(e) =>
|
||||||
|
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
|
||||||
|
}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
||||||
>
|
>
|
||||||
@@ -303,7 +367,7 @@ function Header({
|
|||||||
className="fa-light fa-print py-[3px]"
|
className="fa-light fa-print py-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span className="hidden lg:block">Print</span>
|
<span className="hidden lg:block">{t("print")}</span>
|
||||||
</button>
|
</button>
|
||||||
{isCompleted && (
|
{isCompleted && (
|
||||||
<button
|
<button
|
||||||
@@ -317,57 +381,76 @@ function Header({
|
|||||||
className="fa-light fa-award py-[3px]"
|
className="fa-light fa-award py-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span className="hidden lg:block">Certificate</span>
|
<span className="hidden lg:block">{t("certificate")}</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
if (isCompleted) {
|
||||||
}
|
setIsDownloadModal(true);
|
||||||
|
} else {
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa-light fa-download py-[3px]"
|
className="fa-light fa-download py-[3px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span className="hidden lg:block">Download</span>
|
<span className="hidden lg:block">{t("download")}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex" data-tut="reactourFifth">
|
<div className="flex" data-tut="reactourFifth">
|
||||||
<button
|
{!templateId && (
|
||||||
onClick={() => window.history.go(-2)}
|
<button
|
||||||
type="button"
|
onClick={() => window.history.go(-2)}
|
||||||
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
|
type="button"
|
||||||
>
|
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
|
||||||
Back
|
>
|
||||||
</button>
|
{t("back")}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{currentSigner && (
|
{currentSigner && (
|
||||||
<>
|
<>
|
||||||
|
{templateId && (
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
|
||||||
|
>
|
||||||
|
<span className="hidden lg:block">{t("download")}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
|
||||||
onClick={() => handleDeclinePdfAlert()}
|
onClick={() => handleDeclinePdfAlert()}
|
||||||
>
|
>
|
||||||
Decline
|
{t("decline")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
||||||
onClick={() => embedWidgetsData()}
|
onClick={() => embedWidgetsData()}
|
||||||
>
|
>
|
||||||
Finish
|
{t("finish")}
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
|
||||||
onClick={() =>
|
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
|
|
||||||
<span className="hidden lg:block">Download</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
{!templateId && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
||||||
|
onClick={() =>
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
|
||||||
|
<span className="hidden lg:block">{t("download")}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -383,26 +466,30 @@ function Header({
|
|||||||
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-award" aria-hidden="true"></i>
|
<i className="fa-light fa-award" aria-hidden="true"></i>
|
||||||
<span className="hidden lg:block ml-1">Certificate</span>
|
<span className="hidden lg:block ml-1">
|
||||||
|
{t("certificate")}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
|
onClick={(e) =>
|
||||||
|
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
|
||||||
|
}
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-print" aria-hidden="true"></i>
|
<i className="fa-light fa-print" aria-hidden="true"></i>
|
||||||
<span className="hidden lg:block ml-1">Print</span>
|
<span className="hidden lg:block ml-1">{t("print")}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
setIsDownloadModal(true);
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-download" aria-hidden="true"></i>
|
<i className="fa-light fa-download" aria-hidden="true"></i>
|
||||||
<span className="hidden lg:block ml-1">Download</span>
|
<span className="hidden lg:block ml-1">{t("download")}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -410,23 +497,19 @@ function Header({
|
|||||||
onClick={() => setIsEmail(true)}
|
onClick={() => setIsEmail(true)}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-envelope" aria-hidden="true"></i>
|
<i className="fa-light fa-envelope" aria-hidden="true"></i>
|
||||||
<span className="hidden lg:block ml-1">Mail</span>
|
<span className="hidden lg:block ml-1">{t("mail")}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : isPublicTemplate ? (
|
) : isPublicTemplate ? (
|
||||||
<>
|
<div className="flex">
|
||||||
<div className="flex">
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
className="op-btn op-btn-primary op-btn-sm shadow"
|
||||||
className="op-btn op-btn-primary op-btn-sm shadow"
|
onClick={() => embedWidgetsData()}
|
||||||
onClick={() => {
|
>
|
||||||
embedWidgetsData();
|
{t("sign-now")}
|
||||||
}}
|
</button>
|
||||||
>
|
</div>
|
||||||
Sign Now
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<button
|
<button
|
||||||
@@ -434,18 +517,14 @@ function Header({
|
|||||||
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]"
|
||||||
>
|
>
|
||||||
Back
|
{t("back")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm mr-[3px]"
|
className="op-btn op-btn-primary op-btn-sm mr-[3px]"
|
||||||
onClick={() => {
|
onClick={() => embedWidgetsData()}
|
||||||
if (!pdfUrl) {
|
|
||||||
embedWidgetsData();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Finish
|
{t("finish")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -460,18 +539,14 @@ function Header({
|
|||||||
isOpen={isDownloading === "certificate"}
|
isOpen={isDownloading === "certificate"}
|
||||||
title={
|
title={
|
||||||
isDownloading === "certificate"
|
isDownloading === "certificate"
|
||||||
? "Generating certificate"
|
? t("generating-certificate")
|
||||||
: "PDF Download"
|
: t("pdf-download")
|
||||||
}
|
}
|
||||||
handleClose={() => setIsDownloading("")}
|
handleClose={() => setIsDownloading("")}
|
||||||
>
|
>
|
||||||
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
|
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
|
||||||
{isDownloading === "certificate"}{" "}
|
{isDownloading === "certificate"}{" "}
|
||||||
<p>
|
<p>{t("generate-certificate-alert")}</p>
|
||||||
Your completion certificate is being generated. Please wait
|
|
||||||
momentarily. If the download doesn't start shortly, click the
|
|
||||||
button again.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,48 +1,43 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function PdfZoom(props) {
|
function PdfZoom(props) {
|
||||||
const onClickZoomIn = () => {
|
const { t } = useTranslation();
|
||||||
props.setScale(props.scale + 0.1 * props.scale);
|
|
||||||
props.setZoomPercent(props.zoomPercent + 10);
|
|
||||||
};
|
|
||||||
const onClickZoomOut = () => {
|
|
||||||
if (props.zoomPercent > 0) {
|
|
||||||
if (props.zoomPercent === 10) {
|
|
||||||
props.setScale(1);
|
|
||||||
} else {
|
|
||||||
props.setScale(props.scale - 0.1 * props.scale);
|
|
||||||
}
|
|
||||||
props.setZoomPercent(props.zoomPercent - 10);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleReset = () => {
|
|
||||||
props.setScale(1);
|
|
||||||
props.setZoomPercent(0);
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
// md:mt-[41px] xl:mt-[63px]mt=[]
|
<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-[50px] 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"
|
||||||
onClick={onClickZoomIn}
|
onClick={() => props.clickOnZoomIn()}
|
||||||
title="Zoom in"
|
title={t("zoom-in")}
|
||||||
>
|
>
|
||||||
<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>
|
||||||
<span
|
{!props?.isDisableRotate && (
|
||||||
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
<>
|
||||||
onClick={handleReset}
|
<span
|
||||||
title="Reset"
|
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
||||||
>
|
onClick={() => props.handleRotationFun(90)}
|
||||||
<i className="fa-light fa-magnifying-glass-arrows-rotate text-gray-500 2xl:text-[30px]"></i>
|
title={t("rotate-right")}
|
||||||
</span>
|
>
|
||||||
|
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px]"></i>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
|
||||||
|
title={t("rotate-left")}
|
||||||
|
onClick={() => props.handleRotationFun(-90)}
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px]"></i>
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px]"
|
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px]"
|
||||||
onClick={onClickZoomOut}
|
onClick={() => props.clickOnZoomOut()}
|
||||||
style={{
|
style={{
|
||||||
cursor: props.zoomPercent > 0 ? "pointer" : "default"
|
cursor: props.zoomPercent > 0 ? "pointer" : "default"
|
||||||
}}
|
}}
|
||||||
title="Zoom out"
|
title={t("zoom-out")}
|
||||||
>
|
>
|
||||||
<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>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import PlaceholderBorder from "./PlaceholderBorder";
|
|||||||
import { Rnd } from "react-rnd";
|
import { Rnd } from "react-rnd";
|
||||||
import {
|
import {
|
||||||
defaultWidthHeight,
|
defaultWidthHeight,
|
||||||
|
fontColorArr,
|
||||||
|
fontsizeArr,
|
||||||
|
getContainerScale,
|
||||||
handleCopyNextToWidget,
|
handleCopyNextToWidget,
|
||||||
isTabAndMobile,
|
isTabAndMobile,
|
||||||
onChangeInput,
|
onChangeInput,
|
||||||
@@ -14,6 +17,8 @@ import {
|
|||||||
import PlaceholderType from "./PlaceholderType";
|
import PlaceholderType from "./PlaceholderType";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import "../../styles/opensigndrive.css";
|
import "../../styles/opensigndrive.css";
|
||||||
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const selectFormat = (data) => {
|
const selectFormat = (data) => {
|
||||||
switch (data) {
|
switch (data) {
|
||||||
@@ -88,9 +93,10 @@ const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
|
|||||||
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
|
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
|
||||||
|
|
||||||
function Placeholder(props) {
|
function Placeholder(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [placeholderBorder, setPlaceholderBorder] = useState({ w: 0, h: 0 });
|
const [placeholderBorder, setPlaceholderBorder] = useState({ w: 0, h: 0 });
|
||||||
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
|
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
|
||||||
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
|
const [isDateModal, setIsDateModal] = useState(false);
|
||||||
const [containerScale, setContainerScale] = useState();
|
const [containerScale, setContainerScale] = useState();
|
||||||
const [selectDate, setSelectDate] = useState({
|
const [selectDate, setSelectDate] = useState({
|
||||||
date:
|
date:
|
||||||
@@ -110,6 +116,7 @@ function Placeholder(props) {
|
|||||||
: ""
|
: ""
|
||||||
});
|
});
|
||||||
const [dateFormat, setDateFormat] = useState([]);
|
const [dateFormat, setDateFormat] = useState([]);
|
||||||
|
const [clickonWidget, setClickonWidget] = useState({});
|
||||||
const [startDate, setStartDate] = useState(
|
const [startDate, setStartDate] = useState(
|
||||||
props.pos.type === "date" &&
|
props.pos.type === "date" &&
|
||||||
getDefaultdate(
|
getDefaultdate(
|
||||||
@@ -199,20 +206,6 @@ function Placeholder(props) {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [selectDate]);
|
}, [selectDate]);
|
||||||
|
|
||||||
//it detect outside click of date dropdown menu
|
|
||||||
useEffect(() => {
|
|
||||||
const closeMenuOnOutsideClick = (e) => {
|
|
||||||
if (isShowDateFormat && !e.target.closest("#menu-container")) {
|
|
||||||
setIsShowDateFormat(!isShowDateFormat);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.addEventListener("click", closeMenuOnOutsideClick);
|
|
||||||
return () => {
|
|
||||||
// Cleanup the event listener when the component unmounts
|
|
||||||
document.removeEventListener("click", closeMenuOnOutsideClick);
|
|
||||||
};
|
|
||||||
}, [isShowDateFormat]);
|
|
||||||
|
|
||||||
//`handleWidgetIdandPopup` is used to set current widget id and open relative popup
|
//`handleWidgetIdandPopup` is used to set current widget id and open relative popup
|
||||||
const handleWidgetIdandPopup = () => {
|
const handleWidgetIdandPopup = () => {
|
||||||
if (props.setSelectWidgetId) {
|
if (props.setSelectWidgetId) {
|
||||||
@@ -337,12 +330,10 @@ 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.setSignerObjId(props?.data?.signerObjId);
|
|
||||||
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
|
||||||
@@ -350,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);
|
||||||
@@ -368,7 +355,6 @@ function Placeholder(props) {
|
|||||||
//and on save or cancel button of copy all page popup i have set this temp signer Id in unique id
|
//and on save or cancel button of copy all page popup i have set this temp signer Id in unique id
|
||||||
|
|
||||||
if (props.data && props?.pos?.type !== textWidget) {
|
if (props.data && props?.pos?.type !== textWidget) {
|
||||||
props.setSignerObjId(props?.data?.signerObjId);
|
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
const checkIndex = props.xyPostion.findIndex(
|
||||||
(data) => data.Id === props.data.Id
|
(data) => data.Id === props.data.Id
|
||||||
@@ -377,7 +363,6 @@ function Placeholder(props) {
|
|||||||
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.setSignerObjId(props?.data?.signerObjId);
|
|
||||||
props.setUniqueId(props?.data?.Id);
|
props.setUniqueId(props?.data?.Id);
|
||||||
const checkIndex = props.xyPostion.findIndex(
|
const checkIndex = props.xyPostion.findIndex(
|
||||||
(data) => data.Id === props.data.Id
|
(data) => data.Id === props.data.Id
|
||||||
@@ -429,7 +414,11 @@ function Placeholder(props) {
|
|||||||
props.setXyPostion,
|
props.setXyPostion,
|
||||||
props.data && props.data.Id,
|
props.data && props.data.Id,
|
||||||
false,
|
false,
|
||||||
data?.format
|
data?.format,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
props.fontSize || props.pos?.options?.fontSize || "12",
|
||||||
|
props.fontColor || props.pos?.options?.fontColor || "black"
|
||||||
);
|
);
|
||||||
setSelectDate({ date: date, format: data?.format });
|
setSelectDate({ date: date, format: data?.format });
|
||||||
};
|
};
|
||||||
@@ -521,17 +510,12 @@ function Placeholder(props) {
|
|||||||
)}
|
)}
|
||||||
{/* setting icon only for date widgets */}
|
{/* setting icon only for date widgets */}
|
||||||
{props.pos.type === "date" && selectDate && (
|
{props.pos.type === "date" && selectDate && (
|
||||||
<div
|
<i
|
||||||
id="menu-container"
|
|
||||||
style={{
|
|
||||||
zIndex: "99",
|
|
||||||
top: "-19px",
|
|
||||||
right: props.isPlaceholder ? "60px" : "44px"
|
|
||||||
}}
|
|
||||||
className={`${isShowDateFormat ? "show" : ""} dropdown icon`}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
setIsShowDateFormat(!isShowDateFormat);
|
props.setCurrWidgetsDetails(props.pos);
|
||||||
|
setIsDateModal(!isDateModal);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
setClickonWidget(props.pos);
|
||||||
if (props.data) {
|
if (props.data) {
|
||||||
props.setSignKey(props.pos.key);
|
props.setSignKey(props.pos.key);
|
||||||
props.setUniqueId(props.data.Id);
|
props.setUniqueId(props.data.Id);
|
||||||
@@ -542,8 +526,9 @@ function Placeholder(props) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onTouchEnd={(e) => {
|
onTouchEnd={(e) => {
|
||||||
|
props.setCurrWidgetsDetails(props.pos);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsShowDateFormat(!isShowDateFormat);
|
setIsDateModal(!isDateModal);
|
||||||
if (props.data) {
|
if (props.data) {
|
||||||
props.setSignKey(props.pos.key);
|
props.setSignKey(props.pos.key);
|
||||||
props.setUniqueId(props.data.Id);
|
props.setUniqueId(props.data.Id);
|
||||||
@@ -553,44 +538,15 @@ function Placeholder(props) {
|
|||||||
props.setIsSelectId(checkIndex || 0);
|
props.setIsSelectId(checkIndex || 0);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
style={{
|
||||||
<i
|
zIndex: "99",
|
||||||
className="fa-light fa-gear icon"
|
top: "-18px",
|
||||||
style={{
|
right: props.isPlaceholder ? "50px" : "30px",
|
||||||
color: "#188ae2",
|
color: "#188ae2",
|
||||||
fontSize: "14px"
|
fontSize: "14px"
|
||||||
}}
|
}}
|
||||||
></i>
|
className="fa-light fa-gear icon"
|
||||||
<div
|
></i>
|
||||||
className={
|
|
||||||
isShowDateFormat ? "dropdown-menu show" : "dropdown-menu"
|
|
||||||
}
|
|
||||||
aria-labelledby="dropdownMenuButton"
|
|
||||||
aria-expanded={isShowDateFormat ? "true" : "false"}
|
|
||||||
>
|
|
||||||
{dateFormat.map((data, ind) => {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
key={ind}
|
|
||||||
onTouchEnd={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
setIsShowDateFormat(!isShowDateFormat);
|
|
||||||
setSelectDate(data);
|
|
||||||
handleSaveDate(data);
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setIsShowDateFormat(!isShowDateFormat);
|
|
||||||
setSelectDate(data);
|
|
||||||
handleSaveDate(data);
|
|
||||||
}}
|
|
||||||
className="dropdown-item text-[13px]"
|
|
||||||
>
|
|
||||||
{data?.date ? data?.date : "nodata"}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{/* copy icon for all widgets */}
|
{/* copy icon for all widgets */}
|
||||||
<i
|
<i
|
||||||
@@ -634,10 +590,11 @@ function Placeholder(props) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
const xPos = (pos, signYourself) => {
|
const xPos = (pos, signYourself) => {
|
||||||
const getPdfPageWidth = props.pdfOriginalWH.find(
|
const containerScale = getContainerScale(
|
||||||
(data) => data.pageNumber === props.pageNumber
|
props.pdfOriginalWH,
|
||||||
|
props.pageNumber,
|
||||||
|
props.containerWH
|
||||||
);
|
);
|
||||||
const containerScale = props.containerWH.width / getPdfPageWidth?.width;
|
|
||||||
const resizePos = pos.xPosition;
|
const resizePos = pos.xPosition;
|
||||||
if (signYourself) {
|
if (signYourself) {
|
||||||
return resizePos * containerScale * props.scale;
|
return resizePos * containerScale * props.scale;
|
||||||
@@ -659,10 +616,11 @@ function Placeholder(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const yPos = (pos, signYourself) => {
|
const yPos = (pos, signYourself) => {
|
||||||
const getPdfPageWidth = props.pdfOriginalWH.find(
|
const containerScale = getContainerScale(
|
||||||
(data) => data.pageNumber === props.pageNumber
|
props.pdfOriginalWH,
|
||||||
|
props.pageNumber,
|
||||||
|
props.containerWH
|
||||||
);
|
);
|
||||||
const containerScale = props.containerWH.width / getPdfPageWidth.width;
|
|
||||||
const resizePos = pos.yPosition;
|
const resizePos = pos.yPosition;
|
||||||
|
|
||||||
if (signYourself) {
|
if (signYourself) {
|
||||||
@@ -688,6 +646,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.5 + "px";
|
||||||
|
} else {
|
||||||
|
return fontSize + "px";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getCursor = () => {
|
const getCursor = () => {
|
||||||
if (props.data && props.isNeedSign) {
|
if (props.data && props.isNeedSign) {
|
||||||
@@ -702,228 +675,338 @@ function Placeholder(props) {
|
|||||||
return "all-scroll";
|
return "all-scroll";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Rnd
|
<>
|
||||||
id={props.pos.key}
|
<Rnd
|
||||||
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
id={props.pos.key}
|
||||||
key={props.pos.key}
|
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
||||||
lockAspectRatio={
|
key={props.pos.key}
|
||||||
![
|
lockAspectRatio={
|
||||||
textWidget,
|
![
|
||||||
"email",
|
textWidget,
|
||||||
"name",
|
"email",
|
||||||
"company",
|
"name",
|
||||||
"job title",
|
"company",
|
||||||
textInputWidget
|
"job title",
|
||||||
].includes(props.pos.type) &&
|
textInputWidget
|
||||||
(props.pos.Width
|
].includes(props.pos.type) &&
|
||||||
? props.pos.Width / props.pos.Height
|
(props.pos.Width
|
||||||
: defaultWidthHeight(props.pos.type).width /
|
? props.pos.Width / props.pos.Height
|
||||||
defaultWidthHeight(props.pos.type).height)
|
: defaultWidthHeight(props.pos.type).width /
|
||||||
}
|
defaultWidthHeight(props.pos.type).height)
|
||||||
enableResizing={{
|
}
|
||||||
top: false,
|
enableResizing={{
|
||||||
right: false,
|
top: false,
|
||||||
bottom: false,
|
right: false,
|
||||||
left: false,
|
bottom: false,
|
||||||
topRight: false,
|
left: false,
|
||||||
bottomRight:
|
topRight: false,
|
||||||
props.data && props.isNeedSign
|
bottomRight:
|
||||||
? props.data?.signerObjId === props.signerObjId &&
|
props.data && props.isNeedSign
|
||||||
props.pos.type !== "checkbox" &&
|
? props.data?.signerObjId === props.signerObjId &&
|
||||||
props.pos.type !== radioButtonWidget
|
props.pos.type !== "checkbox" &&
|
||||||
? true
|
props.pos.type !== radioButtonWidget
|
||||||
: false
|
? true
|
||||||
: props.pos.type !== radioButtonWidget &&
|
: false
|
||||||
props.pos.type !== "checkbox" &&
|
: props.pos.type !== radioButtonWidget &&
|
||||||
props.pos.key === props.selectWidgetId &&
|
props.pos.type !== "checkbox" &&
|
||||||
true,
|
props.pos.key === props.selectWidgetId &&
|
||||||
bottomLeft: false,
|
true,
|
||||||
topLeft: false
|
bottomLeft: false,
|
||||||
}}
|
topLeft: false
|
||||||
bounds="parent"
|
}}
|
||||||
className="signYourselfBlock"
|
bounds="parent"
|
||||||
style={{
|
className="signYourselfBlock"
|
||||||
border: "1px solid #007bff",
|
style={{
|
||||||
borderRadius: "2px",
|
border: "1px solid #007bff",
|
||||||
textAlign:
|
borderRadius: "2px",
|
||||||
props.pos.type !== "name" &&
|
textAlign:
|
||||||
props.pos.type !== "company" &&
|
props.pos.type !== "name" &&
|
||||||
props.pos.type !== "job title" &&
|
props.pos.type !== "company" &&
|
||||||
"center",
|
props.pos.type !== "job title" &&
|
||||||
cursor: getCursor(),
|
"center",
|
||||||
zIndex:
|
cursor: getCursor(),
|
||||||
props.pos.type === "date"
|
zIndex:
|
||||||
? props.pos.key === props.selectWidgetId
|
props.pos.type === "date"
|
||||||
? 99 + 1
|
? props.pos.key === props.selectWidgetId
|
||||||
: 99
|
? 99 + 1
|
||||||
: props?.pos?.zIndex
|
: 99
|
||||||
? props.pos.zIndex
|
: props?.pos?.zIndex
|
||||||
: "5",
|
? props.pos.zIndex
|
||||||
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
|
: "5",
|
||||||
}}
|
background: props.data
|
||||||
onDrag={() => {
|
? props.data?.blockColor + "b0"
|
||||||
setDraggingEnabled(true);
|
: "rgba(203, 233, 237, 0.69)"
|
||||||
props.handleTabDrag && props.handleTabDrag(props.pos.key);
|
}}
|
||||||
}}
|
onDrag={() => {
|
||||||
size={{
|
setDraggingEnabled(true);
|
||||||
width:
|
props.handleTabDrag && props.handleTabDrag(props.pos.key);
|
||||||
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
|
}}
|
||||||
? "auto"
|
size={{
|
||||||
: props.posWidth(props.pos, props.isSignYourself),
|
width:
|
||||||
height:
|
props.pos.type === radioButtonWidget ||
|
||||||
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
|
props.pos.type === "checkbox"
|
||||||
? "auto"
|
? "auto"
|
||||||
: props.posHeight(props.pos, props.isSignYourself)
|
: props.posWidth(props.pos, props.isSignYourself),
|
||||||
}}
|
height:
|
||||||
onResizeStart={() => {
|
props.pos.type === radioButtonWidget ||
|
||||||
setDraggingEnabled(true);
|
props.pos.type === "checkbox"
|
||||||
props.setIsResize && props.setIsResize(true);
|
? "auto"
|
||||||
}}
|
: props.posHeight(props.pos, props.isSignYourself)
|
||||||
onResizeStop={(e, direction, ref) => {
|
}}
|
||||||
props.setIsResize && props.setIsResize(false);
|
minHeight={calculateFont(props.pos.options?.fontSize, true)}
|
||||||
props.handleSignYourselfImageResize &&
|
maxHeight="auto"
|
||||||
props.handleSignYourselfImageResize(
|
onResizeStart={() => {
|
||||||
ref,
|
setDraggingEnabled(true);
|
||||||
props.pos.key,
|
props.setIsResize && props.setIsResize(true);
|
||||||
props.xyPostion,
|
}}
|
||||||
props.setXyPostion,
|
onResizeStop={(e, direction, ref) => {
|
||||||
props.index,
|
setTimeout(() => {
|
||||||
containerScale,
|
props.setIsResize && props.setIsResize(false);
|
||||||
props.scale,
|
}, 50);
|
||||||
props.data && props.data.Id,
|
props.handleSignYourselfImageResize &&
|
||||||
props.isResize
|
props.handleSignYourselfImageResize(
|
||||||
);
|
ref,
|
||||||
}}
|
props.pos.key,
|
||||||
disableDragging={
|
props.xyPostion,
|
||||||
props.isNeedSign
|
props.setXyPostion,
|
||||||
? true
|
props.index,
|
||||||
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
|
containerScale,
|
||||||
? false
|
props.scale,
|
||||||
: !isDraggingEnabled
|
props.data && props.data.Id,
|
||||||
}
|
props.isResize
|
||||||
onDragStop={(event, dragElement) =>
|
);
|
||||||
props.handleStop &&
|
}}
|
||||||
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
|
disableDragging={
|
||||||
}
|
props.isNeedSign
|
||||||
position={{
|
? true
|
||||||
x: xPos(props.pos, props.isSignYourself),
|
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
|
||||||
y: yPos(props.pos, props.isSignYourself)
|
? false
|
||||||
}}
|
: !isDraggingEnabled
|
||||||
onResize={(e, direction, ref) => {
|
}
|
||||||
setPlaceholderBorder({
|
onDragStop={(event, dragElement) =>
|
||||||
w: ref.offsetWidth / (props.scale * containerScale),
|
props.handleStop &&
|
||||||
h: ref.offsetHeight / (props.scale * containerScale)
|
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
|
||||||
});
|
}
|
||||||
}}
|
position={{
|
||||||
onClick={() => handleOnClickPlaceholder()}
|
x: xPos(props.pos, props.isSignYourself),
|
||||||
>
|
y: yPos(props.pos, props.isSignYourself)
|
||||||
{props.isShowBorder &&
|
}}
|
||||||
props.pos.type !== radioButtonWidget &&
|
onResize={(e, direction, ref) => {
|
||||||
props.pos.type !== "checkbox" &&
|
setPlaceholderBorder({
|
||||||
props.pos.key === props.selectWidgetId ? (
|
w: ref.offsetWidth / (props.scale * containerScale),
|
||||||
<BorderResize right={-12} top={-11} />
|
h: ref.offsetHeight / (props.scale * containerScale)
|
||||||
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
});
|
||||||
props.data?.signerObjId === props.signerObjId &&
|
}}
|
||||||
props.pos.type !== radioButtonWidget &&
|
onClick={() => !props.isResize && handleOnClickPlaceholder()}
|
||||||
props.pos.type !== "checkbox" ? (
|
>
|
||||||
<BorderResize />
|
{props.isShowBorder &&
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
props.pos.type !== radioButtonWidget &&
|
props.pos.type !== radioButtonWidget &&
|
||||||
props.pos.type !== "checkbox" &&
|
props.pos.type !== "checkbox" &&
|
||||||
props.pos.key === props.selectWidgetId && <BorderResize />
|
props.pos.key === props.selectWidgetId ? (
|
||||||
)}
|
<BorderResize
|
||||||
|
right={-12}
|
||||||
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
|
top={-11}
|
||||||
<PlaceholderBorder
|
|
||||||
setDraggingEnabled={setDraggingEnabled}
|
|
||||||
pos={props.pos}
|
|
||||||
isPlaceholder={props.isPlaceholder}
|
|
||||||
getCheckboxRenderWidth={getCheckboxRenderWidth}
|
|
||||||
scale={props.scale}
|
|
||||||
containerScale={containerScale}
|
|
||||||
placeholderBorder={placeholderBorder}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isTabAndMobile ? (
|
|
||||||
<div
|
|
||||||
className="flex items-stretch"
|
|
||||||
style={{
|
|
||||||
left: xPos(props.pos, props.isSignYourself),
|
|
||||||
top: yPos(props.pos, props.isSignYourself),
|
|
||||||
width:
|
|
||||||
props.pos.type === radioButtonWidget ||
|
|
||||||
props.pos.type === "checkbox"
|
|
||||||
? "auto"
|
|
||||||
: props.posWidth(props.pos, props.isSignYourself),
|
|
||||||
height:
|
|
||||||
props.pos.type === radioButtonWidget ||
|
|
||||||
props.pos.type === "checkbox"
|
|
||||||
? "auto"
|
|
||||||
: props.posHeight(props.pos, props.isSignYourself),
|
|
||||||
zIndex: "10"
|
|
||||||
}}
|
|
||||||
onTouchEnd={() => handleOnClickPlaceholder()}
|
|
||||||
onClick={() => handleOnClickPlaceholder()}
|
|
||||||
>
|
|
||||||
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
|
||||||
|
|
||||||
<PlaceholderType
|
|
||||||
pos={props.pos}
|
pos={props.pos}
|
||||||
xyPostion={props.xyPostion}
|
posHeight={props.posHeight}
|
||||||
index={props.index}
|
|
||||||
setXyPostion={props.setXyPostion}
|
|
||||||
data={props.data}
|
|
||||||
setSignKey={props.setSignKey}
|
|
||||||
isShowDropdown={props?.isShowDropdown}
|
|
||||||
isPlaceholder={props.isPlaceholder}
|
|
||||||
isSignYourself={props.isSignYourself}
|
isSignYourself={props.isSignYourself}
|
||||||
signerObjId={props.signerObjId}
|
|
||||||
handleUserName={props.handleUserName}
|
|
||||||
setDraggingEnabled={setDraggingEnabled}
|
|
||||||
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
|
||||||
isNeedSign={props.isNeedSign}
|
|
||||||
setSelectDate={setSelectDate}
|
|
||||||
selectDate={selectDate}
|
|
||||||
setValidateAlert={props.setValidateAlert}
|
|
||||||
setStartDate={setStartDate}
|
|
||||||
startDate={startDate}
|
|
||||||
handleSaveDate={handleSaveDate}
|
|
||||||
xPos={props.xPos}
|
|
||||||
/>
|
/>
|
||||||
|
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
|
||||||
|
props.data?.signerObjId === props.signerObjId &&
|
||||||
|
props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" ? (
|
||||||
|
<BorderResize
|
||||||
|
posHeight={props.posHeight}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
pos={props.pos}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
props.pos.type !== radioButtonWidget &&
|
||||||
|
props.pos.type !== "checkbox" &&
|
||||||
|
props.pos.key === props.selectWidgetId && <BorderResize />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
|
||||||
|
<PlaceholderBorder
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pos={props.pos}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
getCheckboxRenderWidth={getCheckboxRenderWidth}
|
||||||
|
scale={props.scale}
|
||||||
|
containerScale={containerScale}
|
||||||
|
placeholderBorder={placeholderBorder}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isTabAndMobile ? (
|
||||||
|
<div
|
||||||
|
className="flex items-stretch"
|
||||||
|
style={{
|
||||||
|
left: xPos(props.pos, props.isSignYourself),
|
||||||
|
top: yPos(props.pos, props.isSignYourself),
|
||||||
|
width:
|
||||||
|
props.pos.type === radioButtonWidget ||
|
||||||
|
props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posWidth(props.pos, props.isSignYourself),
|
||||||
|
height:
|
||||||
|
props.pos.type === radioButtonWidget ||
|
||||||
|
props.pos.type === "checkbox"
|
||||||
|
? "auto"
|
||||||
|
: props.posHeight(props.pos, props.isSignYourself),
|
||||||
|
zIndex: "10"
|
||||||
|
}}
|
||||||
|
onTouchEnd={() => handleOnClickPlaceholder()}
|
||||||
|
onClick={() => handleOnClickPlaceholder()}
|
||||||
|
>
|
||||||
|
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
||||||
|
|
||||||
|
<PlaceholderType
|
||||||
|
pos={props.pos}
|
||||||
|
xyPostion={props.xyPostion}
|
||||||
|
index={props.index}
|
||||||
|
setXyPostion={props.setXyPostion}
|
||||||
|
data={props.data}
|
||||||
|
setSignKey={props.setSignKey}
|
||||||
|
isShowDropdown={props?.isShowDropdown}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
signerObjId={props.signerObjId}
|
||||||
|
handleUserName={props.handleUserName}
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
||||||
|
isNeedSign={props.isNeedSign}
|
||||||
|
setSelectDate={setSelectDate}
|
||||||
|
selectDate={selectDate}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
setStartDate={setStartDate}
|
||||||
|
startDate={startDate}
|
||||||
|
handleSaveDate={handleSaveDate}
|
||||||
|
xPos={props.xPos}
|
||||||
|
calculateFont={calculateFont}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
||||||
|
<PlaceholderType
|
||||||
|
pos={props.pos}
|
||||||
|
xyPostion={props.xyPostion}
|
||||||
|
index={props.index}
|
||||||
|
setXyPostion={props.setXyPostion}
|
||||||
|
data={props.data}
|
||||||
|
setSignKey={props.setSignKey}
|
||||||
|
isShowDropdown={props?.isShowDropdown}
|
||||||
|
isPlaceholder={props.isPlaceholder}
|
||||||
|
isSignYourself={props.isSignYourself}
|
||||||
|
signerObjId={props.signerObjId}
|
||||||
|
handleUserName={props.handleUserName}
|
||||||
|
setDraggingEnabled={setDraggingEnabled}
|
||||||
|
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
||||||
|
isNeedSign={props.isNeedSign}
|
||||||
|
setSelectDate={setSelectDate}
|
||||||
|
selectDate={selectDate}
|
||||||
|
setValidateAlert={props.setValidateAlert}
|
||||||
|
setStartDate={setStartDate}
|
||||||
|
startDate={startDate}
|
||||||
|
handleSaveDate={handleSaveDate}
|
||||||
|
xPos={props.xPos}
|
||||||
|
calculateFont={calculateFont}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Rnd>
|
||||||
|
<ModalUi isOpen={isDateModal} title={t("widget-info")} showClose={false}>
|
||||||
|
<div className="h-[100%] p-[20px]">
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
<span>{t("format")} : </span>
|
||||||
|
<div className="flex">
|
||||||
|
<select
|
||||||
|
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
|
defaultValue={""}
|
||||||
|
onChange={(e) => {
|
||||||
|
const selectedIndex = e.target.value;
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectDate(dateFormat[selectedIndex]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="" disabled>
|
||||||
|
{t("select-date-format")}
|
||||||
|
</option>
|
||||||
|
{dateFormat.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<option className="text-[13px]" value={ind} key={ind}>
|
||||||
|
{data?.date ? data?.date : "nodata"}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<span className="text-xs text-gray-400 ml-1">
|
||||||
|
{selectDate.format}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center mt-4 md:mt-2">
|
||||||
|
<span>{t("font-size")} :</span>
|
||||||
|
<select
|
||||||
|
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"}
|
||||||
|
onChange={(e) => props.setFontSize(e.target.value)}
|
||||||
|
>
|
||||||
|
{fontsizeArr.map((size, ind) => {
|
||||||
|
return (
|
||||||
|
<option className="text-[13px]" value={size} key={ind}>
|
||||||
|
{size}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<div className="flex flex-row gap-1 items-center ml-2 md:ml-4 ">
|
||||||
|
<span>{t("color")}: </span>
|
||||||
|
<select
|
||||||
|
value={
|
||||||
|
props.fontColor || clickonWidget.options?.fontColor || "black"
|
||||||
|
}
|
||||||
|
onChange={(e) => props.setFontColor(e.target.value)}
|
||||||
|
className="ml-[4px] md:ml[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
|
>
|
||||||
|
{fontColorArr.map((color, ind) => {
|
||||||
|
return (
|
||||||
|
<option value={color} key={ind}>
|
||||||
|
{t(`color-type.${color}`)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
props.fontColor || props.pos.options?.fontColor || "black"
|
||||||
|
}}
|
||||||
|
className="w-5 h-[19px] ml-1"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
setIsDateModal(false);
|
||||||
|
handleSaveDate(selectDate);
|
||||||
|
props.setFontColor("");
|
||||||
|
props.setFontSize("");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("save")}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</ModalUi>
|
||||||
<>
|
</>
|
||||||
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
|
|
||||||
<PlaceholderType
|
|
||||||
pos={props.pos}
|
|
||||||
xyPostion={props.xyPostion}
|
|
||||||
index={props.index}
|
|
||||||
setXyPostion={props.setXyPostion}
|
|
||||||
data={props.data}
|
|
||||||
setSignKey={props.setSignKey}
|
|
||||||
isShowDropdown={props?.isShowDropdown}
|
|
||||||
isPlaceholder={props.isPlaceholder}
|
|
||||||
isSignYourself={props.isSignYourself}
|
|
||||||
signerObjId={props.signerObjId}
|
|
||||||
handleUserName={props.handleUserName}
|
|
||||||
setDraggingEnabled={setDraggingEnabled}
|
|
||||||
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
|
||||||
isNeedSign={props.isNeedSign}
|
|
||||||
setSelectDate={setSelectDate}
|
|
||||||
selectDate={selectDate}
|
|
||||||
setValidateAlert={props.setValidateAlert}
|
|
||||||
setStartDate={setStartDate}
|
|
||||||
startDate={startDate}
|
|
||||||
handleSaveDate={handleSaveDate}
|
|
||||||
xPos={props.xPos}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Rnd>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,14 +47,11 @@ function PlaceholderBorder(props) {
|
|||||||
onTouchEnd={() =>
|
onTouchEnd={() =>
|
||||||
props.pos.type === textWidget && props?.setDraggingEnabled(true)
|
props.pos.type === textWidget && props?.setDraggingEnabled(true)
|
||||||
}
|
}
|
||||||
className="absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize"
|
className="absolute inline-block w-[14px] h-[14px] border-[0.2px] overflow-hidden border-dashed"
|
||||||
style={{
|
style={{
|
||||||
borderColor: themeColor,
|
borderColor: themeColor,
|
||||||
borderStyle: "dashed",
|
|
||||||
minWidth: handleMinWidth() || 0,
|
minWidth: handleMinWidth() || 0,
|
||||||
minHeight: handleMinHeight() || 0,
|
minHeight: handleMinHeight() || 0
|
||||||
borderWidth: "0.2px",
|
|
||||||
overflow: "hidden"
|
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import { randomId, textWidget } from "../../constant/Utils";
|
import {
|
||||||
|
handleCopyNextToWidget,
|
||||||
|
randomId,
|
||||||
|
textWidget
|
||||||
|
} from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function PlaceholderCopy(props) {
|
function PlaceholderCopy(props) {
|
||||||
const copyType = ["All pages", "All pages but last", "All pages but first"];
|
const { t } = useTranslation();
|
||||||
const [selectCopyType, setSelectCopyType] = useState("");
|
const copyType = [
|
||||||
|
{ id: 1, type: "All pages" },
|
||||||
|
{ id: 2, type: "All pages but last" },
|
||||||
|
{ id: 3, type: "All pages but first" },
|
||||||
|
{ id: 4, type: "Next to current widget" }
|
||||||
|
];
|
||||||
|
const [selectCopyType, setSelectCopyType] = useState(1);
|
||||||
//function for get copy placeholder position
|
//function for get copy placeholder position
|
||||||
const getCopyPlaceholderPosition = (
|
const getCopyPlaceholderPosition = (
|
||||||
type,
|
type,
|
||||||
@@ -18,7 +29,7 @@ function PlaceholderCopy(props) {
|
|||||||
(data) => data.xPosition !== currentPlaceholder.xPosition
|
(data) => data.xPosition !== currentPlaceholder.xPosition
|
||||||
);
|
);
|
||||||
//copy all page placeholder at requested position except first page
|
//copy all page placeholder at requested position except first page
|
||||||
if (newPageNumber === 1 && type === "first") {
|
if (newPageNumber === 1 && type === 3) {
|
||||||
if (filterPosition && filterPosition.length > 0) {
|
if (filterPosition && filterPosition.length > 0) {
|
||||||
return {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
@@ -27,7 +38,7 @@ function PlaceholderCopy(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//copy all page placeholder at requested position except last page
|
//copy all page placeholder at requested position except last page
|
||||||
else if (newPageNumber === props.allPages && type === "last") {
|
else if (newPageNumber === props.allPages && type === 2) {
|
||||||
if (existPlaceholderPosition) {
|
if (existPlaceholderPosition) {
|
||||||
return {
|
return {
|
||||||
pageNumber: newPageNumber,
|
pageNumber: newPageNumber,
|
||||||
@@ -170,25 +181,65 @@ function PlaceholderCopy(props) {
|
|||||||
|
|
||||||
//function for getting selected type placeholder copy
|
//function for getting selected type placeholder copy
|
||||||
const handleApplyCopy = () => {
|
const handleApplyCopy = () => {
|
||||||
if (selectCopyType === "All pages") {
|
if (selectCopyType === 4) {
|
||||||
copyPlaceholder("all");
|
const signerPosition = props.xyPostion;
|
||||||
} else if (selectCopyType === "All pages but last") {
|
let currentXYposition;
|
||||||
copyPlaceholder("last");
|
const signerId = props.signerObjId ? props.signerObjId : props.Id;
|
||||||
} else if (selectCopyType === "All pages but first") {
|
if (signerId) {
|
||||||
copyPlaceholder("first");
|
const filterSignerPosition = signerPosition.filter(
|
||||||
|
(item) => item?.Id === signerId
|
||||||
|
);
|
||||||
|
currentXYposition = filterSignerPosition[0].placeHolder.filter(
|
||||||
|
(data) => data.pageNumber === props?.pageNumber
|
||||||
|
);
|
||||||
|
//get current placeholder position data which user want to copy
|
||||||
|
currentXYposition = currentXYposition[0].pos.find(
|
||||||
|
(position) => position.key === props.signKey
|
||||||
|
);
|
||||||
|
//function to create new widget next to just widget
|
||||||
|
handleCopyNextToWidget(
|
||||||
|
currentXYposition,
|
||||||
|
props.widgetType,
|
||||||
|
props.xyPostion,
|
||||||
|
props.pageNumber,
|
||||||
|
props.setXyPostion,
|
||||||
|
props?.Id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const getIndex = props?.xyPostion.findIndex(
|
||||||
|
(data) => data.pageNumber === props.pageNumber
|
||||||
|
);
|
||||||
|
const placeholderPosition = props?.xyPostion[getIndex];
|
||||||
|
//get current placeholder position data which user want to copy
|
||||||
|
currentXYposition = placeholderPosition.pos.find(
|
||||||
|
(pos) => pos.key === props.signKey
|
||||||
|
);
|
||||||
|
//function to create new widget next to just widget
|
||||||
|
handleCopyNextToWidget(
|
||||||
|
currentXYposition,
|
||||||
|
props.widgetType,
|
||||||
|
props.xyPostion,
|
||||||
|
getIndex,
|
||||||
|
props.setXyPostion
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copyPlaceholder(selectCopyType);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleUniqueId = () => {
|
const handleUniqueId = () => {
|
||||||
if (props.widgetType === textWidget) {
|
const signerId = props.signerObjId ? props.signerObjId : props.Id;
|
||||||
|
if (signerId && props.widgetType === textWidget) {
|
||||||
props.setUniqueId(props?.tempSignerId);
|
props.setUniqueId(props?.tempSignerId);
|
||||||
props.setTempSignerId("");
|
props.setTempSignerId("");
|
||||||
}
|
}
|
||||||
props.setIsPageCopy(false);
|
props.setIsPageCopy(false);
|
||||||
|
setSelectCopyType(1);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={props.isPageCopy}
|
isOpen={props.isPageCopy}
|
||||||
title={"Copy to all pages"}
|
title={t("copy-title")}
|
||||||
handleClose={() => handleUniqueId()}
|
handleClose={() => handleUniqueId()}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px] text-base-content">
|
<div className="h-full p-[20px] text-base-content">
|
||||||
@@ -199,12 +250,11 @@ function PlaceholderCopy(props) {
|
|||||||
<input
|
<input
|
||||||
className="mr-[8px] op-radio op-radio-xs"
|
className="mr-[8px] op-radio op-radio-xs"
|
||||||
type="radio"
|
type="radio"
|
||||||
value={data}
|
value={data.id}
|
||||||
onChange={() => setSelectCopyType(data)}
|
onChange={() => setSelectCopyType(data.id)}
|
||||||
checked={selectCopyType === data}
|
checked={selectCopyType === data.id}
|
||||||
/>
|
/>
|
||||||
|
{t(`copy-type.${data.type}`)}
|
||||||
{data}
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -220,14 +270,14 @@ function PlaceholderCopy(props) {
|
|||||||
disabled={!selectCopyType}
|
disabled={!selectCopyType}
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
Apply
|
{t("apply")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost"
|
className="op-btn op-btn-ghost"
|
||||||
onClick={() => handleUniqueId()}
|
onClick={() => handleUniqueId()}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -14,18 +14,23 @@ import "react-datepicker/dist/react-datepicker.css";
|
|||||||
import "../../styles/signature.css";
|
import "../../styles/signature.css";
|
||||||
import RegexParser from "regex-parser";
|
import RegexParser from "regex-parser";
|
||||||
import { emailRegex } from "../../constant/const";
|
import { emailRegex } from "../../constant/const";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
const textWidgetCls =
|
const textWidgetCls =
|
||||||
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap";
|
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap bg-white";
|
||||||
const selectWidgetCls =
|
const selectWidgetCls =
|
||||||
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none text-base-content";
|
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none text-base-content";
|
||||||
function PlaceholderType(props) {
|
function PlaceholderType(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const type = props?.pos?.type;
|
const type = props?.pos?.type;
|
||||||
|
const widgetTypeTraslation = t(`widgets-name.${props?.pos?.type}`);
|
||||||
const [selectOption, setSelectOption] = useState("");
|
const [selectOption, setSelectOption] = useState("");
|
||||||
const [validatePlaceholder, setValidatePlaceholder] = useState("");
|
const [validatePlaceholder, setValidatePlaceholder] = useState("");
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
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.calculateFont(props.pos.options?.fontSize);
|
||||||
|
const fontColor = props.pos.options?.fontColor || "black";
|
||||||
const months = [
|
const months = [
|
||||||
"January",
|
"January",
|
||||||
"February",
|
"February",
|
||||||
@@ -140,8 +145,12 @@ function PlaceholderType(props) {
|
|||||||
|
|
||||||
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
||||||
<div
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor,
|
||||||
|
fontFamily: "Arial, sans-serif"
|
||||||
|
}}
|
||||||
className={`${selectWidgetCls} overflow-hidden`}
|
className={`${selectWidgetCls} overflow-hidden`}
|
||||||
style={{ fontSize: calculateFontSize() }}
|
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
@@ -172,12 +181,6 @@ function PlaceholderType(props) {
|
|||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [type]);
|
}, [type]);
|
||||||
|
|
||||||
const calculateFontSize = () => {
|
|
||||||
const fontSize = 10 + Math.min(props.pos.Width, props.pos.Height) * 0.1;
|
|
||||||
const size = fontSize ? fontSize : 12;
|
|
||||||
return size + "px";
|
|
||||||
};
|
|
||||||
//function for show checked checkbox
|
//function for show checked checkbox
|
||||||
const selectCheckbox = (ind) => {
|
const selectCheckbox = (ind) => {
|
||||||
const res = props.pos.options?.response;
|
const res = props.pos.options?.response;
|
||||||
@@ -318,7 +321,7 @@ function PlaceholderType(props) {
|
|||||||
props?.handleUserName(
|
props?.handleUserName(
|
||||||
props?.data?.Id,
|
props?.data?.Id,
|
||||||
props?.data?.Role,
|
props?.data?.Role,
|
||||||
props?.pos?.type
|
widgetTypeTraslation
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -336,7 +339,7 @@ function PlaceholderType(props) {
|
|||||||
props?.handleUserName(
|
props?.handleUserName(
|
||||||
props?.data?.Id,
|
props?.data?.Id,
|
||||||
props?.data?.Role,
|
props?.data?.Role,
|
||||||
props?.pos?.type
|
widgetTypeTraslation
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -347,9 +350,13 @@ function PlaceholderType(props) {
|
|||||||
return (
|
return (
|
||||||
<div key={ind} className="flex items-center text-center gap-0.5">
|
<div key={ind} className="flex items-center text-center gap-0.5">
|
||||||
<input
|
<input
|
||||||
|
style={{
|
||||||
|
width: fontSize,
|
||||||
|
height: fontSize
|
||||||
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
ind === 0 ? "mt-0" : "mt-[5px]"
|
||||||
} flex justify-center op-checkbox op-checkbox-xs rounded-[0.350rem]`}
|
} flex justify-center op-checkbox rounded-[1px] `}
|
||||||
onBlur={handleInputBlur}
|
onBlur={handleInputBlur}
|
||||||
disabled={
|
disabled={
|
||||||
props.isNeedSign &&
|
props.isNeedSign &&
|
||||||
@@ -383,7 +390,15 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{!props.pos.options?.isHideLabel && (
|
{!props.pos.options?.isHideLabel && (
|
||||||
<label className="text-xs mb-0 text-center">{data}</label>
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
className="text-xs mb-0 text-center"
|
||||||
|
>
|
||||||
|
{data}
|
||||||
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -414,29 +429,30 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor
|
||||||
: "12px",
|
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
overflow: "hidden"
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{type}</span>
|
<span>{widgetTypeTraslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "dropdown":
|
case "dropdown":
|
||||||
return props.data?.signerObjId === props.signerObjId ? (
|
return props.data?.signerObjId === props.signerObjId ? (
|
||||||
<select
|
<select
|
||||||
className={`${selectWidgetCls} text-[12px]`}
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
className={`${selectWidgetCls} text-[12px] bg-inherit`}
|
||||||
id="myDropdown"
|
id="myDropdown"
|
||||||
value={selectOption}
|
value={selectOption}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -453,13 +469,28 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Default/Title option */}
|
{/* Default/Title option */}
|
||||||
<option value="" disabled hidden>
|
<option
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
value=""
|
||||||
|
disabled
|
||||||
|
hidden
|
||||||
|
>
|
||||||
{props?.pos?.options?.name}
|
{props?.pos?.options?.name}
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
{props.pos?.options?.values?.map((data, ind) => {
|
{props.pos?.options?.values?.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<option key={ind} value={data}>
|
<option
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
key={ind}
|
||||||
|
value={data}
|
||||||
|
>
|
||||||
{data}
|
{data}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
@@ -467,10 +498,15 @@ function PlaceholderType(props) {
|
|||||||
</select>
|
</select>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={selectWidgetCls}
|
style={{
|
||||||
style={{ fontSize: calculateFontSize() }}
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
className=" overflow-hidden"
|
||||||
>
|
>
|
||||||
{props.pos?.options?.name ? props.pos.options.name : type}
|
{props.pos?.options?.name
|
||||||
|
? props.pos.options.name
|
||||||
|
: widgetTypeTraslation}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "initials":
|
case "initials":
|
||||||
@@ -487,7 +523,7 @@ function PlaceholderType(props) {
|
|||||||
props?.handleUserName(
|
props?.handleUserName(
|
||||||
props?.data?.Id,
|
props?.data?.Id,
|
||||||
props?.data?.Role,
|
props?.data?.Role,
|
||||||
props?.pos?.type
|
widgetTypeTraslation
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -515,23 +551,21 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor
|
||||||
: "12px",
|
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
fontFamily: "Arial, sans-serif",
|
||||||
color: props.pos.options?.fontColor || "black"
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{type}</span>
|
<span>{widgetTypeTraslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "company":
|
case "company":
|
||||||
@@ -557,23 +591,21 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor
|
||||||
: "12px",
|
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
overflow: "hidden",
|
||||||
color: props.pos.options?.fontColor || "black"
|
fontFamily: "Arial, sans-serif"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{type}</span>
|
<span>{widgetTypeTraslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "job title":
|
case "job title":
|
||||||
@@ -599,23 +631,21 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor
|
||||||
: "12px",
|
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
fontFamily: "Arial, sans-serif",
|
||||||
color: props.pos.options?.fontColor || "black"
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{type}</span>
|
<span>{widgetTypeTraslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "date":
|
case "date":
|
||||||
@@ -678,7 +708,14 @@ function PlaceholderType(props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-[12px] text-black uppercase items-center">
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor,
|
||||||
|
fontFamily: "Arial, sans-serif"
|
||||||
|
}}
|
||||||
|
className="items-center overflow-hidden"
|
||||||
|
>
|
||||||
<span>
|
<span>
|
||||||
{props.selectDate
|
{props.selectDate
|
||||||
? props.selectDate?.format
|
? props.selectDate?.format
|
||||||
@@ -702,7 +739,7 @@ function PlaceholderType(props) {
|
|||||||
props?.handleUserName(
|
props?.handleUserName(
|
||||||
props?.data?.Id,
|
props?.data?.Id,
|
||||||
props?.data?.Role,
|
props?.data?.Role,
|
||||||
props?.pos?.type
|
widgetTypeTraslation
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -730,23 +767,22 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
fontFamily: "Arial, sans-serif"
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontSize: fontSize,
|
||||||
? props.pos.options?.fontSize + "px"
|
color: fontColor,
|
||||||
: "12px",
|
fontFamily: "Arial, sans-serif",
|
||||||
color: props.pos.options?.fontColor || "black"
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{type}</span>
|
<span>{widgetTypeTraslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case radioButtonWidget:
|
case radioButtonWidget:
|
||||||
@@ -756,9 +792,12 @@ function PlaceholderType(props) {
|
|||||||
return (
|
return (
|
||||||
<div key={ind} className="flex items-center text-center gap-0.5">
|
<div key={ind} className="flex items-center text-center gap-0.5">
|
||||||
<input
|
<input
|
||||||
className={`${
|
style={{
|
||||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
width: fontSize,
|
||||||
} ${"w-[15px] h-[15px]"} flex justify-center op-radio`}
|
height: fontSize,
|
||||||
|
marginTop: ind > 0 ? "10px" : "0px"
|
||||||
|
}}
|
||||||
|
className={`flex justify-center op-radio`}
|
||||||
type="radio"
|
type="radio"
|
||||||
disabled={
|
disabled={
|
||||||
props.isNeedSign &&
|
props.isNeedSign &&
|
||||||
@@ -773,7 +812,15 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{!props.pos.options?.isHideLabel && (
|
{!props.pos.options?.isHideLabel && (
|
||||||
<label className="text-xs mb-0">{data}</label>
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor
|
||||||
|
}}
|
||||||
|
className="text-xs mb-0"
|
||||||
|
>
|
||||||
|
{data}
|
||||||
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -802,10 +849,9 @@ function PlaceholderType(props) {
|
|||||||
}}
|
}}
|
||||||
className={textWidgetCls}
|
className={textWidgetCls}
|
||||||
style={{
|
style={{
|
||||||
fontSize: props.pos.options?.fontSize
|
fontFamily: "Arial, sans-serif",
|
||||||
? props.pos.options?.fontSize + "px"
|
fontSize: fontSize,
|
||||||
: "12px",
|
color: fontColor
|
||||||
color: props.pos.options?.fontColor || "black"
|
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function PrevNext({ pageNumber, allPages, changePage }) {
|
function PrevNext({ pageNumber, allPages, changePage }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
//for go to previous page
|
//for go to previous page
|
||||||
function previousPage() {
|
function previousPage() {
|
||||||
changePage(-1);
|
changePage(-1);
|
||||||
@@ -17,23 +19,21 @@ function PrevNext({ pageNumber, allPages, changePage }) {
|
|||||||
disabled={pageNumber <= 1}
|
disabled={pageNumber <= 1}
|
||||||
onClick={previousPage}
|
onClick={previousPage}
|
||||||
>
|
>
|
||||||
<span className="block lg:hidden">
|
<span className="block">
|
||||||
<i className="fa-light fa-backward" aria-hidden="true"></i>
|
<i className="fa-light fa-backward" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span className="lg:block hidden 2xl:text-[30px]">Prev</span>
|
|
||||||
</button>
|
</button>
|
||||||
<span className="text-xs text-base-content font-medium mx-2 2xl:text-[30px]">
|
<span className="text-xs text-base-content font-medium mx-2 2xl:text-[30px]">
|
||||||
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
|
{pageNumber || (allPages ? 1 : "--")} {t("of")} {allPages || "--"}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-neutral op-btn-xs md:op-btn-sm font-semibold text-xs"
|
className="op-btn op-btn-neutral op-btn-xs md:op-btn-sm font-semibold text-xs"
|
||||||
disabled={pageNumber >= allPages}
|
disabled={pageNumber >= allPages}
|
||||||
onClick={nextPage}
|
onClick={nextPage}
|
||||||
>
|
>
|
||||||
<span className="block lg:hidden">
|
<span className="block">
|
||||||
<i className="fa-light fa-forward" aria-hidden="true"></i>
|
<i className="fa-light fa-forward" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span className="lg:block hidden 2xl:text-[30px]">Next</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const RecipientList = (props) => {
|
|||||||
//function for onhover signer name change background color
|
//function for onhover signer name change background color
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const isWidgetExist = (Id) => {
|
const isWidgetExist = (Id) => {
|
||||||
return props.signerPos.some((x) => x.Id === Id);
|
return props.signerPos.some((x) => x.Id === Id && x.placeHolder);
|
||||||
};
|
};
|
||||||
|
|
||||||
//handle drag start
|
//handle drag start
|
||||||
@@ -63,9 +63,7 @@ const RecipientList = (props) => {
|
|||||||
remainingItems.splice(index, 0, ...draggedItem);
|
remainingItems.splice(index, 0, ...draggedItem);
|
||||||
//set current draggable recipient details,objectId,index,contract_className ... after replace recipient list
|
//set current draggable recipient details,objectId,index,contract_className ... after replace recipient list
|
||||||
props?.setSignersData(remainingItems);
|
props?.setSignersData(remainingItems);
|
||||||
props?.setSignerObjId(remainingItems[index]?.objectId || "");
|
|
||||||
props?.setIsSelectId(index);
|
props?.setIsSelectId(index);
|
||||||
props?.setContractName(remainingItems[index]?.className || "");
|
|
||||||
props?.setUniqueId(remainingItems[index]?.Id);
|
props?.setUniqueId(remainingItems[index]?.Id);
|
||||||
props?.setRoleName(remainingItems[index]?.Role);
|
props?.setRoleName(remainingItems[index]?.Role);
|
||||||
props?.setBlockColor(remainingItems[index]?.blockColor);
|
props?.setBlockColor(remainingItems[index]?.blockColor);
|
||||||
@@ -121,9 +119,7 @@ const RecipientList = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
props.setSignerObjId(obj?.objectId || "");
|
|
||||||
props.setIsSelectId(ind);
|
props.setIsSelectId(ind);
|
||||||
props.setContractName(obj?.className || "");
|
|
||||||
props.setUniqueId(obj.Id);
|
props.setUniqueId(obj.Id);
|
||||||
props.setRoleName(obj.Role);
|
props.setRoleName(obj.Role);
|
||||||
props.setBlockColor(obj?.blockColor);
|
props.setBlockColor(obj?.blockColor);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { Document, Page } from "react-pdf";
|
import { Document, Page } from "react-pdf";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
@@ -11,8 +12,10 @@ function RenderAllPdfPage({
|
|||||||
pageNumber,
|
pageNumber,
|
||||||
signerPos,
|
signerPos,
|
||||||
signerObjectId,
|
signerObjectId,
|
||||||
containerWH
|
containerWH,
|
||||||
|
pdfRotateBase64
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [signPageNumber, setSignPageNumber] = useState([]);
|
const [signPageNumber, setSignPageNumber] = useState([]);
|
||||||
const [bookmarkColor, setBookmarkColor] = useState("");
|
const [bookmarkColor, setBookmarkColor] = useState("");
|
||||||
//set all number of pages after load pdf
|
//set all number of pages after load pdf
|
||||||
@@ -64,19 +67,20 @@ function RenderAllPdfPage({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
|
||||||
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">
|
||||||
Pages
|
{t("pages")}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`flex h-[90%] flex-col items-center m-2
|
className={`flex h-[90%] flex-col items-center m-2
|
||||||
autoSignScroll hide-scrollbar max-h-[100vh] `}
|
autoSignScroll hide-scrollbar max-h-[100vh] `}
|
||||||
>
|
>
|
||||||
<Document
|
<Document
|
||||||
loading={"Loading Document.."}
|
loading={t("loading-doc")}
|
||||||
onLoadSuccess={onDocumentLoad}
|
onLoadSuccess={onDocumentLoad}
|
||||||
file={signPdfUrl}
|
file={(pdfRotateBase64 && pdfDataBase64) || signPdfUrl}
|
||||||
>
|
>
|
||||||
{Array.from(new Array(allPages), (el, index) => (
|
{Array.from(new Array(allPages), (el, index) => (
|
||||||
<div
|
<div
|
||||||
@@ -93,16 +97,16 @@ function RenderAllPdfPage({
|
|||||||
>
|
>
|
||||||
{signerPos && addSignatureBookmark(index)}
|
{signerPos && addSignatureBookmark(index)}
|
||||||
|
|
||||||
<div className="relative z-[1] overflow-hidden">
|
{/* <div className="relative z-[1] overflow-hidden"> */}
|
||||||
<Page
|
<Page
|
||||||
key={`page_${index + 1}`}
|
key={`page_${index + 1}`}
|
||||||
pageNumber={index + 1}
|
pageNumber={index + 1}
|
||||||
width={pageWidth - 60}
|
width={pageWidth - 60}
|
||||||
scale={1}
|
scale={1}
|
||||||
renderAnnotationLayer={false}
|
renderAnnotationLayer={false}
|
||||||
renderTextLayer={false}
|
renderTextLayer={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
{/* </div> */}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Document>
|
</Document>
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import RSC from "react-scrollbars-custom";
|
|||||||
import { Document, Page } from "react-pdf";
|
import { Document, Page } from "react-pdf";
|
||||||
import {
|
import {
|
||||||
defaultWidthHeight,
|
defaultWidthHeight,
|
||||||
|
getContainerScale,
|
||||||
handleImageResize,
|
handleImageResize,
|
||||||
handleSignYourselfImageResize
|
handleSignYourselfImageResize
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
import Placeholder from "./Placeholder";
|
import Placeholder from "./Placeholder";
|
||||||
import Alert from "../../primitives/Alert";
|
import Alert from "../../primitives/Alert";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function RenderPdf({
|
function RenderPdf({
|
||||||
pageNumber,
|
pageNumber,
|
||||||
@@ -23,7 +25,6 @@ function RenderPdf({
|
|||||||
setSignKey,
|
setSignKey,
|
||||||
pdfDetails,
|
pdfDetails,
|
||||||
xyPostion,
|
xyPostion,
|
||||||
pdfUrl,
|
|
||||||
pageDetails,
|
pageDetails,
|
||||||
pdfRequest,
|
pdfRequest,
|
||||||
signerObjectId,
|
signerObjectId,
|
||||||
@@ -40,7 +41,6 @@ function RenderPdf({
|
|||||||
setUniqueId,
|
setUniqueId,
|
||||||
signersdata,
|
signersdata,
|
||||||
setIsPageCopy,
|
setIsPageCopy,
|
||||||
setSignerObjId,
|
|
||||||
setShowDropdown,
|
setShowDropdown,
|
||||||
setIsInitial,
|
setIsInitial,
|
||||||
setIsValidate,
|
setIsValidate,
|
||||||
@@ -60,18 +60,27 @@ function RenderPdf({
|
|||||||
scale,
|
scale,
|
||||||
setIsSelectId,
|
setIsSelectId,
|
||||||
ispublicTemplate,
|
ispublicTemplate,
|
||||||
handleUserDetails
|
handleUserDetails,
|
||||||
|
pdfRotateBase64,
|
||||||
|
fontSize,
|
||||||
|
setFontSize,
|
||||||
|
fontColor,
|
||||||
|
setFontColor,
|
||||||
|
isResize
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
|
|
||||||
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
|
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
|
||||||
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
const isGuestSigner = localStorage.getItem("isGuestSigner");
|
||||||
|
|
||||||
// handle signature block width and height according to screen
|
// handle signature block width and height according to screen
|
||||||
const posWidth = (pos, signYourself) => {
|
const posWidth = (pos, signYourself) => {
|
||||||
const getPdfPageWidth = pdfOriginalWH.find(
|
const containerScale = getContainerScale(
|
||||||
(data) => data.pageNumber === pageNumber
|
pdfOriginalWH,
|
||||||
|
pageNumber,
|
||||||
|
containerWH
|
||||||
);
|
);
|
||||||
const containerScale = containerWH.width / getPdfPageWidth.width || 1;
|
|
||||||
const defaultWidth = defaultWidthHeight(pos.type).width;
|
const defaultWidth = defaultWidthHeight(pos.type).width;
|
||||||
const posWidth = pos.Width ? pos.Width : defaultWidth;
|
const posWidth = pos.Width ? pos.Width : defaultWidth;
|
||||||
if (signYourself) {
|
if (signYourself) {
|
||||||
@@ -96,12 +105,13 @@ function RenderPdf({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const posHeight = (pos, signYourself) => {
|
|
||||||
const getPdfPageWidth = pdfOriginalWH.find(
|
|
||||||
(data) => data.pageNumber === pageNumber
|
|
||||||
);
|
|
||||||
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
|
|
||||||
|
|
||||||
|
const posHeight = (pos, signYourself) => {
|
||||||
|
const containerScale = getContainerScale(
|
||||||
|
pdfOriginalWH,
|
||||||
|
pageNumber,
|
||||||
|
containerWH
|
||||||
|
);
|
||||||
const posHeight = pos.Height || defaultWidthHeight(pos.type).height;
|
const posHeight = pos.Height || defaultWidthHeight(pos.type).height;
|
||||||
if (signYourself) {
|
if (signYourself) {
|
||||||
return posHeight * scale * containerScale;
|
return posHeight * scale * containerScale;
|
||||||
@@ -199,6 +209,7 @@ function RenderPdf({
|
|||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
ispublicTemplate={ispublicTemplate}
|
ispublicTemplate={ispublicTemplate}
|
||||||
handleUserDetails={handleUserDetails}
|
handleUserDetails={handleUserDetails}
|
||||||
|
isResize={isResize}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
@@ -245,154 +256,184 @@ function RenderPdf({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
|
{successEmail && (
|
||||||
|
<Alert type={"success"}>{t("success-email-alert")}</Alert>
|
||||||
|
)}
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<div
|
<RSC
|
||||||
data-tut="reactourForth"
|
style={{
|
||||||
className={`${
|
position: "relative",
|
||||||
isGuestSigner ? "30px" : ""
|
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
||||||
} border-[0.1px] border-[#ebe8e8]`}
|
height: window.innerHeight - 200,
|
||||||
ref={drop}
|
zIndex: 0
|
||||||
id="container"
|
}}
|
||||||
|
className="h-full"
|
||||||
|
noScrollY={false}
|
||||||
|
noScrollX={scale === 1 ? true : false}
|
||||||
>
|
>
|
||||||
{containerWH?.width &&
|
<div
|
||||||
pdfOriginalWH.length > 0 &&
|
data-tut="reactourForth"
|
||||||
(pdfRequest
|
className={`${
|
||||||
? signerPos.map((data, key) => {
|
isGuestSigner ? "30px" : ""
|
||||||
return (
|
} border-[0.1px] border-[#ebe8e8] overflow-x-auto`}
|
||||||
<React.Fragment key={key}>
|
style={{
|
||||||
{checkSignedSigners(data)}
|
width: containerWH?.width && containerWH?.width * scale
|
||||||
</React.Fragment>
|
}}
|
||||||
);
|
ref={drop}
|
||||||
})
|
id="container"
|
||||||
: placeholder // placeholder mobile
|
>
|
||||||
? signerPos.map((data, ind) => {
|
{containerWH?.width &&
|
||||||
|
pdfOriginalWH.length > 0 &&
|
||||||
|
(pdfRequest
|
||||||
|
? signerPos.map((data, key) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={key}>
|
||||||
{data.placeHolder.map((placeData, index) => {
|
{checkSignedSigners(data)}
|
||||||
return (
|
|
||||||
<React.Fragment key={index}>
|
|
||||||
{placeData.pageNumber === pageNumber &&
|
|
||||||
placeData.pos.map((pos) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={pos.key}>
|
|
||||||
<Placeholder
|
|
||||||
pos={pos}
|
|
||||||
setIsPageCopy={setIsPageCopy}
|
|
||||||
setSignKey={setSignKey}
|
|
||||||
handleDeleteSign={handleDeleteSign}
|
|
||||||
setIsStamp={setIsStamp}
|
|
||||||
handleTabDrag={handleTabDrag}
|
|
||||||
handleStop={handleStop}
|
|
||||||
handleSignYourselfImageResize={
|
|
||||||
handleImageResize
|
|
||||||
}
|
|
||||||
index={pageNumber}
|
|
||||||
xyPostion={signerPos}
|
|
||||||
setXyPostion={setSignerPos}
|
|
||||||
setSignerObjId={setSignerObjId}
|
|
||||||
data={data}
|
|
||||||
setIsResize={setIsResize}
|
|
||||||
setShowDropdown={setShowDropdown}
|
|
||||||
isShowBorder={true}
|
|
||||||
isPlaceholder={true}
|
|
||||||
setUniqueId={setUniqueId}
|
|
||||||
handleLinkUser={handleLinkUser}
|
|
||||||
handleUserName={handleUserName}
|
|
||||||
isSignYourself={false}
|
|
||||||
posWidth={posWidth}
|
|
||||||
posHeight={posHeight}
|
|
||||||
isDragging={isDragging}
|
|
||||||
setIsValidate={setIsValidate}
|
|
||||||
setWidgetType={setWidgetType}
|
|
||||||
setIsRadio={setIsRadio}
|
|
||||||
setIsCheckbox={setIsCheckbox}
|
|
||||||
setCurrWidgetsDetails={
|
|
||||||
setCurrWidgetsDetails
|
|
||||||
}
|
|
||||||
setSelectWidgetId={setSelectWidgetId}
|
|
||||||
selectWidgetId={selectWidgetId}
|
|
||||||
handleNameModal={handleNameModal}
|
|
||||||
setTempSignerId={setTempSignerId}
|
|
||||||
uniqueId={uniqueId}
|
|
||||||
handleTextSettingModal={
|
|
||||||
handleTextSettingModal
|
|
||||||
}
|
|
||||||
scale={scale}
|
|
||||||
containerWH={containerWH}
|
|
||||||
pdfOriginalWH={pdfOriginalWH}
|
|
||||||
pageNumber={pageNumber}
|
|
||||||
setIsSelectId={setIsSelectId}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: xyPostion.map((data, ind) => {
|
: placeholder // placeholder mobile
|
||||||
return (
|
? signerPos?.map((data, ind) => {
|
||||||
<React.Fragment key={ind}>
|
return (
|
||||||
{data.pageNumber === pageNumber &&
|
<React.Fragment key={ind}>
|
||||||
data.pos.map((pos) => {
|
{data?.placeHolder &&
|
||||||
return (
|
data?.placeHolder.map((placeData, index) => {
|
||||||
pos && (
|
return (
|
||||||
<Placeholder
|
<React.Fragment key={index}>
|
||||||
pos={pos}
|
{placeData.pageNumber === pageNumber &&
|
||||||
setIsPageCopy={setIsPageCopy}
|
placeData.pos.map((pos) => {
|
||||||
setSignKey={setSignKey}
|
return (
|
||||||
handleDeleteSign={handleDeleteSign}
|
<React.Fragment key={pos.key}>
|
||||||
setIsStamp={setIsStamp}
|
<Placeholder
|
||||||
handleTabDrag={handleTabDrag}
|
pos={pos}
|
||||||
handleStop={handleStop}
|
setIsPageCopy={setIsPageCopy}
|
||||||
handleSignYourselfImageResize={
|
setSignKey={setSignKey}
|
||||||
handleSignYourselfImageResize
|
handleDeleteSign={handleDeleteSign}
|
||||||
}
|
setIsStamp={setIsStamp}
|
||||||
index={index}
|
handleTabDrag={handleTabDrag}
|
||||||
xyPostion={xyPostion}
|
handleStop={handleStop}
|
||||||
setXyPostion={setXyPostion}
|
handleSignYourselfImageResize={
|
||||||
containerWH={containerWH}
|
handleImageResize
|
||||||
setIsSignPad={setIsSignPad}
|
}
|
||||||
isShowBorder={true}
|
index={pageNumber}
|
||||||
isSignYourself={true}
|
xyPostion={signerPos}
|
||||||
posWidth={posWidth}
|
setXyPostion={setSignerPos}
|
||||||
posHeight={posHeight}
|
data={data}
|
||||||
pdfDetails={pdfDetails[0]}
|
setIsResize={setIsResize}
|
||||||
isDragging={isDragging}
|
setShowDropdown={setShowDropdown}
|
||||||
setIsInitial={setIsInitial}
|
isShowBorder={true}
|
||||||
setWidgetType={setWidgetType}
|
isPlaceholder={true}
|
||||||
setSelectWidgetId={setSelectWidgetId}
|
setUniqueId={setUniqueId}
|
||||||
selectWidgetId={selectWidgetId}
|
handleLinkUser={handleLinkUser}
|
||||||
handleUserName={handleUserName}
|
handleUserName={handleUserName}
|
||||||
setIsCheckbox={setIsCheckbox}
|
isSignYourself={false}
|
||||||
setValidateAlert={setValidateAlert}
|
posWidth={posWidth}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
posHeight={posHeight}
|
||||||
handleTextSettingModal={
|
isDragging={isDragging}
|
||||||
handleTextSettingModal
|
setIsValidate={setIsValidate}
|
||||||
}
|
setWidgetType={setWidgetType}
|
||||||
scale={scale}
|
setIsRadio={setIsRadio}
|
||||||
pdfOriginalWH={pdfOriginalWH}
|
setIsCheckbox={setIsCheckbox}
|
||||||
pageNumber={pageNumber}
|
setCurrWidgetsDetails={
|
||||||
/>
|
setCurrWidgetsDetails
|
||||||
)
|
}
|
||||||
);
|
setSelectWidgetId={
|
||||||
})}
|
setSelectWidgetId
|
||||||
</React.Fragment>
|
}
|
||||||
);
|
selectWidgetId={selectWidgetId}
|
||||||
}))}
|
handleNameModal={handleNameModal}
|
||||||
|
setTempSignerId={setTempSignerId}
|
||||||
|
uniqueId={uniqueId}
|
||||||
|
handleTextSettingModal={
|
||||||
|
handleTextSettingModal
|
||||||
|
}
|
||||||
|
scale={scale}
|
||||||
|
containerWH={containerWH}
|
||||||
|
pdfOriginalWH={pdfOriginalWH}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
setIsSelectId={setIsSelectId}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: !pdfDetails?.[0]?.IsCompleted &&
|
||||||
|
xyPostion.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={ind}>
|
||||||
|
{data.pageNumber === pageNumber &&
|
||||||
|
data.pos.map((pos) => {
|
||||||
|
return (
|
||||||
|
pos && (
|
||||||
|
<Placeholder
|
||||||
|
pos={pos}
|
||||||
|
setIsPageCopy={setIsPageCopy}
|
||||||
|
setSignKey={setSignKey}
|
||||||
|
handleDeleteSign={handleDeleteSign}
|
||||||
|
setIsStamp={setIsStamp}
|
||||||
|
handleTabDrag={handleTabDrag}
|
||||||
|
handleStop={handleStop}
|
||||||
|
handleSignYourselfImageResize={
|
||||||
|
handleSignYourselfImageResize
|
||||||
|
}
|
||||||
|
index={index}
|
||||||
|
xyPostion={xyPostion}
|
||||||
|
setXyPostion={setXyPostion}
|
||||||
|
containerWH={containerWH}
|
||||||
|
setIsSignPad={setIsSignPad}
|
||||||
|
isShowBorder={true}
|
||||||
|
isSignYourself={true}
|
||||||
|
posWidth={posWidth}
|
||||||
|
posHeight={posHeight}
|
||||||
|
pdfDetails={pdfDetails[0]}
|
||||||
|
isDragging={isDragging}
|
||||||
|
setIsInitial={setIsInitial}
|
||||||
|
setWidgetType={setWidgetType}
|
||||||
|
setSelectWidgetId={setSelectWidgetId}
|
||||||
|
selectWidgetId={selectWidgetId}
|
||||||
|
handleUserName={handleUserName}
|
||||||
|
setIsCheckbox={setIsCheckbox}
|
||||||
|
setValidateAlert={setValidateAlert}
|
||||||
|
setCurrWidgetsDetails={
|
||||||
|
setCurrWidgetsDetails
|
||||||
|
}
|
||||||
|
handleTextSettingModal={
|
||||||
|
handleTextSettingModal
|
||||||
|
}
|
||||||
|
scale={scale}
|
||||||
|
pdfOriginalWH={pdfOriginalWH}
|
||||||
|
pageNumber={pageNumber}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
setIsResize={setIsResize}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}))}
|
||||||
|
|
||||||
{/* this component for render pdf document is in middle of the component */}
|
|
||||||
<div className="flex items-center justify-center">
|
|
||||||
<Document
|
<Document
|
||||||
onLoadError={() => {
|
onLoadError={() => setPdfLoad(false)}
|
||||||
setPdfLoad(false);
|
loading={t("loading-doc")}
|
||||||
}}
|
|
||||||
loading={"Loading Document.."}
|
|
||||||
onLoadSuccess={pageDetails}
|
onLoadSuccess={pageDetails}
|
||||||
// ref={pdfRef}'
|
// ref={pdfRef}'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -401,14 +442,13 @@ function RenderPdf({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
file={
|
file={
|
||||||
pdfUrl
|
(pdfRotateBase64 && pdfDataBase64) ||
|
||||||
? pdfUrl
|
pdfDetails[0]?.SignedUrl ||
|
||||||
: pdfDetails[0] && pdfDetails[0].SignedUrl
|
pdfDetails[0].URL
|
||||||
? pdfDetails[0].SignedUrl
|
|
||||||
: pdfDetails[0].URL
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Page
|
<Page
|
||||||
|
scale={scale || 1}
|
||||||
key={index}
|
key={index}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
width={containerWH.width}
|
width={containerWH.width}
|
||||||
@@ -420,7 +460,7 @@ function RenderPdf({
|
|||||||
/>
|
/>
|
||||||
</Document>
|
</Document>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</RSC>
|
||||||
) : (
|
) : (
|
||||||
<RSC
|
<RSC
|
||||||
style={{
|
style={{
|
||||||
@@ -454,71 +494,79 @@ function RenderPdf({
|
|||||||
? signerPos.map((data, ind) => {
|
? signerPos.map((data, ind) => {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
{data.placeHolder.map((placeData, index) => {
|
{data?.placeHolder &&
|
||||||
return (
|
data?.placeHolder.map((placeData, index) => {
|
||||||
<React.Fragment key={index}>
|
return (
|
||||||
{placeData.pageNumber === pageNumber &&
|
<React.Fragment key={index}>
|
||||||
placeData.pos.map((pos) => {
|
{placeData.pageNumber === pageNumber &&
|
||||||
return (
|
placeData.pos.map((pos) => {
|
||||||
<React.Fragment key={pos.key}>
|
return (
|
||||||
<Placeholder
|
<React.Fragment key={pos.key}>
|
||||||
pos={pos}
|
<Placeholder
|
||||||
setIsPageCopy={setIsPageCopy}
|
pos={pos}
|
||||||
setSignKey={setSignKey}
|
setIsPageCopy={setIsPageCopy}
|
||||||
handleDeleteSign={handleDeleteSign}
|
setSignKey={setSignKey}
|
||||||
setIsStamp={setIsStamp}
|
handleDeleteSign={handleDeleteSign}
|
||||||
handleTabDrag={handleTabDrag}
|
setIsStamp={setIsStamp}
|
||||||
handleStop={handleStop}
|
handleTabDrag={handleTabDrag}
|
||||||
handleSignYourselfImageResize={
|
handleStop={handleStop}
|
||||||
handleImageResize
|
handleSignYourselfImageResize={
|
||||||
}
|
handleImageResize
|
||||||
index={pageNumber}
|
}
|
||||||
xyPostion={signerPos}
|
index={pageNumber}
|
||||||
setXyPostion={setSignerPos}
|
xyPostion={signerPos}
|
||||||
setSignerObjId={setSignerObjId}
|
setXyPostion={setSignerPos}
|
||||||
data={data}
|
data={data}
|
||||||
setIsResize={setIsResize}
|
setIsResize={setIsResize}
|
||||||
setShowDropdown={setShowDropdown}
|
setShowDropdown={setShowDropdown}
|
||||||
isShowBorder={true}
|
isShowBorder={true}
|
||||||
isPlaceholder={true}
|
isPlaceholder={true}
|
||||||
setUniqueId={setUniqueId}
|
setUniqueId={setUniqueId}
|
||||||
handleLinkUser={handleLinkUser}
|
handleLinkUser={handleLinkUser}
|
||||||
handleUserName={handleUserName}
|
handleUserName={handleUserName}
|
||||||
isSignYourself={false}
|
isSignYourself={false}
|
||||||
posWidth={posWidth}
|
posWidth={posWidth}
|
||||||
posHeight={posHeight}
|
posHeight={posHeight}
|
||||||
isDragging={isDragging}
|
isDragging={isDragging}
|
||||||
setIsValidate={setIsValidate}
|
setIsValidate={setIsValidate}
|
||||||
setWidgetType={setWidgetType}
|
setWidgetType={setWidgetType}
|
||||||
setIsRadio={setIsRadio}
|
setIsRadio={setIsRadio}
|
||||||
setIsCheckbox={setIsCheckbox}
|
setIsCheckbox={setIsCheckbox}
|
||||||
setCurrWidgetsDetails={
|
setCurrWidgetsDetails={
|
||||||
setCurrWidgetsDetails
|
setCurrWidgetsDetails
|
||||||
}
|
}
|
||||||
setSelectWidgetId={setSelectWidgetId}
|
setSelectWidgetId={
|
||||||
selectWidgetId={selectWidgetId}
|
setSelectWidgetId
|
||||||
handleNameModal={handleNameModal}
|
}
|
||||||
setTempSignerId={setTempSignerId}
|
selectWidgetId={selectWidgetId}
|
||||||
uniqueId={uniqueId}
|
handleNameModal={handleNameModal}
|
||||||
handleTextSettingModal={
|
setTempSignerId={setTempSignerId}
|
||||||
handleTextSettingModal
|
uniqueId={uniqueId}
|
||||||
}
|
handleTextSettingModal={
|
||||||
scale={scale}
|
handleTextSettingModal
|
||||||
containerWH={containerWH}
|
}
|
||||||
pdfOriginalWH={pdfOriginalWH}
|
scale={scale}
|
||||||
pageNumber={pageNumber}
|
containerWH={containerWH}
|
||||||
setIsSelectId={setIsSelectId}
|
pdfOriginalWH={pdfOriginalWH}
|
||||||
/>
|
pageNumber={pageNumber}
|
||||||
</React.Fragment>
|
setIsSelectId={setIsSelectId}
|
||||||
);
|
fontSize={fontSize}
|
||||||
})}
|
setFontSize={setFontSize}
|
||||||
</React.Fragment>
|
fontColor={fontColor}
|
||||||
);
|
setFontColor={setFontColor}
|
||||||
})}
|
isResize={isResize}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: xyPostion.map((data, ind) => {
|
: !pdfDetails?.[0]?.IsCompleted &&
|
||||||
|
xyPostion?.map((data, ind) => {
|
||||||
// signyourself flow
|
// signyourself flow
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
@@ -566,6 +614,12 @@ function RenderPdf({
|
|||||||
containerWH={containerWH}
|
containerWH={containerWH}
|
||||||
pdfOriginalWH={pdfOriginalWH}
|
pdfOriginalWH={pdfOriginalWH}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
|
setIsResize={setIsResize}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
@@ -576,10 +630,8 @@ function RenderPdf({
|
|||||||
|
|
||||||
{/* this component for render pdf document is in middle of the component */}
|
{/* this component for render pdf document is in middle of the component */}
|
||||||
<Document
|
<Document
|
||||||
onLoadError={() => {
|
onLoadError={() => setPdfLoad(false)}
|
||||||
pdfLoad(false);
|
loading={t("loading-doc")}
|
||||||
}}
|
|
||||||
loading={"Loading Document.."}
|
|
||||||
onLoadSuccess={pageDetails}
|
onLoadSuccess={pageDetails}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (setSelectWidgetId) {
|
if (setSelectWidgetId) {
|
||||||
@@ -588,11 +640,9 @@ function RenderPdf({
|
|||||||
}}
|
}}
|
||||||
// ref={pdfRef}
|
// ref={pdfRef}
|
||||||
file={
|
file={
|
||||||
pdfUrl
|
(pdfRotateBase64 && pdfDataBase64) ||
|
||||||
? pdfUrl
|
pdfDetails[0]?.SignedUrl ||
|
||||||
: pdfDetails[0] && pdfDetails[0].SignedUrl
|
pdfDetails[0].URL
|
||||||
? pdfDetails[0].SignedUrl
|
|
||||||
: pdfDetails[0].URL
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Page
|
<Page
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import i18next from "i18next";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function SelectLanguage(props) {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
const languages = [
|
||||||
|
{ value: "en", text: "English" },
|
||||||
|
{ value: "es", text: "Española" },
|
||||||
|
{ value: "fr", text: "Français" }
|
||||||
|
];
|
||||||
|
const [lang, setLang] = useState(i18next.language || "en");
|
||||||
|
// This function put query that helps to change the language
|
||||||
|
const handleChangeLang = (e) => {
|
||||||
|
setLang(e.target.value);
|
||||||
|
i18n.changeLanguage(e.target.value);
|
||||||
|
props?.updateExtUser &&
|
||||||
|
props.updateExtUser({
|
||||||
|
language: e.target.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
!props.isProfile && " mt-[9px] pb-2 md:pb-0 "
|
||||||
|
} flex justify-center items-center `}
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
value={lang}
|
||||||
|
onChange={handleChangeLang}
|
||||||
|
className={`${
|
||||||
|
!props.isProfile ? " md:w-[15%] w-[50%]" : "w-[180px]"
|
||||||
|
} op-select op-select-bordered bg-white op-select-sm `}
|
||||||
|
>
|
||||||
|
<option disabled selected>
|
||||||
|
select
|
||||||
|
</option>
|
||||||
|
{languages.map((item) => {
|
||||||
|
return (
|
||||||
|
<option key={item.value} value={item.value}>
|
||||||
|
{item.text}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectLanguage;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useRef, useState, useEffect } from "react";
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
|
|
||||||
function SignPad({
|
function SignPad({
|
||||||
isSignPad,
|
isSignPad,
|
||||||
isStamp,
|
isStamp,
|
||||||
@@ -23,6 +23,7 @@ function SignPad({
|
|||||||
currWidgetsDetails,
|
currWidgetsDetails,
|
||||||
setCurrWidgetsDetails
|
setCurrWidgetsDetails
|
||||||
}) {
|
}) {
|
||||||
|
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);
|
||||||
@@ -30,8 +31,8 @@ function SignPad({
|
|||||||
const [isTab, setIsTab] = useState("draw");
|
const [isTab, setIsTab] = useState("draw");
|
||||||
const [isSignImg, setIsSignImg] = useState("");
|
const [isSignImg, setIsSignImg] = useState("");
|
||||||
const [signValue, setSignValue] = useState("");
|
const [signValue, setSignValue] = useState("");
|
||||||
const [textWidth, setTextWidth] = useState(null);
|
const [textWidth, setTextWidth] = useState(0);
|
||||||
const [textHeight, setTextHeight] = useState(null);
|
const [textHeight, setTextHeight] = useState(0);
|
||||||
const [signatureType, setSignatureType] = useState("draw");
|
const [signatureType, setSignatureType] = useState("draw");
|
||||||
const fontOptions = [
|
const fontOptions = [
|
||||||
{ value: "Fasthand" },
|
{ value: "Fasthand" },
|
||||||
@@ -50,7 +51,7 @@ function SignPad({
|
|||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
);
|
);
|
||||||
const jsonSender = JSON.parse(senderUser);
|
const jsonSender = JSON.parse(senderUser);
|
||||||
const currentUserName = jsonSender && jsonSender.name;
|
const currentUserName = jsonSender && jsonSender?.name;
|
||||||
|
|
||||||
//function for clear signature image
|
//function for clear signature image
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
@@ -82,7 +83,7 @@ function SignPad({
|
|||||||
className="op-btn op-btn-ghost mr-1 mt-[2px]"
|
className="op-btn op-btn-ghost mr-1 mt-[2px]"
|
||||||
onClick={() => handleClear()}
|
onClick={() => handleClear()}
|
||||||
>
|
>
|
||||||
Clear
|
{t("clear")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
@@ -99,7 +100,12 @@ function SignPad({
|
|||||||
} else {
|
} else {
|
||||||
if (isTab === "type") {
|
if (isTab === "type") {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
onSaveSign(null, false, textWidth, textHeight);
|
onSaveSign(
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
!isInitial && textWidth > 150 ? 150 : textWidth,
|
||||||
|
!isInitial && textHeight > 35 ? 35 : textHeight
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setIsSignImg("");
|
setIsSignImg("");
|
||||||
canvasRef.current.clear();
|
canvasRef.current.clear();
|
||||||
@@ -131,14 +137,14 @@ function SignPad({
|
|||||||
(isTab === "draw" && isSignImg) ||
|
(isTab === "draw" && isSignImg) ||
|
||||||
(isTab === "image" && image) ||
|
(isTab === "image" && image) ||
|
||||||
(isTab === "mysignature" && isDefaultSign) ||
|
(isTab === "mysignature" && isDefaultSign) ||
|
||||||
(isTab === "type" && textWidth)
|
(isTab === "type" && signValue)
|
||||||
? false
|
? false
|
||||||
: image
|
: image
|
||||||
? false
|
? false
|
||||||
: true
|
: true
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -163,10 +169,10 @@ 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 = 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
|
||||||
@@ -194,8 +200,10 @@ function SignPad({
|
|||||||
canvasRef.current.fromDataURL(isSignImg);
|
canvasRef.current.fromDataURL(isSignImg);
|
||||||
}
|
}
|
||||||
if (isTab === "type") {
|
if (isTab === "type") {
|
||||||
const trimmedName = signValue ? signValue.trim() : currentUserName.trim();
|
const trimmedName = signValue
|
||||||
const firstCharacter = trimmedName.charAt(0);
|
? signValue?.trim()
|
||||||
|
: currentUserName?.trim();
|
||||||
|
const firstCharacter = trimmedName?.charAt(0);
|
||||||
const userName = isInitial ? firstCharacter : signValue;
|
const userName = isInitial ? firstCharacter : signValue;
|
||||||
setSignValue(userName);
|
setSignValue(userName);
|
||||||
convertToImg(fontSelect, userName);
|
convertToImg(fontSelect, userName);
|
||||||
@@ -211,11 +219,11 @@ function SignPad({
|
|||||||
: fontSelect
|
: fontSelect
|
||||||
? fontSelect
|
? fontSelect
|
||||||
: "Fasthand";
|
: "Fasthand";
|
||||||
|
const fontSizeValue = "40px";
|
||||||
//creating span for getting text content width
|
//creating span for getting text content width
|
||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.textContent = textContent;
|
span.textContent = textContent;
|
||||||
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
|
span.style.font = `${fontSizeValue} ${fontfamily}`; // here put your text size and font family
|
||||||
span.style.color = color ? color : penColor;
|
span.style.color = color ? color : penColor;
|
||||||
span.style.display = "hidden";
|
span.style.display = "hidden";
|
||||||
document.body.appendChild(span); // Replace 'container' with the ID of the container element
|
document.body.appendChild(span); // Replace 'container' with the ID of the container element
|
||||||
@@ -225,7 +233,8 @@ 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 width = span.offsetWidth;
|
const addExtraWidth = isInitial ? 10 : 50;
|
||||||
|
const width = span.offsetWidth + addExtraWidth;
|
||||||
const height = span.offsetHeight;
|
const height = span.offsetHeight;
|
||||||
setTextWidth(width);
|
setTextWidth(width);
|
||||||
setTextHeight(height);
|
setTextHeight(height);
|
||||||
@@ -301,8 +310,8 @@ function SignPad({
|
|||||||
<span className="text-base-content font-bold text-lg">
|
<span className="text-base-content font-bold text-lg">
|
||||||
{widgetType === "image" ||
|
{widgetType === "image" ||
|
||||||
currWidgetsDetails?.type === "image"
|
currWidgetsDetails?.type === "image"
|
||||||
? "Upload image"
|
? t("upload-image")
|
||||||
: "Upload stamp image"}
|
: t("upload-stamp-image")}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -323,7 +332,7 @@ function SignPad({
|
|||||||
: "no-underline"
|
: "no-underline"
|
||||||
} op-link underline-offset-8 ml-[2px]`}
|
} op-link underline-offset-8 ml-[2px]`}
|
||||||
>
|
>
|
||||||
Draw
|
{t("draw")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -340,7 +349,7 @@ function SignPad({
|
|||||||
: "no-underline"
|
: "no-underline"
|
||||||
} op-link underline-offset-8 ml-[2px]`}
|
} op-link underline-offset-8 ml-[2px]`}
|
||||||
>
|
>
|
||||||
Upload Image
|
{t("upload-image")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -358,7 +367,7 @@ function SignPad({
|
|||||||
: "no-underline"
|
: "no-underline"
|
||||||
} op-link underline-offset-8 ml-[2px]`}
|
} op-link underline-offset-8 ml-[2px]`}
|
||||||
>
|
>
|
||||||
Type
|
{t("type")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{!isInitial && defaultSign ? (
|
{!isInitial && defaultSign ? (
|
||||||
@@ -377,7 +386,7 @@ function SignPad({
|
|||||||
: "no-underline"
|
: "no-underline"
|
||||||
} op-link underline-offset-8 ml-[2px]`}
|
} op-link underline-offset-8 ml-[2px]`}
|
||||||
>
|
>
|
||||||
My Signature
|
{t("my-signature")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -398,7 +407,7 @@ function SignPad({
|
|||||||
: "no-underline"
|
: "no-underline"
|
||||||
} op-link underline-offset-8 ml-[2px]`}
|
} op-link underline-offset-8 ml-[2px]`}
|
||||||
>
|
>
|
||||||
My Initials
|
{t("my-initials")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -485,7 +494,7 @@ function SignPad({
|
|||||||
hidden
|
hidden
|
||||||
/>
|
/>
|
||||||
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
|
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
|
||||||
<div className="text-[10px]">Upload</div>
|
<div className="text-[10px]">{t("upload")}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -522,7 +531,7 @@ 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 ? "Initials" : "Signature"}:
|
{isInitial ? t("initial-teb") : t("signature-tab")}:
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
maxLength={isInitial ? 3 : 30}
|
maxLength={isInitial ? 3 : 30}
|
||||||
@@ -587,7 +596,7 @@ 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())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import "../../styles/signature.css";
|
import "../../styles/signature.css";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function Signedby({ pdfDetails }) {
|
function Signedby({ pdfDetails }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const getFirstLetter = (name) => {
|
const getFirstLetter = (name) => {
|
||||||
const firstLetter = name.charAt(0);
|
const firstLetter = name.charAt(0);
|
||||||
return firstLetter;
|
return firstLetter;
|
||||||
@@ -9,7 +11,7 @@ function Signedby({ pdfDetails }) {
|
|||||||
return (
|
return (
|
||||||
<div className="hidden md:block w-full h-full bg-base-100">
|
<div className="hidden md:block w-full h-full bg-base-100">
|
||||||
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
||||||
Signed By
|
{t("signed-by")}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-[2px] bg-base-100">
|
<div className="mt-[2px] bg-base-100">
|
||||||
<div className="bg-[#93a3db] rounded-xl mx-1 flex flex-row items-center py-[10px]">
|
<div className="bg-[#93a3db] rounded-xl mx-1 flex flex-row items-center py-[10px]">
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import RecipientList from "./RecipientList";
|
import RecipientList from "./RecipientList";
|
||||||
import { Tooltip } from "react-tooltip";
|
import { Tooltip } from "react-tooltip";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function SignerListPlace(props) {
|
function SignerListPlace(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<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">
|
||||||
@@ -18,36 +20,12 @@ function SignerListPlace(props) {
|
|||||||
</a>
|
</a>
|
||||||
<Tooltip id="my-tooltip" className="z-[100]">
|
<Tooltip id="my-tooltip" className="z-[100]">
|
||||||
<div className="max-w-[450px] 2xl:max-w-[500px] 2xl:text-[20px] p-[1px]">
|
<div className="max-w-[450px] 2xl:max-w-[500px] 2xl:text-[20px] p-[1px]">
|
||||||
<p className="font-bold pb-[1px]">
|
<p className="font-bold pb-[1px]">{t("role-help.p1")}</p>
|
||||||
What are template roles?
|
<p>{t("role-help.p2")} </p>
|
||||||
</p>
|
<p className="font-bold">{t("role-help.p3")}</p>
|
||||||
<p>
|
<p>{t("role-help.p4")}</p>
|
||||||
Begin by specifying each role needed for the completion of
|
<p className="font-bold">{t("role-help.p5")}</p>
|
||||||
the document. Think about the parties involved in the
|
<p>{t("role-help.p6")}</p>
|
||||||
signing process and what their responsibilities are.
|
|
||||||
Common roles include HR for internal documents, Customer
|
|
||||||
for agreements or Vendor for business agreements.{" "}
|
|
||||||
</p>
|
|
||||||
<p className="font-bold">
|
|
||||||
Why pre-attach users to some roles?
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
For roles that consistently involve the same individual
|
|
||||||
(e.g., the CEO's signature on employee offer
|
|
||||||
letters), you can pre-attach a user to a role within the
|
|
||||||
template. This step is optional but recommended for
|
|
||||||
efficiency and consistency across documents.
|
|
||||||
</p>
|
|
||||||
<p className="font-bold">
|
|
||||||
When do i specify the user attached to each role?
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
When you create a document from your template, you'll
|
|
||||||
be prompted to attach users to each defined role. If a
|
|
||||||
role already has a user attached, this will be pre-filled,
|
|
||||||
but you can modify it as needed before sending out the
|
|
||||||
document.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>
|
</>
|
||||||
@@ -67,7 +45,7 @@ function SignerListPlace(props) {
|
|||||||
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
|
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
|
||||||
onClick={() => props.handleAddSigner()}
|
onClick={() => props.handleAddSigner()}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-plus"></i> Add role
|
<i className="fa-light fa-plus"></i> {t("add-role")}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -77,7 +55,7 @@ function SignerListPlace(props) {
|
|||||||
disabled={props?.isMailSend ? true : false}
|
disabled={props?.isMailSend ? true : false}
|
||||||
onClick={() => props.setIsAddSigner(true)}
|
onClick={() => props.setIsAddSigner(true)}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-plus"></i> Add recipients
|
<i className="fa-light fa-plus"></i> {t("add-recipients")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function TextFontSetting(props) {
|
function TextFontSetting(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
headerColor={"#dc3545"}
|
headerColor={"#dc3545"}
|
||||||
isOpen={props.isTextSetting}
|
isOpen={props.isTextSetting}
|
||||||
reduceWidth={"max-w-[350px]"}
|
reduceWidth={"max-w-[350px]"}
|
||||||
title={"Text field"}
|
title={t("text-field")}
|
||||||
handleClose={() => props.setIsTextSetting(false)}
|
handleClose={() => props.setIsTextSetting(false)}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px]">
|
<div className="h-full p-[20px]">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span>Font size:</span>
|
<span>{t("font-size")} :</span>
|
||||||
<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={
|
||||||
@@ -32,7 +34,7 @@ function TextFontSetting(props) {
|
|||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
<div className="flex flex-row gap-1 items-center ml-4">
|
<div className="flex flex-row gap-1 items-center ml-4">
|
||||||
<span>color: </span>
|
<span>{t("color")}: </span>
|
||||||
<select
|
<select
|
||||||
value={
|
value={
|
||||||
props.fontColor ||
|
props.fontColor ||
|
||||||
@@ -45,7 +47,7 @@ function TextFontSetting(props) {
|
|||||||
{fontColorArr.map((color, ind) => {
|
{fontColorArr.map((color, ind) => {
|
||||||
return (
|
return (
|
||||||
<option value={color} key={ind}>
|
<option value={color} key={ind}>
|
||||||
{color}
|
{t(`color-type.${color}`)}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -67,7 +69,7 @@ function TextFontSetting(props) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary mt-2"
|
className="op-btn op-btn-primary mt-2"
|
||||||
>
|
>
|
||||||
save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Loader from "../../primitives/Loader";
|
import Loader from "../../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function VerifyEmail(props) {
|
function VerifyEmail(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<dialog className="op-modal op-modal-open absolute z-[1999]">
|
<dialog className="op-modal op-modal-open absolute z-[1999]">
|
||||||
<div className="md:w-[40%] w-[80%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
|
<div className="md:w-[40%] w-[80%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
|
||||||
<h3 className="font-bold text-lg pt-[15px] px-[20px] text-base-content">
|
<h3 className="font-bold text-lg pt-[15px] px-[20px] text-base-content">
|
||||||
OTP verification
|
{t("otp-verification")}
|
||||||
</h3>
|
</h3>
|
||||||
{props.isVerifyModal ? (
|
{props.isVerifyModal ? (
|
||||||
<form
|
<form
|
||||||
@@ -16,26 +18,30 @@ function VerifyEmail(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="px-6 py-3 text-base-content">
|
<div className="px-6 py-3 text-base-content">
|
||||||
<label className="mb-2">Enter OTP</label>
|
<label className="mb-2">{t("enter-otp")}</label>
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
type="tel"
|
type="tel"
|
||||||
pattern="[0-9]{4}"
|
pattern="[0-9]{4}"
|
||||||
className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
|
className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
placeholder="Enter OTP received over email"
|
placeholder={t("otp-placeholder")}
|
||||||
value={props.otp}
|
value={props.otp}
|
||||||
onChange={(e) => props.setOtp(e.target.value)}
|
onChange={(e) => props.setOtp(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-6 my-3">
|
<div className="px-6 my-3">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Verify
|
{t("verify")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-secondary ml-2"
|
className="op-btn op-btn-secondary ml-2"
|
||||||
onClick={(e) => props.handleResend(e)}
|
onClick={(e) => props.handleResend(e)}
|
||||||
>
|
>
|
||||||
Resend
|
{t("resend")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -45,16 +51,14 @@ function VerifyEmail(props) {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="px-6 py-3 text-base-content">
|
<div className="px-6 py-3 text-base-content">
|
||||||
<p className="mb-2 text-sm">Please verify your email !</p>
|
<p className="mb-2 text-sm">{t("verify-email")}</p>
|
||||||
<div className="px-0 mt-3">
|
<div className="px-0 mt-3">
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={() => {
|
onClick={() => props.handleVerifyBtn()}
|
||||||
props.handleVerifyBtn();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Send OTP
|
{t("send-otp")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
textWidget,
|
textWidget,
|
||||||
widgets
|
widgets
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function WidgetComponent({
|
function WidgetComponent({
|
||||||
dragSignature,
|
dragSignature,
|
||||||
signRef,
|
signRef,
|
||||||
@@ -19,9 +20,7 @@ function WidgetComponent({
|
|||||||
addPositionOfSignature,
|
addPositionOfSignature,
|
||||||
signersdata,
|
signersdata,
|
||||||
isSelectListId,
|
isSelectListId,
|
||||||
setSignerObjId,
|
|
||||||
setIsSelectId,
|
setIsSelectId,
|
||||||
setContractName,
|
|
||||||
isSigners,
|
isSigners,
|
||||||
dataTut,
|
dataTut,
|
||||||
isMailSend,
|
isMailSend,
|
||||||
@@ -40,6 +39,7 @@ function WidgetComponent({
|
|||||||
setIsAddSigner,
|
setIsAddSigner,
|
||||||
uniqueId
|
uniqueId
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [isSignersModal, setIsSignersModal] = useState(false);
|
const [isSignersModal, setIsSignersModal] = useState(false);
|
||||||
const [, dropdown] = useDrag({
|
const [, dropdown] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
@@ -330,7 +330,7 @@ function WidgetComponent({
|
|||||||
} hidden md:block h-full bg-base-100`}
|
} hidden md:block h-full bg-base-100`}
|
||||||
>
|
>
|
||||||
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
|
||||||
<span>Fields</span>
|
<span>{t("fields")}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -348,7 +348,7 @@ function WidgetComponent({
|
|||||||
)}
|
)}
|
||||||
{isSignersModal && (
|
{isSignersModal && (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={title ? title : "Recipients"}
|
title={title ? title : t("recipients")}
|
||||||
isOpen={isSignersModal}
|
isOpen={isSignersModal}
|
||||||
handleClose={handleModal}
|
handleClose={handleModal}
|
||||||
>
|
>
|
||||||
@@ -358,9 +358,7 @@ function WidgetComponent({
|
|||||||
signerPos={signerPos}
|
signerPos={signerPos}
|
||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
isSelectListId={isSelectListId}
|
isSelectListId={isSelectListId}
|
||||||
setSignerObjId={setSignerObjId}
|
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
setContractName={setContractName}
|
|
||||||
setUniqueId={setUniqueId}
|
setUniqueId={setUniqueId}
|
||||||
setRoleName={setRoleName}
|
setRoleName={setRoleName}
|
||||||
handleDeleteUser={handleDeleteUser}
|
handleDeleteUser={handleDeleteUser}
|
||||||
@@ -375,7 +373,7 @@ function WidgetComponent({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className=" p-[20px] text-[15px] font-medium text-center">
|
<div className=" p-[20px] text-[15px] font-medium text-center">
|
||||||
Please add a {title ? title : "recipients"}
|
{t("please-add")} {title ? title : t("recipients")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { getWidgetType } from "../../constant/Utils";
|
import { getWidgetType } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function WidgetList(props) {
|
function WidgetList(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return props.updateWidgets.map((item, ind) => {
|
return props.updateWidgets.map((item, ind) => {
|
||||||
return (
|
return (
|
||||||
<div className="2xl:p-3 mb-[5px]" key={ind}>
|
<div className="2xl:p-3 mb-[5px]" key={ind}>
|
||||||
@@ -25,7 +28,7 @@ function WidgetList(props) {
|
|||||||
onMouseDown={() => props?.handleMouseLeave()}
|
onMouseDown={() => props?.handleMouseLeave()}
|
||||||
onTouchStart={props?.handleDivClick}
|
onTouchStart={props?.handleDivClick}
|
||||||
>
|
>
|
||||||
{item.ref && getWidgetType(item)}
|
{item.ref && getWidgetType(item, t(`widgets-name.${item.type}`))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ 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";
|
||||||
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const WidgetNameModal = (props) => {
|
const WidgetNameModal = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [formdata, setFormdata] = useState({
|
const [formdata, setFormdata] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
@@ -104,7 +106,7 @@ const WidgetNameModal = (props) => {
|
|||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={props.isOpen}
|
isOpen={props.isOpen}
|
||||||
handleClose={props.handleClose && props.handleClose}
|
handleClose={props.handleClose && props.handleClose}
|
||||||
title={"Widget info"}
|
title={t("widget-info")}
|
||||||
>
|
>
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
@@ -114,7 +116,7 @@ const WidgetNameModal = (props) => {
|
|||||||
>
|
>
|
||||||
<div className="mb-[0.75rem] text-[13px]">
|
<div className="mb-[0.75rem] text-[13px]">
|
||||||
<label htmlFor="name">
|
<label htmlFor="name">
|
||||||
Name
|
{t("name")}
|
||||||
<span className="text-[red]"> *</span>
|
<span className="text-[red]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -122,6 +124,8 @@ const WidgetNameModal = (props) => {
|
|||||||
name="name"
|
name="name"
|
||||||
value={formdata.name}
|
value={formdata.name}
|
||||||
onChange={(e) => handleChange(e)}
|
onChange={(e) => handleChange(e)}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,7 +142,7 @@ const WidgetNameModal = (props) => {
|
|||||||
: ""
|
: ""
|
||||||
} text-[13px]`}
|
} text-[13px]`}
|
||||||
>
|
>
|
||||||
Validation
|
{t("validation")}
|
||||||
</label>
|
</label>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
url={"https://www.w3schools.com/jsref/jsref_obj_regexp.asp"}
|
url={"https://www.w3schools.com/jsref/jsref_obj_regexp.asp"}
|
||||||
@@ -192,7 +196,7 @@ const WidgetNameModal = (props) => {
|
|||||||
)}
|
)}
|
||||||
<div className="mb-[0.75rem]">
|
<div className="mb-[0.75rem]">
|
||||||
<label htmlFor="name" className="text-[13px]">
|
<label htmlFor="name" className="text-[13px]">
|
||||||
Default value
|
{t("default-value")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
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"
|
||||||
@@ -216,7 +220,7 @@ const WidgetNameModal = (props) => {
|
|||||||
className="fa-light fa-exclamation-circle text-[15px]"
|
className="fa-light fa-exclamation-circle text-[15px]"
|
||||||
style={{ color: "#fab005" }}
|
style={{ color: "#fab005" }}
|
||||||
></i>
|
></i>
|
||||||
invalid default value
|
{t("invalid-default-value")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -238,7 +242,9 @@ const WidgetNameModal = (props) => {
|
|||||||
formdata.status.toLowerCase() === data.toLowerCase()
|
formdata.status.toLowerCase() === data.toLowerCase()
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="text-[13px] font-medium">{data}</div>
|
<div className="text-[13px] font-medium">
|
||||||
|
{t(`widget-status.${data}`)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -247,7 +253,7 @@ const WidgetNameModal = (props) => {
|
|||||||
{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]">
|
||||||
Hint
|
{t("hint")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
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"
|
||||||
@@ -266,7 +272,7 @@ const WidgetNameModal = (props) => {
|
|||||||
"email"
|
"email"
|
||||||
].includes(props.defaultdata?.type) && (
|
].includes(props.defaultdata?.type) && (
|
||||||
<div className="flex items-center mb-[0.75rem]">
|
<div className="flex items-center mb-[0.75rem]">
|
||||||
<span>Font size:</span>
|
<span>{t("font-size")}:</span>
|
||||||
<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={
|
||||||
@@ -283,7 +289,7 @@ const WidgetNameModal = (props) => {
|
|||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
<div className="flex flex-row gap-1 items-center ml-4">
|
<div className="flex flex-row gap-1 items-center ml-4">
|
||||||
<span>color: </span>
|
<span>{t("color")}: </span>
|
||||||
<select
|
<select
|
||||||
value={
|
value={
|
||||||
props.fontColor ||
|
props.fontColor ||
|
||||||
@@ -296,7 +302,7 @@ const WidgetNameModal = (props) => {
|
|||||||
{fontColorArr.map((color, ind) => {
|
{fontColorArr.map((color, ind) => {
|
||||||
return (
|
return (
|
||||||
<option value={color} key={ind}>
|
<option value={color} key={ind}>
|
||||||
{color}
|
{t(`color-type.${color}`)}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -316,7 +322,7 @@ const WidgetNameModal = (props) => {
|
|||||||
|
|
||||||
<div className="h-[1px] w-full mb-[16px] bg-[#b7b3b3]"></div>
|
<div className="h-[1px] w-full mb-[16px] bg-[#b7b3b3]"></div>
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
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";
|
||||||
|
|
||||||
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
||||||
const folderPtr = {
|
const folderPtr = {
|
||||||
@@ -9,6 +10,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
className: folderCls,
|
className: folderCls,
|
||||||
objectId: parentFolderId
|
objectId: parentFolderId
|
||||||
};
|
};
|
||||||
|
const { t } = useTranslation();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [folderList, setFolderList] = useState([]);
|
const [folderList, setFolderList] = useState([]);
|
||||||
const [isAlert, setIsAlert] = useState(false);
|
const [isAlert, setIsAlert] = useState(false);
|
||||||
@@ -60,7 +62,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
const templExist = await exsitQuery.first();
|
const templExist = await exsitQuery.first();
|
||||||
if (templExist) {
|
if (templExist) {
|
||||||
setAlert({ type: "danger", message: "Folder already exist!" });
|
setAlert({ type: "danger", message: t("folder-already-exist") });
|
||||||
setIsAlert(true);
|
setIsAlert(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsAlert(false);
|
setIsAlert(false);
|
||||||
@@ -85,7 +87,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
handleLoader(false);
|
handleLoader(false);
|
||||||
setAlert({
|
setAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
message: "Folder created successfully!"
|
message: t("folder-created-successfully")
|
||||||
});
|
});
|
||||||
setIsAlert(true);
|
setIsAlert(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -98,7 +100,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleLoader(false);
|
handleLoader(false);
|
||||||
setAlert({ type: "info", message: "Please fill folder name" });
|
setAlert({ type: "info", message: t("fill-folder-name") });
|
||||||
setIsAlert(true);
|
setIsAlert(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsAlert(false);
|
setIsAlert(false);
|
||||||
@@ -120,20 +122,25 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h1 className="text-base font-semibold mt-[0.4rem]">Create Folder</h1>
|
<h1 className="text-base font-semibold mt-[0.4rem]">
|
||||||
|
{t("create-folder")}
|
||||||
|
</h1>
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
Name<span className="text-red-500 text-[13px]">*</span>
|
{t("name")}
|
||||||
|
<span className="text-red-500 text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
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"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">Parent Folder</label>
|
<label className="block">{t("parent-folder")}</label>
|
||||||
<select
|
<select
|
||||||
value={selectedParent}
|
value={selectedParent}
|
||||||
onChange={handleOptions}
|
onChange={handleOptions}
|
||||||
@@ -155,7 +162,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
|||||||
className="op-btn op-btn-primary op-btn-sm mt-3"
|
className="op-btn op-btn-primary op-btn-sm mt-3"
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-plus"></i>
|
<i className="fa-light fa-plus"></i>
|
||||||
<span>Create</span>
|
<span>{t("create")}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
|||||||
return (
|
return (
|
||||||
<div onClick={handleChoose}>
|
<div onClick={handleChoose}>
|
||||||
{children || (
|
{children || (
|
||||||
<button className="px-2 py-[2px] text-2xl rounded border-[1px] text-blue-400 border-gray-300 w-full">
|
<button className="cursor-pointer op-input op-input-bordered focus:outline-none hover:border-base-content max-h-[35px] max-w-[45px] flex justify-center items-center">
|
||||||
<i className="fa-brands fa-dropbox"></i>
|
<i className="fa-brands fa-dropbox"></i>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import CreateFolder from "./CreateFolder";
|
import CreateFolder from "./CreateFolder";
|
||||||
import ModalUi from "../../../primitives/ModalUi";
|
import ModalUi from "../../../primitives/ModalUi";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const FolderModal = (props) => {
|
const FolderModal = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [clickFolder, setClickFolder] = useState("");
|
const [clickFolder, setClickFolder] = useState("");
|
||||||
const [folderList, setFolderList] = useState([]);
|
const [folderList, setFolderList] = useState([]);
|
||||||
const [tabList, setTabList] = useState([]);
|
const [tabList, setTabList] = useState([]);
|
||||||
@@ -147,7 +149,7 @@ const FolderModal = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Select Folder"}
|
title={t("select-foler")}
|
||||||
isOpen={props.isOpenModal}
|
isOpen={props.isOpenModal}
|
||||||
handleClose={handleCancel}
|
handleClose={handleCancel}
|
||||||
>
|
>
|
||||||
@@ -158,7 +160,7 @@ const FolderModal = (props) => {
|
|||||||
title="OpenSign™ Drive"
|
title="OpenSign™ Drive"
|
||||||
onClick={(e) => removeTabListItem(e)}
|
onClick={(e) => removeTabListItem(e)}
|
||||||
>
|
>
|
||||||
OpenSign™ Drive /{" "}
|
{t("OpenSign-drive")} /{" "}
|
||||||
</span>
|
</span>
|
||||||
{tabList &&
|
{tabList &&
|
||||||
tabList.map((tab, i) => (
|
tabList.map((tab, i) => (
|
||||||
@@ -214,7 +216,7 @@ const FolderModal = (props) => {
|
|||||||
))
|
))
|
||||||
: !isLoader && (
|
: !isLoader && (
|
||||||
<div className="text-base-content text-center my-2">
|
<div className="text-base-content text-center my-2">
|
||||||
No data found
|
{t("no-data")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -236,27 +238,28 @@ const FolderModal = (props) => {
|
|||||||
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
||||||
<div
|
<div
|
||||||
className="op-btn op-btn-seconday op-btn-sm"
|
className="op-btn op-btn-seconday op-btn-sm"
|
||||||
title="Save Here"
|
title={t("save-here")}
|
||||||
onClick={handleCreate}
|
onClick={handleCreate}
|
||||||
>
|
>
|
||||||
{isAdd ? (
|
{isAdd ? (
|
||||||
<>
|
<>
|
||||||
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
|
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
|
||||||
<span className="text-xs">Back</span>
|
<span className="text-xs">{t("back")}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
|
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
|
||||||
<span className="">Add folder</span>
|
<span className="">{t("add-folder")}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="op-btn op-btn-primary op-btn-sm"
|
className="op-btn op-btn-primary op-btn-sm"
|
||||||
title="Save Here"
|
title={t("save-here")}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
|
<i className="fa-light fa-save" aria-hidden="true"></i>
|
||||||
|
{t("save-here")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import Parse from "parse";
|
|||||||
import CreateFolder from "./CreateFolder";
|
import CreateFolder from "./CreateFolder";
|
||||||
import ModalUi from "../../../primitives/ModalUi";
|
import ModalUi from "../../../primitives/ModalUi";
|
||||||
import Tooltip from "../../../primitives/Tooltip";
|
import Tooltip from "../../../primitives/Tooltip";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [isOpen, SetIsOpen] = useState(false);
|
const [isOpen, SetIsOpen] = useState(false);
|
||||||
const [clickFolder, setClickFolder] = useState("");
|
const [clickFolder, setClickFolder] = useState("");
|
||||||
const [selectFolder, setSelectedFolder] = useState({});
|
const [selectFolder, setSelectedFolder] = useState({});
|
||||||
@@ -169,7 +171,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
<div className="text-xs mt-2 ">
|
<div className="text-xs mt-2 ">
|
||||||
<div>
|
<div>
|
||||||
<label className="block">
|
<label className="block">
|
||||||
Select Folder
|
{t("select-folder")}
|
||||||
{required && <span className="text-red-500 text-[13px]">*</span>}
|
{required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,12 +194,12 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
<p>
|
<p>
|
||||||
{selectFolder && selectFolder.Name
|
{selectFolder && selectFolder.Name
|
||||||
? selectFolder.Name
|
? selectFolder.Name
|
||||||
: "OpenSign™ Drive"}
|
: t("OpenSign-drive")}
|
||||||
</p>
|
</p>
|
||||||
<div className="text-black text-sm">
|
<div className="text-black text-sm">
|
||||||
<i
|
<i
|
||||||
className="fa-light fa-pencil cursor-pointer"
|
className="fa-light fa-pencil cursor-pointer"
|
||||||
title="Select Folder"
|
title={t("select-folder")}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -208,15 +210,11 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute top-2 right-1 cursor-pointer">
|
<div className="absolute top-2 right-1 cursor-pointer">
|
||||||
<Tooltip
|
<Tooltip message={t("select-folder-help")} />
|
||||||
message={
|
|
||||||
"If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder."
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Select Folder"}
|
title={t("select-folder")}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
handleClose={handleCancel}
|
handleClose={handleCancel}
|
||||||
>
|
>
|
||||||
@@ -227,7 +225,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
title="OpenSign™ Drive"
|
title="OpenSign™ Drive"
|
||||||
onClick={(e) => removeTabListItem(e)}
|
onClick={(e) => removeTabListItem(e)}
|
||||||
>
|
>
|
||||||
OpenSign™ Drive /{" "}
|
{t("OpenSign-drive")} /{" "}
|
||||||
</span>
|
</span>
|
||||||
{tabList &&
|
{tabList &&
|
||||||
tabList.map((tab, i) => (
|
tabList.map((tab, i) => (
|
||||||
@@ -283,7 +281,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
))
|
))
|
||||||
: !isLoader && (
|
: !isLoader && (
|
||||||
<div className="text-base-content text-center my-2">
|
<div className="text-base-content text-center my-2">
|
||||||
No data found
|
{t("no-data")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -305,27 +303,28 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
|||||||
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
||||||
<div
|
<div
|
||||||
className="op-btn op-btn-seconday op-btn-sm"
|
className="op-btn op-btn-seconday op-btn-sm"
|
||||||
title="Save Here"
|
title={t("save-here")}
|
||||||
onClick={handleCreate}
|
onClick={handleCreate}
|
||||||
>
|
>
|
||||||
{isAdd ? (
|
{isAdd ? (
|
||||||
<>
|
<>
|
||||||
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
|
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
|
||||||
<span className="text-xs">Back</span>
|
<span className="text-xs">{t("back")}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
|
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
|
||||||
<span className="">Add folder</span>
|
<span className="">{t("add-folder")}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="op-btn op-btn-primary op-btn-sm"
|
className="op-btn op-btn-primary op-btn-sm"
|
||||||
title="Save Here"
|
title={t("save-here")}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
|
<i className="fa-light fa-save" aria-hidden="true"></i>
|
||||||
|
{t("save-here")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import AsyncSelect from "react-select/async";
|
import AsyncSelect from "react-select/async";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const SelectSigners = (props) => {
|
const SelectSigners = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [userList, setUserList] = useState([]);
|
const [userList, setUserList] = useState([]);
|
||||||
const [selected, setSelected] = useState();
|
const [selected, setSelected] = useState();
|
||||||
const [userData, setUserData] = useState({});
|
const [userData, setUserData] = useState({});
|
||||||
@@ -71,13 +73,15 @@ const SelectSigners = (props) => {
|
|||||||
<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]">
|
||||||
<div className="mb-0">
|
<div className="mb-0">
|
||||||
<label className="text-[14px] font-bold">Choose from contacts</label>
|
<label className="text-[14px] font-bold">
|
||||||
|
{t("choose-from-contacts")}
|
||||||
|
</label>
|
||||||
<AsyncSelect
|
<AsyncSelect
|
||||||
cacheOptions
|
cacheOptions
|
||||||
defaultOptions
|
defaultOptions
|
||||||
value={selected}
|
value={selected}
|
||||||
loadingMessage={() => "Loading..."}
|
loadingMessage={() => t("loading")}
|
||||||
noOptionsMessage={() => "Contact not found"}
|
noOptionsMessage={() => t("contact-not-found")}
|
||||||
loadOptions={loadOptions}
|
loadOptions={loadOptions}
|
||||||
onChange={handleOptions}
|
onChange={handleOptions}
|
||||||
unstyled
|
unstyled
|
||||||
@@ -102,11 +106,11 @@ const SelectSigners = (props) => {
|
|||||||
isError ? "text-[red]" : "text-transparent"
|
isError ? "text-[red]" : "text-transparent"
|
||||||
} text-[11px] ml-[6px] my-[2px]`}
|
} text-[11px] ml-[6px] my-[2px]`}
|
||||||
>
|
>
|
||||||
Please select signer
|
{t("select-signer")}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<button className="op-btn op-btn-primary" onClick={() => handleAdd()}>
|
<button className="op-btn op-btn-primary" onClick={() => handleAdd()}>
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Select from "react-select";
|
import AsyncSelect from "react-select/async";
|
||||||
import AddSigner from "../../AddSigner";
|
import AddSigner from "../../AddSigner";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Tooltip from "../../../primitives/Tooltip";
|
import Tooltip from "../../../primitives/Tooltip";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
function arrayMove(array, from, to) {
|
function arrayMove(array, from, to) {
|
||||||
array = array.slice();
|
array = array.slice();
|
||||||
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
||||||
@@ -32,8 +33,8 @@ const AddSignerModal = ({ isOpen, children }) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const SignersInput = (props) => {
|
const SignersInput = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [state, setState] = useState(undefined);
|
const [state, setState] = useState(undefined);
|
||||||
// const [editFormData, setEditFormData] = useState([]);
|
|
||||||
const [selected, setSelected] = useState([]);
|
const [selected, setSelected] = useState([]);
|
||||||
const [isModal, setIsModel] = useState(false);
|
const [isModal, setIsModel] = useState(false);
|
||||||
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
||||||
@@ -44,40 +45,6 @@ const SignersInput = (props) => {
|
|||||||
setSelected(newValue);
|
setSelected(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const GetSelectListData = async () => {
|
|
||||||
try {
|
|
||||||
const currentUser = Parse.User.current();
|
|
||||||
const contactbook = new Parse.Query("contracts_Contactbook");
|
|
||||||
contactbook.equalTo(
|
|
||||||
"CreatedBy",
|
|
||||||
Parse.User.createWithoutData(currentUser.id)
|
|
||||||
);
|
|
||||||
contactbook.notEqualTo("IsDeleted", true);
|
|
||||||
const contactRes = await contactbook.find();
|
|
||||||
if (contactRes) {
|
|
||||||
const res = JSON.parse(JSON.stringify(contactRes));
|
|
||||||
let list = [];
|
|
||||||
|
|
||||||
// let _selected = [];
|
|
||||||
res.forEach((x) => {
|
|
||||||
let obj = {
|
|
||||||
label: x.Name,
|
|
||||||
value: x.objectId,
|
|
||||||
isChecked: true
|
|
||||||
};
|
|
||||||
|
|
||||||
list.push(obj);
|
|
||||||
});
|
|
||||||
setState(list);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("err", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
GetSelectListData();
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.isReset && props.isReset === true) {
|
if (props.isReset && props.isReset === true) {
|
||||||
setSelected([]);
|
setSelected([]);
|
||||||
@@ -116,33 +83,71 @@ const SignersInput = (props) => {
|
|||||||
setSelected([data]);
|
setSelected([data]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const loadOptions = async (inputValue) => {
|
||||||
|
try {
|
||||||
|
const currentUser = Parse.User.current();
|
||||||
|
const contactbook = new Parse.Query("contracts_Contactbook");
|
||||||
|
contactbook.equalTo(
|
||||||
|
"CreatedBy",
|
||||||
|
Parse.User.createWithoutData(currentUser.id)
|
||||||
|
);
|
||||||
|
if (inputValue.length > 1) {
|
||||||
|
contactbook.matches("Name", new RegExp(inputValue, "i"));
|
||||||
|
}
|
||||||
|
contactbook.notEqualTo("IsDeleted", true);
|
||||||
|
const contactRes = await contactbook.find();
|
||||||
|
if (contactRes) {
|
||||||
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
|
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
|
||||||
|
//and filter signers from total signer's list which already present in document's signers list
|
||||||
|
const compareArrays = (res, signerObj) => {
|
||||||
|
return res.filter(
|
||||||
|
(item1) =>
|
||||||
|
!signerObj.find((item2) => item2.objectId === item1.objectId)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//get update signer's List if signersdata is present
|
||||||
|
const updateSignersList =
|
||||||
|
props?.signersData && compareArrays(res, props?.signersData);
|
||||||
|
|
||||||
|
const result = updateSignersList ? updateSignersList : res;
|
||||||
|
setState(result);
|
||||||
|
return await result.map((item) => ({
|
||||||
|
label: item.Name,
|
||||||
|
value: item.objectId,
|
||||||
|
isChecked: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="text-xs mt-2 ">
|
<div className="text-xs mt-2 ">
|
||||||
<label className="block relative">
|
<label className="block relative">
|
||||||
Signers
|
{t("signers")}
|
||||||
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
||||||
<span className="absolute ml-1 text-xs z-30">
|
<span className="absolute ml-1 text-xs z-30">
|
||||||
<Tooltip
|
<Tooltip id={"signer-tooltip"} message={t("signers-help")} />
|
||||||
id={"signer-tooltip"}
|
|
||||||
message={
|
|
||||||
"Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed."
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="flex gap-x-[5px]">
|
<div className="flex gap-x-[5px]">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Select
|
<AsyncSelect
|
||||||
onSortEnd={onSortEnd}
|
onSortEnd={onSortEnd}
|
||||||
distance={4}
|
distance={4}
|
||||||
isMulti
|
isMulti
|
||||||
|
cacheOptions
|
||||||
|
defaultOptions
|
||||||
options={state || []}
|
options={state || []}
|
||||||
value={selected}
|
value={selected}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
closeMenuOnSelect={false}
|
closeMenuOnSelect={false}
|
||||||
required={props.required}
|
required={props.required}
|
||||||
noOptionsMessage={() => "Contact not found"}
|
loadingMessage={() => t("loading")}
|
||||||
|
noOptionsMessage={() => t("contact-not-found")}
|
||||||
|
loadOptions={loadOptions}
|
||||||
unstyled
|
unstyled
|
||||||
classNames={{
|
classNames={{
|
||||||
control: () =>
|
control: () =>
|
||||||
@@ -171,7 +176,7 @@ const SignersInput = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<AddSignerModal isOpen={modalIsOpen}>
|
<AddSignerModal isOpen={modalIsOpen}>
|
||||||
<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]">
|
||||||
Add Signer
|
{t("add-signer")}
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
onClick={handleModalCloseClick}
|
onClick={handleModalCloseClick}
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ const SuggestionInput = (props) => {
|
|||||||
|
|
||||||
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() === "") {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
|
|
||||||
const Menu = ({ item, isOpen, closeSidebar }) => {
|
const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<li key={item.title} role="none" className="my-0.5">
|
<li key={item.title} role="none" className="my-0.5">
|
||||||
<NavLink
|
<NavLink
|
||||||
@@ -20,7 +22,7 @@ const Menu = ({ item, isOpen, closeSidebar }) => {
|
|||||||
role="menuitem"
|
role="menuitem"
|
||||||
>
|
>
|
||||||
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
||||||
<span className="ml-3 lg:ml-4">{item.title}</span>
|
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,54 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
|
|
||||||
const SocialMedia = () => {
|
const SocialMedia = () => {
|
||||||
return (
|
const { t } = useTranslation();
|
||||||
<React.Fragment>
|
|
||||||
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i aria-hidden="true" className="fa-brands fa-github"></i>
|
|
||||||
<span className="fa-sr-only">OpenSign's Github</span>
|
|
||||||
</NavLink>
|
|
||||||
<NavLink to="https://www.linkedin.com/company/opensign%E2%84%A2/" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
|
|
||||||
<span className="fa-sr-only">OpenSign's LinkedIn</span>
|
|
||||||
</NavLink>
|
|
||||||
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
|
|
||||||
<span className="fa-sr-only">OpenSign's Twitter</span>
|
|
||||||
</NavLink>
|
|
||||||
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank" rel="noopener noreferrer">
|
|
||||||
<i aria-hidden="true" className="fa-brands fa-discord"></i>
|
|
||||||
<span className="fa-sr-only">OpenSign's Discord</span>
|
|
||||||
</NavLink>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SocialMedia;
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<NavLink
|
||||||
|
to="https://github.com/opensignlabs/opensign"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<i aria-hidden="true" className="fa-brands fa-github"></i>
|
||||||
|
<span className="fa-sr-only">
|
||||||
|
OpenSign's {t("social-media.github")}
|
||||||
|
</span>
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
to="https://www.linkedin.com/company/opensign%E2%84%A2/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
|
||||||
|
<span className="fa-sr-only">
|
||||||
|
OpenSign's {t("social-media.linked-in")}
|
||||||
|
</span>
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
to="https://www.twitter.com/opensignlabs"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
|
||||||
|
<span className="fa-sr-only">
|
||||||
|
OpenSign's {t("social-media.twitter")}
|
||||||
|
</span>
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
to="https://discord.com/invite/xe9TDuyAyj"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<i aria-hidden="true" className="fa-brands fa-discord"></i>
|
||||||
|
<span className="fa-sr-only">
|
||||||
|
OpenSign's {t("social-media.discord")}
|
||||||
|
</span>
|
||||||
|
</NavLink>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SocialMedia;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
|
|
||||||
const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { title, icon, children } = item;
|
const { title, icon, children } = item;
|
||||||
return (
|
return (
|
||||||
<li role="none" className="my-0.5">
|
<li role="none" className="my-0.5">
|
||||||
@@ -14,7 +16,7 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
|||||||
>
|
>
|
||||||
<i className={`${icon} text-[18px]`}></i>
|
<i className={`${icon} text-[18px]`}></i>
|
||||||
<div className="flex justify-between items-center w-full">
|
<div className="flex justify-between items-center w-full">
|
||||||
<span className="ml-3 lg:ml-4">{title}</span>
|
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
|
||||||
<i
|
<i
|
||||||
className={`${
|
className={`${
|
||||||
submenuOpen[item.title]
|
submenuOpen[item.title]
|
||||||
@@ -48,7 +50,9 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
|||||||
className={`${childItem.icon} text-[18px]`}
|
className={`${childItem.icon} text-[18px]`}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
<span className="ml-3 lg:ml-4">{childItem.title}</span>
|
<span className="ml-3 lg:ml-4">
|
||||||
|
{t(`sidebar.${item.title}-Children.${childItem.title}`)}
|
||||||
|
</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
+819
-471
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,23 @@
|
|||||||
import logo from "../assets/images/logo.png";
|
import logo from "../assets/images/logo.png";
|
||||||
|
import { isEnableSubscription } from "./const";
|
||||||
|
|
||||||
|
export function serverUrl_fn() {
|
||||||
|
let baseUrl;
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
baseUrl = process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/api/app";
|
||||||
|
} else {
|
||||||
|
baseUrl = process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/app";
|
||||||
|
}
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
export const appInfo = {
|
export const appInfo = {
|
||||||
applogo: logo,
|
applogo: logo,
|
||||||
appId: process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID : "opensign",
|
appId: process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID : "opensign",
|
||||||
baseUrl: process.env.REACT_APP_SERVERURL
|
baseUrl: serverUrl_fn(),
|
||||||
? process.env.REACT_APP_SERVERURL
|
|
||||||
: window.location.origin + "/api/app",
|
|
||||||
defaultRole: "contracts_User",
|
defaultRole: "contracts_User",
|
||||||
fbAppId: process.env.REACT_APP_FBAPPID
|
fbAppId: process.env.REACT_APP_FBAPPID
|
||||||
? `${process.env.REACT_APP_FBAPPID}`
|
? `${process.env.REACT_APP_FBAPPID}`
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ export const documentCls = "contracts_Document";
|
|||||||
export const themeColor = "#47a3ad";
|
export const themeColor = "#47a3ad";
|
||||||
export const iconColor = "#686968";
|
export const iconColor = "#686968";
|
||||||
export const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
export const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||||
export const isEnableSubscription = true;
|
export const isEnableSubscription =
|
||||||
// process.env.REACT_APP_ENABLE_SUBSCRIPTION &&
|
process.env.REACT_APP_ENABLE_SUBSCRIPTION &&
|
||||||
// process.env.REACT_APP_ENABLE_SUBSCRIPTION?.toLowerCase() === "true"
|
process.env.REACT_APP_ENABLE_SUBSCRIPTION?.toLowerCase() === "true"
|
||||||
// ? true
|
? true
|
||||||
// : false;
|
: false;
|
||||||
export const isStaging = "http://localhost:3001";
|
export const isStaging =
|
||||||
// window.location.origin === "https://staging-app.opensignlabs.com";
|
window.location.origin === "https://staging-app.opensignlabs.com";
|
||||||
|
export const isPublicStaging =
|
||||||
|
window.location.origin === "https://staging.opensign.me";
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { serverUrl_fn } from "./appinfo";
|
||||||
const parseAppId = process.env.REACT_APP_APPID
|
const parseAppId = process.env.REACT_APP_APPID
|
||||||
? process.env.REACT_APP_APPID
|
? process.env.REACT_APP_APPID
|
||||||
: "opensign";
|
: "opensign";
|
||||||
const serverUrl = process.env.REACT_APP_SERVERURL
|
const serverUrl = serverUrl_fn();
|
||||||
? process.env.REACT_APP_SERVERURL
|
|
||||||
: window.location.origin + "/api/app";
|
|
||||||
|
|
||||||
export const SaveFileSize = async (size, imageUrl, tenantId) => {
|
export const SaveFileSize = async (size, imageUrl, tenantId) => {
|
||||||
//checking server url and save file's size
|
//checking server url and save file's size
|
||||||
const tenantPtr = {
|
const tenantPtr = {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import i18n from "i18next";
|
||||||
|
import { initReactI18next } from "react-i18next";
|
||||||
|
import Backend from "i18next-http-backend";
|
||||||
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
|
|
||||||
|
i18n
|
||||||
|
.use(Backend)
|
||||||
|
.use(LanguageDetector) // Use LanguageDetector directly without creating an instance
|
||||||
|
.use(initReactI18next)
|
||||||
|
.init({
|
||||||
|
backend: {
|
||||||
|
loadPath: "/locales/{{lng}}/{{ns}}.json"
|
||||||
|
},
|
||||||
|
fallbackLng: "en", // Fallback to English if no other language is detected
|
||||||
|
detection: {
|
||||||
|
// Specifies the default language to fall back to if the detected language is not available.
|
||||||
|
order: ["localStorage", "navigator"],
|
||||||
|
// Defines where the detected language should be cached.
|
||||||
|
caches: ["localStorage"]
|
||||||
|
},
|
||||||
|
ns: ["translation"], // default namespace
|
||||||
|
defaultNS: "translation", // default namespace
|
||||||
|
//Enables debug mode, which outputs detailed logs to the console about the translation process.
|
||||||
|
debug: false,
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false // Not needed for react as it escapes by default
|
||||||
|
},
|
||||||
|
whitelist: ["en", "es", "fr"] // List of allowed languages
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
@@ -12,23 +12,35 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hide-scrollbar {
|
.hide-scrollbar {
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
-ms-overflow-style: none;
|
||||||
scrollbar-width: none; /* Firefox */
|
/* IE and Edge */
|
||||||
|
scrollbar-width: none;
|
||||||
|
/* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 766px) {
|
||||||
|
.bBofGr {
|
||||||
|
width: 14px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* below css class replace bootstrap background color with daisy */
|
/* below css class replace bootstrap background color with daisy */
|
||||||
.op-bg-primary {
|
.op-bg-primary {
|
||||||
@apply bg-primary;
|
@apply bg-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-bg-secondary {
|
.op-bg-secondary {
|
||||||
@apply bg-secondary;
|
@apply bg-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-bg-info {
|
.op-bg-info {
|
||||||
@apply bg-info;
|
@apply bg-info;
|
||||||
}
|
}
|
||||||
.op-bg-success{
|
|
||||||
|
.op-bg-success {
|
||||||
@apply bg-success;
|
@apply bg-success;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-bg-warning {
|
.op-bg-warning {
|
||||||
@apply bg-warning;
|
@apply bg-warning;
|
||||||
}
|
}
|
||||||
@@ -37,25 +49,37 @@ body {
|
|||||||
.op-text-primary {
|
.op-text-primary {
|
||||||
@apply text-primary;
|
@apply text-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-text-secondary {
|
.op-text-secondary {
|
||||||
@apply text-secondary;
|
@apply text-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-text-info {
|
.op-text-info {
|
||||||
@apply text-info;
|
@apply text-info;
|
||||||
}
|
}
|
||||||
.op-text-success{
|
|
||||||
|
.op-text-accent {
|
||||||
|
@apply text-accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-text-success {
|
||||||
@apply text-success;
|
@apply text-success;
|
||||||
}
|
}
|
||||||
|
|
||||||
.op-text-warning {
|
.op-text-warning {
|
||||||
@apply text-warning;
|
@apply text-warning;
|
||||||
}
|
}
|
||||||
.op-border-primary{
|
|
||||||
@apply border-primary
|
.op-border-primary {
|
||||||
|
@apply border-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CSS for scrollbar customization */
|
/* CSS for scrollbar customization */
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin; /* For Firefox */
|
scrollbar-width: thin;
|
||||||
scrollbar-color: gray; /* For Firefox */
|
/* For Firefox */
|
||||||
|
scrollbar-color: gray;
|
||||||
|
/* For Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For webkit-based browsers like Chrome, Safari */
|
/* For webkit-based browsers like Chrome, Safari */
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ import {
|
|||||||
import DragElement from "./components/pdf/DragElement";
|
import DragElement from "./components/pdf/DragElement";
|
||||||
import TagManager from "react-gtm-module";
|
import TagManager from "react-gtm-module";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import './polyfills'
|
import "./polyfills";
|
||||||
|
import { serverUrl_fn } from "./constant/appinfo";
|
||||||
|
import "./i18n";
|
||||||
|
|
||||||
const appId = process.env.REACT_APP_APPID
|
const appId = process.env.REACT_APP_APPID
|
||||||
? process.env.REACT_APP_APPID
|
? process.env.REACT_APP_APPID
|
||||||
: "opensign";
|
: "opensign";
|
||||||
const serverUrl = process.env.REACT_APP_SERVERURL
|
const serverUrl = serverUrl_fn();
|
||||||
? process.env.REACT_APP_SERVERURL
|
|
||||||
: window.location.origin + "/api/app";
|
|
||||||
Parse.initialize(appId);
|
Parse.initialize(appId);
|
||||||
Parse.serverURL = serverUrl;
|
Parse.serverURL = serverUrl;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
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 = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
||||||
@@ -10,9 +12,43 @@ export default function reportJson(id) {
|
|||||||
"Owner",
|
"Owner",
|
||||||
"Signers"
|
"Signers"
|
||||||
];
|
];
|
||||||
const contactbook = ["Sr.No", "Title", "Email", "Phone"];
|
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 = ["Sr.No", "Title", "File", "Owner", "Signers"];
|
||||||
|
const templateSubAction = isEnableSubscription
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Embed",
|
||||||
|
hoverLabel: "Embed",
|
||||||
|
btnIcon: "fa-light fa-code",
|
||||||
|
action: "Embed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Copy TemplateId",
|
||||||
|
hoverLabel: "Copy TemplateId",
|
||||||
|
btnIcon: "fa-light fa-copy",
|
||||||
|
action: "CopyTemplateId"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Copy Public URL",
|
||||||
|
hoverLabel: "Copy Public URL",
|
||||||
|
btnIcon: "fa-light fa-copy",
|
||||||
|
action: "CopyPublicURL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: [];
|
||||||
switch (id) {
|
switch (id) {
|
||||||
// draft documents report
|
// draft documents report
|
||||||
case "ByHuevtCFY":
|
case "ByHuevtCFY":
|
||||||
@@ -63,7 +99,7 @@ export default function reportJson(id) {
|
|||||||
case "1MwEuxLEkF":
|
case "1MwEuxLEkF":
|
||||||
return {
|
return {
|
||||||
reportName: "In-progress documents",
|
reportName: "In-progress documents",
|
||||||
heading: head,
|
heading: iphead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnId: "8901",
|
btnId: "8901",
|
||||||
@@ -325,9 +361,7 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-light fa-plus",
|
btnIcon: "fa-light fa-plus",
|
||||||
redirectUrl: "placeHolderSign",
|
redirectUrl: "placeHolderSign",
|
||||||
action: "redirect",
|
action: "redirect",
|
||||||
selector: "reactourSecond",
|
selector: "reactourSecond"
|
||||||
message:
|
|
||||||
"Click the 'Use' button to create a new document from an existing template. "
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
btnId: "1631",
|
btnId: "1631",
|
||||||
@@ -337,9 +371,7 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-light fa-envelope",
|
btnIcon: "fa-light fa-envelope",
|
||||||
redirectUrl: "",
|
redirectUrl: "",
|
||||||
action: "bulksend",
|
action: "bulksend",
|
||||||
selector: "tourbulksend",
|
selector: "tourbulksend"
|
||||||
message:
|
|
||||||
"To quickly create and send multiple documents using an existing template, click the 'Quick Send' button."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
btnId: "2234",
|
btnId: "2234",
|
||||||
@@ -349,8 +381,6 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
|
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
|
||||||
action: "option",
|
action: "option",
|
||||||
selector: "reactourThird",
|
selector: "reactourThird",
|
||||||
message:
|
|
||||||
"This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but won’t affect existing documents.Use the Delete button you can delete template. ",
|
|
||||||
subaction: [
|
subaction: [
|
||||||
{
|
{
|
||||||
btnId: "2434",
|
btnId: "2434",
|
||||||
@@ -360,6 +390,7 @@ export default function reportJson(id) {
|
|||||||
redirectUrl: "template",
|
redirectUrl: "template",
|
||||||
action: "redirect"
|
action: "redirect"
|
||||||
},
|
},
|
||||||
|
...templateSubAction,
|
||||||
{
|
{
|
||||||
btnId: "1834",
|
btnId: "1834",
|
||||||
btnLabel: "Delete",
|
btnLabel: "Delete",
|
||||||
@@ -381,18 +412,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;
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ const dashboardJson = [
|
|||||||
key: "count",
|
key: "count",
|
||||||
Redirect_type: "Report",
|
Redirect_type: "Report",
|
||||||
Redirect_id: "4Hhwbp482K",
|
Redirect_id: "4Hhwbp482K",
|
||||||
tourSection: "tourcard1",
|
tourSection: "tourcard1"
|
||||||
tourMessage:
|
|
||||||
"Clicking on this card will take you to the list of documents awaiting your review."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -38,13 +36,11 @@ const dashboardJson = [
|
|||||||
queryType: "",
|
queryType: "",
|
||||||
class: "contracts_Document",
|
class: "contracts_Document",
|
||||||
query:
|
query:
|
||||||
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true,"#*ne":[]},"Placeholders":{"#*ne":null},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
|
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true,"#*ne":[]},"Placeholders":{"#*ne":null},"SignedUrl":{"#*ne":null},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
|
||||||
key: "count",
|
key: "count",
|
||||||
Redirect_type: "Report",
|
Redirect_type: "Report",
|
||||||
Redirect_id: "1MwEuxLEkF",
|
Redirect_id: "1MwEuxLEkF",
|
||||||
tourSection: "tourcard2",
|
tourSection: "tourcard2"
|
||||||
tourMessage:
|
|
||||||
"Clicking on this card will take you to a list of documents awaiting signature."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53,10 +49,9 @@ const dashboardJson = [
|
|||||||
widget: {
|
widget: {
|
||||||
type: "report",
|
type: "report",
|
||||||
reportId: "5Go51Q7T8r",
|
reportId: "5Go51Q7T8r",
|
||||||
|
label: "Recent signature requests",
|
||||||
data: {
|
data: {
|
||||||
tourSection: "tourreport1",
|
tourSection: "tourreport1"
|
||||||
tourMessage:
|
|
||||||
"This is a list of documents that are waiting for your signature."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -65,10 +60,9 @@ const dashboardJson = [
|
|||||||
widget: {
|
widget: {
|
||||||
type: "report",
|
type: "report",
|
||||||
reportId: "d9k3UfYHBc",
|
reportId: "d9k3UfYHBc",
|
||||||
|
label: "Recently sent for signatures",
|
||||||
data: {
|
data: {
|
||||||
tourSection: "tourreport2",
|
tourSection: "tourreport2"
|
||||||
tourMessage:
|
|
||||||
"This is a list of documents you've sent to other parties for signature."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -77,10 +71,9 @@ const dashboardJson = [
|
|||||||
widget: {
|
widget: {
|
||||||
type: "report",
|
type: "report",
|
||||||
reportId: "kC5mfynCi4",
|
reportId: "kC5mfynCi4",
|
||||||
|
label: "Drafts",
|
||||||
data: {
|
data: {
|
||||||
tourSection: "tourreport3",
|
tourSection: "tourreport3"
|
||||||
tourMessage:
|
|
||||||
"This are documents you have started but have not finalized for sending."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { isStaging } from "../constant/const";
|
|||||||
const plans = [
|
const plans = [
|
||||||
{
|
{
|
||||||
planName: "OPENSIGN™ FREE",
|
planName: "OPENSIGN™ FREE",
|
||||||
|
code: { monthly: "freeplan", yearly: "freeplan" },
|
||||||
img: "free.png",
|
img: "free.png",
|
||||||
currency: "",
|
currency: "",
|
||||||
monthlyPrice: "Free",
|
monthlyPrice: "Free",
|
||||||
@@ -12,7 +13,7 @@ const plans = [
|
|||||||
url: "",
|
url: "",
|
||||||
target: "_blank",
|
target: "_blank",
|
||||||
benefits: [
|
benefits: [
|
||||||
"Unlimited envelopes",
|
"Unlimited digital signatures",
|
||||||
"Sign documents yourself",
|
"Sign documents yourself",
|
||||||
"Request signatures from others",
|
"Request signatures from others",
|
||||||
"14 field types",
|
"14 field types",
|
||||||
@@ -26,15 +27,37 @@ const plans = [
|
|||||||
"Decline document support",
|
"Decline document support",
|
||||||
"Email notifications",
|
"Email notifications",
|
||||||
"Recipient authentication using OTP",
|
"Recipient authentication using OTP",
|
||||||
|
"Public profiles",
|
||||||
|
"And much more"
|
||||||
|
],
|
||||||
|
yearlyBenefits: [
|
||||||
|
"Unlimited digital signatures",
|
||||||
|
"Sign documents yourself",
|
||||||
|
"Request signatures from others",
|
||||||
|
"14 field types",
|
||||||
|
"Automatic e-signatures",
|
||||||
|
"Completion certificates",
|
||||||
|
"Send in order",
|
||||||
|
"Document templates",
|
||||||
|
"Import from Dropbox",
|
||||||
|
"Contact book",
|
||||||
|
"Document expiry support",
|
||||||
|
"Decline document support",
|
||||||
|
"Email notifications",
|
||||||
|
"Recipient authentication using OTP",
|
||||||
|
"Public profiles",
|
||||||
"And much more"
|
"And much more"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
planName: "OPENSIGN™ PROFESSIONAL",
|
planName: "OPENSIGN™ PROFESSIONAL",
|
||||||
|
code: isStaging
|
||||||
|
? { monthly: "pro-weekly", yearly: "pro-yearly" }
|
||||||
|
: { monthly: "professional-monthly", yearly: "professional-yearly" },
|
||||||
img: "professional.png",
|
img: "professional.png",
|
||||||
currency: "$",
|
currency: "$",
|
||||||
monthlyPrice: "29.99",
|
monthlyPrice: "29.99",
|
||||||
yearlyPrice: `10 <sup style="font-size: 17px;">/month/user</sup>`,
|
yearlyPrice: `9.99<sup style="font-size: 17px;">/month</sup>`,
|
||||||
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
|
||||||
@@ -52,10 +75,66 @@ const plans = [
|
|||||||
"Webhooks",
|
"Webhooks",
|
||||||
"Zapier integration",
|
"Zapier integration",
|
||||||
"API Access",
|
"API Access",
|
||||||
"100 API signatures included",
|
"upto 100 API signatures",
|
||||||
"DocumentId removal from signed docs",
|
|
||||||
"Custom email templates",
|
"Custom email templates",
|
||||||
"Auto reminders"
|
"Auto reminders",
|
||||||
|
"Bulk send (upto 100 docs)",
|
||||||
|
"Premium Public profile usernames",
|
||||||
|
"Embedding (coming soon)"
|
||||||
|
],
|
||||||
|
yearlyBenefits: [
|
||||||
|
"Everything in OpenSign™ free",
|
||||||
|
"Field validations",
|
||||||
|
"Regular expression validations",
|
||||||
|
"Organize docs in OpenSign™ Drive",
|
||||||
|
"Webhooks",
|
||||||
|
"Zapier integration",
|
||||||
|
"API Access",
|
||||||
|
"upto 240 API signatures",
|
||||||
|
"Custom email templates",
|
||||||
|
"Auto reminders",
|
||||||
|
"Bulk send (upto 240 docs)",
|
||||||
|
"Premium Public profile usernames",
|
||||||
|
"Embedding (coming soon)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
planName: "OPENSIGN™ TEAMS",
|
||||||
|
code: { monthly: "teams-monthly", yearly: "teams-yearly" },
|
||||||
|
img: "teams.png",
|
||||||
|
currency: "$",
|
||||||
|
monthlyPrice: `39.99<sup style="font-size: 17px;">/user</sup>`,
|
||||||
|
yearlyPrice: `19.99<sup style="font-size: 17px;">/user/month</sup>`,
|
||||||
|
subtitle: "Exclusive Access to advanced features.",
|
||||||
|
btn: { text: "Subscribe", color: "op-btn-accent" },
|
||||||
|
url: isStaging
|
||||||
|
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
||||||
|
yearlyUrl: isStaging
|
||||||
|
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly",
|
||||||
|
target: "_self",
|
||||||
|
benefits: [
|
||||||
|
"Everything in OpenSign™ professional",
|
||||||
|
"upto 100 API signatures",
|
||||||
|
"Teams and Organizations",
|
||||||
|
"Share Templates with teams",
|
||||||
|
"Share Templates with individuals",
|
||||||
|
"DocumentId removal from signed docs",
|
||||||
|
"Bulk send (upto 100 docs)",
|
||||||
|
"Request Payments (coming soon)",
|
||||||
|
"Mobile app (coming soon)"
|
||||||
|
],
|
||||||
|
yearlyBenefits: [
|
||||||
|
"Everything in OpenSign™ professional",
|
||||||
|
"upto 500 API signatures",
|
||||||
|
"Teams and Organizations",
|
||||||
|
"Share Templates with teams",
|
||||||
|
"Share Templates with individuals",
|
||||||
|
"DocumentId removal from signed docs",
|
||||||
|
"Bulk send (upto 500 docs)",
|
||||||
|
"Request Payments (coming soon)",
|
||||||
|
"Mobile app (coming soon)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,36 +154,94 @@ const plans = [
|
|||||||
"Uptime SLA",
|
"Uptime SLA",
|
||||||
"SSO support",
|
"SSO support",
|
||||||
"Priority support"
|
"Priority support"
|
||||||
|
],
|
||||||
|
yearlyBenefits: [
|
||||||
|
"All features",
|
||||||
|
"Custom domain",
|
||||||
|
"Custom branding",
|
||||||
|
"Uptime SLA",
|
||||||
|
"SSO support",
|
||||||
|
"Priority support"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
export const stagingPlan = {
|
|
||||||
planName: "OPENSIGN™ TEAMS",
|
export const validplan = {
|
||||||
img: "teams.png",
|
"team-weekly": true,
|
||||||
currency: "$",
|
"team-yearly": true,
|
||||||
monthlyPrice: "40",
|
"teams-monthly": true,
|
||||||
yearlyPrice: `20 <sup style="font-size: 17px;">/month/user</sup>`,
|
"teams-yearly": true,
|
||||||
subtitle: "Exclusive Access to advanced features.",
|
"enterprise-monthly": true,
|
||||||
btn: { text: "Subscribe", color: "op-btn-accent" },
|
"enterprise-yearly": true
|
||||||
url: isStaging
|
};
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
|
export const paidUrl = (plan) => {
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
|
const teamperiod = {
|
||||||
yearlyUrl: isStaging
|
"team-weekly": "monthly",
|
||||||
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
|
"team-yearly": "yearly",
|
||||||
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
|
"teams-monthly": "monthly",
|
||||||
target: "_self",
|
"teams-yearly": "yearly"
|
||||||
benefits: [
|
};
|
||||||
"Everything in OpenSign™ free, professional",
|
const period = teamperiod[plan] || "";
|
||||||
"Field validations",
|
if (period) {
|
||||||
"Regular expression validations",
|
const extUser =
|
||||||
"Organize docs in OpenSign™ Drive",
|
localStorage.getItem("Extand_Class") &&
|
||||||
"Webhooks",
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
"Zapier integration",
|
const user = {
|
||||||
"API Access",
|
name: extUser?.Name,
|
||||||
"100 API signatures included",
|
email: extUser?.Email,
|
||||||
"DocumentId removal from signed docs",
|
company: extUser?.Company,
|
||||||
"Custom email templates",
|
phone: extUser?.Phone
|
||||||
"Auto reminders"
|
};
|
||||||
]
|
// console.log("userDetails ", userDetails);
|
||||||
|
const fullname = user && user.name ? user.name.split(" ") : "";
|
||||||
|
const firstname = fullname?.[0]
|
||||||
|
? "first_name=" + encodeURIComponent(fullname?.[0])
|
||||||
|
: "";
|
||||||
|
const lastname = fullname?.[1]
|
||||||
|
? "&last_name=" + encodeURIComponent(fullname?.[1])
|
||||||
|
: "";
|
||||||
|
const name = firstname ? firstname + lastname : "";
|
||||||
|
const email =
|
||||||
|
user && user.email ? "&email=" + encodeURIComponent(user.email) : "";
|
||||||
|
const company =
|
||||||
|
user && user.company
|
||||||
|
? "&company_name=" + encodeURIComponent(user.company)
|
||||||
|
: "";
|
||||||
|
const phone =
|
||||||
|
user && user.phone ? "&mobile=" + encodeURIComponent(user.phone) : "";
|
||||||
|
const allowedUsers =
|
||||||
|
localStorage.getItem("allowedUsers") &&
|
||||||
|
localStorage.getItem("allowedUsers") > 0
|
||||||
|
? localStorage.getItem("allowedUsers") - 1
|
||||||
|
: "";
|
||||||
|
const quantity = allowedUsers
|
||||||
|
? `addon_code%5B0%5D=extra-teams-users-${period}&addon_quantity%5B0%5D=${allowedUsers}&`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const details =
|
||||||
|
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
||||||
|
quantity +
|
||||||
|
name +
|
||||||
|
email +
|
||||||
|
company +
|
||||||
|
phone;
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
localStorage.setItem("userDetails", JSON.stringify(user));
|
||||||
|
}
|
||||||
|
const url = {
|
||||||
|
monthly: isStaging
|
||||||
|
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
|
||||||
|
yearly: isStaging
|
||||||
|
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly"
|
||||||
|
};
|
||||||
|
|
||||||
|
const planurl = url[period] + details;
|
||||||
|
return planurl;
|
||||||
|
} else {
|
||||||
|
return "/subscription";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
export default plans;
|
export default plans;
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ import { useCookies } from "react-cookie";
|
|||||||
import { fetchSubscription } from "../constant/Utils";
|
import { fetchSubscription } from "../constant/Utils";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { showHeader } from "../redux/reducers/showHeader";
|
import { showHeader } from "../redux/reducers/showHeader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const HomeLayout = () => {
|
const HomeLayout = () => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -32,6 +34,13 @@ const HomeLayout = () => {
|
|||||||
const [, setCookie] = useCookies(["accesstoken", "main_Domain"]);
|
const [, setCookie] = useCookies(["accesstoken", "main_Domain"]);
|
||||||
|
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const language = localStorage.getItem("i18nextLng");
|
||||||
|
i18n.changeLanguage(language);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!tenantId) {
|
if (!tenantId) {
|
||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
@@ -40,7 +49,7 @@ const HomeLayout = () => {
|
|||||||
try {
|
try {
|
||||||
// Use the session token to validate the user
|
// Use the session token to validate the user
|
||||||
const userQuery = new Parse.Query(Parse.User);
|
const userQuery = new Parse.Query(Parse.User);
|
||||||
const user = await userQuery.get(Parse.User.current().id, {
|
const user = await userQuery.get(Parse?.User?.current()?.id, {
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
});
|
});
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -86,7 +95,9 @@ const HomeLayout = () => {
|
|||||||
domain: updateDomain
|
domain: updateDomain
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const handleNavigation = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
async function checkIsSubscribed() {
|
async function checkIsSubscribed() {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription();
|
||||||
@@ -98,10 +109,10 @@ const HomeLayout = () => {
|
|||||||
setIsUserValid(true);
|
setIsUserValid(true);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handleNavigation(res.plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handleNavigation(res.plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsUserValid(true);
|
setIsUserValid(true);
|
||||||
@@ -150,20 +161,20 @@ const HomeLayout = () => {
|
|||||||
setTourConfigs([
|
setTourConfigs([
|
||||||
{
|
{
|
||||||
selector: '[data-tut="reactourFirst"]',
|
selector: '[data-tut="reactourFirst"]',
|
||||||
content: `You have logged in successfully! Let's take a look.`,
|
content: t("tour-mssg.home-layout-1"),
|
||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: '[data-tut="tourbutton"]',
|
selector: '[data-tut="tourbutton"]',
|
||||||
content: `To upload documents for self-signing or to request others’ signatures, simply select the respective buttons.`,
|
content: t("tour-mssg.home-layout-2"),
|
||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
},
|
},
|
||||||
...resArr,
|
...resArr,
|
||||||
{
|
{
|
||||||
selector: '[data-tut="reactourLast"]',
|
selector: '[data-tut="reactourLast"]',
|
||||||
content: `You are ready to start using OpenSign! If you need support feel free to contact us.`,
|
content: t("tour-mssg.home-layout-3"),
|
||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
}
|
}
|
||||||
@@ -212,27 +223,14 @@ const HomeLayout = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function checkTourStatus() {
|
async function checkTourStatus() {
|
||||||
const currentUser = Parse.User.current();
|
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
||||||
const cloudRes = await Parse.Cloud.run("getUserDetails", {
|
if (cloudRes) {
|
||||||
email: currentUser.get("email")
|
const extUser = JSON.parse(JSON.stringify(cloudRes));
|
||||||
});
|
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
|
||||||
const res = { data: cloudRes.toJSON() };
|
const tourStatus = extUser?.TourStatus || [];
|
||||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
|
||||||
const tourStatus = res.data.TourStatus;
|
|
||||||
// console.log("res ", res.data.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);
|
||||||
}
|
}
|
||||||
@@ -244,9 +242,9 @@ const HomeLayout = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLoginBtn = () => {
|
const handleLoginBtn = async () => {
|
||||||
try {
|
try {
|
||||||
Parse.User.logOut();
|
await Parse?.User?.logOut();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -298,7 +296,7 @@ const HomeLayout = () => {
|
|||||||
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
||||||
<p className="text-xl font-medium">Your session has expired.</p>
|
<p className="text-xl font-medium">Your session has expired.</p>
|
||||||
<button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
|
<button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
|
||||||
Login
|
{t("login")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -2,13 +2,19 @@ import React, { useEffect, useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { NavLink, useNavigate } from "react-router-dom";
|
import { NavLink, useNavigate } from "react-router-dom";
|
||||||
import { getAppLogo, openInNewTab } from "../constant/Utils";
|
import {
|
||||||
|
getAppLogo,
|
||||||
|
openInNewTab,
|
||||||
|
saveLanguageInLocal
|
||||||
|
} 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";
|
||||||
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";
|
||||||
|
|
||||||
const AddAdmin = () => {
|
const AddAdmin = () => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
@@ -39,19 +45,23 @@ 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("Admin already exist.");
|
setErrMsg(t("server-down"));
|
||||||
|
} else if (app?.user === "exist") {
|
||||||
|
setErrMsg(t("admin-exists"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrMsg("Something went wrong.");
|
setErrMsg(t("something-went-wrong-mssg"));
|
||||||
console.log("err in check user exist", err);
|
console.log("err in check user exist", err);
|
||||||
} finally {
|
} finally {
|
||||||
setState((prev) => ({ ...prev, loading: false }));
|
setState((prev) => ({ ...prev, loading: false }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const clearStorage = async () => {
|
const clearStorage = async () => {
|
||||||
if (Parse.User.current()) {
|
try {
|
||||||
await Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
}
|
}
|
||||||
const baseUrl = localStorage.getItem("baseUrl");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const appid = localStorage.getItem("parseAppId");
|
const appid = localStorage.getItem("parseAppId");
|
||||||
@@ -61,6 +71,7 @@ const AddAdmin = () => {
|
|||||||
const userSettings = localStorage.getItem("userSettings");
|
const userSettings = localStorage.getItem("userSettings");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
@@ -124,7 +135,7 @@ const AddAdmin = () => {
|
|||||||
const res = await Parse.Cloud.run("getUserDetails", params);
|
const res = await Parse.Cloud.run("getUserDetails", params);
|
||||||
// console.log("Res ", res);
|
// console.log("Res ", res);
|
||||||
if (res) {
|
if (res) {
|
||||||
alert("User already exists with this username!");
|
alert(t("already-exists-this-username"));
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
} else {
|
} else {
|
||||||
// console.log("state.email ", email);
|
// console.log("state.email ", email);
|
||||||
@@ -132,7 +143,7 @@ const AddAdmin = () => {
|
|||||||
await Parse.User.requestPasswordReset(email).then(
|
await Parse.User.requestPasswordReset(email).then(
|
||||||
async function (res) {
|
async function (res) {
|
||||||
if (res.data === undefined) {
|
if (res.data === undefined) {
|
||||||
alert("Verification mail has been sent to your E-mail!");
|
alert(t("verification-code-sent"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -165,10 +176,7 @@ const AddAdmin = () => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
const extUser = await Parse.Cloud.run("getUserDetails");
|
||||||
const extUser = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
if (!IsDisabled) {
|
if (!IsDisabled) {
|
||||||
@@ -199,27 +207,27 @@ const AddAdmin = () => {
|
|||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "success",
|
alertType: "success",
|
||||||
alertMsg: "Registered user successfully."
|
alertMsg: t("registered-user-successfully")
|
||||||
});
|
});
|
||||||
navigate(`/${menu.pageType}/${menu.pageId}`);
|
navigate(`/${menu.pageType}/${menu.pageId}`);
|
||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "danger",
|
alertType: "danger",
|
||||||
alertMsg: "Role not found."
|
alertMsg: t("role-not-found")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "danger",
|
alertType: "danger",
|
||||||
alertMsg: "You don't have access, please contact the admin."
|
alertMsg: t("do-not-access")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("error in fetch extuser", error);
|
console.log("error in fetch extuser", error);
|
||||||
const msg = error.message || "Something went wrong.";
|
const msg = error.message || t("something-went-wrong-mssg");
|
||||||
setState({ loading: false, alertType: "danger", alertMsg: msg });
|
setState({ loading: false, alertType: "danger", alertMsg: msg });
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => setState({ loading: false, alertMsg: "" }), 2000);
|
setTimeout(() => setState({ loading: false, alertMsg: "" }), 2000);
|
||||||
@@ -249,7 +257,7 @@ const AddAdmin = () => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="h-screen flex justify-center">
|
<div className="h-screen flex justify-center">
|
||||||
<Title title={"Add admin"} />
|
<Title title="Add admin" />
|
||||||
{state.loading ? (
|
{state.loading ? (
|
||||||
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
|
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -265,7 +273,7 @@ const AddAdmin = () => {
|
|||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||||
<h2 className="text-[30px] text-center mt-3 font-medium">
|
<h2 className="text-[30px] text-center mt-3 font-medium">
|
||||||
Opensign Setup
|
{t("opensign-setup")}
|
||||||
</h2>
|
</h2>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="https://discord.com/invite/xe9TDuyAyj"
|
to="https://discord.com/invite/xe9TDuyAyj"
|
||||||
@@ -273,7 +281,7 @@ const AddAdmin = () => {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-center text-sm mt-1 text-[blue] cursor-pointer"
|
className="text-center text-sm mt-1 text-[blue] cursor-pointer"
|
||||||
>
|
>
|
||||||
Join our discord server
|
{t("join-discord")}
|
||||||
<i
|
<i
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="fa-brands fa-discord ml-1"
|
className="fa-brands fa-discord ml-1"
|
||||||
@@ -282,52 +290,76 @@ const AddAdmin = () => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
<div className="px-6 py-3 text-xs">
|
<div className="px-6 py-3 text-xs">
|
||||||
<label className="block ">
|
<label className="block ">
|
||||||
Name <span className="text-[red] text-[13px]">*</span>
|
{t("name")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
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"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Email <span className="text-[red] text-[13px]">*</span>
|
{"email"}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="email"
|
||||||
type="email"
|
type="email"
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
|
onChange={(e) =>
|
||||||
|
setEmail(
|
||||||
|
e.target.value?.toLowerCase()?.replace(/\s/g, "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Phone <span className="text-[red] text-[13px]">*</span>
|
{t("phone")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
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"
|
||||||
value={phone}
|
value={phone}
|
||||||
onChange={(e) => setPhone(e.target.value)}
|
onChange={(e) => setPhone(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Company <span className="text-[red] text-[13px]">*</span>
|
{t("company")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
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"
|
||||||
value={company}
|
value={company}
|
||||||
onChange={(e) => setCompany(e.target.value)}
|
onChange={(e) => setCompany(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Job Title{" "}
|
{t("job-title")}{" "}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -335,11 +367,16 @@ const AddAdmin = () => {
|
|||||||
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"
|
||||||
value={jobTitle}
|
value={jobTitle}
|
||||||
onChange={(e) => setJobTitle(e.target.value)}
|
onChange={(e) => setJobTitle(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Password <span className="text-[red] text-[13px]">*</span>
|
{t("password")}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
@@ -348,6 +385,10 @@ const AddAdmin = () => {
|
|||||||
name="password"
|
name="password"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => handlePasswordChange(e)}
|
onChange={(e) => handlePasswordChange(e)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@@ -368,24 +409,22 @@ const AddAdmin = () => {
|
|||||||
lengthValid ? "text-green-600" : "text-red-600"
|
lengthValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{lengthValid ? "✓" : "✗"} Password should be 8
|
{lengthValid ? "✓" : "✗"} {t("password-length")}
|
||||||
characters long
|
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
caseDigitValid ? "text-green-600" : "text-red-600"
|
caseDigitValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{caseDigitValid ? "✓" : "✗"} Password should contain
|
{caseDigitValid ? "✓" : "✗"} {t("password-case")}
|
||||||
uppercase letter, lowercase letter, digit
|
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
specialCharValid ? "text-green-600" : "text-red-600"
|
specialCharValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{specialCharValid ? "✓" : "✗"} Password should contain
|
{specialCharValid ? "✓" : "✗"}{" "}
|
||||||
special character
|
{t("password-special-char")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -396,13 +435,17 @@ const AddAdmin = () => {
|
|||||||
id="termsandcondition"
|
id="termsandcondition"
|
||||||
checked={isAuthorize}
|
checked={isAuthorize}
|
||||||
onChange={(e) => setIsAuthorize(e.target.checked)}
|
onChange={(e) => setIsAuthorize(e.target.checked)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="text-xs cursor-pointer ml-1 mb-0"
|
className="text-xs cursor-pointer ml-1 mb-0"
|
||||||
htmlFor="termsandcondition"
|
htmlFor="termsandcondition"
|
||||||
>
|
>
|
||||||
I agree to the
|
{t("agreee")}
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className="underline cursor-pointer ml-1"
|
className="underline cursor-pointer ml-1"
|
||||||
@@ -412,7 +455,7 @@ const AddAdmin = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Terms of Service
|
{t("term")}
|
||||||
</span>
|
</span>
|
||||||
<span>.</span>
|
<span>.</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -420,15 +463,15 @@ const AddAdmin = () => {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="op-checkbox op-checkbox-sm"
|
className="op-checkbox op-checkbox-sm"
|
||||||
id="termsandcondition"
|
id="subscribetoopensign"
|
||||||
checked={isSubscribeNews}
|
checked={isSubscribeNews}
|
||||||
onChange={(e) => setIsSubscribeNews(e.target.checked)}
|
onChange={(e) => setIsSubscribeNews(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="text-xs cursor-pointer ml-1 mb-0"
|
className="text-xs cursor-pointer ml-1 mb-0"
|
||||||
htmlFor="termsandcondition"
|
htmlFor="subscribetoopensign"
|
||||||
>
|
>
|
||||||
Subscribe to OpenSign newsletter
|
{t("subscribe-to-opensign")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -438,7 +481,7 @@ const AddAdmin = () => {
|
|||||||
className="op-btn op-btn-primary w-full"
|
className="op-btn op-btn-primary w-full"
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
>
|
>
|
||||||
{state.loading ? "Loading..." : "Next"}
|
{state.loading ? t("loading") : t("next")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import React, { useState } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { Navigate } from "react-router-dom";
|
import { Navigate } from "react-router-dom";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function ChangePassword() {
|
function ChangePassword() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [currentpassword, setCurrentPassword] = useState("");
|
const [currentpassword, setCurrentPassword] = useState("");
|
||||||
const [newpassword, setnewpassword] = useState("");
|
const [newpassword, setnewpassword] = useState("");
|
||||||
const [confirmpassword, setconfirmpassword] = useState("");
|
const [confirmpassword, setconfirmpassword] = useState("");
|
||||||
@@ -27,23 +29,23 @@ function ChangePassword() {
|
|||||||
await Parse.User.become(_user.sessionToken);
|
await Parse.User.become(_user.sessionToken);
|
||||||
localStorage.setItem("accesstoken", _user.sessionToken);
|
localStorage.setItem("accesstoken", _user.sessionToken);
|
||||||
}
|
}
|
||||||
alert("Password updated successfully.");
|
alert(t("password-update-alert-1"));
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("err", error);
|
console.log("err", error);
|
||||||
alert("Something went wrong.");
|
alert(t("something-went-wrong-mssg"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
alert("Your current password is missing or incorrect.");
|
alert(t("password-update-alert-2"));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
alert("Your current password is missing or incorrect.");
|
alert(t("password-update-alert-3"));
|
||||||
console.error("Error while logging in user", error);
|
console.error("Error while logging in user", error);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
alert("Your password and confirmation password do not match.");
|
alert(t("password-update-alert-4"));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("err", error);
|
console.log("err", error);
|
||||||
@@ -56,13 +58,13 @@ function ChangePassword() {
|
|||||||
<div className="w-full bg-base-100 text-base-content shadow rounded-box p-2">
|
<div className="w-full bg-base-100 text-base-content shadow rounded-box p-2">
|
||||||
<Title title="Change Password" />
|
<Title title="Change Password" />
|
||||||
<div className="text-xl font-bold border-b-[1px] border-gray-300">
|
<div className="text-xl font-bold border-b-[1px] border-gray-300">
|
||||||
Change Password
|
{t("change-password")}
|
||||||
</div>
|
</div>
|
||||||
<div className="m-2">
|
<div className="m-2">
|
||||||
<form onSubmit={handleSubmit} className=" flex flex-col gap-y-2">
|
<form onSubmit={handleSubmit} className=" flex flex-col gap-y-2">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="currentpassword" className="block text-xs ml-1">
|
<label htmlFor="currentpassword" className="block text-xs ml-1">
|
||||||
Current Password
|
{t("current-password")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
@@ -70,13 +72,15 @@ function ChangePassword() {
|
|||||||
value={currentpassword}
|
value={currentpassword}
|
||||||
onChange={(e) => setCurrentPassword(e.target.value)}
|
onChange={(e) => setCurrentPassword(e.target.value)}
|
||||||
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
||||||
placeholder="Current Password"
|
placeholder={t("current-password")}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="newpassword" className="text-xs block ml-1">
|
<label htmlFor="newpassword" className="text-xs block ml-1">
|
||||||
New Password
|
{t("new-password")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
@@ -84,13 +88,15 @@ function ChangePassword() {
|
|||||||
value={newpassword}
|
value={newpassword}
|
||||||
onChange={(e) => setnewpassword(e.target.value)}
|
onChange={(e) => setnewpassword(e.target.value)}
|
||||||
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
||||||
placeholder="New Password"
|
placeholder={t("new-password")}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="newpassword" className="text-xs block ml-1">
|
<label htmlFor="newpassword" className="text-xs block ml-1">
|
||||||
Confirm Password
|
{t("confirm-password")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
@@ -98,7 +104,9 @@ function ChangePassword() {
|
|||||||
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
className="op-input op-input-bordered op-input-sm text-xs w-full"
|
||||||
value={confirmpassword}
|
value={confirmpassword}
|
||||||
onChange={(e) => setconfirmpassword(e.target.value)}
|
onChange={(e) => setconfirmpassword(e.target.value)}
|
||||||
placeholder="Confirm Password"
|
placeholder={t("confirm-password")}
|
||||||
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -106,7 +114,7 @@ function ChangePassword() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
className="op-btn op-btn-primary shadow-md mt-2"
|
className="op-btn op-btn-primary shadow-md mt-2"
|
||||||
>
|
>
|
||||||
Change Password
|
{t("change-password")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import { useDispatch } from "react-redux";
|
|||||||
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
||||||
import dashboardJson from "../json/dashboardJson";
|
import dashboardJson from "../json/dashboardJson";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@@ -40,7 +42,7 @@ const Dashboard = () => {
|
|||||||
.map((col) => {
|
.map((col) => {
|
||||||
return {
|
return {
|
||||||
selector: `[data-tut=${col.widget.data.tourSection}]`,
|
selector: `[data-tut=${col.widget.data.tourSection}]`,
|
||||||
content: col.widget.data.tourMessage,
|
content: t(`tour-mssg.${col.widget.label}`),
|
||||||
position: "top"
|
position: "top"
|
||||||
// style: { backgroundColor: "#abd4d2" },
|
// style: { backgroundColor: "#abd4d2" },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const DebugPdf = () => {
|
|||||||
|
|
||||||
const inferPdfType = async (pdf) => {
|
const inferPdfType = async (pdf) => {
|
||||||
try {
|
try {
|
||||||
const firstPage = await pdf.getPage(2);
|
const firstPage = await pdf.getPage(pdf?.numPages > 1 ? 2 : 1);
|
||||||
const scale = 1;
|
const scale = 1;
|
||||||
const { width, height } = firstPage.getViewport({ scale });
|
const { width, height } = firstPage.getViewport({ scale });
|
||||||
setPdfDimension({ width: width, height: height });
|
setPdfDimension({ width: width, height: height });
|
||||||
@@ -215,11 +215,7 @@ const DebugPdf = () => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{copied && (
|
{copied && <Alert type="success">Copied</Alert>}
|
||||||
<Alert type="success">
|
|
||||||
<span className="ml-3">Copied</span>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
<Title title={"Debug Pdf"} />
|
<Title title={"Debug Pdf"} />
|
||||||
{width < 800 ? (
|
{width < 800 ? (
|
||||||
<HandleError handleError={"Debug PDF only availble for PC"} />
|
<HandleError handleError={"Debug PDF only availble for PC"} />
|
||||||
|
|||||||
@@ -9,20 +9,21 @@ import { useDispatch } from "react-redux";
|
|||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { isEnableSubscription } from "../constant/const";
|
||||||
import { getAppLogo } from "../constant/Utils";
|
import { getAppLogo } from "../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function ForgotPassword() {
|
function ForgotPassword() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({ email: "", password: "", hideNav: "" });
|
||||||
email: "",
|
|
||||||
password: "",
|
|
||||||
hideNav: ""
|
|
||||||
});
|
|
||||||
const [sentStatus, setSentStatus] = useState("");
|
const [sentStatus, setSentStatus] = useState("");
|
||||||
const [image, setImage] = useState();
|
const [image, setImage] = useState();
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const { name, value } = event.target;
|
let { name, value } = event.target;
|
||||||
|
if (name === "email") {
|
||||||
|
value = value?.toLowerCase()?.replace(/\s/g, "");
|
||||||
|
}
|
||||||
setState({ ...state, [name]: value });
|
setState({ ...state, [name]: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,6 +61,11 @@ function ForgotPassword() {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
const saveLogo = async () => {
|
const saveLogo = async () => {
|
||||||
|
try {
|
||||||
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err while logging out ", err);
|
||||||
|
}
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const app = await getAppLogo();
|
const app = await getAppLogo();
|
||||||
if (app?.logo) {
|
if (app?.logo) {
|
||||||
@@ -75,12 +81,10 @@ function ForgotPassword() {
|
|||||||
<div>
|
<div>
|
||||||
<Title title="Forgot password page" />
|
<Title title="Forgot password page" />
|
||||||
{sentStatus === "success" && (
|
{sentStatus === "success" && (
|
||||||
<Alert type="success">
|
<Alert type="success">{t("reset-password-alert-1")}</Alert>
|
||||||
Reset password link has been sent to your email id
|
|
||||||
</Alert>
|
|
||||||
)}
|
)}
|
||||||
{sentStatus === "failed" && (
|
{sentStatus === "failed" && (
|
||||||
<Alert type={"danger"}>Please setup email adapter </Alert>
|
<Alert type={"danger"}>{t("reset-password-alert-2")}</Alert>
|
||||||
)}
|
)}
|
||||||
<div className="md:p-10 lg:p-16">
|
<div className="md:p-10 lg:p-16">
|
||||||
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
||||||
@@ -96,19 +100,23 @@ function ForgotPassword() {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<h2 className="text-[30px] mt-6">Welcome Back !</h2>
|
<h2 className="text-[30px] mt-6">{t("welcome")}</h2>
|
||||||
<span className="text-[12px] text-[#878787]">
|
<span className="text-[12px] text-[#878787]">
|
||||||
Reset Your Password
|
{t("reset-password-alert-3")}
|
||||||
</span>
|
</span>
|
||||||
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||||
<div className="px-6 py-4">
|
<div className="px-6 py-4">
|
||||||
<label className="block text-xs">Email</label>
|
<label className="block text-xs">{t("email")}</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
className="op-input op-input-bordered op-input-sm w-full"
|
className="op-input op-input-bordered op-input-sm w-full"
|
||||||
value={state.email}
|
value={state.email}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
@@ -116,13 +124,13 @@ function ForgotPassword() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate("/", { replace: true })}
|
onClick={() => navigate("/", { replace: true })}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
Login
|
{t("login")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+856
-320
File diff suppressed because it is too large
Load Diff
@@ -9,32 +9,55 @@ import Tooltip from "../primitives/Tooltip";
|
|||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import SubscribeCard from "../primitives/SubscribeCard";
|
import SubscribeCard from "../primitives/SubscribeCard";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
const tourSteps = [
|
import { useTranslation } from "react-i18next";
|
||||||
{
|
import Parse from "parse";
|
||||||
selector: '[data-tut="apisubscribe"]',
|
|
||||||
content: "Upgrade now to generate API token"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
function GenerateToken() {
|
function GenerateToken() {
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
const origin = window.location.origin;
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
const { t } = useTranslation();
|
||||||
|
const parseBaseUrl = localStorage.getItem("baseUrl");
|
||||||
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const [apiToken, SetApiToken] = useState("");
|
const [apiToken, SetApiToken] = useState("");
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState({
|
||||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
generateapi: false,
|
||||||
|
buyapis: false,
|
||||||
|
unauthorized: false
|
||||||
|
});
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState({
|
||||||
|
plan: "",
|
||||||
|
isValid: false,
|
||||||
|
adminId: "",
|
||||||
|
adminEmail: ""
|
||||||
|
});
|
||||||
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
|
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
|
||||||
const [isTour, setIsTour] = useState(false);
|
const [isTour, setIsTour] = useState(false);
|
||||||
|
const [amount, setAmount] = useState({
|
||||||
|
quantity: 500,
|
||||||
|
priceperapi: 0.15,
|
||||||
|
allowedcredits: 0,
|
||||||
|
addoncredits: 0,
|
||||||
|
totalcredits: 0,
|
||||||
|
price: (75.0).toFixed(2)
|
||||||
|
});
|
||||||
|
const [isFormLoader, setIsFormLoader] = useState(false);
|
||||||
|
const [apitestToken, setApiTestToken] = useState("");
|
||||||
|
const quantityList = [500, 1000, 5000, 50000];
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchToken();
|
fetchToken();
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
const tourSteps = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="apisubscribe"]',
|
||||||
|
content: t("tour-mssg.generate-token")
|
||||||
|
}
|
||||||
|
];
|
||||||
const fetchToken = async () => {
|
const fetchToken = async () => {
|
||||||
try {
|
try {
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const getIsSubscribe = await checkIsSubscribed();
|
const subscribe = await checkIsSubscribed();
|
||||||
setIsSubscribe(getIsSubscribe);
|
setIsSubscribe(subscribe);
|
||||||
}
|
}
|
||||||
const url = parseBaseUrl + "functions/getapitoken";
|
const url = parseBaseUrl + "functions/getapitoken";
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -44,22 +67,40 @@ function GenerateToken() {
|
|||||||
};
|
};
|
||||||
const res = await axios.post(url, {}, { headers: headers });
|
const res = await axios.post(url, {}, { headers: headers });
|
||||||
if (res) {
|
if (res) {
|
||||||
SetApiToken(res.data?.result?.result);
|
const resCredits = await Parse.Cloud.run("allowedcredits");
|
||||||
|
const allowedcredits = resCredits?.allowedcredits || 0;
|
||||||
|
const addoncredits = resCredits?.addoncredits || 0;
|
||||||
|
const totalcredits = allowedcredits + addoncredits;
|
||||||
|
setAmount((obj) => ({
|
||||||
|
...obj,
|
||||||
|
allowedcredits: allowedcredits,
|
||||||
|
addoncredits: addoncredits,
|
||||||
|
totalcredits: totalcredits
|
||||||
|
}));
|
||||||
|
SetApiToken(res?.data?.result?.result);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const body = { email: Parse?.User?.current()?.getEmail() || "" };
|
||||||
|
const testurl = "https://sandbox.opensignlabs.com/api/gettesttoken";
|
||||||
|
const testRes = await axios.post(testurl, body);
|
||||||
|
setApiTestToken(testRes.data?.token);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in fetch test token", err);
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
SetApiToken();
|
SetApiToken();
|
||||||
setIsLoader(false);
|
|
||||||
console.log("Err", err);
|
console.log("Err", err);
|
||||||
|
} finally {
|
||||||
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!isSubscribe && isEnableSubscription) {
|
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
|
||||||
setIsTour(true);
|
setIsTour(true);
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
setIsModal(false);
|
setIsModal((obj) => ({ ...obj, generateapi: false }));
|
||||||
try {
|
try {
|
||||||
const url = parseBaseUrl + "functions/generateapitoken";
|
const url = parseBaseUrl + "functions/generateapitoken";
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -70,13 +111,13 @@ function GenerateToken() {
|
|||||||
const res = await axios.post(url, {}, { headers: headers });
|
const res = await axios.post(url, {}, { headers: headers });
|
||||||
if (res) {
|
if (res) {
|
||||||
SetApiToken(res.data.result.token);
|
SetApiToken(res.data.result.token);
|
||||||
setIsAlert({ type: "success", msg: "Token generated successfully." });
|
setIsAlert({ type: "success", msg: t("token-generated") });
|
||||||
} else {
|
} else {
|
||||||
console.error("Error while generating Token");
|
console.error("Error while generating Token");
|
||||||
setIsAlert({ type: "danger", msg: "Something went wrong." });
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsAlert({ type: "danger", msg: "Something went wrong." });
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
console.log("while generating Token", error);
|
console.log("while generating Token", error);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
@@ -89,21 +130,115 @@ function GenerateToken() {
|
|||||||
|
|
||||||
const copytoclipboard = (text) => {
|
const copytoclipboard = (text) => {
|
||||||
copytoData(text);
|
copytoData(text);
|
||||||
setIsAlert({ type: "success", msg: "Copied" });
|
setIsAlert({ type: "success", msg: t("copied") });
|
||||||
setTimeout(() => {
|
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
|
||||||
setIsAlert({ type: "success", msg: "" });
|
};
|
||||||
}, 1500); // Reset copied state after 1.5 seconds
|
const handleModal = () => {
|
||||||
|
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
|
||||||
|
setIsTour(true);
|
||||||
|
} else {
|
||||||
|
setIsModal((obj) => ({ ...obj, generateapi: !obj.generateapi }));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const handleModal = () => setIsModal(!isModal);
|
|
||||||
|
|
||||||
|
const handleBuyAPIsModal = () => {
|
||||||
|
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
|
||||||
|
setIsTour(true);
|
||||||
|
} else {
|
||||||
|
const extUser =
|
||||||
|
localStorage.getItem("Extand_Class") &&
|
||||||
|
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
|
if (isSubscribe?.adminId && extUser?.objectId === isSubscribe?.adminId) {
|
||||||
|
setIsModal((obj) => ({ ...obj, buyapis: !obj.buyapis }));
|
||||||
|
} else {
|
||||||
|
setIsSubscribe((obj) => ({
|
||||||
|
...obj,
|
||||||
|
adminEmail: extUser?.TenantId?.EmailAddress
|
||||||
|
}));
|
||||||
|
setIsModal((obj) => ({ ...obj, unauthorized: !obj.unauthorized }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setIsModal({ generateapi: false, buyapis: false, unauthorized: false });
|
||||||
|
};
|
||||||
|
const handlePricePerAPIs = (e) => {
|
||||||
|
const quantity = e.target?.value;
|
||||||
|
const price =
|
||||||
|
quantity > 0
|
||||||
|
? (Math.round(quantity * amount.priceperapi * 100) / 100).toFixed(2)
|
||||||
|
: (Math.round(500 * amount.priceperapi * 100) / 100).toFixed(2);
|
||||||
|
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
|
||||||
|
};
|
||||||
|
const handleAddOnApiSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsFormLoader(true);
|
||||||
|
try {
|
||||||
|
const resAddon = await Parse.Cloud.run("buycredits", {
|
||||||
|
credits: amount.quantity
|
||||||
|
});
|
||||||
|
if (resAddon) {
|
||||||
|
const _resAddon = JSON.parse(JSON.stringify(resAddon));
|
||||||
|
if (_resAddon.status === "success") {
|
||||||
|
setAmount((obj) => ({
|
||||||
|
...obj,
|
||||||
|
quantity: 500,
|
||||||
|
priceperapi: 0.15,
|
||||||
|
price: (75.0).toFixed(2),
|
||||||
|
totalcredits: obj?.totalcredits + _resAddon.addon,
|
||||||
|
addoncredits: obj?.addoncredits + _resAddon.addon
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setIsModal((obj) => ({ ...obj, buyapis: false }));
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in buy addon", err);
|
||||||
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
|
} finally {
|
||||||
|
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 2000);
|
||||||
|
setIsFormLoader(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGenerateTestToken = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsLoader(true);
|
||||||
|
// setIsModal((obj) => ({ ...obj, generateapi: false }));
|
||||||
|
try {
|
||||||
|
const url = "https://sandbox.opensignlabs.com/api/generatetesttoken";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
token: apitestToken || "1"
|
||||||
|
};
|
||||||
|
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
|
const body = {
|
||||||
|
name: extUser?.Name,
|
||||||
|
email: extUser?.Email,
|
||||||
|
phone: extUser?.Phone,
|
||||||
|
company: extUser?.Company,
|
||||||
|
jobTitle: extUser?.JobTitle
|
||||||
|
};
|
||||||
|
const res = await axios.post(url, body, { headers: headers });
|
||||||
|
if (res) {
|
||||||
|
setApiTestToken(res.data?.token);
|
||||||
|
setIsAlert({ type: "success", msg: t("token-generated") });
|
||||||
|
} else {
|
||||||
|
console.error("Error while generating Token");
|
||||||
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
|
console.log("while generating Token", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoader(false);
|
||||||
|
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Title title={"API Token"} />
|
<Title title={"API Token"} />
|
||||||
{isAlert.msg && (
|
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
|
||||||
<Alert type={isAlert.type}>
|
|
||||||
<div className="ml-3">{isAlert.msg}</div>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
{isLoader ? (
|
{isLoader ? (
|
||||||
<div className="flex justify-center items-center h-screen">
|
<div className="flex justify-center items-center h-screen">
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -112,31 +247,68 @@ function GenerateToken() {
|
|||||||
<>
|
<>
|
||||||
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
|
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
|
||||||
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
OpenSign™ API{" "}
|
OpenSign™ {t("API")}{" "}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
url={
|
url="https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
|
||||||
}
|
|
||||||
isSubscribe={true}
|
isSubscribe={true}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
<ul className="w-full flex flex-col p-2 text-sm">
|
<ul className="w-full flex flex-col p-2 text-sm">
|
||||||
|
<li className="flex flex-col md:flex-row justify-between items-center border-t-[1px] border-gray-300 break-all py-2">
|
||||||
|
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
|
||||||
|
<span className="ml-1">
|
||||||
|
<span className="font-medium">API Test Token : </span>
|
||||||
|
<span className="text-xs">
|
||||||
|
<Tooltip message={t("help-test-token")} />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span id="token" className="md:text-end py-2 md:py-0">
|
||||||
|
<span
|
||||||
|
className="cursor-pointer"
|
||||||
|
onClick={() => copytoclipboard(apitestToken)}
|
||||||
|
>
|
||||||
|
{apitestToken ? apitestToken : "_____"}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
|
||||||
|
onClick={() => copytoclipboard(apitestToken)}
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy"></i>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleGenerateTestToken}
|
||||||
|
className="op-btn op-btn-primary w-[210px] md:w-auto"
|
||||||
|
>
|
||||||
|
{apitestToken
|
||||||
|
? t("regenerate-test-token")
|
||||||
|
: t("generate-test-token")}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
|
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
|
||||||
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
|
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
|
||||||
<span className="ml-1">API Token:</span>{" "}
|
<span className="ml-1">
|
||||||
|
<span className="font-medium">{t("api-token")} : </span>
|
||||||
|
<span className="text-xs">
|
||||||
|
<Tooltip message={t("help-api-token", { origin })} />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
<span
|
<span
|
||||||
id="token"
|
id="token"
|
||||||
className={`${
|
className={`${
|
||||||
isSubscribe
|
isSubscribe?.plan === "freeplan"
|
||||||
? ""
|
? "bg-white/20 pointer-events-none select-none"
|
||||||
: "bg-white/20 pointer-events-none select-none"
|
: ""
|
||||||
} md:text-end py-2 md:py-0`}
|
} md:text-end py-2 md:py-0`}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={() => copytoclipboard(apiToken)}
|
onClick={() => copytoclipboard(apiToken)}
|
||||||
>
|
>
|
||||||
{apiToken ? apiToken : "_____"}
|
{isSubscribe?.plan !== "freeplan" && apiToken
|
||||||
|
? apiToken
|
||||||
|
: "_____"}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
|
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
|
||||||
@@ -148,13 +320,30 @@ function GenerateToken() {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={apiToken ? handleModal : handleSubmit}
|
onClick={apiToken ? handleModal : handleSubmit}
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary w-[210px] md:w-auto"
|
||||||
>
|
>
|
||||||
{apiToken ? "Regenerate Token" : "Generate Token"}
|
{apiToken ? t("regenerate-token") : t("generate-token")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<div className="text-xs md:text-[15px] my-3 w-full md:w-[70%] flex-col md:flex-row flex items-center gap-x-5">
|
||||||
|
<span className="font-medium">
|
||||||
|
{t("remaining-credits")}{" "}
|
||||||
|
<span className="text-xs">
|
||||||
|
<Tooltip
|
||||||
|
message={t("remaining-credits-help", {
|
||||||
|
allowedcredits: amount?.allowedcredits || 0,
|
||||||
|
addoncredits: amount?.addoncredits || 0
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span className="md:text-end py-2 md:py-0">
|
||||||
|
{amount.totalcredits}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex flex-col md:flex-row items-center justify-center gap-0 md:gap-1">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -162,20 +351,26 @@ function GenerateToken() {
|
|||||||
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="op-btn op-btn-secondary mt-2 mb-3 px-8"
|
className="op-btn op-btn-secondary mt-2 md:mb-3 px-8 w-[210px] md:w-auto"
|
||||||
>
|
>
|
||||||
View Docs
|
{t("view-docs")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleBuyAPIsModal()}
|
||||||
|
className="op-btn op-btn-accent mt-2 mb-3 px-8 w-[210px] md:w-auto"
|
||||||
|
>
|
||||||
|
{t("buy-credits")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isModal}
|
isOpen={isModal.generateapi}
|
||||||
title={apiToken ? "Regenerate Token" : "Generate Token"}
|
title={apiToken ? t("regenerate-token") : t("generate-token")}
|
||||||
handleClose={handleModal}
|
handleClose={handleModal}
|
||||||
>
|
>
|
||||||
<div className="m-[20px]">
|
<div className="m-[20px]">
|
||||||
<div className="text-lg font-normal text-base-content">
|
<div className="text-lg font-normal text-base-content">
|
||||||
Are you sure you want to regenerate token it will expire old
|
{t("generate-token-alert")}
|
||||||
token?
|
|
||||||
</div>
|
</div>
|
||||||
<hr className="bg-[#ccc] mt-4" />
|
<hr className="bg-[#ccc] mt-4" />
|
||||||
<div className="flex items-center mt-3 gap-2 text-white">
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
@@ -183,19 +378,79 @@ function GenerateToken() {
|
|||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
className="op-btn op-btn-primary ml-[2px]"
|
className="op-btn op-btn-primary ml-[2px]"
|
||||||
>
|
>
|
||||||
Yes
|
{t("yes")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleModal}
|
onClick={handleModal}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
No
|
{t("no")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
{/* buy APIs */}
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isModal.buyapis}
|
||||||
|
title={"Buy Credits"}
|
||||||
|
handleClose={handleCloseModal}
|
||||||
|
>
|
||||||
|
{isFormLoader && (
|
||||||
|
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<form onSubmit={handleAddOnApiSubmit} className="p-3">
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label
|
||||||
|
htmlFor="quantity"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("quantity-of-credits")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
value={amount.quantity}
|
||||||
|
onChange={(e) => handlePricePerAPIs(e)}
|
||||||
|
name="quantity"
|
||||||
|
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
{quantityList.length > 0 &&
|
||||||
|
quantityList.map((x) => (
|
||||||
|
<option key={x} value={x}>
|
||||||
|
{x}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex justify-between">
|
||||||
|
<label className="block text-xs text-gray-700 font-semibold">
|
||||||
|
{t("Price")} (1 * {amount.priceperapi})
|
||||||
|
</label>
|
||||||
|
<div className="w-1/4 flex justify-center items-center text-sm">
|
||||||
|
USD {amount.price}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr className="text-base-content mb-3" />
|
||||||
|
<button className="op-btn op-btn-primary w-full mt-2">
|
||||||
|
{t("Proceed")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</ModalUi>
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isModal.unauthorized}
|
||||||
|
title={"Unauthorized"}
|
||||||
|
handleClose={handleCloseModal}
|
||||||
|
>
|
||||||
|
<div className="m-8 flex justify-center text-center items-center font-medium break-all">
|
||||||
|
{t("unauthorized-modal", {
|
||||||
|
adminEmail: isSubscribe?.adminEmail
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
{!isSubscribe && isEnableSubscription && (
|
{isEnableSubscription && isSubscribe?.plan === "freeplan" && (
|
||||||
<div data-tut="apisubscribe">
|
<div data-tut="apisubscribe">
|
||||||
<SubscribeCard />
|
<SubscribeCard />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,13 +2,20 @@ 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 { isEnableSubscription } from "../constant/const";
|
||||||
import { contractUsers, getAppLogo } from "../constant/Utils";
|
import {
|
||||||
|
contractUsers,
|
||||||
|
getAppLogo,
|
||||||
|
saveLanguageInLocal
|
||||||
|
} from "../constant/Utils";
|
||||||
import logo from "../assets/images/logo.png";
|
import logo from "../assets/images/logo.png";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||||
|
|
||||||
function GuestLogin() {
|
function GuestLogin() {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const { id, userMail, contactBookId, base64url } = useParams();
|
const { id, userMail, contactBookId, base64url } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [email, setEmail] = useState(userMail);
|
const [email, setEmail] = useState(userMail);
|
||||||
@@ -21,6 +28,28 @@ function GuestLogin() {
|
|||||||
const [contactId, setContactId] = useState(contactBookId);
|
const [contactId, setContactId] = useState(contactBookId);
|
||||||
const [sendmail, setSendmail] = useState();
|
const [sendmail, setSendmail] = useState();
|
||||||
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
|
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
|
||||||
|
const navigateToDoc = async (docId, contactId) => {
|
||||||
|
try {
|
||||||
|
const docDetails = await Parse.Cloud.run("getDocument", {
|
||||||
|
docId: docId
|
||||||
|
});
|
||||||
|
if (!docDetails.error) {
|
||||||
|
if (sendmail === "false") {
|
||||||
|
navigate(
|
||||||
|
`/load/recipientSignPdf/${docId}/${contactId}?sendmail=${sendmail}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/load/recipientSignPdf/${docId}/${contactId}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err while getting doc", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleServerUrl();
|
handleServerUrl();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@@ -40,6 +69,7 @@ function GuestLogin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
const parseId = appInfo.appId;
|
const parseId = appInfo.appId;
|
||||||
const newServer = `${appInfo.baseUrl}/`;
|
const newServer = `${appInfo.baseUrl}/`;
|
||||||
localStorage.setItem("baseUrl", newServer);
|
localStorage.setItem("baseUrl", newServer);
|
||||||
@@ -62,13 +92,14 @@ function GuestLogin() {
|
|||||||
"linkcontacttodoc",
|
"linkcontacttodoc",
|
||||||
params
|
params
|
||||||
);
|
);
|
||||||
// console.log("linkContactRes ", linkContactRes);
|
|
||||||
setContactId(linkContactRes?.contactId);
|
setContactId(linkContactRes?.contactId);
|
||||||
|
await navigateToDoc(checkSplit[0], linkContactRes?.contactId);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Err in link ext contact", err);
|
console.log("Err in link ext contact", err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setContactId(checkSplit[2]);
|
setContactId(checkSplit[2]);
|
||||||
|
await navigateToDoc(checkSplit[0], checkSplit[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +118,7 @@ function GuestLogin() {
|
|||||||
setEnterOtp(true);
|
setEnterOtp(true);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert("something went wrong!");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,32 +137,29 @@ function GuestLogin() {
|
|||||||
if (OTP) {
|
if (OTP) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
let url = `${serverUrl}functions/AuthLoginAsMail/`;
|
let url = `${serverUrl}functions/AuthLoginAsMail`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseId
|
"X-Parse-Application-Id": parseId
|
||||||
};
|
};
|
||||||
let body = {
|
let body = { email: email, otp: OTP };
|
||||||
email: email,
|
|
||||||
otp: OTP
|
|
||||||
};
|
|
||||||
let user = await axios.post(url, body, { headers: headers });
|
let user = await axios.post(url, body, { headers: headers });
|
||||||
if (user.data.result === "Invalid Otp") {
|
if (user.data.result === "Invalid Otp") {
|
||||||
alert("Invalid Otp");
|
alert(t("invalid-otp"));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} else if (user.data.result === "user not found!") {
|
} else if (user.data.result === "user not found!") {
|
||||||
alert("User not found!");
|
alert(t("user-not-found"));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} else {
|
} else {
|
||||||
let _user = user.data.result;
|
let _user = user.data.result;
|
||||||
|
await Parse.User.become(_user.sessionToken);
|
||||||
const parseId = localStorage.getItem("parseAppId");
|
const parseId = localStorage.getItem("parseAppId");
|
||||||
const contractUserDetails = await contractUsers(_user.email);
|
const contractUserDetails = await contractUsers();
|
||||||
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
localStorage.setItem("UserInformation", JSON.stringify(_user));
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
`Parse/${parseId}/currentUser`,
|
`Parse/${parseId}/currentUser`,
|
||||||
JSON.stringify(_user)
|
JSON.stringify(_user)
|
||||||
);
|
);
|
||||||
// console.log("contractUserDetails ", contractUserDetails);
|
|
||||||
if (contractUserDetails && contractUserDetails.length > 0) {
|
if (contractUserDetails && contractUserDetails.length > 0) {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"Extand_Class",
|
"Extand_Class",
|
||||||
@@ -156,7 +184,7 @@ function GuestLogin() {
|
|||||||
console.log("err ", error);
|
console.log("err ", error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please Enter OTP!");
|
alert(t("enter-otp-alert"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleUserData = async (e) => {
|
const handleUserData = async (e) => {
|
||||||
@@ -165,13 +193,18 @@ function GuestLogin() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
|
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
|
||||||
// console.log("linkContactRes ", linkContactRes);
|
|
||||||
setContactId(linkContactRes.contactId);
|
setContactId(linkContactRes.contactId);
|
||||||
setEnterOtp(true);
|
const IsEnableOTP = await navigateToDoc(
|
||||||
await SendOtp();
|
documentId,
|
||||||
|
linkContactRes.contactId
|
||||||
|
);
|
||||||
|
if (!IsEnableOTP) {
|
||||||
|
setEnterOtp(true);
|
||||||
|
await SendOtp();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
alert("something went wron, please try agian later.");
|
alert(t("something-went-wrong-mssg"));
|
||||||
console.log("Err in link ext contact", err);
|
console.log("Err in link ext contact", err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -179,153 +212,160 @@ function GuestLogin() {
|
|||||||
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="p-[2rem]">
|
<div className="p-14">
|
||||||
{isLoading ? (
|
<div>
|
||||||
<div className="flex flex-col justify-center items-center h-[100vh]">
|
{isLoading ? (
|
||||||
<Loader />
|
<div className="flex flex-col justify-center items-center h-[100vh]">
|
||||||
<span className="text-[13px] text-[gray]">{isLoading.message}</span>
|
<Loader />
|
||||||
</div>
|
<span className="text-[13px] text-[gray]">{isLoading.message}</span>
|
||||||
) : (
|
|
||||||
<div className="m-1 md:m-2 p-[30px] text-base-content bg-base-100 op-card shadow-md">
|
|
||||||
<div className="md:w-[250px] md:h-[66px] inline-block overflow-hidden mt-2 mb-11">
|
|
||||||
{appLogo && (
|
|
||||||
<img src={appLogo} className="object-contain" alt="logo" />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{contactId ? (
|
) : (
|
||||||
<>
|
<div className="m-1 md:m-2 p-[30px] text-base-content bg-base-100 op-card shadow-md">
|
||||||
{!EnterOTP ? (
|
<div className="md:w-[250px] md:h-[66px] inline-block overflow-hidden mt-2 mb-11">
|
||||||
<div className="w-full md:w-[50%] text-base-content">
|
{appLogo && (
|
||||||
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
|
<img src={appLogo} className="object-contain" alt="logo" />
|
||||||
<legend className="text-[12px] text-[#878787] mt-2 mb-1">
|
)}
|
||||||
Verification code is sent to your email
|
</div>
|
||||||
</legend>
|
{contactId ? (
|
||||||
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
|
<>
|
||||||
|
{!EnterOTP ? (
|
||||||
|
<div className="w-full md:w-[50%] text-base-content">
|
||||||
|
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
|
||||||
|
<legend className="text-[12px] text-[#878787] mt-2 mb-1">
|
||||||
|
{t("get-otp-alert")}
|
||||||
|
</legend>
|
||||||
|
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
value={email}
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full disabled:text-[#5c5c5c] text-xs"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-3">
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
onClick={(e) => handleSendOTPBtn(e)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? t("loading") : t("get-verification-code")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<form
|
||||||
|
className="w-full md:w-[50%] text-base-content"
|
||||||
|
onSubmit={VerifyOTP}
|
||||||
|
>
|
||||||
|
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
|
||||||
|
<legend className="text-[12px] text-[#878787] mt-2">
|
||||||
|
{t("guest-email-alert")}
|
||||||
|
</legend>
|
||||||
|
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
|
||||||
|
<p className="text-sm">{t("enter-verification-code")}</p>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="mt-2 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
name="OTP"
|
||||||
|
value={OTP}
|
||||||
|
onChange={(e) => setOTP(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-2.5">
|
||||||
|
<button
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? t("loading") : t("verify")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="w-full md:w-[50%] text-base-content">
|
||||||
|
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
|
||||||
|
<legend className="text-[12px] text-[#878787] mt-2">
|
||||||
|
{t("provide-your-details")}
|
||||||
|
</legend>
|
||||||
|
<form
|
||||||
|
className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"
|
||||||
|
onSubmit={handleUserData}
|
||||||
|
>
|
||||||
|
<div className="mb-2">
|
||||||
|
<label
|
||||||
|
htmlFor="name"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("name")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
value={contact.name}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
disabled={loading}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<label
|
||||||
|
htmlFor="email"
|
||||||
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
|
>
|
||||||
|
{t("email")}
|
||||||
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
name="mobile"
|
name="email"
|
||||||
value={email}
|
value={contact.email}
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full disabled:text-[#5c5c5c] text-xs"
|
onChange={handleInputChange}
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
required
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3">
|
<div className="mt-2.5">
|
||||||
<button
|
<label
|
||||||
className="op-btn op-btn-primary"
|
htmlFor="phone"
|
||||||
onClick={(e) => handleSendOTPBtn(e)}
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
disabled={loading}
|
|
||||||
>
|
>
|
||||||
{loading ? "Loading..." : "Get verification code"}
|
{t("phone")}
|
||||||
</button>
|
</label>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<form
|
|
||||||
className="w-full md:w-[50%] text-base-content"
|
|
||||||
onSubmit={VerifyOTP}
|
|
||||||
>
|
|
||||||
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
|
|
||||||
<legend className="text-[12px] text-[#878787] mt-2">
|
|
||||||
You will get a verification code via Email
|
|
||||||
</legend>
|
|
||||||
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
|
|
||||||
<p className="text-sm">Enter Verification Code</p>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="text"
|
||||||
className="mt-2 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
name="phone"
|
||||||
name="OTP"
|
value={contact.phone}
|
||||||
value={OTP}
|
onChange={handleInputChange}
|
||||||
onChange={(e) => setOTP(e.target.value)}
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
disabled={loading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2.5">
|
<div className="mt-2 flex justify-start">
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary"
|
|
||||||
type="submit"
|
type="submit"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>
|
>
|
||||||
{loading ? "Loading..." : "Verify"}
|
{loading ? t("loading") : t("next")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)}
|
</div>
|
||||||
</>
|
)}
|
||||||
) : (
|
</div>
|
||||||
<div className="w-full md:w-[50%] text-base-content">
|
)}
|
||||||
<h1 className="text-2xl md:text-[30px]">Welcome</h1>
|
</div>
|
||||||
<legend className="text-[12px] text-[#878787] mt-2">
|
<SelectLanguage />
|
||||||
Provide your details
|
|
||||||
</legend>
|
|
||||||
<form
|
|
||||||
className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"
|
|
||||||
onSubmit={handleUserData}
|
|
||||||
>
|
|
||||||
<div className="mb-2">
|
|
||||||
<label
|
|
||||||
htmlFor="name"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Name
|
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
value={contact.name}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
|
||||||
disabled={loading}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-2">
|
|
||||||
<label
|
|
||||||
htmlFor="email"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Email
|
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
name="email"
|
|
||||||
value={contact.email}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
|
||||||
required
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mt-2.5">
|
|
||||||
<label
|
|
||||||
htmlFor="phone"
|
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
|
||||||
>
|
|
||||||
Phone
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="phone"
|
|
||||||
value={contact.phone}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
|
||||||
disabled={loading}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mt-2 flex justify-start">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="op-btn op-btn-primary"
|
|
||||||
disabled={loading}
|
|
||||||
>
|
|
||||||
{loading ? "Loading..." : "Next"}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,18 @@ 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";
|
||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
|
import {
|
||||||
|
fetchSubscription,
|
||||||
|
getAppLogo,
|
||||||
|
openInNewTab,
|
||||||
|
saveLanguageInLocal
|
||||||
|
} from "../constant/Utils";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||||
|
|
||||||
function Login() {
|
function Login() {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -42,20 +51,18 @@ 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(() => {
|
||||||
if (localStorage.getItem("accesstoken")) {
|
checkUserExt();
|
||||||
setState({ ...state, loading: true });
|
|
||||||
GetLoginData();
|
|
||||||
}
|
|
||||||
dispatch(fetchAppInfo());
|
|
||||||
saveLogo();
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const saveLogo = 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) {
|
||||||
@@ -63,12 +70,22 @@ function Login() {
|
|||||||
} else {
|
} else {
|
||||||
setImage(appInfo?.applogo || undefined);
|
setImage(appInfo?.applogo || undefined);
|
||||||
}
|
}
|
||||||
|
if (localStorage.getItem("accesstoken")) {
|
||||||
|
setState({ ...state, loading: true });
|
||||||
|
GetLoginData();
|
||||||
|
}
|
||||||
|
dispatch(fetchAppInfo());
|
||||||
};
|
};
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const { name, value } = event.target;
|
let { name, value } = event.target;
|
||||||
|
if (name === "email") {
|
||||||
|
value = value?.toLowerCase()?.replace(/\s/g, "");
|
||||||
|
}
|
||||||
setState({ ...state, [name]: value });
|
setState({ ...state, [name]: value });
|
||||||
};
|
};
|
||||||
|
const handlePaidRoute = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
localStorage.removeItem("accesstoken");
|
localStorage.removeItem("accesstoken");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -93,12 +110,10 @@ function Login() {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
await Parse.Cloud.run("getUserDetails")
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
})
|
|
||||||
.then(async (extUser) => {
|
.then(async (extUser) => {
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
|
// console.log("extUser", extUser, extUser?.get("IsDisabled"));
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
if (!IsDisabled) {
|
if (!IsDisabled) {
|
||||||
const userRole = extUser?.get("UserRole");
|
const userRole = extUser?.get("UserRole");
|
||||||
@@ -112,8 +127,14 @@ function Login() {
|
|||||||
`/${menu.pageType}/${menu.pageId}`;
|
`/${menu.pageType}/${menu.pageId}`;
|
||||||
let _role = _currentRole.replace("contracts_", "");
|
let _role = _currentRole.replace("contracts_", "");
|
||||||
localStorage.setItem("_user_role", _role);
|
localStorage.setItem("_user_role", _role);
|
||||||
|
const checkLanguage = extUser?.get("Language");
|
||||||
|
if (checkLanguage) {
|
||||||
|
checkLanguage && i18n.changeLanguage(checkLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
const results = [extUser];
|
const results = [extUser];
|
||||||
const extUser_str = JSON.stringify(results);
|
const extUser_str = JSON.stringify(results);
|
||||||
|
|
||||||
localStorage.setItem("Extand_Class", extUser_str);
|
localStorage.setItem("Extand_Class", extUser_str);
|
||||||
const extInfo = JSON.parse(JSON.stringify(extUser));
|
const extInfo = JSON.parse(JSON.stringify(extUser));
|
||||||
localStorage.setItem("userEmail", extInfo.Email);
|
localStorage.setItem("userEmail", extInfo.Email);
|
||||||
@@ -142,9 +163,9 @@ function Login() {
|
|||||||
JSON.stringify(LocalUserDetails)
|
JSON.stringify(LocalUserDetails)
|
||||||
);
|
);
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription();
|
||||||
const freeplan = res.plan;
|
const plan = res.plan;
|
||||||
const billingDate = res.billingDate;
|
const billingDate = res.billingDate;
|
||||||
if (freeplan === "freeplan") {
|
if (plan === "freeplan") {
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else if (billingDate) {
|
} else if (billingDate) {
|
||||||
@@ -155,11 +176,11 @@ function Login() {
|
|||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
@@ -245,7 +266,7 @@ function Login() {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in free subscribe", err.message);
|
console.log("err in free subscribe", err.message);
|
||||||
alert("Somenthing went wrong, please try again later!");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const thirdpartyLoginfn = async (sessionToken) => {
|
const thirdpartyLoginfn = async (sessionToken) => {
|
||||||
@@ -279,10 +300,7 @@ function Login() {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
await Parse.Cloud.run("getUserDetails")
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
})
|
|
||||||
.then(async (extUser) => {
|
.then(async (extUser) => {
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
@@ -317,9 +335,9 @@ function Login() {
|
|||||||
localStorage.setItem("pageType", menu.pageType);
|
localStorage.setItem("pageType", menu.pageType);
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription();
|
||||||
const freeplan = res.plan;
|
const plan = res.plan;
|
||||||
const billingDate = res.billingDate;
|
const billingDate = res.billingDate;
|
||||||
if (freeplan === "freeplan") {
|
if (plan === "freeplan") {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else if (billingDate) {
|
} else if (billingDate) {
|
||||||
if (new Date(billingDate) > new Date()) {
|
if (new Date(billingDate) > new Date()) {
|
||||||
@@ -329,14 +347,14 @@ function Login() {
|
|||||||
if (isFreeplan) {
|
if (isFreeplan) {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isFreeplan) {
|
if (isFreeplan) {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -408,9 +426,7 @@ function Login() {
|
|||||||
localStorage.setItem("profileImg", "");
|
localStorage.setItem("profileImg", "");
|
||||||
}
|
}
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails").then(async (extUser) => {
|
||||||
email: _user.email
|
|
||||||
}).then(async (extUser) => {
|
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
if (!IsDisabled) {
|
if (!IsDisabled) {
|
||||||
@@ -451,8 +467,8 @@ function Login() {
|
|||||||
localStorage.setItem("userDetails", JSON.stringify(userInfo));
|
localStorage.setItem("userDetails", JSON.stringify(userInfo));
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription();
|
||||||
const billingDate = res.billingDate;
|
const billingDate = res.billingDate;
|
||||||
const freeplan = res.plan;
|
const plan = res.plan;
|
||||||
if (freeplan === "freeplan") {
|
if (plan === "freeplan") {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else if (billingDate) {
|
} else if (billingDate) {
|
||||||
if (new Date(billingDate) > new Date()) {
|
if (new Date(billingDate) > new Date()) {
|
||||||
@@ -460,10 +476,10 @@ function Login() {
|
|||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
@@ -549,7 +565,7 @@ function Login() {
|
|||||||
payload &&
|
payload &&
|
||||||
payload.message.replace(/ /g, "_") === "Internal_server_err"
|
payload.message.replace(/ /g, "_") === "Internal_server_err"
|
||||||
) {
|
) {
|
||||||
alert("Internal server error !");
|
alert(t("server-error"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
@@ -562,10 +578,12 @@ function Login() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const logOutUser = () => {
|
const logOutUser = async () => {
|
||||||
setIsModal(false);
|
setIsModal(false);
|
||||||
if (Parse?.User?.current()) {
|
try {
|
||||||
Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
}
|
}
|
||||||
let appdata = localStorage.getItem("userSettings");
|
let appdata = localStorage.getItem("userSettings");
|
||||||
let applogo = localStorage.getItem("appLogo");
|
let applogo = localStorage.getItem("appLogo");
|
||||||
@@ -575,6 +593,7 @@ function Login() {
|
|||||||
let appid = localStorage.getItem("parseAppId");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
|
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||||
@@ -599,11 +618,16 @@ function Login() {
|
|||||||
"_self"
|
"_self"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
alert("Please provide email.");
|
alert(t("provide-email"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
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 && (
|
||||||
@@ -634,14 +658,14 @@ function Login() {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={handleSubmit} aria-label="Login Form">
|
<form onSubmit={handleSubmit} aria-label="Login Form">
|
||||||
<h1 className="text-[30px] mt-6">Welcome Back!</h1>
|
<h1 className="text-[30px] mt-6">{t("welcome")}</h1>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend className="text-[12px] text-[#878787]">
|
<legend className="text-[12px] text-[#878787]">
|
||||||
Login to your account
|
{t("Login-to-your-account")}
|
||||||
</legend>
|
</legend>
|
||||||
<div className="w-full px-6 py-3 my-1 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
<div className="w-full px-6 py-3 my-1 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||||
<label className="block text-xs" htmlFor="email">
|
<label className="block text-xs" htmlFor="email">
|
||||||
Email
|
{t("email")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="email"
|
||||||
@@ -652,12 +676,16 @@ function Login() {
|
|||||||
value={state.email}
|
value={state.email}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
required
|
required
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
/>
|
/>
|
||||||
<hr className="my-1 border-none" />
|
<hr className="my-1 border-none" />
|
||||||
{!isLoginSSO && (
|
{!isLoginSSO && (
|
||||||
<>
|
<>
|
||||||
<label className="block text-xs" htmlFor="password">
|
<label className="block text-xs" htmlFor="password">
|
||||||
Password
|
{t("password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
@@ -670,6 +698,12 @@ function Login() {
|
|||||||
value={state.password}
|
value={state.password}
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(
|
||||||
|
t("input-required")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@@ -690,7 +724,7 @@ function Login() {
|
|||||||
to="/forgetpassword"
|
to="/forgetpassword"
|
||||||
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
|
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
|
||||||
>
|
>
|
||||||
Forgot Password?
|
{t("forgot-password")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -701,7 +735,7 @@ function Login() {
|
|||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
>
|
>
|
||||||
{state.loading ? "Loading..." : "Login"}
|
{state.loading ? t("loading") : t("login")}
|
||||||
</button>
|
</button>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && (
|
||||||
<button
|
<button
|
||||||
@@ -716,13 +750,13 @@ function Login() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Create Account
|
{t("create-account")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{(appInfo.googleClietId || isEnableSubscription) && (
|
{(appInfo.googleClietId || isEnableSubscription) && (
|
||||||
<div className="op-divider my-4 text-sm">OR</div>
|
<div className="op-divider my-4 text-sm">{t("or")}</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col justify-center items-center gap-y-3">
|
<div className="flex flex-col justify-center items-center gap-y-3">
|
||||||
{/* {appInfo?.fbAppId && (
|
{/* {appInfo?.fbAppId && (
|
||||||
@@ -746,7 +780,7 @@ function Login() {
|
|||||||
className="cursor-pointer border-[1px] border-gray-300 rounded px-[40px] py-2 font-semibold text-sm hover:border-[#d2e3fc] hover:bg-[#ecf3feb7]"
|
className="cursor-pointer border-[1px] border-gray-300 rounded px-[40px] py-2 font-semibold text-sm hover:border-[#d2e3fc] hover:bg-[#ecf3feb7]"
|
||||||
onClick={() => handleSignInWithSSO()}
|
onClick={() => handleSignInWithSSO()}
|
||||||
>
|
>
|
||||||
Sign in with SSO
|
{t("sign-SSO")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -764,13 +798,16 @@ function Login() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<SelectLanguage />
|
||||||
{state.alertMsg && (
|
{state.alertMsg && (
|
||||||
<Alert type={state.alertType}>
|
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
||||||
<div className="ml-3">{state.alertMsg}</div>
|
|
||||||
</Alert>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
|
<ModalUi
|
||||||
|
isOpen={isModal}
|
||||||
|
title={t("additional-info")}
|
||||||
|
showClose={false}
|
||||||
|
>
|
||||||
<form className="px-4 py-3 text-base-content">
|
<form className="px-4 py-3 text-base-content">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label
|
<label
|
||||||
@@ -778,7 +815,8 @@ function Login() {
|
|||||||
style={{ display: "flex" }}
|
style={{ display: "flex" }}
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
>
|
>
|
||||||
Company <span className="text-[red] text-[13px]">*</span>
|
{t("company")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -791,6 +829,10 @@ function Login() {
|
|||||||
Company: e.target.value
|
Company: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -800,7 +842,7 @@ function Login() {
|
|||||||
style={{ display: "flex" }}
|
style={{ display: "flex" }}
|
||||||
className="block text-xs text-gray-700 font-semibold"
|
className="block text-xs text-gray-700 font-semibold"
|
||||||
>
|
>
|
||||||
Job Title
|
{t("job-title")}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -814,6 +856,10 @@ function Login() {
|
|||||||
Destination: e.target.value
|
Destination: e.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -823,14 +869,14 @@ function Login() {
|
|||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
onClick={(e) => handleSubmitbtn(e)}
|
onClick={(e) => handleSubmitbtn(e)}
|
||||||
>
|
>
|
||||||
Login
|
{t("login")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost"
|
className="op-btn op-btn-ghost"
|
||||||
onClick={logOutUser}
|
onClick={logOutUser}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ 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 sanitizeFileName from "../primitives/sanitizeFileName";
|
||||||
const ManageSign = () => {
|
const ManageSign = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
const [initialPen, setInitialPen] = useState("blue");
|
const [initialPen, setInitialPen] = useState("blue");
|
||||||
const [image, setImage] = useState();
|
const [image, setImage] = useState();
|
||||||
@@ -21,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
|
||||||
@@ -44,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) {
|
||||||
@@ -84,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("");
|
||||||
setIsValue(true);
|
if (image) {
|
||||||
|
setIsValue(true);
|
||||||
|
}
|
||||||
setIsInitials(false);
|
setIsInitials(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,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.png`);
|
||||||
} else {
|
} else {
|
||||||
if (!isUrl) {
|
if (image && !isUrl) {
|
||||||
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
|
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.png`);
|
||||||
);
|
} else {
|
||||||
initialsUrl = await uploadFile(initialsImg);
|
if (imgInitials && !isInitialsUrl) {
|
||||||
|
initialFile = base64StringtoFile(
|
||||||
|
imgInitials,
|
||||||
|
`${replaceSpace}__sign.png`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let initialsUrl;
|
||||||
|
if (initialFile && !isInitialsUrl) {
|
||||||
|
initialsUrl = await uploadFile(initialFile);
|
||||||
|
} else {
|
||||||
|
initialsUrl = imgInitials;
|
||||||
}
|
}
|
||||||
if (imgUrl) {
|
if (imgUrl) {
|
||||||
await saveEntry({
|
await saveEntry({
|
||||||
@@ -144,7 +178,7 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
function base64StringtoFile(base64String, filename) {
|
function base64StringtoFile(base64String, filename) {
|
||||||
var arr = base64String.split(","),
|
let arr = base64String.split(","),
|
||||||
mime = arr[0].match(/:(.*?);/)[1],
|
mime = arr[0].match(/:(.*?);/)[1],
|
||||||
bstr = atob(arr[1]),
|
bstr = atob(arr[1]),
|
||||||
n = bstr.length,
|
n = bstr.length,
|
||||||
@@ -173,31 +207,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: "Signature saved successfully."
|
|
||||||
});
|
|
||||||
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 {
|
||||||
@@ -208,20 +235,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: "Signature saved successfully."
|
|
||||||
});
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +252,29 @@ const ManageSign = () => {
|
|||||||
};
|
};
|
||||||
const handleInitialsChange = () => {
|
const handleInitialsChange = () => {
|
||||||
setInitials(initailsRef.current.toDataURL());
|
setInitials(initailsRef.current.toDataURL());
|
||||||
setIsValue(true);
|
if (image || signature) {
|
||||||
|
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">
|
||||||
@@ -245,12 +287,12 @@ const ManageSign = () => {
|
|||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
<div className="ml-[5px] my-[20px] md:m-[20px]">
|
<div className="ml-[5px] my-[20px] md:m-[20px]">
|
||||||
<div className="text-[20px] font-semibold m-[10px] md:m-0 mb-2">
|
<div className="text-[20px] font-semibold m-[10px] md:m-0 mb-2">
|
||||||
My Signature
|
{t("my-signature")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col md:flex-row gap-0 md:gap-[12px]">
|
<div className="flex flex-col md:flex-row gap-0 md:gap-[12px]">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
||||||
Signature
|
{t("signature")}
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
@@ -279,7 +321,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())
|
||||||
}
|
}
|
||||||
@@ -330,14 +372,14 @@ const ManageSign = () => {
|
|||||||
className="op-link"
|
className="op-link"
|
||||||
onClick={() => handleUploadBtn()}
|
onClick={() => handleUploadBtn()}
|
||||||
>
|
>
|
||||||
Upload image
|
{t("upload")}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
className="op-link"
|
className="op-link"
|
||||||
onClick={() => handleClear()}
|
onClick={() => handleClear()}
|
||||||
>
|
>
|
||||||
Clear
|
{t("clear")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -345,26 +387,30 @@ const ManageSign = () => {
|
|||||||
{warning && (
|
{warning && (
|
||||||
<span className="customwarning signWarning text-[12px] w-[220px] md:w-[300px]">
|
<span className="customwarning signWarning text-[12px] w-[220px] md:w-[300px]">
|
||||||
<i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i>
|
<i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i>
|
||||||
Please upload signature/Image
|
{t("upload-signature/Image")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
|
||||||
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>
|
||||||
) : (
|
) : (
|
||||||
@@ -374,10 +420,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}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -400,6 +444,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");
|
||||||
@@ -410,7 +455,6 @@ const ManageSign = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={key}
|
key={key}
|
||||||
className="fa-light fa-pen-nib"
|
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
></i>
|
></i>
|
||||||
@@ -419,13 +463,22 @@ const ManageSign = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex flex-row gap-1">
|
||||||
<div
|
<div
|
||||||
type="button"
|
type="button"
|
||||||
className="op-link text-sm md:text-base mr-1"
|
className="op-link text-sm md:text-base mr-1"
|
||||||
onClick={() => handleClearInitials()}
|
onClick={() => handleUploadInitials()}
|
||||||
>
|
>
|
||||||
Clear
|
{t("upload")}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
className="op-link text-sm md:text-base mr-1"
|
||||||
|
onClick={() => handleClearInitials()}
|
||||||
|
>
|
||||||
|
{t("clear")}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -437,7 +490,7 @@ const ManageSign = () => {
|
|||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
onClick={(e) => handleSubmit(e)}
|
onClick={(e) => handleSubmit(e)}
|
||||||
>
|
>
|
||||||
save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const DriveBody = React.lazy(
|
const DriveBody = React.lazy(
|
||||||
() => import("../components/opensigndrive/DriveBody")
|
() => import("../components/opensigndrive/DriveBody")
|
||||||
@@ -22,6 +23,7 @@ const AppLoader = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
function Opensigndrive() {
|
function Opensigndrive() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const scrollRef = useRef(null);
|
const scrollRef = useRef(null);
|
||||||
const [isList, setIsList] = useState(false);
|
const [isList, setIsList] = useState(false);
|
||||||
@@ -37,7 +39,7 @@ function Opensigndrive() {
|
|||||||
const [tourStatusArr, setTourStatusArr] = useState([]);
|
const [tourStatusArr, setTourStatusArr] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: t("loading-mssg")
|
||||||
});
|
});
|
||||||
const [docId, setDocId] = useState();
|
const [docId, setDocId] = useState();
|
||||||
const [handleError, setHandleError] = useState("");
|
const [handleError, setHandleError] = useState("");
|
||||||
@@ -78,7 +80,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourFirst"]',
|
selector: '[data-tut="reactourFirst"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Click on the breadcrumb links to easily navigate through the folder hierarchy and view the documents within each folder.`}
|
message={t("tour-mssg.opensign-drive-1")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -89,7 +91,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourSecond"]',
|
selector: '[data-tut="reactourSecond"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Click the add button to create a new folder or document.`}
|
message={t("tour-mssg.opensign-drive-2")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -100,7 +102,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourThird"]',
|
selector: '[data-tut="reactourThird"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Sort your documents by Date or Name using this menu.`}
|
message={t("tour-mssg.opensign-drive-3")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -111,7 +113,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourForth"]',
|
selector: '[data-tut="reactourForth"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Click on this menu to display the documents in list view.`}
|
message={t("tour-mssg.opensign-drive-4")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -126,7 +128,7 @@ function Opensigndrive() {
|
|||||||
checkTourStatus();
|
checkTourStatus();
|
||||||
}
|
}
|
||||||
if (!disbaleLoading) {
|
if (!disbaleLoading) {
|
||||||
setIsLoading({ isLoad: true, message: "This might take some time" });
|
setIsLoading({ isLoad: true, message: t("loading-mssg") });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const driveDetails = await getDrive(docId, skip, limit);
|
const driveDetails = await getDrive(docId, skip, limit);
|
||||||
@@ -138,7 +140,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourFifth"]',
|
selector: '[data-tut="reactourFifth"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`The document list is displayed according to the selected sorting option. Icons next to each document indicate its current status.`}
|
message={t("tour-mssg.opensign-drive-5")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -149,7 +151,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourSixth"]',
|
selector: '[data-tut="reactourSixth"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Right-click on a document to see options such as Download, Rename, Move, and Delete. Click on the document to open it.`}
|
message={t("tour-mssg.opensign-drive-6")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -160,7 +162,7 @@ function Opensigndrive() {
|
|||||||
selector: '[data-tut="reactourSeventh"]',
|
selector: '[data-tut="reactourSeventh"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Right-click on any folder to see options. Choose ‘Rename’ to change the folder’s name or click on the folder to navigate through its contents.`}
|
message={t("tour-mssg.opensign-drive-7")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -190,12 +192,12 @@ function Opensigndrive() {
|
|||||||
setTourData(tourConfigs);
|
setTourData(tourConfigs);
|
||||||
}
|
}
|
||||||
if (!docId) {
|
if (!docId) {
|
||||||
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
|
setFolderName([{ name: t("OpenSign-drive"), objectId: "" }]);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -319,11 +321,11 @@ function Opensigndrive() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: "something went wrong!"
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setError("Please fill out this field");
|
setError(t("fill-field"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -496,26 +498,14 @@ 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 currentUser = Parse.User.current();
|
const cloudRes = await Parse.Cloud.run("getUserDetails");
|
||||||
const cloudRes = await Parse.Cloud.run("getUserDetails", {
|
if (cloudRes) {
|
||||||
email: currentUser.get("email")
|
const extUser = JSON.parse(JSON.stringify(cloudRes));
|
||||||
});
|
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
|
||||||
const res = { data: cloudRes.toJSON() };
|
const tourStatus = extUser?.TourStatus || [];
|
||||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
|
||||||
const tourStatus = res.data.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);
|
||||||
}
|
}
|
||||||
@@ -525,7 +515,7 @@ function Opensigndrive() {
|
|||||||
<Title title={"OpenSign™ Drive"} drive={true} />
|
<Title title={"OpenSign™ Drive"} drive={true} />
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isAlert.isShow}
|
isOpen={isAlert.isShow}
|
||||||
title={"Alert"}
|
title={t("alert")}
|
||||||
handleClose={() => {
|
handleClose={() => {
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
isShow: false,
|
isShow: false,
|
||||||
@@ -546,13 +536,13 @@ function Opensigndrive() {
|
|||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-neutral op-btn-sm"
|
className="op-btn op-btn-neutral op-btn-sm"
|
||||||
>
|
>
|
||||||
Close
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isFolder}
|
isOpen={isFolder}
|
||||||
title={"Add New Folder"}
|
title={t("add-new-folder")}
|
||||||
handleClose={oncloseFolder}
|
handleClose={oncloseFolder}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px] pt-[10px] pb-[15px]">
|
<div className="h-full p-[20px] pt-[10px] pb-[15px]">
|
||||||
@@ -566,10 +556,14 @@ function Opensigndrive() {
|
|||||||
className="flex flex-col text-base-content"
|
className="flex flex-col text-base-content"
|
||||||
>
|
>
|
||||||
<label className="py-[8px] text-[15px] font-[400] mb-0">
|
<label className="py-[8px] text-[15px] font-[400] mb-0">
|
||||||
Name
|
{t("name")}
|
||||||
<span className="text-[red]">*</span>
|
<span className="text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
className="op-input op-input-bordered op-input-sm"
|
className="op-input op-input-bordered op-input-sm"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -580,14 +574,14 @@ function Opensigndrive() {
|
|||||||
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
|
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Add
|
{t("add")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost ml-1"
|
className="op-btn op-btn-ghost ml-1"
|
||||||
onClick={oncloseFolder}
|
onClick={oncloseFolder}
|
||||||
>
|
>
|
||||||
Close
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -655,21 +649,21 @@ function Opensigndrive() {
|
|||||||
className="fa-light fa-plus mr-[5px]"
|
className="fa-light fa-plus mr-[5px]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Create folder
|
{t("create-folder")}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="dropdown-item text-[10px] md:text-[13px]"
|
className="dropdown-item text-[10px] md:text-[13px]"
|
||||||
onClick={() => navigate("/form/sHAnZphf69")}
|
onClick={() => navigate("/form/sHAnZphf69")}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-pen-nib mr-[5px]"></i>
|
<i className="fa-light fa-pen-nib mr-[5px]"></i>
|
||||||
Sign Yourself
|
{t("form-name.Sign Yourself")}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="dropdown-item text-[10px] md:text-[13px]"
|
className="dropdown-item text-[10px] md:text-[13px]"
|
||||||
onClick={() => navigate("/form/8mZzFxbG1z")}
|
onClick={() => navigate("/form/8mZzFxbG1z")}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-file-signature mr-[5px]"></i>
|
<i className="fa-light fa-file-signature mr-[5px]"></i>
|
||||||
Request Signatures
|
{t("form-name.Request Signatures")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -719,7 +713,9 @@ function Opensigndrive() {
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
<span className="ml-[5px]">{value}</span>
|
<span className="ml-[5px]">
|
||||||
|
{t(`sort-order.${value}`)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -744,7 +740,9 @@ function Opensigndrive() {
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
<span className="ml-[5px]">{order}</span>
|
<span className="ml-[5px]">
|
||||||
|
{t(`sort-order.${order}`)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -781,7 +779,7 @@ function Opensigndrive() {
|
|||||||
{pdfData && pdfData.length === 0 ? (
|
{pdfData && pdfData.length === 0 ? (
|
||||||
<div className="flex justify-center items-center w-full h-[50vh]">
|
<div className="flex justify-center items-center w-full h-[50vh]">
|
||||||
<span className="text-base-content font-bold">
|
<span className="text-base-content font-bold">
|
||||||
No Data Found!
|
{t("no-data")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -803,7 +801,7 @@ function Opensigndrive() {
|
|||||||
sortingData={sortingData}
|
sortingData={sortingData}
|
||||||
/>
|
/>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="text-center pb-[20px]">Loading...</div>
|
<div className="text-center pb-[20px]">{t("loading")}</div>
|
||||||
)}
|
)}
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,10 @@ import { appInfo } from "../constant/appinfo";
|
|||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const PgSignUp = () => {
|
const PgSignUp = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -71,9 +73,7 @@ const PgSignUp = () => {
|
|||||||
if (res) {
|
if (res) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
try {
|
try {
|
||||||
const extUser = await Parse.Cloud.run("getUserDetails", {
|
const extUser = await Parse.Cloud.run("getUserDetails");
|
||||||
email: userDetails.email
|
|
||||||
});
|
|
||||||
const userRole = extUser?.get("UserRole");
|
const userRole = extUser?.get("UserRole");
|
||||||
const _currentRole = userRole;
|
const _currentRole = userRole;
|
||||||
const _role = _currentRole.replace("contracts_", "");
|
const _role = _currentRole.replace("contracts_", "");
|
||||||
@@ -168,11 +168,11 @@ const PgSignUp = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("err ", error);
|
console.log("err ", error);
|
||||||
if (error.message === "Account already exists for this username.") {
|
if (error.message === "Account already exists for this username.") {
|
||||||
alert("Account already exists!");
|
alert(t("account-already-exists"));
|
||||||
navigate("/", { replace: true });
|
navigate("/", { replace: true });
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert("Something went wrong, please try again later!");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -230,10 +230,7 @@ const PgSignUp = () => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
const extUser = await Parse.Cloud.run("getUserDetails");
|
||||||
const extUser = await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
});
|
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
if (!IsDisabled) {
|
if (!IsDisabled) {
|
||||||
@@ -262,7 +259,7 @@ const PgSignUp = () => {
|
|||||||
localStorage.setItem("defaultmenuid", menu.menuId);
|
localStorage.setItem("defaultmenuid", menu.menuId);
|
||||||
localStorage.setItem("pageType", menu.pageType);
|
localStorage.setItem("pageType", menu.pageType);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert("Registered user successfully");
|
alert(t("registered-user-successfully"));
|
||||||
const redirectUrl =
|
const redirectUrl =
|
||||||
location?.state?.from || `/${menu.pageType}/${menu.pageId}`;
|
location?.state?.from || `/${menu.pageType}/${menu.pageId}`;
|
||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
@@ -294,27 +291,31 @@ const PgSignUp = () => {
|
|||||||
>
|
>
|
||||||
<div className="p-[16px]">
|
<div className="p-[16px]">
|
||||||
<h1 className="text-2xl md:text-3xl font-bold">
|
<h1 className="text-2xl md:text-3xl font-bold">
|
||||||
Choose Password
|
{t("choose-password")}
|
||||||
</h1>
|
</h1>
|
||||||
<hr className="border-[1px] border-[#cecece] mb-[5px]" />
|
<hr className="border-[1px] border-[#cecece] mb-[5px]" />
|
||||||
<label htmlFor="password">
|
<label htmlFor="password">
|
||||||
<b className="text-[13px]">Password</b>
|
<b className="text-[13px]">{t("password")}</b>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Enter Password"
|
placeholder={t("enter-password")}
|
||||||
name="password"
|
name="password"
|
||||||
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"
|
||||||
value={formData.password}
|
value={formData.password}
|
||||||
onChange={handlePassowordChange}
|
onChange={handlePassowordChange}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<label htmlFor="confirmPassword">
|
<label htmlFor="confirmPassword">
|
||||||
<b className="text-[13px]">Confirm Password</b>
|
<b className="text-[13px]">{t("confirm-password")}</b>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Confirm Password"
|
placeholder={t("confirm-password")}
|
||||||
name="confirmPassword"
|
name="confirmPassword"
|
||||||
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"
|
||||||
style={{
|
style={{
|
||||||
@@ -326,6 +327,10 @@ const PgSignUp = () => {
|
|||||||
}}
|
}}
|
||||||
value={formData.confirmPassword}
|
value={formData.confirmPassword}
|
||||||
onChange={handleConFirmPassowordChange}
|
onChange={handleConFirmPassowordChange}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@@ -344,24 +349,21 @@ const PgSignUp = () => {
|
|||||||
lengthValid ? "text-green-600" : "text-red-600"
|
lengthValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{lengthValid ? "✓" : "✗"} Password should be 8 characters
|
{lengthValid ? "✓" : "✗"} {t("password-length")}
|
||||||
long
|
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
caseDigitValid ? "text-green-600" : "text-red-600"
|
caseDigitValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{caseDigitValid ? "✓" : "✗"} Password should contain
|
{caseDigitValid ? "✓" : "✗"} {t("password-case")}
|
||||||
uppercase letter, lowercase letter, digit
|
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
specialCharValid ? "text-green-600" : "text-red-600"
|
specialCharValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{specialCharValid ? "✓" : "✗"} Password should contain
|
{specialCharValid ? "✓" : "✗"} {t("password-special-char")}
|
||||||
special character
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -369,7 +371,7 @@ const PgSignUp = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
className="op-btn op-btn-primary w-full mt-[8px]"
|
className="op-btn op-btn-primary w-full mt-[8px]"
|
||||||
>
|
>
|
||||||
Submit
|
{t("submit")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import checkmark from "../assets/images/checkmark.png";
|
import checkmark from "../assets/images/checkmark.png";
|
||||||
import plansArr, { stagingPlan } from "../json/plansArr";
|
import plansArr from "../json/plansArr";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { openInNewTab, saveLanguageInLocal } from "../constant/Utils";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
import { isStaging } from "../constant/const";
|
import { useTranslation } from "react-i18next";
|
||||||
const listItemStyle = {
|
const listItemStyle = {
|
||||||
paddingLeft: "20px", // Add padding to create space for the image
|
paddingLeft: "20px", // Add padding to create space for the image
|
||||||
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
|
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
|
||||||
@@ -16,8 +16,8 @@ const listItemStyle = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const PlanSubscriptions = () => {
|
const PlanSubscriptions = () => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isTeamPlan = plansArr.some((x) => x.planName === "OPENSIGN™ TEAMS");
|
|
||||||
const [yearlyVisible, setYearlyVisible] = useState(true);
|
const [yearlyVisible, setYearlyVisible] = useState(true);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
const extUser =
|
const extUser =
|
||||||
@@ -53,22 +53,45 @@ const PlanSubscriptions = () => {
|
|||||||
? "&mobile=" + encodeURIComponent(userDetails.phone)
|
? "&mobile=" + encodeURIComponent(userDetails.phone)
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const details =
|
|
||||||
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
|
||||||
name +
|
|
||||||
email +
|
|
||||||
company +
|
|
||||||
phone;
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
if (!isTeamPlan && isStaging) {
|
detectLanguage();
|
||||||
plansArr.splice(2, 0, stagingPlan);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
const detectLanguage = () => {
|
||||||
|
const detectedLanguage = i18n.language || "en";
|
||||||
|
i18n.changeLanguage(detectedLanguage);
|
||||||
|
localStorage.setItem("i18nextLng", detectedLanguage);
|
||||||
|
};
|
||||||
|
|
||||||
const handleFreePlan = async (item) => {
|
const handleFreePlan = async (item) => {
|
||||||
if (item.url) {
|
if (item.url) {
|
||||||
|
const code = yearlyVisible ? item.code.yearly : item.code.monthly;
|
||||||
|
const allowedUsers =
|
||||||
|
localStorage.getItem("allowedUsers") &&
|
||||||
|
localStorage.getItem("allowedUsers") > 0
|
||||||
|
? localStorage.getItem("allowedUsers") - 1
|
||||||
|
: "";
|
||||||
|
const teamperiod = {
|
||||||
|
"team-weekly": "monthly",
|
||||||
|
"team-yearly": "yearly",
|
||||||
|
"teams-monthly": "monthly",
|
||||||
|
"teams-yearly": "yearly"
|
||||||
|
};
|
||||||
|
const period = teamperiod[code] || "";
|
||||||
|
|
||||||
|
const quantity =
|
||||||
|
allowedUsers && period
|
||||||
|
? `addon_code%5B0%5D=extra-teams-users-${period}&addon_quantity%5B0%5D=${allowedUsers}&`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const details =
|
||||||
|
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
||||||
|
quantity +
|
||||||
|
name +
|
||||||
|
email +
|
||||||
|
company +
|
||||||
|
phone;
|
||||||
const url = yearlyVisible ? item.yearlyUrl + details : item.url + details;
|
const url = yearlyVisible ? item.yearlyUrl + details : item.url + details;
|
||||||
if (user) {
|
if (user) {
|
||||||
localStorage.setItem("userDetails", JSON.stringify(user));
|
localStorage.setItem("userDetails", JSON.stringify(user));
|
||||||
@@ -81,7 +104,7 @@ const PlanSubscriptions = () => {
|
|||||||
const res = await Parse.Cloud.run("freesubscription", params);
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
if (res.status === "success" && res.result === "already subscribed!") {
|
if (res.status === "success" && res.result === "already subscribed!") {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
alert("You have already subscribed to plan!");
|
alert(t("subscribed-alert"));
|
||||||
} else if (res.status === "success") {
|
} else if (res.status === "success") {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
navigate("/");
|
navigate("/");
|
||||||
@@ -92,10 +115,34 @@ const PlanSubscriptions = () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
console.log("err in free subscribe", err.message);
|
console.log("err in free subscribe", err.message);
|
||||||
alert("Somenthing went wrong, please try again later!");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleLogout = async () => {
|
||||||
|
try {
|
||||||
|
await Parse?.User?.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
|
}
|
||||||
|
let appdata = localStorage.getItem("userSettings");
|
||||||
|
let applogo = localStorage.getItem("appLogo");
|
||||||
|
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
||||||
|
let PageLanding = localStorage.getItem("PageLanding");
|
||||||
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
|
let appid = localStorage.getItem("parseAppId");
|
||||||
|
|
||||||
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
|
localStorage.setItem("appLogo", applogo);
|
||||||
|
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||||
|
localStorage.setItem("PageLanding", PageLanding);
|
||||||
|
localStorage.setItem("userSettings", appdata);
|
||||||
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
|
localStorage.setItem("parseAppId", appid);
|
||||||
|
|
||||||
|
navigate("/");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title={"Subscriptions"} />
|
<Title title={"Subscriptions"} />
|
||||||
@@ -106,7 +153,13 @@ const PlanSubscriptions = () => {
|
|||||||
) : (
|
) : (
|
||||||
<div className="overflow-y-auto max-h-full">
|
<div className="overflow-y-auto max-h-full">
|
||||||
<div className="block my-2">
|
<div className="block my-2">
|
||||||
<div className="flex flex-col justify-center items-center w-full">
|
<div className="flex flex-col justify-center items-center w-full relative">
|
||||||
|
<button
|
||||||
|
className="md:hidden op-btn op-btn-primary op-btn-sm h-[40px] w-[250px] shadow-lg"
|
||||||
|
onClick={() => handleLogout()}
|
||||||
|
>
|
||||||
|
Log out
|
||||||
|
</button>
|
||||||
<div
|
<div
|
||||||
role="tablist"
|
role="tablist"
|
||||||
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
|
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
|
||||||
@@ -116,17 +169,23 @@ const PlanSubscriptions = () => {
|
|||||||
role="tab"
|
role="tab"
|
||||||
className={`${!yearlyVisible ? "op-tab-active" : ""} op-tab`}
|
className={`${!yearlyVisible ? "op-tab-active" : ""} op-tab`}
|
||||||
>
|
>
|
||||||
Monthly
|
{t("monthly")}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
onClick={() => setYearlyVisible(true)}
|
onClick={() => setYearlyVisible(true)}
|
||||||
role="tab"
|
role="tab"
|
||||||
className={`${yearlyVisible ? "op-tab-active" : ""} op-tab`}
|
className={`${yearlyVisible ? "op-tab-active" : ""} op-tab`}
|
||||||
>
|
>
|
||||||
Yearly (10% off)
|
{t("yearly-upto")}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
|
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
|
||||||
|
<button
|
||||||
|
className="hidden md:block -top-12 right-1 absolute w-[150px] h-[40px] op-btn op-btn-primary op-btn-sm shadow-lg"
|
||||||
|
onClick={() => handleLogout()}
|
||||||
|
>
|
||||||
|
{t("log-out")}
|
||||||
|
</button>
|
||||||
{plansArr.map((item) => (
|
{plansArr.map((item) => (
|
||||||
<li
|
<li
|
||||||
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
|
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
|
||||||
@@ -175,7 +234,9 @@ const PlanSubscriptions = () => {
|
|||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<p className="font-semibold pt-2 text-sm">
|
<p className="font-semibold pt-2 text-sm">
|
||||||
{yearlyVisible ? "Billed Yearly" : "Billed Monthly"}
|
{yearlyVisible
|
||||||
|
? t("billed-yearly")
|
||||||
|
: t("billed-monthly")}
|
||||||
</p>
|
</p>
|
||||||
<div className="max-w-[250px] h-[40px] text-center text-sm my-2">
|
<div className="max-w-[250px] h-[40px] text-center text-sm my-2">
|
||||||
<div
|
<div
|
||||||
@@ -209,11 +270,18 @@ const PlanSubscriptions = () => {
|
|||||||
</div>
|
</div>
|
||||||
<hr className="w-full bg-gray-300 h-[0.5px]" />
|
<hr className="w-full bg-gray-300 h-[0.5px]" />
|
||||||
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
||||||
{item.benefits.map((subitem, index) => (
|
{!yearlyVisible &&
|
||||||
<li style={listItemStyle} key={index} className="m-1">
|
item.benefits.map((subitem, index) => (
|
||||||
<span className="relative">{subitem}</span>
|
<li style={listItemStyle} key={index} className="m-1">
|
||||||
</li>
|
<span className="relative">{subitem}</span>
|
||||||
))}
|
</li>
|
||||||
|
))}
|
||||||
|
{yearlyVisible &&
|
||||||
|
item?.yearlyBenefits?.map((subitem, index) => (
|
||||||
|
<li style={listItemStyle} key={index} className="m-1">
|
||||||
|
<span className="relative">{subitem}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
@@ -226,7 +294,7 @@ const PlanSubscriptions = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center items-center">
|
<div className="flex flex-col justify-center items-center">
|
||||||
<h3 className="text-[#002862] mt-1 mb-2">
|
<h3 className="text-[#002862] mt-1 mb-2">
|
||||||
Host it yourself for free
|
{t("plansubscription-1")}
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<div
|
||||||
className="op-btn op-btn-primary w-[200px]"
|
className="op-btn op-btn-primary w-[200px]"
|
||||||
@@ -234,7 +302,7 @@ const PlanSubscriptions = () => {
|
|||||||
openInNewTab("https://github.com/OpenSignLabs/OpenSign")
|
openInNewTab("https://github.com/OpenSignLabs/OpenSign")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Visit Github
|
{t("visit-github")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import Title from "../components/Title";
|
|||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Report = () => {
|
const Report = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [List, setList] = useState([]);
|
const [List, setList] = useState([]);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
@@ -83,9 +85,7 @@ const Report = () => {
|
|||||||
selector: "[data-tut=reactourFirst]",
|
selector: "[data-tut=reactourFirst]",
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={
|
message={t("tour-mssg.report-1")}
|
||||||
"Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. "
|
|
||||||
}
|
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -100,7 +100,7 @@ const Report = () => {
|
|||||||
selector: `[data-tut="${data?.selector}"]`,
|
selector: `[data-tut="${data?.selector}"]`,
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={data?.message}
|
message={t(`tour-mssg.${data?.action}`)}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import { useDispatch } from "react-redux";
|
|||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const SSOVerify = () => {
|
const SSOVerify = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -48,6 +50,9 @@ const SSOVerify = () => {
|
|||||||
console.log("err", err.message);
|
console.log("err", err.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handlePaidRoute = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
const checkExtUser = async (ssosign) => {
|
const checkExtUser = async (ssosign) => {
|
||||||
const params = { email: ssosign?.email };
|
const params = { email: ssosign?.email };
|
||||||
try {
|
try {
|
||||||
@@ -120,16 +125,16 @@ const SSOVerify = () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("error in usersignup", err);
|
console.log("error in usersignup", err);
|
||||||
localStorage.removeItem("accesstoken");
|
localStorage.removeItem("accesstoken");
|
||||||
alert("Something went wrong.");
|
alert(t("something-went-wrong-mssg"));
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem("accesstoken");
|
localStorage.removeItem("accesstoken");
|
||||||
alert("Internal server error.");
|
alert(t("server-error"));
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please fill required details correctly.");
|
alert(t("filed-required-correctly"));
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -149,10 +154,7 @@ const SSOVerify = () => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
await Parse.Cloud.run("getUserDetails")
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
})
|
|
||||||
.then(async (extUser) => {
|
.then(async (extUser) => {
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
@@ -197,29 +199,25 @@ const SSOVerify = () => {
|
|||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
handlePaidRoute(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert(
|
alert(t("do-not-access-contact-admin"));
|
||||||
"Error: You don't have access, please contact the admin."
|
setMessage(t("do-not-access-contact-admin"));
|
||||||
);
|
|
||||||
setMessage(
|
|
||||||
"Error: You don't have access, please contact the admin."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Err in fetch extuser", error);
|
console.error("Err in fetch extuser", error);
|
||||||
alert("user not exist.");
|
alert(t("user-not-exist"));
|
||||||
setMessage("Error: User not exist.");
|
setMessage(t("user-not-exist"));
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in getuserdetails", err);
|
console.log("err in getuserdetails", err);
|
||||||
@@ -230,10 +228,12 @@ const SSOVerify = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// `handleCloseModal` is triggered when the user wants to close the new user flow modal
|
// `handleCloseModal` is triggered when the user wants to close the new user flow modal
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = async () => {
|
||||||
setIsModal(false);
|
setIsModal(false);
|
||||||
if (Parse?.User?.current()) {
|
try {
|
||||||
Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ const SSOVerify = () => {
|
|||||||
>
|
>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="Company" className="block text-xs font-semibold">
|
<label htmlFor="Company" className="block text-xs font-semibold">
|
||||||
Phone <span className="text-[13px] text-[red]">*</span>
|
{t("phone")} <span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
@@ -279,6 +279,10 @@ const SSOVerify = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
disabled={isLoader}
|
disabled={isLoader}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<p className="text-[10px] text-[red] ml-2">
|
<p className="text-[10px] text-[red] ml-2">
|
||||||
@@ -287,7 +291,7 @@ const SSOVerify = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="Company" className="block text-xs font-semibold">
|
<label htmlFor="Company" className="block text-xs font-semibold">
|
||||||
Company <span className="text-[13px] text-[red]">*</span>
|
{t("company")} <span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -301,12 +305,16 @@ const SSOVerify = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
disabled={isLoader}
|
disabled={isLoader}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="JobTitle" className="block text-xs font-semibold">
|
<label htmlFor="JobTitle" className="block text-xs font-semibold">
|
||||||
Job Title
|
{t("job-title")}
|
||||||
<span className="text-[13px] text-[red]">*</span>
|
<span className="text-[13px] text-[red]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -321,19 +329,23 @@ const SSOVerify = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
disabled={isLoader}
|
disabled={isLoader}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<button type="submit" className="op-btn op-btn-primary">
|
<button type="submit" className="op-btn op-btn-primary">
|
||||||
Login
|
{t("login")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost ml-2"
|
className="op-btn op-btn-ghost ml-2"
|
||||||
onClick={handleCloseModal}
|
onClick={handleCloseModal}
|
||||||
>
|
>
|
||||||
Cancel
|
{t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -11,10 +11,17 @@ 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 { isEnableSubscription } from "../constant/const";
|
||||||
import { getAppLogo, openInNewTab } from "../constant/Utils";
|
import {
|
||||||
|
getAppLogo,
|
||||||
|
openInNewTab,
|
||||||
|
saveLanguageInLocal
|
||||||
|
} from "../constant/Utils";
|
||||||
import Loader from "../primitives/Loader";
|
import Loader from "../primitives/Loader";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||||
const Signup = () => {
|
const Signup = () => {
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -38,8 +45,10 @@ const Signup = () => {
|
|||||||
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
||||||
|
|
||||||
const clearStorage = async () => {
|
const clearStorage = async () => {
|
||||||
if (Parse.User.current()) {
|
try {
|
||||||
await Parse.User.logOut();
|
await Parse.User.logOut();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err while logging out", err);
|
||||||
}
|
}
|
||||||
let baseUrl = localStorage.getItem("baseUrl");
|
let baseUrl = localStorage.getItem("baseUrl");
|
||||||
let appid = localStorage.getItem("parseAppId");
|
let appid = localStorage.getItem("parseAppId");
|
||||||
@@ -49,7 +58,7 @@ const Signup = () => {
|
|||||||
let userSettings = localStorage.getItem("userSettings");
|
let userSettings = localStorage.getItem("userSettings");
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
saveLanguageInLocal(i18n);
|
||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
localStorage.setItem("appLogo", applogo);
|
localStorage.setItem("appLogo", applogo);
|
||||||
@@ -69,7 +78,7 @@ const Signup = () => {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in free subscribe", err.message);
|
console.log("err in free subscribe", err.message);
|
||||||
alert("Somenthing went wrong, please try again later!");
|
alert(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
@@ -136,7 +145,7 @@ const Signup = () => {
|
|||||||
const res = await Parse.Cloud.run("getUserDetails", params);
|
const res = await Parse.Cloud.run("getUserDetails", params);
|
||||||
// console.log("Res ", res);
|
// console.log("Res ", res);
|
||||||
if (res) {
|
if (res) {
|
||||||
alert("User already exists with this username!");
|
alert(t("user-already-exist-name"));
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
} else {
|
} else {
|
||||||
// console.log("state.email ", email);
|
// console.log("state.email ", email);
|
||||||
@@ -144,9 +153,7 @@ const Signup = () => {
|
|||||||
await Parse.User.requestPasswordReset(email).then(
|
await Parse.User.requestPasswordReset(email).then(
|
||||||
async function (res1) {
|
async function (res1) {
|
||||||
if (res1.data === undefined) {
|
if (res1.data === undefined) {
|
||||||
alert(
|
alert(t("verification-code-sent"));
|
||||||
"Verification mail has been sent to your E-mail!"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -192,10 +199,7 @@ const Signup = () => {
|
|||||||
// Check extended class user role and tenentId
|
// Check extended class user role and tenentId
|
||||||
try {
|
try {
|
||||||
const userSettings = appInfo.settings;
|
const userSettings = appInfo.settings;
|
||||||
const currentUser = Parse.User.current();
|
await Parse.Cloud.run("getUserDetails")
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
|
||||||
email: currentUser.get("email")
|
|
||||||
})
|
|
||||||
.then(async (extUser) => {
|
.then(async (extUser) => {
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
const IsDisabled = extUser?.get("IsDisabled") || false;
|
const IsDisabled = extUser?.get("IsDisabled") || false;
|
||||||
@@ -233,14 +237,14 @@ const Signup = () => {
|
|||||||
navigate(`/subscription`, { replace: true });
|
navigate(`/subscription`, { replace: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Registered user successfully");
|
alert(t("registered-user-successfully"));
|
||||||
navigate(`/${menu.pageType}/${menu.pageId}`);
|
navigate(`/${menu.pageType}/${menu.pageId}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "danger",
|
alertType: "danger",
|
||||||
alertMsg: "Role not found."
|
alertMsg: t("role-not-found")
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setState({ loading: false, alertMsg: "" });
|
setState({ loading: false, alertMsg: "" });
|
||||||
@@ -250,7 +254,7 @@ const Signup = () => {
|
|||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "danger",
|
alertType: "danger",
|
||||||
alertMsg: "You don't have access, please contact the admin."
|
alertMsg: t("do-not-access-contact-admin")
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setState({ loading: false, alertMsg: "" });
|
setState({ loading: false, alertMsg: "" });
|
||||||
@@ -263,7 +267,7 @@ const Signup = () => {
|
|||||||
setState({
|
setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "danger",
|
alertType: "danger",
|
||||||
alertMsg: "You don't have access, please contact the admin."
|
alertMsg: t("do-not-access-contact-admin")
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setState({ loading: false, alertMsg: "" });
|
setState({ loading: false, alertMsg: "" });
|
||||||
@@ -322,7 +326,7 @@ const Signup = () => {
|
|||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Title title={"Signup page"} />
|
<Title title="Signup page" />
|
||||||
{appInfo && appInfo.applogo ? (
|
{appInfo && appInfo.applogo ? (
|
||||||
<div className="md:p-10 lg:p-16">
|
<div className="md:p-10 lg:p-16">
|
||||||
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
||||||
@@ -334,22 +338,28 @@ const Signup = () => {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<h2 className="text-[30px] mt-6">Create Account !</h2>
|
<h2 className="text-[30px] mt-6">{t("create-account")}!</h2>
|
||||||
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||||
<div className="px-6 py-4 text-xs">
|
<div className="px-6 py-4 text-xs">
|
||||||
<label className="block ">
|
<label className="block ">
|
||||||
Name <span className="text-[red] text-[13px]">*</span>
|
{t("name")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
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"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Email <span className="text-[red] text-[13px]">*</span>
|
{t("email")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="email"
|
||||||
@@ -357,24 +367,35 @@ const Signup = () => {
|
|||||||
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"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setEmail(e.target.value?.toLowerCase())
|
setEmail(
|
||||||
|
e.target.value?.toLowerCase()?.replace(/\s/g, "")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Phone <span className="text-[red] text-[13px]">*</span>
|
{t("phone")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
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"
|
||||||
value={phone}
|
value={phone}
|
||||||
onChange={(e) => setPhone(e.target.value)}
|
onChange={(e) => setPhone(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Company{" "}
|
{t("company")}{" "}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -382,11 +403,15 @@ const Signup = () => {
|
|||||||
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"
|
||||||
value={company}
|
value={company}
|
||||||
onChange={(e) => setCompany(e.target.value)}
|
onChange={(e) => setCompany(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Job Title{" "}
|
{t("job-title")}{" "}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -394,11 +419,15 @@ const Signup = () => {
|
|||||||
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"
|
||||||
value={jobTitle}
|
value={jobTitle}
|
||||||
onChange={(e) => setJobTitle(e.target.value)}
|
onChange={(e) => setJobTitle(e.target.value)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Password{" "}
|
{t("password")}{" "}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -408,6 +437,10 @@ const Signup = () => {
|
|||||||
name="password"
|
name="password"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => handlePasswordChange(e)}
|
onChange={(e) => handlePasswordChange(e)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@@ -428,16 +461,16 @@ const Signup = () => {
|
|||||||
lengthValid ? "text-green-600" : "text-red-600"
|
lengthValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{lengthValid ? "✓" : "✗"} Password should be 8
|
{lengthValid ? "✓" : "✗"}
|
||||||
characters long
|
{t("password-length")}
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
caseDigitValid ? "text-green-600" : "text-red-600"
|
caseDigitValid ? "text-green-600" : "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{caseDigitValid ? "✓" : "✗"} Password should contain
|
{caseDigitValid ? "✓" : "✗"}
|
||||||
uppercase letter, lowercase letter, digit
|
{t("password-case")}
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
className={`${
|
className={`${
|
||||||
@@ -446,8 +479,8 @@ const Signup = () => {
|
|||||||
: "text-red-600"
|
: "text-red-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{specialCharValid ? "✓" : "✗"} Password should
|
{specialCharValid ? "✓" : "✗"}{" "}
|
||||||
contain special character
|
{t("password-special-char")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -458,13 +491,17 @@ const Signup = () => {
|
|||||||
id="termsandcondition"
|
id="termsandcondition"
|
||||||
checked={isAuthorize}
|
checked={isAuthorize}
|
||||||
onChange={(e) => setIsAuthorize(e.target.checked)}
|
onChange={(e) => setIsAuthorize(e.target.checked)}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
className="text-xs cursor-pointer ml-1 mb-0"
|
className="text-xs cursor-pointer ml-1 mb-0"
|
||||||
htmlFor="termsandcondition"
|
htmlFor="termsandcondition"
|
||||||
>
|
>
|
||||||
I agree to the
|
{t("agreee")}
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
className="underline cursor-pointer ml-1"
|
className="underline cursor-pointer ml-1"
|
||||||
@@ -474,7 +511,7 @@ const Signup = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Terms of Service
|
{t("term")}
|
||||||
</span>
|
</span>
|
||||||
<span>.</span>
|
<span>.</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -486,7 +523,7 @@ const Signup = () => {
|
|||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
>
|
>
|
||||||
{state.loading ? "Loading..." : "Register"}
|
{state.loading ? t("loading") : t("register")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -496,7 +533,7 @@ const Signup = () => {
|
|||||||
navigate(location.search ? "/" + location.search : "/")
|
navigate(location.search ? "/" + location.search : "/")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Login
|
{t("login")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -510,6 +547,7 @@ const Signup = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<SelectLanguage />
|
||||||
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,11 @@ import ModalUi from "../primitives/ModalUi";
|
|||||||
import pad from "../assets/images/pad.svg";
|
import pad from "../assets/images/pad.svg";
|
||||||
import AddTeam from "../components/AddTeam";
|
import AddTeam from "../components/AddTeam";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { isEnableSubscription } from "../constant/const";
|
||||||
import { checkIsSubscribedTeam } from "../constant/Utils";
|
import { checkIsSubscribed } from "../constant/Utils";
|
||||||
import SubscribeCard from "../primitives/SubscribeCard";
|
import SubscribeCard from "../primitives/SubscribeCard";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
|
import { validplan } from "../json/plansArr";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const heading = ["Sr.No", "Name", "Parent Team", "Active"];
|
const heading = ["Sr.No", "Name", "Parent Team", "Active"];
|
||||||
const actions = [
|
const actions = [
|
||||||
@@ -25,6 +27,7 @@ const actions = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const TeamList = () => {
|
const TeamList = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const recordperPage = 10;
|
const recordperPage = 10;
|
||||||
const [teamList, setTeamList] = useState([]);
|
const [teamList, setTeamList] = useState([]);
|
||||||
const [isLoader, setIsLoader] = useState(false);
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
@@ -36,7 +39,7 @@ const TeamList = () => {
|
|||||||
const [isActiveModal, setIsActiveModal] = useState({});
|
const [isActiveModal, setIsActiveModal] = useState({});
|
||||||
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
|
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
|
||||||
const [isActLoader, setIsActLoader] = useState({});
|
const [isActLoader, setIsActLoader] = useState({});
|
||||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false });
|
||||||
const [isEditModal, setIsEditModal] = useState({});
|
const [isEditModal, setIsEditModal] = useState({});
|
||||||
const [isAdmin, setIsAdmin] = useState(false);
|
const [isAdmin, setIsAdmin] = useState(false);
|
||||||
const startIndex = (currentPage - 1) * recordperPage; // user per page
|
const startIndex = (currentPage - 1) * recordperPage; // user per page
|
||||||
@@ -95,13 +98,14 @@ const TeamList = () => {
|
|||||||
const pageNumbers = getPaginationRange();
|
const pageNumbers = getPaginationRange();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTeamList();
|
fetchTeamList();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
async function fetchTeamList() {
|
async function fetchTeamList() {
|
||||||
try {
|
try {
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
if (isEnableSubscription) {
|
if (isEnableSubscription) {
|
||||||
const getIsSubscribe = await checkIsSubscribedTeam();
|
const subscribe = await checkIsSubscribed();
|
||||||
setIsSubscribe(getIsSubscribe);
|
setIsSubscribe(subscribe);
|
||||||
}
|
}
|
||||||
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
@@ -120,7 +124,7 @@ const TeamList = () => {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Err in fetch teamlist", err);
|
console.log("Err in fetch teamlist", err);
|
||||||
setIsAlert({ type: "danger", msg: "Something went wrong." });
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsAlert({ type: "success", msg: "" });
|
setIsAlert({ type: "success", msg: "" });
|
||||||
@@ -131,7 +135,7 @@ const TeamList = () => {
|
|||||||
const handleFormModal = () => {
|
const handleFormModal = () => {
|
||||||
setIsModal(!isModal);
|
setIsModal(!isModal);
|
||||||
};
|
};
|
||||||
// Get current list
|
// to slice out 10 objects from array for current page
|
||||||
const indexOfLastDoc = currentPage * recordperPage;
|
const indexOfLastDoc = currentPage * recordperPage;
|
||||||
const indexOfFirstDoc = indexOfLastDoc - recordperPage;
|
const indexOfFirstDoc = indexOfLastDoc - recordperPage;
|
||||||
const currentList = teamList?.slice(indexOfFirstDoc, indexOfLastDoc);
|
const currentList = teamList?.slice(indexOfFirstDoc, indexOfLastDoc);
|
||||||
@@ -142,8 +146,19 @@ const TeamList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Change page
|
// Change page
|
||||||
const paginateFront = () => setCurrentPage(currentPage + 1);
|
const paginateFront = () => {
|
||||||
const paginateBack = () => setCurrentPage(currentPage - 1);
|
const lastValue = pageNumbers?.[pageNumbers?.length - 1];
|
||||||
|
if (currentPage < lastValue) {
|
||||||
|
setCurrentPage(currentPage + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const paginateBack = () => {
|
||||||
|
if (startIndex > 0) {
|
||||||
|
setCurrentPage(currentPage - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleActionBtn = (act, item) => {
|
const handleActionBtn = (act, item) => {
|
||||||
if (act.action === "edit") {
|
if (act.action === "edit") {
|
||||||
setIsEditModal({ [item.objectId]: true });
|
setIsEditModal({ [item.objectId]: true });
|
||||||
@@ -163,16 +178,16 @@ const TeamList = () => {
|
|||||||
setTeamList(newArray);
|
setTeamList(newArray);
|
||||||
try {
|
try {
|
||||||
await Parse.Cloud.run("updateteam", {
|
await Parse.Cloud.run("updateteam", {
|
||||||
IsActive: !IsActive,
|
IsActive: !IsActive === false ? "false" : "true",
|
||||||
TeamId: team.objectId
|
TeamId: team.objectId
|
||||||
});
|
});
|
||||||
// console.log("teamRes ", teamRes);
|
// console.log("teamRes ", teamRes);
|
||||||
setIsAlert({
|
setIsAlert({
|
||||||
type: !IsActive === false ? "danger" : "success",
|
type: !IsActive === false ? "danger" : "success",
|
||||||
msg: !IsActive === false ? "Team disabled." : "Team enabled."
|
msg: !IsActive === false ? t("team-disabled") : t("team-enabled")
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsAlert({ type: "danger", msg: "something went wrong." });
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
console.log("err in disable team", err);
|
console.log("err in disable team", err);
|
||||||
} finally {
|
} finally {
|
||||||
setIsActLoader({});
|
setIsActLoader({});
|
||||||
@@ -200,10 +215,10 @@ const TeamList = () => {
|
|||||||
const data = { Name: team.Name, TeamId: team.objectId };
|
const data = { Name: team.Name, TeamId: team.objectId };
|
||||||
await Parse.Cloud.run("updateteam", data);
|
await Parse.Cloud.run("updateteam", data);
|
||||||
// console.log("updateTeamRes ", updateTeamRes);
|
// console.log("updateTeamRes ", updateTeamRes);
|
||||||
setIsAlert({ type: "success", msg: "Team Update successfully." });
|
setIsAlert({ type: "success", msg: t("Team-update-successfully") });
|
||||||
} catch (Err) {
|
} catch (Err) {
|
||||||
console.log("Err in update team name"), Err;
|
console.log("Err in update team name"), Err;
|
||||||
setIsAlert({ type: "danger", msg: "Something went wrong." });
|
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||||
} finally {
|
} finally {
|
||||||
setIsActLoader({});
|
setIsActLoader({});
|
||||||
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||||
@@ -222,20 +237,16 @@ const TeamList = () => {
|
|||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isSubscribe && isEnableSubscription && !isLoader && (
|
{validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
|
||||||
<>
|
<>
|
||||||
{isAdmin ? (
|
{isAdmin ? (
|
||||||
<div className="p-2 w-full 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">
|
||||||
{isAlert.msg && (
|
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
|
||||||
<Alert type={isAlert.type}>
|
|
||||||
<div className="ml-3">{isAlert.msg}</div>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
<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">
|
||||||
Teams{" "}
|
{t("report-name.Teams")}
|
||||||
<span className="text-xs md:text-[13px] font-normal">
|
<span className="text-xs md:text-[13px] font-normal">
|
||||||
<Tooltip message={"Teams"} />
|
<Tooltip message={t("report-heading.Team")} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -251,7 +262,9 @@ const TeamList = () => {
|
|||||||
<tr className="border-y-[1px]">
|
<tr className="border-y-[1px]">
|
||||||
{heading?.map((item, index) => (
|
{heading?.map((item, index) => (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
<th className="px-4 py-2">{item}</th>
|
<th className="px-4 py-2">
|
||||||
|
{t(`report-heading.${item}`)}
|
||||||
|
</th>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -286,16 +299,16 @@ const TeamList = () => {
|
|||||||
{isActiveModal[item.objectId] && (
|
{isActiveModal[item.objectId] && (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen
|
isOpen
|
||||||
title={"Team status"}
|
title={t("Team status")}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
>
|
>
|
||||||
<div className="m-[20px]">
|
<div className="m-[20px]">
|
||||||
<div className="text-lg font-normal text-black">
|
<div className="text-lg font-normal text-black">
|
||||||
Are you sure you want to{" "}
|
{t("are-you-sure")}{" "}
|
||||||
{item?.IsActive
|
{item?.IsActive
|
||||||
? "disable"
|
? t("disable")
|
||||||
: "enable"}{" "}
|
: t("enable")}{" "}
|
||||||
this team?
|
{t("this-team")}
|
||||||
</div>
|
</div>
|
||||||
<hr className="bg-[#ccc] mt-4 " />
|
<hr className="bg-[#ccc] mt-4 " />
|
||||||
<div className="flex items-center mt-3 gap-2 text-white">
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
@@ -305,13 +318,13 @@ const TeamList = () => {
|
|||||||
}
|
}
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
Yes
|
{t("yes")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
className="op-btn op-btn-secondary"
|
className="op-btn op-btn-secondary"
|
||||||
>
|
>
|
||||||
No
|
{t("no")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -341,7 +354,7 @@ const TeamList = () => {
|
|||||||
{isEditModal[item.objectId] && (
|
{isEditModal[item.objectId] && (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen
|
isOpen
|
||||||
title={"Edit Team"}
|
title={t("edit-team")}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
>
|
>
|
||||||
<form
|
<form
|
||||||
@@ -351,7 +364,7 @@ const TeamList = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<label className="text-xs font-semibold text-base-content ml-1">
|
<label className="text-xs font-semibold text-base-content ml-1">
|
||||||
Name of Team{" "}
|
{t("name-of-team")}{" "}
|
||||||
<span className="text-[red] text-[13px]">
|
<span className="text-[red] text-[13px]">
|
||||||
*
|
*
|
||||||
</span>
|
</span>
|
||||||
@@ -362,13 +375,21 @@ const TeamList = () => {
|
|||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
handleEditChange(e, item)
|
handleEditChange(e, item)
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(
|
||||||
|
t("input-required")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onInput={(e) =>
|
||||||
|
e.target.setCustomValidity("")
|
||||||
|
}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="op-btn op-btn-primary mt-3"
|
className="op-btn op-btn-primary mt-3"
|
||||||
>
|
>
|
||||||
Save
|
{t("save")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
@@ -389,7 +410,7 @@ const TeamList = () => {
|
|||||||
onClick={() => paginateBack()}
|
onClick={() => paginateBack()}
|
||||||
className="op-join-item op-btn op-btn-sm"
|
className="op-join-item op-btn op-btn-sm"
|
||||||
>
|
>
|
||||||
Prev
|
{t("prev")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{pageNumbers.map((x, i) => (
|
{pageNumbers.map((x, i) => (
|
||||||
@@ -409,7 +430,7 @@ const TeamList = () => {
|
|||||||
onClick={() => paginateFront()}
|
onClick={() => paginateFront()}
|
||||||
className="op-join-item op-btn op-btn-sm"
|
className="op-join-item op-btn op-btn-sm"
|
||||||
>
|
>
|
||||||
Next
|
{t("next")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -426,11 +447,13 @@ const TeamList = () => {
|
|||||||
alt="img"
|
alt="img"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm font-semibold">No Data Available</div>
|
<div className="text-sm font-semibold">
|
||||||
|
{t("no-data-avaliable")}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Add Team"}
|
title={t("add-team")}
|
||||||
isOpen={isModal}
|
isOpen={isModal}
|
||||||
handleClose={handleFormModal}
|
handleClose={handleFormModal}
|
||||||
>
|
>
|
||||||
@@ -447,15 +470,17 @@ const TeamList = () => {
|
|||||||
<h1 className="text-[60px] lg:text-[120px] font-semibold">
|
<h1 className="text-[60px] lg:text-[120px] font-semibold">
|
||||||
404
|
404
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-[30px] lg:text-[50px]">Page Not Found</p>
|
<p className="text-[30px] lg:text-[50px]">
|
||||||
|
{t("page-not-found")}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isSubscribe && isEnableSubscription && !isLoader && (
|
{isEnableSubscription && !validplan[isSubscribe.plan] && !isLoader && (
|
||||||
<div data-tut="apisubscribe">
|
<div data-tut="apisubscribe">
|
||||||
<SubscribeCard plan={"TEAMS"} price={"20"} />
|
<SubscribeCard plan="TEAMS" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import { HTML5Backend } from "react-dnd-html5-backend";
|
|||||||
import { useDrag, useDrop } from "react-dnd";
|
import { useDrag, useDrop } from "react-dnd";
|
||||||
import WidgetComponent from "../components/pdf/WidgetComponent";
|
import WidgetComponent from "../components/pdf/WidgetComponent";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|
||||||
import HandleError from "../primitives/HandleError";
|
|
||||||
import SignerListPlace from "../components/pdf/SignerListPlace";
|
import SignerListPlace from "../components/pdf/SignerListPlace";
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
||||||
@@ -24,22 +22,35 @@ import {
|
|||||||
addWidgetOptions,
|
addWidgetOptions,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
fetchSubscription
|
fetchSubscription,
|
||||||
|
getContainerScale,
|
||||||
|
convertBase64ToFile,
|
||||||
|
rotatePdfPage,
|
||||||
|
onClickZoomOut,
|
||||||
|
onClickZoomIn,
|
||||||
|
handleRemoveWidgets,
|
||||||
|
handleRotateWarning
|
||||||
} 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";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import LinkUserModal from "../primitives/LinkUserModal";
|
|
||||||
import EditTemplate from "../components/pdf/EditTemplate";
|
import EditTemplate from "../components/pdf/EditTemplate";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
|
||||||
import AddRoleModal from "../components/pdf/AddRoleModal";
|
import AddRoleModal from "../components/pdf/AddRoleModal";
|
||||||
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|
||||||
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import PdfZoom from "../components/pdf/PdfZoom";
|
import PdfZoom from "../components/pdf/PdfZoom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import RotateAlert from "../components/RotateAlert";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||||
|
import LinkUserModal from "../primitives/LinkUserModal";
|
||||||
|
|
||||||
const TemplatePlaceholder = () => {
|
const TemplatePlaceholder = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isHeader = useSelector((state) => state.showHeader);
|
const isHeader = useSelector((state) => state.showHeader);
|
||||||
const { templateId } = useParams();
|
const { templateId } = useParams();
|
||||||
@@ -52,15 +63,18 @@ const TemplatePlaceholder = () => {
|
|||||||
const [xySignature, setXYSignature] = useState({});
|
const [xySignature, setXYSignature] = useState({});
|
||||||
const [dragKey, setDragKey] = useState();
|
const [dragKey, setDragKey] = useState();
|
||||||
const [signersdata, setSignersData] = useState([]);
|
const [signersdata, setSignersData] = useState([]);
|
||||||
const [signerObjId, setSignerObjId] = useState();
|
|
||||||
const [signerPos, setSignerPos] = useState([]);
|
const [signerPos, setSignerPos] = useState([]);
|
||||||
const [isSelectListId, setIsSelectId] = useState();
|
const [isSelectListId, setIsSelectId] = useState();
|
||||||
const [isSendAlert, setIsSendAlert] = useState(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({
|
||||||
|
status: false,
|
||||||
|
degree: 0
|
||||||
|
});
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: t("loading-mssg")
|
||||||
});
|
});
|
||||||
const [handleError, setHandleError] = useState();
|
const [handleError, setHandleError] = useState();
|
||||||
const [currentEmail, setCurrentEmail] = useState();
|
const [currentEmail, setCurrentEmail] = useState();
|
||||||
@@ -70,7 +84,6 @@ const TemplatePlaceholder = () => {
|
|||||||
const [tourStatus, setTourStatus] = useState([]);
|
const [tourStatus, setTourStatus] = useState([]);
|
||||||
const [signerUserId, setSignerUserId] = useState();
|
const [signerUserId, setSignerUserId] = useState();
|
||||||
const [pdfOriginalWH, setPdfOriginalWH] = useState([]);
|
const [pdfOriginalWH, setPdfOriginalWH] = useState([]);
|
||||||
const [contractName, setContractName] = useState("");
|
|
||||||
const [containerWH, setContainerWH] = useState();
|
const [containerWH, setContainerWH] = useState();
|
||||||
const signRef = useRef(null);
|
const signRef = useRef(null);
|
||||||
const dragRef = useRef(null);
|
const dragRef = useRef(null);
|
||||||
@@ -88,6 +101,7 @@ 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 color = [
|
const color = [
|
||||||
"#93a3db",
|
"#93a3db",
|
||||||
"#e6c3db",
|
"#e6c3db",
|
||||||
@@ -152,14 +166,6 @@ 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 senderUser =
|
|
||||||
localStorage.getItem(
|
|
||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
|
||||||
) &&
|
|
||||||
localStorage.getItem(
|
|
||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
|
||||||
);
|
|
||||||
const jsonSender = JSON.parse(senderUser);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplate();
|
fetchTemplate();
|
||||||
@@ -186,21 +192,25 @@ const TemplatePlaceholder = () => {
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [divRef.current, isHeader]);
|
}, [divRef.current, isHeader]);
|
||||||
|
|
||||||
|
const handleNavigation = () => {
|
||||||
|
navigate("/subscription");
|
||||||
|
};
|
||||||
async function checkIsSubscribed() {
|
async function checkIsSubscribed() {
|
||||||
const res = await fetchSubscription();
|
const res = await fetchSubscription();
|
||||||
const freeplan = res.plan;
|
const plan = res.plan;
|
||||||
const billingDate = res.billingDate;
|
const billingDate = res.billingDate;
|
||||||
if (freeplan === "freeplan") {
|
if (plan === "freeplan") {
|
||||||
return true;
|
return true;
|
||||||
} else if (billingDate) {
|
} else if (billingDate) {
|
||||||
if (new Date(billingDate) > new Date()) {
|
if (new Date(billingDate) > new Date()) {
|
||||||
setIsSubscribe(true);
|
setIsSubscribe(true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handleNavigation(plan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`);
|
handleNavigation(plan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `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
|
||||||
@@ -230,8 +240,6 @@ const TemplatePlaceholder = () => {
|
|||||||
setPdfDetails(documentData);
|
setPdfDetails(documentData);
|
||||||
setIsSigners(true);
|
setIsSigners(true);
|
||||||
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
||||||
setSignerObjId(documentData[0].Signers[0].objectId);
|
|
||||||
setContractName(documentData[0].Signers[0].className);
|
|
||||||
setIsSelectId(0);
|
setIsSelectId(0);
|
||||||
if (
|
if (
|
||||||
documentData[0].Placeholders &&
|
documentData[0].Placeholders &&
|
||||||
@@ -299,10 +307,10 @@ const TemplatePlaceholder = () => {
|
|||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
} else {
|
} else {
|
||||||
setHandleError("No Data Found!");
|
setHandleError(t("no-data-avaliable"));
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
@@ -311,12 +319,12 @@ const TemplatePlaceholder = () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
if (err?.response?.data?.code === 101) {
|
if (err?.response?.data?.code === 101) {
|
||||||
setHandleError("Error: Template not found!");
|
setHandleError(t("no-data-avaliable"));
|
||||||
} else {
|
} else {
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const res = await contractUsers(jsonSender.email);
|
const res = await contractUsers();
|
||||||
if (res[0] && res.length) {
|
if (res[0] && res.length) {
|
||||||
setSignerUserId(res[0].objectId);
|
setSignerUserId(res[0].objectId);
|
||||||
setCurrentEmail(res[0].Email);
|
setCurrentEmail(res[0].Email);
|
||||||
@@ -338,10 +346,10 @@ const TemplatePlaceholder = () => {
|
|||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
} else if (res.length === 0) {
|
} else if (res.length === 0) {
|
||||||
setHandleError("No Data Found!");
|
setHandleError(t("no-data-avaliable"));
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
isLoad: false
|
isLoad: false
|
||||||
};
|
};
|
||||||
@@ -364,26 +372,25 @@ const TemplatePlaceholder = () => {
|
|||||||
if (signer) {
|
if (signer) {
|
||||||
const posZIndex = zIndex + 1;
|
const posZIndex = zIndex + 1;
|
||||||
setZIndex(posZIndex);
|
setZIndex(posZIndex);
|
||||||
const getPdfPageWidth = pdfOriginalWH.find(
|
const containerScale = getContainerScale(
|
||||||
(data) => data.pageNumber === pageNumber
|
pdfOriginalWH,
|
||||||
|
pageNumber,
|
||||||
|
containerWH
|
||||||
);
|
);
|
||||||
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
|
|
||||||
const key = randomId();
|
const key = randomId();
|
||||||
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
|
||||||
const dragTypeValue = item?.text ? item.text : monitor.type;
|
const dragTypeValue = item?.text ? item.text : monitor.type;
|
||||||
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
|
const widgetWidth = defaultWidthHeight(dragTypeValue).width;
|
||||||
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
|
const widgetHeight = defaultWidthHeight(dragTypeValue).height;
|
||||||
let dropData = [];
|
let dropData = [],
|
||||||
|
currentPagePosition;
|
||||||
let placeHolder;
|
let placeHolder;
|
||||||
if (item === "onclick") {
|
if (item === "onclick") {
|
||||||
|
// `getBoundingClientRect()` is used to get accurate measurement height of the div
|
||||||
|
const divHeight = divRef.current.getBoundingClientRect().height;
|
||||||
const dropObj = {
|
const dropObj = {
|
||||||
//onclick put placeholder center on pdf
|
//onclick put placeholder center on pdf
|
||||||
xPosition:
|
xPosition: widgetWidth / 4 + containerWH.width / 2,
|
||||||
(containerWH.width / 2 - widgetWidth / 2) /
|
yPosition: widgetHeight + divHeight / 2,
|
||||||
(containerScale * scale),
|
|
||||||
yPosition:
|
|
||||||
(containerWH.height / 2 - widgetHeight / 2) /
|
|
||||||
(containerScale * scale),
|
|
||||||
isStamp:
|
isStamp:
|
||||||
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
|
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
|
||||||
key: key,
|
key: key,
|
||||||
@@ -434,65 +441,40 @@ const TemplatePlaceholder = () => {
|
|||||||
pos: dropData
|
pos: dropData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const { blockColor, Role } = signer;
|
let filterSignerPos = signerPos.find((data) => data.Id === uniqueId);
|
||||||
//adding placholder in existing signer pos array (placaholder)
|
const getPlaceHolder = filterSignerPos?.placeHolder;
|
||||||
if (filterSignerPos.length > 0) {
|
if (getPlaceHolder) {
|
||||||
const getPlaceHolder = filterSignerPos[0].placeHolder;
|
//checking exist placeholder on same page
|
||||||
|
currentPagePosition = getPlaceHolder.find(
|
||||||
|
(data) => data.pageNumber === pageNumber
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//checking current page has already some placeholders then update that placeholder and add upcoming placehoder position
|
||||||
|
if (getPlaceHolder && currentPagePosition) {
|
||||||
const updatePlace = getPlaceHolder.filter(
|
const updatePlace = getPlaceHolder.filter(
|
||||||
(data) => data.pageNumber !== pageNumber
|
(data) => data.pageNumber !== pageNumber
|
||||||
);
|
);
|
||||||
const getPageNumer = getPlaceHolder.filter(
|
const getPos = currentPagePosition?.pos;
|
||||||
(data) => data.pageNumber === pageNumber
|
const newSignPos = getPos.concat(dropData);
|
||||||
|
let xyPos = {
|
||||||
|
pageNumber: pageNumber,
|
||||||
|
pos: newSignPos
|
||||||
|
};
|
||||||
|
updatePlace.push(xyPos);
|
||||||
|
const updatesignerPos = signerPos.map((x) =>
|
||||||
|
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
|
||||||
);
|
);
|
||||||
|
setSignerPos(updatesignerPos);
|
||||||
//add entry of position for same signer on multiple page
|
|
||||||
if (getPageNumer.length > 0) {
|
|
||||||
const getPos = getPageNumer[0].pos;
|
|
||||||
const newSignPos = getPos.concat(dropData);
|
|
||||||
let xyPos = {
|
|
||||||
pageNumber: pageNumber,
|
|
||||||
pos: newSignPos
|
|
||||||
};
|
|
||||||
updatePlace.push(xyPos);
|
|
||||||
const updatesignerPos = signerPos.map((x) =>
|
|
||||||
x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x
|
|
||||||
);
|
|
||||||
setSignerPos(updatesignerPos);
|
|
||||||
} else {
|
|
||||||
const updatesignerPos = signerPos.map((x) =>
|
|
||||||
x.Id === uniqueId
|
|
||||||
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
|
|
||||||
: x
|
|
||||||
);
|
|
||||||
setSignerPos(updatesignerPos);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//adding new placeholder for selected signer in pos array (placeholder)
|
//else condition to add placeholder widgets on multiple page first time
|
||||||
let placeHolderPos;
|
const updatesignerPos = signerPos.map((x) =>
|
||||||
if (contractName) {
|
x.Id === uniqueId && x?.placeHolder
|
||||||
placeHolderPos = {
|
? { ...x, placeHolder: [...x.placeHolder, placeHolder] }
|
||||||
signerPtr: {
|
: x.Id === uniqueId
|
||||||
__type: "Pointer",
|
? { ...x, placeHolder: [placeHolder] }
|
||||||
className: `${contractName}`,
|
: x
|
||||||
objectId: signerObjId
|
);
|
||||||
},
|
setSignerPos(updatesignerPos);
|
||||||
signerObjId: signerObjId,
|
|
||||||
blockColor: blockColor ? blockColor : color[isSelectListId],
|
|
||||||
placeHolder: [placeHolder],
|
|
||||||
Role: Role ? Role : roleName,
|
|
||||||
Id: uniqueId
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
placeHolderPos = {
|
|
||||||
signerPtr: {},
|
|
||||||
signerObjId: "",
|
|
||||||
blockColor: blockColor ? blockColor : color[isSelectListId],
|
|
||||||
placeHolder: [placeHolder],
|
|
||||||
Role: Role ? Role : roleName,
|
|
||||||
Id: uniqueId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
setSignerPos((prev) => [...prev, placeHolderPos]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragTypeValue === "dropdown") {
|
if (dragTypeValue === "dropdown") {
|
||||||
@@ -526,7 +508,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" }
|
||||||
}
|
}
|
||||||
@@ -561,10 +543,11 @@ const TemplatePlaceholder = () => {
|
|||||||
updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace);
|
updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace);
|
||||||
const signId = signerId; //? signerId : signerObjId;
|
const signId = signerId; //? signerId : signerObjId;
|
||||||
const keyValue = key ? key : dragKey;
|
const keyValue = key ? key : dragKey;
|
||||||
const getPdfPageWidth = pdfOriginalWH.find(
|
const containerScale = getContainerScale(
|
||||||
(data) => data.pageNumber === pageNumber
|
pdfOriginalWH,
|
||||||
|
pageNumber,
|
||||||
|
containerWH
|
||||||
);
|
);
|
||||||
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
|
|
||||||
if (keyValue >= 0) {
|
if (keyValue >= 0) {
|
||||||
const filterSignerPos = updateSignPos.filter(
|
const filterSignerPos = updateSignPos.filter(
|
||||||
(data) => data.Id === signId
|
(data) => data.Id === signId
|
||||||
@@ -618,10 +601,6 @@ const TemplatePlaceholder = () => {
|
|||||||
//function for delete signature block
|
//function for delete signature block
|
||||||
const handleDeleteSign = (key, Id) => {
|
const handleDeleteSign = (key, Id) => {
|
||||||
const updateData = [];
|
const updateData = [];
|
||||||
// const filterSignerPos = signerPos.filter(
|
|
||||||
// (data) => data.signerObjId === signerId
|
|
||||||
// );
|
|
||||||
|
|
||||||
const filterSignerPos = signerPos.filter((data) => data.Id === Id);
|
const filterSignerPos = signerPos.filter((data) => data.Id === Id);
|
||||||
|
|
||||||
if (filterSignerPos.length > 0) {
|
if (filterSignerPos.length > 0) {
|
||||||
@@ -654,11 +633,11 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
setSignerPos(newUpdateSigner);
|
setSignerPos(newUpdateSigner);
|
||||||
} else {
|
} else {
|
||||||
const updateFilter = signerPos.filter((data) => data.Id !== Id);
|
|
||||||
const getRemainPage = filterSignerPos[0].placeHolder.filter(
|
const getRemainPage = filterSignerPos[0].placeHolder.filter(
|
||||||
(data) => data.pageNumber !== pageNumber
|
(data) => data.pageNumber !== pageNumber
|
||||||
);
|
);
|
||||||
|
//condition to check placeholder length is greater than 1 do not need to remove whole placeholder
|
||||||
|
//array only resove particular widgets
|
||||||
if (getRemainPage && getRemainPage.length > 0) {
|
if (getRemainPage && getRemainPage.length > 0) {
|
||||||
const newUpdatePos = filterSignerPos.map((obj) => {
|
const newUpdatePos = filterSignerPos.map((obj) => {
|
||||||
if (obj.Id === Id) {
|
if (obj.Id === Id) {
|
||||||
@@ -672,7 +651,16 @@ const TemplatePlaceholder = () => {
|
|||||||
|
|
||||||
setSignerPos(signerupdate);
|
setSignerPos(signerupdate);
|
||||||
} else {
|
} else {
|
||||||
setSignerPos(updateFilter);
|
const updatedData = signerPos.map((item) => {
|
||||||
|
if (item.Id === Id) {
|
||||||
|
// Create a copy of the item object and delete the placeHolder field
|
||||||
|
const updatedItem = { ...item };
|
||||||
|
delete updatedItem.placeHolder;
|
||||||
|
return updatedItem;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
setSignerPos(updatedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,19 +682,11 @@ const TemplatePlaceholder = () => {
|
|||||||
const touch = e.touches[0]; // Get the first touch point
|
const touch = e.touches[0]; // Get the first touch point
|
||||||
mouseX = touch.clientX - divRect.left;
|
mouseX = touch.clientX - divRect.left;
|
||||||
mouseY = touch.clientY - divRect.top;
|
mouseY = touch.clientY - divRect.top;
|
||||||
setSignBtnPosition([
|
setSignBtnPosition([{ xPos: mouseX, yPos: mouseY }]);
|
||||||
{
|
|
||||||
xPos: mouseX,
|
|
||||||
yPos: mouseY
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
mouseX = e.clientX - divRect.left;
|
mouseX = e.clientX - divRect.left;
|
||||||
mouseY = e.clientY - divRect.top;
|
mouseY = e.clientY - divRect.top;
|
||||||
const xyPosition = {
|
const xyPosition = { xPos: mouseX, yPos: mouseY };
|
||||||
xPos: mouseX,
|
|
||||||
yPos: mouseY
|
|
||||||
};
|
|
||||||
setXYSignature(xyPosition);
|
setXYSignature(xyPosition);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -715,20 +695,54 @@ const TemplatePlaceholder = () => {
|
|||||||
const handleMouseLeave = () => {
|
const handleMouseLeave = () => {
|
||||||
setSignBtnPosition([xySignature]);
|
setSignBtnPosition([xySignature]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const alertSendEmail = async () => {
|
const alertSendEmail = async () => {
|
||||||
if (signerPos.length !== signersdata.length) {
|
const isPlaceholderExist = signerPos.every((data) => data.placeHolder);
|
||||||
setIsSendAlert(true);
|
if (isPlaceholderExist) {
|
||||||
} else {
|
|
||||||
handleSaveTemplate();
|
handleSaveTemplate();
|
||||||
|
} else {
|
||||||
|
setIsSendAlert(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
if (signerPos?.length > 0) {
|
||||||
|
autosavedetails();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [signerPos]);
|
||||||
|
|
||||||
|
// `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 () => {
|
||||||
|
let signers = [];
|
||||||
|
if (signersdata?.length > 0) {
|
||||||
|
signersdata.forEach((x) => {
|
||||||
|
if (x.objectId) {
|
||||||
|
const obj = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "contracts_Contactbook",
|
||||||
|
objectId: x.objectId
|
||||||
|
};
|
||||||
|
signers.push(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const templateCls = new Parse.Object("contracts_Template");
|
||||||
|
templateCls.id = templateId;
|
||||||
|
templateCls.set("Placeholders", signerPos);
|
||||||
|
templateCls.set("Signers", signers);
|
||||||
|
await templateCls.save();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("error in autosave template", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSaveTemplate = async () => {
|
const handleSaveTemplate = async () => {
|
||||||
if (signersdata?.length) {
|
if (signersdata?.length) {
|
||||||
const loadObj = {
|
const loadObj = { isLoad: true, message: t("loading-mssg") };
|
||||||
isLoad: true,
|
|
||||||
message: "This might take some time"
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
setIsSendAlert(false);
|
setIsSendAlert(false);
|
||||||
let signers = [];
|
let signers = [];
|
||||||
@@ -744,6 +758,17 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let pdfUrl = pdfDetails[0]?.URL;
|
||||||
|
if (pdfRotateBase64) {
|
||||||
|
try {
|
||||||
|
pdfUrl = await convertBase64ToFile(
|
||||||
|
pdfDetails[0].Name,
|
||||||
|
pdfRotateBase64
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const data = {
|
const data = {
|
||||||
Placeholders: signerPos,
|
Placeholders: signerPos,
|
||||||
@@ -754,26 +779,23 @@ const TemplatePlaceholder = () => {
|
|||||||
SendinOrder: pdfDetails[0]?.SendinOrder || false,
|
SendinOrder: pdfDetails[0]?.SendinOrder || false,
|
||||||
AutomaticReminders: pdfDetails[0]?.AutomaticReminders,
|
AutomaticReminders: pdfDetails[0]?.AutomaticReminders,
|
||||||
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,
|
||||||
|
IsTourEnabled: pdfDetails[0]?.IsTourEnabled === true ? true : false,
|
||||||
|
URL: pdfUrl
|
||||||
};
|
};
|
||||||
const updateTemplate = new Parse.Object("contracts_Template");
|
const updateTemplate = new Parse.Object("contracts_Template");
|
||||||
updateTemplate.id = templateId;
|
updateTemplate.id = templateId;
|
||||||
for (const key in data) {
|
for (const key in data) {
|
||||||
updateTemplate.set(key, data[key]);
|
updateTemplate.set(key, data[key]);
|
||||||
}
|
}
|
||||||
await updateTemplate.save(null, {
|
await updateTemplate.save();
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
|
||||||
});
|
|
||||||
|
|
||||||
setIsCreateDocModal(true);
|
setIsCreateDocModal(true);
|
||||||
setIsMailSend(true);
|
setIsMailSend(true);
|
||||||
const loadObj = {
|
setIsLoading({ isLoad: false });
|
||||||
isLoad: false
|
|
||||||
};
|
|
||||||
setIsLoading(loadObj);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
alert("Something went wrong, please try again later.");
|
alert(t("something-went-wrong-mssg"));
|
||||||
console.log("error", e);
|
console.log("error", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -791,7 +813,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourAddbtn"]',
|
selector: '[data-tut="reactourAddbtn"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Clicking "Add role" button will allow you to add various signer roles. You can attach users to each role in subsequent steps.`}
|
message={t("tour-mssg.template-placeholder-1")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -803,7 +825,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourFirst"]',
|
selector: '[data-tut="reactourFirst"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Once roles are added, select a role from list to add a place-holder where he is supposed to sign. The placeholder will appear in the same colour as the role name once you drop it on the document.`}
|
message={t("tour-mssg.template-placeholder-2")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -815,7 +837,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="addWidgets"]',
|
selector: '[data-tut="addWidgets"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Drag or click on a field to add it to the document.`}
|
message={t("tour-mssg.template-placeholder-3")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -826,7 +848,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourThird"]',
|
selector: '[data-tut="reactourThird"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Drag the placeholder for a role anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`}
|
message={t("tour-mssg.template-placeholder-4")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -837,7 +859,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="headerArea"]',
|
selector: '[data-tut="headerArea"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Clicking ‘Next’ will store the current template. After saving, you’ll be prompted to create a new document from this template if you wish.`}
|
message={t("tour-mssg.template-placeholder-5")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -894,19 +916,31 @@ const TemplatePlaceholder = () => {
|
|||||||
const handleCreateDocModal = async () => {
|
const handleCreateDocModal = async () => {
|
||||||
setIsCreateDocModal(false);
|
setIsCreateDocModal(false);
|
||||||
setIsCreateDoc(true);
|
setIsCreateDoc(true);
|
||||||
|
let pdfUrl = pdfDetails[0]?.URL;
|
||||||
|
if (pdfRotateBase64) {
|
||||||
|
try {
|
||||||
|
pdfUrl = await convertBase64ToFile(pdfDetails[0].Name, pdfRotateBase64);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error to convertBase64ToFile in placeholder flow", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
// handle create document
|
// handle create document
|
||||||
const res = await createDocument(pdfDetails, signerPos, signersdata);
|
const res = await createDocument(
|
||||||
|
pdfDetails,
|
||||||
|
signerPos,
|
||||||
|
signersdata,
|
||||||
|
pdfUrl
|
||||||
|
);
|
||||||
if (res.status === "success") {
|
if (res.status === "success") {
|
||||||
navigate(`/placeHolderSign/${res.id}`, {
|
navigate(`/placeHolderSign/${res.id}`, {
|
||||||
state: { title: "Use Template" }
|
state: { title: "Use Template" }
|
||||||
});
|
});
|
||||||
setIsCreateDoc(false);
|
setIsCreateDoc(false);
|
||||||
} else {
|
} else {
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
setIsCreateDoc(false);
|
setIsCreateDoc(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// `handleAddSigner` is used to open Add Role Modal
|
// `handleAddSigner` is used to open Add Role Modal
|
||||||
const handleAddSigner = () => {
|
const handleAddSigner = () => {
|
||||||
setIsModalRole(true);
|
setIsModalRole(true);
|
||||||
@@ -917,8 +951,6 @@ const TemplatePlaceholder = () => {
|
|||||||
// save Role in entry in signerList and user
|
// save Role in entry in signerList and user
|
||||||
const handleAddRole = (e) => {
|
const handleAddRole = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setSignerObjId("");
|
|
||||||
setContractName("");
|
|
||||||
const count = signersdata.length > 0 ? signersdata.length + 1 : 1;
|
const count = signersdata.length > 0 ? signersdata.length + 1 : 1;
|
||||||
const Id = randomId();
|
const Id = randomId();
|
||||||
const index = signersdata.length;
|
const index = signersdata.length;
|
||||||
@@ -928,6 +960,15 @@ const TemplatePlaceholder = () => {
|
|||||||
blockColor: color[index]
|
blockColor: color[index]
|
||||||
};
|
};
|
||||||
setSignersData((prevArr) => [...prevArr, obj]);
|
setSignersData((prevArr) => [...prevArr, obj]);
|
||||||
|
const signerPosObj = {
|
||||||
|
signerPtr: {},
|
||||||
|
signerObjId: "",
|
||||||
|
blockColor: color[index],
|
||||||
|
Role: roleName || "User " + count,
|
||||||
|
Id: Id
|
||||||
|
};
|
||||||
|
|
||||||
|
setSignerPos((prev) => [...prev, signerPosObj]);
|
||||||
setIsModalRole(false);
|
setIsModalRole(false);
|
||||||
setRoleName("");
|
setRoleName("");
|
||||||
setUniqueId(Id);
|
setUniqueId(Id);
|
||||||
@@ -959,11 +1000,12 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsMailSend(false);
|
setIsMailSend(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// `handleLinkUser` is used to open Add/Choose Signer Modal when user can link existing or new User with placeholder
|
// `handleLinkUser` is used to open Add/Choose Signer Modal when user can link existing or new User with placeholder
|
||||||
// and update entry in signersList
|
// and update entry in signersList
|
||||||
const handleLinkUser = (id) => {
|
const handleLinkUser = (id) => {
|
||||||
setIsAddUser({ [id]: true });
|
setIsAddUser({ [id]: true });
|
||||||
};
|
};
|
||||||
|
// `handleAddUser` is used to adduser
|
||||||
const handleAddUser = (data) => {
|
const handleAddUser = (data) => {
|
||||||
const signerPtr = {
|
const signerPtr = {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
@@ -1092,7 +1134,13 @@ const TemplatePlaceholder = () => {
|
|||||||
status: status,
|
status: status,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false
|
isHideLabel: isHideLabel || false,
|
||||||
|
fontSize:
|
||||||
|
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
||||||
|
fontColor:
|
||||||
|
fontColor ||
|
||||||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1124,7 +1172,13 @@ const TemplatePlaceholder = () => {
|
|||||||
},
|
},
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
isHideLabel: isHideLabel || false
|
isHideLabel: isHideLabel || false,
|
||||||
|
fontSize:
|
||||||
|
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
||||||
|
fontColor:
|
||||||
|
fontColor ||
|
||||||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1136,7 +1190,13 @@ const TemplatePlaceholder = () => {
|
|||||||
name: dropdownName,
|
name: dropdownName,
|
||||||
status: status,
|
status: status,
|
||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
defaultValue: defaultValue
|
defaultValue: defaultValue,
|
||||||
|
fontSize:
|
||||||
|
fontSize || currWidgetsDetails?.options?.fontSize || "12",
|
||||||
|
fontColor:
|
||||||
|
fontColor ||
|
||||||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1163,6 +1223,8 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setFontSize();
|
||||||
|
setFontColor();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleWidgetdefaultdata = (defaultdata) => {
|
const handleWidgetdefaultdata = (defaultdata) => {
|
||||||
@@ -1253,6 +1315,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setCurrWidgetsDetails({});
|
setCurrWidgetsDetails({});
|
||||||
handleNameModal();
|
handleNameModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNameModal = () => {
|
const handleNameModal = () => {
|
||||||
setIsNameModal(false);
|
setIsNameModal(false);
|
||||||
setCurrWidgetsDetails({});
|
setCurrWidgetsDetails({});
|
||||||
@@ -1261,6 +1324,38 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsCheckbox(false);
|
setIsCheckbox(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clickOnZoomIn = () => {
|
||||||
|
onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent);
|
||||||
|
};
|
||||||
|
const clickOnZoomOut = () => {
|
||||||
|
onClickZoomOut(zoomPercent, scale, setZoomPercent, setScale);
|
||||||
|
};
|
||||||
|
//`handleRotationFun` function is used to roatate pdf particular page
|
||||||
|
const handleRotationFun = async (rotateDegree) => {
|
||||||
|
const isRotate = handleRotateWarning(signerPos, pageNumber);
|
||||||
|
if (isRotate) {
|
||||||
|
setIsRotate({ status: true, degree: rotateDegree });
|
||||||
|
} else {
|
||||||
|
const urlDetails = await rotatePdfPage(
|
||||||
|
pdfDetails[0].URL,
|
||||||
|
rotateDegree,
|
||||||
|
pageNumber - 1,
|
||||||
|
pdfRotateBase64
|
||||||
|
);
|
||||||
|
setPdfRotatese64(urlDetails.base64);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleRemovePlaceholder = async () => {
|
||||||
|
handleRemoveWidgets(setSignerPos, signerPos, pageNumber, setIsRotate);
|
||||||
|
const urlDetails = await rotatePdfPage(
|
||||||
|
pdfDetails[0].URL,
|
||||||
|
isRotate.degree,
|
||||||
|
pageNumber - 1,
|
||||||
|
pdfRotateBase64
|
||||||
|
);
|
||||||
|
setPdfRotatese64(urlDetails.base64);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title={"Template"} />
|
<Title title={"Template"} />
|
||||||
@@ -1308,56 +1403,47 @@ const TemplatePlaceholder = () => {
|
|||||||
{/* 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">
|
||||||
<PdfZoom
|
<PdfZoom
|
||||||
setScale={setScale}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
scale={scale}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
containerWH={containerWH}
|
handleRotationFun={handleRotationFun}
|
||||||
setZoomPercent={setZoomPercent}
|
|
||||||
zoomPercent={zoomPercent}
|
|
||||||
/>
|
/>
|
||||||
<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}
|
isOpen={isSendAlert}
|
||||||
title={"Fields required"}
|
title={t("fields-required")}
|
||||||
handleClose={() => setIsSendAlert(false)}
|
handleClose={() => setIsSendAlert(false)}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px]">
|
<div className="h-full p-[20px]">
|
||||||
<p>
|
<p>{t("template-signature-field")}</p>
|
||||||
Please add at least one signature field for all roles.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={!IsReceipent}
|
isOpen={!IsReceipent}
|
||||||
title={"Roles"}
|
title={t("roles")}
|
||||||
handleClose={() => setIsReceipent(true)}
|
handleClose={() => setIsReceipent(true)}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px] text-center font-medium">
|
<div className="h-full p-[20px] text-center font-medium">
|
||||||
<p>Please add roles first</p>
|
<p>{t("template-role-alert")}</p>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
{/* this modal is used show send mail message and after send mail success message */}
|
{/* this modal is used show send mail message and after send mail success message */}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isCreateDocModal}
|
isOpen={isCreateDocModal}
|
||||||
title={"Create Document"}
|
title={t("create-document")}
|
||||||
handleClose={() => setIsCreateDocModal(false)}
|
handleClose={() => setIsCreateDocModal(false)}
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px]">
|
<div className="h-full p-[20px]">
|
||||||
<p>
|
<p>{t("template-created-alert")}</p>
|
||||||
Do you want to create a document using the template you
|
|
||||||
just created ?
|
|
||||||
</p>
|
|
||||||
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
{currentEmail.length > 0 && (
|
{currentEmail.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => handleCreateDocModal()}
|
||||||
handleCreateDocModal();
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
Yes
|
{t("yes")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1367,7 +1453,7 @@ const TemplatePlaceholder = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-secondary ml-2"
|
className="op-btn op-btn-secondary ml-2"
|
||||||
>
|
>
|
||||||
No
|
{t("no")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -1376,28 +1462,24 @@ const TemplatePlaceholder = () => {
|
|||||||
{isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
|
{isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isShowEmail}
|
isOpen={isShowEmail}
|
||||||
title={"signers alert"}
|
title={t("signers-alert")}
|
||||||
handleClose={() => {
|
handleClose={() => setIsShowEmail(false)}
|
||||||
setIsShowEmail(false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="h-full p-[20px]">
|
<div className="h-full p-[20px]">
|
||||||
<p>Please select signer for add placeholder!</p>
|
<p>{t("template-creation-alert-1")}</p>
|
||||||
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setIsShowEmail(false)}
|
||||||
setIsShowEmail(false);
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary"
|
className="op-btn op-btn-primary"
|
||||||
>
|
>
|
||||||
Ok
|
{t("ok")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
<DropdownWidgetOption
|
<DropdownWidgetOption
|
||||||
type={radioButtonWidget}
|
type={radioButtonWidget}
|
||||||
title="Radio group"
|
title={t("radio-group")}
|
||||||
showDropdown={isRadio}
|
showDropdown={isRadio}
|
||||||
setShowDropdown={setIsRadio}
|
setShowDropdown={setIsRadio}
|
||||||
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
@@ -1405,10 +1487,14 @@ const TemplatePlaceholder = () => {
|
|||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
isSubscribe={isSubscribe}
|
isSubscribe={isSubscribe}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
/>
|
/>
|
||||||
<DropdownWidgetOption
|
<DropdownWidgetOption
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
title="Checkbox"
|
title={t("checkbox")}
|
||||||
showDropdown={isCheckbox}
|
showDropdown={isCheckbox}
|
||||||
setShowDropdown={setIsCheckbox}
|
setShowDropdown={setIsCheckbox}
|
||||||
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
@@ -1416,10 +1502,14 @@ const TemplatePlaceholder = () => {
|
|||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
isSubscribe={isSubscribe}
|
isSubscribe={isSubscribe}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
/>
|
/>
|
||||||
<DropdownWidgetOption
|
<DropdownWidgetOption
|
||||||
type="dropdown"
|
type="dropdown"
|
||||||
title="Dropdown options"
|
title={t("dropdown-options")}
|
||||||
showDropdown={showDropdown}
|
showDropdown={showDropdown}
|
||||||
setShowDropdown={setShowDropdown}
|
setShowDropdown={setShowDropdown}
|
||||||
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
|
||||||
@@ -1427,6 +1517,10 @@ const TemplatePlaceholder = () => {
|
|||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
isSubscribe={isSubscribe}
|
isSubscribe={isSubscribe}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
/>
|
/>
|
||||||
<PlaceholderCopy
|
<PlaceholderCopy
|
||||||
isPageCopy={isPageCopy}
|
isPageCopy={isPageCopy}
|
||||||
@@ -1436,12 +1530,11 @@ const TemplatePlaceholder = () => {
|
|||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
signKey={signKey}
|
signKey={signKey}
|
||||||
// signerObjId={signerObjId}
|
|
||||||
Id={uniqueId}
|
Id={uniqueId}
|
||||||
/>
|
/>
|
||||||
{/* pdf header which contain funish back button */}
|
{/* pdf header which contain funish back button */}
|
||||||
<Header
|
<Header
|
||||||
completeBtnTitle={"Next"}
|
completeBtnTitle={t("next")}
|
||||||
isPlaceholder={true}
|
isPlaceholder={true}
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
@@ -1455,6 +1548,9 @@ const TemplatePlaceholder = () => {
|
|||||||
currentSigner={true}
|
currentSigner={true}
|
||||||
setIsEditTemplate={handleEditTemplateModal}
|
setIsEditTemplate={handleEditTemplateModal}
|
||||||
dataTut4="reactourFour"
|
dataTut4="reactourFour"
|
||||||
|
handleRotationFun={handleRotationFun}
|
||||||
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
ref={divRef}
|
ref={divRef}
|
||||||
@@ -1486,7 +1582,6 @@ const TemplatePlaceholder = () => {
|
|||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
setIsPageCopy={setIsPageCopy}
|
setIsPageCopy={setIsPageCopy}
|
||||||
setSignKey={setSignKey}
|
setSignKey={setSignKey}
|
||||||
setSignerObjId={setSignerObjId}
|
|
||||||
isDragging={isDragging}
|
isDragging={isDragging}
|
||||||
setShowDropdown={setShowDropdown}
|
setShowDropdown={setShowDropdown}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
@@ -1500,6 +1595,12 @@ const TemplatePlaceholder = () => {
|
|||||||
setScale={setScale}
|
setScale={setScale}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
|
pdfRotateBase64={pdfRotateBase64}
|
||||||
|
fontSize={fontSize}
|
||||||
|
setFontSize={setFontSize}
|
||||||
|
fontColor={fontColor}
|
||||||
|
setFontColor={setFontColor}
|
||||||
|
isResize={isResize}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1524,9 +1625,7 @@ const TemplatePlaceholder = () => {
|
|||||||
signerPos={signerPos}
|
signerPos={signerPos}
|
||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
isSelectListId={isSelectListId}
|
isSelectListId={isSelectListId}
|
||||||
setSignerObjId={setSignerObjId}
|
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
setContractName={setContractName}
|
|
||||||
isSigners={isSigners}
|
isSigners={isSigners}
|
||||||
setIsShowEmail={setIsShowEmail}
|
setIsShowEmail={setIsShowEmail}
|
||||||
isMailSend={isMailSend}
|
isMailSend={isMailSend}
|
||||||
@@ -1538,7 +1637,7 @@ const TemplatePlaceholder = () => {
|
|||||||
handleDeleteUser={handleDeleteUser}
|
handleDeleteUser={handleDeleteUser}
|
||||||
handleRoleChange={handleRoleChange}
|
handleRoleChange={handleRoleChange}
|
||||||
handleOnBlur={handleOnBlur}
|
handleOnBlur={handleOnBlur}
|
||||||
title={"Roles"}
|
title={t("roles")}
|
||||||
initial={true}
|
initial={true}
|
||||||
isTemplateFlow={true}
|
isTemplateFlow={true}
|
||||||
sendInOrder={pdfDetails[0].SendinOrder}
|
sendInOrder={pdfDetails[0].SendinOrder}
|
||||||
@@ -1548,26 +1647,22 @@ const TemplatePlaceholder = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div className="w-[23%] bg-base-100 min-h-screen overflow-y-auto hide-scrollbar">
|
||||||
className={`w-[23%] bg-[#FFFFFF] min-h-screen overflow-y-auto hide-scrollbar`}
|
<div className="max-h-screen">
|
||||||
>
|
|
||||||
<div className={`max-h-screen`}>
|
|
||||||
<SignerListPlace
|
<SignerListPlace
|
||||||
isMailSend={isMailSend}
|
isMailSend={isMailSend}
|
||||||
signerPos={signerPos}
|
signerPos={signerPos}
|
||||||
setSignerPos={setSignerPos}
|
setSignerPos={setSignerPos}
|
||||||
signersdata={signersdata}
|
signersdata={signersdata}
|
||||||
isSelectListId={isSelectListId}
|
isSelectListId={isSelectListId}
|
||||||
setSignerObjId={setSignerObjId}
|
|
||||||
setRoleName={setRoleName}
|
setRoleName={setRoleName}
|
||||||
setIsSelectId={setIsSelectId}
|
setIsSelectId={setIsSelectId}
|
||||||
setContractName={setContractName}
|
|
||||||
handleAddSigner={handleAddSigner}
|
handleAddSigner={handleAddSigner}
|
||||||
setUniqueId={setUniqueId}
|
setUniqueId={setUniqueId}
|
||||||
handleDeleteUser={handleDeleteUser}
|
handleDeleteUser={handleDeleteUser}
|
||||||
handleRoleChange={handleRoleChange}
|
handleRoleChange={handleRoleChange}
|
||||||
handleOnBlur={handleOnBlur}
|
handleOnBlur={handleOnBlur}
|
||||||
title={"Roles"}
|
title={t("roles")}
|
||||||
sendInOrder={pdfDetails[0]?.SendinOrder}
|
sendInOrder={pdfDetails[0]?.SendinOrder}
|
||||||
setSignersData={setSignersData}
|
setSignersData={setSignersData}
|
||||||
blockColor={blockColor}
|
blockColor={blockColor}
|
||||||
@@ -1587,7 +1682,7 @@ const TemplatePlaceholder = () => {
|
|||||||
isDragStamp={isDragStamp}
|
isDragStamp={isDragStamp}
|
||||||
isSignYourself={false}
|
isSignYourself={false}
|
||||||
addPositionOfSignature={addPositionOfSignature}
|
addPositionOfSignature={addPositionOfSignature}
|
||||||
title={"Roles"}
|
title={t("roles")}
|
||||||
initial={true}
|
initial={true}
|
||||||
isTemplateFlow={true}
|
isTemplateFlow={true}
|
||||||
/>
|
/>
|
||||||
@@ -1598,7 +1693,6 @@ const TemplatePlaceholder = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div data-tut="reactourAddbtn--observe">
|
<div data-tut="reactourAddbtn--observe">
|
||||||
<AddRoleModal
|
<AddRoleModal
|
||||||
isModalRole={isModalRole}
|
isModalRole={isModalRole}
|
||||||
@@ -1619,7 +1713,7 @@ const TemplatePlaceholder = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Edit Template"}
|
title={t("edit-template")}
|
||||||
isOpen={isEditTemplate}
|
isOpen={isEditTemplate}
|
||||||
handleClose={handleEditTemplateModal}
|
handleClose={handleEditTemplateModal}
|
||||||
>
|
>
|
||||||
@@ -1642,6 +1736,11 @@ const TemplatePlaceholder = () => {
|
|||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
/>
|
/>
|
||||||
|
<RotateAlert
|
||||||
|
isRotate={isRotate.status}
|
||||||
|
setIsRotate={setIsRotate}
|
||||||
|
handleRemoveWidgets={handleRemovePlaceholder}
|
||||||
|
/>
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import Parse from "parse";
|
|||||||
import { NavLink, useNavigate } from "react-router-dom";
|
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";
|
||||||
const UpdateExistUserAdmin = () => {
|
const UpdateExistUserAdmin = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [formdata, setFormdata] = useState({ email: "", masterkey: "" });
|
const [formdata, setFormdata] = useState({ email: "", masterkey: "" });
|
||||||
const [loader, setLoader] = useState(true);
|
const [loader, setLoader] = useState(true);
|
||||||
@@ -14,14 +15,15 @@ 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 () => {
|
||||||
try {
|
try {
|
||||||
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);
|
||||||
@@ -41,19 +43,19 @@ const UpdateExistUserAdmin = () => {
|
|||||||
);
|
);
|
||||||
// console.log("updateUserAsAdmin ", updateUserAsAdmin);
|
// console.log("updateUserAsAdmin ", updateUserAsAdmin);
|
||||||
if (updateUserAsAdmin === "admin_created") {
|
if (updateUserAsAdmin === "admin_created") {
|
||||||
setIsAlert({ type: "success", msg: "Admin created" });
|
setIsAlert({ type: "success", msg: t("admin-created") });
|
||||||
navigate("/");
|
navigate("/");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in updateuserasadmin", err.code);
|
console.log("err in updateuserasadmin", err.code);
|
||||||
if (err.code === 404) {
|
if (err.code === 404) {
|
||||||
setIsAlert((prev) => ({ ...prev, msg: "Invalid masterkey" }));
|
setIsAlert((prev) => ({ ...prev, msg: t("invalid-masterkey") }));
|
||||||
} else if (err.code === 101) {
|
} else if (err.code === 101) {
|
||||||
setIsAlert((prev) => ({ ...prev, msg: "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: "Admin already exist" }));
|
setIsAlert((prev) => ({ ...prev, msg: t("admin-exists") }));
|
||||||
} else {
|
} else {
|
||||||
setErrMsg("Something went wrong.");
|
setErrMsg(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitLoading(false);
|
setIsSubmitLoading(false);
|
||||||
@@ -65,11 +67,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="h-screen flex justify-center">
|
<div className="h-screen flex justify-center">
|
||||||
<Title title={"Add Admin"} />
|
<Title title={"Add Admin"} />
|
||||||
{isAlert.msg && (
|
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
|
||||||
<Alert type={isAlert.type}>
|
|
||||||
<div className="ml-3">{isAlert.msg}</div>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
{loader ? (
|
{loader ? (
|
||||||
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
|
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -90,7 +88,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h2 className="text-[30px] text-center mt-3 font-medium">
|
<h2 className="text-[30px] text-center mt-3 font-medium">
|
||||||
Opensign Setup
|
{t("opensign-Setup")}
|
||||||
</h2>
|
</h2>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="https://discord.com/invite/xe9TDuyAyj"
|
to="https://discord.com/invite/xe9TDuyAyj"
|
||||||
@@ -98,7 +96,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-center text-sm mt-1 text-[blue] cursor-pointer"
|
className="text-center text-sm mt-1 text-[blue] cursor-pointer"
|
||||||
>
|
>
|
||||||
Join our discord server
|
{t("join-discord")}
|
||||||
<i
|
<i
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="fa-brands fa-discord ml-1"
|
className="fa-brands fa-discord ml-1"
|
||||||
@@ -107,7 +105,8 @@ const UpdateExistUserAdmin = () => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
<div className="px-6 py-3 text-xs">
|
<div className="px-6 py-3 text-xs">
|
||||||
<label>
|
<label>
|
||||||
Email <span className="text-[red] text-[13px]">*</span>
|
{t("email")}{" "}
|
||||||
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="email"
|
||||||
@@ -117,14 +116,20 @@ const UpdateExistUserAdmin = () => {
|
|||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormdata((prev) => ({
|
setFormdata((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
email: e.target.value?.toLowerCase()
|
email: e.target.value
|
||||||
|
?.toLowerCase()
|
||||||
|
?.replace(/\s/g, "")
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<hr className="my-2 border-none" />
|
<hr className="my-2 border-none" />
|
||||||
<label>
|
<label>
|
||||||
Master key{" "}
|
{t("master-key")}{" "}
|
||||||
<span className="text-[red] text-[13px]">*</span>
|
<span className="text-[red] text-[13px]">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -137,6 +142,10 @@ const UpdateExistUserAdmin = () => {
|
|||||||
masterkey: e.target.value
|
masterkey: e.target.value
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
onInvalid={(e) =>
|
||||||
|
e.target.setCustomValidity(t("input-required"))
|
||||||
|
}
|
||||||
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -163,7 +172,7 @@ const UpdateExistUserAdmin = () => {
|
|||||||
className="op-btn op-btn-primary w-full"
|
className="op-btn op-btn-primary w-full"
|
||||||
disabled={loader}
|
disabled={loader}
|
||||||
>
|
>
|
||||||
{loader ? "Loading..." : "Next"}
|
{loader ? t("loading") : t("next")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user