mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-04 00:38:57 +02:00
Compare commits
1078
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d758062c07 | ||
|
|
cf698be79e | ||
|
|
c3298ccc6f | ||
|
|
eefa11d827 | ||
|
|
dadc79600f | ||
|
|
76d10d6ab9 | ||
|
|
c8733e6903 | ||
|
|
88ec854dbd | ||
|
|
717d2c0ddd | ||
|
|
8e2d463089 | ||
|
|
1344d8d12f | ||
|
|
51c8040d60 | ||
|
|
e505396e53 | ||
|
|
606bedd2ec | ||
|
|
dc82af0a0a | ||
|
|
8dfc61eeef | ||
|
|
2133a3a460 | ||
|
|
6f615db29d | ||
|
|
4141b3538c | ||
|
|
3bbb78b7b5 | ||
|
|
2caa231154 | ||
|
|
9ac382c188 | ||
|
|
852e109a52 | ||
|
|
d292b5bd6a | ||
|
|
d868fdf6f2 | ||
|
|
4145ce8c0c | ||
|
|
e093d7a5f4 | ||
|
|
3d4e43ede5 | ||
|
|
0bbfe5ae3d | ||
|
|
8538f0710a | ||
|
|
61be45cba2 | ||
|
|
162e07bacc | ||
|
|
806bb2e387 | ||
|
|
9de3331cd2 | ||
|
|
76699d7dc9 | ||
|
|
5888387dd0 | ||
|
|
83e9537176 | ||
|
|
d973a8fea4 | ||
|
|
ae6f727646 | ||
|
|
f9eb9201f0 | ||
|
|
0d884e2f4f | ||
|
|
1c70e4c059 | ||
|
|
e747d0d699 | ||
|
|
2edbafd520 | ||
|
|
14c57cceb3 | ||
|
|
6337f3057e | ||
|
|
537949b7c3 | ||
|
|
180e7c1435 | ||
|
|
9139422180 | ||
|
|
274d01b548 | ||
|
|
4d62048d36 | ||
|
|
921f7c89e9 | ||
|
|
6bfa3e61b5 | ||
|
|
840c7165ff | ||
|
|
9eeb1e9bc2 | ||
|
|
bc7f2d69cf | ||
|
|
34d9296c70 | ||
|
|
725b67e75e | ||
|
|
71bb6d6206 | ||
|
|
f271a113b6 | ||
|
|
71b254f69d | ||
|
|
28b6e9d4aa | ||
|
|
c6f57db04b | ||
|
|
5626b18ab0 | ||
|
|
5adf336119 | ||
|
|
ef1d4967d9 | ||
|
|
7680c8e140 | ||
|
|
0a14122cbf | ||
|
|
6587268f53 | ||
|
|
96d0db22c8 | ||
|
|
d35a03d588 | ||
|
|
7fd743f325 | ||
|
|
b81ff12ae5 | ||
|
|
65be6d1e20 | ||
|
|
9dfd1fb4f1 | ||
|
|
abbc0e91a9 | ||
|
|
1bf2f5622f | ||
|
|
8a1f2bc9a0 | ||
|
|
75518b3f6b | ||
|
|
53d874fd12 | ||
|
|
b7b61df983 | ||
|
|
20f1e68b13 | ||
|
|
e26fac8498 | ||
|
|
02dfec3a0f | ||
|
|
e6a04670b6 | ||
|
|
41aa91152d | ||
|
|
e69fb8eeba | ||
|
|
cb2dab8222 | ||
|
|
ad2672f205 | ||
|
|
e45314c1df | ||
|
|
34b0a1ca02 | ||
|
|
c05f541189 | ||
|
|
68cad8e10c | ||
|
|
2afad89b29 | ||
|
|
6c57ee6591 | ||
|
|
48bcaa5614 | ||
|
|
e595672e3c | ||
|
|
8fe31ee59b | ||
|
|
c6b139c456 | ||
|
|
10d99f12bb | ||
|
|
55ebdb5919 | ||
|
|
4b6712a0ff | ||
|
|
fcb983f68a | ||
|
|
f92ff170db | ||
|
|
c8b3f1fcbf | ||
|
|
936717fc6f | ||
|
|
be948ed4df | ||
|
|
5d8e7f738d | ||
|
|
128f6378cf | ||
|
|
1641217c43 | ||
|
|
63cc034b4a | ||
|
|
49a63eeb50 | ||
|
|
da45fcfc85 | ||
|
|
b73b0c6b2d | ||
|
|
c9fe580e44 | ||
|
|
b0556310dd | ||
|
|
9da13a23cc | ||
|
|
d727e16ef9 | ||
|
|
1508c63d0e | ||
|
|
8a198c1543 | ||
|
|
da0652d8ed | ||
|
|
59f1453176 | ||
|
|
ad748fbd03 | ||
|
|
2a1afca818 | ||
|
|
8e1cfd1ce5 | ||
|
|
6236353316 | ||
|
|
b5271017dc | ||
|
|
4b6b955fe5 | ||
|
|
a2b3761d5e | ||
|
|
2c5e311c7f | ||
|
|
98facb2f6d | ||
|
|
77618e57ea | ||
|
|
0bb8aa880d | ||
|
|
f97f2c1253 | ||
|
|
b76add3b2b | ||
|
|
07b14a0a47 | ||
|
|
aa7326a941 | ||
|
|
336d3424fe | ||
|
|
73ae7b1c06 | ||
|
|
ccfd7450d5 | ||
|
|
e23c04cf06 | ||
|
|
7bf661d584 | ||
|
|
98c18357cd | ||
|
|
8b7079bd8b | ||
|
|
9f0963d8a3 | ||
|
|
ebc79ddec7 | ||
|
|
24c6e9f5c0 | ||
|
|
475b2e09af | ||
|
|
05a922446a | ||
|
|
81a426b087 | ||
|
|
743b751b5a | ||
|
|
3d6e83b4af | ||
|
|
4f3e8ab95a | ||
|
|
cc00b35ac8 | ||
|
|
1c86caac1f | ||
|
|
20dd3c90d6 | ||
|
|
8b87a90e78 | ||
|
|
bd7937deb2 | ||
|
|
7b0dc4cf9a | ||
|
|
81c47190bf | ||
|
|
cecf22bb85 | ||
|
|
17eacfe86b | ||
|
|
8f5c9d1b40 | ||
|
|
f34e277657 | ||
|
|
7cc7e36f64 | ||
|
|
b340463ea7 | ||
|
|
9364bb7859 | ||
|
|
9f676c12e7 | ||
|
|
0077b71388 | ||
|
|
50af669bd2 | ||
|
|
45055b567f | ||
|
|
4a7fd118bb | ||
|
|
d27e8a43dc | ||
|
|
4d3635a5bd | ||
|
|
aeef6ca567 | ||
|
|
cc68dd109f | ||
|
|
7943f1444f | ||
|
|
876e04d815 | ||
|
|
43dbe71c99 | ||
|
|
73b36fafd7 | ||
|
|
095040713e | ||
|
|
ac884185b4 | ||
|
|
eede170d16 | ||
|
|
c4d6d8e442 | ||
|
|
14a2f6f78a | ||
|
|
dd28cefac8 | ||
|
|
00179f5415 | ||
|
|
7b465687ef | ||
|
|
e67fdfb134 | ||
|
|
ceee0e1089 | ||
|
|
1d184a69b0 | ||
|
|
8e09d7235b | ||
|
|
a39c01ef12 | ||
|
|
d96504bb30 | ||
|
|
0b8c4eac6e | ||
|
|
98f7de5e0c | ||
|
|
998a50412a | ||
|
|
e16c5e08a8 | ||
|
|
72a61bc621 | ||
|
|
f095629134 | ||
|
|
a0c1e08091 | ||
|
|
3583d7a549 | ||
|
|
69e679982a | ||
|
|
3303fcb895 | ||
|
|
6b5815f52a | ||
|
|
a01e361d14 | ||
|
|
c059e95fa9 | ||
|
|
70abddec3a | ||
|
|
ca8eaa492c | ||
|
|
94806c895f | ||
|
|
8b08995e7d | ||
|
|
de9c58e5fd | ||
|
|
6d914829e9 | ||
|
|
0193e4946f | ||
|
|
14c6b14c27 | ||
|
|
794365f6dc | ||
|
|
d0a0a28dec | ||
|
|
1385f12543 | ||
|
|
0d81ffe677 | ||
|
|
9d7376aedb | ||
|
|
5eb7d8ce13 | ||
|
|
4609bba4c1 | ||
|
|
de0de1973e | ||
|
|
16c48e9d23 | ||
|
|
344ccadfb1 | ||
|
|
eb1086e5b1 | ||
|
|
ae568a89d5 | ||
|
|
daa348c2e3 | ||
|
|
78532731da | ||
|
|
2e26d5687e | ||
|
|
4b8b7ed8d9 | ||
|
|
ac986af20f | ||
|
|
a96333bba5 | ||
|
|
78ca0d1fdb | ||
|
|
415760ba52 | ||
|
|
67bd246ef9 | ||
|
|
4963a7ad7f | ||
|
|
94b02105f3 | ||
|
|
6aaeeeeaf5 | ||
|
|
8039f5a744 | ||
|
|
a5ebd67967 | ||
|
|
266a4c5654 | ||
|
|
406a29054e | ||
|
|
57f8ba8a72 | ||
|
|
f1a70eac5a | ||
|
|
f228ae5ba8 | ||
|
|
2c1239dcf0 | ||
|
|
6ca9cbab16 | ||
|
|
9922f22ef7 | ||
|
|
84cc1d65fe | ||
|
|
7a5db1ca40 | ||
|
|
de79c9a4b3 | ||
|
|
7a7e1b506a | ||
|
|
fa2e66914d | ||
|
|
b0c65fe5f1 | ||
|
|
b0440876cd | ||
|
|
6359067839 | ||
|
|
71f36ff383 | ||
|
|
beab4bdfc9 | ||
|
|
c9e6750724 | ||
|
|
06c7355efd | ||
|
|
73f7d1b32f | ||
|
|
fecc87d8c3 | ||
|
|
57c89bf601 | ||
|
|
b10b2617b8 | ||
|
|
eaed35cefd | ||
|
|
44e92344fc | ||
|
|
9aebbde627 | ||
|
|
8ece6ef046 | ||
|
|
7d46e26365 | ||
|
|
e2646bd49f | ||
|
|
6158ac7bc4 | ||
|
|
596340bea9 | ||
|
|
73d1cdee00 | ||
|
|
f88f2c681b | ||
|
|
25ecf7221d | ||
|
|
bb18feaacf | ||
|
|
19324ad0d8 | ||
|
|
8a0f5c460f | ||
|
|
625689b203 | ||
|
|
d919e8514b | ||
|
|
18f183f48b | ||
|
|
69135afe6b | ||
|
|
474a20aa41 | ||
|
|
19478536b3 | ||
|
|
dc29d7a23b | ||
|
|
f5137f54b0 | ||
|
|
42f2122070 | ||
|
|
e4ca29c2c3 | ||
|
|
b8a039bc20 | ||
|
|
331b2d5a40 | ||
|
|
46e390d3c5 | ||
|
|
0b8fb87a29 | ||
|
|
e0249211d2 | ||
|
|
a244c1ba3d | ||
|
|
0a79807cb4 | ||
|
|
b70c473002 | ||
|
|
937390fca0 | ||
|
|
1140318719 | ||
|
|
655371c6d9 | ||
|
|
f07fc78eff | ||
|
|
60034a4ad8 | ||
|
|
ead7bf8841 | ||
|
|
15d2798aab | ||
|
|
58a0af40e6 | ||
|
|
1b79b45b1f | ||
|
|
f831ff3b7a | ||
|
|
f1b6859e9c | ||
|
|
2148f5196c | ||
|
|
5495e569df | ||
|
|
e121df48fe | ||
|
|
39c05b1eb3 | ||
|
|
78892a497d | ||
|
|
ccb08949ff | ||
|
|
74b091b1eb | ||
|
|
264214babd | ||
|
|
38930133f7 | ||
|
|
758cfc8e8d | ||
|
|
2a9ae74c33 | ||
|
|
2f73ba974c | ||
|
|
7c0b744c40 | ||
|
|
010d2dba60 | ||
|
|
c0b45e97ea | ||
|
|
7316fcd18a | ||
|
|
08a2d8a1a4 | ||
|
|
dbd53ba0d2 | ||
|
|
8b0c73c58e | ||
|
|
a292687a8c | ||
|
|
8659c1f4dc | ||
|
|
8ed73ba07b | ||
|
|
a41a31176d | ||
|
|
d6740efaf9 | ||
|
|
aac4ea8e2a | ||
|
|
3fe26cfb07 | ||
|
|
c837df6540 | ||
|
|
03b6b567fc | ||
|
|
09fbd442be | ||
|
|
5f32ca0140 | ||
|
|
46e5aa2815 | ||
|
|
db635f80f8 | ||
|
|
c3a101bc18 | ||
|
|
1af4bd430f | ||
|
|
0459c404f5 | ||
|
|
492f242e4d | ||
|
|
e06d6d5427 | ||
|
|
747c7c549c | ||
|
|
e91d615e68 | ||
|
|
2d527d59b0 | ||
|
|
340947a36d | ||
|
|
91d098ef65 | ||
|
|
d9f8ea8aca | ||
|
|
33bcb55124 | ||
|
|
5a93207dc2 | ||
|
|
fa7c36dbe2 | ||
|
|
faba8b8201 | ||
|
|
3422bc6f9e | ||
|
|
a195b758e6 | ||
|
|
083cd60f2d | ||
|
|
f4b7449262 | ||
|
|
fb68931538 | ||
|
|
be07fcec24 | ||
|
|
f6245cfada | ||
|
|
77cf6de722 | ||
|
|
2b17c26722 | ||
|
|
9862921297 | ||
|
|
685b2ceabd | ||
|
|
786b674db3 | ||
|
|
0b9074611a | ||
|
|
6ebfa038b3 | ||
|
|
4c809bb8d3 | ||
|
|
2dcb7eb7a2 | ||
|
|
743e89038c | ||
|
|
f9f25dc0c3 | ||
|
|
ca75698328 | ||
|
|
f117aeb7c4 | ||
|
|
e36557e844 | ||
|
|
e73b8ed5a5 | ||
|
|
0aaeb28eb7 | ||
|
|
305a5f6fda | ||
|
|
045961be02 | ||
|
|
c612dd3e70 | ||
|
|
ea4527e2dd | ||
|
|
aada33f23f | ||
|
|
1f44582658 | ||
|
|
198a58e524 | ||
|
|
0d78aef414 | ||
|
|
8f99cb0514 | ||
|
|
9a734d9b3c | ||
|
|
7a2c93a3e9 | ||
|
|
a5e1768f7e | ||
|
|
30e27062bd | ||
|
|
97d28a1b48 | ||
|
|
aade153f1c | ||
|
|
df6f5d4b33 | ||
|
|
ab14628769 | ||
|
|
69effb5af0 | ||
|
|
6e9078d64b | ||
|
|
9c73b7818f | ||
|
|
c5246d7a83 | ||
|
|
35511e08ac | ||
|
|
39dc8b226a | ||
|
|
7cb531b183 | ||
|
|
58422b17e5 | ||
|
|
0b2191f97c | ||
|
|
a3e672cde0 | ||
|
|
5a0b10bdff | ||
|
|
dfbf4d8a8f | ||
|
|
4727d622db | ||
|
|
e18e62754f | ||
|
|
bec7af5142 | ||
|
|
0db937eeeb | ||
|
|
c8d26a5ea9 | ||
|
|
1659ebd2ac | ||
|
|
7877d13776 | ||
|
|
2f7cacb933 | ||
|
|
16fcbf8a54 | ||
|
|
719a23c95b | ||
|
|
f4db8af201 | ||
|
|
3549c63cc0 | ||
|
|
b9ed7e5293 | ||
|
|
e34e2c4386 | ||
|
|
a09b2e186f | ||
|
|
cc273261c3 | ||
|
|
26c5c951b6 | ||
|
|
e63178b899 | ||
|
|
eb42f08640 | ||
|
|
2843bfd5c9 | ||
|
|
b2a838dc4e | ||
|
|
c682a6d8eb | ||
|
|
c4a23b4f1b | ||
|
|
12e74533c7 | ||
|
|
24c8f6012f | ||
|
|
b20fb9ea3f | ||
|
|
079e0defc4 | ||
|
|
00ad406e1b | ||
|
|
5c7a9e1d08 | ||
|
|
ea2c981a7f | ||
|
|
ee18d1b317 | ||
|
|
7f6771e56d | ||
|
|
1308b143c4 | ||
|
|
7be2d1f06a | ||
|
|
62021e8870 | ||
|
|
ea5f407786 | ||
|
|
2ecd1823e1 | ||
|
|
1e2eee63df | ||
|
|
8fda979870 | ||
|
|
c59002c375 | ||
|
|
1fe05b402b | ||
|
|
c7d5bef886 | ||
|
|
ca2fc2bd5c | ||
|
|
8bf9fb6299 | ||
|
|
031f24180a | ||
|
|
8663777097 | ||
|
|
342876cd0b | ||
|
|
beaa256e3f | ||
|
|
27ae27187d | ||
|
|
e8d692a707 | ||
|
|
4f71d1bd03 | ||
|
|
8d33d4c44e | ||
|
|
8be55a30c1 | ||
|
|
46a0cfa1eb | ||
|
|
6988bca7f4 | ||
|
|
1a2c0ecbfc | ||
|
|
f2281505a4 | ||
|
|
3ff790c57b | ||
|
|
d5b0fc4e3b | ||
|
|
69129c2d47 | ||
|
|
1486d66b9b | ||
|
|
67323d01f5 | ||
|
|
d0566e6645 | ||
|
|
a3e1fa866e | ||
|
|
6d6b70a888 | ||
|
|
c152d3bf35 | ||
|
|
56a0211b03 | ||
|
|
87fb943ddb | ||
|
|
dacc9bb27e | ||
|
|
43a9fa6820 | ||
|
|
523d7a0896 | ||
|
|
df53e243a5 | ||
|
|
b30d7e3337 | ||
|
|
7a8e2bcd02 | ||
|
|
7aa505f1a3 | ||
|
|
beecd2d26f | ||
|
|
96ecbe97f1 | ||
|
|
7161da4a2f | ||
|
|
462fdfe1be | ||
|
|
dc25133b10 | ||
|
|
bb7552a7bf | ||
|
|
79b4ca053a | ||
|
|
8d91bd218b | ||
|
|
8e0c96589a | ||
|
|
3ac66ea4c5 | ||
|
|
acbff61d9e | ||
|
|
83a1da04d1 | ||
|
|
b86155de49 | ||
|
|
2108ce52ca | ||
|
|
4af96da515 | ||
|
|
eda2085d4b | ||
|
|
6cdcf66e81 | ||
|
|
a701522dca | ||
|
|
ddeb31e530 | ||
|
|
f827ead0b6 | ||
|
|
ae87703a34 | ||
|
|
250c2d768b | ||
|
|
e5e6587490 | ||
|
|
4921152336 | ||
|
|
0c7da91fab | ||
|
|
add07026bc | ||
|
|
7f64418a6c | ||
|
|
e83ceaa815 | ||
|
|
e3dcb99438 | ||
|
|
78821cb5e4 | ||
|
|
548441dded | ||
|
|
7c53ae421c | ||
|
|
a71a867aea | ||
|
|
4d0d2e9a58 | ||
|
|
fcda1e325e | ||
|
|
b41fed0d12 | ||
|
|
ac533d92f6 | ||
|
|
792b48b75a | ||
|
|
175eb921c1 | ||
|
|
4cd959b34b | ||
|
|
0083efb7dc | ||
|
|
18738a56c0 | ||
|
|
3254fc8199 | ||
|
|
4a52299d35 | ||
|
|
7a1247051c | ||
|
|
71d34dd3d3 | ||
|
|
1971ffd221 | ||
|
|
a0af2145f3 | ||
|
|
64bd5cef35 | ||
|
|
4eb511e76e | ||
|
|
6e7fa2a7f8 | ||
|
|
1e3765990a | ||
|
|
2ef608fa33 | ||
|
|
479878a59d | ||
|
|
475eba8b7e | ||
|
|
c0ddec8896 | ||
|
|
38cd32b8c8 | ||
|
|
9a6ee0397b | ||
|
|
57f7bf6375 | ||
|
|
93f3cd7868 | ||
|
|
157b5a891e | ||
|
|
fcd10703a8 | ||
|
|
d17a8524c5 | ||
|
|
2d42013fed | ||
|
|
5288fe1512 | ||
|
|
3988361471 | ||
|
|
62204bda9d | ||
|
|
1ac4418d41 | ||
|
|
23914274b5 | ||
|
|
a668aa11db | ||
|
|
0aefb792dc | ||
|
|
54de1c1f5a | ||
|
|
f53f125e3e | ||
|
|
0269647d75 | ||
|
|
5fc05e7faa | ||
|
|
8c3caed1fb | ||
|
|
fbcb1fc47a | ||
|
|
fdd6e64060 | ||
|
|
3dd88f2453 | ||
|
|
d06bfefc40 | ||
|
|
30236206bc | ||
|
|
24b0231495 | ||
|
|
57946fea6d | ||
|
|
187990ce05 | ||
|
|
8cfcecf440 | ||
|
|
041d290f0f | ||
|
|
291791cb08 | ||
|
|
3d081cb7a0 | ||
|
|
0201159b31 | ||
|
|
4caaa203bb | ||
|
|
783bd63da0 | ||
|
|
82a187fe46 | ||
|
|
8ebf96f1e1 | ||
|
|
b25152a5e8 | ||
|
|
b1b488a8a0 | ||
|
|
8a76b92b5f | ||
|
|
724f3a9724 | ||
|
|
388d9cb29e | ||
|
|
6b463c6f1a | ||
|
|
4afca77d1e | ||
|
|
53d8e60ec3 | ||
|
|
23c22b79d8 | ||
|
|
4943517145 | ||
|
|
c71398c6e3 | ||
|
|
dfaa278636 | ||
|
|
139c3b42f5 | ||
|
|
d89c28334e | ||
|
|
7638bcad02 | ||
|
|
63090b82e3 | ||
|
|
63b7cb8188 | ||
|
|
ad9dda27ba | ||
|
|
3f3137874a | ||
|
|
440eaaeb26 | ||
|
|
2d6d8ce2be | ||
|
|
229d0731b8 | ||
|
|
418cd92f80 | ||
|
|
6e4ed4bc09 | ||
|
|
51b417aa7e | ||
|
|
0fc895ad17 | ||
|
|
2dea2172bc | ||
|
|
fcd3c15ec7 | ||
|
|
4cd9b08698 | ||
|
|
b21b641e2a | ||
|
|
af9c8d71c6 | ||
|
|
8bd1891fcc | ||
|
|
e5a62f17a5 | ||
|
|
db383d0e88 | ||
|
|
e519d86cad | ||
|
|
bf68656d05 | ||
|
|
69913151b6 | ||
|
|
46312eb138 | ||
|
|
1a13936681 | ||
|
|
251ea22f5f | ||
|
|
8f8808ce1c | ||
|
|
bb207b953c | ||
|
|
2984d6876d | ||
|
|
5d2b131c99 | ||
|
|
43c9b4db9c | ||
|
|
ce9e27e116 | ||
|
|
e25b7deaf3 | ||
|
|
81078073cb | ||
|
|
e6e5db95ba | ||
|
|
2cf3af242b | ||
|
|
ed664359a6 | ||
|
|
4a5e855b76 | ||
|
|
1e60863a40 | ||
|
|
10ad3ee5bd | ||
|
|
32c5a0a77a | ||
|
|
b6651f12e2 | ||
|
|
15ad35bf76 | ||
|
|
9a986dd000 | ||
|
|
714146f616 | ||
|
|
96d2b4e9fd | ||
|
|
122c42153e | ||
|
|
32c4ee16a0 | ||
|
|
53cdb411b7 | ||
|
|
0708e0ae1c | ||
|
|
95db24f8ed | ||
|
|
bcdd2e7feb | ||
|
|
4adfa9f830 | ||
|
|
dcc8f99991 | ||
|
|
3bdb56462d | ||
|
|
b8bffe97b5 | ||
|
|
af817b6bc3 | ||
|
|
8e1cbc65d7 | ||
|
|
e38a1f9c1a | ||
|
|
50c3133dae | ||
|
|
b1e2a74ad5 | ||
|
|
7e9dc8cd65 | ||
|
|
7d87cc27fc | ||
|
|
25714cde90 | ||
|
|
8241482c19 | ||
|
|
3044e010f6 | ||
|
|
9743b933da | ||
|
|
1ce8ec4758 | ||
|
|
cb99b7646c | ||
|
|
5af7279c67 | ||
|
|
224d9f6787 | ||
|
|
ed7df13f9b | ||
|
|
2c5f6631d7 | ||
|
|
a32b88f6b0 | ||
|
|
88cb271332 | ||
|
|
e18d1a7a16 | ||
|
|
b2dfc6f32c | ||
|
|
a64e30a94c | ||
|
|
6d5b28f75f | ||
|
|
c7decaec02 | ||
|
|
8600437c5a | ||
|
|
ece3f42ab3 | ||
|
|
32be8dfe3a | ||
|
|
2aebceda24 | ||
|
|
85b463f0e0 | ||
|
|
f6c8d4f51a | ||
|
|
b84c1c8821 | ||
|
|
a3334fdf2d | ||
|
|
d6b12b75b0 | ||
|
|
a9e623391b | ||
|
|
fd34ba778c | ||
|
|
d00d31eaf2 | ||
|
|
016a0f62bd | ||
|
|
cf52292f7c | ||
|
|
8b26c94ada | ||
|
|
582b10b5ee | ||
|
|
b51e152d10 | ||
|
|
5f197f5f9f | ||
|
|
5a3ee25dfd | ||
|
|
7050138e5e | ||
|
|
049d268314 | ||
|
|
6f71afb418 | ||
|
|
7e65692b5a | ||
|
|
bd1f44479b | ||
|
|
c0935001ce | ||
|
|
f65ab5dfea | ||
|
|
dbb7fd576f | ||
|
|
be5cc6126e | ||
|
|
6a4eb24630 | ||
|
|
61a8bc519f | ||
|
|
b15f3c0333 | ||
|
|
5830fda578 | ||
|
|
102f837263 | ||
|
|
5cee42a76e | ||
|
|
8fc7cc924a | ||
|
|
80170b814f | ||
|
|
91fcb71bc3 | ||
|
|
eb13d91bbb | ||
|
|
a464437b3a | ||
|
|
3a67dc9b08 | ||
|
|
a6ff20a657 | ||
|
|
4bf380edf8 | ||
|
|
ab3148b705 | ||
|
|
2ffd1ebf2a | ||
|
|
d1155bc8ef | ||
|
|
33ff706803 | ||
|
|
7fdd819722 | ||
|
|
aeaea23098 | ||
|
|
ff7f45f055 | ||
|
|
40665684a8 | ||
|
|
861f822151 | ||
|
|
62541f1450 | ||
|
|
a356e77f54 | ||
|
|
74abeff8d9 | ||
|
|
78dfaccd38 | ||
|
|
757b72161a | ||
|
|
c2065bf752 | ||
|
|
5608dae6e3 | ||
|
|
2288880eba | ||
|
|
ba7d0a9723 | ||
|
|
1ac8800b40 | ||
|
|
bb7827b762 | ||
|
|
8caa0275ab | ||
|
|
7e1d0f8a49 | ||
|
|
f7f5c2de37 | ||
|
|
f75710c836 | ||
|
|
a02cc89e5d | ||
|
|
f54a51c546 | ||
|
|
b12eb87b38 | ||
|
|
93f7408847 | ||
|
|
8c209f5a9e | ||
|
|
995a2a5cef | ||
|
|
71fd7b20a6 | ||
|
|
d8e73eef72 | ||
|
|
61209f4c6c | ||
|
|
c4507dd06b | ||
|
|
773e8b8dbb | ||
|
|
91976d2355 | ||
|
|
77042224a1 | ||
|
|
0b64908eab | ||
|
|
fc3f134bd5 | ||
|
|
d6c2c66fdd | ||
|
|
d5853e6fc3 | ||
|
|
765c3c19fa | ||
|
|
f13991b88b | ||
|
|
47ddac3529 | ||
|
|
e51feaa1fe | ||
|
|
d224a44e54 | ||
|
|
f5c0694e32 | ||
|
|
dec13e8b5f | ||
|
|
dd536dc7d0 | ||
|
|
b6ce00519f | ||
|
|
7495955420 | ||
|
|
d17951af30 | ||
|
|
42c6f03f28 | ||
|
|
a9d6bc2246 | ||
|
|
428bb3b7c3 | ||
|
|
ac0cdd28cf | ||
|
|
37250f8a11 | ||
|
|
0102480954 | ||
|
|
f3a1c74a45 | ||
|
|
2544651ff1 | ||
|
|
93297b972a | ||
|
|
7165ed82f5 | ||
|
|
17422427a8 | ||
|
|
9ef2bc9ee2 | ||
|
|
12ec1bad0f | ||
|
|
fd552cedec | ||
|
|
5784378073 | ||
|
|
e0448cd4fa | ||
|
|
9a4bd79d75 | ||
|
|
9ae0334249 | ||
|
|
eb355f562b | ||
|
|
92dc13185b | ||
|
|
65ec4e78ad | ||
|
|
0c4b8143b2 | ||
|
|
1cc4cf93cb | ||
|
|
944370134a | ||
|
|
c1621f64e6 | ||
|
|
e8c06d0836 | ||
|
|
a6295a6e56 | ||
|
|
47ae52c881 | ||
|
|
f2f0b55596 | ||
|
|
0c415de598 | ||
|
|
411941d9f7 | ||
|
|
3c54f2287c | ||
|
|
dfa121fe57 | ||
|
|
52b17730ef | ||
|
|
346d69124c | ||
|
|
7f35074acd | ||
|
|
b9e9694d61 | ||
|
|
ee4a787b81 | ||
|
|
d801680846 | ||
|
|
d84ab89a9b | ||
|
|
26d38f4ca2 | ||
|
|
745e519eec | ||
|
|
45b3e739d7 | ||
|
|
5ce50db001 | ||
|
|
a8c7b60c1b | ||
|
|
16860bc7b8 | ||
|
|
57f20ae1c0 | ||
|
|
d3b0c614ff | ||
|
|
e28f929ffc | ||
|
|
9f8f9a0992 | ||
|
|
60857638ba | ||
|
|
8041151243 | ||
|
|
7faed512b8 | ||
|
|
5d99a4a9c8 | ||
|
|
25c50d5387 | ||
|
|
5719dcca79 | ||
|
|
db1e81a249 | ||
|
|
ecd3395453 | ||
|
|
4327b2e348 | ||
|
|
06e8140be4 | ||
|
|
14e9330651 | ||
|
|
636910a78e | ||
|
|
e4f9152de8 | ||
|
|
e0b9df9ba5 | ||
|
|
a20bd407a8 | ||
|
|
5630dd45a7 | ||
|
|
20220dd8c9 | ||
|
|
db4b8ec0ee | ||
|
|
2ee9ae16fb | ||
|
|
e50a55403d | ||
|
|
23ae72738d | ||
|
|
8619021f30 | ||
|
|
6c579178c0 | ||
|
|
01e19632a9 | ||
|
|
79ff8fd71d | ||
|
|
8700fd837d | ||
|
|
cdc8eb5bf6 | ||
|
|
95200e234f | ||
|
|
d94527e31a | ||
|
|
903066e6fa | ||
|
|
8c8015fe4a | ||
|
|
a002ac779c | ||
|
|
5c9bfbbdfe | ||
|
|
4a1e6d1318 | ||
|
|
90dc7c738a | ||
|
|
777028f3a7 | ||
|
|
c5a0ff4021 | ||
|
|
bf9f42e94d | ||
|
|
5556de2ef5 | ||
|
|
1b3508a9ef | ||
|
|
3992a9be94 | ||
|
|
eaf875be06 | ||
|
|
e62897e729 | ||
|
|
4c58fe2040 | ||
|
|
298068207e | ||
|
|
d0abe615cb | ||
|
|
87c65e4bea | ||
|
|
be49cb9d6d | ||
|
|
2b73087b7e | ||
|
|
d11dff2987 | ||
|
|
8ac82b1214 | ||
|
|
c46fa19bbb | ||
|
|
2fa2f56bac | ||
|
|
ef50aaa417 | ||
|
|
a1d7275fcd | ||
|
|
080acc9ed6 | ||
|
|
30b888f3a0 | ||
|
|
df11a77971 | ||
|
|
03e660527d | ||
|
|
f7bd439df5 | ||
|
|
2a55c03788 | ||
|
|
f712532793 | ||
|
|
cbdeaf8cc9 | ||
|
|
6bb353fd1f | ||
|
|
523dd43b4d | ||
|
|
bd0216fc39 | ||
|
|
50c40bfec1 | ||
|
|
0e2b6ee180 | ||
|
|
359d86e17b | ||
|
|
0b19c87a50 | ||
|
|
4a35eab7c6 | ||
|
|
b178a3c91e | ||
|
|
9fb0fecba4 | ||
|
|
cfc7408a52 | ||
|
|
aed0b8a3db | ||
|
|
910bd801ac | ||
|
|
22dad33b2e | ||
|
|
4d3ed0232e | ||
|
|
6d83f05b13 | ||
|
|
66cc2e1f2f | ||
|
|
f773fc6e3c | ||
|
|
dc83f21f5e | ||
|
|
0186c48d59 | ||
|
|
43f20508ae | ||
|
|
f678dd02cb | ||
|
|
5c2d6cddcb | ||
|
|
1bbf64fe83 | ||
|
|
296f43101e | ||
|
|
ed6f44fd62 | ||
|
|
776b1a7b43 | ||
|
|
06cdb660b3 | ||
|
|
db9268e1af | ||
|
|
83ce3a1c21 | ||
|
|
bda31de345 | ||
|
|
cdfc952a3f | ||
|
|
9434315775 | ||
|
|
47bb4cac38 | ||
|
|
11d3e6c696 | ||
|
|
0173727bc5 | ||
|
|
3cfa2639e5 | ||
|
|
502400ee56 | ||
|
|
4a3276f4e3 | ||
|
|
750e48ca2e | ||
|
|
823e6a9e2f | ||
|
|
642ef334f6 | ||
|
|
939a67b2c5 | ||
|
|
e1f8481aa2 | ||
|
|
b8e8cd127a | ||
|
|
876a2d78d5 | ||
|
|
16f287fdc0 | ||
|
|
d396a4f71d | ||
|
|
6bee566d8d | ||
|
|
79acd8ae13 | ||
|
|
01666b49cf | ||
|
|
a20ebbf08f | ||
|
|
26cf9c5310 | ||
|
|
3ad58ee52b | ||
|
|
2b67af6097 | ||
|
|
f61dae35ff | ||
|
|
dead3088d6 | ||
|
|
45d65cfbe2 | ||
|
|
6d2010facb | ||
|
|
48d3166049 | ||
|
|
82992d324d | ||
|
|
9a549fa35d | ||
|
|
93a891c8b6 | ||
|
|
2ede742b10 | ||
|
|
c43690faa8 | ||
|
|
a482a92d34 | ||
|
|
1d429cbe36 | ||
|
|
0a36550907 | ||
|
|
09610112fc | ||
|
|
a14454227c | ||
|
|
0d8767ee98 | ||
|
|
f463dc7af7 | ||
|
|
407b01565a | ||
|
|
6c565a144a | ||
|
|
141351de49 | ||
|
|
edecf3ea23 | ||
|
|
e708dad596 | ||
|
|
48012c9343 | ||
|
|
009a24e943 | ||
|
|
04a3251968 | ||
|
|
82694a24f2 | ||
|
|
748cc042dd | ||
|
|
6b8bca0802 | ||
|
|
fed1cff0cb | ||
|
|
b2eba6409f | ||
|
|
81af6a6c61 | ||
|
|
c326849b8d | ||
|
|
a92188d8e2 | ||
|
|
b5dbc69188 | ||
|
|
4055574785 | ||
|
|
9b295f784a | ||
|
|
bfae7f236c | ||
|
|
fe907116e2 | ||
|
|
ade39c2f46 | ||
|
|
31baefcce3 | ||
|
|
59eb4eb9c7 | ||
|
|
3b93f96479 | ||
|
|
dbff436bc2 | ||
|
|
c3cf9c891e | ||
|
|
4e7c8c63bb | ||
|
|
db4494c463 | ||
|
|
d208a90107 | ||
|
|
450a971ca9 | ||
|
|
5ba1f79f3b | ||
|
|
f81f72a147 | ||
|
|
d255d5bfb2 | ||
|
|
f5e835cbc4 | ||
|
|
b40eb7119d | ||
|
|
f56faf3afd | ||
|
|
5fa60d8135 | ||
|
|
695345d911 | ||
|
|
3f60509254 | ||
|
|
6bd9ac0b8f | ||
|
|
2022df000e | ||
|
|
ec6e037422 | ||
|
|
d4be4aec2c | ||
|
|
4b11fe77e0 | ||
|
|
4caf7b8c1a | ||
|
|
c736bbce55 | ||
|
|
4bbf0d05d5 | ||
|
|
d42e11c5c1 | ||
|
|
f227b79316 | ||
|
|
d4b4e02b62 | ||
|
|
1e76cf5253 | ||
|
|
4b9088b252 | ||
|
|
820d6378f9 | ||
|
|
dfc816bdac | ||
|
|
0f62419d99 | ||
|
|
37af995aaa | ||
|
|
4c69971ba1 | ||
|
|
fe37f3e021 | ||
|
|
9047aa7dc8 | ||
|
|
d33df9b934 | ||
|
|
95558d1407 | ||
|
|
3164ee5824 | ||
|
|
6a98adebd2 | ||
|
|
015b752f5b | ||
|
|
11164a716f | ||
|
|
64638acd43 | ||
|
|
133769d5fd | ||
|
|
e330285e24 | ||
|
|
2acf851852 | ||
|
|
73978ebce4 | ||
|
|
96ae95a97c | ||
|
|
356d2e81c5 | ||
|
|
66f91d27f5 | ||
|
|
344d9458ba | ||
|
|
408d84daed | ||
|
|
f1f4b0f7a2 | ||
|
|
a7d0b10c95 | ||
|
|
23a8637539 | ||
|
|
ef45221fea | ||
|
|
e8350c331d | ||
|
|
8726f06ebf | ||
|
|
184b401582 | ||
|
|
08ba8b2e47 | ||
|
|
71c5f5923f | ||
|
|
93daef36cd | ||
|
|
540e5e2997 | ||
|
|
fc2eab7d73 | ||
|
|
a3ebe95a5e | ||
|
|
ecfad497a2 | ||
|
|
86a4ee7f56 | ||
|
|
a64e4d943a | ||
|
|
1a5f1dfa29 | ||
|
|
4e90ae60a0 | ||
|
|
afe1a2b52e | ||
|
|
2c3b4ec3fe | ||
|
|
b034cfd501 | ||
|
|
bb04583bca | ||
|
|
c684d00bdf | ||
|
|
6ac323846f | ||
|
|
b5830ac792 | ||
|
|
1c81e9e9e8 | ||
|
|
9ce58dc859 | ||
|
|
a6231dca66 | ||
|
|
8d62515383 | ||
|
|
826da6cda6 | ||
|
|
17076013fc | ||
|
|
e302d0f1f1 | ||
|
|
3d744bd476 | ||
|
|
72af4d979f | ||
|
|
5ccd2bc27d | ||
|
|
65c277c996 | ||
|
|
f3a1a0efa9 | ||
|
|
39ff162b1c | ||
|
|
4ff36d7c4b | ||
|
|
0d82c435f9 | ||
|
|
aa08a0a290 | ||
|
|
0a08b742fb | ||
|
|
fbe8701f87 | ||
|
|
bcd66b38d0 | ||
|
|
37ec427ed5 | ||
|
|
5533cfe831 | ||
|
|
ef9697b9d6 | ||
|
|
c4b6a8c99f | ||
|
|
22e121d094 | ||
|
|
91e691630c | ||
|
|
b58d72c176 | ||
|
|
4d18aea692 | ||
|
|
f5e164cb3c | ||
|
|
d8d52ab080 |
@@ -151,6 +151,60 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rishabjasrotia",
|
||||
"name": "Rishab",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/33950743?v=4",
|
||||
"profile": "https://github.com/rishabjasrotia",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "maoo",
|
||||
"name": "Maurizio Pillitu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/327285?v=4",
|
||||
"profile": "https://session.it",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lsprr",
|
||||
"name": "Luis Parra",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/16653744?v=4",
|
||||
"profile": "https://luisparra.dev",
|
||||
"contributions": [
|
||||
"a11y"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Govinda04",
|
||||
"name": "Govinda Kocharekar",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/50038172?v=4",
|
||||
"profile": "https://github.com/Govinda04",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "crediblebilal",
|
||||
"name": "Bilal Ahmad Bhat",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/55330484?v=4",
|
||||
"profile": "https://bilal.cc",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "VikramNagwal",
|
||||
"name": "Vikram",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/123088024?v=4",
|
||||
"profile": "https://github.com/VikramNagwal",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+12
-2
@@ -39,11 +39,21 @@ DO_ACCESS_KEY_ID=
|
||||
DO_SECRET_ACCESS_KEY=
|
||||
# Digital ocean spaces region or AWS s3 region
|
||||
DO_REGION=us-west
|
||||
# Set this to true id you are using local storage instead of s3 compatible storage
|
||||
# USE_LOCAL=TRUE
|
||||
|
||||
# Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=
|
||||
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=XXXXX
|
||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||
SMTP_ENABLE=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USER_EMAIL=
|
||||
SMTP_PASS=
|
||||
|
||||
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
||||
PFX_BASE64=
|
||||
|
||||
# Provide Pass pharse of above PFX or p12 document
|
||||
PASS_PHRASE=
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
# Clone the repo and rename this file to .env if you want to run the frontend react app locally for some quick contributions to the project.
|
||||
# When used as it is, this env config will connect to our hosted UAT backend
|
||||
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
|
||||
|
||||
# Set CI to false while running the app locally
|
||||
CI=false
|
||||
# Set it to the URL form where the app home page will be accessed
|
||||
PUBLIC_URL=http://localhost:3000
|
||||
# Set it to true if you want to generate the Sourcemap for debugging
|
||||
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)
|
||||
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.
|
||||
REACT_APP_APPID=opensignstgn
|
||||
|
||||
|
||||
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
||||
# A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App.
|
||||
APP_ID=opensignstgn
|
||||
# Name of the app. It will be visible in the verification emails sent out.
|
||||
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.
|
||||
MASTER_KEY=XnAadwKxxByMr
|
||||
# Mongodb URI to connect to
|
||||
MONGODB_URI=mongodb://host.docker.internal: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.
|
||||
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)
|
||||
SERVER_URL=http://127.0.0.1:8080/app
|
||||
|
||||
# Storage config ************************************************************************************************************************************************************************************************
|
||||
# Digital ocean space name or AWS S3 bucket name for uploading documents
|
||||
DO_SPACE=DOSPACENAME
|
||||
# Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents
|
||||
DO_ENDPOINT=ams3.digitaloceanspaces.com
|
||||
# Digital ocean baseurl or AWS S3 base URL
|
||||
DO_BASEURL=https://DOSPACENAME.ams3.digitaloceanspaces.com
|
||||
# Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs
|
||||
DO_ACCESS_KEY_ID=
|
||||
# Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs
|
||||
DO_SECRET_ACCESS_KEY=
|
||||
# Digital ocean spaces region or AWS s3 region
|
||||
DO_REGION=us-west
|
||||
# local storage
|
||||
USE_LOCAL=TRUE
|
||||
|
||||
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=XXXXX
|
||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||
SMTP_ENABLE=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USER_EMAIL=
|
||||
SMTP_PASS=
|
||||
|
||||
|
||||
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
||||
PFX_BASE64='MIIKCQIBAzCCCc8GCSqGSIb3DQEHAaCCCcAEggm8MIIJuDCCBG8GCSqGSIb3DQEH
|
||||
BqCCBGAwggRcAgEAMIIEVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIpumu
|
||||
bFabBWACAggAgIIEKDqHS7Icd5MzIBk1dBokGK2s+5a2fA4308WA1QzEWmczqVYI
|
||||
z6lYmW8qsiZIw4PFkRzdIx1+zCmP8jgWiiqh5RKnbHYmh1JPNyx9SqmUDILDXmjg
|
||||
KxO9agRw9LXge4hgRL7YW0TxYZYw4EeXV9Yr7kcOq9DoO2MoRikJ+2Tuvvq/hfuV
|
||||
9zFHsz4jpf7W95k1IeH6bZ92klz5R1e/EK8JuHy592i/u+BxxW1vTkiPpTaHD6s9
|
||||
1lDSkT1j0LIDU6l9gVvJvFBV8j88vet/Z4QkTbHPMYvBnKNRstKuOvDasEJE4RkA
|
||||
PV4TfBwFF6uvREZI1vBboM/18pzeyjoRX+mlJNfcH3kh1tkck+Jg+M2bLXAH1EdD
|
||||
GRwENvnTNW1CFIn37VVja7SFBQNXA+E6rejmqtUmZ5XktSINDBUyjow9XuYTUtI/
|
||||
sgcRSC0aB0EKKpphbFPp1niKCLm1ef33e+bWyWbtR2L2Kc3ETmhjNADpyapAGmzc
|
||||
LP2BafGaKj18KiLAG4GL6+kXk0GUz7Fw5q8H8RY1T33o+xjWvC0+aJgvr65qWdKw
|
||||
+ug6wuu4Cr2kFEuXxPKsnYqmE5NT/x+lfunlZ5iEQN3w2XO5J2u2eMXVRUsPH2T6
|
||||
0sJKomjY0RB1JsqZBnyleWm+tYo0RpVAyJ3NGBp9dVb7a3Qw6jNZBG/xMW+gvtUJ
|
||||
q6hfK/cD3cagD0NQFVD5STMOuGOSqq/bbwAKjZ/lrPmCCYATKwkjAFybYfHJVrrW
|
||||
Y2tQgCQ/zrZLIxQjp7F17hU0+gT54x0MpF6AoqIM/qqNnHrQ0fi50ECmLvx3SqYa
|
||||
nvjvt/HZhMZfqRXiXjeicIwpnNoG7+uQknySk+7cc9GNhHZR7cfPfkTpgvuuebrQ
|
||||
l5YW+k9tG+xrX8g72nvtFMnammlBixlFwECJaEszEQk5tc2ti8uG2z+kGnFoDoBV
|
||||
M6ZVMpKDJzXPxLdzT6ChIPyatjIkqOKe6vDpnmzcoEhbBhmtkVjWFA2dfX846ugV
|
||||
y1QiecWgk8pMNWhh3IDd05v/wzbFwNcq+Gi+1dZsPmFH+egIcrQKZu2r3jCJtGHh
|
||||
DNG/nyf/anqvKXF90bi4hRT3vdDXXuWgY7EUwfn9h5jYabCO6HsQxQOBjFYNmBrh
|
||||
MfaiBZe72E8fzNAfIlwDcJ4AWY1SOM7hi8bqfRWw1NtNxuMUiRFoR31O6XkQauye
|
||||
9hAmpdlZHZXtJ6LM0QaWkPJmG3058GMtIn/qS60V9nINh+zXhwza/1pnFB+e9MWc
|
||||
hAPgo0nn55FusM//g1nM31PKe+nOm3Jyp0nEQ4m8aDtJS63o2fvp3e2KJbPWQMHE
|
||||
a83W975diWg4NTdevV9lFpNllHclVoPoavUHIzHd7HF9TcPpjbXJSUZ7cITHHefr
|
||||
kQTa/2G9cWuRhN9GKIHBdr13nfEvMIIFQQYJKoZIhvcNAQcBoIIFMgSCBS4wggUq
|
||||
MIIFJgYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECDgnjfOf
|
||||
AjArAgIIAASCBMgkbVuptroBdyMY5gl/eBQj5+iAV02YSaF969ihStLSWI4x5FAf
|
||||
HuDgqCyEMSl4RHG8ZvNaO9JoNfIpMK/TPQBoQRCzE2Vjf66VTERaQtU6h7tZrbQt
|
||||
K96n9eqvohm/vXbXe08fsodYp2s79kAvKgpuGG5iX77qYVzJHBPed87cvczo4ToP
|
||||
CpurDpByt8fGEmjtcikal8o+H9uoHjcFwqMigX1Q7IEjuKXrb5e6wTvxMRob8yfv
|
||||
LVl6ahteKSkWCMb6rLZ5f12jDoCGX/YXRrSsU9t/lXe0Nxv5i7c8flb2EsNtwygD
|
||||
fexVvn5u6ble6RDYNpuQkPgF41HyZh+JvGAF6i1r4tJPL9Pf4HnjEB8Y8IHgon+w
|
||||
T5I+8LTgcrWyhptzblXMjKySTEp9OEa2cCVwZkl4z43PWJ5oIAQ2IDTOQ603/5o/
|
||||
d9KA76/zMPQ5O0gv17OA7kwFv98v6sTcR4vgkQZqnyDpJSEPHyNxhw2MSBqS3jq3
|
||||
YPhRz+3Ei1oFp9uYFhzn39f9gzNi++X9pOjSrDb8v3mcDXZKNrxQLuoRMSf0eQNI
|
||||
dgJRqj/fuqNZ5ac3kd4P5BALCsnA1tM27zYrgUdpOnrc2D9FBthEjpRlQKMMzhQf
|
||||
cNMFWmoNjakDilvvLcsQeQ3P6cXbN1ODoNnjgK3VzcmeKyzW2PrTXEPHARUM3j4V
|
||||
sZzGaUOVKLqaaDrXWQKC0vrTvxP2WMfjQ1dTdXQP/kSZTXRC5rtB9tky38flBor0
|
||||
N9rhUDIGMs5qBvyrkV2hKXiW39G69p1KWY+Cw28AzY+CNSjePRi60TsnUxgcOS7i
|
||||
0AT25Gx3A4YqxmTY38MPB4wPcBPcw4hjNoQamaC9mqs+KVHcP5YHUlqykMeH0YVi
|
||||
J+ehytJE9xuDcfBOjxjadxp3/q/Lku4rky89gdJGFQWuuz75VulDywPRZRwmQTel
|
||||
sjEGMHR1zTOlPJdTDWhqaKmWvL4GhbCgEPIKwmqd1QKRTl/3Baa1nYllJeYVwiTT
|
||||
qLCkbA6qXrLGj1ENZxrKn9yqr8HwOoApjwhARu4LF/BRMgdkzelK2kOXHnZ26sZ2
|
||||
NY/MMtVmq4c59y6iQwmsbHr9tWGz3ahyXcZZufjNXU/AVnO1c92g7umAWZF4RohL
|
||||
gMmh57cAhN9PEbEv6j/6BT3XXp8jB0ywcRriYxfxwidviCKH/76Q4sytYJQaDFI1
|
||||
fnzmv0aDotbG2BdpWSiYPDOPm+3cmfjlULsn1FYWL4NDCX1f+C4lNtKVX9LU8c5M
|
||||
m8dA1DUlDfnuNO5/BShuoGXG2z4O/XwxIaRFizMxWS2sWurbAEFJ6oNw3kC7WSah
|
||||
NIe8aUC1umpc1Gk3X2f4Ytzj9OEqn0y55qoqLINJuejXMffF/gjopxHWadLVaVaj
|
||||
Q1SewrECuEXdSbBR/a10po24wmRtkmlvRJXJl7sG95xE5ZCqp+m6sRPWGdf1yKbV
|
||||
vyWNUe4Qvkxe4a0VAJpTyIGr980CKz/jkvtNQMobGl7AfhxKJ450wg454WcexMct
|
||||
BYXvZMSdUDCgMLlh0nHJHl5btrFWqE0Z/fqWmIknZL2jZ4J+2hdVl/xB/sUt6kcu
|
||||
txw+RfL+vNE8PxhTNaOdJFwD8yeN1mJ3yMUA8HHYpw9yljgxJTAjBgkqhkiG9w0B
|
||||
CRUxFgQUDYlgGVxSxuOknhQc256x3++7BDwwMTAhMAkGBSsOAwIaBQAEFFjASdYl
|
||||
3pXAXxZuvVvv9tsb4bdrBAhyb+KCIjp/gAICCAA='
|
||||
|
||||
# Provide Pass pharse of above PFX or p12 document
|
||||
PASS_PHRASE=opensign
|
||||
@@ -0,0 +1,73 @@
|
||||
name: "Bug Report"
|
||||
labels: ["bug","up-for-grabs"]
|
||||
title: "[Bug]: "
|
||||
assignees:
|
||||
- andrew-opensignlabs
|
||||
description: Create a bug report to help us make OpenSign™ the world's best document e-signature platform
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Please provide a clear & concise description of the problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: Describe what you expected to happen.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: Describe what is happening instead.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide step-by-step instructions to reproduce the issue. Include code snippets, URLs, error messages and any other relevant information.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots of the issue(optional)
|
||||
description: Add screenshots to better explain the issue.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Operating System [e.g. MacOS Sonoma 14.1, Windows 11]
|
||||
- type: dropdown
|
||||
id: browsers
|
||||
attributes:
|
||||
label: What browsers are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Safari
|
||||
- Microsoft Edge
|
||||
default: 0
|
||||
- type: input
|
||||
attributes:
|
||||
label: What version of OpenSign™ are you seeing this issue on? [e.g. 1.0.6]
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: environment
|
||||
attributes:
|
||||
label: What environment are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Production (app.opensignlabs.com)
|
||||
- Staging (staging-app.opensignlabs.com)
|
||||
- Hosted (app.yourdomain.com)
|
||||
- Dev (localhost or vercel)
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please check the boxes that apply to this issue report.
|
||||
options:
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
required: true
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for OpenSign™
|
||||
title: "Feature Request: [Short Description]"
|
||||
labels: [feature request, needs triage]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Thanks for taking the time to fill out this feature request!
|
||||
|
||||
- type: input
|
||||
id: title
|
||||
attributes:
|
||||
label: Feature Title
|
||||
description: What would you call this feature?
|
||||
placeholder: e.g., Advanced Signature Verification
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: |
|
||||
Please provide a detailed description of the feature you're proposing.
|
||||
placeholder: |
|
||||
e.g., I'm proposing an advanced signature verification feature that...
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: featuretype
|
||||
attributes:
|
||||
label: What type of feature are you requesting?
|
||||
multiple: true
|
||||
options:
|
||||
- UI/UX Improvement
|
||||
- Security / Compliance
|
||||
- Performance / Optimization
|
||||
- 3rd party integration
|
||||
- Other
|
||||
- type: dropdown
|
||||
id: importance
|
||||
attributes:
|
||||
label: Importance
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- Critical
|
||||
- High
|
||||
- Medium
|
||||
- Low
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other context or screenshots about the feature request here.
|
||||
placeholder: Additional details, examples, or screenshots...
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
required: true
|
||||
@@ -0,0 +1,22 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
# maintain dependencies for frontend
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "/apps/OpenSign" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# maintain dependencies for server
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "/apps/OpenSignServer" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# maintain dependencies for microfrontends
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "microfrontends/SignDocuments" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- feat-docs
|
||||
# Review gh actions docs if you want to further define triggers, paths, etc
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
- name: Install dependencies
|
||||
working-directory: ./docs
|
||||
run: npm ci
|
||||
- name: Clean api-docs
|
||||
working-directory: ./docs
|
||||
run: npm run docusaurus clean-api-docs all
|
||||
- name: Build api-docs
|
||||
working-directory: ./docs
|
||||
run: npm run docusaurus gen-api-docs all
|
||||
- name: Build website
|
||||
working-directory: ./docs
|
||||
run: npm run build
|
||||
|
||||
# Popular action to deploy to GitHub Pages:
|
||||
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Build output to publish to the `gh-pages` branch:
|
||||
publish_dir: ./docs/build
|
||||
# The following lines assign commit authorship to the official
|
||||
# GH-Actions bot for deploys to `gh-pages` branch:
|
||||
# https://github.com/actions/checkout/issues/13#issuecomment-724415212
|
||||
# The GH actions bot is used by default if you didn't specify the two fields.
|
||||
# You can swap them out with your own user credentials.
|
||||
user_name: github-actions[bot]
|
||||
user_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
@@ -22,3 +22,6 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
apps/OpenSign/public/mfbuild/*
|
||||
microfrontends/SignDocuments/build/*
|
||||
apps/OpenSignServer/files/files/*
|
||||
+3
-4
@@ -1,5 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx eslint '**/*.{js,jsx}'
|
||||
npx pretty-quick --staged '**/*.{js,jsx}'
|
||||
npm run lint-staged-changes
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"*.js": "prettier --write"
|
||||
}
|
||||
@@ -7,6 +7,7 @@ or follow below instructions to install it on your own infrastructure.
|
||||
|
||||
- Localhost(Frontend only)
|
||||
- Digital Ocean
|
||||
- Localhost(Docker)
|
||||
|
||||
## Localhost(Frontend only)
|
||||
|
||||
@@ -83,3 +84,66 @@ You can install all 3 components on digital ocean using the button below -
|
||||
|
||||
Visit below link if you face any issues while following the above instructions -
|
||||
- https://repost.aws/knowledge-center/create-access-key
|
||||
|
||||
|
||||
## Localhost(Docker)
|
||||
|
||||
For local Setup we need to need following prerequisite:
|
||||
|
||||
Environment Varaibles:
|
||||
|
||||
| Environment Varibale | Value | Description |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| CI | false | Set CI to false while running the app locally |
|
||||
| PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
|
||||
| GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging |
|
||||
| REACT_APP_SERVERURL | http://localhost:8080/app | Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead) |
|
||||
| REACT_APP_APPID | opensignstgn | A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API. |
|
||||
| APP_ID | opensignstgn | A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App. |
|
||||
| appName | open_sign_server | Name of the app. It will be visible in the verification emails sent out. |
|
||||
| MASTER_KEY | XnAadwKxxByMr | A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database. |
|
||||
| MONGODB_URI | mongodb://host.docker.internal:27017/OpenSignDB | Mongodb URI to connect to |
|
||||
| PARSE_MOUNT |/app | Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions. |
|
||||
| SERVER_URL | http://127.0.0.1:8080/app | Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead) |
|
||||
| DO_SPACE | DOSPACENAME | Digital ocean space name or AWS S3 bucket name for uploading documents |
|
||||
| DO_ENDPOINT | ams3.digitaloceanspaces.com | Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents |
|
||||
| DO_BASEURL |https://DOSPACENAME.ams3.digitaloceanspaces.com | Digital ocean baseurl or AWS S3 base URL |
|
||||
| DO_ACCESS_KEY_ID | YOUR_S3_ACCESS_ID | Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs |
|
||||
| DO_SECRET_ACCESS_KEY | YOUR_S3_ACCESS_KEY | Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs |
|
||||
| DO_REGION | YOUR_S3_REGION | Digital ocean spaces region or AWS s3 region |
|
||||
| USE_LOCAL | FALSE | To use local file storage to save file |
|
||||
| MAILGUN_API_KEY | YOUR_MAILGUNAPI_KEY | Mailgun API Key |
|
||||
| MAILGUN_DOMAIN | YOUR_MAILGUNAPI_DOMAIN | Mailgun API Domain |
|
||||
| MAILGUN_SENDER | - | Mailgun Sender Mail ID |
|
||||
| PFX_BASE64 | - | Base64 encoded PFX or p12 document signing certificate file. You can generate base64 encoded self sign certificate using the passphrase `emudhra` |
|
||||
|
||||
# Steps to Generate Self Sign Certificate
|
||||
```
|
||||
# execute below command and use passphrase emudhra
|
||||
openssl genrsa -des3 -out ./cert/local_dev.key 2048
|
||||
openssl req -key ./cert/local_dev.key -new -x509 -days 365 -out ./cert/local_dev.crt
|
||||
openssl pkcs12 -inkey ./cert/local_dev.key -in ./cert/local_dev.crt -export -out ./cert/local_dev.pfx
|
||||
openssl base64 -in ./cert/local_dev.pfx -out ./cert/base64_pfx
|
||||
```
|
||||
|
||||
# CORS Configuration
|
||||
|
||||
As document storage is delegated to S3-compatible services that reside in a different host than the OpenSign one, document operations (loading, storing, deleting) are subject to [Cross-Origin Resource Sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) restriction policies; as a consequence, OpenSign app may fail with (browser console) errors like the following:
|
||||
```
|
||||
Access to fetch at 'https://foo.nyc3.digitaloceanspaces.com/exported_file_4627_0000-00-00T00%3A45%3A43.344Z.pdf'
|
||||
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
|
||||
is present on the requested resource. If an opaque response serves your needs, set the request's mode to
|
||||
'no-cors' to fetch the resource with CORS disabled.
|
||||
```
|
||||
|
||||
In order to address this, your document storage system must be instructed to accept requests from other hosts; below the relevant documentation links:
|
||||
- [How to Configure CORS on DigitalOcean Spaces](https://docs.digitalocean.com/products/spaces/how-to/configure-cors/)
|
||||
- [Configuring cross-origin resource sharing on AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)
|
||||
|
||||
# Build Local Environment
|
||||
|
||||
Command to build project -
|
||||
- Execute `make build`
|
||||
|
||||
Command to run project -
|
||||
- Execute `make run`
|
||||
@@ -0,0 +1,9 @@
|
||||
build:
|
||||
cp .env.local_dev .env
|
||||
rm -rf apps/OpenSign/public/mfbuild
|
||||
cd microfrontends/SignDocuments && npm install && npm run build
|
||||
docker compose up --build --force-recreate
|
||||
|
||||
run:
|
||||
cp .env.local_dev .env
|
||||
docker compose up -d
|
||||
@@ -1,8 +1,7 @@
|
||||
<h1 align="center"><a href='https://www.opensignlabs.com'>OpenSign™</a></h1>
|
||||
|
||||
<div align="center">
|
||||
<h1 align="center"><a href='https://www.opensignlabs.com'><img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/e518cc9c-5de3-47da-950b-f93336b9f14e></a>
|
||||
</h1><div align="center">
|
||||
|
||||
The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign | Smartwaiver | SignRequest | HelloSign | Zoho sign.
|
||||
[The free and open source alternative to DocuSign](https://www.opensignlabs.com)
|
||||
|
||||
[](http://isitmaintained.com/project/opensignlabs/opensign "Average time to resolve an issue")
|
||||
[](#contributors)
|
||||
@@ -23,7 +22,7 @@ The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign |
|
||||
<a href="https://www.linkedin.com/company/opensign%E2%84%A2/about/">LinkedIn</a>
|
||||
|
||||
|
||||
## An Open-Source Alternative to DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, and HelloSign
|
||||
## The open-source document e-signing solution
|
||||
|
||||
---
|
||||
</div>
|
||||
@@ -48,14 +47,18 @@ Welcome to OpenSign, an open-source document e-signing solution designed to prov
|
||||
|
||||
### Features
|
||||
|
||||
- **Secure Signing**: Utilizes state-of-the-art cryptographic algorithms to ensure the security & integrity of your documents.
|
||||
- **User-Friendly Interface**: Designed with usability in mind, making it easy for both technical and non-technical users.
|
||||
- **Multi-Platform Support**: Compatible with various browsers and devices.
|
||||
- **Invite & collaborate users**: Bring multiple people from your team into the signing process, all within your own infrastructure.
|
||||
- **Secure**: Allows for the easy, secure and seamless organization of your documents using 'OpenSigDrive'.
|
||||
- **Audit Trails**: Keeps a detailed log of all activities related to the document signing process including IP addresses and access timings.
|
||||
- **Completion Certificate**: Generate secure completion certificate as soon as a document is signed by all participants.
|
||||
- **API Support**: Provides a robust API for integration into other software and services.
|
||||
- **Secure PDF E-Signing:** With the help of Robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
|
||||
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that comes with hand drawn signatures support as well as uploaded images & saved signatures for the simplest signing experience.
|
||||
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders.
|
||||
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players.
|
||||
- **Email Unique Code(OTP) verification support for guest signers:** With OpenSign™, your documents are fully secure even when being signed by guest users. Guest signers can only sign the document after entering a unique code sent to their email address.
|
||||
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign it. Not just this, OpenSign also allows signers to reject signing a document.
|
||||
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates.
|
||||
- **PDF Template Creation(coming soon):** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time.
|
||||
- **OpenSign™ Drive:** It is a centralised secure vault for your signed documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
|
||||
- **Audit Trails & completion certificate:** Being a security focused solution, OpenSign™ makes it a top priority to save detailed logs for tracking document activities along with time-stamps, IP addresses, email IDs & phone numbers. A completion certificate is generated as soon as document is completed which contains all the document related logs for added safety.
|
||||
- **API Support(coming soon):** OpenSign™ API allows seamless integration into existing systems and software. APIs will soon be available as a cloud hosted solution.
|
||||
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is coming soon.
|
||||
|
||||
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/b37ff443-7099-4273-9aeb-21c46d7154cf height='200'>
|
||||
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/86db91b7-6c2f-4885-a33c-58f4fd35ec89 height='200'>
|
||||
@@ -122,6 +125,14 @@ We would like to thank all our contributors and users for their support and feed
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VishakhaSainani"><img src="https://avatars.githubusercontent.com/u/113436770?v=4?s=100" width="100px;" alt="VishakhaSainani"/><br /><sub><b>VishakhaSainani</b></sub></a><br /><a href="#code-VishakhaSainani" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrew-opensignlabs"><img src="https://avatars.githubusercontent.com/u/148278535?v=4?s=100" width="100px;" alt="Andrew"/><br /><sub><b>Andrew</b></sub></a><br /><a href="#code-andrew-opensignlabs" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rishabjasrotia"><img src="https://avatars.githubusercontent.com/u/33950743?v=4?s=100" width="100px;" alt="Rishab"/><br /><sub><b>Rishab</b></sub></a><br /><a href="#code-rishabjasrotia" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://session.it"><img src="https://avatars.githubusercontent.com/u/327285?v=4?s=100" width="100px;" alt="Maurizio Pillitu"/><br /><sub><b>Maurizio Pillitu</b></sub></a><br /><a href="#bug-maoo" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://luisparra.dev"><img src="https://avatars.githubusercontent.com/u/16653744?v=4?s=100" width="100px;" alt="Luis Parra"/><br /><sub><b>Luis Parra</b></sub></a><br /><a href="#a11y-lsprr" title="Accessibility">️️️️♿️</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Govinda04"><img src="https://avatars.githubusercontent.com/u/50038172?v=4?s=100" width="100px;" alt="Govinda Kocharekar"/><br /><sub><b>Govinda Kocharekar</b></sub></a><br /><a href="#code-Govinda04" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://bilal.cc"><img src="https://avatars.githubusercontent.com/u/55330484?v=4?s=100" width="100px;" alt="Bilal Ahmad Bhat"/><br /><sub><b>Bilal Ahmad Bhat</b></sub></a><br /><a href="#code-crediblebilal" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
# production
|
||||
/build
|
||||
/mfbuild
|
||||
|
||||
# misc
|
||||
.env
|
||||
|
||||
@@ -5,14 +5,14 @@ FROM node:16
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package.json and package-lock.json first to leverage Docker cache
|
||||
COPY apps/OpenSign/package*.json ./
|
||||
COPY ./package*.json ./
|
||||
|
||||
# Install application dependencies
|
||||
RUN npm install
|
||||
|
||||
# Copy the current directory contents into the container
|
||||
COPY apps/OpenSign/ .
|
||||
COPY apps/OpenSign/.husky .
|
||||
COPY ./ .
|
||||
COPY ./.husky .
|
||||
|
||||
# Make port 3000 available to the world outside this container
|
||||
EXPOSE 3000
|
||||
@@ -21,5 +21,5 @@ EXPOSE 3000
|
||||
# ENV NODE_ENV production
|
||||
|
||||
# Run the application
|
||||
CMD ["npm", "start"]
|
||||
ENTRYPOINT npm run start-dev
|
||||
|
||||
|
||||
@@ -40,8 +40,10 @@
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "mf-cra start",
|
||||
"build": "npm run micro && CI=false && mf-cra build",
|
||||
"start": "serve -s build",
|
||||
"start-dev": "mf-cra start",
|
||||
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
||||
"build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
|
||||
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
|
||||
|
||||
<title>Open sign</title>
|
||||
<title>OpenSign™</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -50,4 +50,4 @@
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
v1.0.5-beta
|
||||
@@ -14,6 +14,7 @@ import PageNotFound from "./routes/PageNotFound";
|
||||
import ForgetPassword from "./routes/ForgetPassword";
|
||||
import ChangePassword from "./routes/ChangePassword";
|
||||
import ReportMicroapp from "./components/ReportMicroapp";
|
||||
import LoadMf from "./routes/LoadMf";
|
||||
|
||||
function App() {
|
||||
const [isloading, setIsLoading] = useState(true);
|
||||
@@ -59,6 +60,7 @@ function App() {
|
||||
<Routes>
|
||||
<Route exact path="/" element={<Login />} />
|
||||
<Route exact path="/signup" element={<Signup />} />
|
||||
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
|
||||
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
|
||||
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
|
||||
<>
|
||||
|
||||
@@ -32,6 +32,7 @@ const AppendFormInForm = (props) => {
|
||||
try {
|
||||
const query = new Parse.Query("contracts_Contactbook");
|
||||
query.equalTo("CreatedBy", user);
|
||||
query.notEqualTo("IsDeleted", true);
|
||||
query.equalTo("Email", user.getEmail());
|
||||
const res = await query.first();
|
||||
// console.log(res);
|
||||
@@ -241,26 +242,6 @@ const AppendFormInForm = (props) => {
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
Phone
|
||||
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="phone"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
required
|
||||
disabled={addYourself}
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="email"
|
||||
@@ -279,6 +260,24 @@ const AppendFormInForm = (props) => {
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
Phone
|
||||
<span style={{ color: "red", fontSize: 13 }}> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="phone"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
required
|
||||
disabled={addYourself}
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex justify-start">
|
||||
<button
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Package from "../../package.json";
|
||||
|
||||
import axios from "axios";
|
||||
const Footer = () => {
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
axios
|
||||
.get("/version.txt")
|
||||
.then((response) => {
|
||||
setVersion(response.data); // Set the retrieved data to the state variable
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error reading the file:", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleScroll = () => {
|
||||
if (window.pageYOffset >= 50) {
|
||||
setShowButton(true);
|
||||
@@ -25,16 +37,12 @@ const Footer = () => {
|
||||
}, []);
|
||||
|
||||
const appName = "OpenSign™";
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
|
||||
All Rights Reserved © {new Date().getFullYear()}
|
||||
{appName}{" "}
|
||||
(version:{" "}
|
||||
{localStorage.getItem("appVersion") &&
|
||||
`${Package.version}.${localStorage.getItem("appVersion")}`}
|
||||
)
|
||||
{appName} ( version: {version ? version : `${Package.version} `})
|
||||
</div>
|
||||
<button
|
||||
className={`${
|
||||
|
||||
@@ -27,14 +27,14 @@ const LoginFacebook = ({
|
||||
setThirdpartyLoader(true);
|
||||
const details = {
|
||||
Email: response.email,
|
||||
Name: response.name,
|
||||
Name: response.name
|
||||
};
|
||||
setUserDetails({ ...userDetails, ...details });
|
||||
const fDetails = {
|
||||
Id: response.userID,
|
||||
AccessToken: response.accessToken,
|
||||
Name: response.name,
|
||||
Email: response.email,
|
||||
Email: response.email
|
||||
};
|
||||
setFBDetails({ ...fBDetails, ...fDetails });
|
||||
const res = await checkExtUser(fDetails);
|
||||
@@ -42,9 +42,11 @@ const LoginFacebook = ({
|
||||
};
|
||||
|
||||
const checkExtUser = async (details) => {
|
||||
const extUser = new Parse.Query("contracts_Users");
|
||||
extUser.equalTo("Email", details.Email);
|
||||
const extRes = await extUser.first();
|
||||
// const extUser = new Parse.Query("contracts_Users");
|
||||
// extUser.equalTo("Email", details.Email);
|
||||
// const extRes = await extUser.first();
|
||||
const params = { email: details.Email };
|
||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||
// console.log("extRes ", extRes);
|
||||
if (extRes) {
|
||||
const params = { ...details, Phone: extRes.get("Phone") };
|
||||
@@ -209,18 +211,19 @@ const LoginFacebook = ({
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setIsModal(false)}
|
||||
style={{ marginRight: 10, width: 90 }}
|
||||
onClick={() => handleSubmitbtn()}
|
||||
className="btn btn-info"
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
Cancel
|
||||
Sign up
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSubmitbtn()}
|
||||
className="btn btn-info"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setIsModal(false)}
|
||||
style={{ width: 90 }}
|
||||
>
|
||||
Sign up
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -42,7 +42,42 @@ const GoogleSignInBtn = ({
|
||||
width: "187px"
|
||||
});
|
||||
});
|
||||
const clearStorage = async () => {
|
||||
if (Parse.User.current()) {
|
||||
await Parse.User.logOut();
|
||||
}
|
||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
||||
let appid = localStorage.getItem("AppID12");
|
||||
let applogo = localStorage.getItem("appLogo");
|
||||
let domain = localStorage.getItem("domain");
|
||||
let appversion = localStorage.getItem("appVersion");
|
||||
let appTitle = localStorage.getItem("appTitle");
|
||||
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
||||
let PageLanding = localStorage.getItem("PageLanding");
|
||||
let _appName = localStorage.getItem("_appName");
|
||||
let _app_objectId = localStorage.getItem("_app_objectId");
|
||||
let appName = localStorage.getItem("appName");
|
||||
let userSettings = localStorage.getItem("userSettings");
|
||||
|
||||
localStorage.clear();
|
||||
|
||||
localStorage.setItem("BaseUrl12", baseUrl);
|
||||
localStorage.setItem("AppID12", appid);
|
||||
localStorage.setItem("appLogo", applogo);
|
||||
localStorage.setItem("domain", domain);
|
||||
localStorage.setItem("appversion", appversion);
|
||||
localStorage.setItem("appTitle", appTitle);
|
||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||
localStorage.setItem("PageLanding", PageLanding);
|
||||
localStorage.setItem("_appName", _appName);
|
||||
localStorage.setItem("_app_objectId", _app_objectId);
|
||||
localStorage.setItem("appName", appName);
|
||||
localStorage.setItem("userSettings", userSettings);
|
||||
localStorage.setItem("baseUrl", baseUrl);
|
||||
localStorage.setItem("parseAppId", appid);
|
||||
};
|
||||
const responseGoogle = async (response) => {
|
||||
clearStorage();
|
||||
setThirdpartyLoader(true);
|
||||
// console.log("response ", response);
|
||||
if (response.credential) {
|
||||
@@ -66,9 +101,11 @@ const GoogleSignInBtn = ({
|
||||
}
|
||||
};
|
||||
const checkExtUser = async (details) => {
|
||||
const extUser = new Parse.Query("contracts_Users");
|
||||
extUser.equalTo("Email", details.Gmail);
|
||||
const extRes = await extUser.first();
|
||||
// const extUser = new Parse.Query("contracts_Users");
|
||||
// extUser.equalTo("Email", details.Gmail);
|
||||
// const extRes = await extUser.first();
|
||||
const params = { email: details.Gmail };
|
||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||
// console.log("extRes ", extRes);
|
||||
if (extRes) {
|
||||
const params = { ...details, Phone: extRes.get("Phone") };
|
||||
@@ -141,6 +178,32 @@ const GoogleSignInBtn = ({
|
||||
alert("Please fill required details!");
|
||||
}
|
||||
};
|
||||
const handleCloseModal = () => {
|
||||
setIsModal(false);
|
||||
Parse.User.logOut();
|
||||
|
||||
let appdata = localStorage.getItem("userSettings");
|
||||
let applogo = localStorage.getItem("appLogo");
|
||||
let appName = localStorage.getItem("appName");
|
||||
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
||||
let PageLanding = localStorage.getItem("PageLanding");
|
||||
let domain = localStorage.getItem("domain");
|
||||
let _appName = localStorage.getItem("_appName");
|
||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
||||
let appid = localStorage.getItem("AppID12");
|
||||
|
||||
localStorage.clear();
|
||||
|
||||
localStorage.setItem("appLogo", applogo);
|
||||
localStorage.setItem("appName", appName);
|
||||
localStorage.setItem("_appName", _appName);
|
||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||
localStorage.setItem("PageLanding", PageLanding);
|
||||
localStorage.setItem("domain", domain);
|
||||
localStorage.setItem("userSettings", appdata);
|
||||
localStorage.setItem("BaseUrl12", baseUrl);
|
||||
localStorage.setItem("AppID12", appid);
|
||||
};
|
||||
return (
|
||||
<div style={{ position: "relative" }}>
|
||||
{thirdpartyLoader && (
|
||||
@@ -235,17 +298,17 @@ const GoogleSignInBtn = ({
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="Destination"
|
||||
htmlFor="JobTitle"
|
||||
style={{ display: "flex" }}
|
||||
className="col-form-label"
|
||||
>
|
||||
Destination{" "}
|
||||
Job Title{" "}
|
||||
<span style={{ fontSize: 13, color: "red" }}>*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="Destination"
|
||||
id="JobTitle"
|
||||
value={userDetails.Destination}
|
||||
onChange={(e) =>
|
||||
setUserDetails({
|
||||
@@ -259,18 +322,19 @@ const GoogleSignInBtn = ({
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setIsModal(false)}
|
||||
style={{ marginRight: 10, width: 90 }}
|
||||
className="bg-[#17a2b8] p-2 text-white rounded"
|
||||
onClick={() => handleSubmitbtn()}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
Cancel
|
||||
Sign up
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSubmitbtn()}
|
||||
className="btn btn-info"
|
||||
className="bg-[#6c757d] p-2 text-white rounded"
|
||||
onClick={handleCloseModal}
|
||||
style={{ width: 90 }}
|
||||
>
|
||||
Sign up
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import useFederatedComponent from "mf-cra";
|
||||
import React, { Suspense, useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
const MicroappModal = () => {
|
||||
const { remoteApp } = useParams();
|
||||
@@ -15,7 +15,9 @@ const MicroappModal = () => {
|
||||
// console.log("value ", key + ":" + value);
|
||||
|
||||
if (key === "remoteUrl") {
|
||||
obj = { ...obj, [key]: atob(value) };
|
||||
const url = window.location.origin + "/mfbuild/remoteEntry.js";
|
||||
// console.log("atob(value) ", atob(value))
|
||||
obj = { ...obj, [key]: url };
|
||||
} else {
|
||||
if (key === "moduleToLoad") {
|
||||
obj = { ...obj, [key]: "./" + value };
|
||||
@@ -26,60 +28,36 @@ const MicroappModal = () => {
|
||||
}
|
||||
// console.log("app ", remoteApp);
|
||||
const { Component: RemoteComponent } = useFederatedComponent(obj);
|
||||
const navigate = useNavigate();
|
||||
// console.log("RemoteComponent ", RemoteComponent);
|
||||
return (
|
||||
<div className="w-full h-full flex items-center justify-center ">
|
||||
{/* <!-- Modal Container --> */}
|
||||
<div className="bg-white rounded-lg shadow-lg w-full">
|
||||
{/* <!-- Modal Header --> */}
|
||||
<div className="flex w-full items-center border-b-2 mb-2 p-2">
|
||||
<button
|
||||
className="focus:outline-none bg-blue-500 text-white text-sm shadow px-2.5 py-1 rounded"
|
||||
id="closeModal"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// setIsModal(false);
|
||||
navigate(-1);
|
||||
<div className="w-full">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div style={{ height: "300px" }}>
|
||||
<div
|
||||
style={{
|
||||
marginLeft: "45%",
|
||||
marginTop: "150px",
|
||||
fontSize: "45px",
|
||||
color: "#3dd3e0"
|
||||
}}
|
||||
className="loader-37"
|
||||
></div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "#ffffff",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
minHeight: "50vh"
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
{localStorage.getItem('domain') && (
|
||||
<p className="flex-1 w-full text-sm md:text-base text-black text-center">
|
||||
{localStorage.getItem('domain') === "contracts" ? "Document":""}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* <!-- Modal Body --> */}
|
||||
<div className="w-full">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div style={{ height: "300px" }}>
|
||||
<div
|
||||
style={{
|
||||
marginLeft: "45%",
|
||||
marginTop: "150px",
|
||||
fontSize: "45px",
|
||||
color: "#3dd3e0"
|
||||
}}
|
||||
className="loader-37"
|
||||
></div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "#ffffff",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
minHeight: "50vh"
|
||||
}}
|
||||
>
|
||||
{RemoteComponent && <RemoteComponent />}
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
{RemoteComponent && <RemoteComponent />}
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -49,12 +49,9 @@ const TreeWidget = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
var emp = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
var q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
res = await q.first();
|
||||
res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (res) res = res.toJSON();
|
||||
}
|
||||
if (res) {
|
||||
@@ -79,12 +76,9 @@ const TreeWidget = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
emp = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
res = await q.first();
|
||||
res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (res) res = res.toJSON();
|
||||
}
|
||||
|
||||
@@ -121,10 +115,15 @@ const TreeWidget = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
emp = Parse.Object.extend(localStorage.getItem("extended_class"));
|
||||
q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
res = await q.first();
|
||||
// emp = Parse.Object.extend(localStorage.getItem("extended_class"));
|
||||
// q = new Parse.Query(emp);
|
||||
// q.equalTo("UserId", currentUser);
|
||||
// res = await q.first();
|
||||
// if (res) res = res.toJSON();
|
||||
const currentUser = Parse.User.current();
|
||||
res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (res) res = res.toJSON();
|
||||
}
|
||||
|
||||
@@ -473,6 +472,8 @@ const TreeWidget = (props) => {
|
||||
props.schema.data.FolderTypeField,
|
||||
props.schema.data.FolderTypeValue
|
||||
);
|
||||
const currentUser = Parse.User.current();
|
||||
folder.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||
if (tabList.length > 0) {
|
||||
let len = tabList.length - 1;
|
||||
folder.set(props.schema.data.ParentFolderField, {
|
||||
@@ -532,7 +533,7 @@ const TreeWidget = (props) => {
|
||||
padding: 0
|
||||
},
|
||||
overlay: {
|
||||
width:"100%",
|
||||
width: "100%",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
||||
zIndex: 50
|
||||
}
|
||||
@@ -699,7 +700,7 @@ const TreeWidget = (props) => {
|
||||
))}
|
||||
<hr />
|
||||
</div>
|
||||
{editable && (
|
||||
{/* {editable && (
|
||||
<TreeEditForm
|
||||
FormId={props.schema.data.FormId}
|
||||
objectId={editId}
|
||||
@@ -708,7 +709,7 @@ const TreeWidget = (props) => {
|
||||
selectFolderHandle();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
)} */}
|
||||
{isAddField && !loader && !editable && (
|
||||
<TreeFormComponent
|
||||
Id={props.schema.data.FormId}
|
||||
@@ -796,7 +797,7 @@ const TreeWidget = (props) => {
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{fldr[props.schema.data.FolderTypeField] ===
|
||||
{/* {fldr[props.schema.data.FolderTypeField] ===
|
||||
props.schema.data.FolderTypeValue && (
|
||||
<a
|
||||
className="float-right"
|
||||
@@ -816,7 +817,7 @@ const TreeWidget = (props) => {
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</a>
|
||||
)}
|
||||
)} */}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import Parse from "parse";
|
||||
import onSearchFilter from "../../constant/searchQuery";
|
||||
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
|
||||
import "../../styles/loader.css";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@@ -35,14 +34,9 @@ const DashboardCard = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
var emp = Parse.Object.extend(localStorage.getItem("extended_class"));
|
||||
var q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUser
|
||||
res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
res = await q.first();
|
||||
if (res) res = res.toJSON();
|
||||
}
|
||||
if (res) {
|
||||
@@ -50,12 +44,7 @@ const DashboardCard = (props) => {
|
||||
var reg = /(\#.*?\#)/gi; // eslint-disable-line
|
||||
var str = props.Data.query;
|
||||
var test = "";
|
||||
if (str.includes("#filterCondition#")) {
|
||||
str = str.replace(
|
||||
"#filterCondition#",
|
||||
onSearchFilter(props.DefaultQuery)
|
||||
);
|
||||
}
|
||||
|
||||
if (props.Data.extendkey) {
|
||||
let a = props.Data.extendkey.split(".");
|
||||
if (a.length > 0) {
|
||||
@@ -110,13 +99,10 @@ const DashboardCard = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
resr = data[0];
|
||||
} else {
|
||||
let emp = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
let q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
let t = await q.first();
|
||||
resr = t.toJSON();
|
||||
resr = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (resr) resr = resr.toJSON();
|
||||
}
|
||||
|
||||
let json = resr;
|
||||
@@ -150,47 +136,65 @@ const DashboardCard = (props) => {
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
};
|
||||
await axios.get(url, { headers: headers }).then((res) => {
|
||||
if (res.data.results.length > 0) {
|
||||
setLoading(false);
|
||||
if (props.Data.key !== "count") {
|
||||
setresponse(res.data.results[0][props.Data.key]);
|
||||
} else {
|
||||
if (props.Label === "Need your Signature") {
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
// handle need your sign report count
|
||||
if (props.Data.Redirect_id === "4Hhwbp482K") {
|
||||
const params = {
|
||||
reportId: props.Data.Redirect_id,
|
||||
skip: 0,
|
||||
limit: 200
|
||||
};
|
||||
const url = `${parseBaseUrl}/functions/getReport`;
|
||||
await axios
|
||||
.post(url, params, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
sessiontoken: localStorage.getItem("accesstoken")
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
const listData = res.data?.result.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
(item) => item.UserId.objectId === currentUser.id
|
||||
);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
(item) => item.UserId.objectId === currentUser.id
|
||||
);
|
||||
if (isSigner) {
|
||||
let isRecord;
|
||||
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
|
||||
isRecord = obj?.AuditTrail.some(
|
||||
(item) =>
|
||||
item?.UserPtr?.UserId?.objectId === currentUser.id &&
|
||||
item.Activity === "Signed"
|
||||
);
|
||||
} else {
|
||||
isRecord = false;
|
||||
}
|
||||
if (isRecord === false) {
|
||||
arr.push(obj);
|
||||
}
|
||||
if (isSigner) {
|
||||
let isRecord;
|
||||
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
|
||||
isRecord = obj?.AuditTrail.some(
|
||||
(item) =>
|
||||
item?.UserPtr?.UserId?.objectId === currentUser.id &&
|
||||
item.Activity === "Signed"
|
||||
);
|
||||
} else {
|
||||
isRecord = false;
|
||||
}
|
||||
if (isRecord === false) {
|
||||
arr.push(obj);
|
||||
}
|
||||
}
|
||||
setresponse(arr.length);
|
||||
}
|
||||
setresponse(arr.length);
|
||||
setLoading(false);
|
||||
});
|
||||
} else {
|
||||
await axios.get(url, { headers: headers }).then((res) => {
|
||||
if (res.data.results.length > 0) {
|
||||
setLoading(false);
|
||||
if (props.Data.key !== "count") {
|
||||
setresponse(res.data.results[0][props.Data.key]);
|
||||
} else {
|
||||
setresponse(res.data[props.Data.key]);
|
||||
}
|
||||
} else {
|
||||
setresponse(0);
|
||||
setLoading(false);
|
||||
}
|
||||
} else {
|
||||
setresponse(0);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Problem", e);
|
||||
setLoading(false);
|
||||
@@ -227,13 +231,10 @@ const DashboardCard = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
var emp = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
var q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
let resr = await q.first();
|
||||
res = resr.toJSON();
|
||||
let resr = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (res) res = resr.toJSON();
|
||||
}
|
||||
|
||||
let json = res;
|
||||
|
||||
@@ -9,39 +9,60 @@ function DashboardReport(props) {
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
const [reportName, setReportName] = useState("");
|
||||
const [actions, setActions] = useState([]);
|
||||
const [heading, setHeading] = useState([]);
|
||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
||||
const abortController = new AbortController();
|
||||
const docPerPage = 5;
|
||||
|
||||
useEffect(() => {
|
||||
setReportName("");
|
||||
getReportData(props.Record.reportId);
|
||||
|
||||
// Function returned from useEffect is called on unmount
|
||||
return () => {
|
||||
setIsLoader(true);
|
||||
setList([]);
|
||||
setIsNextRecord(false);
|
||||
// Here it'll abort the fetch
|
||||
abortController.abort();
|
||||
};
|
||||
// eslint-disable-next-line
|
||||
}, [props.Record.reportId]);
|
||||
|
||||
const getReportData = async (id) => {
|
||||
// below useEffect call when isNextRecord state is true and fetch next record
|
||||
useEffect(() => {
|
||||
if (isNextRecord) {
|
||||
getReportData(props.Record.reportId, List.length, 200);
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [isNextRecord]);
|
||||
|
||||
const getReportData = async (id, skipUserRecord = 0, limit = 200) => {
|
||||
setIsLoader(true);
|
||||
const json = reportJson(id);
|
||||
if (json) {
|
||||
setActions(json.actions);
|
||||
setReportName(json.reportName);
|
||||
const { className, params, keys, orderBy } = json;
|
||||
setHeading(json.heading);
|
||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
||||
Parse.initialize(localStorage.getItem("AppID12"));
|
||||
const serverURL =
|
||||
localStorage.getItem("BaseUrl12") + "classes/" + className;
|
||||
const currentUser = Parse.User.current().id;
|
||||
|
||||
const strParams = JSON.stringify(params);
|
||||
const strKeys = keys.join();
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
sessiontoken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
try {
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
// console.log("res ", res.data?.results);
|
||||
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
||||
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
|
||||
const res = await axios.post(url, params, {
|
||||
headers: headers,
|
||||
signal: abortController.signal // is used to cancel fetch query
|
||||
});
|
||||
if (id === "5Go51Q7T8r") {
|
||||
const currentUser = Parse.User.current().id;
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
const listData = res.data?.result.filter((x) => x.Signers.length > 0);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
@@ -63,14 +84,34 @@ function DashboardReport(props) {
|
||||
}
|
||||
}
|
||||
}
|
||||
setList(arr);
|
||||
if (arr.length === docPerPage) {
|
||||
setIsMoreDocs(true);
|
||||
} else {
|
||||
setIsMoreDocs(false);
|
||||
}
|
||||
setList((prevRecord) =>
|
||||
prevRecord.length > 0 ? [...prevRecord, ...arr] : arr
|
||||
);
|
||||
} else {
|
||||
setList(res.data?.results);
|
||||
if (res.data.result.length === docPerPage) {
|
||||
setIsMoreDocs(true);
|
||||
} else {
|
||||
setIsMoreDocs(false);
|
||||
}
|
||||
setIsNextRecord(false);
|
||||
setList((prevRecord) =>
|
||||
prevRecord.length > 0
|
||||
? [...prevRecord, ...res.data.result]
|
||||
: res.data.result
|
||||
);
|
||||
}
|
||||
setIsLoader(false);
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
setIsLoader(false);
|
||||
const isCancel = axios.isCancel(err);
|
||||
if (!isCancel) {
|
||||
console.log("err ", err);
|
||||
setIsLoader(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setIsLoader(false);
|
||||
@@ -101,8 +142,12 @@ function DashboardReport(props) {
|
||||
<ReportTable
|
||||
ReportName={reportName}
|
||||
List={List}
|
||||
act={"Sign"}
|
||||
setList={setList}
|
||||
actions={actions}
|
||||
heading={heading}
|
||||
setIsNextRecord={setIsNextRecord}
|
||||
isMoreDocs={isMoreDocs}
|
||||
docPerPage={docPerPage}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { useState, Suspense, lazy } from "react";
|
||||
import moment from "moment";
|
||||
import React, { Suspense, lazy } from "react";
|
||||
import ErrorBoundary from "../ErrorBoundary";
|
||||
|
||||
const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||
@@ -7,258 +6,6 @@ const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||
const DashboardReport = lazy(() => import("./DashboardReport"));
|
||||
|
||||
const GetDashboard = (props) => {
|
||||
const [filter, setfilter] = useState("");
|
||||
const [option, setoption] = useState("");
|
||||
|
||||
const onSearchFilter = (e) => {
|
||||
let _search = e.target.value;
|
||||
localStorage.setItem("DashboardDefaultFilter", _search);
|
||||
switch (_search) {
|
||||
case "Today": {
|
||||
let d = new Date();
|
||||
let formDate = new Date(
|
||||
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
let Todate = new Date(
|
||||
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
|
||||
setfilter(Query);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Yesterday": {
|
||||
let d1 = new Date();
|
||||
d1.setDate(d1.getDate() - 1);
|
||||
let yesFrDate = new Date(
|
||||
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
|
||||
let YesTodate = new Date(
|
||||
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
|
||||
setfilter(Query1);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "This week": {
|
||||
let oneDay = 24 * 60 * 60 * 1000;
|
||||
let curr = new Date(); // get current date
|
||||
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
|
||||
|
||||
let firstday = new Date(
|
||||
new Date(
|
||||
Date.UTC(
|
||||
curr.getFullYear(),
|
||||
curr.getMonth(),
|
||||
curr.getDate(),
|
||||
0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
).setDate(first)
|
||||
).toISOString();
|
||||
let diffDays = Math.round(
|
||||
Math.abs(
|
||||
(new Date(
|
||||
Date.UTC(
|
||||
curr.getFullYear(),
|
||||
curr.getMonth(),
|
||||
curr.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
) -
|
||||
new Date(firstday)) /
|
||||
oneDay
|
||||
)
|
||||
); //Days since last week
|
||||
let last = first + diffDays;
|
||||
let lastday = new Date(
|
||||
new Date(
|
||||
Date.UTC(
|
||||
curr.getFullYear(),
|
||||
curr.getMonth(),
|
||||
curr.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).setDate(last)
|
||||
).toISOString();
|
||||
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
|
||||
setfilter(Query2);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last 7 days": {
|
||||
let d7 = new Date();
|
||||
let d7l = new Date();
|
||||
d7.setDate(d7.getDate() - 7);
|
||||
let l7t = new Date(
|
||||
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let date7 = new Date(
|
||||
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
|
||||
setfilter(Query7);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last 14 days": {
|
||||
let d14 = new Date();
|
||||
let d14l = new Date();
|
||||
let l14t = new Date(
|
||||
Date.UTC(
|
||||
d14l.getFullYear(),
|
||||
d14l.getMonth(),
|
||||
d14l.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).toISOString();
|
||||
d14.setDate(d14.getDate() - 14);
|
||||
let date14 = new Date(
|
||||
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
|
||||
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
|
||||
setfilter(Query14);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last 30 days": {
|
||||
let d30 = new Date();
|
||||
let d30l = new Date();
|
||||
let l30t = new Date(
|
||||
Date.UTC(
|
||||
d30l.getFullYear(),
|
||||
d30l.getMonth(),
|
||||
d30l.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).toISOString();
|
||||
d30.setDate(d30.getDate() - 30);
|
||||
let date30 = new Date(
|
||||
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
let Query30 = `'$gte':'${date30}','$lte':'${l30t}'`;
|
||||
setfilter(Query30);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last week": {
|
||||
const from_date = moment().startOf("week").subtract(7, "days");
|
||||
const to_date = moment().endOf("week").subtract(7, "days");
|
||||
let Queryl = `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
|
||||
setfilter(Queryl);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "This month": {
|
||||
const tdate = new Date();
|
||||
let tfirstDay = new Date(
|
||||
tdate.getFullYear(),
|
||||
tdate.getMonth(),
|
||||
1
|
||||
).toISOString();
|
||||
let tlastDay = new Date(
|
||||
tdate.getFullYear(),
|
||||
tdate.getMonth() + 1,
|
||||
0
|
||||
).toISOString();
|
||||
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
|
||||
setfilter(Querylt);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last month": {
|
||||
const ldate = new Date();
|
||||
var lfirstDay = new Date(
|
||||
ldate.getFullYear(),
|
||||
ldate.getMonth() - 1,
|
||||
2
|
||||
).toISOString();
|
||||
var llastDay = new Date(
|
||||
ldate.getFullYear(),
|
||||
ldate.getMonth(),
|
||||
1
|
||||
).toISOString();
|
||||
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
|
||||
setfilter(Queryltl);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "All": {
|
||||
let fall = new Date(
|
||||
new Date().getFullYear() - 100,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).toISOString();
|
||||
let fall_year = `'$gte':'${fall}'`;
|
||||
setfilter(fall_year);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "This year": {
|
||||
let fcy = new Date(
|
||||
new Date().getFullYear(),
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).toISOString();
|
||||
let lcy = new Date(
|
||||
new Date().getFullYear(),
|
||||
11,
|
||||
31,
|
||||
23,
|
||||
59,
|
||||
59
|
||||
).toISOString();
|
||||
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
|
||||
setfilter(cur_year);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
case "Last year": {
|
||||
let fly = new Date(
|
||||
new Date().getFullYear() - 1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).toISOString();
|
||||
let lly = new Date(
|
||||
new Date().getFullYear() - 1,
|
||||
11,
|
||||
31,
|
||||
23,
|
||||
59,
|
||||
59
|
||||
).toISOString();
|
||||
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
|
||||
setfilter(last_year);
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setoption(_search);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
const renderSwitchWithTour = (col) => {
|
||||
switch (col.widget.type) {
|
||||
case "Card":
|
||||
@@ -272,7 +19,6 @@ const GetDashboard = (props) => {
|
||||
<DashboardCard
|
||||
Icon={col.widget.icon}
|
||||
Label={col.widget.label}
|
||||
Filter={filter}
|
||||
Format={col.widget.format && col.widget.format}
|
||||
Data={col.widget.data}
|
||||
FilterData={col.widget.filter}
|
||||
@@ -281,50 +27,12 @@ const GetDashboard = (props) => {
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
case "customeHtml":
|
||||
return (
|
||||
<div data-tut={col.widget.data.tourSection}>
|
||||
<select
|
||||
id="searchFiltr"
|
||||
className="form-control"
|
||||
value={
|
||||
option ||
|
||||
localStorage.getItem("DashboardDefaultFilter") ||
|
||||
col.widget.data[0].default
|
||||
}
|
||||
onChange={onSearchFilter}
|
||||
>
|
||||
{col.widget.data[0].options.map((opt) => (
|
||||
<option key={opt} value={opt}>
|
||||
{opt}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
|
||||
case "customeTag":
|
||||
return (
|
||||
<h3
|
||||
data-tut={col.widget.data.tourSection}
|
||||
style={{
|
||||
marginBottom: "4px",
|
||||
color: "currentColor",
|
||||
marginLeft: "4px"
|
||||
}}
|
||||
>
|
||||
{col.widget.label}
|
||||
</h3>
|
||||
);
|
||||
case "report": {
|
||||
let _filter = `${col.widget.filterKey}:${filter}`;
|
||||
return (
|
||||
<div data-tut={col.widget.data.tourSection}>
|
||||
<Suspense fallback={<div>please wait</div>}>
|
||||
<div className="mb-4 md:mb-0">
|
||||
<DashboardReport Filter={_filter} Record={col.widget} />
|
||||
<DashboardReport Record={col.widget} />
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
@@ -346,7 +54,6 @@ const GetDashboard = (props) => {
|
||||
<DashboardCard
|
||||
Icon={col.widget.icon}
|
||||
Label={col.widget.label}
|
||||
Filter={filter}
|
||||
Format={col.widget.format && col.widget.format}
|
||||
Data={col.widget.data}
|
||||
FilterData={col.widget.filter}
|
||||
@@ -355,48 +62,11 @@ const GetDashboard = (props) => {
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
case "customeHtml":
|
||||
return (
|
||||
<div>
|
||||
<select
|
||||
id="searchFiltr"
|
||||
className="form-control"
|
||||
value={
|
||||
option ||
|
||||
localStorage.getItem("DashboardDefaultFilter") ||
|
||||
col.widget.data[0].default
|
||||
}
|
||||
onChange={onSearchFilter}
|
||||
>
|
||||
{col.widget.data[0].options.map((opt) => (
|
||||
<option key={opt} value={opt}>
|
||||
{opt}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
|
||||
case "customeTag":
|
||||
return (
|
||||
<h3
|
||||
style={{
|
||||
marginBottom: "4px",
|
||||
color: "currentColor",
|
||||
marginLeft: "4px"
|
||||
}}
|
||||
>
|
||||
{col.widget.label}
|
||||
</h3>
|
||||
);
|
||||
case "report": {
|
||||
let _filter = `${col.widget.filterKey}:${filter}`;
|
||||
return (
|
||||
<Suspense fallback={<div>please wait</div>}>
|
||||
<div className="mb-4 md:mb-0">
|
||||
<DashboardReport Filter={_filter} Record={col.widget} />
|
||||
<DashboardReport Record={col.widget} />
|
||||
</div>
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
import { useDropScript } from "../../hook/useScript";
|
||||
|
||||
const DROPBOX_APP_KEY = process.env.REACT_APP_DROPBOX_API_KEY; // App key
|
||||
const DROPBOX_SDK_URL = "https://www.dropbox.com/static/api/2/dropins.js";
|
||||
const DROPBOX_SCRIPT_ID = "dropboxjs";
|
||||
|
||||
export default function DropboxChooser({ children, onSuccess, onCancel }) {
|
||||
useDropScript(DROPBOX_SDK_URL, {
|
||||
attrs: {
|
||||
id: DROPBOX_SCRIPT_ID,
|
||||
"data-app-key": DROPBOX_APP_KEY
|
||||
}
|
||||
});
|
||||
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
// Required. Called when a user selects an item in the Chooser.
|
||||
success: (files) => {
|
||||
// console.log("success", files);
|
||||
onSuccess && onSuccess(files);
|
||||
},
|
||||
// Optional. Called when the user closes the dialog without selecting a file
|
||||
// and does not include any parameters.
|
||||
cancel: () => {
|
||||
console.log("cancel");
|
||||
onCancel && onCancel();
|
||||
},
|
||||
|
||||
// Optional. "preview" (default) is a preview link to the document for sharing,
|
||||
// "direct" is an expiring link to download the contents of the file. For more
|
||||
linkType: "direct", // or "preview"
|
||||
multiselect: false, // 是否支持多选
|
||||
extensions: [".pdf"],
|
||||
|
||||
// Optional. A value of false (default) limits selection to files,
|
||||
// while true allows the user to select both folders and files.
|
||||
// You cannot specify `linkType: "direct"` when using `folderselect: true`.
|
||||
folderselect: false // or true
|
||||
}),
|
||||
[onSuccess, onCancel]
|
||||
);
|
||||
|
||||
const handleChoose = useCallback(() => {
|
||||
if (window.Dropbox) {
|
||||
window.Dropbox.choose(options);
|
||||
}
|
||||
}, [options]);
|
||||
|
||||
return (
|
||||
<div onClick={handleChoose}>
|
||||
{children || (
|
||||
<button className="px-2 py-[2px] text-2xl rounded border-[1px] text-blue-400 border-gray-300 w-full">
|
||||
<i className="fa-brands fa-dropbox"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { SaveFileSize } from "../../constant/saveFileSize";
|
||||
// import Parse from "parse";
|
||||
// import sanitizeFileName from "../../primitives/sanitizeFileName";
|
||||
import axios from "axios";
|
||||
|
||||
import Parse from "parse";
|
||||
import sanitizeFileName from "../../primitives/sanitizeFileName";
|
||||
import DropboxChooser from "./DropboxChoose";
|
||||
const FileUpload = (props) => {
|
||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||
const [_fileupload, setFileUpload] = useState("");
|
||||
const [fileload, setfileload] = useState(false);
|
||||
|
||||
const [localValue, setLocalValue] = useState("");
|
||||
const [Message] = useState(false);
|
||||
const [percentage, setpercentage] = useState(0);
|
||||
|
||||
@@ -26,7 +23,6 @@ const FileUpload = (props) => {
|
||||
const onChange = (e) => {
|
||||
try {
|
||||
let files = e.target.files;
|
||||
setLocalValue(e.target.files);
|
||||
if (typeof files[0] !== "undefined") {
|
||||
if (props.schema.filetypes && props.schema.filetypes.length > 0) {
|
||||
var fileName = files[0].name;
|
||||
@@ -69,53 +65,94 @@ const FileUpload = (props) => {
|
||||
};
|
||||
|
||||
const handleFileUpload = async (file) => {
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
setfileload(true);
|
||||
const file_url = parseBaseUrl.slice(0, -4);
|
||||
const url = `${file_url}file_upload`;
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
const config = {
|
||||
headers: {
|
||||
"content-type": "multipart/form-data",
|
||||
"X-Parse-Application-Id": parseAppId
|
||||
},
|
||||
onUploadProgress: function (progressEvent) {
|
||||
var percentCompleted = Math.round(
|
||||
(progressEvent.loaded * 100) / progressEvent.total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
};
|
||||
const size = file.size;
|
||||
const fileName = file.name;
|
||||
const name = sanitizeFileName(fileName);
|
||||
const pdfFile = file;
|
||||
const parseFile = new Parse.File(name, pdfFile);
|
||||
|
||||
try {
|
||||
await axios
|
||||
.post(url, formData, config)
|
||||
.then((res) => {
|
||||
if (res.data.status === "Error") {
|
||||
alert(res.data.message);
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
// console.log("percentCompleted ", percentCompleted);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
setFileUpload(res.data.imageUrl);
|
||||
props.onChange(res.data.imageUrl);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
}
|
||||
});
|
||||
|
||||
if (res.data.imageUrl) {
|
||||
SaveFileSize(file.size, res.data.imageUrl);
|
||||
return res.data.imageUrl;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
alert(`${err.message}`);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
});
|
||||
setFileUpload(response.url());
|
||||
props.onChange(response.url());
|
||||
setfileload(false);
|
||||
// The response object will contain information about the uploaded file
|
||||
// console.log("File uploaded:", response);
|
||||
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
// console.log("File URL:", response.url());
|
||||
if (response.url()) {
|
||||
SaveFileSize(size, response.url());
|
||||
return response.url();
|
||||
}
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const dropboxSuccess = async (files) => {
|
||||
// console.log("file ", files);
|
||||
setfileload(true);
|
||||
const file = files[0];
|
||||
const url = file.link;
|
||||
const size = file.bytes;
|
||||
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
||||
|
||||
if (mb > 10) {
|
||||
setTimeout(() => {
|
||||
alert(
|
||||
`The selected file size is too large. Please select a file less than 10 MB`
|
||||
);
|
||||
}, 500);
|
||||
return;
|
||||
} else {
|
||||
const name = sanitizeFileName(file.name);
|
||||
|
||||
const parseFile = new Parse.File(name, { uri: url });
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
// console.log("percentCompleted ", percentCompleted);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
// console.log("response.url() ", response.url());
|
||||
setFileUpload(response.url());
|
||||
props.onChange(response.url());
|
||||
setfileload(false);
|
||||
|
||||
if (response.url()) {
|
||||
SaveFileSize(size, response.url());
|
||||
return response.url();
|
||||
}
|
||||
} catch (error) {
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
const dropboxCancel = async () => {
|
||||
console.log("cancel clicked ");
|
||||
};
|
||||
let fileView =
|
||||
props.formData &&
|
||||
props.schema.uploadtype === "s3viajw" ? null : props.formData &&
|
||||
@@ -124,7 +161,7 @@ const FileUpload = (props) => {
|
||||
<a
|
||||
href={props.formData}
|
||||
title={props.formData}
|
||||
style={{ paddingBottom: "10px", color: "blue"}}
|
||||
style={{ paddingBottom: "10px", color: "blue" }}
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
@@ -217,55 +254,51 @@ const FileUpload = (props) => {
|
||||
</div>
|
||||
|
||||
<>
|
||||
{localValue ? (
|
||||
<input
|
||||
type="file"
|
||||
id="hashfile"
|
||||
style={{
|
||||
border: "1px solid #ccc",
|
||||
color: "gray",
|
||||
backgroundColor: "white",
|
||||
padding: "5px 10px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "13px",
|
||||
width: "100%",
|
||||
fontWeight: "bold"
|
||||
}}
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : props.formData ? (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #ccc",
|
||||
color: "gray",
|
||||
backgroundColor: "white",
|
||||
padding: "5px 10px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "13px",
|
||||
width: "100%",
|
||||
fontWeight: "bold"
|
||||
}}
|
||||
>
|
||||
file selected : {props.formData.split("/")[3]}
|
||||
{props.formData ? (
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
<div className="flex justify-between items-center px-2 py-[3px] w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
||||
<div className="break-all">
|
||||
file selected : {props.formData.split("/")[3]}
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
console.log("clicked");
|
||||
setFileUpload([]);
|
||||
props.onChange(undefined);
|
||||
}}
|
||||
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
||||
>
|
||||
<i className="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<input
|
||||
type="file"
|
||||
id="hashfile"
|
||||
style={{
|
||||
border: "1px solid #ccc",
|
||||
color: "gray",
|
||||
backgroundColor: "white",
|
||||
padding: "5px 10px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "13px",
|
||||
width: "100%",
|
||||
fontWeight: "bold"
|
||||
}}
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
onChange={onChange}
|
||||
/>
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
<input
|
||||
type="file"
|
||||
id="hashfile"
|
||||
style={{
|
||||
border: "1px solid #ccc",
|
||||
color: "gray",
|
||||
backgroundColor: "white",
|
||||
padding: "5px 10px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "13px",
|
||||
width: "100%",
|
||||
fontWeight: "bold"
|
||||
}}
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
onChange={onChange}
|
||||
/>
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from "react";
|
||||
import Parse from "parse";
|
||||
import axios from "axios";
|
||||
// import axios from "axios";
|
||||
|
||||
export class HiddenField extends Component {
|
||||
state = {
|
||||
@@ -37,31 +37,46 @@ export class HiddenField extends Component {
|
||||
this.setState({ _fields: custome_Filed });
|
||||
} else {
|
||||
if (currentUser) {
|
||||
let url = `${this.state.baseUrl}classes/${localStorage.getItem(
|
||||
"extended_class"
|
||||
)}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${
|
||||
currentUser.id
|
||||
}"}}&keys=${this.props.schema.data.valueKey}`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": this.state.parseAppId
|
||||
};
|
||||
await axios.get(url, { headers: headers }).then((res) => {
|
||||
let custome_Filed = "";
|
||||
let _rdata = res.data.results;
|
||||
let splitArray = this.props.schema.data.valueKey.split(".");
|
||||
if (splitArray.length > 1) {
|
||||
custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
||||
} else {
|
||||
console.log(_rdata[0][splitArray[0]]);
|
||||
custome_Filed = _rdata[0][splitArray[0]];
|
||||
}
|
||||
this.setState({ _fields: custome_Filed });
|
||||
// let url = `${this.state.baseUrl}classes/${localStorage.getItem(
|
||||
// "extended_class"
|
||||
// )}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${
|
||||
// currentUser.id
|
||||
// }"}}&keys=${this.props.schema.data.valueKey}`;
|
||||
// const headers = {
|
||||
// "Content-Type": "application/json",
|
||||
// "X-Parse-Application-Id": this.state.parseAppId
|
||||
// };
|
||||
// await axios.get(url, { headers: headers }).then((res) => {
|
||||
// let custome_Filed = "";
|
||||
// let _rdata = res.data.results;
|
||||
// let splitArray = this.props.schema.data.valueKey.split(".");
|
||||
// if (splitArray.length > 1) {
|
||||
// custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
||||
// } else {
|
||||
// console.log(_rdata[0][splitArray[0]]);
|
||||
// custome_Filed = _rdata[0][splitArray[0]];
|
||||
// }
|
||||
// this.setState({ _fields: custome_Filed });
|
||||
// });
|
||||
|
||||
const res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
let custome_Filed = "";
|
||||
const result = res.toJSON();
|
||||
let _rdata = [result];
|
||||
let splitArray = this.props.schema.data.valueKey.split(".");
|
||||
if (splitArray.length > 1) {
|
||||
custome_Filed = _rdata[0][splitArray[0]][splitArray[1]];
|
||||
} else {
|
||||
console.log(_rdata[0][splitArray[0]]);
|
||||
custome_Filed = _rdata[0][splitArray[0]];
|
||||
}
|
||||
this.setState({ _fields: custome_Filed });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('err', error)
|
||||
console.log("err", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,12 +120,10 @@ const Level1Dropdown = (props) => {
|
||||
let data = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
res = data[0];
|
||||
} else {
|
||||
var emp = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
var q = new Parse.Query(emp);
|
||||
q.equalTo("UserId", currentUser);
|
||||
res = await q.first();
|
||||
const currentUser = Parse.User.current();
|
||||
res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
if (res) res = res.toJSON();
|
||||
}
|
||||
|
||||
@@ -339,7 +337,7 @@ const Level1Dropdown = (props) => {
|
||||
x.className = x.className.replace("show", "");
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
console.log("Err", error)
|
||||
console.log("Err", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||
return (
|
||||
<li key={item.title} role="none">
|
||||
<NavLink
|
||||
to={`/${item.pageType}/${item.objectId}`}
|
||||
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4"
|
||||
onClick={closeSidebar}
|
||||
tabIndex={isOpen ? 0 : -1}
|
||||
role="menuitem"
|
||||
>
|
||||
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
||||
<span className="ml-3 lg:ml-4">{item.title}</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default Menu;
|
||||
@@ -1,115 +1,76 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Link, NavLink } from "react-router-dom";
|
||||
|
||||
import Menu from './Menu';
|
||||
import Submenu from "./SubMenu";
|
||||
import dp from "../../assets/images/dp.png";
|
||||
import SocialMedia from './SocialMedia';
|
||||
|
||||
import Parse from "parse";
|
||||
import dp from "../../assets/images/dp.png";
|
||||
|
||||
const Sidebar = ({ isOpen, closeSidebar }) => {
|
||||
const [menuList, setmenuList] = useState([]);
|
||||
let username = localStorage.getItem("username");
|
||||
const image = localStorage.getItem("profileImg") || dp;
|
||||
const tenantname = localStorage.getItem("TenantName");
|
||||
const [menuList, setmenuList] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem("accesstoken")) {
|
||||
menuItem();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const menuItem = async () => {
|
||||
const parseBaseUrl = localStorage.getItem("baseUrl");
|
||||
const parseAppId = localStorage.getItem("parseAppId");
|
||||
|
||||
try {
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
var sideMenu = Parse.Object.extend("w_menu");
|
||||
var query = new Parse.Query(sideMenu);
|
||||
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
|
||||
|
||||
|
||||
const results = await query.first();
|
||||
const resultjson = results.toJSON();
|
||||
// console.log("resultjson ", resultjson);
|
||||
let result = resultjson;
|
||||
setmenuList(result.menuItems);
|
||||
} catch (e) {
|
||||
console.error("Problem", e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
isOpen ? "block" : "hidden"
|
||||
} bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 ${
|
||||
isOpen ? "translate-x-0" : "-translate-x-full"
|
||||
}`}
|
||||
<aside
|
||||
className={`bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 md:translate-x-0
|
||||
${isOpen ? "translate-x-0 block" : "-translate-x-full hidden"}`}
|
||||
>
|
||||
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
|
||||
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
|
||||
<img className="w-full h-full object-contain" src={image} alt="img" />
|
||||
<img className="w-full h-full object-cover" src={image} alt="Profile" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[14px] font-bold">{username && username}</p>
|
||||
<p
|
||||
className={`text-[12px] ${tenantname && tenantname ? "mt-2" : ""}`}
|
||||
>
|
||||
{tenantname && tenantname}
|
||||
<p className="text-[14px] font-bold">{username}</p>
|
||||
<p className={`text-[12px] ${tenantname ? "mt-2" : ""}`}>
|
||||
{tenantname}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="text-sm">
|
||||
{menuList.length > 0 && (
|
||||
<>
|
||||
{menuList.map((item) =>
|
||||
!item.children ? (
|
||||
<li key={item.title} onClick={() => closeSidebar()}>
|
||||
<Link
|
||||
className={`mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 hover:no-underline cursor-pointer`}
|
||||
to={`/${item.pageType}/${item.objectId}`}
|
||||
>
|
||||
<i className={item.icon + " text-[18px]"}></i>
|
||||
<span title={item.description} className="ml-3 lg:ml-4">
|
||||
{item.title}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
) : (
|
||||
<Submenu key={item.title} icon={item.icon} title={item.title}>
|
||||
{item.children.map((item) => (
|
||||
<li key={item.title} onClick={() => closeSidebar()} className="pl-6 md:pl-8 hover:bg-[#eef1f5] cursor-pointer">
|
||||
<Link
|
||||
className={`mx-auto flex items-center p-2 lg:p-3 hover:no-underline`}
|
||||
to={`/${item.pageType}/${item.objectId}`}
|
||||
>
|
||||
<i className={item.icon + " text-[18px]"}></i>
|
||||
<span title={item.description} className="ml-3 lg:ml-4">
|
||||
{item.title}
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</Submenu>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
<div className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
|
||||
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank">
|
||||
<i className="fa-brands fa-github"></i>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="https://www.linkedin.com/company/opensign%E2%84%A2/"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa-brands fa-linkedin"></i>
|
||||
</NavLink>
|
||||
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank">
|
||||
<i className="fa-brands fa-square-x-twitter"></i>
|
||||
</NavLink>
|
||||
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank">
|
||||
<i className="fa-brands fa-discord"></i>
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
<nav aria-label="OpenSign Sidebar Navigation">
|
||||
<ul className="text-sm" role="menubar" aria-label="OpenSign Sidebar Navigation">
|
||||
{menuList.map((item) => (
|
||||
!item.children ? (
|
||||
<Menu key={item.title} item={item} isOpen={isOpen} closeSidebar={closeSidebar} />
|
||||
) : (
|
||||
<Submenu key={item.title} item={item} closeSidebar={closeSidebar} />
|
||||
)
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
|
||||
<SocialMedia />
|
||||
</footer>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
const 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 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;
|
||||
@@ -1,30 +1,52 @@
|
||||
import React, { useState } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
const Submenu = ({ icon, title, children }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const Submenu = ({ item, closeSidebar }) => {
|
||||
const [submenuOpen, setSubmenuOpen] = useState(false);
|
||||
const { title, icon, children } = item;
|
||||
|
||||
const toggleSubmenu = () => {
|
||||
setIsOpen(!isOpen);
|
||||
setSubmenuOpen(!submenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<li role="none">
|
||||
<button
|
||||
onClick={toggleSubmenu}
|
||||
className="w-full mx-auto flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:outline-none"
|
||||
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:ring-2 focus:ring-blue-600"
|
||||
aria-expanded={submenuOpen}
|
||||
aria-haspopup="true"
|
||||
aria-controls={`submenu-${title}`}
|
||||
>
|
||||
<i className={icon + " text-[18px]"}></i>
|
||||
<i className={`${icon} text-[18px]`}></i>
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<span className="ml-3 lg:ml-4">{title}</span>
|
||||
<i
|
||||
className={
|
||||
isOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
|
||||
}
|
||||
className={`${submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
|
||||
}`}
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</div>
|
||||
</button>
|
||||
{isOpen && <ul>{children}</ul>}
|
||||
</div>
|
||||
{submenuOpen && (
|
||||
<ul id={`submenu-${title}`} role="menu" aria-label={`${title} submenu`}>
|
||||
{children.map((childItem) => (
|
||||
<li key={childItem.title} role="none">
|
||||
<NavLink
|
||||
to={`/${childItem.pageType}/${childItem.objectId}`}
|
||||
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white"
|
||||
onClick={closeSidebar}
|
||||
role="menuitem"
|
||||
tabIndex={submenuOpen ? 0 : -1}
|
||||
>
|
||||
<i className={`${childItem.icon} text-[18px]`} aria-hidden="true"></i>
|
||||
<span className="ml-3 lg:ml-4">{childItem.title}</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
import moment from "moment";
|
||||
|
||||
export default function onSearchFilter(_search) {
|
||||
switch (_search) {
|
||||
case "Today": {
|
||||
let d = new Date();
|
||||
let formDate = new Date(
|
||||
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
let Todate = new Date(
|
||||
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
|
||||
return Query;
|
||||
}
|
||||
case "Yesterday": {
|
||||
let d1 = new Date();
|
||||
d1.setDate(d1.getDate() - 1);
|
||||
let yesFrDate = new Date(
|
||||
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
|
||||
let YesTodate = new Date(
|
||||
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
|
||||
return Query1;
|
||||
}
|
||||
|
||||
case "This week": {
|
||||
let oneDay = 24 * 60 * 60 * 1000;
|
||||
let curr = new Date(); // get current date
|
||||
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
|
||||
|
||||
let firstday = new Date(
|
||||
new Date(
|
||||
Date.UTC(curr.getFullYear(), curr.getMonth(), curr.getDate(), 0, 0, 0)
|
||||
).setDate(first)
|
||||
).toISOString();
|
||||
let diffDays = Math.round(
|
||||
Math.abs(
|
||||
(new Date(
|
||||
Date.UTC(
|
||||
curr.getFullYear(),
|
||||
curr.getMonth(),
|
||||
curr.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
) -
|
||||
new Date(firstday)) /
|
||||
oneDay
|
||||
)
|
||||
); //Days since last week
|
||||
let last = first + diffDays;
|
||||
let lastday = new Date(
|
||||
new Date(
|
||||
Date.UTC(
|
||||
curr.getFullYear(),
|
||||
curr.getMonth(),
|
||||
curr.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).setDate(last)
|
||||
).toISOString();
|
||||
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
|
||||
return Query2;
|
||||
}
|
||||
|
||||
case "Last 7 days": {
|
||||
let d7 = new Date();
|
||||
let d7l = new Date();
|
||||
d7.setDate(d7.getDate() - 7);
|
||||
let l7t = new Date(
|
||||
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
|
||||
).toISOString();
|
||||
let date7 = new Date(
|
||||
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
|
||||
return Query7;
|
||||
}
|
||||
case "Last 14 days": {
|
||||
let d14 = new Date();
|
||||
let d14l = new Date();
|
||||
let l14t = new Date(
|
||||
Date.UTC(
|
||||
d14l.getFullYear(),
|
||||
d14l.getMonth(),
|
||||
d14l.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).toISOString();
|
||||
d14.setDate(d14.getDate() - 14);
|
||||
let date14 = new Date(
|
||||
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
|
||||
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
|
||||
return Query14;
|
||||
}
|
||||
|
||||
case "Last 30 days": {
|
||||
let d30 = new Date();
|
||||
let d30l = new Date();
|
||||
let l30t = new Date(
|
||||
Date.UTC(
|
||||
d30l.getFullYear(),
|
||||
d30l.getMonth(),
|
||||
d30l.getDate(),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
)
|
||||
).toISOString();
|
||||
d30.setDate(d30.getDate() - 30);
|
||||
let date30 = new Date(
|
||||
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
|
||||
).toISOString();
|
||||
return `'$gte':'${date30}','$lte':'${l30t}'`;
|
||||
}
|
||||
case "Last week": {
|
||||
const from_date = moment().startOf("week").subtract(7, "days");
|
||||
const to_date = moment().endOf("week").subtract(7, "days");
|
||||
return `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
|
||||
}
|
||||
case "This month": {
|
||||
var tdate = new Date();
|
||||
var tfirstDay = new Date(
|
||||
tdate.getFullYear(),
|
||||
tdate.getMonth(),
|
||||
1
|
||||
).toISOString();
|
||||
var tlastDay = new Date(
|
||||
tdate.getFullYear(),
|
||||
tdate.getMonth() + 1,
|
||||
0
|
||||
).toISOString();
|
||||
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
|
||||
return Querylt;
|
||||
}
|
||||
case "Last month": {
|
||||
var ldate = new Date();
|
||||
var lfirstDay = new Date(
|
||||
ldate.getFullYear(),
|
||||
ldate.getMonth() - 1,
|
||||
2
|
||||
).toISOString();
|
||||
var llastDay = new Date(
|
||||
ldate.getFullYear(),
|
||||
ldate.getMonth(),
|
||||
1
|
||||
).toISOString();
|
||||
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
|
||||
return Queryltl;
|
||||
}
|
||||
case "All": {
|
||||
let fall = new Date(
|
||||
new Date().getFullYear() - 100,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).toISOString();
|
||||
let fall_year = `'$gte':'${fall}'`;
|
||||
return fall_year;
|
||||
}
|
||||
case "This year": {
|
||||
let fcy = new Date(new Date().getFullYear(), 0, 1, 0, 0, 0).toISOString();
|
||||
let lcy = new Date(
|
||||
new Date().getFullYear(),
|
||||
11,
|
||||
31,
|
||||
23,
|
||||
59,
|
||||
59
|
||||
).toISOString();
|
||||
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
|
||||
return cur_year;
|
||||
}
|
||||
case "Last year": {
|
||||
let fly = new Date(
|
||||
new Date().getFullYear() - 1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).toISOString();
|
||||
let lly = new Date(
|
||||
new Date().getFullYear() - 1,
|
||||
11,
|
||||
31,
|
||||
23,
|
||||
59,
|
||||
59
|
||||
).toISOString();
|
||||
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
|
||||
return last_year;
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,20 @@ export const useScript = (url, onload) => {
|
||||
};
|
||||
}, [url, onload]);
|
||||
};
|
||||
|
||||
/**`useScript` hook is generated scripte for google sign in button */
|
||||
export const useDropScript = (url, onload) => {
|
||||
useEffect(() => {
|
||||
const script = document.createElement("script");
|
||||
//add url parameter to the script src, for load and it will remove after load in return
|
||||
script.src = url;
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.id = "dropboxjs";
|
||||
script.setAttribute("data-app-key", "8k0thg9r1t7asqg");
|
||||
document.head.appendChild(script);
|
||||
return () => {
|
||||
document.head.removeChild(script);
|
||||
};
|
||||
}, [url, onload]);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ export const formJson = (id) => {
|
||||
type: "string",
|
||||
title: "Select Document",
|
||||
filetypes: [],
|
||||
maxfilesizeKB: "5000",
|
||||
maxfilesizeKB: "10000",
|
||||
uploadtype: "regular",
|
||||
helpbody: "",
|
||||
helplink: ""
|
||||
@@ -147,7 +147,7 @@ export const formJson = (id) => {
|
||||
class: "contracts_Contactbook",
|
||||
displayKey: "Name",
|
||||
valueKey: "objectId",
|
||||
query: `where={"CreatedBy":${userPtr}}&keys=Name`,
|
||||
query: `where={"CreatedBy":${userPtr},"IsDeleted":{"$ne":true}}&keys=Name`,
|
||||
isPointer: true,
|
||||
helpbody: "",
|
||||
helplink: "",
|
||||
@@ -582,4 +582,3 @@ export const formJson = (id) => {
|
||||
return formData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,35 +1,13 @@
|
||||
import Parse from "parse";
|
||||
export default function reportJson(id) {
|
||||
const currentUserId = Parse.User.current().id;
|
||||
// console.log("json ", json);
|
||||
|
||||
const head = ["Sr.No", "Name", "Note", "Folder", "File", "Owner", "Signers"];
|
||||
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
||||
switch (id) {
|
||||
// draft documents report
|
||||
case "ByHuevtCFY":
|
||||
return {
|
||||
reportName: "Draft Documents",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: null,
|
||||
$or: [
|
||||
{ Signers: null, SignedUrl: null },
|
||||
{ Signers: { $exists: true }, Placeholders: null }
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -45,27 +23,7 @@ export default function reportJson(id) {
|
||||
case "4Hhwbp482K":
|
||||
return {
|
||||
reportName: "Need your sign",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: { $ne: "Folder" },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
},
|
||||
Placeholders: { $ne: null }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name",
|
||||
"Signers.UserId",
|
||||
"AuditTrail"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -81,31 +39,7 @@ export default function reportJson(id) {
|
||||
case "1MwEuxLEkF":
|
||||
return {
|
||||
reportName: "In-progress documents",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: { $ne: "Folder" },
|
||||
Signers: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -121,27 +55,7 @@ export default function reportJson(id) {
|
||||
case "kQUoW4hUXz":
|
||||
return {
|
||||
reportName: "Completed Documents",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: null,
|
||||
IsCompleted: true,
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
IsDeclined: { $ne: true }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name",
|
||||
"TimeToCompleteDays"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -153,63 +67,11 @@ export default function reportJson(id) {
|
||||
}
|
||||
]
|
||||
};
|
||||
// OpenSignDrive™ documents Drafts
|
||||
case "VRFDmUmw5B":
|
||||
return {
|
||||
reportName: "OpenSignDrive™ Drafts",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: "AIDoc",
|
||||
$or: [
|
||||
{ Signers: null, SignedUrl: null },
|
||||
{ Signers: { $exists: true }, Placeholders: null }
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "edit",
|
||||
btnColor: "#3ac9d6",
|
||||
textColor: "white",
|
||||
btnIcon: "fa fa-plus",
|
||||
redirectUrl:
|
||||
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie"
|
||||
}
|
||||
]
|
||||
};
|
||||
// declined documents report
|
||||
case "UPr2Fm5WY3":
|
||||
return {
|
||||
reportName: "Declined Documents",
|
||||
className: "contracts_Document",
|
||||
params: { Type: null, IsDeclined: true },
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -225,39 +87,7 @@ export default function reportJson(id) {
|
||||
case "zNqBHXHsYH":
|
||||
return {
|
||||
reportName: "Expired Documents",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
Type: { $ne: "Folder" },
|
||||
$and: [
|
||||
{
|
||||
$or: [
|
||||
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
|
||||
{ Placeholders: { $ne: null } }
|
||||
]
|
||||
},
|
||||
{
|
||||
ExpiryDate: {
|
||||
$lt: { __type: "Date", iso: new Date().toISOString() }
|
||||
}
|
||||
}
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -273,31 +103,7 @@ export default function reportJson(id) {
|
||||
case "d9k3UfYHBc":
|
||||
return {
|
||||
reportName: "Recently sent for signatures",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: { $ne: "Folder" },
|
||||
Signers: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -313,27 +119,7 @@ export default function reportJson(id) {
|
||||
case "5Go51Q7T8r":
|
||||
return {
|
||||
reportName: "Recent signature requests",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: { $ne: "Folder" },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
},
|
||||
Placeholders: { $ne: null }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name",
|
||||
"Signers.UserId",
|
||||
"AuditTrail"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "Sign",
|
||||
@@ -349,28 +135,7 @@ export default function reportJson(id) {
|
||||
case "kC5mfynCi4":
|
||||
return {
|
||||
reportName: "Drafts",
|
||||
className: "contracts_Document",
|
||||
params: {
|
||||
Type: null,
|
||||
$or: [
|
||||
{ Signers: null, SignedUrl: null },
|
||||
{ Signers: { $exists: true }, Placeholders: null }
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
}
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -382,6 +147,20 @@ export default function reportJson(id) {
|
||||
}
|
||||
]
|
||||
};
|
||||
// contactbook report
|
||||
case "5KhaPr482K":
|
||||
return {
|
||||
reportName: "Contactbook",
|
||||
heading: contactbook,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "",
|
||||
btnColor: "#f55a42",
|
||||
textColor: "white",
|
||||
btnIcon: "fa-solid fa-trash"
|
||||
}
|
||||
]
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"subtitle": "Free for life One click install.",
|
||||
"btnText": "Visit github",
|
||||
"url": "https://github.com/opensignlabs/opensign",
|
||||
"target": "_blank",
|
||||
"benefits": [
|
||||
"Sign Unlimited Documents",
|
||||
"S3 Doc Storage",
|
||||
@@ -26,9 +27,10 @@
|
||||
"planName": "THANKS PLAN",
|
||||
"currency": "$",
|
||||
"price": "29.99",
|
||||
"subtitle": "Use code 'FREEBETA' to get this for free(First 100 users)",
|
||||
"subtitle": "Use code 'FREEBETA' to get this for free(First 1000 users)",
|
||||
"btnText": "Subscribe",
|
||||
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
|
||||
"target": "_self",
|
||||
"benefits": [
|
||||
"Sign Unlimited Documents",
|
||||
"Unlimited Secure Doc Storage with OpenSignDrive",
|
||||
@@ -50,6 +52,7 @@
|
||||
"subtitle": "Customization available Priority support.",
|
||||
"btnText": "Contact us",
|
||||
"url": "https://www.opensignlabs.com/contact-us",
|
||||
"target": "_blank",
|
||||
"benefits": [
|
||||
"All features",
|
||||
"Custom domain",
|
||||
|
||||
@@ -6,10 +6,10 @@ import { useWindowSize } from "../hook/useWindowSize";
|
||||
import Tour from "reactour";
|
||||
import axios from "axios";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import Parse from "parse";
|
||||
const HomeLayout = ({ children }) => {
|
||||
const { width } = useWindowSize();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const arr = useSelector((state) => state.TourSteps);
|
||||
|
||||
// reactour state
|
||||
@@ -19,13 +19,11 @@ const HomeLayout = ({ children }) => {
|
||||
const [tourConfigs, setTourConfigs] = useState([]);
|
||||
|
||||
const showSidebar = () => {
|
||||
setIsOpen(!isOpen);
|
||||
setIsOpen(value => !value);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (width && width <= 768) {
|
||||
setIsOpen(false);
|
||||
} else {
|
||||
setIsOpen(true);
|
||||
}
|
||||
}, [width]);
|
||||
|
||||
@@ -124,20 +122,11 @@ const HomeLayout = ({ children }) => {
|
||||
};
|
||||
|
||||
async function checkTourStatus() {
|
||||
const serverUrl = localStorage.getItem("baseUrl");
|
||||
const appId = localStorage.getItem("AppID12");
|
||||
const extUserClass = localStorage.getItem("extended_class");
|
||||
const json = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
const extUserId = json && json.length > 0 && json[0].objectId;
|
||||
// console.log("extUserId ", extUserId);
|
||||
const res = await axios.get(
|
||||
serverUrl + "classes/" + extUserClass + "/" + extUserId,
|
||||
{
|
||||
headers: {
|
||||
"X-Parse-Application-Id": appId
|
||||
}
|
||||
}
|
||||
);
|
||||
const currentUser = Parse.User.current();
|
||||
const cloudRes = await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
});
|
||||
const res = { data: cloudRes.toJSON() };
|
||||
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
|
||||
const tourStatus = res.data.TourStatus;
|
||||
// console.log("res ", res.data.TourStatus);
|
||||
|
||||
@@ -1,9 +1,41 @@
|
||||
import React from "react";
|
||||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import pad from "../assets/images/pad.svg";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const ReportTable = ({ ReportName, List, actions }) => {
|
||||
import axios from "axios";
|
||||
import "../styles/report.css";
|
||||
const ReportTable = ({
|
||||
ReportName,
|
||||
List,
|
||||
setList,
|
||||
actions,
|
||||
heading,
|
||||
setIsNextRecord,
|
||||
isMoreDocs,
|
||||
docPerPage
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [actLoader, setActLoader] = useState({});
|
||||
const [isAlert, setIsAlert] = useState(false);
|
||||
const [isErr, setIsErr] = useState(false);
|
||||
// For loop is used to calculate page numbers visible below table
|
||||
// Initialize pageNumbers using useMemo to avoid unnecessary re-creation
|
||||
const pageNumbers = useMemo(() => {
|
||||
const calculatedPageNumbers = [];
|
||||
for (let i = 1; i <= Math.ceil(List.length / docPerPage); i++) {
|
||||
calculatedPageNumbers.push(i);
|
||||
}
|
||||
return calculatedPageNumbers;
|
||||
}, [List, docPerPage]);
|
||||
// below useEffect reset currenpage to 1 if user change route
|
||||
useEffect(() => {
|
||||
return () => setCurrentPage(1);
|
||||
}, []);
|
||||
|
||||
// `formatRow` is used to show data in poper manner like
|
||||
// if data is of array type then it will join array items with ","
|
||||
// if data is of object type then it Name values will be show in row
|
||||
// if no data available it will show hyphen "-"
|
||||
const formatRow = (row) => {
|
||||
if (Array.isArray(row)) {
|
||||
let updateArr = row.map((x) => x.Name);
|
||||
@@ -14,44 +46,84 @@ const ReportTable = ({ ReportName, List, actions }) => {
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
// below useEffect is used to render next record if IsMoreDoc is true
|
||||
// second last value of pageNumber array is same as currentPage
|
||||
useEffect(() => {
|
||||
if (isMoreDocs && pageNumbers[pageNumbers.length - 1] === currentPage) {
|
||||
setIsNextRecord(true);
|
||||
}
|
||||
}, [isMoreDocs, pageNumbers, currentPage, setIsNextRecord]);
|
||||
|
||||
// `handlemicroapp` is used to open microapp
|
||||
const handlemicroapp = (item, url) => {
|
||||
localStorage.removeItem("rowlevel");
|
||||
// const params = new URLSearchParams(url);
|
||||
// let arr = [];
|
||||
// for (let [key, value] of params.entries()) {
|
||||
// if (key === "remoteUrl") {
|
||||
// arr.push(
|
||||
// `${key}=${window.btoa(
|
||||
// window.location.origin + "/mfbuild/remoteEntry.js"
|
||||
// )}`
|
||||
// );
|
||||
// } else {
|
||||
// arr.push(`${key}=${value}`);
|
||||
// }
|
||||
// }
|
||||
// const remoteUrl = arr.join("&");
|
||||
// console.log("arr", remoteUrl);
|
||||
|
||||
navigate("/rpmf/" + url);
|
||||
localStorage.setItem("rowlevel", JSON.stringify(item));
|
||||
// localStorage.setItem("rowlevelMicro");
|
||||
};
|
||||
const handlebtn = () => {
|
||||
console.log("clicked");
|
||||
const handlebtn = async (item) => {
|
||||
if (ReportName === "Contactbook") {
|
||||
setActLoader({ [item.objectId]: true });
|
||||
try {
|
||||
const url =
|
||||
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
|
||||
const body = { IsDeleted: true };
|
||||
const res = await axios.put(url + item.objectId, body, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
}
|
||||
});
|
||||
// console.log("Res ", res.data);
|
||||
if (res.data && res.data.updatedAt) {
|
||||
setActLoader({});
|
||||
setIsAlert(true);
|
||||
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
|
||||
setList(upldatedList);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err", err);
|
||||
setIsAlert(true);
|
||||
setIsErr(true);
|
||||
setActLoader({});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get current list
|
||||
const indexOfLastDoc = currentPage * docPerPage;
|
||||
const indexOfFirstDoc = indexOfLastDoc - docPerPage;
|
||||
// `currentLists` is total record render on current page
|
||||
const currentLists = List.slice(indexOfFirstDoc, indexOfLastDoc);
|
||||
|
||||
// Change page
|
||||
const paginateFront = () => setCurrentPage(currentPage + 1);
|
||||
const paginateBack = () => setCurrentPage(currentPage - 1);
|
||||
|
||||
return (
|
||||
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
|
||||
{isAlert && (
|
||||
<div
|
||||
className={`alert alert-${isErr ? "danger" : "success"} alertBox`}
|
||||
role="alert"
|
||||
onAnimationEnd={() => setIsAlert(false)}
|
||||
>
|
||||
{isErr
|
||||
? "Something went wrong, Please try again later!"
|
||||
: "Record deleted successfully!"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<h2 className="text-[23px] font-light my-2">{ReportName}</h2>
|
||||
<table className="table-auto w-full border-collapse">
|
||||
<thead className="text-[14px]">
|
||||
<tr className="border-y-[1px]">
|
||||
<th className="px-4 py-2 font-thin">Sr.No</th>
|
||||
<th className="px-4 py-2 font-thin">Name</th>
|
||||
<th className="px-4 py-2 font-thin">Note</th>
|
||||
<th className="px-4 py-2 font-thin">Folder</th>
|
||||
<th className="px-4 py-2 font-thin">File</th>
|
||||
<th className="px-4 py-2 font-thin">Owner</th>
|
||||
<th className="px-4 py-2 font-thin">Signers</th>
|
||||
{heading?.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<th className="px-4 py-2 font-thin">{item}</th>
|
||||
</React.Fragment>
|
||||
))}
|
||||
{actions?.length > 0 && (
|
||||
<th className="px-4 py-2 font-thin">Action</th>
|
||||
)}
|
||||
@@ -60,69 +132,161 @@ const ReportTable = ({ ReportName, List, actions }) => {
|
||||
<tbody className="text-[12px]">
|
||||
{List?.length > 0 ? (
|
||||
<>
|
||||
{List.map((item, index) => (
|
||||
<tr className="border-t-[1px]" key={index}>
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
|
||||
<td className="px-4 py-2">{item?.Note || "-"}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Folder?.Name || "OpenSignDrive"}
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={item?.URL}
|
||||
href={item?.URL}
|
||||
download={item?.URL}
|
||||
className="text-[blue] hover:text-[blue] hover:underline"
|
||||
>
|
||||
{item?.URL ? "Download" : "-"}
|
||||
</a>
|
||||
</td>
|
||||
{currentLists.map((item, index) =>
|
||||
ReportName === "Contactbook" ? (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
|
||||
<td className="px-4 py-2">{item?.Email || "-"}</td>
|
||||
<td className="px-4 py-2">{item?.Phone || "-"}</td>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && (
|
||||
<i
|
||||
className={
|
||||
actLoader[item.objectId]
|
||||
? "fa-solid fa-spinner fa-spin-pulse"
|
||||
: act.btnIcon
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
</span>
|
||||
{act?.btnLabel && (
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "View"}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
|
||||
<td className="px-4 py-2">{item?.Note || "-"}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Folder?.Name || "OpenSignDrive"}
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={item?.URL}
|
||||
href={item?.URL}
|
||||
download={item?.URL}
|
||||
className="text-[blue] hover:text-[blue] hover:underline"
|
||||
>
|
||||
{item?.URL ? "Download" : "-"}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Signers ? formatRow(item?.Signers) : "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && <i className={act.btnIcon}></i>}
|
||||
</span>
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "view"}
|
||||
</span>
|
||||
</button>
|
||||
// )
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Signers ? formatRow(item?.Signers) : "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && (
|
||||
<i
|
||||
className={
|
||||
actLoader[item.objectId]
|
||||
? "fa-solid fa-spinner fa-spin-pulse"
|
||||
: act.btnIcon
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
</span>
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "view"}
|
||||
</span>
|
||||
</button>
|
||||
// )
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="flex flex-wrap items-center gap-2 p-2 ">
|
||||
{List.length > docPerPage && (
|
||||
<>
|
||||
{currentPage > 1 && (
|
||||
<button
|
||||
onClick={() => paginateBack()}
|
||||
className="bg-blue-400 text-white rounded px-3 py-2 focus:outline-none"
|
||||
>
|
||||
Prev
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{pageNumbers.map((x) => (
|
||||
<button
|
||||
key={x}
|
||||
onClick={() => setCurrentPage(x)}
|
||||
className=" bg-sky-400 text-white rounded px-3 py-2 focus:outline-none"
|
||||
>
|
||||
{x}
|
||||
</button>
|
||||
))}
|
||||
{isMoreDocs && (
|
||||
<button className="text-black rounded px-1 py-2">...</button>
|
||||
)}
|
||||
{List.length > docPerPage && (
|
||||
<>
|
||||
{pageNumbers.includes(currentPage + 1) && (
|
||||
<button
|
||||
onClick={() => paginateFront()}
|
||||
className="bg-blue-400 text-white rounded px-3 py-2 focus:outline-none"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{List?.length <= 0 && (
|
||||
<div className="flex flex-col items-center justify-center w-full bg-white roundedm py-4">
|
||||
<div className="flex flex-col items-center justify-center w-full bg-white rounded py-4">
|
||||
<div className="w-[60px] h-[60px] overflow-hidden">
|
||||
<img className="w-full h-full object-contain" src={pad} alt="img" />
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,8 @@ export const fetchAppInfo = (str, burl, app_id) => async (dispatch) => {
|
||||
let _base = ""; // Define _base here and initialize it to an empty string
|
||||
if (response && response.baseurl) {
|
||||
_base = response.baseurl.charAt(response.baseurl.length - 1);
|
||||
} localStorage.removeItem("baseUrl");
|
||||
}
|
||||
localStorage.removeItem("baseUrl");
|
||||
localStorage.setItem("_appName", response.appname);
|
||||
localStorage.setItem("_app_objectId", response.objectId);
|
||||
if (_base === "/") {
|
||||
@@ -120,16 +121,11 @@ export const login = (username, password) => async (dispatch) => {
|
||||
localStorage.setItem("_user_role", _role);
|
||||
}
|
||||
try {
|
||||
const tour = Parse.Object.extend(
|
||||
localStorage.getItem("extended_class")
|
||||
);
|
||||
let _tour = new Parse.Query(tour);
|
||||
_tour.equalTo("UserId", {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: resultjson.objectId
|
||||
});
|
||||
await _tour.first().then(
|
||||
const currentUser = Parse.User.current();
|
||||
await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
})
|
||||
.then(
|
||||
(results) => {
|
||||
let userinfo = results.toJSON();
|
||||
if (userinfo.TenantId) {
|
||||
@@ -142,7 +138,7 @@ export const login = (username, password) => async (dispatch) => {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("err ", error)
|
||||
console.log("err ", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,11 +2,12 @@ import React, { useState, useEffect } from "react";
|
||||
import Parse from "parse";
|
||||
import "../styles/loader.css";
|
||||
import GetDashboard from "../components/dashboard/GetDashboard";
|
||||
import { Navigate, useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import Title from "../components/Title";
|
||||
import { save_tourSteps } from "../redux/actions";
|
||||
import { connect } from "react-redux";
|
||||
const Dashboard = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
const [dashboard, setdashboard] = useState([]);
|
||||
const [classnameArray, setclassnameArray] = useState([]);
|
||||
@@ -15,6 +16,19 @@ const Dashboard = (props) => {
|
||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||
const [defaultQuery, setDefaultQuery] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem("accesstoken")) {
|
||||
if (id !== undefined) {
|
||||
getDashboard(id);
|
||||
} else {
|
||||
getDashboard(localStorage.getItem("PageLanding"));
|
||||
}
|
||||
} else {
|
||||
navigate("/", { replace: true });
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [id]);
|
||||
|
||||
const getDashboard = async (id) => {
|
||||
setloading(true);
|
||||
try {
|
||||
@@ -93,20 +107,6 @@ const Dashboard = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (id !== undefined) {
|
||||
getDashboard(id);
|
||||
} else {
|
||||
getDashboard(localStorage.getItem("PageLanding"));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
}, [id]);
|
||||
|
||||
if (localStorage.getItem("accesstoken") === "" || null) {
|
||||
return <Navigate to="/" />;
|
||||
}
|
||||
|
||||
let _dash = (
|
||||
<GetDashboard
|
||||
dashboard={dashboard}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Suspense } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import useFederatedComponent from "mf-cra";
|
||||
import React from "react";
|
||||
import Title from "../components/Title";
|
||||
function RemoteApp({ app }) {
|
||||
// console.log("app ", app);
|
||||
const { Component: RemoteComponent } = useFederatedComponent(app);
|
||||
// console.log("RemoteComponent ", RemoteComponent);
|
||||
return (
|
||||
<>
|
||||
<Title title={app.remoteName} />
|
||||
<Suspense
|
||||
fallback={
|
||||
<div style={{ height: "300px" }}>
|
||||
<div
|
||||
style={{
|
||||
marginLeft: "45%",
|
||||
marginTop: "150px",
|
||||
fontSize: "45px",
|
||||
color: "#3dd3e0"
|
||||
}}
|
||||
className="loader-37"
|
||||
></div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.33)",
|
||||
backgroundColor: "#ffffff",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
borderRadius: 3,
|
||||
minHeight: "70vh"
|
||||
}}
|
||||
>
|
||||
{RemoteComponent && <RemoteComponent />}
|
||||
</div>
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
}
|
||||
function checkObjectProperties(obj) {
|
||||
// Check if all three properties exist in the object
|
||||
if (
|
||||
obj &&
|
||||
obj.remoteName !== undefined &&
|
||||
obj.remoteUrl !== undefined &&
|
||||
obj.moduleToLoad !== undefined
|
||||
) {
|
||||
return true; // All properties are present
|
||||
} else {
|
||||
return false; // At least one property is missing
|
||||
}
|
||||
}
|
||||
export default function RemoteAppContainer() {
|
||||
const { remoteApp } = useParams();
|
||||
|
||||
const obj = {
|
||||
remoteUrl: window.location.origin + "/mfbuild/remoteEntry.js",
|
||||
moduleToLoad: "./AppRoutes",
|
||||
remoteName: remoteApp
|
||||
};
|
||||
// console.log("obj ", obj);
|
||||
const isMf = checkObjectProperties(obj);
|
||||
if (isMf) {
|
||||
const appToLoad = obj;
|
||||
return <RemoteApp app={appToLoad} />;
|
||||
} else {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
|
||||
<div className="text-center">
|
||||
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black">
|
||||
404
|
||||
</h1>
|
||||
<p className="text-[30px] lg:text-[50px] text-black">
|
||||
Page Not Found
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
+470
-360
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,9 @@ const PgSignUp = (props) => {
|
||||
});
|
||||
const [validationMessage, setValidationMessage] = useState("");
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
const [lengthValid, setLengthValid] = useState(false);
|
||||
const [caseDigitValid, setCaseDigitValid] = useState(false);
|
||||
const [specialCharValid, setSpecialCharValid] = useState(false);
|
||||
|
||||
// below useEffect is used to fetch App data and save to redux state
|
||||
useEffect(() => {
|
||||
@@ -67,9 +70,8 @@ const PgSignUp = (props) => {
|
||||
const userSettings = JSON.parse(localStorage.getItem("userSettings"));
|
||||
const extClass = userSettings[0].extended_class;
|
||||
// console.log("extClass ", extClass);
|
||||
const checkUser = new Parse.Query(extClass);
|
||||
checkUser.equalTo("Email", userDetails.email);
|
||||
const res = await checkUser.first();
|
||||
const params = { email: userDetails.email };
|
||||
const res = await Parse.Cloud.run("getUserDetails", params);
|
||||
// console.log("res", res);
|
||||
if (res) {
|
||||
const checkUser = new Parse.Query(extClass);
|
||||
@@ -105,21 +107,23 @@ const PgSignUp = (props) => {
|
||||
// "handleSubmit" is used to save user details signup him/her who come from plan-pricing page
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
setIsLoader(true);
|
||||
if (formData.password === formData.confirmPassword) {
|
||||
const url = window.location.href;
|
||||
let paramString = url.split("?")[1];
|
||||
let queryString = new URLSearchParams(paramString);
|
||||
// console.log("url ", queryString);
|
||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||
setIsLoader(true);
|
||||
if (formData.password === formData.confirmPassword) {
|
||||
const url = window.location.href;
|
||||
let paramString = url.split("?")[1];
|
||||
let queryString = new URLSearchParams(paramString);
|
||||
// console.log("url ", queryString);
|
||||
|
||||
let obj = { ...formData };
|
||||
for (let pair of queryString.entries()) {
|
||||
// console.log("Key is: " + pair[0]);
|
||||
// console.log("Value is: " + pair[1]);
|
||||
obj = { ...obj, [pair[0]]: pair[1] };
|
||||
let obj = { ...formData };
|
||||
for (let pair of queryString.entries()) {
|
||||
// console.log("Key is: " + pair[0]);
|
||||
// console.log("Value is: " + pair[1]);
|
||||
obj = { ...obj, [pair[0]]: pair[1] };
|
||||
}
|
||||
saveUser(obj);
|
||||
// console.log("obj ", obj);}
|
||||
}
|
||||
saveUser(obj);
|
||||
// console.log("obj ", obj);}
|
||||
}
|
||||
};
|
||||
const saveUser = async (obj) => {
|
||||
@@ -152,6 +156,7 @@ const PgSignUp = (props) => {
|
||||
if (res) {
|
||||
const params = {
|
||||
userDetails: {
|
||||
jobTitle: zohoRes.data.result.jobTitle,
|
||||
company: zohoRes.data.result.company,
|
||||
name: zohoRes.data.result.name,
|
||||
email: zohoRes.data.result.email,
|
||||
@@ -194,6 +199,15 @@ const PgSignUp = (props) => {
|
||||
const newPassword = e.target.value;
|
||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||
validatePasswords(newPassword, formData.confirmPassword);
|
||||
|
||||
// Check conditions separately
|
||||
setLengthValid(newPassword.length >= 8);
|
||||
setCaseDigitValid(
|
||||
/[a-z]/.test(newPassword) &&
|
||||
/[A-Z]/.test(newPassword) &&
|
||||
/\d/.test(newPassword)
|
||||
);
|
||||
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
|
||||
};
|
||||
const handleConFirmPassowordChange = (e) => {
|
||||
const newConfirmPassword = e.target.value;
|
||||
@@ -279,13 +293,6 @@ const PgSignUp = (props) => {
|
||||
""
|
||||
);
|
||||
localStorage.setItem("_user_role", _role);
|
||||
|
||||
if (element.enableCart) {
|
||||
localStorage.setItem("EnableCart", element.enableCart);
|
||||
props.setEnableCart(element.enableCart);
|
||||
} else {
|
||||
localStorage.removeItem("EnableCart");
|
||||
}
|
||||
// Get TenentID from Extendend Class
|
||||
localStorage.setItem(
|
||||
"extended_class",
|
||||
@@ -293,14 +300,12 @@ const PgSignUp = (props) => {
|
||||
);
|
||||
localStorage.setItem("userpointer", element.userpointer);
|
||||
|
||||
const extendedClass = Parse.Object.extend(
|
||||
element.extended_class
|
||||
);
|
||||
let query = new Parse.Query(extendedClass);
|
||||
query.equalTo("UserId", Parse.User.current());
|
||||
query.include("TenantId");
|
||||
await query.find().then(
|
||||
(results) => {
|
||||
const currentUser = Parse.User.current();
|
||||
await Parse.Cloud.run("getUserDetails", {
|
||||
email: currentUser.get("email")
|
||||
}).then(
|
||||
(result) => {
|
||||
const results = [result];
|
||||
let tenentInfo = [];
|
||||
if (results) {
|
||||
let extendedInfo_stringify =
|
||||
@@ -415,7 +420,7 @@ const PgSignUp = (props) => {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err', err)
|
||||
console.log("err", err);
|
||||
setIsLoader(false);
|
||||
});
|
||||
}
|
||||
@@ -448,10 +453,10 @@ const PgSignUp = (props) => {
|
||||
) : (
|
||||
<form id="signup" className="pgsignup-content" onSubmit={handleSubmit}>
|
||||
<div className="pgsignup-container">
|
||||
<h1 className="text-4xl font-bold">Choose Password</h1>
|
||||
<h1 className="text-2xl md:text-3xl font-bold">Choose Password</h1>
|
||||
<hr className="hrt" />
|
||||
<label htmlFor="password">
|
||||
<b>Password</b>
|
||||
<b className="text-[13px]">Password</b>
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
@@ -464,7 +469,7 @@ const PgSignUp = (props) => {
|
||||
/>
|
||||
|
||||
<label htmlFor="confirmPassword">
|
||||
<b>Confirm Password</b>
|
||||
<b className="text-[13px]">Confirm Password</b>
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
@@ -494,6 +499,33 @@ const PgSignUp = (props) => {
|
||||
>
|
||||
{validationMessage}
|
||||
</div>
|
||||
{formData.password.length > 0 && (
|
||||
<div className="mt-1 text-[11px]">
|
||||
<p
|
||||
className={`${
|
||||
lengthValid ? "text-green-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{lengthValid ? "✓" : "✗"} Password should be 8 characters long
|
||||
</p>
|
||||
<p
|
||||
className={`${
|
||||
caseDigitValid ? "text-green-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{caseDigitValid ? "✓" : "✗"} Password should contain uppercase
|
||||
letter, lowercase letter, digit
|
||||
</p>
|
||||
<p
|
||||
className={`${
|
||||
specialCharValid ? "text-green-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{specialCharValid ? "✓" : "✗"} Password should contain special
|
||||
character
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="clearfix">
|
||||
<button type="submit" className="signupbtn">
|
||||
Submit
|
||||
|
||||
@@ -2,14 +2,14 @@ import React, { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import checkmark from "../assets/images/checkmark.png";
|
||||
import plansArr from '../json/plansArr.json'
|
||||
import plansArr from "../json/plansArr.json";
|
||||
import Title from "../components/Title";
|
||||
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
|
||||
backgroundPosition: 'left',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: '16px 16px', // Adjust the size of the image
|
||||
backgroundPosition: "left",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: "16px 16px" // Adjust the size of the image
|
||||
};
|
||||
|
||||
const PlanSubscriptions = () => {
|
||||
@@ -28,7 +28,12 @@ const PlanSubscriptions = () => {
|
||||
: "";
|
||||
const phone =
|
||||
userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : "";
|
||||
const details = "?" + name + email + company + phone;
|
||||
const details =
|
||||
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
||||
name +
|
||||
email +
|
||||
company +
|
||||
phone;
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem("accesstoken")) {
|
||||
setIsLoader(false);
|
||||
@@ -41,7 +46,7 @@ const PlanSubscriptions = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title title={"Subscriptions"} />
|
||||
<Title title={"Subscriptions"} />
|
||||
{isLoader ? (
|
||||
<div
|
||||
style={{
|
||||
@@ -64,7 +69,7 @@ const PlanSubscriptions = () => {
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
overflowY: "auto",
|
||||
maxHeight: "600px",
|
||||
maxHeight: "100%",
|
||||
"--theme-color": "#7952b3",
|
||||
"--plan-width": 30
|
||||
}}
|
||||
@@ -131,15 +136,18 @@ const PlanSubscriptions = () => {
|
||||
<p>{item.subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#002862] w-full text-white py-2 rounded">
|
||||
<NavLink
|
||||
to={item.url + details}
|
||||
className="rounded uppercase hover:no-underline hover:text-white"
|
||||
target="_self"
|
||||
>
|
||||
{item.btnText}
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<NavLink
|
||||
to={
|
||||
item.btnText === "Subscribe"
|
||||
? item.url + details
|
||||
: item.url
|
||||
}
|
||||
className="bg-[#002862] w-full text-white py-2 rounded uppercase hover:no-underline hover:text-white"
|
||||
target={item.target}
|
||||
>
|
||||
{item.btnText}
|
||||
</NavLink>
|
||||
</div>
|
||||
<hr className="w-full bg-gray-300 p-[.5px]" />
|
||||
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
||||
|
||||
@@ -65,7 +65,9 @@ export default function RemoteAppContainer() {
|
||||
// console.log("value ", key + ":" + value);
|
||||
|
||||
if (key === "remoteUrl") {
|
||||
obj = { ...obj, [key]: atob(value) };
|
||||
const url = window.location.origin + "/mfbuild/remoteEntry.js";
|
||||
// console.log("atob(value) ", atob(value))
|
||||
obj = { ...obj, [key]: url };
|
||||
} else {
|
||||
if (key === "moduleToLoad") {
|
||||
obj = { ...obj, [key]: "./" + value };
|
||||
|
||||
@@ -12,39 +12,62 @@ const Report = () => {
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
const [reportName, setReportName] = useState("");
|
||||
const [actions, setActions] = useState([]);
|
||||
const [heading, setHeading] = useState([]);
|
||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
||||
const abortController = new AbortController();
|
||||
const docPerPage = 10;
|
||||
|
||||
// below useEffect is call when id param change
|
||||
useEffect(() => {
|
||||
setReportName("");
|
||||
setList([]);
|
||||
getReportData();
|
||||
|
||||
// Function returned from useEffect is called on unmount
|
||||
return () => {
|
||||
setIsLoader(true);
|
||||
setList([]);
|
||||
setIsNextRecord(false);
|
||||
// Here it'll abort the fetch
|
||||
abortController.abort();
|
||||
};
|
||||
// eslint-disable-next-line
|
||||
}, [id]);
|
||||
|
||||
const getReportData = async () => {
|
||||
setIsLoader(true);
|
||||
// below useEffect call when isNextRecord state is true and fetch next record
|
||||
useEffect(() => {
|
||||
if (isNextRecord) {
|
||||
getReportData(List.length, 200);
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [isNextRecord]);
|
||||
|
||||
const getReportData = async (skipUserRecord = 0, limit = 200) => {
|
||||
// setIsLoader(true);
|
||||
const json = reportJson(id);
|
||||
if (json) {
|
||||
setActions(json.actions);
|
||||
setHeading(json.heading);
|
||||
setReportName(json.reportName);
|
||||
const { className, params, keys, orderBy } = json;
|
||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
||||
Parse.initialize(localStorage.getItem("AppID12"));
|
||||
const currentUser = Parse.User.current().id;
|
||||
const serverURL =
|
||||
localStorage.getItem("BaseUrl12") + "classes/" + className;
|
||||
|
||||
const strParams = JSON.stringify(params);
|
||||
const strKeys = keys.join();
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
sessiontoken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
try {
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
const params = { reportId: id, skip: skipUserRecord, limit: limit };
|
||||
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
|
||||
const res = await axios.post(url, params, {
|
||||
headers: headers,
|
||||
signal: abortController.signal // is used to cancel fetch query
|
||||
});
|
||||
if (id === "4Hhwbp482K") {
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
const listData = res.data?.result.filter((x) => x.Signers.length > 0);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
@@ -66,14 +89,34 @@ const Report = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
setList(arr);
|
||||
if (arr.length === docPerPage) {
|
||||
setIsMoreDocs(true);
|
||||
} else {
|
||||
setIsMoreDocs(false);
|
||||
}
|
||||
setList((prevRecord) =>
|
||||
prevRecord.length > 0 ? [...prevRecord, ...arr] : arr
|
||||
);
|
||||
} else {
|
||||
setList(res.data?.results);
|
||||
if (res.data.result.length === docPerPage) {
|
||||
setIsMoreDocs(true);
|
||||
} else {
|
||||
setIsMoreDocs(false);
|
||||
}
|
||||
setIsNextRecord(false);
|
||||
setList((prevRecord) =>
|
||||
prevRecord.length > 0
|
||||
? [...prevRecord, ...res.data.result]
|
||||
: res.data.result
|
||||
);
|
||||
}
|
||||
setIsLoader(false);
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
setIsLoader(false);
|
||||
const isCancel = axios.isCancel(err);
|
||||
if (!isCancel) {
|
||||
console.log("err ", err);
|
||||
setIsLoader(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setIsLoader(false);
|
||||
@@ -105,7 +148,12 @@ const Report = () => {
|
||||
<ReportTable
|
||||
ReportName={reportName}
|
||||
List={List}
|
||||
setList={setList}
|
||||
actions={actions}
|
||||
heading={heading}
|
||||
setIsNextRecord={setIsNextRecord}
|
||||
isMoreDocs={isMoreDocs}
|
||||
docPerPage={docPerPage}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
|
||||
|
||||
+187
-113
@@ -6,8 +6,10 @@ import Title from "../components/Title";
|
||||
import { fetchAppInfo, showTenantName } from "../redux/actions";
|
||||
import { useNavigate, NavLink } from "react-router-dom";
|
||||
import login_img from "../assets/images/login_img.svg";
|
||||
import { useWindowSize } from "../hook/useWindowSize";
|
||||
|
||||
const Signup = (props) => {
|
||||
const { width } = useWindowSize();
|
||||
const navigate = useNavigate();
|
||||
const [name, setName] = useState("");
|
||||
const [phone, setPhone] = useState("");
|
||||
@@ -18,93 +20,143 @@ const Signup = (props) => {
|
||||
const [company, setCompany] = useState("");
|
||||
const [jobTitle, setJobTitle] = useState("");
|
||||
const [state, setState] = useState({
|
||||
hideNav: "",
|
||||
loading: false,
|
||||
toastColor: "#5cb85c",
|
||||
toastDescription: ""
|
||||
});
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [lengthValid, setLengthValid] = useState(false);
|
||||
const [caseDigitValid, setCaseDigitValid] = useState(false);
|
||||
const [specialCharValid, setSpecialCharValid] = useState(false);
|
||||
|
||||
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
||||
const image = props.appInfo.applogo;
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
setState({ loading: true });
|
||||
const userDetails = {
|
||||
name: name,
|
||||
email: email,
|
||||
phone: phone,
|
||||
company: company,
|
||||
jobTitle: jobTitle
|
||||
};
|
||||
localStorage.setItem("userDetails", JSON.stringify(userDetails));
|
||||
try {
|
||||
event.preventDefault();
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
event.preventDefault();
|
||||
var user = new Parse.User();
|
||||
user.set("name", name);
|
||||
user.set("email", email);
|
||||
user.set("password", password);
|
||||
user.set("phone", phone);
|
||||
user.set("username", email);
|
||||
let res = user.save();
|
||||
res
|
||||
.then(async (r) => {
|
||||
if (r) {
|
||||
let roleurl = `${parseBaseUrl}functions/AddUserToRole`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
sessionToken:
|
||||
r.getSessionToken() || localStorage.getItem("accesstoken")
|
||||
};
|
||||
let body = {
|
||||
appName: props.appInfo.appname,
|
||||
roleName: props.appInfo.defaultRole,
|
||||
userId: r.id
|
||||
};
|
||||
await axios.post(roleurl, body, { headers: headers });
|
||||
const clearStorage = async () => {
|
||||
if (Parse.User.current()) {
|
||||
await Parse.User.logOut();
|
||||
}
|
||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
||||
let appid = localStorage.getItem("AppID12");
|
||||
let applogo = localStorage.getItem("appLogo");
|
||||
let domain = localStorage.getItem("domain");
|
||||
let appversion = localStorage.getItem("appVersion");
|
||||
let appTitle = localStorage.getItem("appTitle");
|
||||
let defaultmenuid = localStorage.getItem("defaultmenuid");
|
||||
let PageLanding = localStorage.getItem("PageLanding");
|
||||
let _appName = localStorage.getItem("_appName");
|
||||
let _app_objectId = localStorage.getItem("_app_objectId");
|
||||
let appName = localStorage.getItem("appName");
|
||||
let userSettings = localStorage.getItem("userSettings");
|
||||
|
||||
let roleData = props.appInfo.settings;
|
||||
if (roleData && roleData.length > 0) {
|
||||
roleData.forEach((rld) => {
|
||||
if (rld.role === props.appInfo.defaultRole) {
|
||||
const extCls = Parse.Object.extend(rld.extended_class);
|
||||
const newObj = new extCls();
|
||||
newObj.set("UserId", {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: r.id
|
||||
});
|
||||
newObj.set("UserRole", props.appInfo.defaultRole);
|
||||
newObj.set("Email", email);
|
||||
newObj.set("Name", name);
|
||||
newObj.set("Phone", phone);
|
||||
newObj.set("Company", company);
|
||||
newObj.set("JobTitle", jobTitle);
|
||||
newObj
|
||||
.save()
|
||||
.then((ex) => {
|
||||
if (ex) {
|
||||
handleNavigation(r.getSessionToken());
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
alert(err.message);
|
||||
setState({ loading: false });
|
||||
});
|
||||
localStorage.clear();
|
||||
|
||||
localStorage.setItem("BaseUrl12", baseUrl);
|
||||
localStorage.setItem("AppID12", appid);
|
||||
localStorage.setItem("appLogo", applogo);
|
||||
localStorage.setItem("domain", domain);
|
||||
localStorage.setItem("appversion", appversion);
|
||||
localStorage.setItem("appTitle", appTitle);
|
||||
localStorage.setItem("defaultmenuid", defaultmenuid);
|
||||
localStorage.setItem("PageLanding", PageLanding);
|
||||
localStorage.setItem("_appName", _appName);
|
||||
localStorage.setItem("_app_objectId", _app_objectId);
|
||||
localStorage.setItem("appName", appName);
|
||||
localStorage.setItem("userSettings", userSettings);
|
||||
localStorage.setItem("baseUrl", baseUrl);
|
||||
localStorage.setItem("parseAppId", appid);
|
||||
};
|
||||
const handleSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||
clearStorage();
|
||||
setState({ loading: true });
|
||||
const userDetails = {
|
||||
name: name,
|
||||
email: email,
|
||||
phone: phone,
|
||||
company: company,
|
||||
jobTitle: jobTitle
|
||||
};
|
||||
localStorage.setItem("userDetails", JSON.stringify(userDetails));
|
||||
try {
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
event.preventDefault();
|
||||
var user = new Parse.User();
|
||||
user.set("name", name);
|
||||
user.set("email", email);
|
||||
user.set("password", password);
|
||||
user.set("phone", phone);
|
||||
user.set("username", email);
|
||||
let res = user.save();
|
||||
res
|
||||
.then(async (r) => {
|
||||
if (r) {
|
||||
let roleData = props.appInfo.settings;
|
||||
if (roleData && roleData.length > 0) {
|
||||
const params = {
|
||||
userDetails: {
|
||||
jobTitle: jobTitle,
|
||||
company: company,
|
||||
name: name,
|
||||
email: email,
|
||||
phone: phone,
|
||||
role: props.appInfo.defaultRole
|
||||
}
|
||||
};
|
||||
try {
|
||||
const usersignup = await Parse.Cloud.run(
|
||||
"usersignup",
|
||||
params
|
||||
);
|
||||
if (usersignup) {
|
||||
handleNavigation(r.getSessionToken());
|
||||
}
|
||||
} catch (err) {
|
||||
alert(err.message);
|
||||
setState({ loading: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
alert(err.message);
|
||||
setState({ loading: false });
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("err ", error);
|
||||
})
|
||||
.catch(async (err) => {
|
||||
if (err.code === 202) {
|
||||
const params = { email: email };
|
||||
const res = await Parse.Cloud.run("getUserDetails", params);
|
||||
// console.log("Res ", res);
|
||||
if (res) {
|
||||
alert("User already exists with this username!");
|
||||
setState({ loading: false });
|
||||
} else {
|
||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
||||
let parseAppId = localStorage.getItem("AppID12");
|
||||
// console.log("state.email ", email);
|
||||
try {
|
||||
Parse.serverURL = baseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
await Parse.User.requestPasswordReset(email).then(
|
||||
async function (res1) {
|
||||
if (res1.data === undefined) {
|
||||
alert(
|
||||
"Verification mail has been sent to your E-mail!"
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
setState({ loading: false });
|
||||
}
|
||||
} else {
|
||||
alert(err.message);
|
||||
setState({ loading: false });
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("err ", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -179,13 +231,6 @@ const Signup = (props) => {
|
||||
""
|
||||
);
|
||||
localStorage.setItem("_user_role", _role);
|
||||
|
||||
if (element.enableCart) {
|
||||
localStorage.setItem("EnableCart", element.enableCart);
|
||||
props.setEnableCart(element.enableCart);
|
||||
} else {
|
||||
localStorage.removeItem("EnableCart");
|
||||
}
|
||||
// Get TenentID from Extendend Class
|
||||
localStorage.setItem(
|
||||
"extended_class",
|
||||
@@ -193,15 +238,12 @@ const Signup = (props) => {
|
||||
);
|
||||
localStorage.setItem("userpointer", element.userpointer);
|
||||
|
||||
const extendedClass = Parse.Object.extend(
|
||||
element.extended_class
|
||||
);
|
||||
let query = new Parse.Query(extendedClass);
|
||||
query.equalTo("UserId", Parse.User.current());
|
||||
query.include("TenantId");
|
||||
await query.find().then(
|
||||
(results) => {
|
||||
await Parse.Cloud.run("getUserDetails", {
|
||||
email: email
|
||||
}).then(
|
||||
(result) => {
|
||||
let tenentInfo = [];
|
||||
const results = [result];
|
||||
if (results) {
|
||||
let extendedInfo_stringify =
|
||||
JSON.stringify(results);
|
||||
@@ -251,7 +293,7 @@ const Signup = (props) => {
|
||||
element.pageType
|
||||
);
|
||||
setState({ loading: false });
|
||||
navigate("/login");
|
||||
navigate("/");
|
||||
} else {
|
||||
extendedInfo.forEach((x) => {
|
||||
if (x.TenantId) {
|
||||
@@ -289,7 +331,7 @@ const Signup = (props) => {
|
||||
);
|
||||
setState({ loading: false });
|
||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
||||
navigate("/subscription");
|
||||
navigate(`/subscription`, { replace: true });
|
||||
} else {
|
||||
alert("Registered user successfully");
|
||||
navigate(
|
||||
@@ -307,7 +349,7 @@ const Signup = (props) => {
|
||||
localStorage.setItem("pageType", element.pageType);
|
||||
setState({ loading: false });
|
||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
||||
navigate("/subscription");
|
||||
navigate(`/subscription`, { replace: true });
|
||||
} else {
|
||||
navigate(
|
||||
`/${element.pageType}/${element.pageId}`
|
||||
@@ -392,23 +434,26 @@ const Signup = (props) => {
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", resize);
|
||||
props.fetchAppInfo(
|
||||
localStorage.getItem("domain"),
|
||||
localStorage.getItem("BaseUrl12"),
|
||||
localStorage.getItem("AppID12")
|
||||
);
|
||||
return () => {
|
||||
window.removeEventListener("resize", resize);
|
||||
};
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
const resize = () => {
|
||||
let currentHideNav = window.innerWidth <= 760;
|
||||
if (currentHideNav !== state.hideNav) {
|
||||
setState({ hideNav: currentHideNav });
|
||||
}
|
||||
const handlePasswordChange = (e) => {
|
||||
const newPassword = e.target.value;
|
||||
setPassword(newPassword);
|
||||
|
||||
// Check conditions separately
|
||||
setLengthValid(newPassword.length >= 8);
|
||||
setCaseDigitValid(
|
||||
/[a-z]/.test(newPassword) &&
|
||||
/[A-Z]/.test(newPassword) &&
|
||||
/\d/.test(newPassword)
|
||||
);
|
||||
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
|
||||
};
|
||||
return (
|
||||
<div className="bg-white">
|
||||
@@ -443,17 +488,13 @@ const Signup = (props) => {
|
||||
<div>
|
||||
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
||||
<div className="w-[250px] h-[66px] inline-block">
|
||||
{state.hideNav ? (
|
||||
<img src={image} width="100%" alt="" />
|
||||
) : (
|
||||
<img src={image} width="100%" alt="" />
|
||||
)}
|
||||
<img src={image} width="100%" alt="" />
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||
<div className="">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h2 className="text-[30px] mt-6">Create Account !</h2>
|
||||
<div className="shadow-md rounded my-4">
|
||||
<div className="outline outline-1 outline-slate-300/50 shadow-md rounded my-4">
|
||||
<div className="px-6 py-4 text-xs">
|
||||
<label className="block ">
|
||||
Name{" "}
|
||||
@@ -472,6 +513,7 @@ const Signup = (props) => {
|
||||
<span style={{ color: "red", fontSize: 13 }}>*</span>
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="text"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
value={email}
|
||||
@@ -525,7 +567,7 @@ const Signup = (props) => {
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
name="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => handlePasswordChange(e)}
|
||||
required
|
||||
/>
|
||||
<span
|
||||
@@ -541,6 +583,38 @@ const Signup = (props) => {
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
{password.length > 0 && (
|
||||
<div className="mt-1 text-[11px]">
|
||||
<p
|
||||
className={`${
|
||||
lengthValid ? "text-green-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{lengthValid ? "✓" : "✗"} Password should be 8
|
||||
characters long
|
||||
</p>
|
||||
<p
|
||||
className={`${
|
||||
caseDigitValid ? "text-green-600" : "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{caseDigitValid ? "✓" : "✗"} Password should contain
|
||||
uppercase letter, lowercase letter, digit
|
||||
</p>
|
||||
<p
|
||||
className={`${
|
||||
specialCharValid
|
||||
? "text-green-600"
|
||||
: "text-red-600"
|
||||
}`}
|
||||
>
|
||||
{specialCharValid ? "✓" : "✗"} Password should
|
||||
contain special character
|
||||
</p>
|
||||
{/* </>
|
||||
)} */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
|
||||
@@ -554,16 +628,16 @@ const Signup = (props) => {
|
||||
<NavLink
|
||||
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
|
||||
to="/"
|
||||
style={state.hideNav ? { textAlign: "center" } : {}}
|
||||
style={width < 768 ? { textAlign: "center" } : {}}
|
||||
>
|
||||
Login
|
||||
</NavLink>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{!state.hideNav && (
|
||||
{width >= 768 && (
|
||||
<div className="self-center">
|
||||
<div className="mx-auto md:w-[300px] lg:w-[500px]">
|
||||
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
|
||||
<img src={login_img} alt="bisec" width="100%" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SaveFileSize } from "../constant/saveFileSize";
|
||||
import dp from "../assets/images/dp.png";
|
||||
import Title from "../components/Title";
|
||||
import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||
|
||||
import axios from "axios";
|
||||
function UserProfile() {
|
||||
const navigate = useNavigate();
|
||||
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
||||
@@ -16,6 +16,8 @@ function UserProfile() {
|
||||
const [Phone, SetPhone] = useState(UserProfile && UserProfile.phone);
|
||||
const [Image, setImage] = useState(localStorage.getItem("profileImg"));
|
||||
const [isLoader, setIsLoader] = useState(false);
|
||||
const [percentage, setpercentage] = useState(0);
|
||||
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
const handleSubmit = async (e) => {
|
||||
@@ -44,7 +46,7 @@ function UserProfile() {
|
||||
await updateExtUser({ Name: res.name, Phone: res.phone });
|
||||
alert("Profile updated successfully.");
|
||||
setEditMode(false);
|
||||
navigate("/");
|
||||
navigate("/dashboard/35KBoSgoAK");
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
@@ -64,18 +66,24 @@ function UserProfile() {
|
||||
const extClass = localStorage.getItem("extended_class");
|
||||
const extData = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
const ExtUserId = extData[0].objectId;
|
||||
// console.log("extData ", extData);
|
||||
// console.log("UserId ", ExtUserId);
|
||||
const body = { Phone: obj.Phone, Name: obj.Name };
|
||||
await axios.put(
|
||||
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
|
||||
body,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": parseAppId,
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
}
|
||||
}
|
||||
);
|
||||
const res = await Parse.Cloud.run("getUserDetails", {
|
||||
email: extData[0].Email
|
||||
});
|
||||
|
||||
const extQuery = new Parse.Query(extClass);
|
||||
const update = await extQuery.get(ExtUserId);
|
||||
// console.log("update ", update);
|
||||
|
||||
update.set("Phone", obj.Phone);
|
||||
update.set("Name", obj.Name);
|
||||
const updateRes = await update.save();
|
||||
|
||||
const json = JSON.parse(JSON.stringify([updateRes]));
|
||||
const json = JSON.parse(JSON.stringify([res]));
|
||||
const extRes = JSON.stringify(json);
|
||||
|
||||
localStorage.setItem("Extand_Class", extRes);
|
||||
@@ -96,7 +104,15 @@ function UserProfile() {
|
||||
const parseFile = new Parse.File(name, pdfFile);
|
||||
|
||||
try {
|
||||
const response = await parseFile.save();
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
// console.log("percentCompleted ", percentCompleted);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
// // The response object will contain information about the uploaded file
|
||||
// console.log("File uploaded:", response);
|
||||
|
||||
@@ -105,6 +121,7 @@ function UserProfile() {
|
||||
if (response.url()) {
|
||||
setImage(response.url());
|
||||
localStorage.setItem("profileImg", response.url());
|
||||
setpercentage(0);
|
||||
SaveFileSize(size, response.url());
|
||||
return response.url();
|
||||
}
|
||||
@@ -141,113 +158,126 @@ function UserProfile() {
|
||||
></div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||
<div className="flex flex-col justify-center items-center my-4">
|
||||
<div className="w-[200px] h-[200px] overflow-hidden rounded-full">
|
||||
<img
|
||||
className="object-contain w-full h-full"
|
||||
src={Image === "" ? dp : Image}
|
||||
alt="dp"
|
||||
/>
|
||||
</div>
|
||||
{editmode && (
|
||||
<input
|
||||
type="file"
|
||||
className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded"
|
||||
onChange={(e) => {
|
||||
let files = e.target.files;
|
||||
fileUpload(files[0]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="text-base font-semibold pt-4">
|
||||
{" "}
|
||||
{localStorage.getItem("_user_role")}
|
||||
</div>
|
||||
</div>
|
||||
<ul className="w-full flex flex-col p-2 text-sm">
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1" : "py-2"
|
||||
}`}
|
||||
>
|
||||
<span>Name:</span>{" "}
|
||||
{editmode ? (
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||
onChange={(e) => SetName(e.target.value)}
|
||||
<div className="flex justify-center items-center w-full">
|
||||
<div className="bg-white flex flex-col justify-center shadow rounded w-[450px]">
|
||||
<div className="flex flex-col justify-center items-center my-4">
|
||||
<div className="w-[200px] h-[200px] overflow-hidden rounded-full">
|
||||
<img
|
||||
className="object-contain w-full h-full"
|
||||
src={Image === "" ? dp : Image}
|
||||
alt="dp"
|
||||
/>
|
||||
) : (
|
||||
<span>{localStorage.getItem("username")}</span>
|
||||
)}
|
||||
</li>
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1" : "py-2"
|
||||
}`}
|
||||
>
|
||||
<span>Phone:</span>{" "}
|
||||
{editmode ? (
|
||||
</div>
|
||||
{editmode && (
|
||||
<input
|
||||
type="text"
|
||||
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||
onChange={(e) => SetPhone(e.target.value)}
|
||||
value={Phone}
|
||||
type="file"
|
||||
className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded"
|
||||
accept="image/png, image/gif, image/jpeg"
|
||||
onChange={(e) => {
|
||||
let files = e.target.files;
|
||||
fileUpload(files[0]);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<span>{UserProfile && UserProfile.phone}</span>
|
||||
)}
|
||||
</li>
|
||||
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
|
||||
<span>Email:</span>{" "}
|
||||
<span>{UserProfile && UserProfile.email}</span>
|
||||
</li>
|
||||
<li className="flex justify-between items-center border-y-[1px] border-gray-300 py-2 break-all">
|
||||
<span>Is Email verified:</span>{" "}
|
||||
<span>
|
||||
{UserProfile && UserProfile.emailVerified
|
||||
? "Verified"
|
||||
: "Not verified"}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex justify-center pb-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (editmode) {
|
||||
setEditMode(false);
|
||||
} else {
|
||||
navigate("/changepassword");
|
||||
}
|
||||
}}
|
||||
className={`rounded shadow text-white bg-[#3598dc] mr-4 ${
|
||||
editmode ? "px-4 py-2 " : "p-2"
|
||||
}`}
|
||||
>
|
||||
{editmode ? "Cancel" : "Change Password"}
|
||||
</button>
|
||||
{editmode ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSubmit}
|
||||
className="rounded bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-2"
|
||||
{percentage !== 0 && (
|
||||
<div className="flex items-center gap-x-2">
|
||||
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
|
||||
<div
|
||||
className="h-2 rounded-full bg-blue-500"
|
||||
style={{ width: `${percentage}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-black text-sm">{percentage}%</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-base font-semibold pt-4">
|
||||
{localStorage.getItem("_user_role")}
|
||||
</div>
|
||||
</div>
|
||||
<ul className="w-full flex flex-col p-2 text-sm">
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1" : "py-2"
|
||||
}`}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
) : (
|
||||
<span className="font-semibold">Name:</span>{" "}
|
||||
{editmode ? (
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||
onChange={(e) => SetName(e.target.value)}
|
||||
/>
|
||||
) : (
|
||||
<span>{localStorage.getItem("username")}</span>
|
||||
)}
|
||||
</li>
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1" : "py-2"
|
||||
}`}
|
||||
>
|
||||
<span className="font-semibold">Phone:</span>{" "}
|
||||
{editmode ? (
|
||||
<input
|
||||
type="text"
|
||||
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||
onChange={(e) => SetPhone(e.target.value)}
|
||||
value={Phone}
|
||||
/>
|
||||
) : (
|
||||
<span>{UserProfile && UserProfile.phone}</span>
|
||||
)}
|
||||
</li>
|
||||
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
|
||||
<span className="font-semibold">Email:</span>{" "}
|
||||
<span>{UserProfile && UserProfile.email}</span>
|
||||
</li>
|
||||
<li className="flex justify-between items-center border-y-[1px] border-gray-300 py-2 break-all">
|
||||
<span className="font-semibold">Is Email verified:</span>{" "}
|
||||
<span>
|
||||
{UserProfile && UserProfile.emailVerified
|
||||
? "Verified"
|
||||
: "Not verified"}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
|
||||
{editmode ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSubmit}
|
||||
className="rounded shadow focus:outline-none border-[2px] border-[#15b4e9] bg-white text-[#15b4e9] px-4 py-2 mr-4"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setEditMode(true);
|
||||
}}
|
||||
className="rounded shadow focus:outline-none text-white bg-[#e7505a] px-4 py-2 mr-4"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setEditMode(true);
|
||||
if (editmode) {
|
||||
setEditMode(false);
|
||||
} else {
|
||||
navigate("/changepassword");
|
||||
}
|
||||
}}
|
||||
className="rounded shadow text-white bg-[#e7505a] px-4 py-2"
|
||||
className={`rounded shadow focus:outline-none text-white bg-[#3598dc] ${
|
||||
editmode ? "px-4 py-2 " : "p-2"
|
||||
}`}
|
||||
>
|
||||
Edit
|
||||
{editmode ? "Cancel" : "Change Password"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/* Full-width input fields */
|
||||
.inputt {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin: 5px 0 22px 0;
|
||||
padding: 8px;
|
||||
margin-bottom: 10px;
|
||||
/* margin: 5px 0 14px 0; */
|
||||
display: inline-block;
|
||||
border: none;
|
||||
background: #f1f1f1;
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Add a background color when the inputs get focus */
|
||||
@@ -18,11 +20,12 @@
|
||||
|
||||
.confirmInputt {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin: 5px 0 1px 0;
|
||||
padding: 8px;
|
||||
/* margin: 5px 0 14px 0; */
|
||||
display: inline-block;
|
||||
background: #f1f1f1;
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.inputt::placeholder,
|
||||
@@ -42,11 +45,10 @@
|
||||
.signupbtn {
|
||||
background-color: #15b4e9;
|
||||
color: white;
|
||||
padding: 14px 20px;
|
||||
padding: 12px 12px;
|
||||
margin: 8px 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
opacity: 0.9;
|
||||
float: left;
|
||||
width: 50%;
|
||||
@@ -87,7 +89,7 @@
|
||||
margin: 5% auto 15% auto;
|
||||
/* 5% from the top, 15% from the bottom and centered */
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
width: 50%;
|
||||
/* Could be more or less, depending on screen size */
|
||||
}
|
||||
|
||||
@@ -111,8 +113,26 @@
|
||||
}
|
||||
|
||||
/* Change styles for cancel button and signup button on extra small screens */
|
||||
@media screen and (max-width: 300px) {
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
/* pgsignup Content/Box */
|
||||
.pgsignup-content {
|
||||
background-color: #fefefe;
|
||||
margin: 5% auto 15% auto;
|
||||
/* 5% from the top, 15% from the bottom and centered */
|
||||
border: 1px solid #888;
|
||||
width: 90%;
|
||||
/* Could be more or less, depending on screen size */
|
||||
}
|
||||
|
||||
.signupbtn {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Style the horizontal ruler */
|
||||
.hrt {
|
||||
border: 1px solid #f1f1f1;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
.alertBox {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 13px;
|
||||
animation: inAnimation 2s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes inAnimation {
|
||||
0% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
25% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
75% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ FROM node:16
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package.json and package-lock.json first to leverage Docker cache
|
||||
COPY apps/OpenSignServer/package*.json ./
|
||||
COPY ./package*.json ./
|
||||
|
||||
# Install application dependencies
|
||||
RUN npm install
|
||||
@@ -14,7 +14,7 @@ RUN npm install
|
||||
# RUN apk add --no-cache make gcc g++ python3
|
||||
|
||||
# Copy the current directory contents into the container
|
||||
COPY apps/OpenSignServer/ .
|
||||
COPY ./ .
|
||||
|
||||
# Make port 8080 available to the world outside this container
|
||||
EXPOSE 8080
|
||||
@@ -24,4 +24,4 @@ EXPOSE 8080
|
||||
# ENV DATABASE_URL mongodb://db:27017
|
||||
|
||||
# Run the application
|
||||
CMD ["npm", "start"]
|
||||
ENTRYPOINT npm start
|
||||
|
||||
@@ -4,6 +4,12 @@ import multerS3 from 'multer-s3';
|
||||
import aws from 'aws-sdk';
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
function sanitizeFileName(fileName) {
|
||||
// Remove spaces and invalid characters
|
||||
return fileName.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||
}
|
||||
|
||||
async function uploadFile(req, res) {
|
||||
try {
|
||||
//--size extended to 100 mb
|
||||
@@ -50,16 +56,28 @@ async function uploadFile(req, res) {
|
||||
region: process.env.DO_REGION,
|
||||
});
|
||||
|
||||
// const s3 = new aws.S3();
|
||||
const upload = multer({
|
||||
fileFilter: function (req, file, cb) {
|
||||
if (accepted_extensions.some(ext => file.originalname.toLowerCase().endsWith('.' + ext))) {
|
||||
return cb(null, true);
|
||||
const parseBaseUrl = process.env.SERVER_URL;
|
||||
const parseAppId = process.env.APP_ID;
|
||||
|
||||
if (process.env.USE_LOCAL == "TRUE") {
|
||||
var fileStorage = multer.diskStorage({
|
||||
destination: function(req, file, cb) {
|
||||
cb(null, "files/files");
|
||||
},
|
||||
metadata: function (req, file, cb) {
|
||||
cb(null, { fieldName: 'OPENSIGN_METADATA' });
|
||||
},
|
||||
filename: function(req, file, cb) {
|
||||
let filename = file.originalname;
|
||||
let newFileName = filename.split('.')[0];
|
||||
let extension = filename.split('.')[1];
|
||||
newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension)
|
||||
console.log(newFileName);
|
||||
cb(null, newFileName);
|
||||
}
|
||||
// otherwise, return error
|
||||
return cb('Only ' + accepted_extensions.join(', ') + ' files are allowed!');
|
||||
},
|
||||
storage: multerS3({
|
||||
});
|
||||
} else {
|
||||
var fileStorage = multerS3({
|
||||
acl: 'public-read',
|
||||
s3,
|
||||
bucket: DO_SPACE,
|
||||
@@ -69,14 +87,25 @@ async function uploadFile(req, res) {
|
||||
key: function (req, file, cb) {
|
||||
//console.log(file);
|
||||
let filename = file.originalname;
|
||||
let filenam = filename.split('.')[0];
|
||||
let newFileName = filename.split('.')[0];
|
||||
let extension = filename.split('.')[1];
|
||||
filenam = filenam + '_' + new Date().toISOString() + '.' + extension;
|
||||
console.log(filenam);
|
||||
cb(null, filenam);
|
||||
},
|
||||
}),
|
||||
newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension)
|
||||
console.log(newFileName);
|
||||
cb(null, newFileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// const s3 = new aws.S3();
|
||||
const upload = multer({
|
||||
fileFilter: function (req, file, cb) {
|
||||
if (accepted_extensions.some(ext => file.originalname.toLowerCase().endsWith('.' + ext))) {
|
||||
return cb(null, true);
|
||||
}
|
||||
// otherwise, return error
|
||||
return cb('Only ' + accepted_extensions.join(', ') + ' files are allowed!');
|
||||
},
|
||||
storage: fileStorage,
|
||||
limits: { fileSize: size },
|
||||
}).single('file');
|
||||
|
||||
@@ -93,7 +122,14 @@ async function uploadFile(req, res) {
|
||||
const status = 'Success';
|
||||
//res.header("Access-Control-Allow-Headers", "Content-Type");
|
||||
//res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
return res.json({ status, imageUrl: req.file.location });
|
||||
if (process.env.USE_LOCAL == "TRUE") {
|
||||
console.log(req.file);
|
||||
var fileUrl = `${parseBaseUrl}/files/${parseAppId}/${req.file.filename}`;
|
||||
} else {
|
||||
var fileUrl = req.file.location;
|
||||
}
|
||||
|
||||
return res.json({ status, imageUrl: fileUrl });
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('Exeption in query ' + err.stack);
|
||||
|
||||
@@ -13,6 +13,10 @@ import sendMailOTPv1 from './parsefunction/SendMailOTPv1.js';
|
||||
import SendMailv1 from './parsefunction/SendMailv1.js';
|
||||
import AuthLoginAsMail from './parsefunction/AuthLoginAsMail.js';
|
||||
import getUserId from './parsefunction/getUserId.js';
|
||||
import getUserDetails from './parsefunction/getUserDetails.js';
|
||||
import getDocument from './parsefunction/getDocument.js';
|
||||
import getDrive from './parsefunction/getDrive.js';
|
||||
import getReport from './parsefunction/getReport.js';
|
||||
|
||||
Parse.Cloud.define('AddUserToRole', addUserToGroups);
|
||||
Parse.Cloud.define('UserGroups', getUserGroups);
|
||||
@@ -29,3 +33,7 @@ Parse.Cloud.define('SendOTPMailV1', sendMailOTPv1);
|
||||
Parse.Cloud.define('sendmail', SendMailv1);
|
||||
Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail);
|
||||
Parse.Cloud.define('getUserId', getUserId);
|
||||
Parse.Cloud.define('getUserDetails', getUserDetails);
|
||||
Parse.Cloud.define('getDocument', getDocument);
|
||||
Parse.Cloud.define('getDrive', getDrive)
|
||||
Parse.Cloud.define('getReport', getReport)
|
||||
@@ -16,6 +16,7 @@ async function ContactbookAftersave(request) {
|
||||
acl.setWriteAccess(object.get('UserId'), true);
|
||||
|
||||
object.setACL(acl);
|
||||
object.set('IsDeleted', false)
|
||||
// Continue saving the object
|
||||
return object.save(null, { useMasterKey: true });
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ async function SendMailv1(request) {
|
||||
const recipient = request.params.email;
|
||||
const otp = request.params.otp;
|
||||
const res = await Parse.Cloud.sendEmail({
|
||||
from: 'Test user' + ' <' + process.env.MAILGUN_SENDER + '>',
|
||||
from: 'Test user' + ' <' + process.env.SMTP_ENABLE ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER + '>',
|
||||
recipient: recipient,
|
||||
subject: 'Your OpenSign™ OTP',
|
||||
text: 'This email is a test.',
|
||||
|
||||
@@ -46,15 +46,20 @@ export default async function ZohoDetails(request) {
|
||||
(userData.data.data.subscription.customer &&
|
||||
userData.data.data.subscription.customer.company_name) ||
|
||||
'';
|
||||
const jobTitle =
|
||||
(userData.data.data.subscription.customer &&
|
||||
userData.data.data.subscription.customer.cd_job_title) ||
|
||||
'';
|
||||
const resData = {
|
||||
phone: userData.data.data.subscription.contactpersons[0].mobile,
|
||||
name: first_name + ' ' + last_name,
|
||||
email: userData.data.data.subscription.contactpersons[0].email,
|
||||
nextBillingDate: userData.data.expiring_time,
|
||||
nextBillingDate: userData.data.data.subscription.next_billing_at,
|
||||
company: company_name,
|
||||
plan: userData.data.data.subscription.plan,
|
||||
customer_id: userData.data.data.subscription.customer_id,
|
||||
subscription_id: userData.data.data.subscription.subscription_id,
|
||||
jobTitle: jobTitle,
|
||||
};
|
||||
return resData;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export default async function getDocument(request) {
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const docId = request.params.docId;
|
||||
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (docId && userId) {
|
||||
try {
|
||||
const query = new Parse.Query('contracts_Document');
|
||||
query.equalTo('objectId', docId);
|
||||
query.include('ExtUserPtr');
|
||||
query.include('CreatedBy');
|
||||
query.include('Signers');
|
||||
query.include('AuditTrail.UserPtr');
|
||||
query.include('Placeholders');
|
||||
const res = await query.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
const acl = res.getACL();
|
||||
if (acl && acl.getReadAccess(userId)) {
|
||||
return res;
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err', err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
return { error: 'Please pass required parameters!' };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err');
|
||||
if (err.code == 209) {
|
||||
return { error: 'Invalid session token' };
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import axios from 'axios';
|
||||
export default async function getDrive(request) {
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const appId = process.env.APP_ID;
|
||||
|
||||
const classUrl = serverUrl + '/classes/contracts_Document';
|
||||
const docId = request.params.docId;
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (userId) {
|
||||
let url;
|
||||
if (docId) {
|
||||
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers,Folder`;
|
||||
} else {
|
||||
url = `${classUrl}?where={"Folder":{"$exists":false},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers`;
|
||||
}
|
||||
try {
|
||||
const res = await axios.get(url, {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-key': process.env.MASTER_KEY,
|
||||
},
|
||||
});
|
||||
// console.log('res.data.results ', res.data.results);
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err', err);
|
||||
return { error: "You don't have access to drive" };
|
||||
}
|
||||
} else {
|
||||
return { error: 'Please provide required parameter!' };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err', err);
|
||||
if (err.code == 209) {
|
||||
return { error: 'Invalid session token' };
|
||||
} else {
|
||||
return { error: "You don't have access!" };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import reportJson from './reportsJson.js';
|
||||
import axios from 'axios';
|
||||
|
||||
export default async function getReport(request) {
|
||||
const reportId = request.params.reportId;
|
||||
const limit = request.params.limit;
|
||||
const skip = request.params.skip;
|
||||
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const appId = process.env.APP_ID;
|
||||
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (userId) {
|
||||
const json = reportId && reportJson(reportId, userId);
|
||||
const clsName = reportId === '5KhaPr482K' ? 'contracts_Contactbook' : 'contracts_Document';
|
||||
if (json) {
|
||||
const { params, keys } = json;
|
||||
const orderBy = '-updatedAt';
|
||||
const strParams = JSON.stringify(params);
|
||||
const strKeys = keys.join();
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||
};
|
||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return { error: 'Report is not available!' };
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err', err);
|
||||
if (err.code == 209) {
|
||||
return { error: 'Invalid session token' };
|
||||
} else {
|
||||
return { error: "You don't have access!" };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
async function getUserDetails(request) {
|
||||
try {
|
||||
const userQuery = new Parse.Query('contracts_Users');
|
||||
userQuery.equalTo('Email', request.params.email);
|
||||
userQuery.include('TenantId');
|
||||
userQuery.include('UserId')
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
return res;
|
||||
} catch (err) {
|
||||
console.log('Err ', err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
export default getUserDetails;
|
||||
+4
-4
@@ -79,7 +79,7 @@ async function sendCompletedMail(e) {
|
||||
url: a,
|
||||
from: 'OpenSign™',
|
||||
recipient: e.receiver,
|
||||
subject: `Document ${s} has beeen signed by all parties`,
|
||||
subject: `Document ${s} has been signed by all parties`,
|
||||
pdfName: s,
|
||||
html:
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document sign successfully</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document" +
|
||||
@@ -105,7 +105,7 @@ async function PDF(s, r) {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Session-Token': s.headers.sessiontoken,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
}),
|
||||
d = await axios.get(serverUrl + '/users/me', {
|
||||
@@ -132,7 +132,7 @@ async function PDF(s, r) {
|
||||
: ((a = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Session-Token': s.headers.sessiontoken,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
})),
|
||||
'contracts_Users')
|
||||
@@ -142,7 +142,7 @@ async function PDF(s, r) {
|
||||
(c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Session-Token': s.headers.sessiontoken,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
})).data && 0 < c.data.results.length
|
||||
? ((a = c), 'contracts_Users')
|
||||
|
||||
@@ -1 +1 @@
|
||||
const signer=require("node-signpdf").default;class SignPDF{constructor(e,t){this.pdfDoc=e,this.certificate=t}async signPDF(){return signer.sign(this.pdfDoc,this.certificate,{passphrase:"emudhra"})}static unit8ToBuffer(e){var t=Buffer.alloc(e.byteLength),r=new Uint8Array(e);for(let e=0;e<t.length;++e)t[e]=r[e];return t}}module.exports=SignPDF;
|
||||
const signer=require("node-signpdf").default;class SignPDF{constructor(e,t){this.pdfDoc=e,this.certificate=t}async signPDF(){return signer.sign(this.pdfDoc,this.certificate, process.env.PASS_PHRASE ? {passphrase : process.env.PASS_PHRASE}: null)}static unit8ToBuffer(e){var t=Buffer.alloc(e.byteLength),r=new Uint8Array(e);for(let e=0;e<t.length;++e)t[e]=r[e];return t}}module.exports=SignPDF;
|
||||
+22
-22
@@ -1,28 +1,28 @@
|
||||
import{DEFAULT_BYTE_RANGE_PLACEHOLDER,DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import PNG from"png-js";import zlib from"zlib";import fs from"node:fs";const specialCharacters=["á","Á","é","É","í","Í","ó","Ó","ö","Ö","ő","Ő","ú","Ú","ű","Ű"],MARKERS=[65472,65473,65474,65475,65477,65478,65479,65480,65481,65482,65483,65484,65485,65486,65487],COLOR_SPACE_MAP={1:"DeviceGray",3:"DeviceRGB",4:"DeviceCMYK"};function getImage(e,t){let n;if(255===e[0]&&216===e[1])n=getJpgImage(t,e);else{if(137!==e[0]||"PNG"!==e.toString("ascii",1,4))throw new Error("Unknown image format.");n=getPngImage(t,e)}return n}function getAnnotationApparance(e,t,n){return e.ref({CropBox:[0,0,197,70],Type:"XObject",FormType:1,BBox:[0,0,197,70],Resources:`<</XObject <<
|
||||
import{DEFAULT_BYTE_RANGE_PLACEHOLDER,DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import PNG from"png-js";import zlib from"zlib";const specialCharacters=["á","Á","é","É","í","Í","ó","Ó","ö","Ö","ő","Ő","ú","Ú","ű","Ű"],MARKERS=[65472,65473,65474,65475,65477,65478,65479,65480,65481,65482,65483,65484,65485,65486,65487],COLOR_SPACE_MAP={1:"DeviceGray",3:"DeviceRGB",4:"DeviceCMYK"};function getImage(e,t){let n;if(255===e[0]&&216===e[1])n=getJpgImage(t,e);else{if(137!==e[0]||"PNG"!==e.toString("ascii",1,4))throw new Error("Unknown image format.");n=getPngImage(t,e)}return n}function getAnnotationApparance(e,t,n){return e.ref({CropBox:[0,10,200,60],Type:"XObject",FormType:1,BBox:[0,10,200,60],Resources:`<</XObject <<
|
||||
/Img${t.index} ${t.index} 0 R
|
||||
>>
|
||||
/Font <<
|
||||
/f1 ${n.index} 0 R
|
||||
>>
|
||||
>>`,MediaBox:[0,0,197,70],Subtype:"Form"},null,getStream(t.index))}const getStream=e=>getConvertedText(`
|
||||
1.0 1.0 1.0 rg
|
||||
0.0 0.0 0.0 RG
|
||||
q
|
||||
q
|
||||
200 0 0 50 0 10 cm
|
||||
/Img${e} Do
|
||||
Q
|
||||
0 0 0 rg
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 45.97412 Tm
|
||||
ET
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 33.56006 Tm
|
||||
ET
|
||||
Q`),getFont=(e,t)=>e.ref({Type:"Font",BaseFont:t,Encoding:"WinAnsiEncoding",Subtype:"Type1"}),getJpgImage=(e,t)=>{if(65496!==t.readUInt16BE(0))throw"SOI not found in JPEG";let n=2,a;for(;n<t.length&&(a=t.readUInt16BE(n),n+=2,!MARKERS.includes(a));)n+=t.readUInt16BE(n);if(!MARKERS.includes(a))throw"Invalid JPEG.";n+=2;var r=t[n++],o=t.readUInt16BE(n),i=(n+=2,t.readUInt16BE(n)),l=(n+=2,t[n++]),l=COLOR_SPACE_MAP[l],r={Type:"XObject",Subtype:"Image",BitsPerComponent:r,Width:i,Height:o,ColorSpace:l,Filter:"DCTDecode"},i=("DeviceCMYK"===l&&(r.Decode=[1,0,1,0,1,0,1,0]),e.ref(r,null,t));return i},getPngImage=(e,t)=>{var t=new PNG(t),n=t.hasAlphaChannel,a={Type:"XObject",Subtype:"Image",BitsPerComponent:n?8:t.bits,Width:t.width,Height:t.height,Filter:"FlateDecode"};if(n||(r=e.ref({Predictor:15,Colors:t.colors,BitsPerComponent:t.bits,Columns:t.width}),a.DecodeParms=r),0===t.palette.length?a.ColorSpace=t.colorSpace:(r=e.ref({stream:new Buffer(t.palette)}),a.ColorSpace=["Indexed","DeviceRGB",t.palette.length/3-1,r]),null!=t.transparency.grayscale){var r=t.transparency.grayscale;a.Mask=[r,r]}else if(t.transparency.rgb){var o,r=t.transparency["rgb"],i=[];for(o of r)i.push(o,o);a.Mask=i}else t.transparency.indexed?loadIndexedAlphaChannel(t):n&&(splitAlphaChannel(t),r=getSmask(e,t),a.Mask=r);return e.ref(a,null,t.imgData)},loadIndexedAlphaChannel=e=>{const o=e.transparency.indexed;return e.decodePixels(n=>{var a=new Buffer(e.width*e.height);let r=0;for(let e=0,t=n.length;e<t;e++)a[r++]=o[n[e]];e.alphaChannel=zlib.deflateSync(a)})},splitAlphaChannel=d=>{d.decodePixels(t=>{let e,n;var a=d.colors,r=d.width*d.height,o=new Buffer(r*a),i=new Buffer(r);let l=n=e=0;for(var g=t.length,c=16===d.bits?1:0;l<g;){for(let e=0;e<a;e++)o[n++]=t[l++],l+=c;i[e++]=t[l++],l+=c}d.imgData=zlib.deflateSync(o),d.alphaChannel=zlib.deflateSync(i)})},getSmask=(e,t)=>{let n;return console.log("image.hasAlphaChannel ",t.hasAlphaChannel),t.hasAlphaChannel&&(console.log("image.alphaChannel ",t.alphaChannel),n=e.ref({Type:"XObject",Subtype:"Image",Height:t.height,Width:t.width,BitsPerComponent:8,Filter:"FlateDecode",ColorSpace:"DeviceGray",Decode:[0,1],stream:t.alphaChannel})),n},getConvertedText=e=>e.split("").map(e=>specialCharacters.includes(e)?getOctalCodeFromCharacter(e):e).join(""),getOctalCodeFromCharacter=e=>"\\"+e.charCodeAt(0).toString(8),pdfkitAddPlaceholder=({pdf:e,pdfBuffer:a,reason:r,contactInfo:t="emailfromp1289@gmail.com",name:n="Name from p12",location:o="Location from p12",signatureLength:i=DEFAULT_SIGNATURE_LENGTH,byteRangePlaceholder:l=DEFAULT_BYTE_RANGE_PLACEHOLDER,subFilter:g=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:c})=>{var d=getFont(e,"Helvetica"),s=getFont(e,"ZapfDingbats"),f=getFont(e,"Helvetica"),p=c.Base64,p=getAnnotationApparance(e,getImage(Buffer.from(p,"base64"),e),f),f=e.ref({Type:"Sig",Filter:"Adobe.PPKLite",SubFilter:g,ByteRange:[0,l,l,l],Contents:Buffer.from(String.fromCharCode(0).repeat(i)),Reason:new String(r),M:new Date,ContactInfo:new String(t),Name:new String(n),Location:new String(o)}),h=a.lastIndexOf("/Type /AcroForm"),g=-1!==h;let m=[],C;if(g){let e=h;var S=h-10;let t="",n=11;for(n;n<22;n+=1){var A=a.slice(h-n,S).toString();if("\n"===A[0])break;t=A,e=h-n}l=a.slice(e),i=l.slice(0,l.indexOf("endobj")).toString(),r=(C=parseInt(t),i.slice(i.indexOf("/Fields [")+9,i.indexOf("]")));m=r.split(" ").filter((e,t)=>t%3==0).map(e=>new PDFKitReferenceMock(e))}m.length;t=c.Left,n=c.Bottom,o=t+c.Width,l=n+c.Height,i=e.ref({Type:"Annot",Subtype:"Widget",FT:"Sig",Rect:[t,n,o,l],V:f,T:new String("Signature"+(m.length+1)),F:4,P:e.page.dictionary,AP:`<</N ${p.index} 0 R>>`,DA:new String("/Helvetica 0 Tf 0 g")});e.page.dictionary.data.Annots=[i];let T;return T=g?e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i],DR:`<</Font
|
||||
>>`,MediaBox:[0,10,200,60],Subtype:"Form"},null,getStream(t.index))}const getStream=e=>getConvertedText(`
|
||||
1.0 1.0 1.0 rg
|
||||
0.0 0.0 0.0 RG
|
||||
q
|
||||
q
|
||||
200 0 0 50 0 10 cm
|
||||
/Img${e} Do
|
||||
Q
|
||||
0 0 0 rg
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 45.97412 Tm
|
||||
ET
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 33.56006 Tm
|
||||
ET
|
||||
Q`),getFont=(e,t)=>e.ref({Type:"Font",BaseFont:t,Encoding:"WinAnsiEncoding",Subtype:"Type1"}),getJpgImage=(e,t)=>{if(65496!==t.readUInt16BE(0))throw"SOI not found in JPEG";let n=2,a;for(;n<t.length&&(a=t.readUInt16BE(n),n+=2,!MARKERS.includes(a));)n+=t.readUInt16BE(n);if(!MARKERS.includes(a))throw"Invalid JPEG.";n+=2;var r=t[n++],o=t.readUInt16BE(n),i=(n+=2,t.readUInt16BE(n)),l=(n+=2,t[n++]),l=COLOR_SPACE_MAP[l],r={Type:"XObject",Subtype:"Image",BitsPerComponent:r,Width:i,Height:o,ColorSpace:l,Filter:"DCTDecode"},i=("DeviceCMYK"===l&&(r.Decode=[1,0,1,0,1,0,1,0]),e.ref(r,null,t));return i},getPngImage=(e,t)=>{var t=new PNG(t),n=t.hasAlphaChannel,a={Type:"XObject",Subtype:"Image",BitsPerComponent:n?8:t.bits,Width:t.width,Height:t.height,Filter:"FlateDecode"};if(n||(r=e.ref({Predictor:15,Colors:t.colors,BitsPerComponent:t.bits,Columns:t.width}),a.DecodeParms=r),0===t.palette.length?a.ColorSpace=t.colorSpace:(r=e.ref({stream:new Buffer(t.palette)}),a.ColorSpace=["Indexed","DeviceRGB",t.palette.length/3-1,r]),null!=t.transparency.grayscale){var r=t.transparency.grayscale;a.Mask=[r,r]}else if(t.transparency.rgb){var o,r=t.transparency["rgb"],i=[];for(o of r)i.push(o,o);a.Mask=i}else t.transparency.indexed?loadIndexedAlphaChannel(t):n&&(splitAlphaChannel(t),r=getSmask(e,t),a.Mask=r);return e.ref(a,null,t.imgData)},loadIndexedAlphaChannel=e=>{const o=e.transparency.indexed;return e.decodePixels(n=>{var a=new Buffer(e.width*e.height);let r=0;for(let e=0,t=n.length;e<t;e++)a[r++]=o[n[e]];e.alphaChannel=zlib.deflateSync(a)})},splitAlphaChannel=d=>{d.decodePixels(t=>{let e,n;var a=d.colors,r=d.width*d.height,o=new Buffer(r*a),i=new Buffer(r);let l=n=e=0;for(var c=t.length,g=16===d.bits?1:0;l<c;){for(let e=0;e<a;e++)o[n++]=t[l++],l+=g;i[e++]=t[l++],l+=g}d.imgData=zlib.deflateSync(o),d.alphaChannel=zlib.deflateSync(i)})},getSmask=(e,t)=>{let n;return console.log("image.hasAlphaChannel ",t.hasAlphaChannel),t.hasAlphaChannel&&(console.log("image.alphaChannel ",t.alphaChannel),n=e.ref({Type:"XObject",Subtype:"Image",Height:t.height,Width:t.width,BitsPerComponent:8,Filter:"FlateDecode",ColorSpace:"DeviceGray",Decode:[0,1],stream:t.alphaChannel})),n},getConvertedText=e=>e.split("").map(e=>specialCharacters.includes(e)?getOctalCodeFromCharacter(e):e).join(""),getOctalCodeFromCharacter=e=>"\\"+e.charCodeAt(0).toString(8),pdfkitAddPlaceholder=({pdf:e,pdfBuffer:a,reason:r,contactInfo:t="emailfromp1289@gmail.com",name:n="Name from p12",location:o="Location from p12",signatureLength:i=DEFAULT_SIGNATURE_LENGTH,byteRangePlaceholder:l=DEFAULT_BYTE_RANGE_PLACEHOLDER,subFilter:c=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:g})=>{var d=getFont(e,"Helvetica"),s=getFont(e,"ZapfDingbats"),p=getFont(e,"Helvetica"),f=g.Base64,f=getAnnotationApparance(e,getImage(Buffer.from(f,"base64"),e),p,g),p=e.ref({Type:"Sig",Filter:"Adobe.PPKLite",SubFilter:c,ByteRange:[0,l,l,l],Contents:Buffer.from(String.fromCharCode(0).repeat(i)),Reason:new String(r),M:new Date,ContactInfo:new String(t),Name:new String(n),Location:new String(o)}),h=a.lastIndexOf("/Type /AcroForm"),c=-1!==h;let m=[],C;if(c){let e=h;var S=h-10;let t="",n=11;for(n;n<22;n+=1){var A=a.slice(h-n,S).toString();if("\n"===A[0])break;t=A,e=h-n}l=a.slice(e),i=l.slice(0,l.indexOf("endobj")).toString(),r=(C=parseInt(t),i.slice(i.indexOf("/Fields [")+9,i.indexOf("]")));m=r.split(" ").filter((e,t)=>t%3==0).map(e=>new PDFKitReferenceMock(e))}t=g.Left,n=g.Bottom,o=t+g.Width,l=n+g.Height,i=e.ref({Type:"Annot",Subtype:"Widget",FT:"Sig",Rect:[t,n,o,l],V:p,T:new String("Signature"+(m.length+1)),F:4,P:e.page.dictionary,AP:`<</N ${f.index} 0 R>>`,DA:new String("/Helvetica 0 Tf 0 g")});e.page.dictionary.data.Annots=[i];let T;return T=c?e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i],DR:`<</Font
|
||||
<</Helvetica ${d.index} 0 R/ZapfDingbats ${s.index} 0 R>>
|
||||
>>`},C):e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i]}),{signature:f,form:e._root.data.AcroForm=T,widget:i}};export default pdfkitAddPlaceholder;
|
||||
>>`},C):e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i]}),{signature:p,form:e._root.data.AcroForm=T,widget:i}};export default pdfkitAddPlaceholder;
|
||||
@@ -0,0 +1,218 @@
|
||||
export default function reportJson(id, userId) {
|
||||
const currentUserId = userId;
|
||||
|
||||
switch (id) {
|
||||
// draft documents report
|
||||
case 'ByHuevtCFY':
|
||||
return {
|
||||
reportName: 'Draft Documents',
|
||||
params: {
|
||||
Type: null,
|
||||
$or: [
|
||||
{ Signers: null, SignedUrl: null },
|
||||
{ Signers: { $exists: true }, Placeholders: null },
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// Need your sign report
|
||||
case '4Hhwbp482K':
|
||||
return {
|
||||
reportName: 'Need your sign',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
ExpiryDate: {
|
||||
$gt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
Placeholders: { $ne: null },
|
||||
},
|
||||
keys: [
|
||||
'Name',
|
||||
'Note',
|
||||
'Folder.Name',
|
||||
'URL',
|
||||
'ExtUserPtr.Name',
|
||||
'Signers.Name',
|
||||
'Signers.UserId',
|
||||
'AuditTrail',
|
||||
],
|
||||
};
|
||||
// In progess report
|
||||
case '1MwEuxLEkF':
|
||||
return {
|
||||
reportName: 'In-progress documents',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
Signers: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
ExpiryDate: {
|
||||
$gt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// completed documents report
|
||||
case 'kQUoW4hUXz':
|
||||
return {
|
||||
reportName: 'Completed Documents',
|
||||
params: {
|
||||
Type: null,
|
||||
IsCompleted: true,
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
IsDeclined: { $ne: true },
|
||||
},
|
||||
keys: [
|
||||
'Name',
|
||||
'Note',
|
||||
'Folder.Name',
|
||||
'URL',
|
||||
'ExtUserPtr.Name',
|
||||
'Signers.Name',
|
||||
'TimeToCompleteDays',
|
||||
],
|
||||
};
|
||||
|
||||
// declined documents report
|
||||
case 'UPr2Fm5WY3':
|
||||
return {
|
||||
reportName: 'Declined Documents',
|
||||
params: {
|
||||
Type: null,
|
||||
IsDeclined: true,
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
},
|
||||
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// Expired Documents report
|
||||
case 'zNqBHXHsYH':
|
||||
return {
|
||||
reportName: 'Expired Documents',
|
||||
params: {
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
Type: { $ne: 'Folder' },
|
||||
$and: [
|
||||
{
|
||||
$or: [
|
||||
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
|
||||
{ Placeholders: { $ne: null } },
|
||||
],
|
||||
},
|
||||
{
|
||||
ExpiryDate: {
|
||||
$lt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
},
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// Recently sent for signatures report show on dashboard
|
||||
case 'd9k3UfYHBc':
|
||||
return {
|
||||
reportName: 'Recently sent for signatures',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
Signers: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
ExpiryDate: {
|
||||
$gt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// Recent signature requests report show on dashboard
|
||||
case '5Go51Q7T8r':
|
||||
return {
|
||||
reportName: 'Recent signature requests',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
ExpiryDate: {
|
||||
$gt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
Placeholders: { $ne: null },
|
||||
},
|
||||
keys: [
|
||||
'Name',
|
||||
'Note',
|
||||
'Folder.Name',
|
||||
'URL',
|
||||
'ExtUserPtr.Name',
|
||||
'Signers.Name',
|
||||
'Signers.UserId',
|
||||
'AuditTrail',
|
||||
],
|
||||
};
|
||||
// Drafts report show on dashboard
|
||||
case 'kC5mfynCi4':
|
||||
return {
|
||||
reportName: 'Drafts',
|
||||
params: {
|
||||
Type: null,
|
||||
$or: [
|
||||
{ Signers: null, SignedUrl: null },
|
||||
{ Signers: { $exists: true }, Placeholders: null },
|
||||
],
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// contact book report
|
||||
case '5KhaPr482K':
|
||||
return {
|
||||
reportName: 'Contactbook',
|
||||
params: {
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
IsDeleted: { $ne: true },
|
||||
},
|
||||
keys: ['Name', 'Email', 'Phone'],
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,30 @@
|
||||
import fs from 'node:fs';
|
||||
import https from 'https';
|
||||
import formData from 'form-data';
|
||||
import Mailgun from 'mailgun.js';
|
||||
import https from 'https';
|
||||
import { createTransport } from 'nodemailer';
|
||||
|
||||
const mailgun = new Mailgun(formData);
|
||||
const mailgunClient = mailgun.client({
|
||||
username: 'api',
|
||||
key: process.env.MAILGUN_API_KEY,
|
||||
});
|
||||
const mailgunDomain = process.env.MAILGUN_DOMAIN;
|
||||
let transporterSMTP;
|
||||
let mailgunClient;
|
||||
let mailgunDomain;
|
||||
if (process.env.SMTP_ENABLE) {
|
||||
transporterSMTP = createTransport({
|
||||
host: process.env.SMTP_HOST,
|
||||
port: process.env.SMTP_PORT || 465,
|
||||
secure: process.env.SMTP_SECURE || true,
|
||||
auth: {
|
||||
user: process.env.SMTP_USER_EMAIL,
|
||||
pass: process.env.SMTP_PASS,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const mailgun = new Mailgun(formData);
|
||||
mailgunClient = mailgun.client({
|
||||
username: 'api',
|
||||
key: process.env.MAILGUN_API_KEY,
|
||||
});
|
||||
mailgunDomain = process.env.MAILGUN_DOMAIN;
|
||||
}
|
||||
|
||||
async function sendmail(req) {
|
||||
try {
|
||||
@@ -38,22 +54,67 @@ async function sendmail(req) {
|
||||
const pdfName = req.params.pdfName && `${req.params.pdfName}.pdf`;
|
||||
const file = {
|
||||
filename: pdfName || 'exported.pdf',
|
||||
data: PdfBuffer, //fs.readFileSync('./exports/exported_file_1223.pdf'),
|
||||
content: process.env.SMTP_ENABLE ? PdfBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
|
||||
data: process.env.SMTP_ENABLE ? undefined : PdfBuffer,
|
||||
};
|
||||
|
||||
// const html = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body style='text-align: center;'> <p style='font-weight: bolder; font-size: large;'>Hello!</p> <p>This is a html checking mail</p><p><button style='background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue'>Verify email</button></p></body></html>"
|
||||
|
||||
const from = req.params.from || '';
|
||||
const mailsender = process.env.SMTP_ENABLE
|
||||
? process.env.SMTP_USER_EMAIL
|
||||
: process.env.MAILGUN_SENDER;
|
||||
|
||||
const messageParams = {
|
||||
from: from + ' <' + process.env.MAILGUN_SENDER + '>',
|
||||
from: from + ' <' + mailsender + '>',
|
||||
to: req.params.recipient,
|
||||
subject: req.params.subject,
|
||||
text: req.params.text || 'mail',
|
||||
html: req.params.html || '',
|
||||
attachment: file,
|
||||
attachments: process.env.SMTP_ENABLE ? [file] : undefined,
|
||||
attachment: process.env.SMTP_ENABLE ? undefined : file,
|
||||
};
|
||||
if (transporterSMTP) {
|
||||
const res = await transporterSMTP.sendMail(messageParams);
|
||||
console.log('Res ', res);
|
||||
if (!res.err) {
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
||||
console.log('Res ', res);
|
||||
if (res.status === 200) {
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const from = req.params.from || '';
|
||||
const mailsender = process.env.SMTP_ENABLE
|
||||
? process.env.SMTP_USER_EMAIL
|
||||
: process.env.MAILGUN_SENDER;
|
||||
|
||||
const messageParams = {
|
||||
from: from + ' <' + mailsender + '>',
|
||||
to: req.params.recipient,
|
||||
subject: req.params.subject,
|
||||
text: req.params.text || 'mail',
|
||||
html: req.params.html || '',
|
||||
};
|
||||
|
||||
if (transporterSMTP) {
|
||||
const res = await transporterSMTP.sendMail(messageParams);
|
||||
console.log('Res ', res);
|
||||
if (!res.err) {
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
||||
console.log('Res ', res);
|
||||
if (res.status === 200) {
|
||||
@@ -62,23 +123,6 @@ async function sendmail(req) {
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const from = req.params.from || '';
|
||||
const messageParams = {
|
||||
from: from + ' <' + process.env.MAILGUN_SENDER + '>',
|
||||
to: req.params.recipient,
|
||||
subject: req.params.subject,
|
||||
text: req.params.text || 'mail',
|
||||
html: req.params.html || '',
|
||||
};
|
||||
|
||||
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
||||
console.log('Res ', res);
|
||||
if (res.status === 200) {
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err ', err);
|
||||
|
||||
@@ -123,6 +123,9 @@ export default async function (request) {
|
||||
if (userDetails && userDetails.company) {
|
||||
newObj.set("Company", userDetails.company);
|
||||
}
|
||||
if (userDetails && userDetails.jobTitle) {
|
||||
newObj.set("JobTitle", userDetails.jobTitle);
|
||||
}
|
||||
if (planDetails && planDetails.customer_id) {
|
||||
newObj.set("Next_billing_date", new Date(planDetails.nextBillingDate));
|
||||
newObj.set("Plan", planDetails.plan);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.up = async Parse => {
|
||||
// TODO: set className here
|
||||
const className = 'contracts_Users';
|
||||
const schema = new Parse.Schema(className);
|
||||
// schema.addString('Name');
|
||||
// schema.addString('Phone');
|
||||
// schema.addString('JobTitle');
|
||||
// schema.addString('Email');
|
||||
// schema.addString('Company');
|
||||
// schema.addString('UserRole');
|
||||
// schema.addObject('Plan');
|
||||
// schema.addString('Customer_id');
|
||||
// schema.addString('Subscription_id');
|
||||
// schema.addString('Next_billing_date');
|
||||
// schema.addBoolean('IsContactEntry');
|
||||
// schema.addBoolean('ShareWithTeam');
|
||||
// schema.addPointer('TenantId', 'partners_Tenant');
|
||||
// schema.addPointer('UserId', '_User');
|
||||
// schema.addPointer('CreatedBy', '_User');
|
||||
schema.setCLP({
|
||||
get: {},
|
||||
find: {},
|
||||
count: {},
|
||||
create: { '*': true },
|
||||
update: { '*': true },
|
||||
delete: {},
|
||||
addField: {},
|
||||
});
|
||||
|
||||
return schema.update();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.down = async Parse => {
|
||||
// TODO: set className here
|
||||
const className = 'contracts_Users';
|
||||
const schema = new Parse.Schema(className);
|
||||
|
||||
return schema.purge().then(() => schema.delete());
|
||||
};
|
||||
@@ -0,0 +1,556 @@
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.up = async Parse => {
|
||||
const className = 'w_menu';
|
||||
const userMenu = new Parse.Query(className);
|
||||
const updateUserMenu = await userMenu.get('H9vRfEYKhT');
|
||||
updateUserMenu.set('menuItems', [
|
||||
{
|
||||
icon: 'fas fa-tachometer-alt',
|
||||
title: 'Dashboard',
|
||||
target: '',
|
||||
pageType: 'dashboard',
|
||||
description: '',
|
||||
objectId: '35KBoSgoAK',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-newspaper',
|
||||
title: 'New Document',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: null,
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-nib',
|
||||
title: 'Sign yourself',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'sHAnZphf69',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-address-card',
|
||||
title: 'Reports',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-signature',
|
||||
title: 'Need your sign',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '4Hhwbp482K',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-tasks',
|
||||
title: 'In Progress',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '1MwEuxLEkF',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-check-circle',
|
||||
title: 'Completed',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'kQUoW4hUXz',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-edit',
|
||||
title: 'Drafts',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'ByHuevtCFY',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-times-circle',
|
||||
title: 'Declined',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'UPr2Fm5WY3',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-hourglass-end',
|
||||
title: 'Expired',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'zNqBHXHsYH',
|
||||
},
|
||||
{
|
||||
icon: 'fa-solid fa-address-book',
|
||||
title: 'Contactbook',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '5KhaPr482K',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const AdminMenu = new Parse.Query(className);
|
||||
const updateAdminMenu = await AdminMenu.get('VPh91h0ZHk');
|
||||
updateAdminMenu.set('menuItems', [
|
||||
{
|
||||
icon: 'fas fa-tachometer-alt',
|
||||
title: 'Dashboard',
|
||||
target: '',
|
||||
pageType: 'dashboard',
|
||||
description: '',
|
||||
objectId: '35KBoSgoAK',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-newspaper',
|
||||
title: 'New Document',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: null,
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-nib',
|
||||
title: 'Sign yourself',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'sHAnZphf69',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-address-card',
|
||||
title: 'Reports',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-signature',
|
||||
title: 'Need your sign',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '4Hhwbp482K',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-tasks',
|
||||
title: 'In Progress',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '1MwEuxLEkF',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-check-circle',
|
||||
title: 'Completed',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'kQUoW4hUXz',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-edit',
|
||||
title: 'Drafts',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'ByHuevtCFY',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-times-circle',
|
||||
title: 'Declined',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'UPr2Fm5WY3',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-hourglass-end',
|
||||
title: 'Expired',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'zNqBHXHsYH',
|
||||
},
|
||||
{
|
||||
icon: 'fa-solid fa-address-book',
|
||||
title: 'Contactbook',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '5KhaPr482K',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-user',
|
||||
title: 'Add User',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'lM0xRnM3iE',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
// TODO: Set the schema here
|
||||
// Example:
|
||||
// schema.addString('name').addNumber('cash');
|
||||
const batch = [updateUserMenu, updateAdminMenu];
|
||||
return Parse.Object.saveAll(batch, { useMasterKey: true });
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.down = async Parse => {
|
||||
// TODO: set className here
|
||||
const className = 'w_menu';
|
||||
const userMenu = new Parse.Query(className);
|
||||
const revertUserMenu = await userMenu.get('H9vRfEYKhT');
|
||||
revertUserMenu.set('menuItems', [
|
||||
{
|
||||
icon: 'fas fa-tachometer-alt',
|
||||
title: 'Dashboard',
|
||||
target: '',
|
||||
pageType: 'dashboard',
|
||||
description: '',
|
||||
objectId: '35KBoSgoAK',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-newspaper',
|
||||
title: 'New Document',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: null,
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-nib',
|
||||
title: 'Sign yourself',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'sHAnZphf69',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-address-card',
|
||||
title: 'Reports',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-signature',
|
||||
title: 'Need your sign',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '4Hhwbp482K',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-tasks',
|
||||
title: 'In Progress',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '1MwEuxLEkF',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-check-circle',
|
||||
title: 'Completed',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'kQUoW4hUXz',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-edit',
|
||||
title: 'Drafts',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'ByHuevtCFY',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-times-circle',
|
||||
title: 'Declined',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'UPr2Fm5WY3',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-hourglass-end',
|
||||
title: 'Expired',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'zNqBHXHsYH',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const adminMenu = new Parse.Query(className);
|
||||
const revertAdminMenu = await adminMenu.get('VPh91h0ZHk');
|
||||
revertAdminMenu.set('menuItems', [
|
||||
{
|
||||
icon: 'fas fa-tachometer-alt',
|
||||
title: 'Dashboard',
|
||||
target: '',
|
||||
pageType: 'dashboard',
|
||||
description: '',
|
||||
objectId: '35KBoSgoAK',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-newspaper',
|
||||
title: 'New Document',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: null,
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-nib',
|
||||
title: 'Sign yourself',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'sHAnZphf69',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-address-card',
|
||||
title: 'Reports',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-signature',
|
||||
title: 'Need your sign',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '4Hhwbp482K',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-tasks',
|
||||
title: 'In Progress',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: '1MwEuxLEkF',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-check-circle',
|
||||
title: 'Completed',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'kQUoW4hUXz',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-edit',
|
||||
title: 'Drafts',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'ByHuevtCFY',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-times-circle',
|
||||
title: 'Declined',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'UPr2Fm5WY3',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-hourglass-end',
|
||||
title: 'Expired',
|
||||
target: '_self',
|
||||
pageType: 'report',
|
||||
description: '',
|
||||
objectId: 'zNqBHXHsYH',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-user',
|
||||
title: 'Add User',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'lM0xRnM3iE',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
// TODO: Set the schema here
|
||||
// Example:
|
||||
// schema.addString('name').addNumber('cash');
|
||||
const batch = [revertUserMenu, revertAdminMenu];
|
||||
return Parse.Object.saveAll(batch, { useMasterKey: true });
|
||||
};
|
||||
@@ -10,7 +10,7 @@
|
||||
<br />
|
||||
<p><a href="{{{link}}}" style="background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue">Verify email</a></p>
|
||||
<br />
|
||||
<p>ExampleApp</p>
|
||||
<p><a href="https://www.opensignlabs.com">OpenSign™</a></p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -14,32 +14,55 @@ import formData from 'form-data';
|
||||
import Mailgun from 'mailgun.js';
|
||||
import { ApiPayloadConverter } from 'parse-server-api-mail-adapter';
|
||||
import S3Adapter from 'parse-server-s3-adapter';
|
||||
import FSFilesAdapter from 'parse-server-fs-adapter';
|
||||
import AWS from 'aws-sdk';
|
||||
import { app as customRoute } from './cloud/customRoute/customApp.js';
|
||||
import { exec } from 'child_process';
|
||||
import { createTransport } from 'nodemailer';
|
||||
|
||||
const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT);
|
||||
// console.log("configuration ", configuration);
|
||||
const s3Options = {
|
||||
bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket,
|
||||
baseUrl: process.env.DO_BASEURL,
|
||||
region: process.env.DO_REGION,
|
||||
directAccess: true,
|
||||
preserveFileName: true,
|
||||
s3overrides: {
|
||||
accessKeyId: process.env.DO_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
|
||||
endpoint: spacesEndpoint,
|
||||
},
|
||||
};
|
||||
if (process.env.USE_LOCAL !== 'TRUE') {
|
||||
const s3Options = {
|
||||
bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket,
|
||||
baseUrl: process.env.DO_BASEURL,
|
||||
region: process.env.DO_REGION,
|
||||
directAccess: true,
|
||||
preserveFileName: true,
|
||||
s3overrides: {
|
||||
accessKeyId: process.env.DO_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
|
||||
endpoint: spacesEndpoint,
|
||||
},
|
||||
};
|
||||
var fsAdapter = new S3Adapter(s3Options);
|
||||
} else {
|
||||
var fsAdapter = new FSFilesAdapter({
|
||||
filesSubDirectory: 'files', // optional, defaults to ./files
|
||||
});
|
||||
}
|
||||
|
||||
let transporterMail;
|
||||
let mailgunClient;
|
||||
let mailgunDomain;
|
||||
if (process.env.MAILGUN_API_KEY) {
|
||||
|
||||
if (process.env.SMTP_ENABLE) {
|
||||
transporterMail = createTransport({
|
||||
host: process.env.SMTP_HOST,
|
||||
port: process.env.SMTP_PORT || 465,
|
||||
secure: process.env.SMTP_SECURE || true,
|
||||
auth: {
|
||||
user: process.env.SMTP_USER_EMAIL,
|
||||
pass: process.env.SMTP_PASS,
|
||||
},
|
||||
});
|
||||
} else if (process.env.MAILGUN_API_KEY) {
|
||||
const mailgun = new Mailgun(formData);
|
||||
mailgunClient = mailgun.client({
|
||||
username: 'api',
|
||||
key: process.env.MAILGUN_API_KEY,
|
||||
});
|
||||
|
||||
mailgunDomain = process.env.MAILGUN_DOMAIN;
|
||||
}
|
||||
|
||||
@@ -51,41 +74,47 @@ export const config = {
|
||||
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
|
||||
masterKeyIps: ['0.0.0.0/0', '::1'], // '::1'
|
||||
serverURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Don't forget to change to https if needed
|
||||
// verifyUserEmails: true,
|
||||
verifyUserEmails: true,
|
||||
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
|
||||
// Your apps name. This will appear in the subject and body of the emails that are sent.
|
||||
appName: 'Open Sign',
|
||||
emailAdapter: process.env.MAILGUN_API_KEY
|
||||
? {
|
||||
module: 'parse-server-api-mail-adapter',
|
||||
options: {
|
||||
// The email address from which emails are sent.
|
||||
sender: process.env.MAILGUN_SENDER,
|
||||
// The email templates.
|
||||
templates: {
|
||||
// The template used by Parse Server to send an email for password
|
||||
// reset; this is a reserved template name.
|
||||
passwordResetEmail: {
|
||||
subjectPath: './files/password_reset_email_subject.txt',
|
||||
textPath: './files/password_reset_email.txt',
|
||||
htmlPath: './files/password_reset_email.html',
|
||||
allowClientClassCreation: false,
|
||||
emailAdapter:
|
||||
process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY
|
||||
? {
|
||||
module: 'parse-server-api-mail-adapter',
|
||||
options: {
|
||||
// The email address from which emails are sent.
|
||||
sender: process.env.SMTP_ENABLE
|
||||
? process.env.SMTP_USER_EMAIL
|
||||
: process.env.MAILGUN_SENDER,
|
||||
// The email templates.
|
||||
templates: {
|
||||
// The template used by Parse Server to send an email for password
|
||||
// reset; this is a reserved template name.
|
||||
passwordResetEmail: {
|
||||
subjectPath: './files/password_reset_email_subject.txt',
|
||||
textPath: './files/password_reset_email.txt',
|
||||
htmlPath: './files/password_reset_email.html',
|
||||
},
|
||||
// The template used by Parse Server to send an email for email
|
||||
// address verification; this is a reserved template name.
|
||||
verificationEmail: {
|
||||
subjectPath: './files/verification_email_subject.txt',
|
||||
textPath: './files/verification_email.txt',
|
||||
htmlPath: './files/verification_email.html',
|
||||
},
|
||||
},
|
||||
// The template used by Parse Server to send an email for email
|
||||
// address verification; this is a reserved template name.
|
||||
verificationEmail: {
|
||||
subjectPath: './files/verification_email_subject.txt',
|
||||
textPath: './files/verification_email.txt',
|
||||
htmlPath: './files/verification_email.html',
|
||||
apiCallback: async ({ payload, locale }) => {
|
||||
if (mailgunClient) {
|
||||
const mailgunPayload = ApiPayloadConverter.mailgun(payload);
|
||||
await mailgunClient.messages.create(mailgunDomain, mailgunPayload);
|
||||
} else if (transporterMail) await transporterMail.sendMail(payload);
|
||||
},
|
||||
},
|
||||
apiCallback: async ({ payload, locale }) => {
|
||||
const mailgunPayload = ApiPayloadConverter.mailgun(payload);
|
||||
await mailgunClient.messages.create(mailgunDomain, mailgunPayload);
|
||||
},
|
||||
},
|
||||
}
|
||||
: null,
|
||||
filesAdapter: new S3Adapter(s3Options),
|
||||
}
|
||||
: null,
|
||||
filesAdapter: fsAdapter,
|
||||
auth: {
|
||||
google: {
|
||||
enabled: true,
|
||||
@@ -141,12 +170,6 @@ app.get('/', function (req, res) {
|
||||
res.status(200).send('open-sign-server is running !!!');
|
||||
});
|
||||
|
||||
// There will be a test page available on the /test path of your server url
|
||||
// Remove this before launching your app
|
||||
app.get('/test', function (req, res) {
|
||||
res.sendFile(path.join(__dirname, '/public/test.html'));
|
||||
});
|
||||
|
||||
if (!process.env.TESTING) {
|
||||
const port = process.env.PORT || 8080;
|
||||
const httpServer = http.createServer(app);
|
||||
@@ -155,6 +178,20 @@ if (!process.env.TESTING) {
|
||||
httpServer.headersTimeout = 100000; // in milliseconds
|
||||
httpServer.listen(port, function () {
|
||||
console.log('parse-server-example running on port ' + port + '.');
|
||||
const migrate = `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=http://localhost:8080/app MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
|
||||
|
||||
exec(migrate, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(`Error: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
console.log(`Command output: ${stdout}`);
|
||||
});
|
||||
});
|
||||
// This will enable the Live Query real-time server
|
||||
await ParseServer.createLiveQueryServer(httpServer);
|
||||
|
||||
Generated
+684
-248
File diff suppressed because it is too large
Load Diff
@@ -27,16 +27,19 @@
|
||||
"express-sse": "^0.5.3",
|
||||
"form-data": "^4.0.0",
|
||||
"jsonschema": "^1.4.1",
|
||||
"mailgun.js": "^9.0.1",
|
||||
"mailgun.js": "^9.3.0",
|
||||
"mongoose": "^7.2.1",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"multer-s3": "^2.10.0",
|
||||
"node-forge": "^1.3.1",
|
||||
"node-signpdf": "^1.5.1",
|
||||
"nodemailer": "^6.9.7",
|
||||
"openai": "^4.8.0",
|
||||
"parse": "4.0.1",
|
||||
"parse-server": "6.0.0",
|
||||
"parse": "4.1.0",
|
||||
"parse-dbtool": "^1.2.0",
|
||||
"parse-server": "6.3.1",
|
||||
"parse-server-api-mail-adapter": "^3.0.0",
|
||||
"parse-server-fs-adapter": "1.0.1",
|
||||
"parse-server-s3-adapter": "^1.2.0",
|
||||
"pdf-lib": "^1.16.0",
|
||||
"pdfkit": "^0.13.0",
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// const { exec } = require('child_process');
|
||||
import { exec } from 'child_process';
|
||||
|
||||
const migrate =
|
||||
'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool migrate';
|
||||
// `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=${process.env.SERVER_URL} MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
|
||||
|
||||
exec(migrate, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(`Error: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Command output: ${stdout}`);
|
||||
});
|
||||
|
||||
// const seeder =
|
||||
// 'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool seed';
|
||||
|
||||
// exec(seeder, (error, stdout, stderr) => {
|
||||
// if (error) {
|
||||
// console.error(`Error: ${error.message}`);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (stderr) {
|
||||
// console.error(`Error: ${stderr}`);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// console.log(`Command output: ${stdout}`);
|
||||
// });
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
awslocal s3api \
|
||||
create-bucket --bucket my-bucket \
|
||||
--create-bucket-configuration LocationConstraint=eu-central-1 \
|
||||
--region eu-central-1
|
||||
@@ -0,0 +1,11 @@
|
||||
# Use the official MongoDB imagee
|
||||
FROM mongo:latest
|
||||
|
||||
# Create a directory to host initialization scripts
|
||||
RUN mkdir -p /docker-entrypoint-initdb.d
|
||||
|
||||
# Copy default data JSON files to the initialization directory
|
||||
COPY ./default-data/*.json /docker-entrypoint-initdb.d/
|
||||
|
||||
# Execute the initialization script during container startup
|
||||
CMD ["mongod"]
|
||||
@@ -0,0 +1,70 @@
|
||||
[{
|
||||
"_id": "lpm8ijrwod",
|
||||
"name": "contracts_Admin",
|
||||
"_wperm": [
|
||||
"*"
|
||||
],
|
||||
"_rperm": [
|
||||
"*"
|
||||
],
|
||||
"_acl": {
|
||||
"*": {
|
||||
"r": true,
|
||||
"w": true
|
||||
}
|
||||
},
|
||||
"_created_at": {
|
||||
"$date": "2023-09-19T09:25:20.205Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-09-28T09:47:03.968Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "Bz90QJSYMw",
|
||||
"name": "contracts_Guest",
|
||||
"_wperm": [
|
||||
"ZhOmhqvw7S"
|
||||
],
|
||||
"_rperm": [
|
||||
"*",
|
||||
"ZhOmhqvw7S"
|
||||
],
|
||||
"_acl": {
|
||||
"ZhOmhqvw7S": {
|
||||
"w": true,
|
||||
"r": true
|
||||
},
|
||||
"*": {
|
||||
"r": true
|
||||
}
|
||||
},
|
||||
"_created_at": {
|
||||
"$date": "2023-10-20T07:56:10.094Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-10-20T10:50:36.229Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "Tb14x04JK2",
|
||||
"name": "contracts_User",
|
||||
"_wperm": [
|
||||
"*"
|
||||
],
|
||||
"_rperm": [
|
||||
"*"
|
||||
],
|
||||
"_acl": {
|
||||
"*": {
|
||||
"r": true,
|
||||
"w": true
|
||||
}
|
||||
},
|
||||
"_created_at": {
|
||||
"$date": "2023-09-19T09:25:20.205Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-10-20T06:54:09.836Z"
|
||||
}
|
||||
}]
|
||||
@@ -0,0 +1,657 @@
|
||||
[{
|
||||
"_id": "_Role",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"name": "string",
|
||||
"users": "relation<_User>",
|
||||
"roles": "relation<_Role>",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"name_1": {
|
||||
"name": 1
|
||||
},
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {},
|
||||
"protectedFields": {
|
||||
"*": []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "_Session",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"user": "*_User",
|
||||
"installationId": "string",
|
||||
"sessionToken": "string",
|
||||
"expiresAt": "date",
|
||||
"createdWith": "object",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "_User",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"username": "string",
|
||||
"email": "string",
|
||||
"emailVerified": "boolean",
|
||||
"authData": "object",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"phone_1": {
|
||||
"phone": 1
|
||||
},
|
||||
"username_1": {
|
||||
"username": 1
|
||||
},
|
||||
"case_insensitive_username": {
|
||||
"username": 1
|
||||
},
|
||||
"email_1": {
|
||||
"email": 1
|
||||
},
|
||||
"case_insensitive_email": {
|
||||
"email": 1
|
||||
},
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {},
|
||||
"protectedFields": {
|
||||
"*": [
|
||||
"email"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "string",
|
||||
"phone": "string",
|
||||
"ProfilePic": "string"
|
||||
},
|
||||
{
|
||||
"_id": "contracts_Contactbook",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"Phone": "string",
|
||||
"Email": "string",
|
||||
"Name": "string",
|
||||
"UserRole": "string",
|
||||
"UserId": "*_User",
|
||||
"CreatedBy": "*_User",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"TenantId": "*partners_Tenant",
|
||||
"TourStatus": "array"
|
||||
},
|
||||
{
|
||||
"_id": "contracts_Document",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"_metadata": {
|
||||
"fields_options": {
|
||||
"EnablePhoneOTP": {
|
||||
"required": "false"
|
||||
},
|
||||
"IsCompleted": {
|
||||
"required": "false",
|
||||
"defaultValue": false
|
||||
},
|
||||
"IsDeclined": {
|
||||
"required": "false",
|
||||
"defaultValue": false
|
||||
},
|
||||
"SendinOrder": {
|
||||
"required": "false",
|
||||
"defaultValue": false
|
||||
},
|
||||
"ExpiryDate": {
|
||||
"required": "false"
|
||||
},
|
||||
"Signers": {
|
||||
"required": "false"
|
||||
},
|
||||
"Name": {
|
||||
"required": "false"
|
||||
},
|
||||
"AgreementValidUntil": {
|
||||
"required": "false"
|
||||
},
|
||||
"URL": {
|
||||
"required": "false"
|
||||
},
|
||||
"RemindOnceInEvery": {
|
||||
"required": "false",
|
||||
"defaultValue": 5
|
||||
},
|
||||
"EnableEmailOTP": {
|
||||
"required": "false"
|
||||
},
|
||||
"AutomaticReminders": {
|
||||
"required": "false",
|
||||
"defaultValue": false
|
||||
},
|
||||
"SentToOthers": {
|
||||
"required": "false",
|
||||
"defaultValue": false
|
||||
},
|
||||
"TimeToCompleteDays": {
|
||||
"required": "false",
|
||||
"defaultValue": 15
|
||||
},
|
||||
"Recipients": {
|
||||
"required": "false"
|
||||
},
|
||||
"Type": {
|
||||
"required": "false"
|
||||
},
|
||||
"Description": {
|
||||
"required": "false"
|
||||
},
|
||||
"ExtUserPtr": {
|
||||
"required": "false"
|
||||
},
|
||||
"SignedUrl": {
|
||||
"required": "false"
|
||||
},
|
||||
"AuditTrail": {
|
||||
"required": "false"
|
||||
},
|
||||
"Placeholders": {
|
||||
"required": "false"
|
||||
},
|
||||
"Folder": {
|
||||
"required": "false"
|
||||
},
|
||||
"Note": {
|
||||
"required": false
|
||||
},
|
||||
"Clauses": {
|
||||
"required": false
|
||||
},
|
||||
"AgreementDelta": {
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {},
|
||||
"protectedFields": {
|
||||
"*": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"EnablePhoneOTP": "boolean",
|
||||
"IsCompleted": "boolean",
|
||||
"IsDeclined": "boolean",
|
||||
"SendinOrder": "boolean",
|
||||
"ExpiryDate": "date",
|
||||
"Signers": "array",
|
||||
"Name": "string",
|
||||
"AgreementValidUntil": "date",
|
||||
"URL": "string",
|
||||
"RemindOnceInEvery": "number",
|
||||
"EnableEmailOTP": "boolean",
|
||||
"AutomaticReminders": "boolean",
|
||||
"SentToOthers": "boolean",
|
||||
"TimeToCompleteDays": "number",
|
||||
"Recipients": "array",
|
||||
"Type": "string",
|
||||
"Description": "string",
|
||||
"ExtUserPtr": "*contracts_Users",
|
||||
"SignedUrl": "string",
|
||||
"AuditTrail": "array",
|
||||
"Placeholders": "array",
|
||||
"Folder": "*contracts_Document",
|
||||
"Note": "string",
|
||||
"CreatedBy": "*_User",
|
||||
"Clauses": "array",
|
||||
"AgreementDelta": "array"
|
||||
},
|
||||
{
|
||||
"_id": "contracts_Signature",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"_metadata": {
|
||||
"fields_options": {
|
||||
"SignatureName": {
|
||||
"required": "false"
|
||||
},
|
||||
"SignText": {
|
||||
"required": "false"
|
||||
},
|
||||
"ImageURL": {
|
||||
"required": "false"
|
||||
},
|
||||
"SignTextFont": {
|
||||
"required": "false"
|
||||
},
|
||||
"InitialsText": {
|
||||
"required": "false"
|
||||
},
|
||||
"InitialsFont": {
|
||||
"required": "false"
|
||||
},
|
||||
"UserId": {
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {},
|
||||
"protectedFields": {
|
||||
"*": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"SignatureName": "string",
|
||||
"SignText": "string",
|
||||
"ImageURL": "string",
|
||||
"SignTextFont": "string",
|
||||
"InitialsText": "string",
|
||||
"InitialsFont": "string",
|
||||
"Initials": "string",
|
||||
"UserId": "*_User"
|
||||
},
|
||||
{
|
||||
"_id": "contracts_Users",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"_metadata": {
|
||||
"fields_options": {
|
||||
"Name": {
|
||||
"required": "false"
|
||||
},
|
||||
"Phone": {
|
||||
"required": "false"
|
||||
},
|
||||
"JobTitle": {
|
||||
"required": "false"
|
||||
},
|
||||
"Email": {
|
||||
"required": "false"
|
||||
},
|
||||
"Company": {
|
||||
"required": "false"
|
||||
},
|
||||
"UserId": {
|
||||
"required": "false"
|
||||
},
|
||||
"TenantId": {
|
||||
"required": "false"
|
||||
},
|
||||
"TourStatus": {
|
||||
"required": false
|
||||
},
|
||||
"IsContactEntry": {
|
||||
"required": false,
|
||||
"defaultValue": false
|
||||
},
|
||||
"ShareWithTeam": {
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {},
|
||||
"protectedFields": {
|
||||
"*": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"Name": "string",
|
||||
"Phone": "string",
|
||||
"JobTitle": "string",
|
||||
"Email": "string",
|
||||
"Company": "string",
|
||||
"UserId": "*_User",
|
||||
"TenantId": "*partners_Tenant",
|
||||
"TourStatus": "array",
|
||||
"Plan": "object",
|
||||
"UserRole": "string",
|
||||
"Next_billing_date": "date",
|
||||
"Customer_id": "string",
|
||||
"Subscription_id": "string",
|
||||
"CreatedBy": "*_User",
|
||||
"IsContactEntry": "boolean",
|
||||
"ShareWithTeam": "boolean"
|
||||
},
|
||||
{
|
||||
"_id": "partners_DataFiles",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"FileSize": "number",
|
||||
"FileUrl": "string",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "partners_Subscriptions",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date"
|
||||
},
|
||||
{
|
||||
"_id": "partners_Tenant",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"EmailAddress": "string",
|
||||
"TenantName": "string",
|
||||
"IsActive": "boolean",
|
||||
"CreatedBy": "*_User",
|
||||
"ContactNumber": "string",
|
||||
"UserId": "*_User",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "partners_TenantCredits",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"usedStorage": "number",
|
||||
"PartnersTenant": "*partners_Tenant",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "w_appinfo",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"orgId": "string",
|
||||
"forgetpassFormId": "string",
|
||||
"mainformObjId": "string",
|
||||
"applogo": "string",
|
||||
"fbAppId": "string",
|
||||
"appname": "string",
|
||||
"loginFormId": "string",
|
||||
"baseurl": "string",
|
||||
"org_name": "string",
|
||||
"signUpFormId": "string",
|
||||
"defaultmenuid": "string",
|
||||
"version": "string",
|
||||
"formTitle": "string",
|
||||
"googleClietId": "string",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"class_permissions": {
|
||||
"get": {
|
||||
"*": true
|
||||
},
|
||||
"find": {
|
||||
"*": true
|
||||
},
|
||||
"count": {
|
||||
"*": true
|
||||
},
|
||||
"create": {
|
||||
"*": true
|
||||
},
|
||||
"update": {
|
||||
"*": true
|
||||
},
|
||||
"delete": {
|
||||
"*": true
|
||||
},
|
||||
"addField": {
|
||||
"*": true
|
||||
}
|
||||
},
|
||||
"fields_options": {
|
||||
"uploadUrl": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"class": "string",
|
||||
"LandingPageId": "string",
|
||||
"accessType": "string",
|
||||
"settings": "array",
|
||||
"appTitle": "string",
|
||||
"metaDescription": "string",
|
||||
"branding_image": "string",
|
||||
"fev_Icon": "string",
|
||||
"defaultRole": "string",
|
||||
"results": "array",
|
||||
"loginType": "string",
|
||||
"createdBy": "*_User",
|
||||
"domain": "string",
|
||||
"enableWebNotification": "boolean",
|
||||
"allowWhiteLabel": "boolean",
|
||||
"uploadUrl": "string"
|
||||
},
|
||||
{
|
||||
"_id": "w_dashboard",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"dbDescription": "string",
|
||||
"dbTitle": "string",
|
||||
"bgColor": "string",
|
||||
"rows": "array",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"appId": "*w_appinfo"
|
||||
},
|
||||
{
|
||||
"_id": "w_formV3",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"description": "string",
|
||||
"uiSchema": "object",
|
||||
"jsonSchema": "object",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"class": "string",
|
||||
"success_message": "string",
|
||||
"restrict_form_entry": "object",
|
||||
"send_email": "boolean",
|
||||
"restrict_form_access": "object",
|
||||
"email_template": "object",
|
||||
"form_permission": "string",
|
||||
"success_redirect": "string",
|
||||
"form_buttons": "object",
|
||||
"buttons": "object",
|
||||
"appId": "*w_appinfo",
|
||||
"rpTitle": "string",
|
||||
"rpDescription": "string",
|
||||
"rpType": "string",
|
||||
"bgColor": "string",
|
||||
"rows": "array",
|
||||
"redirect_id": "string",
|
||||
"formACL": "object",
|
||||
"userSchema": "object",
|
||||
"isRegisterForm": "boolean",
|
||||
"liveValidate": "boolean",
|
||||
"noValidate": "boolean",
|
||||
"validFunction": "string",
|
||||
"help": "object",
|
||||
"name": "string",
|
||||
"phone": "string",
|
||||
"email": "string",
|
||||
"password": "string",
|
||||
"username": "string",
|
||||
"role": "string",
|
||||
"helpText": "object",
|
||||
"helpTextForm": "object",
|
||||
"hideActionsAfter": "number",
|
||||
"rules": "array",
|
||||
"extraActions": "object",
|
||||
"persistentFields": "array"
|
||||
},
|
||||
{
|
||||
"_id": "w_menu",
|
||||
"objectId": "string",
|
||||
"updatedAt": "date",
|
||||
"createdAt": "date",
|
||||
"menuTitle": "string",
|
||||
"menuType": "string",
|
||||
"menuItems": "array",
|
||||
"_metadata": {
|
||||
"indexes": {
|
||||
"_id_": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"appId": "*w_appinfo"
|
||||
}]
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,104 @@
|
||||
[{
|
||||
"_id": "35KBoSgoAK",
|
||||
"rows": [
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"colxs": "12",
|
||||
"colmd": "6",
|
||||
"collg": "6",
|
||||
"widget": {
|
||||
"type": "Card",
|
||||
"icon": "fas fa-signature",
|
||||
"bgColor": "#f0058e",
|
||||
"label": "Need your Signature",
|
||||
"description": null,
|
||||
"data": {
|
||||
"id": "e04ee9dc-932d-6b80-0202-703fd154eb74",
|
||||
"queryType": "",
|
||||
"class": "contracts_Document",
|
||||
"query": "where={\"$and\":[{\"AuditTrail.UserPtr\":{\"$ne\":{\"__type\":\"Pointer\",\"className\": \"contracts_Users\",\"objectId\":\"#objectId#\"}}},{\"AuditTrail.Activity\":{\"$ne\":\"Signed\"}}],\"Signers\":{\"$in\":[{\"__type\":\"Pointer\",\"className\":\"contracts_Users\",\"objectId\":\"#objectId#\"}]},\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&count=1",
|
||||
"key": "count",
|
||||
"Redirect_type": "Report",
|
||||
"Redirect_id": "4Hhwbp482K",
|
||||
"tourSection": "tourcard1",
|
||||
"tourMessage": "This card shows the aggregate count of documents that are awaiting your signature. Clicking on this card will seamlessly take you to the detailed list of such documents for your review and action."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"colxs": "12",
|
||||
"colmd": "6",
|
||||
"collg": "6",
|
||||
"widget": {
|
||||
"type": "Card",
|
||||
"icon": "fas fa-sign-out-alt",
|
||||
"bgColor": "#g0058e",
|
||||
"label": "Out for signatures",
|
||||
"description": null,
|
||||
"data": {
|
||||
"id": "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f",
|
||||
"queryType": "",
|
||||
"class": "contracts_Document",
|
||||
"query": "where={\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&include=Signers,AuditTrail.UserPtr",
|
||||
"key": "count",
|
||||
"Redirect_type": "Report",
|
||||
"Redirect_id": "1MwEuxLEkF",
|
||||
"tourSection": "tourcard2",
|
||||
"tourMessage": "This card indicates the total number of documents you've sent out for signatures. A single click on this card will navigate you to a comprehensive list of these documents, allowing you to monitor their status."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"colxs": "12",
|
||||
"colmd": "6",
|
||||
"collg": "6",
|
||||
"widget": {
|
||||
"type": "report",
|
||||
"reportId": "5Go51Q7T8r",
|
||||
"data": {
|
||||
"tourSection": "tourreport1",
|
||||
"tourMessage": "Here lies a curated list of documents that are pending your signature. These are requests from other users that require your immediate attention for completion."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"colxs": "12",
|
||||
"colmd": "6",
|
||||
"collg": "6",
|
||||
"widget": {
|
||||
"type": "report",
|
||||
"reportId": "d9k3UfYHBc",
|
||||
"data": {
|
||||
"tourSection": "tourreport2",
|
||||
"tourMessage": "This area displays all the documents you've dispatched for signatures from other parties. It serves as a real-time tracker for documents pending external approval."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"colxs": "12",
|
||||
"colmd": "12",
|
||||
"collg": "12",
|
||||
"widget": {
|
||||
"type": "report",
|
||||
"reportId": "kC5mfynCi4",
|
||||
"data": {
|
||||
"tourSection": "tourreport3",
|
||||
"tourMessage": "In this section, you'll find your draft documents awaiting completion. These are the documents you've initiated but haven't yet finalized for sending."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"_p_appId": "w_appinfo$aIPmIvMzGM",
|
||||
"dbTitle": "Dashboard",
|
||||
"dbDescription": null,
|
||||
"bgColor": "#ffffff",
|
||||
"_created_at": {
|
||||
"$date": "2023-09-04T13:17:26.707Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-09-27T04:53:20.395Z"
|
||||
}
|
||||
}]
|
||||
@@ -0,0 +1,290 @@
|
||||
[
|
||||
{
|
||||
"_id": "H9vRfEYKhT",
|
||||
"_created_at": {
|
||||
"$date": "2023-09-04T14:04:00.669Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-10-20T06:27:02.314Z"
|
||||
},
|
||||
"_p_appId": "w_appinfo$aIPmIvMzGM",
|
||||
"menuItems": [
|
||||
{
|
||||
"icon": "fas fa-tachometer-alt",
|
||||
"title": "Dashboard",
|
||||
"target": "",
|
||||
"pageType": "dashboard",
|
||||
"description": "",
|
||||
"objectId": "35KBoSgoAK"
|
||||
},
|
||||
{
|
||||
"icon": "far fa-newspaper",
|
||||
"title": "New Document",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": null,
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-pen-nib",
|
||||
"title": "Sign yourself",
|
||||
"target": "_self",
|
||||
"pageType": "form",
|
||||
"description": "",
|
||||
"objectId": "sHAnZphf69"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-file-signature",
|
||||
"title": "Request signatures",
|
||||
"target": "_self",
|
||||
"pageType": "form",
|
||||
"description": "",
|
||||
"objectId": "8mZzFxbG1z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-folder",
|
||||
"title": "OpenSignDrive™",
|
||||
"target": "_self",
|
||||
"pageType": "mf",
|
||||
"description": "",
|
||||
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-address-card",
|
||||
"title": "Reports",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": "",
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-signature",
|
||||
"title": "Need your sign",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "4Hhwbp482K"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-tasks",
|
||||
"title": "In Progress",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "1MwEuxLEkF"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-check-circle",
|
||||
"title": "Completed",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "kQUoW4hUXz"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-edit",
|
||||
"title": "Drafts",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "ByHuevtCFY"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-times-circle",
|
||||
"title": "Declined",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "UPr2Fm5WY3"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-hourglass-end",
|
||||
"title": "Expired",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "zNqBHXHsYH"
|
||||
},
|
||||
{
|
||||
"icon": "fa-solid fa-address-book",
|
||||
"title": "Contactbook",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "5KhaPr482K"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-cog",
|
||||
"title": "Settings",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": "",
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-pen-fancy",
|
||||
"title": "My Signature",
|
||||
"target": "_self",
|
||||
"pageType": "mf",
|
||||
"description": "",
|
||||
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menuTitle": "Default Menu",
|
||||
"menuType": "Side Menu"
|
||||
},
|
||||
{
|
||||
"_id": "VPh91h0ZHk",
|
||||
"_created_at": {
|
||||
"$date": "2023-09-04T14:16:15.424Z"
|
||||
},
|
||||
"_updated_at": {
|
||||
"$date": "2023-10-20T06:25:59.660Z"
|
||||
},
|
||||
"_p_appId": "w_appinfo$aIPmIvMzGM",
|
||||
"menuItems": [
|
||||
{
|
||||
"icon": "fas fa-tachometer-alt",
|
||||
"title": "Dashboard",
|
||||
"target": "",
|
||||
"pageType": "dashboard",
|
||||
"description": "",
|
||||
"objectId": "35KBoSgoAK"
|
||||
},
|
||||
{
|
||||
"icon": "far fa-newspaper",
|
||||
"title": "New Document",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": null,
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-pen-nib",
|
||||
"title": "Sign yourself",
|
||||
"target": "_self",
|
||||
"pageType": "form",
|
||||
"description": "",
|
||||
"objectId": "sHAnZphf69"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-file-signature",
|
||||
"title": "Request signatures",
|
||||
"target": "_self",
|
||||
"pageType": "form",
|
||||
"description": "",
|
||||
"objectId": "8mZzFxbG1z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-folder",
|
||||
"title": "OpenSignDrive™",
|
||||
"target": "_self",
|
||||
"pageType": "mf",
|
||||
"description": "",
|
||||
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-address-card",
|
||||
"title": "Reports",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": "",
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-signature",
|
||||
"title": "Need your sign",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "4Hhwbp482K"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-tasks",
|
||||
"title": "In Progress",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "1MwEuxLEkF"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-check-circle",
|
||||
"title": "Completed",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "kQUoW4hUXz"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-edit",
|
||||
"title": "Drafts",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "ByHuevtCFY"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-times-circle",
|
||||
"title": "Declined",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "UPr2Fm5WY3"
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-hourglass-end",
|
||||
"title": "Expired",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "zNqBHXHsYH"
|
||||
},
|
||||
{
|
||||
"icon": "fa-solid fa-address-book",
|
||||
"title": "Contactbook",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "5KhaPr482K"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"icon": "fas fa-cog",
|
||||
"title": "Settings",
|
||||
"target": "_self",
|
||||
"pageType": null,
|
||||
"description": "",
|
||||
"objectId": null,
|
||||
"children": [
|
||||
{
|
||||
"icon": "fas fa-pen-fancy",
|
||||
"title": "My Signature",
|
||||
"target": "_self",
|
||||
"pageType": "mf",
|
||||
"description": "",
|
||||
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
|
||||
},
|
||||
{
|
||||
"icon": "far fa-user",
|
||||
"title": "Add User",
|
||||
"target": "_self",
|
||||
"pageType": "form",
|
||||
"description": "",
|
||||
"objectId": "lM0xRnM3iE"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menuTitle": "Admin Menu",
|
||||
"menuType": "Side Menu"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Starting MongoDB initial data import..."
|
||||
|
||||
# Wait for MongoDB to fully start
|
||||
sleep 10
|
||||
|
||||
# Import the data
|
||||
mongoimport --host localhost --db OpenSignDB --collection _Role --type json --file /docker-entrypoint-initdb.d/legadraGCva._Role.json --jsonArray
|
||||
mongoimport --host localhost --db OpenSignDB --collection _SCHEMA --type json --file /docker-entrypoint-initdb.d/legadraGCva._SCHEMA.json --jsonArray
|
||||
mongoimport --host localhost --db OpenSignDB --collection w_appinfo --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_appinfo.json --jsonArray
|
||||
mongoimport --host localhost --db OpenSignDB --collection w_dashboard --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_dashboard.json --jsonArray
|
||||
mongoimport --host localhost --db OpenSignDB --collection w_menu --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_menu.json --jsonArray
|
||||
|
||||
|
||||
|
||||
echo "MongoDB initial data import done."
|
||||
@@ -0,0 +1,54 @@
|
||||
MIIKCQIBAzCCCc8GCSqGSIb3DQEHAaCCCcAEggm8MIIJuDCCBG8GCSqGSIb3DQEH
|
||||
BqCCBGAwggRcAgEAMIIEVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIpumu
|
||||
bFabBWACAggAgIIEKDqHS7Icd5MzIBk1dBokGK2s+5a2fA4308WA1QzEWmczqVYI
|
||||
z6lYmW8qsiZIw4PFkRzdIx1+zCmP8jgWiiqh5RKnbHYmh1JPNyx9SqmUDILDXmjg
|
||||
KxO9agRw9LXge4hgRL7YW0TxYZYw4EeXV9Yr7kcOq9DoO2MoRikJ+2Tuvvq/hfuV
|
||||
9zFHsz4jpf7W95k1IeH6bZ92klz5R1e/EK8JuHy592i/u+BxxW1vTkiPpTaHD6s9
|
||||
1lDSkT1j0LIDU6l9gVvJvFBV8j88vet/Z4QkTbHPMYvBnKNRstKuOvDasEJE4RkA
|
||||
PV4TfBwFF6uvREZI1vBboM/18pzeyjoRX+mlJNfcH3kh1tkck+Jg+M2bLXAH1EdD
|
||||
GRwENvnTNW1CFIn37VVja7SFBQNXA+E6rejmqtUmZ5XktSINDBUyjow9XuYTUtI/
|
||||
sgcRSC0aB0EKKpphbFPp1niKCLm1ef33e+bWyWbtR2L2Kc3ETmhjNADpyapAGmzc
|
||||
LP2BafGaKj18KiLAG4GL6+kXk0GUz7Fw5q8H8RY1T33o+xjWvC0+aJgvr65qWdKw
|
||||
+ug6wuu4Cr2kFEuXxPKsnYqmE5NT/x+lfunlZ5iEQN3w2XO5J2u2eMXVRUsPH2T6
|
||||
0sJKomjY0RB1JsqZBnyleWm+tYo0RpVAyJ3NGBp9dVb7a3Qw6jNZBG/xMW+gvtUJ
|
||||
q6hfK/cD3cagD0NQFVD5STMOuGOSqq/bbwAKjZ/lrPmCCYATKwkjAFybYfHJVrrW
|
||||
Y2tQgCQ/zrZLIxQjp7F17hU0+gT54x0MpF6AoqIM/qqNnHrQ0fi50ECmLvx3SqYa
|
||||
nvjvt/HZhMZfqRXiXjeicIwpnNoG7+uQknySk+7cc9GNhHZR7cfPfkTpgvuuebrQ
|
||||
l5YW+k9tG+xrX8g72nvtFMnammlBixlFwECJaEszEQk5tc2ti8uG2z+kGnFoDoBV
|
||||
M6ZVMpKDJzXPxLdzT6ChIPyatjIkqOKe6vDpnmzcoEhbBhmtkVjWFA2dfX846ugV
|
||||
y1QiecWgk8pMNWhh3IDd05v/wzbFwNcq+Gi+1dZsPmFH+egIcrQKZu2r3jCJtGHh
|
||||
DNG/nyf/anqvKXF90bi4hRT3vdDXXuWgY7EUwfn9h5jYabCO6HsQxQOBjFYNmBrh
|
||||
MfaiBZe72E8fzNAfIlwDcJ4AWY1SOM7hi8bqfRWw1NtNxuMUiRFoR31O6XkQauye
|
||||
9hAmpdlZHZXtJ6LM0QaWkPJmG3058GMtIn/qS60V9nINh+zXhwza/1pnFB+e9MWc
|
||||
hAPgo0nn55FusM//g1nM31PKe+nOm3Jyp0nEQ4m8aDtJS63o2fvp3e2KJbPWQMHE
|
||||
a83W975diWg4NTdevV9lFpNllHclVoPoavUHIzHd7HF9TcPpjbXJSUZ7cITHHefr
|
||||
kQTa/2G9cWuRhN9GKIHBdr13nfEvMIIFQQYJKoZIhvcNAQcBoIIFMgSCBS4wggUq
|
||||
MIIFJgYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECDgnjfOf
|
||||
AjArAgIIAASCBMgkbVuptroBdyMY5gl/eBQj5+iAV02YSaF969ihStLSWI4x5FAf
|
||||
HuDgqCyEMSl4RHG8ZvNaO9JoNfIpMK/TPQBoQRCzE2Vjf66VTERaQtU6h7tZrbQt
|
||||
K96n9eqvohm/vXbXe08fsodYp2s79kAvKgpuGG5iX77qYVzJHBPed87cvczo4ToP
|
||||
CpurDpByt8fGEmjtcikal8o+H9uoHjcFwqMigX1Q7IEjuKXrb5e6wTvxMRob8yfv
|
||||
LVl6ahteKSkWCMb6rLZ5f12jDoCGX/YXRrSsU9t/lXe0Nxv5i7c8flb2EsNtwygD
|
||||
fexVvn5u6ble6RDYNpuQkPgF41HyZh+JvGAF6i1r4tJPL9Pf4HnjEB8Y8IHgon+w
|
||||
T5I+8LTgcrWyhptzblXMjKySTEp9OEa2cCVwZkl4z43PWJ5oIAQ2IDTOQ603/5o/
|
||||
d9KA76/zMPQ5O0gv17OA7kwFv98v6sTcR4vgkQZqnyDpJSEPHyNxhw2MSBqS3jq3
|
||||
YPhRz+3Ei1oFp9uYFhzn39f9gzNi++X9pOjSrDb8v3mcDXZKNrxQLuoRMSf0eQNI
|
||||
dgJRqj/fuqNZ5ac3kd4P5BALCsnA1tM27zYrgUdpOnrc2D9FBthEjpRlQKMMzhQf
|
||||
cNMFWmoNjakDilvvLcsQeQ3P6cXbN1ODoNnjgK3VzcmeKyzW2PrTXEPHARUM3j4V
|
||||
sZzGaUOVKLqaaDrXWQKC0vrTvxP2WMfjQ1dTdXQP/kSZTXRC5rtB9tky38flBor0
|
||||
N9rhUDIGMs5qBvyrkV2hKXiW39G69p1KWY+Cw28AzY+CNSjePRi60TsnUxgcOS7i
|
||||
0AT25Gx3A4YqxmTY38MPB4wPcBPcw4hjNoQamaC9mqs+KVHcP5YHUlqykMeH0YVi
|
||||
J+ehytJE9xuDcfBOjxjadxp3/q/Lku4rky89gdJGFQWuuz75VulDywPRZRwmQTel
|
||||
sjEGMHR1zTOlPJdTDWhqaKmWvL4GhbCgEPIKwmqd1QKRTl/3Baa1nYllJeYVwiTT
|
||||
qLCkbA6qXrLGj1ENZxrKn9yqr8HwOoApjwhARu4LF/BRMgdkzelK2kOXHnZ26sZ2
|
||||
NY/MMtVmq4c59y6iQwmsbHr9tWGz3ahyXcZZufjNXU/AVnO1c92g7umAWZF4RohL
|
||||
gMmh57cAhN9PEbEv6j/6BT3XXp8jB0ywcRriYxfxwidviCKH/76Q4sytYJQaDFI1
|
||||
fnzmv0aDotbG2BdpWSiYPDOPm+3cmfjlULsn1FYWL4NDCX1f+C4lNtKVX9LU8c5M
|
||||
m8dA1DUlDfnuNO5/BShuoGXG2z4O/XwxIaRFizMxWS2sWurbAEFJ6oNw3kC7WSah
|
||||
NIe8aUC1umpc1Gk3X2f4Ytzj9OEqn0y55qoqLINJuejXMffF/gjopxHWadLVaVaj
|
||||
Q1SewrECuEXdSbBR/a10po24wmRtkmlvRJXJl7sG95xE5ZCqp+m6sRPWGdf1yKbV
|
||||
vyWNUe4Qvkxe4a0VAJpTyIGr980CKz/jkvtNQMobGl7AfhxKJ450wg454WcexMct
|
||||
BYXvZMSdUDCgMLlh0nHJHl5btrFWqE0Z/fqWmIknZL2jZ4J+2hdVl/xB/sUt6kcu
|
||||
txw+RfL+vNE8PxhTNaOdJFwD8yeN1mJ3yMUA8HHYpw9yljgxJTAjBgkqhkiG9w0B
|
||||
CRUxFgQUDYlgGVxSxuOknhQc256x3++7BDwwMTAhMAkGBSsOAwIaBQAEFFjASdYl
|
||||
3pXAXxZuvVvv9tsb4bdrBAhyb+KCIjp/gAICCAA=
|
||||
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDxTCCAq2gAwIBAgIUAZQ9QST2eBZz5k9pCa//mHQVm1QwDQYJKoZIhvcNAQEL
|
||||
BQAwcjELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQKDA1P
|
||||
cGVuU2lnbiBMYWJzMREwDwYDVQQDDAhPcGVuU2lnbjElMCMGCSqGSIb3DQEJARYW
|
||||
aGVsbG9Ab3BlbnNpZ25sYWJzLmNvbTAeFw0yMzExMTcxOTQ0MzZaFw0yNDExMTYx
|
||||
OTQ0MzZaMHIxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEWMBQGA1UE
|
||||
CgwNT3BlblNpZ24gTGFiczERMA8GA1UEAwwIT3BlblNpZ24xJTAjBgkqhkiG9w0B
|
||||
CQEWFmhlbGxvQG9wZW5zaWdubGFicy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQDLRKLjCSrvV1zAY2leWxCvdKTUaThpQO8nWPE/4v5ilMU2aRON
|
||||
krAnli0LUfQ/tIRWNurxwVjJ7HrW3ICLn05GBLjm2AUCfuMbJCvOEEdmFJqRY04n
|
||||
12fBZWz2KtzbZEIBVxLhc4E4g+Rz68hQA2fqwNuFdyGkkIbhVXpZIePEppqRmw+2
|
||||
uuDvIzJ77rdDaLqwwPoHWenZ2uZTedKXx7PGYs98psg35GvcpssqAJGAIAi9Rzg/
|
||||
ZV4oSpGXCjn/TJy61zTDbmPFCS/rC1XBWzBQfwDeBPDI18W6gPVX6N4dp0Ao+n8Q
|
||||
txeI6g4FzMH91KPbdbZXxm8rZqXj87VQs9trAgMBAAGjUzBRMB0GA1UdDgQWBBRN
|
||||
NtRPagnqovdmbrdhSUON9Rwd3TAfBgNVHSMEGDAWgBRNNtRPagnqovdmbrdhSUON
|
||||
9Rwd3TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBrcPyA7GHq
|
||||
+ol9qjy9HijpoU5MaEiV9v9H8/0v7KoXUND3rMl37yFyjxGN8uda8WxpEhE2eFnk
|
||||
Xjtm2NgPrv8qeYHor/A3y5RfQhnlCY4kE1bREZGhcuKihR4rOtmComwFjx4Ibwwj
|
||||
4nKsflj6rXcWKSfSNHLkXFXHPYwyqRsKdtClrD/8YJn6LeeMlMjIYGGP4qyi2WwS
|
||||
Z8hExWGEMaMWiA9rxTMX6iu/parGH/pWU/55Os3WlcHPhlvqchBkQFJ+f8b+NYz0
|
||||
vIHQgwn4K5WMsZVLxoiUcU7cSqE/qhnP+pzBf8lRaYwd+zUznDvzpKKz6nFgeHok
|
||||
s8BK7JAKkIsl
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,30 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,5932FA9F02938D1B
|
||||
|
||||
6gkkZP80WrVnR3dVwkimtfirSeYNXZlrXXBv+Ddjyq7FScqca7svJFd8ObC0xXjg
|
||||
nbxChDKS8SXcSjsNCTzixG0QReO5vaqovrpQoYbkSQ9GRMIVV8WuWNzlyMnypNJ4
|
||||
Z6hdpd5nkc1hIP8A6WcY3lA8msyHceU9IidEEb75CE743qsvUMko+XvqntZx/LNe
|
||||
0uK8Bs+cXeDzolpNX8ORKBTAOMii+WPlN2l+9ldsWTECEk4GmWa51QfpKouLxz5E
|
||||
u7fuGuku/nPKGb4Yj7sCgaD91UabRksDLS9UGDBqeNL+mogG3gY/Iu0/q2cUs6XR
|
||||
x1W6KW1eJHnOf1pAp7+G/zNqzdsxI3pnoR+nsV6/G0glBLar+Xqc99B568lnUWWv
|
||||
5NGN3Buz1axx1jPKIknDcT4Skmvt6TcmgrjoCQ9XvmNKVClpExQ+dKPmJI/EVNoU
|
||||
jjDZyfghcJ6BEMcTgoOBDiUrPM0273sb89u/AzyUA1tTciW2KARz6cOUTPWVRSRn
|
||||
4yXpkA4BJDpxRmK68BXorZLNxtvHk+on80c9tu5e+IVa3Gu1K7gc269TPmlIolAM
|
||||
v//i+jpwJ4Pe2IGVYdojMr15useUv7JC6/Kconnkx4q9rkMriguuXoQt8qW3kvEs
|
||||
Ur8KuibtDqhz2zGbsKboQFMOd6cdd+63dJCGAUqk4hFrSikTw3LhkXNcg9GZHq1z
|
||||
WFAfaA3x2jd+kJJ5xg8xMVEHax5IAOXDL2ektyPFpI1UZOuTc2i7FK6Y0NnXPkSN
|
||||
G/+DsKdLWT943mPfZj01mTRi3MgseDXsHMHGmmPxW9J4jv+WW4OdpHvd474QzJ8b
|
||||
vQmyiKq4XPHsuQUkzHVPbTrGe1B9z4p97YQKdEfXP2ChGFsUHCYQdpHyXwie2+pq
|
||||
E2rc7Bai0OuL0anYMSIvDrJ0DE8mVVaFur1b2Uz6ieCDlrOXnzD1BrcleiZem7og
|
||||
on/3oCUK+qxibCCcd5Hg2HtPusa43U0/UbCrqb2sww9iN36DLdtef/jlozKNiBx9
|
||||
e8ZztF6GtAKhIdgGW/M9TXMUZOYr7aaXO71MsqhwpVWZ5dNqagOBzhmd7Etokf1H
|
||||
O0WxJZ5XPDsnlKwYq86ssK+2RCNYAuvZoM3dRCysPvXoBFmsmHDzKdbKcckd8Vxr
|
||||
6P1yaCkB/iX55dUqwKfIuqxY3m4MA2Us9DD0BRxZOSUqHhzHHSogsLhqLQEQENA4
|
||||
U9N/v/za81UaU8nfkAswsGlTdTKjWH6Fzc0NeagbEFtpUaG/WIHPesUzU7ZNvMzR
|
||||
SQACVWl62Dley2g2eAgcrsIn78MbwNJI2YN5eXIw0K2MiMlGXWOEvkjIIVfjc0/d
|
||||
QxLFJwqShZBVO+jnAJ8jti7mP6PgskjtfHNAIphRJ4fm9h/Ns1YMpipBRVBDhbwY
|
||||
AOVT4bRw9Q3O5I0pe10ZdViAhexegQ8yGt3pUlKaUf9GRwIFEknjZ5Pc98V/R/wC
|
||||
INSIOZzDHj2uyZ3p7ToF1Z6kVVbbyfqDOnxUiV2ykR8ZqQMXNWcEJKH8qRqI+VHf
|
||||
oszD2BQvXgkWdrJtHuHjJCdDl03Y+daS5yP8IKTDucHvRv4ZSMghZ34SJTw5MaBP
|
||||
-----END RSA PRIVATE KEY-----
|
||||
Binary file not shown.
+12
-6
@@ -5,25 +5,30 @@ services:
|
||||
build:
|
||||
context: ./apps/OpenSignServer
|
||||
dockerfile: Dockerfile
|
||||
image: OpenSignServer-image
|
||||
image: opensignserver-image
|
||||
container_name: OpenSignServer-container
|
||||
command: /usr/src/app/node_modules/.bin/nodemon server.js
|
||||
volumes:
|
||||
- ./apps/OpenSignServer/:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
ports:
|
||||
- "5000:5000"
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
- mongo
|
||||
env_file: ./OpenSignServer/.env
|
||||
env_file: .env
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
networks:
|
||||
- app-network
|
||||
mongo:
|
||||
image: mongo
|
||||
build:
|
||||
context: ./apps/mongo
|
||||
dockerfile: Dockerfile
|
||||
container_name: mongo-container
|
||||
image: opensign-mongo
|
||||
volumes:
|
||||
- data-volume:/data/db
|
||||
- ./apps/mongo/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
|
||||
ports:
|
||||
- "27017:27017"
|
||||
networks:
|
||||
@@ -32,9 +37,10 @@ services:
|
||||
build:
|
||||
context: ./apps/OpenSign
|
||||
dockerfile: Dockerfile
|
||||
image: OpenSign-image
|
||||
image: opensign-image
|
||||
container_name: OpenSign-container
|
||||
command: npm start
|
||||
env_file: .env
|
||||
volumes:
|
||||
- ./apps/OpenSign/:/usr/app
|
||||
- /usr/app/node_modules
|
||||
@@ -53,4 +59,4 @@ volumes:
|
||||
data-volume:
|
||||
node_modules:
|
||||
web-root:
|
||||
driver: local
|
||||
driver: local
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
@@ -0,0 +1,41 @@
|
||||
# Website
|
||||
|
||||
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
$ yarn
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
```
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
### Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
slug: first-blog-post
|
||||
title: First Blog Post
|
||||
authors:
|
||||
name: Gao Wei
|
||||
title: Docusaurus Core Team
|
||||
url: https://github.com/wgao19
|
||||
image_url: https://github.com/wgao19.png
|
||||
tags: [hola, docusaurus]
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
slug: long-blog-post
|
||||
title: Long Blog Post
|
||||
authors: endi
|
||||
tags: [hello, docusaurus]
|
||||
---
|
||||
|
||||
This is the summary of a very long blog post,
|
||||
|
||||
Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
slug: mdx-blog-post
|
||||
title: MDX Blog Post
|
||||
authors: [slorber]
|
||||
tags: [docusaurus]
|
||||
---
|
||||
|
||||
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
|
||||
|
||||
:::tip
|
||||
|
||||
Use the power of React to create interactive blog posts.
|
||||
|
||||
```js
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
```
|
||||
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
|
||||
:::
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
@@ -0,0 +1,25 @@
|
||||
---
|
||||
slug: welcome
|
||||
title: Welcome
|
||||
authors: [slorber, yangshun]
|
||||
tags: [facebook, hello, docusaurus]
|
||||
---
|
||||
|
||||
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
|
||||
|
||||
Simply add Markdown files (or folders) to the `blog` directory.
|
||||
|
||||
Regular blog authors can be added to `authors.yml`.
|
||||
|
||||
The blog post date can be extracted from filenames, such as:
|
||||
|
||||
- `2019-05-30-welcome.md`
|
||||
- `2019-05-30-welcome/index.md`
|
||||
|
||||
A blog post folder can be convenient to co-locate blog post images:
|
||||
|
||||

|
||||
|
||||
The blog supports tags as well!
|
||||
|
||||
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user