mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-10 19:57:40 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
498e0c6be6 | ||
|
|
b4d73b2b44 | ||
|
|
440d253124 | ||
|
|
2b6bf7bcaa | ||
|
|
cb6d9e9b9b | ||
|
|
ebeeedc96c | ||
|
|
5cecf3390b | ||
|
|
9890d568fd | ||
|
|
06bcae64be | ||
|
|
fb017c4bcd | ||
|
|
01d3edd262 | ||
|
|
41a025715e | ||
|
|
306768fbd2 | ||
|
|
d82da53258 | ||
|
|
673245df02 | ||
|
|
42549e5792 | ||
|
|
cc8b4b7157 | ||
|
|
4cbd7e74f7 | ||
|
|
b300a5bb39 | ||
|
|
5422fefc54 | ||
|
|
248b0cac0b | ||
|
|
a388a7c345 | ||
|
|
fc564ca37b | ||
|
|
37b2e4c97a | ||
|
|
a3bc9817e7 | ||
|
|
8a216e6c0d | ||
|
|
613b1cfe07 | ||
|
|
ee77534e35 | ||
|
|
737b33db1e | ||
|
|
ac214d0467 | ||
|
|
f8b21e7a93 | ||
|
|
7e6df13b71 | ||
|
|
3e584cec1a | ||
|
|
bc75dd109f | ||
|
|
6b3abed782 | ||
|
|
f163958cd0 | ||
|
|
ecd461b96c | ||
|
|
1371c2c09a | ||
|
|
3121f35158 | ||
|
|
3c0db9473c | ||
|
|
4f2b72dd4d | ||
|
|
7d9af1db95 | ||
|
|
0e38783560 | ||
|
|
6880ae35a8 | ||
|
|
9a07c67b69 | ||
|
|
33bfdeef15 | ||
|
|
a404247604 | ||
|
|
c48579daa7 | ||
|
|
509f8f9a07 | ||
|
|
5b85d5b277 | ||
|
|
bbf3170398 | ||
|
|
c172a7c55c | ||
|
|
90f3e0066b | ||
|
|
b6e028a2c0 | ||
|
|
11384192ba | ||
|
|
9df63265fb | ||
|
|
ff6a8ce755 | ||
|
|
60c1aa253a | ||
|
|
ad2fec0d66 | ||
|
|
0451a6cae0 | ||
|
|
0d5f8981fe | ||
|
|
cfd8be0eee | ||
|
|
86e5ef6ef5 | ||
|
|
1af47c8425 | ||
|
|
f0395cb2c7 | ||
|
|
598aa2975f | ||
|
|
0742291216 | ||
|
|
94eeceeaf9 | ||
|
|
970fbecb7b | ||
|
|
361e082930 | ||
|
|
3f9b6eb5a9 | ||
|
|
2265bee61f | ||
|
|
6390706d8d | ||
|
|
37e03c1026 | ||
|
|
c6fa6c710d | ||
|
|
2e921e30b6 | ||
|
|
686a773d34 | ||
|
|
b03e1b8f9d | ||
|
|
f1ceae794f | ||
|
|
5a8bcb8f9a | ||
|
|
ce70da7d8e | ||
|
|
db03dfa641 | ||
|
|
7e70a5e111 | ||
|
|
f5f18f1630 | ||
|
|
fa6856c649 | ||
|
|
3b4946e47b | ||
|
|
05fe68d458 | ||
|
|
2f3cdca821 | ||
|
|
4d8a54a6c5 | ||
|
|
4fe5bdaad8 | ||
|
|
b95ede5273 | ||
|
|
5b2684a9f4 | ||
|
|
d779720f26 | ||
|
|
3cf8029978 | ||
|
|
0bb857a942 | ||
|
|
103d32edcb | ||
|
|
eca6ad374b | ||
|
|
d2efe88266 | ||
|
|
450e5ec7f7 | ||
|
|
3bbbda91b8 | ||
|
|
a48db306bb | ||
|
|
2a60b30c75 | ||
|
|
19cfa9d27d | ||
|
|
0fc12c957e | ||
|
|
6fd332f8b4 | ||
|
|
39f7ccecaa | ||
|
|
3bd306809b | ||
|
|
04e9d13206 | ||
|
|
b24739d61b | ||
|
|
9dda211605 | ||
|
|
93708a6875 | ||
|
|
e78f6f6df4 | ||
|
|
ccaaca75ba | ||
|
|
dedff36b35 | ||
|
|
4d561ca19e | ||
|
|
f70e9e2a3f | ||
|
|
e4a3ce405e | ||
|
|
c3be2a1fef | ||
|
|
8b2f7f1e95 | ||
|
|
55465a035f | ||
|
|
d30105299c | ||
|
|
78b038da13 | ||
|
|
d230ad2655 | ||
|
|
367c824918 | ||
|
|
5f8affb1bb | ||
|
|
3bd23f83cf | ||
|
|
ab1dbecab2 | ||
|
|
44c6aa9b0b | ||
|
|
ad922c16c7 | ||
|
|
87ee2e881e | ||
|
|
3659a1de55 | ||
|
|
cc49a2fd4e | ||
|
|
babd43e710 | ||
|
|
8dde38edf1 | ||
|
|
6c16d00031 | ||
|
|
99f444a8a1 | ||
|
|
f0149f6fd8 | ||
|
|
bdb7d9be8f | ||
|
|
27dcd7fefd | ||
|
|
a2467ef1a6 | ||
|
|
824b0a5407 | ||
|
|
ac8195a52d | ||
|
|
e0920bf5d8 | ||
|
|
4a5f030d87 | ||
|
|
ba839b0fc8 | ||
|
|
27130fd223 | ||
|
|
19ba9e3091 | ||
|
|
8c64a89f08 | ||
|
|
1c3d2d5c9a | ||
|
|
b36df32b19 | ||
|
|
155a3eee14 | ||
|
|
7bb46782a3 | ||
|
|
40961936d0 | ||
|
|
db310b0d73 | ||
|
|
f0e9c6b3e4 | ||
|
|
97bd375de3 | ||
|
|
e2d450f9aa | ||
|
|
add01cb02a | ||
|
|
cea1653805 | ||
|
|
9d81fce956 | ||
|
|
79e3762b36 | ||
|
|
aa04a957ed | ||
|
|
d31910aefa | ||
|
|
96a4a2e7fa | ||
|
|
e8aaab99f9 | ||
|
|
c61be7c35b | ||
|
|
0ee85f53da | ||
|
|
748e2196da | ||
|
|
58199a934a | ||
|
|
7eec822a65 | ||
|
|
6c21028523 | ||
|
|
099a3cc46d | ||
|
|
5adaffc684 | ||
|
|
d588caf6d4 | ||
|
|
5930fd940d | ||
|
|
741f66b019 | ||
|
|
de26c2d719 | ||
|
|
881ac12b03 | ||
|
|
1932dda6d6 | ||
|
|
46159b7214 | ||
|
|
c57c15a4cb | ||
|
|
724fa7c27e | ||
|
|
2762c3e170 | ||
|
|
74bfd39abc | ||
|
|
3115ff3e2a | ||
|
|
adbf1fe1e0 | ||
|
|
fe2f3c5f7c | ||
|
|
8a01efee4c | ||
|
|
eafb26d462 |
Generated
+175
-5
@@ -22,6 +22,7 @@
|
|||||||
"radix-ui": "^1.0.1",
|
"radix-ui": "^1.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.2",
|
"react-bootstrap": "^2.10.2",
|
||||||
|
"react-cookie": "^7.1.4",
|
||||||
"react-datepicker": "^6.4.0",
|
"react-datepicker": "^6.4.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
"react-konva": "^18.2.10",
|
"react-konva": "^18.2.10",
|
||||||
"react-modal": "^3.16.1",
|
"react-modal": "^3.16.1",
|
||||||
"react-pdf": "^7.7.1",
|
"react-pdf": "^7.7.1",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.0",
|
"react-redux": "^9.1.0",
|
||||||
"react-rnd": "^10.4.1",
|
"react-rnd": "^10.4.1",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
@@ -41,6 +43,7 @@
|
|||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.0",
|
||||||
"react-signature-canvas": "^1.0.6",
|
"react-signature-canvas": "^1.0.6",
|
||||||
"react-tooltip": "^5.26.3",
|
"react-tooltip": "^5.26.3",
|
||||||
|
"react-web-share": "^2.0.2",
|
||||||
"reactour": "^1.19.2",
|
"reactour": "^1.19.2",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-thunk": "^3.1.0",
|
"redux-thunk": "^3.1.0",
|
||||||
@@ -6054,6 +6057,11 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
|
||||||
|
},
|
||||||
"node_modules/@types/eslint": {
|
"node_modules/@types/eslint": {
|
||||||
"version": "8.44.4",
|
"version": "8.44.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz",
|
||||||
@@ -6108,11 +6116,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/hoist-non-react-statics": {
|
"node_modules/@types/hoist-non-react-statics": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
|
||||||
"integrity": "sha512-Wny3a2UXn5FEA1l7gc6BbpoV5mD1XijZqgkp4TRgDCDL5r3B5ieOFGUX5h3n78Tr1MEG7BfvoM8qeztdvNU0fw==",
|
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
"hoist-non-react-statics": "^3.3.0"
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
@@ -6205,6 +6211,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz",
|
||||||
"integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg=="
|
"integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/quill": {
|
||||||
|
"version": "1.3.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
|
||||||
|
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
|
||||||
|
"dependencies": {
|
||||||
|
"parchment": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/range-parser": {
|
"node_modules/@types/range-parser": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz",
|
||||||
@@ -9428,6 +9442,25 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||||
"integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
|
"integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-equal": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-arguments": "^1.1.1",
|
||||||
|
"is-date-object": "^1.0.5",
|
||||||
|
"is-regex": "^1.1.4",
|
||||||
|
"object-is": "^1.1.5",
|
||||||
|
"object-keys": "^1.1.1",
|
||||||
|
"regexp.prototype.flags": "^1.5.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/deep-extend": {
|
"node_modules/deep-extend": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
@@ -10986,6 +11019,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||||
|
},
|
||||||
"node_modules/external-editor": {
|
"node_modules/external-editor": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||||
@@ -12612,6 +12650,21 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arguments": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-array-buffer": {
|
"node_modules/is-array-buffer": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
||||||
@@ -16841,6 +16894,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object-is": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"define-properties": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-keys": {
|
"node_modules/object-keys": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
@@ -17194,6 +17262,11 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parchment": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -19134,6 +19207,50 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/quill": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
|
||||||
|
"dependencies": {
|
||||||
|
"clone": "^2.1.1",
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"eventemitter3": "^2.0.3",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"parchment": "^1.1.4",
|
||||||
|
"quill-delta": "^3.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/quill-delta": {
|
||||||
|
"version": "3.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
|
||||||
|
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
|
||||||
|
"dependencies": {
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"fast-diff": "1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/quill-delta/node_modules/fast-diff": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
|
||||||
|
},
|
||||||
|
"node_modules/quill/node_modules/clone": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/quill/node_modules/eventemitter3": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
|
||||||
|
},
|
||||||
"node_modules/radix-ui": {
|
"node_modules/radix-ui": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.0.1.tgz",
|
||||||
@@ -19354,6 +19471,19 @@
|
|||||||
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-cookie": {
|
||||||
|
"version": "7.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.1.4.tgz",
|
||||||
|
"integrity": "sha512-wDxxa/HYaSXSMlyWJvJ5uZTzIVtQTPf1gMksFgwAz/2/W3lCtY8r4OChCXMPE7wax0PAdMY97UkNJedGv7KnDw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.5",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"universal-cookie": "^7.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-datepicker": {
|
"node_modules/react-datepicker": {
|
||||||
"version": "6.4.0",
|
"version": "6.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.4.0.tgz",
|
||||||
@@ -19732,6 +19862,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-quill": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/quill": "^1.3.10",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"quill": "^1.3.7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16 || ^17 || ^18",
|
||||||
|
"react-dom": "^16 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-reconciler": {
|
"node_modules/react-reconciler": {
|
||||||
"version": "0.29.0",
|
"version": "0.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
|
||||||
@@ -20082,6 +20226,15 @@
|
|||||||
"react-dom": ">=16.6.0"
|
"react-dom": ">=16.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-web-share": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-web-share/-/react-web-share-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-bGm1TJc6xtC0MhAnYFsrzT4En7l2oAdLTgCK7nk7b4xGTg3L5gOldiPrmYQ8a/dEXNydgekvOj/tfjduIlIRVA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16 || ^17 || ^18",
|
||||||
|
"react-dom": "^16 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reactour": {
|
"node_modules/reactour": {
|
||||||
"version": "1.19.2",
|
"version": "1.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/reactour/-/reactour-1.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/reactour/-/reactour-1.19.2.tgz",
|
||||||
@@ -22701,6 +22854,23 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/universal-cookie": {
|
||||||
|
"version": "7.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.1.4.tgz",
|
||||||
|
"integrity": "sha512-Q+DVJsdykStWRMtXr2Pdj3EF98qZHUH/fXv/gwFz/unyToy1Ek1w5GsWt53Pf38tT8Gbcy5QNsj61Xe9TggP4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/cookie": "^0.6.0",
|
||||||
|
"cookie": "^0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/universal-cookie/node_modules/cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/universalify": {
|
"node_modules/universalify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"radix-ui": "^1.0.1",
|
"radix-ui": "^1.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.2",
|
"react-bootstrap": "^2.10.2",
|
||||||
|
"react-cookie": "^7.1.4",
|
||||||
"react-datepicker": "^6.4.0",
|
"react-datepicker": "^6.4.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"react-konva": "^18.2.10",
|
"react-konva": "^18.2.10",
|
||||||
"react-modal": "^3.16.1",
|
"react-modal": "^3.16.1",
|
||||||
"react-pdf": "^7.7.1",
|
"react-pdf": "^7.7.1",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.0",
|
"react-redux": "^9.1.0",
|
||||||
"react-rnd": "^10.4.1",
|
"react-rnd": "^10.4.1",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
@@ -36,6 +38,7 @@
|
|||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.0",
|
||||||
"react-signature-canvas": "^1.0.6",
|
"react-signature-canvas": "^1.0.6",
|
||||||
"react-tooltip": "^5.26.3",
|
"react-tooltip": "^5.26.3",
|
||||||
|
"react-web-share": "^2.0.2",
|
||||||
"reactour": "^1.19.2",
|
"reactour": "^1.19.2",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-thunk": "^3.1.0",
|
"redux-thunk": "^3.1.0",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<!-- <link rel="icon" type="image/png"
|
<!-- <link rel="icon" type="image/png"
|
||||||
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALlJREFUaEPtmN0NwjAMBpNxYDKYiM1Yp90g93CKStH1NbIdfz921Dker2Pc+Js1cDF7MXAxASMGYkAigBI6vh9ZwoXP53uZoAYcvhwdA3mAVbI2aSb+9zFKU4IURB6j/HoPUIEa2G3iGIAhQQDlAUIoE2diabIklISS0NoFPebo77RF6OenEF3QntOm128he0GKrwHyACFoz2MgBqSGkpAEcHs47oHtN5AFakACqMNjQEMoE8SABFCHn4HE2zGHSLeEAAAAAElFTkSuQmCC"
|
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALlJREFUaEPtmN0NwjAMBpNxYDKYiM1Yp90g93CKStH1NbIdfz921Dker2Pc+Js1cDF7MXAxASMGYkAigBI6vh9ZwoXP53uZoAYcvhwdA3mAVbI2aSb+9zFKU4IURB6j/HoPUIEa2G3iGIAhQQDlAUIoE2diabIklISS0NoFPebo77RF6OenEF3QntOm128he0GKrwHyACFoz2MgBqSGkpAEcHs47oHtN5AFakACqMNjQEMoE8SABFCHn4HE2zGHSLeEAAAAAElFTkSuQmCC"
|
||||||
sizes="40x40" /> -->
|
sizes="40x40" /> -->
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
-->
|
-->
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import DraftDocument from "./components/pdf/DraftDocument";
|
|||||||
import PlaceHolderSign from "./pages/PlaceHolderSign";
|
import PlaceHolderSign from "./pages/PlaceHolderSign";
|
||||||
import PdfRequestFiles from "./pages/PdfRequestFiles";
|
import PdfRequestFiles from "./pages/PdfRequestFiles";
|
||||||
import LazyPage from "./primitives/LazyPage";
|
import LazyPage from "./primitives/LazyPage";
|
||||||
|
import { isEnableSubscription } from "./constant/const";
|
||||||
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
||||||
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
||||||
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
||||||
@@ -113,7 +114,7 @@ function App() {
|
|||||||
path="/forgetpassword"
|
path="/forgetpassword"
|
||||||
element={<LazyPage Page={ForgetPassword} />}
|
element={<LazyPage Page={ForgetPassword} />}
|
||||||
/>
|
/>
|
||||||
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
|
{isEnableSubscription && (
|
||||||
<>
|
<>
|
||||||
<Route
|
<Route
|
||||||
path="/pgsignup"
|
path="/pgsignup"
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ const AddSigner = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_Guest");
|
contactQuery.set("UserRole", "contracts_Guest");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ const AddUser = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_User");
|
contactQuery.set("UserRole", "contracts_User");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,43 @@ import FullScreenButton from "./FullScreenButton";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { checkIsSubscribed, getAppLogo, openInNewTab } from "../constant/Utils";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
|
||||||
const Header = ({ showSidebar }) => {
|
const Header = ({ showSidebar }) => {
|
||||||
const navigation = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
let applogo = localStorage.getItem("appLogo") || "";
|
|
||||||
let username = localStorage.getItem("username");
|
let username = localStorage.getItem("username");
|
||||||
const image = localStorage.getItem("profileImg") || dp;
|
const image = localStorage.getItem("profileImg") || dp;
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(true);
|
||||||
|
const [isPro, setIsPro] = useState(false);
|
||||||
|
const [applogo, setAppLogo] = useState(
|
||||||
|
localStorage.getItem("appLogo") || " "
|
||||||
|
);
|
||||||
|
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
checkSubscription();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
async function checkSubscription() {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
if (getIsSubscribe) {
|
||||||
|
const applogo = await getAppLogo();
|
||||||
|
if (applogo) {
|
||||||
|
setAppLogo(applogo);
|
||||||
|
} else {
|
||||||
|
setAppLogo(localStorage.getItem("appLogo") || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setIsPro(getIsSubscribe);
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const closeDropdown = () => {
|
const closeDropdown = () => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
@@ -43,7 +67,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
|
|
||||||
navigation("/");
|
navigate("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
//handle to close profile drop down menu onclick screen
|
//handle to close profile drop down menu onclick screen
|
||||||
@@ -83,6 +107,21 @@ const Header = ({ showSidebar }) => {
|
|||||||
id="profile-menu"
|
id="profile-menu"
|
||||||
className="flex justify-between items-center gap-x-3"
|
className="flex justify-between items-center gap-x-3"
|
||||||
>
|
>
|
||||||
|
{!isSubscribe && (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="text-xs bg-[#002864] p-2 text-white rounded shadow"
|
||||||
|
onClick={() => navigate("/subscription")}
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isPro && (
|
||||||
|
<div className="w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
|
||||||
|
PRO
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<FullScreenButton />
|
<FullScreenButton />
|
||||||
</div>
|
</div>
|
||||||
@@ -123,7 +162,7 @@ const Header = ({ showSidebar }) => {
|
|||||||
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
navigation("/profile");
|
navigate("/profile");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-regular fa-user"></i> Profile
|
<i className="fa-regular fa-user"></i> Profile
|
||||||
@@ -132,11 +171,19 @@ const Header = ({ showSidebar }) => {
|
|||||||
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
navigation("/changepassword");
|
navigate("/changepassword");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-lock"></i> Change Password
|
<i className="fa-solid fa-lock"></i> Change Password
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
|
||||||
|
onClick={() => {
|
||||||
|
window.open("https://console.opensignlabs.com/");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa-regular fa-id-card"></i> Console
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
className="hover:bg-gray-100 rounded-b-lg py-1 px-2 cursor-pointer font-normal"
|
className="hover:bg-gray-100 rounded-b-lg py-1 px-2 cursor-pointer font-normal"
|
||||||
onClick={closeDropdown}
|
onClick={closeDropdown}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ const DashboardCard = (props) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const listData = res.data?.result.filter(
|
const listData = res.data?.result?.filter(
|
||||||
(x) => x.Signers.length > 0
|
(x) => x.Signers.length > 0
|
||||||
);
|
);
|
||||||
let arr = [];
|
let arr = [];
|
||||||
|
|||||||
@@ -97,11 +97,13 @@ function DashboardReport(props) {
|
|||||||
setIsMoreDocs(false);
|
setIsMoreDocs(false);
|
||||||
}
|
}
|
||||||
setIsNextRecord(false);
|
setIsNextRecord(false);
|
||||||
setList((prevRecord) =>
|
if (!res.data.result.error) {
|
||||||
prevRecord.length > 0
|
setList((prevRecord) =>
|
||||||
? [...prevRecord, ...res.data.result]
|
prevRecord.length > 0
|
||||||
: res.data.result
|
? [...prevRecord, ...res.data.result]
|
||||||
);
|
: res.data.result
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -110,6 +112,7 @@ function DashboardReport(props) {
|
|||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ function DriveBody(props) {
|
|||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
props.setPdfData(updatedData);
|
props.setPdfData(updatedData);
|
||||||
|
props.sortingData(null, null, updatedData);
|
||||||
await axios
|
await axios
|
||||||
.put(
|
.put(
|
||||||
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
|
||||||
@@ -214,8 +215,8 @@ function DriveBody(props) {
|
|||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
: selecFolderId
|
: selecFolderId
|
||||||
? false
|
? false
|
||||||
: true;
|
: true;
|
||||||
if (!checkExist) {
|
if (!checkExist) {
|
||||||
if (moveFolderId) {
|
if (moveFolderId) {
|
||||||
updateData = {
|
updateData = {
|
||||||
@@ -384,6 +385,7 @@ function DriveBody(props) {
|
|||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
|
data-tut={props.dataTutSeventh}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="no img"
|
alt="no img"
|
||||||
@@ -451,6 +453,7 @@ function DriveBody(props) {
|
|||||||
className="pdf-icon"
|
className="pdf-icon"
|
||||||
src={pdfLogo}
|
src={pdfLogo}
|
||||||
onClick={() => checkPdfStatus(data)}
|
onClick={() => checkPdfStatus(data)}
|
||||||
|
data-tut={props.dataTutSixth}
|
||||||
/>
|
/>
|
||||||
{rename === data.objectId ? (
|
{rename === data.objectId ? (
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const AddRoleModal = (props) => {
|
|||||||
margin: "10px 0 10px 5px"
|
margin: "10px 0 10px 5px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
e.g: Hr, Director, Manager, New joinee, Accountant, etc...
|
e.g: Customer, Hr, Director, Manager, Student, etc...
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { themeColor } from "../../constant/const";
|
import { isEnableSubscription, themeColor } from "../../constant/const";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import { radioButtonWidget } from "../../constant/Utils";
|
import { radioButtonWidget } from "../../constant/Utils";
|
||||||
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||||
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
function DropdownWidgetOption(props) {
|
function DropdownWidgetOption(props) {
|
||||||
const [dropdownOptionList, setDropdownOptionList] = useState([
|
const [dropdownOptionList, setDropdownOptionList] = useState([
|
||||||
"option-1",
|
"option-1",
|
||||||
@@ -241,36 +242,59 @@ function DropdownWidgetOption(props) {
|
|||||||
}}
|
}}
|
||||||
className="fa-solid fa-square-plus"
|
className="fa-solid fa-square-plus"
|
||||||
></i>
|
></i>
|
||||||
{props.type === "checkbox" && !props.isSignYourself && (
|
<div>
|
||||||
<>
|
{props.type === "checkbox" && !props.isSignYourself && (
|
||||||
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
<>
|
||||||
Minimun check
|
<label
|
||||||
</label>
|
style={{
|
||||||
<input
|
fontSize: "13px",
|
||||||
required
|
fontWeight: "600",
|
||||||
defaultValue={0}
|
color: !props.isSubscribe && "gray"
|
||||||
value={minCount}
|
}}
|
||||||
onChange={(e) => {
|
>
|
||||||
const count = handleSetMinMax(e);
|
Minimun check
|
||||||
setMinCount(count);
|
</label>
|
||||||
}}
|
{!props.isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
className="drodown-input"
|
<input
|
||||||
/>
|
required
|
||||||
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
defaultValue={0}
|
||||||
Maximum check
|
value={minCount}
|
||||||
</label>
|
onChange={(e) => {
|
||||||
<input
|
const count = handleSetMinMax(e);
|
||||||
required
|
setMinCount(count);
|
||||||
defaultValue={0}
|
}}
|
||||||
value={maxCount}
|
className={
|
||||||
onChange={(e) => {
|
props.isSubscribe || !isEnableSubscription
|
||||||
const count = handleSetMinMax(e);
|
? "drodown-input"
|
||||||
setMaxCount(count);
|
: "disabled drodown-input"
|
||||||
}}
|
}
|
||||||
className="drodown-input"
|
/>
|
||||||
/>
|
<label
|
||||||
</>
|
style={{
|
||||||
)}
|
fontSize: "13px",
|
||||||
|
fontWeight: "600",
|
||||||
|
color: !props.isSubscribe && "gray"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Maximum check
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
defaultValue={0}
|
||||||
|
value={maxCount}
|
||||||
|
onChange={(e) => {
|
||||||
|
const count = handleSetMinMax(e);
|
||||||
|
setMaxCount(count);
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
props.isSubscribe || !isEnableSubscription
|
||||||
|
? "drodown-input"
|
||||||
|
: "disabled drodown-input"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{["dropdown", radioButtonWidget].includes(props.type) && (
|
{["dropdown", radioButtonWidget].includes(props.type) && (
|
||||||
<>
|
<>
|
||||||
@@ -378,13 +402,15 @@ function DropdownWidgetOption(props) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{props.type === "checkbox" && !props.isSignYourself && (
|
{props.type === "checkbox" &&
|
||||||
<PremiumAlertHeader
|
!props.isSignYourself &&
|
||||||
message={
|
!isEnableSubscription && (
|
||||||
"Field validations are free in beta, this feature will incur a fee later."
|
<PremiumAlertHeader
|
||||||
}
|
message={
|
||||||
/>
|
"Field validations are free in beta, this feature will incur a fee later."
|
||||||
)}
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
props.type === "checkbox" && !props.isSignYourself
|
props.type === "checkbox" && !props.isSignYourself
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import "../../styles/AddUser.css";
|
import "../../styles/AddUser.css";
|
||||||
|
import { getFileName } from "../../constant/Utils";
|
||||||
// import SelectFolder from "../../premitives/SelectFolder";
|
// import SelectFolder from "../../premitives/SelectFolder";
|
||||||
|
|
||||||
const EditTemplate = ({ template, onSuccess }) => {
|
const EditTemplate = ({ template, onSuccess }) => {
|
||||||
@@ -45,7 +46,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
|||||||
fontWeight: "700"
|
fontWeight: "700"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{template.URL?.split("/")?.pop()?.split("_")[1]}
|
{getFileName(template.URL)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Quill } from "react-quill";
|
||||||
|
|
||||||
|
// Custom Undo button icon component for Quill editor. You can import it directly
|
||||||
|
// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
|
||||||
|
// handle them correctly
|
||||||
|
const CustomUndo = () => (
|
||||||
|
<svg viewBox="0 0 18 18">
|
||||||
|
<polygon className="ql-fill ql-stroke" points="6 10 4 12 2 10 6 10" />
|
||||||
|
<path
|
||||||
|
className="ql-stroke"
|
||||||
|
d="M8.09,13.91A4.6,4.6,0,0,0,9,14,5,5,0,1,0,4,9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Redo button icon component for Quill editor
|
||||||
|
const CustomRedo = () => (
|
||||||
|
<svg viewBox="0 0 18 18">
|
||||||
|
<polygon className="ql-fill ql-stroke" points="12 10 14 12 16 10 12 10" />
|
||||||
|
<path
|
||||||
|
className="ql-stroke"
|
||||||
|
d="M9.91,13.91A4.6,4.6,0,0,1,9,14a5,5,0,1,1,5-5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Undo and redo functions for Custom Toolbar
|
||||||
|
function undoChange() {
|
||||||
|
this.quill.history.undo();
|
||||||
|
}
|
||||||
|
function redoChange() {
|
||||||
|
this.quill.history.redo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sizes to whitelist and register them
|
||||||
|
const Size = Quill.import("formats/size");
|
||||||
|
Size.whitelist = ["extra-small", "small", "medium", "large"];
|
||||||
|
Quill.register(Size, true);
|
||||||
|
|
||||||
|
// Add fonts to whitelist and register them
|
||||||
|
const Font = Quill.import("formats/font");
|
||||||
|
Font.whitelist = [
|
||||||
|
"arial",
|
||||||
|
"comic-sans",
|
||||||
|
"courier-new",
|
||||||
|
"georgia",
|
||||||
|
"helvetica",
|
||||||
|
"lucida"
|
||||||
|
];
|
||||||
|
Quill.register(Font, true);
|
||||||
|
|
||||||
|
// Modules object for setting up the Quill editor
|
||||||
|
export const module1 = {
|
||||||
|
toolbar: {
|
||||||
|
container: "#toolbar1",
|
||||||
|
handlers: {
|
||||||
|
undo: undoChange,
|
||||||
|
redo: redoChange
|
||||||
|
}
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
delay: 500,
|
||||||
|
maxStack: 100,
|
||||||
|
userOnly: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Formats objects for setting up the Quill editor
|
||||||
|
export const formats = [
|
||||||
|
"header",
|
||||||
|
"font",
|
||||||
|
"size",
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"underline",
|
||||||
|
"align",
|
||||||
|
"strike",
|
||||||
|
"script",
|
||||||
|
"blockquote",
|
||||||
|
"background",
|
||||||
|
"list",
|
||||||
|
"bullet",
|
||||||
|
"indent",
|
||||||
|
"link",
|
||||||
|
"image",
|
||||||
|
"color",
|
||||||
|
"code-block"
|
||||||
|
];
|
||||||
|
// Quill Toolbar component
|
||||||
|
export const QuillToolbar = ({ containerId }) => (
|
||||||
|
<div id={containerId}>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<select className="ql-font" defaultValue="arial">
|
||||||
|
<option value="arial">Arial</option>
|
||||||
|
<option value="comic-sans">Comic Sans</option>
|
||||||
|
<option value="courier-new">Courier New</option>
|
||||||
|
<option value="georgia">Georgia</option>
|
||||||
|
<option value="helvetica">Helvetica</option>
|
||||||
|
<option value="lucida">Lucida</option>
|
||||||
|
</select>
|
||||||
|
<select className="ql-size" defaultValue="medium">
|
||||||
|
<option value="extra-small">Size 1</option>
|
||||||
|
<option value="small">Size 2</option>
|
||||||
|
<option value="medium">Size 3</option>
|
||||||
|
<option value="large">Size 4</option>
|
||||||
|
</select>
|
||||||
|
<select className="ql-header" defaultValue="3">
|
||||||
|
<option value="1">Heading</option>
|
||||||
|
<option value="2">Subheading</option>
|
||||||
|
<option value="3">Normal</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-bold" />
|
||||||
|
<button className="ql-italic" />
|
||||||
|
<button className="ql-underline" />
|
||||||
|
<button className="ql-strike" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-list" value="ordered" />
|
||||||
|
<button className="ql-list" value="bullet" />
|
||||||
|
<button className="ql-indent" value="-1" />
|
||||||
|
<button className="ql-indent" value="+1" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-script" value="super" />
|
||||||
|
<button className="ql-script" value="sub" />
|
||||||
|
<button className="ql-blockquote" />
|
||||||
|
<button className="ql-direction" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<select className="ql-align" />
|
||||||
|
<select className="ql-color" />
|
||||||
|
<select className="ql-background" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-link" />
|
||||||
|
<button className="ql-image" />
|
||||||
|
<button className="ql-video" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-formula" />
|
||||||
|
<button className="ql-code-block" />
|
||||||
|
<button className="ql-clean" />
|
||||||
|
</span>
|
||||||
|
<span className="ql-formats">
|
||||||
|
<button className="ql-undo">
|
||||||
|
<CustomUndo />
|
||||||
|
</button>
|
||||||
|
<button className="ql-redo">
|
||||||
|
<CustomRedo />
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default QuillToolbar;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Tooltip from "../../primitives/Tooltip";
|
||||||
|
|
||||||
|
import ReactQuill from "react-quill";
|
||||||
|
import "react-quill/dist/quill.snow.css";
|
||||||
|
import EditorToolbar, { module1, formats } from "./EditorToolbar";
|
||||||
|
|
||||||
|
export function EmailBody(props) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<div className={`flex justify-center py-1 p-2`}>
|
||||||
|
<div className=" flex flex-col">
|
||||||
|
<form>
|
||||||
|
<div className="text-lg font-normal text-black">
|
||||||
|
<div className=" m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md">
|
||||||
|
<label className="text-sm ml-2">
|
||||||
|
Subject <Tooltip message={"email subject"} />
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
value={props.requestSubject}
|
||||||
|
onChange={(e) => props.setRequestSubject(e.target.value)}
|
||||||
|
placeholder="${senderName} has requested you to sign ${documentName}"
|
||||||
|
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||||
|
/>
|
||||||
|
<label className="text-sm ml-2 mt-3">
|
||||||
|
Body <Tooltip message={"email body"} />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="px-3 py-2 w-full focus:outline-none text-xs">
|
||||||
|
<EditorToolbar containerId="toolbar1" />
|
||||||
|
<ReactQuill
|
||||||
|
theme="snow"
|
||||||
|
value={props.requestBody}
|
||||||
|
// value={typedText}
|
||||||
|
placeholder="add body of email "
|
||||||
|
// readOnly={loading}
|
||||||
|
// onChangeSelection={handleTextSelection} // Listen for text selection
|
||||||
|
ref={props.editorRef}
|
||||||
|
modules={module1}
|
||||||
|
formats={formats}
|
||||||
|
onChange={props.handleOnchangeRequest}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,7 +15,8 @@ function EmailComponent({
|
|||||||
setSuccessEmail,
|
setSuccessEmail,
|
||||||
pdfName,
|
pdfName,
|
||||||
sender,
|
sender,
|
||||||
setIsAlert
|
setIsAlert,
|
||||||
|
extUserId
|
||||||
}) {
|
}) {
|
||||||
const [emailList, setEmailList] = useState([]);
|
const [emailList, setEmailList] = useState([]);
|
||||||
const [emailValue, setEmailValue] = useState();
|
const [emailValue, setEmailValue] = useState();
|
||||||
@@ -38,6 +39,7 @@ function EmailComponent({
|
|||||||
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
||||||
const themeBGcolor = themeColor;
|
const themeBGcolor = themeColor;
|
||||||
let params = {
|
let params = {
|
||||||
|
extUserId: extUserId,
|
||||||
pdfName: pdfName,
|
pdfName: pdfName,
|
||||||
url: pdfUrl,
|
url: pdfUrl,
|
||||||
recipient: emailList[i],
|
recipient: emailList[i],
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import PrevNext from "./PrevNext";
|
import PrevNext from "./PrevNext";
|
||||||
import { PDFDownloadLink } from "@react-pdf/renderer";
|
|
||||||
import Certificate from "./Certificate";
|
|
||||||
import printModule from "print-js";
|
import printModule from "print-js";
|
||||||
import { getBase64FromUrl } from "../../constant/Utils";
|
import { getBase64FromUrl } from "../../constant/Utils";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
@@ -9,18 +7,17 @@ import "../../styles/signature.css";
|
|||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { themeColor } from "../../constant/const";
|
import { themeColor } from "../../constant/const";
|
||||||
|
import Certificate from "./Certificate";
|
||||||
|
import { PDFDownloadLink } from "@react-pdf/renderer";
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
isPdfRequestFiles,
|
isPdfRequestFiles,
|
||||||
isPlaceholder,
|
isPlaceholder,
|
||||||
recipient,
|
|
||||||
setIsDecline,
|
setIsDecline,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
isAlreadySign,
|
|
||||||
allPages,
|
allPages,
|
||||||
changePage,
|
changePage,
|
||||||
pdfUrl,
|
pdfUrl,
|
||||||
documentStatus,
|
|
||||||
embedWidgetsData,
|
embedWidgetsData,
|
||||||
pdfDetails,
|
pdfDetails,
|
||||||
signerPos,
|
signerPos,
|
||||||
@@ -94,8 +91,21 @@ function Header({
|
|||||||
// Replace spaces with underscore
|
// Replace spaces with underscore
|
||||||
return pdfName.replace(/ /g, "_");
|
return pdfName.replace(/ /g, "_");
|
||||||
};
|
};
|
||||||
//certificate generate and download component in mobile view
|
|
||||||
const CertificateDropDown = () => {
|
//handle download signed pdf
|
||||||
|
const handleDownloadCertificate = async () => {
|
||||||
|
if (pdfDetails?.length > 0 && pdfDetails[0]?.CertificateUrl) {
|
||||||
|
try {
|
||||||
|
await fetch(pdfDetails[0] && pdfDetails[0]?.CertificateUrl);
|
||||||
|
const certificateUrl = pdfDetails[0] && pdfDetails[0]?.CertificateUrl;
|
||||||
|
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in download in certificate", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const GenerateCertificate = () => {
|
||||||
//after generate download certifcate pdf
|
//after generate download certifcate pdf
|
||||||
const handleDownload = (pdfBlob, fileName) => {
|
const handleDownload = (pdfBlob, fileName) => {
|
||||||
if (pdfBlob) {
|
if (pdfBlob) {
|
||||||
@@ -122,76 +132,20 @@ function Header({
|
|||||||
document={<Certificate pdfData={pdfDetails} />}
|
document={<Certificate pdfData={pdfDetails} />}
|
||||||
>
|
>
|
||||||
{({ blob, loading }) => (
|
{({ blob, loading }) => (
|
||||||
<>
|
|
||||||
{loading ? (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
border: "none",
|
|
||||||
backgroundColor: "#fff"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa-solid fa-award"
|
|
||||||
style={{ marginRight: "2px" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Certificate
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
style={{ border: "none", backgroundColor: "#fff" }}
|
|
||||||
onClick={() =>
|
|
||||||
handleDownload(
|
|
||||||
blob,
|
|
||||||
`completion certificate-${
|
|
||||||
pdfDetails[0] && pdfDetails[0].Name
|
|
||||||
}.pdf`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa-solid fa-award"
|
|
||||||
style={{ marginRight: "2px" }}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Certificate
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</PDFDownloadLink>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
const CertificateComponent = () => {
|
|
||||||
return (
|
|
||||||
<PDFDownloadLink
|
|
||||||
style={{ textDecoration: "none" }}
|
|
||||||
document={<Certificate pdfData={pdfDetails} />}
|
|
||||||
fileName={`completion certificate-${
|
|
||||||
pdfDetails[0] && pdfDetails[0].Name
|
|
||||||
}.pdf`}
|
|
||||||
>
|
|
||||||
{({ loading }) => (
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
onClick={() =>
|
||||||
className="defaultBtn certificateBtn"
|
handleDownload(
|
||||||
|
blob,
|
||||||
|
`completion certificate-${
|
||||||
|
pdfDetails[0] && pdfDetails[0].Name
|
||||||
|
}.pdf`
|
||||||
|
)
|
||||||
|
}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
style={{
|
className=" md:bg-[#08bc66] border-none focus:outline-none flex flex-row items-center md:shadow md:rounded-[3px] py-[3px] md:px-[11px] md:text-white text-black md:font-[500] text-[13px] mr-[5px]"
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa-solid fa-award py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa-solid fa-award"
|
<span className="md:hidden lg:block ml-1">Certificate</span>
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Certificate
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</PDFDownloadLink>
|
</PDFDownloadLink>
|
||||||
@@ -210,11 +164,7 @@ function Header({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="preBtn2">
|
<div className="preBtn2">
|
||||||
<div
|
<div onClick={() => navigate(-1)}>
|
||||||
onClick={() => {
|
|
||||||
navigate(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i
|
<i
|
||||||
className="fa fa-arrow-left"
|
className="fa fa-arrow-left"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -266,7 +216,6 @@ function Header({
|
|||||||
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
|
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content
|
<DropdownMenu.Content
|
||||||
className="DropdownMenuContent"
|
className="DropdownMenuContent"
|
||||||
@@ -290,42 +239,53 @@ function Header({
|
|||||||
Download
|
Download
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{recipient && pdfDetails[0] && pdfDetails.length > 0 ? (
|
{isCompleted && (
|
||||||
<DropdownMenu.Item className="DropdownMenuItem">
|
<>
|
||||||
<CertificateDropDown />
|
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
|
||||||
</DropdownMenu.Item>
|
|
||||||
) : isPdfRequestFiles &&
|
|
||||||
alreadySign &&
|
|
||||||
isCompleted.isCertificate ? (
|
|
||||||
<DropdownMenu.Item className="DropdownMenuItem">
|
|
||||||
<CertificateDropDown />
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
) : (
|
|
||||||
isSignYourself && (
|
|
||||||
<>
|
|
||||||
<DropdownMenu.Item className="DropdownMenuItem">
|
|
||||||
<CertificateDropDown />
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="DropdownMenuItem"
|
className="DropdownMenuItem"
|
||||||
onClick={() => setIsEmail(true)}
|
onClick={() => handleDownloadCertificate()}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
border: "none",
|
||||||
flexDirection: "row"
|
backgroundColor: "#fff"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-envelope"
|
className="fa-solid fa-award"
|
||||||
style={{ marginRight: "2px" }}
|
style={{ marginRight: "2px" }}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></i>
|
></i>
|
||||||
Mail
|
Certificate
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</>
|
) : (
|
||||||
)
|
<DropdownMenu.Item className="DropdownMenuItem">
|
||||||
|
<GenerateCertificate />
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{isSignYourself && (
|
||||||
|
<DropdownMenu.Item
|
||||||
|
className="DropdownMenuItem"
|
||||||
|
onClick={() => setIsEmail(true)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa fa-envelope"
|
||||||
|
style={{ marginRight: "2px" }}
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
Mail
|
||||||
|
</div>
|
||||||
|
</DropdownMenu.Item>
|
||||||
)}
|
)}
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="DropdownMenuItem"
|
className="DropdownMenuItem"
|
||||||
@@ -337,7 +297,6 @@ function Header({
|
|||||||
flexDirection: "row"
|
flexDirection: "row"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{" "}
|
|
||||||
<i
|
<i
|
||||||
className="fa fa-print"
|
className="fa fa-print"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -416,217 +375,126 @@ function Header({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="signatureHeader headerBtn">
|
<div className="flex flex-wrap justify-between items-center mt-[5px]">
|
||||||
<PrevNext
|
<PrevNext
|
||||||
pageNumber={pageNumber}
|
pageNumber={pageNumber}
|
||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
changePage={changePage}
|
changePage={changePage}
|
||||||
/>
|
/>
|
||||||
|
{isPlaceholder ? (
|
||||||
{recipient ? (
|
|
||||||
pdfUrl || isAlreadySign.mssg ? (
|
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
|
||||||
{pdfDetails && pdfDetails.length > 0 && (
|
|
||||||
<CertificateComponent />
|
|
||||||
)}
|
|
||||||
<button
|
|
||||||
onClick={handleToPrint}
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
className="defaultBtn printBtn"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-print"
|
|
||||||
style={{
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px",
|
|
||||||
color: "white"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Print
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
className="defaultBtn downloadBtn"
|
|
||||||
onClick={() => handleDownloadPdf()}
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="fa fa-download"
|
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Download
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
|
||||||
<button
|
|
||||||
style={{
|
|
||||||
background: "#de4337"
|
|
||||||
}}
|
|
||||||
className="finishBtn hoverCss"
|
|
||||||
onClick={() => {
|
|
||||||
handleDeclinePdfAlert();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Decline
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
data-tut="reactourThird"
|
|
||||||
style={{
|
|
||||||
background: !pdfUrl ? "#188ae2" : "#d3edeb"
|
|
||||||
}}
|
|
||||||
className="finishBtn sendHover"
|
|
||||||
onClick={() => {
|
|
||||||
if (!pdfUrl) {
|
|
||||||
embedWidgetsData();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Finish
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
) : isPlaceholder ? (
|
|
||||||
<>
|
<>
|
||||||
{!isMailSend &&
|
<div className="flex mx-[100px] lg:mx-0 order-last lg:order-none">
|
||||||
signersdata.length > 0 &&
|
{!isMailSend &&
|
||||||
signersdata.length !== filterPrefill.length && (
|
signersdata.length > 0 &&
|
||||||
<div>
|
signersdata.length !== filterPrefill.length && (
|
||||||
{filterPrefill.length === 0 ? (
|
<div>
|
||||||
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
{filterPrefill.length === 0 ? (
|
||||||
Add {signersdata.length - filterPrefill.length}{" "}
|
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
||||||
recipients signature
|
Add {signersdata.length - filterPrefill.length}{" "}
|
||||||
</span>
|
recipients signature
|
||||||
) : (
|
</span>
|
||||||
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
) : (
|
||||||
Add {signersdata.length - filterPrefill.length} more
|
<span style={{ fontSize: "13px", color: "#f5405e" }}>
|
||||||
recipients signature
|
Add {signersdata.length - filterPrefill.length} more
|
||||||
</span>
|
recipients signature
|
||||||
)}
|
</span>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
</div>
|
||||||
|
<div className="flex">
|
||||||
{setIsEditTemplate && (
|
{setIsEditTemplate && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsEditTemplate(true)}
|
onClick={() => setIsEditTemplate(true)}
|
||||||
style={{
|
className="outline-none border-none text-center mr-[5px]"
|
||||||
border: "none",
|
|
||||||
outline: "none",
|
|
||||||
textAlign: "center"
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-gear fa-lg"></i>
|
<i className="fa-solid fa-gear fa-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => navigate(-1)}
|
||||||
navigate(-1);
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn backBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white"
|
||||||
>
|
>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
disabled={isMailSend && true}
|
disabled={isMailSend && true}
|
||||||
data-tut="reactourFour"
|
data-tut="reactourFour"
|
||||||
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] font-[500] text-sm mr-[5px]"
|
||||||
style={{
|
style={{
|
||||||
background: isMailSend ? "rgb(203, 203, 203)" : "#188ae2",
|
background: isMailSend ? "rgb(203, 203, 203)" : "#188ae2",
|
||||||
color: isMailSend && "rgb(77, 75, 75)"
|
color: isMailSend ? "rgb(77, 75, 75)" : "white"
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
alertSendEmail();
|
alertSendEmail();
|
||||||
}}
|
}}
|
||||||
className={isMailSend ? "sendMail" : "sendMail sendHover"}
|
|
||||||
>
|
>
|
||||||
{completeBtnTitle ? completeBtnTitle : "Send"}
|
{completeBtnTitle
|
||||||
|
? completeBtnTitle
|
||||||
|
: isMailSend
|
||||||
|
? "Sent"
|
||||||
|
: "Send"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : isPdfRequestFiles ? (
|
) : isPdfRequestFiles ? (
|
||||||
alreadySign ? (
|
alreadySign ? (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
{isCompleted.isCertificate && <CertificateComponent />}
|
{isCompleted && (
|
||||||
|
<>
|
||||||
|
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleDownloadCertificate()}
|
||||||
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-award py-[3px]"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span className="hidden lg:block ml-1">
|
||||||
|
Certificate
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<GenerateCertificate />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleToPrint}
|
onClick={handleToPrint}
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn printBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]"
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa fa-print py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa fa-print"
|
<span className="hidden lg:block ml-1">Print</span>
|
||||||
style={{
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px",
|
|
||||||
color: "white"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Print
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn downloadBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]"
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
onClick={() => handleDownloadPdf()}
|
onClick={() => handleDownloadPdf()}
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa fa-download py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa fa-download"
|
<span className="hidden lg:block ml-1">Download</span>
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Download
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div className="flex">
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => navigate(-1)}
|
||||||
navigate(-1);
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn backBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white"
|
||||||
>
|
>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
{currentSigner && (
|
{currentSigner && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{ background: "#de4337" }}
|
||||||
background: "#de4337"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]"
|
||||||
}}
|
|
||||||
className="finishBtn hoverCss"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleDeclinePdfAlert();
|
handleDeclinePdfAlert();
|
||||||
}}
|
}}
|
||||||
@@ -638,7 +506,7 @@ function Header({
|
|||||||
background: "#188ae2"
|
background: "#188ae2"
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className="finishBtn sendHover"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
embedWidgetsData();
|
embedWidgetsData();
|
||||||
}}
|
}}
|
||||||
@@ -649,93 +517,69 @@ function Header({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
) : pdfUrl || (documentStatus && documentStatus.isCompleted) ? (
|
) : isCompleted ? (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
<CertificateComponent />
|
{isCompleted && (
|
||||||
|
<>
|
||||||
|
{pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleDownloadCertificate()}
|
||||||
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-award py-[3px]"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
<span className="hidden lg:block ml-1">Certificate</span>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<GenerateCertificate />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={handleToPrint}
|
onClick={handleToPrint}
|
||||||
type="button"
|
type="button"
|
||||||
style={{
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]"
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
className="defaultBtn printBtn"
|
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa fa-print py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa fa-print"
|
<span className="hidden lg:block ml-1">Print</span>
|
||||||
style={{
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px",
|
|
||||||
color: "white"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Print
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn downloadBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]"
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
marginLeft: "10px"
|
|
||||||
}}
|
|
||||||
onClick={() => handleDownloadPdf()}
|
onClick={() => handleDownloadPdf()}
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa fa-download py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa fa-download"
|
<span className="hidden lg:block ml-1">Download</span>
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Download
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn mailBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#3ba7e5]"
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
marginLeft: "10px"
|
|
||||||
}}
|
|
||||||
onClick={() => setIsEmail(true)}
|
onClick={() => setIsEmail(true)}
|
||||||
>
|
>
|
||||||
<i
|
<i className="fa fa-envelope py-[3px]" aria-hidden="true"></i>
|
||||||
className="fa fa-envelope"
|
<span className="hidden lg:block ml-1">Mail</span>
|
||||||
style={{
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
marginRight: "3px"
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
Mail
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div className="flex">
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className="defaultBtn backBtn"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white"
|
||||||
>
|
>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
background: "#188ae2"
|
background: "#188ae2"
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className="finishBtn sendHover"
|
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!pdfUrl) {
|
if (!pdfUrl) {
|
||||||
embedWidgetsData();
|
embedWidgetsData();
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ function Placeholder(props) {
|
|||||||
|
|
||||||
{props.pos.type !== textWidget && !props.isSignYourself && (
|
{props.pos.type !== textWidget && !props.isSignYourself && (
|
||||||
<i
|
<i
|
||||||
data-tut="reactourLinkUser"
|
data-tut="assignSigner"
|
||||||
className="fa-regular fa-user signUserIcon"
|
className="fa-regular fa-user signUserIcon"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -542,7 +542,15 @@ function Placeholder(props) {
|
|||||||
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
||||||
key={props.pos.key}
|
key={props.pos.key}
|
||||||
lockAspectRatio={
|
lockAspectRatio={
|
||||||
props.pos.type !== textWidget &&
|
// props.pos.type !== textWidget
|
||||||
|
![
|
||||||
|
textWidget,
|
||||||
|
"email",
|
||||||
|
"name",
|
||||||
|
"company",
|
||||||
|
"job title",
|
||||||
|
textInputWidget
|
||||||
|
].includes(props.pos.type) &&
|
||||||
(props.pos.Width
|
(props.pos.Width
|
||||||
? props.pos.Width / props.pos.Height
|
? props.pos.Width / props.pos.Height
|
||||||
: defaultWidthHeight(props.pos.type).width /
|
: defaultWidthHeight(props.pos.type).width /
|
||||||
|
|||||||
@@ -38,15 +38,17 @@ function PlaceholderType(props) {
|
|||||||
"December"
|
"December"
|
||||||
];
|
];
|
||||||
const validateExpression = (regexValidation) => {
|
const validateExpression = (regexValidation) => {
|
||||||
let regexObject = regexValidation;
|
if (textValue) {
|
||||||
if (props.pos?.options.validation.type === "regex") {
|
let regexObject = regexValidation;
|
||||||
regexObject = RegexParser(regexValidation);
|
if (props.pos?.options?.validation?.type === "regex") {
|
||||||
}
|
regexObject = RegexParser(regexValidation);
|
||||||
// new RegExp(regexValidation);
|
}
|
||||||
let isValidate = regexObject.test(textValue);
|
// new RegExp(regexValidation);
|
||||||
if (!isValidate) {
|
let isValidate = regexObject.test(textValue);
|
||||||
props?.setValidateAlert(true);
|
if (!isValidate) {
|
||||||
inputRef.current.focus();
|
props?.setValidateAlert(true);
|
||||||
|
inputRef.current.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ function PlaceholderType(props) {
|
|||||||
validateExpression(regexValidation);
|
validateExpression(regexValidation);
|
||||||
break;
|
break;
|
||||||
case "number":
|
case "number":
|
||||||
regexValidation = /^\d+$/;
|
regexValidation = /^[0-9\s]*$/;
|
||||||
validateExpression(regexValidation);
|
validateExpression(regexValidation);
|
||||||
break;
|
break;
|
||||||
case "text":
|
case "text":
|
||||||
@@ -87,11 +89,11 @@ function PlaceholderType(props) {
|
|||||||
case "number":
|
case "number":
|
||||||
setValidatePlaceholder("12345");
|
setValidatePlaceholder("12345");
|
||||||
break;
|
break;
|
||||||
case textInputWidget:
|
case "text":
|
||||||
setValidatePlaceholder("enter text");
|
setValidatePlaceholder("please enter text");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setValidatePlaceholder("enter text");
|
setValidatePlaceholder("please enter value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ function PlaceholderType(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [props.pos]);
|
}, [props.pos?.options?.defaultValue]);
|
||||||
|
|
||||||
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
||||||
<div
|
<div
|
||||||
@@ -288,7 +290,7 @@ function PlaceholderType(props) {
|
|||||||
};
|
};
|
||||||
//handle height on enter press in text area
|
//handle height on enter press in text area
|
||||||
const handleEnterPress = (e) => {
|
const handleEnterPress = (e) => {
|
||||||
const height = 15;
|
const height = 18;
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
//function to save height of text area
|
//function to save height of text area
|
||||||
onChangeHeightOfTextArea(
|
onChangeHeightOfTextArea(
|
||||||
@@ -403,19 +405,12 @@ function PlaceholderType(props) {
|
|||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
return props.isSignYourself ||
|
return props.isSignYourself ||
|
||||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
<input
|
<textarea
|
||||||
className="inputPlaceholder"
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={validatePlaceholder}
|
placeholder={validatePlaceholder || "please enter value"}
|
||||||
style={{ fontSize: calculateFontSize() }}
|
rows={1}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
value={textValue}
|
value={textValue}
|
||||||
type="text"
|
|
||||||
tabIndex="0"
|
|
||||||
disabled={
|
|
||||||
props.isNeedSign && props.data?.signerObjId !== props.signerObjId
|
|
||||||
? true
|
|
||||||
: props.isPlaceholder
|
|
||||||
}
|
|
||||||
onBlur={handleInputBlur}
|
onBlur={handleInputBlur}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setTextValue(e.target.value);
|
setTextValue(e.target.value);
|
||||||
@@ -429,6 +424,13 @@ function PlaceholderType(props) {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -506,15 +508,12 @@ function PlaceholderType(props) {
|
|||||||
case "name":
|
case "name":
|
||||||
return props.isSignYourself ||
|
return props.isSignYourself ||
|
||||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
<input
|
<textarea
|
||||||
tabIndex="0"
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={"name"}
|
placeholder={"name"}
|
||||||
style={{ fontSize: calculateFontSize() }}
|
rows={1}
|
||||||
className="inputPlaceholder"
|
onKeyDown={handleEnterPress}
|
||||||
type="text"
|
|
||||||
value={textValue}
|
value={textValue}
|
||||||
onBlur={handleInputBlur}
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const isDefault = false;
|
const isDefault = false;
|
||||||
handleTextValid(e);
|
handleTextValid(e);
|
||||||
@@ -528,6 +527,13 @@ function PlaceholderType(props) {
|
|||||||
isDefault
|
isDefault
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -542,14 +548,12 @@ function PlaceholderType(props) {
|
|||||||
case "company":
|
case "company":
|
||||||
return props.isSignYourself ||
|
return props.isSignYourself ||
|
||||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
<input
|
<textarea
|
||||||
className="inputPlaceholder"
|
|
||||||
type="text"
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={"company"}
|
placeholder="Enter text"
|
||||||
style={{ fontSize: calculateFontSize() }}
|
rows={1}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
value={textValue}
|
value={textValue}
|
||||||
onBlur={handleInputBlur}
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handleTextValid(e);
|
handleTextValid(e);
|
||||||
onChangeInput(
|
onChangeInput(
|
||||||
@@ -562,6 +566,13 @@ function PlaceholderType(props) {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -576,14 +587,12 @@ function PlaceholderType(props) {
|
|||||||
case "job title":
|
case "job title":
|
||||||
return props.isSignYourself ||
|
return props.isSignYourself ||
|
||||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
<input
|
<textarea
|
||||||
className="inputPlaceholder"
|
|
||||||
type="text"
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={"job title"}
|
placeholder={"job title"}
|
||||||
style={{ fontSize: calculateFontSize() }}
|
rows={1}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
value={textValue}
|
value={textValue}
|
||||||
onBlur={handleInputBlur}
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handleTextValid(e);
|
handleTextValid(e);
|
||||||
onChangeInput(
|
onChangeInput(
|
||||||
@@ -596,6 +605,13 @@ function PlaceholderType(props) {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -692,12 +708,11 @@ function PlaceholderType(props) {
|
|||||||
case "email":
|
case "email":
|
||||||
return props.isSignYourself ||
|
return props.isSignYourself ||
|
||||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||||
<input
|
<textarea
|
||||||
className="inputPlaceholder"
|
|
||||||
type="text"
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={"email"}
|
placeholder={"enter email"}
|
||||||
style={{ fontSize: calculateFontSize() }}
|
rows={1}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
value={textValue}
|
value={textValue}
|
||||||
onBlur={handleInputBlur}
|
onBlur={handleInputBlur}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -712,6 +727,13 @@ function PlaceholderType(props) {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? "labelTextArea labelWidthMobile"
|
||||||
|
: "labelTextArea labelWidthDesktop"
|
||||||
|
}
|
||||||
|
style={{ whiteSpace: "pre-wrap" }}
|
||||||
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@@ -760,7 +782,7 @@ function PlaceholderType(props) {
|
|||||||
case textWidget:
|
case textWidget:
|
||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
placeholder="Enter label"
|
placeholder="Enter text"
|
||||||
rows={1}
|
rows={1}
|
||||||
onKeyDown={handleEnterPress}
|
onKeyDown={handleEnterPress}
|
||||||
value={textValue}
|
value={textValue}
|
||||||
@@ -782,7 +804,7 @@ function PlaceholderType(props) {
|
|||||||
? "labelTextArea labelWidthMobile"
|
? "labelTextArea labelWidthMobile"
|
||||||
: "labelTextArea labelWidthDesktop"
|
: "labelTextArea labelWidthDesktop"
|
||||||
}
|
}
|
||||||
style={{ whiteSpace: "pre-wrap" }}
|
style={{ whiteSpace: "pre-wrap", overflow: "hidden" }}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
function PrevNext({ pageNumber, allPages, changePage }) {
|
function PrevNext({ pageNumber, allPages, changePage }) {
|
||||||
//for go to previous page
|
//for go to previous page
|
||||||
@@ -14,41 +15,35 @@ function PrevNext({ pageNumber, allPages, changePage }) {
|
|||||||
<div>
|
<div>
|
||||||
<div className="preBtn1">
|
<div className="preBtn1">
|
||||||
<button
|
<button
|
||||||
style={{
|
className="py-[3px] px-[10px] text-xs bg-[#d3edeb] font-[600] mr-[5px]"
|
||||||
padding: "3px 20px ",
|
|
||||||
fontSize: "10px",
|
|
||||||
background: "#d3edeb",
|
|
||||||
fontWeight: "600",
|
|
||||||
|
|
||||||
border: "0px",
|
|
||||||
marginRight: "5px"
|
|
||||||
}}
|
|
||||||
disabled={pageNumber <= 1}
|
disabled={pageNumber <= 1}
|
||||||
onClick={previousPage}
|
onClick={previousPage}
|
||||||
>
|
>
|
||||||
Prev
|
<span className="block lg:hidden">
|
||||||
|
<i
|
||||||
|
className="fa fa-backward"
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{ color: themeColor, cursor: "pointer" }}
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<span className="lg:block hidden">Prev</span>
|
||||||
</button>
|
</button>
|
||||||
<span
|
<span className="text-xs font-[500]">
|
||||||
style={{
|
|
||||||
fontSize: "13px",
|
|
||||||
fontWeight: "600"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
|
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
style={{
|
className="py-[3px] px-[10px] text-xs bg-[#d3edeb] font-[600] ml-[5px]"
|
||||||
padding: "3px 20px ",
|
|
||||||
fontSize: "10px",
|
|
||||||
background: "#d3edeb",
|
|
||||||
fontWeight: "600",
|
|
||||||
marginLeft: "5px",
|
|
||||||
border: "0px"
|
|
||||||
}}
|
|
||||||
disabled={pageNumber >= allPages}
|
disabled={pageNumber >= allPages}
|
||||||
onClick={nextPage}
|
onClick={nextPage}
|
||||||
>
|
>
|
||||||
Next
|
<span className="block lg:hidden">
|
||||||
|
<i
|
||||||
|
className="fa fa-forward"
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{ color: themeColor, cursor: "pointer" }}
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<span className="lg:block hidden">Next</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -230,7 +230,11 @@ const RecipientList = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{obj.Name && <span className={"useEmail"}>{obj.Role}</span>}
|
{obj.Name && (
|
||||||
|
<span className={"useEmail"}>
|
||||||
|
{obj?.Role || obj?.Email}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isMobile && props.sendInOrder && (
|
{isMobile && props.sendInOrder && (
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { Document, Page } from "react-pdf";
|
|||||||
import { themeColor } from "../../constant/const";
|
import { themeColor } from "../../constant/const";
|
||||||
|
|
||||||
function RenderAllPdfPage({
|
function RenderAllPdfPage({
|
||||||
pdfUrl,
|
|
||||||
signPdfUrl,
|
signPdfUrl,
|
||||||
allPages,
|
allPages,
|
||||||
setAllPages,
|
setAllPages,
|
||||||
@@ -50,8 +49,7 @@ function RenderAllPdfPage({
|
|||||||
<Document
|
<Document
|
||||||
loading={"Loading Document.."}
|
loading={"Loading Document.."}
|
||||||
onLoadSuccess={onDocumentLoad}
|
onLoadSuccess={onDocumentLoad}
|
||||||
file={pdfUrl ? pdfUrl : signPdfUrl}
|
file={signPdfUrl}
|
||||||
// file="https://api.printnode.com/static/test/pdf/multipage.pdf"
|
|
||||||
>
|
>
|
||||||
{Array.from(new Array(allPages), (el, index) => (
|
{Array.from(new Array(allPages), (el, index) => (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -296,9 +296,11 @@ function RenderPdf({
|
|||||||
{type && (
|
{type && (
|
||||||
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
|
||||||
)}
|
)}
|
||||||
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
{Role && (
|
||||||
{`(${Role})`}
|
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
|
||||||
</div>
|
{`(${Role})`}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { themeColor } from "../../constant/const";
|
import { themeColor } from "../../constant/const";
|
||||||
import RecipientList from "./RecipientList";
|
import RecipientList from "./RecipientList";
|
||||||
|
import { Tooltip } from "react-tooltip";
|
||||||
|
|
||||||
function SignerListPlace(props) {
|
function SignerListPlace(props) {
|
||||||
return (
|
return (
|
||||||
@@ -13,12 +14,64 @@ function SignerListPlace(props) {
|
|||||||
>
|
>
|
||||||
<span className="signedStyle">
|
<span className="signedStyle">
|
||||||
{props.title ? props.title : "Recipients"}
|
{props.title ? props.title : "Recipients"}
|
||||||
|
<span className="absolute text-xs z-[30] mt-1 ml-0.5">
|
||||||
|
{props?.title === "Roles" && (
|
||||||
|
<>
|
||||||
|
<a data-tooltip-id="my-tooltip">
|
||||||
|
<sup>
|
||||||
|
<i
|
||||||
|
className="fa-solid fa-question rounded-full"
|
||||||
|
style={{
|
||||||
|
borderColor: "white",
|
||||||
|
color: "white",
|
||||||
|
fontSize: 11,
|
||||||
|
borderWidth: 1.5,
|
||||||
|
padding: "1px 3px"
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</sup>
|
||||||
|
</a>
|
||||||
|
<Tooltip id="my-tooltip">
|
||||||
|
<div className="max-w-[450px]">
|
||||||
|
<p className="font-bold">What are template roles?</p>
|
||||||
|
<p>
|
||||||
|
Begin by specifying each role needed for the completion of
|
||||||
|
the document. Think about the parties involved in the
|
||||||
|
signing process and what their responsibilities are.
|
||||||
|
Common roles include HR for internal documents, Customer
|
||||||
|
for agreements or Vendor for business agreements.{" "}
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">
|
||||||
|
Why pre-attach users to some roles?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For roles that consistently involve the same individual
|
||||||
|
(e.g., the CEO's signature on employee offer
|
||||||
|
letters), you can pre-attach a user to a role within the
|
||||||
|
template. This step is optional but recommended for
|
||||||
|
efficiency and consistency across documents.
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">
|
||||||
|
When do i specify the user attached to each role?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When you create a document from your template, you'll
|
||||||
|
be prompted to attach users to each defined role. If a
|
||||||
|
role already has a user attached, this will be pre-filled,
|
||||||
|
but you can modify it as needed before sending out the
|
||||||
|
document.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="signerList">
|
<div className="signerList">
|
||||||
<RecipientList {...props} />
|
<RecipientList {...props} />
|
||||||
</div>
|
</div>
|
||||||
{props.handleAddSigner && (
|
{props.handleAddSigner ? (
|
||||||
<div
|
<div
|
||||||
data-tut="reactourAddbtn"
|
data-tut="reactourAddbtn"
|
||||||
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
||||||
@@ -31,6 +84,19 @@ function SignerListPlace(props) {
|
|||||||
<i className="fa-solid fa-plus"></i>
|
<i className="fa-solid fa-plus"></i>
|
||||||
<span style={{ marginLeft: 2 }}>Add role</span>
|
<span style={{ marginLeft: 2 }}>Add role</span>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
data-tut="reactourAddbtn"
|
||||||
|
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
||||||
|
onClick={() => props.setIsAddSigner(true)}
|
||||||
|
style={{
|
||||||
|
opacity: props.isMailSend && "0.5",
|
||||||
|
pointerEvents: props.isMailSend && "none"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus"></i>
|
||||||
|
<span style={{ marginLeft: 2 }}>Add recipients</span>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ function WidgetComponent({
|
|||||||
sendInOrder,
|
sendInOrder,
|
||||||
isTemplateFlow,
|
isTemplateFlow,
|
||||||
setBlockColor,
|
setBlockColor,
|
||||||
blockColor
|
blockColor,
|
||||||
|
setIsAddSigner
|
||||||
}) {
|
}) {
|
||||||
const [isSignersModal, setIsSignersModal] = useState(false);
|
const [isSignersModal, setIsSignersModal] = useState(false);
|
||||||
|
|
||||||
@@ -319,7 +320,7 @@ function WidgetComponent({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{handleAddSigner && (
|
{handleAddSigner ? (
|
||||||
<div
|
<div
|
||||||
data-tut="reactourAddbtn"
|
data-tut="reactourAddbtn"
|
||||||
style={{
|
style={{
|
||||||
@@ -333,6 +334,22 @@ function WidgetComponent({
|
|||||||
<i className="fa-solid fa-plus"></i>
|
<i className="fa-solid fa-plus"></i>
|
||||||
<span style={{ marginLeft: 2 }}>Add role</span>
|
<span style={{ marginLeft: 2 }}>Add role</span>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
setIsAddSigner && (
|
||||||
|
<div
|
||||||
|
data-tut="reactourAddbtn"
|
||||||
|
style={{
|
||||||
|
margin: "5px 0 5px 0",
|
||||||
|
backgroundColor: themeColor,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
|
||||||
|
onClick={() => setIsAddSigner(true)}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-plus"></i>
|
||||||
|
<span style={{ marginLeft: 2 }}>Add recipients</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -391,7 +408,7 @@ function WidgetComponent({
|
|||||||
)}
|
)}
|
||||||
{isSignersModal && (
|
{isSignersModal && (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Roles"}
|
title={title ? title : "Recipients"}
|
||||||
isOpen={isSignersModal}
|
isOpen={isSignersModal}
|
||||||
handleClose={handleModal}
|
handleClose={handleModal}
|
||||||
>
|
>
|
||||||
@@ -424,7 +441,7 @@ function WidgetComponent({
|
|||||||
textAlign: "center"
|
textAlign: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Please add a role
|
Please add a {title ? title : "recipients"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import "../../styles/AddUser.css";
|
|||||||
import RegexParser from "regex-parser";
|
import RegexParser from "regex-parser";
|
||||||
import { textInputWidget } from "../../constant/Utils";
|
import { textInputWidget } from "../../constant/Utils";
|
||||||
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||||
|
import Upgrade from "../../primitives/Upgrade";
|
||||||
|
import { isEnableSubscription } from "../../constant/const";
|
||||||
|
|
||||||
const WidgetNameModal = (props) => {
|
const WidgetNameModal = (props) => {
|
||||||
const [formdata, setFormdata] = useState({
|
const [formdata, setFormdata] = useState({
|
||||||
@@ -11,7 +13,7 @@ const WidgetNameModal = (props) => {
|
|||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
status: "required",
|
status: "required",
|
||||||
hint: "",
|
hint: "",
|
||||||
textvalidate: "text"
|
textvalidate: ""
|
||||||
});
|
});
|
||||||
const [isValid, setIsValid] = useState(true);
|
const [isValid, setIsValid] = useState(true);
|
||||||
const statusArr = ["Required", "Optional"];
|
const statusArr = ["Required", "Optional"];
|
||||||
@@ -46,7 +48,7 @@ const WidgetNameModal = (props) => {
|
|||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
status: "required",
|
status: "required",
|
||||||
hint: "",
|
hint: "",
|
||||||
textvalidate: "text"
|
textvalidate: ""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -80,7 +82,7 @@ const WidgetNameModal = (props) => {
|
|||||||
|
|
||||||
function handleBlurRegex() {
|
function handleBlurRegex() {
|
||||||
if (!formdata.textvalidate) {
|
if (!formdata.textvalidate) {
|
||||||
setFormdata({ ...formdata, textvalidate: "text" });
|
setFormdata({ ...formdata, textvalidate: "" });
|
||||||
} else {
|
} else {
|
||||||
if (formdata.defaultValue) {
|
if (formdata.defaultValue) {
|
||||||
const regexObject = RegexParser(
|
const regexObject = RegexParser(
|
||||||
@@ -100,13 +102,14 @@ const WidgetNameModal = (props) => {
|
|||||||
title={"Widget info"}
|
title={"Widget info"}
|
||||||
>
|
>
|
||||||
{(props.defaultdata?.type === textInputWidget ||
|
{(props.defaultdata?.type === textInputWidget ||
|
||||||
props.widgetName === textInputWidget) && (
|
props.widgetName === textInputWidget) &&
|
||||||
<PremiumAlertHeader
|
!isEnableSubscription && (
|
||||||
message={
|
<PremiumAlertHeader
|
||||||
"Field validations are free in beta, this feature will incur a fee later."
|
message={
|
||||||
}
|
"Field validations are free in beta, this feature will incur a fee later."
|
||||||
/>
|
}
|
||||||
)}
|
/>
|
||||||
|
)}
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -133,10 +136,20 @@ const WidgetNameModal = (props) => {
|
|||||||
props.widgetName === textInputWidget) && (
|
props.widgetName === textInputWidget) && (
|
||||||
<>
|
<>
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
<label htmlFor="textvalidate" style={{ fontSize: 13 }}>
|
<label
|
||||||
|
htmlFor="textvalidate"
|
||||||
|
className={
|
||||||
|
!props.isSubscribe && isEnableSubscription && "disabled"
|
||||||
|
}
|
||||||
|
style={{ fontSize: 13 }}
|
||||||
|
>
|
||||||
Validation
|
Validation
|
||||||
</label>
|
</label>
|
||||||
|
{!props.isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
<div
|
<div
|
||||||
|
className={
|
||||||
|
!props.isSubscribe && isEnableSubscription && "disabled"
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@@ -178,6 +191,7 @@ const WidgetNameModal = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
<label htmlFor="name" style={{ fontSize: 13 }}>
|
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||||
Default value
|
Default value
|
||||||
@@ -196,7 +210,10 @@ const WidgetNameModal = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{isValid === false && (
|
{isValid === false && (
|
||||||
<div className="warning defaultvalueWarning" style={{ fontSize: 12 }}>
|
<div
|
||||||
|
className="warning defaultvalueWarning"
|
||||||
|
style={{ fontSize: 12 }}
|
||||||
|
>
|
||||||
<i
|
<i
|
||||||
className="fas fa-exclamation-circle"
|
className="fas fa-exclamation-circle"
|
||||||
style={{ color: "#fab005", fontSize: 15 }}
|
style={{ color: "#fab005", fontSize: 15 }}
|
||||||
|
|||||||
@@ -53,9 +53,22 @@ const SelectSigners = (props) => {
|
|||||||
const contactRes = await contactbook.find();
|
const contactRes = await contactbook.find();
|
||||||
if (contactRes) {
|
if (contactRes) {
|
||||||
const res = JSON.parse(JSON.stringify(contactRes));
|
const res = JSON.parse(JSON.stringify(contactRes));
|
||||||
// console.log("userList ", res);
|
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
|
||||||
setUserList(res);
|
//and filter signers from total signer's list which already present in document's signers list
|
||||||
return await res.map((item) => ({
|
const compareArrays = (res, signerObj) => {
|
||||||
|
return res.filter(
|
||||||
|
(item1) =>
|
||||||
|
!signerObj.find((item2) => item2.objectId === item1.objectId)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//get update signer's List if signersdata is present
|
||||||
|
const updateSignersList =
|
||||||
|
props?.signersData && compareArrays(res, props?.signersData);
|
||||||
|
|
||||||
|
const result = updateSignersList ? updateSignersList : res;
|
||||||
|
setUserList(result);
|
||||||
|
return await result.map((item) => ({
|
||||||
label: item.Email,
|
label: item.Email,
|
||||||
value: item.objectId
|
value: item.objectId
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
|||||||
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
|
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
|
||||||
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
|
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
|
||||||
<img
|
<img
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-contain"
|
||||||
src={image}
|
src={image}
|
||||||
alt="Profile"
|
alt="Profile"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { themeColor } from "./const";
|
import { isEnableSubscription, themeColor } from "./const";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { rgb } from "pdf-lib";
|
import { rgb } from "pdf-lib";
|
||||||
|
import Parse from "parse";
|
||||||
|
|
||||||
export const isMobile = window.innerWidth < 767;
|
export const isMobile = window.innerWidth < 767;
|
||||||
export const textInputWidget = "text input";
|
export const textInputWidget = "text input";
|
||||||
@@ -12,6 +13,54 @@ export const openInNewTab = (url) => {
|
|||||||
window.open(url, "_blank", "noopener,noreferrer");
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function fetchSubscription(extUserId) {
|
||||||
|
try {
|
||||||
|
const extClass = localStorage.getItem("Extand_Class");
|
||||||
|
let extUser;
|
||||||
|
if (extClass) {
|
||||||
|
const jsonSender = JSON.parse(extClass);
|
||||||
|
extUser = jsonSender[0].objectId;
|
||||||
|
} else {
|
||||||
|
extUser = extUserId;
|
||||||
|
}
|
||||||
|
const baseURL = localStorage.getItem("baseUrl");
|
||||||
|
const url = `${baseURL}functions/getsubscriptions`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
|
};
|
||||||
|
const params = { extUserId: extUser };
|
||||||
|
const tenatRes = await axios.post(url, params, { headers: headers });
|
||||||
|
const plan = tenatRes.data?.result?.result?.PlanCode;
|
||||||
|
const billingDate = tenatRes.data?.result?.result?.Next_billing_date?.iso;
|
||||||
|
return { plan, billingDate };
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in fetch subscription", err);
|
||||||
|
return { plan: "", billingDate: "" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//function to get subcripition details from Extand user class
|
||||||
|
export async function checkIsSubscribed() {
|
||||||
|
try {
|
||||||
|
const res = await fetchSubscription();
|
||||||
|
if (res.plan === "freeplan") {
|
||||||
|
return false;
|
||||||
|
} else if (res.billingDate) {
|
||||||
|
if (new Date(res.billingDate) > new Date()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Err in fetch subscription", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const color = [
|
export const color = [
|
||||||
"#93a3db",
|
"#93a3db",
|
||||||
"#e6c3db",
|
"#e6c3db",
|
||||||
@@ -274,15 +323,15 @@ export const addWidgetOptions = (type) => {
|
|||||||
options: { isReadOnly: false, isHideLabel: false }
|
options: { isReadOnly: false, isHideLabel: false }
|
||||||
};
|
};
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
|
return { ...defaultOpt };
|
||||||
case "initials":
|
case "initials":
|
||||||
return defaultOpt;
|
return defaultOpt;
|
||||||
case "name":
|
case "name":
|
||||||
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
|
return { ...defaultOpt };
|
||||||
case "company":
|
case "company":
|
||||||
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
|
return { ...defaultOpt };
|
||||||
case "job title":
|
case "job title":
|
||||||
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
|
return { ...defaultOpt };
|
||||||
case "date":
|
case "date":
|
||||||
return {
|
return {
|
||||||
...defaultOpt,
|
...defaultOpt,
|
||||||
@@ -477,16 +526,33 @@ export const signPdfFun = async (
|
|||||||
base64Url,
|
base64Url,
|
||||||
documentId,
|
documentId,
|
||||||
signerObjectId,
|
signerObjectId,
|
||||||
setIsAlert
|
setIsAlert,
|
||||||
|
objectId,
|
||||||
|
isSubscribed
|
||||||
) => {
|
) => {
|
||||||
let singleSign;
|
let singleSign,
|
||||||
|
isCustomCompletionMail = false;
|
||||||
|
|
||||||
|
//get tenant details
|
||||||
|
const tenantDetails = await getTenantDetails(objectId);
|
||||||
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
|
alert("User does not exist");
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
tenantDetails?.CompletionBody &&
|
||||||
|
tenantDetails?.CompletionSubject &&
|
||||||
|
(!isEnableSubscription || isSubscribed)
|
||||||
|
) {
|
||||||
|
isCustomCompletionMail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
singleSign = {
|
singleSign = {
|
||||||
pdfFile: base64Url,
|
pdfFile: base64Url,
|
||||||
docId: documentId,
|
docId: documentId,
|
||||||
userId: signerObjectId
|
userId: signerObjectId,
|
||||||
|
isCustomCompletionMail: isCustomCompletionMail
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await axios
|
const response = await axios
|
||||||
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
|
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -1111,10 +1177,10 @@ export const multiSignEmbed = async (
|
|||||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
const newUrl = await convertPNGtoJPEG(signUrl);
|
||||||
signUrl = newUrl;
|
signUrl = newUrl;
|
||||||
}
|
}
|
||||||
const checkUrl = urlValidator(signUrl);
|
// const checkUrl = urlValidator(signUrl);
|
||||||
if (checkUrl) {
|
// if (checkUrl) {
|
||||||
signUrl = signUrl + "?get";
|
// signUrl = signUrl + "?get";
|
||||||
}
|
// }
|
||||||
const res = await fetch(signUrl);
|
const res = await fetch(signUrl);
|
||||||
return res.arrayBuffer();
|
return res.arrayBuffer();
|
||||||
}
|
}
|
||||||
@@ -1249,6 +1315,7 @@ export const multiSignEmbed = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const widgetTypeExist = [
|
const widgetTypeExist = [
|
||||||
|
textWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
"name",
|
"name",
|
||||||
"company",
|
"company",
|
||||||
@@ -1304,7 +1371,7 @@ export const multiSignEmbed = async (
|
|||||||
checkbox.enableReadOnly();
|
checkbox.enableReadOnly();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (position.type === textWidget) {
|
} else if (widgetTypeExist) {
|
||||||
const font = await pdfDoc.embedFont("Helvetica");
|
const font = await pdfDoc.embedFont("Helvetica");
|
||||||
const fontSize = 12;
|
const fontSize = 12;
|
||||||
let textContent;
|
let textContent;
|
||||||
@@ -1380,24 +1447,8 @@ export const multiSignEmbed = async (
|
|||||||
color: rgb(0, 0, 0),
|
color: rgb(0, 0, 0),
|
||||||
size: fontSize
|
size: fontSize
|
||||||
});
|
});
|
||||||
y -= 15; // Adjust the line height as needed
|
y -= 18; // Adjust the line height as needed
|
||||||
}
|
}
|
||||||
} else if (widgetTypeExist) {
|
|
||||||
const font = await pdfDoc.embedFont("Helvetica");
|
|
||||||
const fontSize = 12;
|
|
||||||
let textContent;
|
|
||||||
if (position?.options?.response) {
|
|
||||||
textContent = position.options?.response;
|
|
||||||
} else if (position?.options?.defaultValue) {
|
|
||||||
textContent = position?.options?.defaultValue;
|
|
||||||
}
|
|
||||||
page.drawText(textContent, {
|
|
||||||
x: xPos(position),
|
|
||||||
y: yPos(position) + 10,
|
|
||||||
size: fontSize,
|
|
||||||
font,
|
|
||||||
color: rgb(0, 0, 0)
|
|
||||||
});
|
|
||||||
} else if (position.type === "dropdown") {
|
} else if (position.type === "dropdown") {
|
||||||
const dropdownRandomId = "dropdown" + randomId();
|
const dropdownRandomId = "dropdown" + randomId();
|
||||||
const dropdown = form.createDropdown(dropdownRandomId);
|
const dropdown = form.createDropdown(dropdownRandomId);
|
||||||
@@ -1768,3 +1819,101 @@ export const handleCopyNextToWidget = (
|
|||||||
setXyPostion(updatePlaceholder);
|
setXyPostion(updatePlaceholder);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFileName = (fileUrl) => {
|
||||||
|
if (fileUrl) {
|
||||||
|
const url = new URL(fileUrl);
|
||||||
|
const filename = url.pathname.substring(url.pathname.indexOf("_") + 1);
|
||||||
|
return filename || "";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//fetch tenant app logo from `partners_Tenant` class by domain name
|
||||||
|
export const getAppLogo = async () => {
|
||||||
|
const domainName = window.location.host;
|
||||||
|
try {
|
||||||
|
const tenantCreditsQuery = new Parse.Query("partners_Tenant");
|
||||||
|
tenantCreditsQuery.equalTo("Domain", domainName);
|
||||||
|
const res = await tenantCreditsQuery.first();
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
const updateRes = JSON.parse(JSON.stringify(res));
|
||||||
|
return updateRes?.Logo;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTenantDetails = async (objectId) => {
|
||||||
|
try {
|
||||||
|
const tenantCreditsQuery = new Parse.Query("partners_Tenant");
|
||||||
|
tenantCreditsQuery.equalTo("UserId", {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "_User",
|
||||||
|
objectId: objectId
|
||||||
|
});
|
||||||
|
const res = await tenantCreditsQuery.first();
|
||||||
|
if (res) {
|
||||||
|
const updateRes = JSON.parse(JSON.stringify(res));
|
||||||
|
return updateRes;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return "user does not exist!";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function to convert variable string name to variable value of email body and subject
|
||||||
|
export function replaceMailVaribles(subject, body, variables) {
|
||||||
|
let replacedSubject = subject;
|
||||||
|
let replacedBody = body;
|
||||||
|
|
||||||
|
for (const variable in variables) {
|
||||||
|
const regex = new RegExp(`{{${variable}}}`, "g");
|
||||||
|
if (subject) {
|
||||||
|
replacedSubject = replacedSubject.replace(regex, variables[variable]);
|
||||||
|
}
|
||||||
|
if (body) {
|
||||||
|
replacedBody = replacedBody.replace(regex, variables[variable]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
subject: replacedSubject,
|
||||||
|
body: replacedBody
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const copytoData = (text) => {
|
||||||
|
// navigator.clipboard.writeText(text);
|
||||||
|
if (navigator.clipboard) {
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
} else {
|
||||||
|
// Fallback for browsers that don't support navigator.clipboard
|
||||||
|
const textArea = document.createElement("textarea");
|
||||||
|
textArea.value = text;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const convertPdfArrayBuffer = async (url) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
// Check if the response was successful (status 200)
|
||||||
|
if (!response.ok) {
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
// Convert the response to ArrayBuffer
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
return arrayBuffer;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ export const modalSubmitBtnColor = "#17a2b8";
|
|||||||
export const modalCancelBtnColor = "white";
|
export const modalCancelBtnColor = "white";
|
||||||
export const themeColor = "#47a3ad";
|
export const themeColor = "#47a3ad";
|
||||||
export const iconColor = "#686968";
|
export const iconColor = "#686968";
|
||||||
|
export const isEnableSubscription = process.env.REACT_APP_ENABLE_SUBSCRIPTION;
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
const parseAppId = process.env.REACT_APP_APPID
|
||||||
const serverUrl = localStorage.getItem("baseUrl");
|
? process.env.REACT_APP_APPID
|
||||||
|
: "opensign";
|
||||||
|
const serverUrl = process.env.REACT_APP_SERVERURL
|
||||||
|
? process.env.REACT_APP_SERVERURL
|
||||||
|
: window.location.origin + "/api/app";
|
||||||
|
|
||||||
export const SaveFileSize = async (size, imageUrl) => {
|
export const SaveFileSize = async (size, imageUrl, tenantId) => {
|
||||||
//checking server url and save file's size
|
//checking server url and save file's size
|
||||||
|
const tenantPtr = {
|
||||||
|
__type: "Pointer",
|
||||||
|
className: "partners_Tenant",
|
||||||
|
objectId: tenantId
|
||||||
|
};
|
||||||
|
const _tenantPtr = JSON.stringify(tenantPtr);
|
||||||
try {
|
try {
|
||||||
const response = await axios
|
const res = await axios.get(
|
||||||
.get(`${serverUrl}classes/partners_TenantCredits`, {
|
`${serverUrl}/classes/partners_TenantCredits?where={"PartnersTenant":${_tenantPtr}}`,
|
||||||
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.then((result) => {
|
);
|
||||||
const res = result.data;
|
const response = res.data.results;
|
||||||
// console.log("res", res);
|
|
||||||
|
|
||||||
return res.results;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
|
||||||
let data;
|
let data;
|
||||||
// console.log("response", response);
|
// console.log("response", response);
|
||||||
if (response && response.length > 0) {
|
if (response && response.length > 0) {
|
||||||
@@ -30,69 +33,48 @@ export const SaveFileSize = async (size, imageUrl) => {
|
|||||||
? response[0].usedStorage + size
|
? response[0].usedStorage + size
|
||||||
: size
|
: size
|
||||||
};
|
};
|
||||||
await axios
|
await axios.put(
|
||||||
.put(
|
`${serverUrl}/classes/partners_TenantCredits/${response[0].objectId}`,
|
||||||
`${serverUrl}classes/partners_TenantCredits/${response[0].objectId}`,
|
data,
|
||||||
data,
|
{
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Parse-Application-Id": parseAppId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
// const res = result.data;
|
|
||||||
// console.log("save res", res);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
data = {
|
|
||||||
usedStorage: size
|
|
||||||
};
|
|
||||||
await axios
|
|
||||||
.post(`${serverUrl}classes/partners_TenantCredits`, data, {
|
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.then(() => {
|
);
|
||||||
// const res = result.data;
|
} else {
|
||||||
// console.log("res", res);
|
data = { usedStorage: size, PartnersTenant: tenantPtr };
|
||||||
})
|
await axios.post(`${serverUrl}/classes/partners_TenantCredits`, data, {
|
||||||
.catch((err) => {
|
headers: {
|
||||||
console.log("axois err ", err);
|
"Content-Type": "application/json",
|
||||||
});
|
"X-Parse-Application-Id": parseAppId
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (err) {
|
||||||
console.log("org app error", e);
|
console.log("err in save usage", err);
|
||||||
}
|
}
|
||||||
saveDataFile(size, imageUrl);
|
saveDataFile(size, imageUrl, tenantPtr);
|
||||||
};
|
};
|
||||||
|
|
||||||
//function for save fileUrl and file size in particular client db class partners_DataFiles
|
//function for save fileUrl and file size in particular client db class partners_DataFiles
|
||||||
const saveDataFile = async (size, imageUrl) => {
|
const saveDataFile = async (size, imageUrl, tenantPtr) => {
|
||||||
const data = {
|
const data = {
|
||||||
FileUrl: imageUrl,
|
FileUrl: imageUrl,
|
||||||
FileSize: size
|
FileSize: size,
|
||||||
|
TenantPtr: tenantPtr
|
||||||
};
|
};
|
||||||
|
|
||||||
// console.log("data save",file, data)
|
// console.log("data save",file, data)
|
||||||
await axios
|
try {
|
||||||
.post(`${serverUrl}classes/partners_DataFiles`, data, {
|
await axios.post(`${serverUrl}/classes/partners_DataFiles`, data, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// const res = result.data;
|
|
||||||
// console.log("res", res);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log("axois err ", err);
|
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in save usage ", err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import "./index.css";
|
|||||||
import App from "./App";
|
import App from "./App";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { store } from "./redux/store";
|
import { store } from "./redux/store";
|
||||||
|
import { CookiesProvider } from "react-cookie";
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
import { TouchBackend } from "react-dnd-touch-backend";
|
import { TouchBackend } from "react-dnd-touch-backend";
|
||||||
import {
|
import {
|
||||||
@@ -62,10 +63,12 @@ if (process.env.REACT_APP_GTM) {
|
|||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||||
root.render(
|
root.render(
|
||||||
<Provider store={store}>
|
<CookiesProvider defaultSetOptions={{ path: "/" }}>
|
||||||
<DndProvider options={HTML5toTouch}>
|
<Provider store={store}>
|
||||||
<Preview>{generatePreview}</Preview>
|
<DndProvider options={HTML5toTouch}>
|
||||||
<App />
|
<Preview>{generatePreview}</Preview>
|
||||||
</DndProvider>
|
<App />
|
||||||
</Provider>
|
</DndProvider>
|
||||||
|
</Provider>
|
||||||
|
</CookiesProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,14 +12,26 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "sign",
|
btnId: "1231",
|
||||||
|
hoverLabel: "Edit",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa-solid fa-pen",
|
||||||
redirectUrl: "draftDocument"
|
redirectUrl: "draftDocument",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2142",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnColor: "#ff4848",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg: "This are documents you have started but have not finalized for sending."
|
helpMsg:
|
||||||
|
"These are documents you have started but have not finalized for sending."
|
||||||
};
|
};
|
||||||
// Need your sign report
|
// Need your sign report
|
||||||
case "4Hhwbp482K":
|
case "4Hhwbp482K":
|
||||||
@@ -28,11 +40,14 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
|
btnId: "4536",
|
||||||
btnLabel: "sign",
|
btnLabel: "sign",
|
||||||
|
hoverLabel: "Sign",
|
||||||
btnColor: "#3ac9d6",
|
btnColor: "#3ac9d6",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa-solid fa-signature",
|
||||||
redirectUrl: "pdfRequestFiles"
|
redirectUrl: "pdfRequestFiles",
|
||||||
|
action: "redirect"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg:
|
helpMsg:
|
||||||
@@ -45,11 +60,48 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnId: "8901",
|
||||||
|
hoverLabel: "Share",
|
||||||
|
btnColor: "#4bd396",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa-solid fa-share",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "share"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1588",
|
||||||
|
hoverLabel: "View",
|
||||||
btnColor: "#3ac9d6",
|
btnColor: "#3ac9d6",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl: "pdfRequestFiles"
|
redirectUrl: "pdfRequestFiles",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2234",
|
||||||
|
hoverLabel: "option",
|
||||||
|
btnColor: "transparent",
|
||||||
|
textColor: "black",
|
||||||
|
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
|
||||||
|
action: "option",
|
||||||
|
subaction: [
|
||||||
|
{
|
||||||
|
btnId: "1688",
|
||||||
|
btnLabel: "Revoke",
|
||||||
|
hoverLabel: "Revoke",
|
||||||
|
btnIcon: "fa-solid fa-file-circle-xmark",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "revoke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1488",
|
||||||
|
btnLabel: "Delete",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg:
|
helpMsg:
|
||||||
@@ -62,14 +114,26 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnId: "1378",
|
||||||
|
hoverLabel: "Edit",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl: "draftDocument"
|
redirectUrl: "draftDocument",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1278",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnColor: "#ff4848",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg: "This is a list of documents that have been signed by all parties."
|
helpMsg:
|
||||||
|
"This is a list of documents that have been signed by all parties."
|
||||||
};
|
};
|
||||||
// declined documents report
|
// declined documents report
|
||||||
case "UPr2Fm5WY3":
|
case "UPr2Fm5WY3":
|
||||||
@@ -78,14 +142,26 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnId: "1458",
|
||||||
|
hoverLabel: "View",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl: "draftDocument"
|
redirectUrl: "draftDocument",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1358",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnColor: "#ff4848",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg: "This is a list of documents that have been declined by one of the signers."
|
helpMsg:
|
||||||
|
"This is a list of documents that have been declined by one of the signers."
|
||||||
};
|
};
|
||||||
// Expired Documents report
|
// Expired Documents report
|
||||||
case "zNqBHXHsYH":
|
case "zNqBHXHsYH":
|
||||||
@@ -94,14 +170,26 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnId: "1898",
|
||||||
|
hoverLabel: "View",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl: "draftDocument"
|
redirectUrl: "draftDocument",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1998",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnColor: "#ff4848",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg: "This is a list of documents that have reached their expiration date."
|
helpMsg:
|
||||||
|
"This is a list of documents that have reached their expiration date."
|
||||||
};
|
};
|
||||||
// Recently sent for signatures report show on dashboard
|
// Recently sent for signatures report show on dashboard
|
||||||
case "d9k3UfYHBc":
|
case "d9k3UfYHBc":
|
||||||
@@ -110,11 +198,48 @@ export default function reportJson(id) {
|
|||||||
heading: dashboardReportHead,
|
heading: dashboardReportHead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "View",
|
btnId: "1999",
|
||||||
|
hoverLabel: "Share",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
|
btnIcon: "fa-solid fa-share",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "share"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1999",
|
||||||
|
hoverLabel: "View",
|
||||||
|
btnColor: "#3ac9d6",
|
||||||
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa fa-eye",
|
||||||
redirectUrl: "pdfRequestFiles"
|
redirectUrl: "pdfRequestFiles",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2234",
|
||||||
|
hoverLabel: "option",
|
||||||
|
btnColor: "transparent",
|
||||||
|
textColor: "black",
|
||||||
|
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
|
||||||
|
action: "option",
|
||||||
|
subaction: [
|
||||||
|
{
|
||||||
|
btnId: "6788",
|
||||||
|
btnLabel: "Revoke",
|
||||||
|
hoverLabel: "Revoke",
|
||||||
|
btnIcon: "fa-solid fa-file-circle-xmark",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "revoke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2000",
|
||||||
|
btnLabel: "Delete",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -125,11 +250,14 @@ export default function reportJson(id) {
|
|||||||
heading: dashboardReportHead,
|
heading: dashboardReportHead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "Sign",
|
btnId: "2001",
|
||||||
btnColor: "#4bd396",
|
btnLabel: "sign",
|
||||||
|
hoverLabel: "Sign",
|
||||||
|
btnColor: "#3ac9d6",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-eye",
|
btnIcon: "fa-solid fa-signature",
|
||||||
redirectUrl: "pdfRequestFiles"
|
redirectUrl: "pdfRequestFiles",
|
||||||
|
action: "redirect"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -140,11 +268,22 @@ export default function reportJson(id) {
|
|||||||
heading: ["Title", "Note", "Folder", "File", "Owner", "Signers"],
|
heading: ["Title", "Note", "Folder", "File", "Owner", "Signers"],
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "sign",
|
btnId: "2003",
|
||||||
|
hoverLabel: "Edit",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa-solid fa-pen",
|
||||||
redirectUrl: "draftDocument"
|
redirectUrl: "draftDocument",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2004",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnColor: "#ff4848",
|
||||||
|
textColor: "white",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -155,14 +294,17 @@ export default function reportJson(id) {
|
|||||||
heading: contactbook,
|
heading: contactbook,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnLabel: "",
|
btnId: "2204",
|
||||||
|
hoverLabel: "Delete",
|
||||||
btnColor: "#f55a42",
|
btnColor: "#f55a42",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa-solid fa-trash"
|
btnIcon: "fa-solid fa-trash",
|
||||||
|
action: "delete"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
form: "ContactBook",
|
form: "ContactBook",
|
||||||
helpMsg: "This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document."
|
helpMsg:
|
||||||
|
"This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document."
|
||||||
};
|
};
|
||||||
// template report
|
// template report
|
||||||
case "6TeaPr321t":
|
case "6TeaPr321t":
|
||||||
@@ -171,18 +313,46 @@ export default function reportJson(id) {
|
|||||||
heading: head,
|
heading: head,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
|
btnId: "2234",
|
||||||
btnLabel: "Use",
|
btnLabel: "Use",
|
||||||
|
hoverLabel: "Use",
|
||||||
btnColor: "#4bd396",
|
btnColor: "#4bd396",
|
||||||
textColor: "white",
|
textColor: "white",
|
||||||
btnIcon: "fa fa-plus",
|
btnIcon: "fa fa-plus",
|
||||||
redirectUrl: "placeHolderSign"
|
redirectUrl: "placeHolderSign",
|
||||||
|
action: "redirect",
|
||||||
|
selector: "reactourSecond",
|
||||||
|
message:
|
||||||
|
"Click the 'Use' button to create a new document from an existing template. "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
btnLabel: "Edit",
|
btnId: "2234",
|
||||||
btnColor: "#00c9d5",
|
hoverLabel: "option",
|
||||||
textColor: "white",
|
btnColor: "transparent",
|
||||||
btnIcon: "fa fa-plus",
|
textColor: "black",
|
||||||
redirectUrl: "template"
|
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
|
||||||
|
action: "option",
|
||||||
|
selector: "reactourThird",
|
||||||
|
message:
|
||||||
|
"This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but won’t affect existing documents.Use the Delete button you can delete template. ",
|
||||||
|
subaction: [
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Edit",
|
||||||
|
hoverLabel: "Edit",
|
||||||
|
btnIcon: "fa-solid fa-pen",
|
||||||
|
redirectUrl: "template",
|
||||||
|
action: "redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "1834",
|
||||||
|
btnLabel: "Delete",
|
||||||
|
hoverLabel: "Delete",
|
||||||
|
btnIcon: "fa fa-trash",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "delete"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
helpMsg:
|
helpMsg:
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
const plans = [
|
||||||
|
{
|
||||||
|
planName: "OPENSIGN™ FREE",
|
||||||
|
currency: "",
|
||||||
|
monthlyPrice: "Free",
|
||||||
|
yearlyPrice: "Free",
|
||||||
|
subtitle: "Free Unlimited E-signatures, Forever.",
|
||||||
|
btnText: "Subscribe",
|
||||||
|
url: "",
|
||||||
|
target: "_blank",
|
||||||
|
benefits: [
|
||||||
|
"Unlimited envelopes",
|
||||||
|
"Sign documents yourself",
|
||||||
|
"Request signatures from others",
|
||||||
|
"14 field types",
|
||||||
|
"Automatic e-signatures",
|
||||||
|
"Completion certificates",
|
||||||
|
"Send in order",
|
||||||
|
"Document templates",
|
||||||
|
"Import from Dropbox",
|
||||||
|
"Contact book",
|
||||||
|
"Document expiry support",
|
||||||
|
"Decline document support",
|
||||||
|
"Email notifications",
|
||||||
|
"Recipient authentication using OTP",
|
||||||
|
"And much more"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
planName: "OPENSIGN™ PROFESSIONAL",
|
||||||
|
currency: "$",
|
||||||
|
monthlyPrice: "29.99",
|
||||||
|
yearlyPrice: "329.99",
|
||||||
|
subtitle: "Exclusive Access to advanced features.",
|
||||||
|
btnText: "Subscribe",
|
||||||
|
url:
|
||||||
|
window.location.origin === "https://staging-app.opensignlabs.com"
|
||||||
|
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328dd84ecda20eeae13878ce581d60240f206/pro-weekly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
|
||||||
|
yearlyUrl:
|
||||||
|
window.location.origin === "https://staging-app.opensignlabs.com"
|
||||||
|
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328ddc184411129224f1f29ed84f6cef3b862/pro-yearly"
|
||||||
|
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
|
||||||
|
target: "_self",
|
||||||
|
benefits: [
|
||||||
|
"Everything in OpenSign™ professional",
|
||||||
|
"Field validations",
|
||||||
|
"Regular expression validations",
|
||||||
|
"Organize docs in OpenSign™ Drive",
|
||||||
|
"Webhooks",
|
||||||
|
"Zapier integration",
|
||||||
|
"API Access",
|
||||||
|
"100 API signatures included",
|
||||||
|
"DocumentId removal from signed docs",
|
||||||
|
"Custom email templates(coming soon)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
planName: "OPENSIGN™ ENTERPRISE",
|
||||||
|
currency: "",
|
||||||
|
monthlyPrice: "Request Price",
|
||||||
|
yearlyPrice: "Request Price",
|
||||||
|
subtitle: "Scalable Features with priority support.",
|
||||||
|
btnText: "Contact us",
|
||||||
|
url: "https://www.opensignlabs.com/contact-us",
|
||||||
|
target: "_blank",
|
||||||
|
benefits: [
|
||||||
|
"All features",
|
||||||
|
"Custom domain",
|
||||||
|
"Custom branding",
|
||||||
|
"Uptime SLA",
|
||||||
|
"SSO support",
|
||||||
|
"Priority support"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default plans;
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"planName": "SELF HOSTED",
|
|
||||||
"currency": "",
|
|
||||||
"price": "Free",
|
|
||||||
"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",
|
|
||||||
"Unlimited Guest Signers",
|
|
||||||
"Unlimited completion certificates",
|
|
||||||
"Unique Code(OTP) verification for guest signers",
|
|
||||||
"Expiring docs & reject signature support",
|
|
||||||
"PDF Template Creation(coming soon)",
|
|
||||||
"Audit Trails",
|
|
||||||
"API support",
|
|
||||||
"Add-ons support(coming soon)",
|
|
||||||
"Self hosted cloud infrastructure",
|
|
||||||
"Free for lifetime",
|
|
||||||
"Community support"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"planName": "THANKS PLAN",
|
|
||||||
"currency": "$",
|
|
||||||
"price": "29.99",
|
|
||||||
"subtitle": "Use code <span style='background-color: yellow;'>'FREEBETA'</span> to get this for free(First 1000 users)",
|
|
||||||
"btnText": "Subscribe",
|
|
||||||
"url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks",
|
|
||||||
"target": "_self",
|
|
||||||
"benefits": [
|
|
||||||
"Sign Unlimited Documents",
|
|
||||||
"Unlimited Secure Doc Storage with OpenSign™ Drive",
|
|
||||||
"Unlimited Guest Signers",
|
|
||||||
"Unlimited completion certificates",
|
|
||||||
"Unique Code(OTP) verification for guest signers",
|
|
||||||
"Expiring docs & reject signature support",
|
|
||||||
"PDF Template Creation(coming soon)",
|
|
||||||
"Audit Trails",
|
|
||||||
"API support",
|
|
||||||
"Add-ons support(coming soon)",
|
|
||||||
"Self hosted cloud infrastructure"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"planName": "ENTERPRISE",
|
|
||||||
"currency": "",
|
|
||||||
"price": "Request Price",
|
|
||||||
"subtitle": "Customization available Priority support.",
|
|
||||||
"btnText": "Contact us",
|
|
||||||
"url": "https://www.opensignlabs.com/contact-us",
|
|
||||||
"target": "_blank",
|
|
||||||
"benefits": [
|
|
||||||
"All features",
|
|
||||||
"Custom domain",
|
|
||||||
"Whitelabeling",
|
|
||||||
"Uptime SLA",
|
|
||||||
"SSO support",
|
|
||||||
"24/7 support"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -9,6 +9,9 @@ import { useSelector } from "react-redux";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { useNavigate, useLocation, Outlet } from "react-router-dom";
|
import { useNavigate, useLocation, Outlet } from "react-router-dom";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { useCookies } from "react-cookie";
|
||||||
|
import { fetchSubscription } from "../constant/Utils";
|
||||||
|
|
||||||
const HomeLayout = () => {
|
const HomeLayout = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -18,6 +21,13 @@ const HomeLayout = () => {
|
|||||||
const arr = useSelector((state) => state.TourSteps);
|
const arr = useSelector((state) => state.TourSteps);
|
||||||
const [isUserValid, setIsUserValid] = useState(true);
|
const [isUserValid, setIsUserValid] = useState(true);
|
||||||
const [isLoader, setIsLoader] = useState(true);
|
const [isLoader, setIsLoader] = useState(true);
|
||||||
|
// reactour state
|
||||||
|
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
||||||
|
const [isTour, setIsTour] = useState(false);
|
||||||
|
const [tourStatusArr, setTourStatusArr] = useState([]);
|
||||||
|
const [tourConfigs, setTourConfigs] = useState([]);
|
||||||
|
const [, setCookie] = useCookies(["accesstoken", "main_Domain"]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -27,8 +37,8 @@ const HomeLayout = () => {
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
});
|
});
|
||||||
if (user) {
|
if (user) {
|
||||||
setIsUserValid(true);
|
localStorage.setItem("profileImg", user.get("ProfilePic") || "");
|
||||||
setIsLoader(false);
|
checkIsSubscribed();
|
||||||
} else {
|
} else {
|
||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
}
|
}
|
||||||
@@ -37,14 +47,49 @@ const HomeLayout = () => {
|
|||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
saveCookies();
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
//function to use save data in cookies storage
|
||||||
|
const saveCookies = () => {
|
||||||
|
const main_Domain = window.location.origin;
|
||||||
|
const domainName = window.location.hostname; //app.opensignlabs.com
|
||||||
|
// Find the index of the first dot in the string
|
||||||
|
const indexOfFirstDot = domainName.indexOf(".");
|
||||||
|
// Remove the first dot and get the substring starting from the next character
|
||||||
|
const updateDomain = domainName.substring(indexOfFirstDot); //.opensignlabs.com
|
||||||
|
setCookie("accesstoken", localStorage.getItem("accesstoken"), {
|
||||||
|
secure: true,
|
||||||
|
domain: updateDomain
|
||||||
|
});
|
||||||
|
setCookie("main_Domain", main_Domain, {
|
||||||
|
secure: true,
|
||||||
|
domain: updateDomain
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// reactour state
|
async function checkIsSubscribed() {
|
||||||
const [isCloseBtn, setIsCloseBtn] = useState(true);
|
if (isEnableSubscription) {
|
||||||
const [isTour, setIsTour] = useState(false);
|
const res = await fetchSubscription();
|
||||||
const [tourStatusArr, setTourStatusArr] = useState([]);
|
if (res.plan === "freeplan") {
|
||||||
const [tourConfigs, setTourConfigs] = useState([]);
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else if (res.billingDate) {
|
||||||
|
if (new Date(res.billingDate) > new Date()) {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsUserValid(true);
|
||||||
|
setIsLoader(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
const showSidebar = () => {
|
const showSidebar = () => {
|
||||||
setIsOpen((value) => !value);
|
setIsOpen((value) => !value);
|
||||||
};
|
};
|
||||||
@@ -198,7 +243,7 @@ const HomeLayout = () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="sticky top-0 z-50">
|
<div className="sticky top-0 z-50">
|
||||||
<Header showSidebar={showSidebar} />
|
{!isLoader && <Header showSidebar={showSidebar} />}
|
||||||
</div>
|
</div>
|
||||||
{isUserValid ? (
|
{isUserValid ? (
|
||||||
<>
|
<>
|
||||||
@@ -223,7 +268,6 @@ const HomeLayout = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="flex md:flex-row flex-col z-50">
|
<div className="flex md:flex-row flex-col z-50">
|
||||||
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="renderList"
|
id="renderList"
|
||||||
className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"
|
className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useNavigate, useParams } from "react-router-dom";
|
|||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import SelectFolder from "../components/shared/fields/SelectFolder";
|
|||||||
import SignersInput from "../components/shared/fields/SignersInput";
|
import SignersInput from "../components/shared/fields/SignersInput";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
|
import { getFileName } from "../constant/Utils";
|
||||||
|
|
||||||
// `Form` render all type of Form on this basis of their provided in path
|
// `Form` render all type of Form on this basis of their provided in path
|
||||||
function Form() {
|
function Form() {
|
||||||
@@ -82,6 +84,7 @@ const Forms = (props) => {
|
|||||||
const handleFileUpload = async (file) => {
|
const handleFileUpload = async (file) => {
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const fileName = file.name;
|
const fileName = file.name;
|
||||||
|
const size = file.size;
|
||||||
const name = sanitizeFileName(fileName);
|
const name = sanitizeFileName(fileName);
|
||||||
const pdfFile = file;
|
const pdfFile = file;
|
||||||
const parseFile = new Parse.File(name, pdfFile);
|
const parseFile = new Parse.File(name, pdfFile);
|
||||||
@@ -101,6 +104,8 @@ const Forms = (props) => {
|
|||||||
setFileUpload(response.url());
|
setFileUpload(response.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -113,6 +118,7 @@ const Forms = (props) => {
|
|||||||
const dropboxSuccess = async (files) => {
|
const dropboxSuccess = async (files) => {
|
||||||
setfileload(true);
|
setfileload(true);
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
|
const size = file.bytes;
|
||||||
const url = file.link;
|
const url = file.link;
|
||||||
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
||||||
|
|
||||||
@@ -141,6 +147,8 @@ const Forms = (props) => {
|
|||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -247,6 +255,7 @@ const Forms = (props) => {
|
|||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
setTimeout(() => setIsReset(false), 50);
|
setTimeout(() => setIsReset(false), 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
||||||
<Title title={props?.title} />
|
<Title title={props?.title} />
|
||||||
@@ -291,13 +300,10 @@ const Forms = (props) => {
|
|||||||
<div className="flex gap-2 justify-center items-center">
|
<div className="flex gap-2 justify-center items-center">
|
||||||
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
||||||
<div className="break-all">
|
<div className="break-all">
|
||||||
file selected :{" "}
|
file selected : {getFileName(fileupload)}
|
||||||
{fileupload?.split("/")?.pop()?.split("_")[1]}
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => setFileUpload([])}
|
||||||
setFileUpload([]);
|
|
||||||
}}
|
|
||||||
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-xmark"></i>
|
<i className="fa-solid fa-xmark"></i>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { rejectBtn, submitBtn } from "../constant/const";
|
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { checkIsSubscribed, copytoData, openInNewTab } from "../constant/Utils";
|
||||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
import Tooltip from "../primitives/Tooltip";
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
|
||||||
function GenerateToken() {
|
function GenerateToken() {
|
||||||
|
const navigation = useNavigate();
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
const [apiToken, SetApiToken] = useState("");
|
const [apiToken, SetApiToken] = useState("");
|
||||||
@@ -17,6 +19,7 @@ function GenerateToken() {
|
|||||||
const [isGenerate, setIsGenerate] = useState(false);
|
const [isGenerate, setIsGenerate] = useState(false);
|
||||||
const [isErr, setIsErr] = useState(false);
|
const [isErr, setIsErr] = useState(false);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchToken();
|
fetchToken();
|
||||||
@@ -25,6 +28,11 @@ function GenerateToken() {
|
|||||||
|
|
||||||
const fetchToken = async () => {
|
const fetchToken = async () => {
|
||||||
try {
|
try {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
|
|
||||||
const url = parseBaseUrl + "functions/getapitoken";
|
const url = parseBaseUrl + "functions/getapitoken";
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -35,6 +43,7 @@ function GenerateToken() {
|
|||||||
if (res) {
|
if (res) {
|
||||||
SetApiToken(res.data.result.result);
|
SetApiToken(res.data.result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
SetApiToken();
|
SetApiToken();
|
||||||
@@ -83,13 +92,14 @@ function GenerateToken() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const copytoclipboard = (text) => {
|
const copytoclipboard = (text) => {
|
||||||
navigator.clipboard.writeText(text);
|
copytoData(text);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setCopied(false);
|
setCopied(false);
|
||||||
}, 1500); // Reset copied state after 1.5 seconds
|
}, 1500); // Reset copied state after 1.5 seconds
|
||||||
};
|
};
|
||||||
const handleModal = () => setIsModal(!isModal);
|
const handleModal = () => setIsModal(!isModal);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Title title={"API Token"} />
|
<Title title={"API Token"} />
|
||||||
@@ -117,35 +127,47 @@ function GenerateToken() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||||
<PremiumAlertHeader />
|
{!isEnableSubscription && <PremiumAlertHeader />}
|
||||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
API Token{" "}
|
OpenSign™ API{" "}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
url={"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"}
|
url={
|
||||||
|
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
|
}
|
||||||
|
isSubscribe={true}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
<ul className="w-full flex flex-col p-2 text-sm">
|
<ul
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "w-full flex flex-col p-2 text-sm "
|
||||||
|
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
<li
|
<li
|
||||||
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
>
|
>
|
||||||
<span className="w-[40%]">Api Token:</span>{" "}
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
|
||||||
<span
|
<span className="">Api Token:</span>{" "}
|
||||||
id="token"
|
<span
|
||||||
className="w-[60%] md:text-end cursor-pointer"
|
id="token"
|
||||||
onClick={() => copytoclipboard(apiToken)}
|
className=" md:text-end cursor-pointer"
|
||||||
|
onClick={() => copytoclipboard(apiToken)}
|
||||||
|
>
|
||||||
|
{apiToken ? apiToken : "_____"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={apiToken ? handleModal : handleSubmit}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
||||||
>
|
>
|
||||||
{apiToken && apiToken}
|
{apiToken ? "Regenerate Token" : "Generate Token"}
|
||||||
</span>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
|
||||||
<button
|
<div className="flex items-center justify-center ">
|
||||||
type="button"
|
|
||||||
onClick={apiToken ? handleModal : handleSubmit}
|
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
|
||||||
>
|
|
||||||
{apiToken ? "Regenerate Token" : "Generate Token"}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -153,12 +175,41 @@ function GenerateToken() {
|
|||||||
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
className="rounded hover:bg-[#15b4e9] border-[1px] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
>
|
>
|
||||||
View Docs
|
View Docs
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<>
|
||||||
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
Upgrade to PRO Plan
|
||||||
|
</h1>
|
||||||
|
<ul className={"w-full flex flex-col p-2 text-sm "}>
|
||||||
|
<li
|
||||||
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
|
||||||
|
<span className="">$29.99/month:</span>{" "}
|
||||||
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
|
Sign 100 docs using API. Only 0.15/docs after that.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigation("/subscription")}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isModal}
|
isOpen={isModal}
|
||||||
title={"Regenerate Token"}
|
title={"Regenerate Token"}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { useNavigate, useParams } from "react-router-dom";
|
|||||||
import "../styles/loginPage.css";
|
import "../styles/loginPage.css";
|
||||||
import loader from "../assets/images/loader2.gif";
|
import loader from "../assets/images/loader2.gif";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { themeColor } from "../constant/const";
|
import { isEnableSubscription, themeColor } from "../constant/const";
|
||||||
import { contractUsers } from "../constant/Utils";
|
import { contractUsers, getAppLogo } from "../constant/Utils";
|
||||||
|
import logo from "../assets/images/logo.png";
|
||||||
|
|
||||||
function GuestLogin() {
|
function GuestLogin() {
|
||||||
const { id, userMail, contactBookId, serverUrl } = useParams();
|
const { id, userMail, contactBookId, serverUrl } = useParams();
|
||||||
@@ -14,14 +15,27 @@ function GuestLogin() {
|
|||||||
const [EnterOTP, setEnterOtp] = useState(false);
|
const [EnterOTP, setEnterOtp] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [appLogo, setAppLogo] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleServerUrl();
|
handleServerUrl();
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
//function generate serverUrl and parseAppId from url and save it in local storage
|
//function generate serverUrl and parseAppId from url and save it in local storage
|
||||||
const handleServerUrl = () => {
|
const handleServerUrl = async () => {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const applogo = await getAppLogo();
|
||||||
|
if (applogo) {
|
||||||
|
setAppLogo(applogo);
|
||||||
|
} else {
|
||||||
|
setAppLogo(logo);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setAppLogo(logo);
|
||||||
|
}
|
||||||
|
|
||||||
//split url in array from '&'
|
//split url in array from '&'
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
const checkSplit = serverUrl.split("&");
|
const checkSplit = serverUrl.split("&");
|
||||||
@@ -59,7 +73,8 @@ function GuestLogin() {
|
|||||||
"X-Parse-Application-Id": parseId
|
"X-Parse-Application-Id": parseId
|
||||||
};
|
};
|
||||||
let body = {
|
let body = {
|
||||||
email: email.toString()
|
email: email.toString(),
|
||||||
|
docId: id
|
||||||
};
|
};
|
||||||
let Otp = await axios.post(url, body, { headers: headers });
|
let Otp = await axios.post(url, body, { headers: headers });
|
||||||
|
|
||||||
@@ -163,12 +178,14 @@ function GuestLogin() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="main_head">
|
<div className="main_head">
|
||||||
<div className="main-logo">
|
<div className="w-[250px] h-[66px] inline-block overflow-hidden">
|
||||||
<img
|
{appLogo && (
|
||||||
alt="sign img"
|
<img
|
||||||
src="https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"
|
src={appLogo}
|
||||||
width="100%"
|
className="object-contain h-full"
|
||||||
/>
|
alt="logo"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,16 @@ import { NavLink, useNavigate, useLocation } from "react-router-dom";
|
|||||||
import login_img from "../assets/images/login_img.svg";
|
import login_img from "../assets/images/login_img.svg";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
|
import {
|
||||||
|
isEnableSubscription,
|
||||||
|
modalCancelBtnColor,
|
||||||
|
modalSubmitBtnColor
|
||||||
|
} from "../constant/const";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
|
import { fetchSubscription, getAppLogo } from "../constant/Utils";
|
||||||
function Login() {
|
function Login() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -39,7 +44,7 @@ function Login() {
|
|||||||
Destination: ""
|
Destination: ""
|
||||||
});
|
});
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
const image = appInfo?.applogo || undefined;
|
const [image, setImage] = useState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem("accesstoken")) {
|
if (localStorage.getItem("accesstoken")) {
|
||||||
@@ -47,8 +52,23 @@ function Login() {
|
|||||||
GetLoginData();
|
GetLoginData();
|
||||||
}
|
}
|
||||||
dispatch(fetchAppInfo());
|
dispatch(fetchAppInfo());
|
||||||
|
saveLogo();
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const saveLogo = async () => {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const logo = await getAppLogo();
|
||||||
|
if (logo) {
|
||||||
|
setImage(logo);
|
||||||
|
} else {
|
||||||
|
setImage(appInfo?.applogo || undefined);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setImage(appInfo?.applogo || undefined);
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
setState({ ...state, [name]: value });
|
setState({ ...state, [name]: value });
|
||||||
@@ -149,7 +169,7 @@ function Login() {
|
|||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
}).then(
|
}).then(
|
||||||
(result) => {
|
async (result) => {
|
||||||
let tenentInfo = [];
|
let tenentInfo = [];
|
||||||
const results = [result];
|
const results = [result];
|
||||||
if (results) {
|
if (results) {
|
||||||
@@ -209,7 +229,7 @@ function Login() {
|
|||||||
x.TenantId.TenantName || ""
|
x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
@@ -239,10 +259,7 @@ function Login() {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (
|
if (isEnableSubscription) {
|
||||||
process.env
|
|
||||||
.REACT_APP_ENABLE_SUBSCRIPTION
|
|
||||||
) {
|
|
||||||
const LocalUserDetails = {
|
const LocalUserDetails = {
|
||||||
name: results[0].get("Name"),
|
name: results[0].get("Name"),
|
||||||
email: results[0].get("Email"),
|
email: results[0].get("Email"),
|
||||||
@@ -253,11 +270,15 @@ function Login() {
|
|||||||
"userDetails",
|
"userDetails",
|
||||||
JSON.stringify(LocalUserDetails)
|
JSON.stringify(LocalUserDetails)
|
||||||
);
|
);
|
||||||
const billingDate =
|
const res = await fetchSubscription();
|
||||||
results[0].get("Next_billing_date") &&
|
const freeplan = res.plan;
|
||||||
results[0].get("Next_billing_date");
|
const billingDate = res.billingDate;
|
||||||
if (billingDate) {
|
if (freeplan === "freeplan") {
|
||||||
if (billingDate > new Date()) {
|
navigate(redirectUrl);
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (
|
||||||
|
new Date(billingDate) > new Date()
|
||||||
|
) {
|
||||||
localStorage.removeItem(
|
localStorage.removeItem(
|
||||||
"userDetails"
|
"userDetails"
|
||||||
);
|
);
|
||||||
@@ -292,9 +313,7 @@ function Login() {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (
|
if (isEnableSubscription) {
|
||||||
process.env.REACT_APP_ENABLE_SUBSCRIPTION
|
|
||||||
) {
|
|
||||||
const LocalUserDetails = {
|
const LocalUserDetails = {
|
||||||
name: _user.name,
|
name: _user.name,
|
||||||
email: email,
|
email: email,
|
||||||
@@ -391,6 +410,18 @@ function Login() {
|
|||||||
const setThirdpartyLoader = (value) => {
|
const setThirdpartyLoader = (value) => {
|
||||||
setState({ ...state, thirdpartyLoader: value });
|
setState({ ...state, thirdpartyLoader: value });
|
||||||
};
|
};
|
||||||
|
const handleFreePlan = async (id) => {
|
||||||
|
try {
|
||||||
|
const params = { userId: id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "error") {
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
const thirdpartyLoginfn = async (sessionToken, billingDate) => {
|
const thirdpartyLoginfn = async (sessionToken, billingDate) => {
|
||||||
const baseUrl = localStorage.getItem("baseUrl");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
@@ -400,6 +431,11 @@ function Login() {
|
|||||||
"X-Parse-Application-Id": parseAppId
|
"X-Parse-Application-Id": parseAppId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const param = new URLSearchParams(location.search);
|
||||||
|
const isFreeplan = param?.get("subscription") === "freeplan";
|
||||||
|
if (isFreeplan) {
|
||||||
|
await handleFreePlan(res.data.objectId);
|
||||||
|
}
|
||||||
await Parse.User.become(sessionToken).then(() => {
|
await Parse.User.become(sessionToken).then(() => {
|
||||||
window.localStorage.setItem("accesstoken", sessionToken);
|
window.localStorage.setItem("accesstoken", sessionToken);
|
||||||
});
|
});
|
||||||
@@ -542,7 +578,7 @@ function Login() {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
@@ -571,18 +607,28 @@ function Login() {
|
|||||||
);
|
);
|
||||||
setThirdpartyLoader(false);
|
setThirdpartyLoader(false);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, {
|
navigate(`/subscription`, {
|
||||||
replace: true
|
replace: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
navigate(`/subscription`, { replace: true });
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
@@ -597,17 +643,29 @@ function Login() {
|
|||||||
localStorage.setItem("pageType", element.pageType);
|
localStorage.setItem("pageType", element.pageType);
|
||||||
setState({ ...state, loading: false });
|
setState({ ...state, loading: false });
|
||||||
setThirdpartyLoader(false);
|
setThirdpartyLoader(false);
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
if (billingDate) {
|
if (billingDate) {
|
||||||
if (billingDate > new Date()) {
|
if (billingDate > new Date()) {
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
// Redirect to the appropriate URL after successful login
|
// Redirect to the appropriate URL after successful login
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, {
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(redirectUrl);
|
navigate(redirectUrl);
|
||||||
@@ -745,10 +803,17 @@ function Login() {
|
|||||||
// Get TenentID from Extendend Class
|
// Get TenentID from Extendend Class
|
||||||
localStorage.setItem("extended_class", item.extended_class);
|
localStorage.setItem("extended_class", item.extended_class);
|
||||||
const currentUser = Parse.User.current();
|
const currentUser = Parse.User.current();
|
||||||
|
const userSettings = appInfo.settings;
|
||||||
|
const setting = userSettings.find(
|
||||||
|
(x) => x.role === _currentRole
|
||||||
|
);
|
||||||
|
const redirectUrl =
|
||||||
|
location?.state?.from ||
|
||||||
|
`/${setting.pageType}/${setting.pageId}`;
|
||||||
await Parse.Cloud.run("getUserDetails", {
|
await Parse.Cloud.run("getUserDetails", {
|
||||||
email: currentUser.get("email")
|
email: currentUser.get("email")
|
||||||
}).then(
|
}).then(
|
||||||
(result) => {
|
async (result) => {
|
||||||
let tenentInfo = [];
|
let tenentInfo = [];
|
||||||
const results = [result];
|
const results = [result];
|
||||||
if (results) {
|
if (results) {
|
||||||
@@ -777,22 +842,74 @@ function Login() {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
localStorage.setItem("PageLanding", item.pageId);
|
localStorage.setItem("PageLanding", setting.pageId);
|
||||||
localStorage.setItem("defaultmenuid", item.menuId);
|
localStorage.setItem(
|
||||||
localStorage.setItem("pageType", item.pageType);
|
"defaultmenuid",
|
||||||
navigate(`/${item.pageType}/${item.pageId}`);
|
setting.menuId
|
||||||
|
);
|
||||||
|
localStorage.setItem("pageType", setting.pageType);
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const LocalUserDetails = {
|
||||||
|
name: results[0].get("Name"),
|
||||||
|
email: results[0].get("Email"),
|
||||||
|
phone: results[0].get("Phone"),
|
||||||
|
company: results[0].get("Company")
|
||||||
|
};
|
||||||
|
localStorage.setItem(
|
||||||
|
"userDetails",
|
||||||
|
JSON.stringify(LocalUserDetails)
|
||||||
|
);
|
||||||
|
const res = await fetchSubscription();
|
||||||
|
const billingDate = res.billingDate;
|
||||||
|
const freeplan = res.plan;
|
||||||
|
if (freeplan === "freeplan") {
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (new Date(billingDate) > new Date()) {
|
||||||
|
localStorage.removeItem("userDetails");
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem("PageLanding", item.pageId);
|
localStorage.setItem("PageLanding", setting.pageId);
|
||||||
localStorage.setItem("defaultmenuid", item.menuId);
|
localStorage.setItem("defaultmenuid", setting.menuId);
|
||||||
localStorage.setItem("pageType", item.pageType);
|
localStorage.setItem("pageType", setting.pageType);
|
||||||
navigate(`/${item.pageType}/${item.pageId}`);
|
setState({ ...state, loading: false });
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const LocalUserDetails = {
|
||||||
|
name: results[0].get("Name"),
|
||||||
|
email: results[0].get("Email"),
|
||||||
|
phone: results[0].get("Phone")
|
||||||
|
// company: results.get("Company"),
|
||||||
|
};
|
||||||
|
localStorage.setItem(
|
||||||
|
"userDetails",
|
||||||
|
JSON.stringify(LocalUserDetails)
|
||||||
|
);
|
||||||
|
const billingDate = "";
|
||||||
|
if (billingDate) {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect to the appropriate URL after successful login
|
||||||
|
navigate(redirectUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
@@ -949,12 +1066,14 @@ function Login() {
|
|||||||
<>
|
<>
|
||||||
<div aria-labelledby="loginHeading" role="region">
|
<div aria-labelledby="loginHeading" role="region">
|
||||||
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
||||||
<div className="w-[250px] h-[66px] inline-block">
|
<div className="w-[250px] h-[66px] inline-block overflow-hidden">
|
||||||
<img
|
{image && (
|
||||||
src={image}
|
<img
|
||||||
width="100%"
|
src={image}
|
||||||
alt="The image displays the OpenSign logo with a stylized blue square with an open corner, accompanied by the tagline Seal the Deal, Openly."
|
className="object-contain h-full"
|
||||||
/>
|
alt="The image displays the OpenSign logo with a stylized blue square with an open corner, accompanied by the tagline Seal the Deal, Openly."
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||||
<div>
|
<div>
|
||||||
@@ -1045,7 +1164,11 @@ function Login() {
|
|||||||
</button>
|
</button>
|
||||||
<NavLink
|
<NavLink
|
||||||
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
|
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
|
||||||
to="/signup"
|
to={
|
||||||
|
location.search
|
||||||
|
? "/signup" + location.search
|
||||||
|
: "/signup"
|
||||||
|
}
|
||||||
style={width < 768 ? { textAlign: "center" } : {}}
|
style={width < 768 ? { textAlign: "center" } : {}}
|
||||||
>
|
>
|
||||||
Create Account
|
Create Account
|
||||||
@@ -1054,25 +1177,12 @@ function Login() {
|
|||||||
</form>
|
</form>
|
||||||
<br />
|
<br />
|
||||||
{(appInfo.fbAppId || appInfo.googleClietId) && (
|
{(appInfo.fbAppId || appInfo.googleClietId) && (
|
||||||
<div
|
<div className="text-sm flex justify-center items-center">
|
||||||
style={{
|
<hr className="border-[1px] border-gray-300 w-full" />
|
||||||
display: "flex",
|
<span className="px-2 text-gray-500 cursor-default">
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
className="text-sm"
|
|
||||||
>
|
|
||||||
<hr
|
|
||||||
className={"border-[1px] border-gray-300 w-full"}
|
|
||||||
style={{ color: "grey" }}
|
|
||||||
/>
|
|
||||||
<span style={{ color: "grey" }} className="px-2 ">
|
|
||||||
OR
|
OR
|
||||||
</span>
|
</span>
|
||||||
<hr
|
<hr className="border-[1px] border-gray-300 w-full" />
|
||||||
className={"border-[1px] border-gray-300 w-full"}
|
|
||||||
style={{ color: "grey" }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "../styles/signature.css";
|
|||||||
import { toDataUrl } from "../constant/Utils";
|
import { toDataUrl } from "../constant/Utils";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
const ManageSign = () => {
|
const ManageSign = () => {
|
||||||
const appName = appInfo.appname;
|
const appName = appInfo.appname;
|
||||||
const [penColor, setPenColor] = useState("blue");
|
const [penColor, setPenColor] = useState("blue");
|
||||||
@@ -158,7 +159,11 @@ const ManageSign = () => {
|
|||||||
try {
|
try {
|
||||||
const parseFile = new Parse.File(file.name, file);
|
const parseFile = new Parse.File(file.name, file);
|
||||||
const response = await parseFile.save();
|
const response = await parseFile.save();
|
||||||
return response?.url();
|
if (response?.url()) {
|
||||||
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(file.size, response.url(), tenantId);
|
||||||
|
return response?.url();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("sign upload err", err);
|
console.log("sign upload err", err);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import Tour from "reactour";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
const DriveBody = React.lazy(
|
const DriveBody = React.lazy(
|
||||||
() => import("../components/opensigndrive/DriveBody")
|
() => import("../components/opensigndrive/DriveBody")
|
||||||
);
|
);
|
||||||
@@ -42,6 +46,8 @@ function Opensigndrive() {
|
|||||||
const [error, setError] = useState();
|
const [error, setError] = useState();
|
||||||
const [folderLoader, setIsFolderLoader] = useState(false);
|
const [folderLoader, setIsFolderLoader] = useState(false);
|
||||||
const [isShowSort, setIsShowSort] = useState(false);
|
const [isShowSort, setIsShowSort] = useState(false);
|
||||||
|
const [isTour, setIsTour] = useState(false);
|
||||||
|
const [tourStatusArr, setTourStatusArr] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
@@ -56,6 +62,8 @@ function Opensigndrive() {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const sortOrder = ["Ascending", "Descending"];
|
const sortOrder = ["Ascending", "Descending"];
|
||||||
const sortingValue = ["Name", "Date"];
|
const sortingValue = ["Name", "Date"];
|
||||||
|
const [isDontShow, setIsDontShow] = useState(false);
|
||||||
|
const [tourData, setTourData] = useState();
|
||||||
const orderName = {
|
const orderName = {
|
||||||
Ascending: "Ascending",
|
Ascending: "Ascending",
|
||||||
Descending: "Descending",
|
Descending: "Descending",
|
||||||
@@ -73,12 +81,60 @@ function Opensigndrive() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getPdfDocumentList();
|
getPdfDocumentList();
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [docId]);
|
}, [docId]);
|
||||||
|
|
||||||
|
const tourConfigs = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourFirst"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Click on the breadcrumb links to easily navigate through the folder hierarchy and view the documents within each folder.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourSecond"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Click the add button to create a new folder or document.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourThird"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Sort your documents by Date or Name using this menu.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourForth"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Click on this menu to display the documents in list view.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
//function for get all pdf document list
|
//function for get all pdf document list
|
||||||
const getPdfDocumentList = async (disbaleLoading) => {
|
const getPdfDocumentList = async (disbaleLoading) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
checkTourStatus();
|
||||||
if (!disbaleLoading) {
|
if (!disbaleLoading) {
|
||||||
setIsLoading({ isLoad: true, message: "This might take some time" });
|
setIsLoading({ isLoad: true, message: "This might take some time" });
|
||||||
}
|
}
|
||||||
@@ -87,8 +143,61 @@ function Opensigndrive() {
|
|||||||
if (driveDetails && driveDetails === "Error: Something went wrong!") {
|
if (driveDetails && driveDetails === "Error: Something went wrong!") {
|
||||||
setHandleError("Error: Something went wrong!");
|
setHandleError("Error: Something went wrong!");
|
||||||
} else if (driveDetails && driveDetails.length > 0) {
|
} else if (driveDetails && driveDetails.length > 0) {
|
||||||
|
const addMoreTour = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourFifth"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`The document list is displayed according to the selected sorting option. Icons next to each document indicate its current status.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "bottom",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourSixth"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Right-click on a document to see options such as Download, Rename, Move, and Delete. Click on the document to open it.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "bottom",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourSeventh"]',
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={`Right-click on any folder to see options. Choose ‘Rename’ to change the folder’s name or click on the folder to navigate through its contents.`}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "bottom",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
let newTour = [...tourConfigs, ...addMoreTour];
|
||||||
|
const isFolderExist = driveDetails.some(
|
||||||
|
(data) => data.Type === "Folder"
|
||||||
|
);
|
||||||
|
if (!isFolderExist) {
|
||||||
|
newTour = newTour.filter(
|
||||||
|
(data) => data.selector !== '[data-tut="reactourSeventh"]'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const isDocumentExist = driveDetails.some((data) => data.URL);
|
||||||
|
if (!isDocumentExist) {
|
||||||
|
newTour = newTour.filter(
|
||||||
|
(data) => data.selector !== '[data-tut="reactourSixth"]'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setTourData(newTour);
|
||||||
setSkip((prevSkip) => prevSkip + limit);
|
setSkip((prevSkip) => prevSkip + limit);
|
||||||
sortingData(null, null, driveDetails, true);
|
sortingData(null, null, driveDetails, true);
|
||||||
|
} else {
|
||||||
|
setTourData(tourConfigs);
|
||||||
}
|
}
|
||||||
if (!docId) {
|
if (!docId) {
|
||||||
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
|
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
|
||||||
@@ -203,6 +312,7 @@ function Opensigndrive() {
|
|||||||
const result = JSON.parse(JSON.stringify(res));
|
const result = JSON.parse(JSON.stringify(res));
|
||||||
|
|
||||||
setPdfData((prev) => [...prev, result]);
|
setPdfData((prev) => [...prev, result]);
|
||||||
|
sortingData(null, null, [result], true);
|
||||||
setNewFolderName();
|
setNewFolderName();
|
||||||
setIsFolderLoader(false);
|
setIsFolderLoader(false);
|
||||||
setIsFolder(false);
|
setIsFolder(false);
|
||||||
@@ -223,9 +333,13 @@ function Opensigndrive() {
|
|||||||
const sortedBy = (appInfo, type, order) => {
|
const sortedBy = (appInfo, type, order) => {
|
||||||
if (type === orderName.Name) {
|
if (type === orderName.Name) {
|
||||||
if (order === orderName.Ascending) {
|
if (order === orderName.Ascending) {
|
||||||
return appInfo.sort((a, b) => (a.Name > b.Name ? 1 : -1));
|
return appInfo.sort((a, b) =>
|
||||||
|
a.Name.toLowerCase() < b.Name.toLowerCase() ? -1 : 1
|
||||||
|
);
|
||||||
} else if (order === orderName.Descending) {
|
} else if (order === orderName.Descending) {
|
||||||
return appInfo.sort((a, b) => (a.Name > b.Name ? -1 : 1));
|
return appInfo.sort((a, b) =>
|
||||||
|
a.Name.toLowerCase() < b.Name.toLowerCase() ? 1 : -1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (type === orderName.Date) {
|
} else if (type === orderName.Date) {
|
||||||
if (order === orderName.Ascending) {
|
if (order === orderName.Ascending) {
|
||||||
@@ -353,9 +467,76 @@ function Opensigndrive() {
|
|||||||
setNewFolderName("");
|
setNewFolderName("");
|
||||||
setError("");
|
setError("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDontShow = (isChecked) => {
|
||||||
|
setIsDontShow(isChecked);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeTour = async () => {
|
||||||
|
setIsTour(false);
|
||||||
|
if (isDontShow) {
|
||||||
|
const serverUrl = localStorage.getItem("baseUrl");
|
||||||
|
const appId = localStorage.getItem("parseAppId");
|
||||||
|
const extUserClass = localStorage.getItem("extended_class");
|
||||||
|
const json = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
|
const extUserId = json && json.length > 0 && json[0].objectId;
|
||||||
|
let updatedTourStatus = [];
|
||||||
|
if (tourStatusArr.length > 0) {
|
||||||
|
updatedTourStatus = [...tourStatusArr];
|
||||||
|
const driveTourIndex = tourStatusArr.findIndex(
|
||||||
|
(obj) => obj["driveTour"] === false || obj["driveTour"] === true
|
||||||
|
);
|
||||||
|
if (driveTourIndex !== -1) {
|
||||||
|
updatedTourStatus[driveTourIndex] = { driveTour: true };
|
||||||
|
} else {
|
||||||
|
updatedTourStatus.push({ driveTour: true });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedTourStatus = [{ driveTour: true }];
|
||||||
|
}
|
||||||
|
await axios.put(
|
||||||
|
serverUrl + "classes/" + extUserClass + "/" + extUserId,
|
||||||
|
{
|
||||||
|
TourStatus: updatedTourStatus
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Parse-Application-Id": appId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//function to use check tour status of open sign drive
|
||||||
|
async function checkTourStatus() {
|
||||||
|
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;
|
||||||
|
setTourStatusArr(tourStatus);
|
||||||
|
const filteredtourStatus = tourStatus.filter((obj) => obj["driveTour"]);
|
||||||
|
if (filteredtourStatus.length > 0) {
|
||||||
|
const driveTour = filteredtourStatus[0]["driveTour"];
|
||||||
|
// console.log("loginTour", loginTour);
|
||||||
|
if (driveTour) {
|
||||||
|
setIsTour(false);
|
||||||
|
} else {
|
||||||
|
setIsTour(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsTour(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsTour(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div style={{ backgroundColor: "white" }} className="folderComponent">
|
<div style={{ backgroundColor: "white" }} className="folderComponent">
|
||||||
<Title title={"OpenSign™ Drive"} drive={true} />
|
<Title title={"OpenSign™ Drive"} drive={true} />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
headerColor={"#dc3545"}
|
headerColor={"#dc3545"}
|
||||||
@@ -518,7 +699,19 @@ function Opensigndrive() {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="folderContainer">
|
<div className="folderContainer">
|
||||||
|
{tourData && (
|
||||||
|
<Tour
|
||||||
|
onRequestClose={closeTour}
|
||||||
|
steps={tourData}
|
||||||
|
isOpen={isTour}
|
||||||
|
closeWithMask={false}
|
||||||
|
scrollOffset={-100}
|
||||||
|
rounded={5}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
data-tut="reactourFirst"
|
||||||
onMouseEnter={(e) => handleMouseEnter(e)}
|
onMouseEnter={(e) => handleMouseEnter(e)}
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
style={{
|
style={{
|
||||||
@@ -536,7 +729,7 @@ function Opensigndrive() {
|
|||||||
}
|
}
|
||||||
onClick={() => setIsNewFol(!isNewFol)}
|
onClick={() => setIsNewFol(!isNewFol)}
|
||||||
>
|
>
|
||||||
<div className="sort">
|
<div className="sort" data-tut="reactourSecond">
|
||||||
<i
|
<i
|
||||||
className="fa fa-plus-square"
|
className="fa fa-plus-square"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -597,7 +790,11 @@ function Opensigndrive() {
|
|||||||
className={isShowSort ? "dropdown show" : "dropdown"}
|
className={isShowSort ? "dropdown show" : "dropdown"}
|
||||||
onClick={() => setIsShowSort(!isShowSort)}
|
onClick={() => setIsShowSort(!isShowSort)}
|
||||||
>
|
>
|
||||||
<div className=" sort " data-toggle="dropdown">
|
<div
|
||||||
|
data-tut="reactourThird"
|
||||||
|
className=" sort "
|
||||||
|
data-toggle="dropdown"
|
||||||
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-sort-amount-asc"
|
className="fa fa-sort-amount-asc"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -687,7 +884,11 @@ function Opensigndrive() {
|
|||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="sort" onClick={() => setIsList(!isList)}>
|
<div
|
||||||
|
data-tut="reactourForth"
|
||||||
|
className="sort"
|
||||||
|
onClick={() => setIsList(!isList)}
|
||||||
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-list"
|
className="fa fa-list"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -712,23 +913,28 @@ function Opensigndrive() {
|
|||||||
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<React.Suspense fallback={<Loader />}>
|
<div data-tut="reactourFifth">
|
||||||
<DriveBody
|
<React.Suspense fallback={<Loader />}>
|
||||||
pdfData={pdfData}
|
<DriveBody
|
||||||
setFolderName={setFolderName}
|
dataTutSixth="reactourSixth"
|
||||||
setIsLoading={setIsLoading}
|
dataTutSeventh="reactourSeventh"
|
||||||
setDocId={setDocId}
|
pdfData={pdfData}
|
||||||
getPdfDocumentList={getPdfDocumentList}
|
setFolderName={setFolderName}
|
||||||
isDocId={docId}
|
setIsLoading={setIsLoading}
|
||||||
setPdfData={setPdfData}
|
setDocId={setDocId}
|
||||||
isList={isList}
|
getPdfDocumentList={getPdfDocumentList}
|
||||||
setIsAlert={setIsAlert}
|
isDocId={docId}
|
||||||
setSkip={setSkip}
|
setPdfData={setPdfData}
|
||||||
/>
|
isList={isList}
|
||||||
{loading && (
|
setIsAlert={setIsAlert}
|
||||||
<div style={{ textAlign: "center" }}>Loading...</div>
|
setSkip={setSkip}
|
||||||
)}
|
sortingData={sortingData}
|
||||||
</React.Suspense>
|
/>
|
||||||
|
{loading && (
|
||||||
|
<div style={{ textAlign: "center" }}>Loading...</div>
|
||||||
|
)}
|
||||||
|
</React.Suspense>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -41,12 +41,8 @@ const PgSignUp = () => {
|
|||||||
const url = window.location.href;
|
const url = window.location.href;
|
||||||
let paramString = url.split("?")[1];
|
let paramString = url.split("?")[1];
|
||||||
let queryString = new URLSearchParams(paramString);
|
let queryString = new URLSearchParams(paramString);
|
||||||
// console.log("url ", queryString);
|
|
||||||
|
|
||||||
let obj = { ...formData };
|
let obj = { ...formData };
|
||||||
for (let pair of queryString.entries()) {
|
for (let pair of queryString.entries()) {
|
||||||
// console.log("Key is: " + pair[0]);
|
|
||||||
// console.log("Value is: " + pair[1]);
|
|
||||||
obj = { ...obj, [pair[0]]: pair[1] };
|
obj = { ...obj, [pair[0]]: pair[1] };
|
||||||
}
|
}
|
||||||
const zohoRes = await axios.post(
|
const zohoRes = await axios.post(
|
||||||
@@ -61,34 +57,27 @@ const PgSignUp = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// console.log("zohoRes ", zohoRes);
|
|
||||||
const userSettings = JSON.parse(localStorage.getItem("userSettings"));
|
const userSettings = JSON.parse(localStorage.getItem("userSettings"));
|
||||||
const extClass = userSettings[0].extended_class;
|
const params = { subscription: zohoRes.data.result.subscription };
|
||||||
// console.log("extClass ", extClass);
|
const baseurl = `${parseBaseUrl}functions/savesubscription`;
|
||||||
const params = { email: userDetails.email };
|
try {
|
||||||
const res = await Parse.Cloud.run("getUserDetails", params);
|
const res = await axios.post(baseurl, params, {
|
||||||
// console.log("res", res);
|
headers: {
|
||||||
if (res) {
|
"Content-Type": "application/json",
|
||||||
const updateQuery = new Parse.Object(extClass);
|
"X-Parse-Application-Id": parseAppId,
|
||||||
updateQuery.id = res.id;
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
updateQuery.set(
|
}
|
||||||
"Next_billing_date",
|
});
|
||||||
new Date(zohoRes.data.result.nextBillingDate)
|
if (res) {
|
||||||
);
|
|
||||||
updateQuery.set("Plan", zohoRes.data.result.plan);
|
|
||||||
updateQuery.set("Customer_id", zohoRes.data.result.customer_id);
|
|
||||||
updateQuery.set(
|
|
||||||
"Subscription_id",
|
|
||||||
zohoRes.data.result.subscription_id
|
|
||||||
);
|
|
||||||
const updateRes = await updateQuery.save();
|
|
||||||
if (updateRes) {
|
|
||||||
localStorage.removeItem("userDetails");
|
localStorage.removeItem("userDetails");
|
||||||
navigate(
|
navigate(
|
||||||
"/" + userSettings[0].pageType + "/" + userSettings[0].pageId
|
"/" + userSettings[0].pageType + "/" + userSettings[0].pageId
|
||||||
);
|
);
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err ", err.message);
|
||||||
|
setIsLoader(false);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err ", err);
|
console.log("err ", err);
|
||||||
@@ -108,12 +97,8 @@ const PgSignUp = () => {
|
|||||||
const url = window.location.href;
|
const url = window.location.href;
|
||||||
let paramString = url.split("?")[1];
|
let paramString = url.split("?")[1];
|
||||||
let queryString = new URLSearchParams(paramString);
|
let queryString = new URLSearchParams(paramString);
|
||||||
// console.log("url ", queryString);
|
|
||||||
|
|
||||||
let obj = { ...formData };
|
let obj = { ...formData };
|
||||||
for (let pair of queryString.entries()) {
|
for (let pair of queryString.entries()) {
|
||||||
// console.log("Key is: " + pair[0]);
|
|
||||||
// console.log("Value is: " + pair[1]);
|
|
||||||
obj = { ...obj, [pair[0]]: pair[1] };
|
obj = { ...obj, [pair[0]]: pair[1] };
|
||||||
}
|
}
|
||||||
saveUser(obj);
|
saveUser(obj);
|
||||||
@@ -157,19 +142,8 @@ const PgSignUp = () => {
|
|||||||
email: zohoRes.data.result.email,
|
email: zohoRes.data.result.email,
|
||||||
phone: zohoRes.data.result.phone,
|
phone: zohoRes.data.result.phone,
|
||||||
role: obj.role
|
role: obj.role
|
||||||
// "pincode": "",
|
|
||||||
// "address": "",
|
|
||||||
// "country": "",
|
|
||||||
// "state": "",
|
|
||||||
// "city": ""
|
|
||||||
},
|
},
|
||||||
|
subscription: zohoRes.data.result.subscription
|
||||||
planDetails: {
|
|
||||||
plan: zohoRes.data.result.plan || {},
|
|
||||||
nextBillingDate: zohoRes.data.result.nextBillingDate || "",
|
|
||||||
customer_id: zohoRes.data.result.customer_id || "",
|
|
||||||
subscription_id: zohoRes.data.result.subscription_id || ""
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const usersignup = await Parse.Cloud.run("usersignup", params);
|
const usersignup = await Parse.Cloud.run("usersignup", params);
|
||||||
// console.log("usersignup ", usersignup);
|
// console.log("usersignup ", usersignup);
|
||||||
@@ -353,7 +327,7 @@ const PgSignUp = () => {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router";
|
import { NavLink, useNavigate } from "react-router-dom";
|
||||||
import { NavLink } from "react-router-dom";
|
|
||||||
import checkmark from "../assets/images/checkmark.png";
|
import checkmark from "../assets/images/checkmark.png";
|
||||||
import plansArr from "../json/plansArr.json";
|
import plansArr from "../json/plansArr";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
|
import Parse from "parse";
|
||||||
const listItemStyle = {
|
const listItemStyle = {
|
||||||
paddingLeft: "20px", // Add padding to create space for the image
|
paddingLeft: "20px", // Add padding to create space for the image
|
||||||
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
|
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
|
||||||
@@ -19,15 +19,22 @@ const PlanSubscriptions = () => {
|
|||||||
|
|
||||||
const userDetails = JSON.parse(localStorage.getItem("userDetails"));
|
const userDetails = JSON.parse(localStorage.getItem("userDetails"));
|
||||||
const name =
|
const name =
|
||||||
userDetails && userDetails.name ? "first_name=" + userDetails.name : "";
|
userDetails && userDetails.name
|
||||||
|
? "first_name=" + encodeURIComponent(userDetails.name)
|
||||||
|
: "";
|
||||||
const email =
|
const email =
|
||||||
userDetails && userDetails.email ? "&email=" + userDetails.email : "";
|
userDetails && userDetails.email
|
||||||
|
? "&email=" + encodeURIComponent(userDetails.email)
|
||||||
|
: "";
|
||||||
const company =
|
const company =
|
||||||
userDetails && userDetails.company
|
userDetails && userDetails.company
|
||||||
? "&company_name=" + userDetails.company
|
? "&company_name=" + encodeURIComponent(userDetails.company)
|
||||||
: "";
|
: "";
|
||||||
const phone =
|
const phone =
|
||||||
userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : "";
|
userDetails && userDetails.phone
|
||||||
|
? "&mobile=" + encodeURIComponent(userDetails.phone)
|
||||||
|
: "";
|
||||||
|
|
||||||
const details =
|
const details =
|
||||||
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
|
||||||
name +
|
name +
|
||||||
@@ -35,15 +42,35 @@ const PlanSubscriptions = () => {
|
|||||||
company +
|
company +
|
||||||
phone;
|
phone;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem("accesstoken")) {
|
// if (localStorage.getItem("accesstoken")) {
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
setYearlyVisible(false);
|
// } else {
|
||||||
} else {
|
// navigate("/", { replace: true });
|
||||||
navigate("/", { replace: true });
|
// }
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleFreePlan = async () => {
|
||||||
|
setIsLoader(true);
|
||||||
|
try {
|
||||||
|
const params = { userId: Parse.User.current().id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "success" && res.result === "already subscribed!") {
|
||||||
|
setIsLoader(false);
|
||||||
|
alert("You have already subscribed to plan!");
|
||||||
|
} else if (res.status === "success") {
|
||||||
|
setIsLoader(false);
|
||||||
|
navigate("/");
|
||||||
|
} else if (res.status === "error") {
|
||||||
|
setIsLoader(false);
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setIsLoader(false);
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title={"Subscriptions"} />
|
<Title title={"Subscriptions"} />
|
||||||
@@ -69,23 +96,40 @@ const PlanSubscriptions = () => {
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
maxHeight: "100%",
|
maxHeight: "100%"
|
||||||
"--theme-color": "#7952b3",
|
|
||||||
"--plan-width": 30
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div className="block my-2">
|
||||||
id="monthlyPlans"
|
<div className="flex flex-col justify-center items-center w-full">
|
||||||
className={`${yearlyVisible ? "none" : "block my-2"}`}
|
<div className="mb-6 mt-2 flex flex-row border-[1px] p-2 border-gray-300 rounded text-sm">
|
||||||
>
|
<span
|
||||||
<div className="flex justify-center w-full my-2">
|
onClick={() => setYearlyVisible(false)}
|
||||||
<ul className=" flex flex-col md:flex-row h-full bg-white justify-center border-collapse border-[1px] border-gray-300">
|
className={`${
|
||||||
|
!yearlyVisible
|
||||||
|
? "bg-[#002862] text-white"
|
||||||
|
: "bg-white text-black"
|
||||||
|
} px-4 py-1 rounded cursor-pointer`}
|
||||||
|
>
|
||||||
|
Monthly
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
onClick={() => setYearlyVisible(true)}
|
||||||
|
className={`${
|
||||||
|
yearlyVisible
|
||||||
|
? "bg-[#002862] text-white"
|
||||||
|
: "bg-white text-black"
|
||||||
|
} px-4 py-1 rounded cursor-pointer`}
|
||||||
|
>
|
||||||
|
Yearly (10% off)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ul className="flex flex-col md:flex-row h-full bg-white justify-center">
|
||||||
{plansArr.map((item) => (
|
{plansArr.map((item) => (
|
||||||
<li
|
<li
|
||||||
className="flex flex-col md:my-0 text-center border-[1px] border-gray-300 w-[260px]"
|
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
|
||||||
key={item.planName}
|
key={item.planName}
|
||||||
>
|
>
|
||||||
<div className="p-2 flex flex-col justify-center items-center">
|
<div className="p-2 flex flex-col justify-center items-center max-h-[310px]">
|
||||||
<h3 className="text-[#002862] uppercase">
|
<h3 className="text-[#002862] uppercase">
|
||||||
{item.planName}
|
{item.planName}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -96,20 +140,20 @@ const PlanSubscriptions = () => {
|
|||||||
alt="freeimg"
|
alt="freeimg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="">
|
<div>
|
||||||
<span className="text-3xl">
|
<span className="text-3xl">
|
||||||
{item.currency && <small>{item.currency}</small>}
|
{item.currency && <small>{item.currency}</small>}
|
||||||
{item.price}
|
{yearlyVisible
|
||||||
|
? item?.yearlyPrice
|
||||||
|
: item.monthlyPrice}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<p className="font-semibold pt-2 text-sm">
|
||||||
className={`${
|
{yearlyVisible ? "Billed Yearly" : "Billed Monthly"}
|
||||||
item.subtitle.length <= 32
|
</p>
|
||||||
? "w-[150px] text-center"
|
<div className="max-w-[250px] h-[40px] text-center text-sm my-2">
|
||||||
: ""
|
<div
|
||||||
} text-sm text-center my-2`}
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
style={{
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
backgroundColor: item.subtitlecolor
|
backgroundColor: item.subtitlecolor
|
||||||
? item.subtitlecolor
|
? item.subtitlecolor
|
||||||
: "white"
|
: "white"
|
||||||
@@ -124,23 +168,33 @@ const PlanSubscriptions = () => {
|
|||||||
) : (
|
) : (
|
||||||
<span>{item.subtitle}</span>
|
<span>{item.subtitle}</span>
|
||||||
)}
|
)}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{item.url ? (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={
|
to={
|
||||||
item.btnText === "Subscribe"
|
item.btnText === "Subscribe"
|
||||||
? item.url + details
|
? yearlyVisible
|
||||||
: item.url
|
? item.yearlyUrl + details
|
||||||
}
|
: item.url + details
|
||||||
className="bg-[#002862] w-full text-white py-2 rounded uppercase hover:no-underline hover:text-white"
|
: item.url
|
||||||
target={item.target}
|
}
|
||||||
>
|
className="bg-[#002862] w-full text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer"
|
||||||
{item.btnText}
|
target={item.target}
|
||||||
</NavLink>
|
>
|
||||||
|
{item.btnText}
|
||||||
|
</NavLink>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
className="bg-[#002862] w-full text-white py-2 rounded uppercase hover:text-white cursor-pointer"
|
||||||
|
onClick={() => handleFreePlan()}
|
||||||
|
>
|
||||||
|
{item.btnText}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<hr className="w-full bg-gray-300 p-[.5px]" />
|
<hr className="w-full bg-gray-300 h-[0.5px]" />
|
||||||
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
|
||||||
{item.benefits.map((subitem, index) => (
|
{item.benefits.map((subitem, index) => (
|
||||||
<li style={listItemStyle} key={index} className="m-1">
|
<li style={listItemStyle} key={index} className="m-1">
|
||||||
@@ -154,6 +208,23 @@ const PlanSubscriptions = () => {
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-sm flex justify-center items-center">
|
||||||
|
<hr className="border-[1px] border-gray-300 w-[20%]" />
|
||||||
|
<span className="px-2 text-gray-500 cursor-default">or</span>
|
||||||
|
<hr className="border-[1px] border-gray-300 w-[20%]" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center w-full items-center">
|
||||||
|
<h3 className="text-[#002862] mt-1 mb-2">
|
||||||
|
Host it yourself for free
|
||||||
|
</h3>
|
||||||
|
<NavLink
|
||||||
|
to={"https://github.com/OpenSignLabs/OpenSign"}
|
||||||
|
className="bg-[#002862] w-[200px] text-center text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer"
|
||||||
|
target={"_blank"}
|
||||||
|
>
|
||||||
|
Visit Github
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import reportJson from "../json/ReportJson";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
|
||||||
const Report = () => {
|
const Report = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@@ -18,6 +19,8 @@ const Report = () => {
|
|||||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||||
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
||||||
const [form, setForm] = useState("");
|
const [form, setForm] = useState("");
|
||||||
|
const [tourData, setTourData] = useState([]);
|
||||||
|
const [isDontShow, setIsDontShow] = useState(false);
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
const docPerPage = 10;
|
const docPerPage = 10;
|
||||||
|
|
||||||
@@ -46,6 +49,9 @@ const Report = () => {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [isNextRecord]);
|
}, [isNextRecord]);
|
||||||
|
|
||||||
|
const handleDontShow = (isChecked) => {
|
||||||
|
setIsDontShow(isChecked);
|
||||||
|
};
|
||||||
const getReportData = async (skipUserRecord = 0, limit = 200) => {
|
const getReportData = async (skipUserRecord = 0, limit = 200) => {
|
||||||
// setIsLoader(true);
|
// setIsLoader(true);
|
||||||
const json = reportJson(id);
|
const json = reportJson(id);
|
||||||
@@ -54,7 +60,7 @@ const Report = () => {
|
|||||||
setHeading(json.heading);
|
setHeading(json.heading);
|
||||||
setReportName(json.reportName);
|
setReportName(json.reportName);
|
||||||
setForm(json.form);
|
setForm(json.form);
|
||||||
setReportHelp(json?.helpMsg)
|
setReportHelp(json?.helpMsg);
|
||||||
const currentUser = Parse.User.current().id;
|
const currentUser = Parse.User.current().id;
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -69,6 +75,42 @@ const Report = () => {
|
|||||||
headers: headers,
|
headers: headers,
|
||||||
signal: abortController.signal // is used to cancel fetch query
|
signal: abortController.signal // is used to cancel fetch query
|
||||||
});
|
});
|
||||||
|
if (id === "6TeaPr321t") {
|
||||||
|
const tourConfig = [
|
||||||
|
{
|
||||||
|
selector: "[data-tut=reactourFirst]",
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={
|
||||||
|
"Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. "
|
||||||
|
}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
if (res.data.result && res.data.result?.length > 0) {
|
||||||
|
json.actions.map((data) => {
|
||||||
|
const newConfig = {
|
||||||
|
selector: `[data-tut="${data?.selector}"]`,
|
||||||
|
content: () => (
|
||||||
|
<TourContentWithBtn
|
||||||
|
message={data?.message}
|
||||||
|
isChecked={handleDontShow}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
};
|
||||||
|
tourConfig.push(newConfig);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTourData(tourConfig);
|
||||||
|
}
|
||||||
if (id === "4Hhwbp482K") {
|
if (id === "4Hhwbp482K") {
|
||||||
const listData = res.data?.result.filter((x) => x.Signers.length > 0);
|
const listData = res.data?.result.filter((x) => x.Signers.length > 0);
|
||||||
let arr = [];
|
let arr = [];
|
||||||
@@ -106,12 +148,14 @@ const Report = () => {
|
|||||||
} else {
|
} else {
|
||||||
setIsMoreDocs(false);
|
setIsMoreDocs(false);
|
||||||
}
|
}
|
||||||
setIsNextRecord(false);
|
if (!res.data.result.error) {
|
||||||
setList((prevRecord) =>
|
setIsNextRecord(false);
|
||||||
prevRecord.length > 0
|
setList((prevRecord) =>
|
||||||
? [...prevRecord, ...res.data.result]
|
prevRecord.length > 0
|
||||||
: res.data.result
|
? [...prevRecord, ...res.data.result]
|
||||||
);
|
: res.data.result
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setIsLoader(false);
|
setIsLoader(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -159,6 +203,8 @@ const Report = () => {
|
|||||||
docPerPage={docPerPage}
|
docPerPage={docPerPage}
|
||||||
form={form}
|
form={form}
|
||||||
report_help={reporthelp}
|
report_help={reporthelp}
|
||||||
|
tourData={tourData}
|
||||||
|
isDontShow={isDontShow}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<PageNotFound prefix={"Report"} />
|
<PageNotFound prefix={"Report"} />
|
||||||
|
|||||||
@@ -2,17 +2,20 @@ import React, { useState, useEffect } from "react";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import { useNavigate, NavLink } from "react-router-dom";
|
import { useNavigate, NavLink, useLocation } from "react-router-dom";
|
||||||
import login_img from "../assets/images/login_img.svg";
|
import login_img from "../assets/images/login_img.svg";
|
||||||
import { useWindowSize } from "../hook/useWindowSize";
|
import { useWindowSize } from "../hook/useWindowSize";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import { appInfo } from "../constant/appinfo";
|
import { appInfo } from "../constant/appinfo";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||||
import { showTenant } from "../redux/reducers/ShowTenant";
|
import { showTenant } from "../redux/reducers/ShowTenant";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { getAppLogo } from "../constant/Utils";
|
||||||
const Signup = () => {
|
const Signup = () => {
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [phone, setPhone] = useState("");
|
const [phone, setPhone] = useState("");
|
||||||
@@ -20,6 +23,7 @@ const Signup = () => {
|
|||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [company, setCompany] = useState("");
|
const [company, setCompany] = useState("");
|
||||||
const [jobTitle, setJobTitle] = useState("");
|
const [jobTitle, setJobTitle] = useState("");
|
||||||
|
const [image, setImage] = useState();
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
alertType: "success",
|
alertType: "success",
|
||||||
@@ -31,7 +35,6 @@ const Signup = () => {
|
|||||||
const [specialCharValid, setSpecialCharValid] = useState(false);
|
const [specialCharValid, setSpecialCharValid] = useState(false);
|
||||||
|
|
||||||
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
const togglePasswordVisibility = () => setShowPassword(!showPassword);
|
||||||
const image = appInfo.applogo;
|
|
||||||
|
|
||||||
const clearStorage = async () => {
|
const clearStorage = async () => {
|
||||||
if (Parse.User.current()) {
|
if (Parse.User.current()) {
|
||||||
@@ -67,6 +70,19 @@ const Signup = () => {
|
|||||||
localStorage.setItem("baseUrl", baseUrl);
|
localStorage.setItem("baseUrl", baseUrl);
|
||||||
localStorage.setItem("parseAppId", appid);
|
localStorage.setItem("parseAppId", appid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFreePlan = async (id) => {
|
||||||
|
try {
|
||||||
|
const params = { userId: id };
|
||||||
|
const res = await Parse.Cloud.run("freesubscription", params);
|
||||||
|
if (res.status === "error") {
|
||||||
|
alert(res.result);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in free subscribe", err.message);
|
||||||
|
alert("Somenthing went wrong, please try again later!");
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (lengthValid && caseDigitValid && specialCharValid) {
|
if (lengthValid && caseDigitValid && specialCharValid) {
|
||||||
@@ -110,7 +126,13 @@ const Signup = () => {
|
|||||||
params
|
params
|
||||||
);
|
);
|
||||||
if (usersignup) {
|
if (usersignup) {
|
||||||
handleNavigation(r.getSessionToken());
|
const param = new URLSearchParams(location.search);
|
||||||
|
const isFreeplan =
|
||||||
|
param?.get("subscription") === "freeplan";
|
||||||
|
if (isFreeplan) {
|
||||||
|
await handleFreePlan(r.id);
|
||||||
|
}
|
||||||
|
handleNavigation(r.getSessionToken(), isFreeplan);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err.message);
|
alert(err.message);
|
||||||
@@ -155,7 +177,7 @@ const Signup = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigation = async (sessionToken) => {
|
const handleNavigation = async (sessionToken, isFreeplan = false) => {
|
||||||
const baseUrl = localStorage.getItem("baseUrl");
|
const baseUrl = localStorage.getItem("baseUrl");
|
||||||
const parseAppId = localStorage.getItem("parseAppId");
|
const parseAppId = localStorage.getItem("parseAppId");
|
||||||
const res = await axios.get(baseUrl + "users/me", {
|
const res = await axios.get(baseUrl + "users/me", {
|
||||||
@@ -259,9 +281,7 @@ const Signup = () => {
|
|||||||
});
|
});
|
||||||
if (tenentInfo.length) {
|
if (tenentInfo.length) {
|
||||||
dispatch(
|
dispatch(
|
||||||
showTenant(
|
showTenant(tenentInfo[0].tenentName || "")
|
||||||
tenentInfo[0].tenentName || ""
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenantName",
|
"TenantName",
|
||||||
@@ -297,7 +317,7 @@ const Signup = () => {
|
|||||||
tenentName: x.TenantId.TenantName || ""
|
tenentName: x.TenantId.TenantName || ""
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"TenetId",
|
"TenantId",
|
||||||
x.TenantId.objectId
|
x.TenantId.objectId
|
||||||
);
|
);
|
||||||
tenentInfo.push(obj);
|
tenentInfo.push(obj);
|
||||||
@@ -325,8 +345,14 @@ const Signup = () => {
|
|||||||
element.pageType
|
element.pageType
|
||||||
);
|
);
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(
|
||||||
|
`/${element.pageType}/${element.pageId}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, { replace: true });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Registered user successfully");
|
alert("Registered user successfully");
|
||||||
navigate(
|
navigate(
|
||||||
@@ -343,8 +369,14 @@ const Signup = () => {
|
|||||||
);
|
);
|
||||||
localStorage.setItem("pageType", element.pageType);
|
localStorage.setItem("pageType", element.pageType);
|
||||||
setState({ loading: false });
|
setState({ loading: false });
|
||||||
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
|
if (isEnableSubscription) {
|
||||||
navigate(`/subscription`, { replace: true });
|
if (isFreeplan) {
|
||||||
|
navigate(
|
||||||
|
`/${element.pageType}/${element.pageId}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`, { replace: true });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
navigate(
|
||||||
`/${element.pageType}/${element.pageId}`
|
`/${element.pageType}/${element.pageId}`
|
||||||
@@ -438,9 +470,23 @@ const Signup = () => {
|
|||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(fetchAppInfo());
|
dispatch(fetchAppInfo());
|
||||||
|
saveLogo();
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const saveLogo = async () => {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const logo = await getAppLogo();
|
||||||
|
if (logo) {
|
||||||
|
setImage(logo);
|
||||||
|
} else {
|
||||||
|
setImage(appInfo?.applogo || undefined);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setImage(appInfo?.applogo || undefined);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handlePasswordChange = (e) => {
|
const handlePasswordChange = (e) => {
|
||||||
const newPassword = e.target.value;
|
const newPassword = e.target.value;
|
||||||
setPassword(newPassword);
|
setPassword(newPassword);
|
||||||
@@ -486,8 +532,10 @@ const Signup = () => {
|
|||||||
{appInfo && appInfo.applogo ? (
|
{appInfo && appInfo.applogo ? (
|
||||||
<div>
|
<div>
|
||||||
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
|
||||||
<div className="w-[250px] h-[66px] inline-block">
|
<div className="w-[250px] h-[66px] inline-block overflow-hidden">
|
||||||
<img src={image} width="100%" alt="" />
|
{image && (
|
||||||
|
<img src={image} className="object-contain h-full" alt="logo" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||||
<div className="">
|
<div className="">
|
||||||
@@ -626,7 +674,7 @@ const Signup = () => {
|
|||||||
</button>
|
</button>
|
||||||
<NavLink
|
<NavLink
|
||||||
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
|
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
|
||||||
to="/"
|
to={location.search ? "/" + location.search : "/"}
|
||||||
style={width < 768 ? { textAlign: "center" } : {}}
|
style={width < 768 ? { textAlign: "center" } : {}}
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
@@ -661,4 +709,4 @@ const Signup = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Signup
|
export default Signup;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { PDFDocument } from "pdf-lib";
|
import { PDFDocument } from "pdf-lib";
|
||||||
import "../styles/signature.css";
|
import "../styles/signature.css";
|
||||||
import { themeColor } from "../constant/const";
|
import { isEnableSubscription, themeColor } from "../constant/const";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Loader from "../primitives/LoaderWithMsg";
|
import Loader from "../primitives/LoaderWithMsg";
|
||||||
import loader from "../assets/images/loader2.gif";
|
import loader from "../assets/images/loader2.gif";
|
||||||
@@ -26,7 +26,10 @@ import {
|
|||||||
contactBook,
|
contactBook,
|
||||||
randomId,
|
randomId,
|
||||||
getDate,
|
getDate,
|
||||||
textWidget
|
textWidget,
|
||||||
|
getTenantDetails,
|
||||||
|
checkIsSubscribed,
|
||||||
|
convertPdfArrayBuffer
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
@@ -67,7 +70,6 @@ function SignYourSelf() {
|
|||||||
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
|
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
|
||||||
const [successEmail, setSuccessEmail] = useState(false);
|
const [successEmail, setSuccessEmail] = useState(false);
|
||||||
const imageRef = useRef(null);
|
const imageRef = useRef(null);
|
||||||
const [documentStatus, setDocumentStatus] = useState({ isCompleted: false });
|
|
||||||
const [myInitial, setMyInitial] = useState("");
|
const [myInitial, setMyInitial] = useState("");
|
||||||
const [isInitial, setIsInitial] = useState(false);
|
const [isInitial, setIsInitial] = useState(false);
|
||||||
const [isUiLoading, setIsUiLoading] = useState(false);
|
const [isUiLoading, setIsUiLoading] = useState(false);
|
||||||
@@ -99,6 +101,9 @@ function SignYourSelf() {
|
|||||||
});
|
});
|
||||||
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
||||||
const [isDontShow, setIsDontShow] = useState(false);
|
const [isDontShow, setIsDontShow] = useState(false);
|
||||||
|
const [extUserId, setExtUserId] = useState("");
|
||||||
|
const [isCompleted, setIsCompleted] = useState(false);
|
||||||
|
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
||||||
const divRef = useRef(null);
|
const divRef = useRef(null);
|
||||||
const nodeRef = useRef(null);
|
const nodeRef = useRef(null);
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
@@ -186,13 +191,18 @@ function SignYourSelf() {
|
|||||||
|
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
setPdfDetails(documentData);
|
setPdfDetails(documentData);
|
||||||
|
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
|
||||||
|
const url = documentData[0] && documentData[0]?.URL;
|
||||||
|
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
|
||||||
|
const arrayBuffer = await convertPdfArrayBuffer(url);
|
||||||
|
if (arrayBuffer === "Error") {
|
||||||
|
setHandleError("Error: Something went wrong!");
|
||||||
|
} else {
|
||||||
|
setPdfArrayBuffer(arrayBuffer);
|
||||||
|
}
|
||||||
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
|
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
|
||||||
if (isCompleted) {
|
if (isCompleted) {
|
||||||
const docStatus = {
|
setIsCompleted(true);
|
||||||
isCompleted: isCompleted
|
|
||||||
};
|
|
||||||
setDocumentStatus(docStatus);
|
|
||||||
setPdfUrl(documentData[0].SignedUrl);
|
setPdfUrl(documentData[0].SignedUrl);
|
||||||
const alreadySign = {
|
const alreadySign = {
|
||||||
status: true,
|
status: true,
|
||||||
@@ -255,9 +265,7 @@ function SignYourSelf() {
|
|||||||
setHandleError("Error: Something went wrong!");
|
setHandleError("Error: Something went wrong!");
|
||||||
setIsLoading(loadObj);
|
setIsLoading(loadObj);
|
||||||
});
|
});
|
||||||
|
|
||||||
const contractUsersRes = await contractUsers(jsonSender.email);
|
const contractUsersRes = await contractUsers(jsonSender.email);
|
||||||
|
|
||||||
if (contractUsersRes[0] && contractUsersRes.length > 0) {
|
if (contractUsersRes[0] && contractUsersRes.length > 0) {
|
||||||
setContractName("_Users");
|
setContractName("_Users");
|
||||||
setSignerUserId(contractUsersRes[0].objectId);
|
setSignerUserId(contractUsersRes[0].objectId);
|
||||||
@@ -561,22 +569,14 @@ function SignYourSelf() {
|
|||||||
setIsCeleb(false);
|
setIsCeleb(false);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
setIsUiLoading(true);
|
setIsUiLoading(true);
|
||||||
const url = pdfDetails[0] && pdfDetails[0].URL;
|
const existingPdfBytes = pdfArrayBuffer;
|
||||||
|
|
||||||
const existingPdfBytes = await fetch(url).then((res) =>
|
|
||||||
res.arrayBuffer()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load a PDFDocument from the existing PDF bytes
|
// Load a PDFDocument from the existing PDF bytes
|
||||||
const pdfDoc = await PDFDocument.load(existingPdfBytes, {
|
const pdfDoc = await PDFDocument.load(existingPdfBytes, {
|
||||||
ignoreEncryption: true
|
ignoreEncryption: true
|
||||||
});
|
});
|
||||||
|
const isSignYourSelfFlow = true;
|
||||||
const flag = true;
|
|
||||||
|
|
||||||
const extUserPtr = pdfDetails[0].ExtUserPtr;
|
const extUserPtr = pdfDetails[0].ExtUserPtr;
|
||||||
const HeaderDocId = extUserPtr?.HeaderDocId;
|
const HeaderDocId = extUserPtr?.HeaderDocId;
|
||||||
|
|
||||||
//embed document's object id to all pages in pdf document
|
//embed document's object id to all pages in pdf document
|
||||||
if (!HeaderDocId) {
|
if (!HeaderDocId) {
|
||||||
await embedDocId(pdfDoc, documentId, allPages);
|
await embedDocId(pdfDoc, documentId, allPages);
|
||||||
@@ -586,7 +586,7 @@ function SignYourSelf() {
|
|||||||
xyPostion,
|
xyPostion,
|
||||||
pdfDoc,
|
pdfDoc,
|
||||||
pdfOriginalWidth,
|
pdfOriginalWidth,
|
||||||
flag,
|
isSignYourSelfFlow,
|
||||||
containerWH
|
containerWH
|
||||||
);
|
);
|
||||||
// console.log("pdf", pdfBytes);
|
// console.log("pdf", pdfBytes);
|
||||||
@@ -597,9 +597,25 @@ function SignYourSelf() {
|
|||||||
// console.log("signyourself", xyPostion);
|
// console.log("signyourself", xyPostion);
|
||||||
//function for get digital signature
|
//function for get digital signature
|
||||||
const signPdfFun = async (base64Url, documentId) => {
|
const signPdfFun = async (base64Url, documentId) => {
|
||||||
|
let isCustomCompletionMail = false;
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
const tenantDetails = await getTenantDetails(jsonSender.objectId);
|
||||||
|
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||||
|
alert("User does not exist");
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
tenantDetails?.CompletionBody &&
|
||||||
|
tenantDetails?.CompletionSubject &&
|
||||||
|
(!isEnableSubscription || getIsSubscribe)
|
||||||
|
) {
|
||||||
|
isCustomCompletionMail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let singleSign = {
|
let singleSign = {
|
||||||
pdfFile: base64Url,
|
pdfFile: base64Url,
|
||||||
docId: documentId
|
docId: documentId,
|
||||||
|
isCustomCompletionMail: isCustomCompletionMail
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios
|
await axios
|
||||||
@@ -985,8 +1001,9 @@ function SignYourSelf() {
|
|||||||
{/* this component used to render all pdf pages in left side */}
|
{/* this component used to render all pdf pages in left side */}
|
||||||
|
|
||||||
<RenderAllPdfPage
|
<RenderAllPdfPage
|
||||||
pdfUrl={pdfUrl}
|
signPdfUrl={
|
||||||
signPdfUrl={pdfDetails[0] && pdfDetails[0].URL}
|
pdfDetails[0] && (pdfDetails[0].SignedUrl || pdfDetails[0].URL)
|
||||||
|
}
|
||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
setAllPages={setAllPages}
|
setAllPages={setAllPages}
|
||||||
setPageNumber={setPageNumber}
|
setPageNumber={setPageNumber}
|
||||||
@@ -1120,6 +1137,7 @@ function SignYourSelf() {
|
|||||||
setSuccessEmail={setSuccessEmail}
|
setSuccessEmail={setSuccessEmail}
|
||||||
sender={jsonSender}
|
sender={jsonSender}
|
||||||
setIsAlert={setIsAlert}
|
setIsAlert={setIsAlert}
|
||||||
|
extUserId={extUserId}
|
||||||
/>
|
/>
|
||||||
{/* pdf header which contain funish back button */}
|
{/* pdf header which contain funish back button */}
|
||||||
<Header
|
<Header
|
||||||
@@ -1127,7 +1145,6 @@ function SignYourSelf() {
|
|||||||
allPages={allPages}
|
allPages={allPages}
|
||||||
changePage={changePage}
|
changePage={changePage}
|
||||||
pdfUrl={pdfUrl}
|
pdfUrl={pdfUrl}
|
||||||
documentStatus={documentStatus}
|
|
||||||
embedWidgetsData={embedWidgetsData}
|
embedWidgetsData={embedWidgetsData}
|
||||||
pdfDetails={pdfDetails}
|
pdfDetails={pdfDetails}
|
||||||
isShowHeader={true}
|
isShowHeader={true}
|
||||||
@@ -1135,6 +1152,7 @@ function SignYourSelf() {
|
|||||||
alreadySign={pdfUrl ? true : false}
|
alreadySign={pdfUrl ? true : false}
|
||||||
isSignYourself={true}
|
isSignYourself={true}
|
||||||
setIsEmail={setIsEmail}
|
setIsEmail={setIsEmail}
|
||||||
|
isCompleted={isCompleted}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div data-tut="reactourSecond">
|
<div data-tut="reactourSecond">
|
||||||
@@ -1187,7 +1205,7 @@ function SignYourSelf() {
|
|||||||
}}
|
}}
|
||||||
className="autoSignScroll"
|
className="autoSignScroll"
|
||||||
>
|
>
|
||||||
{!documentStatus.isCompleted ? (
|
{!isCompleted ? (
|
||||||
<div>
|
<div>
|
||||||
<WidgetComponent
|
<WidgetComponent
|
||||||
dataTut="reactourFirst"
|
dataTut="reactourFirst"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
|||||||
import { useParams, useNavigate } from "react-router-dom";
|
import { useParams, useNavigate } from "react-router-dom";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import "../styles/signature.css";
|
import "../styles/signature.css";
|
||||||
import { themeColor } from "../constant/const";
|
import { isEnableSubscription, themeColor } from "../constant/const";
|
||||||
import { DndProvider } from "react-dnd";
|
import { DndProvider } from "react-dnd";
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
import { useDrag, useDrop } from "react-dnd";
|
import { useDrag, useDrop } from "react-dnd";
|
||||||
@@ -23,7 +23,8 @@ import {
|
|||||||
defaultWidthHeight,
|
defaultWidthHeight,
|
||||||
addWidgetOptions,
|
addWidgetOptions,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
radioButtonWidget
|
radioButtonWidget,
|
||||||
|
fetchSubscription
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import "../styles/AddUser.css";
|
import "../styles/AddUser.css";
|
||||||
@@ -52,6 +53,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const [isSelectListId, setIsSelectId] = useState();
|
const [isSelectListId, setIsSelectId] = useState();
|
||||||
const [isSendAlert, setIsSendAlert] = useState(false);
|
const [isSendAlert, setIsSendAlert] = useState(false);
|
||||||
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState({
|
const [isLoading, setIsLoading] = useState({
|
||||||
isLoad: true,
|
isLoad: true,
|
||||||
message: "This might take some time"
|
message: "This might take some time"
|
||||||
@@ -143,6 +145,7 @@ const TemplatePlaceholder = () => {
|
|||||||
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
|
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
|
||||||
const [isCheckbox, setIsCheckbox] = useState(false);
|
const [isCheckbox, setIsCheckbox] = useState(false);
|
||||||
const [widgetName, setWidgetName] = useState(false);
|
const [widgetName, setWidgetName] = useState(false);
|
||||||
|
const [isAddRole, setIsAddRole] = useState(false);
|
||||||
const senderUser =
|
const senderUser =
|
||||||
localStorage.getItem(
|
localStorage.getItem(
|
||||||
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
@@ -168,7 +171,23 @@ const TemplatePlaceholder = () => {
|
|||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [divRef.current]);
|
}, [divRef.current]);
|
||||||
|
async function checkIsSubscribed() {
|
||||||
|
const res = await fetchSubscription();
|
||||||
|
const freeplan = res.plan;
|
||||||
|
const billingDate = res.billingDate;
|
||||||
|
if (freeplan === "freeplan") {
|
||||||
|
return true;
|
||||||
|
} else if (billingDate) {
|
||||||
|
if (new Date(billingDate) > new Date()) {
|
||||||
|
setIsSubscribe(true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigate(`/subscription`);
|
||||||
|
}
|
||||||
|
}
|
||||||
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
|
||||||
const fetchTemplate = async () => {
|
const fetchTemplate = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -190,6 +209,9 @@ const TemplatePlaceholder = () => {
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (documentData && documentData.length > 0) {
|
if (documentData && documentData.length > 0) {
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
checkIsSubscribed(documentData[0]?.ExtUserPtr?.Email);
|
||||||
|
}
|
||||||
setPdfDetails(documentData);
|
setPdfDetails(documentData);
|
||||||
setIsSigners(true);
|
setIsSigners(true);
|
||||||
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
|
||||||
@@ -287,10 +309,10 @@ const TemplatePlaceholder = () => {
|
|||||||
if (tourstatus && tourstatus.length > 0) {
|
if (tourstatus && tourstatus.length > 0) {
|
||||||
setTourStatus(tourstatus);
|
setTourStatus(tourstatus);
|
||||||
const checkTourRecipients = tourstatus.filter(
|
const checkTourRecipients = tourstatus.filter(
|
||||||
(data) => data.templatetour
|
(data) => data.templateTour
|
||||||
);
|
);
|
||||||
if (checkTourRecipients && checkTourRecipients.length > 0) {
|
if (checkTourRecipients && checkTourRecipients.length > 0) {
|
||||||
setCheckTourStatus(checkTourRecipients[0].templatetour);
|
setCheckTourStatus(checkTourRecipients[0].templateTour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const loadObj = {
|
const loadObj = {
|
||||||
@@ -460,9 +482,20 @@ const TemplatePlaceholder = () => {
|
|||||||
} else {
|
} else {
|
||||||
setIsReceipent(false);
|
setIsReceipent(false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setIsAddRole(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tourAddRole = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="reactourAddbtn"]',
|
||||||
|
content: "You need to add a role before you can add fields for it. ",
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
//function for get pdf page details
|
//function for get pdf page details
|
||||||
const pageDetails = async (pdf) => {
|
const pageDetails = async (pdf) => {
|
||||||
const load = {
|
const load = {
|
||||||
@@ -741,7 +774,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourSecond"]',
|
selector: '[data-tut="reactourSecond"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Drag a widget placeholder onto the PDF to choose your desired signing location.`}
|
message={`Drag or click on a field to add it to the document.`}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -763,7 +796,7 @@ const TemplatePlaceholder = () => {
|
|||||||
selector: '[data-tut="reactourFour"]',
|
selector: '[data-tut="reactourFour"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={`Clicking "Save" button will save the template and will ask you if you want to create a new document using this template.`}
|
message={`Clicking ‘Save’ will store the current template. After saving, you’ll be prompted to create a new document from this template if you wish.`}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -781,15 +814,15 @@ const TemplatePlaceholder = () => {
|
|||||||
if (tourStatus.length > 0) {
|
if (tourStatus.length > 0) {
|
||||||
updatedTourStatus = [...tourStatus];
|
updatedTourStatus = [...tourStatus];
|
||||||
const templatetourIndex = tourStatus.findIndex(
|
const templatetourIndex = tourStatus.findIndex(
|
||||||
(obj) => obj["templatetour"] === false || obj["templatetour"] === true
|
(obj) => obj["templateTour"] === false || obj["templateTour"] === true
|
||||||
);
|
);
|
||||||
if (templatetourIndex !== -1) {
|
if (templatetourIndex !== -1) {
|
||||||
updatedTourStatus[templatetourIndex] = { templatetour: true };
|
updatedTourStatus[templatetourIndex] = { templateTour: true };
|
||||||
} else {
|
} else {
|
||||||
updatedTourStatus.push({ templatetour: true });
|
updatedTourStatus.push({ templateTour: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updatedTourStatus = [{ templatetour: true }];
|
updatedTourStatus = [{ templateTour: true }];
|
||||||
}
|
}
|
||||||
await axios
|
await axios
|
||||||
.put(
|
.put(
|
||||||
@@ -1099,8 +1132,6 @@ const TemplatePlaceholder = () => {
|
|||||||
inputype = options.includes(defaultdata.textvalidate)
|
inputype = options.includes(defaultdata.textvalidate)
|
||||||
? defaultdata.textvalidate
|
? defaultdata.textvalidate
|
||||||
: "regex";
|
: "regex";
|
||||||
} else {
|
|
||||||
inputype = "text";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
@@ -1125,11 +1156,14 @@ const TemplatePlaceholder = () => {
|
|||||||
status: defaultdata?.status || "required",
|
status: defaultdata?.status || "required",
|
||||||
hint: defaultdata?.hint || "",
|
hint: defaultdata?.hint || "",
|
||||||
defaultValue: defaultdata?.defaultValue || "",
|
defaultValue: defaultdata?.defaultValue || "",
|
||||||
validation: {
|
validation:
|
||||||
type: inputype,
|
(isSubscribe || !isEnableSubscription) && inputype
|
||||||
pattern:
|
? {
|
||||||
inputype === "regex" ? defaultdata.textvalidate : ""
|
type: inputype,
|
||||||
}
|
pattern:
|
||||||
|
inputype === "regex" ? defaultdata.textvalidate : ""
|
||||||
|
}
|
||||||
|
: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -1173,6 +1207,7 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsCheckbox(false);
|
setIsCheckbox(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("signerpos", signerPos);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Title title={"Template"} />
|
<Title title={"Template"} />
|
||||||
@@ -1197,6 +1232,15 @@ const TemplatePlaceholder = () => {
|
|||||||
closeWithMask={false}
|
closeWithMask={false}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{isAddRole && (
|
||||||
|
<Tour
|
||||||
|
onRequestClose={() => setIsAddRole(false)}
|
||||||
|
steps={tourAddRole}
|
||||||
|
isOpen={isAddRole}
|
||||||
|
rounded={5}
|
||||||
|
closeWithMask={false}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{/* this component used to render all pdf pages in left side */}
|
{/* this component used to render all pdf pages in left side */}
|
||||||
<RenderAllPdfPage
|
<RenderAllPdfPage
|
||||||
signPdfUrl={pdfDetails[0].URL}
|
signPdfUrl={pdfDetails[0].URL}
|
||||||
@@ -1222,7 +1266,7 @@ const TemplatePlaceholder = () => {
|
|||||||
handleClose={() => setIsSendAlert(false)}
|
handleClose={() => setIsSendAlert(false)}
|
||||||
>
|
>
|
||||||
<div style={{ height: "100%", padding: 20 }}>
|
<div style={{ height: "100%", padding: 20 }}>
|
||||||
<p>Please add field for all recipients.</p>
|
<p>Please add at least one signature field for all roles.</p>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
@@ -1323,6 +1367,7 @@ const TemplatePlaceholder = () => {
|
|||||||
currWidgetsDetails={currWidgetsDetails}
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
/>
|
/>
|
||||||
<DropdownWidgetOption
|
<DropdownWidgetOption
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -1333,6 +1378,7 @@ const TemplatePlaceholder = () => {
|
|||||||
currWidgetsDetails={currWidgetsDetails}
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
/>
|
/>
|
||||||
<DropdownWidgetOption
|
<DropdownWidgetOption
|
||||||
type="dropdown"
|
type="dropdown"
|
||||||
@@ -1343,6 +1389,7 @@ const TemplatePlaceholder = () => {
|
|||||||
currWidgetsDetails={currWidgetsDetails}
|
currWidgetsDetails={currWidgetsDetails}
|
||||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
/>
|
/>
|
||||||
<PlaceholderCopy
|
<PlaceholderCopy
|
||||||
isPageCopy={isPageCopy}
|
isPageCopy={isPageCopy}
|
||||||
@@ -1524,6 +1571,7 @@ const TemplatePlaceholder = () => {
|
|||||||
isAddUser={isAddUser}
|
isAddUser={isAddUser}
|
||||||
uniqueId={uniqueId}
|
uniqueId={uniqueId}
|
||||||
closePopup={closePopup}
|
closePopup={closePopup}
|
||||||
|
signersData={signersdata}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
@@ -1542,6 +1590,7 @@ const TemplatePlaceholder = () => {
|
|||||||
isOpen={isNameModal}
|
isOpen={isNameModal}
|
||||||
handleClose={handleNameModal}
|
handleClose={handleNameModal}
|
||||||
handleData={handleWidgetdefaultdata}
|
handleData={handleWidgetdefaultdata}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ import sanitizeFileName from "../primitives/sanitizeFileName";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
import Tooltip from "../primitives/Tooltip";
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import { checkIsSubscribed } from "../constant/Utils";
|
||||||
|
import Upgrade from "../primitives/Upgrade";
|
||||||
|
|
||||||
function UserProfile() {
|
function UserProfile() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
||||||
|
let extendUser = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
const [editmode, setEditMode] = useState(false);
|
const [editmode, setEditMode] = useState(false);
|
||||||
@@ -21,15 +25,30 @@ function UserProfile() {
|
|||||||
const [isLoader, setIsLoader] = useState(false);
|
const [isLoader, setIsLoader] = useState(false);
|
||||||
const [percentage, setpercentage] = useState(0);
|
const [percentage, setpercentage] = useState(0);
|
||||||
const [isDisableDocId, setIsDisableDocId] = useState(false);
|
const [isDisableDocId, setIsDisableDocId] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
const [company, setCompany] = useState(
|
||||||
|
extendUser && extendUser?.[0]?.Company
|
||||||
|
);
|
||||||
|
const [jobTitle, setJobTitle] = useState(
|
||||||
|
extendUser && extendUser?.[0]?.JobTitle
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getUserDetail();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getUserDetail = async () => {
|
||||||
const extClass = localStorage.getItem("Extand_Class");
|
const extClass = localStorage.getItem("Extand_Class");
|
||||||
const jsonSender = JSON.parse(extClass);
|
const jsonSender = JSON.parse(extClass);
|
||||||
const HeaderDocId = jsonSender[0]?.HeaderDocId;
|
const HeaderDocId = jsonSender[0]?.HeaderDocId;
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
if (HeaderDocId) {
|
if (HeaderDocId) {
|
||||||
setIsDisableDocId(HeaderDocId);
|
setIsDisableDocId(HeaderDocId);
|
||||||
}
|
}
|
||||||
}, []);
|
};
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsLoader(true);
|
setIsLoader(true);
|
||||||
@@ -54,6 +73,7 @@ function UserProfile() {
|
|||||||
SetPhone(res.phone);
|
SetPhone(res.phone);
|
||||||
setImage(res.ProfilePic);
|
setImage(res.ProfilePic);
|
||||||
localStorage.setItem("username", res.name);
|
localStorage.setItem("username", res.name);
|
||||||
|
localStorage.setItem("profileImg", res.ProfilePic);
|
||||||
await updateExtUser({ Name: res.name, Phone: res.phone });
|
await updateExtUser({ Name: res.name, Phone: res.phone });
|
||||||
alert("Profile updated successfully.");
|
alert("Profile updated successfully.");
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
@@ -81,7 +101,9 @@ function UserProfile() {
|
|||||||
const body = {
|
const body = {
|
||||||
Phone: obj.Phone,
|
Phone: obj.Phone,
|
||||||
Name: obj.Name,
|
Name: obj.Name,
|
||||||
HeaderDocId: isDisableDocId
|
HeaderDocId: isDisableDocId,
|
||||||
|
JobTitle: jobTitle,
|
||||||
|
Company: company
|
||||||
};
|
};
|
||||||
await axios.put(
|
await axios.put(
|
||||||
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
|
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
|
||||||
@@ -135,9 +157,9 @@ function UserProfile() {
|
|||||||
// console.log("File URL:", response.url());
|
// console.log("File URL:", response.url());
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
setImage(response.url());
|
setImage(response.url());
|
||||||
localStorage.setItem("profileImg", response.url());
|
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
SaveFileSize(size, response.url());
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -155,7 +177,6 @@ function UserProfile() {
|
|||||||
const handleDisableDocId = () => {
|
const handleDisableDocId = () => {
|
||||||
setIsDisableDocId((prevChecked) => !prevChecked);
|
setIsDisableDocId((prevChecked) => !prevChecked);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Title title={"Profile"} />
|
<Title title={"Profile"} />
|
||||||
@@ -252,6 +273,40 @@ function UserProfile() {
|
|||||||
<span className="font-semibold">Email:</span>{" "}
|
<span className="font-semibold">Email:</span>{" "}
|
||||||
<span>{UserProfile && UserProfile.email}</span>
|
<span>{UserProfile && UserProfile.email}</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||||
|
editmode ? "py-1" : "py-2"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span className="font-semibold">Company:</span>{" "}
|
||||||
|
{editmode ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={company}
|
||||||
|
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||||
|
onChange={(e) => setCompany(e.target.value)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span>{extendUser?.[0].Company}</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">Job title:</span>{" "}
|
||||||
|
{editmode ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={jobTitle}
|
||||||
|
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
|
||||||
|
onChange={(e) => setJobTitle(e.target.value)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span>{extendUser?.[0]?.JobTitle}</span>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
|
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
|
||||||
<span className="font-semibold">Is Email verified:</span>{" "}
|
<span className="font-semibold">Is Email verified:</span>{" "}
|
||||||
<span>
|
<span>
|
||||||
@@ -262,14 +317,30 @@ function UserProfile() {
|
|||||||
</li>
|
</li>
|
||||||
<li className="border-y-[1px] border-gray-300 break-all">
|
<li className="border-y-[1px] border-gray-300 break-all">
|
||||||
<div className="flex justify-between items-center py-2">
|
<div className="flex justify-between items-center py-2">
|
||||||
<span className="font-semibold">
|
<span
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "font-semibold"
|
||||||
|
: "font-semibold text-gray-300"
|
||||||
|
}
|
||||||
|
>
|
||||||
Disable DocumentId :{" "}
|
Disable DocumentId :{" "}
|
||||||
<Tooltip url={"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"} />{" "}
|
<Tooltip
|
||||||
|
url={
|
||||||
|
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
|
||||||
|
}
|
||||||
|
isSubscribe={isSubscribe}
|
||||||
|
/>{" "}
|
||||||
|
{!isSubscribe && isEnableSubscription && <Upgrade />}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<label
|
<label
|
||||||
className={`${
|
className={
|
||||||
editmode ? "cursor-pointer" : ""
|
isSubscribe || !isEnableSubscription
|
||||||
} relative inline-flex items-center mb-0`}
|
? `${
|
||||||
|
editmode ? "cursor-pointer" : ""
|
||||||
|
} relative inline-flex items-center mb-0`
|
||||||
|
: "relative inline-flex items-center mb-0 pointer-events-none opacity-50"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
disabled={editmode ? false : true}
|
disabled={editmode ? false : true}
|
||||||
@@ -282,11 +353,13 @@ function UserProfile() {
|
|||||||
<div className="w-9 h-5 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-black rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-black peer-checked:bg-blue-600"></div>
|
<div className="w-9 h-5 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-black rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-black peer-checked:bg-blue-600"></div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<PremiumAlertHeader
|
{!isEnableSubscription && (
|
||||||
message={
|
<PremiumAlertHeader
|
||||||
"Disable documentId is free in beta, this feature will incur a fee later."
|
message={
|
||||||
}
|
"Disable documentId is free in beta, this feature will incur a fee later."
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
|
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import Alert from "../primitives/Alert";
|
import Alert from "../primitives/Alert";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
import ModalUi from "../primitives/ModalUi";
|
||||||
import { rejectBtn, submitBtn } from "../constant/const";
|
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||||
import Tooltip from "../primitives/Tooltip";
|
import Tooltip from "../primitives/Tooltip";
|
||||||
|
|
||||||
function Webhook() {
|
function Webhook() {
|
||||||
|
const navigation = useNavigate();
|
||||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||||
const [webhook, setWebhook] = useState();
|
const [webhook, setWebhook] = useState();
|
||||||
@@ -17,6 +19,8 @@ function Webhook() {
|
|||||||
const [isGenerate, setIsGenerate] = useState(false);
|
const [isGenerate, setIsGenerate] = useState(false);
|
||||||
const [isErr, setIsErr] = useState(false);
|
const [isErr, setIsErr] = useState(false);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchWebhook();
|
fetchWebhook();
|
||||||
@@ -25,6 +29,10 @@ function Webhook() {
|
|||||||
|
|
||||||
const fetchWebhook = async () => {
|
const fetchWebhook = async () => {
|
||||||
const email = Parse.User.current().getEmail();
|
const email = Parse.User.current().getEmail();
|
||||||
|
if (isEnableSubscription) {
|
||||||
|
const getIsSubscribe = await checkIsSubscribed();
|
||||||
|
setIsSubscribe(getIsSubscribe);
|
||||||
|
}
|
||||||
const params = { email: email };
|
const params = { email: email };
|
||||||
try {
|
try {
|
||||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||||
@@ -40,41 +48,48 @@ function Webhook() {
|
|||||||
};
|
};
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsLoader(true);
|
if (webhook && webhook.startsWith("https://")) {
|
||||||
setIsModal(false);
|
setIsLoader(true);
|
||||||
try {
|
setIsModal(false);
|
||||||
const params = { url: webhook };
|
try {
|
||||||
const url = parseBaseUrl + "functions/savewebhook";
|
const params = { url: webhook };
|
||||||
const headers = {
|
const url = parseBaseUrl + "functions/savewebhook";
|
||||||
"Content-Type": "application/json",
|
const headers = {
|
||||||
"X-Parse-Application-Id": parseAppId,
|
"Content-Type": "application/json",
|
||||||
sessiontoken: localStorage.getItem("accesstoken")
|
"X-Parse-Application-Id": parseAppId,
|
||||||
};
|
sessiontoken: localStorage.getItem("accesstoken")
|
||||||
await axios.post(url, params, { headers: headers }).then((res) => {
|
};
|
||||||
if (res.data && res.data.result && res.data.result.Webhook) {
|
await axios.post(url, params, { headers: headers }).then((res) => {
|
||||||
setWebhook(res.data.result.Webhook);
|
if (res.data && res.data.result && res.data.result.Webhook) {
|
||||||
setIsGenerate(true);
|
setWebhook(res.data.result.Webhook);
|
||||||
setTimeout(() => {
|
setIsGenerate(true);
|
||||||
setIsGenerate(false);
|
setTimeout(() => {
|
||||||
}, 1500);
|
setIsGenerate(false);
|
||||||
setIsLoader(false);
|
}, 1500);
|
||||||
} else {
|
setIsLoader(false);
|
||||||
console.error("Error while generating webhook");
|
} else {
|
||||||
setIsLoader(false);
|
console.error("Error while generating webhook");
|
||||||
setIsErr(true);
|
setIsLoader(false);
|
||||||
setTimeout(() => {
|
setIsErr(true);
|
||||||
setIsErr(false);
|
setTimeout(() => {
|
||||||
}, 1500);
|
setIsErr(false);
|
||||||
}
|
}, 1500);
|
||||||
});
|
}
|
||||||
} catch (error) {
|
});
|
||||||
setIsLoader(false);
|
} catch (error) {
|
||||||
setIsErr(true);
|
setIsLoader(false);
|
||||||
setTimeout(() => {
|
setIsErr(true);
|
||||||
setIsErr(false);
|
setTimeout(() => {
|
||||||
}, 1500);
|
setIsErr(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
console.log("err", error);
|
console.log("err", error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setError("The webhook url should always start with https://");
|
||||||
|
setTimeout(() => {
|
||||||
|
setError("");
|
||||||
|
}, 1500);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,6 +99,7 @@ function Webhook() {
|
|||||||
<Title title={"Webhook"} />
|
<Title title={"Webhook"} />
|
||||||
{isGenerate && <Alert type="success">Webhook added successfully!</Alert>}
|
{isGenerate && <Alert type="success">Webhook added successfully!</Alert>}
|
||||||
{isErr && <Alert type="danger">Something went wrong!</Alert>}
|
{isErr && <Alert type="danger">Something went wrong!</Alert>}
|
||||||
|
|
||||||
{isLoader ? (
|
{isLoader ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -103,31 +119,41 @@ function Webhook() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||||
<PremiumAlertHeader />
|
{!isEnableSubscription && <PremiumAlertHeader />}
|
||||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
Webhook{" "}
|
OpenSign™ Webhook{" "}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
|
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
|
||||||
|
isSubscribe={true}
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
<ul className="w-full flex flex-col p-2 text-sm">
|
<ul
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "w-full flex flex-col p-2 text-sm "
|
||||||
|
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
<li
|
<li
|
||||||
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
>
|
>
|
||||||
<span className="w-[40%]">Webhook:</span>{" "}
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
|
||||||
<span id="token" className="w-[60%] md:text-end cursor-pointer">
|
<span className="">Webhook:</span>{" "}
|
||||||
{webhook && webhook}
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
</span>
|
{webhook ? webhook : "_____"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleModal}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
{webhook ? "Update Webhook" : "Add Webhook"}
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
|
||||||
<button
|
<div className="flex items-center justify-center ">
|
||||||
type="button"
|
|
||||||
onClick={handleModal}
|
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none"
|
|
||||||
>
|
|
||||||
{webhook ? "Update Webhook" : "Add Webhook"}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -135,17 +161,47 @@ function Webhook() {
|
|||||||
"https://docs.opensignlabs.com/docs/API-docs/save-update-webhook"
|
"https://docs.opensignlabs.com/docs/API-docs/save-update-webhook"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
className="rounded hover:bg-[#15b4e9] border-[1px] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
>
|
>
|
||||||
View Docs
|
View Docs
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<>
|
||||||
|
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
|
||||||
|
Upgrade to PRO Plan
|
||||||
|
</h1>
|
||||||
|
<ul className={"w-full flex flex-col p-2 text-sm "}>
|
||||||
|
<li
|
||||||
|
className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||||
|
>
|
||||||
|
<div className="w-[70%] flex-col md:flex-row flex items-center gap-3 ">
|
||||||
|
<span className="">$29.99/month:</span>{" "}
|
||||||
|
<span id="token" className=" md:text-end cursor-pointer">
|
||||||
|
First 100 documents included, then just $0.15 per
|
||||||
|
document.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{!isSubscribe && isEnableSubscription && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigation("/subscription")}
|
||||||
|
className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none"
|
||||||
|
>
|
||||||
|
Upgrade Now
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isModal}
|
isOpen={isModal}
|
||||||
title={"Regenerate Token"}
|
title={"Regenerate Token"}
|
||||||
handleClose={handleModal}
|
handleClose={handleModal}
|
||||||
>
|
>
|
||||||
|
{error && <Alert type="danger">{error}</Alert>}
|
||||||
<div className="m-[20px]">
|
<div className="m-[20px]">
|
||||||
<div className="text-lg font-normal text-black">
|
<div className="text-lg font-normal text-black">
|
||||||
<label className="text-sm ml-2">Webhook</label>
|
<label className="text-sm ml-2">Webhook</label>
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ const AddUser = (props) => {
|
|||||||
contactQuery.set("Email", email);
|
contactQuery.set("Email", email);
|
||||||
contactQuery.set("UserRole", "contracts_Guest");
|
contactQuery.set("UserRole", "contracts_Guest");
|
||||||
|
|
||||||
if (localStorage.getItem("TenetId")) {
|
if (localStorage.getItem("TenantId")) {
|
||||||
contactQuery.set("TenantId", {
|
contactQuery.set("TenantId", {
|
||||||
__type: "Pointer",
|
__type: "Pointer",
|
||||||
className: "partners_Tenant",
|
className: "partners_Tenant",
|
||||||
objectId: localStorage.getItem("TenetId")
|
objectId: localStorage.getItem("TenantId")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,12 +7,16 @@ const LinkUserModal = (props) => {
|
|||||||
return (
|
return (
|
||||||
<ModalUi
|
<ModalUi
|
||||||
title={"Add/Choose Signer"}
|
title={"Add/Choose Signer"}
|
||||||
isOpen={props.isAddUser[props.uniqueId]}
|
isOpen={
|
||||||
|
props?.isAddSigner ||
|
||||||
|
(props?.isAddUser && props?.isAddUser[props?.uniqueId])
|
||||||
|
}
|
||||||
handleClose={props.closePopup}
|
handleClose={props.closePopup}
|
||||||
>
|
>
|
||||||
<SelectSigners
|
<SelectSigners
|
||||||
details={props.handleAddUser}
|
details={props.handleAddUser}
|
||||||
closePopup={props.closePopup}
|
closePopup={props.closePopup}
|
||||||
|
signersData={props?.signersData}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
import PremiumAlertHeader from "./PremiumAlertHeader";
|
||||||
|
|
||||||
const ModalUi = ({
|
const ModalUi = ({
|
||||||
children,
|
children,
|
||||||
@@ -8,12 +10,13 @@ const ModalUi = ({
|
|||||||
handleClose,
|
handleClose,
|
||||||
showHeader = true,
|
showHeader = true,
|
||||||
showClose = true,
|
showClose = true,
|
||||||
styleClass
|
styleClass,
|
||||||
|
showHeaderMessage
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="fixed z-[999] top-0 left-0 w-[100%] h-[100%] bg-black bg-opacity-[75%]">
|
<div className="fixed z-[999] 2 top-0 left-0 w-[100%] h-[100%] bg-black bg-opacity-[75%]">
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
styleClass
|
styleClass
|
||||||
@@ -37,6 +40,13 @@ const ModalUi = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{!isEnableSubscription && showHeaderMessage && (
|
||||||
|
<PremiumAlertHeader
|
||||||
|
message={
|
||||||
|
"Cutomize Email is free in beta, this feature will incur a fee later."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div>{children}</div>
|
<div>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,19 +8,11 @@ function CustomModal({
|
|||||||
bodyMssg,
|
bodyMssg,
|
||||||
footerMessage,
|
footerMessage,
|
||||||
declineDoc,
|
declineDoc,
|
||||||
setIsDecline,
|
setIsDecline
|
||||||
containerWH
|
|
||||||
}) {
|
}) {
|
||||||
const isMobile = window.innerWidth < 767;
|
|
||||||
return (
|
return (
|
||||||
show && (
|
show && (
|
||||||
<div
|
<div className="bg-black bg-opacity-[75%] absolute z-[999] flex flex-col items-center justify-center w-full h-full rounded">
|
||||||
className="bg-black bg-opacity-[75%] absolute z-[999] flex flex-col items-center justify-center"
|
|
||||||
style={{
|
|
||||||
width: containerWH && containerWH.width,
|
|
||||||
height: isMobile ? "100%" : containerWH && containerWH.height
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="bg-white rounded outline-none md:w-[40%] w-[80%]">
|
<div className="bg-white rounded outline-none md:w-[40%] w-[80%]">
|
||||||
<div className="bg-[#de4337] text-white p-[10px] rounded-t">
|
<div className="bg-[#de4337] text-white p-[10px] rounded-t">
|
||||||
{headMsg && headMsg}
|
{headMsg && headMsg}
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Tooltip as ReactTooltip } from "react-tooltip";
|
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||||
import { openInNewTab } from "../constant/Utils";
|
import { openInNewTab } from "../constant/Utils";
|
||||||
const Tooltip = ({ id, message, url, iconColor }) =>
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
const Tooltip = ({ id, message, url, iconColor, isSubscribe }) =>
|
||||||
url ? (
|
url ? (
|
||||||
<button onClick={() => openInNewTab(url)} className="text-center">
|
<button
|
||||||
|
onClick={() => openInNewTab(url)}
|
||||||
|
className={
|
||||||
|
isSubscribe || !isEnableSubscription
|
||||||
|
? "text-center"
|
||||||
|
: "text-center opacity-20 pointer-events-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
<sup>
|
<sup>
|
||||||
<i
|
<i
|
||||||
className="fa-solid fa-question rounded-full"
|
className="fa-solid fa-question rounded-full"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { openInNewTab } from "../constant/Utils";
|
||||||
|
|
||||||
|
function Upgrade({ message, newWindow }) {
|
||||||
|
const navigation = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<sup>
|
||||||
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
if (newWindow) {
|
||||||
|
const url = window.location.origin + "/subscription";
|
||||||
|
openInNewTab(url);
|
||||||
|
} else {
|
||||||
|
navigation("/subscription");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="text-blue-800 text-sm cursor-pointer underline"
|
||||||
|
>
|
||||||
|
{message ? message : "Upgrade now"}
|
||||||
|
</span>
|
||||||
|
</sup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Upgrade;
|
||||||
@@ -9,9 +9,15 @@ const Validate = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
const userDetails = JSON.parse(
|
||||||
|
localStorage.getItem(
|
||||||
|
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// Use the session token to validate the user
|
// Use the session token to validate the user
|
||||||
const userQuery = new Parse.Query(Parse.User);
|
const userQuery = new Parse.Query(Parse.User);
|
||||||
const user = await userQuery.get(Parse.User.current().id, {
|
const user = await userQuery.get(userDetails?.objectId, {
|
||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
});
|
});
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -24,7 +30,10 @@ const Validate = () => {
|
|||||||
setIsUserValid(false);
|
setIsUserValid(false);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleLoginBtn = () => {
|
const handleLoginBtn = () => {
|
||||||
try {
|
try {
|
||||||
Parse.User.logOut();
|
Parse.User.logOut();
|
||||||
|
|||||||
@@ -395,14 +395,6 @@
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.backBtn {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backBtn:hover {
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.defaultBtn {
|
.defaultBtn {
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
|
||||||
padding: 3px 26px;
|
padding: 3px 26px;
|
||||||
@@ -420,42 +412,6 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.downloadBtn {
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
||||||
padding: 3px 15px !important;
|
|
||||||
background-color: rgb(241 79 79);
|
|
||||||
border: none !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.downloadBtn:hover {
|
|
||||||
box-shadow: 0 2px 4px rgba(154, 36, 36, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.printBtn {
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
||||||
padding: 3px 15px !important;
|
|
||||||
background: #188ae2;
|
|
||||||
border: none !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.printBtn:hover {
|
|
||||||
box-shadow: 0 2px 4px rgba(23, 48, 137, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.certificateBtn {
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
|
|
||||||
padding: 3px 15px !important;
|
|
||||||
background: #08bc66;
|
|
||||||
border: none !important;
|
|
||||||
color: white !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.certificateBtn:hover {
|
|
||||||
box-shadow: 0 2px 4px rgba(15, 150, 87, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.signerList {
|
.signerList {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@@ -496,11 +452,15 @@
|
|||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.disabled {
|
||||||
opacity: 0.5; /* Example: reduce opacity to visually indicate disabled state */
|
opacity: 0.5;
|
||||||
pointer-events: none; /* Prevents mouse clicks and other events */
|
/* Example: reduce opacity to visually indicate disabled state */
|
||||||
|
pointer-events: none;
|
||||||
|
/* Prevents mouse clicks and other events */
|
||||||
/* background-color: #888; */
|
/* background-color: #888; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.useEmail {
|
.useEmail {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
color: #424242;
|
color: #424242;
|
||||||
@@ -557,13 +517,6 @@
|
|||||||
position: "relative";
|
position: "relative";
|
||||||
}
|
}
|
||||||
|
|
||||||
.signatureHeader {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.signerComponent {
|
.signerComponent {
|
||||||
/* box-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px; */
|
/* box-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px; */
|
||||||
@@ -851,6 +804,7 @@ option {
|
|||||||
z-index: 999;
|
z-index: 999;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.labelTextArea:focus {
|
.labelTextArea:focus {
|
||||||
@@ -1014,6 +968,9 @@ option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scroll-hide::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@media screen and (max-width: 350px) and (min-width: 311px) {
|
@media screen and (max-width: 350px) and (min-width: 311px) {
|
||||||
.signatureCanvas {
|
.signatureCanvas {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const appId = process.env.APP_ID;
|
||||||
|
const serverUrl = process.env.SERVER_URL;
|
||||||
export function customAPIurl() {
|
export function customAPIurl() {
|
||||||
const url = new URL(process.env.SERVER_URL);
|
const url = new URL(process.env.SERVER_URL);
|
||||||
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
|
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
|
||||||
@@ -38,3 +42,204 @@ export function replaceMailVaribles(subject, body, variables) {
|
|||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const saveFileUsage = async (size, imageUrl, userId) => {
|
||||||
|
//checking server url and save file's size
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tenantQuery = new Parse.Query('partners_Tenant');
|
||||||
|
tenantQuery.equalTo('UserId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: userId,
|
||||||
|
});
|
||||||
|
const tenant = await tenantQuery.first();
|
||||||
|
if (tenant) {
|
||||||
|
const tenantPtr = {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: tenant.id,
|
||||||
|
};
|
||||||
|
const _tenantPtr = JSON.stringify(tenantPtr);
|
||||||
|
try {
|
||||||
|
const res = await axios.get(
|
||||||
|
`${serverUrl}/classes/partners_TenantCredits?where={"PartnersTenant":${_tenantPtr}}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': appId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const response = res.data.results;
|
||||||
|
|
||||||
|
let data;
|
||||||
|
// console.log("response", response);
|
||||||
|
if (response && response.length > 0) {
|
||||||
|
data = {
|
||||||
|
usedStorage: response[0].usedStorage ? response[0].usedStorage + size : size,
|
||||||
|
};
|
||||||
|
await axios.put(
|
||||||
|
`${serverUrl}/classes/partners_TenantCredits/${response[0].objectId}`,
|
||||||
|
data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': appId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
data = { usedStorage: size, PartnersTenant: tenantPtr };
|
||||||
|
await axios.post(`${serverUrl}/classes/partners_TenantCredits`, data, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': appId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in save usage', err);
|
||||||
|
}
|
||||||
|
saveDataFile(size, imageUrl, tenantPtr);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in fetch tenant Id', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//function for save fileUrl and file size in particular client db class partners_DataFiles
|
||||||
|
const saveDataFile = async (size, imageUrl, tenantPtr) => {
|
||||||
|
const data = {
|
||||||
|
FileUrl: imageUrl,
|
||||||
|
FileSize: size,
|
||||||
|
TenantPtr: tenantPtr,
|
||||||
|
};
|
||||||
|
|
||||||
|
// console.log("data save",file, data)
|
||||||
|
try {
|
||||||
|
await axios.post(`${serverUrl}/classes/partners_DataFiles`, data, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': appId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log('error in save usage ', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateMailCount = async extUserId => {
|
||||||
|
// Update count in contracts_Users class
|
||||||
|
const query = new Parse.Query('contracts_Users');
|
||||||
|
query.equalTo('objectId', extUserId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const contractUser = await query.first({ useMasterKey: true });
|
||||||
|
if (contractUser) {
|
||||||
|
contractUser.increment('EmailCount', 1);
|
||||||
|
await contractUser.save(null, { useMasterKey: true });
|
||||||
|
} else {
|
||||||
|
// Create new entry if not found
|
||||||
|
const ContractsUsers = Parse.Object.extend('contracts_users');
|
||||||
|
const newContractUser = new ContractsUsers();
|
||||||
|
newContractUser.set('EmailCount', 1);
|
||||||
|
await newContractUser.save(null, { useMasterKey: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error updating EmailCount in contracts_users: ' + error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function formatWidgetOptions(type, options) {
|
||||||
|
const status = options?.required === true ? 'required' : 'optional' || 'required';
|
||||||
|
const defaultValue = options?.default || '';
|
||||||
|
const values = options?.values || [];
|
||||||
|
switch (type) {
|
||||||
|
case 'signature':
|
||||||
|
return { name: 'signature', status: 'required' };
|
||||||
|
case 'stamp':
|
||||||
|
return { status: status, name: 'stamp' };
|
||||||
|
case 'initials':
|
||||||
|
return { status: status, name: options.name || 'initials' };
|
||||||
|
case 'image':
|
||||||
|
return { status: status, name: options.name || 'image' };
|
||||||
|
case 'email':
|
||||||
|
return { status: status, name: options.name || 'email', validation: { type: 'email' } };
|
||||||
|
case 'name':
|
||||||
|
return { status: status, name: options.name || 'name' };
|
||||||
|
case 'job title':
|
||||||
|
return { status: status, name: options.name || 'job title' };
|
||||||
|
case 'company':
|
||||||
|
return { status: status, name: options.name || 'company' };
|
||||||
|
case 'date': {
|
||||||
|
let today = new Date();
|
||||||
|
let dd = String(today.getDate()).padStart(2, '0');
|
||||||
|
let mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0!
|
||||||
|
let yyyy = today.getFullYear();
|
||||||
|
today = dd + '-' + mm + '-' + yyyy;
|
||||||
|
let dateFormat = options?.format;
|
||||||
|
dateFormat = dateFormat.replace(/m/g, 'M');
|
||||||
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'date',
|
||||||
|
response: defaultValue || today,
|
||||||
|
validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'textbox':
|
||||||
|
return {
|
||||||
|
status: status,
|
||||||
|
name: 'textbox',
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
hint: options.hint,
|
||||||
|
validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' },
|
||||||
|
};
|
||||||
|
case 'checkbox': {
|
||||||
|
const arr = options?.values;
|
||||||
|
let selectedvalues = [];
|
||||||
|
for (const obj of options.selectedvalues) {
|
||||||
|
const index = arr.indexOf(obj);
|
||||||
|
selectedvalues.push(index);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'checkbox',
|
||||||
|
values: values,
|
||||||
|
isReadOnly: options?.readonly || false,
|
||||||
|
isHideLabel: options?.hidelabel || false,
|
||||||
|
validation: {
|
||||||
|
minRequiredCount: options?.validation?.minselections || 0,
|
||||||
|
maxRequiredCount: options?.validation?.maxselections || 0,
|
||||||
|
},
|
||||||
|
defaultValue: selectedvalues || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'radio button': {
|
||||||
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'radio',
|
||||||
|
values: values,
|
||||||
|
isReadOnly: options?.readonly || false,
|
||||||
|
isHideLabel: options?.hidelabel || false,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'dropdown':
|
||||||
|
return {
|
||||||
|
status: status,
|
||||||
|
name: options.name || 'dropdown',
|
||||||
|
values: values,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sanitizeFileName(fileName) {
|
||||||
|
// Remove spaces and invalid characters
|
||||||
|
const file = fileName.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||||
|
const removedot = file.replace(/\.(?=.*\.)/g, '');
|
||||||
|
return removedot.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
//--npm modules
|
//--npm modules
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
export const app = express();
|
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
|
import uploadFile from './uploadFile.js';
|
||||||
|
import saveSubscription from './saveSubscription.js';
|
||||||
|
import saveInvoice from './saveInvoice.js';
|
||||||
|
import savePayments from './savePayments.js';
|
||||||
|
export const app = express();
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json({ limit: '50mb' }));
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ limit: '50mb', extended: true }));
|
||||||
import uploadFile from './uploadFile.js';
|
|
||||||
|
|
||||||
app.post('/file_upload', uploadFile);
|
app.post('/file_upload', uploadFile);
|
||||||
|
|
||||||
|
app.post('/savesubscription', saveSubscription)
|
||||||
|
app.post('/saveinvoice', saveInvoice)
|
||||||
|
app.post('/savepayment', savePayments)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
export default async function saveInvoice(request, response) {
|
||||||
|
const InvoiceId = request.body.data.invoice.invoice_id;
|
||||||
|
const body = request.body;
|
||||||
|
const Email = request.body.data.invoice.email;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('Email', Email);
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const invoiceCls = new Parse.Query('contracts_Invoices');
|
||||||
|
invoiceCls.equalTo('InvoiceId', InvoiceId);
|
||||||
|
const invoice = await invoiceCls.first({ useMasterKey: true });
|
||||||
|
if (invoice) {
|
||||||
|
const updateInvoice = new Parse.Object('contracts_Invoices');
|
||||||
|
updateInvoice.id = invoice.id;
|
||||||
|
updateInvoice.set('InvoiceDetails', body);
|
||||||
|
await updateInvoice.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'update invoice!' });
|
||||||
|
} else {
|
||||||
|
const createInvoice = new Parse.Object('contracts_Invoices');
|
||||||
|
createInvoice.set('InvoiceId', InvoiceId);
|
||||||
|
createInvoice.set('InvoiceDetails', body);
|
||||||
|
createInvoice.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUser.id,
|
||||||
|
});
|
||||||
|
createInvoice.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: extUser.get('UserId').id,
|
||||||
|
});
|
||||||
|
if (extUser?.get('TenantId')?.id) {
|
||||||
|
createInvoice.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await createInvoice.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'create invoice!' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return response.status(404).json({ status: 'user not found!' });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in save invoice', err);
|
||||||
|
return response.status(400).json({ status: 'error:' + err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
export default async function savePayments(request, response) {
|
||||||
|
const PaymentId = request.body.data.payment.payment_id;
|
||||||
|
const body = request.body;
|
||||||
|
const Email = request.body.data.payment.email;
|
||||||
|
try {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('Email', Email);
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const paymentCls = new Parse.Query('contracts_Payments');
|
||||||
|
paymentCls.equalTo('PaymentId', PaymentId);
|
||||||
|
const payment = await paymentCls.first({ useMasterKey: true });
|
||||||
|
if (payment) {
|
||||||
|
const updatePayment = new Parse.Object('contracts_Payments');
|
||||||
|
updatePayment.id = payment.id;
|
||||||
|
updatePayment.set('PaymentDetails', body);
|
||||||
|
await updatePayment.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'update Payment!' });
|
||||||
|
} else {
|
||||||
|
const createPayment = new Parse.Object('contracts_Payments');
|
||||||
|
createPayment.set('PaymentId', PaymentId);
|
||||||
|
createPayment.set('PaymentDetails', body);
|
||||||
|
createPayment.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUser.id,
|
||||||
|
});
|
||||||
|
createPayment.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: extUser.get('UserId').id,
|
||||||
|
});
|
||||||
|
if (extUser?.get('TenantId')?.id) {
|
||||||
|
createPayment.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await createPayment.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'create payments!' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return response.status(404).json({ status: 'user not found!' });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in save payment', err);
|
||||||
|
return response.status(400).json({ status: 'error:' + err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
export default async function saveSubscription(request, response) {
|
||||||
|
const SubscriptionId = request.body.data.subscription.subscription_id;
|
||||||
|
const body = request.body;
|
||||||
|
const Email = request.body.data.subscription.customer.email;
|
||||||
|
const Next_billing_date = request.body.data.subscription.next_billing_at;
|
||||||
|
const planCode = request.body.data.subscription.plan.plan_code
|
||||||
|
|
||||||
|
try {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('Email', Email);
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const subcriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||||
|
subcriptionCls.equalTo('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
const subscription = await subcriptionCls.first({ useMasterKey: true });
|
||||||
|
if (subscription) {
|
||||||
|
const updateSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
updateSubscription.id = subscription.id;
|
||||||
|
updateSubscription.set('SubscriptionId', SubscriptionId);
|
||||||
|
updateSubscription.set('SubscriptionDetails', body);
|
||||||
|
updateSubscription.set('Next_billing_date', new Date(Next_billing_date));
|
||||||
|
updateSubscription.set('PlanCode', planCode);
|
||||||
|
await updateSubscription.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'update subscription!' });
|
||||||
|
} else {
|
||||||
|
const createSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
createSubscription.set('SubscriptionId', SubscriptionId);
|
||||||
|
createSubscription.set('SubscriptionDetails', body);
|
||||||
|
createSubscription.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUser.id,
|
||||||
|
});
|
||||||
|
createSubscription.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: extUser.get('UserId').id,
|
||||||
|
});
|
||||||
|
createSubscription.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
createSubscription.set('Next_billing_date', new Date(Next_billing_date));
|
||||||
|
createSubscription.set('PlanCode', planCode);
|
||||||
|
await createSubscription.save(null, { useMasterKey: true });
|
||||||
|
return response.status(200).json({ status: 'create subscription!' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return response.status(404).json({ status: 'user not found!' });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in save subscription', err);
|
||||||
|
return response.status(400).json({ status: 'error:' + err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -284,6 +284,7 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
subject: subject,
|
subject: subject,
|
||||||
from: sender,
|
from: sender,
|
||||||
html: html,
|
html: html,
|
||||||
|
extUserId: template.ExtUserPtr.objectId,
|
||||||
};
|
};
|
||||||
sendMail = await axios.post(url, params, { headers: headers });
|
sendMail = await axios.post(url, params, { headers: headers });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { color, customAPIurl, replaceMailVaribles } from '../../../../Utils.js';
|
import {
|
||||||
|
color,
|
||||||
|
customAPIurl,
|
||||||
|
replaceMailVaribles,
|
||||||
|
saveFileUsage,
|
||||||
|
formatWidgetOptions,
|
||||||
|
sanitizeFileName,
|
||||||
|
} from '../../../../Utils.js';
|
||||||
|
|
||||||
// `sendDoctoWebhook` is used to send res data of document on webhook
|
// `sendDoctoWebhook` is used to send res data of document on webhook
|
||||||
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
|
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
|
||||||
@@ -8,6 +15,7 @@ async function sendDoctoWebhook(doc, WebhookUrl, userId) {
|
|||||||
event: 'created',
|
event: 'created',
|
||||||
...doc,
|
...doc,
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios
|
await axios
|
||||||
.post(WebhookUrl, params, {
|
.post(WebhookUrl, params, {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -65,6 +73,7 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
if (!reqToken) {
|
if (!reqToken) {
|
||||||
return response.status(400).json({ error: 'Please Provide API Token' });
|
return response.status(400).json({ error: 'Please Provide API Token' });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tokenQuery = new Parse.Query('appToken');
|
const tokenQuery = new Parse.Query('appToken');
|
||||||
tokenQuery.equalTo('token', reqToken);
|
tokenQuery.equalTo('token', reqToken);
|
||||||
@@ -81,17 +90,21 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
let fileUrl;
|
let fileUrl;
|
||||||
if (request.files?.[0]) {
|
if (request.files?.[0]) {
|
||||||
|
const base64 = fileData?.toString('base64');
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
const file = new Parse.File(request.files?.[0]?.originalname, {
|
||||||
base64: fileData?.toString('base64'),
|
base64: base64,
|
||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
const file = new Parse.File(`${name}.pdf`, {
|
const filename = sanitizeFileName(`${name}.pdf`);
|
||||||
base64: base64File,
|
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
const contractsUser = new Parse.Query('contracts_Users');
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
contractsUser.equalTo('UserId', userPtr);
|
||||||
@@ -170,17 +183,17 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
|
|
||||||
for (const widget of signer.widgets) {
|
for (const widget of signer.widgets) {
|
||||||
const pageNumber = widget.page;
|
const pageNumber = widget.page;
|
||||||
|
const options = formatWidgetOptions(widget.type, widget.options);
|
||||||
const page = placeHolder.find(page => page.pageNumber === pageNumber);
|
const page = placeHolder.find(page => page.pageNumber === pageNumber);
|
||||||
const signOpt = { name: 'signature', status: 'required' };
|
|
||||||
const widgetData = {
|
const widgetData = {
|
||||||
isStamp: widget.type === 'stamp',
|
isStamp: widget.type === 'stamp' || widget.type === 'image',
|
||||||
key: randomId(),
|
key: randomId(),
|
||||||
isDrag: false,
|
isDrag: false,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
type: widget.type,
|
type: widget.type === 'textbox' ? 'text input' : widget.type,
|
||||||
options: widget.type === 'signature' ? signOpt : widget.options,
|
options: options,
|
||||||
Width: widget.w,
|
Width: widget.w,
|
||||||
Height: widget.h,
|
Height: widget.h,
|
||||||
xPosition: widget.x,
|
xPosition: widget.x,
|
||||||
@@ -242,7 +255,6 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
});
|
});
|
||||||
let sender = parseExtUser.Email;
|
let sender = parseExtUser.Email;
|
||||||
let sendMail;
|
|
||||||
const serverUrl = process.env.SERVER_URL;
|
const serverUrl = process.env.SERVER_URL;
|
||||||
const newServer = serverUrl.replaceAll('/', '%2F');
|
const newServer = serverUrl.replaceAll('/', '%2F');
|
||||||
const serverParams = `${newServer}%2F&${process.env.APP_ID}&contracts`;
|
const serverParams = `${newServer}%2F&${process.env.APP_ID}&contracts`;
|
||||||
@@ -330,9 +342,10 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
subject: subject,
|
subject: subject,
|
||||||
from: sender,
|
from: sender,
|
||||||
html: html,
|
html: html,
|
||||||
|
extUserId: extUser.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
sendMail = await axios.post(url, params, { headers: headers });
|
await axios.post(url, params, { headers: headers });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('error', error);
|
console.log('error', error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { customAPIurl } from '../../../../Utils.js';
|
import { saveFileUsage } from '../../../../Utils.js';
|
||||||
|
|
||||||
const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
|
||||||
export default async function createTemplate(request, response) {
|
export default async function createTemplate(request, response) {
|
||||||
const name = request.body?.title;
|
const name = request.body?.title;
|
||||||
const note = request.body?.note;
|
const note = request.body?.note;
|
||||||
@@ -36,12 +34,17 @@ export default async function createTemplate(request, response) {
|
|||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
|
const base64 = fileData?.toString('base64');
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
const file = new Parse.File(request.files?.[0]?.originalname, {
|
||||||
base64: fileData?.toString('base64'),
|
base64: base64,
|
||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
const contractsUser = new Parse.Query('contracts_Users');
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { color, customAPIurl } from '../../../../Utils.js';
|
import {
|
||||||
|
color,
|
||||||
|
customAPIurl,
|
||||||
|
saveFileUsage,
|
||||||
|
formatWidgetOptions,
|
||||||
|
sanitizeFileName,
|
||||||
|
} from '../../../../Utils.js';
|
||||||
|
|
||||||
const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
const randomId = () => Math.floor(1000 + Math.random() * 9000);
|
||||||
export default async function createTemplatewithCoordinate(request, response) {
|
export default async function createTemplatewithCoordinate(request, response) {
|
||||||
@@ -34,17 +40,21 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
let fileUrl;
|
let fileUrl;
|
||||||
if (request.files?.[0]) {
|
if (request.files?.[0]) {
|
||||||
|
const base64 = fileData?.toString('base64');
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
const file = new Parse.File(request.files?.[0]?.originalname, {
|
||||||
base64: fileData?.toString('base64'),
|
base64: base64,
|
||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
const file = new Parse.File(`${name}.pdf`, {
|
const filename = sanitizeFileName(`${name}.pdf`);
|
||||||
base64: base64File,
|
const file = new Parse.File(filename, { base64: base64File }, 'application/pdf');
|
||||||
});
|
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
const contractsUser = new Parse.Query('contracts_Users');
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
contractsUser.equalTo('UserId', userPtr);
|
||||||
@@ -129,16 +139,16 @@ export default async function createTemplatewithCoordinate(request, response) {
|
|||||||
for (const widget of signer.widgets) {
|
for (const widget of signer.widgets) {
|
||||||
const pageNumber = widget.page;
|
const pageNumber = widget.page;
|
||||||
const page = placeHolder.find(page => page.pageNumber === pageNumber);
|
const page = placeHolder.find(page => page.pageNumber === pageNumber);
|
||||||
const signOpt = { name: 'signature', status: 'required' };
|
const options = formatWidgetOptions(widget.type, widget.options);
|
||||||
const widgetData = {
|
const widgetData = {
|
||||||
isStamp: widget.type === 'stamp',
|
isStamp: widget.type === 'stamp' || widget.type === 'image',
|
||||||
key: randomId(),
|
key: randomId(),
|
||||||
isDrag: false,
|
isDrag: false,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
type: widget.type,
|
type: widget.type === 'textbox' ? 'text input' : widget.type,
|
||||||
options: widget.type === 'signature' ? signOpt : widget.options,
|
options: options,
|
||||||
Width: widget.w,
|
Width: widget.w,
|
||||||
Height: widget.h,
|
Height: widget.h,
|
||||||
xPosition: widget.x,
|
xPosition: widget.x,
|
||||||
|
|||||||
@@ -36,17 +36,22 @@ export default async function draftDocument(request, response) {
|
|||||||
if (signers && signers.length > 0) {
|
if (signers && signers.length > 0) {
|
||||||
let fileUrl;
|
let fileUrl;
|
||||||
if (request.files?.[0]) {
|
if (request.files?.[0]) {
|
||||||
|
const base64 = fileData?.toString('base64');
|
||||||
const file = new Parse.File(request.files?.[0]?.originalname, {
|
const file = new Parse.File(request.files?.[0]?.originalname, {
|
||||||
base64: fileData?.toString('base64'),
|
base64: base64,
|
||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
} else {
|
} else {
|
||||||
const file = new Parse.File(`${name}.pdf`, {
|
const file = new Parse.File(`${name}.pdf`, {
|
||||||
base64: base64File,
|
base64: base64File,
|
||||||
});
|
});
|
||||||
await file.save({ useMasterKey: true });
|
await file.save({ useMasterKey: true });
|
||||||
fileUrl = file.url();
|
fileUrl = file.url();
|
||||||
|
const buffer = Buffer.from(base64File, 'base64');
|
||||||
|
saveFileUsage(buffer.length, fileUrl, parseUser.userId.objectId);
|
||||||
}
|
}
|
||||||
const contractsUser = new Parse.Query('contracts_Users');
|
const contractsUser = new Parse.Query('contracts_Users');
|
||||||
contractsUser.equalTo('UserId', userPtr);
|
contractsUser.equalTo('UserId', userPtr);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import PDF from './parsefunction/pdf/PDF.min.js';
|
import PDF from './parsefunction/pdf/PDF.min.js';
|
||||||
import sendmail from './parsefunction/sendMail.js';
|
import sendmailv3 from './parsefunction/sendMailv3.js';
|
||||||
import GoogleSign from './parsefunction/GoogleSign.js';
|
import GoogleSign from './parsefunction/GoogleSign.js';
|
||||||
import ZohoDetails from './parsefunction/ZohoDetails.js';
|
import ZohoDetails from './parsefunction/ZohoDetails.js';
|
||||||
import usersignup from './parsefunction/usersignup.js';
|
import usersignup from './parsefunction/usersignup.js';
|
||||||
@@ -10,7 +10,6 @@ import DocumentAftersave from './parsefunction/DocumentAftersave.js';
|
|||||||
import ContactbookAftersave from './parsefunction/ContactBookAftersave.js';
|
import ContactbookAftersave from './parsefunction/ContactBookAftersave.js';
|
||||||
import ContractUsersAftersave from './parsefunction/ContractUsersAftersave.js';
|
import ContractUsersAftersave from './parsefunction/ContractUsersAftersave.js';
|
||||||
import sendMailOTPv1 from './parsefunction/SendMailOTPv1.js';
|
import sendMailOTPv1 from './parsefunction/SendMailOTPv1.js';
|
||||||
import SendMailv1 from './parsefunction/SendMailv1.js';
|
|
||||||
import AuthLoginAsMail from './parsefunction/AuthLoginAsMail.js';
|
import AuthLoginAsMail from './parsefunction/AuthLoginAsMail.js';
|
||||||
import getUserId from './parsefunction/getUserId.js';
|
import getUserId from './parsefunction/getUserId.js';
|
||||||
import getUserDetails from './parsefunction/getUserDetails.js';
|
import getUserDetails from './parsefunction/getUserDetails.js';
|
||||||
@@ -23,17 +22,28 @@ import TemplateAfterSave from './parsefunction/TemplateAfterSave.js';
|
|||||||
import GetTemplate from './parsefunction/GetTemplate.js';
|
import GetTemplate from './parsefunction/GetTemplate.js';
|
||||||
import savewebhook from './parsefunction/saveWebhook.js';
|
import savewebhook from './parsefunction/saveWebhook.js';
|
||||||
import callWebhook from './parsefunction/callWebhook.js';
|
import callWebhook from './parsefunction/callWebhook.js';
|
||||||
|
import SubscribeFree from './parsefunction/SubscribeFree.js';
|
||||||
|
import DocumentBeforesave from './parsefunction/DocumentBeforesave.js';
|
||||||
|
import TemplateBeforeSave from './parsefunction/TemplateBeforesave.js';
|
||||||
|
import DocumentBeforeFind from './parsefunction/DocumentAfterFind.js';
|
||||||
|
import TemplateAfterFind from './parsefunction/TemplateAfterFind.js';
|
||||||
|
import UserAfterFind from './parsefunction/UserAfterFInd.js';
|
||||||
|
import SignatureAfterFind from './parsefunction/SignatureAfterFind.js';
|
||||||
|
import getInvoices from './parsefunction/getInvoices.js';
|
||||||
|
import getPayments from './parsefunction/getPayments.js';
|
||||||
|
import getSubscriptions from './parsefunction/getSubscriptions.js';
|
||||||
|
import TenantAterFind from './parsefunction/TenantAfterFind.js';
|
||||||
|
import saveSubscriptio from './parsefunction/saveSubscription.js';
|
||||||
|
|
||||||
Parse.Cloud.define('AddUserToRole', addUserToGroups);
|
Parse.Cloud.define('AddUserToRole', addUserToGroups);
|
||||||
Parse.Cloud.define('UserGroups', getUserGroups);
|
Parse.Cloud.define('UserGroups', getUserGroups);
|
||||||
Parse.Cloud.define('signPdf', PDF);
|
Parse.Cloud.define('signPdf', PDF);
|
||||||
Parse.Cloud.define('sendmailv3', sendmail);
|
Parse.Cloud.define('sendmailv3', sendmailv3);
|
||||||
Parse.Cloud.define('googlesign', GoogleSign);
|
Parse.Cloud.define('googlesign', GoogleSign);
|
||||||
Parse.Cloud.define('zohodetails', ZohoDetails);
|
Parse.Cloud.define('zohodetails', ZohoDetails);
|
||||||
Parse.Cloud.define('usersignup', usersignup);
|
Parse.Cloud.define('usersignup', usersignup);
|
||||||
Parse.Cloud.define('facebooksign', FacebookSign);
|
Parse.Cloud.define('facebooksign', FacebookSign);
|
||||||
Parse.Cloud.define('SendOTPMailV1', sendMailOTPv1);
|
Parse.Cloud.define('SendOTPMailV1', sendMailOTPv1);
|
||||||
Parse.Cloud.define('sendmail', SendMailv1);
|
|
||||||
Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail);
|
Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail);
|
||||||
Parse.Cloud.define('getUserId', getUserId);
|
Parse.Cloud.define('getUserId', getUserId);
|
||||||
Parse.Cloud.define('getUserDetails', getUserDetails);
|
Parse.Cloud.define('getUserDetails', getUserDetails);
|
||||||
@@ -45,7 +55,19 @@ Parse.Cloud.define('getapitoken', getapitoken);
|
|||||||
Parse.Cloud.define('getTemplate', GetTemplate);
|
Parse.Cloud.define('getTemplate', GetTemplate);
|
||||||
Parse.Cloud.define('savewebhook', savewebhook);
|
Parse.Cloud.define('savewebhook', savewebhook);
|
||||||
Parse.Cloud.define('callwebhook', callWebhook);
|
Parse.Cloud.define('callwebhook', callWebhook);
|
||||||
|
Parse.Cloud.define('freesubscription', SubscribeFree);
|
||||||
|
Parse.Cloud.define('getinvoices', getInvoices);
|
||||||
|
Parse.Cloud.define('getpayments', getPayments);
|
||||||
|
Parse.Cloud.define('getsubscriptions', getSubscriptions);
|
||||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||||
Parse.Cloud.afterSave('contracts_Contactbook', ContactbookAftersave);
|
Parse.Cloud.afterSave('contracts_Contactbook', ContactbookAftersave);
|
||||||
Parse.Cloud.afterSave('contracts_Users', ContractUsersAftersave);
|
Parse.Cloud.afterSave('contracts_Users', ContractUsersAftersave);
|
||||||
Parse.Cloud.afterSave('contracts_Template', TemplateAfterSave);
|
Parse.Cloud.afterSave('contracts_Template', TemplateAfterSave);
|
||||||
|
Parse.Cloud.beforeSave('contracts_Document', DocumentBeforesave);
|
||||||
|
Parse.Cloud.beforeSave('contracts_Template', TemplateBeforeSave);
|
||||||
|
Parse.Cloud.afterFind(Parse.User, UserAfterFind);
|
||||||
|
Parse.Cloud.afterFind('contracts_Document', DocumentBeforeFind);
|
||||||
|
Parse.Cloud.afterFind('contracts_Template', TemplateAfterFind);
|
||||||
|
Parse.Cloud.afterFind('contracts_Signature', SignatureAfterFind);
|
||||||
|
Parse.Cloud.afterFind('partners_Tenant', TenantAterFind);
|
||||||
|
Parse.Cloud.define('savesubscription', saveSubscriptio);
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
|
async function DocumentAfterFind(request) {
|
||||||
|
if (request.objects.length === 1) {
|
||||||
|
if (request.objects) {
|
||||||
|
const obj = request.objects[0];
|
||||||
|
const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl');
|
||||||
|
const Url = obj?.get('URL') && obj?.get('URL');
|
||||||
|
const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl');
|
||||||
|
if (SignedUrl) {
|
||||||
|
obj.set('SignedUrl', getPresignedUrl(SignedUrl));
|
||||||
|
}
|
||||||
|
if (Url) {
|
||||||
|
obj.set('URL', getPresignedUrl(Url));
|
||||||
|
}
|
||||||
|
if (certificateUrl) {
|
||||||
|
obj.set('CertificateUrl', getPresignedUrl(certificateUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [obj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default DocumentAfterFind;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
async function DocumentBeforesave(request) {
|
||||||
|
try {
|
||||||
|
// below code is used to update document when user sent document or self signed
|
||||||
|
const document = request.object;
|
||||||
|
const oldDocument = request.original;
|
||||||
|
|
||||||
|
// Check if SignedUrl field has been added (transition from undefined to defined)
|
||||||
|
if (!oldDocument?.get('SignedUrl') && document?.get('SignedUrl')) {
|
||||||
|
// Update count in contracts_Users class
|
||||||
|
const query = new Parse.Query('contracts_Users');
|
||||||
|
query.equalTo('objectId', oldDocument.get('ExtUserPtr').id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const contractUser = await query.first({ useMasterKey: true });
|
||||||
|
if (contractUser) {
|
||||||
|
contractUser.increment('DocumentCount', 1);
|
||||||
|
await contractUser.save(null, { useMasterKey: true });
|
||||||
|
} else {
|
||||||
|
// Create new entry if not found
|
||||||
|
const ContractsUsers = Parse.Object.extend('contracts_users');
|
||||||
|
const newContractUser = new ContractsUsers();
|
||||||
|
newContractUser.set('DocumentCount', 1);
|
||||||
|
await newContractUser.save(null, { useMasterKey: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error updating document count in contracts_users: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in document beforesave', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default DocumentBeforesave;
|
||||||
@@ -1,47 +1,65 @@
|
|||||||
import axios from 'axios'
|
import { updateMailCount } from '../../Utils.js';
|
||||||
|
async function getDocument(docId) {
|
||||||
|
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');
|
||||||
|
query.notEqualTo('IsArchive', true);
|
||||||
|
const res = await query.first({ useMasterKey: true });
|
||||||
|
const _res = res.toJSON();
|
||||||
|
return _res?.ExtUserPtr?.objectId;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err ', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
async function sendMailOTPv1(request) {
|
async function sendMailOTPv1(request) {
|
||||||
try {
|
try {
|
||||||
//--for elearning app side
|
//--for elearning app side
|
||||||
let code = Math.floor(1000 + Math.random() * 9000);
|
let code = Math.floor(1000 + Math.random() * 9000);
|
||||||
let email = request.params.email;
|
let email = request.params.email;
|
||||||
var TenantId = request.params.TenantId ? request.params.TenantId : undefined;
|
var TenantId = request.params.TenantId ? request.params.TenantId : undefined;
|
||||||
// console.log("In tempSendOTPv2");
|
|
||||||
|
|
||||||
// console.log(JSON.stringify(request));
|
|
||||||
|
|
||||||
if (email) {
|
if (email) {
|
||||||
axios({
|
const recipient = request.params.email;
|
||||||
method: 'POST',
|
const mailsender = process.env.SMTP_ENABLE
|
||||||
url: process.env.SERVER_URL + '/functions/sendmail',
|
? process.env.SMTP_USER_EMAIL
|
||||||
headers: {
|
: process.env.MAILGUN_SENDER;
|
||||||
'Content-Type': 'application/json',
|
try {
|
||||||
'X-Parse-Application-Id': process.env.APP_ID,
|
await Parse.Cloud.sendEmail({
|
||||||
},
|
from: 'Opensign™' + ' <' + mailsender + '>',
|
||||||
params: {
|
recipient: recipient,
|
||||||
otp: code,
|
subject: 'Your OpenSign™ OTP',
|
||||||
email: email,
|
text: 'This email is a test.',
|
||||||
TenantId: TenantId,
|
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 style='background-color:red;padding:2px;font-family:system-ui; background-color:#47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',>OTP Verification</p></div><div style='padding:20px'><p style='font-family:system-ui;font-size:14px'>Your OTP for OpenSign™ verification is:</p><p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px;margin:20px'>" +
|
||||||
}).then(
|
code +
|
||||||
function (httpResponse) {},
|
'</p></div> </div> </div></body></html>',
|
||||||
function (httpResponse) {
|
});
|
||||||
console.error('sms Request failed with response code ' + httpResponse.status);
|
console.log('OTP sent');
|
||||||
return Promise.reject('sms Request failed with response code ' + httpResponse.status);
|
if (request.params?.docId) {
|
||||||
|
const extUserId = await getDocument(request.params?.docId);
|
||||||
|
if (extUserId) {
|
||||||
|
updateMailCount(extUserId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
} catch (err) {
|
||||||
|
console.log('error in send OTP mail', err);
|
||||||
|
}
|
||||||
const tempOtp = new Parse.Query('defaultdata_Otp');
|
const tempOtp = new Parse.Query('defaultdata_Otp');
|
||||||
tempOtp.equalTo('Email', email);
|
tempOtp.equalTo('Email', email);
|
||||||
const resultOTP = await tempOtp.first({ useMasterKey: true });
|
const resultOTP = await tempOtp.first({ useMasterKey: true });
|
||||||
console.log('resultOTP', resultOTP);
|
// console.log('resultOTP', resultOTP);
|
||||||
if (resultOTP !== undefined) {
|
if (resultOTP !== undefined) {
|
||||||
const updateOtpQuery = new Parse.Query('defaultdata_Otp');
|
const updateOtpQuery = new Parse.Query('defaultdata_Otp');
|
||||||
const updateOtp = await updateOtpQuery.get(resultOTP.id, {
|
const updateOtp = await updateOtpQuery.get(resultOTP.id, {
|
||||||
useMasterKey: true,
|
useMasterKey: true,
|
||||||
});
|
});
|
||||||
updateOtp.set('OTP', code);
|
updateOtp.set('OTP', code);
|
||||||
const updateRes = updateOtp.save(null, { useMasterKey: true });
|
updateOtp.save(null, { useMasterKey: true });
|
||||||
// console.log("update otp Res in tempSendOtp ", updateRes);
|
// console.log("update otp Res in tempSendOtp ", updateRes);
|
||||||
} else {
|
} else {
|
||||||
const otpClass = Parse.Object.extend('defaultdata_Otp');
|
const otpClass = Parse.Object.extend('defaultdata_Otp');
|
||||||
@@ -49,17 +67,17 @@ async function sendMailOTPv1(request) {
|
|||||||
newOtpQuery.set('OTP', code);
|
newOtpQuery.set('OTP', code);
|
||||||
newOtpQuery.set('Email', email);
|
newOtpQuery.set('Email', email);
|
||||||
newOtpQuery.set('TenantId', TenantId);
|
newOtpQuery.set('TenantId', TenantId);
|
||||||
const newRes = await newOtpQuery.save(null, { useMasterKey: true });
|
await newOtpQuery.save(null, { useMasterKey: true });
|
||||||
// console.log("new otp Res in tempSendOtp ", newRes);
|
// console.log("new otp Res in tempSendOtp ", newRes);
|
||||||
}
|
}
|
||||||
return 'Otp send';
|
return 'Otp send';
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject('Please Enter valid email');
|
return 'Please Enter valid email';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('err in sendMailOTPv1');
|
console.log('err in sendMailOTPv1');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return Promise.reject(err);
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default sendMailOTPv1;
|
export default sendMailOTPv1;
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
async function SendMailv1(request) {
|
|
||||||
console.log('in SendMailv1');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const recipient = request.params.email;
|
|
||||||
const otp = request.params.otp;
|
|
||||||
const res = await Parse.Cloud.sendEmail({
|
|
||||||
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.',
|
|
||||||
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 style='background-color:red;padding:2px;font-family:system-ui; background-color:#47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',>OTP Verification</p></div><div style='padding:20px'><p style='font-family:system-ui;font-size:14px'>Your OTP for OpenSign™ verification is:</p><p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px;margin:20px'>" +
|
|
||||||
otp +
|
|
||||||
'</p></div> </div> </div></body></html>',
|
|
||||||
// "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body style='text-align: center;'><div style='display:flex;flex-direction:column;justify-content:center;align-item:center;margin:40px'> <p style='font-weight: bolder; font-size: large;'>Hello,</p> <span>Your OTP for LegaDaft verification . </span> <p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px'>76984</p><span>Thank You!</span> </div> </body></html>"
|
|
||||||
});
|
|
||||||
console.log('Res');
|
|
||||||
console.log(res);
|
|
||||||
return otp;
|
|
||||||
} catch (err) {
|
|
||||||
console.log('err in SendMailv1');
|
|
||||||
console.log(err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default SendMailv1;
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
|
async function SignatureAfterFind(request) {
|
||||||
|
if (request.objects.length === 1) {
|
||||||
|
if (request.objects) {
|
||||||
|
const obj = request.objects[0];
|
||||||
|
const ImageURL = obj?.get('ImageURL') && obj?.get('ImageURL');
|
||||||
|
const Initials = obj?.get('Initials') && obj?.get('Initials');
|
||||||
|
|
||||||
|
if (ImageURL) {
|
||||||
|
obj.set('ImageURL', getPresignedUrl(ImageURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Initials) {
|
||||||
|
obj.set('Initials', getPresignedUrl(Initials));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [obj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default SignatureAfterFind;
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
export default async function SubscribeFree(request) {
|
||||||
|
const userId = request.params.userId;
|
||||||
|
const userPtr = { __type: 'Pointer', className: '_User', objectId: userId };
|
||||||
|
try {
|
||||||
|
const extQuery = new Parse.Query('contracts_Users');
|
||||||
|
extQuery.equalTo('UserId', userPtr);
|
||||||
|
const extUser = await extQuery.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const subscriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||||
|
subscriptionCls.equalTo('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
subscriptionCls.descending('createdAt');
|
||||||
|
const subcripitions = await subscriptionCls.first({ useMasterKey: true });
|
||||||
|
if (subcripitions?.get('PlanCode') === 'freeplan') {
|
||||||
|
return { status: 'success', result: 'already subscribed!' };
|
||||||
|
} else if (subcripitions?.get('Next_billing_date') < new Date()) {
|
||||||
|
try {
|
||||||
|
const updateSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
updateSubscription.id = subcripitions.id;
|
||||||
|
updateSubscription.set('PlanCode', 'freeplan');
|
||||||
|
await updateSubscription.save(null, { useMasterKey: true });
|
||||||
|
return { status: 'success', result: 'subscribed!' };
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err ', err);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
} else if (subcripitions?.get('Next_billing_date') > new Date()) {
|
||||||
|
return { status: 'success', result: 'already subscribed!' };
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const createSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
createSubscription.set('PlanCode', 'freeplan');
|
||||||
|
createSubscription.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUser.id,
|
||||||
|
});
|
||||||
|
createSubscription.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: extUser.get('UserId').id,
|
||||||
|
});
|
||||||
|
if (extUser?.get('TenantId')) {
|
||||||
|
createSubscription.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await createSubscription.save(null, { useMasterKey: true });
|
||||||
|
return { status: 'success', result: 'subscribed!' };
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err ', err);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'error', result: 'User not found!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err ', err);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
|
async function TemplateAfterFind(request) {
|
||||||
|
if (request.objects.length === 1) {
|
||||||
|
if (request.objects) {
|
||||||
|
const obj = request.objects[0];
|
||||||
|
const SignedUrl = obj?.get('SignedUrl') && obj?.get('SignedUrl');
|
||||||
|
const Url = obj?.get('URL') && obj?.get('URL');
|
||||||
|
const certificateUrl = obj.get('CertificateUrl') && obj.get('CertificateUrl');
|
||||||
|
if (SignedUrl) {
|
||||||
|
obj.set('SignedUrl', getPresignedUrl(SignedUrl));
|
||||||
|
}
|
||||||
|
if (Url) {
|
||||||
|
obj.set('URL', getPresignedUrl(Url));
|
||||||
|
}
|
||||||
|
if (certificateUrl) {
|
||||||
|
obj.set('CertificateUrl', getPresignedUrl(certificateUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [obj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default TemplateAfterFind;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
async function TemplateBeforeSave(request) {
|
||||||
|
try {
|
||||||
|
if (!request.original) {
|
||||||
|
// below code is used to update template when user sent template or self signed
|
||||||
|
const template = request.object;
|
||||||
|
|
||||||
|
// Update count in contracts_Users class
|
||||||
|
const query = new Parse.Query('contracts_Users');
|
||||||
|
query.equalTo('objectId', template.get('ExtUserPtr').id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const contractUser = await query.first({ useMasterKey: true });
|
||||||
|
if (contractUser) {
|
||||||
|
contractUser.increment('TemplateCount', 1);
|
||||||
|
await contractUser.save(null, { useMasterKey: true });
|
||||||
|
} else {
|
||||||
|
// Create new entry if not found
|
||||||
|
const ContractsUsers = Parse.Object.extend('contracts_users');
|
||||||
|
const newContractUser = new ContractsUsers();
|
||||||
|
newContractUser.set('TemplateCount', 1);
|
||||||
|
await newContractUser.save(null, { useMasterKey: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error updating template count in contracts_users: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in template beforesave', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default TemplateBeforeSave;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
|
async function TenantAterFind(request) {
|
||||||
|
if (request.objects.length === 1) {
|
||||||
|
if (request.objects) {
|
||||||
|
const obj = request.objects[0];
|
||||||
|
const Logo = obj?.get('Logo') && obj?.get('Logo');
|
||||||
|
if (Logo) {
|
||||||
|
obj.set('Logo', getPresignedUrl(Logo));
|
||||||
|
}
|
||||||
|
return [obj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default TenantAterFind;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import getPresignedUrl from './getSignedUrl.js';
|
||||||
|
|
||||||
|
async function UserAfterFind(request) {
|
||||||
|
if (request.objects.length === 1) {
|
||||||
|
if (request.objects) {
|
||||||
|
const obj = request.objects[0];
|
||||||
|
const ProfilePic = obj?.get('ProfilePic') && obj?.get('ProfilePic');
|
||||||
|
|
||||||
|
if (ProfilePic) {
|
||||||
|
obj.set('ProfilePic', getPresignedUrl(ProfilePic));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [obj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default UserAfterFind;
|
||||||
@@ -23,23 +23,16 @@ export default async function ZohoDetails(request) {
|
|||||||
};
|
};
|
||||||
// Make the POST request using Axios
|
// Make the POST request using Axios
|
||||||
const res = await axios.post(url, formData, { headers });
|
const res = await axios.post(url, formData, { headers });
|
||||||
|
|
||||||
// console.log("Access Token:", res.data);
|
// console.log("Access Token:", res.data);
|
||||||
|
|
||||||
if (res.data.access_token) {
|
if (res.data.access_token) {
|
||||||
const hostedpages = request.params.hostedpagesId;
|
const hostedpages = request.params.hostedpagesId;
|
||||||
const userData = await axios.get('https://billing.zoho.in/api/v1/hostedpages/' + hostedpages, {
|
const userData = await axios.get('https://billing.zoho.in/api/v1/hostedpages/' + hostedpages, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'Zoho-oauthtoken ' + res.data.access_token,
|
Authorization: 'Zoho-oauthtoken ' + res.data.access_token,
|
||||||
'X-com-zoho-billing-organizationid': process.env.ZOHO_BILLING_ORG_ID,
|
'X-com-zoho-subscriptions-organizationid': process.env.ZOHO_BILLING_ORG_ID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// console.log(
|
|
||||||
// "userData.data.data.subscription.contactpersons ",
|
|
||||||
// userData.data.data.subscription.contactpersons
|
|
||||||
// );
|
|
||||||
|
|
||||||
// console.log("userData.data.expiring_time ", userData.data.expiring_time);
|
|
||||||
const first_name = userData.data.data.subscription.contactpersons[0].first_name || '';
|
const first_name = userData.data.data.subscription.contactpersons[0].first_name || '';
|
||||||
const last_name = userData.data.data.subscription.contactpersons[0].last_name || '';
|
const last_name = userData.data.data.subscription.contactpersons[0].last_name || '';
|
||||||
const company_name =
|
const company_name =
|
||||||
@@ -60,6 +53,7 @@ export default async function ZohoDetails(request) {
|
|||||||
customer_id: userData.data.data.subscription.customer_id,
|
customer_id: userData.data.data.subscription.customer_id,
|
||||||
subscription_id: userData.data.data.subscription.subscription_id,
|
subscription_id: userData.data.data.subscription.subscription_id,
|
||||||
jobTitle: jobTitle,
|
jobTitle: jobTitle,
|
||||||
|
subscription: userData.data,
|
||||||
};
|
};
|
||||||
return resData;
|
return resData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default async function getDocument(request) {
|
|||||||
query.include('Signers');
|
query.include('Signers');
|
||||||
query.include('AuditTrail.UserPtr');
|
query.include('AuditTrail.UserPtr');
|
||||||
query.include('Placeholders');
|
query.include('Placeholders');
|
||||||
query.notEqualTo('IsArchive', true)
|
query.notEqualTo('IsArchive', true);
|
||||||
const res = await query.first({ useMasterKey: true });
|
const res = await query.first({ useMasterKey: true });
|
||||||
if (res) {
|
if (res) {
|
||||||
const acl = res.getACL();
|
const acl = res.getACL();
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
const serverUrl = process.env.SERVER_URL;
|
||||||
|
const appId = process.env.APP_ID;
|
||||||
|
export default async function getInvoices(request) {
|
||||||
|
const limit = request.params.limit || 100;
|
||||||
|
const skip = request.params.skip || 0;
|
||||||
|
const extUserId = request.params.extUserId;
|
||||||
|
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) {
|
||||||
|
if (!extUserId) {
|
||||||
|
return { status: 'error', result: 'Please provide parameter!' };
|
||||||
|
}
|
||||||
|
const invoiceCls = new Parse.Query('contracts_Invoices');
|
||||||
|
invoiceCls.equalTo('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUserId,
|
||||||
|
});
|
||||||
|
invoiceCls.limit(limit);
|
||||||
|
invoiceCls.skip(skip);
|
||||||
|
invoiceCls.descending('createdAt');
|
||||||
|
const invoices = await invoiceCls.find({ useMasterKey: true });
|
||||||
|
if (invoices?.length > 0) {
|
||||||
|
const _invoices = JSON.parse(JSON.stringify(invoices));
|
||||||
|
return { status: 'success', result: _invoices };
|
||||||
|
} else {
|
||||||
|
return { status: 'success', result: [] };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'error', result: 'Invalid session token!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in get invoices', err.message);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
const serverUrl = process.env.SERVER_URL;
|
||||||
|
const appId = process.env.APP_ID;
|
||||||
|
export default async function getPayments(request) {
|
||||||
|
const limit = request.params.limit || 100;
|
||||||
|
const skip = request.params.skip || 0;
|
||||||
|
const extUserId = request.params.extUserId;
|
||||||
|
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 paymentsCls = new Parse.Query('contracts_Payments');
|
||||||
|
paymentsCls.equalTo('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_User',
|
||||||
|
objectId: extUserId,
|
||||||
|
});
|
||||||
|
paymentsCls.limit(limit);
|
||||||
|
paymentsCls.skip(skip);
|
||||||
|
paymentsCls.descending('createdAt');
|
||||||
|
const payments = await paymentsCls.find({ useMasterKey: true });
|
||||||
|
if (payments?.length > 0) {
|
||||||
|
const _payments = JSON.parse(JSON.stringify(payments));
|
||||||
|
return { status: 'success', result: _payments };
|
||||||
|
} else {
|
||||||
|
return { status: 'success', result: [] };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'error', result: 'Invalid session token!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in get Payments', err.message);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ export default async function getReport(request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('err', err);
|
console.log('err', err.message);
|
||||||
if (err.code == 209) {
|
if (err.code == 209) {
|
||||||
return { error: 'Invalid session token' };
|
return { error: 'Invalid session token' };
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import AWS from 'aws-sdk';
|
||||||
|
const credentials = {
|
||||||
|
accessKeyId: process.env.DO_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
|
||||||
|
};
|
||||||
|
AWS.config.update({ credentials: credentials, region: process.env.DO_REGION });
|
||||||
|
const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT);
|
||||||
|
|
||||||
|
const s3 = new AWS.S3({ endpoint: spacesEndpoint });
|
||||||
|
|
||||||
|
export default function getPresignedUrl(url) {
|
||||||
|
// Create a new URL object
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
// Get the pathname of the URL
|
||||||
|
const pathname = parsedUrl.pathname;
|
||||||
|
// Extract the filename from the pathname
|
||||||
|
const filename = pathname.substring(pathname.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
// presignedGETURL return presignedUrl with expires time
|
||||||
|
const presignedGETURL = s3.getSignedUrl('getObject', {
|
||||||
|
Bucket: process.env.DO_SPACE,
|
||||||
|
Key: filename, //filename
|
||||||
|
Expires: 160, //time to expire in seconds
|
||||||
|
});
|
||||||
|
return presignedGETURL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
const serverUrl = process.env.SERVER_URL;
|
||||||
|
const appId = process.env.APP_ID;
|
||||||
|
export default async function getSubscription(request) {
|
||||||
|
const extUserId = request.params.extUserId;
|
||||||
|
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 subcriptionCls = new Parse.Query('contracts_Users');
|
||||||
|
const exUser = await subcriptionCls.get(extUserId, { useMasterKey: true });
|
||||||
|
if (exUser) {
|
||||||
|
const subscriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||||
|
subscriptionCls.equalTo('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: exUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
subscriptionCls.descending('createdAt');
|
||||||
|
const subcripitions = await subscriptionCls.first({ useMasterKey: true });
|
||||||
|
if (subcripitions) {
|
||||||
|
const _subcripitions = JSON.parse(JSON.stringify(subcripitions));
|
||||||
|
return { status: 'success', result: _subcripitions };
|
||||||
|
} else {
|
||||||
|
return { status: 'success', result: {} };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'error', result: 'User not found!' };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'error', result: 'Invalid session token!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in get subscription', err.message);
|
||||||
|
return { status: 'error', result: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
export default async function GenerateCertificate(docDetails) {
|
||||||
|
const pdfDoc = await PDFDocument.create();
|
||||||
|
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);
|
||||||
|
const pngUrl = fs.readFileSync('./logo.png').buffer;
|
||||||
|
const pngImage = await pdfDoc.embedPng(pngUrl);
|
||||||
|
const page = pdfDoc.addPage();
|
||||||
|
const { width, height } = page.getSize();
|
||||||
|
const startX = 15;
|
||||||
|
const startY = 15;
|
||||||
|
const borderColor = rgb(0.12, 0.12, 0.12);
|
||||||
|
const titleColor = rgb(0, 0.2, 0.4); //rgb(0, 0.53, 0.71);
|
||||||
|
const titleUnderline = rgb(0, 0.2, 0.4); // rgb(0.12, 0.12, 0.12);
|
||||||
|
const title = 25;
|
||||||
|
const subtitle = 20;
|
||||||
|
const text = 14;
|
||||||
|
const textKeyColor = rgb(0.12, 0.12, 0.12);
|
||||||
|
const textValueColor = rgb(0.3, 0.3, 0.3);
|
||||||
|
const completedAt = new Date(docDetails.updatedAt);
|
||||||
|
const completedUTCtime = completedAt.toUTCString();
|
||||||
|
const signersCount = docDetails?.Signers?.length || 1;
|
||||||
|
const createdAt = new Date();
|
||||||
|
const createdUTCTime = createdAt.toUTCString();
|
||||||
|
const createDate = 'Generated On ' + createdUTCTime;
|
||||||
|
const company = docDetails?.ExtUserPtr?.Company || '';
|
||||||
|
const auditTrail =
|
||||||
|
docDetails.AuditTrail?.length > 1
|
||||||
|
? docDetails.AuditTrail.map(x => {
|
||||||
|
const data = docDetails.Signers.find(y => y.objectId === x.UserPtr.objectId);
|
||||||
|
return { ...data, ipAddress: x.ipAddress };
|
||||||
|
})
|
||||||
|
: [{ ...docDetails.ExtUserPtr, ipAddress: docDetails?.AuditTrail[0].ipAddress }];
|
||||||
|
|
||||||
|
// Draw a border
|
||||||
|
page.drawRectangle({
|
||||||
|
x: startX,
|
||||||
|
y: startY,
|
||||||
|
width: width - 2 * startX,
|
||||||
|
height: height - 2 * startY,
|
||||||
|
borderColor: borderColor,
|
||||||
|
borderWidth: 1,
|
||||||
|
});
|
||||||
|
page.drawImage(pngImage, {
|
||||||
|
x: 30,
|
||||||
|
y: 790,
|
||||||
|
width: 100,
|
||||||
|
height: 25,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(createDate, {
|
||||||
|
x: 320,
|
||||||
|
y: 810,
|
||||||
|
size: 12,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: rgb(0.12, 0.12, 0.12),
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Certificate of Completion', {
|
||||||
|
x: 160,
|
||||||
|
y: 750,
|
||||||
|
size: title,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: titleColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
const underlineY = 740;
|
||||||
|
page.drawLine({
|
||||||
|
start: { x: 30, y: underlineY },
|
||||||
|
end: { x: width - 30, y: underlineY },
|
||||||
|
color: titleUnderline,
|
||||||
|
thickness: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Summary', {
|
||||||
|
x: 30,
|
||||||
|
y: 710,
|
||||||
|
size: subtitle,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: titleColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Document Id :', {
|
||||||
|
x: 30,
|
||||||
|
y: 685,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(docDetails.objectId, {
|
||||||
|
x: 115,
|
||||||
|
y: 685,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Document Name :', {
|
||||||
|
x: 30,
|
||||||
|
y: 665,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(docDetails.Name, {
|
||||||
|
x: 140,
|
||||||
|
y: 665,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Organization :', {
|
||||||
|
x: 30,
|
||||||
|
y: 645,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(company, {
|
||||||
|
x: 115,
|
||||||
|
y: 645,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Completed on :', {
|
||||||
|
x: 30,
|
||||||
|
y: 625,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(`${completedUTCtime}`, {
|
||||||
|
x: 120,
|
||||||
|
y: 625,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Signers :', {
|
||||||
|
x: 30,
|
||||||
|
y: 605,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(`${signersCount}`, {
|
||||||
|
x: 80,
|
||||||
|
y: 605,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawLine({
|
||||||
|
start: { x: 30, y: 565 },
|
||||||
|
end: { x: width - 30, y: 565 },
|
||||||
|
color: rgb(0.12, 0.12, 0.12),
|
||||||
|
thickness: 0.5,
|
||||||
|
});
|
||||||
|
page.drawText('Recipients', {
|
||||||
|
x: 30,
|
||||||
|
y: 575,
|
||||||
|
size: subtitle,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: titleColor,
|
||||||
|
});
|
||||||
|
let yPosition1 = 550;
|
||||||
|
let yPosition2 = 530;
|
||||||
|
let yPosition3 = 510;
|
||||||
|
let yPosition4 = 500;
|
||||||
|
auditTrail.forEach(x => {
|
||||||
|
page.drawText('Name :', {
|
||||||
|
x: 30,
|
||||||
|
y: yPosition1,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(x?.Name, {
|
||||||
|
x: 75,
|
||||||
|
y: yPosition1,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Email :', {
|
||||||
|
x: 30,
|
||||||
|
y: yPosition2,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(x?.Email, {
|
||||||
|
x: 75,
|
||||||
|
y: yPosition2,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText('Accessed from :', {
|
||||||
|
x: 30,
|
||||||
|
y: yPosition3,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textKeyColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawText(x?.ipAddress, {
|
||||||
|
x: 125,
|
||||||
|
y: yPosition3,
|
||||||
|
size: text,
|
||||||
|
font: timesRomanFont,
|
||||||
|
color: textValueColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
page.drawLine({
|
||||||
|
start: { x: 30, y: yPosition4 },
|
||||||
|
end: { x: width - 30, y: yPosition4 },
|
||||||
|
color: rgb(0.12, 0.12, 0.12),
|
||||||
|
thickness: 0.5,
|
||||||
|
});
|
||||||
|
|
||||||
|
yPosition1 = yPosition4 - 20;
|
||||||
|
yPosition2 = yPosition1 - 20;
|
||||||
|
yPosition3 = yPosition2 - 20;
|
||||||
|
yPosition4 = yPosition4 - 70;
|
||||||
|
});
|
||||||
|
|
||||||
|
const pdfBytes = await pdfDoc.save();
|
||||||
|
return pdfBytes;
|
||||||
|
}
|
||||||
+197
-156
@@ -3,13 +3,15 @@ import fs from 'node:fs';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { pdflibAddPlaceholder } from './customSignPdf/pdflibplaceholder.min.js';
|
import { pdflibAddPlaceholder } from './customSignPdf/pdflibplaceholder.min.js';
|
||||||
import { PDFDocument } from 'pdf-lib';
|
import { PDFDocument } from 'pdf-lib';
|
||||||
|
import { replaceMailVaribles, saveFileUsage } from '../../../Utils.js';
|
||||||
|
import GenerateCertificate from './GenerateCertificate.js';
|
||||||
const serverUrl = process.env.SERVER_URL,
|
const serverUrl = process.env.SERVER_URL,
|
||||||
APPID = process.env.APP_ID,
|
APPID = process.env.APP_ID,
|
||||||
masterKEY = process.env.MASTER_KEY;
|
masterKEY = process.env.MASTER_KEY;
|
||||||
async function uploadFile(e, a) {
|
async function uploadFile(e, a) {
|
||||||
try {
|
try {
|
||||||
var t = fs.readFileSync(a),
|
var t = fs.readFileSync(a),
|
||||||
s = new Parse.File(e, [...t]),
|
s = new Parse.File(e, [...t], 'application/pdf'),
|
||||||
r = (await s.save({ useMasterKey: !0 }), s.url());
|
r = (await s.save({ useMasterKey: !0 }), s.url());
|
||||||
return { imageUrl: r };
|
return { imageUrl: r };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -18,18 +20,18 @@ async function uploadFile(e, a) {
|
|||||||
}
|
}
|
||||||
async function updateDoc(t, s, r, i, o, n) {
|
async function updateDoc(t, s, r, i, o, n) {
|
||||||
try {
|
try {
|
||||||
var d = {
|
var l = {
|
||||||
UserPtr: { __type: 'Pointer', className: n, objectId: r },
|
UserPtr: { __type: 'Pointer', className: n, objectId: r },
|
||||||
SignedUrl: s,
|
SignedUrl: s,
|
||||||
Activity: 'Signed',
|
Activity: 'Signed',
|
||||||
ipAddress: i,
|
ipAddress: i,
|
||||||
};
|
};
|
||||||
let e;
|
let e;
|
||||||
var l = (e = o.AuditTrail && 0 < o.AuditTrail.length ? [...o.AuditTrail, d] : [d]).filter(
|
var d = (e = o.AuditTrail && 0 < o.AuditTrail.length ? [...o.AuditTrail, l] : [l]).filter(
|
||||||
e => 'Signed' === e.Activity
|
e => 'Signed' === e.Activity
|
||||||
);
|
);
|
||||||
let a = !1;
|
let a = !1;
|
||||||
!((o.Signers && 0 < o.Signers.length && l.length !== o.Signers.length) || !(a = !0));
|
!((o.Signers && 0 < o.Signers.length && d.length !== o.Signers.length) || !(a = !0));
|
||||||
var c = { SignedUrl: s, AuditTrail: e, IsCompleted: a };
|
var c = { SignedUrl: s, AuditTrail: e, IsCompleted: a };
|
||||||
await axios.put(serverUrl + '/classes/contracts_Document/' + t, c, {
|
await axios.put(serverUrl + '/classes/contracts_Document/' + t, c, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -38,54 +40,70 @@ async function updateDoc(t, s, r, i, o, n) {
|
|||||||
'X-Parse-Master-Key': masterKEY,
|
'X-Parse-Master-Key': masterKEY,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return { isCompleted: a, message: 'success' };
|
return { isCompleted: a, message: 'success', AuditTrail: e };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return console.log('update doc err ', e), 'err';
|
return console.log('update doc err ', e), 'err';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function sendMail(e) {
|
|
||||||
var a = e.url,
|
|
||||||
t = e.sender,
|
|
||||||
s = e.pdfName,
|
|
||||||
a = {
|
|
||||||
url: a,
|
|
||||||
from: 'OpenSign™',
|
|
||||||
recipient: e.receiver,
|
|
||||||
subject: 'You have signed the doc - ' + s,
|
|
||||||
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 Copy</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document " +
|
|
||||||
s +
|
|
||||||
' Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' +
|
|
||||||
t.Mail +
|
|
||||||
' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>',
|
|
||||||
};
|
|
||||||
await axios.post(serverUrl + '/functions/sendmailv3', a, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-Parse-Application-Id': APPID,
|
|
||||||
'X-Parse-Master-Key': masterKEY,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function sendCompletedMail(e) {
|
async function sendCompletedMail(e) {
|
||||||
var a = e.url,
|
var a = e.url,
|
||||||
t = e.sender,
|
t = e.doc,
|
||||||
s = e.pdfName,
|
s = e.doc.ExtUserPtr,
|
||||||
a = {
|
r = t.Name,
|
||||||
url: a,
|
i = s.Email;
|
||||||
from: 'OpenSign™',
|
let o = `Document "${r}" has been signed by all parties`,
|
||||||
recipient: e.receiver,
|
n =
|
||||||
subject: `Document ${s} has been signed by all parties`,
|
"<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 signed successfully</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document " +
|
||||||
pdfName: s,
|
`<b>"${r}"</b>` +
|
||||||
html:
|
'. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' +
|
||||||
"<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" +
|
s.Email +
|
||||||
s +
|
' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>';
|
||||||
'. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' +
|
if (e?.isCustomMail)
|
||||||
t.Mail +
|
try {
|
||||||
' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>',
|
var l,
|
||||||
};
|
d,
|
||||||
await axios.post(serverUrl + '/functions/sendmailv3', a, {
|
c,
|
||||||
|
p,
|
||||||
|
m,
|
||||||
|
g = new Parse.Query('partners_Tenant');
|
||||||
|
g.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: s.UserId.objectId });
|
||||||
|
const u = await g.first();
|
||||||
|
u &&
|
||||||
|
((l = JSON.parse(JSON.stringify(u)))?.CompletionSubject && (o = l?.CompletionSubject),
|
||||||
|
l?.CompletionBody && (n = l?.CompletionBody),
|
||||||
|
(d = t.ExpiryDate.iso),
|
||||||
|
(c = new Date(d).toLocaleDateString('en-US', {
|
||||||
|
day: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
})),
|
||||||
|
(p = {
|
||||||
|
document_title: r,
|
||||||
|
sender_name: s.Name,
|
||||||
|
sender_mail: s.Email,
|
||||||
|
sender_phone: s.Phone,
|
||||||
|
receiver_name: s.Name,
|
||||||
|
receiver_email: s.Email,
|
||||||
|
receiver_phone: s.Phone,
|
||||||
|
expiry_date: c,
|
||||||
|
company_name: s.Company,
|
||||||
|
}),
|
||||||
|
(m = replaceMailVaribles(o, n, p)),
|
||||||
|
(o = m.subject),
|
||||||
|
(n = m.body));
|
||||||
|
} catch (e) {
|
||||||
|
console.log('error in fetch tenant in signpdf', e.message);
|
||||||
|
}
|
||||||
|
e = {
|
||||||
|
extUserId: s.objectId,
|
||||||
|
url: a,
|
||||||
|
from: 'OpenSign™',
|
||||||
|
recipient: i,
|
||||||
|
subject: o,
|
||||||
|
pdfName: r,
|
||||||
|
html: n,
|
||||||
|
};
|
||||||
|
await axios.post(serverUrl + '/functions/sendmailv3', e, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Parse-Application-Id': APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
@@ -132,11 +150,11 @@ async function sendDoctoWebhook(t, e, a, s) {
|
|||||||
}),
|
}),
|
||||||
a.save(null, { useMasterKey: !0 });
|
a.save(null, { useMasterKey: !0 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('err save in contracts_Webhook', e);
|
console.log('err save in contracts_Webhook', e.message);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
console.log('Err send data to webhook', e);
|
console.log('Err send data to webhook', e.message);
|
||||||
try {
|
try {
|
||||||
var a = new Parse.Object('contracts_Webhook');
|
var a = new Parse.Object('contracts_Webhook');
|
||||||
a.set('Log', e?.status),
|
a.set('Log', e?.status),
|
||||||
@@ -147,16 +165,17 @@ async function sendDoctoWebhook(t, e, a, s) {
|
|||||||
}),
|
}),
|
||||||
a.save(null, { useMasterKey: !0 });
|
a.save(null, { useMasterKey: !0 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('err save in contracts_Webhook', e);
|
console.log('err save in contracts_Webhook', e.message);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
async function PDF(i) {
|
async function PDF(o) {
|
||||||
try {
|
try {
|
||||||
var e = i.params.docId,
|
var n = o.params.docId,
|
||||||
a = i.params.userId,
|
e = o.params.userId,
|
||||||
o = await axios.get(
|
l = o.params.isCustomCompletionMail,
|
||||||
serverUrl + '/classes/contracts_Document/' + e + '?include=ExtUserPtr,Signers',
|
d = await axios.get(
|
||||||
|
serverUrl + '/classes/contracts_Document/' + n + '?include=ExtUserPtr,Signers',
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -165,143 +184,165 @@ async function PDF(i) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
t = await axios.get(serverUrl + '/users/me', {
|
c = await axios.get(serverUrl + '/users/me', {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
'X-Parse-Session-Token': i.headers.sessiontoken,
|
'X-Parse-Session-Token': o.headers.sessiontoken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!t.data || !t.data.objectId) return { status: 'error', message: 'this user not allowed!' };
|
if (!c.data || !c.data.objectId) return { status: 'error', message: 'This user not allowed!' };
|
||||||
{
|
{
|
||||||
var n,
|
var a,
|
||||||
d,
|
t,
|
||||||
l,
|
s,
|
||||||
c = JSON.stringify({ objectId: a });
|
p = JSON.stringify({ objectId: e });
|
||||||
let s, r;
|
let r, i;
|
||||||
r = a
|
i = e
|
||||||
? (n = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + c, {
|
? (a = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + p, {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
'X-Parse-Session-Token': i.headers.sessiontoken,
|
'X-Parse-Session-Token': o.headers.sessiontoken,
|
||||||
},
|
},
|
||||||
})).data && 0 < n.data.results.length
|
})).data && 0 < a.data.results.length
|
||||||
? ((s = n), 'contracts_Contactbook')
|
? ((r = a), 'contracts_Contactbook')
|
||||||
: ((s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + c, {
|
: ((r = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, {
|
||||||
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
|
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
|
||||||
})),
|
})),
|
||||||
'contracts_Users')
|
'contracts_Users')
|
||||||
: ((d = JSON.stringify({
|
: ((t = JSON.stringify({
|
||||||
UserId: { __type: 'Pointer', className: '_User', objectId: t.data.objectId },
|
UserId: { __type: 'Pointer', className: '_User', objectId: c.data.objectId },
|
||||||
})),
|
})),
|
||||||
(l = await axios.get(serverUrl + '/classes/contracts_Users?where=' + d, {
|
(s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + t, {
|
||||||
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
|
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
|
||||||
})).data && 0 < l.data.results.length
|
})).data && 0 < s.data.results.length
|
||||||
? ((s = l), 'contracts_Users')
|
? ((r = s), 'contracts_Users')
|
||||||
: ((s = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + d, {
|
: ((r = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + t, {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
'X-Parse-Session-Token': i.headers.sessiontoken,
|
'X-Parse-Session-Token': o.headers.sessiontoken,
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
'contracts_Contactbook'));
|
'contracts_Contactbook'));
|
||||||
var p = s.data.results[0].Name,
|
var m = r.data.results[0].Name,
|
||||||
m = s.data.results[0].Email;
|
g = r.data.results[0].Email;
|
||||||
if (!i.params.pdfFile) return { status: 'error', message: 'pdf file not present!' };
|
if (!o.params.pdfFile) return { status: 'error', message: 'Pdf file not present!' };
|
||||||
{
|
{
|
||||||
let e = Buffer.from(i.params.pdfFile, 'base64');
|
let e = Buffer.from(o.params.pdfFile, 'base64');
|
||||||
var g = process.env.PFX_BASE64,
|
var u = process.env.PFX_BASE64,
|
||||||
h = Buffer.from(g, 'base64'),
|
h = Buffer.from(u, 'base64'),
|
||||||
u = {
|
f = {
|
||||||
UserPtr: { __type: 'Pointer', className: r, objectId: s.data.results[0].objectId },
|
UserPtr: { __type: 'Pointer', className: i, objectId: r.data.results[0].objectId },
|
||||||
SignedUrl: '',
|
SignedUrl: '',
|
||||||
Activity: 'Signed',
|
Activity: 'Signed',
|
||||||
ipAddress: i.headers['x-real-ip'],
|
ipAddress: o.headers['x-real-ip'],
|
||||||
};
|
};
|
||||||
let a;
|
let a;
|
||||||
var f = (a =
|
var P = (a =
|
||||||
o.data.AuditTrail && 0 < o.data.AuditTrail.length
|
d.data.AuditTrail && 0 < d.data.AuditTrail.length
|
||||||
? [...o.data.AuditTrail, u]
|
? [...d.data.AuditTrail, f]
|
||||||
: [u]).filter(e => 'Signed' === e.Activity);
|
: [f]).filter(e => 'Signed' === e.Activity);
|
||||||
let t = !1;
|
let t = !1;
|
||||||
!(
|
!(
|
||||||
(o.data.Signers && 0 < o.data.Signers.length && f.length !== o.data.Signers.length) ||
|
(d.data.Signers && 0 < d.data.Signers.length && P.length !== d.data.Signers.length) ||
|
||||||
!(t = !0)
|
!(t = !0)
|
||||||
);
|
);
|
||||||
var y,
|
var y,
|
||||||
P,
|
|
||||||
v,
|
|
||||||
b,
|
b,
|
||||||
x,
|
v,
|
||||||
w,
|
|
||||||
U,
|
U,
|
||||||
I,
|
I,
|
||||||
S,
|
w,
|
||||||
A = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
|
D = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
|
||||||
D = './exports/' + A,
|
S = './exports/' + D;
|
||||||
E =
|
let s = e.length;
|
||||||
(t
|
s = (
|
||||||
? ((y = o.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
|
t
|
||||||
(e =
|
? ((y = d.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
|
||||||
y && 0 < y.length
|
(e =
|
||||||
? ((P = await PDFDocument.load(e)),
|
y && 0 < y.length
|
||||||
pdflibAddPlaceholder({
|
? ((b = await PDFDocument.load(e)),
|
||||||
pdfDoc: P,
|
pdflibAddPlaceholder({
|
||||||
reason: 'Digitally signed by OpenSign for ' + y?.join(', '),
|
pdfDoc: b,
|
||||||
location: 'location',
|
reason: 'Digitally signed by OpenSign for ' + y?.join(', '),
|
||||||
signatureLength: 15e3,
|
location: 'n/a',
|
||||||
}),
|
signatureLength: 15e3,
|
||||||
(v = await P.save()),
|
}),
|
||||||
Buffer.from(v))
|
(v = await b.save()),
|
||||||
: ((b = await PDFDocument.load(e)),
|
Buffer.from(v))
|
||||||
pdflibAddPlaceholder({
|
: ((U = await PDFDocument.load(e)),
|
||||||
pdfDoc: b,
|
pdflibAddPlaceholder({
|
||||||
reason: 'Digitally signed by OpenSign for ' + p + ' <' + m + '>',
|
pdfDoc: U,
|
||||||
location: 'location',
|
reason: 'Digitally signed by OpenSign for ' + m + ' <' + g + '>',
|
||||||
signatureLength: 15e3,
|
location: 'n/a',
|
||||||
}),
|
signatureLength: 15e3,
|
||||||
(x = await b.save()),
|
}),
|
||||||
Buffer.from(x))),
|
(I = await U.save()),
|
||||||
(w = await new SignPDF(e, h).signPDF()),
|
Buffer.from(I))),
|
||||||
fs.writeFileSync(D, w))
|
(w = await new SignPDF(e, h).signPDF()),
|
||||||
: fs.writeFileSync(D, e),
|
fs.writeFileSync(S, w),
|
||||||
await uploadFile(A, D));
|
w)
|
||||||
if (E && E.imageUrl)
|
: (fs.writeFileSync(S, e), e)
|
||||||
|
).length;
|
||||||
|
var _,
|
||||||
|
A,
|
||||||
|
x,
|
||||||
|
E,
|
||||||
|
j,
|
||||||
|
k,
|
||||||
|
F,
|
||||||
|
C,
|
||||||
|
T,
|
||||||
|
N = await uploadFile(D, S);
|
||||||
|
if (N && N.imageUrl)
|
||||||
return (
|
return (
|
||||||
(U = await updateDoc(
|
(_ = await updateDoc(
|
||||||
i.params.docId,
|
o.params.docId,
|
||||||
E.imageUrl,
|
N.imageUrl,
|
||||||
s.data.results[0].objectId,
|
r.data.results[0].objectId,
|
||||||
i.headers['x-real-ip'],
|
o.headers['x-real-ip'],
|
||||||
o.data,
|
d.data,
|
||||||
r
|
i
|
||||||
)),
|
)),
|
||||||
(I = {
|
sendDoctoWebhook(d, N.imageUrl, 'signed', r?.data.results?.[0]),
|
||||||
url: E.imageUrl,
|
saveFileUsage(s, N.imageUrl, c.data.objectId),
|
||||||
sender: { Mail: o.data.ExtUserPtr.Email, Name: o.data.ExtUserPtr.Name },
|
_ &&
|
||||||
pdfName: o.data.Name,
|
_.isCompleted &&
|
||||||
receiver: m,
|
((A = { ...d.data, AuditTrail: _.AuditTrail }),
|
||||||
}),
|
(x = await GenerateCertificate(A)),
|
||||||
o.data.IsSendMail && !1 === o.data.IsSendMail
|
(E = await PDFDocument.load(x)),
|
||||||
? console.log("don't send mail")
|
pdflibAddPlaceholder({
|
||||||
: sendMail(I),
|
pdfDoc: E,
|
||||||
sendDoctoWebhook(o, E.imageUrl, 'signed', s?.data.results?.[0]),
|
reason: 'Digitally signed by OpenSign.',
|
||||||
U &&
|
location: 'n/a',
|
||||||
U.isCompleted &&
|
signatureLength: 15e3,
|
||||||
((S = {
|
|
||||||
url: E.imageUrl,
|
|
||||||
sender: { Mail: o.data.ExtUserPtr.Email, Name: 'OpenSign™' },
|
|
||||||
pdfName: o.data.Name,
|
|
||||||
receiver: o.data.ExtUserPtr.Email,
|
|
||||||
}),
|
}),
|
||||||
o.data.IsSendMail && !1 === o.data.IsSendMail
|
(j = await E.save()),
|
||||||
|
(k = Buffer.from(j)),
|
||||||
|
(F = await new SignPDF(k, h).signPDF()),
|
||||||
|
fs.writeFileSync('./exports/certificate.pdf', F),
|
||||||
|
(T = {
|
||||||
|
CertificateUrl: (C = await uploadFile(
|
||||||
|
'certificate.pdf',
|
||||||
|
'./exports/certificate.pdf'
|
||||||
|
)).imageUrl,
|
||||||
|
}),
|
||||||
|
await axios.put(serverUrl + '/classes/contracts_Document/' + n, T, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Parse-Application-Id': APPID,
|
||||||
|
'X-Parse-Master-Key': masterKEY,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
d.data.IsSendMail && !1 === d.data.IsSendMail
|
||||||
? console.log("don't send mail")
|
? console.log("don't send mail")
|
||||||
: sendCompletedMail(S),
|
: sendCompletedMail({ url: N.imageUrl, isCustomMail: l, doc: d.data }),
|
||||||
sendDoctoWebhook(o, E.imageUrl, 'completed')),
|
saveFileUsage(k.length, C.imageUrl, c.data.objectId),
|
||||||
fs.unlinkSync(D),
|
sendDoctoWebhook(d, N.imageUrl, 'completed')),
|
||||||
console.log('New Signed PDF created called: ' + D),
|
fs.unlinkSync(S),
|
||||||
'success' === U.message
|
console.log('New Signed PDF created called: ' + S),
|
||||||
? { status: 'success', data: E.imageUrl }
|
'success' === _.message
|
||||||
: { status: 'error', message: 'please provide required parameters!' }
|
? { status: 'success', data: N.imageUrl }
|
||||||
|
: { status: 'error', message: 'Please provide required parameters!' }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,19 +164,10 @@ export default function reportJson(id, userId) {
|
|||||||
IsDeclined: { $ne: true },
|
IsDeclined: { $ne: true },
|
||||||
IsArchive: { $ne: true },
|
IsArchive: { $ne: true },
|
||||||
Type: { $ne: 'Folder' },
|
Type: { $ne: 'Folder' },
|
||||||
$and: [
|
SignedUrl: { $ne: null },
|
||||||
{
|
ExpiryDate: {
|
||||||
$or: [
|
$lt: { __type: 'Date', iso: new Date().toISOString() },
|
||||||
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
|
},
|
||||||
{ Placeholders: { $ne: null } },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ExpiryDate: {
|
|
||||||
$lt: { __type: 'Date', iso: new Date().toISOString() },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
CreatedBy: {
|
CreatedBy: {
|
||||||
__type: 'Pointer',
|
__type: 'Pointer',
|
||||||
className: '_User',
|
className: '_User',
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
export default async function saveSubscriptio(request) {
|
||||||
|
const serverUrl = process.env.SERVER_URL;
|
||||||
|
const appId = process.env.APP_ID;
|
||||||
|
const subscription = request.params.subscription;
|
||||||
|
const SubscriptionId = subscription.data.subscription.subscription_id;
|
||||||
|
const body = subscription;
|
||||||
|
const Next_billing_date = subscription.data.subscription.next_billing_at;
|
||||||
|
const planCode = subscription.data.subscription.plan.plan_code;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': appId,
|
||||||
|
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (userRes.data && userRes.data.objectId) {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('UserId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: userRes.data.objectId,
|
||||||
|
});
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const subcriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||||
|
subcriptionCls.equalTo('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
const subscription = await subcriptionCls.first({ useMasterKey: true });
|
||||||
|
if (subscription) {
|
||||||
|
const updateSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
updateSubscription.id = subscription.id;
|
||||||
|
updateSubscription.set('SubscriptionId', SubscriptionId);
|
||||||
|
updateSubscription.set('SubscriptionDetails', body);
|
||||||
|
updateSubscription.set('Next_billing_date', new Date(Next_billing_date));
|
||||||
|
updateSubscription.set('PlanCode', planCode);
|
||||||
|
await updateSubscription.save(null, { useMasterKey: true });
|
||||||
|
return { status: 'update subscription!' };
|
||||||
|
} else {
|
||||||
|
const createSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
createSubscription.set('SubscriptionId', SubscriptionId);
|
||||||
|
createSubscription.set('SubscriptionDetails', body);
|
||||||
|
createSubscription.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUser.id,
|
||||||
|
});
|
||||||
|
createSubscription.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: extUser.get('UserId').id,
|
||||||
|
});
|
||||||
|
createSubscription.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: extUser.get('TenantId').id,
|
||||||
|
});
|
||||||
|
createSubscription.set('Next_billing_date', new Date(Next_billing_date));
|
||||||
|
createSubscription.set('PlanCode', planCode);
|
||||||
|
await createSubscription.save(null, { useMasterKey: true });
|
||||||
|
return { status: 'create subscription!' };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'user not found!' };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { status: 'user not found!' };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in save subscription', err);
|
||||||
|
throw new Error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
-7
@@ -3,8 +3,9 @@ import https from 'https';
|
|||||||
import formData from 'form-data';
|
import formData from 'form-data';
|
||||||
import Mailgun from 'mailgun.js';
|
import Mailgun from 'mailgun.js';
|
||||||
import { createTransport } from 'nodemailer';
|
import { createTransport } from 'nodemailer';
|
||||||
|
import { updateMailCount } from '../../Utils.js';
|
||||||
|
|
||||||
async function sendmail(req) {
|
async function sendmailv3(req) {
|
||||||
try {
|
try {
|
||||||
let transporterSMTP;
|
let transporterSMTP;
|
||||||
let mailgunClient;
|
let mailgunClient;
|
||||||
@@ -57,8 +58,20 @@ async function sendmail(req) {
|
|||||||
data: process.env.SMTP_ENABLE ? undefined : PdfBuffer,
|
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>"
|
let attachment;
|
||||||
|
// `certificateBuffer` used to create buffer from pdf file
|
||||||
|
try {
|
||||||
|
const certificateBuffer = fs.readFileSync('./exports/certificate.pdf');
|
||||||
|
const certificate = {
|
||||||
|
filename: 'certificate.pdf',
|
||||||
|
content: process.env.SMTP_ENABLE ? certificateBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
|
||||||
|
data: process.env.SMTP_ENABLE ? undefined : certificateBuffer,
|
||||||
|
};
|
||||||
|
attachment = [file, certificate];
|
||||||
|
} catch (err) {
|
||||||
|
attachment = [file];
|
||||||
|
console.log('Err in read certificate sendmailv3', err);
|
||||||
|
}
|
||||||
const from = req.params.from || '';
|
const from = req.params.from || '';
|
||||||
const mailsender = process.env.SMTP_ENABLE
|
const mailsender = process.env.SMTP_ENABLE
|
||||||
? process.env.SMTP_USER_EMAIL
|
? process.env.SMTP_USER_EMAIL
|
||||||
@@ -70,13 +83,21 @@ async function sendmail(req) {
|
|||||||
subject: req.params.subject,
|
subject: req.params.subject,
|
||||||
text: req.params.text || 'mail',
|
text: req.params.text || 'mail',
|
||||||
html: req.params.html || '',
|
html: req.params.html || '',
|
||||||
attachments: process.env.SMTP_ENABLE ? [file] : undefined,
|
attachments: process.env.SMTP_ENABLE ? attachment : undefined,
|
||||||
attachment: process.env.SMTP_ENABLE ? undefined : file,
|
attachment: process.env.SMTP_ENABLE ? undefined : attachment,
|
||||||
};
|
};
|
||||||
if (transporterSMTP) {
|
if (transporterSMTP) {
|
||||||
const res = await transporterSMTP.sendMail(messageParams);
|
const res = await transporterSMTP.sendMail(messageParams);
|
||||||
console.log('Res ', res);
|
console.log('Res ', res);
|
||||||
if (!res.err) {
|
if (!res.err) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fs.unlinkSync('./exports/certificate.pdf');
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in unlink certificate sendmailv3');
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
};
|
};
|
||||||
@@ -85,6 +106,14 @@ async function sendmail(req) {
|
|||||||
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
||||||
console.log('Res ', res);
|
console.log('Res ', res);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fs.unlinkSync('./exports/certificate.pdf');
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in unlink certificate sendmailv3');
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
};
|
};
|
||||||
@@ -109,6 +138,9 @@ async function sendmail(req) {
|
|||||||
const res = await transporterSMTP.sendMail(messageParams);
|
const res = await transporterSMTP.sendMail(messageParams);
|
||||||
console.log('Res ', res);
|
console.log('Res ', res);
|
||||||
if (!res.err) {
|
if (!res.err) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
};
|
};
|
||||||
@@ -117,6 +149,9 @@ async function sendmail(req) {
|
|||||||
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
|
||||||
console.log('Res ', res);
|
console.log('Res ', res);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
};
|
};
|
||||||
@@ -124,11 +159,11 @@ async function sendmail(req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('err ', err);
|
console.log('err in sendmailv3', err);
|
||||||
if (err) {
|
if (err) {
|
||||||
return { status: 'error' };
|
return { status: 'error' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default sendmail;
|
export default sendmailv3;
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import axios from "axios";
|
import axios from 'axios';
|
||||||
const serverUrl = process.env.SERVER_URL;
|
const serverUrl = process.env.SERVER_URL;
|
||||||
const APPID = process.env.APP_ID;
|
const APPID = process.env.APP_ID;
|
||||||
const masterKEY = process.env.MASTER_KEY;
|
const masterKEY = process.env.MASTER_KEY;
|
||||||
|
|
||||||
async function saveUser(userDetails) {
|
async function saveUser(userDetails) {
|
||||||
const userQuery = new Parse.Query(Parse.User);
|
const userQuery = new Parse.Query(Parse.User);
|
||||||
userQuery.equalTo("username", userDetails.email);
|
userQuery.equalTo('username', userDetails.email);
|
||||||
const userRes = await userQuery.first({ useMasterKey: true });
|
const userRes = await userQuery.first({ useMasterKey: true });
|
||||||
|
|
||||||
if (userRes) {
|
if (userRes) {
|
||||||
const url = `${serverUrl}/loginAs`;
|
const url = `${serverUrl}/loginAs`;
|
||||||
const axiosRes = await axios({
|
const axiosRes = await axios({
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json;charset=utf-8",
|
'Content-Type': 'application/json;charset=utf-8',
|
||||||
"X-Parse-Application-Id": APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
"X-Parse-Master-Key": masterKEY,
|
'X-Parse-Master-Key': masterKEY,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
userId: userRes.id,
|
userId: userRes.id,
|
||||||
@@ -27,39 +27,39 @@ async function saveUser(userDetails) {
|
|||||||
return { id: login.objectId, sessionToken: login.sessionToken };
|
return { id: login.objectId, sessionToken: login.sessionToken };
|
||||||
} else {
|
} else {
|
||||||
const user = new Parse.User();
|
const user = new Parse.User();
|
||||||
user.set("username", userDetails.email);
|
user.set('username', userDetails.email);
|
||||||
user.set("password", userDetails.password);
|
user.set('password', userDetails.password);
|
||||||
user.set("email", userDetails.email);
|
user.set('email', userDetails.email);
|
||||||
user.set("phone", userDetails.phone);
|
user.set('phone', userDetails.phone);
|
||||||
user.set("name", userDetails.name);
|
user.set('name', userDetails.name);
|
||||||
|
|
||||||
const res = await user.signUp();
|
const res = await user.signUp();
|
||||||
// console.log("res ", res);
|
// console.log("res ", res);
|
||||||
return { id: res.id, sessionToken: res.getSessionToken() };
|
return { id: res.id, sessionToken: res.getSessionToken() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default async function (request) {
|
export default async function usersignup(request) {
|
||||||
const userDetails = request.params.userDetails;
|
const userDetails = request.params.userDetails;
|
||||||
const planDetails = request.params.planDetails;
|
const subscription = request.params.subscription;
|
||||||
const user = await saveUser(userDetails);
|
const user = await saveUser(userDetails);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const extClass = userDetails.role.split("_")[0];
|
const extClass = userDetails.role.split('_')[0];
|
||||||
|
|
||||||
const extQuery = new Parse.Query(extClass + "_Users");
|
const extQuery = new Parse.Query(extClass + '_Users');
|
||||||
extQuery.equalTo("UserId", {
|
extQuery.equalTo('UserId', {
|
||||||
__type: "Pointer",
|
__type: 'Pointer',
|
||||||
className: "_User",
|
className: '_User',
|
||||||
objectId: user.id,
|
objectId: user.id,
|
||||||
});
|
});
|
||||||
const extUser = await extQuery.first({ useMasterKey: true });
|
const extUser = await extQuery.first({ useMasterKey: true });
|
||||||
if (extUser) {
|
if (extUser) {
|
||||||
return { message: "User already exist" };
|
return { message: 'User already exist' };
|
||||||
} else {
|
} else {
|
||||||
const roleurl = `${serverUrl}/functions/AddUserToRole`;
|
const roleurl = `${serverUrl}/functions/AddUserToRole`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
"X-Parse-Application-Id": APPID,
|
'X-Parse-Application-Id': APPID,
|
||||||
sessionToken: user.sessionToken, //localStorage.getItem("accesstoken"),
|
sessionToken: user.sessionToken, //localStorage.getItem("accesstoken"),
|
||||||
};
|
};
|
||||||
let body = {
|
let body = {
|
||||||
@@ -69,74 +69,98 @@ export default async function (request) {
|
|||||||
};
|
};
|
||||||
let role = await axios.post(roleurl, body, { headers: headers });
|
let role = await axios.post(roleurl, body, { headers: headers });
|
||||||
// console.log("role ", role);
|
// console.log("role ", role);
|
||||||
const partnerCls = Parse.Object.extend("partners_Tenant");
|
const partnerCls = Parse.Object.extend('partners_Tenant');
|
||||||
const partnerQuery = new partnerCls();
|
const partnerQuery = new partnerCls();
|
||||||
partnerQuery.set("UserId", {
|
partnerQuery.set('UserId', {
|
||||||
__type: "Pointer",
|
__type: 'Pointer',
|
||||||
className: "_User",
|
className: '_User',
|
||||||
objectId: user.id,
|
objectId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
partnerQuery.set("ContactNumber", userDetails.phone);
|
partnerQuery.set('ContactNumber', userDetails.phone);
|
||||||
partnerQuery.set("TenantName", userDetails.name);
|
partnerQuery.set('TenantName', userDetails.name);
|
||||||
partnerQuery.set("EmailAddress", userDetails.email);
|
partnerQuery.set('EmailAddress', userDetails.email);
|
||||||
partnerQuery.set("IsActive", true);
|
partnerQuery.set('IsActive', true);
|
||||||
partnerQuery.set("CreatedBy", {
|
partnerQuery.set('CreatedBy', {
|
||||||
__type: "Pointer",
|
__type: 'Pointer',
|
||||||
className: "_User",
|
className: '_User',
|
||||||
objectId: user.id,
|
objectId: user.id,
|
||||||
});
|
});
|
||||||
if (userDetails && userDetails.pincode) {
|
if (userDetails && userDetails.pincode) {
|
||||||
partnerQuery.set("PinCode", userDetails.pincode);
|
partnerQuery.set('PinCode', userDetails.pincode);
|
||||||
}
|
}
|
||||||
if (userDetails && userDetails.country) {
|
if (userDetails && userDetails.country) {
|
||||||
partnerQuery.set("Country", userDetails.country);
|
partnerQuery.set('Country', userDetails.country);
|
||||||
}
|
}
|
||||||
if (userDetails && userDetails.state) {
|
if (userDetails && userDetails.state) {
|
||||||
partnerQuery.set("State", userDetails.state);
|
partnerQuery.set('State', userDetails.state);
|
||||||
}
|
}
|
||||||
if (userDetails && userDetails.city) {
|
if (userDetails && userDetails.city) {
|
||||||
partnerQuery.set("City", userDetails.city);
|
partnerQuery.set('City', userDetails.city);
|
||||||
}
|
}
|
||||||
if (userDetails && userDetails.address) {
|
if (userDetails && userDetails.address) {
|
||||||
partnerQuery.set("Address", userDetails.address);
|
partnerQuery.set('Address', userDetails.address);
|
||||||
}
|
}
|
||||||
const tenantRes = await partnerQuery.save(null, { useMasterKey: true });
|
const tenantRes = await partnerQuery.save(null, { useMasterKey: true });
|
||||||
// console.log("tenantRes ", tenantRes);
|
// console.log("tenantRes ", tenantRes);
|
||||||
const extCls = Parse.Object.extend(extClass + "_Users");
|
const extCls = Parse.Object.extend(extClass + '_Users');
|
||||||
const newObj = new extCls();
|
const newObj = new extCls();
|
||||||
newObj.set("UserId", {
|
newObj.set('UserId', {
|
||||||
__type: "Pointer",
|
__type: 'Pointer',
|
||||||
className: "_User",
|
className: '_User',
|
||||||
objectId: user.id,
|
objectId: user.id,
|
||||||
});
|
});
|
||||||
newObj.set("UserRole", userDetails.role);
|
newObj.set('UserRole', userDetails.role);
|
||||||
newObj.set("Email", userDetails.email);
|
newObj.set('Email', userDetails.email);
|
||||||
newObj.set("Name", userDetails.name);
|
newObj.set('Name', userDetails.name);
|
||||||
newObj.set("Phone", userDetails.phone);
|
newObj.set('Phone', userDetails.phone);
|
||||||
newObj.set("TenantId", {
|
newObj.set('TenantId', {
|
||||||
__type: "Pointer",
|
__type: 'Pointer',
|
||||||
className: "partners_Tenant",
|
className: 'partners_Tenant',
|
||||||
objectId: tenantRes.id,
|
objectId: tenantRes.id,
|
||||||
});
|
});
|
||||||
if (userDetails && userDetails.company) {
|
if (userDetails && userDetails.company) {
|
||||||
newObj.set("Company", userDetails.company);
|
newObj.set('Company', userDetails.company);
|
||||||
}
|
}
|
||||||
if (userDetails && userDetails.jobTitle) {
|
if (userDetails && userDetails.jobTitle) {
|
||||||
newObj.set("JobTitle", 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);
|
|
||||||
newObj.set("Customer_id", planDetails.customer_id);
|
|
||||||
newObj.set("Subscription_id", planDetails.subscription_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const extRes = await newObj.save(null, { useMasterKey: true });
|
const extRes = await newObj.save(null, { useMasterKey: true });
|
||||||
|
await saveSubscription(extRes.id, user.id, tenantRes.id, subscription);
|
||||||
return { message: "User sign up", sessionToken: user.sessionToken };
|
return { message: 'User sign up', sessionToken: user.sessionToken };
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Err ", err);
|
console.log('Err ', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSubscription(extUserId, UserId, tenantId, subscription) {
|
||||||
|
const SubscriptionId = subscription?.data?.subscription?.subscription_id || '';
|
||||||
|
const Next_billing_date = subscription?.data?.subscription?.next_billing_at || '';
|
||||||
|
const planCode = subscription?.data?.subscription?.plan?.plan_code || '';
|
||||||
|
try {
|
||||||
|
const createSubscription = new Parse.Object('contracts_Subscriptions');
|
||||||
|
createSubscription.set('SubscriptionId', SubscriptionId);
|
||||||
|
createSubscription.set('SubscriptionDetails', subscription);
|
||||||
|
createSubscription.set('ExtUserPtr', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'contracts_Users',
|
||||||
|
objectId: extUserId,
|
||||||
|
});
|
||||||
|
createSubscription.set('CreatedBy', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: '_User',
|
||||||
|
objectId: UserId,
|
||||||
|
});
|
||||||
|
createSubscription.set('TenantId', {
|
||||||
|
__type: 'Pointer',
|
||||||
|
className: 'partners_Tenant',
|
||||||
|
objectId: tenantId,
|
||||||
|
});
|
||||||
|
createSubscription.set('Next_billing_date', new Date(Next_billing_date));
|
||||||
|
createSubscription.set('PlanCode', planCode);
|
||||||
|
await createSubscription.save(null, { useMasterKey: true });
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err in save subscription pgsignup', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Parse} Parse
|
||||||
|
*/
|
||||||
|
exports.up = async Parse => {
|
||||||
|
// TODO: set className here
|
||||||
|
const className = 'contracts_Document';
|
||||||
|
const schema = new Parse.Schema(className);
|
||||||
|
schema.addString('RequestBody');
|
||||||
|
schema.addString('RequestSubject');
|
||||||
|
// TODO: Set the schema here
|
||||||
|
// Example:
|
||||||
|
// schema.addString('name').addNumber('cash');
|
||||||
|
|
||||||
|
return schema.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Parse} Parse
|
||||||
|
*/
|
||||||
|
exports.down = async Parse => {
|
||||||
|
// TODO: set className here
|
||||||
|
const className = 'contracts_Document';
|
||||||
|
const schema = new Parse.Schema(className);
|
||||||
|
schema.deleteField('RequestBody');
|
||||||
|
schema.deleteField('RequestSubject');
|
||||||
|
// TODO: Set the schema here
|
||||||
|
// Example:
|
||||||
|
// schema.deleteField('name').deleteField('cash');
|
||||||
|
|
||||||
|
return schema.update();
|
||||||
|
};
|
||||||
@@ -13,7 +13,7 @@ import http from 'http';
|
|||||||
import formData from 'form-data';
|
import formData from 'form-data';
|
||||||
import Mailgun from 'mailgun.js';
|
import Mailgun from 'mailgun.js';
|
||||||
import { ApiPayloadConverter } from 'parse-server-api-mail-adapter';
|
import { ApiPayloadConverter } from 'parse-server-api-mail-adapter';
|
||||||
import S3Adapter from 'parse-server-s3-adapter';
|
import S3Adapter from '@parse/s3-files-adapter';
|
||||||
import FSFilesAdapter from 'parse-server-fs-adapter';
|
import FSFilesAdapter from 'parse-server-fs-adapter';
|
||||||
import AWS from 'aws-sdk';
|
import AWS from 'aws-sdk';
|
||||||
import { app as customRoute } from './cloud/customRoute/customApp.js';
|
import { app as customRoute } from './cloud/customRoute/customApp.js';
|
||||||
@@ -32,6 +32,8 @@ if (process.env.USE_LOCAL !== 'TRUE') {
|
|||||||
region: process.env.DO_REGION,
|
region: process.env.DO_REGION,
|
||||||
directAccess: true,
|
directAccess: true,
|
||||||
preserveFileName: true,
|
preserveFileName: true,
|
||||||
|
presignedUrl: true,
|
||||||
|
presignedUrlExpires: 900,
|
||||||
s3overrides: {
|
s3overrides: {
|
||||||
accessKeyId: process.env.DO_ACCESS_KEY_ID,
|
accessKeyId: process.env.DO_ACCESS_KEY_ID,
|
||||||
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
|
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
|
||||||
@@ -86,7 +88,9 @@ if (process.env.SMTP_ENABLE) {
|
|||||||
console.log('Please provide valid Mailgun credentials');
|
console.log('Please provide valid Mailgun credentials');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const mailsender = process.env.SMTP_ENABLE
|
||||||
|
? process.env.SMTP_USER_EMAIL
|
||||||
|
: process.env.MAILGUN_SENDER;
|
||||||
export const config = {
|
export const config = {
|
||||||
databaseURI:
|
databaseURI:
|
||||||
process.env.DATABASE_URI || process.env.MONGODB_URI || 'mongodb://localhost:27017/dev',
|
process.env.DATABASE_URI || process.env.MONGODB_URI || 'mongodb://localhost:27017/dev',
|
||||||
@@ -102,7 +106,7 @@ export const config = {
|
|||||||
verifyUserEmails: isMailAdapter === true ? true : false,
|
verifyUserEmails: isMailAdapter === true ? true : false,
|
||||||
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
|
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.
|
// Your apps name. This will appear in the subject and body of the emails that are sent.
|
||||||
appName: 'Open Sign',
|
appName: 'Opensign',
|
||||||
allowClientClassCreation: false,
|
allowClientClassCreation: false,
|
||||||
allowExpiredAuthDataToken: false,
|
allowExpiredAuthDataToken: false,
|
||||||
encodeParseObjectInCloudFunction: true,
|
encodeParseObjectInCloudFunction: true,
|
||||||
@@ -112,9 +116,7 @@ export const config = {
|
|||||||
module: 'parse-server-api-mail-adapter',
|
module: 'parse-server-api-mail-adapter',
|
||||||
options: {
|
options: {
|
||||||
// The email address from which emails are sent.
|
// The email address from which emails are sent.
|
||||||
sender: process.env.SMTP_ENABLE
|
sender: 'Opensign™' + ' <' + mailsender + '>',
|
||||||
? process.env.SMTP_USER_EMAIL
|
|
||||||
: process.env.MAILGUN_SENDER,
|
|
||||||
// The email templates.
|
// The email templates.
|
||||||
templates: {
|
templates: {
|
||||||
// The template used by Parse Server to send an email for password
|
// The template used by Parse Server to send an email for password
|
||||||
@@ -147,6 +149,14 @@ export const config = {
|
|||||||
google: {
|
google: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
ldap: {
|
||||||
|
enabled: true,
|
||||||
|
url: 'ldap://ldap.forumsys.com:389',
|
||||||
|
suffix: 'dc=example,dc=com',
|
||||||
|
// dn: 'ou=mathematicians, dc=example, dc=com',
|
||||||
|
groupCn: 'mathematicians',
|
||||||
|
groupFilter: '(&(uniqueMember=uid=,dc=example,dc=com)(objectClass=groupOfUniqueNames))',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
|
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Generated
+64
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@parse/s3-files-adapter": "^2.2.0",
|
||||||
"aws-sdk": "^2.1581.0",
|
"aws-sdk": "^2.1581.0",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
@@ -2560,6 +2561,69 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-y+d7+AvmRUrROe4kJOF8128yUSxieM53vXQsSaG2gvY9VgPScfpfho0pE7VZ5mLumzxJjmwW6oufiGdgcjgcTA==",
|
||||||
|
"dependencies": {
|
||||||
|
"aws-sdk": "2.1363.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter/node_modules/aws-sdk": {
|
||||||
|
"version": "2.1363.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1363.0.tgz",
|
||||||
|
"integrity": "sha512-M2MZZXehgi/EMQv5GlzRkn3TlhoOYHg2cYdSAAqhjv67WaEG50MjaQy5vRvfN1i8XvB24aJFJ5pCrx69TaCaIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "4.9.2",
|
||||||
|
"events": "1.1.1",
|
||||||
|
"ieee754": "1.1.13",
|
||||||
|
"jmespath": "0.16.0",
|
||||||
|
"querystring": "0.2.0",
|
||||||
|
"sax": "1.2.1",
|
||||||
|
"url": "0.10.3",
|
||||||
|
"util": "^0.12.4",
|
||||||
|
"uuid": "8.0.0",
|
||||||
|
"xml2js": "0.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter/node_modules/buffer": {
|
||||||
|
"version": "4.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
||||||
|
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.0.2",
|
||||||
|
"ieee754": "^1.1.4",
|
||||||
|
"isarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter/node_modules/ieee754": {
|
||||||
|
"version": "1.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
||||||
|
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
||||||
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter/node_modules/uuid": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parse/s3-files-adapter/node_modules/xml2js": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": ">=0.6.0",
|
||||||
|
"xmlbuilder": "~11.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pdf-lib/standard-fonts": {
|
"node_modules/@pdf-lib/standard-fonts": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user