Compare commits

...
294 Commits
Author SHA1 Message Date
prafull-opensignlabsandGitHub acd1c589d7 update pdf worker url 2024-06-16 12:59:34 +05:30
prafull-opensignlabsandGitHub de62052453 refactor: load pdf worker from local using fetch method 2024-06-16 01:01:05 +05:30
prafull-opensignlabsandGitHub de120dae39 fix: update pdf worker import path 2024-06-16 00:03:48 +05:30
AmolandGitHub 08d1e9a360 Merge pull request #848 from OpenSignLabs/resolve_stage 2024-06-15 23:16:00 +05:30
prafull-opensignlabs 74a9d08550 style: update design of invalid session popup 2024-06-15 23:14:59 +05:30
AmolandGitHub 6fc86e026b Merge pull request #847 from OpenSignLabs/revert-846-revert-845-main
Revert "Safari issue patch "
2024-06-15 22:46:38 +05:30
AmolandGitHub 72da56a916 Revert "Revert "Safari issue patch "" 2024-06-15 22:45:55 +05:30
AmolandGitHub 4ba7ffbb1a Merge pull request #846 from OpenSignLabs/revert-845-main
Revert "Safari issue patch "
2024-06-15 22:44:59 +05:30
AmolandGitHub 0d9a0b8bb1 Revert "Safari issue patch " 2024-06-15 22:44:05 +05:30
AmolandGitHub 084aa69702 Merge pull request #845 from OpenSignLabs/main
Safari issue patch
2024-06-15 22:39:36 +05:30
AmolandGitHub 597635800f Merge branch 'staging' into main 2024-06-15 22:38:52 +05:30
AmolandGitHub 8da2c7fad4 Merge pull request #844 from OpenSignLabs/fix_withresolver 2024-06-15 22:33:49 +05:30
prafull-opensignlabs 2b0276ead9 fix: Promise.withResolvers is not function 2024-06-15 22:28:21 +05:30
AmolandGitHub 45a96ece54 Merge pull request #843 from OpenSignLabs/resolve_stage 2024-06-14 21:11:50 +05:30
prafull-opensignlabs 729d19dfd3 style: update css and add email sent gif 2024-06-14 20:47:18 +05:30
AmolandGitHub 29aa123669 Merge pull request #842 from OpenSignLabs/resolve_stage
fix: showing blank screen when try to send document
2024-06-14 19:14:18 +05:30
prafull-opensignlabs f69caf016a fix: showing blank screen when try to send document 2024-06-14 19:13:07 +05:30
AmolandGitHub 48e0e0ee15 fix: change docker branch to main 2024-06-14 18:16:15 +05:30
AmolandGitHub a71278f95c Merge pull request #840 from OpenSignLabs/resolve_stage 2024-06-14 18:07:24 +05:30
prafull-opensignlabs f7bb11ede1 style: update loader and ui design of components 2024-06-14 18:05:10 +05:30
prafull-opensignlabs 6a365f7734 style: update widget detail popups 2024-06-13 20:21:25 +05:30
prafull-opensignlabs e4d946e519 style: update UI of signyourself, edit document, request signature 2024-06-13 19:29:23 +05:30
prafull-opensignlabs 149a16f150 style: update design of template ui 2024-06-13 13:27:06 +05:30
prafull-opensignlabs d8ff3d9faa refactor: resolve eslint warning 2024-06-12 18:41:03 +05:30
prafull-opensignlabs fe34001e42 style: change default theme and ui changes in components 2024-06-12 17:28:03 +05:30
prafull-opensignlabs fcdd7e2758 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into resolve_stage 2024-06-12 17:05:21 +05:30
AndrewandGitHub 025c30b685 Merge pull request #836 from OpenSignLabs/fix_smtp
Fix: smtp is not working
2024-06-12 16:58:42 +05:30
prafull-opensignlabs e742e85f0e Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into fix_smtp 2024-06-12 16:58:21 +05:30
prafull-opensignlabs 476a99feae fix: smtpsecure is not defined 2024-06-12 16:56:28 +05:30
prafull-opensignlabs 29464585b8 fix: SMTP setup is not working 2024-06-12 16:54:09 +05:30
prafull-opensignlabs cdd078699b Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into resolve_stage 2024-06-12 11:15:00 +05:30
AmolandGitHub 9ef1e22fda Merge pull request #835 from OpenSignLabs/fix_linkcontact 2024-06-12 11:11:40 +05:30
prafull-opensignlabsandGitHub 655401e04b "Fix: Third contact is not receiving mail when second contact is non-existent." 2024-06-12 11:10:25 +05:30
prafull-opensignlabs b550c07ca8 style: change ui design of popups 2024-06-11 18:33:47 +05:30
prafull-opensignlabsandGitHub fd72094b8a Merge pull request #833 from OpenSignLabs/staging
fix: Ensure real-time updates to records in reports after actions are performed
2024-06-11 11:40:42 +05:30
AmolandGitHub 4d7348abc2 Merge pull request #832 from OpenSignLabs/fix_actions 2024-06-11 11:34:58 +05:30
prafull-opensignlabsandGitHub ec68479e98 fix: Ensure real-time updates to records in reports after actions are performed 2024-06-11 11:32:37 +05:30
prafull-opensignlabs ac05942e58 Merge branch 'feat_dasyui' of https://github.com/OpenSignLabs/OpenSign into resolve_stage 2024-06-11 11:11:25 +05:30
prafull-opensignlabsandGitHub b387b6b402 Merge pull request #829 from Zathiel/staging
build(deps): minor update
2024-06-11 10:01:54 +05:30
ZathielandGitHub e13baeb2fc Merge pull request #20 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/babel/runtime-corejs2-7.24.7
build(deps-dev): bump @babel/runtime-corejs2 from 7.24.6 to 7.24.7 in /apps/OpenSign
2024-06-11 00:32:07 +02:00
ZathielandGitHub 52eb8e4a68 Merge pull request #15 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/babel/eslint-parser-7.24.7
build(deps-dev): bump @babel/eslint-parser from 7.24.6 to 7.24.7 in /apps/OpenSignServer
2024-06-11 00:31:19 +02:00
ZathielandGitHub 71189783a8 Merge pull request #18 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/nodemon-3.1.3
build(deps-dev): bump nodemon from 3.1.1 to 3.1.3 in /apps/OpenSignServer
2024-06-11 00:30:31 +02:00
ZathielandGitHub aec9396524 Merge pull request #21 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/tailwindcss-3.4.4
build(deps-dev): bump tailwindcss from 3.4.3 to 3.4.4 in /apps/OpenSign
2024-06-11 00:29:36 +02:00
ZathielandGitHub d74390b974 Merge pull request #23 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/braces-3.0.3
build(deps): bump braces from 3.0.2 to 3.0.3 in /apps/OpenSignServer
2024-06-11 00:29:03 +02:00
ZathielandGitHub 998fe013c8 Merge pull request #24 from Zathiel/dependabot/npm_and_yarn/braces-3.0.3
build(deps-dev): bump braces from 3.0.2 to 3.0.3
2024-06-11 00:28:48 +02:00
dependabot[bot]andGitHub 06d4c9aeaf build(deps-dev): bump nodemon in /apps/OpenSignServer
Bumps [nodemon](https://github.com/remy/nodemon) from 3.1.1 to 3.1.3.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v3.1.1...v3.1.3)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 22:27:44 +00:00
dependabot[bot]andGitHub bc77a9b0a1 build(deps-dev): bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 22:27:19 +00:00
dependabot[bot]andGitHub 07c0390401 build(deps): bump braces from 3.0.2 to 3.0.3 in /apps/OpenSignServer
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 22:27:00 +00:00
ZathielandGitHub c50d753d74 Merge pull request #22 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/grpc/grpc-js-1.10.9
build(deps): bump @grpc/grpc-js from 1.10.8 to 1.10.9 in /apps/OpenSignServer
2024-06-11 00:26:56 +02:00
dependabot[bot]andGitHub 65eef5739d build(deps): bump @grpc/grpc-js in /apps/OpenSignServer
Bumps [@grpc/grpc-js](https://github.com/grpc/grpc-node) from 1.10.8 to 1.10.9.
- [Release notes](https://github.com/grpc/grpc-node/releases)
- [Commits](https://github.com/grpc/grpc-node/compare/@grpc/grpc-js@1.10.8...@grpc/grpc-js@1.10.9)

---
updated-dependencies:
- dependency-name: "@grpc/grpc-js"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 22:22:20 +00:00
dependabot[bot]andGitHub 01eed3664b build(deps-dev): bump tailwindcss from 3.4.3 to 3.4.4 in /apps/OpenSign
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.3 to 3.4.4.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.4/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.3...v3.4.4)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 16:00:42 +00:00
dependabot[bot]andGitHub 685e09d406 build(deps-dev): bump @babel/runtime-corejs2 in /apps/OpenSign
Bumps [@babel/runtime-corejs2](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs2) from 7.24.6 to 7.24.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.7/packages/babel-runtime-corejs2)

---
updated-dependencies:
- dependency-name: "@babel/runtime-corejs2"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 16:00:25 +00:00
dependabot[bot]andGitHub 7bacca1f78 build(deps-dev): bump @babel/eslint-parser in /apps/OpenSignServer
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.24.6 to 7.24.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.7/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 15:51:30 +00:00
prafull-opensignlabsandGitHub 3764ab5c30 Merge pull request #827 from OpenSignLabs/resolve_main
fix: conflict resolve
2024-06-10 20:40:07 +05:30
RaktimaNXG 2f7a1d67b6 fix: conflict resolve 2024-06-10 20:38:42 +05:30
prafull-opensignlabs 8726efb0aa style: updated buttons from report and signers input box 2024-06-10 20:37:21 +05:30
prafull-opensignlabsandGitHub e073e83ad6 Merge pull request #824 from OpenSignLabs/raktima-opensignlabs-patch-9
fix: a mismatch permits a signer placeholder to sign any placeholder not allocated to that signer issue in the quick send flow.
2024-06-10 18:42:08 +05:30
RaktimaNXG 69140d2139 fix: a mismatch permits a signer placeholder to sign any placeholder not allocated to that signer issue in the quick send flow. 2024-06-10 18:14:28 +05:30
prafull-opensignlabs aeed48c0ef style: change ui design of login, signup, forgetpassword page 2024-06-10 15:51:52 +05:30
prafull-opensignlabs 1f9504b9cc style: change default theme emerald to cupcake 2024-06-10 15:01:16 +05:30
prafull-opensignlabsandGitHub 5518d6932e Merge pull request #823 from OpenSignLabs/raktima-opensignlabs-patch-9
fix: second non existing signer is not receiving the signature request email in the quick-send process.
2024-06-10 12:19:49 +05:30
RaktimaNXG f14e301b6c fix: change condition of email send 2024-06-10 12:15:48 +05:30
RaktimaNXG 901ddf35bb remove console 2024-06-10 11:43:56 +05:30
RaktimaNXG 9aa3166528 fix: second signer is not receiving the signature request email in the quick-send process. 2024-06-10 11:24:35 +05:30
prafull-opensignlabsandGitHub a90e679228 Merge pull request #813 from OpenSignLabs/raktima-opensignlabs-patch-9
fix: display the list of unsigned signers in the 'Yet to Sign' panel using the QuickSend flow.
2024-06-07 20:16:34 +05:30
RaktimaNXG 90b5e3c860 fix: exist contact not recieving maiin in quick send flow 2024-06-07 19:55:40 +05:30
RaktimaNXG 74f6612271 refactor code 2024-06-07 19:33:28 +05:30
prafull-opensignlabs 2862a97c4e feat: implement daisy-ui in alert, report, drive 2024-06-07 19:32:00 +05:30
RaktimaNXG 5c3f967128 fix: add validation of signature widgetat in quick send flow, update SentToOthers field when document is in inProgress , resolve resend nonexist email issue 2024-06-07 19:07:56 +05:30
prafull-opensignlabs 6fde71e947 feat: implement daisy-ui in all pages 2024-06-07 14:24:15 +05:30
RaktimaNXG 2900464272 fix: display the list of unsigned signers in the 'Yet to Sign' panel using the QuickSend flow. 2024-06-07 14:20:36 +05:30
prafull-opensignlabs 10bac3c11f refactor: change prefix of daisy-ui theme classes 2024-06-07 11:19:08 +05:30
AmolandGitHub 302f38d472 Merge pull request #808 from OpenSignLabs/autoreminder 2024-06-06 19:36:19 +05:30
prafull-opensignlabs 8ecdbc43a3 feat: implement daisy ui in forms 2024-06-06 18:36:31 +05:30
prafull-opensignlabs 6721b334cf refactor: remove unncessary code from dashboard & css changes in sidebar 2024-06-06 14:38:08 +05:30
prafull-opensignlabs 454f557d14 fix: position of cards and reports in dashboard 2024-06-06 11:49:06 +05:30
prafull-opensignlabs 635693b394 fix: position of cards and reports 2024-06-06 11:48:06 +05:30
prafull-opensignlabsandGitHub 0be1816046 Merge pull request #801 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemon-3.1.2
build(deps-dev): bump nodemon from 3.1.1 to 3.1.2 in /apps/OpenSignServer
2024-06-06 11:09:30 +05:30
prafull-opensignlabsandGitHub feb162e03e Merge pull request #809 from Zathiel/staging
build(deps) : react-rnd && mongoose
2024-06-06 11:06:42 +05:30
prafull-opensignlabs c8801846fa feat: implement daisy ui in dashboard 2024-06-05 20:23:50 +05:30
ZathielandGitHub a793fc3722 Merge pull request #1 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/react-rnd-10.4.11
build(deps): bump react-rnd from 10.4.10 to 10.4.11 in /apps/OpenSign
2024-06-05 14:26:30 +02:00
ZathielandGitHub ffdabe4a00 Merge pull request #13 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.4.1
build(deps): bump mongoose from 8.4.0 to 8.4.1 in /apps/OpenSignServer
2024-06-05 14:25:43 +02:00
prafull-opensignlabs 5536c99052 feat: implement daisy-ui in sidebar 2024-06-05 17:35:31 +05:30
prafull-opensignlabsandGitHub ba1c3145f3 fix: mail and document count in autoreminder API is not correct 2024-06-05 13:49:20 +05:30
prafull-opensignlabs 0fbe6aeb6c feat: implement dasyui in header, footer & report 2024-06-04 19:38:41 +05:30
AmolandGitHub 4898c4a851 Merge pull request #807 from OpenSignLabs/feat_sso 2024-06-04 10:06:34 +05:30
prafull-opensignlabs 85aa6b2947 fix: update sso url 2024-06-04 10:03:30 +05:30
AmolandGitHub 3b02d2bcdb fix: update SSO url 2024-06-04 01:01:52 +05:30
dependabot[bot]andGitHub ed01f4a7a0 build(deps): bump mongoose from 8.4.0 to 8.4.1 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.4.0 to 8.4.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.4.0...8.4.1)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 15:38:51 +00:00
AmolandGitHub 1f395cf25f Merge pull request #806 from OpenSignLabs/feat_sso 2024-06-03 18:52:09 +05:30
prafull-opensignlabs cf98e73d13 fix: freeze sign in with sso button after click 2024-06-03 18:50:38 +05:30
AmolandGitHub 10112ac20d Merge pull request #805 from OpenSignLabs/feat_sso 2024-06-03 18:28:12 +05:30
prafull-opensignlabs 9a0183274f fix: Set send_email to false to stop receiving mails through API 2024-06-03 18:27:17 +05:30
AmolandGitHub 6b2e16c21d Merge pull request #804 from OpenSignLabs/feat_sso 2024-06-03 15:49:45 +05:30
prafull-opensignlabs 3c51baf1c9 build(deps): updated nth-check dependency for security 2024-06-03 15:46:24 +05:30
dependabot[bot]andGitHub 3f4be1c4f3 build(deps): bump react-rnd from 10.4.10 to 10.4.11 in /apps/OpenSign
Bumps [react-rnd](https://github.com/bokuweb/react-rnd) from 10.4.10 to 10.4.11.
- [Release notes](https://github.com/bokuweb/react-rnd/releases)
- [Commits](https://github.com/bokuweb/react-rnd/commits)

---
updated-dependencies:
- dependency-name: react-rnd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 09:15:34 +00:00
AmolandGitHub 62b36f58f7 Merge pull request #803 from OpenSignLabs/feat_sso 2024-06-03 14:00:27 +05:30
prafull-opensignlabs ba3591c7bc fix: enable mail send feature for non-quick send documents when sendinorder is true 2024-06-03 13:51:15 +05:30
dependabot[bot]andGitHub 1ec11b8733 build(deps-dev): bump nodemon in /apps/OpenSignServer
Bumps [nodemon](https://github.com/remy/nodemon) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v3.1.1...v3.1.2)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 07:16:39 +00:00
prafull-opensignlabsandGitHub ab89d3b71f Merge pull request #799 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/prettier-3.3.0
build(deps-dev): bump prettier from 3.2.5 to 3.3.0 in /apps/OpenSignServer
2024-06-03 12:45:41 +05:30
prafull-opensignlabsandGitHub 1811173648 Merge pull request #796 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/reactour-1.19.4
build(deps): bump reactour from 1.19.3 to 1.19.4 in /apps/OpenSign
2024-06-03 12:44:34 +05:30
AmolandGitHub b218e96107 Merge pull request #802 from OpenSignLabs/fix_email 2024-06-03 12:39:24 +05:30
prafull-opensignlabs 64a0be8776 fix: cannot read property of undefined 'email' 2024-06-03 12:38:17 +05:30
dependabot[bot]andGitHub 414e2d819c build(deps-dev): bump prettier in /apps/OpenSignServer
Bumps [prettier](https://github.com/prettier/prettier) from 3.2.5 to 3.3.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.5...3.3.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 01:11:29 +00:00
dependabot[bot]andGitHub 0769101f28 build(deps): bump reactour from 1.19.3 to 1.19.4 in /apps/OpenSign
Bumps [reactour](https://github.com/elrumordelaluz/reactour) from 1.19.3 to 1.19.4.
- [Release notes](https://github.com/elrumordelaluz/reactour/releases)
- [Commits](https://github.com/elrumordelaluz/reactour/commits)

---
updated-dependencies:
- dependency-name: reactour
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 00:25:47 +00:00
AmolandGitHub 5dc86119d3 Merge pull request #794 from OpenSignLabs/feat_sso 2024-05-31 19:28:52 +05:30
prafull-opensignlabs 4999dc2b18 Fix: password field is not visible for non-sso user 2024-05-31 19:27:18 +05:30
AmolandGitHub 962d36c088 Merge pull request #793 from OpenSignLabs/feat_sso 2024-05-31 19:02:40 +05:30
prafull-opensignlabs d071986aac feat: hide password input for sso and restict sso 2024-05-31 19:00:29 +05:30
prafull-opensignlabs afb4de9d0c Feat: create SSO user account on platform 2024-05-31 18:22:16 +05:30
prafull-opensignlabs bc5c8cac33 feat: existing user can sign in with sso 2024-05-31 11:41:53 +05:30
prafull-opensignlabsandGitHub be93e6a214 Merge pull request #777 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/runtime-corejs2-7.24.6
build(deps-dev): bump @babel/runtime-corejs2 from 7.24.5 to 7.24.6 in /apps/OpenSign
2024-05-31 10:40:37 +05:30
prafull-opensignlabsandGitHub 37748057e3 Merge pull request #791 from OpenSignLabs/public_url
fix: incorrect condition implementation for setting template as public based on isEnableSubscription
2024-05-30 18:10:34 +05:30
RaktimaNXG eb3bb77692 fix: incorrect condition implementation for setting template as public based on isEnableSubscription 2024-05-30 18:08:54 +05:30
prafull-opensignlabsandGitHub df0ce3f086 Merge pull request #788 from OpenSignLabs/public_url
feat: create public profile URLs to add username and develop functionality to make public template from report
2024-05-30 17:53:07 +05:30
AmolandGitHub 0a99b5181e Merge pull request #790 from OpenSignLabs/feat_bulksend 2024-05-30 17:37:45 +05:30
prafull-opensignlabs 8a5d3a0368 Fix: not able to create contract from add user icon in PDF UI 2024-05-30 17:35:40 +05:30
RaktimaNXG c00406e401 fix: template list status issue on pagination 2024-05-30 17:24:33 +05:30
RaktimaNXG aeead23c86 fix: change public profile url 2024-05-30 15:57:16 +05:30
RaktimaNXG 83fe88911f fix: public toggle issue,cloud function error handling 2024-05-30 15:55:16 +05:30
prafull-opensignlabsandGitHub 527bca32d2 Merge pull request #789 from Zathiel/staging
FIX : update USE_LOCAL variable
2024-05-30 15:14:09 +05:30
ZathielandGitHub 9bf4940c2e Merge branch 'OpenSignLabs:staging' into staging 2024-05-30 10:46:55 +02:00
ZathielandGitHub a653df6935 FIX : USE_LOCAL variable 2024-05-30 01:45:05 +02:00
RaktimaNXG dfc6da388c fix: add comment 2024-05-29 19:44:17 +05:30
RaktimaNXG 3e2c822bbc fix: handle condition to save username 2024-05-29 19:39:27 +05:30
RaktimaandGitHub 1a20841a94 Merge branch 'staging' into public_url 2024-05-29 19:31:17 +05:30
RaktimaNXG c6be81923b fix: conflict resolved in userProfile 2024-05-29 19:24:04 +05:30
RaktimaNXG 6b47f6a27b fix: add comment 2024-05-29 18:56:17 +05:30
RaktimaNXG 33b0111ed0 fix: remove console 2024-05-29 18:43:24 +05:30
RaktimaNXG 48fd9e52b3 fix: update isEnableSuscription variable nname 2024-05-29 18:20:16 +05:30
RaktimaNXG d85074b127 fix: username issue to get details from GetPublicUserNmae cloud function 2024-05-29 18:17:07 +05:30
AmolandGitHub 5ada9a411b Merge pull request #787 from OpenSignLabs/feat_bulksend 2024-05-29 17:56:43 +05:30
prafull-opensignlabs 6f50de1ef1 fix: make phone field optional for contact 2024-05-29 17:55:22 +05:30
AmolandGitHub 612150cf4b Merge pull request #786 from OpenSignLabs/feat_bulksend 2024-05-29 16:59:49 +05:30
prafull-opensignlabs 634db83e8e fix: duplicate contact are creatable, Update the the header 'Document signed' in the success message popup 2024-05-29 16:58:35 +05:30
RaktimaNXG b32c8068ef fix: merge changes from staging 2024-05-29 16:07:05 +05:30
RaktimaNXG ae464274b0 fix: update ReportJson file 2024-05-29 15:55:07 +05:30
AmolandGitHub c5ceba8d57 Merge pull request #785 from OpenSignLabs/feat_bulksend
fix: issue of something went wrong due to quick send
2024-05-29 13:56:05 +05:30
prafull-opensignlabs 903d626c27 fix: issue of something went wrong due to quick send 2024-05-29 13:05:57 +05:30
prafull-opensignlabsandGitHub e5b4fb123f Merge pull request #782 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemon-3.1.1
build(deps-dev): bump nodemon from 3.1.0 to 3.1.1 in /apps/OpenSignServer
2024-05-28 20:21:00 +05:30
prafull-opensignlabsandGitHub 116893c1b4 Merge pull request #781 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/babel/eslint-parser-7.24.6
build(deps-dev): bump @babel/eslint-parser from 7.24.5 to 7.24.6 in /apps/OpenSignServer
2024-05-28 20:20:36 +05:30
prafull-opensignlabsandGitHub 592254a9a3 Merge pull request #778 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lint-staged-15.2.5
build(deps-dev): bump lint-staged from 15.2.4 to 15.2.5 in /apps/OpenSign
2024-05-28 20:20:19 +05:30
AmolandGitHub f52c6e24fe Merge pull request #784 from OpenSignLabs/feat_bulksend 2024-05-28 19:23:50 +05:30
prafull-opensignlabs 70ae1e24fc fix: merge conflict 2024-05-28 19:18:41 +05:30
prafull-opensignlabs c491595fc8 Fix: issues in quick send 2024-05-28 18:56:56 +05:30
AmolandGitHub 6875135ede Merge pull request #783 from OpenSignLabs/feat_bulksend
Fix: issues in quick send
2024-05-28 10:42:33 +05:30
RaktimaNXG 662049d878 fix: remove console 2024-05-28 09:50:38 +05:30
RaktimaNXG 1764d7f9ba feat: create public profile URLs for users and develop functionality to make the report template public 2024-05-27 21:08:05 +05:30
prafull-opensignlabs 07933b56b1 Fix: issue of 'something went wrong' err in guest login flow when using quick send 2024-05-27 20:53:38 +05:30
prafull-opensignlabs f6ba4db62d Fix: Role, type are not visible on placeholder for non-exist contact 2024-05-27 20:06:06 +05:30
prafull-opensignlabs 5bd36f91d9 Fix: issue with multiple linking user in quick send 2024-05-27 18:46:37 +05:30
prafull-opensignlabs c199c3019e feat: add message for all signers linked in template for quick send 2024-05-27 14:50:17 +05:30
prafull-opensignlabs facbc8e76e Fix: issue of showing 'Please add Signers or Roles in template' even when roles are already exist in quick send 2024-05-27 12:59:43 +05:30
prafull-opensignlabs c3c6f6bab3 fix: send mail only first signer if sendinorder, takeout quick send btn from 3 dots 2024-05-27 11:59:25 +05:30
prafull-opensignlabsandGitHub f5e216fedc Merge pull request #768 from OpenSignLabs/raktima-opensignlabs-patch-8
feat: add download, certificate & print buttons on the document completion popup
2024-05-27 10:40:31 +05:30
RaktimaandGitHub c40a923388 Merge branch 'staging' into raktima-opensignlabs-patch-8 2024-05-27 10:30:38 +05:30
dependabot[bot]andGitHub a86f4fd9b7 build(deps-dev): bump nodemon in /apps/OpenSignServer
Bumps [nodemon](https://github.com/remy/nodemon) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 00:27:27 +00:00
dependabot[bot]andGitHub 59f6d022cf build(deps-dev): bump @babel/eslint-parser in /apps/OpenSignServer
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.24.5 to 7.24.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.6/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 00:27:04 +00:00
dependabot[bot]andGitHub b7beeee260 build(deps-dev): bump lint-staged in /apps/OpenSign
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 15.2.4 to 15.2.5.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md)
- [Commits](https://github.com/okonet/lint-staged/compare/v15.2.4...v15.2.5)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 00:14:13 +00:00
dependabot[bot]andGitHub 31c861cbe4 build(deps-dev): bump @babel/runtime-corejs2 in /apps/OpenSign
Bumps [@babel/runtime-corejs2](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs2) from 7.24.5 to 7.24.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.6/packages/babel-runtime-corejs2)

---
updated-dependencies:
- dependency-name: "@babel/runtime-corejs2"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 00:13:57 +00:00
AmolandGitHub 6a9408b7b4 docs: add Zathiel as a contributor for security 2024-05-24 19:24:52 +05:30
AmolandGitHub a9fd264a01 Merge pull request #772 from OpenSignLabs/feat_bulksend
Feat: quick send feature to create & send multiple documents at a time
2024-05-24 16:42:08 +05:30
prafull-opensignlabs 6c77bbfe75 feat: quick send feature to create & send multiple documents at a time 2024-05-24 16:29:03 +05:30
prafull-opensignlabs 890c3d2b1f Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into feat_bulksend 2024-05-24 11:34:58 +05:30
AmolandGitHub 3ede441f54 Merge pull request #771 from OpenSignLabs/staging
v1.7.4
2024-05-24 10:29:10 +05:30
AmolandGitHub 2433ad5957 Merge pull request #770 from OpenSignLabs/build_dep 2024-05-24 10:23:10 +05:30
prafull-opensignlabs fffd907d63 Fix: handle owner subscription has expired error in guest login 2024-05-24 10:13:34 +05:30
AmolandGitHub 51edc339cd Merge pull request #769 from OpenSignLabs/staging
v1.7.3
2024-05-23 18:22:49 +05:30
AmolandGitHub bf307abe9a Update plansArr.js 2024-05-23 18:17:00 +05:30
RaktimaNXG 08a97707b7 fix: completion popup design issue in tablet view 2024-05-23 13:46:17 +05:30
RaktimaNXG d99fecd46e feat: add download, certificate & print buttons on the document completion popup 2024-05-23 12:52:10 +05:30
prafull-opensignlabsandGitHub 6c59c0ec9a Merge pull request #767 from OpenSignLabs/raktima-opensignlabs-patch-8
feat: add help button for text validation
2024-05-23 10:35:45 +05:30
RaktimaNXG 32c75d1fc3 feat: add help button for text validation 2024-05-23 10:30:41 +05:30
AmolandGitHub 7f0f81c334 Merge pull request #766 from OpenSignLabs/build_dep
fix: issue in guestlogin of owner subscription has expired
2024-05-22 19:59:23 +05:30
prafull-opensignlabsandGitHub a882f07f57 Merge pull request #765 from OpenSignLabs/tour_message_requestsign
fix: download menu is not wokring inProgress report in mobile view
2024-05-22 19:58:21 +05:30
prafull-opensignlabs 74b81a5363 fix: issue in guestlogin of owner subscription has expired 2024-05-22 19:56:44 +05:30
AmolandGitHub 9b75764717 Merge pull request #764 from OpenSignLabs/build_dep
fix: resend mail not working, create contact API not working
2024-05-22 19:47:11 +05:30
RaktimaNXG c1468112b0 fix: download menu is not wokring inProgress report in mobile view 2024-05-22 19:46:22 +05:30
prafull-opensignlabs 950b74789c fix: create contact API not working 2024-05-22 19:46:09 +05:30
prafull-opensignlabs 7e4f12e41a feat: bulk send is working for exist contact 2024-05-22 19:31:32 +05:30
prafull-opensignlabs d75c1d7c0c fix: resend mail not working 2024-05-22 19:19:33 +05:30
prafull-opensignlabsandGitHub 7eacbedf59 Merge pull request #763 from OpenSignLabs/tour_message_requestsign
feat: add tour messages to request signatures flow
2024-05-22 19:02:12 +05:30
RaktimaNXG 2e5947279f fix:onclick upgrade button navigate user to new window 2024-05-22 18:51:57 +05:30
RaktimaNXG ef5ac7d626 fix: err is not defined 2024-05-22 17:49:24 +05:30
RaktimaNXG 658c37cc4d feat: add tour messages to request signatures flow 2024-05-22 17:48:15 +05:30
prafull-opensignlabs ffc8e4b23e Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into feat_bulksend 2024-05-22 13:44:14 +05:30
prafull-opensignlabsandGitHub 3fb96fc792 Merge pull request #762 from OpenSignLabs/build_dep
build(deps): update dependencies
2024-05-22 12:55:31 +05:30
prafull-opensignlabs 71016ba5e0 build(deps): update dependecies 2024-05-22 12:46:34 +05:30
prafull-opensignlabs cd1a6fdaf6 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into feat_bulksend 2024-05-22 12:11:46 +05:30
prafull-opensignlabsandGitHub c2afeed448 Merge pull request #760 from OpenSignLabs/raktima-opensignlabs-patch-7
fix: unnecessary emails are sent when a signers sign a document via a shared link.
2024-05-22 11:24:15 +05:30
RaktimaNXG 37fd7bbeda fix: update migration script add SendCompletionMail filed in contracts_Document class 2024-05-22 11:22:35 +05:30
RaktimaNXG 71fbde0099 fix: add migration script to add new filed SendMail and handle email sent using share link from inProgress report 2024-05-22 09:50:12 +05:30
prafull-opensignlabs ca6cb60d78 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into feat_bulksend 2024-05-22 09:49:51 +05:30
prafull-opensignlabsandGitHub df1c0ea66c Merge pull request #761 from Zathiel/staging
build(deps): react-redux, autoprefixer , react-datepicker axios, @reduxjs/toolkit, react-tooltip, tailwindcss react-pdf
2024-05-22 09:45:54 +05:30
Zathiel 46279efc2c build(deps): react-redux, autoprefixer , react-datepicker axios, @reduxjs/toolkit, react-tooltip, tailwindcss react-pdf 2024-05-21 15:29:38 +00:00
prafull-opensignlabs aca2848406 add Ui for bulk send, changes in reportjson 2024-05-21 20:26:46 +05:30
prafull-opensignlabsandGitHub eaec3cf607 Merge pull request #750 from Zathiel/staging
build(deps): update @reduxjs/toolkit package
2024-05-21 20:00:00 +05:30
ZathielandGitHub ad25d73f26 Merge branch 'OpenSignLabs:staging' into staging 2024-05-21 16:19:31 +02:00
RaktimaNXG 481b9ac1e0 fix: add send mail false using share link from inprogress report 2024-05-21 17:36:41 +05:30
AmolandGitHub 4cd3791feb Merge pull request #759 from OpenSignLabs/feat_resendmail 2024-05-21 15:18:10 +05:30
RaktimaNXG 7de8699437 fix: unnecessary emails are sent when a user signs a document via a shared link. 2024-05-21 15:08:40 +05:30
prafull-opensignlabsandGitHub 4c162676b1 Merge pull request #753 from OpenSignLabs/raktima-opensignlabs-patch-7
feat:  celebration confetti on document completion
2024-05-21 14:02:28 +05:30
prafull-opensignlabs ca390bdfa6 refactor: remove Signpdf file 2024-05-21 13:56:37 +05:30
prafull-opensignlabs 22d064fd38 build(dep): update node-signpdf pacakge and it's dependencies, remove customsignpdf folder 2024-05-21 13:49:10 +05:30
AmolandGitHub 444c9bbfdf Merge pull request #756 from OpenSignLabs/feat_resendmail 2024-05-21 13:44:07 +05:30
prafull-opensignlabs b289686d42 build(dep): update parse-server package and it's dependencies 2024-05-21 13:42:50 +05:30
RaktimaNXG eeb878b340 refactor:refactor code 2024-05-21 13:40:54 +05:30
RaktimaNXG 7894d69cc9 fix: increase time to show confetti celebration 2024-05-21 13:35:22 +05:30
RaktimaNXG b992d7db24 fix: change celebration effect and add for whole screen 2024-05-21 13:03:51 +05:30
AmolandGitHub 50b72f4d85 Merge pull request #755 from OpenSignLabs/feat_resendmail 2024-05-20 18:43:49 +05:30
prafull-opensignlabs 44639f66b0 fix: autoreminder API not working 2024-05-20 18:42:32 +05:30
RaktimaNXG ae740efced refactor: refactor code 2024-05-20 17:46:07 +05:30
RaktimaNXG 66c020d903 fix: fix celebration ui for mobile view 2024-05-20 17:26:18 +05:30
AmolandGitHub 562a7d6fc8 Merge pull request #754 from OpenSignLabs/feat_resendmail
feat: now user can send automatic reminders
2024-05-20 15:44:54 +05:30
RaktimaNXG 090c17c2c0 refactor: add comment 2024-05-20 15:41:04 +05:30
RaktimaNXG 70637d6143 fix: handle condition to show complete message 2024-05-20 15:39:14 +05:30
prafull-opensignlabs f38e8705de feat: now user can sent automatic reminders 2024-05-20 15:31:20 +05:30
RaktimaNXG ba06ff72a0 fix: mismatch complete message issue in multiple signers flow 2024-05-20 14:01:06 +05:30
RaktimaNXG 82312a1e0d feat: celebration confetti on document completion 2024-05-20 11:42:37 +05:30
ZathielandGitHub 1a8cf11a3e Merge pull request #22 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/reduxjs/toolkit-2.2.4
build(deps): bump @reduxjs/toolkit from 2.2.1 to 2.2.4 in /apps/OpenSign
2024-05-19 02:18:41 +02:00
ZathielandGitHub 3deacbabc3 Merge pull request #8 from Zathiel/dependabot/npm_and_yarn/apps/OpenSignServer/babel/eslint-parser-7.24.5
build(deps-dev): bump @babel/eslint-parser from 7.24.1 to 7.24.5 in /apps/OpenSignServer
2024-05-19 02:18:23 +02:00
AmolandGitHub c28805add9 Merge pull request #749 from OpenSignLabs/feat_resendmail 2024-05-17 19:22:04 +05:30
prafull-opensignlabs 80fb320ae4 refactor: add mail in resend mail UI 2024-05-17 19:20:17 +05:30
AmolandGitHub 76c9c1fa53 Merge pull request #748 from OpenSignLabs/feat_resendmail 2024-05-17 14:53:57 +05:30
prafull-opensignlabs f38d83dbe0 style: change z-index of alert 2024-05-17 12:05:18 +05:30
AmolandGitHub ee9411729d Merge pull request #747 from OpenSignLabs/feat_resendmail
refactor: change in subject & body of resend mail
2024-05-17 10:57:29 +05:30
prafull-opensignlabs f6f7c6cecd refactor: change in subject & body of resend mail 2024-05-17 10:56:14 +05:30
AmolandGitHub a45fc0dd60 Merge pull request #746 from OpenSignLabs/feat_resendmail
fix: Cannot read properties of undefined (reading 'find') in resend mail & resend mail not available dashboard report
2024-05-17 10:49:06 +05:30
prafull-opensignlabs 348f7810b9 fix: Cannot read properties of undefined (reading 'find') in resend mail & resend mail not available dashboard report 2024-05-17 10:09:15 +05:30
AmolandGitHub 45bec128a9 Merge pull request #744 from OpenSignLabs/feat_resendmail 2024-05-16 19:37:39 +05:30
prafull-opensignlabs 4da307315c feat: add resend mail functionality for inprogress document 2024-05-16 19:34:28 +05:30
AmolandGitHub c87aa415a9 Merge pull request #743 from OpenSignLabs/signPdf
feat: move forget password button in login box
2024-05-15 20:13:38 +05:30
prafull-opensignlabs b1786ec16a feat: move forget password button in login box 2024-05-15 20:03:30 +05:30
AmolandGitHub 6ad35e979e Merge pull request #742 from OpenSignLabs/signPdf 2024-05-15 16:12:25 +05:30
prafull-opensignlabs 9d996d5cb7 feat: add copy icon beside API token 2024-05-15 16:09:11 +05:30
AmolandGitHub 008e3e8783 Merge pull request #741 from OpenSignLabs/signPdf 2024-05-15 14:52:04 +05:30
prafull-opensignlabs 8458906b0b fix: delete foler are still visible 2024-05-15 14:49:36 +05:30
AmolandGitHub 6933aa309b Merge pull request #740 from OpenSignLabs/signPdf 2024-05-15 13:55:49 +05:30
prafull-opensignlabs 067ea68d3b feat: add download button in 3 dots beside finish button 2024-05-15 13:25:13 +05:30
prafull-opensignlabs e4e8a0b721 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into signPdf 2024-05-15 11:10:29 +05:30
prafull-opensignlabs dc392adc1d feat: add delete folder API 2024-05-14 19:19:17 +05:30
AmolandGitHub 741efff1fa Merge pull request #739 from OpenSignLabs/staging
v1.7.2
2024-05-14 18:56:09 +05:30
AmolandGitHub 93b0d00ab0 Merge pull request #738 from OpenSignLabs/signPdf
fix: some webhook event are not working for second signer & add certificate in completed webhook
2024-05-14 18:33:31 +05:30
prafull-opensignlabs d731951159 fix: some webhook event are not working for second signer & add certificate in completed webhook 2024-05-14 18:30:26 +05:30
AmolandGitHub 24bf08c14f Merge pull request #737 from OpenSignLabs/signPdf
fix: resend mail API is not working
2024-05-14 16:44:42 +05:30
prafull-opensignlabs c03819f5a9 fix: resend mail API is not working 2024-05-14 16:36:58 +05:30
prafull-opensignlabsandGitHub 4521d16891 Merge pull request #719 from ugoconsonni/patch-4
Update createDocumentwithCoordinate.js
2024-05-14 13:57:08 +05:30
prafull-opensignlabs f77525cd8b fix: change baseUrl in APIs 2024-05-14 13:55:32 +05:30
AmolandGitHub 38b7311e66 Merge pull request #736 from OpenSignLabs/staging
v1.7.1
2024-05-14 10:45:00 +05:30
AmolandGitHub c934f8ccd6 Merge pull request #735 from OpenSignLabs/signPdf
fix: change  parameter name in updatefolder API
2024-05-14 10:40:30 +05:30
prafull-opensignlabs 4e128e5a5a fix: change parameter name in updatefolder API 2024-05-14 10:40:04 +05:30
AmolandGitHub e0ccf049a6 Merge pull request #734 from OpenSignLabs/staging
v1.7.0
2024-05-14 01:49:55 +05:30
AndrewandGitHub b202d78059 Merge pull request #730 from OpenSignLabs/signPdf 2024-05-13 19:35:04 +05:30
prafull-opensignlabsandGitHub e15136ce51 Merge pull request #705 from Zathiel/staging
[SECURITY] Package update
2024-05-13 19:34:38 +05:30
prafull-opensignlabs 39c9211167 fix: pass parentFolderId as query parameter in folderlist API 2024-05-13 19:31:01 +05:30
AndrewandGitHub 64864e3f54 Merge pull request #729 from OpenSignLabs/signPdf 2024-05-13 18:25:15 +05:30
prafull-opensignlabs af0bef6d29 refactor: update response for folder APIs 2024-05-13 18:24:12 +05:30
AndrewandGitHub 130704b32f Merge pull request #728 from OpenSignLabs/signPdf 2024-05-13 17:09:23 +05:30
prafull-opensignlabsandGitHub 5b139b66a9 Merge pull request #727 from OpenSignLabs/raktima-opensignlabs-patch-6
feat: add help message button on send-in-order in request signature form
2024-05-13 17:07:06 +05:30
prafull-opensignlabs f9c5041af1 feat: add folder api 2024-05-13 17:02:37 +05:30
dependabot[bot]andGitHub 1e58b35db5 build(deps): bump @reduxjs/toolkit from 2.2.1 to 2.2.4 in /apps/OpenSign
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.1 to 2.2.4.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.1...v2.2.4)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 10:51:45 +00:00
RaktimaNXG 245bf8046b feat: add help message on send-in-order in request signature form 2024-05-13 15:49:26 +05:30
AndrewandGitHub 94eb5f9efe Merge pull request #726 from OpenSignLabs/signPdf 2024-05-13 13:22:16 +05:30
prafull-opensignlabs 044128f36a feat: make entire folder selection box clickable 2024-05-13 13:21:32 +05:30
AndrewandGitHub 594383fe14 Merge pull request #725 from OpenSignLabs/signPdf 2024-05-13 11:50:03 +05:30
prafull-opensignlabs 90a585367e fix: change body parameter of create document api 2024-05-13 11:48:03 +05:30
prafull-opensignlabsandGitHub 0b8382df00 Merge pull request #723 from OpenSignLabs/raktima-opensignlabs-patch-5
fix: help button fridge in user's profile of disable documentId
2024-05-13 11:15:19 +05:30
RaktimaNXG a54c7e7fd7 fix: help button fridge in user profile ofdisable documentId 2024-05-13 10:57:53 +05:30
prafull-opensignlabsandGitHub 45a2c88e90 Merge pull request #718 from OpenSignLabs/raktima-opensignlabs-patch-4
fix: tour & model for email verification is shown simaltaneously in signyourself flow, navigate tour message on another page
2024-05-13 10:25:55 +05:30
AndrewandGitHub e4526f026b Merge pull request #720 from OpenSignLabs/signPdf 2024-05-10 21:48:25 +05:30
prafull-opensignlabs 11a2f6b8ec feat: add resend mail api, add expiry date in create document api & return certificate url in get document api 2024-05-10 21:07:06 +05:30
RaktimaNXG 3bf35166fc fix: bookmark color according to user's widget color 2024-05-10 20:27:04 +05:30
RaktimaNXG cd50c8cf20 Merge branch 'raktima-opensignlabs-patch-4' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-4 2024-05-10 19:31:42 +05:30
RaktimaNXG 055ef3f209 fix: min required checkbox validation issue 2024-05-10 19:28:53 +05:30
ugoconsonniandGitHub 964ec0d422 Update createDocumentwithCoordinate.js
fix: email and api return url server and not front
2024-05-10 15:22:00 +02:00
RaktimaandGitHub ec0e291604 Update RenderAllPdfPage.js 2024-05-10 18:16:11 +05:30
RaktimaNXG 836e952ba0 fix: add comment 2024-05-10 18:14:19 +05:30
RaktimaNXG c5f39e2a24 fix: tour & model for email verification is shown simaltaneously, issue of navigate tour message on another page to show warning complete signature 2024-05-10 16:59:58 +05:30
AmolandGitHub 498bd18630 Merge pull request #717 from OpenSignLabs/staging
v1.6.2
2024-05-10 16:02:39 +05:30
AndrewandGitHub 56dd060531 Merge pull request #716 from OpenSignLabs/fix_guestlogin 2024-05-10 15:14:19 +05:30
prafull-opensignlabs 960fbdb0eb fix: issue of owner subscription has expired in guest login 2024-05-10 15:10:57 +05:30
AmolandGitHub b530ef882a Merge pull request #715 from OpenSignLabs/staging
v1.6.1
2024-05-10 11:18:58 +05:30
ZathielandGitHub bb69518674 Merge branch 'OpenSignLabs:staging' into staging 2024-05-09 18:08:05 +02:00
AmolandGitHub 850d14064a Merge pull request #710 from OpenSignLabs/staging
v1.6.0
2024-05-09 16:38:17 +05:30
ZathielandGitHub dc1fab5250 Merge pull request #14 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/ejs-3.1.10
build(deps): bump ejs from 3.1.9 to 3.1.10 in /apps/OpenSign
2024-05-08 23:21:58 +02:00
ZathielandGitHub 3e185ef796 Merge pull request #15 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/tar-6.2.1
build(deps): bump tar from 6.2.0 to 6.2.1 in /apps/OpenSign
2024-05-08 23:19:47 +02:00
ZathielandGitHub 8cf5adb273 Merge pull request #16 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/webpack-dev-middleware-5.3.4
build(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /apps/OpenSign
2024-05-08 23:15:43 +02:00
ZathielandGitHub 803faed97b Merge pull request #17 from Zathiel/dependabot/npm_and_yarn/apps/OpenSign/react-pdf-7.7.3
build(deps): bump react-pdf from 7.7.1 to 7.7.3 in /apps/OpenSign
2024-05-08 23:13:12 +02:00
prafull-opensignlabsandGitHub 273ada837b Merge pull request #703 from OpenSignLabs/staging
v1.5.9
2024-05-08 16:12:46 +05:30
dependabot[bot]andGitHub b1dd4df3c0 build(deps): bump react-pdf from 7.7.1 to 7.7.3 in /apps/OpenSign
Bumps [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) from 7.7.1 to 7.7.3.
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v7.7.3/packages/react-pdf)

---
updated-dependencies:
- dependency-name: react-pdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 17:03:30 +00:00
dependabot[bot]andGitHub 13e2d92ce6 build(deps): bump webpack-dev-middleware in /apps/OpenSign
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 02:26:18 +00:00
dependabot[bot]andGitHub 4b9f22a5bc build(deps): bump tar from 6.2.0 to 6.2.1 in /apps/OpenSign
Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 02:25:30 +00:00
dependabot[bot]andGitHub 77c61c89a2 build(deps): bump ejs from 3.1.9 to 3.1.10 in /apps/OpenSign
Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 02:24:33 +00:00
dependabot[bot]andGitHub 280b812e5b build(deps-dev): bump @babel/eslint-parser in /apps/OpenSignServer
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.24.1 to 7.24.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.5/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 12:51:25 +00:00
176 changed files with 13973 additions and 10972 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ DO_SECRET_ACCESS_KEY=
# Digital ocean spaces region or AWS s3 region # Digital ocean spaces region or AWS s3 region
DO_REGION=us-west DO_REGION=us-west
# local storage # local storage
USE_LOCAL=TRUE USE_LOCAL=true
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) ********************************************************************************************************************* # Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
MAILGUN_API_KEY= MAILGUN_API_KEY=
+1 -1
View File
@@ -2,7 +2,7 @@ name: ci
on: on:
push: push:
branches: branches:
- 'staging' - 'main'
jobs: jobs:
docker: docker:
+1 -1
View File
@@ -136,7 +136,7 @@ We would like to thank all our contributors and users for their support and feed
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VikramNagwal"><img src="https://avatars.githubusercontent.com/u/123088024?v=4?s=100" width="100px;" alt="Vikram"/><br /><sub><b>Vikram</b></sub></a><br /><a href="#code-VikramNagwal" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/VikramNagwal"><img src="https://avatars.githubusercontent.com/u/123088024?v=4?s=100" width="100px;" alt="Vikram"/><br /><sub><b>Vikram</b></sub></a><br /><a href="#code-VikramNagwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ugoconsonni"><img src="https://avatars.githubusercontent.com/u/13661702?v=4?s=100" width="100px;" alt="ugoconsonni"/><br /><sub><b>ugoconsonni</b></sub></a><br /><a href="#code-ugoconsonni" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/ugoconsonni"><img src="https://avatars.githubusercontent.com/u/13661702?v=4?s=100" width="100px;" alt="ugoconsonni"/><br /><sub><b>ugoconsonni</b></sub></a><br /><a href="#code-ugoconsonni" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-mutwiri"><img src="https://avatars.githubusercontent.com/u/8936960?v=4?s=100" width="100px;" alt="Daniel Mutwiri"/><br /><sub><b>Daniel Mutwiri</b></sub></a><br /><a href="#code-daniel-mutwiri" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-mutwiri"><img src="https://avatars.githubusercontent.com/u/8936960?v=4?s=100" width="100px;" alt="Daniel Mutwiri"/><br /><sub><b>Daniel Mutwiri</b></sub></a><br /><a href="#code-daniel-mutwiri" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a><a href="#security-Zathiel" title="Security">🛡️</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
+4058 -3508
View File
File diff suppressed because it is too large Load Diff
+21 -16
View File
@@ -4,21 +4,23 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@formkit/auto-animate": "^0.8.2", "@formkit/auto-animate": "^0.8.2",
"@radix-ui/themes": "^2.0.3", "@radix-ui/themes": "^3.0.5",
"@react-pdf/renderer": "^3.4.4", "@react-pdf/renderer": "^3.4.4",
"@reduxjs/toolkit": "^2.2.1", "@reduxjs/toolkit": "^2.2.5",
"axios": "^1.6.8", "axios": "^1.7.2",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"parse": "^4.3.1", "nth-check": "^2.1.1",
"parse": "^5.1.0",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"radix-ui": "^1.0.1", "radix-ui": "^1.0.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-bootstrap": "^2.10.2", "react-bootstrap": "^2.10.2",
"react-confetti": "^6.1.0",
"react-cookie": "^7.1.4", "react-cookie": "^7.1.4",
"react-datepicker": "^6.4.0", "react-datepicker": "^6.9.0",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1", "react-dnd-html5-backend": "^16.0.1",
"react-dnd-multi-backend": "^8.0.3", "react-dnd-multi-backend": "^8.0.3",
@@ -27,25 +29,24 @@
"react-gtm-module": "^2.0.11", "react-gtm-module": "^2.0.11",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-konva": "^18.2.10", "react-konva": "^18.2.10",
"react-modal": "^3.16.1", "react-pdf": "^9.0.0",
"react-pdf": "^7.7.1",
"react-quill": "^2.0.0", "react-quill": "^2.0.0",
"react-redux": "^9.1.0", "react-redux": "^9.1.2",
"react-rnd": "^10.4.10", "react-rnd": "^10.4.11",
"react-router-dom": "^6.22.3", "react-router-dom": "^6.22.3",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"react-scrollbars-custom": "^4.1.1", "react-scrollbars-custom": "^4.1.1",
"react-select": "^5.8.0", "react-select": "^5.8.0",
"react-signature-canvas": "^1.0.6", "react-signature-canvas": "^1.0.6",
"react-tooltip": "^5.26.3", "react-tooltip": "^5.26.4",
"react-web-share": "^2.0.2", "react-web-share": "^2.0.2",
"reactour": "^1.19.3", "reactour": "^1.19.4",
"redux": "^5.0.1", "redux": "^5.0.1",
"redux-thunk": "^3.1.0", "redux-thunk": "^3.1.0",
"regex-parser": "^2.3.0", "regex-parser": "^2.3.0",
"serve": "^14.2.1", "serve": "^14.2.3",
"styled-components": "^4.4.1", "styled-components": "^4.4.1",
"web-vitals": "^2.1.4" "web-vitals": "^4.0.1"
}, },
"scripts": { "scripts": {
"start": "serve -s build", "start": "serve -s build",
@@ -83,16 +84,20 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@babel/runtime-corejs2": "^7.24.5", "@babel/runtime-corejs2": "^7.24.7",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"daisyui": "^4.12.2",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.34.1", "eslint-plugin-react": "^7.34.1",
"lint-staged": "^15.2.2", "lint-staged": "^15.2.5",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"pretty-quick": "^3.3.1", "pretty-quick": "^3.3.1",
"tailwindcss": "^3.4.1" "tailwindcss": "^3.4.4"
},
"overrides": {
"nth-check": "$nth-check"
} }
} }
+2 -2
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" data-theme="opensigncss">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
@@ -50,4 +50,4 @@
--> -->
</body> </body>
</html> </html>
Binary file not shown.
+10 -19
View File
@@ -16,6 +16,8 @@ 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"; import { isEnableSubscription } from "./constant/const";
import SSOVerify from "./pages/SSOVerify";
import Loader from "./primitives/Loader";
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"));
@@ -28,25 +30,13 @@ const Opensigndrive = lazy(() => import("./pages/Opensigndrive"));
const ManageSign = lazy(() => import("./pages/Managesign")); const ManageSign = lazy(() => import("./pages/Managesign"));
const GenerateToken = lazy(() => import("./pages/GenerateToken")); const GenerateToken = lazy(() => import("./pages/GenerateToken"));
const Webhook = lazy(() => import("./pages/Webhook")); const Webhook = lazy(() => import("./pages/Webhook"));
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
const Loader = () => { pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
const AppLoader = () => {
return ( return (
<div <div className="flex justify-center items-center h-[100vh]">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
); );
}; };
@@ -75,9 +65,9 @@ function App() {
}; };
return ( return (
<div className="bg-[#eef1f5]"> <div className="bg-base-200">
{isloading ? ( {isloading ? (
<Loader /> <AppLoader />
) : ( ) : (
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
@@ -181,6 +171,7 @@ function App() {
element={<PdfRequestFiles />} element={<PdfRequestFiles />}
/> />
</Route> </Route>
<Route path="/sso" element={<SSOVerify />} />
<Route path="*" element={<PageNotFound />} /> <Route path="*" element={<PageNotFound />} />
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

+167 -172
View File
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Parse from "parse"; import Parse from "parse";
import axios from "axios"; import axios from "axios";
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const"; import Loader from "../primitives/Loader";
const AddSigner = (props) => { const AddSigner = (props) => {
const [name, setName] = useState(""); const [name, setName] = useState("");
@@ -23,7 +23,7 @@ const AddSigner = (props) => {
); );
if (savedUserDetails && addYourself) { if (savedUserDetails && addYourself) {
setName(savedUserDetails.name); setName(savedUserDetails.name);
setPhone(savedUserDetails.phone); setPhone(savedUserDetails?.phone || "");
setEmail(savedUserDetails.email); setEmail(savedUserDetails.email);
} }
}, [addYourself]); }, [addYourself]);
@@ -49,144 +49,162 @@ const AddSigner = (props) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
setIsLoader(true); setIsLoader(true);
try { if (localStorage.getItem("TenantId")) {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
contactQuery.set("Phone", phone);
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest");
if (localStorage.getItem("TenantId")) {
contactQuery.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
}
try { try {
const _users = Parse.Object.extend("User"); const user = Parse.User.current();
const _user = new _users(); const query = new Parse.Query("contracts_Contactbook");
_user.set("name", name); query.equalTo("CreatedBy", user);
_user.set("username", email); query.notEqualTo("IsDeleted", true);
_user.set("email", email); query.equalTo("Email", email);
_user.set("phone", phone); const res = await query.first();
_user.set("password", phone); // console.log(res);
if (!res) {
const user = await _user.save(); const contactQuery = new Parse.Object("contracts_Contactbook");
if (user) { contactQuery.set("Name", name);
const roleurl = `${parseBaseUrl}functions/AddUserToRole`; if (phone) {
const headers = { contactQuery.set("Phone", phone);
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: localStorage.getItem("_appName"),
roleName: "contracts_Guest",
userId: user.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", user);
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
} }
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest");
contactQuery.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", name);
_user.set("username", email);
_user.set("email", email);
_user.set("password", email);
if (phone) {
_user.set("phone", phone);
}
const user = await _user.save();
if (user) {
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: localStorage.getItem("_appName"),
roleName: "contracts_Guest",
userId: user.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", user);
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
} catch (err) {
console.log("err ", err);
if (err.code === 202) {
const params = { email: email };
const userRes = await Parse.Cloud.run("getUserId", params);
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: localStorage.getItem("_appName"),
roleName: "contracts_Guest",
userId: userRes.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
});
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
}
} else {
alert("Contact already exist!");
setIsLoader(false); setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
} }
} catch (err) { } catch (err) {
console.log("err ", err); console.log("err in fetch contact", err);
if (err.code === 202) { setIsLoader(false);
const params = { email: email }; alert("something went wrong, please try again later");
const userRes = await Parse.Cloud.run("getUserId", params);
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: localStorage.getItem("_appName"),
roleName: "contracts_Guest",
userId: userRes.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
});
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
} }
} catch (err) { } else {
// console.log("err", err);
setIsLoader(false); setIsLoader(false);
alert("something went wrong!"); alert("something went wrong, please try again later");
} }
}; };
@@ -209,38 +227,29 @@ const AddSigner = (props) => {
<div className="h-full p-[20px]"> <div className="h-full p-[20px]">
{isLoader && ( {isLoader && (
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30"> <div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30">
<div <Loader />
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
)} )}
<div className="w-full mx-auto p-2"> <div className="w-full mx-auto p-2 text-base-content">
{isUserExist && ( {isUserExist && (
<div className="mb-3"> <div className="mb-3 flex items-center">
<input <input
type="checkbox" type="checkbox"
id="addYourself" id="addYourself"
checked={addYourself} checked={addYourself}
onChange={handleAddYourselfChange} onChange={handleAddYourselfChange}
className="form-checkbox" className="op-checkbox op-checkbox-sm"
/> />
<label htmlFor="addYourself" className="ml-2 text-gray-700"> <label htmlFor="addYourself" className="ml-2 mb-0">
Add Yourself Add Yourself
</label> </label>
</div> </div>
)} )}
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="name" className="block text-xs font-semibold">
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
Name Name
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
type="text" type="text"
@@ -249,59 +258,45 @@ const AddSigner = (props) => {
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
required required
disabled={addYourself} disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="email" className="block text-xs font-semibold">
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email Email
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
type="email" type="email"
id="email" id="email"
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value?.toLowerCase())}
required required
disabled={addYourself} disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="phone" className="block text-xs font-semibold">
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Phone Phone
<span style={{ color: "red", fontSize: 13 }}> *</span>
</label> </label>
<input <input
type="text" type="text"
id="phone" id="phone"
value={phone} value={phone}
onChange={(e) => setPhone(e.target.value)} onChange={(e) => setPhone(e.target.value)}
required
disabled={addYourself} disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="mt-4 flex gap-x-2 justify-start">
<div className="mt-4 flex justify-start"> <button type="submit" className="op-btn op-btn-primary">
<button
type="submit"
style={{ backgroundColor: modalSubmitBtnColor }}
className="mr-2 px-[20px] py-1.5 text-white rounded shadow-md text-center focus:outline-none "
>
Submit Submit
</button> </button>
<button <button
type="button" type="button"
onClick={() => handleReset()} onClick={() => handleReset()}
style={{ backgroundColor: modalCancelBtnColor }} className="op-btn op-btn-secondary"
className="px-4 py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none"
> >
Reset Reset
</button> </button>
+12 -15
View File
@@ -3,6 +3,7 @@ import Parse from "parse";
import axios from "axios"; import axios from "axios";
import Title from "./Title"; import Title from "./Title";
import Alert from "../primitives/Alert"; import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
const AddUser = (props) => { const AddUser = (props) => {
const [name, setName] = useState(""); const [name, setName] = useState("");
@@ -62,8 +63,10 @@ const AddUser = (props) => {
_user.set("name", name); _user.set("name", name);
_user.set("username", email); _user.set("username", email);
_user.set("email", email); _user.set("email", email);
_user.set("phone", phone); _user.set("password", email);
_user.set("password", phone); if (phone) {
_user.set("phone", phone);
}
const user = await _user.save(); const user = await _user.save();
if (user) { if (user) {
@@ -193,13 +196,7 @@ const AddUser = (props) => {
{isUserExist && <Alert type="danger">User already exists!</Alert>} {isUserExist && <Alert type="danger">User already exists!</Alert>}
{isLoader && ( {isLoader && (
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50"> <div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50">
<div <Loader />
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
)} )}
<div className="w-full mx-auto"> <div className="w-full mx-auto">
@@ -211,7 +208,7 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold" className="block text-xs text-gray-700 font-semibold"
> >
Name Name
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
type="text" type="text"
@@ -219,7 +216,7 @@ const AddUser = (props) => {
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
required required
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
@@ -228,7 +225,7 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold" className="block text-xs text-gray-700 font-semibold"
> >
Email Email
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
type="email" type="email"
@@ -236,7 +233,7 @@ const AddUser = (props) => {
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
required required
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
@@ -245,7 +242,7 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold" className="block text-xs text-gray-700 font-semibold"
> >
Phone Phone
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
type="text" type="text"
@@ -253,7 +250,7 @@ const AddUser = (props) => {
value={phone} value={phone}
onChange={(e) => setPhone(e.target.value)} onChange={(e) => setPhone(e.target.value)}
required required
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
+256
View File
@@ -0,0 +1,256 @@
import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import SuggestionInput from "./shared/fields/SuggestionInput";
import Loader from "../primitives/Loader";
const BulkSendUi = (props) => {
const [forms, setForms] = useState([]);
const [formId, setFormId] = useState(2);
const formRef = useRef(null);
const [scrollOnNextUpdate, setScrollOnNextUpdate] = useState(false);
const [isSubmit, setIsSubmit] = useState(false);
const [allowedForm, setAllowedForm] = useState(0);
const [isSignatureExist, setIsSignatureExist] = useState();
const allowedSigners = 50;
useEffect(() => {
signatureExist();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//function to check atleast one signature field exist
const signatureExist = () => {
const getPlaceholder = props.item?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
)
);
setIsSignatureExist(checkIsSignatureExistt);
};
useEffect(() => {
if (scrollOnNextUpdate && formRef.current) {
formRef.current.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
});
setScrollOnNextUpdate(false);
}
}, [forms, scrollOnNextUpdate]);
useEffect(() => {
(() => {
if (props?.Placeholders?.length > 0) {
let users = [];
props?.Placeholders?.forEach((element) => {
if (!element.signerObjId) {
users = [
...users,
{
fieldId: element.Id,
email: "",
label: element.Role,
signer: {}
}
];
}
});
setForms((prevForms) => [...prevForms, { Id: 1, fields: users }]);
const totalForms = Math.floor(allowedSigners / users?.length);
setAllowedForm(totalForms);
}
})();
// eslint-disable-next-line
}, []);
const handleInputChange = (index, signer, fieldIndex) => {
const newForms = [...forms];
newForms[index].fields[fieldIndex].email = signer?.Email
? signer?.Email
: signer || "";
newForms[index].fields[fieldIndex].signer = signer?.objectId ? signer : "";
setForms(newForms);
};
const handleAddForm = (e) => {
e.preventDefault();
// Check if the quick send limit has been reached
if (forms?.length < allowedForm) {
if (props?.Placeholders.length > 0) {
let newForm = [];
props?.Placeholders?.forEach((element) => {
if (!element.signerObjId) {
newForm = [
...newForm,
{
fieldId: element.Id,
email: "",
label: element.Role,
signer: {}
}
];
}
});
setForms([...forms, { Id: formId, fields: newForm }]);
}
setFormId(formId + 1);
setScrollOnNextUpdate(true);
} else {
// If the limit has been reached, throw an error with the appropriate message
alert("Quick send reached limit.");
}
};
const handleRemoveForm = (index) => {
const updatedForms = forms.filter((_, i) => i !== index);
setForms(updatedForms);
};
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsSubmit(true);
// Create a copy of Placeholders array from props.item
let Placeholders = [...props.item.Placeholders];
// Initialize an empty array to store updated documents
let Documents = [];
// Loop through each form
forms.forEach((form) => {
// Map through the copied Placeholders array to update email values
const updatedPlaceholders = Placeholders.map((placeholder) => {
// Find the field in the current form that matches the placeholder Id
const field = form.fields.find(
(element) => parseInt(element.fieldId) === placeholder.Id
);
// If a matching field is found, update the email value in the placeholder
const signer = field?.signer?.objectId ? field.signer : {};
if (field) {
return {
...placeholder,
email: field.email,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
}
// If no matching field is found, keep the placeholder as is
return placeholder;
});
// Push a new document object with updated Placeholders into the Documents array
Documents.push({ ...props.item, Placeholders: updatedPlaceholders });
});
// console.log("Documents ", Documents);
await batchQuery(Documents);
};
const batchQuery = async (Documents) => {
const serverUrl = localStorage.getItem("baseUrl");
const functionsUrl = `${serverUrl}functions/batchdocuments`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
};
const params = {
Documents: JSON.stringify(Documents)
};
try {
const res = await axios.post(functionsUrl, params, { headers: headers });
// console.log("res ", res);
if (res.data && res.data.result) {
props.handleClose("success", Documents?.length);
}
} catch (err) {
console.log("Err ", err);
props.handleClose("error", 0);
} finally {
setIsSubmit(false);
}
};
return (
<>
{isSubmit && (
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
{props.Placeholders?.length > 0 ? (
isSignatureExist ? (
<>
{props.Placeholders?.some((x) => !x.signerObjId) ? (
<form onSubmit={handleSubmit}>
<div className="min-h-max max-h-[250px] overflow-y-auto">
{forms?.map((form, index) => (
<div
key={form.Id}
className="p-3 op-card border-[1px] border-gray-400 mt-3 mx-4 mb-4 bg-base-200 text-base-content grid grid-cols-1 md:grid-cols-2 gap-2 relative"
>
{form?.fields?.map((field, fieldIndex) => (
<div className="flex flex-col" key={field.fieldId}>
<label>{field.label}</label>
<SuggestionInput
required
type="email"
value={field.value}
index={fieldIndex}
onChange={(signer) =>
handleInputChange(index, signer, fieldIndex)
}
/>
</div>
))}
{forms?.length > 1 && (
<button
onClick={() => handleRemoveForm(index)}
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
>
<i className="fa-solid fa-trash"></i>
</button>
)}
<div ref={formRef}></div>
</div>
))}
</div>
<div className="flex flex-col mx-4 mb-4 gap-3">
<button
onClick={handleAddForm}
className="op-btn op-btn-primary focus:outline-none"
>
<i className="fa-solid fa-plus"></i> <span>Add new</span>
</button>
<button
type="submit"
className="op-btn op-btn-secondary focus:outline-none"
>
<i className="fa-solid fa-paper-plane"></i>{" "}
<span>Send</span>
</button>
</div>
</form>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
All roles in this document are currently linked to contacts. To
&apos;quick send&apos; copies of this template to multiple
signers, please ensure that at least one role is not linked to
any contact.
</div>
)}
</>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
Please ensure there&#39;s at least one signature widget added for
all recipients.
</div>
)
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
Please add at least one role to this template in order to &apos;quick
send&apos; copies of it to multiple signers.
</div>
)}
</>
);
};
export default BulkSendUi;
+10 -6
View File
@@ -45,12 +45,16 @@ const Footer = () => {
}; };
return ( return (
<> <>
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3"> <footer className="op-footer op-footer-center py-3 bg-base-300 text-base-content text-center text-[13px]">
All Rights Reserved &copy; {new Date().getFullYear()} &nbsp; <aside>
<span onClick={openUrl} className="hover:underline cursor-pointer"> <p>
{appName} ( version: {version ? version : `${Package.version} `}) All Rights Reserved &copy; {new Date().getFullYear()} &nbsp;
</span> <span onClick={openUrl} className="hover:underline cursor-pointer">
</div> {appName} ( version: {version ? version : `${Package.version} `})
</span>
</p>
</aside>
</footer>
<button <button
className={`${ className={`${
showButton ? "block" : "hidden" showButton ? "block" : "hidden"
@@ -67,7 +67,7 @@ const FullScreenButton = () => {
<div className="flex items-center"> <div className="flex items-center">
<button <button
onClick={toggleFullScreen} onClick={toggleFullScreen}
className="text-black p-2 text-sm focus:outline-none" className="text-base-content p-2 text-sm focus:outline-none"
> >
{isFullScreen ? ( {isFullScreen ? (
<i className="fa-solid fa-compress"></i> <i className="fa-solid fa-compress"></i>
+69 -58
View File
@@ -44,7 +44,13 @@ const Header = ({ showSidebar }) => {
const closeDropdown = () => { const closeDropdown = () => {
setIsOpen(false); setIsOpen(false);
Parse.User.logOut(); if (Parse?.User?.current()) {
try {
Parse.User.logOut();
} catch (err) {
console.log("Err", err);
}
}
let appdata = localStorage.getItem("userSettings"); let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo"); let applogo = localStorage.getItem("appLogo");
let appName = localStorage.getItem("appName"); let appName = localStorage.getItem("appName");
@@ -87,14 +93,16 @@ const Header = ({ showSidebar }) => {
}, [isOpen]); }, [isOpen]);
return ( return (
<div className="flex flex-row justify-between items-center gap-x-3 md:gap-x-4 bg-white md:px-4 px-2 shadow h-[50px] md:w-full "> <div className="op-navbar bg-base-100 shadow">
<button <div className="flex-none">
className="cursor-pointer focus:outline-none" <button
onClick={showSidebar} className="op-btn op-btn-square op-btn-ghost focus:outline-none"
> onClick={showSidebar}
<i className={`fa-solid fa-bars text-xl `}></i> >
</button> <i className="fa-solid fa-bars text-xl text-base-content"></i>
<div className="flex-1"> </button>
</div>
<div className="flex-1 ml-2">
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden"> <div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
<img <img
className="object-contain h-full w-auto" className="object-contain h-full w-auto"
@@ -103,10 +111,7 @@ const Header = ({ showSidebar }) => {
/> />
</div> </div>
</div> </div>
<div <div id="profile-menu" className="flex-none gap-2">
id="profile-menu"
className="flex justify-between items-center gap-x-3"
>
{!isSubscribe && ( {!isSubscribe && (
<div> <div>
<button <button
@@ -118,7 +123,7 @@ const Header = ({ showSidebar }) => {
</div> </div>
)} )}
{isPro && ( {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"> <div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
PRO PRO
</div> </div>
)} )}
@@ -138,60 +143,66 @@ const Header = ({ showSidebar }) => {
</div> </div>
)} )}
{width >= 768 && ( {width >= 768 && (
<div onClick={toggleDropdown} className="cursor-pointer text-sm"> <div
onClick={toggleDropdown}
className="cursor-pointer text-base-content text-sm"
>
{username && username} {username && username}
</div> </div>
)} )}
<div className="relative"> <div className="op-dropdown op-dropdown-end" id="profile-menu">
<div className="cursor-pointer"> <div tabIndex={0} role="button" className="op-btn op-btn-ghost">
<i onClick={toggleDropdown} className="fa-solid fa-angle-down"></i> <i
tabIndex={0}
role="button"
onClick={toggleDropdown}
className="fa-solid fa-angle-down text-base-content"
></i>
</div> </div>
<div <ul
className={`dropdown absolute text-sm text-gray-700 font-light right-0 mt-4 p-1 w-48 bg-white border rounded-lg shadow-lg z-10 ${ tabIndex={0}
isOpen ? "block" : "hidden" className="mt-3 z-[1] p-2 shadow op-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52"
}`}
> >
<ul> <li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
<li <span>
className="hover:bg-gray-100 rounded-t-lg py-1 px-2 cursor-pointer font-normal"
onClick={() => openInNewTab("https://docs.opensignlabs.com")}
>
<i className="fa-solid fa-book"></i> Docs <i className="fa-solid fa-book"></i> Docs
</li> </span>
<li </li>
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal" <li
onClick={() => { onClick={() => {
setIsOpen(false); setIsOpen(false);
navigate("/profile"); navigate("/profile");
}} }}
> >
<span>
<i className="fa-regular fa-user"></i> Profile <i className="fa-regular fa-user"></i> Profile
</li> </span>
<li </li>
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal" <li
onClick={() => { onClick={() => {
setIsOpen(false); setIsOpen(false);
navigate("/changepassword"); navigate("/changepassword");
}} }}
> >
<span>
<i className="fa-solid fa-lock"></i> Change Password <i className="fa-solid fa-lock"></i> Change Password
</li> </span>
<li </li>
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal" <li
onClick={() => { onClick={() => {
window.open("https://console.opensignlabs.com/"); window.open("https://console.opensignlabs.com/");
}} }}
> >
<span>
<i className="fa-regular fa-id-card"></i> Console <i className="fa-regular fa-id-card"></i> Console
</li> </span>
<li </li>
className="hover:bg-gray-100 rounded-b-lg py-1 px-2 cursor-pointer font-normal" <li onClick={closeDropdown}>
onClick={closeDropdown} <span>
>
<i className="fa-solid fa-arrow-right-from-bracket"></i> Log Out <i className="fa-solid fa-arrow-right-from-bracket"></i> Log Out
</li> </span>
</ul> </li>
</div> </ul>
</div> </div>
</div> </div>
</div> </div>
+16 -47
View File
@@ -1,5 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import Parse from "parse"; import Parse from "parse";
import Loader from "../primitives/Loader";
// import FacebookLogin from "react-facebook-login"; // import FacebookLogin from "react-facebook-login";
const LoginFacebook = ({ const LoginFacebook = ({
@@ -49,7 +50,7 @@ const LoginFacebook = ({
const extRes = await Parse.Cloud.run("getUserDetails", params); const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes); // console.log("extRes ", extRes);
if (extRes) { if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") }; const params = { ...details, Phone: extRes?.get("Phone") || "" };
const payload = await Parse.Cloud.run("facebooksign", params); const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload); // console.log("payload ", payload);
if (payload && payload.sessiontoken) { if (payload && payload.sessiontoken) {
@@ -59,7 +60,7 @@ const LoginFacebook = ({
const LocalUserDetails = { const LocalUserDetails = {
name: details.Name, name: details.Name,
email: details.Email, email: details.Email,
phone: extRes.get("Phone"), phone: extRes?.get("Phone") || "",
company: extRes.get("Company") company: extRes.get("Company")
}; };
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails)); localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
@@ -75,7 +76,7 @@ const LoginFacebook = ({
const handleSubmitbtn = async () => { const handleSubmitbtn = async () => {
if (userDetails.Phone && userDetails.Company) { if (userDetails.Phone && userDetails.Company) {
setThirdpartyLoader(true); setThirdpartyLoader(true);
const params = { ...fBDetails, Phone: userDetails.Phone }; const params = { ...fBDetails, Phone: userDetails?.Phone || "" };
const payload = await Parse.Cloud.run("facebooksign", params); const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload); // console.log("payload ", payload);
@@ -85,7 +86,7 @@ const LoginFacebook = ({
name: userDetails.Name, name: userDetails.Name,
email: userDetails.Email, email: userDetails.Email,
// "passsword":userDetails.Phone, // "passsword":userDetails.Phone,
phone: userDetails.Phone, phone: userDetails?.Phone || "",
role: "contracts_User", role: "contracts_User",
company: userDetails.Company company: userDetails.Company
} }
@@ -96,7 +97,7 @@ const LoginFacebook = ({
const LocalUserDetails = { const LocalUserDetails = {
name: userDetails.Name, name: userDetails.Name,
email: userDetails.Email, email: userDetails.Email,
phone: userDetails.Phone, phone: userDetails?.Phone || "",
company: userDetails.Company company: userDetails.Company
}; };
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails)); localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
@@ -112,29 +113,10 @@ const LoginFacebook = ({
} }
}; };
return ( return (
<div style={{ position: "relative" }}> <div className="relative">
{thirdpartyLoader && ( {thirdpartyLoader && (
<div <div className="fixed flex justify-center items-center inset-0 bg-black bg-opacity-25 z-20 ">
style={{ <Loader />
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</div> </div>
)} )}
{/* <FacebookLogin {/* <FacebookLogin
@@ -146,11 +128,10 @@ const LoginFacebook = ({
/> */} /> */}
{isModal && ( {isModal && (
<div <div
className="modal fade show" className="modal fade show block z-[1]"
id="exampleModal" id="exampleModal"
tabIndex="-1" tabIndex="-1"
role="dialog" role="dialog"
style={{ display: "block", zIndex: 1 }}
> >
<div className="modal-dialog" role="document"> <div className="modal-dialog" role="document">
<div className="modal-content"> <div className="modal-content">
@@ -163,13 +144,8 @@ const LoginFacebook = ({
<div className="modal-body"> <div className="modal-body">
<form> <form>
<div className="form-group"> <div className="form-group">
<label <label htmlFor="Phone" className="col-form-label">
htmlFor="Phone" Phone <span className="text-[red] text-[13px]">*</span>
style={{ display: "flex" }}
className="col-form-label"
>
Phone{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="tel" type="tel"
@@ -186,13 +162,8 @@ const LoginFacebook = ({
/> />
</div> </div>
<div className="form-group"> <div className="form-group">
<label <label htmlFor="Company" className="col-form-label">
htmlFor="Company" Company <span className="text-[red] text-[13px]">*</span>
style={{ display: "flex" }}
className="col-form-label"
>
Company{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="text" type="text"
@@ -212,16 +183,14 @@ const LoginFacebook = ({
<button <button
type="button" type="button"
onClick={() => handleSubmitbtn()} onClick={() => handleSubmitbtn()}
className="btn btn-info" className="btn btn-info mr-[10px]"
style={{ marginRight: 10 }}
> >
Sign up Sign up
</button> </button>
<button <button
type="button" type="button"
className="btn btn-secondary" className="btn btn-secondary w-[90px]"
onClick={() => setIsModal(false)} onClick={() => setIsModal(false)}
style={{ width: 90 }}
> >
Cancel Cancel
</button> </button>
+22 -55
View File
@@ -3,7 +3,7 @@ import Parse from "parse";
import { jwtDecode } from "jwt-decode"; import { jwtDecode } from "jwt-decode";
import { useScript } from "../hook/useScript"; import { useScript } from "../hook/useScript";
import ModalUi from "../primitives/ModalUi"; import ModalUi from "../primitives/ModalUi";
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const"; import Loader from "../primitives/Loader";
/* /*
* `GoogleSignInBtn`as it's name indicates it render google sign in button * `GoogleSignInBtn`as it's name indicates it render google sign in button
@@ -110,7 +110,7 @@ const GoogleSignInBtn = ({
const extRes = await Parse.Cloud.run("getUserDetails", params); const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes); // console.log("extRes ", extRes);
if (extRes) { if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") }; const params = { ...details, Phone: extRes?.get("Phone") || "" };
const payload = await Parse.Cloud.run("googlesign", params); const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload); // console.log("payload ", payload);
if (payload && payload.sessiontoken) { if (payload && payload.sessiontoken) {
@@ -121,7 +121,7 @@ const GoogleSignInBtn = ({
const LocalUserDetails = { const LocalUserDetails = {
name: details.Name, name: details.Name,
email: details.Gmail, email: details.Gmail,
phone: extRes.get("Phone"), phone: extRes?.get("Phone") || "",
company: extRes.get("Company") company: extRes.get("Company")
}; };
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails)); localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
@@ -139,7 +139,7 @@ const GoogleSignInBtn = ({
setThirdpartyLoader(true); setThirdpartyLoader(true);
// e.preventDefault() // e.preventDefault()
// console.log("handelSubmit", userDetails); // console.log("handelSubmit", userDetails);
const params = { ...googleDetails, Phone: userDetails.Phone }; const params = { ...googleDetails, Phone: userDetails?.Phone };
const payload = await Parse.Cloud.run("googlesign", params); const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload); // console.log("payload ", payload);
@@ -149,7 +149,7 @@ const GoogleSignInBtn = ({
name: userDetails.Name, name: userDetails.Name,
email: userDetails.Email, email: userDetails.Email,
// "passsword":userDetails.Phone, // "passsword":userDetails.Phone,
phone: userDetails.Phone, phone: userDetails?.Phone || "",
role: "contracts_User", role: "contracts_User",
company: userDetails.Company, company: userDetails.Company,
jobTitle: userDetails.Destination jobTitle: userDetails.Destination
@@ -161,7 +161,7 @@ const GoogleSignInBtn = ({
const LocalUserDetails = { const LocalUserDetails = {
name: userDetails.Name, name: userDetails.Name,
email: userDetails.Email, email: userDetails.Email,
phone: userDetails.Phone, phone: userDetails?.Phone || "",
company: userDetails.Company company: userDetails.Company
// jobTitle: userDetails.JobTitle // jobTitle: userDetails.JobTitle
}; };
@@ -207,45 +207,22 @@ const GoogleSignInBtn = ({
localStorage.setItem("parseAppId", appid); localStorage.setItem("parseAppId", appid);
}; };
return ( return (
<div style={{ position: "relative" }}> <div className="relative">
{thirdpartyLoader && ( {thirdpartyLoader && (
<div <div className="fixed flex justify-center items-center inset-0 bg-black bg-opacity-25 z-20 ">
style={{ <Loader />
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</div> </div>
)} )}
<div ref={googleBtn} className="text-sm"></div> <div ref={googleBtn} className="text-sm"></div>
<ModalUi showClose={false} isOpen={isModal} title="Sign up form"> <ModalUi showClose={false} isOpen={isModal} title="Sign up form">
<form className="px-4 py-3"> <form className="px-4 py-3 text-base-content">
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="Phone" className="block text-xs font-semibold">
htmlFor="Phone" Phone <span className="text-[13px] text-[red]">*</span>
style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold"
>
Phone <span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="tel" type="tel"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="Phone" id="Phone"
value={userDetails.Phone} value={userDetails.Phone}
onChange={(e) => onChange={(e) =>
@@ -258,16 +235,12 @@ const GoogleSignInBtn = ({
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="Company" className="block text-xs font-semibold">
htmlFor="Company" Company <span className="text-[13px] text-[red]">*</span>
style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold"
>
Company <span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="Company" id="Company"
value={userDetails.Company} value={userDetails.Company}
onChange={(e) => onChange={(e) =>
@@ -280,16 +253,12 @@ const GoogleSignInBtn = ({
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<label <label htmlFor="JobTitle" className="block text-xs font-semibold">
htmlFor="JobTitle" Job Title <span className="text-[13px] text-[red]">*</span>
style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold"
>
Job Title <span style={{ fontSize: 13, color: "red" }}>*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="JobTitle" id="JobTitle"
value={userDetails.Destination} value={userDetails.Destination}
onChange={(e) => onChange={(e) =>
@@ -301,20 +270,18 @@ const GoogleSignInBtn = ({
required required
/> />
</div> </div>
<div> <div className="flex flex-row gap-2">
<button <button
type="button" type="button"
className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none " className="op-btn op-btn-primary"
onClick={() => handleSubmitbtn()} onClick={() => handleSubmitbtn()}
style={{ marginRight: 10, backgroundColor: modalSubmitBtnColor }}
> >
Sign up Sign up
</button> </button>
<button <button
type="button" type="button"
className="p-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" className="op-btn op-btn-ghost"
onClick={handleCloseModal} onClick={handleCloseModal}
style={{ width: 90, backgroundColor: modalCancelBtnColor }}
> >
Cancel Cancel
</button> </button>
+3 -19
View File
@@ -4,27 +4,11 @@ import { Stage, Layer, Rect } from "react-konva";
const RenderDebugPdf = (props) => { const RenderDebugPdf = (props) => {
return ( return (
<div> <div>
<div <div className="sticky top-0 p-[10px] z-10 bg-white border-[1px] border-[gray] my-[5px]">
style={{
position: "sticky",
top: 0,
padding: 10,
zIndex: 1,
backgroundColor: "white",
border: "1px solid grey",
margin: "5px 0"
}}
>
{`Co-ordinates: X - ${props.hoverCoordinates.x}, Y - ${props.hoverCoordinates.y}`} {`Co-ordinates: X - ${props.hoverCoordinates.x}, Y - ${props.hoverCoordinates.y}`}
</div> </div>
<div <div
style={{ className="relative flex-1 cursor-crosshair border-[1px] border-[gray] overflow-auto"
flex: 1,
position: "relative",
border: "1px solid grey",
overflow: "auto",
cursor: "crosshair"
}}
onMouseMove={props.handleMouseMoveDiv} onMouseMove={props.handleMouseMoveDiv}
> >
<Document <Document
@@ -57,7 +41,7 @@ const RenderDebugPdf = (props) => {
onMouseUp={props.handleMouseUp} onMouseUp={props.handleMouseUp}
width={props.pdfDimension.width} width={props.pdfDimension.width}
height={props.pdfDimension.height} height={props.pdfDimension.height}
style={{ position: "absolute", top: 0, left: 0 }} className="absolute top-0 right-0"
> >
<Layer> <Layer>
{props.annotations {props.annotations
@@ -26,18 +26,18 @@ const DashboardButton = (props) => {
props.Data && props.Data.Redirect_type props.Data && props.Data.Redirect_type
? "cursor-pointer" ? "cursor-pointer"
: "cursor-default" : "cursor-default"
} w-full px-3 py-2 flex text-white rounded-md shadow overflow-hidden`} } w-full shadow-md px-3 py-2 op-card bg-base-100`}
> >
<div className="flex items-center justify-start gap-5"> <div className="flex flex-row items-center">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center"> <span className="rounded-full bg-base-content bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i <i
className={`${ className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info" props.Icon ? props.Icon : "fa fa-solid fa-info"
} text-[25px] lg:text-[30px]`} } text-[25px] lg:text-[30px]`}
></i> ></i>
</span> </span>
<div className=""> <div className="op-card-title text-lg ml-3 text-base-content">
<div className="text-base lg:text-lg text-black"> {props.Label}</div> {props.Label}
</div> </div>
</div> </div>
</div> </div>
@@ -336,25 +336,29 @@ const DashboardCard = (props) => {
props.Data && props.Data.Redirect_type props.Data && props.Data.Redirect_type
? "cursor-pointer" ? "cursor-pointer"
: "cursor-default" : "cursor-default"
} w-full h-[140px] px-3 pt-4 pb-10 text-white rounded-md shadow overflow-hidden relative`} }`}
> >
<div className="flex items-center justify-start gap-5"> <div className="flex items-center justify-start gap-5 text-white">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center"> <span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i <i
className={`${ className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info" props.Icon ? props.Icon : "fa fa-solid fa-info"
} text-[25px] lg:text-[30px]`} } text-[25px] lg:text-[30px]`}
></i> ></i>
</span> </span>
<div className=""> <div className="font-medium">
<div className="text-base lg:text-lg"> {props.Label}</div> <div className="text-base lg:text-lg"> {props.Label}</div>
<div className="text-2xl font-light"> <div className="text-2xl font-light">
{loading ? <div className="loader-01"></div> : setFormat(response)} {loading ? <div className="loader-01"></div> : setFormat(response)}
</div> </div>
</div> </div>
</div> </div>
<div className="text-xs absolute top-2 right-1"> <div className="text-xs absolute top-3 right-2">
<Tooltip id={props.Label} iconColor={"white"} message={props?.Data?.tourMessage} /> <Tooltip
id={props.Label}
iconColor={"white"}
message={props?.Data?.tourMessage}
/>
</div> </div>
</div> </div>
); );
@@ -3,6 +3,7 @@ import Parse from "parse";
import ReportTable from "../../primitives/GetReportDisplay"; import ReportTable from "../../primitives/GetReportDisplay";
import reportJson from "../../json/ReportJson"; import reportJson from "../../json/ReportJson";
import axios from "axios"; import axios from "axios";
import Loader from "../../primitives/Loader";
function DashboardReport(props) { function DashboardReport(props) {
// console.log("props ", props) // console.log("props ", props)
const [List, setList] = useState([]); const [List, setList] = useState([]);
@@ -121,21 +122,8 @@ function DashboardReport(props) {
return ( return (
<> <>
{isLoader ? ( {isLoader ? (
<div <div className="h-[250px] flex justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<> <>
@@ -18,51 +18,26 @@ const buttonList = [
]; ];
const GetDashboard = (props) => { const GetDashboard = (props) => {
const Button = ({ label, redirectId, redirectType, icon }) => ( const Button = ({ label, redirectId, redirectType, icon }) => (
<div className={"bg-white rounded-md shadow w-full"}> <DashboardButton
<Suspense Icon={icon}
fallback={ Label={label}
<div style={{ height: "300px" }}> Data={{ Redirect_type: redirectType, Redirect_id: redirectId }}
<div />
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<DashboardButton
Icon={icon}
Label={label}
Data={{ Redirect_type: redirectType, Redirect_id: redirectId }}
/>
</Suspense>
</div>
); );
const renderSwitchWithTour = (col) => { const renderSwitchWithTour = (col) => {
switch (col.widget.type) { switch (col.widget.type) {
case "Card": case "Card":
return ( return (
<div <div
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"} className={`${
col?.widget?.bgColor ? col.widget.bgColor : "bg-[#2ed8b6]"
} op-card w-full h-[140px] px-3 pt-4 mb-3 shadow-md"`}
data-tut={col.widget.data.tourSection} data-tut={col.widget.data.tourSection}
style={{ background: col.widget.bgColor }}
> >
<Suspense <Suspense
fallback={ fallback={
<div style={{ height: "300px" }}> <div className="h-[150px] w-full flex justify-center items-center">
<div loading...
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
} }
> >
@@ -72,7 +47,6 @@ const GetDashboard = (props) => {
Format={col.widget.format && col.widget.format} Format={col.widget.format && col.widget.format}
Data={col.widget.data} Data={col.widget.data}
FilterData={col.widget.filter} FilterData={col.widget.filter}
DefaultQuery={props.DefaultQuery}
/> />
</Suspense> </Suspense>
</div> </div>
@@ -89,7 +63,7 @@ const GetDashboard = (props) => {
); );
} }
default: default:
return null; return <></>;
} }
}; };
const renderSwitch = (col) => { const renderSwitch = (col) => {
@@ -97,8 +71,9 @@ const GetDashboard = (props) => {
case "Card": case "Card":
return ( return (
<div <div
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"} className={`${
style={{ background: col.widget.bgColor }} col?.widget?.bgColor ? col.widget.bgColor : "bg-[#2ed8b6]"
} op-card w-full h-[140px] px-3 pt-4 mb-3 shadow-md"`}
> >
<Suspense fallback={<div>please wait</div>}> <Suspense fallback={<div>please wait</div>}>
<DashboardCard <DashboardCard
@@ -107,7 +82,6 @@ const GetDashboard = (props) => {
Format={col.widget.format && col.widget.format} Format={col.widget.format && col.widget.format}
Data={col.widget.data} Data={col.widget.data}
FilterData={col.widget.filter} FilterData={col.widget.filter}
DefaultQuery={props.DefaultQuery}
/> />
</Suspense> </Suspense>
</div> </div>
@@ -122,7 +96,7 @@ const GetDashboard = (props) => {
); );
} }
default: default:
return null; return <></>;
} }
}; };
return ( return (
@@ -130,7 +104,7 @@ const GetDashboard = (props) => {
<div className="mb-3"> <div className="mb-3">
<div <div
data-tut={"tourbutton"} data-tut={"tourbutton"}
className="flex flex-col md:flex-row gap-6 md:gap-8" className="flex flex-col md:flex-row gap-4"
> >
{buttonList.map((btn) => ( {buttonList.map((btn) => (
<Button <Button
@@ -143,21 +117,19 @@ const GetDashboard = (props) => {
))} ))}
</div> </div>
</div> </div>
{props.dashboard.map((val, key) => ( <div className="grid grid-cols-12 w-full gap-x-4">
<div key={"a" + key} className="row"> {props?.dashboard?.columns?.map((col, i) =>
{val.columns.map((col, i) => col.widget.data && col.widget.data.tourSection ? (
col.widget.data && col.widget.data.tourSection ? ( <div key={i} className={col?.colsize}>
<div key={i} className={props.classnameArray[key][i]}> {renderSwitchWithTour(col)}
{renderSwitchWithTour(col)} </div>
</div> ) : (
) : ( <div key={i} className={col?.colsize}>
<div key={i} className={props.classnameArray[key][i]}> {renderSwitch(col)}
{renderSwitch(col)} </div>
</div> )
) )}
)} </div>
</div>
))}
</div> </div>
); );
}; };
@@ -9,7 +9,6 @@ import { useNavigate } from "react-router-dom";
import Table from "react-bootstrap/Table"; import Table from "react-bootstrap/Table";
import * as HoverCard from "@radix-ui/react-hover-card"; import * as HoverCard from "@radix-ui/react-hover-card";
import ModalUi from "../../primitives/ModalUi"; import ModalUi from "../../primitives/ModalUi";
import { themeColor } from "../../constant/const";
import FolderModal from "../shared/fields/FolderModal"; import FolderModal from "../shared/fields/FolderModal";
function DriveBody(props) { function DriveBody(props) {
@@ -313,32 +312,21 @@ function DriveBody(props) {
const signersName = () => { const signersName = () => {
const getSignersName = signerExist.map((data) => data.Name); const getSignersName = signerExist.map((data) => data.Name);
const signerName = getSignersName.join(","); const signerName = getSignersName.join(", ");
return ( return (
<span <span className="statusSpan w-[90%] break-words">{signerName}</span>
className="statusSpan"
style={{ width: "90%", wordWrap: "break-word" }}
>
{signerName}{" "}
</span>
); );
}; };
return listType === "table" ? ( return listType === "table" ? (
data.Type === "Folder" ? ( data.Type === "Folder" ? (
<tr onClick={() => handleOnclikFolder(data)}> <tr onClick={() => handleOnclikFolder(data)}>
<td <td className="cursor-pointer flex items-center">
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
<i <i
className="fa fa-folder" className="fa fa-folder mr-[8px] text-[26px] text-[#f0ad26]"
aria-hidden="true" aria-hidden="true"
style={{ color: "#f0ad26", marginRight: "8px", fontSize: "26px" }}
></i> ></i>
<span className="text-[12px] font-medium">{data.Name}</span>
<span style={{ fontSize: "12px", fontWeight: "500" }}>
{data.Name}
</span>
</td> </td>
<td>_</td> <td>_</td>
<td>Folder</td> <td>Folder</td>
@@ -347,17 +335,9 @@ function DriveBody(props) {
</tr> </tr>
) : ( ) : (
<tr onClick={() => checkPdfStatus(data)}> <tr onClick={() => checkPdfStatus(data)}>
<td <td className="cursor-pointer flex items-center">
style={{ cursor: "pointer", display: "flex", alignItems: "center" }} <i className="fa fa-file-pdf mr-[8px] text-[26px] text-[#ed4d0e]"></i>
> <span className="text-[12px] font-medium">{data.Name}</span>
<i
className="fa fa-file-pdf"
style={{ color: "#ed4d0e", marginRight: "8px", fontSize: "26px" }}
></i>
<span style={{ fontSize: "12px", fontWeight: "500" }}>
{data.Name}
</span>
</td> </td>
<td>{createddate}</td> <td>{createddate}</td>
<td>Pdf</td> <td>Pdf</td>
@@ -368,31 +348,22 @@ function DriveBody(props) {
e.stopPropagation(); e.stopPropagation();
handleMenuItemClick("Download", data); handleMenuItemClick("Download", data);
}} }}
className="fa fa-download" className="fa fa-download mr-[8px] text-[#ed280e]"
aria-hidden="true" aria-hidden="true"
style={{ color: "#ed280e", marginRight: "8px" }}
></i> ></i>
</td> </td>
</tr> </tr>
) )
) : listType === "list" && data.Type === "Folder" ? ( ) : listType === "list" && data.Type === "Folder" ? (
<div key={ind} className="folderBox"> <div key={ind} className="icon-container">
<ContextMenu.Root> <ContextMenu.Root>
<ContextMenu.Trigger className="ContextMenuTrigger"> <ContextMenu.Trigger className="ContextMenuTrigger">
<div <div data-tut={props.dataTutSeventh}>
style={{
display: "flex",
flexDirection: "column",
cursor: "pointer"
}}
data-tut={props.dataTutSeventh}
>
<img <img
alt="no img" alt="folder"
onClick={() => handleOnclikFolder(data)} onClick={() => handleOnclikFolder(data)}
src={folder} src={folder}
width={100} className="w-full h-full"
height={103}
/> />
{rename === data.objectId ? ( {rename === data.objectId ? (
<input <input
@@ -411,12 +382,7 @@ function DriveBody(props) {
defaultValue={renameValue} defaultValue={renameValue}
// value={renameValue} // value={renameValue}
onChange={(e) => setRenameValue(e.target.value)} onChange={(e) => setRenameValue(e.target.value)}
style={{ className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
width: "100px",
border: "1.5px solid black",
borderRadius: "2px",
fontSize: "10px"
}}
/> />
) : ( ) : (
<span className="foldName">{data.Name}</span> <span className="foldName">{data.Name}</span>
@@ -434,8 +400,8 @@ function DriveBody(props) {
onClick={() => handleMenuItemClick("Rename", data)} onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem" className="ContextMenuItem"
> >
<i className="fa-solid fa-font"></i> <i className="fa-solid fa-font mr-[8px]"></i>
<span style={{ marginLeft: "8px" }}>Rename</span> <span>Rename</span>
</ContextMenu.Item> </ContextMenu.Item>
</ContextMenu.Content> </ContextMenu.Content>
</ContextMenu.Portal> </ContextMenu.Portal>
@@ -450,7 +416,7 @@ function DriveBody(props) {
<ContextMenu.Trigger className="ContextMenuTrigger"> <ContextMenu.Trigger className="ContextMenuTrigger">
<img <img
alt="PDF" alt="PDF"
className="pdf-icon" className="w-full h-full"
src={pdfLogo} src={pdfLogo}
onClick={() => checkPdfStatus(data)} onClick={() => checkPdfStatus(data)}
data-tut={props.dataTutSixth} data-tut={props.dataTutSixth}
@@ -472,12 +438,7 @@ function DriveBody(props) {
defaultValue={renameValue} defaultValue={renameValue}
// value={renameValue} // value={renameValue}
onChange={(e) => setRenameValue(e.target.value)} onChange={(e) => setRenameValue(e.target.value)}
style={{ className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
width: "100px",
border: "1.5px solid black",
borderRadius: "2px",
fontSize: "10px"
}}
/> />
) : ( ) : (
<span className="fileName">{data.Name}</span> <span className="fileName">{data.Name}</span>
@@ -522,7 +483,7 @@ function DriveBody(props) {
className="ContextMenuItem" className="ContextMenuItem"
> >
<i className={menu.icon}></i> <i className={menu.icon}></i>
<span style={{ marginLeft: "8px" }}>{menu.type}</span> <span className="ml-[8px]">{menu.type}</span>
</ContextMenu.Item> </ContextMenu.Item>
); );
})} })}
@@ -533,21 +494,21 @@ function DriveBody(props) {
</HoverCard.Trigger> </HoverCard.Trigger>
<HoverCard.Portal> <HoverCard.Portal>
<HoverCard.Content className="HoverCardContent" sideOffset={5}> <HoverCard.Content className="HoverCardContent" sideOffset={5}>
<strong style={{ fontSize: "13px" }}>Title: </strong> <strong className="text-[13px]">Title: </strong>
<span className="statusSpan" style={{ marginBottom: "0px" }}> <span className="statusSpan" style={{ marginBottom: "0px" }}>
{" "} {" "}
{data.Name} {data.Name}
</span> </span>
<br /> <br />
<strong style={{ fontSize: "13px" }}>Status: </strong> <strong className="text-[13px]">Status: </strong>
<span className="statusSpan"> {status}</span> <span className="statusSpan"> {status}</span>
<br /> <br />
<strong style={{ fontSize: "13px" }}>Created Date: </strong> <strong className="text-[13px]">Created Date: </strong>
<span className="statusSpan">{createddate}</span> <span className="statusSpan">{createddate}</span>
<br /> <br />
{signerExist && ( {signerExist && (
<> <>
<strong style={{ fontSize: "13px" }}>Signers: </strong> <strong className="text-[13px]">Signers: </strong>
{/* <span className="statusSpan">kjefjjnejkfnkbjs bbfjkdsbjbfjkbjk kscbjkbjkb</span> */} {/* <span className="statusSpan">kjefjjnejkfnkbjs bbfjkdsbjbfjkbjk kscbjkbjkb</span> */}
{signersName()} {signersName()}
</> </>
@@ -587,13 +548,9 @@ function DriveBody(props) {
</Table> </Table>
</div> </div>
) : ( ) : (
<div className="pdfContainer"> <div className="flex flex-row flex-wrap items-center mt-1 pb-[20px] mx-[5px]">
{props.pdfData.map((data, ind) => { {props.pdfData.map((data, ind) => {
return ( return <div key={ind}>{handleFolderData(data, ind, "list")}</div>;
<div className="box" key={ind}>
{handleFolderData(data, ind, "list")}
</div>
);
})} })}
</div> </div>
)} )}
@@ -609,44 +566,23 @@ function DriveBody(props) {
)} )}
<ModalUi <ModalUi
isOpen={isDeleteDoc} isOpen={isDeleteDoc}
headerColor={themeColor}
title={"Delete Document"} title={"Delete Document"}
handleClose={() => { handleClose={() => setIsDeleteDoc(false)}
setIsDeleteDoc(false);
}}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px] text-base-content">
<p>Are you sure you want to delete this document?</p> <p>Are you sure you want to delete this document?</p>
<div className="h-[1px] w-full bg-[#9f9f9f] my-[15px]"></div>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => { onClick={() => handleDeleteDocument(selectDoc)}
handleDeleteDocument(selectDoc);
}}
style={{
background: themeColor,
color: "white"
}}
type="button" type="button"
className="finishBtn" className="op-btn op-btn-primary mr-2"
> >
Yes Yes
</button> </button>
<button <button
onClick={() => { onClick={() => setIsDeleteDoc(false)}
setIsDeleteDoc(false);
}}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-neutral"
> >
No No
</button> </button>
@@ -8,11 +8,8 @@ const AddRoleModal = (props) => {
isOpen={props.isModalRole} isOpen={props.isModalRole}
handleClose={props.handleCloseRoleModal} handleClose={props.handleCloseRoleModal}
> >
<div className="addusercontainer"> <div className="h-full py-[10px] px-[20px]">
<form <form className="flex flex-col" onSubmit={props.handleAddRole}>
style={{ display: "flex", flexDirection: "column" }}
onSubmit={props.handleAddRole}
>
<input <input
value={props.roleName} value={props.roleName}
onChange={(e) => props.setRoleName(e.target.value)} onChange={(e) => props.setRoleName(e.target.value)}
@@ -21,39 +18,20 @@ const AddRoleModal = (props) => {
? "User " + (props.signersdata.length + 1) ? "User " + (props.signersdata.length + 1)
: "User 1" : "User 1"
} }
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs mt-1"
/> />
<p <p className="text-[gray] text-[11px] mt-[5px] mb-[10px] ml-[10px]">
style={{
color: "grey",
fontSize: 11,
margin: "10px 0 10px 5px"
}}
>
e.g: Customer, Hr, Director, Manager, Student, etc... e.g: Customer, Hr, Director, Manager, Student, etc...
</p> </p>
<div> <div>
<div <div className="h-[1px] w-full bg-[#9f9f9f] mb-[10px]"></div>
style={{ <button type="submit" className="op-btn op-btn-primary">
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginBottom: "15px"
}}
></div>
<button
type="submit"
style={{
background: "#00a2b7"
}}
className="finishBtn"
>
Add Add
</button> </button>
<button <button
onClick={props.handleCloseRoleModal} onClick={props.handleCloseRoleModal}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost ml-2"
> >
Close Close
</button> </button>
@@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import { themeColor } from "../../constant/const";
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) { function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
const confirmToaddDefaultSign = () => { const confirmToaddDefaultSign = () => {
if (xyPostion.length > 0) { if (xyPostion.length > 0) {
@@ -17,55 +16,26 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
}; };
return ( return (
<div> <div data-tut="reactourThird">
<div <div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
style={{
background: themeColor,
color: "white",
padding: "5px",
fontFamily: "sans-serif",
marginTop: "5px"
}}
>
Signature Signature
</div> </div>
<div <div className="flex flex-col items-center mt-[10px] font-semibold">
style={{ <p className="text-base-content">Your Signature</p>
display: "flex", <div className="op-card shadow-md h-[111px] w-[90%] p-2">
flexDirection: "column", <img
alignItems: "center", alt="signature"
marginTop: "10px", className="w-full h-full object-contain"
fontWeight: "600" src={defaultSignImg}
}} />
> </div>
<> <button
<p>Your Signature</p> type="button"
<div className="defaultSignBox"> className="op-btn op-btn-primary op-btn-sm mt-[10px]"
<img onClick={() => confirmToaddDefaultSign()}
alt="default img" >
style={{ Auto Sign All
width: "100%", </button>
height: "100%",
objectFit: "contain"
}}
src={defaultSignImg}
/>
</div>
<button
style={{
background: themeColor,
color: "white",
marginTop: "20px",
cursor: "pointer",
marginBottom: "10px"
}}
type="button"
className="finishBtn finishnHover"
onClick={() => confirmToaddDefaultSign()}
>
Auto Sign All
</button>
</>
</div> </div>
</div> </div>
); );
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Loader from "../../primitives/LoaderWithMsg"; import LoaderWithMsg from "../../primitives/LoaderWithMsg";
import { contractDocument } from "../../constant/Utils"; import { contractDocument } from "../../constant/Utils";
import HandleError from "../../primitives/HandleError"; import HandleError from "../../primitives/HandleError";
function DraftDocument() { function DraftDocument() {
@@ -86,7 +86,7 @@ function DraftDocument() {
return ( return (
<div> <div>
{isLoading.isLoader ? ( {isLoading.isLoader ? (
<Loader isLoading={isLoading} /> <LoaderWithMsg isLoading={isLoading} />
) : ( ) : (
<HandleError handleError={isLoading.message} /> <HandleError handleError={isLoading.message} />
)} )}
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { isEnableSubscription, themeColor } from "../../constant/const"; import { isEnableSubscription } from "../../constant/const";
import ModalUi from "../../primitives/ModalUi"; import ModalUi from "../../primitives/ModalUi";
import { radioButtonWidget } from "../../constant/Utils"; import { radioButtonWidget } from "../../constant/Utils";
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader"; import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
@@ -147,7 +147,7 @@ function DropdownWidgetOption(props) {
return ( return (
<ModalUi isOpen={props.showDropdown} title={props.title} showClose={false}> <ModalUi isOpen={props.showDropdown} title={props.title} showClose={false}>
<div className="h-full p-[15px]"> <div className="h-full p-[15px] text-base-content">
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
@@ -155,38 +155,25 @@ function DropdownWidgetOption(props) {
}} }}
> >
<div> <div>
<label style={{ fontSize: "13px", fontWeight: "600" }}> <label className="text-[13px] font-semibold">
Name<span style={{ color: "red", fontSize: 13 }}> *</span> Name<span className="text-[red] text-[13px]"> *</span>
</label> </label>
<input <input
required required
defaultValue={dropdownName} defaultValue={dropdownName}
value={dropdownName} value={dropdownName}
onChange={(e) => setDropdownName(e.target.value)} onChange={(e) => setDropdownName(e.target.value)}
className="drodown-input" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
<label <label className="text-[13px] font-semibold mt-[5px]">
style={{ fontSize: "13px", fontWeight: "600", marginTop: "5px" }}
>
Options Options
</label> </label>
<div className="flex flex-col">
<div
style={{
display: "flex",
flexDirection: "column"
}}
>
{dropdownOptionList.map((option, index) => ( {dropdownOptionList.map((option, index) => (
<div <div
key={index} key={index}
style={{ className="flex flex-row mb-[5px] items-center"
display: "flex",
flexDirection: "row",
marginBottom: "5px",
alignItems: "center"
}}
> >
{props.type === "checkbox" && !props.isSignYourself && ( {props.type === "checkbox" && !props.isSignYourself && (
<input <input
@@ -206,51 +193,34 @@ function DropdownWidgetOption(props) {
setDefaultCheckbox(removeOption); setDefaultCheckbox(removeOption);
} }
}} }}
style={{ className="op-checkbox focus:outline-none hover:border-base-content mr-[5px]"
width: "23px",
height: "19px",
marginRight: "5px"
}}
/> />
)} )}
<input <input
required required
className="drodown-input" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
type="text" type="text"
value={option} value={option}
onChange={(e) => handleInputChange(index, e.target.value)} onChange={(e) => handleInputChange(index, e.target.value)}
/> />
<i <i
className="fa-solid fa-rectangle-xmark" className="fa-solid fa-rectangle-xmark text-[25px] ml-[10px] text-error"
onClick={() => handleDeleteInput(index)} onClick={() => handleDeleteInput(index)}
style={{
color: "red",
fontSize: "25px",
marginLeft: "10px"
}}
></i> ></i>
</div> </div>
))} ))}
<i <i
onClick={handleAddInput} onClick={handleAddInput}
style={{ className="fa-solid fa-square-plus text-[25px] ml-[10px] text-primary"
cursor: "pointer",
color: themeColor,
fontSize: "25px",
marginLeft: "10px"
}}
className="fa-solid fa-square-plus"
></i> ></i>
<div> <div>
{props.type === "checkbox" && !props.isSignYourself && ( {props.type === "checkbox" && !props.isSignYourself && (
<> <>
<label <label
style={{ className={`${
fontSize: "13px", !props.isSubscribe ? "text-[gray]" : ""
fontWeight: "600", } text-[13px] font-semibold`}
color: !props.isSubscribe && "gray"
}}
> >
Minimun check Minimun check
</label> </label>
@@ -263,18 +233,16 @@ function DropdownWidgetOption(props) {
const count = handleSetMinMax(e); const count = handleSetMinMax(e);
setMinCount(count); setMinCount(count);
}} }}
className={ className={`${
props.isSubscribe || !isEnableSubscription props.isSubscribe || !isEnableSubscription
? "drodown-input" ? ""
: "disabled drodown-input" : "pointer-events-none bg-opacity-50"
} } op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs`}
/> />
<label <label
style={{ className={`${
fontSize: "13px", !props.isSubscribe ? "text-[gray]" : ""
fontWeight: "600", } text-[13px] font-semibold`}
color: !props.isSubscribe && "gray"
}}
> >
Maximum check Maximum check
</label> </label>
@@ -286,11 +254,11 @@ function DropdownWidgetOption(props) {
const count = handleSetMinMax(e); const count = handleSetMinMax(e);
setMaxCount(count); setMaxCount(count);
}} }}
className={ className={`${
props.isSubscribe || !isEnableSubscription props.isSubscribe || !isEnableSubscription
? "drodown-input" ? ""
: "disabled drodown-input" : "pointer-events-none bg-opacity-50"
} } op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs`}
/> />
</> </>
)} )}
@@ -298,32 +266,22 @@ function DropdownWidgetOption(props) {
</div> </div>
{["dropdown", radioButtonWidget].includes(props.type) && ( {["dropdown", radioButtonWidget].includes(props.type) && (
<> <>
<label <label className="text-[13px] font-semibold mt-[5px]">
style={{
fontSize: "13px",
fontWeight: "600",
marginTop: "5px"
}}
>
Default value Default value
</label> </label>
<select <select
onChange={(e) => setDefaultValue(e.target.value)} onChange={(e) => setDefaultValue(e.target.value)}
className="drodown-input" className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
name="defaultvalue" name="defaultvalue"
value={defaultValue} value={defaultValue}
placeholder="select default value" placeholder="select default value"
> >
<option value="" disabled hidden style={{ fontSize: "13px" }}> <option value="" disabled hidden className="text-[13px]">
Select... Select...
</option> </option>
{dropdownOptionList.map((data, ind) => { {dropdownOptionList.map((data, ind) => {
return ( return (
<option <option className="text-[13px]" key={ind} value={data}>
style={{ fontSize: "13px" }}
key={ind}
value={data}
>
{data} {data}
</option> </option>
); );
@@ -333,35 +291,21 @@ function DropdownWidgetOption(props) {
)} )}
{props.type !== "checkbox" && props.type !== radioButtonWidget && ( {props.type !== "checkbox" && props.type !== radioButtonWidget && (
<> <>
<div <div className="flex flex-row gap-[10px] mt-[0.5rem]">
style={{
display: "flex",
flexDirection: "row",
gap: 10,
marginTop: "0.5rem"
}}
>
{statusArr.map((data, ind) => { {statusArr.map((data, ind) => {
return ( return (
<div <div
key={ind} key={ind}
style={{ className="flex flex-row gap-[5px] items-center"
display: "flex",
flexDirection: "row",
gap: 5,
alignItems: "center"
}}
> >
<input <input
style={{ accentColor: "red" }} className="op-radio op-radio-xs my-1"
type="radio" type="radio"
name="status" name="status"
onChange={() => setStatus(data.toLowerCase())} onChange={() => setStatus(data.toLowerCase())}
checked={status.toLowerCase() === data.toLowerCase()} checked={status.toLowerCase() === data.toLowerCase()}
/> />
<div style={{ fontSize: "13px", fontWeight: "500" }}> <div className="text-[13px] font-500">{data}</div>
{data}
</div>
</div> </div>
); );
})} })}
@@ -369,33 +313,31 @@ function DropdownWidgetOption(props) {
</> </>
)} )}
{["checkbox", radioButtonWidget].includes(props.type) && ( {["checkbox", radioButtonWidget].includes(props.type) && (
<div className="flex flex-row gap-5 mt-2 items-center text-center"> <div className="flex flex-row gap-5 my-2 items-center text-center">
{!props.isSignYourself && ( {!props.isSignYourself && (
<div> <div className="flex items-center">
<input <input
id="isreadonly" id="isreadonly"
type="checkbox" type="checkbox"
checked={isReadOnly} checked={isReadOnly}
onChange={(e) => { className="op-checkbox op-checkbox-sm"
setIsReadOnly(e.target.checked); onChange={(e) => setIsReadOnly(e.target.checked)}
}}
/> />
<label className="ml-1" htmlFor="isreadonly"> <label className="ml-1 mb-0" htmlFor="isreadonly">
Is read only Is read only
</label> </label>
</div> </div>
)} )}
<div> <div className="flex items-center">
<input <input
id="ishidelabel" id="ishidelabel"
type="checkbox" type="checkbox"
checked={isHideLabel} checked={isHideLabel}
onChange={(e) => { className="op-checkbox op-checkbox-sm"
setIsHideLabel(e.target.checked); onChange={(e) => setIsHideLabel(e.target.checked)}
}}
/> />
<label className="ml-1" htmlFor="ishidelabel"> <label className="ml-1 mb-0" htmlFor="ishidelabel">
Hide labels Hide labels
</label> </label>
</div> </div>
@@ -421,19 +363,15 @@ function DropdownWidgetOption(props) {
<button <button
disabled={dropdownOptionList.length === 0 && true} disabled={dropdownOptionList.length === 0 && true}
style={{
background: themeColor,
color: "white"
}}
type="submit" type="submit"
className={"finishBtn"} className="op-btn op-btn-primary"
> >
Save Save
</button> </button>
{props.currWidgetsDetails?.options?.values?.length > 0 && ( {props.currWidgetsDetails?.options?.values?.length > 0 && (
<button <button
type="submit" type="submit"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost ml-1"
onClick={() => { onClick={() => {
props.handleClose && props.handleClose(); props.handleClose && props.handleClose();
resetState(); resetState();
+104 -50
View File
@@ -1,6 +1,8 @@
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import "../../styles/AddUser.css"; import { checkIsSubscribed, getFileName } from "../../constant/Utils";
import { getFileName } from "../../constant/Utils"; import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const";
// import SelectFolder from "../../premitives/SelectFolder"; // import SelectFolder from "../../premitives/SelectFolder";
const EditTemplate = ({ template, onSuccess }) => { const EditTemplate = ({ template, onSuccess }) => {
@@ -9,9 +11,21 @@ const EditTemplate = ({ template, onSuccess }) => {
Name: template?.Name || "", Name: template?.Name || "",
Note: template?.Note || "", Note: template?.Note || "",
Description: template?.Description || "", Description: template?.Description || "",
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false" SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
AutomaticReminders: template?.AutomaticReminders || false,
RemindOnceInEvery: template?.RemindOnceInEvery || 5
}); });
const [isSubscribe, setIsSubscribe] = useState(false);
useEffect(() => {
fetchSubscription();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const fetchSubscription = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
}
};
const handleStrInput = (e) => { const handleStrInput = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value }); setFormData({ ...formData, [e.target.name]: e.target.value });
}; };
@@ -25,34 +39,40 @@ const EditTemplate = ({ template, onSuccess }) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const isChecked = formData.SendinOrder === "true" ? true : false; const isChecked = formData.SendinOrder === "true" ? true : false;
const data = { ...formData, SendinOrder: isChecked }; const AutoReminder = formData?.AutomaticReminders || false;
let reminderDate = {};
if (AutoReminder) {
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
const ReminderDate = new Date(template?.createdAt);
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
reminderDate = { NextReminderDate: ReminderDate };
}
const data = { ...formData, SendinOrder: isChecked, ...reminderDate };
onSuccess(data); onSuccess(data);
}; };
const handleAutoReminder = () => {
setFormData((prev) => ({
...prev,
AutomaticReminders: !formData.AutomaticReminders
}));
};
return ( return (
<div className="addusercontainer"> <div className="max-h-[300px] md:max-h-[400px] overflow-y-scroll p-[10px]">
<div className="form-wrapper"> <div className="text-base-content">
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div> <div>
<label htmlFor="name" style={{ fontSize: 13 }}> <label htmlFor="name" className="text-[13px]">
File File
</label> </label>
<div <div className="op-input op-input-bordered op-input-sm focus:outline-none py-2 font-semibold w-full text-xs">
style={{
padding: "0.5rem 0.75rem",
border: "1px solid #d1d5db",
borderRadius: "0.375rem",
fontSize: "0.75rem",
fontWeight: "700"
}}
>
{getFileName(template.URL)} {getFileName(template.URL)}
</div> </div>
</div> </div>
<div className="form-section"> <div className="form-section">
<label htmlFor="name" style={{ fontSize: 13 }}> <label htmlFor="name" className="text-[13px]">
Name Name
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[13px] text-[red]"> *</span>
</label> </label>
<input <input
type="text" type="text"
@@ -60,11 +80,11 @@ const EditTemplate = ({ template, onSuccess }) => {
value={formData.Name} value={formData.Name}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
required required
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="form-section"> <div className="form-section">
<label htmlFor="Note" style={{ fontSize: 13 }}> <label htmlFor="Note" className="text-[13px]">
Note Note
</label> </label>
<input <input
@@ -73,11 +93,11 @@ const EditTemplate = ({ template, onSuccess }) => {
id="Note" id="Note"
value={formData.Note} value={formData.Note}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="form-section"> <div className="form-section">
<label htmlFor="Description" style={{ fontSize: 13 }}> <label htmlFor="Description" className="text-[13px]">
Description Description
</label> </label>
<input <input
@@ -86,51 +106,85 @@ const EditTemplate = ({ template, onSuccess }) => {
id="Description" id="Description"
value={formData.Description} value={formData.Description}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="form-section"> <div className="form-section">
<label style={{ fontSize: 13 }}>Send In Order</label> <label className="text-[13px]">Send In Order</label>
<div <div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
style={{
display: "flex",
alignItems: "center",
gap: 8,
marginLeft: 8,
marginBottom: 5
}}
>
<input <input
type="radio" type="radio"
value={"true"} value={"true"}
className="op-radio op-radio-xs"
name="SendinOrder" name="SendinOrder"
checked={formData.SendinOrder === "true"} checked={formData.SendinOrder === "true"}
onChange={handleStrInput} onChange={handleStrInput}
/> />
<div style={{ fontSize: 12 }}>Yes</div> <div className="text-[12px]">Yes</div>
</div> </div>
<div <div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
style={{
display: "flex",
alignItems: "center",
gap: 8,
marginLeft: 8,
marginBottom: 5
}}
>
<input <input
type="radio" type="radio"
value={"false"} value={"false"}
name="SendinOrder" name="SendinOrder"
className="op-radio op-radio-xs"
checked={formData.SendinOrder === "false"} checked={formData.SendinOrder === "false"}
onChange={handleStrInput} onChange={handleStrInput}
/> />
<div style={{ fontSize: 12 }}>No</div> <div className="text-[12px]">No</div>
</div> </div>
</div> </div>
{/* <SelectFolder onSuccess={handleFolder} folderCls={"contracts_Template"} /> */} <div className="text-xs mt-2">
<div className="buttoncontainer"> {!isEnableSubscription && (
<button type="submit" className="submitbutton"> <PremiumAlertHeader
message={
"Disable Auto reminder is free in beta, this feature will incur a fee later."
}
/>
)}
<span
className={
isSubscribe || !isEnableSubscription
? "font-semibold"
: "font-semibold text-gray-300"
}
>
Auto reminder{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<label
className={`${
isSubscribe || !isEnableSubscription
? "cursor-pointer "
: "pointer-events-none opacity-50"
} relative block items-center mb-0`}
>
<input
checked={formData.AutomaticReminders}
onChange={handleAutoReminder}
type="checkbox"
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white mt-2"
/>
</label>
</div>
{isSubscribe && formData?.AutomaticReminders === true && (
<div className="text-xs mt-2">
<label className="block">
Remind once in every (Days)
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
type="number"
value={formData.RemindOnceInEvery}
name="RemindOnceInEvery"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
onChange={handleStrInput}
required
/>
</div>
)}
<div className="mt-[1rem] flex justify-start">
<button type="submit" className="op-btn op-btn-primary">
Submit Submit
</button> </button>
</div> </div>
+30 -40
View File
@@ -1,52 +1,42 @@
import React from "react"; import React from "react";
import Tooltip from "../../primitives/Tooltip"; import Tooltip from "../../primitives/Tooltip";
import ReactQuill from "react-quill"; import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css"; import "react-quill/dist/quill.snow.css";
import EditorToolbar, { module1, formats } from "./EditorToolbar"; import EditorToolbar, { module1, formats } from "./EditorToolbar";
export function EmailBody(props) { export function EmailBody(props) {
return ( return (
<React.Fragment> <form className="flex flex-col text-base-content text-lg font-normal">
<div className={`flex justify-center py-1 p-2`}> <div className="m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md">
<div className=" flex flex-col"> <label className="text-sm ml-2">
<form> Subject <Tooltip message={"email subject"} />
<div className="text-lg font-normal text-black"> </label>
<div className=" m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md"> <input
<label className="text-sm ml-2"> required
Subject <Tooltip message={"email subject"} /> value={props.requestSubject}
</label> onChange={(e) => props.setRequestSubject(e.target.value)}
<input placeholder='${senderName} has requested you to sign "${documentName}"'
required className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={props.requestSubject} />
onChange={(e) => props.setRequestSubject(e.target.value)} <label className="text-sm ml-2 mt-3">
placeholder='${senderName} has requested you to sign "${documentName}"' Body <Tooltip message={"email body"} />
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" </label>
/> <div className="px-3 py-2 w-full focus:outline-none text-xs">
<label className="text-sm ml-2 mt-3"> <EditorToolbar containerId="toolbar1" />
Body <Tooltip message={"email body"} /> <ReactQuill
</label> theme="snow"
value={props.requestBody}
<div className="px-3 py-2 w-full focus:outline-none text-xs"> // value={typedText}
<EditorToolbar containerId="toolbar1" /> placeholder="add body of email "
<ReactQuill // readOnly={loading}
theme="snow" // onChangeSelection={handleTextSelection} // Listen for text selection
value={props.requestBody} ref={props.editorRef}
// value={typedText} modules={module1}
placeholder="add body of email " formats={formats}
// readOnly={loading} onChange={props.handleOnchangeRequest}
// onChangeSelection={handleTextSelection} // Listen for text selection />
ref={props.editorRef}
modules={module1}
formats={formats}
onChange={props.handleOnchangeRequest}
/>
</div>
</div>
</div>
</form>
</div> </div>
</div> </div>
</React.Fragment> </form>
); );
} }
@@ -5,12 +5,11 @@ import axios from "axios";
import { getBase64FromUrl } from "../../constant/Utils"; import { getBase64FromUrl } from "../../constant/Utils";
import { themeColor } from "../../constant/const"; import { themeColor } from "../../constant/const";
import printModule from "print-js"; import printModule from "print-js";
import loader from "../../assets/images/loader2.gif"; import Loader from "../../primitives/Loader";
function EmailComponent({ function EmailComponent({
isEmail, isEmail,
pdfUrl, pdfUrl,
isCeleb,
setIsEmail, setIsEmail,
setSuccessEmail, setSuccessEmail,
pdfName, pdfName,
@@ -22,6 +21,7 @@ function EmailComponent({
const [emailList, setEmailList] = useState([]); const [emailList, setEmailList] = useState([]);
const [emailValue, setEmailValue] = useState(); const [emailValue, setEmailValue] = useState();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isEmailCelebration, setIsEmailCelebration] = useState(false);
//function for send email //function for send email
const sendEmail = async () => { const sendEmail = async () => {
setIsLoading(true); setIsLoading(true);
@@ -62,6 +62,10 @@ function EmailComponent({
" target=_blank>here</a> </p></div></div></body></html>" " target=_blank>here</a> </p></div></div></body></html>"
}; };
sendMail = await axios.post(url, params, { headers: headers }); sendMail = await axios.post(url, params, { headers: headers });
setIsEmailCelebration(true);
setTimeout(() => {
setIsEmailCelebration(false);
}, 3000);
} catch (error) { } catch (error) {
console.log("error", error); console.log("error", error);
setIsLoading(false); setIsLoading(false);
@@ -169,148 +173,59 @@ function EmailComponent({
<div className="modaloverlay"> <div className="modaloverlay">
<div className="modalcontainer"> <div className="modalcontainer">
{isLoading && ( {isLoading && (
<div <div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2] bg-opacity-80">
style={{ <Loader />
position: "absolute", <span className="text-[12px] font-bold">
height: "100%",
width: "100%",
display: "flex",
justifyContent: "center",
flexDirection: "column",
alignItems: "center",
zIndex: "20",
backgroundColor: "#e6f2f2",
opacity: 0.8
}}
>
<img
alt="no img"
src={loader}
style={{ width: "70px", height: "70px" }}
/>
<span style={{ fontSize: "12px", fontWeight: "bold" }}>
This might take some time This might take some time
</span> </span>
</div> </div>
)} )}
<div style={{ background: "#32a3ac" }} className="modalheader"> <div style={{ background: "#32a3ac" }} className="modalheader">
<span style={{ color: "white" }}>Successfully signed!</span> <span className="text-white">Successfully signed!</span>
<div className="flex flex-row">
<div style={{ display: "flex", flexDirection: "row" }}>
<div></div> <div></div>
{!isAndroid && ( {!isAndroid && (
<button <button
onClick={handleToPrint} onClick={handleToPrint}
style={{ className="op-btn op-btn-neutral op-btn-sm text-[15px]"
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
className="btn btn-primary btn-sm"
> >
<i <i className="fa fa-print" aria-hidden="true"></i>
className="fa fa-print"
style={{
fontSize: "15px",
marginRight: "3px",
color: "white"
}}
aria-hidden="true"
></i>
Print Print
</button> </button>
)} )}
<button <button
className="btn btn-danger btn-sm" className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()} onClick={() => handleDownloadPdf()}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
marginLeft: "10px"
}}
> >
<i <i className="fa fa-download" aria-hidden="true"></i>
className="fa fa-download"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Download Download
</button> </button>
</div> </div>
</div> </div>
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px]">
{isCeleb && ( {isEmailCelebration && (
<div <div className="absolute w-[100%] flex justify-center items-center">
style={{ <img alt="celeb" width={300} height={250} src={celebration} />
position: "absolute",
marginLeft: "50px"
}}
>
<img
alt="print img"
width={300}
height={250}
// style={styles.gifCeleb}
src={celebration}
/>
</div> </div>
)} )}
<p <p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
style={{
fontFamily: "system-ui",
verticalAlign: "baseline",
fontWeight: "500",
color: "#403f3e",
fontSize: "15px",
marginBottom: "5px"
}}
>
Recipients added here will get a copy of the signed document. Recipients added here will get a copy of the signed document.
</p> </p>
{emailList.length > 0 ? ( {emailList.length > 0 ? (
<> <>
<div className="addEmail"> <div className="addEmail">
<div <div className="flex flex-row flex-wrap">
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap"
}}
>
{emailList.map((data, ind) => { {emailList.map((data, ind) => {
return ( return (
<div <div
className="emailChip" className="flex flex-row items-center bg-[#47a3ad] m-[4px] rounded-md py-[5px] px-[10px]"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
key={ind} key={ind}
> >
<span <span className="text-white text-[13px]">
style={{
color: "white",
fontSize: "13px"
}}
>
{data} {data}
</span> </span>
<span <span
style={{ className="text-white text-[13px] font-semibold ml-[7px] cursor-pointer"
color: "white",
fontSize: 13,
fontWeight: 600,
marginLeft: 7,
cursor: "pointer"
}}
onClick={() => removeChip(ind)} onClick={() => removeChip(ind)}
> >
<i className="fa-solid fa-xmark"></i> <i className="fa-solid fa-xmark"></i>
@@ -323,7 +238,7 @@ function EmailComponent({
<input <input
type="text" type="text"
value={emailValue} value={emailValue}
className="addEmailInput" className="p-[10px] pb-[20px] rounded w-full text-[15px] bg-white outline-none"
onChange={handleEmailValue} onChange={handleEmailValue}
onKeyDown={handleEnterPress} onKeyDown={handleEnterPress}
onBlur={() => { onBlur={() => {
@@ -341,7 +256,7 @@ function EmailComponent({
<input <input
type="text" type="text"
value={emailValue} value={emailValue}
className="emailInput" className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-white border-2 border-[#47a3ad]"
onChange={handleEmailValue} onChange={handleEmailValue}
onKeyDown={handleEnterPress} onKeyDown={handleEnterPress}
placeholder="Add the email addresses" placeholder="Add the email addresses"
@@ -354,67 +269,36 @@ function EmailComponent({
/> />
</div> </div>
)} )}
<span <button
style={{ className={`${
cursor: emailValue && "pointer" emailValue ? "cursor-pointer" : "cursor-default"
}} } op-btn op-btn-primary op-btn-sm m-2 shadow-md`}
onClick={() => { onClick={() => {
if (emailValue) { if (emailValue) {
handleEnterPress("add"); handleEnterPress("add");
} }
}} }}
> >
<i <i className="fa fa-plus" aria-hidden="true"></i>
style={{ </button>
backgroundColor: themeColor,
padding: "5px 7px",
marginTop: "10px",
color: "white",
borderRadius: "2px"
}}
className="fa fa-plus"
aria-hidden="true"
></i>
</span>
<div <div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
style={{ <span className="font-bold">Note: </span>
background: "#e3e2e1", <span className="text-[15px]">
marginTop: "10px",
padding: "5px",
borderRadius: "3px"
}}
>
<span style={{ fontWeight: "700" }}>Note:</span>
<span style={{ fontSize: "15px" }}>
{" "}
You can only send to ten recipients at a time. You can only send to ten recipients at a time.
</span> </span>
</div> </div>
<div <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
disabled={emailList.length === 0 && true}
style={{
background: themeColor,
color: "white"
}}
type="button" type="button"
className={emailList.length === 0 ? "defaultBtn" : "finishBtn"} className="op-btn op-btn-primary"
onClick={() => sendEmail()} onClick={() => emailList.length > 0 && sendEmail()}
> >
Send Send
</button> </button>
<button <button
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost ml-2"
onClick={() => { onClick={() => {
setIsEmail(false); setIsEmail(false);
setEmailValue(""); setEmailValue("");
+173 -302
View File
@@ -1,15 +1,15 @@
import React, { useState } from "react"; import React, { useState } from "react";
import PrevNext from "./PrevNext"; import PrevNext from "./PrevNext";
import printModule from "print-js"; import {
import { getBase64FromUrl } from "../../constant/Utils"; handleDownloadCertificate,
import { saveAs } from "file-saver"; handleDownloadPdf,
handleToPrint
} from "../../constant/Utils";
import "../../styles/signature.css"; import "../../styles/signature.css";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { themeColor } from "../../constant/const";
import axios from "axios";
import ModalUi from "../../primitives/ModalUi"; import ModalUi from "../../primitives/ModalUi";
import { appInfo } from "../../constant/appinfo"; import Loader from "../../primitives/Loader";
function Header({ function Header({
isPdfRequestFiles, isPdfRequestFiles,
@@ -40,16 +40,9 @@ function Header({
signerPos && signerPos?.filter((data) => data.Role !== "prefill"); signerPos && signerPos?.filter((data) => data.Role !== "prefill");
const isMobile = window.innerWidth < 767; const isMobile = window.innerWidth < 767;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCertificate, setIsCertificate] = useState(false); const [isDownloading, setIsDownloading] = useState("");
const isGuestSigner = localStorage.getItem("isGuestSigner"); const isGuestSigner = localStorage.getItem("isGuestSigner");
//for go to previous page
function previousPage() {
changePage(-1);
}
//for go to next page
function nextPage() {
changePage(1);
}
//function for show decline alert //function for show decline alert
const handleDeclinePdfAlert = async () => { const handleDeclinePdfAlert = async () => {
const currentDecline = { const currentDecline = {
@@ -59,123 +52,6 @@ function Header({
setIsDecline(currentDecline); setIsDecline(currentDecline);
}; };
//function for print digital sign pdf
const handleToPrint = async (event) => {
event.preventDefault();
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
`${appInfo.baseUrl}/functions/getsignedurl`,
{ url: pdfUrl },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": appInfo.appId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
const pdf = await getBase64FromUrl(url);
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" &&
navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(
atob(pdf)
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank");
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
}
} catch (err) {
console.log("err in getsignedurl", err);
alert("something went wrong, please try again later.");
}
};
//handle download signed pdf
const handleDownloadPdf = async () => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
`${appInfo.baseUrl}/functions/getsignedurl`,
{ url: pdfUrl },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": appInfo.appId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
} catch (err) {
console.log("err in getsignedurl", err);
alert("something went wrong, please try again later.");
}
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
//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);
}
} else {
setIsCertificate(true);
try {
const data = {
docId: pdfDetails[0]?.objectId
};
const docDetails = await axios.post(
`${localStorage.getItem("baseUrl")}functions/getDocument`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
}
);
if (docDetails.data && docDetails.data.result) {
const doc = docDetails.data.result;
if (doc?.CertificateUrl) {
await fetch(doc?.CertificateUrl);
const certificateUrl = doc?.CertificateUrl;
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
setIsCertificate(false);
} else {
setIsCertificate(true);
}
}
} catch (err) {
console.log("err in download in certificate", err);
alert("something went wrong, please try again later.");
}
}
};
return ( return (
<div style={{ padding: "5px 0px 5px 0px" }} className="mobileHead"> <div style={{ padding: "5px 0px 5px 0px" }} className="mobileHead">
{isMobile && isShowHeader ? ( {isMobile && isShowHeader ? (
@@ -188,56 +64,22 @@ function Header({
: window.innerWidth - 30 + "px" : window.innerWidth - 30 + "px"
}} }}
> >
<div className="preBtn2"> <div className="flex justify-between items-center py-[5px] px-[10px] ">
<div onClick={() => navigate(-1)}> <div onClick={() => navigate(-1)}>
<i <i
className="fa fa-arrow-left" className="fa fa-arrow-left text-base-content"
aria-hidden="true" aria-hidden="true"
style={{ color: themeColor, cursor: "pointer" }}
></i>
</div>
<div>
<i
onClick={() => {
if (pageNumber > 1) {
previousPage();
}
}}
className="fa fa-backward"
style={{ color: "gray", cursor: "pointer" }}
></i>
<span
style={{
fontSize: "13px",
fontWeight: "600",
marginLeft: "10px",
marginRight: "10px"
}}
>
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
</span>
<i
onClick={() => {
if (pageNumber < allPages) {
nextPage();
}
}}
className="fa fa-forward"
style={{ color: "gray", cursor: "pointer" }}
></i> ></i>
</div> </div>
<PrevNext
pageNumber={pageNumber}
allPages={allPages}
changePage={changePage}
/>
{pdfUrl && alreadySign ? ( {pdfUrl && alreadySign ? (
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger asChild> <DropdownMenu.Trigger asChild>
<div <div className="op-link op-link-primary no-underline text-[16px] font-semibold pr-[3px] pl-[5px]">
style={{
color: themeColor,
border: "none",
fontWeight: "650",
fontSize: "16px",
padding: "0px 3px 0px 5px"
}}
>
<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>
@@ -248,18 +90,14 @@ function Header({
> >
<DropdownMenu.Item <DropdownMenu.Item
className="DropdownMenuItem" className="DropdownMenuItem"
onClick={() => handleDownloadPdf()} onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
> >
<div <div className="flex flex-row">
style={{
display: "flex",
flexDirection: "row"
}}
>
<i <i
className="fa fa-arrow-down" className="fa fa-arrow-down mr-[2px]"
aria-hidden="true" aria-hidden="true"
style={{ marginRight: "2px" }}
></i> ></i>
Download Download
</div> </div>
@@ -267,17 +105,16 @@ function Header({
{isCompleted && ( {isCompleted && (
<DropdownMenu.Item <DropdownMenu.Item
className="DropdownMenuItem" className="DropdownMenuItem"
onClick={() => handleDownloadCertificate()} onClick={() =>
handleDownloadCertificate(
pdfDetails,
setIsDownloading
)
}
> >
<div <div className="border-none bg-[#fff]">
style={{
border: "none",
backgroundColor: "#fff"
}}
>
<i <i
className="fa-solid fa-award" className="fa-solid fa-award mr-[2px]"
style={{ marginRight: "2px" }}
aria-hidden="true" aria-hidden="true"
></i> ></i>
Certificate Certificate
@@ -289,15 +126,9 @@ function Header({
className="DropdownMenuItem" className="DropdownMenuItem"
onClick={() => setIsEmail(true)} onClick={() => setIsEmail(true)}
> >
<div <div className="flex flex-row">
style={{
display: "flex",
flexDirection: "row"
}}
>
<i <i
className="fa fa-envelope" className="fa fa-envelope mr-[2px]"
style={{ marginRight: "2px" }}
aria-hidden="true" aria-hidden="true"
></i> ></i>
Mail Mail
@@ -306,18 +137,14 @@ function Header({
)} )}
<DropdownMenu.Item <DropdownMenu.Item
className="DropdownMenuItem" className="DropdownMenuItem"
onClick={handleToPrint} onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading)
}
> >
<div <div className="flex flex-row">
style={{
display: "flex",
flexDirection: "row"
}}
>
<i <i
className="fa fa-print" className="fa fa-print mr-[2px]"
aria-hidden="true" aria-hidden="true"
style={{ marginRight: "2px" }}
></i> ></i>
Print Print
</div> </div>
@@ -326,24 +153,16 @@ function Header({
</DropdownMenu.Portal> </DropdownMenu.Portal>
</DropdownMenu.Root> </DropdownMenu.Root>
) : ( ) : (
<div style={{ display: "flex", justifyContent: "space-around" }}> <div className="flex justify-around items-center">
{/* current signer is checking user send request and check status of pdf sign than if current {/* current signer is checking user send request and check status of pdf sign than if current
user exist than show finish button else no user exist than show finish button else no
*/} */}
{currentSigner && ( {currentSigner && (
<> <div className="flex items-center" data-tut="reactourFifth">
{decline && ( {decline && (
<div <div
onClick={() => { onClick={() => handleDeclinePdfAlert()}
handleDeclinePdfAlert(); className="text-[red] border-none font-[650] text-[14px] mr-2"
}}
style={{
color: "red",
border: "none",
fontWeight: "650",
fontSize: "16px",
marginRight: "10px"
}}
> >
Decline Decline
</div> </div>
@@ -355,12 +174,9 @@ function Header({
alertSendEmail(); alertSendEmail();
} }
}} }}
style={{ className={`${
color: isMailSend ? "gray" : themeColor, isMailSend ? "" : "op-link-primary"
border: "none", } op-link no-underline font-[650] text-[14px]`}
fontWeight: "650",
fontSize: "16px"
}}
data-tut={dataTut4} data-tut={dataTut4}
> >
{completeBtnTitle ? completeBtnTitle : "Send"} {completeBtnTitle ? completeBtnTitle : "Send"}
@@ -375,17 +191,45 @@ function Header({
embedWidgetsData(); embedWidgetsData();
} }
}} }}
style={{ className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
color: themeColor,
border: "none",
fontWeight: "650",
fontSize: "16px"
}}
> >
Finish Finish
</div> </div>
)} )}
</> <DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<div className="font-[650] text-[18px] px-2 ml-[4px] op-link op-link-info no-underline">
<i
className="fa fa-ellipsis-v"
aria-hidden="true"
></i>
</div>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
className="bg-white shadow-md rounded px-2 py-1"
sideOffset={5}
>
<DropdownMenu.Item
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
}
>
<i
className="fa fa-arrow-down mr-[5px]"
aria-hidden="true"
></i>
<span className="font-[500]">Download</span>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div>
)} )}
</div> </div>
)} )}
@@ -406,12 +250,12 @@ function Header({
signersdata.length !== filterPrefill.length && ( signersdata.length !== filterPrefill.length && (
<div> <div>
{filterPrefill.length === 0 ? ( {filterPrefill.length === 0 ? (
<span style={{ fontSize: "13px", color: "#f5405e" }}> <span className="text-[13px] text-[#f5405e]">
Add {signersdata.length - filterPrefill.length}{" "} Add {signersdata.length - filterPrefill.length}{" "}
recipients signature recipients signature
</span> </span>
) : ( ) : (
<span style={{ fontSize: "13px", color: "#f5405e" }}> <span className="text-[13px] text-[#f5405e]">
Add {signersdata.length - filterPrefill.length} more Add {signersdata.length - filterPrefill.length} more
recipients signature recipients signature
</span> </span>
@@ -431,158 +275,175 @@ function Header({
<button <button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white" className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
> >
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]" className="op-btn op-btn-primary op-btn-sm mr-[5px]"
style={{ onClick={() => alertSendEmail()}
background: isMailSend ? "rgb(203, 203, 203)" : "#188ae2",
color: isMailSend ? "rgb(77, 75, 75)" : "white"
}}
onClick={() => {
alertSendEmail();
}}
> >
{completeBtnTitle {completeBtnTitle
? completeBtnTitle ? completeBtnTitle
: isMailSend : isMailSend
? "Sent" ? "Sent"
: "Send"} : "Send"}
</button> </button>
</div> </div>
</> </>
) : isPdfRequestFiles ? ( ) : isPdfRequestFiles ? (
alreadySign ? ( alreadySign ? (
<div style={{ display: "flex", flexDirection: "row" }}> <div className="flex flex-row">
{isCompleted && ( {isCompleted && (
<button <button
type="button" type="button"
onClick={() => handleDownloadCertificate()} onClick={() =>
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]" handleDownloadCertificate(pdfDetails, setIsDownloading)
}
className="op-btn op-btn-secondary op-btn-sm mr-[5px] shadow"
> >
<i <i
className="fa-solid fa-award py-[3px]" className="fa-solid fa-award py-[3px]"
aria-hidden="true" aria-hidden="true"
></i> ></i>
<span className="hidden lg:block ml-1">Certificate</span> <span className="hidden lg:block">Certificate</span>
</button> </button>
)} )}
<button <button
onClick={handleToPrint} onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]" className="op-btn op-btn-neutral op-btn-sm mr-[5px] shadow"
> >
<i className="fa fa-print py-[3px]" aria-hidden="true"></i> <i className="fa fa-print py-[3px]" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Print</span> <span className="hidden lg:block">Print</span>
</button> </button>
<button <button
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]" className="op-btn op-btn-primary op-btn-sm mr-[5px] shadow"
onClick={() => handleDownloadPdf()} onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
> >
<i className="fa fa-download py-[3px]" aria-hidden="true"></i> <i className="fa fa-download py-[3px]" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Download</span> <span className="hidden lg:block">Download</span>
</button> </button>
</div> </div>
) : ( ) : (
<div className="flex"> <div className="flex" data-tut="reactourFifth">
<button <button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white" className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
> >
Back Back
</button> </button>
{currentSigner && ( {currentSigner && (
<> <>
<button <button
style={{ background: "#de4337" }} className="op-btn op-btn-secondary op-btn-sm mr-[5px] shadow"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]" onClick={() => handleDeclinePdfAlert()}
onClick={() => {
handleDeclinePdfAlert();
}}
> >
Decline Decline
</button> </button>
<button <button
style={{
background: "#188ae2"
}}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]" className="op-btn op-btn-primary op-btn-sm mr-[5px] shadow"
onClick={() => { onClick={() => embedWidgetsData()}
embedWidgetsData();
}}
> >
Finish Finish
</button> </button>
<div className="op-dropdown op-dropdown-end">
<div
tabIndex={0}
role="button"
className="op-btn op-btn-info op-btn-sm shadow"
>
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
</div>
<ul
tabIndex={0}
className="op-dropdown-content z-[1] op-menu op-menu-sm p-1 shadow bg-base-100 rounded-box mt-1"
>
<li
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
}
>
<span className="font-semibold text-[12px]">
<i
className="fa fa-arrow-down"
aria-hidden="true"
></i>{" "}
Download
</span>
</li>
</ul>
</div>
</> </>
)} )}
</div> </div>
) )
) : isCompleted ? ( ) : isCompleted ? (
<div style={{ display: "flex", flexDirection: "row" }}> <div className="flex flex-row">
{isCompleted && ( {isCompleted && (
<button <button
type="button" type="button"
onClick={() => handleDownloadCertificate()} onClick={() =>
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#08bc66]" handleDownloadCertificate(pdfDetails, setIsDownloading)
}
className="op-btn op-btn-secondary op-btn-sm font-medium text-[13px] mr-[5px] shadow"
> >
<i <i className="fa-solid fa-award" aria-hidden="true"></i>
className="fa-solid fa-award py-[3px]" <span className="hidden lg:block">Certificate</span>
aria-hidden="true"
></i>
<span className="hidden lg:block ml-1">Certificate</span>
</button> </button>
)} )}
<button <button
onClick={handleToPrint} onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]" className="op-btn op-btn-neutral op-btn-sm font-medium text-[13px] mr-[5px] shadow"
> >
<i className="fa fa-print py-[3px]" aria-hidden="true"></i> <i className="fa fa-print" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Print</span> <span className="hidden lg:block">Print</span>
</button> </button>
<button <button
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#f14343]" className="op-btn op-btn-primary op-btn-sm font-medium text-[13px] mr-[5px] shadow"
onClick={() => handleDownloadPdf()} onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
> >
<i className="fa fa-download py-[3px]" aria-hidden="true"></i> <i className="fa fa-download" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Download</span> <span className="hidden lg:block">Download</span>
</button> </button>
<button <button
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[11px] text-white font-[500] text-[13px] mr-[5px] bg-[#3ba7e5]" className="op-btn op-btn-info op-btn-sm font-medium text-[13px] mr-[5px] shadow"
onClick={() => setIsEmail(true)} onClick={() => setIsEmail(true)}
> >
<i className="fa fa-envelope py-[3px]" aria-hidden="true"></i> <i className="fa fa-envelope" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Mail</span> <span className="hidden lg:block">Mail</span>
</button> </button>
</div> </div>
) : ( ) : (
<div className="flex"> <div className="flex">
<button <button
onClick={() => { onClick={() => navigate(-1)}
navigate(-1);
}}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-black font-[500] text-sm mr-[5px] bg-white" className="op-btn op-btn-ghost op-btn-sm mr-[5px]"
> >
Back Back
</button> </button>
<button <button
style={{
background: "#188ae2"
}}
type="button" type="button"
className="flex flex-row items-center shadow rounded-[3px] py-[3px] px-[18px] text-white font-[500] text-[13px] mr-[5px] bg-[#188ae2]" className="op-btn op-btn-primary op-btn-sm mr-[5px]"
onClick={() => { onClick={() => {
if (!pdfUrl) { if (!pdfUrl) {
embedWidgetsData(); embedWidgetsData();
@@ -595,12 +456,22 @@ function Header({
)} )}
</div> </div>
)} )}
{isDownloading === "pdf" && (
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<ModalUi <ModalUi
isOpen={isCertificate} isOpen={isDownloading === "certificate"}
title={"Generating certificate"} title={
handleClose={() => setIsCertificate(false)} isDownloading === "certificate"
? "Generating certificate"
: "PDF Download"
}
handleClose={() => setIsDownloading("")}
> >
<div className="p-3 md:p-5 text-[13px] md:text-base text-center"> <div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
{isDownloading === "certificate"}{" "}
<p> <p>
Your completion certificate is being generated. Please wait Your completion certificate is being generated. Please wait
momentarily. momentarily.
@@ -1,5 +1,4 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { themeColor } from "../../constant/const";
import ModalUi from "../../primitives/ModalUi"; import ModalUi from "../../primitives/ModalUi";
import { randomId, textWidget } from "../../constant/Utils"; import { randomId, textWidget } from "../../constant/Utils";
@@ -195,13 +194,13 @@ function PlaceholderCopy(props) {
props.setIsPageCopy(false); props.setIsPageCopy(false);
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px] text-base-content">
{copyType.map((data, key) => { {copyType.map((data, key) => {
return ( return (
<div key={key} style={{ display: "flex", flexDirection: "column" }}> <div key={key} className="flex flex-col">
<label key={key} style={{ fontSize: "16px", fontWeight: "500" }}> <label className="text-[16px] font-medium">
<input <input
style={{ accentColor: "red", marginRight: "10px" }} className="mr-[8px] op-radio op-radio-xs"
type="radio" type="radio"
value={data} value={data}
onChange={() => setSelectCopyType(data)} onChange={() => setSelectCopyType(data)}
@@ -214,33 +213,22 @@ function PlaceholderCopy(props) {
); );
})} })}
<div <div className="flex bg-[#9f9f9f] w-full my-[15px]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => { onClick={() => {
handleApplyCopy(); handleApplyCopy();
handleUniqueId(); handleUniqueId();
}} }}
style={{ background: themeColor }}
type="button" type="button"
disabled={!selectCopyType} disabled={!selectCopyType}
className="finishBtn" className="op-btn op-btn-primary"
> >
Apply Apply
</button> </button>
<button <button
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost"
onClick={() => { onClick={() => handleUniqueId()}
handleUniqueId();
}}
> >
Cancel Cancel
</button> </button>
@@ -352,12 +352,9 @@ function PlaceholderType(props) {
return ( return (
<div key={ind} className="flex items-center text-center gap-0.5"> <div key={ind} className="flex items-center text-center gap-0.5">
<input <input
style={{ className={`${
// width: props.pos.Width, ind === 0 ? "mt-0" : "mt-[5px]"
display: "flex", } flex justify-center op-checkbox op-checkbox-xs rounded-[0.350rem]`}
justifyContent: "center",
marginTop: ind === 0 ? 0 : "5px"
}}
onBlur={handleInputBlur} onBlur={handleInputBlur}
disabled={ disabled={
props.isNeedSign && props.isNeedSign &&
@@ -425,7 +422,7 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap" }} style={{ whiteSpace: "pre-wrap", color: "initial" }}
cols="50" cols="50"
/> />
) : ( ) : (
@@ -443,7 +440,7 @@ function PlaceholderType(props) {
<select <select
className="inputPlaceholder" className="inputPlaceholder"
id="myDropdown" id="myDropdown"
style={{ fontSize: "12px" }} style={{ fontSize: "12px", color: "initial" }}
value={selectOption} value={selectOption}
onChange={(e) => { onChange={(e) => {
setSelectOption(e.target.value); setSelectOption(e.target.value);
@@ -528,7 +525,7 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap" }} style={{ whiteSpace: "pre-wrap", color: "initial" }}
cols="50" cols="50"
/> />
) : ( ) : (
@@ -567,7 +564,7 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap" }} style={{ whiteSpace: "pre-wrap", color: "initial" }}
cols="50" cols="50"
/> />
) : ( ) : (
@@ -606,7 +603,7 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap" }} style={{ whiteSpace: "pre-wrap", color: "initial" }}
cols="50" cols="50"
/> />
) : ( ) : (
@@ -728,7 +725,7 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap" }} style={{ whiteSpace: "pre-wrap", color: "initial" }}
cols="50" cols="50"
/> />
) : ( ) : (
@@ -748,12 +745,11 @@ function PlaceholderType(props) {
return ( return (
<div key={ind} className="flex items-center text-center gap-0.5"> <div key={ind} className="flex items-center text-center gap-0.5">
<input <input
style={{ className={`${ind === 0 ? "mt-0" : "mt-[5px]"} ${
width: props.pos.Width, props?.pos?.Width
display: "flex", ? `w-[${props?.pos?.Width}px] h-[${props?.pos?.Width}px]`
justifyContent: "center", : "w-[15px] h-[15px]"
marginTop: ind === 0 ? 0 : "5px" } flex justify-center op-radio`}
}}
type="radio" type="radio"
disabled={ disabled={
props.isNeedSign && props.isNeedSign &&
@@ -800,7 +796,11 @@ function PlaceholderType(props) {
? "labelTextArea labelWidthMobile" ? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop" : "labelTextArea labelWidthDesktop"
} }
style={{ whiteSpace: "pre-wrap", overflow: "hidden" }} style={{
whiteSpace: "pre-wrap",
overflow: "hidden",
color: "initial"
}}
cols="50" cols="50"
/> />
); );
+23 -34
View File
@@ -1,5 +1,4 @@
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
@@ -12,40 +11,30 @@ function PrevNext({ pageNumber, allPages, changePage }) {
} }
return ( return (
<div> <div className="flex items-center">
<div className="preBtn1"> <button
<button className="op-btn op-btn-secondary op-btn-xs md:op-btn-sm font-semibold text-xs"
className="py-[3px] px-[10px] text-xs bg-[#d3edeb] font-[600] mr-[5px]" disabled={pageNumber <= 1}
disabled={pageNumber <= 1} onClick={previousPage}
onClick={previousPage} >
> <span className="block lg:hidden">
<span className="block lg:hidden"> <i className="fa fa-backward" aria-hidden="true"></i>
<i
className="fa fa-backward"
aria-hidden="true"
style={{ color: themeColor, cursor: "pointer" }}
></i>
</span>
<span className="lg:block hidden">Prev</span>
</button>
<span className="text-xs font-[500]">
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
</span> </span>
<button <span className="lg:block hidden">Prev</span>
className="py-[3px] px-[10px] text-xs bg-[#d3edeb] font-[600] ml-[5px]" </button>
disabled={pageNumber >= allPages} <span className="text-xs text-base-content font-medium mx-2">
onClick={nextPage} {pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
> </span>
<span className="block lg:hidden"> <button
<i className="op-btn op-btn-secondary op-btn-xs md:op-btn-sm font-semibold text-xs"
className="fa fa-forward" disabled={pageNumber >= allPages}
aria-hidden="true" onClick={nextPage}
style={{ color: themeColor, cursor: "pointer" }} >
></i> <span className="block lg:hidden">
</span> <i className="fa fa-forward" aria-hidden="true"></i>
<span className="lg:block hidden">Next</span> </span>
</button> <span className="lg:block hidden">Next</span>
</div> </button>
</div> </div>
); );
} }
+87 -117
View File
@@ -7,37 +7,15 @@ import {
isMobile, isMobile,
nameColor nameColor
} from "../../constant/Utils"; } from "../../constant/Utils";
const cursor =
"cursor-[url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAASElEQVR4nGNgwAMkJSUbpKSkOvCpIaT5PxSTbogUQjMYMwxeIIXmVFIxA8UGDDyQGg0DnIDi6JKUlCxHMqCeZAOghjSAMD5FAKfeaURdUFxCAAAAAElFTkSuQmCC'),_pointer]";
const RecipientList = (props) => { const RecipientList = (props) => {
const [animationParent] = useAutoAnimate(); const [animationParent] = useAutoAnimate();
const [isHover, setIsHover] = useState(); const [isHover, setIsHover] = useState();
const [isEdit, setIsEdit] = useState(false); const [isEdit, setIsEdit] = useState(false);
//function for onhover signer name change background color //function for onhover signer name change background color
const inputRef = useRef(null); const inputRef = useRef(null);
const onHoverStyle = (ind, blockColor) => {
const style = {
background: blockColor ? blockColor : color[ind % color.length],
padding: "10px",
marginTop: "2px",
display: "flex",
flexDirection: "row",
borderBottom: "1px solid #e3e1e1",
alignItems: "center"
};
return style;
};
//function for onhover signer name remove background color
const nonHoverStyle = () => {
const style = {
padding: "10px",
marginTop: "2px",
display: "flex",
flexDirection: "row",
borderBottom: "1px solid #e3e1e1",
alignItems: "center"
};
return style;
};
const isWidgetExist = (Id) => { const isWidgetExist = (Id) => {
return props.signerPos.some((x) => x.Id === Id); return props.signerPos.some((x) => x.Id === Id);
}; };
@@ -116,18 +94,21 @@ const RecipientList = (props) => {
data-tut="reactourFirst" data-tut="reactourFirst"
onMouseEnter={() => setIsHover(ind)} onMouseEnter={() => setIsHover(ind)}
onMouseLeave={() => setIsHover(null)} onMouseLeave={() => setIsHover(null)}
className={ className={`${
props.sendInOrder props.sendInOrder
? props.isMailSend ? props.isMailSend
? "disabled" ? "pointer-events-none bg-opacity-80"
: "dragCursor" : `text-[12px] font-bold ${cursor}`
: props.isMailSend && "disabled" : props.isMailSend && "pointer-events-none bg-opacity-80"
} } flex flex-row rounded-xl px-2 py-[10px] mt-1 mx-1 items-center last:mb-0.5`}
style={ style={{
(!isMobile && isHover === ind) || props.isSelectListId === ind background:
? onHoverStyle(ind, obj?.blockColor) (!isMobile && isHover === ind) || props.isSelectListId === ind
: nonHoverStyle(ind) ? obj?.blockColor
} ? obj?.blockColor
: color[ind % color.length]
: "transparent"
}}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
props.setSignerObjId(obj?.objectId || ""); props.setSignerObjId(obj?.objectId || "");
@@ -141,38 +122,16 @@ const RecipientList = (props) => {
} }
}} }}
> >
<div <div className="flex flex-row items-center w-full">
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%"
}}
>
<div <div
className="flex w-[30px] h-[30px] rounded-full items-center justify-center mr-2"
style={{ style={{
background: obj?.blockColor background: obj?.blockColor
? darkenColor(obj?.blockColor, 0.4) ? darkenColor(obj?.blockColor, 0.4)
: nameColor[ind % nameColor.length], : nameColor[ind % nameColor.length]
width: 30,
height: 30,
display: "flex",
borderRadius: 30 / 2,
justifyContent: "center",
alignItems: "center",
marginRight: "12px"
}} }}
> >
<span <span className="text-white uppercase font-bold text-center text-[12px]">
className={props.sendInOrder && "dragCursor"}
style={{
fontSize: "12px",
textAlign: "center",
fontWeight: "bold",
color: "white",
textTransform: "uppercase"
}}
>
{isWidgetExist(obj.Id) ? ( {isWidgetExist(obj.Id) ? (
<i className="fa-solid fa-check"></i> <i className="fa-solid fa-check"></i>
) : ( ) : (
@@ -185,67 +144,72 @@ const RecipientList = (props) => {
</span> </span>
</div> </div>
<div <div
style={{ className={`${
display: "flex", obj?.Name ? "flex-col" : "flex-row"
flexDirection: obj.Name ? "column" : "row", } flex items-center`}
alignItems: "center"
}}
> >
{obj.Name ? ( {obj.Name ? (
<span className={"userName"}>{obj.Name}</span> <span
className={`${
(!isMobile && isHover === ind) ||
props.isSelectListId === ind
? "text-[#424242]"
: "text-base-content"
} text-[12px] font-bold w-[100px] whitespace-nowrap overflow-hidden text-ellipsis`}
>
{obj.Name}
</span>
) : ( ) : (
<> <span
<span className={`${
className="userName" (!isMobile && isHover === ind) ||
style={{ cursor: "pointer" }} props.isSelectListId === ind
onClick={() => { ? "text-[#424242]"
setIsEdit({ [obj.Id]: true }); : "text-base-content"
props.setRoleName(obj.Role); } text-[12px] font-bold w-[100px] whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer`}
}} onClick={() => {
> setIsEdit({ [obj.Id]: true });
{isEdit?.[obj.Id] && props.handleRoleChange ? ( props.setRoleName(obj.Role);
<input }}
ref={inputRef} >
style={{ {isEdit?.[obj.Id] && props.handleRoleChange ? (
backgroundColor: "transparent", <input
width: "inherit", ref={inputRef}
padding: "3px" className="bg-transparent p-[3px"
}} value={obj.Role}
value={obj.Role} onChange={(e) => props.handleRoleChange(e, obj.Id)}
onChange={(e) => props.handleRoleChange(e, obj.Id)} onBlur={() => {
onBlur={() => { setIsEdit({});
setIsEdit({}); props.handleOnBlur(obj.Role, obj.Id);
props.handleOnBlur(obj.Role, obj.Id); }}
}} onKeyDown={(e) => {
onKeyDown={(e) => { if (e.key === "Enter") {
if (e.key === "Enter") { e.preventDefault();
e.preventDefault(); inputRef.current.blur();
inputRef.current.blur(); }
} }}
}} />
/> ) : (
) : ( <span className="p-[3px]">{obj.Role}</span>
<span style={{ padding: "3px" }}>{obj.Role}</span> )}
)} </span>
</span>
</>
)} )}
{obj.Name && ( {obj.Name && (
<span className={"useEmail"}> <span
className={` ${
(!isMobile && isHover === ind) ||
props.isSelectListId === ind
? "text-[#424242]"
: "text-base-content"
} text-[10px] font-medium w-[100px] whitespace-nowrap overflow-hidden text-ellipsis`}
>
{obj?.Role || obj?.Email} {obj?.Role || obj?.Email}
</span> </span>
)} )}
</div> </div>
</div> </div>
{isMobile && props.sendInOrder && ( {isMobile && props.sendInOrder && (
<div <div className="flex flex-row items-center gap-[5px]">
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 5
}}
>
<div <div
onClick={(e) => { onClick={(e) => {
if (ind !== 0) { if (ind !== 0) {
@@ -253,7 +217,7 @@ const RecipientList = (props) => {
handleChangeSequence(e, ind, "up"); handleChangeSequence(e, ind, "up");
} }
}} }}
style={{ color: ind === 0 ? "gray" : "black" }} className={ind === 0 ? "text-[gray]" : "text-black"}
> >
</div> </div>
@@ -264,10 +228,11 @@ const RecipientList = (props) => {
handleChangeSequence(e, ind, null, "down"); handleChangeSequence(e, ind, null, "down");
} }
}} }}
style={{ className={
color: ind === props.signersdata.length - 1
ind === props.signersdata.length - 1 ? "gray" : "black" ? "text-[gray]"
}} : "text-black"
}
> >
</div> </div>
@@ -279,7 +244,12 @@ const RecipientList = (props) => {
e.stopPropagation(); e.stopPropagation();
props.handleDeleteUser(obj.Id); props.handleDeleteUser(obj.Id);
}} }}
style={{ cursor: "pointer", marginLeft: "5px" }} className={`${
(!isMobile && isHover === ind) ||
props.isSelectListId === ind
? "text-[#424242]"
: "text-base-content"
} cursor-pointer ml-[5px]`}
> >
<i className="fa-regular fa-trash-can"></i> <i className="fa-regular fa-trash-can"></i>
</div> </div>
@@ -1,7 +1,6 @@
import React from "react"; import React, { useState } from "react";
import RSC from "react-scrollbars-custom"; import RSC from "react-scrollbars-custom";
import { Document, Page } from "react-pdf"; import { Document, Page } from "react-pdf";
import { themeColor } from "../../constant/const";
function RenderAllPdfPage({ function RenderAllPdfPage({
signPdfUrl, signPdfUrl,
@@ -9,32 +8,51 @@ function RenderAllPdfPage({
setAllPages, setAllPages,
setPageNumber, setPageNumber,
setSignBtnPosition, setSignBtnPosition,
pageNumber pageNumber,
signerPos,
signerObjectId
}) { }) {
const [signPageNumber, setSignPageNumber] = useState([]);
const [bookmarkColor, setBookmarkColor] = useState("");
//set all number of pages after load pdf //set all number of pages after load pdf
function onDocumentLoad({ numPages }) { function onDocumentLoad({ numPages }) {
setAllPages(numPages); setAllPages(numPages);
//check if signerPos array exist then save page number exist in signerPos array to show bookmark icon
if (signerPos) {
const checkUser = signerPos.filter(
(data) => data.signerObjId === signerObjectId
);
setBookmarkColor(checkUser[0]?.blockColor);
let pageNumberArr = [];
if (checkUser?.length > 0) {
checkUser[0]?.placeHolder?.map((data) => {
pageNumberArr.push(data?.pageNumber);
});
setSignPageNumber(pageNumberArr);
}
}
} }
//'function `addSignatureBookmark` is used to display the page where the user's signature is located.
const addSignatureBookmark = (index) => {
const ispageNumber = signPageNumber.includes(index + 1);
return (
ispageNumber && (
<div className="absolute z-20 top-[1px] -right-[13px] -translate-x-1/2 -translate-y-1/2">
<i
style={{ color: bookmarkColor || "red" }}
className="fa-solid fa-bookmark"
></i>
</div>
)
);
};
return ( return (
<div className="showPages"> <div>
<div <div className=" hidden md:flex flex-row bg-base-100 h-full">
style={{ <div className="w-[140px]">
display: "flex", <div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
flexDirection: "row",
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
backgroundColor: "white",
height: "100%"
}}
>
<div style={{ width: "140px" }}>
<div
style={{
background: themeColor
// color:"white"
}}
className="signedStyle"
>
Pages Pages
</div> </div>
@@ -54,20 +72,11 @@ function RenderAllPdfPage({
{Array.from(new Array(allPages), (el, index) => ( {Array.from(new Array(allPages), (el, index) => (
<div <div
key={index} key={index}
style={{ className={`${
width: "100px", pageNumber - 1 === index
border: ? "border-[red]"
pageNumber - 1 === index : "border-[#878787]"
? "2px solid red" } border-2 w-[100px] m-[10px] flex justify-center items-center relative`}
: "2px solid #878787",
// padding: "5px",
margin: "10px",
display: "flex",
justifyContent: "center",
alignItems: "center",
contain: "content"
}}
onClick={() => { onClick={() => {
setPageNumber(index + 1); setPageNumber(index + 1);
if (setSignBtnPosition) { if (setSignBtnPosition) {
@@ -75,15 +84,19 @@ function RenderAllPdfPage({
} }
}} }}
> >
<Page {signerPos && addSignatureBookmark(index)}
key={`page_${index + 1}`}
pageNumber={index + 1} <div className="relative z-[1] overflow-hidden">
width={100} <Page
height={100} key={`page_${index + 1}`}
scale={1} pageNumber={index + 1}
renderAnnotationLayer={false} width={100}
renderTextLayer={false} height={100}
/> scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
/>
</div>
</div> </div>
))} ))}
</Document> </Document>
+33 -54
View File
@@ -204,34 +204,32 @@ function RenderPdf({
}; };
//function for render placeholder block over pdf document //function for render placeholder block over pdf document
const checkSignedSignes = (data) => { const checkSignedSignes = (data) => {
const checkSign = signedSigners.filter( let checkSign = [];
(sign) => sign.objectId === data.signerObjId //condition to handle quick send flow and using normal request sign flow
checkSign = signedSigners.filter(
(sign) => sign?.Id === data?.Id || sign?.objectId === data?.signerObjId
); );
if (data.signerObjId === signerObjectId) { if (data.signerObjId === signerObjectId) {
setCurrentSigner(true); setCurrentSigner(true);
} }
const handleAllUserName = (Id, Role, type) => { const handleAllUserName = (Id, Role, type) => {
return pdfDetails[0].Signers.map((signerData, key) => { return (
return ( <React.Fragment>
signerData.objectId === data.signerObjId && ( <div className="text-black text-[8px] font-medium">
<React.Fragment key={key}> {
{signerData?.Name && ( pdfDetails[0].Signers?.find(
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}> (signer) => signer.objectId === data.signerObjId
{signerData.Name} )?.Name
</div> }
)} </div>
{type && ( {type && <div className="text-[11px] font-bold">{type}</div>}
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div> {Role && (
)} <div className="text-black text-[8px] font-medium">
{Role && ( {`(${Role})`}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}> </div>
{`(${Role})`} )}
</div> </React.Fragment>
)} );
</React.Fragment>
)
);
});
}; };
return ( return (
@@ -290,14 +288,12 @@ function RenderPdf({
if (checkSign?.Name) { if (checkSign?.Name) {
return ( return (
<> <>
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}> <div className="text-black text-[8px] font-medium">
{checkSign?.Name} {checkSign?.Name}
</div> </div>
{type && ( {type && <div className="text-[11px] font-bold">{type}</div>}
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
{Role && ( {Role && (
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}> <div className="text-black text-[8px] font-medium">
{`(${Role})`} {`(${Role})`}
</div> </div>
)} )}
@@ -306,24 +302,16 @@ function RenderPdf({
} else { } else {
return ( return (
<> <>
{type && ( {type && <div className="text-[11px] font-bold">{type}</div>}
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div> <div className="text-black text-[8px] font-medium">{Role}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</> </>
); );
} }
} else { } else {
return ( return (
<> <>
{type && ( {type && <div className="text-[11px] font-bold">{type}</div>}
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div> <div className="text-black text-[8px] font-medium">{Role}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</> </>
); );
} }
@@ -334,6 +322,7 @@ function RenderPdf({
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>} {successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{isMobile && scale ? ( {isMobile && scale ? (
<div <div
data-tut="reactourForth"
style={{ style={{
border: "0.1px solid #ebe8e8", border: "0.1px solid #ebe8e8",
marginTop: isGuestSigner && "30px" marginTop: isGuestSigner && "30px"
@@ -461,17 +450,9 @@ function RenderPdf({
}))} }))}
{/* this component for render pdf document is in middle of the component */} {/* this component for render pdf document is in middle of the component */}
<div <div className="flex items-center justify-center">
style={{
display: "flex",
justifyContent: "center",
alignItems: "center"
}}
>
<Document <Document
onLoadError={() => { onLoadError={() => setPdfLoadFail(true)}
setPdfLoadFail(true);
}}
loading={"Loading Document.."} loading={"Loading Document.."}
onLoadSuccess={pageDetails} onLoadSuccess={pageDetails}
// ref={pdfRef}' // ref={pdfRef}'
@@ -517,10 +498,8 @@ function RenderPdf({
noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true} noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true}
> >
<div <div
style={{ data-tut="reactourForth"
border: "0.1px solid #ebe8e8", style={{ border: "0.1px solid #ebe8e8", width: pdfOriginalWidth }}
width: pdfOriginalWidth
}}
ref={drop} ref={drop}
id="container" id="container"
> >
+59 -171
View File
@@ -1,6 +1,5 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useRef, useState, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas"; import SignatureCanvas from "react-signature-canvas";
import { themeColor } from "../../constant/const";
function SignPad({ function SignPad({
isSignPad, isSignPad,
@@ -78,21 +77,16 @@ function SignPad({
//save button component //save button component
const SaveBtn = () => { const SaveBtn = () => {
return ( return (
<div style={{ marginTop: "2px" }}> <div>
{(isTab === "draw" || isTab === "uploadImage") && ( {(isTab === "draw" || isTab === "uploadImage") && (
<button <button
style={{
color: "black",
border: "1px solid #ccc"
}}
type="button" type="button"
className="finishBtn saveBtn" className="op-btn op-btn-ghost mr-1 mt-[2px]"
onClick={() => handleClear()} onClick={() => handleClear()}
> >
Clear Clear
</button> </button>
)} )}
<button <button
onClick={() => { onClick={() => {
setCurrWidgetsDetails({}); setCurrWidgetsDetails({});
@@ -127,19 +121,12 @@ function SignPad({
setSignValue(""); setSignValue("");
setIsStamp(false); setIsStamp(false);
}} }}
style={{
background: themeColor,
color: "white"
}}
disabled={
isSignImg || image || isDefaultSign || textWidth ? false : true
}
type="button" type="button"
className={ className={`${
isSignImg || image || isDefaultSign || textWidth isSignImg || image || isDefaultSign || textWidth
? "finishBtn saveBtn" ? ""
: "disabledFinish saveBtn" : "pointer-events-none"
} } op-btn op-btn-primary shadow-lg`}
> >
Save Save
</button> </button>
@@ -214,8 +201,8 @@ function SignPad({
const fontfamily = fontStyle const fontfamily = fontStyle
? fontStyle ? fontStyle
: fontSelect : fontSelect
? fontSelect ? fontSelect
: "Fasthand"; : "Fasthand";
//creating span for getting text content width //creating span for getting text content width
const span = document.createElement("span"); const span = document.createElement("span");
@@ -256,7 +243,7 @@ function SignPad({
const PenColorComponent = (props) => { const PenColorComponent = (props) => {
return ( return (
<div style={{ display: "flex", flexDirection: "row" }}> <div className="flex flex-row items-start">
{allColor.map((data, key) => { {allColor.map((data, key) => {
return ( return (
<i <i
@@ -267,10 +254,10 @@ function SignPad({
key === 0 && penColor === "blue" key === 0 && penColor === "blue"
? "2px solid blue" ? "2px solid blue"
: key === 1 && penColor === "red" : key === 1 && penColor === "red"
? "2px solid red" ? "2px solid red"
: key === 2 && penColor === "black" : key === 2 && penColor === "black"
? "2px solid black" ? "2px solid black"
: "2px solid white" : "2px solid white"
}} }}
onClick={() => { onClick={() => {
props?.convertToImg && props?.convertToImg &&
@@ -296,33 +283,14 @@ function SignPad({
return ( return (
<div> <div>
{isSignPad && ( {isSignPad && (
<div className="modaloverlay"> <div className="op-modal op-modal-open">
<div className="modalcontainer"> <div className="op-modal-box px-[13px] pt-2 pb-0">
<div <div className="flex justify-between text-base-content items-center">
className="modalheader" <div className="text-[1.2rem]">
style={{ padding: "0 13px", marginTop: "5px" }} <div className="flex flex-row justify-between mt-[3px]">
> <div className="flex flex-row justify-between gap-[5px] md:gap-[8px] text-[11px] md:text-base">
<div className="modaltitle">
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
background: "white",
marginTop: "3px"
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-around",
alignItems: "end",
gap: 10
}}
>
{isStamp ? ( {isStamp ? (
<span style={{ color: themeColor }} className="signTab"> <span className="op-link-primary op-link">
{widgetType === "image" {widgetType === "image"
? "Upload image" ? "Upload image"
: "Upload stamp image"} : "Upload stamp image"}
@@ -337,23 +305,14 @@ function SignPad({
setIsTab("draw"); setIsTab("draw");
setImage(); setImage();
}} }}
style={{ className={`${
color: isTab === "draw" ? themeColor : "#515252", isTab === "draw"
marginLeft: "2px" ? "op-link-primary"
}} : "no-underline"
className="signTab" } op-link underline-offset-8 ml-[2px]`}
> >
Draw Draw
</span> </span>
<div
style={{
border:
isTab === "draw"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div> </div>
<div> <div>
<span <span
@@ -363,22 +322,14 @@ function SignPad({
setIsTab("uploadImage"); setIsTab("uploadImage");
setSignatureType(""); setSignatureType("");
}} }}
style={{ className={`${
color: isTab === "uploadImage"
isTab === "uploadImage" ? themeColor : "#515252" ? "op-link-primary"
}} : "no-underline"
className="signTab" } op-link underline-offset-8 ml-[2px]`}
> >
Upload Image Upload Image
</span> </span>
<div
style={{
border:
isTab === "uploadImage"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div> </div>
<div> <div>
<span <span
@@ -389,23 +340,14 @@ function SignPad({
setSignatureType(""); setSignatureType("");
setImage(); setImage();
}} }}
style={{ className={`${
color: isTab === "type" ? themeColor : "#515252", isTab === "type"
marginLeft: "2px" ? "op-link-primary"
}} : "no-underline"
className="signTab" } op-link underline-offset-8 ml-[2px]`}
> >
Type Type
</span> </span>
<div
style={{
border:
isTab === "type"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div> </div>
{!isInitial && defaultSign ? ( {!isInitial && defaultSign ? (
<div> <div>
@@ -417,24 +359,14 @@ function SignPad({
setSignatureType(""); setSignatureType("");
setImage(); setImage();
}} }}
style={{ className={`${
color: isTab === "mysignature"
isTab === "mysignature" ? "op-link-primary"
? themeColor : "no-underline"
: "#515252" } op-link underline-offset-8 ml-[2px]`}
}}
className="signTab"
> >
My Signature My Signature
</span> </span>
<div
style={{
border:
isTab === "mysignature"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div> </div>
) : ( ) : (
isInitial && isInitial &&
@@ -448,24 +380,14 @@ function SignPad({
setSignatureType(""); setSignatureType("");
setImage(); setImage();
}} }}
style={{ className={`${
color: isTab === "mysignature"
isTab === "mysignature" ? "op-link-primary"
? themeColor : "no-underline"
: "#515252" } op-link underline-offset-8 ml-[2px]`}
}}
className="signTab"
> >
My Initials My Initials
</span> </span>
<div
style={{
border:
isTab === "mysignature"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div> </div>
) )
)} )}
@@ -475,8 +397,7 @@ function SignPad({
</div> </div>
</div> </div>
<div <div
className="closebtn" className="text-[1.5rem] cursor-pointer"
style={{ color: "black" }}
onClick={() => { onClick={() => {
setPenColor("blue"); setPenColor("blue");
setIsSignPad(false); setIsSignPad(false);
@@ -493,10 +414,10 @@ function SignPad({
&times; &times;
</div> </div>
</div> </div>
<div style={{ height: "100%", padding: 20 }}> <div className="p-[20px] h-full">
{isDefaultSign ? ( {isDefaultSign ? (
<> <>
<div style={{ display: "flex", justifyContent: "center" }}> <div className="flex justify-center">
<div <div
style={{ style={{
border: "1.3px solid #007bff", border: "1.3px solid #007bff",
@@ -514,24 +435,19 @@ function SignPad({
> >
<img <img
alt="stamp img" alt="stamp img"
style={{ className="w-full h-full object-contain bg-white"
width: "100%",
height: "100%",
background: "rgb(255, 255, 255)",
objectFit: "contain"
}}
draggable="false" draggable="false"
src={isInitial ? myInitial : defaultSign} src={isInitial ? myInitial : defaultSign}
/> />
</div> </div>
</div> </div>
<div style={{ display: "flex", justifyContent: "flex-end" }}> <div className="flex justify-end">
<SaveBtn /> <SaveBtn />
</div> </div>
</> </>
) : isImageSelect || isStamp ? ( ) : isImageSelect || isStamp ? (
!image ? ( !image ? (
<div style={{ display: "flex", justifyContent: "center" }}> <div className="flex justify-center">
<div <div
style={{ style={{
border: "1.3px solid #007bff", border: "1.3px solid #007bff",
@@ -562,7 +478,7 @@ function SignPad({
</div> </div>
) : ( ) : (
<> <>
<div style={{ display: "flex", justifyContent: "center" }}> <div className="flex justify-center">
<div <div
style={{ style={{
border: "1.3px solid #007bff", border: "1.3px solid #007bff",
@@ -581,39 +497,26 @@ function SignPad({
ref={imageRef} ref={imageRef}
src={image.src} src={image.src}
draggable="false" draggable="false"
style={{ className=" object-contain h-full w-full"
objectFit: "contain",
height: "100%",
width: "100%"
}}
/> />
</div> </div>
</div> </div>
<div <div className="flex justify-end">
style={{ display: "flex", justifyContent: "flex-end" }}
>
<SaveBtn /> <SaveBtn />
</div> </div>
</> </>
) )
) : isTab === "type" ? ( ) : isTab === "type" ? (
<div> <div>
<div <div className="flex justify-between items-center">
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center"
}}
>
<span className="signatureText"> <span className="signatureText">
{isInitial ? "Initials" : "Signature"}: {isInitial ? "Initials" : "Signature"}:
</span> </span>
<input <input
maxLength={isInitial ? 3 : 30} maxLength={isInitial ? 3 : 30}
style={{ fontFamily: fontSelect, color: penColor }} style={{ fontFamily: fontSelect, color: penColor }}
type="text" type="text"
className="signatureInput" className="ml-1 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-[20px]"
placeholder="Your signature" placeholder="Your signature"
value={signValue} value={signValue}
onChange={(e) => { onChange={(e) => {
@@ -622,7 +525,6 @@ function SignPad({
}} }}
/> />
</div> </div>
<div className="fontOptionContainer"> <div className="fontOptionContainer">
{fontOptions.map((font, ind) => { {fontOptions.map((font, ind) => {
return ( return (
@@ -653,21 +555,14 @@ function SignPad({
})} })}
</div> </div>
<div <div className="flex flex-row justify-between mt-[10px]">
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginTop: "10px"
}}
>
<PenColorComponent convertToImg={convertToImg} /> <PenColorComponent convertToImg={convertToImg} />
<SaveBtn /> <SaveBtn />
</div> </div>
</div> </div>
) : ( ) : (
<> <>
<div style={{ display: "flex", justifyContent: "center" }}> <div className="flex justify-center">
<SignatureCanvas <SignatureCanvas
ref={canvasRef} ref={canvasRef}
penColor={penColor} penColor={penColor}
@@ -687,14 +582,7 @@ function SignPad({
dotSize={1} dotSize={1}
/> />
</div> </div>
<div <div className="flex flex-row justify-between mt-[10px]">
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginTop: "10px"
}}
>
<PenColorComponent /> <PenColorComponent />
<SaveBtn /> <SaveBtn />
</div> </div>
+7 -40
View File
@@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import { themeColor } from "../../constant/const";
import "../../styles/signature.css"; import "../../styles/signature.css";
function Signedby({ pdfDetails }) { function Signedby({ pdfDetails }) {
const getFirstLetter = (name) => { const getFirstLetter = (name) => {
@@ -8,50 +7,18 @@ function Signedby({ pdfDetails }) {
}; };
return ( return (
<div className="signerComponent"> <div className="hidden md:block w-[180px] h-full bg-base-100">
<div <div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
style={{
background: themeColor,
color: "white"
}}
className="signedStyle"
>
Signed By Signed By
</div> </div>
<div style={{ marginTop: "2px", background: "white" }}> <div className="mt-[2px] bg-base-100">
<div <div className="bg-[#93a3db] rounded-xl mx-1 flex flex-row items-center py-[10px]">
style={{ <div className="bg-[#576081] flex w-[30px] h-[30px] rounded-full justify-center items-center mx-1">
display: "flex", <span className="text-[12px] text-center font-bold text-white uppercase">
flexDirection: "row",
padding: "10px",
background: "#93a3db"
}}
>
<div
className="signerStyle"
style={{
background: "#abd1d0",
width: 20,
height: 20,
display: "flex",
borderRadius: 30 / 2,
justifyContent: "center",
alignItems: "center",
marginRight: "20px",
marginTop: "5px"
}}
>
<span
style={{
fontSize: "8px",
textAlign: "center",
fontWeight: "bold"
}}
>
{getFirstLetter(pdfDetails.ExtUserPtr.Name)} {getFirstLetter(pdfDetails.ExtUserPtr.Name)}
</span> </span>
</div> </div>
<div style={{ display: "flex", flexDirection: "column" }}> <div className="flex flex-col">
<span className="userName">{pdfDetails.ExtUserPtr.Name}</span> <span className="userName">{pdfDetails.ExtUserPtr.Name}</span>
<span className="useEmail">{pdfDetails.ExtUserPtr.Email}</span> <span className="useEmail">{pdfDetails.ExtUserPtr.Email}</span>
</div> </div>
@@ -1,37 +1,22 @@
import React from "react"; import React from "react";
import { themeColor } from "../../constant/const";
import RecipientList from "./RecipientList"; import RecipientList from "./RecipientList";
import { Tooltip } from "react-tooltip"; import { Tooltip } from "react-tooltip";
function SignerListPlace(props) { function SignerListPlace(props) {
return ( return (
<div> <div>
<div <div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
style={{ <span>
background: themeColor,
padding: "5px"
}}
>
<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"> <span className="text-xs mt-1 ml-0.5">
{props?.title === "Roles" && ( {props?.title === "Roles" && (
<> <>
<a data-tooltip-id="my-tooltip"> <a data-tooltip-id="my-tooltip">
<sup> <sup>
<i <i className="fa-solid fa-question rounded-full border-[1.5px] border-base-content text-[11px] py-[1px] px-[3px]"></i>
className="fa-solid fa-question rounded-full"
style={{
borderColor: "white",
color: "white",
fontSize: 11,
borderWidth: 1.5,
padding: "1px 3px"
}}
></i>
</sup> </sup>
</a> </a>
<Tooltip id="my-tooltip"> <Tooltip id="my-tooltip" className="z-[100]">
<div className="max-w-[450px]"> <div className="max-w-[450px]">
<p className="font-bold">What are template roles?</p> <p className="font-bold">What are template roles?</p>
<p> <p>
@@ -68,36 +53,32 @@ function SignerListPlace(props) {
</span> </span>
</span> </span>
</div> </div>
<div className="signerList"> <div className="overflow-auto hide-scrollbar max-h-[180px]">
<RecipientList {...props} /> <RecipientList {...props} />
</div> </div>
{props.handleAddSigner ? ( <div className="mx-1">
<div {props.handleAddSigner ? (
data-tut="reactourAddbtn" <div
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" role="button"
onClick={() => props.handleAddSigner()} data-tut="reactourAddbtn"
style={{ className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
opacity: props.isMailSend && "0.5", disabled={props?.isMailSend ? true : false}
pointerEvents: props.isMailSend && "none" onClick={() => props.handleAddSigner()}
}} >
> <i className="fa-solid fa-plus"></i> Add role
<i className="fa-solid fa-plus"></i> </div>
<span style={{ marginLeft: 2 }}>Add role</span> ) : (
</div> <div
) : ( role="button"
<div data-tut="reactourAddbtn"
data-tut="reactourAddbtn" className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
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" disabled={props?.isMailSend ? true : false}
onClick={() => props.setIsAddSigner(true)} onClick={() => props.setIsAddSigner(true)}
style={{ >
opacity: props.isMailSend && "0.5", <i className="fa-solid fa-plus"></i> Add recipients
pointerEvents: props.isMailSend && "none" </div>
}} )}
> </div>
<i className="fa-solid fa-plus"></i>
<span style={{ marginLeft: 2 }}>Add recipients</span>
</div>
)}
</div> </div>
); );
} }
+15 -33
View File
@@ -1,16 +1,13 @@
import React from "react"; import React from "react";
import { rejectBtn, submitBtn, themeColor } from "../../constant/const"; import Loader from "../../primitives/Loader";
function VerifyEmail(props) { function VerifyEmail(props) {
return ( return (
<div className="bg-black bg-opacity-[75%] absolute z-[999] flex flex-col items-center justify-center w-full h-full rounded"> <dialog className="op-modal op-modal-open absolute z-[1999]">
<div className="bg-white rounded outline-none md:w-[40%] w-[80%]"> <div className="md:w-[40%] w-[80%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<div <h3 className="font-bold text-lg pt-[15px] px-[20px] text-base-content">
style={{ backgroundColor: themeColor }}
className=" text-white p-[10px] rounded-t"
>
OTP verification OTP verification
</div> </h3>
{props.isVerifyModal ? ( {props.isVerifyModal ? (
<form <form
onSubmit={(e) => { onSubmit={(e) => {
@@ -18,25 +15,24 @@ function VerifyEmail(props) {
props.handleVerifyEmail(e); props.handleVerifyEmail(e);
}} }}
> >
<div className="px-6 py-3"> <div className="px-6 py-3 text-base-content">
<label className="mb-2">Enter OTP</label> <label className="mb-2">Enter OTP</label>
<input <input
required required
type="tel" type="tel"
pattern="[0-9]{4}" pattern="[0-9]{4}"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
placeholder="Enter OTP received over email" placeholder="Enter OTP received over email"
value={props.otp} value={props.otp}
onChange={(e) => props.setOtp(e.target.value)} onChange={(e) => props.setOtp(e.target.value)}
/> />
</div> </div>
<hr />
<div className="px-6 my-3"> <div className="px-6 my-3">
<button type="submit" className={submitBtn}> <button type="submit" className="op-btn op-btn-primary">
Verify Verify
</button> </button>
<button <button
className={`${rejectBtn} ml-2`} className="op-btn op-btn-secondary ml-2"
onClick={(e) => props.handleResend(e)} onClick={(e) => props.handleResend(e)}
> >
Resend Resend
@@ -44,29 +40,15 @@ function VerifyEmail(props) {
</div> </div>
</form> </form>
) : props.otpLoader ? ( ) : props.otpLoader ? (
<div <div className="h-[150px] flex items-center justify-center">
style={{ <Loader />
height: "150px",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<div className="px-6 py-3"> <div className="px-6 py-3 text-base-content">
<p className="mb-2">Please verify your email !</p> <p className="mb-2 text-sm">Please verify your email !</p>
<hr />
<div className="px-0 mt-3"> <div className="px-0 mt-3">
<button <button
className={submitBtn} className="op-btn op-btn-primary"
type="submit" type="submit"
onClick={() => { onClick={() => {
props.handleVerifyBtn(); props.handleVerifyBtn();
@@ -78,7 +60,7 @@ function VerifyEmail(props) {
</div> </div>
)} )}
</div> </div>
</div> </dialog>
); );
} }
@@ -9,7 +9,6 @@ import {
textWidget, textWidget,
widgets widgets
} from "../../constant/Utils"; } from "../../constant/Utils";
import { themeColor } from "../../constant/const";
function WidgetComponent({ function WidgetComponent({
dragSignature, dragSignature,
signRef, signRef,
@@ -256,117 +255,82 @@ function WidgetComponent({
className="stickyfooter" className="stickyfooter"
style={{ width: window.innerWidth + "px" }} style={{ width: window.innerWidth + "px" }}
> >
{isSigners && ( <div className="mx-1">
<div {isSigners && (
data-tut={dataTut} <div
style={{ data-tut={dataTut}
background: blockColor className="py-[10px] flex justify-center items-center op-card"
? blockColor
: isSelectListId
? color[isSelectListId % color.length]
: color[0],
padding: "10px 20px",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
onClick={() => handleModal()}
>
<span
style={{ style={{
fontSize: "13px", background: blockColor
fontWeight: "700", ? blockColor
textAlign: "center" : isSelectListId
? color[isSelectListId % color.length]
: color[0]
}} }}
onClick={() => handleModal()}
> >
{title ? title : "Recipient"} <span className="text-[13px] font-bold flex items-center">
</span> {title ? title : "Recipient"}
<span {signersdata[isSelectListId]?.Role && (
style={{ <div>
fontSize: "13px", {signersdata[isSelectListId]?.Name ? (
fontWeight: "700", <>
display: "flex", :{" "}
alignItems: "center" {signersdata[isSelectListId]?.Name?.length > 12
}} ? `${signersdata[isSelectListId].Name.slice(
> 0,
{signersdata[isSelectListId]?.Role && ( 12
<div> )}...`
{signersdata[isSelectListId]?.Name ? ( : signersdata[isSelectListId]?.Name}
<> </>
:{" "} ) : (
{signersdata[isSelectListId]?.Name?.length > 12 <>
? `${signersdata[isSelectListId].Name.slice( :{" "}
0, {signersdata[isSelectListId]?.Role?.length > 12
12 ? `${signersdata[isSelectListId].Role.slice(
)}...` 0,
: signersdata[isSelectListId]?.Name} 12
</> )}...`
) : ( : signersdata[isSelectListId]?.Role}
<> </>
:{" "} )}
{signersdata[isSelectListId]?.Role?.length > 12 </div>
? `${signersdata[isSelectListId].Role.slice( )}
0, <div className="ml-[6px] text-[16px]">
12 <i className="fa-solid fa-angle-down"></i>
)}...`
: signersdata[isSelectListId]?.Role}
</>
)}
</div> </div>
)} </span>
<div style={{ marginLeft: 6, fontSize: 16 }}> </div>
<i className="fa-solid fa-angle-down"></i> )}
</div> </div>
</span> <div className="mx-1">
</div> {handleAddSigner ? (
)}
{handleAddSigner ? (
<div
data-tut="reactourAddbtn"
style={{
margin: "5px 0 5px 0",
backgroundColor: themeColor,
color: "white"
}}
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
onClick={() => handleAddSigner()}
>
<i className="fa-solid fa-plus"></i>
<span style={{ marginLeft: 2 }}>Add role</span>
</div>
) : (
setIsAddSigner && (
<div <div
data-tut="reactourAddbtn" data-tut="reactourAddbtn"
style={{ className="op-btn op-btn-accent w-full my-[2px]"
margin: "5px 0 5px 0", onClick={() => handleAddSigner()}
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> <i className="fa-solid fa-plus"></i>
<span style={{ marginLeft: 2 }}>Add recipients</span> <span>Add role</span>
</div> </div>
) ) : (
)} setIsAddSigner && (
<div
data-tut="reactourAddbtn"
className="op-btn op-btn-accent w-full my-[2px]"
onClick={() => setIsAddSigner(true)}
>
<i className="fa-solid fa-plus"></i>
<span>Add recipients</span>
</div>
)
)}
</div>
<div <div
ref={scrollContainerRef} ref={scrollContainerRef}
style={{ className="bg-base-100 border-[2px] border-t-primary"
background: "white",
borderTop: `2px solid ${themeColor}`
}}
> >
<div <div className="flex whitespace-nowrap overflow-x-scroll pt-[10px] pb-[5px] pr-[5px]">
style={{
display: "flex",
overflowX: "scroll",
whiteSpace: "nowrap",
padding: "10px 5px 10px 1px"
}}
>
<WidgetList <WidgetList
updateWidgets={updateWidgets} updateWidgets={updateWidgets}
handleDivClick={handleDivClick} handleDivClick={handleDivClick}
@@ -383,20 +347,14 @@ function WidgetComponent({
) : ( ) : (
<div <div
data-tut={dataTut} data-tut={dataTut}
className={ className={`${
isMailSend ? "disabled signerComponent " : "signerComponent" isMailSend ? "bg-opacity-50 pointer-events-none" : ""
} } hidden md:block w-[180px] h-full bg-base-100`}
> >
<div <div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
style={{ <span>Fields</span>
background: themeColor,
padding: "5px"
}}
>
<span className="signedStyle">Fields</span>
</div> </div>
<div className="flex flex-col items-center my-3">
<div className="signLayoutContainer1">
<WidgetList <WidgetList
updateWidgets={updateWidgets} updateWidgets={updateWidgets}
handleDivClick={handleDivClick} handleDivClick={handleDivClick}
@@ -413,7 +371,7 @@ function WidgetComponent({
handleClose={handleModal} handleClose={handleModal}
> >
{signersdata.length > 0 ? ( {signersdata.length > 0 ? (
<div style={{ maxHeight: "600px", overflow: "auto" }}> <div className="max-h-[600px] overflow-auto pb-1">
<RecipientList <RecipientList
signerPos={signerPos} signerPos={signerPos}
signersdata={signersdata} signersdata={signersdata}
@@ -433,14 +391,7 @@ function WidgetComponent({
/> />
</div> </div>
) : ( ) : (
<div <div className=" p-[20px] text-[15px] font-medium text-center">
style={{
padding: 20,
fontSize: 15,
fontWeight: "500",
textAlign: "center"
}}
>
Please add a {title ? title : "recipients"} Please add a {title ? title : "recipients"}
</div> </div>
)} )}
@@ -4,9 +4,9 @@ import { getWidgetType } from "../../constant/Utils";
function WidgetList(props) { function WidgetList(props) {
return props.updateWidgets.map((item, ind) => { return props.updateWidgets.map((item, ind) => {
return ( return (
<div key={ind} style={{ marginBottom: "5px" }}> <div key={ind} className="mb-[5px]">
<div <div
className="widgets" className="select-none"
onClick={() => { onClick={() => {
props.addPositionOfSignature && props.addPositionOfSignature &&
props.addPositionOfSignature("onclick", item); props.addPositionOfSignature("onclick", item);
@@ -6,6 +6,7 @@ import { textInputWidget } from "../../constant/Utils";
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader"; import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
import Upgrade from "../../primitives/Upgrade"; import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const"; import { isEnableSubscription } from "../../constant/const";
import Tooltip from "../../primitives/Tooltip";
const WidgetNameModal = (props) => { const WidgetNameModal = (props) => {
const [formdata, setFormdata] = useState({ const [formdata, setFormdata] = useState({
@@ -121,15 +122,15 @@ const WidgetNameModal = (props) => {
props.widgetName === textInputWidget props.widgetName === textInputWidget
? "pt-0" ? "pt-0"
: "" : ""
} p-[20px]`} } p-[20px] text-base-content`}
> >
<div className="form-section"> <div className="mb-[0.75rem] text-[13px]">
<label htmlFor="name" style={{ fontSize: 13 }}> <label htmlFor="name">
Name Name
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[red]"> *</span>
</label> </label>
<input <input
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="name" name="name"
value={formdata.name} value={formdata.name}
onChange={(e) => handleChange(e)} onChange={(e) => handleChange(e)}
@@ -139,39 +140,41 @@ const WidgetNameModal = (props) => {
{(props.defaultdata?.type === textInputWidget || {(props.defaultdata?.type === textInputWidget ||
props.widgetName === textInputWidget) && ( props.widgetName === textInputWidget) && (
<> <>
<div className="form-section"> <div className="mb-[0.75rem]">
<label <div className="flex items-center gap-1">
htmlFor="textvalidate" <label
className={ htmlFor="textvalidate"
!props.isSubscribe && isEnableSubscription && "disabled" className={`${
} !props.isSubscribe && isEnableSubscription
style={{ fontSize: 13 }} ? "bg-opacity-50 pointer-events-none"
> : ""
Validation } text-[13px]`}
</label> >
{!props.isSubscribe && isEnableSubscription && <Upgrade />} Validation
</label>
<Tooltip
url={"https://www.w3schools.com/jsref/jsref_obj_regexp.asp"}
/>
{!props.isSubscribe && isEnableSubscription && <Upgrade />}
</div>
<div <div
className={ className={`${
!props.isSubscribe && isEnableSubscription && "disabled" !props.isSubscribe && isEnableSubscription
} ? "bg-opacity-50 pointer-events-none"
style={{ : ""
display: "flex", } flex flex-row gap-[10px] mb-[0.5rem]`}
flexDirection: "row",
gap: 10,
marginBottom: "0.5rem"
}}
> >
<div style={{ width: "100%", position: "relative" }}> <div className="w-full relative group">
<input <input
className="relative z-20 w-[87%] md:w-[92%] p-2.5 border-[1px] border-[#d1d5db] rounded-l-md outline-none text-xs" className="z-20 relative op-input op-input-bordered rounded-r-none op-input-sm focus:outline-none group-hover:border-base-content w-[87%] md:w-[92%] text-xs"
name="textvalidate" name="textvalidate"
placeholder="Enter custom expression" placeholder="Enter custom regular expression"
value={formdata.textvalidate} value={formdata.textvalidate}
onChange={(e) => handleChange(e)} onChange={(e) => handleChange(e)}
// onBlur={() => handleBlurRegex()} // onBlur={() => handleBlurRegex()}
/> />
<select <select
className="validationlist addUserInput" className="validationlist op-input op-input-bordered op-input-sm focus:outline-none group-hover:border-base-content w-full text-xs"
name="textvalidate" name="textvalidate"
value={formdata.textvalidate} value={formdata.textvalidate}
onChange={(e) => handleChange(e)} onChange={(e) => handleChange(e)}
@@ -179,17 +182,13 @@ const WidgetNameModal = (props) => {
> >
<option <option
disabled={formdata?.textvalidate} disabled={formdata?.textvalidate}
style={{ fontSize: "13px" }} className="text-[13px]"
> >
Select... Select...
</option> </option>
{inputOpt.map((data, ind) => { {inputOpt.map((data, ind) => {
return ( return (
<option <option className="text-[13px]" key={ind} value={data}>
style={{ fontSize: "13px" }}
key={ind}
value={data}
>
{data} {data}
</option> </option>
); );
@@ -199,12 +198,12 @@ const WidgetNameModal = (props) => {
</div> </div>
</div> </div>
<div className="form-section"> <div className="mb-[0.75rem]">
<label htmlFor="name" style={{ fontSize: 13 }}> <label htmlFor="name" className="text-[13px]">
Default value Default value
</label> </label>
<input <input
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="defaultValue" name="defaultValue"
value={formdata.defaultValue} value={formdata.defaultValue}
onChange={(e) => handledefaultChange(e)} onChange={(e) => handledefaultChange(e)}
@@ -222,37 +221,22 @@ const WidgetNameModal = (props) => {
style={{ fontSize: 12 }} style={{ fontSize: 12 }}
> >
<i <i
className="fas fa-exclamation-circle" className="fas fa-exclamation-circle text-[15px]"
style={{ color: "#fab005", fontSize: 15 }} style={{ color: "#fab005" }}
></i>{" "} ></i>
invalid default value invalid default value
</div> </div>
)} )}
</div> </div>
</> </>
)} )}
<div className="form-section"> <div className="mb-[0.75rem]">
<div <div className="flex flex-row gap-[10px] mb-[0.5rem]">
style={{
display: "flex",
flexDirection: "row",
gap: 10,
marginBottom: "0.5rem"
}}
>
{statusArr.map((data, ind) => { {statusArr.map((data, ind) => {
return ( return (
<div <div key={ind} className="flex flex-row gap-[5px] items-center">
key={ind}
style={{
display: "flex",
flexDirection: "row",
gap: 5,
alignItems: "center"
}}
>
<input <input
style={{ accentColor: "red", marginRight: "10px" }} className="mr-[2px] op-radio op-radio-xs"
type="radio" type="radio"
name="status" name="status"
onChange={() => onChange={() =>
@@ -262,9 +246,7 @@ const WidgetNameModal = (props) => {
formdata.status.toLowerCase() === data.toLowerCase() formdata.status.toLowerCase() === data.toLowerCase()
} }
/> />
<div style={{ fontSize: "13px", fontWeight: "500" }}> <div className="text-[13px] font-medium">{data}</div>
{data}
</div>
</div> </div>
); );
})} })}
@@ -272,35 +254,20 @@ const WidgetNameModal = (props) => {
</div> </div>
{(props.defaultdata?.type === textInputWidget || {(props.defaultdata?.type === textInputWidget ||
props?.widgetName === textInputWidget) && ( props?.widgetName === textInputWidget) && (
<div className="form-section"> <div className="mb-[0.75rem]">
<label htmlFor="hint" style={{ fontSize: 13 }}> <label htmlFor="hint" className="text-[13px]">
Hint Hint
</label> </label>
<input <input
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="hint" name="hint"
value={formdata.hint} value={formdata.hint}
onChange={(e) => handleChange(e)} onChange={(e) => handleChange(e)}
/> />
</div> </div>
)} )}
<div <div className="h-[1px] w-full mb-[16px] bg-[#b7b3b3]"></div>
style={{ <button type="submit" className="op-btn op-btn-primary">
height: 1,
backgroundColor: "#b7b3b3",
width: "100%",
marginBottom: "16px"
}}
></div>
<button
style={{
color: "white",
padding: "5px 20px",
backgroundColor: "#32a3ac"
}}
type="submit"
className="finishBtn"
>
Save Save
</button> </button>
</form> </form>
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Parse from "parse"; import Parse from "parse";
import Alert from "../../../primitives/Alert"; import Alert from "../../../primitives/Alert";
import Loader from "../../../primitives/Loader";
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => { const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const folderPtr = { const folderPtr = {
@@ -25,9 +26,11 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
if (parentFolderId) { if (parentFolderId) {
FolderQuery.equalTo("Folder", folderPtr); FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} else { } else {
FolderQuery.doesNotExist("Folder"); FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} }
const res = await FolderQuery.find(); const res = await FolderQuery.find();
@@ -49,6 +52,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const exsitQuery = new Parse.Query(folderCls); const exsitQuery = new Parse.Query(folderCls);
exsitQuery.equalTo("Name", name); exsitQuery.equalTo("Name", name);
exsitQuery.equalTo("Type", "Folder"); exsitQuery.equalTo("Type", "Folder");
exsitQuery.notEqualTo("IsArchive", true);
if (parentFolderId) { if (parentFolderId) {
exsitQuery.equalTo("Folder", folderPtr); exsitQuery.equalTo("Folder", folderPtr);
} }
@@ -110,11 +114,8 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>} {isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
<div id="createFolder" className="relative"> <div id="createFolder" className="relative">
{isLoader && ( {isLoader && (
<div className="absolute h-full w-full flex justify-center items-center "> <div className="absolute h-full w-full flex justify-center items-center">
<div <Loader />
style={{ fontSize: "45px", color: "#3dd3e0" }}
className="loader-37"
></div>
</div> </div>
)} )}
<h1 className="text-base font-semibold">Create Folder</h1> <h1 className="text-base font-semibold">Create Folder</h1>
@@ -25,9 +25,11 @@ const FolderModal = (props) => {
if (folderPtr) { if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr); FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} else { } else {
FolderQuery.doesNotExist("Folder"); FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} }
const res = await FolderQuery.find(); const res = await FolderQuery.find();
@@ -45,9 +45,11 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
if (folderPtr) { if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr); FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} else { } else {
FolderQuery.doesNotExist("Folder"); FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder"); FolderQuery.equalTo("Type", "Folder");
FolderQuery.notEqualTo("IsArchive", true);
} }
const res = await FolderQuery.find(); const res = await FolderQuery.find();
@@ -169,32 +171,40 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
{required && <span className="text-red-500 text-[13px]">*</span>} {required && <span className="text-red-500 text-[13px]">*</span>}
</label> </label>
</div> </div>
<div className="relative rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center"> <div className="relative max-w-sm">
<div> <div
<i onClick={() => SetIsOpen(true)}
className="far fa-folder-open text-[40px] text-[#33bbff]" className=" cursor-pointer rounded px-[20px] py-[20px] bg-base-100 border-[1px] border-base-200 shadow flex max-w-sm gap-8 items-center"
style={{ fontSize: "40px" }} >
aria-hidden="true" <div>
></i> <i
</div> className="far fa-folder-open text-[40px] text-[#33bbff]"
<div className="font-semibold "> style={{ fontSize: "40px" }}
<div className="flex items-center gap-2"> aria-hidden="true"
<p> ></i>
{selectFolder && selectFolder.Name </div>
? selectFolder.Name <div className="font-semibold ">
: "OpenSign™ Drive"} <div className="flex items-center gap-2">
</p> <p>
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}> {selectFolder && selectFolder.Name
<i ? selectFolder.Name
className="fa fa-pencil" : "OpenSign™ Drive"}
title="Select Folder" </p>
aria-hidden="true" <div
></i> className="text-black text-sm"
</div> // onClick={() => SetIsOpen(true)}
>
<i
className="fa fa-pencil cursor-pointer"
title="Select Folder"
aria-hidden="true"
></i>
</div>
</div>
<p className="text-[10px] text-gray-400">
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
</p>
</div> </div>
<p className="text-[10px] text-gray-400">
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
</p>
</div> </div>
<div className="absolute top-2 right-1 cursor-pointer"> <div className="absolute top-2 right-1 cursor-pointer">
<Tooltip <Tooltip
@@ -3,16 +3,6 @@ import Parse from "parse";
import "../../../styles/AddUser.css"; import "../../../styles/AddUser.css";
import AsyncSelect from "react-select/async"; import AsyncSelect from "react-select/async";
const customStyles = {
control: (provided) => ({
...provided,
fontSize: "13px" // Font size for the control
}),
option: (provided) => ({
...provided,
fontSize: "13px" // Font size for the options
})
};
const SelectSigners = (props) => { const SelectSigners = (props) => {
const [userList, setUserList] = useState([]); const [userList, setUserList] = useState([]);
const [selected, setSelected] = useState(); const [selected, setSelected] = useState();
@@ -79,32 +69,44 @@ const SelectSigners = (props) => {
}; };
return ( return (
<div className="addusercontainer"> <div className="h-full px-[20px] py-[10px] text-base-content">
<div className="form-wrapper"> <div className="w-full mx-auto p-[8px]">
<div className="form-section" style={{ marginBottom: 0 }}> <div className="mb-0">
<label style={{ fontSize: 14, fontWeight: "700" }}>Choose User</label> <label className="text-[14px] font-bold">Choose from contacts</label>
<AsyncSelect <AsyncSelect
cacheOptions cacheOptions
defaultOptions defaultOptions
value={selected} value={selected}
loadingMessage={() => "Loading..."} loadingMessage={() => "Loading..."}
noOptionsMessage={() => "User not Found"} noOptionsMessage={() => "Contact not found"}
loadOptions={loadOptions} loadOptions={loadOptions}
onChange={handleOptions} onChange={handleOptions}
styles={customStyles} unstyled
classNames={{
control: () =>
"op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full h-full text-[11px]",
valueContainer: () =>
"flex flex-row gap-x-[2px] gap-y-[2px] md:gap-y-0 w-full my-[2px]",
multiValue: () => "op-badge op-badge-primary h-full text-[11px]",
multiValueLabel: () => "mb-[2px]",
menu: () =>
"mt-1 shadow-md rounded-lg bg-base-200 text-base-content",
menuList: () => "shadow-md rounded-lg overflow-hidden",
option: () =>
"bg-base-200 text-base-content rounded-lg m-1 hover:bg-base-300 p-2",
noOptionsMessage: () => "p-2 bg-base-200 rounded-lg m-1 p-2"
}}
/> />
</div> </div>
{isError ? ( <p
<p style={{ color: "red", fontSize: "12px", margin: "5px" }}> className={`${
Please select signer isError ? "text-[red]" : "text-transparent"
</p> } text-[11px] ml-[6px] my-[2px]`}
) : ( >
<p style={{ color: "transparent", fontSize: "12px", margin: "5px" }}> Please select signer
. </p>
</p>
)}
<div> <div>
<button className="submitbutton" onClick={() => handleAdd()}> <button className="op-btn op-btn-primary" onClick={() => handleAdd()}>
Submit Submit
</button> </button>
</div> </div>
@@ -1,15 +1,30 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Select from "react-select"; import Select from "react-select";
import AddSigner from "../../AddSigner"; import AddSigner from "../../AddSigner";
import Modal from "react-modal";
import Parse from "parse"; import Parse from "parse";
import Tooltip from "../../../primitives/Tooltip"; import Tooltip from "../../../primitives/Tooltip";
import { createPortal } from "react-dom";
function arrayMove(array, from, to) { function arrayMove(array, from, to) {
array = array.slice(); array = array.slice();
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]); array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
return array; return array;
} }
const AddSignerModal = ({ isOpen, children }) => {
if (!isOpen) {
return null;
}
return createPortal(
<div className="op-modal op-modal-open">
<div className="op-modal-box p-0 min-w-[90%] md:min-w-[500px] max-h-90 overflow-y-auto hide-scrollbar text-sm">
{children}
</div>
</div>,
document.body
);
};
/** /**
* react-sortable-hoc is depcreated not usable from react 18.x.x * react-sortable-hoc is depcreated not usable from react 18.x.x
* need to replace it with @dnd-kit * need to replace it with @dnd-kit
@@ -17,7 +32,6 @@ function arrayMove(array, from, to) {
*/ */
const SignersInput = (props) => { const SignersInput = (props) => {
Modal.setAppElement("body");
const [state, setState] = useState(undefined); const [state, setState] = useState(undefined);
// const [editFormData, setEditFormData] = useState([]); // const [editFormData, setEditFormData] = useState([]);
const [selected, setSelected] = useState([]); const [selected, setSelected] = useState([]);
@@ -108,15 +122,17 @@ const SignersInput = (props) => {
<label className="block relative"> <label className="block relative">
Signers Signers
{props.required && <span className="text-red-500 text-[13px]">*</span>} {props.required && <span className="text-red-500 text-[13px]">*</span>}
<span className="absolute ml-1 text-xs z-50"> <span className="absolute ml-1 text-xs z-30">
<Tooltip <Tooltip
id={"signer-tooltip"} id={"signer-tooltip"}
message={"Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed."} message={
"Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed."
}
/> />
</span> </span>
</label> </label>
<div style={{ display: "flex", gap: 5 }}> <div className="flex gap-x-[5px]">
<div style={{ flexWrap: "wrap", width: "100%" }}> <div className="w-full">
<Select <Select
onSortEnd={onSortEnd} onSortEnd={onSortEnd}
distance={4} distance={4}
@@ -126,6 +142,22 @@ const SignersInput = (props) => {
onChange={onChange} onChange={onChange}
closeMenuOnSelect={false} closeMenuOnSelect={false}
required={props.required} required={props.required}
noOptionsMessage={() => "Contact not found"}
unstyled
classNames={{
control: () =>
"op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full h-full text-[11px]",
valueContainer: () =>
"flex flex-row gap-x-[2px] gap-y-[2px] md:gap-y-0 w-full my-[2px]",
multiValue: () => "op-badge op-badge-primary h-full text-[11px]",
multiValueLabel: () => "mb-[2px]",
menu: () =>
"mt-1 shadow-md rounded-lg bg-base-200 text-base-content",
menuList: () => "shadow-md rounded-lg overflow-hidden",
option: () =>
"bg-base-200 text-base-content rounded-lg m-1 hover:bg-base-300 p-2",
noOptionsMessage: () => "p-2 bg-base-200 rounded-lg m-1 p-2"
}}
/> />
</div> </div>
<div <div
@@ -133,66 +165,29 @@ const SignersInput = (props) => {
setIsModel(true); setIsModel(true);
openModal(); openModal();
}} }}
style={{ className="cursor-pointer op-input op-input-bordered focus:outline-none hover:border-base-content max-h-[38px] min-w-[48px] flex justify-center items-center"
cursor: "pointer",
borderRadius: 4,
border: "1px solid #ccc",
minHeight: 38,
minWidth: 48,
display: "flex",
justifyContent: "center",
alignItems: "center"
}}
> >
<i className="fas fa-plus"></i> <i className="fas fa-plus"></i>
</div> </div>
<Modal <AddSignerModal isOpen={modalIsOpen}>
isOpen={modalIsOpen} <h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
onRequestClose={handleModalCloseClick} Add Signer
shouldCloseOnOverlayClick={false} </h3>
id="modal1" <button
contentLabel="Modal" onClick={handleModalCloseClick}
style={{ className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2"
content: { >
top: "50%",
left: "50%", </button>
right: "auto", {isModal && (
bottom: "auto", <AddSigner
transform: "translate(-50%, -50%)", valueKey={"objectId"}
border: "1px transparent", displayKey={"Name"}
padding: 0 details={handleNewDetails}
}, closePopup={handleModalCloseClick}
overlay: { />
width: "100%", )}
backgroundColor: "rgba(0, 0, 0, 0.75)", </AddSignerModal>
zIndex: 50
}
}}
>
<div className="min-w-full md:min-w-[500px]">
<div
className="flex justify-between rounded-t items-center py-[10px] px-[20px] text-white"
style={{ background: "#32a3ac" }}
>
<div className="text-[1.2rem] font-normal">Add Signer</div>
<button
onClick={handleModalCloseClick}
className="text-[1.5rem] cursor-pointer focus:outline-none"
>
&times;
</button>
</div>
{isModal && (
<AddSigner
valueKey={"objectId"}
displayKey={"Name"}
details={handleNewDetails}
closePopup={handleModalCloseClick}
/>
)}
</div>
</Modal>
</div> </div>
</div> </div>
); );
@@ -0,0 +1,92 @@
import React, { useState, useEffect, useRef } from "react";
import { findContact } from "../../../constant/Utils";
const SuggestionInput = (props) => {
const [inputValue, setInputValue] = useState(props?.value || "");
const [suggestions, setSuggestions] = useState([]);
const [showSuggestions, setShowSuggestions] = useState(false);
const ref = useRef(null);
useEffect(() => {
document.addEventListener("mousedown", Clickout);
return () => {
document.removeEventListener("mousedown", Clickout);
};
}, []);
const Clickout = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setShowSuggestions(false);
}
};
// create debounce to avoid unnecessay api calls
useEffect(() => {
let timer;
if (inputValue) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
(async () => {
const res = await findContact(inputValue);
if (res?.length > 0) {
setSuggestions(res);
setShowSuggestions(true);
} else {
setSuggestions(res);
setShowSuggestions(false);
}
})();
}, 1000);
}
return () => clearTimeout(timer);
}, [inputValue]);
const handleInputChange = async (e) => {
const value = e.target.value;
setInputValue(value?.toLowerCase());
if (props.onChange) {
props.onChange(value);
}
if (value.trim() === "") {
setSuggestions([]);
setShowSuggestions(false);
return;
}
};
const handleSuggestionClick = (suggestion) => {
setInputValue(suggestion.Email);
setSuggestions([]);
setShowSuggestions(false);
if (props.onChange) {
props.onChange(suggestion);
}
};
return (
<div className="flex flex-col items-center relative text-base-content">
<input
type={props?.type || "text"}
value={inputValue}
onChange={handleInputChange}
placeholder="Enter Email..."
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs lowercase"
required={props.required}
/>
{showSuggestions && (
<ul
ref={ref}
className="absolute z-50 left-0 top-[2.55rem] w-full max-h-[100px] overflow-auto bg-base-200 border border-gray-300 rounded shadow-md"
>
{suggestions.map((suggestion, index) => (
<li
key={index}
className="py-2 px-2 w-full text-sm cursor-pointer hover:bg-base-300"
onClick={() => handleSuggestionClick(suggestion)}
>
{suggestion.Email}
</li>
))}
</ul>
)}
</div>
);
};
export default SuggestionInput;
+6 -2
View File
@@ -3,14 +3,18 @@ import { NavLink } from "react-router-dom";
const Menu = ({ item, isOpen, closeSidebar }) => { const Menu = ({ item, isOpen, closeSidebar }) => {
return ( return (
<li key={item.title} role="none"> <li key={item.title} role="none" className="my-0.5">
<NavLink <NavLink
to={ to={
item.pageType item.pageType
? `/${item.pageType}/${item.objectId}` ? `/${item.pageType}/${item.objectId}`
: `/${item.objectId}` : `/${item.objectId}`
} }
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer focus:text-[#0056b3] focus:bg-[#eef1f5]" className={({ isActive }) =>
`${
isActive ? " bg-base-300 text-base-content" : ""
} flex items-center text-left p-3 lg:p-4 text-base-content hover:text-base-content focus:bg-base-300 hover:bg-base-300 hover:no-underline focus:outline-none`
}
onClick={closeSidebar} onClick={closeSidebar}
tabIndex={isOpen ? 0 : -1} tabIndex={isOpen ? 0 : -1}
role="menuitem" role="menuitem"
@@ -9,6 +9,7 @@ import dp from "../../assets/images/dp.png";
const Sidebar = ({ isOpen, closeSidebar }) => { const Sidebar = ({ isOpen, closeSidebar }) => {
const [menuList, setmenuList] = useState([]); const [menuList, setmenuList] = useState([]);
const [submenuOpen, setSubmenuOpen] = useState(false);
let username = localStorage.getItem("username"); let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp; const image = localStorage.getItem("profileImg") || dp;
const tenantname = localStorage.getItem("TenantName"); const tenantname = localStorage.getItem("TenantName");
@@ -33,10 +34,18 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
} }
}; };
const toggleSubmenu = (title) => {
setSubmenuOpen({ [title]: !submenuOpen[title] });
};
const handleMenuItem = () => {
closeSidebar();
setSubmenuOpen({});
};
return ( return (
<aside <aside
className={`bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 md:translate-x-0 className={`absolute md:relative bg-base-100 h-screen overflow-y-auto transition-all z-[100] hide-scrollbar
${isOpen ? "translate-x-0 block" : "-translate-x-full hidden"}`} ${isOpen ? "w-full md:w-[300px]" : "w-0"}`}
> >
<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">
@@ -47,13 +56,20 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
/> />
</div> </div>
<div> <div>
<p className="text-[14px] font-bold">{username}</p> <p className="text-[14px] font-bold text-base-content">{username}</p>
<p className={`text-[12px] ${tenantname ? "mt-2" : ""}`}> <p
className={`text-[12px] text-base-content ${
tenantname ? "mt-2" : ""
}`}
>
{tenantname} {tenantname}
</p> </p>
</div> </div>
</div> </div>
<nav aria-label="OpenSign Sidebar Navigation"> <nav
className="op-menu op-menu-sm"
aria-label="OpenSign Sidebar Navigation"
>
<ul <ul
className="text-sm" className="text-sm"
role="menubar" role="menubar"
@@ -65,19 +81,21 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
key={item.title} key={item.title}
item={item} item={item}
isOpen={isOpen} isOpen={isOpen}
closeSidebar={closeSidebar} closeSidebar={handleMenuItem}
/> />
) : ( ) : (
<Submenu <Submenu
key={item.title} key={item.title}
item={item} item={item}
closeSidebar={closeSidebar} closeSidebar={closeSidebar}
toggleSubmenu={toggleSubmenu}
submenuOpen={submenuOpen}
/> />
) )
)} )}
</ul> </ul>
</nav> </nav>
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3"> <footer className="mt-4 flex justify-center items-center text-[25px] text-base-content gap-3">
<SocialMedia /> <SocialMedia />
</footer> </footer>
</aside> </aside>
+15 -15
View File
@@ -1,19 +1,13 @@
import React, { useState } from "react"; import React from "react";
import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
const Submenu = ({ item, closeSidebar }) => { const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
const [submenuOpen, setSubmenuOpen] = useState(false);
const { title, icon, children } = item; const { title, icon, children } = item;
const toggleSubmenu = () => {
setSubmenuOpen(!submenuOpen);
};
return ( return (
<li role="none"> <li role="none" className="my-0.5">
<button <button
onClick={toggleSubmenu} onClick={() => toggleSubmenu(item.title)}
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:outline-none focus:text-[#0056b3] focus:bg-[#eef1f5]" className="flex items-center text-left p-3 lg:p-4 text-base-content hover:text-base-content focus:bg-base-300 hover:bg-base-300 hover:no-underline focus:outline-none "
aria-expanded={submenuOpen} aria-expanded={submenuOpen}
aria-haspopup="true" aria-haspopup="true"
aria-controls={`submenu-${title}`} aria-controls={`submenu-${title}`}
@@ -23,23 +17,29 @@ const Submenu = ({ item, closeSidebar }) => {
<span className="ml-3 lg:ml-4">{title}</span> <span className="ml-3 lg:ml-4">{title}</span>
<i <i
className={`${ className={`${
submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right" submenuOpen[item.title]
? "fa-solid fa-angle-down"
: "fa-solid fa-angle-right"
}`} }`}
aria-hidden="true" aria-hidden="true"
></i> ></i>
</div> </div>
</button> </button>
{submenuOpen && ( {submenuOpen[item.title] && (
<ul id={`submenu-${title}`} role="menu" aria-label={`${title} submenu`}> <ul id={`submenu-${title}`} role="menu" aria-label={`${title} submenu`}>
{children.map((childItem) => ( {children.map((childItem) => (
<li key={childItem.title} role="none"> <li key={childItem.title} role="none" className="my-0.5">
<NavLink <NavLink
to={ to={
childItem.pageType childItem.pageType
? `/${childItem.pageType}/${childItem.objectId}` ? `/${childItem.pageType}/${childItem.objectId}`
: `/${childItem.objectId}` : `/${childItem.objectId}`
} }
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white focus:text-[#0056b3] focus:bg-[#eef1f5] cursor-pointer" className={({ isActive }) =>
`${
isActive ? "bg-base-300 text-base-content" : ""
} flex items-center text-left pl-6 md:pl-8 py-2 text-sm cursor-pointer text-base-content hover:text-base-content focus:bg-base-300 hover:bg-base-300 hover:no-underline focus:outline-none`
}
onClick={closeSidebar} onClick={closeSidebar}
role="menuitem" role="menuitem"
tabIndex={submenuOpen ? 0 : -1} tabIndex={submenuOpen ? 0 : -1}
+179 -44
View File
@@ -1,16 +1,23 @@
import axios from "axios"; import axios from "axios";
import moment from "moment"; import moment from "moment";
import { isEnableSubscription, themeColor } from "./const"; import { isEnableSubscription } from "./const";
import React from "react"; import React from "react";
import { rgb } from "pdf-lib"; import { rgb } from "pdf-lib";
import Parse from "parse"; import Parse from "parse";
import { appInfo } from "./appinfo";
import { saveAs } from "file-saver";
import printModule from "print-js";
export const isMobile = window.innerWidth < 767; export const isMobile = window.innerWidth < 767;
export const textInputWidget = "text input"; export const textInputWidget = "text input";
export const textWidget = "text"; export const textWidget = "text";
export const radioButtonWidget = "radio button"; export const radioButtonWidget = "radio button";
export const openInNewTab = (url) => { export const openInNewTab = (url, target) => {
window.open(url, "_blank", "noopener,noreferrer"); if (target) {
window.open(url, target, "noopener,noreferrer");
} else {
window.open(url, "_blank", "noopener,noreferrer");
}
}; };
export async function fetchSubscription( export async function fetchSubscription(
@@ -19,11 +26,12 @@ export async function fetchSubscription(
isGuestSign = false isGuestSign = false
) { ) {
try { try {
const extClass = localStorage.getItem("Extand_Class"); const Extand_Class = localStorage.getItem("Extand_Class");
const extClass = Extand_Class && JSON.parse(Extand_Class);
// console.log("extClass ", extClass);
let extUser; let extUser;
if (extClass) { if (extClass && extClass.length > 0) {
const jsonSender = JSON.parse(extClass); extUser = extClass[0].objectId;
extUser = jsonSender[0].objectId;
} else { } else {
extUser = extUserId; extUser = extUserId;
} }
@@ -171,11 +179,10 @@ export const contractUsers = async (email) => {
.then((Listdata) => { .then((Listdata) => {
const json = Listdata.data; const json = Listdata.data;
let data = []; let data = [];
if (json && json.result) { if (json && json.result) {
data.push(json.result); data.push(json.result);
return data;
} }
return data;
}) })
.catch((err) => { .catch((err) => {
console.log("Err ", err); console.log("Err ", err);
@@ -369,43 +376,21 @@ export const addWidgetOptions = (type) => {
return {}; return {};
} }
}; };
export const getWidgetType = (item, marginLeft) => { export const getWidgetType = (item) => {
return ( return (
<> <div className="op-btn op-btn-primary op-btn-outline op-btn-sm focus:outline-none outline outline-[1.5px] w-fit md:w-[150px] ml-[6px] md:ml-0 p-0 overflow-hidden">
<div <div className="w-full h-full flex md:justify-between items-center">
className="signatureBtn widgets" <div className="flex justify-start items-center text-[13px] ml-1">
style={{ {!isMobile && <i className="fa-sharp fa-solid fa-grip-vertical"></i>}
boxShadow: <span className="text-center text-[15px] ml-[5px] font-semibold">
"0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18)",
marginLeft: marginLeft && `${marginLeft}px`
}}
>
<div className="flex items-center mr-1">
{!isMobile && (
<i
className="fa-sharp fa-solid fa-grip-vertical"
style={{ color: "#908d8d", fontSize: "13px", marginLeft: 4 }}
></i>
)}
<span className=" font-[400] text-[15px] text-black ml-[5px]">
{item.type} {item.type}
</span> </span>
</div> </div>
<div <div className="text-[20px] op-btn op-btn-primary w-[40px] h-full flex justify-center items-center">
style={{ <i className={item.icon}></i>
backgroundColor: themeColor,
padding: "0 5px",
display: "flex",
alignItems: "center"
}}
>
<i
style={{ color: "white", fontSize: item.iconSize }}
className={item.icon}
></i>
</div> </div>
</div> </div>
</> </div>
); );
}; };
@@ -561,7 +546,7 @@ export const signPdfFun = async (
isCustomCompletionMail = true; isCustomCompletionMail = true;
} }
} }
// below for loop is used to get first signature of user to send if to signpdf // below for loop is used to get first signature of user to send if to signpdf
// for adding it in completion certificate // for adding it in completion certificate
let getSignature; let getSignature;
@@ -662,6 +647,7 @@ export const createDocument = async (template, placeholders, signerData) => {
Name: Doc.Name, Name: Doc.Name,
URL: Doc.URL, URL: Doc.URL,
SignedUrl: Doc.SignedUrl, SignedUrl: Doc.SignedUrl,
SentToOthers: Doc.SentToOthers,
Description: Doc.Description, Description: Doc.Description,
Note: Doc.Note, Note: Doc.Note,
Placeholders: placeholdersArr, Placeholders: placeholdersArr,
@@ -676,7 +662,9 @@ export const createDocument = async (template, placeholders, signerData) => {
objectId: Doc.CreatedBy.objectId objectId: Doc.CreatedBy.objectId
}, },
Signers: signers, Signers: signers,
SendinOrder: Doc?.SendinOrder || false SendinOrder: Doc?.SendinOrder || false,
AutomaticReminders: Doc?.AutomaticReminders || false,
RemindOnceInEvery: parseInt(Doc?.RemindOnceInEvery || 5)
}; };
try { try {
@@ -1349,8 +1337,8 @@ export const multiSignEmbed = async (
position.type === radioButtonWidget position.type === radioButtonWidget
? 10 ? 10
: position.type === "checkbox" : position.type === "checkbox"
? 10 ? 10
: newUpdateHeight; : newUpdateHeight;
const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight; const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight;
if (signyourself) { if (signyourself) {
@@ -2028,3 +2016,150 @@ export const handleSendOTP = async (email) => {
alert(error.message); alert(error.message);
} }
}; };
//handle download signed pdf
export const handleDownloadPdf = async (
pdfDetails,
pdfUrl,
setIsDownloading
) => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
setIsDownloading("pdf");
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
`${appInfo.baseUrl}/functions/getsignedurl`,
{ url: pdfUrl },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": appInfo.appId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
setIsDownloading("");
} catch (err) {
console.log("err in getsignedurl", err);
setIsDownloading("");
alert("something went wrong, please try again later.");
}
};
export const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
//function for print digital sign pdf
export const handleToPrint = async (event, pdfUrl, setIsDownloading) => {
event.preventDefault();
setIsDownloading("pdf");
try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post(
`${appInfo.baseUrl}/functions/getsignedurl`,
{ url: pdfUrl },
{
headers: {
"content-type": "Application/json",
"X-Parse-Application-Id": appInfo.appId,
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const url = axiosRes.data.result;
const pdf = await getBase64FromUrl(url);
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(
atob(pdf)
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank");
setIsDownloading("");
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
setIsDownloading("");
}
} catch (err) {
setIsDownloading("");
console.log("err in getsignedurl", err);
alert("something went wrong, please try again later.");
}
};
//handle download signed pdf
export const handleDownloadCertificate = async (
pdfDetails,
setIsDownloading
) => {
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);
}
} else {
setIsDownloading("certificate");
try {
const data = {
docId: pdfDetails[0]?.objectId
};
const docDetails = await axios.post(
`${localStorage.getItem("baseUrl")}functions/getDocument`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
}
);
if (docDetails.data && docDetails.data.result) {
const doc = docDetails.data.result;
if (doc?.CertificateUrl) {
await fetch(doc?.CertificateUrl);
const certificateUrl = doc?.CertificateUrl;
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
setIsDownloading("");
} else {
setIsDownloading("certificate");
}
}
} catch (err) {
console.log("err in download in certificate", err);
alert("something went wrong, please try again later.");
}
}
};
export async function findContact(value) {
try {
const currentUser = Parse.User.current();
const contactbook = new Parse.Query("contracts_Contactbook");
contactbook.equalTo(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactbook.notEqualTo("IsDeleted", true);
contactbook.matches("Email", new RegExp(value, "i"));
const contactRes = await contactbook.find();
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
return res;
}
} catch (error) {
console.error("Error fetching suggestions:", error);
}
}
-6
View File
@@ -1,12 +1,6 @@
export const contactCls = "contracts_Contactbook"; export const contactCls = "contracts_Contactbook";
export const templateCls = "contracts_Template"; export const templateCls = "contracts_Template";
export const documentCls = "contracts_Document"; export const documentCls = "contracts_Document";
export const rejectBtn =
"bg-[#ffffff] rounded-sm shadow-md text-[12px] font-semibold uppercase text-black py-1.5 px-4 focus:outline-none text-center border-[1px] border-[#b4b4b4]";
export const submitBtn =
"bg-[#32a3ac] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-4 focus:outline-none text-center";
export const modalSubmitBtnColor = "#17a2b8";
export const modalCancelBtnColor = "white";
export const themeColor = "#47a3ad"; export const themeColor = "#47a3ad";
export const iconColor = "#686968"; export const iconColor = "#686968";
export const isEnableSubscription = process.env.REACT_APP_ENABLE_SUBSCRIPTION; export const isEnableSubscription = process.env.REACT_APP_ENABLE_SUBSCRIPTION;
+8 -9
View File
@@ -2,17 +2,16 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
body{ body {
background-color: white; background-color: white;
} }
/* Custom CSS to hide scrollbar */ /* Custom CSS to hide scrollbar */
.hide-scrollbar::-webkit-scrollbar { .hide-scrollbar::-webkit-scrollbar {
display: none; display: none;
} }
.hide-scrollbar { .hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */ -ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */ scrollbar-width: none; /* Firefox */
} }
+1
View File
@@ -16,6 +16,7 @@ import {
import DragElement from "./components/pdf/DragElement"; import DragElement from "./components/pdf/DragElement";
import TagManager from "react-gtm-module"; import TagManager from "react-gtm-module";
import Parse from "parse"; import Parse from "parse";
import './polyfills'
const appId = process.env.REACT_APP_APPID const appId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID
: "opensign"; : "opensign";
+51 -41
View File
@@ -3,7 +3,7 @@ export default function reportJson(id) {
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"]; const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
const contactbook = ["Sr.No", "Title", "Email", "Phone"]; const contactbook = ["Sr.No", "Title", "Email", "Phone"];
const dashboardReportHead = ["Title", "File", "Owner", "Signers"]; const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
switch (id) { switch (id) {
// draft documents report // draft documents report
case "ByHuevtCFY": case "ByHuevtCFY":
@@ -14,8 +14,7 @@ export default function reportJson(id) {
{ {
btnId: "1231", btnId: "1231",
hoverLabel: "Edit", hoverLabel: "Edit",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-pen", btnIcon: "fa-solid fa-pen",
redirectUrl: "draftDocument", redirectUrl: "draftDocument",
action: "redirect" action: "redirect"
@@ -23,8 +22,7 @@ export default function reportJson(id) {
{ {
btnId: "2142", btnId: "2142",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#ff4848", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-trash", btnIcon: "fa fa-trash",
redirectUrl: "", redirectUrl: "",
action: "delete" action: "delete"
@@ -43,8 +41,7 @@ export default function reportJson(id) {
btnId: "4536", btnId: "4536",
btnLabel: "sign", btnLabel: "sign",
hoverLabel: "Sign", hoverLabel: "Sign",
btnColor: "#3ac9d6", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-signature", btnIcon: "fa-solid fa-signature",
redirectUrl: "pdfRequestFiles", redirectUrl: "pdfRequestFiles",
action: "redirect" action: "redirect"
@@ -62,8 +59,7 @@ export default function reportJson(id) {
{ {
btnId: "8901", btnId: "8901",
hoverLabel: "Share", hoverLabel: "Share",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-share", btnIcon: "fa-solid fa-share",
redirectUrl: "", redirectUrl: "",
action: "share" action: "share"
@@ -71,8 +67,7 @@ export default function reportJson(id) {
{ {
btnId: "1588", btnId: "1588",
hoverLabel: "View", hoverLabel: "View",
btnColor: "#3ac9d6", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-eye", btnIcon: "fa fa-eye",
redirectUrl: "pdfRequestFiles", redirectUrl: "pdfRequestFiles",
action: "redirect" action: "redirect"
@@ -80,11 +75,19 @@ export default function reportJson(id) {
{ {
btnId: "2234", btnId: "2234",
hoverLabel: "option", hoverLabel: "option",
btnColor: "transparent", btnColor: "",
textColor: "black", textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg", btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
action: "option", action: "option",
subaction: [ subaction: [
{
btnId: "1630",
btnLabel: "Resend",
hoverLabel: "Resend",
btnIcon: "fa-solid fa-envelope",
redirectUrl: "",
action: "resend"
},
{ {
btnId: "1688", btnId: "1688",
btnLabel: "Revoke", btnLabel: "Revoke",
@@ -116,8 +119,7 @@ export default function reportJson(id) {
{ {
btnId: "1378", btnId: "1378",
hoverLabel: "Edit", hoverLabel: "Edit",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa fa-eye", btnIcon: "fa fa-eye",
redirectUrl: "draftDocument", redirectUrl: "draftDocument",
action: "redirect" action: "redirect"
@@ -125,8 +127,7 @@ export default function reportJson(id) {
{ {
btnId: "1278", btnId: "1278",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#ff4848", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-trash", btnIcon: "fa fa-trash",
redirectUrl: "", redirectUrl: "",
action: "delete" action: "delete"
@@ -144,8 +145,7 @@ export default function reportJson(id) {
{ {
btnId: "1458", btnId: "1458",
hoverLabel: "View", hoverLabel: "View",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa fa-eye", btnIcon: "fa fa-eye",
redirectUrl: "draftDocument", redirectUrl: "draftDocument",
action: "redirect" action: "redirect"
@@ -153,8 +153,7 @@ export default function reportJson(id) {
{ {
btnId: "1358", btnId: "1358",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#ff4848", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-trash", btnIcon: "fa fa-trash",
redirectUrl: "", redirectUrl: "",
action: "delete" action: "delete"
@@ -172,8 +171,7 @@ export default function reportJson(id) {
{ {
btnId: "1898", btnId: "1898",
hoverLabel: "View", hoverLabel: "View",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa fa-eye", btnIcon: "fa fa-eye",
redirectUrl: "draftDocument", redirectUrl: "draftDocument",
action: "redirect" action: "redirect"
@@ -181,8 +179,7 @@ export default function reportJson(id) {
{ {
btnId: "1998", btnId: "1998",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#ff4848", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-trash", btnIcon: "fa fa-trash",
redirectUrl: "", redirectUrl: "",
action: "delete" action: "delete"
@@ -200,8 +197,7 @@ export default function reportJson(id) {
{ {
btnId: "1999", btnId: "1999",
hoverLabel: "Share", hoverLabel: "Share",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-share", btnIcon: "fa-solid fa-share",
redirectUrl: "", redirectUrl: "",
action: "share" action: "share"
@@ -209,8 +205,7 @@ export default function reportJson(id) {
{ {
btnId: "1999", btnId: "1999",
hoverLabel: "View", hoverLabel: "View",
btnColor: "#3ac9d6", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-eye", btnIcon: "fa fa-eye",
redirectUrl: "pdfRequestFiles", redirectUrl: "pdfRequestFiles",
action: "redirect" action: "redirect"
@@ -218,11 +213,19 @@ export default function reportJson(id) {
{ {
btnId: "2234", btnId: "2234",
hoverLabel: "option", hoverLabel: "option",
btnColor: "transparent", btnColor: "",
textColor: "black", textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg", btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
action: "option", action: "option",
subaction: [ subaction: [
{
btnId: "1631",
btnLabel: "Resend",
hoverLabel: "Resend",
btnIcon: "fa-solid fa-envelope",
redirectUrl: "",
action: "resend"
},
{ {
btnId: "6788", btnId: "6788",
btnLabel: "Revoke", btnLabel: "Revoke",
@@ -253,8 +256,7 @@ export default function reportJson(id) {
btnId: "2001", btnId: "2001",
btnLabel: "sign", btnLabel: "sign",
hoverLabel: "Sign", hoverLabel: "Sign",
btnColor: "#3ac9d6", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-signature", btnIcon: "fa-solid fa-signature",
redirectUrl: "pdfRequestFiles", redirectUrl: "pdfRequestFiles",
action: "redirect" action: "redirect"
@@ -270,8 +272,7 @@ export default function reportJson(id) {
{ {
btnId: "2003", btnId: "2003",
hoverLabel: "Edit", hoverLabel: "Edit",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa-solid fa-pen", btnIcon: "fa-solid fa-pen",
redirectUrl: "draftDocument", redirectUrl: "draftDocument",
action: "redirect" action: "redirect"
@@ -279,8 +280,7 @@ export default function reportJson(id) {
{ {
btnId: "2004", btnId: "2004",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#ff4848", btnColor: "op-btn-secondary",
textColor: "white",
btnIcon: "fa fa-trash", btnIcon: "fa fa-trash",
redirectUrl: "", redirectUrl: "",
action: "delete" action: "delete"
@@ -296,8 +296,7 @@ export default function reportJson(id) {
{ {
btnId: "2204", btnId: "2204",
hoverLabel: "Delete", hoverLabel: "Delete",
btnColor: "#f55a42", btnColor: "op-btn-outline op-btn-error",
textColor: "white",
btnIcon: "fa-solid fa-trash", btnIcon: "fa-solid fa-trash",
action: "delete" action: "delete"
} }
@@ -310,14 +309,13 @@ export default function reportJson(id) {
case "6TeaPr321t": case "6TeaPr321t":
return { return {
reportName: "Templates", reportName: "Templates",
heading: head, heading: templateReport,
actions: [ actions: [
{ {
btnId: "2234", btnId: "2234",
btnLabel: "Use", btnLabel: "Use",
hoverLabel: "Use", hoverLabel: "Use",
btnColor: "#4bd396", btnColor: "op-btn-primary",
textColor: "white",
btnIcon: "fa fa-plus", btnIcon: "fa fa-plus",
redirectUrl: "placeHolderSign", redirectUrl: "placeHolderSign",
action: "redirect", action: "redirect",
@@ -325,10 +323,22 @@ export default function reportJson(id) {
message: message:
"Click the 'Use' button to create a new document from an existing template. " "Click the 'Use' button to create a new document from an existing template. "
}, },
{
btnId: "1631",
btnLabel: "Quick send",
hoverLabel: "Quick send",
btnColor: "op-btn-secondary",
btnIcon: "fa-solid fa-envelope",
redirectUrl: "",
action: "bulksend",
selector: "tourbulksend",
message:
"To quickly create and send multiple documents using an existing template, click the 'Quick Send' button."
},
{ {
btnId: "2234", btnId: "2234",
hoverLabel: "option", hoverLabel: "option",
btnColor: "transparent", btnColor: "",
textColor: "black", textColor: "black",
btnIcon: "fa-solid fa-ellipsis-vertical fa-lg", btnIcon: "fa-solid fa-ellipsis-vertical fa-lg",
action: "option", action: "option",
+90
View File
@@ -0,0 +1,90 @@
const dashboardJson = [
{
id: "35KBoSgoAK",
columns: [
{
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-signature",
bgColor: "bg-[#f0058e]",
label: "Need your Signature",
description: null,
data: {
id: "e04ee9dc-932d-6b80-0202-703fd154eb74",
queryType: "",
class: "contracts_Document",
query:
'where={"$and":[{"AuditTrail.UserPtr":{"$ne":{"__type":"Pointer","className": "contracts_Users","objectId":"#objectId#"}}},{"AuditTrail.Activity":{"$ne":"Signed"}}],"Signers":{"$in":[{"__type":"Pointer","className":"contracts_Users","objectId":"#objectId#"}]},"IsDeclined":{"$ne":true},"IsCompleted":{"$ne":true},"Type":{"$ne":"Folder"},"Placeholders":{"$ne":null},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
key: "count",
Redirect_type: "Report",
Redirect_id: "4Hhwbp482K",
tourSection: "tourcard1",
tourMessage:
"Clicking on this card will take you to the list of documents awaiting your review."
}
}
},
{
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "Card",
icon: "fas fa-sign-out-alt",
bgColor: "bg-[#2ed8b6]",
label: "Out for signatures",
description: null,
data: {
id: "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f",
queryType: "",
class: "contracts_Document",
query:
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true,"#*ne":[]},"Placeholders":{"#*ne":null},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
key: "count",
Redirect_type: "Report",
Redirect_id: "1MwEuxLEkF",
tourSection: "tourcard2",
tourMessage:
"Clicking on this card will take you to a list of documents awaiting signature."
}
}
},
{
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "report",
reportId: "5Go51Q7T8r",
data: {
tourSection: "tourreport1",
tourMessage:
"This is a list of documents that are waiting for your signature."
}
}
},
{
colsize: "col-span-12 md:col-span-6 lg:col-span-6",
widget: {
type: "report",
reportId: "d9k3UfYHBc",
data: {
tourSection: "tourreport2",
tourMessage:
"This is a list of documents you've sent to other parties for signature."
}
}
},
{
colsize: "col-span-12 md:col-span-12 lg:col-span-12",
widget: {
type: "report",
reportId: "kC5mfynCi4",
data: {
tourSection: "tourreport3",
tourMessage:
"This are documents you have started but have not finalized for sending."
}
}
}
]
}
];
export default dashboardJson;
+2 -1
View File
@@ -52,7 +52,8 @@ const plans = [
"API Access", "API Access",
"100 API signatures included", "100 API signatures included",
"DocumentId removal from signed docs", "DocumentId removal from signed docs",
"Custom email templates" "Custom email templates",
"Auto reminders"
] ]
}, },
{ {
+31 -41
View File
@@ -12,6 +12,7 @@ import { useNavigate, useLocation, Outlet } from "react-router-dom";
import { isEnableSubscription } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { useCookies } from "react-cookie"; import { useCookies } from "react-cookie";
import { fetchSubscription } from "../constant/Utils"; import { fetchSubscription } from "../constant/Utils";
import Loader from "../primitives/Loader";
const HomeLayout = () => { const HomeLayout = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -28,29 +29,34 @@ const HomeLayout = () => {
const [tourConfigs, setTourConfigs] = useState([]); const [tourConfigs, setTourConfigs] = useState([]);
const [, setCookie] = useCookies(["accesstoken", "main_Domain"]); const [, setCookie] = useCookies(["accesstoken", "main_Domain"]);
const tenantId = localStorage.getItem("TenantId");
useEffect(() => { useEffect(() => {
(async () => { if (!tenantId) {
try { setIsUserValid(false);
// Use the session token to validate the user } else {
const userQuery = new Parse.Query(Parse.User); (async () => {
const user = await userQuery.get(Parse.User.current().id, { try {
sessionToken: localStorage.getItem("accesstoken") // Use the session token to validate the user
}); const userQuery = new Parse.Query(Parse.User);
if (user) { const user = await userQuery.get(Parse.User.current().id, {
localStorage.setItem("profileImg", user.get("ProfilePic") || ""); sessionToken: localStorage.getItem("accesstoken")
checkIsSubscribed(); });
} else { if (user) {
localStorage.setItem("profileImg", user.get("ProfilePic") || "");
checkIsSubscribed();
} else {
setIsUserValid(false);
}
} catch (error) {
// Session token is invalid or there was an error
setIsUserValid(false); setIsUserValid(false);
} }
} catch (error) { })();
// Session token is invalid or there was an error saveCookies();
setIsUserValid(false); }
}
})();
saveCookies();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, [tenantId]);
//function to use save data in cookies storage //function to use save data in cookies storage
const saveCookies = () => { const saveCookies = () => {
const main_Domain = window.location.origin; const main_Domain = window.location.origin;
@@ -242,27 +248,14 @@ const HomeLayout = () => {
}; };
return ( return (
<div> <div>
<div className="sticky top-0 z-50"> <div className="sticky top-0 z-[101]">
{!isLoader && <Header showSidebar={showSidebar} />} {!isLoader && <Header showSidebar={showSidebar} />}
</div> </div>
{isUserValid ? ( {isUserValid ? (
<> <>
{isLoader ? ( {isLoader ? (
<div <div className="flex h-[100vh] justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<> <>
@@ -272,7 +265,7 @@ const HomeLayout = () => {
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"
> >
<div className="bg-[#eef1f5] p-3">{<Outlet />}</div> <div className="bg-base-200 p-3">{<Outlet />}</div>
<div className="z-30"> <div className="z-30">
<Footer /> <Footer />
</div> </div>
@@ -293,13 +286,10 @@ const HomeLayout = () => {
)} )}
</> </>
) : ( ) : (
<ModalUi title={"Session Expired"} isOpen={true} showClose={false}> <ModalUi showHeader={false} isOpen={true} showClose={false}>
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5"> <div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
<p className="text-xl font-normal">Your session has expired.</p> <p className="text-xl font-medium">Your session has expired.</p>
<button <button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
onClick={handleLoginBtn}
className="text-base px-3 py-1.5 rounded shadow-md text-white bg-[#1ab6ce]"
>
Login Login
</button> </button>
</div> </div>
+6 -9
View File
@@ -49,13 +49,13 @@ function ChangePassword() {
return <Navigate to="/" />; return <Navigate to="/" />;
} }
return ( return (
<div className="w-full bg-white shadow rounded p-2"> <div className="w-full bg-base-100 text-base-content shadow rounded p-2">
<Title title={"Change Password"} /> <Title title={"Change Password"} />
<div className="text-xl font-bold border-b-[1px] border-gray-300"> <div className="text-xl font-bold border-b-[1px] border-gray-300">
Change Password Change Password
</div> </div>
<div className="m-2"> <div className="m-2">
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit} className=" flex flex-col gap-y-2">
<div> <div>
<label htmlFor="currentpassword" className="block text-xs ml-1"> <label htmlFor="currentpassword" className="block text-xs ml-1">
Current Password Current Password
@@ -65,7 +65,7 @@ function ChangePassword() {
name="currentpassword" name="currentpassword"
value={currentpassword} value={currentpassword}
onChange={(e) => setCurrentPassword(e.target.value)} onChange={(e) => setCurrentPassword(e.target.value)}
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm text-xs w-full"
placeholder="Current Password" placeholder="Current Password"
required required
/> />
@@ -79,7 +79,7 @@ function ChangePassword() {
name="newpassword" name="newpassword"
value={newpassword} value={newpassword}
onChange={(e) => setnewpassword(e.target.value)} onChange={(e) => setnewpassword(e.target.value)}
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm text-xs w-full"
placeholder="New Password" placeholder="New Password"
required required
/> />
@@ -91,17 +91,14 @@ function ChangePassword() {
<input <input
type="password" type="password"
name="confirmpassword" name="confirmpassword"
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm text-xs w-full"
value={confirmpassword} value={confirmpassword}
onChange={(e) => setconfirmpassword(e.target.value)} onChange={(e) => setconfirmpassword(e.target.value)}
placeholder="Confirm Password" placeholder="Confirm Password"
required required
/> />
</div> </div>
<button <button type="submit" className="op-btn op-btn-primary shadow-md m-2">
type="submit"
className="bg-[#188ae2] m-2 px-4 py-3 rounded-sm shadow-md text-white text-xs font-semibold uppercase"
>
Change Password Change Password
</button> </button>
</form> </form>
+16 -83
View File
@@ -1,20 +1,19 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Parse from "parse";
import "../styles/loader.css"; import "../styles/loader.css";
import GetDashboard from "../components/dashboard/GetDashboard"; import GetDashboard from "../components/dashboard/GetDashboard";
import { useNavigate, useParams } from "react-router-dom"; 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";
import dashboardJson from "../json/dashboardJson";
import Loader from "../primitives/Loader";
const Dashboard = () => { const Dashboard = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { id } = useParams(); const { id } = useParams();
const [dashboard, setdashboard] = useState([]); const [dashboard, setdashboard] = useState({});
const [classnameArray, setclassnameArray] = useState([]); const [loading, setloading] = useState(true);
const [loading, setloading] = useState(false);
const [defaultQuery, setDefaultQuery] = useState("");
useEffect(() => { useEffect(() => {
if (localStorage.getItem("accesstoken")) { if (localStorage.getItem("accesstoken")) {
@@ -24,59 +23,16 @@ const Dashboard = () => {
getDashboard(localStorage.getItem("PageLanding")); getDashboard(localStorage.getItem("PageLanding"));
} }
} else { } else {
navigate("/", { replace: true, state: { from: location } }); navigate("/", { replace: true, state: { from: "" } });
} }
// eslint-disable-next-line // eslint-disable-next-line
}, [id]); }, [id]);
const getDashboard = async (id) => { const getDashboard = async (id) => {
setloading(true);
try { try {
var forms = Parse.Object.extend("w_dashboard"); const dashboard = dashboardJson.find((x) => x.id === id);
var query = new Parse.Query(forms); setdashboard(dashboard);
query.equalTo("objectId", id); const dashboardTour = dashboard.columns
const results = await query.first();
const resultjson = results.toJSON();
let classArray = [];
let DefaultQuery = "";
resultjson.rows.forEach((x) => {
let col_lg = "",
col_md = "",
col_xs = "",
col_sm = "",
col_ = "",
obj = {};
let subItem = [];
let item = "";
x.columns.forEach((y) => {
if (y.widget.type === "customeHtml") {
DefaultQuery = y.widget.data[0].default;
}
if (Number(y["collg"]) > 0) {
col_lg = "col-lg-" + y["collg"];
}
if (Number(y["colmd"]) > 0) {
col_md = "col-md-" + y["colmd"];
}
if (Number(y["colxs"]) > 0) {
col_xs = "col-xs-" + y["colxs"];
}
if (Number(y["colsm"]) > 0) {
col_sm = "col-sm-" + y["colsm"];
}
if (Number(y["col"]) > 0) {
col_ = "col-" + y["col"];
}
item =
col_lg + " " + col_md + " " + col_xs + " " + col_sm + " " + col_;
subItem.push(item);
});
obj = subItem;
classArray.push(obj);
});
setdashboard(resultjson.rows);
// console.log("resultjson.rows ", resultjson.rows);
const arr = resultjson.rows[0].columns
.filter((col) => { .filter((col) => {
if (col.widget.data && col.widget.data.tourSection) { if (col.widget.data && col.widget.data.tourSection) {
return col; return col;
@@ -90,14 +46,7 @@ const Dashboard = () => {
// style: { backgroundColor: "#abd4d2" }, // style: { backgroundColor: "#abd4d2" },
}; };
}); });
dispatch(saveTourSteps(arr)); dispatch(saveTourSteps(dashboardTour));
// console.log("arr ", arr);
setclassnameArray(classArray);
if (localStorage.getItem("DashboardDefaultFilter")) {
setDefaultQuery(localStorage.getItem("DashboardDefaultFilter"));
} else {
setDefaultQuery(DefaultQuery);
}
setloading(false); setloading(false);
} catch (e) { } catch (e) {
console.error("Problem", e); console.error("Problem", e);
@@ -105,32 +54,16 @@ const Dashboard = () => {
} }
}; };
let _dash = (
<GetDashboard
dashboard={dashboard}
classnameArray={classnameArray}
DefaultQuery={defaultQuery}
/>
);
if (loading) {
_dash = (
<div style={{ height: "300px", backgroundColor: "white" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
);
}
return ( return (
<React.Fragment> <React.Fragment>
<Title title="Dashboard" /> <Title title="Dashboard" />
{_dash} {loading ? (
<div className="h-[300px] w-full bg-white flex justify-center items-center rounded-md">
<Loader />
</div>
) : (
<GetDashboard dashboard={dashboard} />
)}
</React.Fragment> </React.Fragment>
); );
}; };
+39 -24
View File
@@ -1,21 +1,26 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Title from "../components/Title"; import Title from "../components/Title";
import { NavLink } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import login_img from "../assets/images/login_img.svg"; import login_img from "../assets/images/login_img.svg";
import Parse from "parse"; import Parse from "parse";
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 { isEnableSubscription } from "../constant/const";
import { getAppLogo } from "../constant/Utils";
function ForgotPassword() { function ForgotPassword() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate();
const [state, setState] = useState({ const [state, setState] = useState({
email: "", email: "",
password: "", password: "",
hideNav: "" hideNav: ""
}); });
const [sentStatus, setSentStatus] = useState(""); const [sentStatus, setSentStatus] = useState("");
const [image, setImage] = useState();
const handleChange = (event) => { const handleChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
setState({ ...state, [name]: value }); setState({ ...state, [name]: value });
@@ -51,15 +56,26 @@ function ForgotPassword() {
useEffect(() => { useEffect(() => {
dispatch(fetchAppInfo()); dispatch(fetchAppInfo());
saveLogo();
resize(); resize();
window.addEventListener("resize", resize); window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize); return () => window.removeEventListener("resize", resize);
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, []);
const saveLogo = async () => {
let image = appInfo.applogo; if (isEnableSubscription) {
const logo = await getAppLogo();
if (logo) {
setImage(logo);
} else {
setImage(appInfo?.applogo || undefined);
}
} else {
setImage(appInfo?.applogo || undefined);
}
};
return ( return (
<div className="bg-white"> <div>
<Title title="Forgot password page" /> <Title title="Forgot password page" />
{sentStatus === "success" && ( {sentStatus === "success" && (
<Alert type="success"> <Alert type="success">
@@ -69,29 +85,31 @@ function ForgotPassword() {
{sentStatus === "failed" && ( {sentStatus === "failed" && (
<Alert type={"danger"}>Please setup email adapter </Alert> <Alert type={"danger"}>Please setup email adapter </Alert>
)} )}
<div> <div className="md:p-10 lg:p-16">
<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:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
<div className="w-[250px] h-[66px] inline-block"> <div className="w-[250px] h-[66px] inline-block overflow-hidden">
{state.hideNav ? ( {image && (
<img src={image} width="100%" alt="" /> <img
) : ( src={image}
<img src={image} width="100%" alt="" /> className="object-contain h-full"
alt="applogo"
/>
)} )}
</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>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Welcome Back !</h2> <h2 className="text-[30px] mt-6">Welcome Back !</h2>
<span className="text-[12px] text-[#878787]"> <span className="text-[12px] text-[#878787]">
Reset Your Password Reset Your Password
</span> </span>
<div className="shadow-md rounded my-4"> <div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<div className="px-6 py-4"> <div className="px-6 py-4">
<label className="block text-xs">Email</label> <label className="block text-xs">Email</label>
<input <input
type="text" type="email"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="email" name="email"
className="op-input op-input-bordered op-input-sm w-full"
value={state.email} value={state.email}
onChange={handleChange} onChange={handleChange}
required required
@@ -99,19 +117,16 @@ function ForgotPassword() {
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
</div> </div>
</div> </div>
<div className="flex justify-between items-center px-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
<button <button type="submit" className="op-btn op-btn-primary">
type="submit"
className="rounded-sm bg-[#3ac9d6] text-white px-4 py-3 text-xs font-semibold shadow uppercase"
>
Submit Submit
</button> </button>
<NavLink <button
to="/" onClick={() => navigate("/", { replace: true })}
className="rounded-sm bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-3 text-xs font-semibold shadow uppercase" className="op-btn op-btn-secondary"
> >
Login Login
</NavLink> </button>
</div> </div>
</form> </form>
</div> </div>
+207 -74
View File
@@ -11,11 +11,15 @@ 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 { SaveFileSize } from "../constant/saveFileSize";
import { getFileName, toDataUrl } from "../constant/Utils"; import { checkIsSubscribed, getFileName, toDataUrl } from "../constant/Utils";
import { PDFDocument } from "pdf-lib"; import { PDFDocument } from "pdf-lib";
import axios from "axios"; import axios from "axios";
import { isEnableSubscription, submitBtn } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import ModalUi from "../primitives/ModalUi"; import ModalUi from "../primitives/ModalUi";
import { Tooltip } from "react-tooltip";
import Upgrade from "../primitives/Upgrade";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Loader from "../primitives/Loader";
// `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() {
@@ -47,7 +51,9 @@ const Forms = (props) => {
TimeToCompleteDays: 15, TimeToCompleteDays: 15,
SendinOrder: "false", SendinOrder: "false",
password: "", password: "",
file: "" file: "",
remindOnceInEvery: 5,
autoreminder: false
}); });
const [fileupload, setFileUpload] = useState(""); const [fileupload, setFileUpload] = useState("");
const [fileload, setfileload] = useState(false); const [fileload, setfileload] = useState(false);
@@ -59,6 +65,7 @@ const Forms = (props) => {
const [isPassword, setIsPassword] = useState(false); const [isPassword, setIsPassword] = useState(false);
const [isDecrypting, setIsDecrypting] = useState(false); const [isDecrypting, setIsDecrypting] = useState(false);
const [isCorrectPass, setIsCorrectPass] = useState(true); const [isCorrectPass, setIsCorrectPass] = useState(true);
const [isSubscribe, setIsSubscribe] = useState(false);
const handleStrInput = (e) => { const handleStrInput = (e) => {
setIsCorrectPass(true); setIsCorrectPass(true);
setFormData({ ...formData, [e.target.name]: e.target.value }); setFormData({ ...formData, [e.target.name]: e.target.value });
@@ -69,6 +76,17 @@ const Forms = (props) => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.title]); }, [props.title]);
useEffect(() => {
fetchSubscription();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const fetchSubscription = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
}
};
function getFileAsArrayBuffer(file) { function getFileAsArrayBuffer(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const reader = new FileReader(); const reader = new FileReader();
@@ -382,6 +400,8 @@ const Forms = (props) => {
if (props.title !== "Sign Yourself") { if (props.title !== "Sign Yourself") {
const isChecked = formData.SendinOrder === "false" ? false : true; const isChecked = formData.SendinOrder === "false" ? false : true;
object.set("SendinOrder", isChecked); object.set("SendinOrder", isChecked);
object.set("AutomaticReminders", formData.autoreminder);
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
} }
object.set("URL", fileupload); object.set("URL", fileupload);
object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
@@ -401,7 +421,6 @@ const Forms = (props) => {
className: "contracts_Users", className: "contracts_Users",
objectId: ExtCls[0].objectId objectId: ExtCls[0].objectId
}); });
const res = await object.save(); const res = await object.save();
if (res) { if (res) {
setSigners([]); setSigners([]);
@@ -456,12 +475,19 @@ const Forms = (props) => {
? "Note to myself" ? "Note to myself"
: "Please review and sign this document", : "Please review and sign this document",
TimeToCompleteDays: 15, TimeToCompleteDays: 15,
SendinOrder: "true" SendinOrder: "true",
password: "",
file: "",
remindOnceInEvery: 5,
autoreminder: false
}); });
setFileUpload(""); setFileUpload("");
setpercentage(0); setpercentage(0);
setTimeout(() => setIsReset(false), 50); setTimeout(() => setIsReset(false), 50);
}; };
const handleCancel = () => {
navigate("/dashboard/35KBoSgoAK");
};
const handlePasswordSubmit = async (e) => { const handlePasswordSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
setIsPassword(false); setIsPassword(false);
@@ -535,8 +561,11 @@ const Forms = (props) => {
inputFileRef.current.value = ""; // Set file input value to empty string inputFileRef.current.value = ""; // Set file input value to empty string
} }
}; };
const handleAutoReminder = () => {
setFormData((prev) => ({ ...prev, autoreminder: !formData.autoreminder }));
};
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-base-100 text-base-content md:border-[1px] md:border-gray-600/50">
<Title title={props?.title} /> <Title title={props?.title} />
{isAlert && ( {isAlert && (
<Alert type={isErr ? "danger" : "success"}> <Alert type={isErr ? "danger" : "success"}>
@@ -546,16 +575,8 @@ const Forms = (props) => {
</Alert> </Alert>
)} )}
{isSubmit ? ( {isSubmit ? (
<div style={{ height: "300px" }}> <div className="h-[300px] flex justify-center items-center">
<div <Loader />
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<> <>
@@ -566,29 +587,30 @@ const Forms = (props) => {
> >
<form onSubmit={handlePasswordSubmit}> <form onSubmit={handlePasswordSubmit}>
<div className="px-6 pt-3 pb-2"> <div className="px-6 pt-3 pb-2">
<label className="mb-2 text-xs">Password</label> <label className="mb-2 text-xs text-base-content">
Password
</label>
<input <input
type="text" type="text"
name="password" name="password"
value={formData.password} value={formData.password}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
placeholder="Enter pdf password" placeholder="Enter pdf password"
required required
/> />
{!isCorrectPass ? ( <p
<p className="ml-2 text-[11px] text-red-600"> className={`${
Please provide correct password !isCorrectPass
</p> ? "text-red-600"
) : ( : "text-transparent pointer-events-none"
<p className="ml-2 text-[11px] text-transparent text-red-600"> } ml-2 text-[11px] `}
. >
</p> Please provide correct password
)} </p>
</div> </div>
<hr /> <div className="px-6 mb-3">
<div className="px-6 my-3"> <button type="submit" className="op-btn op-btn-primary">
<button type="submit" className={submitBtn}>
Submit Submit
</button> </button>
</div> </div>
@@ -604,12 +626,12 @@ const Forms = (props) => {
style={{ width: `${percentage}%` }} style={{ width: `${percentage}%` }}
></div> ></div>
</div> </div>
<span className="text-black text-sm">{percentage}%</span> <span className="text-base-content text-sm">{percentage}%</span>
</div> </div>
)} )}
{isDecrypting && ( {isDecrypting && (
<div className="flex items-center gap-x-2"> <div className="flex items-center gap-x-2">
<span className="text-black text-sm"> <span className="text-base-content text-sm">
Decrypting pdf please wait... Decrypting pdf please wait...
</span> </span>
</div> </div>
@@ -623,13 +645,13 @@ const Forms = (props) => {
</label> </label>
{fileupload.length > 0 ? ( {fileupload.length > 0 ? (
<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 op-input op-input-bordered op-input-sm w-full text-x text-[13px]">
<div className="break-all"> <div className="break-all">
file selected : {getFileName(fileupload)} file selected : {getFileName(fileupload)}
</div> </div>
<div <div
onClick={() => setFileUpload("")} onClick={() => setFileUpload("")}
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" className="cursor-pointer px-[10px] text-[20px] font-bold text-red-500"
> >
<i className="fa-solid fa-xmark"></i> <i className="fa-solid fa-xmark"></i>
</div> </div>
@@ -642,10 +664,10 @@ const Forms = (props) => {
)} )}
</div> </div>
) : ( ) : (
<div className="flex gap-2 justify-center items-center"> <div className="flex gap-2 justify-center items-center ">
<input <input
type="file" type="file"
className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-file-input op-file-input-bordered op-file-input-sm focus:outline-none hover:border-base-content w-full text-xs"
onChange={(e) => handleFileInput(e)} onChange={(e) => handleFileInput(e)}
ref={inputFileRef} ref={inputFileRef}
accept={ accept={
@@ -673,7 +695,7 @@ const Forms = (props) => {
</label> </label>
<input <input
name="Name" name="Name"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.Name} value={formData.Name}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
required required
@@ -683,7 +705,7 @@ const Forms = (props) => {
<label className="block">Description</label> <label className="block">Description</label>
<input <input
name="Description" name="Description"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.Description} value={formData.Description}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
/> />
@@ -701,18 +723,19 @@ const Forms = (props) => {
</label> </label>
<input <input
name="Note" name="Note"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.Note} value={formData.Note}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
required required
/> />
</div> </div>
<SelectFolder {props.title !== "New Template" && (
onSuccess={handleFolder} <SelectFolder
folderCls={props.Cls} onSuccess={handleFolder}
isReset={isReset} folderCls={props.Cls}
/> isReset={isReset}
/>
)}
{props.title === "Request Signatures" && ( {props.title === "Request Signatures" && (
<div className="text-xs mt-2"> <div className="text-xs mt-2">
<label className="block"> <label className="block">
@@ -722,7 +745,7 @@ const Forms = (props) => {
<input <input
type="number" type="number"
name="TimeToCompleteDays" name="TimeToCompleteDays"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.TimeToCompleteDays} value={formData.TimeToCompleteDays}
onChange={(e) => handleStrInput(e)} onChange={(e) => handleStrInput(e)}
required required
@@ -730,46 +753,156 @@ const Forms = (props) => {
</div> </div>
)} )}
{props.title !== "Sign Yourself" && ( {props.title !== "Sign Yourself" && (
<div className="text-xs mt-2"> <>
<label className="block">Send In Order</label> <div className="text-xs mt-2">
<div className="flex items-center gap-2 ml-2 mb-1"> <label className="block">
<input Send In Order
type="radio" <a data-tooltip-id="sendInOrder-tooltip" className="ml-1">
value={"true"} <sup>
name="SendinOrder" <i
checked={formData.SendinOrder === "true"} className="fa-solid fa-question rounded-full"
className="" style={{
onChange={handleStrInput} borderColor: "#33bbff",
/> color: "#33bbff",
<div className="text-center">Yes</div> fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
}}
></i>
</sup>
</a>
<Tooltip id="sendInOrder-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">Send in Order</p>
<p>
Choose how you want the signing requests to be sent to
the document signers:
</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">Yes:</span>
<span>
Selecting this option will send the signing
request to the first signer initially. Once the
first signer completes their part, the next
signer in the sequence will receive the request.
This process continues until all signers have
signed the document. This method ensures that
the document is signed in a specific order.
</span>
</li>
<li>
<span className="font-bold">No: </span>
<span>
Selecting this option will send the signing
links to all signers simultaneously. Every
signer can sign the document at their
convenience, regardless of whether other signers
have completed their signatures. This method is
faster but does not enforce any signing order
among the participants.
</span>
</li>
</ol>
</p>
<p>
Select the option that best suits the needs of your
document processing.
</p>
</div>
</Tooltip>
</label>
<div className="flex items-center gap-2 ml-2 mb-1">
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="SendinOrder"
checked={formData.SendinOrder === "true"}
onChange={handleStrInput}
/>
<div className="text-center">Yes</div>
</div>
<div className="flex items-center gap-2 ml-2 mb-1">
<input
type="radio"
value={"false"}
name="SendinOrder"
className="op-radio op-radio-xs"
checked={formData.SendinOrder === "false"}
onChange={handleStrInput}
/>
<div className="text-center">No</div>
</div>
</div> </div>
<div className="flex items-center gap-2 ml-2 mb-1"> <div className="text-xs mt-2">
<input {!isEnableSubscription && (
type="radio" <PremiumAlertHeader
value={"false"} message={
name="SendinOrder" "Disable Auto reminder is free in beta, this feature will incur a fee later."
checked={formData.SendinOrder === "false"} }
onChange={handleStrInput} />
/> )}
<div className="text-center">No</div> <span
className={
isSubscribe || !isEnableSubscription
? "font-semibold"
: "font-semibold text-gray-300"
}
>
Auto reminder{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<label
className={`${
isSubscribe || !isEnableSubscription
? "cursor-pointer "
: "pointer-events-none opacity-50"
} relative block items-center mb-0`}
>
<input
type="checkbox"
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white"
checked={formData.autoreminder}
onChange={handleAutoReminder}
/>
</label>
</div> </div>
</div> {formData?.autoreminder === true && (
<div className="text-xs mt-2">
<label className="block">
Remind once in every (Days)
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
type="number"
value={formData.remindOnceInEvery}
name="remindOnceInEvery"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
onChange={handleStrInput}
required
/>
</div>
)}
</>
)} )}
<div className="flex items-center mt-3 gap-2 text-white"> <div className="flex items-center mt-3 gap-2">
<button <button
className={`${ className={`${
isSubmit && "cursor-progress" isSubmit ? "cursor-progress" : ""
} bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none`} } op-btn op-btn-primary`}
type="submit" type="submit"
disabled={isSubmit} disabled={isSubmit}
> >
Next Next
</button> </button>
<div <div
className="cursor-pointer bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none" className="op-btn op-btn-ghost"
onClick={() => handleReset()} onClick={() => handleCancel()}
> >
Reset Cancel
</div> </div>
</div> </div>
</form> </form>
+28 -34
View File
@@ -4,10 +4,11 @@ import axios from "axios";
import { useNavigate } from "react-router-dom"; 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 { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribed, copytoData, 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";
import Loader from "../primitives/Loader";
function GenerateToken() { function GenerateToken() {
const navigation = useNavigate(); const navigation = useNavigate();
@@ -109,24 +110,11 @@ function GenerateToken() {
{copied && <Alert type="success">Copied</Alert>} {copied && <Alert type="success">Copied</Alert>}
{isErr && <Alert type="danger">Something went wrong!</Alert>} {isErr && <Alert type="danger">Something went wrong!</Alert>}
{isLoader ? ( {isLoader ? (
<div <div className="flex justify-center items-center h-screen">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<div className="bg-white flex flex-col justify-center shadow rounded"> <div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded">
{!isEnableSubscription && <PremiumAlertHeader />} {!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}> <h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign API{" "} OpenSign API{" "}
@@ -144,29 +132,32 @@ function GenerateToken() {
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none" : "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none"
} }
> >
<li <li className="flex flex-col md:flex-row 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`} <div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5 ">
>
<div className="w-[70%] flex-col md:flex-row flex items-center gap-5 ">
<span className="">Api Token:</span>{" "} <span className="">Api Token:</span>{" "}
<span <span id="token" className="md:text-end py-2 md:py-0">
id="token" <span
className=" md:text-end cursor-pointer" className="cursor-pointer"
onClick={() => copytoclipboard(apiToken)} onClick={() => copytoclipboard(apiToken)}
> >
{apiToken ? apiToken : "_____"} {apiToken ? apiToken : "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2"
onClick={() => copytoclipboard(apiToken)}
>
<i className="fa-solid fa-copy"></i>
</button>
</span> </span>
</div> </div>
<button <button
type="button"
onClick={apiToken ? handleModal : handleSubmit} 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" className="op-btn op-btn-primary"
> >
{apiToken ? "Regenerate Token" : "Generate Token"} {apiToken ? "Regenerate Token" : "Generate Token"}
</button> </button>
</li> </li>
</ul> </ul>
<div className="flex items-center justify-center "> <div className="flex items-center justify-center ">
<button <button
type="button" type="button"
@@ -175,7 +166,7 @@ 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] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none" className="op-btn op-btn-secondary my-2"
> >
View Docs View Docs
</button> </button>
@@ -216,7 +207,7 @@ function GenerateToken() {
handleClose={handleModal} handleClose={handleModal}
> >
<div className="m-[20px]"> <div className="m-[20px]">
<div className="text-lg font-normal text-black"> <div className="text-lg font-normal text-base-content">
Are you sure you want to regenerate token it will expire old Are you sure you want to regenerate token it will expire old
token? token?
</div> </div>
@@ -224,11 +215,14 @@ function GenerateToken() {
<div className="flex items-center mt-3 gap-2 text-white"> <div className="flex items-center mt-3 gap-2 text-white">
<button <button
onClick={handleSubmit} onClick={handleSubmit}
className={submitBtn + "ml-[2px]"} className="op-btn op-btn-primary ml-[2px]"
> >
Yes Yes
</button> </button>
<button onClick={handleModal} className={rejectBtn}> <button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No No
</button> </button>
</div> </div>
+188 -169
View File
@@ -1,16 +1,16 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import "../styles/loginPage.css";
import loader from "../assets/images/loader2.gif";
import axios from "axios"; import axios from "axios";
import { isEnableSubscription, themeColor } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { contractUsers, getAppLogo } from "../constant/Utils"; import { contractUsers, getAppLogo } from "../constant/Utils";
import logo from "../assets/images/logo.png"; import logo from "../assets/images/logo.png";
import { appInfo } from "../constant/appinfo"; import { appInfo } from "../constant/appinfo";
import Parse from "parse";
import Loader from "../primitives/Loader";
function GuestLogin() { function GuestLogin() {
const { id, userMail, contactBookId, base64url } = useParams(); const { id, userMail, contactBookId, base64url } = useParams();
let navigate = useNavigate(); const navigate = useNavigate();
const [email, setEmail] = useState(userMail); const [email, setEmail] = useState(userMail);
const [OTP, setOTP] = useState(""); const [OTP, setOTP] = useState("");
const [EnterOTP, setEnterOtp] = useState(false); const [EnterOTP, setEnterOtp] = useState(false);
@@ -19,9 +19,10 @@ function GuestLogin() {
const [appLogo, setAppLogo] = useState(""); const [appLogo, setAppLogo] = useState("");
const [documentId, setDocumentId] = useState(id); const [documentId, setDocumentId] = useState(id);
const [contactId, setContactId] = useState(contactBookId); const [contactId, setContactId] = useState(contactBookId);
const [sendmail, setSendmail] = useState();
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
useEffect(() => { useEffect(() => {
handleServerUrl(); handleServerUrl();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@@ -52,53 +53,51 @@ function GuestLogin() {
//split url in array from '/' //split url in array from '/'
const checkSplit = decodebase64.split("/"); const checkSplit = decodebase64.split("/");
setDocumentId(checkSplit[0]); setDocumentId(checkSplit[0]);
setContact((prev) => ({ ...prev, email: checkSplit[1] }));
setEmail(checkSplit[1]); setEmail(checkSplit[1]);
setContactId(checkSplit[2]); const contactId = checkSplit?.[2];
setSendmail(checkSplit[3]);
if (!contactId) {
const params = { email: checkSplit[1], docId: checkSplit[0] };
try {
const linkContactRes = await Parse.Cloud.run(
"linkcontacttodoc",
params
);
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes?.contactId);
} catch (err) {
console.log("Err in link ext contact", err);
}
} else {
setContactId(checkSplit[2]);
}
} }
setIsLoading(false); setIsLoading(false);
}; };
const handleChange = (event) => {
const { value } = event.target;
setOTP(value);
};
//send email OTP function //send email OTP function
const SendOtp = async (e) => { const SendOtp = async () => {
const serverUrl = setLoading(true);
localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl"); setEmail(email);
const parseId = try {
localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId"); const params = { email: email.toString(), docId: documentId };
if (serverUrl && localStorage) { const Otp = await Parse.Cloud.run("SendOTPMailV1", params);
setLoading(true); if (Otp) {
e.preventDefault(); setLoading(false);
setEmail(email); setEnterOtp(true);
try {
let url = `${serverUrl}functions/SendOTPMailV1/`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseId
};
let body = {
email: email.toString(),
docId: documentId
};
let Otp = await axios.post(url, body, { headers: headers });
if (Otp) {
setLoading(false);
setEnterOtp(true);
}
} catch (error) {
alert("something went wrong!");
} }
} else { } catch (error) {
alert("something went wrong!"); alert("something went wrong!");
} }
}; };
const handleSendOTPBtn = async (e) => {
e.preventDefault();
await SendOtp();
};
//verify OTP send on via email //verify OTP send on via email
const VerifyOTP = async (e) => { const VerifyOTP = async (e) => {
e.preventDefault(); e.preventDefault();
@@ -134,7 +133,8 @@ function GuestLogin() {
`Parse/${parseId}/currentUser`, `Parse/${parseId}/currentUser`,
JSON.stringify(_user) JSON.stringify(_user)
); );
if (contractUserDetails) { // console.log("contractUserDetails ", contractUserDetails);
if (contractUserDetails && contractUserDetails.length > 0) {
localStorage.setItem( localStorage.setItem(
"Extand_Class", "Extand_Class",
JSON.stringify(contractUserDetails) JSON.stringify(contractUserDetails)
@@ -146,7 +146,13 @@ function GuestLogin() {
//save isGuestSigner true in local to handle login flow header in mobile view //save isGuestSigner true in local to handle login flow header in mobile view
localStorage.setItem("isGuestSigner", true); localStorage.setItem("isGuestSigner", true);
setLoading(false); setLoading(false);
navigate(`/load/recipientSignPdf/${documentId}/${contactId}`); if (sendmail === "false") {
navigate(
`/load/recipientSignPdf/${documentId}/${contactId}?sendmail=${sendmail}`
);
} else {
navigate(`/load/recipientSignPdf/${documentId}/${contactId}`);
}
} }
} catch (error) { } catch (error) {
console.log("err ", error); console.log("err ", error);
@@ -155,156 +161,169 @@ function GuestLogin() {
alert("Please Enter OTP!"); alert("Please Enter OTP!");
} }
}; };
const handleUserData = async (e) => {
e.preventDefault();
const params = { ...contact, docId: documentId };
try {
setLoading(true);
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes.contactId);
setEnterOtp(true);
await SendOtp();
} catch (err) {
setLoading(false);
alert("something went wron, please try agian later.");
console.log("Err in link ext contact", err);
}
};
const handleInputChange = (e) => {
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
return ( return (
<div style={{ padding: "2rem", background: "white" }}> <div className="p-[2rem]">
{isLoading ? ( {isLoading ? (
<div <div className="flex flex-col justify-center items-center h-[100vh]">
style={{ <Loader />
display: "flex", <span className="text-[13px] text-[gray]">{isLoading.message}</span>
justifyContent: "center",
alignItems: "center",
height: "100vh",
flexDirection: "column"
}}
>
<img
alt="no img"
src={loader}
style={{ width: "80px", height: "80px" }}
/>
<span style={{ fontSize: "13px", color: "gray" }}>
{isLoading.message}
</span>
</div> </div>
) : ( ) : (
<div <div className="m-1 md:m-2 p-[30px] text-base-content bg-base-100 op-card shadow-md">
style={{ <div className="md:w-[250px] md:h-[66px] inline-block overflow-hidden mt-2 mb-11">
margin: "10px", {appLogo && (
border: "0.5px solid #c5c7c9", <img src={appLogo} className="object-contain h-full" alt="logo" />
padding: "30px", )}
boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
}}
>
<div className="main_head">
<div className="w-[250px] h-[66px] inline-block overflow-hidden">
{appLogo && (
<img
src={appLogo}
className="object-contain h-full"
alt="logo"
/>
)}
</div>
</div> </div>
{contactId ? (
{!EnterOTP ? ( <>
<div className="row"> {!EnterOTP ? (
<div className="col-sm-6 KLO"> <div className="w-full md:w-[50%] text-base-content">
<span className="welcomeText">Welcome Back !</span> <h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
<br /> <legend className="text-[12px] text-[#878787] mt-2">
<span className="KNLO"> Verification code is sent to your email
Verification code is sent to your email </legend>
</span> <div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
<div className="card card-box" style={{ borderRadius: "0px" }}>
<div className="card-body">
<input <input
type="email" type="email"
name="mobile" name="mobile"
value={email} value={email}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled disabled
className="loginInput"
/> />
<br /> </div>
<div className="mt-2">
<button
className="op-btn op-btn-primary"
onClick={(e) => handleSendOTPBtn(e)}
disabled={loading}
>
{loading ? "Loading..." : "Send OTP"}
</button>
</div> </div>
</div> </div>
<div className="btnContainer"> ) : (
{loading ? ( <form
<button className="w-full md:w-[50%] text-base-content"
type="button" onSubmit={VerifyOTP}
style={{ >
background: themeColor, <h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
color: "white" <legend className="text-[12px] text-[#878787] mt-2">
}} You will get a OTP via Email
className="verifyBtn" </legend>
disabled <div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
> <p className="text-sm">Enter Verification Code</p>
<span
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button>
) : (
<button
className="verifyBtn"
style={{
background: themeColor,
color: "white",
marginLeft: "0px !important"
}}
onClick={(e) => SendOtp(e)}
>
Send OTP
</button>
)}
</div>
</div>
</div>
) : (
<div className="row">
<div className="col-sm-6 KLO">
<span className="welcomeText">Welcome Back !</span>
<br />
<span className="KNLO">You will get a OTP via Email</span>
<div className="card card-box">
<div className="card-body">
<label>Enter Verification Code</label>
<input <input
type="number" type="number"
className="loginInput" className="mt-2 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="OTP" name="OTP"
value={OTP} value={OTP}
onChange={handleChange} onChange={(e) => setOTP(e.target.value)}
/> />
<br />
</div> </div>
</div> <div className="mt-2">
<div>
{loading ? (
<button <button
style={{ className="op-btn op-btn-primary"
background: themeColor, type="submit"
color: "white" disabled={loading}
}}
className="verifyBtn"
type="button"
disabled
> >
<span {loading ? "Loading..." : "Verify"}
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button> </button>
) : ( </div>
<button </form>
type="button" )}
onClick={(e) => VerifyOTP(e)} </>
style={{ ) : (
background: themeColor, <div className="w-full md:w-[50%] text-base-content">
color: "white" <h1 className="text-2xl md:text-[30px]">Welcome</h1>
}} <legend className="text-[12px] text-[#878787] mt-2">
className="verifyBtn" Provide your details
> </legend>
Verify <form
</button> className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"
)} onSubmit={handleUserData}
>
<div className="mb-2">
<label
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
Name
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="text"
name="name"
value={contact.name}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
required
/>
</div> </div>
</div> <div className="mb-2">
<label
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="email"
name="email"
value={contact.email}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
required
disabled
/>
</div>
<div className="mb-2">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Phone
</label>
<input
type="text"
name="phone"
value={contact.phone}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
/>
</div>
<div className="mt-2 flex justify-start">
<button
type="submit"
className="op-btn op-btn-primary"
disabled={loading}
>
{loading ? "Loading..." : "Next"}
</button>
</div>
</form>
</div> </div>
)} )}
</div> </div>
+154 -193
View File
@@ -10,16 +10,13 @@ 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 { import { isEnableSubscription } from "../constant/const";
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"; import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
function Login() { function Login() {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
@@ -45,6 +42,7 @@ function Login() {
}); });
const [isModal, setIsModal] = useState(false); const [isModal, setIsModal] = useState(false);
const [image, setImage] = useState(); const [image, setImage] = useState();
const [isLoginSSO, setIsLoginSSO] = useState(false);
useEffect(() => { useEffect(() => {
if (localStorage.getItem("accesstoken")) { if (localStorage.getItem("accesstoken")) {
@@ -263,7 +261,7 @@ function Login() {
const LocalUserDetails = { const LocalUserDetails = {
name: results[0].get("Name"), name: results[0].get("Name"),
email: results[0].get("Email"), email: results[0].get("Email"),
phone: results[0].get("Phone"), phone: results[0]?.get("Phone") || "",
company: results[0].get("Company") company: results[0].get("Company")
}; };
localStorage.setItem( localStorage.setItem(
@@ -317,7 +315,7 @@ function Login() {
const LocalUserDetails = { const LocalUserDetails = {
name: _user.name, name: _user.name,
email: email, email: email,
phone: _user.phone phone: _user?.phone || ""
// company: results.get("Company"), // company: results.get("Company"),
}; };
localStorage.setItem( localStorage.setItem(
@@ -868,7 +866,7 @@ function Login() {
const LocalUserDetails = { const LocalUserDetails = {
name: results[0].get("Name"), name: results[0].get("Name"),
email: results[0].get("Email"), email: results[0].get("Email"),
phone: results[0].get("Phone"), phone: results[0]?.get("Phone") || "",
company: results[0].get("Company") company: results[0].get("Company")
}; };
localStorage.setItem( localStorage.setItem(
@@ -905,7 +903,7 @@ function Login() {
const LocalUserDetails = { const LocalUserDetails = {
name: results[0].get("Name"), name: results[0].get("Name"),
email: results[0].get("Email"), email: results[0].get("Email"),
phone: results[0].get("Phone") phone: results[0]?.get("Phone") || ""
// company: results.get("Company"), // company: results.get("Company"),
}; };
localStorage.setItem( localStorage.setItem(
@@ -982,7 +980,7 @@ function Login() {
userDetails: { userDetails: {
name: userInformation.name, name: userInformation.name,
email: userInformation.email, email: userInformation.email,
phone: userInformation.phone, phone: userInformation?.phone || "",
role: "contracts_User", role: "contracts_User",
company: userDetails.Company, company: userDetails.Company,
jobTitle: userDetails.Destination jobTitle: userDetails.Destination
@@ -994,7 +992,7 @@ function Login() {
const LocalUserDetails = { const LocalUserDetails = {
name: userInformation.name, name: userInformation.name,
email: userInformation.email, email: userInformation.email,
phone: userInformation.phone, phone: userInformation?.phone || "",
company: userDetails.Company, company: userDetails.Company,
jobTitle: userDetails.JobTitle jobTitle: userDetails.JobTitle
}; };
@@ -1016,8 +1014,9 @@ function Login() {
const handleCloseModal = () => { const handleCloseModal = () => {
setIsModal(false); setIsModal(false);
Parse.User.logOut(); if (Parse?.User?.current()) {
Parse.User.logOut();
}
let appdata = localStorage.getItem("userSettings"); let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo"); let applogo = localStorage.getItem("appLogo");
let appName = localStorage.getItem("appName"); let appName = localStorage.getItem("appName");
@@ -1040,201 +1039,172 @@ function Login() {
localStorage.setItem("baseUrl", baseUrl); localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid); localStorage.setItem("parseAppId", appid);
}; };
// `handleSignInWithSSO` is trigger when user click sign in with sso and open sso authorize endpoint
const handleSignInWithSSO = () => {
if (isLoginSSO === false) {
if (state?.email) {
setIsLoginSSO(true);
const encodedEmail = encodeURIComponent(state.email);
const clientUrl = window.location.origin;
const domain = state.email.split("@")?.pop();
const ssoApiUrl =
process.env.SSO_API_URL || "https://sso.opensignlabs.com/api";
openInNewTab(
`${ssoApiUrl}/oauth/authorize?response_type=code&provider=saml&tenant=${domain}&product=OpenSign&redirect_uri=${clientUrl}/sso&state=${encodedEmail}`,
"_self"
);
} else {
alert("Please provide email.");
}
}
};
return ( return (
<div className="bg-white"> <div>
<Title title={"Login Page"} /> <Title title={"Login Page"} />
{state.loading && ( {state.loading && (
<div <div
aria-live="assertive" aria-live="assertive"
style={{ className="fixed w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-50"
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
> >
<div <Loader />
role="status"
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)"
}}
className="loader-37"
>
<span className="sr-only">Loading...</span>
</div>
</div> </div>
)} )}
{appInfo && appInfo.appId ? ( {appInfo && appInfo.appId ? (
<> <>
<div aria-labelledby="loginHeading" role="region"> <div
<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 "> aria-labelledby="loginHeading"
role="region"
className="md:p-10 lg:p-16"
>
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
<div className="w-[250px] h-[66px] inline-block overflow-hidden"> <div className="w-[250px] h-[66px] inline-block overflow-hidden">
{image && ( {image && (
<img <img
src={image} src={image}
className="object-contain h-full" 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." alt="applogo"
/> />
)} )}
</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>
<div> <form onSubmit={handleSubmit} aria-label="Login Form">
<form onSubmit={handleSubmit} aria-label="Login Form"> <h1 className="text-[30px] mt-6">Welcome Back!</h1>
<h1 className="text-[30px] mt-6">Welcome Back!</h1> <fieldset>
<fieldset> <legend className="text-[12px] text-[#878787]">
<legend className="text-[12px] text-[#878787]"> Login to your account
Login to your account </legend>
</legend> <div className="w-full px-6 py-3 my-1 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<div className="px-6 py-4 outline outline-1 outline-slate-300/50 my-2 rounded shadow-md"> <label className="block text-xs" htmlFor="email">
<label className="block text-xs" htmlFor="email"> Email
Username </label>
</label> <input
<input id="email"
id="email" type="email"
type="text" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs" name="email"
name="email" value={state.email}
value={state.email} onChange={handleChange}
onChange={handleChange} required
required />
/> <hr className="my-1 border-none" />
<hr className="my-2 border-none" /> {!isLoginSSO && (
<label className="block text-xs" htmlFor="password"> <>
Password <label className="block text-xs" htmlFor="password">
</label> Password
<div className="relative"> </label>
<input <div className="relative">
id="password" <input
type={state.passwordVisible ? "text" : "password"} id="password"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs" type={
name="password" state.passwordVisible ? "text" : "password"
value={state.password} }
onChange={handleChange} className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
required name="password"
/> value={state.password}
<span onChange={handleChange}
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${ required
state.passwordVisible />
? "text-[#007bff]" <span
: "text-black" className="absolute cursor-pointer top-[50%] right-[10px] -translate-y-[50%] text-base-content"
}`} onClick={togglePasswordVisibility}
onClick={togglePasswordVisibility} >
> {state.passwordVisible ? (
{state.passwordVisible ? ( <i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon
<i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon ) : (
) : ( <i className="fa fa-eye text-xs pb-1 " /> // Open eye icon
<i className="fa fa-eye text-xs pb-1 " /> // Open eye icon )}
)} </span>
</span> </div>
</div> </>
</div> )}
</fieldset> <div className="relative mt-1">
<div className="flex flex-row justify-between items-center ml-4 py-2">
<div>
<label
className="form-check-label inline-block cursor-pointer"
htmlFor="rememberpassword"
>
<input
type="checkbox"
className="form-check-input mr-1"
value=""
id="rememberpassword"
/>
<span className="text-[13px]">
Remember Password
</span>
</label>
</div>
<div>
<NavLink <NavLink
to="/forgetpassword" to="/forgetpassword"
className="text-[13px] underline focus:outline-none focus:ring-2 focus:ring-blue-600" className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
> >
Forgot Password ? Forgot Password?
</NavLink> </NavLink>
</div> </div>
</div> </div>
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2"> </fieldset>
<button <div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold mt-2">
type="submit" <button
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow outline-none uppercase focus:ring-2 focus:ring-blue-600" type="submit"
disabled={state.loading} className="op-btn op-btn-primary"
> disabled={state.loading}
{state.loading ? "Loading..." : "Login"} >
</button> {state.loading ? "Loading..." : "Login"}
<NavLink </button>
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase" <button
to={ type="button"
className="op-btn op-btn-accent"
disabled={state.loading}
onClick={() =>
navigate(
location.search location.search
? "/signup" + location.search ? "/signup" + location.search
: "/signup" : "/signup"
} )
style={width < 768 ? { textAlign: "center" } : {}} }
> >
Create Account Create Account
</NavLink> </button>
</div> </div>
</form> </form>
<br /> {(appInfo.googleClietId || isEnableSubscription) && (
{(appInfo.fbAppId || appInfo.googleClietId) && ( <div className="op-divider my-4 text-sm">OR</div>
<div className="text-sm flex justify-center items-center"> )}
<hr className="border-[1px] border-gray-300 w-full" /> <div className="flex flex-col justify-center items-center gap-y-3">
<span className="px-2 text-gray-500 cursor-default"> {/* {appInfo?.fbAppId && (
OR
</span>
<hr className="border-[1px] border-gray-300 w-full" />
</div>
)}
<br />
<div
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{/* {appInfo.fbAppId && appInfo.fbAppId !== "" ? (
<LoginFacebook <LoginFacebook
FBCred={appInfo.fbAppId} FBCred={appInfo.fbAppId}
thirdpartyLoginfn={thirdpartyLoginfn} thirdpartyLoginfn={thirdpartyLoginfn}
thirdpartyLoader={state.thirdpartyLoader} thirdpartyLoader={state.thirdpartyLoader}
setThirdpartyLoader={setThirdpartyLoader} setThirdpartyLoader={setThirdpartyLoader}
/> />
) : null} */} )} */}
</div> {appInfo?.googleClietId && (
<div style={{ margin: "10px 0" }}></div> <GoogleSignInBtn
<div GoogleCred={appInfo.googleClietId}
style={{ thirdpartyLoginfn={thirdpartyLoginfn}
textAlign: "center", thirdpartyLoader={state.thirdpartyLoader}
display: "flex", setThirdpartyLoader={setThirdpartyLoader}
alignItems: "center", />
justifyContent: "center" )}
}} {isEnableSubscription && (
> <div
{appInfo.googleClietId && appInfo.googleClietId !== "" ? ( className="cursor-pointer border-[1px] border-gray-300 rounded px-[40px] py-2 font-semibold text-sm hover:border-[#d2e3fc] hover:bg-[#ecf3feb7]"
<GoogleSignInBtn onClick={() => handleSignInWithSSO()}
GoogleCred={appInfo.googleClietId} >
thirdpartyLoginfn={thirdpartyLoginfn} Sign in with SSO
thirdpartyLoader={state.thirdpartyLoader} </div>
setThirdpartyLoader={setThirdpartyLoader} )}
/>
) : null}
</div>
</div> </div>
</div> </div>
{width >= 768 && ( {width >= 768 && (
<div className="self-center"> <div className="place-self-center">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]"> <div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img <img
src={login_img} src={login_img}
@@ -1249,18 +1219,18 @@ function Login() {
<Alert type={state.alertType}>{state.alertMsg}</Alert> <Alert type={state.alertType}>{state.alertMsg}</Alert>
</div> </div>
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}> <ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
<form className="px-4 py-3"> <form className="px-4 py-3 text-base-content">
<div className="mb-3"> <div className="mb-3">
<label <label
htmlFor="Company" htmlFor="Company"
style={{ display: "flex" }} style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold" className="block text-xs text-gray-700 font-semibold"
> >
Company <span style={{ fontSize: 13, color: "red" }}>*</span> Company <span className="text-[red] text-[13px]">*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="Company" id="Company"
value={userDetails.Company} value={userDetails.Company}
onChange={(e) => onChange={(e) =>
@@ -1279,11 +1249,11 @@ function Login() {
className="block text-xs text-gray-700 font-semibold" className="block text-xs text-gray-700 font-semibold"
> >
Job Title Job Title
<span style={{ fontSize: 13, color: "red" }}>*</span> <span className="text-[red] text-[13px]">*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="JobTitle" id="JobTitle"
value={userDetails.Destination} value={userDetails.Destination}
onChange={(e) => onChange={(e) =>
@@ -1295,23 +1265,18 @@ function Login() {
required required
/> />
</div> </div>
<div className="mt-4"> <div className="mt-4 gap-2 flex flex-row">
<button <button
type="button" type="button"
className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none " className="op-btn op-btn-primary"
onClick={(e) => handleSubmitbtn(e)} onClick={(e) => handleSubmitbtn(e)}
style={{
marginRight: 10,
backgroundColor: modalSubmitBtnColor
}}
> >
Login Login
</button> </button>
<button <button
type="button" type="button"
className="py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" className="op-btn op-btn-ghost"
onClick={handleCloseModal} onClick={handleCloseModal}
style={{ width: 75, backgroundColor: modalCancelBtnColor }}
> >
Cancel Cancel
</button> </button>
@@ -1321,15 +1286,11 @@ function Login() {
</> </>
) : ( ) : (
<div <div
style={{ aria-live="assertive"
position: "fixed", className="fixed w-full h-full flex justify-center items-center z-50"
fontSize: "50px", >
color: "#3ac9d6", <Loader />
top: "50%", </div>
left: "45%"
}}
className="loader-37"
></div>
)} )}
</div> </div>
); );
+44 -82
View File
@@ -6,6 +6,8 @@ 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"; import { SaveFileSize } from "../constant/saveFileSize";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
const ManageSign = () => { const ManageSign = () => {
const appName = appInfo.appname; const appName = appInfo.appname;
const [penColor, setPenColor] = useState("blue"); const [penColor, setPenColor] = useState("blue");
@@ -17,7 +19,7 @@ const ManageSign = () => {
const [isvalue, setIsValue] = useState(false); const [isvalue, setIsValue] = useState(false);
const allColor = ["blue", "red", "black"]; const allColor = ["blue", "red", "black"];
const [isLoader, setIsLoader] = useState(true); const [isLoader, setIsLoader] = useState(true);
const [isSuccess, setIsSuccess] = useState(false); const [isAlert, setIsAlert] = useState({ type: "success", message: "" });
const [Initials, setInitials] = useState(""); const [Initials, setInitials] = useState("");
const [isInitials, setIsInitials] = useState(false); const [isInitials, setIsInitials] = useState(false);
const [id, setId] = useState(""); const [id, setId] = useState("");
@@ -185,12 +187,20 @@ const ManageSign = () => {
updateSign.set("UserId", userId); updateSign.set("UserId", userId);
const res = await updateSign.save(); const res = await updateSign.save();
setIsLoader(false); setIsLoader(false);
setIsSuccess(true); setIsAlert({
type: "success",
message: "Signature saved successfully."
});
setTimeout(() => setIsAlert({}), 2000);
return res; return res;
} catch (err) { } catch (err) {
console.log(err); console.log(err);
setIsLoader(false); setIsLoader(false);
alert(`${err.message}`); setIsAlert({
type: "danger",
message: `${err.message}`
});
setTimeout(() => setIsAlert({}), 2000);
} }
} else { } else {
try { try {
@@ -201,12 +211,20 @@ const ManageSign = () => {
updateSign.set("UserId", userId); updateSign.set("UserId", userId);
const res = await updateSign.save(); const res = await updateSign.save();
setIsLoader(false); setIsLoader(false);
setIsSuccess(true); setIsAlert({
type: "success",
message: "Signature saved successfully."
});
setTimeout(() => setIsAlert({}), 2000);
return res; return res;
} catch (err) { } catch (err) {
console.log(err); console.log(err);
setIsLoader(false); setIsLoader(false);
alert(`${err.message}`); setIsAlert({
type: "success",
message: `${err.message}`
});
setTimeout(() => setIsAlert({}), 2000);
} }
} }
}; };
@@ -224,24 +242,13 @@ const ManageSign = () => {
setIsValue(true); setIsValue(true);
}; };
return ( return (
<div className="relative h-full bg-white flex shadow rounded overflow-auto"> <div className="relative h-full bg-base-100 text-base-content flex shadow rounded overflow-auto">
{isLoader && ( {isLoader && (
<div className="absolute bg-black bg-opacity-75 z-50 w-full h-full flex justify-center items-center"> <div className="absolute bg-black bg-opacity-30 z-50 w-full h-full flex justify-center items-center">
<div <Loader />
style={{ color: "#3dd3e0" }}
className="loader-37 text-[45px]"
></div>
</div>
)}
{isSuccess && (
<div
className="alert alert-success successBox"
role="alert"
onAnimationEnd={() => setIsSuccess(false)}
>
Signature saved successfully!
</div> </div>
)} )}
{isAlert?.message && <Alert type={isAlert.type}>{isAlert.message}</Alert>}
<div <div
className="mainDiv" className="mainDiv"
style={{ style={{
@@ -249,39 +256,13 @@ const ManageSign = () => {
paddingRight: "10px" paddingRight: "10px"
}} }}
> >
<div style={{ margin: 20 }}> <div className="m-[20px]">
<div <div className="font-[700] text-[15px] pb-[8px]">My Signature</div>
style={{
fontWeight: "700",
fontSize: 15,
color: "#000",
paddingBottom: 8
}}
>
My Signature
</div>
<div className="signBlock mt-4"> <div className="signBlock mt-4">
<div> <div>
<div style={{ position: "relative" }}> <div className="relative">
<div <div className="flex flex-row justify-between w-1/2 pl-[10px]">
style={{ <div className="flex flex-row justify-around items-center gap-[10px] mb-[10px]">
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
width: "50%",
paddingLeft: 10
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-around",
alignItems: "center",
gap: 10,
marginBottom: 10
}}
>
<> <>
<span <span
onClick={() => handleSignatureBtn()} onClick={() => handleSignatureBtn()}
@@ -307,24 +288,14 @@ const ManageSign = () => {
/> />
</div> </div>
</div> </div>
<div style={{ position: "relative" }}> <div className="relative">
<div> <div>
{image ? ( {image ? (
<div <div className="signatureCanvas relative border-[2px] border-[#888]">
style={{
position: "relative",
border: "2px solid #888"
}}
className="signatureCanvas"
>
<img <img
alt="preview image" alt="preview image"
src={image} src={image}
style={{ className="w-full h-full object-contain"
width: "100%",
height: "100%",
objectFit: "contain"
}}
/> />
</div> </div>
) : ( ) : (
@@ -366,10 +337,10 @@ const ManageSign = () => {
key === 0 && penColor === "blue" key === 0 && penColor === "blue"
? "2px solid blue" ? "2px solid blue"
: key === 1 && penColor === "red" : key === 1 && penColor === "red"
? "2px solid red" ? "2px solid red"
: key === 2 && penColor === "black" : key === 2 && penColor === "black"
? "2px solid black" ? "2px solid black"
: "2px solid white" : "2px solid white"
}} }}
onClick={() => { onClick={() => {
if (key === 0) { if (key === 0) {
@@ -474,10 +445,10 @@ const ManageSign = () => {
key === 0 && initialPen === "blue" key === 0 && initialPen === "blue"
? "2px solid blue" ? "2px solid blue"
: key === 1 && initialPen === "red" : key === 1 && initialPen === "red"
? "2px solid red" ? "2px solid red"
: key === 2 && initialPen === "black" : key === 2 && initialPen === "black"
? "2px solid black" ? "2px solid black"
: "2px solid white" : "2px solid white"
}} }}
onClick={() => { onClick={() => {
if (key === 0) { if (key === 0) {
@@ -509,20 +480,11 @@ const ManageSign = () => {
</div> </div>
</div> </div>
</div> </div>
{/* {!warning && (
<div className="warning signWarning" style={{ fontSize: 12 }}>
<i
className="fas fa-exclamation-circle"
style={{ color: "#fab005", fontSize: 15 }}
></i>{" "}
Please upload signature/Image
</div>
)} */}
</div> </div>
</div> </div>
<div style={{ paddingTop: 10 }}> <div style={{ paddingTop: 10 }}>
<button <button
className="customBtn successBtn" className="op-btn op-btn-primary"
onClick={(e) => handleSubmit(e)} onClick={(e) => handleSubmit(e)}
> >
save save
+275 -418
View File
@@ -1,7 +1,6 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import "../styles/opensigndrive.css"; import "../styles/opensigndrive.css";
import loader from "../assets/images/loader2.gif"; import { iconColor } from "../constant/const";
import { themeColor, iconColor } from "../constant/const";
import { getDrive } from "../constant/Utils"; import { getDrive } from "../constant/Utils";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Title from "../components/Title"; import Title from "../components/Title";
@@ -10,27 +9,15 @@ import ModalUi from "../primitives/ModalUi";
import TourContentWithBtn from "../primitives/TourContentWithBtn"; import TourContentWithBtn from "../primitives/TourContentWithBtn";
import Tour from "reactour"; import Tour from "reactour";
import axios from "axios"; import axios from "axios";
import Loader from "../primitives/Loader";
const DriveBody = React.lazy( const DriveBody = React.lazy(
() => import("../components/opensigndrive/DriveBody") () => import("../components/opensigndrive/DriveBody")
); );
const Loader = () => { const AppLoader = () => {
return ( return (
<div <div className="h-[100vh] flex justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
); );
}; };
@@ -279,7 +266,8 @@ function Opensigndrive() {
setNewFolderName(value); setNewFolderName(value);
}; };
//function for create folder //function for create folder
const handleAddFolder = async () => { const handleAddFolder = async (e) => {
e.preventDefault();
if (newFolderName) { if (newFolderName) {
setIsFolderLoader(true); setIsFolderLoader(true);
const getParentObjId = folderName[folderName.length - 1]; const getParentObjId = folderName[folderName.length - 1];
@@ -300,6 +288,7 @@ function Opensigndrive() {
const exsitQuery = new Parse.Query(foldercls); const exsitQuery = new Parse.Query(foldercls);
exsitQuery.equalTo("Name", newFolderName); exsitQuery.equalTo("Name", newFolderName);
exsitQuery.equalTo("Type", "Folder"); exsitQuery.equalTo("Type", "Folder");
exsitQuery.notEqualTo("IsArchive", true);
if (parentId) { if (parentId) {
exsitQuery.equalTo("Folder", folderPtr); exsitQuery.equalTo("Folder", folderPtr);
} }
@@ -449,21 +438,10 @@ function Opensigndrive() {
<React.Fragment key={id}> <React.Fragment key={id}>
<span <span
onClick={() => handleRoute(id, folderData)} onClick={() => handleRoute(id, folderData)}
style={{ className="text-[#a64b4e] font-normal cursor-pointer"
color: "#a64b4e",
fontWeight: "400",
cursor: "pointer"
}}
> >
{data.name} {data.name}
<span <span className="text-[#a64b4e] font-extralight cursor-pointer mx-[4px]">
style={{
color: "#a64b4e",
fontWeight: "200",
cursor: "pointer",
margin: "0 4px"
}}
>
&gt; &gt;
</span> </span>
</span> </span>
@@ -544,411 +522,290 @@ function Opensigndrive() {
} }
} }
return ( return (
<div style={{ backgroundColor: "white" }} className="folderComponent"> <div className="bg-base-100 text-base-content rounded-xl w-full">
<Title title={"OpenSign™ Drive"} drive={true} /> <Title title={"OpenSign™ Drive"} drive={true} />
<ModalUi
<div> isOpen={isAlert.isShow}
<ModalUi title={"Alert"}
headerColor={"#dc3545"} handleClose={() => {
isOpen={isAlert.isShow} setIsAlert({
title={"Alert"} isShow: false,
handleClose={() => { alertMessage: ""
setIsAlert({ });
isShow: false, }}
alertMessage: "" >
}); <div className="h-full p-[20px] pb-[15px]">
}} <p>{isAlert.alertMessage}</p>
> <div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
<div style={{ height: "100%", padding: 20 }}> <button
<p>{isAlert.alertMessage}</p> onClick={() =>
setIsAlert({
<div isShow: false,
style={{ alertMessage: ""
height: "1px", })
backgroundColor: "#9f9f9f", }
width: "100%", type="button"
marginTop: "15px", className="op-btn op-btn-neutral op-btn-sm"
marginBottom: "15px" >
}} Close
></div> </button>
<button </div>
onClick={() => </ModalUi>
setIsAlert({ <ModalUi
isShow: false, isOpen={isFolder}
alertMessage: "" title={"Add New Folder"}
}) handleClose={oncloseFolder}
} >
type="button" <div className="h-full p-[20px] pt-[10px] pb-[15px]">
className="finishBtn cancelBtn" {folderLoader ? (
<div className="h-[200px] flex justify-center items-center">
<Loader />
</div>
) : (
<form
onSubmit={handleAddFolder}
className="flex flex-col text-base-content"
> >
Close <label className="py-[8px] text-[15px] font-[400] mb-0">
</button> Name
</div> <span className="text-[red]">*</span>
</ModalUi> </label>
<ModalUi <input
isOpen={isFolder} required
title={"Add New Folder"} className="op-input op-input-bordered op-input-sm"
handleClose={oncloseFolder} type="text"
> value={newFolderName}
<div style={{ height: "100%", padding: 20 }}> onChange={(e) => handleFolderName(e)}
{folderLoader ? ( />
<div <span className="text-[red] text-[12px] mt-[6px]">{error}</span>
style={{ <div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
height: "200px", <div className="flex flex-row">
display: "flex", <button type="submit" className="op-btn op-btn-primary">
flexDirection: "column", Add
justifyContent: "center", </button>
alignItems: "center" <button
}} type="button"
> className="op-btn op-btn-ghost ml-1"
<img onClick={oncloseFolder}
alt="loader img" >
src={loader} Close
style={{ width: "50px", height: "50px" }} </button>
/>
<span style={{ fontSize: "13px", color: "gray" }}>
Loading...
</span>
</div> </div>
) : ( </form>
<form )}
onSubmit={(e) => { </div>
e.preventDefault(); </ModalUi>
handleAddFolder(); {isLoading.isLoad ? (
}} <div className="flex flex-col justify-center items-center h-[100vh] w-full">
style={{ display: "flex", flexDirection: "column" }} <Loader />
> <span className="text-[13px] text-[gray]">{isLoading.message}</span>
<label </div>
style={{ ) : handleError ? (
margin: "10px 0px 10px 0px", <div className="flex justify-center items-center h-[100vh] w-full">
fontSize: "15px", <span className="text-[20px] text-[gray]">{handleError}</span>
fontWeight: "400" </div>
}} ) : (
> <>
Name <div className="flex flex-row justify-between items-center px-[25px] pt-[20px]">
<span style={{ color: "red" }}>*</span> {tourData && (
</label> <Tour
onRequestClose={closeTour}
<input steps={tourData}
required isOpen={isTour}
className="form-control inputStyle" closeWithMask={false}
type="text" scrollOffset={-100}
value={newFolderName} rounded={5}
onChange={(e) => handleFolderName(e)} />
// className="addFolderInput"
/>
<span
style={{ color: "red", fontSize: "12px", marginTop: "6px" }}
>
{error}
</span>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<div style={{ display: "flex", flexDirection: "row" }}>
<button
style={{ background: themeColor }}
type="submit"
className="finishBtn"
>
Add
</button>
<button
type="button"
className="finishBtn cancelBtn"
onClick={oncloseFolder}
>
Close
</button>
</div>
</form>
)} )}
</div> <div
</ModalUi> data-tut="reactourFirst"
onMouseEnter={(e) => handleMouseEnter(e)}
{isLoading.isLoad ? ( ref={scrollRef}
<div className="w-full whitespace-nowrap cursor-pointer select-none overflow-x-auto"
style={{ >
display: "flex", {handleFolderTab(folderName)}
justifyContent: "center", </div>
alignItems: "center", <div className="dropMenuBD">
height: "100vh",
width: "100%",
flexDirection: "column"
}}
>
<img
alt="loader img"
src={loader}
style={{ width: "80px", height: "80px" }}
/>
<span style={{ fontSize: "13px", color: "gray" }}>
{isLoading.message}
</span>
</div>
) : handleError ? (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh",
width: "100%"
}}
>
<span style={{ fontSize: "20px", color: "gray" }}>
{handleError}
</span>
</div>
) : (
<>
<div className="folderContainer">
{tourData && (
<Tour
onRequestClose={closeTour}
steps={tourData}
isOpen={isTour}
closeWithMask={false}
scrollOffset={-100}
rounded={5}
/>
)}
<div <div
data-tut="reactourFirst" id="folder-menu"
onMouseEnter={(e) => handleMouseEnter(e)} className={
ref={scrollRef} isNewFol ? "dropdown show dropDownStyle" : "dropdown"
style={{ }
width: "100%" onClick={() => setIsNewFol(!isNewFol)}
}}
className="folderPath"
> >
{handleFolderTab(folderName)} <div className="sort" data-tut="reactourSecond">
</div> <i
<div className="dropMenuBD"> className="fa fa-plus-square"
<div aria-hidden="true"
id="folder-menu" style={{ fontSize: "25px", color: `${iconColor}` }}
className={ ></i>
isNewFol ? "dropdown show dropDownStyle" : "dropdown"
}
onClick={() => setIsNewFol(!isNewFol)}
>
<div className="sort" data-tut="reactourSecond">
<i
className="fa fa-plus-square"
aria-hidden="true"
style={{ fontSize: "25px", color: `${iconColor}` }}
></i>
</div>
<div
className={
isNewFol ? "dropdown-menu show" : "dropdown-menu"
}
aria-labelledby="dropdownMenuButton"
aria-expanded={isNewFol ? "true" : "false"}
>
{" "}
<div
style={{
display: "flex",
flexDirection: "column"
}}
>
<span
className="dropdown-item itemColor"
onClick={() => setIsFolder(true)}
>
<i
style={{ marginRight: "5px" }}
className="fa fa-plus"
aria-hidden="true"
></i>
Create folder
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/sHAnZphf69")}
>
<i
style={{ marginRight: "5px" }}
className="fas fa-pen-nib"
></i>
Sign Yourself
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/8mZzFxbG1z")}
>
{" "}
<i
style={{ marginRight: "5px" }}
className="fa fa-file-signature"
></i>
Request Signatures{" "}
</span>
</div>
</div>
</div> </div>
<div <div
id="menu-container" className={isNewFol ? "dropdown-menu show" : "dropdown-menu"}
className={isShowSort ? "dropdown show" : "dropdown"} aria-labelledby="dropdownMenuButton"
onClick={() => setIsShowSort(!isShowSort)} aria-expanded={isNewFol ? "true" : "false"}
> >
<div <div className="flex flex-col">
data-tut="reactourThird"
className=" sort "
data-toggle="dropdown"
>
<i
className="fa fa-sort-amount-asc"
aria-hidden="true"
style={{
marginRight: "5px",
fontSize: "14px",
color: `${iconColor}`
}}
></i>
<span <span
style={{ className="dropdown-item itemColor"
fontSize: "15px", onClick={() => setIsFolder(true)}
color: `${iconColor}`
}}
> >
{selectedSort} <i className="fa fa-plus mr-[5px]" aria-hidden="true"></i>
Create folder
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/sHAnZphf69")}
>
<i className="fas fa-pen-nib mr-[5px"></i>
Sign Yourself
</span>
<span
className="dropdown-item itemColor"
onClick={() => navigate("/form/8mZzFxbG1z")}
>
<i className="fa fa-file-signature mr-[5px"></i>
Request Signatures
</span> </span>
</div> </div>
<div
className={
isShowSort ? "dropdown-menu show" : "dropdown-menu"
}
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowSort ? "true" : "false"}
>
{sortingValue.map((value, ind) => {
return (
<span
key={ind}
onClick={() => {
setSelectedSort(value);
sortingData(value, null, pdfData);
}}
className="dropdown-item itemColor"
style={{
paddingLeft: selectedSort !== value && "33px"
}}
>
{selectedSort === value && (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
{value}
</span>
);
})}
<hr className="hrStyle" />
{sortOrder.map((order, ind) => {
return (
<span
key={ind}
onClick={() => {
setSortingOrder(order);
sortingData(null, order, pdfData);
}}
className="dropdown-item itemColor"
style={{
paddingLeft: sortingOrder !== order && "33px"
}}
>
{sortingOrder === order && (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
{order}
</span>
);
})}
</div>
</div> </div>
</div>
<div
id="menu-container"
className={isShowSort ? "dropdown show" : "dropdown"}
onClick={() => setIsShowSort(!isShowSort)}
>
<div
data-tut="reactourThird"
className="sort "
data-toggle="dropdown"
>
<i
className="fa fa-sort-amount-asc mr-[5px] text-[14px]"
aria-hidden="true"
style={{ color: `${iconColor}` }}
></i>
<span style={{ fontSize: "15px", color: `${iconColor}` }}>
{selectedSort}
</span>
</div>
<div
className={
isShowSort ? "dropdown-menu show" : "dropdown-menu"
}
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowSort ? "true" : "false"}
>
{sortingValue.map((value, ind) => {
return (
<span
key={ind}
onClick={() => {
setSelectedSort(value);
sortingData(value, null, pdfData);
}}
className="dropdown-item itemColor"
style={{
paddingLeft: selectedSort !== value && "33px"
}}
>
{selectedSort === value && (
<i
className="fa fa-check mr-[5px"
aria-hidden="true"
></i>
)}
{value}
</span>
);
})}
<div> <hr className="hrStyle" />
{isList ? ( {sortOrder.map((order, ind) => {
<div className="sort" onClick={() => setIsList(!isList)}> return (
<i <span
onClick={() => setIsList(!isList)} key={ind}
className="fa fa-th-large" onClick={() => {
style={{ fontSize: "24px", color: `${iconColor}` }} setSortingOrder(order);
aria-hidden="true" sortingData(null, order, pdfData);
></i> }}
</div> className="dropdown-item itemColor"
) : ( style={{
<div paddingLeft: sortingOrder !== order && "33px"
data-tut="reactourForth" }}
className="sort" >
{sortingOrder === order && (
<i
className="fa fa-check mr-[5px"
aria-hidden="true"
></i>
)}
{order}
</span>
);
})}
</div>
</div>
<div>
{isList ? (
<div className="sort" onClick={() => setIsList(!isList)}>
<i
onClick={() => setIsList(!isList)} onClick={() => setIsList(!isList)}
> className="fa fa-th-large"
<i style={{ fontSize: "24px", color: `${iconColor}` }}
className="fa fa-list" aria-hidden="true"
aria-hidden="true" ></i>
style={{ fontSize: "23px", color: `${iconColor}` }} </div>
></i> ) : (
</div> <div
)} data-tut="reactourForth"
</div> className="sort"
onClick={() => setIsList(!isList)}
>
<i
className="fa fa-list"
aria-hidden="true"
style={{ fontSize: "23px", color: `${iconColor}` }}
></i>
</div>
)}
</div> </div>
</div> </div>
</div>
{pdfData && pdfData.length === 0 ? ( {pdfData && pdfData.length === 0 ? (
<div <div className="flex justify-center items-center w-full h-[50vh]">
style={{ <span className="text-base-content font-bold">
display: "flex", No Data Found!
justifyContent: "center", </span>
alignItems: "center", </div>
height: "50vh", ) : (
width: "100%" <div data-tut="reactourFifth">
}} <React.Suspense fallback={<AppLoader />}>
> <DriveBody
<span style={{ fontWeight: "bold" }}>No Data Found!</span> dataTutSixth="reactourSixth"
</div> dataTutSeventh="reactourSeventh"
) : ( pdfData={pdfData}
<div data-tut="reactourFifth"> setFolderName={setFolderName}
<React.Suspense fallback={<Loader />}> setIsLoading={setIsLoading}
<DriveBody setDocId={setDocId}
dataTutSixth="reactourSixth" getPdfDocumentList={getPdfDocumentList}
dataTutSeventh="reactourSeventh" isDocId={docId}
pdfData={pdfData} setPdfData={setPdfData}
setFolderName={setFolderName} isList={isList}
setIsLoading={setIsLoading} setIsAlert={setIsAlert}
setDocId={setDocId} setSkip={setSkip}
getPdfDocumentList={getPdfDocumentList} sortingData={sortingData}
isDocId={docId} />
setPdfData={setPdfData} {loading && (
isList={isList} <div className="text-center pb-[20px]">Loading...</div>
setIsAlert={setIsAlert} )}
setSkip={setSkip} </React.Suspense>
sortingData={sortingData} </div>
/> )}
{loading && ( </>
<div style={{ textAlign: "center" }}>Loading...</div> )}
)}
</React.Suspense>
</div>
)}
</>
)}
</div>
</div> </div>
); );
} }
+3 -5
View File
@@ -4,13 +4,11 @@ import Title from "../components/Title";
const PageNotFound = ({ prefix }) => { const PageNotFound = ({ prefix }) => {
return ( return (
<div className="flex items-center justify-center h-screen w-full bg-white rounded"> <div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded">
<Title title={"Page Not Found"} /> <Title title={"Page Not Found"} />
<div className="text-center"> <div className="text-center">
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black"> <h1 className="text-[60px] lg:text-[120px] font-semibold">404</h1>
404 <p className="text-[30px] lg:text-[50px]">
</h1>
<p className="text-[30px] lg:text-[50px] text-black">
{prefix ? prefix : "Page"} Not Found {prefix ? prefix : "Page"} Not Found
</p> </p>
</div> </div>
File diff suppressed because it is too large Load Diff
+7 -17
View File
@@ -8,6 +8,7 @@ import { useNavigate, useLocation } from "react-router-dom";
import { appInfo } from "../constant/appinfo"; import { appInfo } from "../constant/appinfo";
import { showTenant } from "../redux/reducers/ShowTenant"; import { showTenant } from "../redux/reducers/ShowTenant";
import { fetchAppInfo } from "../redux/reducers/infoReducer"; import { fetchAppInfo } from "../redux/reducers/infoReducer";
import Loader from "../primitives/Loader";
const PgSignUp = () => { const PgSignUp = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -127,7 +128,9 @@ const PgSignUp = () => {
user.set("username", zohoRes.data.result.email); user.set("username", zohoRes.data.result.email);
user.set("password", obj.password); user.set("password", obj.password);
user.set("email", zohoRes.data.result.email); user.set("email", zohoRes.data.result.email);
user.set("phone", zohoRes.data.result.phone); if (zohoRes?.data?.result?.phone) {
user.set("phone", zohoRes.data.result.phone);
}
user.set("name", zohoRes.data.result.name); user.set("name", zohoRes.data.result.name);
const res = await user.signUp(); const res = await user.signUp();
@@ -140,7 +143,7 @@ const PgSignUp = () => {
company: zohoRes.data.result.company, company: zohoRes.data.result.company,
name: zohoRes.data.result.name, name: zohoRes.data.result.name,
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
}, },
subscription: zohoRes.data.result.subscription subscription: zohoRes.data.result.subscription
@@ -409,21 +412,8 @@ const PgSignUp = () => {
<div className="bg-white"> <div className="bg-white">
<Title title={"Pgsignup page"} /> <Title title={"Pgsignup page"} />
{isLoader ? ( {isLoader ? (
<div <div className="flex justify-center items-center h-[100vh]">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<form id="signup" className="pgsignup-content" onSubmit={handleSubmit}> <form id="signup" className="pgsignup-content" onSubmit={handleSubmit}>
+156 -236
View File
@@ -10,9 +10,8 @@ import { useDrag, useDrop } from "react-dnd";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage"; import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import WidgetComponent from "../components/pdf/WidgetComponent"; import WidgetComponent from "../components/pdf/WidgetComponent";
import Tour from "reactour"; import Tour from "reactour";
import loader from "../assets/images/loader2.gif";
import { useLocation, useParams } from "react-router-dom"; import { useLocation, useParams } from "react-router-dom";
import Loader from "../primitives/LoaderWithMsg"; import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError"; import HandleError from "../primitives/HandleError";
import SignerListPlace from "../components/pdf/SignerListPlace"; import SignerListPlace from "../components/pdf/SignerListPlace";
import Header from "../components/pdf/PdfHeader"; import Header from "../components/pdf/PdfHeader";
@@ -49,7 +48,8 @@ import { SaveFileSize } from "../constant/saveFileSize";
import { EmailBody } from "../components/pdf/EmailBody"; import { EmailBody } from "../components/pdf/EmailBody";
import Upgrade from "../primitives/Upgrade"; import Upgrade from "../primitives/Upgrade";
import Alert from "../primitives/Alert"; import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
import mail_sent_gif from "../assets/gif/mail_sent.gif";
function PlaceHolderSign() { function PlaceHolderSign() {
const editorRef = useRef(); const editorRef = useRef();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -405,11 +405,14 @@ function PlaceHolderSign() {
}; };
setHandleError("Error: Something went wrong!"); setHandleError("Error: Something went wrong!");
setIsLoading(loadObj); setIsLoading(loadObj);
} else if (res[0] && res.length) { } else if (res.length && res[0]?.objectId) {
setActiveMailAdapter(res[0]?.active_mail_adapter); setActiveMailAdapter(res[0]?.active_mail_adapter);
setSignerUserId(res[0].objectId); setSignerUserId(res[0].objectId);
const tourstatus = res[0].TourStatus && res[0].TourStatus; const tourstatus = res[0].TourStatus && res[0].TourStatus;
if (tourstatus && tourstatus.length > 0) { const alreadyPlaceholder = documentData[0]?.SignedUrl;
if (alreadyPlaceholder) {
setCheckTourStatus(true);
} else if (tourstatus && tourstatus.length > 0) {
setTourStatus(tourstatus); setTourStatus(tourstatus);
const checkTourRecipients = tourstatus.filter( const checkTourRecipients = tourstatus.filter(
(data) => data.placeholder (data) => data.placeholder
@@ -933,6 +936,7 @@ function PlaceHolderSign() {
Placeholders: filterPrefill, Placeholders: filterPrefill,
SignedUrl: pdfUrl, SignedUrl: pdfUrl,
Signers: signers, Signers: signers,
SentToOthers: true,
ExpiryDate: { ExpiryDate: {
iso: updateExpiryDate, iso: updateExpiryDate,
__type: "Date" __type: "Date"
@@ -942,7 +946,8 @@ function PlaceHolderSign() {
data = { data = {
Placeholders: filterPrefill, Placeholders: filterPrefill,
SignedUrl: pdfUrl, SignedUrl: pdfUrl,
Signers: signers Signers: signers,
SentToOthers: true
}; };
} }
await axios await axios
@@ -995,9 +1000,10 @@ function PlaceHolderSign() {
for (let i = 0; i < signerMail.length; i++) { for (let i = 0; i < signerMail.length; i++) {
const objectId = signerMail[i].objectId; const objectId = signerMail[i].objectId;
const hostUrl = window.location.origin; const hostUrl = window.location.origin;
const sendMail = false;
//encode this url value `${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}` to base64 using `btoa` function //encode this url value `${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}` to base64 using `btoa` function
const encodeBase64 = btoa( const encodeBase64 = btoa(
`${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}` `${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}/${sendMail}`
); );
let signPdf = `${hostUrl}/login/${encodeBase64}`; let signPdf = `${hostUrl}/login/${encodeBase64}`;
shareLinkList.push({ signerEmail: signerMail[i].Email, url: signPdf }); shareLinkList.push({ signerEmail: signerMail[i].Email, url: signPdf });
@@ -1008,7 +1014,11 @@ function PlaceHolderSign() {
className="flex flex-row justify-between items-center mb-1" className="flex flex-row justify-between items-center mb-1"
key={ind} key={ind}
> >
{copied && <Alert type="success">Copied</Alert>} {copied && (
<Alert type="success">
<div className="ml-3">Copied</div>
</Alert>
)}
<span className="w-[220px] md:w-[300px] whitespace-nowrap overflow-hidden text-ellipsis "> <span className="w-[220px] md:w-[300px] whitespace-nowrap overflow-hidden text-ellipsis ">
{data.signerEmail} {data.signerEmail}
</span> </span>
@@ -1016,26 +1026,13 @@ function PlaceHolderSign() {
<button <button
onClick={() => copytoclipboard(data.url)} onClick={() => copytoclipboard(data.url)}
type="button" type="button"
className="flex flex-row items-center text-white font-[500]" className="flex flex-row items-center op-link op-link-primary"
> >
<i <i className="fa-solid fa-link" aria-hidden="true"></i>
className="fa-solid fa-link underline text-blue-700" <span className=" hidden md:block ml-1 ">Copy link</span>
aria-hidden="true"
></i>
<span className=" hidden md:block ml-1 underline text-blue-700">
Copy link
</span>
</button> </button>
<RWebShare <RWebShare data={{ url: data.url, title: "Sign url" }}>
data={{ <i className="fa-solid fa-share-from-square op-link op-link-secondary no-underline"></i>
url: data.url,
title: "Sign url"
}}
>
<i
className="fa-solid fa-share-from-square cursor-pointer "
style={{ color: themeColor }}
></i>
</RWebShare> </RWebShare>
</div> </div>
</div> </div>
@@ -1104,10 +1101,10 @@ function PlaceHolderSign() {
document_title: documentName, document_title: documentName,
sender_name: senderName, sender_name: senderName,
sender_mail: senderEmail, sender_mail: senderEmail,
sender_phone: senderPhone, sender_phone: senderPhone || "",
receiver_name: signerMail[i].Name, receiver_name: signerMail[i].Name,
receiver_email: signerMail[i].Email, receiver_email: signerMail[i].Email,
receiver_phone: signerMail[i].Phone, receiver_phone: signerMail[i]?.Phone || "",
expiry_date: localExpireDate, expiry_date: localExpireDate,
company_name: orgName, company_name: orgName,
signing_url: `<a href=${signPdf}>Sign here</a>` signing_url: `<a href=${signPdf}>Sign here</a>`
@@ -1159,40 +1156,45 @@ function PlaceHolderSign() {
} }
if (sendMail.data.result.status === "success") { if (sendMail.data.result.status === "success") {
setMailStatus("success"); setMailStatus("success");
try {
if ( let data;
requestBody && if (
requestSubject && requestBody &&
isCustomize && requestSubject &&
(isSubscribe || !isEnableSubscription) isCustomize &&
) { (isSubscribe || !isEnableSubscription)
try { ) {
const data = { data = {
RequestBody: htmlReqBody, RequestBody: htmlReqBody,
RequestSubject: requestSubject RequestSubject: requestSubject,
SendMail: true
};
} else {
data = {
SendMail: true
}; };
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document/${documentId}`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then(() => {})
.catch((err) => {
console.log("axois err ", err);
});
} catch (e) {
console.log("error", e);
} }
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document/${documentId}`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then(() => {})
.catch((err) => {
console.log("axois err ", err);
});
} catch (e) {
console.log("error", e);
} }
setIsSend(true); setIsSend(true);
@@ -1622,32 +1624,18 @@ function PlaceHolderSign() {
<Title title={state?.title ? state.title : "New Document"} /> <Title title={state?.title ? state.title : "New Document"} />
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? ( {isLoading.isLoad ? (
<Loader isLoading={isLoading} /> <LoaderWithMsg isLoading={isLoading} />
) : handleError ? ( ) : handleError ? (
<HandleError handleError={handleError} /> <HandleError handleError={handleError} />
) : ( ) : (
<div className="signatureContainer" ref={divRef}> <div
className="op-card overflow-hidden flex flex-row justify-between bg-base-300 relative"
ref={divRef}
>
{isUiLoading && ( {isUiLoading && (
<div <div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80">
style={{ <Loader />
position: "absolute", <span className="text-[13px] font-bold">
height: "100vh",
width: "100%",
display: "flex",
justifyContent: "center",
flexDirection: "column",
alignItems: "center",
zIndex: "999",
backgroundColor: "#e6f2f2",
opacity: 0.8
}}
>
<img
alt="no img"
src={loader}
style={{ width: "100px", height: "100px" }}
/>
<span style={{ fontSize: "13px", fontWeight: "bold" }}>
This might take some time This might take some time
</span> </span>
</div> </div>
@@ -1693,11 +1681,6 @@ function PlaceHolderSign() {
{/* this modal is used show alert set placeholder for all signers before send mail */} {/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi <ModalUi
headerColor={
isSendAlert.mssg === "sure" || isSendAlert.mssg === textWidget
? "#dc3545"
: isSendAlert.mssg === "confirm" && themeColor
}
isOpen={isSendAlert.alert} isOpen={isSendAlert.alert}
title={ title={
isSendAlert.mssg === "sure" || isSendAlert.mssg === textWidget isSendAlert.mssg === "sure" || isSendAlert.mssg === textWidget
@@ -1707,10 +1690,7 @@ function PlaceHolderSign() {
handleClose={() => setIsSendAlert({})} handleClose={() => setIsSendAlert({})}
showHeaderMessage={isSendAlert.mssg === "confirm"} showHeaderMessage={isSendAlert.mssg === "confirm"}
> >
<div <div className="max-h-96 overflow-y-scroll scroll-hide p-[20px] text-base-content">
className="max-h-96 overflow-y-scroll scroll-hide"
style={{ padding: 20 }}
>
{isSendAlert.mssg === "sure" ? ( {isSendAlert.mssg === "sure" ? (
<span> <span>
Please ensure there&apos;s at least one signature widget Please ensure there&apos;s at least one signature widget
@@ -1721,88 +1701,67 @@ function PlaceHolderSign() {
) : ( ) : (
isSendAlert.mssg === "confirm" && ( isSendAlert.mssg === "confirm" && (
<> <>
<> {!isCustomize && (
{!isCustomize && ( <span>
<span> Are you sure you want to send out this document for
Are you sure you want to send out this document signatures?
for signatures? </span>
</span> )}
)} {isCustomize &&
{isCustomize && (!isEnableSubscription || isSubscribe) && (
(!isEnableSubscription || isSubscribe) && ( <>
<> <EmailBody
<EmailBody editorRef={editorRef}
editorRef={editorRef} requestBody={requestBody}
requestBody={requestBody} requestSubject={requestSubject}
requestSubject={requestSubject} handleOnchangeRequest={handleOnchangeRequest}
handleOnchangeRequest={handleOnchangeRequest} setRequestSubject={setRequestSubject}
setRequestSubject={setRequestSubject} />
/> <div
<div className="flex justify-end items-center gap-1 mt-2 op-link op-link-primary"
className={ onClick={() => {
"flex justify-end items-center gap-1 mt-2 underline text-blue-700 focus:outline-none cursor-pointer " setRequestBody(defaultBody);
} setRequestSubject(defaultSubject);
onClick={() => {
setRequestBody(defaultBody);
setRequestSubject(defaultSubject);
}}
>
<span>Reset to default</span>
</div>
</>
)}
<div
className={
"flex flex-row md:items-center gap-2 md:gap-6 mt-2 "
}
>
<div className="flex flex-row gap-2">
<button
onClick={() => sendEmailToSigners()}
className=" shadow rounded-[2px] py-[3px] px-[25px] font-[500] text-sm "
style={{
background: themeColor,
color: "white"
}} }}
> >
Send <span>Reset to default</span>
</button>
{isCustomize && (
<button
onClick={() => {
setIsCustomize(false);
}}
className=" shadow rounded-[2px] py-[3px] px-[25px] font-[500] text-sm border-[0.1px] border-gray-300"
>
Close
</button>
)}
</div>
{!isCustomize &&
(isSubscribe || !isEnableSubscription) && (
<span
className={
"cursor-pointer underline text-blue-700 focus:outline-none"
}
onClick={() => {
setIsCustomize(!isCustomize);
}}
>
Cutomize Email
</span>
)}
{!isSubscribe && isEnableSubscription && (
<div className="mt-2">
<Upgrade
message="Upgrade to customize Email"
newWindow={true}
/>
</div> </div>
</>
)}
<div className="flex flex-row md:items-center gap-2 md:gap-6 mt-2">
<div className="flex flex-row gap-2">
<button
onClick={() => sendEmailToSigners()}
className="op-btn op-btn-primary font-[500] text-sm shadow"
>
Send
</button>
{isCustomize && (
<button
onClick={() => setIsCustomize(false)}
className="op-btn op-btn-ghost font-[500] text-sm"
>
Close
</button>
)} )}
</div> </div>
</>
{!isCustomize &&
(isSubscribe || !isEnableSubscription) && (
<span
className="op-link op-link-accent text-sm"
onClick={() => setIsCustomize(!isCustomize)}
>
Cutomize Email
</span>
)}
{!isSubscribe && isEnableSubscription && (
<div className="mt-2">
<Upgrade message="Upgrade to customize Email" />
</div>
)}
</div>
</> </>
) )
)} )}
@@ -1810,28 +1769,15 @@ function PlaceHolderSign() {
{isSendAlert.mssg === "confirm" && ( {isSendAlert.mssg === "confirm" && (
<> <>
<div className="flex justify-center items-center mt-3"> <div className="flex justify-center items-center mt-3">
<span <span className="h-[1px] w-[20%] bg-[#ccc]"></span>
style={{
height: 1,
width: "20%",
backgroundColor: "#ccc"
}}
></span>
<span className="ml-[5px] mr-[5px]">or</span> <span className="ml-[5px] mr-[5px]">or</span>
<span <span className="h-[1px] w-[20%] bg-[#ccc]"></span>
style={{
height: 1,
width: "20%",
backgroundColor: "#ccc"
}}
></span>
</div> </div>
<div className="mt-3 mb-3">{handleShareList()}</div> <div className="mt-3 mb-3">{handleShareList()}</div>
</> </>
)} )}
</div> </div>
</ModalUi> </ModalUi>
{/* this modal is used show send mail message and after send mail success message */} {/* this modal is used show send mail message and after send mail success message */}
<ModalUi <ModalUi
isOpen={isSend} isOpen={isSend}
@@ -1841,77 +1787,61 @@ function PlaceHolderSign() {
setSignerPos([]); setSignerPos([]);
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-[100%] p-[20px]">
{mailStatus === "success" ? ( {mailStatus === "success" ? (
<p>You have successfully sent mails to all recipients!</p> <div className="text-center mb-[10px]">
<img
src={mail_sent_gif}
className="w-[120px] h-[120px] mx-auto"
/>
<p>You have successfully sent mails to all recipients!</p>
{isCurrUser && (
<p>Do you want to sign documents right now ?</p>
)}
</div>
) : ( ) : (
<p>Please setup mail adapter to send mail!</p> <p>Please setup mail adapter to send mail!</p>
)} )}
{isCurrUser && ( {!mailStatus && (
<p>Do you want to sign documents right now ?</p> <div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
)} )}
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
{isCurrUser && ( {isCurrUser && (
<button <button
onClick={() => { onClick={() => handleRecipientSign()}
handleRecipientSign();
}}
style={{
background: themeColor,
color: "white"
}}
type="button" type="button"
className="finishBtn" className="op-btn op-btn-primary mr-1"
> >
Yes Yes
</button> </button>
)} )}
<button <button
onClick={() => { onClick={() => {
setIsSend(false); setIsSend(false);
setSignerPos([]); setSignerPos([]);
}} }}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost"
> >
{isCurrUser ? "No" : "Close"} {isCurrUser ? "No" : "Close"}
</button> </button>
</div> </div>
</ModalUi> </ModalUi>
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={isShowEmail} isOpen={isShowEmail}
title={"signers alert"} title={"signers alert"}
handleClose={() => { handleClose={() => {
setIsShowEmail(false); setIsShowEmail(false);
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-[100%] p-[20px]">
<p>Please select signer for add placeholder!</p> <p>Please select signer for add placeholder!</p>
<div <div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => { onClick={() => {
setIsShowEmail(false); setIsShowEmail(false);
}} }}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-primary"
> >
Ok Ok
</button> </button>
@@ -2065,12 +1995,13 @@ function PlaceHolderSign() {
</div> </div>
) : ( ) : (
<div> <div>
<div className="signerComponent" aria-disabled> <div
className="hidden md:block w-[180px] h-full bg-base-100"
aria-disabled
>
<div <div
style={{ style={{ maxHeight: window.innerHeight - 70 + "px" }}
maxHeight: window.innerHeight - 70 + "px" className="overflow-y-auto hide-scrollbar"
}}
className="autoSignScroll"
> >
<SignerListPlace <SignerListPlace
signerPos={signerPos} signerPos={signerPos}
@@ -2116,33 +2047,22 @@ function PlaceHolderSign() {
</DndProvider> </DndProvider>
<div> <div>
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={isAlreadyPlace.status} isOpen={isAlreadyPlace.status}
title={"Document Alert"} title={"Document Alert"}
showClose={false} showClose={false}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-[100%] p-[20px]">
<p>{isAlreadyPlace.message}</p> <p>{isAlreadyPlace.message}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => handleRecipientSign()} onClick={() => handleRecipientSign()}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-primary"
> >
View View
</button> </button>
</div> </div>
</ModalUi> </ModalUi>
<LinkUserModal <LinkUserModal
handleAddUser={handleAddUser} handleAddUser={handleAddUser}
isAddUser={isAddUser} isAddUser={isAddUser}
+41 -53
View File
@@ -4,6 +4,8 @@ import checkmark from "../assets/images/checkmark.png";
import plansArr from "../json/plansArr"; import plansArr from "../json/plansArr";
import Title from "../components/Title"; import Title from "../components/Title";
import Parse from "parse"; import Parse from "parse";
import { openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
const listItemStyle = { const listItemStyle = {
paddingLeft: "20px", // Add padding to create space for the image paddingLeft: "20px", // Add padding to create space for the image
backgroundImage: `url(${checkmark})`, // Set your image as the list style image backgroundImage: `url(${checkmark})`, // Set your image as the list style image
@@ -16,8 +18,17 @@ const PlanSubscriptions = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [yearlyVisible, setYearlyVisible] = useState(false); const [yearlyVisible, setYearlyVisible] = useState(false);
const [isLoader, setIsLoader] = useState(true); const [isLoader, setIsLoader] = useState(true);
const extUser =
const userDetails = JSON.parse(localStorage.getItem("userDetails")); localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const user = {
name: extUser?.Name,
email: extUser?.Email,
company: extUser?.Company,
phone: extUser?.Phone
};
const userDetails = JSON.parse(localStorage.getItem("userDetails")) || user;
// console.log("userDetails ", userDetails);
const name = const name =
userDetails && userDetails.name userDetails && userDetails.name
? "first_name=" + encodeURIComponent(userDetails.name) ? "first_name=" + encodeURIComponent(userDetails.name)
@@ -75,55 +86,33 @@ const PlanSubscriptions = () => {
<> <>
<Title title={"Subscriptions"} /> <Title title={"Subscriptions"} />
{isLoader ? ( {isLoader ? (
<div <div className="flex items-center justify-center h-screen">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<div <div className="overflow-y-auto max-h-full">
style={{
backgroundColor: "white",
overflowY: "auto",
maxHeight: "100%"
}}
>
<div className="block my-2"> <div className="block my-2">
<div className="flex flex-col justify-center items-center w-full"> <div className="flex flex-col justify-center items-center w-full">
<div className="mb-6 mt-2 flex flex-row border-[1px] p-2 border-gray-300 rounded text-sm"> <div
<span role="tablist"
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
>
<a
onClick={() => setYearlyVisible(false)} onClick={() => setYearlyVisible(false)}
className={`${ role="tab"
!yearlyVisible className={`${!yearlyVisible ? "op-tab-active" : ""} op-tab`}
? "bg-[#002862] text-white"
: "bg-white text-black"
} px-4 py-1 rounded cursor-pointer`}
> >
Monthly Monthly
</span> </a>
<span <a
onClick={() => setYearlyVisible(true)} onClick={() => setYearlyVisible(true)}
className={`${ role="tab"
yearlyVisible className={`${yearlyVisible ? "op-tab-active" : ""} op-tab`}
? "bg-[#002862] text-white"
: "bg-white text-black"
} px-4 py-1 rounded cursor-pointer`}
> >
Yearly (10% off) Yearly (10% off)
</span> </a>
</div> </div>
<ul className="flex flex-col md:flex-row h-full bg-white justify-center"> <ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
{plansArr.map((item) => ( {plansArr.map((item) => (
<li <li
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]" className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
@@ -198,9 +187,7 @@ const PlanSubscriptions = () => {
<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">
<span style={{ position: "relative" }}> <span className="relative">{subitem}</span>
{subitem}
</span>
</li> </li>
))} ))}
</ul> </ul>
@@ -208,22 +195,23 @@ const PlanSubscriptions = () => {
))} ))}
</ul> </ul>
</div> </div>
<div className="text-sm flex justify-center items-center"> <div className="text-sm flex justify-center items-center mt-3 mb-2">
<hr className="border-[1px] border-gray-300 w-[20%]" /> <hr className="border-[2px] border-gray-350 w-[20%]" />
<span className="px-2 text-gray-500 cursor-default">or</span> <span className="px-2 text-base-content cursor-default">or</span>
<hr className="border-[1px] border-gray-300 w-[20%]" /> <hr className="border-[2px] border-gray-350 w-[20%]" />
</div> </div>
<div className="flex flex-col justify-center w-full items-center"> <div className="flex flex-col justify-center items-center">
<h3 className="text-[#002862] mt-1 mb-2"> <h3 className="text-[#002862] mt-1 mb-2">
Host it yourself for free Host it yourself for free
</h3> </h3>
<NavLink <div
to={"https://github.com/OpenSignLabs/OpenSign"} className="op-btn op-btn-primary w-[200px]"
className="bg-[#002862] w-[200px] text-center text-white py-2 rounded uppercase hover:no-underline hover:text-white cursor-pointer" onClick={() =>
target={"_blank"} openInNewTab("https://github.com/OpenSignLabs/OpenSign")
}
> >
Visit Github Visit Github
</NavLink> </div>
</div> </div>
</div> </div>
</div> </div>
+3 -15
View File
@@ -7,6 +7,7 @@ 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"; import TourContentWithBtn from "../primitives/TourContentWithBtn";
import Loader from "../primitives/Loader";
const Report = () => { const Report = () => {
const { id } = useParams(); const { id } = useParams();
@@ -173,21 +174,8 @@ const Report = () => {
<> <>
<Title title={reportName} /> <Title title={reportName} />
{isLoader ? ( {isLoader ? (
<div <div className="h-[100vh] flex justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<> <>
+384
View File
@@ -0,0 +1,384 @@
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import Parse from "parse";
import axios from "axios";
import { appInfo } from "../constant/appinfo";
import { isEnableSubscription } from "../constant/const";
import { fetchSubscription } from "../constant/Utils";
import { useDispatch } from "react-redux";
import { showTenant } from "../redux/reducers/ShowTenant";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
const SSOVerify = () => {
const location = useLocation();
const navigate = useNavigate();
const dispatch = useDispatch();
const [isModal, setIsModal] = useState(false);
const [message, setMessage] = useState("Verifying SSO...");
const [isLoader, setIsLoader] = useState(false);
const [userDetails, setUserDetails] = useState({
name: "",
email: "",
phone: "",
Destination: "",
Company: ""
});
useEffect(() => {
linkUserWithSSO();
// eslint-disable-next-line
}, []);
// `linkUserWithSSO` is used to sign in or sign up a user using an SSO code and check if the user is present in the extended class
const linkUserWithSSO = async () => {
const param = new URLSearchParams(location.search);
const code = param?.get("code");
const state = param?.get("state");
try {
// The `ssosign` cloud function is used to sign in or sign up a user
const ssosign = await Parse.Cloud.run("ssosign", {
code: code,
email: state
});
localStorage.setItem("accesstoken", ssosign.sessiontoken);
// `checkExtUser` checks if the user is present in the extended class `contracts_Users` and if not, initiates the new user flow
await checkExtUser(ssosign);
} catch (err) {
setMessage("Error: " + err.message);
console.log("err", err.message);
}
};
const checkExtUser = async (ssosign) => {
const params = { email: ssosign?.email };
try {
// `isextenduser` checks if the current user is present in the extended class
const extRes = await Parse.Cloud.run("isextenduser", params);
if (extRes?.isUserExist) {
// `getUserDetails` retrieves the current user's details from the extended class
const extRes = await Parse.Cloud.run("getUserDetails", params);
if (ssosign && ssosign.sessiontoken) {
const LocalUserDetails = {
name: extRes.Name,
email: extRes.email,
phone: extRes?.get("Phone") || "",
company: extRes.get("Company")
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(ssosign.sessiontoken);
}
} else {
setIsModal(true);
setUserDetails((prev) => ({
...prev,
name: ssosign.name,
email: ssosign.email,
phone: ssosign?.phone || ""
}));
}
} catch (err) {
console.log("Err in isextenduser or getuserdetails cloud function", err);
setMessage("Error: " + err.message);
}
};
// `handleSubmitbtn` is used to create a user in the extended class
const handleSubmitbtn = async (e) => {
e.preventDefault();
setIsLoader(true);
let phone;
if (userDetails?.phone) {
phone = validateInput(userDetails?.phone);
} else {
phone = true;
}
if (userDetails.Destination && userDetails.Company && phone) {
const payload = { sessionToken: localStorage.getItem("accesstoken") };
if (payload && payload.sessionToken) {
const params = {
userDetails: {
name: userDetails.name,
email: userDetails.email,
phone: userDetails?.phone || "",
role: "contracts_User",
company: userDetails.Company,
jobTitle: userDetails.Destination
}
};
try {
const userSignUp = await Parse.Cloud.run("usersignup", params);
if (userSignUp && userSignUp.sessionToken) {
const LocalUserDetails = params.userDetails;
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
);
await thirdpartyLoginfn(userSignUp.sessionToken);
setIsLoader(false);
} else {
alert(userSignUp.message);
setIsLoader(false);
}
} catch (err) {
console.log("error in usersignup", err);
localStorage.removeItem("accesstoken");
alert("Something went wrong.");
setIsLoader(false);
}
} else {
localStorage.removeItem("accesstoken");
alert("Internal server error.");
setIsLoader(false);
}
} else {
alert("Please fill required details correctly.");
setIsLoader(false);
}
};
// `thirdpartyLoginfn` is used to save necessary parameters locally for the logged-in user
const thirdpartyLoginfn = async (sessionToken) => {
const baseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
try {
const validUser = await Parse.User.become(sessionToken);
if (validUser) {
localStorage.setItem("accesstoken", sessionToken);
const _user = JSON.parse(JSON.stringify(validUser));
localStorage.setItem("UserInformation", JSON.stringify(_user));
if (_user.ProfilePic) {
localStorage.setItem("profileImg", _user.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
let userRoles = [];
const userSettings = appInfo.settings;
//Get Current user roles
const url = `${baseUrl}functions/UserGroups`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: _user.sessionToken
};
const body = { appname: appInfo.appname };
const UserGroupsRes = await axios.post(url, JSON.stringify(body), {
headers: headers
});
userRoles = (UserGroupsRes.data && UserGroupsRes.data.result) || [];
if (userRoles) {
let _currentRole = "";
const excludeRoles = ["contracts_Guest", `contracts_appeditor`];
const filteredRole = userRoles.filter(
(x) => !excludeRoles.includes(x)
);
if (filteredRole?.length > 1) {
console.log("user has two roles");
// _currentRole = filteredRole.filter((x) => x === "contracts_User");
} else {
_currentRole = filteredRole?.[0] || "";
}
if (_currentRole) {
const roleSetting = userSettings?.find(
(setting) => setting.role === _currentRole
);
const redirectUrl =
location?.state?.from ||
`/${roleSetting.pageType}/${roleSetting.pageId}`;
const _role = _currentRole.replace(`${appInfo.appname}_`, "");
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
roleSetting.extended_class
);
try {
const extUser = await Parse.Cloud.run("getUserDetails", {
email: _user.email
});
if (extUser) {
const _extUser = JSON.parse(JSON.stringify(extUser));
localStorage.setItem("userEmail", _extUser.Email);
localStorage.setItem("username", _extUser.Name);
localStorage.setItem("scriptId", true);
let tenentInfo = [];
const results = [extUser];
if (results) {
let extendedInfo_stringify = JSON.stringify(results);
localStorage.setItem(
"Extand_Class",
extendedInfo_stringify
);
if (_extUser.TenantId) {
const obj = {
tenentId: _extUser.TenantId.objectId,
tenentName: _extUser.TenantId.TenantName || ""
};
localStorage.setItem("TenantId", obj.tenentId);
tenentInfo.push(obj);
dispatch(showTenant(obj.tenentName || ""));
localStorage.setItem("TenantName", obj.tenentName || "");
}
localStorage.setItem("PageLanding", roleSetting.pageId);
localStorage.setItem("defaultmenuid", roleSetting.menuId);
localStorage.setItem("pageType", roleSetting.pageType);
if (isEnableSubscription) {
const res = await fetchSubscription();
const plan = res.plan;
const billingDate = res.billingDate;
if (plan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
localStorage.removeItem("userDetails");
navigate(redirectUrl);
} else {
navigate(`/subscription`, {
replace: true
});
}
} else {
navigate(`/subscription`, {
replace: true
});
}
} else {
navigate(redirectUrl);
}
}
}
} catch (err) {
alert("user not exist.");
setMessage("Error: User not exist.");
console.log("err in get extUser", err);
}
} else {
alert("Role does not exists.");
setMessage("Error: Role does not exists.");
}
} else {
alert("Role does not exists.");
setMessage("Error: Role does not exists.");
}
} catch (err) {
console.log("err in usergroups", err);
}
}
} catch (err) {
console.log("Err in become method", err);
}
};
// `handleCloseModal` is triggered when the user wants to close the new user flow modal
const handleCloseModal = () => {
setIsModal(false);
if (Parse?.User?.current()) {
Parse.User.logOut();
}
};
// `validateInput` is used to verify the phone pattern
function validateInput(input) {
if (input) {
const pattern = /^(?!.*\+.*\+)[\d+-]*$/;
return pattern.test(input);
} else {
return true;
}
}
return (
<div>
<div className="w-full h-screen flex flex-col justify-center items-center text-sm md:text-xl ">
{message === "Verifying SSO..." && <Loader />}
<div className="text-base-content">{message}</div>
</div>
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
<div className="relative">
{isLoader && (
<div className="absolute w-full h-full bg-black bg-opacity-25 flex justify-center items-center">
<Loader />
</div>
)}
<form
className="px-4 py-3 text-base-content"
onSubmit={handleSubmitbtn}
>
<div className="mb-3">
<label htmlFor="Company" className="block text-xs font-semibold">
Phone <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="tel"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="Phone"
value={userDetails.phone}
onChange={(e) =>
setUserDetails({
...userDetails,
phone: e.target.value
})
}
disabled={isLoader}
required
/>
<p className="text-[10px] text-[red] ml-2">
{!validateInput(userDetails.phone) && "Invalid phone value"}
</p>
</div>
<div className="mb-3">
<label htmlFor="Company" className="block text-xs font-semibold">
Company <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="text"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="Company"
value={userDetails.Company}
onChange={(e) =>
setUserDetails({
...userDetails,
Company: e.target.value
})
}
disabled={isLoader}
required
/>
</div>
<div className="mb-3">
<label htmlFor="JobTitle" className="block text-xs font-semibold">
Job Title
<span className="text-[13px] text-[red]">*</span>
</label>
<input
type="text"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
id="JobTitle"
value={userDetails.Destination}
onChange={(e) =>
setUserDetails({
...userDetails,
Destination: e.target.value
})
}
disabled={isLoader}
required
/>
</div>
<div className="mt-4">
<button type="submit" className="op-btn op-btn-primary">
Login
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={handleCloseModal}
>
Cancel
</button>
</div>
</form>
</div>
</ModalUi>
</div>
);
};
export default SSOVerify;
+69 -71
View File
@@ -2,7 +2,7 @@ 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, useLocation } from "react-router-dom"; import { 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 Alert from "../primitives/Alert"; import Alert from "../primitives/Alert";
@@ -11,7 +11,8 @@ import { useDispatch } from "react-redux";
import { fetchAppInfo } from "../redux/reducers/infoReducer"; import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant"; import { showTenant } from "../redux/reducers/ShowTenant";
import { isEnableSubscription } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { getAppLogo } from "../constant/Utils"; import { getAppLogo, openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
const Signup = () => { const Signup = () => {
const { width } = useWindowSize(); const { width } = useWindowSize();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -33,7 +34,7 @@ const Signup = () => {
const [lengthValid, setLengthValid] = useState(false); const [lengthValid, setLengthValid] = useState(false);
const [caseDigitValid, setCaseDigitValid] = useState(false); const [caseDigitValid, setCaseDigitValid] = useState(false);
const [specialCharValid, setSpecialCharValid] = useState(false); const [specialCharValid, setSpecialCharValid] = useState(false);
const [isAuthorize, setIsAuthorize] = useState(false);
const togglePasswordVisibility = () => setShowPassword(!showPassword); const togglePasswordVisibility = () => setShowPassword(!showPassword);
const clearStorage = async () => { const clearStorage = async () => {
@@ -501,80 +502,58 @@ const Signup = () => {
setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword)); setSpecialCharValid(/[!@#$%^&*()\-_=+{};:,<.>]/.test(newPassword));
}; };
return ( return (
<div className="bg-white"> <div className="">
{state.loading && ( {state.loading && (
<div <div className="fixed w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-50">
style={{ <Loader />
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</div> </div>
)} )}
<Title title={"Signup page"} /> <Title title={"Signup page"} />
{appInfo && appInfo.applogo ? ( {appInfo && appInfo.applogo ? (
<div> <div className="md:p-10 lg:p-16">
<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:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
<div className="w-[250px] h-[66px] inline-block overflow-hidden"> <div className="w-[250px] h-[66px] inline-block overflow-hidden">
{image && ( {image && (
<img src={image} className="object-contain h-full" alt="logo" /> <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>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Create Account !</h2> <h2 className="text-[30px] mt-6">Create Account !</h2>
<div className="outline outline-1 outline-slate-300/50 shadow-md rounded my-4"> <div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<div className="px-6 py-4 text-xs"> <div className="px-6 py-4 text-xs">
<label className="block "> <label className="block ">
Name{" "} Name <span className="text-[red] text-[13px]">*</span>
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
required required
/> />
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
<label> <label>
Email{" "} Email <span className="text-[red] text-[13px]">*</span>
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label> </label>
<input <input
id="email" id="email"
type="text" type="email"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) =>
setEmail(e.target.value?.toLowerCase())
}
required required
/> />
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
<label> <label>
Phone{" "} Phone <span className="text-[red] text-[13px]">*</span>
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label> </label>
<input <input
type="tel" type="tel"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={phone} value={phone}
onChange={(e) => setPhone(e.target.value)} onChange={(e) => setPhone(e.target.value)}
required required
@@ -582,11 +561,11 @@ const Signup = () => {
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
<label> <label>
Company{" "} Company{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span> <span className="text-[red] text-[13px]">*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={company} value={company}
onChange={(e) => setCompany(e.target.value)} onChange={(e) => setCompany(e.target.value)}
required required
@@ -594,11 +573,11 @@ const Signup = () => {
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
<label> <label>
Job Title{" "} Job Title{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span> <span className="text-[red] text-[13px]">*</span>
</label> </label>
<input <input
type="text" type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={jobTitle} value={jobTitle}
onChange={(e) => setJobTitle(e.target.value)} onChange={(e) => setJobTitle(e.target.value)}
required required
@@ -606,21 +585,19 @@ const Signup = () => {
<hr className="my-2 border-none" /> <hr className="my-2 border-none" />
<label> <label>
Password{" "} Password{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span> <span className="text-[red] text-[13px]">*</span>
</label> </label>
<div className="relative"> <div className="relative">
<input <input
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="password" name="password"
value={password} value={password}
onChange={(e) => handlePasswordChange(e)} onChange={(e) => handlePasswordChange(e)}
required required
/> />
<span <span
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${ className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer text-base-content`}
showPassword ? "text-[#007bff]" : "text-black"
}`}
onClick={togglePasswordVisibility} onClick={togglePasswordVisibility}
> >
{showPassword ? ( {showPassword ? (
@@ -658,34 +635,62 @@ const Signup = () => {
{specialCharValid ? "✓" : "✗"} Password should {specialCharValid ? "✓" : "✗"} Password should
contain special character contain special character
</p> </p>
{/* </>
)} */}
</div> </div>
)} )}
<div className="mt-2.5 ml-1 flex flex-row items-center">
<input
type="checkbox"
className="op-checkbox op-checkbox-sm"
id="termsandcondition"
checked={isAuthorize}
onChange={(e) => setIsAuthorize(e.target.checked)}
required
/>
<label
className="text-xs cursor-pointer ml-1 mb-0"
htmlFor="termsandcondition"
>
I agree to the
</label>
<span
className="underline cursor-pointer ml-1"
onClick={() =>
openInNewTab(
"https://www.opensignlabs.com/terms-and-conditions"
)
}
>
Terms of Service
</span>
<span>.</span>
</div>
</div> </div>
</div> </div>
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2"> <div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold mt-2">
<button <button
type="submit" type="submit"
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow uppercase" className="op-btn op-btn-primary"
disabled={state.loading} disabled={state.loading}
> >
{state.loading ? "Loading..." : "Register"} {state.loading ? "Loading..." : "Register"}
</button> </button>
<NavLink <button
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase" type="button"
to={location.search ? "/" + location.search : "/"} className="op-btn op-btn-secondary"
style={width < 768 ? { textAlign: "center" } : {}} disabled={state.loading}
onClick={() =>
navigate(location.search ? "/" + location.search : "/")
}
> >
Login Login
</NavLink> </button>
</div> </div>
</form> </form>
</div> </div>
{width >= 768 && ( {width >= 768 && (
<div className="self-center"> <div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]"> <div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img src={login_img} alt="bisec" width="100%" /> <img src={login_img} alt="loader" width="100%" />
</div> </div>
</div> </div>
)} )}
@@ -694,16 +699,9 @@ const Signup = () => {
<Alert type={state.alertType}>{state.alertMsg}</Alert> <Alert type={state.alertType}>{state.alertMsg}</Alert>
</div> </div>
) : ( ) : (
<div <div className="fixed w-full h-full flex justify-center items-center z-50">
style={{ <Loader />
position: "fixed", </div>
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
)} )}
</div> </div>
); );
+139 -170
View File
@@ -2,10 +2,10 @@ 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 Parse from "parse"; import Parse from "parse";
import { isEnableSubscription, themeColor } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import Confetti from "react-confetti";
import axios from "axios"; import axios from "axios";
import Loader from "../primitives/LoaderWithMsg"; import LoaderWithMsg from "../primitives/LoaderWithMsg";
import loader from "../assets/images/loader2.gif";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage"; import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import { DndProvider } from "react-dnd"; import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend"; import { HTML5Backend } from "react-dnd-html5-backend";
@@ -47,7 +47,7 @@ import Title from "../components/Title";
import ModalUi from "../primitives/ModalUi"; import ModalUi from "../primitives/ModalUi";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption"; import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import VerifyEmail from "../components/pdf/VerifyEmail"; import VerifyEmail from "../components/pdf/VerifyEmail";
import Loader from "../primitives/Loader";
//For signYourself inProgress section signer can add sign and complete doc sign. //For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() { function SignYourSelf() {
const [pdfDetails, setPdfDetails] = useState([]); const [pdfDetails, setPdfDetails] = useState([]);
@@ -70,7 +70,6 @@ function SignYourSelf() {
const [dragKey, setDragKey] = useState(); const [dragKey, setDragKey] = useState();
const [signKey, setSignKey] = useState(); const [signKey, setSignKey] = useState();
const [imgWH, setImgWH] = useState({}); const [imgWH, setImgWH] = useState({});
const [isCeleb, setIsCeleb] = useState(false);
const [pdfNewWidth, setPdfNewWidth] = useState(); const [pdfNewWidth, setPdfNewWidth] = useState();
const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [successEmail, setSuccessEmail] = useState(false); const [successEmail, setSuccessEmail] = useState(false);
@@ -109,6 +108,7 @@ function SignYourSelf() {
const [isDontShow, setIsDontShow] = useState(false); const [isDontShow, setIsDontShow] = useState(false);
const [extUserId, setExtUserId] = useState(""); const [extUserId, setExtUserId] = useState("");
const [isCompleted, setIsCompleted] = useState(false); const [isCompleted, setIsCompleted] = useState(false);
const [isCelebration, setIsCelebration] = useState(false);
const [pdfArrayBuffer, setPdfArrayBuffer] = useState(""); const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
const [activeMailAdapter, setActiveMailAdapter] = useState(""); const [activeMailAdapter, setActiveMailAdapter] = useState("");
const [isEmailVerified, setIsEmailVerified] = useState(true); const [isEmailVerified, setIsEmailVerified] = useState(true);
@@ -229,31 +229,12 @@ function SignYourSelf() {
setIsUiLoading(false); setIsUiLoading(false);
setIsSignPad(false); setIsSignPad(false);
setIsEmail(true); setIsEmail(true);
setIsCelebration(true);
setXyPostion([]); setXyPostion([]);
setSignBtnPosition([]); setSignBtnPosition([]);
} setTimeout(() => {
} setIsCelebration(false);
}, 5000);
if (!isCompleted) {
//check current user email verified or not
const currentUser = JSON.parse(JSON.stringify(Parse.User.current()));
let isEmailVerified;
isEmailVerified = currentUser?.emailVerified;
if (isEmailVerified) {
setIsEmailVerified(isEmailVerified);
} else {
try {
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(currentUser.objectId, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
isEmailVerified = user?.get("emailVerified");
setIsEmailVerified(isEmailVerified);
}
} catch (e) {
setHandleError("Error: Something went wrong!");
}
} }
} }
} else if ( } else if (
@@ -603,104 +584,122 @@ function SignYourSelf() {
}; };
//function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url //function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url
async function embedWidgetsData() { async function embedWidgetsData() {
let showAlert = false, //check current user email is verified or not
isSignatureExist = false; const currentUser = JSON.parse(JSON.stringify(Parse.User.current()));
try { let isEmailVerified;
for (let i = 0; i < xyPostion?.length; i++) { isEmailVerified = currentUser?.emailVerified;
const requiredWidgets = xyPostion[i].pos.filter( if (isEmailVerified) {
(position) => position.type !== "checkbox" setIsEmailVerified(isEmailVerified);
); } else {
if (requiredWidgets && requiredWidgets?.length > 0) { try {
let checkSigned; const userQuery = new Parse.Query(Parse.User);
for (let i = 0; i < requiredWidgets?.length; i++) { const user = await userQuery.get(currentUser.objectId, {
checkSigned = requiredWidgets[i]?.options?.response; sessionToken: localStorage.getItem("accesstoken")
if (!checkSigned) { });
const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; if (user) {
let checkDefaultSigned = isEmailVerified = user?.get("emailVerified");
requiredWidgets[i]?.options?.defaultValue; setIsEmailVerified(isEmailVerified);
if (!checkSignUrl) { }
if (!checkDefaultSigned) { } catch (e) {
if (!showAlert) { setHandleError("Error: Something went wrong!");
showAlert = true; }
}
if (isEmailVerified) {
let showAlert = false,
isSignatureExist = false;
try {
for (let i = 0; i < xyPostion?.length; i++) {
const requiredWidgets = xyPostion[i].pos.filter(
(position) => position.type !== "checkbox"
);
if (requiredWidgets && requiredWidgets?.length > 0) {
let checkSigned;
for (let i = 0; i < requiredWidgets?.length; i++) {
checkSigned = requiredWidgets[i]?.options?.response;
if (!checkSigned) {
const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl;
let checkDefaultSigned =
requiredWidgets[i]?.options?.defaultValue;
if (!checkSignUrl) {
if (!checkDefaultSigned) {
if (!showAlert) {
showAlert = true;
}
} }
} }
} }
} }
} }
} //condition to check exist signature widget or not
//condition to check exist signature widget or not if (!isSignatureExist) {
if (!isSignatureExist) { isSignatureExist = xyPostion[i].pos.some(
isSignatureExist = xyPostion[i].pos.some( (data) => data?.type === "signature"
(data) => data?.type === "signature" );
);
}
}
if (xyPostion.length === 0 || !isSignatureExist) {
setIsAlert({
header: "Fields required",
isShow: true,
alertMessage:
"Please ensure there's at least one signature widget added"
});
return;
} else if (showAlert) {
setIsAlert({
isShow: true,
alertMessage:
"Please ensure all field is accurately filled and meets all requirements."
});
return;
} else {
setIsCeleb(true);
setTimeout(() => {
setIsCeleb(false);
}, 3000);
setIsUiLoading(true);
const existingPdfBytes = pdfArrayBuffer;
// Load a PDFDocument from the existing PDF bytes
try {
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const isSignYourSelfFlow = true;
const extUserPtr = pdfDetails[0].ExtUserPtr;
const HeaderDocId = extUserPtr?.HeaderDocId;
//embed document's object id to all pages in pdf document
if (!HeaderDocId) {
await embedDocId(pdfDoc, documentId, allPages);
}
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed(
xyPostion,
pdfDoc,
pdfOriginalWidth,
isSignYourSelfFlow,
containerWH
);
// console.log("pdf", pdfBytes);
//function for call to embed signature in pdf and get digital signature pdf
await signPdfFun(pdfBytes, documentId);
} catch (err) {
setIsUiLoading(false);
if (err && err.message.includes("is encrypted.")) {
setIsAlert({
isShow: true,
alertMessage: `Currently encrypted pdf files are not supported.`
});
} else {
console.log("err in signing", err);
setIsAlert({
isShow: true,
alertMessage: `Something went wrong.`
});
} }
} }
if (xyPostion.length === 0 || !isSignatureExist) {
setIsAlert({
header: "Fields required",
isShow: true,
alertMessage:
"Please ensure there's at least one signature widget added"
});
return;
} else if (showAlert) {
setIsAlert({
isShow: true,
alertMessage:
"Please ensure all field is accurately filled and meets all requirements."
});
return;
} else {
setIsUiLoading(true);
const existingPdfBytes = pdfArrayBuffer;
// Load a PDFDocument from the existing PDF bytes
try {
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const isSignYourSelfFlow = true;
const extUserPtr = pdfDetails[0].ExtUserPtr;
const HeaderDocId = extUserPtr?.HeaderDocId;
//embed document's object id to all pages in pdf document
if (!HeaderDocId) {
await embedDocId(pdfDoc, documentId, allPages);
}
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed(
xyPostion,
pdfDoc,
pdfOriginalWidth,
isSignYourSelfFlow,
containerWH
);
// console.log("pdf", pdfBytes);
//function for call to embed signature in pdf and get digital signature pdf
await signPdfFun(pdfBytes, documentId);
} catch (err) {
setIsUiLoading(false);
if (err && err.message.includes("is encrypted.")) {
setIsAlert({
isShow: true,
alertMessage: `Currently encrypted pdf files are not supported.`
});
} else {
console.log("err in signing", err);
setIsAlert({
isShow: true,
alertMessage: `Something went wrong.`
});
}
}
}
} catch (err) {
console.log("err in embedselfsign ", err);
setIsUiLoading(false);
setIsAlert({
isShow: true,
alertMessage: "something went wrong, please try again later."
});
} }
} catch (err) {
console.log("err in embedselfsign ", err);
setIsUiLoading(false);
setIsAlert({
isShow: true,
alertMessage: "something went wrong, please try again later."
});
} }
} }
//function for get digital signature //function for get digital signature
@@ -1093,38 +1092,29 @@ function SignYourSelf() {
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
<Title title={"Self Sign"} /> <Title title={"Self Sign"} />
{isLoading.isLoad ? ( {isLoading.isLoad ? (
<Loader isLoading={isLoading} /> <LoaderWithMsg isLoading={isLoading} />
) : handleError ? ( ) : handleError ? (
<HandleError handleError={handleError} /> <HandleError handleError={handleError} />
) : ( ) : (
<div> <div>
{isUiLoading && ( {isUiLoading && (
<div <div className="absolute h-[100vh] w-full z-[999] flex flex-col justify-center items-start bg-[#e6f2f2] bg-opacity-80">
style={{ <Loader />
position: "absolute", <span className="font-bold text-[13px]">
height: "100vh",
width: "100%",
display: "flex",
justifyContent: "center",
flexDirection: "column",
alignItems: "center",
zIndex: "999",
backgroundColor: "#e6f2f2",
opacity: 0.8
}}
>
<img
alt="no img"
src={loader}
style={{ width: "100px", height: "100px" }}
/>
<span style={{ fontSize: "13px", fontWeight: "bold" }}>
This might take some time This might take some time
</span> </span>
</div> </div>
)} )}
{isCelebration && (
<div className="relative z-[999]">
<Confetti width={window.innerWidth} height={window.innerHeight} />
</div>
)}
<div className="signatureContainer" ref={divRef}> <div
className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300"
ref={divRef}
>
{!isEmailVerified && ( {!isEmailVerified && (
<VerifyEmail <VerifyEmail
isVerifyModal={isVerifyModal} isVerifyModal={isVerifyModal}
@@ -1169,7 +1159,6 @@ function SignYourSelf() {
}} }}
> >
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={isAlert.isShow} isOpen={isAlert.isShow}
title={isAlert?.header || "Alert"} title={isAlert?.header || "Alert"}
handleClose={() => { handleClose={() => {
@@ -1179,7 +1168,7 @@ function SignYourSelf() {
}); });
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p> <p>{isAlert.alertMessage}</p>
</div> </div>
</ModalUi> </ModalUi>
@@ -1187,25 +1176,16 @@ function SignYourSelf() {
{/* this modal is used show this document is already sign */} {/* this modal is used show this document is already sign */}
<ModalUi <ModalUi
isOpen={showAlreadySignDoc.status} isOpen={showAlreadySignDoc.status}
title={"Sign Documents"} title={"Document signed"}
handleClose={() => { handleClose={() => {
setShowAlreadySignDoc({ status: false }); setShowAlreadySignDoc({ status: false });
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="p-[20px] h-full">
<p>{showAlreadySignDoc.mssg}</p> <p>{showAlreadySignDoc.mssg}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
className="finishBtn cancelBtn" className="op-btn op-btn-ghost shadow-md"
onClick={() => setShowAlreadySignDoc({ status: false })} onClick={() => setShowAlreadySignDoc({ status: false })}
> >
Close Close
@@ -1259,7 +1239,6 @@ function SignYourSelf() {
<EmailComponent <EmailComponent
isEmail={isEmail} isEmail={isEmail}
pdfUrl={pdfUrl} pdfUrl={pdfUrl}
isCeleb={isCeleb}
setIsEmail={setIsEmail} setIsEmail={setIsEmail}
pdfName={pdfDetails[0] && pdfDetails[0].Name} pdfName={pdfDetails[0] && pdfDetails[0].Name}
setSuccessEmail={setSuccessEmail} setSuccessEmail={setSuccessEmail}
@@ -1332,7 +1311,7 @@ function SignYourSelf() {
maxHeight: window.innerHeight - 70 + "px", maxHeight: window.innerHeight - 70 + "px",
backgroundColor: "white" backgroundColor: "white"
}} }}
className="autoSignScroll" className="overflow-y-auto hide-scrollbar"
> >
{!isCompleted ? ( {!isCompleted ? (
<div> <div>
@@ -1344,7 +1323,6 @@ function SignYourSelf() {
handleDivClick={handleDivClick} handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave} handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign} isDragSign={isDragSign}
themeColor={themeColor}
dragStamp={dragStamp} dragStamp={dragStamp}
dragRef={dragRef} dragRef={dragRef}
isDragStamp={isDragStamp} isDragStamp={isDragStamp}
@@ -1365,31 +1343,22 @@ function SignYourSelf() {
</div> </div>
)} )}
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={validateAlert} isOpen={validateAlert}
title={"Validation alert"} title={"Validation alert"}
handleClose={() => { handleClose={() => {
setValidateAlert(false); setValidateAlert(false);
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="p-[20px] h-full">
<p> <p>
The input does not meet the criteria set by the regular expression. The input does not meet the criteria set by the regular expression.
</p> </p>
<div <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => setValidateAlert(false)} onClick={() => setValidateAlert(false)}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-ghost shadow-md"
> >
Close Close
</button> </button>
+44 -74
View File
@@ -3,13 +3,13 @@ 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 { isEnableSubscription, themeColor } from "../constant/const"; import { isEnableSubscription } 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";
import WidgetComponent from "../components/pdf/WidgetComponent"; import WidgetComponent from "../components/pdf/WidgetComponent";
import Tour from "reactour"; import Tour from "reactour";
import Loader from "../primitives/LoaderWithMsg"; import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError"; import HandleError from "../primitives/HandleError";
import SignerListPlace from "../components/pdf/SignerListPlace"; import SignerListPlace from "../components/pdf/SignerListPlace";
import Header from "../components/pdf/PdfHeader"; import Header from "../components/pdf/PdfHeader";
@@ -36,6 +36,7 @@ import AddRoleModal from "../components/pdf/AddRoleModal";
import PlaceholderCopy from "../components/pdf/PlaceholderCopy"; import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
import TourContentWithBtn from "../primitives/TourContentWithBtn"; import TourContentWithBtn from "../primitives/TourContentWithBtn";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption"; import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import Parse from "parse";
const TemplatePlaceholder = () => { const TemplatePlaceholder = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { templateId } = useParams(); const { templateId } = useParams();
@@ -704,35 +705,29 @@ const TemplatePlaceholder = () => {
Name: pdfDetails[0]?.Name || "", Name: pdfDetails[0]?.Name || "",
Note: pdfDetails[0]?.Note || "", Note: pdfDetails[0]?.Note || "",
Description: pdfDetails[0]?.Description || "", Description: pdfDetails[0]?.Description || "",
SendinOrder: pdfDetails[0]?.SendinOrder || false SendinOrder: pdfDetails[0]?.SendinOrder || false,
AutomaticReminders: pdfDetails[0]?.AutomaticReminders,
RemindOnceInEvery: parseInt(pdfDetails[0]?.RemindOnceInEvery),
NextReminderDate: pdfDetails[0]?.NextReminderDate
}; };
const updateTemplate = new Parse.Object("contracts_Template");
updateTemplate.id = templateId;
for (const key in data) {
updateTemplate.set(key, data[key]);
}
await updateTemplate.save(null, {
sessionToken: localStorage.getItem("accesstoken")
});
await axios setIsCreateDocModal(true);
.put( setIsMailSend(true);
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( const loadObj = {
"_appName" isLoad: false
)}_Template/${templateId}`, };
data, setIsLoading(loadObj);
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then(() => {
setIsCreateDocModal(true);
setIsMailSend(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
})
.catch((err) => {
console.log("axois err ", err);
});
} catch (e) { } catch (e) {
setIsLoading(false);
alert("Something went wrong, please try again later.");
console.log("error", e); console.log("error", e);
} }
} else { } else {
@@ -1207,17 +1202,19 @@ const TemplatePlaceholder = () => {
setIsCheckbox(false); setIsCheckbox(false);
}; };
console.log("signerpos", signerPos);
return ( return (
<div> <div>
<Title title={"Template"} /> <Title title={"Template"} />
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? ( {isLoading.isLoad ? (
<Loader isLoading={isLoading} /> <LoaderWithMsg isLoading={isLoading} />
) : handleError ? ( ) : handleError ? (
<HandleError handleError={handleError} /> <HandleError handleError={handleError} />
) : ( ) : (
<div className="signatureContainer" ref={divRef}> <div
className="op-card overflow-hidden flex flex-row justify-between bg-base-300 relative"
ref={divRef}
>
{/* this component used for UI interaction and show their functionality */} {/* this component used for UI interaction and show their functionality */}
{!checkTourStatus && ( {!checkTourStatus && (
//this tour component used in your html component where you want to put //this tour component used in your html component where you want to put
@@ -1260,23 +1257,21 @@ const TemplatePlaceholder = () => {
> >
{/* this modal is used show alert set placeholder for all signers before send mail */} {/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={isSendAlert} isOpen={isSendAlert}
title={"Fields required"} title={"Fields required"}
handleClose={() => setIsSendAlert(false)} handleClose={() => setIsSendAlert(false)}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px]">
<p>Please add at least one signature field for all roles.</p> <p>Please add at least one signature field for all roles.</p>
</div> </div>
</ModalUi> </ModalUi>
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={!IsReceipent} isOpen={!IsReceipent}
title={"Roles"} title={"Roles"}
handleClose={() => setIsReceipent(true)} handleClose={() => setIsReceipent(true)}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px] text-center font-medium">
<p>Please add a role</p> <p>Please add roles first</p>
</div> </div>
</ModalUi> </ModalUi>
{/* this modal is used show send mail message and after send mail success message */} {/* this modal is used show send mail message and after send mail success message */}
@@ -1285,32 +1280,18 @@ const TemplatePlaceholder = () => {
title={"Create Document"} title={"Create Document"}
handleClose={() => setIsCreateDocModal(false)} handleClose={() => setIsCreateDocModal(false)}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px]">
<p> <p>
Do you want to create a document using the template you just Do you want to create a document using the template you just
created ? created ?
</p> </p>
<div <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
{currentEmail.length > 0 && ( {currentEmail.length > 0 && (
<> <>
<button <button
onClick={() => { onClick={() => handleCreateDocModal()}
handleCreateDocModal();
}}
style={{
background: themeColor,
color: "white"
}}
type="button" type="button"
className="finishBtn" className="op-btn op-btn-primary"
> >
Yes Yes
</button> </button>
@@ -1319,7 +1300,7 @@ const TemplatePlaceholder = () => {
setIsCreateDocModal(false); setIsCreateDocModal(false);
}} }}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-secondary ml-2"
> >
No No
</button> </button>
@@ -1327,32 +1308,21 @@ const TemplatePlaceholder = () => {
)} )}
</div> </div>
</ModalUi> </ModalUi>
{isCreateDoc && <Loader isLoading={isLoading} />} {isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
<ModalUi <ModalUi
headerColor={"#dc3545"}
isOpen={isShowEmail} isOpen={isShowEmail}
title={"signers alert"} title={"signers alert"}
handleClose={() => { handleClose={() => {
setIsShowEmail(false); setIsShowEmail(false);
}} }}
> >
<div style={{ height: "100%", padding: 20 }}> <div className="h-full p-[20px]">
<p>Please select signer for add placeholder!</p> <p>Please select signer for add placeholder!</p>
<div <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button <button
onClick={() => { onClick={() => setIsShowEmail(false)}
setIsShowEmail(false);
}}
type="button" type="button"
className="finishBtn cancelBtn" className="op-btn op-btn-primary"
> >
Ok Ok
</button> </button>
@@ -1402,7 +1372,7 @@ const TemplatePlaceholder = () => {
// signerObjId={signerObjId} // signerObjId={signerObjId}
Id={uniqueId} Id={uniqueId}
/> />
{/* pdf header which contain funish back button */} {/* pdf header which contain finish, back button */}
<Header <Header
completeBtnTitle={"Save"} completeBtnTitle={"Save"}
isPlaceholder={true} isPlaceholder={true}
@@ -1505,10 +1475,10 @@ const TemplatePlaceholder = () => {
</div> </div>
) : ( ) : (
<div> <div>
<div className="signerComponent"> <div className="hidden md:block w-[180px] h-full bg-base-100">
<div <div
style={{ maxHeight: window.innerHeight - 70 + "px" }} style={{ maxHeight: window.innerHeight - 70 + "px" }}
className="autoSignScroll" className="overflow-y-auto hide-scrollbar"
> >
<SignerListPlace <SignerListPlace
isMailSend={isMailSend} isMailSend={isMailSend}
+181 -132
View File
@@ -1,4 +1,8 @@
import React, { useState, useEffect } from "react"; import React, {
useState,
useEffect
// useRef
} from "react";
import { Navigate, useNavigate } from "react-router-dom"; import { Navigate, useNavigate } from "react-router-dom";
import Parse from "parse"; import Parse from "parse";
import { SaveFileSize } from "../constant/saveFileSize"; import { SaveFileSize } from "../constant/saveFileSize";
@@ -8,10 +12,11 @@ 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, rejectBtn, submitBtn } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribed, handleSendOTP } from "../constant/Utils"; import { checkIsSubscribed, handleSendOTP } from "../constant/Utils";
import Upgrade from "../primitives/Upgrade"; import Upgrade from "../primitives/Upgrade";
import ModalUi from "../primitives/ModalUi"; import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
function UserProfile() { function UserProfile() {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -27,6 +32,10 @@ function UserProfile() {
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 [isSubscribe, setIsSubscribe] = useState(false);
// const [publicUserName, setPublicUserName] = useState(
// extendUser && extendUser?.[0]?.UserName
// );
// const previousPublicUserName = useRef(publicUserName);
const [company, setCompany] = useState( const [company, setCompany] = useState(
extendUser && extendUser?.[0]?.Company extendUser && extendUser?.[0]?.Company
); );
@@ -37,6 +46,7 @@ function UserProfile() {
const [otp, setOtp] = useState(""); const [otp, setOtp] = useState("");
const [otpLoader, setOtpLoader] = useState(false); const [otpLoader, setOtpLoader] = useState(false);
const [isEmailVerified, setIsEmailVerified] = useState(false); const [isEmailVerified, setIsEmailVerified] = useState(false);
// const [userNameError, setUserNameError] = useState("");
useEffect(() => { useEffect(() => {
getUserDetail(); getUserDetail();
}, []); }, []);
@@ -74,46 +84,72 @@ function UserProfile() {
} }
} }
}; };
//function to check public username already exist
// const handleCheckPublicUserName = async () => {
// try {
// const res = await Parse.Cloud.run("getpublicusername", {
// username: publicUserName
// });
// if (res) {
// setIsLoader(false);
// setUserNameError("user name already exist");
// setTimeout(() => {
// setUserNameError("");
// }, 3000);
// return res;
// }
// } catch (e) {
// console.log("error in getpublicusername cloud function");
// }
// };
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
setIsLoader(true); let phn = Phone,
let phn = Phone; res = "";
//condition to call cloud function when user change publicUserName
try { // if (previousPublicUserName.current !== publicUserName) {
const tour = Parse.Object.extend("_User"); // res = await handleCheckPublicUserName();
const query = new Parse.Query(tour); // }
if (!res) {
await query.get(UserProfile.objectId).then((object) => { setIsLoader(true);
object.set("name", name); try {
object.set("ProfilePic", Image); const userQuery = Parse.Object.extend("_User");
object.set("phone", phn); const query = new Parse.Query(userQuery);
await query.get(UserProfile.objectId).then((object) => {
object.save().then( object.set("name", name);
async (response) => { object.set("ProfilePic", Image);
if (response) { object.set("phone", phn || "");
let res = response.toJSON(); object.save().then(
let rr = JSON.stringify(res); async (response) => {
localStorage.setItem("UserInformation", rr); if (response) {
SetName(res.name); let res = response.toJSON();
SetPhone(res.phone); let rr = JSON.stringify(res);
setImage(res.ProfilePic); localStorage.setItem("UserInformation", rr);
localStorage.setItem("username", res.name); SetName(res.name);
localStorage.setItem("profileImg", res.ProfilePic); SetPhone(res?.phone || "");
await updateExtUser({ Name: res.name, Phone: res.phone }); setImage(res.ProfilePic);
alert("Profile updated successfully."); localStorage.setItem("username", res.name);
setEditMode(false); localStorage.setItem("profileImg", res.ProfilePic);
navigate("/dashboard/35KBoSgoAK"); await updateExtUser({
Name: res.name,
Phone: res?.phone || ""
});
alert("Profile updated successfully.");
setEditMode(false);
setIsLoader(false);
//navigate("/dashboard/35KBoSgoAK");
}
},
(error) => {
alert("Something went wrong.");
console.error("Error while updating tour", error);
setIsLoader(false);
} }
}, );
(error) => { });
alert("Something went wrong."); } catch (error) {
console.error("Error while updating tour", error); console.log("err", error);
setIsLoader(false); }
}
);
});
} catch (error) {
console.log("err", error);
} }
}; };
@@ -122,14 +158,15 @@ function UserProfile() {
const extClass = localStorage.getItem("extended_class"); const extClass = localStorage.getItem("extended_class");
const extData = JSON.parse(localStorage.getItem("Extand_Class")); const extData = JSON.parse(localStorage.getItem("Extand_Class"));
const ExtUserId = extData[0].objectId; const ExtUserId = extData[0].objectId;
const body = { const body = {
Phone: obj.Phone, Phone: obj?.Phone || "",
Name: obj.Name, Name: obj.Name,
HeaderDocId: isDisableDocId, HeaderDocId: isDisableDocId,
JobTitle: jobTitle, JobTitle: jobTitle,
Company: company Company: company
// UserName: publicUserName || ""
}; };
await axios.put( await axios.put(
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId, parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
body, body,
@@ -147,7 +184,6 @@ function UserProfile() {
const json = JSON.parse(JSON.stringify([res])); const json = JSON.parse(JSON.stringify([res]));
const extRes = JSON.stringify(json); const extRes = JSON.stringify(json);
localStorage.setItem("Extand_Class", extRes); localStorage.setItem("Extand_Class", extRes);
// console.log("updateRes ", updateRes); // console.log("updateRes ", updateRes);
}; };
@@ -241,29 +277,45 @@ function UserProfile() {
setOtpLoader(false); setOtpLoader(false);
alert("OTP sent on you email"); alert("OTP sent on you email");
}; };
//function to handle onchange username and restrict 6-characters username for free users
// const handleOnchangeUserName = (e) => {
// const value = e.target.value;
// if (value.length > 6 && !isSubscribe) {
// setUserNameError("Please upgrade to allow more than 6 characters.");
// setTimeout(() => {
// setUserNameError("");
// }, 2000);
// } else {
// setPublicUserName(e.target.value);
// }
// };
const handleCancel = () => {
setEditMode(false);
SetName(localStorage.getItem("username"));
SetPhone(UserProfile && UserProfile.phone);
setImage(localStorage.getItem("profileImg"));
// setPublicUserName(extendUser && extendUser?.[0]?.UserName);
setCompany(extendUser && extendUser?.[0]?.Company);
setJobTitle(extendUser?.[0]?.JobTitle);
setIsDisableDocId(extendUser?.[0]?.HeaderDocId);
};
return ( return (
<React.Fragment> <React.Fragment>
<Title title={"Profile"} /> <Title title={"Profile"} />
{isLoader ? ( {isLoader ? (
<div <div className="h-[100vh] flex justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<div className="flex justify-center items-center w-full"> <div className="flex justify-center items-center w-full relative">
<div className="bg-white flex flex-col justify-center shadow rounded w-[450px]"> {/* {userNameError && (
<div
className={`z-[1000] fixed top-[50%] transform border-[1px] text-sm border-[#f0a8a8] bg-[#f4bebe] text-[#c42121] rounded py-[.75rem] px-[1.25rem]`}
>
{userNameError}
</div>
)} */}
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded-xl w-[450px]">
<div className="flex flex-col justify-center items-center my-4"> <div className="flex flex-col justify-center items-center my-4">
<div className="w-[200px] h-[200px] overflow-hidden rounded-full"> <div className="w-[200px] h-[200px] overflow-hidden rounded-full">
<img <img
@@ -275,7 +327,7 @@ function UserProfile() {
{editmode && ( {editmode && (
<input <input
type="file" type="file"
className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded" className="op-file-input op-file-input-bordered op-file-input-sm max-w-[270px] mt-4 text-sm"
accept="image/png, image/gif, image/jpeg" accept="image/png, image/gif, image/jpeg"
onChange={(e) => { onChange={(e) => {
let files = e.target.files; let files = e.target.files;
@@ -301,7 +353,7 @@ function UserProfile() {
<ul className="w-full flex flex-col p-2 text-sm"> <ul className="w-full flex flex-col p-2 text-sm">
<li <li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${ className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2" editmode ? "py-1.5" : "py-2"
}`} }`}
> >
<span className="font-semibold">Name:</span>{" "} <span className="font-semibold">Name:</span>{" "}
@@ -309,7 +361,7 @@ function UserProfile() {
<input <input
type="text" type="text"
value={name} value={name}
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-sm"
onChange={(e) => SetName(e.target.value)} onChange={(e) => SetName(e.target.value)}
/> />
) : ( ) : (
@@ -318,14 +370,14 @@ function UserProfile() {
</li> </li>
<li <li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${ className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2" editmode ? "py-1.5" : "py-2"
}`} }`}
> >
<span className="font-semibold">Phone:</span>{" "} <span className="font-semibold">Phone:</span>{" "}
{editmode ? ( {editmode ? (
<input <input
type="text" type="text"
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-sm"
onChange={(e) => SetPhone(e.target.value)} onChange={(e) => SetPhone(e.target.value)}
value={Phone} value={Phone}
/> />
@@ -339,7 +391,7 @@ function UserProfile() {
</li> </li>
<li <li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${ className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2" editmode ? "py-1.5" : "py-2"
}`} }`}
> >
<span className="font-semibold">Company:</span>{" "} <span className="font-semibold">Company:</span>{" "}
@@ -347,7 +399,7 @@ function UserProfile() {
<input <input
type="text" type="text"
value={company} value={company}
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-sm"
onChange={(e) => setCompany(e.target.value)} onChange={(e) => setCompany(e.target.value)}
/> />
) : ( ) : (
@@ -356,7 +408,7 @@ function UserProfile() {
</li> </li>
<li <li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${ className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2" editmode ? "py-1.5" : "py-2"
}`} }`}
> >
<span className="font-semibold">Job title:</span>{" "} <span className="font-semibold">Job title:</span>{" "}
@@ -364,7 +416,7 @@ function UserProfile() {
<input <input
type="text" type="text"
value={jobTitle} value={jobTitle}
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-sm"
onChange={(e) => setJobTitle(e.target.value)} onChange={(e) => setJobTitle(e.target.value)}
/> />
) : ( ) : (
@@ -390,6 +442,37 @@ function UserProfile() {
)} )}
</span> </span>
</li> </li>
{/* {isEnableSubscription && (
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
<span className="font-semibold">
Public profile :{" "}
<Tooltip
message={`this is your public URL. Copy or share it
with the signer, and you will be able to see
all your publicly set templates.`}
/>
</span>
<div className="flex text-xs items-center">
<span>opensign-me.vercel.app/</span>
{editmode ? (
<input
onChange={handleOnchangeUserName}
value={publicUserName}
disabled={!editmode}
placeholder="enter user name"
className="op-input op-input-bordered focus:outline-none hover:border-base-content op-input-xs"
/>
) : (
<input
value={extendUser?.[0]?.UserName}
disabled
placeholder="enter user name"
className="op-input op-input-bordered op-input-xs"
/>
)}
</div>
</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 <span
@@ -404,28 +487,23 @@ function UserProfile() {
url={ url={
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid" "https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
} }
isSubscribe={isSubscribe} />
/>{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />} {!isSubscribe && isEnableSubscription && <Upgrade />}
</span>{" "} </span>
<label <label
className={ className={`${
isSubscribe || !isEnableSubscription isSubscribe || !isEnableSubscription
? `${ ? `${editmode ? "cursor-pointer" : ""}`
editmode ? "cursor-pointer" : "" : "pointer-events-none opacity-50"
} relative inline-flex items-center mb-0` } relative block 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}
type="checkbox"
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white"
checked={isDisableDocId} checked={isDisableDocId}
onChange={handleDisableDocId} onChange={handleDisableDocId}
type="checkbox"
value=""
className="sr-only peer"
/> />
<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>
{!isEnableSubscription && ( {!isEnableSubscription && (
@@ -437,44 +515,29 @@ function UserProfile() {
)} )}
</li> </li>
</ul> </ul>
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4"> <div className="flex justify-center gap-2 pt-2 pb-3 md:pt-3 md:pb-4">
{editmode ? (
<button
type="button"
onClick={handleSubmit}
className="rounded shadow focus:outline-none border-[2px] border-[#15b4e9] bg-white text-[#15b4e9] px-4 py-2 mr-4"
>
Save
</button>
) : (
<button
type="button"
onClick={() => {
setEditMode(true);
}}
className="rounded shadow focus:outline-none text-white bg-[#e7505a] px-4 py-2 mr-4"
>
Edit
</button>
)}
<button <button
type="button" type="button"
onClick={() => { onClick={(e) =>
if (editmode) { editmode ? handleSubmit(e) : setEditMode(true)
setEditMode(false); }
} else { className="op-btn op-btn-primary"
navigate("/changepassword"); >
} {editmode ? "Save" : "Edit"}
}} </button>
className={`rounded shadow focus:outline-none text-white bg-[#3598dc] ${ <button
editmode ? "px-4 py-2 " : "p-2" type="button"
onClick={() =>
editmode ? handleCancel() : navigate("/changepassword")
}
className={`op-btn ${
editmode ? "op-btn-ghost" : "op-btn-secondary"
}`} }`}
> >
{editmode ? "Cancel" : "Change Password"} {editmode ? "Cancel" : "Change Password"}
</button> </button>
</div> </div>
</div> </div>
{isVerifyModal && ( {isVerifyModal && (
<ModalUi <ModalUi
isOpen isOpen
@@ -482,43 +545,29 @@ function UserProfile() {
handleClose={handleCloseVerifyModal} handleClose={handleCloseVerifyModal}
> >
{otpLoader ? ( {otpLoader ? (
<div <div className="h-[150px] flex justify-center items-center">
style={{ <Loader />
height: "150px",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<form onSubmit={(e) => handleVerifyEmail(e)}> <form onSubmit={(e) => handleVerifyEmail(e)}>
<div className="px-6 py-3"> <div className="px-6 py-3 text-base-content">
<label className="mb-2">Enter OTP</label> <label className="mb-2">Enter OTP</label>
<input <input
required required
type="tel" type="tel"
pattern="[0-9]{4}" pattern="[0-9]{4}"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
placeholder="Enter OTP received over email" placeholder="Enter OTP received over email"
value={otp} value={otp}
onChange={(e) => setOtp(e.target.value)} onChange={(e) => setOtp(e.target.value)}
/> />
</div> </div>
<hr /> <div className="px-6 mb-3">
<div className="px-6 my-3"> <button type="submit" className="op-btn op-btn-primary">
<button type="submit" className={submitBtn}>
Verify Verify
</button> </button>
<button <button
className={`${rejectBtn} ml-2`} className="op-btn op-btn-secondary ml-2"
onClick={(e) => handleResend(e)} onClick={(e) => handleResend(e)}
> >
Resend Resend
+19 -28
View File
@@ -4,11 +4,12 @@ import axios from "axios";
import { useNavigate } from "react-router-dom"; 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 { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribed, 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";
import Loader from "../primitives/Loader";
function Webhook() { function Webhook() {
const navigation = useNavigate(); const navigation = useNavigate();
@@ -97,28 +98,15 @@ function Webhook() {
return ( return (
<React.Fragment> <React.Fragment>
<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 className="h-[100vh] flex justify-center items-center">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
) : ( ) : (
<div className="bg-white flex flex-col justify-center shadow rounded"> <div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded">
{!isEnableSubscription && <PremiumAlertHeader />} {!isEnableSubscription && <PremiumAlertHeader />}
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}> <h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign Webhook{" "} OpenSign Webhook{" "}
@@ -146,14 +134,14 @@ function Webhook() {
<button <button
type="button" type="button"
onClick={handleModal} 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" className="op-btn op-btn-primary "
> >
{webhook ? "Update Webhook" : "Add Webhook"} {webhook ? "Update Webhook" : "Add Webhook"}
</button> </button>
</li> </li>
</ul> </ul>
<div className="flex items-center justify-center "> <div className="flex items-center justify-center ">
<button <button
type="button" type="button"
onClick={() => onClick={() =>
@@ -161,7 +149,7 @@ 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] my-2 border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none" className="op-btn op-btn-secondary my-2"
> >
View Docs View Docs
</button> </button>
@@ -203,24 +191,27 @@ function Webhook() {
> >
{error && <Alert type="danger">{error}</Alert>} {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-base-content">
<label className="text-sm ml-2">Webhook</label> <label className="text-sm ml-2">Webhook</label>
<input <input
value={webhook} value={webhook}
onChange={(e) => setWebhook(e.target.value)} onChange={(e) => setWebhook(e.target.value)}
placeholder="Enter webhook url" placeholder="Enter webhook url"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<hr className="bg-[#ccc] mt-4 " /> <hr className="bg-[#ccc] mt-3" />
<div className="flex items-center mt-3 gap-2 text-white"> <div className="flex items-center mt-3 gap-2">
<button <button
onClick={handleSubmit} onClick={handleSubmit}
className={submitBtn + "ml-[2px]"} className="op-btn op-btn-primary ml-[2px]"
> >
Yes Yes
</button> </button>
<button onClick={handleModal} className={rejectBtn}> <button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No No
</button> </button>
</div> </div>
+16
View File
@@ -0,0 +1,16 @@
// below code is used to handle undefined Promise.withResolvers for safari
if (typeof Promise.withResolvers === "undefined") {
Promise.withResolvers = function () {
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
};
}
// Usage:
// const { promise, resolve, reject } = Promise.withResolvers()
// console.log(promise, resolve, reject) // Promise { <pending> } [Function (anonymous)] [Function (anonymous)]
// ... Do something async and then call resolve or reject!
@@ -2,7 +2,8 @@ import React, { useState, useEffect } from "react";
import Parse from "parse"; import Parse from "parse";
import axios from "axios"; import axios from "axios";
import "../styles/AddUser.css"; import "../styles/AddUser.css";
const AddUser = (props) => { import Loader from "./Loader";
const AddContact = (props) => {
const [name, setName] = useState(""); const [name, setName] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
@@ -21,7 +22,7 @@ const AddUser = (props) => {
); );
if (savedUserDetails && addYourself) { if (savedUserDetails && addYourself) {
setName(savedUserDetails.name); setName(savedUserDetails.name);
setPhone(savedUserDetails.phone); setPhone(savedUserDetails?.phone || "");
setEmail(savedUserDetails.email); setEmail(savedUserDetails.email);
} }
}, [addYourself]); }, [addYourself]);
@@ -50,7 +51,9 @@ const AddUser = (props) => {
try { try {
const contactQuery = new Parse.Object("contracts_Contactbook"); const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name); contactQuery.set("Name", name);
contactQuery.set("Phone", phone); if (phone) {
contactQuery.set("Phone", phone);
}
contactQuery.set("Email", email); contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest"); contactQuery.set("UserRole", "contracts_Guest");
@@ -68,8 +71,10 @@ const AddUser = (props) => {
_user.set("name", name); _user.set("name", name);
_user.set("username", email); _user.set("username", email);
_user.set("email", email); _user.set("email", email);
_user.set("phone", phone); _user.set("password", email);
_user.set("password", phone); if (phone) {
_user.set("phone", phone);
}
const user = await _user.save(); const user = await _user.save();
if (user) { if (user) {
@@ -191,40 +196,36 @@ const AddUser = (props) => {
}; };
return ( return (
<div className="addusercontainer"> <div className="h-full px-[20px] py-[10px]">
{isLoader && ( {isLoader && (
<div className="loaderdiv"> <div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30">
<div <Loader />
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
)} )}
<div className="form-wrapper"> <div className="w-full mx-auto p-[8px]">
<div style={{ fontSize: 14, fontWeight: "700" }}>Add User</div> <div className="text-[14px] font-[700]">Add User</div>
{isUserExist && ( {isUserExist && (
<div className="form-section"> <div className="mb-[0.75rem] flex items-center mt-1">
<input <input
type="checkbox" type="checkbox"
id="addYourself" id="addYourself"
checked={addYourself} checked={addYourself}
onChange={handleAddYourselfChange} onChange={handleAddYourselfChange}
className="form-checkbox" className="op-checkbox op-checkbox-sm"
/> />
<label htmlFor="addYourself" className="checkbox-label "> <label
htmlFor="addYourself"
className="ml-[0.5rem] text-base-content mb-0"
>
Add Yourself Add Yourself
</label> </label>
</div> </div>
)} )}
<form onSubmit={handleSubmit}> <form className="text-base-content" onSubmit={handleSubmit}>
<div className="form-section"> <div className="mb-[0.75rem]">
<label htmlFor="name" style={{ fontSize: 13 }}> <label htmlFor="name" className="text-[13px]">
Name Name
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[13px] text-[red]"> *</span>
</label> </label>
<input <input
type="text" type="text"
@@ -233,48 +234,46 @@ const AddUser = (props) => {
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
required required
disabled={addYourself} disabled={addYourself}
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="form-section"> <div className="mb-[0.75rem]">
<label htmlFor="email" style={{ fontSize: 13 }}> <label htmlFor="email" className="text-[13px]">
Email Email
<span style={{ color: "red", fontSize: 13 }}> *</span> <span className="text-[13px] text-[red]"> *</span>
</label> </label>
<input <input
type="email" type="email"
id="email" id="email"
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value?.toLowerCase())}
required required
disabled={addYourself} disabled={addYourself}
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs lowercase"
/> />
</div> </div>
<div className="form-section"> <div className="mb-[0.75rem]">
<label htmlFor="phone" style={{ fontSize: 13 }}> <label htmlFor="phone" className="text-[13px]">
Phone Phone
<span style={{ color: "red", fontSize: 13 }}> *</span>
</label> </label>
<input <input
type="text" type="text"
id="phone" id="phone"
value={phone} value={phone}
onChange={(e) => setPhone(e.target.value)} onChange={(e) => setPhone(e.target.value)}
required
disabled={addYourself} disabled={addYourself}
className="addUserInput" className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/> />
</div> </div>
<div className="buttoncontainer"> <div className="mt-6 flex justify-start gap-2">
<button type="submit" className="submitbutton"> <button type="submit" className="op-btn op-btn-primary">
Submit Submit
</button> </button>
<button <button
type="button" type="button"
onClick={() => handleReset()} onClick={() => handleReset()}
className="resetbutton" className="op-btn op-btn-secondary"
> >
Reset Reset
</button> </button>
@@ -285,4 +284,4 @@ const AddUser = (props) => {
); );
}; };
export default AddUser; export default AddContact;
+12 -12
View File
@@ -5,25 +5,25 @@ const Alert = ({ children, type }) => {
function theme(color) { function theme(color) {
switch (color) { switch (color) {
case "success": case "success":
return "border-[#c3e6cb] bg-[#d4edda] text-[#155724]"; return "op-alert-success";
case "info": case "info":
return "border-[#adcdeb] bg-[#c1daf0] text-[#153756]"; return "op-alert-info";
case "danger": case "danger":
return "border-[#f0a8a8] bg-[#f4bebe] text-[#c42121]"; return "op-alert-error";
case "warning":
return "op-alert-warning";
default: default:
return "border-[#d6d6d6] bg-[#d9d9d9] text-[#575757]"; return "";
} }
} }
return ( return (
<> children && (
{children && ( <div className="z-[1000] fixed top-20 left-1/2 transform -translate-x-1/2 text-sm">
<div <div className={`op-alert ${textcolor}`}>
className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] z-50`} <span>{children}</span>
>
{children}
</div> </div>
)} </div>
</> )
); );
}; };
File diff suppressed because it is too large Load Diff
+2 -9
View File
@@ -2,15 +2,8 @@ import React from "react";
function HandleError({ handleError }) { function HandleError({ handleError }) {
return ( return (
<div <div className="flex justify-center items-center h-[100vh]">
style={{ <span className="text-[20px] text-[gray]">{handleError}</span>
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh"
}}
>
<span style={{ fontSize: "20px", color: "gray" }}>{handleError}</span>
</div> </div>
); );
} }
+3 -15
View File
@@ -1,24 +1,12 @@
import React, { Suspense } from "react"; import React, { Suspense } from "react";
import Loader from "./Loader";
const LazyPage = ({ Page }) => { const LazyPage = ({ Page }) => {
return ( return (
<Suspense <Suspense
fallback={ fallback={
<div <div className="flex justify-center items-center h-[100vh]">
style={{ <Loader />
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div> </div>
} }
> >
+3 -27
View File
@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import SelectSigners from "../components/shared/fields/SelectSigners"; import SelectSigners from "../components/shared/fields/SelectSigners";
import AddUser from "./AddUser"; import AddContact from "./AddContact";
import ModalUi from "./ModalUi"; import ModalUi from "./ModalUi";
const LinkUserModal = (props) => { const LinkUserModal = (props) => {
@@ -18,32 +18,8 @@ const LinkUserModal = (props) => {
closePopup={props.closePopup} closePopup={props.closePopup}
signersData={props?.signersData} signersData={props?.signersData}
/> />
<div <div className="op-divider text-base-content mx-[25%] my-1">or</div>
style={{ <AddContact details={props.handleAddUser} closePopup={props.closePopup} />
display: "flex",
alignItems: "center",
gap: 5,
margin: "0 30%",
color: "#808080"
}}
>
<span
style={{
height: 1,
width: "100%",
backgroundColor: "#ccc"
}}
></span>
<span>or</span>
<span
style={{
height: 1,
width: "100%",
backgroundColor: "#ccc"
}}
></span>
</div>
<AddUser details={props.handleAddUser} closePopup={props.closePopup} />
</ModalUi> </ModalUi>
); );
}; };
+9
View File
@@ -0,0 +1,9 @@
import React from "react";
const Loader = () => {
return (
<div className="op-loading op-loading-infinity w-[5rem] text-accent"></div>
);
};
export default Loader;
+7 -20
View File
@@ -1,27 +1,14 @@
import React from "react"; import React from "react";
import loader from "../assets/images/loader2.gif"; import Loader from "./Loader";
function Loader({ isLoading }) { function LoaderWithMsg({ isLoading }) {
return ( return (
<div <div className="flex flex-col justify-center items-center h-[100vh]">
style={{ {/* <img alt="loader" src={loader} className="w-[80px] h-[80px]" /> */}
display: "flex", <Loader />
justifyContent: "center", <span className="text-[13px] text-base-cotent">{isLoading.message}</span>
alignItems: "center",
height: "100vh",
flexDirection: "column"
}}
>
<img
alt="no img"
src={loader}
style={{ width: "80px", height: "80px" }}
/>
<span style={{ fontSize: "13px", color: "gray" }}>
{isLoading.message}
</span>
</div> </div>
); );
} }
export default Loader; export default LoaderWithMsg;
+15 -19
View File
@@ -6,39 +6,35 @@ const ModalUi = ({
children, children,
title, title,
isOpen, isOpen,
headColor,
handleClose, handleClose,
showHeader = true, showHeader = true,
showClose = true, showClose = true,
styleClass, reduceWidth,
showHeaderMessage showHeaderMessage
}) => { }) => {
return ( return (
<> <>
{isOpen && ( {isOpen && (
<div className="fixed z-[999] 2 top-0 left-0 w-[100%] h-[100%] bg-black bg-opacity-[75%]"> <dialog className="op-modal op-modal-open">
<div <div
className={ className={`${
styleClass reduceWidth || "md:min-w-[500px]"
? styleClass } op-modal-box p-0 max-h-90 min-w-[90%] overflow-y-auto hide-scrollbar text-sm`}
: "fixed z-[1000] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-sm bg-white rounded shadow-md max-h-90 min-w-[90%] md:min-w-[500px] overflow-y-auto hide-scrollbar"
}
> >
{showHeader && ( {showHeader && (
<div <>
className="flex justify-between rounded-t items-center py-[15px] px-[20px] text-white" <h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
style={{ background: headColor ? headColor : "#32a3ac" }} {title}
> </h3>
<div className="text-[1.2rem] font-normal">{title}</div>
{showClose && ( {showClose && (
<div <button
className="text-[1.5rem] cursor-pointer" className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2"
onClick={() => handleClose && handleClose()} onClick={() => handleClose && handleClose()}
> >
&times;
</div> </button>
)} )}
</div> </>
)} )}
{!isEnableSubscription && showHeaderMessage && ( {!isEnableSubscription && showHeaderMessage && (
<PremiumAlertHeader <PremiumAlertHeader
@@ -49,7 +45,7 @@ const ModalUi = ({
)} )}
<div>{children}</div> <div>{children}</div>
</div> </div>
</div> </dialog>
)} )}
</> </>
); );
@@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import "../styles/signature.css"; import "../styles/signature.css";
import { rejectBtn } from "../constant/const";
function CustomModal({ function CustomModal({
show, show,
@@ -12,12 +11,12 @@ function CustomModal({
}) { }) {
return ( return (
show && ( show && (
<div className="bg-black bg-opacity-[75%] absolute z-[999] flex flex-col items-center justify-center w-full h-full rounded"> <dialog className="op-modal op-modal-open absolute z-[1999]">
<div className="bg-white rounded outline-none md:w-[40%] w-[80%]"> <div className="w-[80%] md:w-[40%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<div className="bg-[#de4337] text-white p-[10px] rounded-t"> <h3 className="text-[#de4337] font-bold text-lg pt-[15px] px-[20px]">
{headMsg && headMsg} {headMsg && headMsg}
</div> </h3>
<div className="p-[15px]"> <div className="p-[10px] px-[20px]">
<p className="text-[15px]">{bodyMssg && bodyMssg}</p> <p className="text-[15px]">{bodyMssg && bodyMssg}</p>
</div> </div>
{footerMessage && ( {footerMessage && (
@@ -25,8 +24,7 @@ function CustomModal({
<div className="h-[1px] bg-[#9f9f9f] w-full"></div> <div className="h-[1px] bg-[#9f9f9f] w-full"></div>
<div className="m-[15px] "> <div className="m-[15px] ">
<button <button
className={`${rejectBtn} text-white mr-2`} className="op-btn op-btn-primary mr-2"
style={{ background: "#de4337" }}
type="button" type="button"
onClick={() => declineDoc()} onClick={() => declineDoc()}
> >
@@ -34,7 +32,7 @@ function CustomModal({
</button> </button>
<button <button
type="button" type="button"
className={rejectBtn} className="op-btn op-btn-secondary"
onClick={() => setIsDecline({ isDeclined: false })} onClick={() => setIsDecline({ isDeclined: false })}
> >
Close Close
@@ -43,7 +41,7 @@ function CustomModal({
</> </>
)} )}
</div> </div>
</div> </dialog>
) )
); );
} }
+2 -10
View File
@@ -1,17 +1,9 @@
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";
import { isEnableSubscription } from "../constant/const"; const Tooltip = ({ id, message, url, iconColor }) =>
const Tooltip = ({ id, message, url, iconColor, isSubscribe }) =>
url ? ( url ? (
<button <button onClick={() => openInNewTab(url)} className={"text-center"}>
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"
@@ -12,22 +12,14 @@ export default function TourContentWithBtn({ message, isChecked }) {
return ( return (
<div> <div>
<p>{message}</p> <p>{message}</p>
<label <label className="flex items-center justify-center mb-0">
style={{
textAlign: "center",
display: "flex",
justifyContent: "center"
}}
>
<input <input
type="checkbox" type="checkbox"
style={{ marginRight: 3 }} className="op-checkbox op-checkbox-xs mr-1"
checked={isCheck} checked={isCheck}
onChange={handleCheck} onChange={handleCheck}
/>{" "} />
<span style={{ color: "#787878", fontSize: 12 }}> <span className="#787878 text-[12px]">Don&apos;t show this again</span>
Don&apos;t show this again
</span>
</label> </label>
</div> </div>
); );
+3 -10
View File
@@ -1,20 +1,13 @@
import React from "react"; import React from "react";
import { useNavigate } from "react-router-dom";
import { openInNewTab } from "../constant/Utils"; import { openInNewTab } from "../constant/Utils";
function Upgrade({ message, newWindow }) { function Upgrade({ message }) {
const navigation = useNavigate();
return ( return (
<sup> <sup>
<span <span
onClick={() => { onClick={() => {
if (newWindow) { const url = window.location.origin + "/subscription";
const url = window.location.origin + "/subscription"; openInNewTab(url);
openInNewTab(url);
} else {
navigation("/subscription");
}
}} }}
className="text-blue-800 text-sm cursor-pointer underline" className="text-blue-800 text-sm cursor-pointer underline"
> >
+3 -6
View File
@@ -49,13 +49,10 @@ const Validate = () => {
<Outlet /> <Outlet />
</div> </div>
) : ( ) : (
<ModalUi title={"Session Expired"} isOpen={true} showClose={false}> <ModalUi showHeader={false} isOpen={true} showClose={false}>
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5"> <div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
<p className="text-xl font-normal">Your session has expired.</p> <p className="text-xl font-medium">Your session has expired.</p>
<button <button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
onClick={handleLoginBtn}
className="text-base px-3 py-1.5 rounded shadow-md text-white bg-[#1ab6ce]"
>
Login Login
</button> </button>
</div> </div>
-1
View File
@@ -90,7 +90,6 @@
background-size: 1rem auto; background-size: 1rem auto;
} }
@media (max-width: 375px) { @media (max-width: 375px) {
.validationlist { .validationlist {
background-position: right 0.5rem top 50%; background-position: right 0.5rem top 50%;
-197
View File
@@ -1,197 +0,0 @@
.loginInput {
padding: 10px;
border-radius: 4px;
width: 100%;
font-size: 0.75rem;
border: 1px solid #e2dddd;
background-color: #e0e5f5;
color: black;
padding-left: 1rem !important;
padding-right: 1rem !important;
padding-top: 0.5rem !important;
font-family: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
font-weight: inherit;
overflow: visible;
}
.loginInput:focus {
outline: none;
border: none;
}
.verifyBtn {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 30px;
color: white;
font-weight: 500 !important;
font-size: 14px !important;
border: none;
}
.verifyBtn:focus {
border: none;
outline: none;
}
.verifyBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
color: white;
}
.fakeimg {
height: 200px;
background: #aaa;
}
.GTRY {
border: 1px solid #dee2e6;
margin-top: 75px;
padding-bottom: 20px;
background-color: #fff;
}
.main_head {
width: 100%;
height: 66px;
background-color: #fff;
margin-bottom: 52px;
padding-top: 10px;
}
.main-logo {
width: 250px;
height: 66px;
display: inline-block;
}
.card-box {
background: #fff;
min-height: 50px;
box-shadow: 0 20px 20px rgba(0, 0, 0, 0.1);
position: relative;
margin-bottom: 20px;
transition: 0.5s;
border: 1px solid #f2f2f2;
border-radius: 7px;
margin-top: 10px;
}
.LKJH {
display: flex;
}
.GTR {
text-align: left;
}
.JUI {
text-align: right;
}
.btn-info {
color: #fff;
background-color: #15b4e9;
border-color: #15b4e9;
}
.btn-info:hover {
color: #fff;
background-color: #15b4e9;
border-color: #15b4e9;
}
.btn-reg {
color: #15b4e9;
background-color: #ffffff;
border-color: #15b4e9;
}
.btn-reg:hover {
color: #15b4e9;
background-color: #ffffff;
border-color: #15b4e9;
}
.SYTU {
display: flex;
}
.MLKI {
float: right;
margin-bottom: 12px;
}
.login-btn {
width: 100% !important;
display: block !important;
}
@media only screen and (max-width: 667px) {
.MLKI {
float: inherit;
}
.login-btn {
width: 210px !important;
}
}
.MLKI a {
color: #212529;
}
.KNLO {
color: #878787;
font-size: 13px;
}
.form-check-label {
margin-left: 17px;
margin-bottom: 12px;
}
.welcomeText {
font-size: 30px;
}
@media only screen and (max-width: 600px) {
.KLO1 {
display: none;
}
.MLKI a {
font-size: 12px;
}
.form-check-label {
font-size: 12px;
margin-bottom: 14px;
}
.MKUY {
text-align: center;
padding-top: 10px;
}
.main_head {
margin-bottom: 12px;
padding-top: 10px;
border-bottom: 1px dashed #eeeeee;
}
}
@media screen and (max-width: 366px) {
.main-logo {
width: 150px;
height: 46px;
display: inline-block;
}
.welcomeText {
font-size: 20px;
}
.KNLO {
color: #878787;
font-size: 10px;
}
.btnContainer {
display: flex;
justify-content: center;
align-items: center;
}
}

Some files were not shown because too many files have changed in this diff Show More